summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGraeme Geldenhuys <graeme@mastermaths.co.za>2012-02-27 19:53:35 +0200
committerGraeme Geldenhuys <graeme@mastermaths.co.za>2012-03-07 22:44:08 +0200
commitb50c7fe536960a49349475f5c361044b097f24dc (patch)
treeeb74f0624ebaca3b6ee64a08b3edb63883eb06c2
parenta955b0e4833ba419478be83523fe433d645cd789 (diff)
downloadfpGUI-b50c7fe536960a49349475f5c361044b097f24dc.tar.xz
initial import of AggPas 2.4 RM3
The AggPas demos will not compile at this time, because I have restructured the directories a bit. I wanted a pristine checkin though. The demos will be fixed in the next few commits.
-rw-r--r--src/corelib/render/software/Agg2D.pas3403
-rw-r--r--src/corelib/render/software/agg-demos/Agg2DDemo.dpr758
-rw-r--r--src/corelib/render/software/agg-demos/aa_demo.dpr456
-rw-r--r--src/corelib/render/software/agg-demos/aa_test.dpr804
-rw-r--r--src/corelib/render/software/agg-demos/alpha_gradient.dpr503
-rw-r--r--src/corelib/render/software/agg-demos/alpha_mask.dpr346
-rw-r--r--src/corelib/render/software/agg-demos/alpha_mask2.dpr584
-rw-r--r--src/corelib/render/software/agg-demos/alpha_mask3.dpr793
-rw-r--r--src/corelib/render/software/agg-demos/arial.ttfbin0 -> 367112 bytes
-rw-r--r--src/corelib/render/software/agg-demos/bezier_div.dpr885
-rw-r--r--src/corelib/render/software/agg-demos/blend_color.dpr843
-rw-r--r--src/corelib/render/software/agg-demos/blur.dpr492
-rw-r--r--src/corelib/render/software/agg-demos/bspline.dpr270
-rwxr-xr-xsrc/corelib/render/software/agg-demos/build-find_compilers_linux2
-rwxr-xr-xsrc/corelib/render/software/agg-demos/build-find_compilers_mac2
-rwxr-xr-xsrc/corelib/render/software/agg-demos/build-upi1
-rwxr-xr-xsrc/corelib/render/software/agg-demos/build-x111
-rw-r--r--src/corelib/render/software/agg-demos/circles.dpr419
-rw-r--r--src/corelib/render/software/agg-demos/compile_upi.dpr19
-rw-r--r--src/corelib/render/software/agg-demos/compile_x11.dpr27
-rw-r--r--src/corelib/render/software/agg-demos/component_rendering.dpr171
-rw-r--r--src/corelib/render/software/agg-demos/compositing.dpr576
-rw-r--r--src/corelib/render/software/agg-demos/compositing2.dpr336
-rw-r--r--src/corelib/render/software/agg-demos/conv_contour.dpr274
-rw-r--r--src/corelib/render/software/agg-demos/conv_dash_marker.dpr434
-rw-r--r--src/corelib/render/software/agg-demos/conv_stroke.dpr405
-rw-r--r--src/corelib/render/software/agg-demos/distortions.dpr913
-rwxr-xr-xsrc/corelib/render/software/agg-demos/expat-pas/ascii.inc116
-rwxr-xr-xsrc/corelib/render/software/agg-demos/expat-pas/asciitab.inc67
-rwxr-xr-xsrc/corelib/render/software/agg-demos/expat-pas/asciitab_bt_colon_.inc67
-rwxr-xr-xsrc/corelib/render/software/agg-demos/expat-pas/expat.pas898
-rwxr-xr-xsrc/corelib/render/software/agg-demos/expat-pas/expat_basics.pas218
-rwxr-xr-xsrc/corelib/render/software/agg-demos/expat-pas/expat_external.inc147
-rwxr-xr-xsrc/corelib/render/software/agg-demos/expat-pas/expat_external.pas52
-rwxr-xr-xsrc/corelib/render/software/agg-demos/expat-pas/expat_mode.inc92
-rwxr-xr-xsrc/corelib/render/software/agg-demos/expat-pas/iasciitab.inc69
-rwxr-xr-xsrc/corelib/render/software/agg-demos/expat-pas/iasciitab_bt_colon_.inc68
-rwxr-xr-xsrc/corelib/render/software/agg-demos/expat-pas/readme.txt104
-rwxr-xr-xsrc/corelib/render/software/agg-demos/expat-pas/utf8tab.inc67
-rwxr-xr-xsrc/corelib/render/software/agg-demos/expat-pas/winconfig.inc52
-rwxr-xr-xsrc/corelib/render/software/agg-demos/expat-pas/xmlparse.inc6475
-rwxr-xr-xsrc/corelib/render/software/agg-demos/expat-pas/xmlrole.pas659
-rwxr-xr-xsrc/corelib/render/software/agg-demos/expat-pas/xmltok.pas1598
-rwxr-xr-xsrc/corelib/render/software/agg-demos/expat-pas/xmltok_impl.inc4176
-rwxr-xr-xsrc/corelib/render/software/agg-demos/expat-pas/xmltok_ns.inc176
-rwxr-xr-xsrc/corelib/render/software/agg-demos/expat-wrap/expat.pas1024
-rwxr-xr-xsrc/corelib/render/software/agg-demos/expat-wrap/linux/ReadMe_Linux.txt33
-rwxr-xr-xsrc/corelib/render/software/agg-demos/expat-wrap/linux/libexpat.la32
-rwxr-xr-xsrc/corelib/render/software/agg-demos/expat-wrap/linux/libexpat.so.0.4.0bin0 -> 313637 bytes
-rwxr-xr-xsrc/corelib/render/software/agg-demos/expat-wrap/linux/libexpatw.la32
-rwxr-xr-xsrc/corelib/render/software/agg-demos/expat-wrap/linux/libexpatw.so.0.4.0bin0 -> 314029 bytes
-rw-r--r--src/corelib/render/software/agg-demos/find_compilers_linux.dpr489
-rw-r--r--src/corelib/render/software/agg-demos/find_compilers_mac.dpr662
-rw-r--r--src/corelib/render/software/agg-demos/find_compilers_win.dpr1496
-rw-r--r--src/corelib/render/software/agg-demos/flash_rasterizer.dpr1006
-rw-r--r--src/corelib/render/software/agg-demos/flash_rasterizer2.dpr983
-rw-r--r--src/corelib/render/software/agg-demos/freetype_test.dpr698
-rw-r--r--src/corelib/render/software/agg-demos/gamma_correction.dpr323
-rw-r--r--src/corelib/render/software/agg-demos/gamma_ctrl.dpr400
-rw-r--r--src/corelib/render/software/agg-demos/gouraud.dpr453
-rw-r--r--src/corelib/render/software/agg-demos/gouraud_mesh.dpr983
-rwxr-xr-xsrc/corelib/render/software/agg-demos/gpc/copying.txt22
-rwxr-xr-xsrc/corelib/render/software/agg-demos/gpc/gpc.pas1965
-rwxr-xr-xsrc/corelib/render/software/agg-demos/gpc/versions.txt123
-rw-r--r--src/corelib/render/software/agg-demos/gpc_test.dpr962
-rw-r--r--src/corelib/render/software/agg-demos/gradient_focal.dpr437
-rw-r--r--src/corelib/render/software/agg-demos/gradients.dpr728
-rw-r--r--src/corelib/render/software/agg-demos/gradients_contour.dpr1907
-rw-r--r--src/corelib/render/software/agg-demos/graph_test.dpr1591
-rw-r--r--src/corelib/render/software/agg-demos/idea.dpr517
-rw-r--r--src/corelib/render/software/agg-demos/image1.dpr295
-rw-r--r--src/corelib/render/software/agg-demos/image_alpha.dpr351
-rw-r--r--src/corelib/render/software/agg-demos/image_filters.dpr616
-rw-r--r--src/corelib/render/software/agg-demos/image_filters2.dpr412
-rw-r--r--src/corelib/render/software/agg-demos/image_fltr_graph.dpr516
-rw-r--r--src/corelib/render/software/agg-demos/image_perspective.dpr452
-rw-r--r--src/corelib/render/software/agg-demos/image_resample.dpr579
-rw-r--r--src/corelib/render/software/agg-demos/image_transforms.dpr635
-rw-r--r--src/corelib/render/software/agg-demos/image_transforms.txt189
-rw-r--r--src/corelib/render/software/agg-demos/interactive_polygon_.pas638
-rw-r--r--src/corelib/render/software/agg-demos/line_patterns.dpr489
-rw-r--r--src/corelib/render/software/agg-demos/lion.dpr305
-rw-r--r--src/corelib/render/software/agg-demos/lion_lens.dpr293
-rw-r--r--src/corelib/render/software/agg-demos/lion_outline.dpr334
-rw-r--r--src/corelib/render/software/agg-demos/make_arrows_.pas61
-rw-r--r--src/corelib/render/software/agg-demos/make_gb_poly_.pas1927
-rw-r--r--src/corelib/render/software/agg-demos/multi_clip.dpr542
-rw-r--r--src/corelib/render/software/agg-demos/parse_lion_.pas605
-rw-r--r--src/corelib/render/software/agg-demos/particle_demo.dpr843
-rw-r--r--src/corelib/render/software/agg-demos/pattern_fill.dpr522
-rw-r--r--src/corelib/render/software/agg-demos/pattern_perspective.dpr438
-rw-r--r--src/corelib/render/software/agg-demos/perspective.dpr416
-rw-r--r--src/corelib/render/software/agg-demos/polymorphic_renderer.dpr249
-rwxr-xr-xsrc/corelib/render/software/agg-demos/ppm/1.ppmbin0 -> 845 bytes
-rwxr-xr-xsrc/corelib/render/software/agg-demos/ppm/2.ppmbin0 -> 936 bytes
-rwxr-xr-xsrc/corelib/render/software/agg-demos/ppm/3.ppmbin0 -> 1158 bytes
-rwxr-xr-xsrc/corelib/render/software/agg-demos/ppm/4.ppm5
-rwxr-xr-xsrc/corelib/render/software/agg-demos/ppm/5.ppmbin0 -> 1086 bytes
-rwxr-xr-xsrc/corelib/render/software/agg-demos/ppm/6.ppmbin0 -> 3861 bytes
-rwxr-xr-xsrc/corelib/render/software/agg-demos/ppm/7.ppmbin0 -> 2496 bytes
-rwxr-xr-xsrc/corelib/render/software/agg-demos/ppm/8.ppm5
-rwxr-xr-xsrc/corelib/render/software/agg-demos/ppm/9.ppm5
-rwxr-xr-xsrc/corelib/render/software/agg-demos/ppm/agg.ppmbin0 -> 3108 bytes
-rwxr-xr-xsrc/corelib/render/software/agg-demos/ppm/compositing.ppm101
-rwxr-xr-xsrc/corelib/render/software/agg-demos/ppm/spheres.ppmbin0 -> 288015 bytes
-rwxr-xr-xsrc/corelib/render/software/agg-demos/ppm/spheres2.ppmbin0 -> 288038 bytes
-rw-r--r--src/corelib/render/software/agg-demos/pure_api_win.dpr254
-rw-r--r--src/corelib/render/software/agg-demos/raster_text.dpr257
-rw-r--r--src/corelib/render/software/agg-demos/rasterizer_compound.dpr435
-rw-r--r--src/corelib/render/software/agg-demos/rasterizers.dpr449
-rw-r--r--src/corelib/render/software/agg-demos/rasterizers2.dpr805
-rw-r--r--src/corelib/render/software/agg-demos/readme.txt385
-rw-r--r--src/corelib/render/software/agg-demos/rounded_rect.dpr293
-rw-r--r--src/corelib/render/software/agg-demos/scanline_boolean.dpr385
-rw-r--r--src/corelib/render/software/agg-demos/scanline_boolean2.dpr947
-rw-r--r--src/corelib/render/software/agg-demos/settings.dat56
-rw-r--r--src/corelib/render/software/agg-demos/shapes.txt10740
-rw-r--r--src/corelib/render/software/agg-demos/simple_blur.dpr450
-rwxr-xr-xsrc/corelib/render/software/agg-demos/svg/agg@pas.svg279
-rwxr-xr-xsrc/corelib/render/software/agg-demos/svg/tiger.svg728
-rw-r--r--src/corelib/render/software/agg-demos/svg_test.dpr439
-rw-r--r--src/corelib/render/software/agg-demos/times.ttfbin0 -> 409280 bytes
-rw-r--r--src/corelib/render/software/agg-demos/timesi.ttfbin0 -> 248368 bytes
-rw-r--r--src/corelib/render/software/agg-demos/trans_curve1.dpr454
-rw-r--r--src/corelib/render/software/agg-demos/trans_curve1_ft.dpr450
-rw-r--r--src/corelib/render/software/agg-demos/trans_curve2.dpr541
-rw-r--r--src/corelib/render/software/agg-demos/trans_curve2_ft.dpr536
-rw-r--r--src/corelib/render/software/agg-demos/trans_polar.dpr324
-rw-r--r--src/corelib/render/software/agg-demos/truetype_test.dpr706
-rw-r--r--src/corelib/render/software/agg-demos/verdana.ttfbin0 -> 171792 bytes
-rw-r--r--src/corelib/render/software/agg_2D.pas3302
-rw-r--r--src/corelib/render/software/agg_alpha_mask_u8.pas1350
-rw-r--r--src/corelib/render/software/agg_arc.pas221
-rw-r--r--src/corelib/render/software/agg_array.pas1194
-rw-r--r--src/corelib/render/software/agg_arrowhead.pas255
-rw-r--r--src/corelib/render/software/agg_basics.pas1679
-rw-r--r--src/corelib/render/software/agg_bezier_arc.pas507
-rw-r--r--src/corelib/render/software/agg_bitset_iterator.pas88
-rw-r--r--src/corelib/render/software/agg_blur.pas1624
-rw-r--r--src/corelib/render/software/agg_bounding_rect.pas390
-rw-r--r--src/corelib/render/software/agg_bspline.pas478
-rw-r--r--src/corelib/render/software/agg_clip_liang_barsky.pas511
-rw-r--r--src/corelib/render/software/agg_color.pas515
-rw-r--r--src/corelib/render/software/agg_conv_adaptor_vcgen.pas321
-rw-r--r--src/corelib/render/software/agg_conv_adaptor_vpgen.pas234
-rw-r--r--src/corelib/render/software/agg_conv_bspline.pas91
-rw-r--r--src/corelib/render/software/agg_conv_clip_polygon.pas127
-rw-r--r--src/corelib/render/software/agg_conv_clip_polyline.pas127
-rw-r--r--src/corelib/render/software/agg_conv_concat.pas141
-rw-r--r--src/corelib/render/software/agg_conv_contour.pas199
-rw-r--r--src/corelib/render/software/agg_conv_curve.pas285
-rw-r--r--src/corelib/render/software/agg_conv_dash.pas120
-rw-r--r--src/corelib/render/software/agg_conv_gpc.pas526
-rw-r--r--src/corelib/render/software/agg_conv_marker.pas216
-rw-r--r--src/corelib/render/software/agg_conv_marker_adaptor.pas92
-rw-r--r--src/corelib/render/software/agg_conv_segmentator.pas91
-rw-r--r--src/corelib/render/software/agg_conv_shorten_path.pas91
-rw-r--r--src/corelib/render/software/agg_conv_smooth_poly1.pas135
-rw-r--r--src/corelib/render/software/agg_conv_stroke.pas388
-rw-r--r--src/corelib/render/software/agg_conv_transform.pas113
-rw-r--r--src/corelib/render/software/agg_curves.pas1929
-rw-r--r--src/corelib/render/software/agg_dda_line.pas436
-rw-r--r--src/corelib/render/software/agg_ellipse.pas205
-rw-r--r--src/corelib/render/software/agg_ellipse_bresenham.pas175
-rw-r--r--src/corelib/render/software/agg_embedded_raster_fonts.pas10382
-rw-r--r--src/corelib/render/software/agg_font_cache_manager.pas612
-rw-r--r--src/corelib/render/software/agg_font_engine.pas94
-rw-r--r--src/corelib/render/software/agg_font_freetype.pas1731
-rw-r--r--src/corelib/render/software/agg_font_freetype_lib.pas369
-rw-r--r--src/corelib/render/software/agg_font_win32_tt.pas1774
-rw-r--r--src/corelib/render/software/agg_gamma_functions.pas297
-rw-r--r--src/corelib/render/software/agg_gamma_lut.pas278
-rw-r--r--src/corelib/render/software/agg_glyph_raster_bin.pas268
-rw-r--r--src/corelib/render/software/agg_gradient_lut.pas334
-rw-r--r--src/corelib/render/software/agg_gsv_text.pas974
-rw-r--r--src/corelib/render/software/agg_image_filters.pas1143
-rw-r--r--src/corelib/render/software/agg_line_aa_basics.pas281
-rw-r--r--src/corelib/render/software/agg_math.pas593
-rw-r--r--src/corelib/render/software/agg_math_stroke.pas1169
-rw-r--r--src/corelib/render/software/agg_mode.inc101
-rw-r--r--src/corelib/render/software/agg_path_storage.pas1262
-rw-r--r--src/corelib/render/software/agg_path_storage_integer.pas965
-rw-r--r--src/corelib/render/software/agg_pattern_filters_rgba.pas267
-rw-r--r--src/corelib/render/software/agg_pixfmt.pas409
-rw-r--r--src/corelib/render/software/agg_pixfmt_amask_adaptor.pas226
-rw-r--r--src/corelib/render/software/agg_pixfmt_gray.pas443
-rw-r--r--src/corelib/render/software/agg_pixfmt_rgb.pas397
-rw-r--r--src/corelib/render/software/agg_pixfmt_rgb_packed.pas329
-rw-r--r--src/corelib/render/software/agg_pixfmt_rgba.pas1771
-rw-r--r--src/corelib/render/software/agg_pixfmt_transposer.pas233
-rw-r--r--src/corelib/render/software/agg_rasterizer_cells_aa.pas1074
-rw-r--r--src/corelib/render/software/agg_rasterizer_compound_aa.pas1062
-rw-r--r--src/corelib/render/software/agg_rasterizer_outline.pas163
-rw-r--r--src/corelib/render/software/agg_rasterizer_outline_aa.pas643
-rw-r--r--src/corelib/render/software/agg_rasterizer_scanline_aa.pas1824
-rw-r--r--src/corelib/render/software/agg_rasterizer_sl_clip.pas1154
-rw-r--r--src/corelib/render/software/agg_render_scanlines.pas103
-rw-r--r--src/corelib/render/software/agg_renderer_base.pas1162
-rw-r--r--src/corelib/render/software/agg_renderer_markers.pas1648
-rw-r--r--src/corelib/render/software/agg_renderer_mclip.pas439
-rw-r--r--src/corelib/render/software/agg_renderer_outline_aa.pas2599
-rw-r--r--src/corelib/render/software/agg_renderer_outline_image.pas1453
-rw-r--r--src/corelib/render/software/agg_renderer_primitives.pas333
-rw-r--r--src/corelib/render/software/agg_renderer_raster_text.pas385
-rw-r--r--src/corelib/render/software/agg_renderer_scanline.pas931
-rw-r--r--src/corelib/render/software/agg_rendering_buffer.pas329
-rw-r--r--src/corelib/render/software/agg_rendering_buffer_dynarow.pas212
-rw-r--r--src/corelib/render/software/agg_rounded_rect.pas468
-rw-r--r--src/corelib/render/software/agg_scanline.pas127
-rw-r--r--src/corelib/render/software/agg_scanline_bin.pas220
-rw-r--r--src/corelib/render/software/agg_scanline_boolean_algebra.pas1663
-rw-r--r--src/corelib/render/software/agg_scanline_p.pas278
-rw-r--r--src/corelib/render/software/agg_scanline_storage_aa.pas1857
-rw-r--r--src/corelib/render/software/agg_scanline_storage_bin.pas1009
-rw-r--r--src/corelib/render/software/agg_scanline_u.pas393
-rw-r--r--src/corelib/render/software/agg_shorten_path.pas103
-rw-r--r--src/corelib/render/software/agg_simul_eq.pas240
-rw-r--r--src/corelib/render/software/agg_span_allocator.pas105
-rw-r--r--src/corelib/render/software/agg_span_converter.pas93
-rw-r--r--src/corelib/render/software/agg_span_generator.pas90
-rw-r--r--src/corelib/render/software/agg_span_gouraud.pas235
-rw-r--r--src/corelib/render/software/agg_span_gouraud_gray.pas336
-rw-r--r--src/corelib/render/software/agg_span_gouraud_rgba.pas629
-rw-r--r--src/corelib/render/software/agg_span_gradient.pas805
-rw-r--r--src/corelib/render/software/agg_span_gradient_alpha.pas270
-rw-r--r--src/corelib/render/software/agg_span_gradient_contour.pas519
-rw-r--r--src/corelib/render/software/agg_span_gradient_image.pas315
-rw-r--r--src/corelib/render/software/agg_span_image_filter.pas235
-rw-r--r--src/corelib/render/software/agg_span_image_filter_gray.pas869
-rw-r--r--src/corelib/render/software/agg_span_image_filter_rgb.pas1081
-rw-r--r--src/corelib/render/software/agg_span_image_filter_rgba.pas1072
-rw-r--r--src/corelib/render/software/agg_span_image_resample.pas312
-rw-r--r--src/corelib/render/software/agg_span_image_resample_gray.pas445
-rw-r--r--src/corelib/render/software/agg_span_image_resample_rgb.pas519
-rw-r--r--src/corelib/render/software/agg_span_image_resample_rgba.pas519
-rw-r--r--src/corelib/render/software/agg_span_interpolator_adaptor.pas123
-rw-r--r--src/corelib/render/software/agg_span_interpolator_linear.pas371
-rw-r--r--src/corelib/render/software/agg_span_interpolator_persp.pas642
-rw-r--r--src/corelib/render/software/agg_span_interpolator_trans.pas157
-rw-r--r--src/corelib/render/software/agg_span_pattern.pas501
-rw-r--r--src/corelib/render/software/agg_span_pattern_filter_gray.pas599
-rw-r--r--src/corelib/render/software/agg_span_pattern_filter_rgb.pas740
-rw-r--r--src/corelib/render/software/agg_span_pattern_filter_rgba.pas755
-rw-r--r--src/corelib/render/software/agg_span_pattern_resample_gray.pas428
-rw-r--r--src/corelib/render/software/agg_span_pattern_resample_rgb.pas488
-rw-r--r--src/corelib/render/software/agg_span_pattern_resample_rgba.pas506
-rw-r--r--src/corelib/render/software/agg_span_pattern_rgb.pas167
-rw-r--r--src/corelib/render/software/agg_span_pattern_rgba.pas165
-rw-r--r--src/corelib/render/software/agg_span_solid.pas109
-rw-r--r--src/corelib/render/software/agg_span_subdiv_adaptor.pas233
-rw-r--r--src/corelib/render/software/agg_trans_affine.pas926
-rw-r--r--src/corelib/render/software/agg_trans_bilinear.pas257
-rw-r--r--src/corelib/render/software/agg_trans_double_path.pas521
-rw-r--r--src/corelib/render/software/agg_trans_perspective.pas1276
-rw-r--r--src/corelib/render/software/agg_trans_single_path.pas395
-rw-r--r--src/corelib/render/software/agg_trans_viewport.pas443
-rw-r--r--src/corelib/render/software/agg_trans_warp_magnifier.pas142
-rw-r--r--src/corelib/render/software/agg_vcgen_bspline.pas403
-rw-r--r--src/corelib/render/software/agg_vcgen_contour.pas453
-rw-r--r--src/corelib/render/software/agg_vcgen_dash.pas382
-rw-r--r--src/corelib/render/software/agg_vcgen_markers_term.pas217
-rw-r--r--src/corelib/render/software/agg_vcgen_smooth_poly1.pas431
-rw-r--r--src/corelib/render/software/agg_vcgen_stroke.pas1008
-rw-r--r--src/corelib/render/software/agg_vcgen_vertex_sequence.pas196
-rw-r--r--src/corelib/render/software/agg_vertex_sequence.pas180
-rw-r--r--src/corelib/render/software/agg_vertex_source.pas111
-rw-r--r--src/corelib/render/software/agg_vpgen_clip_polygon.pas329
-rw-r--r--src/corelib/render/software/agg_vpgen_clip_polyline.pas386
-rw-r--r--src/corelib/render/software/agg_vpgen_segmentator.pas205
-rw-r--r--src/corelib/render/software/ctrl/agg_bezier_ctrl.pas887
-rw-r--r--src/corelib/render/software/ctrl/agg_cbox_ctrl.pas430
-rw-r--r--src/corelib/render/software/ctrl/agg_ctrl.pas223
-rw-r--r--src/corelib/render/software/ctrl/agg_gamma_ctrl.pas881
-rw-r--r--src/corelib/render/software/ctrl/agg_gamma_spline.pas265
-rw-r--r--src/corelib/render/software/ctrl/agg_polygon_ctrl.pas769
-rw-r--r--src/corelib/render/software/ctrl/agg_rbox_ctrl.pas621
-rw-r--r--src/corelib/render/software/ctrl/agg_scale_ctrl.pas747
-rw-r--r--src/corelib/render/software/ctrl/agg_slider_ctrl.pas695
-rw-r--r--src/corelib/render/software/ctrl/agg_spline_ctrl.pas816
-rw-r--r--src/corelib/render/software/pf_abgr32.inc608
-rw-r--r--src/corelib/render/software/pf_abgr32_pre.inc489
-rw-r--r--src/corelib/render/software/pf_alpha32.inc781
-rw-r--r--src/corelib/render/software/pf_argb32.inc608
-rw-r--r--src/corelib/render/software/pf_argb32_pre.inc489
-rw-r--r--src/corelib/render/software/pf_bgr24.inc533
-rw-r--r--src/corelib/render/software/pf_bgr24_gamma.inc429
-rw-r--r--src/corelib/render/software/pf_bgr24_pre.inc434
-rw-r--r--src/corelib/render/software/pf_bgra32.inc610
-rw-r--r--src/corelib/render/software/pf_bgra32_pre.inc490
-rw-r--r--src/corelib/render/software/pf_cubl32.inc361
-rw-r--r--src/corelib/render/software/pf_gray8.inc437
-rw-r--r--src/corelib/render/software/pf_gray8_pre.inc342
-rw-r--r--src/corelib/render/software/pf_rgb24.inc533
-rw-r--r--src/corelib/render/software/pf_rgb24_gamma.inc429
-rw-r--r--src/corelib/render/software/pf_rgb24_pre.inc434
-rw-r--r--src/corelib/render/software/pf_rgb555.inc453
-rw-r--r--src/corelib/render/software/pf_rgb555_gamma.inc458
-rw-r--r--src/corelib/render/software/pf_rgb555_pre.inc454
-rw-r--r--src/corelib/render/software/pf_rgb565.inc452
-rw-r--r--src/corelib/render/software/pf_rgb565_gamma.inc456
-rw-r--r--src/corelib/render/software/pf_rgb565_pre.inc453
-rw-r--r--src/corelib/render/software/pf_rgba32.inc608
-rw-r--r--src/corelib/render/software/pf_rgba32_pre.inc489
-rw-r--r--src/corelib/render/software/platform/linux/agg_platform_support.pas2505
-rw-r--r--src/corelib/render/software/platform/linux/file_utils_.pas776
-rw-r--r--src/corelib/render/software/platform/mac/agg_mac_pmap.pas471
-rw-r--r--src/corelib/render/software/platform/mac/agg_platform_support.pas2212
-rw-r--r--src/corelib/render/software/platform/mac/file_utils_.pas846
-rw-r--r--src/corelib/render/software/platform/win/agg_platform_support.pas2121
-rw-r--r--src/corelib/render/software/platform/win/agg_win32_bmp.pas719
-rw-r--r--src/corelib/render/software/platform/win/file_utils_.pas776
-rw-r--r--src/corelib/render/software/svg/agg_svg_exception.pas172
-rw-r--r--src/corelib/render/software/svg/agg_svg_parser.pas1386
-rw-r--r--src/corelib/render/software/svg/agg_svg_path_renderer.pas893
-rw-r--r--src/corelib/render/software/svg/agg_svg_path_tokenizer.pas325
-rw-r--r--src/corelib/render/software/util/agg_color_conv.pas565
316 files changed, 198775 insertions, 0 deletions
diff --git a/src/corelib/render/software/Agg2D.pas b/src/corelib/render/software/Agg2D.pas
new file mode 100644
index 00000000..cdbd9ba7
--- /dev/null
+++ b/src/corelib/render/software/Agg2D.pas
@@ -0,0 +1,3403 @@
+//----------------------------------------------------------------------------
+// Agg2D - Version 1.0
+// Based on Anti-Grain Geometry
+// Copyright (C) 2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// TAgg2D - Version 1.0 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2007 - 2008
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 22.11.2007-Milano: Unit port establishment
+// 23.11.2007-Milano: Porting
+// 11.12.2007-Milano: -"-
+// 13.12.2007-Milano: -"-
+// 13.01.2008-Milano: Finished OK
+//
+{ Agg2D.pas }
+unit
+ Agg2D ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+// With this define you can switch use of FreeType or Win32 TrueType font engine
+{DEFINE AGG2D_USE_FREETYPE }
+
+uses
+ agg_basics ,
+ agg_array ,
+ agg_trans_affine ,
+ agg_trans_viewport ,
+ agg_path_storage ,
+ agg_conv_stroke ,
+ agg_conv_transform ,
+ agg_conv_curve ,
+ agg_rendering_buffer ,
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_span_gradient ,
+ agg_span_image_filter_rgba ,
+ agg_span_image_resample_rgba ,
+ agg_span_converter ,
+ agg_span_interpolator_linear ,
+ agg_span_allocator ,
+ agg_rasterizer_scanline_aa ,
+ agg_gamma_functions ,
+ agg_scanline_u ,
+ agg_arc ,
+ agg_bezier_arc ,
+ agg_rounded_rect ,
+ agg_font_engine ,
+ agg_font_cache_manager ,
+ agg_pixfmt ,
+ agg_pixfmt_rgb ,
+ agg_pixfmt_rgba ,
+ agg_color ,
+ agg_math_stroke ,
+ agg_image_filters ,
+ agg_vertex_source ,
+ agg_render_scanlines ,
+
+{$IFDEF AGG2D_USE_FREETYPE }
+ agg_font_freetype ,
+
+{$ELSE }
+ agg_font_win32_tt ,
+
+{$ENDIF }
+
+ Math ,Windows ,Classes ,Graphics ;
+
+{ GLOBAL VARIABLES & CONSTANTS }
+const
+// LineJoin
+ AGG_JoinMiter = miter_join;
+ AGG_JoinRound = round_join;
+ AGG_JoinBevel = bevel_join;
+
+// LineCap
+ AGG_CapButt = butt_cap;
+ AGG_CapSquare = square_cap;
+ AGG_CapRound = round_cap;
+
+// TextAlignment
+ AGG_AlignLeft = 0;
+ AGG_AlignRight = 1;
+ AGG_AlignCenter = 2;
+ AGG_AlignTop = AGG_AlignRight;
+ AGG_AlignBottom = AGG_AlignLeft;
+
+// BlendMode
+ AGG_BlendAlpha = end_of_comp_op_e;
+ AGG_BlendClear = comp_op_clear;
+ AGG_BlendSrc = comp_op_src;
+ AGG_BlendDst = comp_op_dst;
+ AGG_BlendSrcOver = comp_op_src_over;
+ AGG_BlendDstOver = comp_op_dst_over;
+ AGG_BlendSrcIn = comp_op_src_in;
+ AGG_BlendDstIn = comp_op_dst_in;
+ AGG_BlendSrcOut = comp_op_src_out;
+ AGG_BlendDstOut = comp_op_dst_out;
+ AGG_BlendSrcAtop = comp_op_src_atop;
+ AGG_BlendDstAtop = comp_op_dst_atop;
+ AGG_BlendXor = comp_op_xor;
+ AGG_BlendAdd = comp_op_plus;
+ AGG_BlendSub = comp_op_minus;
+ AGG_BlendMultiply = comp_op_multiply;
+ AGG_BlendScreen = comp_op_screen;
+ AGG_BlendOverlay = comp_op_overlay;
+ AGG_BlendDarken = comp_op_darken;
+ AGG_BlendLighten = comp_op_lighten;
+ AGG_BlendColorDodge = comp_op_color_dodge;
+ AGG_BlendColorBurn = comp_op_color_burn;
+ AGG_BlendHardLight = comp_op_hard_light;
+ AGG_BlendSoftLight = comp_op_soft_light;
+ AGG_BlendDifference = comp_op_difference;
+ AGG_BlendExclusion = comp_op_exclusion;
+ AGG_BlendContrast = comp_op_contrast;
+
+{ TYPES DEFINITION }
+type
+ PDouble = ^double;
+
+ PAggColor = ^TAggColor;
+ TAggColor = rgba8;
+
+ TAggRectD = agg_basics.rect_d;
+
+ TAggAffine = trans_affine;
+ PAggAffine = trans_affine_ptr;
+
+ TAggFontRasterizer = gray8_adaptor_type;
+ PAggFontRasterizer = gray8_adaptor_type_ptr;
+
+ TAggFontScanline = gray8_scanline_type;
+ PAggFontScanline = gray8_scanline_type_ptr;
+
+{$IFDEF AGG2D_USE_FREETYPE }
+ TAggFontEngine = font_engine_freetype_int32;
+
+{$ELSE }
+ TAggFontEngine = font_engine_win32_tt_int32;
+
+{$ENDIF }
+
+ TAggGradient = (AGG_Solid ,AGG_Linear ,AGG_Radial );
+ TAggDirection = (AGG_CW, AGG_CCW );
+
+ TAggLineJoin = int;
+ TAggLineCap = int;
+ TAggBlendMode = comp_op_e;
+
+ TAggTextAlignment = int;
+
+ TAggDrawPathFlag = (
+ AGG_FillOnly ,
+ AGG_StrokeOnly ,
+ AGG_FillAndStroke ,
+ AGG_FillWithLineColor );
+
+ TAggViewportOption = (
+ AGG_Anisotropic ,
+ AGG_XMinYMin ,
+ AGG_XMidYMin ,
+ AGG_XMaxYMin ,
+ AGG_XMinYMid ,
+ AGG_XMidYMid ,
+ AGG_XMaxYMid ,
+ AGG_XMinYMax ,
+ AGG_XMidYMax ,
+ AGG_XMaxYMax );
+
+ TAggImageFilter = (
+ AGG_NoFilter ,
+ AGG_Bilinear ,
+ AGG_Hanning ,
+ AGG_Hermite ,
+ AGG_Quadric ,
+ AGG_Bicubic ,
+ AGG_Catrom ,
+ AGG_Spline16 ,
+ AGG_Spline36 ,
+ AGG_Blackman144 );
+
+ TAggImageResample = (
+ AGG_NoResample ,
+ AGG_ResampleAlways ,
+ AGG_ResampleOnZoomOut );
+
+ TAggFontCacheType = (
+ AGG_RasterFontCache ,
+ AGG_VectorFontCache );
+
+ PAggTransformations = ^TAggTransformations;
+ TAggTransformations = record
+ affineMatrix : array[0..5 ] of double;
+
+ end;
+
+ TAggRasterizerGamma = object(vertex_source )
+ m_alpha : gamma_multiply;
+ m_gamma : gamma_power;
+
+ constructor Construct(alpha ,gamma : double );
+
+ function func_operator_gamma(x : double ) : double; virtual;
+
+ end;
+
+ PAggImage = ^TAggImage;
+ TAggImage = object
+ renBuf : rendering_buffer;
+
+ constructor Construct;
+ destructor Destruct;
+
+ function attach(bitmap : TBitmap; flip : boolean ) : boolean;
+
+ function width : int;
+ function height : int;
+
+ end;
+
+ TAgg2D = class
+ private
+ m_rbuf : rendering_buffer;
+ m_pixf : TPixelFormat;
+
+ m_pixFormat ,m_pixFormatComp ,m_pixFormatPre ,m_pixFormatCompPre : pixel_formats;
+ m_renBase ,m_renBaseComp ,m_renBasePre ,m_renBaseCompPre : renderer_base;
+
+ m_renSolid ,m_renSolidComp : renderer_scanline_aa_solid;
+
+ m_allocator : span_allocator;
+ m_clipBox : TAggRectD;
+
+ m_blendMode ,m_imageBlendMode : TAggBlendMode;
+
+ m_imageBlendColor : TAggColor;
+
+ m_scanline : scanline_u8;
+ m_rasterizer : rasterizer_scanline_aa;
+
+ m_masterAlpha ,m_antiAliasGamma : double;
+
+ m_fillColor ,m_lineColor : TAggColor;
+
+ m_fillGradient ,m_lineGradient : pod_auto_array;
+
+ m_lineCap : TAggLineCap;
+ m_lineJoin : TAggLineJoin;
+
+ m_fillGradientFlag ,m_lineGradientFlag : TAggGradient;
+
+ m_fillGradientMatrix ,m_lineGradientMatrix : trans_affine;
+
+ m_fillGradientD1 ,
+ m_lineGradientD1 ,
+ m_fillGradientD2 ,
+ m_lineGradientD2 ,
+ m_textAngle : double;
+ m_textAlignX ,
+ m_textAlignY : TAggTextAlignment;
+ m_textHints : boolean;
+ m_fontHeight ,
+ m_fontAscent ,
+ m_fontDescent : double;
+ m_fontCacheType : TAggFontCacheType;
+
+ m_imageFilter : TAggImageFilter;
+ m_imageResample : TAggImageResample;
+ m_imageFilterLut : image_filter_lut;
+
+ m_fillGradientInterpolator ,
+ m_lineGradientInterpolator : span_interpolator_linear;
+
+ m_linearGradientFunction : gradient_x;
+ m_radialGradientFunction : gradient_circle;
+
+ m_lineWidth : double;
+ m_evenOddFlag : boolean;
+
+ m_path : path_storage;
+ m_transform : trans_affine;
+
+ m_convCurve : conv_curve;
+ m_convStroke : conv_stroke;
+
+ m_pathTransform ,m_strokeTransform : conv_transform;
+
+ m_imageFlip : boolean;
+
+ {$IFNDEF AGG2D_USE_FREETYPE }
+ m_fontDC : HDC;
+
+ {$ENDIF }
+
+ m_fontEngine : TAggFontEngine;
+ m_fontCacheManager : font_cache_manager;
+
+ // Other Pascal-specific members
+ m_gammaNone : gamma_none;
+ m_gammaAgg2D : TAggRasterizerGamma;
+
+ m_ifBilinear : image_filter_bilinear;
+ m_ifHanning : image_filter_hanning;
+ m_ifHermite : image_filter_hermite;
+ m_ifQuadric : image_filter_quadric;
+ m_ifBicubic : image_filter_bicubic;
+ m_ifCatrom : image_filter_catrom;
+ m_ifSpline16 : image_filter_spline16;
+ m_ifSpline36 : image_filter_spline36;
+ m_ifBlackman144 : image_filter_blackman144;
+
+ public
+ constructor Create;
+ destructor Destroy; override;
+
+ // Vector Graphics Engine Initialization
+ function Attach(bitmap : TBitmap; flip_y : boolean = false ) : boolean;
+
+ procedure ClearAll(c : TAggColor ); overload;
+ procedure ClearAll(r ,g ,b : byte; a : byte = 255 ); overload;
+
+ // Master Rendering Properties
+ procedure BlendMode(m : TAggBlendMode ); overload;
+ function BlendMode : TAggBlendMode; overload;
+
+ procedure MasterAlpha(a : double ); overload;
+ function MasterAlpha : double; overload;
+
+ procedure AntiAliasGamma(g : double ); overload;
+ function AntiAliasGamma : double; overload;
+
+ procedure FillColor(c : TAggColor ); overload;
+ procedure FillColor(r ,g ,b : byte; a : byte = 255 ); overload;
+ procedure NoFill;
+
+ procedure LineColor(c : TAggColor ); overload;
+ procedure LineColor(r ,g ,b : byte; a : byte = 255 ); overload;
+ procedure NoLine;
+
+ function FillColor : TAggColor; overload;
+ function LineColor : TAggColor; overload;
+
+ procedure FillLinearGradient(x1 ,y1 ,x2 ,y2 : double; c1 ,c2 : TAggColor; profile : double = 1.0 );
+ procedure LineLinearGradient(x1 ,y1 ,x2 ,y2 : double; c1 ,c2 : TAggColor; profile : double = 1.0 );
+
+ procedure FillRadialGradient(x ,y ,r : double; c1 ,c2 : TAggColor; profile : double = 1.0 ); overload;
+ procedure LineRadialGradient(x ,y ,r : double; c1 ,c2 : TAggColor; profile : double = 1.0 ); overload;
+
+ procedure FillRadialGradient(x ,y ,r : double; c1 ,c2 ,c3 : TAggColor ); overload;
+ procedure LineRadialGradient(x ,y ,r : double; c1 ,c2 ,c3 : TAggColor ); overload;
+
+ procedure FillRadialGradient(x ,y ,r : double ); overload;
+ procedure LineRadialGradient(x ,y ,r : double ); overload;
+
+ procedure LineWidth(w : double ); overload;
+ function LineWidth : double; overload;
+
+ procedure LineCap(cap : TAggLineCap ); overload;
+ function LineCap : TAggLineCap; overload;
+
+ procedure LineJoin(join : TAggLineJoin ); overload;
+ function LineJoin : TAggLineJoin; overload;
+
+ procedure FillEvenOdd(evenOddFlag : boolean ); overload;
+ function FillEvenOdd : boolean; overload;
+
+ // Affine Transformations
+ function Transformations : TAggTransformations; overload;
+ procedure Transformations(tr : PAggTransformations ); overload;
+ procedure ResetTransformations;
+
+ procedure Affine(tr : PAggAffine ); overload;
+ procedure Affine(tr : PAggTransformations ); overload;
+
+ procedure Rotate (angle : double );
+ procedure Scale (sx ,sy : double );
+ procedure Skew (sx ,sy : double );
+ procedure Translate(x ,y : double );
+
+ procedure Parallelogram(x1 ,y1 ,x2 ,y2 : double; para : PDouble );
+
+ procedure Viewport(
+ worldX1 ,worldY1 ,worldX2 ,worldY2 ,
+ screenX1 ,screenY1 ,screenX2 ,screenY2 : double;
+ opt : TAggViewportOption = AGG_XMidYMid );
+
+ // Coordinates Conversions
+ procedure WorldToScreen(x ,y : PDouble ); overload;
+ procedure ScreenToWorld(x ,y : PDouble ); overload;
+ function WorldToScreen(scalar : double ) : double; overload;
+ function ScreenToWorld(scalar : double ) : double; overload;
+
+ procedure AlignPoint(x ,y : PDouble );
+
+ // Clipping
+ procedure ClipBox(x1 ,y1 ,x2 ,y2 : double ); overload;
+ function ClipBox : TAggRectD; overload;
+
+ procedure ClearClipBox(c : TAggColor ); overload;
+ procedure ClearClipBox(r ,g ,b : byte; a : byte = 255 ); overload;
+
+ function InBox(worldX ,worldY : double ) : boolean;
+
+ // Basic Shapes
+ procedure Line (x1 ,y1 ,x2 ,y2 : double );
+ procedure Triangle (x1 ,y1 ,x2 ,y2 ,x3 ,y3 : double );
+ procedure Rectangle(x1 ,y1 ,x2 ,y2 : double );
+
+ procedure RoundedRect(x1 ,y1 ,x2 ,y2 ,r : double ); overload;
+ procedure RoundedRect(x1 ,y1 ,x2 ,y2 ,rx ,ry : double ); overload;
+ procedure RoundedRect(
+ x1 ,y1 ,x2 ,y2 ,
+ rxBottom ,ryBottom ,
+ rxTop ,ryTop : double ); overload;
+
+ procedure Ellipse(cx ,cy ,rx ,ry : double );
+
+ procedure Arc (cx ,cy ,rx ,ry ,start ,sweep : double );
+ procedure Star(cx ,cy ,r1 ,r2 ,startAngle : double; numRays : integer );
+
+ procedure Curve(x1 ,y1 ,x2 ,y2 ,x3 ,y3 : double ); overload;
+ procedure Curve(x1 ,y1 ,x2 ,y2 ,x3 ,y3 ,x4 ,y4 : double ); overload;
+
+ procedure Polygon (xy : PDouble; numPoints : integer );
+ procedure Polyline(xy : PDouble; numPoints : integer );
+
+ // Path Commands
+ procedure ResetPath;
+
+ procedure MoveTo (x ,y : double );
+ procedure MoveRel(dx ,dy : double );
+
+ procedure LineTo (x ,y : double );
+ procedure LineRel(dx ,dy : double );
+
+ procedure HorLineTo (x : double );
+ procedure HorLineRel(dx : double );
+
+ procedure VerLineTo (y : double );
+ procedure VerLineRel(dy : double );
+
+ procedure ArcTo(
+ rx ,ry ,angle : double;
+ largeArcFlag ,sweepFlag : boolean;
+ x ,y : double );
+
+ procedure ArcRel(
+ rx ,ry ,angle : double;
+ largeArcFlag ,sweepFlag : boolean;
+ dx ,dy : double );
+
+ procedure QuadricCurveTo (xCtrl ,yCtrl ,xTo ,yTo : double ); overload;
+ procedure QuadricCurveRel(dxCtrl ,dyCtrl ,dxTo ,dyTo : double ); overload;
+ procedure QuadricCurveTo (xTo ,yTo : double ); overload;
+ procedure QuadricCurveRel(dxTo ,dyTo : double ); overload;
+
+ procedure CubicCurveTo (xCtrl1 ,yCtrl1 ,xCtrl2 ,yCtrl2 ,xTo ,yTo : double ); overload;
+ procedure CubicCurveRel(dxCtrl1 ,dyCtrl1 ,dxCtrl2 ,dyCtrl2 ,dxTo ,dyTo : double ); overload;
+ procedure CubicCurveTo (xCtrl2 ,yCtrl2 ,xTo ,yTo : double ); overload;
+ procedure CubicCurveRel(dxCtrl2 ,dyCtrl2 ,dxTo ,dyTo : double ); overload;
+
+ procedure AddEllipse(cx ,cy ,rx ,ry : double; dir : TAggDirection );
+ procedure ClosePolygon;
+
+ procedure DrawPath(flag : TAggDrawPathFlag = AGG_FillAndStroke );
+
+ // Text Rendering
+ procedure FlipText(flip : boolean );
+
+ procedure Font(
+ fileName : AnsiString; height : double;
+ bold : boolean = false;
+ italic : boolean = false;
+ cache : TAggFontCacheType = AGG_VectorFontCache;
+ angle : double = 0.0 );
+
+ function FontHeight : double;
+
+ procedure TextAlignment(alignX ,alignY : TAggTextAlignment );
+
+ function TextHints : boolean; overload;
+ procedure TextHints(hints : boolean ); overload;
+ function TextWidth(str : AnsiString ) : double;
+
+ procedure Text(
+ x ,y : double; str : AnsiString;
+ roundOff : boolean = false;
+ ddx : double = 0.0;
+ ddy : double = 0.0 );
+
+ // Image Rendering
+ procedure ImageFilter(f : TAggImageFilter ); overload;
+ function ImageFilter : TAggImageFilter; overload;
+
+ procedure ImageResample(f : TAggImageResample ); overload;
+ function ImageResample : TAggImageResample; overload;
+
+ procedure ImageFlip(f : boolean );
+
+ procedure TransformImage(
+ bitmap : TBitmap;
+ imgX1 ,imgY1 ,imgX2 ,imgY2 : integer;
+ dstX1 ,dstY1 ,dstX2 ,dstY2 : double ); overload;
+
+ procedure TransformImage(
+ bitmap : TBitmap;
+ dstX1 ,dstY1 ,dstX2 ,dstY2 : double ); overload;
+
+ procedure TransformImage(
+ bitmap : TBitmap;
+ imgX1 ,imgY1 ,imgX2 ,imgY2 : integer;
+ parallelo : PDouble ); overload;
+
+ procedure TransformImage(bitmap : TBitmap; parallelo : PDouble ); overload;
+
+ procedure TransformImagePath(
+ bitmap : TBitmap;
+ imgX1 ,imgY1 ,imgX2 ,imgY2 : integer;
+ dstX1 ,dstY1 ,dstX2 ,dstY2 : double ); overload;
+
+ procedure TransformImagePath(
+ bitmap : TBitmap;
+ dstX1 ,dstY1 ,dstX2 ,dstY2 : double ); overload;
+
+ procedure TransformImagePath(
+ bitmap : TBitmap;
+ imgX1 ,imgY1 ,imgX2 ,imgY2 : integer;
+ parallelo : PDouble ); overload;
+
+ procedure TransformImagePath(bitmap : TBitmap; parallelo : PDouble ); overload;
+
+ procedure CopyImage(
+ bitmap : TBitmap;
+ imgX1 ,imgY1 ,imgX2 ,imgY2 : integer;
+ dstX ,dstY : double ); overload;
+
+ procedure CopyImage(bitmap : TBitmap; dstX ,dstY : double ); overload;
+
+ private
+ procedure render(fillColor_ : boolean ); overload;
+ procedure render(ras : PAggFontRasterizer; sl : PAggFontScanline ); overload;
+
+ procedure addLine(x1 ,y1 ,x2 ,y2 : double );
+ procedure updateRasterizerGamma;
+ procedure renderImage(
+ img : PAggImage;
+ x1 ,y1 ,x2 ,y2 : integer;
+ parl : PDouble );
+
+ end;
+
+{ GLOBAL PROCEDURES }
+// Standalone API
+ function Deg2Rad(v : double ) : double;
+ function Rad2Deg(v : double ) : double;
+
+ function Agg2DUsesFreeType : boolean;
+
+ function BitmapAlphaTransparency(bitmap : TBitmap; alpha : byte ) : boolean;
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+var
+ g_approxScale : double = 2.0;
+
+type
+ PAggSpanConvImageBlend = ^TAggSpanConvImageBlend;
+ TAggSpanConvImageBlend = object(span_convertor )
+ private
+ m_mode : TAggBlendMode;
+ m_color : TAggColor;
+ m_pixel : pixel_formats_ptr; // m_pixFormatCompPre
+
+ public
+ constructor Construct(m : TAggBlendMode; c : TAggColor; p : pixel_formats_ptr );
+
+ procedure convert(span : aggclr_ptr; x ,y : int; len : unsigned ); virtual;
+
+ end;
+
+{ OPERATOR_IS_EQUAL }
+function operator_is_equal(c1 ,c2 : PAggColor ) : boolean;
+begin
+ result:=
+ (c1.r = c2.r ) and
+ (c1.g = c2.g ) and
+ (c1.b = c2.b ) and
+ (c1.a = c2.a );
+
+end;
+
+{ OPERATOR_IS_NOT_EQUAL }
+function operator_is_not_equal(c1 ,c2 : PAggColor ) : boolean;
+begin
+ result:=not operator_is_equal(c1 ,c2 );
+
+end;
+
+{ AGG2DRENDERER_RENDER }
+procedure Agg2DRenderer_render(
+ gr : TAgg2D;
+ renBase : renderer_base_ptr;
+ renSolid : renderer_scanline_aa_solid_ptr;
+ fillColor_ : boolean ); overload;
+var
+ span : span_gradient;
+ ren : renderer_scanline_aa;
+ clr : aggclr;
+
+begin
+ if (fillColor_ and
+ (gr.m_fillGradientFlag = AGG_Linear ) ) or
+ (not fillColor_ and
+ (gr.m_lineGradientFlag = AGG_Linear ) ) then
+ if fillColor_ then
+ begin
+ span.Construct(
+ @gr.m_allocator ,
+ @gr.m_fillGradientInterpolator ,
+ @gr.m_linearGradientFunction ,
+ @gr.m_fillGradient ,
+ gr.m_fillGradientD1 ,
+ gr.m_fillGradientD2 );
+
+ ren.Construct (renBase ,@span );
+ render_scanlines(@gr.m_rasterizer ,@gr.m_scanline ,@ren );
+
+ end
+ else
+ begin
+ span.Construct(
+ @gr.m_allocator ,
+ @gr.m_lineGradientInterpolator ,
+ @gr.m_linearGradientFunction ,
+ @gr.m_lineGradient ,
+ gr.m_lineGradientD1 ,
+ gr.m_lineGradientD2 );
+
+ ren.Construct (renBase ,@span );
+ render_scanlines(@gr.m_rasterizer ,@gr.m_scanline ,@ren );
+
+ end
+ else
+ if (fillColor_ and
+ (gr.m_fillGradientFlag = AGG_Radial ) ) or
+ (not fillColor_ and
+ (gr.m_lineGradientFlag = AGG_Radial ) ) then
+ if fillColor_ then
+ begin
+ span.Construct(
+ @gr.m_allocator ,
+ @gr.m_fillGradientInterpolator ,
+ @gr.m_radialGradientFunction ,
+ @gr.m_fillGradient ,
+ gr.m_fillGradientD1 ,
+ gr.m_fillGradientD2 );
+
+ ren.Construct (renBase ,@span );
+ render_scanlines(@gr.m_rasterizer ,@gr.m_scanline ,@ren );
+
+ end
+ else
+ begin
+ span.Construct(
+ @gr.m_allocator ,
+ @gr.m_lineGradientInterpolator ,
+ @gr.m_radialGradientFunction ,
+ @gr.m_lineGradient ,
+ gr.m_lineGradientD1 ,
+ gr.m_lineGradientD2 );
+
+ ren.Construct (renBase ,@span );
+ render_scanlines(@gr.m_rasterizer ,@gr.m_scanline ,@ren );
+
+ end
+ else
+ begin
+ if fillColor_ then
+ clr.Construct(gr.m_fillColor )
+ else
+ clr.Construct(gr.m_lineColor );
+
+ renSolid.color_ (@clr );
+ render_scanlines(@gr.m_rasterizer ,@gr.m_scanline ,renSolid );
+
+ end;
+
+end;
+
+{ AGG2DRENDERER_RENDER }
+procedure Agg2DRenderer_render(
+ gr : TAgg2D;
+ renBase : renderer_base_ptr;
+ renSolid : renderer_scanline_aa_solid_ptr;
+ ras : gray8_adaptor_type_ptr;
+ sl : gray8_scanline_type_ptr ); overload;
+var
+ span : span_gradient;
+ ren : renderer_scanline_aa;
+ clr : aggclr;
+
+begin
+ if gr.m_fillGradientFlag = AGG_Linear then
+ begin
+ span.Construct(
+ @gr.m_allocator ,
+ @gr.m_fillGradientInterpolator ,
+ @gr.m_linearGradientFunction ,
+ @gr.m_fillGradient ,
+ gr.m_fillGradientD1 ,
+ gr.m_fillGradientD2 );
+
+ ren.Construct (renBase ,@span );
+ render_scanlines(ras ,sl ,@ren );
+
+ end
+ else
+ if gr.m_fillGradientFlag = AGG_Radial then
+ begin
+ span.Construct(
+ @gr.m_allocator ,
+ @gr.m_fillGradientInterpolator ,
+ @gr.m_radialGradientFunction ,
+ @gr.m_fillGradient ,
+ gr.m_fillGradientD1 ,
+ gr.m_fillGradientD2 );
+
+ ren.Construct (renBase ,@span );
+ render_scanlines(ras ,sl ,@ren );
+
+ end
+ else
+ begin
+ clr.Construct (gr.m_fillColor );
+ renSolid.color_ (@clr );
+ render_scanlines(ras ,sl ,renSolid );
+
+ end;
+
+end;
+
+{ AGG2DRENDERER_RENDERIMAGE }
+procedure Agg2DRenderer_renderImage(
+ gr : TAgg2D;
+ img : PAggImage;
+ renBase : renderer_base_ptr;
+ interpolator : span_interpolator_linear_ptr );
+var
+ blend : TAggSpanConvImageBlend;
+
+ si : span_image_filter_rgba;
+ sg : span_image_filter_rgba_nn;
+ sb : span_image_filter_rgba_bilinear;
+ s2 : span_image_filter_rgba_2x2;
+ sa : span_image_resample_rgba_affine;
+ sc : span_converter;
+ ri : renderer_scanline_aa;
+
+ clr : aggclr;
+
+ resample : boolean;
+
+ sx ,sy : double;
+
+begin
+ case gr.m_pixf of
+ pf32bit :
+ blend.Construct(gr.m_imageBlendMode ,gr.m_imageBlendColor ,@gr.m_pixFormatCompPre );
+
+ else
+ blend.Construct(gr.m_imageBlendMode ,gr.m_imageBlendColor ,NIL );
+
+ end;
+
+ if gr.m_imageFilter = AGG_NoFilter then
+ begin
+ clr.ConstrInt(0 ,0 ,0 ,0 );
+ sg.Construct (@gr.m_allocator ,@img.renBuf ,@clr ,interpolator ,rgba_order );
+ sc.Construct (@sg ,@blend );
+ ri.Construct (renBase ,@sc );
+
+ render_scanlines(@gr.m_rasterizer ,@gr.m_scanline ,@ri );
+
+ end
+ else
+ begin
+ resample:=gr.m_imageResample = AGG_ResampleAlways;
+
+ if gr.m_imageResample = AGG_ResampleOnZoomOut then
+ begin
+ interpolator._transformer.scaling_abs(@sx ,@sy );
+
+ if (sx > 1.125 ) or
+ (sy > 1.125 ) then
+ resample:=true;
+
+ end;
+
+ if resample then
+ begin
+ clr.ConstrInt(0 ,0 ,0 ,0 );
+ sa.Construct(
+ @gr.m_allocator ,
+ @img.renBuf ,
+ @clr ,
+ interpolator ,
+ @gr.m_imageFilterLut ,
+ rgba_order );
+
+ sc.Construct(@sa ,@blend );
+ ri.Construct(renBase ,@sc );
+
+ render_scanlines(@gr.m_rasterizer ,@gr.m_scanline ,@ri );
+
+ end
+ else
+ if gr.m_imageFilter = AGG_Bilinear then
+ begin
+ clr.ConstrInt(0 ,0 ,0 ,0 );
+ sb.Construct(
+ @gr.m_allocator ,
+ @img.renBuf ,
+ @clr ,
+ interpolator ,
+ rgba_order );
+
+ sc.Construct(@sb ,@blend );
+ ri.Construct(renBase ,@sc );
+
+ render_scanlines(@gr.m_rasterizer ,@gr.m_scanline ,@ri );
+
+ end
+ else
+ if gr.m_imageFilterLut.diameter = 2 then
+ begin
+ clr.ConstrInt(0 ,0 ,0 ,0 );
+ s2.Construct(
+ @gr.m_allocator ,
+ @img.renBuf ,
+ @clr ,
+ interpolator,
+ @gr.m_imageFilterLut ,
+ rgba_order );
+
+ sc.Construct(@s2 ,@blend );
+ ri.Construct(renBase ,@sc );
+
+ render_scanlines(@gr.m_rasterizer ,@gr.m_scanline ,@ri );
+
+ end
+ else
+ begin
+ clr.ConstrInt(0 ,0 ,0 ,0 );
+ si.Construct(
+ @gr.m_allocator ,
+ @img.renBuf ,
+ @clr ,
+ interpolator ,
+ @gr.m_imageFilterLut ,
+ rgba_order );
+
+ sc.Construct(@si ,@blend );
+ ri.Construct(renBase ,@sc );
+
+ render_scanlines(@gr.m_rasterizer ,@gr.m_scanline ,@ri );
+
+ end;
+
+ end;
+
+end;
+
+{ AGG2DUSESFREETYPE }
+function Agg2DUsesFreeType : boolean;
+begin
+{$IFDEF AGG2D_USE_FREETYPE }
+ result:=true;
+
+{$ELSE }
+ result:=false;
+
+{$ENDIF }
+
+end;
+
+{ CONSTRUCT }
+constructor TAggSpanConvImageBlend.Construct(m : TAggBlendMode; c : TAggColor; p : pixel_formats_ptr );
+begin
+ m_mode :=m;
+ m_color:=c;
+ m_pixel:=p;
+
+end;
+
+{ CONVERT }
+procedure TAggSpanConvImageBlend.convert(span : aggclr_ptr; x ,y : int; len : unsigned );
+var
+ l2 ,a : unsigned;
+
+ s2 : PAggColor;
+
+begin
+ if (m_mode <> AGG_BlendDst ) and
+ (m_pixel <> NIL ) then
+ begin{!}
+ l2:=len;
+ s2:=PAggColor(span );
+
+ repeat
+ comp_op_adaptor_clip_to_dst_rgba_pre(
+ m_pixel ,
+ unsigned(m_mode ) ,
+ int8u_ptr(s2 ) ,
+ m_color.r ,
+ m_color.g ,
+ m_color.b ,
+ base_mask ,
+ cover_full );
+
+ inc(ptrcomp(s2 ) ,sizeof(aggclr ) );
+ dec(l2 );
+
+ until l2 = 0;
+
+ end;
+
+ if m_color.a < base_mask then
+ begin
+ l2:=len;
+ s2:=PAggColor(span );
+ a :=m_color.a;
+
+ repeat
+ s2.r:=(s2.r * a ) shr base_shift;
+ s2.g:=(s2.g * a ) shr base_shift;
+ s2.b:=(s2.b * a ) shr base_shift;
+ s2.a:=(s2.a * a ) shr base_shift;
+
+ inc(ptrcomp(s2 ) ,sizeof(aggclr ) );
+ dec(l2 );
+
+ until l2 = 0;
+
+ end;
+
+end;
+
+{ DEG2RAD }
+function deg2Rad(v : double ) : double;
+begin
+ result:=v * agg_basics.pi / 180.0;
+
+end;
+
+{ RAD2DEG }
+function rad2Deg(v : double ) : double;
+begin
+ result:=v * 180.0 / agg_basics.pi;
+
+end;
+
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor TAggImage.Construct;
+begin
+ renBuf.Construct;
+
+end;
+
+{ DESTRUCT }
+destructor TAggImage.Destruct;
+begin
+ renBuf.Destruct;
+
+end;
+
+{ ATTACH }
+function TAggImage.attach(bitmap : TBitmap; flip : boolean ) : boolean;
+var
+ buffer : pointer;
+ stride : integer;
+
+begin
+ result:=false;
+
+ if Assigned(bitmap ) and
+ not bitmap.Empty then
+ case bitmap.PixelFormat of
+ pf32bit :
+ begin
+ { Rendering Buffer }
+ stride:=integer(bitmap.ScanLine[1 ] ) - integer(bitmap.ScanLine[0 ] );
+
+ if stride < 0 then
+ buffer:=bitmap.ScanLine[bitmap.Height - 1 ]
+ else
+ buffer:=bitmap.ScanLine[0 ];
+
+ if flip then
+ stride:=stride * -1;
+
+ renBuf.attach(
+ buffer ,
+ bitmap.Width ,
+ bitmap.Height ,
+ stride );
+
+ { OK }
+ result:=true;
+
+ end;
+
+ end;
+
+end;
+
+{ WIDTH }
+function TAggImage.width : int;
+begin
+ result:=renBuf._width;
+
+end;
+
+{ HEIGHT }
+function TAggImage.height : int;
+begin
+ result:=renBuf._height;
+
+end;
+
+{ CONSTRUCT }
+constructor TAggRasterizerGamma.Construct(alpha ,gamma : double );
+begin
+ m_alpha.Construct(alpha );
+ m_gamma.Construct(gamma );
+
+end;
+
+{ FUNC_OPERATOR_GAMMA }
+function TAggRasterizerGamma.func_operator_gamma(x : double ) : double;
+begin
+ result:=m_alpha.func_operator_gamma(m_gamma.func_operator_gamma(x ) );
+
+end;
+
+{ CREATE }
+constructor TAgg2D.Create;
+begin
+ m_rbuf.Construct;
+
+ m_pixf:=pf32bit;
+
+ pixfmt_rgba32 (m_pixFormat ,@m_rbuf );
+ pixfmt_custom_blend_rgba(m_pixFormatComp ,@m_rbuf ,@comp_op_adaptor_rgba ,rgba_order );
+ pixfmt_rgba32 (m_pixFormatPre ,@m_rbuf );
+ pixfmt_custom_blend_rgba(m_pixFormatCompPre ,@m_rbuf ,@comp_op_adaptor_rgba ,rgba_order );
+
+ m_renBase.Construct (@m_pixFormat );
+ m_renBaseComp.Construct (@m_pixFormatComp );
+ m_renBasePre.Construct (@m_pixFormatPre );
+ m_renBaseCompPre.Construct(@m_pixFormatCompPre );
+
+ m_renSolid.Construct (@m_renBase );
+ m_renSolidComp.Construct(@m_renBaseComp );
+
+ m_allocator.Construct;
+ m_clipBox.Construct(0 ,0 ,0 ,0 );
+
+ m_blendMode :=AGG_BlendAlpha;
+ m_imageBlendMode:=AGG_BlendDst;
+
+ m_imageBlendColor.Construct(0 ,0 ,0 );
+
+ m_scanline.Construct;
+ m_rasterizer.Construct;
+
+ m_masterAlpha :=1.0;
+ m_antiAliasGamma:=1.0;
+
+ m_fillColor.Construct(255 ,255 ,255 );
+ m_lineColor.Construct(0 ,0 ,0 );
+
+ m_fillGradient.Construct(256 ,sizeof(aggclr ) );
+ m_lineGradient.Construct(256 ,sizeof(aggclr ) );
+
+ m_lineCap :=AGG_CapRound;
+ m_lineJoin:=AGG_JoinRound;
+
+ m_fillGradientFlag:=AGG_Solid;
+ m_lineGradientFlag:=AGG_Solid;
+
+ m_fillGradientMatrix.Construct;
+ m_lineGradientMatrix.Construct;
+
+ m_fillGradientD1:=0.0;
+ m_lineGradientD1:=0.0;
+ m_fillGradientD2:=100.0;
+ m_lineGradientD2:=100.0;
+
+ m_textAngle :=0.0;
+ m_textAlignX :=AGG_AlignLeft;
+ m_textAlignY :=AGG_AlignBottom;
+ m_textHints :=true;
+ m_fontHeight :=0.0;
+ m_fontAscent :=0.0;
+ m_fontDescent:=0.0;
+
+ m_fontCacheType:=AGG_RasterFontCache;
+ m_imageFilter :=AGG_Bilinear;
+ m_imageResample:=AGG_NoResample;
+
+ m_gammaNone.Construct;
+
+ m_ifBilinear.Construct;
+ m_ifHanning.Construct;
+ m_ifHermite.Construct;
+ m_ifQuadric.Construct;
+ m_ifBicubic.Construct;
+ m_ifCatrom.Construct;
+ m_ifSpline16.Construct;
+ m_ifSpline36.Construct;
+ m_ifBlackman144.Construct;
+
+ m_imageFilterLut.Construct(@m_ifBilinear ,true );
+
+ m_linearGradientFunction.Construct;
+ m_radialGradientFunction.Construct;
+
+ m_fillGradientInterpolator.Construct(@m_fillGradientMatrix );
+ m_lineGradientInterpolator.Construct(@m_lineGradientMatrix );
+
+ m_lineWidth :=1;
+ m_evenOddFlag:=false;
+
+ m_imageFlip:=false;
+
+ m_path.Construct;
+ m_transform.Construct;
+
+ m_convCurve.Construct (@m_path );
+ m_convStroke.Construct(@m_convCurve );
+
+ m_pathTransform.Construct (@m_convCurve ,@m_transform );
+ m_strokeTransform.Construct(@m_convStroke ,@m_transform );
+
+{$IFDEF AGG2D_USE_FREETYPE }
+ m_fontEngine.Construct;
+
+{$ELSE }
+ m_fontDC:=GetDC(0 );
+
+ m_fontEngine.Construct(m_fontDC );
+
+{$ENDIF }
+
+ m_fontCacheManager.Construct(@m_fontEngine );
+
+ LineCap (m_lineCap );
+ LineJoin(m_lineJoin );
+
+end;
+
+{ DESTROY }
+destructor TAgg2D.Destroy;
+begin
+ m_rbuf.Destruct;
+
+ m_allocator.Destruct;
+
+ m_scanline.Destruct;
+ m_rasterizer.Destruct;
+
+ m_fillGradient.Destruct;
+ m_lineGradient.Destruct;
+
+ m_imageFilterLut.Destruct;
+ m_path.Destruct;
+
+ m_convCurve.Destruct;
+ m_convStroke.Destruct;
+
+ m_fontEngine.Destruct;
+ m_fontCacheManager.Destruct;
+
+{$IFNDEF AGG2D_USE_FREETYPE }
+ ReleaseDC(0 ,m_fontDC );
+
+{$ENDIF }
+
+end;
+
+{ ATTACH }
+function TAgg2D.Attach(bitmap : TBitmap; flip_y : boolean = false ) : boolean;
+var
+ buffer : pointer;
+ stride : integer;
+
+begin
+ result:=false;
+
+ if Assigned(bitmap ) and
+ not bitmap.Empty then
+ case bitmap.PixelFormat of
+ pf24bit ,pf32bit :
+ begin
+ { Rendering Buffer }
+ stride:=integer(bitmap.ScanLine[1 ] ) - integer(bitmap.ScanLine[0 ] );
+
+ if stride < 0 then
+ buffer:=bitmap.ScanLine[bitmap.Height - 1 ]
+ else
+ buffer:=bitmap.ScanLine[0 ];
+
+ if flip_y then
+ stride:=stride * -1;
+
+ m_rbuf.attach(
+ buffer ,
+ bitmap.Width ,
+ bitmap.Height ,
+ stride );
+
+ { Pixel Format }
+ m_pixf:=bitmap.PixelFormat;
+
+ case m_pixf of
+ pf24bit :
+ begin
+ pixfmt_rgb24(m_pixFormat ,@m_rbuf );
+ pixfmt_rgb24(m_pixFormatPre ,@m_rbuf );
+
+ end;
+
+ pf32bit :
+ begin
+ pixfmt_rgba32 (m_pixFormat ,@m_rbuf );
+ pixfmt_custom_blend_rgba(m_pixFormatComp ,@m_rbuf ,@comp_op_adaptor_rgba ,rgba_order );
+ pixfmt_rgba32 (m_pixFormatPre ,@m_rbuf );
+ pixfmt_custom_blend_rgba(m_pixFormatCompPre ,@m_rbuf ,@comp_op_adaptor_rgba ,rgba_order );
+
+ end;
+
+ end;
+
+ { Reset state }
+ m_renBase.reset_clipping (true );
+ m_renBaseComp.reset_clipping (true );
+ m_renBasePre.reset_clipping (true );
+ m_renBaseCompPre.reset_clipping(true );
+
+ ResetTransformations;
+
+ LineWidth(1.0 );
+ LineColor(0 ,0 ,0 );
+ FillColor(255 ,255 ,255 );
+
+ TextAlignment(AGG_AlignLeft ,AGG_AlignBottom );
+
+ ClipBox (0 ,0 ,bitmap.Width ,bitmap.Height );
+ LineCap (AGG_CapRound );
+ LineJoin(AGG_JoinRound );
+ FlipText(false );
+
+ ImageFilter (AGG_Bilinear );
+ ImageResample(AGG_NoResample );
+ ImageFlip (false );
+
+ m_masterAlpha :=1.0;
+ m_antiAliasGamma:=1.0;
+
+ m_rasterizer.gamma(@m_gammaNone );
+
+ m_blendMode:=AGG_BlendAlpha;
+
+ FillEvenOdd(false );
+ BlendMode (AGG_BlendAlpha );
+
+ FlipText(false );
+ ResetPath;
+
+ ImageFilter (AGG_Bilinear );
+ ImageResample(AGG_NoResample );
+
+ { OK }
+ result:=true;
+
+ end;
+
+ end;
+
+end;
+
+{ CLIPBOX }
+procedure TAgg2D.ClipBox(x1 ,y1 ,x2 ,y2 : double );
+var
+ rx1 ,ry1 ,rx2 ,ry2 : int;
+
+begin
+ m_clipBox.Construct(x1 ,y1 ,x2 ,y2 );
+
+ rx1:=Trunc(x1 );
+ ry1:=Trunc(y1 );
+ rx2:=Trunc(x2 );
+ ry2:=Trunc(y2 );
+
+ m_renBase.clip_box_ (rx1 ,ry1 ,rx2 ,ry2 );
+ m_renBaseComp.clip_box_ (rx1 ,ry1 ,rx2 ,ry2 );
+ m_renBasePre.clip_box_ (rx1 ,ry1 ,rx2 ,ry2 );
+ m_renBaseCompPre.clip_box_(rx1 ,ry1 ,rx2 ,ry2 );
+
+ m_rasterizer.clip_box(x1 ,y1 ,x2 ,y2 );
+
+end;
+
+{ CLIPBOX }
+function TAgg2D.ClipBox : TAggRectD;
+begin
+ result:=m_clipBox;
+
+end;
+
+{ CLEARALL }
+procedure TAgg2D.ClearAll(c : TAggColor );
+var
+ clr : aggclr;
+
+begin
+ clr.Construct (c );
+ m_renBase.clear(@clr );
+
+end;
+
+{ CLEARALL }
+procedure TAgg2D.ClearAll(r ,g ,b : byte; a : byte = 255 );
+var
+ clr : TAggColor;
+
+begin
+ clr.Construct(r ,g ,b ,a );
+ ClearAll (clr );
+
+end;
+
+{ CLEARCLIPBOX }
+procedure TAgg2D.ClearClipBox(c : TAggColor );
+var
+ clr : aggclr;
+
+begin
+ clr.Construct(c );
+
+ m_renBase.copy_bar(0 ,0 ,m_renBase.width ,m_renBase.height ,@clr );
+
+end;
+
+{ CLEARCLIPBOX }
+procedure TAgg2D.ClearClipBox(r ,g ,b : byte; a : byte = 255 );
+var
+ clr : TAggColor;
+
+begin
+ clr.Construct(r ,g ,b ,a );
+ ClearClipBox (clr );
+
+end;
+
+{ WORLDTOSCREEN }
+procedure TAgg2D.WorldToScreen(x ,y : PDouble );
+begin
+ m_transform.transform(@m_transform ,double_ptr(x ) ,double_ptr(y ) );
+
+end;
+
+{ SCREENTOWORLD }
+procedure TAgg2D.ScreenToWorld(x ,y : PDouble );
+begin
+ m_transform.inverse_transform(@m_transform ,double_ptr(x ) ,double_ptr(y ) );
+
+end;
+
+{ WORLDTOSCREEN }
+function TAgg2D.WorldToScreen(scalar : double ) : double;
+var
+ x1 ,y1 ,x2 ,y2 : double;
+
+begin
+ x1:=0;
+ y1:=0;
+ x2:=scalar;
+ y2:=scalar;
+
+ WorldToScreen(@x1 ,@y1 );
+ WorldToScreen(@x2 ,@y2 );
+
+ result:=Sqrt((x2 - x1 ) * (x2 - x1 ) + (y2 - y1 ) * (y2 - y1 ) ) * 0.7071068;
+
+end;
+
+{ SCREENTOWORLD }
+function TAgg2D.ScreenToWorld(scalar : double ) : double;
+var
+ x1 ,y1 ,x2 ,y2 : double;
+
+begin
+ x1:=0;
+ y1:=0;
+ x2:=scalar;
+ y2:=scalar;
+
+ ScreenToWorld(@x1 ,@y1 );
+ ScreenToWorld(@x2 ,@y2 );
+
+ result:=Sqrt((x2 - x1 ) * (x2 - x1 ) + (y2 - y1 ) * (y2 - y1 ) ) * 0.7071068;
+
+end;
+
+{ ALIGNPOINT }
+procedure TAgg2D.AlignPoint(x ,y : PDouble );
+begin
+ WorldToScreen(x ,y );
+
+ x^:=Floor(x^ ) + 0.5;
+ y^:=Floor(y^ ) + 0.5;
+
+ ScreenToWorld(x ,y );
+
+end;
+
+{ INBOX }
+function TAgg2D.InBox(worldX ,worldY : double ) : boolean;
+begin
+ WorldToScreen(@worldX ,@worldY );
+
+ result:=m_renBase.inbox(Trunc(worldX ) ,Trunc(worldY ) );
+
+end;
+
+{ BLENDMODE }
+procedure TAgg2D.BlendMode(m : TAggBlendMode );
+begin
+ m_blendMode:=m;
+
+ m_pixFormatComp.comp_op_ (unsigned(m ) );
+ m_pixFormatCompPre.comp_op_(unsigned(m ) );
+
+end;
+
+{ BLENDMODE }
+function TAgg2D.BlendMode : TAggBlendMode;
+begin
+ result:=m_blendMode;
+
+end;
+
+{ MASTERALPHA }
+procedure TAgg2D.MasterAlpha(a : double );
+begin
+ m_masterAlpha:=a;
+
+ UpdateRasterizerGamma;
+
+end;
+
+{ MASTERALPHA }
+function TAgg2D.MasterAlpha : double;
+begin
+ result:=m_masterAlpha;
+
+end;
+
+{ ANTIALIASGAMMA }
+procedure TAgg2D.AntiAliasGamma(g : double );
+begin
+ m_antiAliasGamma:=g;
+
+ UpdateRasterizerGamma;
+
+end;
+
+{ ANTIALIASGAMMA }
+function TAgg2D.AntiAliasGamma : double;
+begin
+ result:=m_antiAliasGamma;
+
+end;
+
+{ FILLCOLOR }
+procedure TAgg2D.FillColor(c : TAggColor );
+begin
+ m_fillColor :=c;
+ m_fillGradientFlag:=AGG_Solid;
+
+end;
+
+{ FILLCOLOR }
+procedure TAgg2D.FillColor(r ,g ,b : byte; a : byte = 255 );
+var
+ clr : TAggColor;
+
+begin
+ clr.Construct(r ,g ,b ,a );
+ FillColor (clr );
+
+end;
+
+{ NOFILL }
+procedure TAgg2D.NoFill;
+var
+ clr : TAggColor;
+
+begin
+ clr.Construct(0 ,0 ,0 ,0 );
+ FillColor (clr );
+
+end;
+
+{ LINECOLOR }
+procedure TAgg2D.LineColor(c : TAggColor );
+begin
+ m_lineColor :=c;
+ m_lineGradientFlag:=AGG_Solid;
+
+end;
+
+{ LINECOLOR }
+procedure TAgg2D.LineColor(r ,g ,b : byte; a : byte = 255 );
+var
+ clr : TAggColor;
+
+begin
+ clr.Construct(r ,g ,b ,a );
+ LineColor (clr );
+
+end;
+
+{ NOLINE }
+procedure TAgg2D.NoLine;
+var
+ clr : TAggColor;
+
+begin
+ clr.Construct(0 ,0 ,0 ,0 );
+ LineColor (clr );
+
+end;
+
+{ FILLCOLOR }
+function TAgg2D.FillColor : TAggColor;
+begin
+ result:=m_fillColor;
+
+end;
+
+{ LINECOLOR }
+function TAgg2D.LineColor : TAggColor;
+begin
+ result:=m_lineColor;
+
+end;
+
+{ FILLLINEARGRADIENT }
+procedure TAgg2D.FillLinearGradient(x1 ,y1 ,x2 ,y2 : double; c1 ,c2 : TAggColor; profile : double = 1.0 );
+var
+ i ,startGradient ,endGradient : int;
+
+ k ,angle : double;
+
+ c : TAggColor;
+
+ clr : aggclr;
+ tar : trans_affine_rotation;
+ tat : trans_affine_translation;
+
+begin
+ startGradient:=128 - Trunc(profile * 127.0 );
+ endGradient :=128 + Trunc(profile * 127.0 );
+
+ if endGradient <= startGradient then
+ endGradient:=startGradient + 1;
+
+ k:=1.0 / (endGradient - startGradient );
+ i:=0;
+
+ while i < startGradient do
+ begin
+ clr.Construct(c1 );
+
+ move(clr ,m_fillGradient.array_operator(i )^ ,sizeof(aggclr ) );
+ inc (i );
+
+ end;
+
+ while i < endGradient do
+ begin
+ c:=c1.gradient(c2 ,(i - startGradient ) * k );
+
+ clr.Construct(c );
+
+ move(clr ,m_fillGradient.array_operator(i )^ ,sizeof(aggclr ) );
+ inc (i );
+
+ end;
+
+ while i < 256 do
+ begin
+ clr.Construct(c2 );
+
+ move(clr ,m_fillGradient.array_operator(i )^ ,sizeof(aggclr ) );
+ inc (i );
+
+ end;
+
+ angle:=ArcTan2(y2 - y1 ,x2 - x1 );
+
+ m_fillGradientMatrix.reset;
+
+ tar.Construct(angle );
+
+ m_fillGradientMatrix.multiply(@tar );
+
+ tat.Construct(x1 ,y1 );
+
+ m_fillGradientMatrix.multiply(@tat );
+ m_fillGradientMatrix.multiply(@m_transform );
+ m_fillGradientMatrix.invert;
+
+ m_fillGradientD1 :=0.0;
+ m_fillGradientD2 :=Sqrt((x2 - x1 ) * (x2 - x1 ) + (y2 - y1 ) * (y2 - y1 ) );
+ m_fillGradientFlag:=AGG_Linear;
+
+ m_fillColor.Construct(0 ,0 ,0 ); // Set some real color
+
+end;
+
+{ LINELINEARGRADIENT }
+procedure TAgg2D.LineLinearGradient(x1 ,y1 ,x2 ,y2 : double; c1 ,c2 : TAggColor; profile : double = 1.0 );
+var
+ i ,startGradient ,endGradient : int;
+
+ k ,angle : double;
+
+ c : TAggColor;
+
+ clr : aggclr;
+ tar : trans_affine_rotation;
+ tat : trans_affine_translation;
+
+begin
+ startGradient:=128 - Trunc(profile * 128.0 );
+ endGradient :=128 + Trunc(profile * 128.0 );
+
+ if endGradient <= startGradient then
+ endGradient:=startGradient + 1;
+
+ k:=1.0 / (endGradient - startGradient );
+ i:=0;
+
+ while i < startGradient do
+ begin
+ clr.Construct(c1 );
+
+ move(clr ,m_lineGradient.array_operator(i )^ ,sizeof(aggclr ) );
+ inc (i );
+
+ end;
+
+ while i < endGradient do
+ begin
+ c:=c1.gradient(c2 ,(i - startGradient) * k );
+
+ clr.Construct(c );
+
+ move(clr ,m_lineGradient.array_operator(i )^ ,sizeof(aggclr ) );
+ inc (i );
+
+ end;
+
+ while i < 256 do
+ begin
+ clr.Construct(c2 );
+
+ move(clr ,m_lineGradient.array_operator(i )^ ,sizeof(aggclr ) );
+ inc (i );
+
+ end;
+
+ angle:=ArcTan2(y2 - y1 ,x2 - x1 );
+
+ m_lineGradientMatrix.reset;
+
+ tar.Construct(angle );
+
+ m_lineGradientMatrix.multiply(@tar );
+
+ tat.Construct(x1 ,y1 );
+
+ m_lineGradientMatrix.multiply(@tat );
+ m_lineGradientMatrix.multiply(@m_transform );
+ m_lineGradientMatrix.invert;
+
+ m_lineGradientD1 :=0.0;
+ m_lineGradientD2 :=Sqrt((x2 - x1 ) * (x2 - x1 ) + (y2 - y1 ) * (y2 - y1 ) );
+ m_lineGradientFlag:=AGG_Linear;
+
+ m_lineColor.Construct(0 ,0 ,0 ); // Set some real color
+
+end;
+
+{ FILLRADIALGRADIENT }
+procedure TAgg2D.FillRadialGradient(x ,y ,r : double; c1 ,c2 : TAggColor; profile : double = 1.0 );
+var
+ i ,startGradient ,endGradient : int;
+
+ k : double;
+ c : TAggColor;
+
+ clr : aggclr;
+ tat : trans_affine_translation;
+
+begin
+ startGradient:=128 - Trunc(profile * 127.0 );
+ endGradient :=128 + Trunc(profile * 127.0 );
+
+ if endGradient <= startGradient then
+ endGradient:=startGradient + 1;
+
+ k:=1.0 / (endGradient - startGradient );
+ i:=0;
+
+ while i < startGradient do
+ begin
+ clr.Construct(c1 );
+
+ move(clr ,m_fillGradient.array_operator(i )^ ,sizeof(aggclr ) );
+ inc (i );
+
+ end;
+
+ while i < endGradient do
+ begin
+ c:=c1.gradient(c2 ,(i - startGradient ) * k );
+
+ clr.Construct(c );
+
+ move(clr ,m_fillGradient.array_operator(i )^ ,sizeof(aggclr ) );
+ inc (i );
+
+ end;
+
+ while i < 256 do
+ begin
+ clr.Construct(c2 );
+
+ move(clr ,m_fillGradient.array_operator(i )^ ,sizeof(aggclr ) );
+ inc (i );
+
+ end;
+
+ m_fillGradientD2:=worldToScreen(r );
+
+ WorldToScreen(@x ,@y );
+
+ m_fillGradientMatrix.reset;
+
+ tat.Construct(x ,y );
+
+ m_fillGradientMatrix.multiply(@tat );
+ m_fillGradientMatrix.invert;
+
+ m_fillGradientD1 :=0;
+ m_fillGradientFlag:=AGG_Radial;
+
+ m_fillColor.Construct(0 ,0 ,0 ); // Set some real color
+
+end;
+
+{ LINERADIALGRADIENT }
+procedure TAgg2D.LineRadialGradient(x ,y ,r : double; c1 ,c2 : TAggColor; profile : double = 1.0 );
+var
+ i ,startGradient ,endGradient : int;
+
+ k : double;
+ c : TAggColor;
+
+ clr : aggclr;
+ tat : trans_affine_translation;
+
+begin
+ startGradient:=128 - Trunc(profile * 128.0 );
+ endGradient :=128 + Trunc(profile * 128.0 );
+
+ if endGradient <= startGradient then
+ endGradient:=startGradient + 1;
+
+ k:=1.0 / (endGradient - startGradient );
+ i:=0;
+
+ while i < startGradient do
+ begin
+ clr.Construct(c1 );
+
+ move(clr ,m_lineGradient.array_operator(i )^ ,sizeof(aggclr ) );
+ inc (i );
+
+ end;
+
+ while i < endGradient do
+ begin
+ c:=c1.gradient(c2 ,(i - startGradient ) * k );
+
+ clr.Construct(c );
+
+ move(clr ,m_lineGradient.array_operator(i )^ ,sizeof(aggclr ) );
+ inc (i );
+
+ end;
+
+ while i < 256 do
+ begin
+ clr.Construct(c2 );
+
+ move(clr ,m_lineGradient.array_operator(i )^ ,sizeof(aggclr ) );
+ inc (i );
+
+ end;
+
+ m_lineGradientD2:=worldToScreen(r );
+
+ WorldToScreen(@x ,@y );
+
+ m_lineGradientMatrix.reset;
+
+ tat.Construct(x ,y );
+
+ m_lineGradientMatrix.multiply(@tat );
+ m_lineGradientMatrix.invert;
+
+ m_lineGradientD1 :=0;
+ m_lineGradientFlag:=AGG_Radial;
+
+ m_lineColor.Construct(0 ,0 ,0 ); // Set some real color
+
+end;
+
+{ FILLRADIALGRADIENT }
+procedure TAgg2D.FillRadialGradient(x ,y ,r : double; c1 ,c2 ,c3 : TAggColor );
+var
+ i : int;
+ c : TAggColor;
+
+ clr : aggclr;
+ tat : trans_affine_translation;
+
+begin
+ i:=0;
+
+ while i < 128 do
+ begin
+ c:=c1.gradient(c2 ,i / 127.0 );
+
+ clr.Construct(c );
+
+ move(clr ,m_fillGradient.array_operator(i )^ ,sizeof(aggclr ) );
+ inc (i );
+
+ end;
+
+ while i < 256 do
+ begin
+ c:=c2.gradient(c3 ,(i - 128 ) / 127.0 );
+
+ clr.Construct(c );
+
+ move(clr ,m_fillGradient.array_operator(i )^ ,sizeof(aggclr ) );
+ inc (i );
+
+ end;
+
+ m_fillGradientD2:=worldToScreen(r );
+
+ WorldToScreen(@x ,@y );
+
+ m_fillGradientMatrix.reset;
+
+ tat.Construct(x ,y );
+
+ m_fillGradientMatrix.multiply(@tat );
+ m_fillGradientMatrix.invert;
+
+ m_fillGradientD1 :=0;
+ m_fillGradientFlag:=AGG_Radial;
+
+ m_fillColor.Construct(0 ,0 ,0 ); // Set some real color
+
+end;
+
+{ LINERADIALGRADIENT }
+procedure TAgg2D.LineRadialGradient(x ,y ,r : double; c1 ,c2 ,c3 : TAggColor );
+var
+ i : int;
+ c : TAggColor;
+
+ clr : aggclr;
+ tat : trans_affine_translation;
+
+begin
+ i:=0;
+
+ while i < 128 do
+ begin
+ c:=c1.gradient(c2 ,i / 127.0 );
+
+ clr.Construct(c );
+
+ move(clr ,m_lineGradient.array_operator(i )^ ,sizeof(aggclr ) );
+ inc (i );
+
+ end;
+
+ while i < 256 do
+ begin
+ c:=c2.gradient(c3 ,(i - 128 ) / 127.0 );
+
+ clr.Construct(c );
+
+ move(clr ,m_lineGradient.array_operator(i )^ ,sizeof(aggclr ) );
+ inc (i );
+
+ end;
+
+ m_lineGradientD2:=worldToScreen(r );
+
+ WorldToScreen(@x ,@y );
+
+ m_lineGradientMatrix.reset;
+
+ tat.Construct(x ,y );
+
+ m_lineGradientMatrix.multiply(@tat );
+ m_lineGradientMatrix.invert;
+
+ m_lineGradientD1 :=0;
+ m_lineGradientFlag:=AGG_Radial;
+
+ m_lineColor.Construct(0 ,0 ,0 ); // Set some real color
+
+end;
+
+{ FILLRADIALGRADIENT }
+procedure TAgg2D.FillRadialGradient(x ,y ,r : double );
+var
+ tat : trans_affine_translation;
+
+begin
+ m_fillGradientD2:=worldToScreen(r );
+
+ WorldToScreen(@x ,@y );
+
+ m_fillGradientMatrix.reset;
+
+ tat.Construct(x ,y );
+
+ m_fillGradientMatrix.multiply(@tat );
+ m_fillGradientMatrix.invert;
+
+ m_fillGradientD1:=0;
+
+end;
+
+{ LINERADIALGRADIENT }
+procedure TAgg2D.LineRadialGradient(x ,y ,r : double );
+var
+ tat : trans_affine_translation;
+
+begin
+ m_lineGradientD2:=worldToScreen(r );
+
+ WorldToScreen(@x ,@y );
+
+ m_lineGradientMatrix.reset;
+
+ tat.Construct(x ,y );
+
+ m_lineGradientMatrix.multiply(@tat );
+ m_lineGradientMatrix.invert;
+
+ m_lineGradientD1:=0;
+
+end;
+
+{ LINEWIDTH }
+procedure TAgg2D.LineWidth(w : double );
+begin
+ m_lineWidth:=w;
+
+ m_convStroke.width_(w );
+
+end;
+
+{ LINEWIDTH }
+function TAgg2D.LineWidth : double;
+begin
+ result:=m_lineWidth;
+
+end;
+
+{ LINECAP }
+procedure TAgg2D.LineCap(cap : TAggLineCap );
+begin
+ m_lineCap:=cap;
+
+ m_convStroke.line_cap_(cap );
+
+end;
+
+{ LINECAP }
+function TAgg2D.LineCap : TAggLineCap;
+begin
+ result:=m_lineCap;
+
+end;
+
+{ LINEJOIN }
+procedure TAgg2D.LineJoin(join : TAggLineJoin );
+begin
+ m_lineJoin:=join;
+
+ m_convStroke.line_join_(join );
+
+end;
+
+{ LINEJOIN }
+function TAgg2D.LineJoin : TAggLineJoin;
+begin
+ result:=m_lineJoin;
+
+end;
+
+{ FILLEVENODD }
+procedure TAgg2D.FillEvenOdd(evenOddFlag : boolean );
+begin
+ m_evenOddFlag:=evenOddFlag;
+
+ if evenOddFlag then
+ m_rasterizer.filling_rule(fill_even_odd )
+ else
+ m_rasterizer.filling_rule(fill_non_zero );
+
+end;
+
+{ FILLEVENODD }
+function TAgg2D.FillEvenOdd : boolean;
+begin
+ result:=m_evenOddFlag;
+
+end;
+
+{ TRANSFORMATIONS }
+function TAgg2D.Transformations : TAggTransformations;
+begin
+ m_transform.store_to(@result.affineMatrix[0 ] );
+
+end;
+
+{ TRANSFORMATIONS }
+procedure TAgg2D.Transformations(tr : PAggTransformations );
+begin
+ m_transform.load_from(@tr.affineMatrix[0 ] );
+
+ m_convCurve.approximation_scale_ (worldToScreen(1.0 ) * g_approxScale );
+ m_convStroke.approximation_scale_(worldToScreen(1.0 ) * g_approxScale );
+
+end;
+
+{ RESETTRANSFORMATIONS }
+procedure TAgg2D.ResetTransformations;
+begin
+ m_transform.reset;
+
+end;
+
+{ AFFINE }
+procedure TAgg2D.Affine(tr : PAggAffine );
+begin
+ m_transform.multiply(tr );
+
+ m_convCurve.approximation_scale_ (WorldToScreen(1.0 ) * g_approxScale );
+ m_convStroke.approximation_scale_(WorldToScreen(1.0 ) * g_approxScale );
+
+end;
+
+{ AFFINE }
+procedure TAgg2D.Affine(tr : PAggTransformations );
+var
+ ta : trans_affine;
+
+begin
+ ta.Construct(
+ tr.affineMatrix[0 ] ,tr.affineMatrix[1 ] ,tr.affineMatrix[2 ] ,
+ tr.affineMatrix[3 ] ,tr.affineMatrix[4 ] ,tr.affineMatrix[5 ] );
+
+ affine(PAggAffine(@ta ) );
+
+end;
+
+{ ROTATE }
+procedure TAgg2D.Rotate(angle : double );
+var
+ tar : trans_affine_rotation;
+
+begin
+ tar.Construct(angle );
+
+ m_transform.multiply(@tar );
+
+end;
+
+{ SCALE }
+procedure TAgg2D.Scale(sx ,sy : double );
+var
+ tas : trans_affine_scaling;
+
+begin
+ tas.Construct(sx ,sy );
+
+ m_transform.multiply(@tas );
+
+ m_convCurve.approximation_scale_ (worldToScreen(1.0 ) * g_approxScale );
+ m_convStroke.approximation_scale_(worldToScreen(1.0 ) * g_approxScale );
+
+end;
+
+{ SKEW }
+procedure TAgg2D.Skew(sx ,sy : double );
+var
+ tas : trans_affine_skewing;
+
+begin
+ tas.Construct(sx ,sy );
+
+ m_transform.multiply(@tas );
+
+end;
+
+{ TRANSLATE }
+procedure TAgg2D.Translate(x ,y : double );
+var
+ tat : trans_affine_translation;
+
+begin
+ tat.Construct(x ,y );
+
+ m_transform.multiply(@tat );
+
+end;
+
+{ PARALLELOGRAM }
+procedure TAgg2D.Parallelogram(x1 ,y1 ,x2 ,y2 : double; para : PDouble );
+var
+ ta : trans_affine;
+
+begin
+ ta.Construct(x1 ,y1 ,x2 ,y2 ,parallelo_ptr(para ) );
+
+ m_transform.multiply(@ta );
+
+ m_convCurve.approximation_scale_ (worldToScreen(1.0 ) * g_approxScale );
+ m_convStroke.approximation_scale_(worldToScreen(1.0 ) * g_approxScale );
+
+end;
+
+{ VIEWPORT }
+procedure TAgg2D.Viewport(
+ worldX1 ,worldY1 ,worldX2 ,worldY2 ,
+ screenX1 ,screenY1 ,screenX2 ,screenY2 : double;
+ opt : TAggViewportOption = AGG_XMidYMid );
+var
+ vp : trans_viewport;
+ mx : trans_affine;
+
+begin
+ vp.Construct;
+
+ case opt of
+ AGG_Anisotropic :
+ vp.preserve_aspect_ratio(0.0 ,0.0 ,aspect_ratio_stretch );
+
+ AGG_XMinYMin :
+ vp.preserve_aspect_ratio(0.0 ,0.0 ,aspect_ratio_meet );
+
+ AGG_XMidYMin :
+ vp.preserve_aspect_ratio(0.5 ,0.0 ,aspect_ratio_meet );
+
+ AGG_XMaxYMin :
+ vp.preserve_aspect_ratio(1.0 ,0.0 ,aspect_ratio_meet );
+
+ AGG_XMinYMid :
+ vp.preserve_aspect_ratio(0.0 ,0.5 ,aspect_ratio_meet );
+
+ AGG_XMidYMid :
+ vp.preserve_aspect_ratio(0.5 ,0.5 ,aspect_ratio_meet );
+
+ AGG_XMaxYMid :
+ vp.preserve_aspect_ratio(1.0 ,0.5 ,aspect_ratio_meet );
+
+ AGG_XMinYMax :
+ vp.preserve_aspect_ratio(0.0 ,1.0 ,aspect_ratio_meet );
+
+ AGG_XMidYMax :
+ vp.preserve_aspect_ratio(0.5 ,1.0 ,aspect_ratio_meet );
+
+ AGG_XMaxYMax :
+ vp.preserve_aspect_ratio(1.0 ,1.0 ,aspect_ratio_meet );
+
+ end;
+
+ vp.world_viewport (worldX1 ,worldY1 ,worldX2 ,worldY2 );
+ vp.device_viewport(screenX1 ,screenY1 ,screenX2 ,screenY2 );
+
+ mx.Construct;
+
+ vp.to_affine (@mx );
+ m_transform.multiply(@mx );
+
+ m_convCurve.approximation_scale_ (WorldToScreen(1.0 ) * g_approxScale );
+ m_convStroke.approximation_scale_(WorldToScreen(1.0 ) * g_approxScale );
+
+end;
+
+{ LINE }
+procedure TAgg2D.Line(x1 ,y1 ,x2 ,y2 : double );
+begin
+ m_path.remove_all;
+
+ addLine (x1 ,y1 ,x2 ,y2 );
+ DrawPath(AGG_StrokeOnly );
+
+end;
+
+{ TRIANGLE }
+procedure TAgg2D.Triangle(x1 ,y1 ,x2 ,y2 ,x3 ,y3 : double );
+begin
+ m_path.remove_all;
+ m_path.move_to(x1 ,y1 );
+ m_path.line_to(x2 ,y2 );
+ m_path.line_to(x3 ,y3 );
+ m_path.close_polygon;
+
+ DrawPath(AGG_FillAndStroke );
+
+end;
+
+{ RECTANGLE }
+procedure TAgg2D.Rectangle(x1 ,y1 ,x2 ,y2 : double );
+begin
+ m_path.remove_all;
+ m_path.move_to(x1 ,y1 );
+ m_path.line_to(x2 ,y1 );
+ m_path.line_to(x2 ,y2 );
+ m_path.line_to(x1 ,y2 );
+ m_path.close_polygon;
+
+ DrawPath(AGG_FillAndStroke );
+
+end;
+
+{ ROUNDEDRECT }
+procedure TAgg2D.RoundedRect(x1 ,y1 ,x2 ,y2 ,r : double );
+var
+ rc : rounded_rect;
+
+begin
+ m_path.remove_all;
+ rc.Construct(x1 ,y1 ,x2 ,y2 ,r );
+
+ rc.normalize_radius;
+ rc.approximation_scale_(worldToScreen(1.0 ) * g_approxScale );
+
+ m_path.add_path(@rc ,0 ,false );
+
+ DrawPath(AGG_FillAndStroke );
+
+end;
+
+{ ROUNDEDRECT }
+procedure TAgg2D.RoundedRect(x1 ,y1 ,x2 ,y2 ,rx ,ry : double );
+var
+ rc : rounded_rect;
+
+begin
+ m_path.remove_all;
+ rc.Construct;
+
+ rc.rect (x1 ,y1 ,x2 ,y2 );
+ rc.radius(rx ,ry );
+ rc.normalize_radius;
+
+ m_path.add_path(@rc ,0 ,false );
+
+ DrawPath(AGG_FillAndStroke );
+
+end;
+
+{ ROUNDEDRECT }
+procedure TAgg2D.RoundedRect(
+ x1 ,y1 ,x2 ,y2 ,
+ rxBottom ,ryBottom ,
+ rxTop ,ryTop : double );
+var
+ rc : rounded_rect;
+
+begin
+ m_path.remove_all;
+ rc.Construct;
+
+ rc.rect (x1 ,y1 ,x2 ,y2 );
+ rc.radius(rxBottom ,ryBottom ,rxTop ,ryTop );
+ rc.normalize_radius;
+
+ rc.approximation_scale_(worldToScreen(1.0 ) * g_approxScale );
+
+ m_path.add_path(@rc ,0 ,false );
+
+ DrawPath(AGG_FillAndStroke );
+
+end;
+
+{ ELLIPSE }
+procedure TAgg2D.Ellipse(cx ,cy ,rx ,ry : double );
+var
+ el : bezier_arc;
+
+begin
+ m_path.remove_all;
+
+ el.Construct(cx ,cy ,rx ,ry ,0 ,2 * pi );
+
+ m_path.add_path(@el ,0 ,false );
+ m_path.close_polygon;
+
+ DrawPath(AGG_FillAndStroke );
+
+end;
+
+{ ARC }
+procedure TAgg2D.Arc(cx ,cy ,rx ,ry ,start ,sweep : double );
+var
+ ar : {bezier_}agg_arc.arc;
+
+begin
+ m_path.remove_all;
+
+ ar.Construct(cx ,cy ,rx ,ry ,sweep ,start ,false );
+
+ m_path.add_path(@ar ,0 ,false );
+
+ DrawPath(AGG_StrokeOnly );
+
+end;
+
+{ STAR }
+procedure TAgg2D.Star(cx ,cy ,r1 ,r2 ,startAngle : double; numRays : integer );
+var
+ da ,a ,x ,y : double;
+
+ i : int;
+
+begin
+ m_path.remove_all;
+
+ da:=pi / numRays;
+ a :=startAngle;
+
+ i:=0;
+
+ while i < numRays do
+ begin
+ x:=Cos(a ) * r2 + cx;
+ y:=Sin(a ) * r2 + cy;
+
+ if i <> 0 then
+ m_path.line_to(x ,y )
+ else
+ m_path.move_to(x ,y );
+
+ a:=a + da;
+
+ m_path.line_to(Cos(a ) * r1 + cx ,Sin(a ) * r1 + cy );
+
+ a:=a + da;
+
+ inc(i );
+
+ end;
+
+ ClosePolygon;
+ DrawPath(AGG_FillAndStroke );
+
+end;
+
+{ CURVE }
+procedure TAgg2D.Curve(x1 ,y1 ,x2 ,y2 ,x3 ,y3 : double );
+begin
+ m_path.remove_all;
+ m_path.move_to(x1 ,y1 );
+ m_path.curve3 (x2 ,y2 ,x3 ,y3 );
+
+ DrawPath(AGG_StrokeOnly );
+
+end;
+
+{ CURVE }
+procedure TAgg2D.Curve(x1 ,y1 ,x2 ,y2 ,x3 ,y3 ,x4 ,y4 : double );
+begin
+ m_path.remove_all;
+ m_path.move_to(x1 ,y1 );
+ m_path.curve4 (x2 ,y2 ,x3 ,y3 ,x4 ,y4 );
+
+ DrawPath(AGG_StrokeOnly );
+
+end;
+
+{ POLYGON }
+procedure TAgg2D.Polygon(xy : PDouble; numPoints : integer );
+begin
+ m_path.remove_all;
+ m_path.add_poly(double_2_ptr(xy ) ,numPoints );
+
+ ClosePolygon;
+ DrawPath(AGG_FillAndStroke );
+
+end;
+
+{ POLYLINE }
+procedure TAgg2D.Polyline(xy : PDouble; numPoints : integer );
+begin
+ m_path.remove_all;
+ m_path.add_poly(double_2_ptr(xy ) ,numPoints );
+
+ DrawPath(AGG_StrokeOnly );
+
+end;
+
+{ FLIPTEXT }
+procedure TAgg2D.FlipText(flip : boolean );
+begin
+ m_fontEngine.flip_y_(not flip );
+
+end;
+
+{ FONT }
+procedure TAgg2D.Font(
+ fileName : AnsiString; height : double;
+ bold : boolean = false;
+ italic : boolean = false;
+ cache : TAggFontCacheType = AGG_VectorFontCache;
+ angle : double = 0.0 );
+var
+ b : int;
+
+begin
+ m_textAngle :=angle;
+ m_fontHeight :=height;
+ m_fontCacheType:=cache;
+
+{$IFDEF AGG2D_USE_FREETYPE }
+ if cache = AGG_VectorFontCache then
+ m_fontEngine.load_font(PChar(@fileName[1 ] ) ,0 ,glyph_ren_outline )
+ else
+ m_fontEngine.load_font(PChar(@fileName[1 ] ) ,0 ,glyph_ren_agg_gray8 );
+
+ m_fontEngine.hinting_(m_textHints );
+
+ if cahce = AGG_VectorFontCache then
+ m_fontEngine.height_(height )
+ else
+ m_fontEngine.height_(worldToScreen(height ) );
+
+{$ELSE }
+ m_fontEngine.hinting_(m_textHints );
+
+ if bold then
+ b:=700
+ else
+ b:=400;
+
+ if cache = AGG_VectorFontCache then
+ m_fontEngine.create_font_(PChar(@fileName[1 ] ) ,glyph_ren_outline ,height ,0.0 ,b ,italic )
+ else
+ m_fontEngine.create_font_(PChar(@fileName[1 ] ) ,glyph_ren_agg_gray8 ,worldToScreen(height) ,0.0 ,b ,italic );
+
+{$ENDIF }
+
+end;
+
+{ FONTHEIGHT }
+function TAgg2D.FontHeight : double;
+begin
+ result:=m_fontHeight;
+
+end;
+
+{ TEXTALIGNMENT }
+procedure TAgg2D.TextAlignment(alignX ,alignY : TAggTextAlignment );
+begin
+ m_textAlignX:=alignX;
+ m_textAlignY:=alignY;
+
+end;
+
+{ TEXTHINTS }
+function TAgg2D.TextHints : boolean;
+begin
+ result:=m_textHints;
+
+end;
+
+{ TEXTHINTS }
+procedure TAgg2D.TextHints(hints : boolean );
+begin
+ m_textHints:=hints;
+
+end;
+
+{ TEXTWIDTH }
+function TAgg2D.TextWidth(str : AnsiString ) : double;
+var
+ x ,y : double;
+ first : boolean;
+ glyph : glyph_cache_ptr;
+ str_ : PChar;
+
+begin
+ x:=0;
+ y:=0;
+
+ first:=true;
+ str_ :=@str[1 ];
+
+ while str_^ <> #0 do
+ begin
+ glyph:=m_fontCacheManager.glyph(int32u(str_^ ) );
+
+ if glyph <> NIL then
+ begin
+ if not first then
+ m_fontCacheManager.add_kerning(@x ,@y );
+
+ x:=x + glyph.advance_x;
+ y:=y + glyph.advance_y;
+
+ first:=false;
+
+ end;
+
+ inc(ptrcomp(str_ ) );
+
+ end;
+
+ if m_fontCacheType = AGG_VectorFontCache then
+ result:=x
+ else
+ result:=ScreenToWorld(x );
+
+end;
+
+{ TEXT }
+procedure TAgg2D.Text(
+ x ,y : double; str : AnsiString;
+ roundOff : boolean = false;
+ ddx : double = 0.0;
+ ddy : double = 0.0 );
+var
+ dx ,dy ,asc ,start_x ,start_y : double;
+
+ glyph : glyph_cache_ptr;
+
+ mtx : trans_affine;
+ str_ : PChar;
+
+ i : int;
+
+ tat : trans_affine_translation;
+ tar : trans_affine_rotation;
+
+ tr : conv_transform;
+
+begin
+ dx:=0.0;
+ dy:=0.0;
+
+ case m_textAlignX of
+ AGG_AlignCenter :
+ dx:=-textWidth(str ) * 0.5;
+
+ AGG_AlignRight :
+ dx:=-textWidth(str );
+
+ end;
+
+ asc :=fontHeight;
+ glyph:=m_fontCacheManager.glyph(int32u('H' ) );
+
+ if glyph <> NIL then
+ asc:=glyph.bounds.y2 - glyph.bounds.y1;
+
+ if m_fontCacheType = AGG_RasterFontCache then
+ asc:=screenToWorld(asc );
+
+ case m_textAlignY of
+ AGG_AlignCenter :
+ dy:=-asc * 0.5;
+
+ AGG_AlignTop :
+ dy:=-asc;
+
+ end;
+
+ if m_fontEngine._flip_y then
+ dy:=-dy;
+
+ mtx.Construct;
+
+ start_x:=x + dx;
+ start_y:=y + dy;
+
+ if roundOff then
+ begin
+ start_x:=Trunc(start_x );
+ start_y:=Trunc(start_y );
+
+ end;
+
+ start_x:=start_x + ddx;
+ start_y:=start_y + ddy;
+
+ tat.Construct(-x ,-y );
+ mtx.multiply (@tat );
+
+ tar.Construct(m_textAngle );
+ mtx.multiply (@tar );
+
+ tat.Construct(x ,y );
+ mtx.multiply (@tat );
+
+ tr.Construct(m_fontCacheManager.path_adaptor ,@mtx );
+
+ if m_fontCacheType = AGG_RasterFontCache then
+ WorldToScreen(@start_x ,@start_y );
+
+ i:=0;
+
+ str_:=@str[1 ];
+
+ while char_ptr(ptrcomp(str_ ) + i * sizeof(char ) )^ <> #0 do
+ begin
+ glyph:=m_fontCacheManager.glyph(int32u(char_ptr(ptrcomp(str_ ) + i * sizeof(char ) )^ ) );
+
+ if glyph <> NIL then
+ begin
+ if i <> 0 then
+ m_fontCacheManager.add_kerning(@x ,@y );
+
+ m_fontCacheManager.init_embedded_adaptors(glyph ,start_x ,start_y );
+
+ if glyph.data_type = glyph_data_outline then
+ begin
+ m_path.remove_all;
+ m_path.add_path(@tr ,0 ,false );
+
+ drawPath;
+
+ end;
+
+ if glyph.data_type = glyph_data_gray8 then
+ begin
+ render(
+ m_fontCacheManager.gray8_adaptor ,
+ m_fontCacheManager.gray8_scanline );
+
+ end;
+
+ start_x:=start_x + glyph.advance_x;
+ start_y:=start_y + glyph.advance_y;
+
+ end;
+
+ inc(i );
+
+ end;
+
+end;
+
+{ RESETPATH }
+procedure TAgg2D.ResetPath;
+begin
+ m_path.remove_all;
+ m_path.move_to(0 ,0 );
+
+end;
+
+{ MOVETO }
+procedure TAgg2D.MoveTo(x ,y : double );
+begin
+ m_path.move_to(x ,y );
+
+end;
+
+{ MOVEREL }
+procedure TAgg2D.MoveRel(dx ,dy : double );
+begin
+ m_path.move_rel(dx ,dy );
+
+end;
+
+{ LINETO }
+procedure TAgg2D.LineTo(x ,y : double );
+begin
+ m_path.line_to(x ,y );
+
+end;
+
+{ LINEREL }
+procedure TAgg2D.LineRel(dx ,dy : double );
+begin
+ m_path.line_rel(dx ,dy );
+
+end;
+
+{ HORLINETO }
+procedure TAgg2D.HorLineTo(x : double );
+begin
+ m_path.hline_to(x );
+
+end;
+
+{ HORLINEREL }
+procedure TAgg2D.HorLineRel(dx : double );
+begin
+ m_path.hline_rel(dx );
+
+end;
+
+{ VERLINETO }
+procedure TAgg2D.VerLineTo(y : double );
+begin
+ m_path.vline_to(y );
+
+end;
+
+{ VERLINEREL }
+procedure TAgg2D.VerLineRel(dy : double );
+begin
+ m_path.vline_rel(dy );
+
+end;
+
+{ ARCTO }
+procedure TAgg2D.ArcTo(
+ rx ,ry ,angle : double;
+ largeArcFlag ,sweepFlag : boolean;
+ x ,y : double );
+begin
+ m_path.arc_to(rx ,ry ,angle ,largeArcFlag ,sweepFlag ,x ,y );
+
+end;
+
+{ ARCREL }
+procedure TAgg2D.ArcRel(
+ rx ,ry ,angle : double;
+ largeArcFlag ,sweepFlag : boolean;
+ dx ,dy : double );
+begin
+ m_path.arc_rel(rx ,ry ,angle ,largeArcFlag ,sweepFlag ,dx ,dy );
+
+end;
+
+{ QUADRICCURVETO }
+procedure TAgg2D.QuadricCurveTo (xCtrl ,yCtrl ,xTo ,yTo : double );
+begin
+ m_path.curve3(xCtrl ,yCtrl ,xTo ,yTo );
+
+end;
+
+{ QUADRICCURVEREL }
+procedure TAgg2D.QuadricCurveRel(dxCtrl ,dyCtrl ,dxTo ,dyTo : double );
+begin
+ m_path.curve3_rel(dxCtrl ,dyCtrl ,dxTo ,dyTo );
+
+end;
+
+{ QUADRICCURVETO }
+procedure TAgg2D.QuadricCurveTo (xTo ,yTo : double );
+begin
+ m_path.curve3(xTo ,yTo );
+
+end;
+
+{ QUADRICCURVEREL }
+procedure TAgg2D.QuadricCurveRel(dxTo ,dyTo : double );
+begin
+ m_path.curve3_rel(dxTo ,dyTo );
+
+end;
+
+{ CUBICCURVETO }
+procedure TAgg2D.CubicCurveTo (xCtrl1 ,yCtrl1 ,xCtrl2 ,yCtrl2 ,xTo ,yTo : double );
+begin
+ m_path.curve4(xCtrl1 ,yCtrl1 ,xCtrl2 ,yCtrl2 ,xTo ,yTo );
+
+end;
+
+{ CUBICCURVEREL }
+procedure TAgg2D.CubicCurveRel(dxCtrl1 ,dyCtrl1 ,dxCtrl2 ,dyCtrl2 ,dxTo ,dyTo : double );
+begin
+ m_path.curve4_rel(dxCtrl1 ,dyCtrl1 ,dxCtrl2 ,dyCtrl2 ,dxTo ,dyTo );
+
+end;
+
+{ CUBICCURVETO }
+procedure TAgg2D.CubicCurveTo (xCtrl2 ,yCtrl2 ,xTo ,yTo : double );
+begin
+ m_path.curve4(xCtrl2 ,yCtrl2 ,xTo ,yTo );
+
+end;
+
+{ CUBICCURVEREL }
+procedure TAgg2D.CubicCurveRel(dxCtrl2 ,dyCtrl2 ,dxTo ,dyTo : double );
+begin
+ m_path.curve4_rel(dxCtrl2 ,dyCtrl2 ,dxTo ,dyTo );
+
+end;
+
+{ ADDELLIPSE }
+procedure TAgg2D.AddEllipse(cx ,cy ,rx ,ry : double; dir : TAggDirection );
+var
+ ar : bezier_arc;
+
+begin
+ if dir = AGG_CCW then
+ ar.Construct(cx ,cy ,rx ,ry ,0 ,2 * pi )
+ else
+ ar.Construct(cx ,cy ,rx ,ry ,0 ,-2 * pi );
+
+ m_path.add_path(@ar ,0 ,false );
+ m_path.close_polygon;
+
+end;
+
+{ CLOSEPOLYGON }
+procedure TAgg2D.ClosePolygon;
+begin
+ m_path.close_polygon;
+
+end;
+
+{ DRAWPATH }
+procedure TAgg2D.DrawPath(flag : TAggDrawPathFlag = AGG_FillAndStroke );
+begin
+ m_rasterizer.reset;
+
+ case flag of
+ AGG_FillOnly :
+ if m_fillColor.a <> 0 then
+ begin
+ m_rasterizer.add_path(@m_pathTransform );
+
+ render(true );
+
+ end;
+
+ AGG_StrokeOnly :
+ if (m_lineColor.a <> 0 ) and
+ (m_lineWidth > 0.0 ) then
+ begin
+ m_rasterizer.add_path(@m_strokeTransform );
+
+ render(false );
+
+ end;
+
+ AGG_FillAndStroke :
+ begin
+ if m_fillColor.a <> 0 then
+ begin
+ m_rasterizer.add_path(@m_pathTransform );
+
+ render(true );
+
+ end;
+
+ if (m_lineColor.a <> 0 ) and
+ (m_lineWidth > 0.0 ) then
+ begin
+ m_rasterizer.add_path(@m_strokeTransform );
+
+ render(false );
+
+ end;
+
+ end;
+
+ AGG_FillWithLineColor :
+ if m_lineColor.a <> 0 then
+ begin
+ m_rasterizer.add_path(@m_pathTransform );
+
+ render(false );
+
+ end;
+
+ end;
+
+end;
+
+{ IMAGEFILTER }
+procedure TAgg2D.ImageFilter(f : TAggImageFilter );
+begin
+ m_imageFilter:=f;
+
+ case f of
+ AGG_Bilinear :
+ m_imageFilterLut.calculate(@m_ifBilinear ,true );
+
+ AGG_Hanning :
+ m_imageFilterLut.calculate(@m_ifHanning ,true );
+
+ AGG_Hermite :
+ m_imageFilterLut.calculate(@m_ifHermite ,true );
+
+ AGG_Quadric :
+ m_imageFilterLut.calculate(@m_ifQuadric ,true );
+
+ AGG_Bicubic :
+ m_imageFilterLut.calculate(@m_ifBicubic ,true );
+
+ AGG_Catrom :
+ m_imageFilterLut.calculate(@m_ifCatrom ,true );
+
+ AGG_Spline16 :
+ m_imageFilterLut.calculate(@m_ifSpline16 ,true );
+
+ AGG_Spline36 :
+ m_imageFilterLut.calculate(@m_ifSpline36 ,true );
+
+ AGG_Blackman144 :
+ m_imageFilterLut.calculate(@m_ifBlackman144 ,true );
+
+ end;
+
+end;
+
+{ IMAGEFILTER }
+function TAgg2D.ImageFilter : TAggImageFilter;
+begin
+ result:=m_imageFilter;
+
+end;
+
+{ IMAGERESAMPLE }
+procedure TAgg2D.ImageResample(f : TAggImageResample );
+begin
+ m_imageResample:=f;
+
+end;
+
+{ IMAGEFLIP }
+procedure TAgg2D.ImageFlip(f : boolean );
+begin
+ m_imageFlip:=f;
+
+end;
+
+{ IMAGERESAMPLE }
+function TAgg2D.ImageResample : TAggImageResample;
+begin
+ result:=m_imageResample;
+
+end;
+
+{ TRANSFORMIMAGE }
+procedure TAgg2D.TransformImage(
+ bitmap : TBitmap;
+ imgX1 ,imgY1 ,imgX2 ,imgY2 : integer;
+ dstX1 ,dstY1 ,dstX2 ,dstY2 : double );
+var
+ parall : array[0..5 ] of double;
+ image : TAggImage;
+
+begin
+ image.Construct;
+
+ if image.attach(bitmap ,m_imageFlip ) then
+ begin
+ resetPath;
+ moveTo(dstX1 ,dstY1 );
+ lineTo(dstX2 ,dstY1 );
+ lineTo(dstX2 ,dstY2 );
+ lineTo(dstX1 ,dstY2 );
+ closePolygon;
+
+ parall[0 ]:=dstX1;
+ parall[1 ]:=dstY1;
+ parall[2 ]:=dstX2;
+ parall[3 ]:=dstY1;
+ parall[4 ]:=dstX2;
+ parall[5 ]:=dstY2;
+
+ renderImage(@image ,imgX1 ,imgY1 ,imgX2 ,imgY2 ,@parall[0 ] );
+
+ image.Destruct;
+
+ end;
+
+end;
+
+{ TRANSFORMIMAGE }
+procedure TAgg2D.TransformImage(
+ bitmap : TBitmap;
+ dstX1 ,dstY1 ,dstX2 ,dstY2 : double );
+var
+ parall : array[0..5 ] of double;
+ image : TAggImage;
+
+begin
+ image.Construct;
+
+ if image.attach(bitmap ,m_imageFlip ) then
+ begin
+ ResetPath;
+ MoveTo(dstX1 ,dstY1 );
+ LineTo(dstX2 ,dstY1 );
+ LineTo(dstX2 ,dstY2 );
+ LineTo(dstX1 ,dstY2 );
+ ClosePolygon;
+
+ parall[0 ]:=dstX1;
+ parall[1 ]:=dstY1;
+ parall[2 ]:=dstX2;
+ parall[3 ]:=dstY1;
+ parall[4 ]:=dstX2;
+ parall[5 ]:=dstY2;
+
+ renderImage(@image ,0 ,0 ,image.renBuf._width ,image.renBuf._height ,@parall[0 ] );
+
+ image.Destruct;
+
+ end;
+
+end;
+
+{ TRANSFORMIMAGE }
+procedure TAgg2D.TransformImage(
+ bitmap : TBitmap;
+ imgX1 ,imgY1 ,imgX2 ,imgY2 : integer;
+ parallelo : PDouble );
+var
+ image : TAggImage;
+
+begin
+ image.Construct;
+
+ if image.attach(bitmap ,m_imageFlip ) then
+ begin
+ ResetPath;
+
+ MoveTo(
+ PDouble(ptrcomp(parallelo ) + 0 * sizeof(double ) )^ ,
+ PDouble(ptrcomp(parallelo ) + 1 * sizeof(double ) )^ );
+
+ LineTo(
+ PDouble(ptrcomp(parallelo ) + 2 * sizeof(double ) )^ ,
+ PDouble(ptrcomp(parallelo ) + 3 * sizeof(double ) )^ );
+
+ LineTo(
+ PDouble(ptrcomp(parallelo ) + 4 * sizeof(double ) )^ ,
+ PDouble(ptrcomp(parallelo ) + 5 * sizeof(double ) )^ );
+
+ LineTo(
+ PDouble(ptrcomp(parallelo ) + 0 * sizeof(double ) )^ +
+ PDouble(ptrcomp(parallelo ) + 4 * sizeof(double ) )^ -
+ PDouble(ptrcomp(parallelo ) + 2 * sizeof(double ) )^ ,
+ PDouble(ptrcomp(parallelo ) + 1 * sizeof(double ) )^ +
+ PDouble(ptrcomp(parallelo ) + 5 * sizeof(double ) )^ -
+ PDouble(ptrcomp(parallelo ) + 3 * sizeof(double ) )^ );
+
+ ClosePolygon;
+
+ renderImage(@image ,imgX1 ,imgY1 ,imgX2 ,imgY2 ,parallelo );
+
+ image.Destruct;
+
+ end;
+
+end;
+
+{ TRANSFORMIMAGE }
+procedure TAgg2D.TransformImage(bitmap : TBitmap; parallelo : PDouble );
+var
+ image : TAggImage;
+
+begin
+ image.Construct;
+
+ if image.attach(bitmap ,m_imageFlip ) then
+ begin
+ ResetPath;
+
+ MoveTo(
+ PDouble(ptrcomp(parallelo ) + 0 * sizeof(double ) )^ ,
+ PDouble(ptrcomp(parallelo ) + 1 * sizeof(double ) )^ );
+
+ LineTo(
+ PDouble(ptrcomp(parallelo ) + 2 * sizeof(double ) )^ ,
+ PDouble(ptrcomp(parallelo ) + 3 * sizeof(double ) )^ );
+
+ LineTo(
+ PDouble(ptrcomp(parallelo ) + 4 * sizeof(double ) )^ ,
+ PDouble(ptrcomp(parallelo ) + 5 * sizeof(double ) )^ );
+
+ LineTo(
+ PDouble(ptrcomp(parallelo ) + 0 * sizeof(double ) )^ +
+ PDouble(ptrcomp(parallelo ) + 4 * sizeof(double ) )^ -
+ PDouble(ptrcomp(parallelo ) + 2 * sizeof(double ) )^ ,
+ PDouble(ptrcomp(parallelo ) + 1 * sizeof(double ) )^ +
+ PDouble(ptrcomp(parallelo ) + 5 * sizeof(double ) )^ -
+ PDouble(ptrcomp(parallelo ) + 3 * sizeof(double ) )^ );
+
+ ClosePolygon;
+
+ renderImage(@image ,0 ,0 ,image.renBuf._width ,image.renBuf._height ,parallelo );
+
+ image.Destruct;
+
+ end;
+
+end;
+
+{ TRANSFORMIMAGEPATH }
+procedure TAgg2D.TransformImagePath(
+ bitmap : TBitmap;
+ imgX1 ,imgY1 ,imgX2 ,imgY2 : integer;
+ dstX1 ,dstY1 ,dstX2 ,dstY2 : double );
+var
+ parall : array[0..5 ] of double;
+ image : TAggImage;
+
+begin
+ image.Construct;
+
+ if image.attach(bitmap ,m_imageFlip ) then
+ begin
+ parall[0 ]:=dstX1;
+ parall[1 ]:=dstY1;
+ parall[2 ]:=dstX2;
+ parall[3 ]:=dstY1;
+ parall[4 ]:=dstX2;
+ parall[5 ]:=dstY2;
+
+ renderImage(@image ,imgX1 ,imgY1 ,imgX2 ,imgY2 ,@parall[0 ] );
+
+ image.Destruct;
+
+ end;
+
+end;
+
+{ TRANSFORMIMAGEPATH }
+procedure TAgg2D.TransformImagePath(
+ bitmap : TBitmap;
+ dstX1 ,dstY1 ,dstX2 ,dstY2 : double );
+var
+ parall : array[0..5 ] of double;
+ image : TAggImage;
+
+begin
+ image.Construct;
+
+ if image.attach(bitmap ,m_imageFlip ) then
+ begin
+ parall[0 ]:=dstX1;
+ parall[1 ]:=dstY1;
+ parall[2 ]:=dstX2;
+ parall[3 ]:=dstY1;
+ parall[4 ]:=dstX2;
+ parall[5 ]:=dstY2;
+
+ renderImage(@image ,0 ,0 ,image.renBuf._width ,image.renBuf._height ,@parall[0 ] );
+
+ image.Destruct;
+
+ end;
+
+end;
+
+{ TRANSFORMIMAGEPATH }
+procedure TAgg2D.TransformImagePath(
+ bitmap : TBitmap;
+ imgX1 ,imgY1 ,imgX2 ,imgY2 : integer;
+ parallelo : PDouble );
+var
+ image : TAggImage;
+
+begin
+ image.Construct;
+
+ if image.attach(bitmap ,m_imageFlip ) then
+ begin
+ renderImage(@image ,imgX1 ,imgY1 ,imgX2 ,imgY2 ,parallelo );
+
+ image.Destruct;
+
+ end;
+
+end;
+
+{ TRANSFORMIMAGEPATH }
+procedure TAgg2D.TransformImagePath(bitmap : TBitmap; parallelo : PDouble );
+var
+ image : TAggImage;
+
+begin
+ image.Construct;
+
+ if image.attach(bitmap ,m_imageFlip ) then
+ begin
+ renderImage(@image ,0 ,0 ,image.renBuf._width ,image.renBuf._height ,parallelo );
+
+ image.Destruct;
+
+ end;
+
+end;
+
+{ COPYIMAGE }
+procedure TAgg2D.CopyImage(
+ bitmap : TBitmap;
+ imgX1 ,imgY1 ,imgX2 ,imgY2 : integer;
+ dstX ,dstY : double );
+var
+ r : agg_basics.rect;
+ image : TAggImage;
+
+begin
+ image.Construct;
+
+ if image.attach(bitmap ,m_imageFlip ) then
+ begin
+ WorldToScreen(@dstX ,@dstY );
+ r.Construct (imgX1 ,imgY1 ,imgX2 ,imgY2 );
+
+ m_renBase.copy_from(@image.renBuf ,@r ,Trunc(dstX ) - imgX1 ,Trunc(dstY ) - imgY1 );
+
+ image.Destruct;
+
+ end;
+
+end;
+
+{ COPYIMAGE }
+procedure TAgg2D.CopyImage(bitmap : TBitmap; dstX ,dstY : double );
+var
+ image : TAggImage;
+
+begin
+ image.Construct;
+
+ if image.attach(bitmap ,m_imageFlip ) then
+ begin
+ WorldToScreen(@dstX ,@dstY );
+
+ m_renBase.copy_from(@image.renBuf ,NIL ,Trunc(dstX ) ,Trunc(dstY ) );
+
+ image.Destruct;
+
+ end;
+
+end;
+
+{ RENDER }
+procedure TAgg2D.render(fillColor_ : boolean );
+begin
+ if (m_blendMode = AGG_BlendAlpha ) or
+ (m_pixf = pf24bit ) then
+ Agg2DRenderer_render(self ,@m_renBase ,@m_renSolid ,fillColor_ )
+ else
+ Agg2DRenderer_render(self ,@m_renBaseComp ,@m_renSolidComp ,fillColor_ );
+
+end;
+
+{ RENDER }
+procedure TAgg2D.render(ras : PAggFontRasterizer; sl : PAggFontScanline );
+begin
+ if (m_blendMode = AGG_BlendAlpha ) or
+ (m_pixf = pf24bit ) then
+ Agg2DRenderer_render(self ,@m_renBase ,@m_renSolid ,ras ,sl )
+ else
+ Agg2DRenderer_render(self ,@m_renBaseComp ,@m_renSolidComp ,ras ,sl );
+
+end;
+
+{ ADDLINE }
+procedure TAgg2D.addLine(x1 ,y1 ,x2 ,y2 : double );
+begin
+ m_path.move_to(x1 ,y1 );
+ m_path.line_to(x2 ,y2 );
+
+end;
+
+{ UPDATERASTERIZERGAMMA }
+procedure TAgg2D.updateRasterizerGamma;
+begin
+ m_gammaAgg2D.Construct(m_masterAlpha ,m_antiAliasGamma );
+ m_rasterizer.gamma (@m_gammaAgg2D );
+
+end;
+
+{ RENDERIMAGE }
+procedure TAgg2D.renderImage(
+ img : PAggImage;
+ x1 ,y1 ,x2 ,y2 : integer;
+ parl : PDouble );
+var
+ mtx : trans_affine;
+
+ interpolator : span_interpolator_linear;
+
+begin
+ mtx.Construct(x1 ,y1 ,x2 ,y2 ,parallelo_ptr(parl ) );
+ mtx.multiply (@m_transform );
+ mtx.invert;
+
+ m_rasterizer.reset;
+ m_rasterizer.add_path(@m_pathTransform );
+
+ interpolator.Construct(@mtx );
+
+ if (m_blendMode = AGG_BlendAlpha ) or
+ (m_pixf = pf24bit ) then
+ Agg2DRenderer_renderImage(self ,img ,@m_renBasePre ,@interpolator )
+ else
+ Agg2DRenderer_renderImage(self ,img ,@m_renBaseCompPre ,@interpolator );
+
+end;
+
+{ BITMAPALPHATRANSPARENCY }
+function BitmapAlphaTransparency(bitmap : TBitmap; alpha : byte ) : boolean;
+var
+ fcx ,fcy : integer;
+ transp : ^byte;
+
+begin
+ result:=false;
+
+ if Assigned(bitmap ) and
+ not bitmap.Empty and
+ (bitmap.PixelFormat = pf32bit ) then
+ begin
+ for fcy:=0 to bitmap.Height - 1 do
+ begin
+ transp:=pointer(ptrcomp(bitmap.ScanLine[fcy ] ) + 3 );
+
+ for fcx:=0 to bitmap.Width - 1 do
+ begin
+ transp^:=alpha;
+
+ inc(ptrcomp(transp ) ,4 );
+
+ end;
+
+ end;
+
+ { OK }
+ result:=true;
+
+ end;
+
+end;
+
+END.
+
+{*}
+{!}{ To look At }
+
+
diff --git a/src/corelib/render/software/agg-demos/Agg2DDemo.dpr b/src/corelib/render/software/agg-demos/Agg2DDemo.dpr
new file mode 100644
index 00000000..36fc844d
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/Agg2DDemo.dpr
@@ -0,0 +1,758 @@
+{mac_copy:spheres2.bmp}
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ Agg2DDemo ;
+
+uses
+ SysUtils ,
+ agg_basics ,
+ agg_platform_support ,
+ file_utils_ ,
+ agg_2D ;
+
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+ angle_step = 5;
+ gamma_step = 0.1;
+
+var
+ FONT_TIMES : AnsiString = 'Times New Roman';
+ FONT_ARIAL : AnsiString = 'Arial';
+ FONT_VERDA : AnsiString = 'Verdana';
+
+type
+ the_application = object(platform_support )
+ m_graphics ,
+ m_timer : Agg2D;
+ m_angle ,
+ m_gamma : double;
+ m_image : int;
+ m_gmText : AnsiString;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure on_init; virtual;
+ procedure on_draw; virtual;
+
+ procedure on_mouse_move(x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_up (x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_graphics.Construct;
+ m_timer.Construct;
+
+ m_angle:=0;
+ m_gamma:=1.4;
+ m_image:=6;
+
+ Str(m_gamma:0:2 ,m_gmText ); m_gmText:='Gamma: ' + m_gmText;
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_graphics.Destruct;
+ m_timer.Destruct;
+
+ Finalize(m_gmText );
+
+end;
+
+{ ON_INIT }
+procedure the_application.on_init;
+begin
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ xb1 ,yb1 ,xb2 ,yb2 : double;
+
+ clr ,c1 ,c2 ,c3 : Color;
+
+ img : Image;
+
+ parl : array[0..5 ] of double;
+ poly : array[0..11 ] of double;
+
+ tm : double;
+ fps : int;
+
+ timer ,rate : AnsiString;
+
+begin
+ start_timer;
+
+ m_graphics.attach(
+ rbuf_window._buf ,
+ rbuf_window._width ,
+ rbuf_window._height ,
+ rbuf_window._stride );
+
+ m_graphics.clearAll(255 ,255 ,255 );
+
+ //m_graphics.clearAll(0 ,0 ,0 );
+
+ //m_graphics.blendMode(BlendSub );
+ //m_graphics.blendMode(BlendAdd );
+
+ m_graphics.antiAliasGamma(m_gamma );
+
+// Set flipText(true) if you have the Y axis upside down.
+ m_graphics.flipText(not flip_y );
+
+// ClipBox.
+ //m_graphics.clipBox(50 ,50 ,rbuf_window._width - 50 ,rbuf_window._height - 50 );
+
+// Transfornations - Rotate around (300,300) to 5 degree
+ m_graphics.translate(-300 ,-300 );
+ m_graphics.rotate (deg2Rad(m_angle ) );
+ m_graphics.translate(300 ,300 );
+ //m_graphics.skew (0.1 ,0.1 );
+
+// Viewport - set 0,0,600,600 to the actual window size
+// preserving aspect ratio and placing the viewport in the center.
+// To ignore aspect ratio use Agg2D::Anisotropic
+// Note that the viewport just adds transformations to the current
+// affine matrix. So that, set the viewport *after* all transformations!
+ m_graphics.viewport(
+ 0 ,0 ,600 ,600 ,
+ 0 ,0 ,_width ,_height ,
+ //Anisotropic );
+ XMidYMid );
+ //XMinYMin );
+ //XMidYMin );
+ //XMaxYMin );
+ //XMinYMid );
+ //XMaxYMid );
+ //XMinYMax );
+ //XMidYMax );
+ //XMaxYMax );
+
+// Rounded Rect
+ m_graphics.lineColor(0 ,0 ,0 );
+ m_graphics.noFill;
+ m_graphics.roundedRect(0.5 ,0.5 ,600 - 0.5 ,600 - 0.5 ,20.0 );
+
+// Regular Text
+{ m_graphics.font(char_ptr(FONT_TIMES ) ,14.0 ,false ,false );
+ m_graphics.fillColor(0 ,0 ,0 );
+ m_graphics.noLine;
+ m_graphics.text(100 ,20 ,char_ptr(PChar('Regular Raster Text -- Fast, but can''t be rotated' ) ) );{}
+
+// Outlined Text
+ m_graphics.font(char_ptr(FONT_TIMES ) ,50.0 ,false ,false ,{RasterFontCache}VectorFontCache );
+ m_graphics.lineColor(50 ,0 ,0 );
+ m_graphics.fillColor(180 ,200 ,100 );
+ m_graphics.lineWidth(1.0 );
+ m_graphics.text(100.5 ,50.5 ,char_ptr(PChar('Outlined Text' ) ) );
+
+// Gamma Text
+(* m_graphics.font(char_ptr(FONT_ARIAL ) ,38.0 ,true ,true ,VectorFontCache );
+
+ c1.Construct (255 ,0 ,0 ,255 );
+ c2.Construct (0 ,255 ,0 ,255 );
+ m_graphics.fillLinearGradient(50 ,1 ,300 ,10 ,c1 ,c2 );
+
+ m_graphics.noLine;
+ m_graphics.text(12.5 ,565.5 ,char_ptr(@m_gmText[1 ] ) );
+ //m_graphics.rectangle(12.5 ,565.5 ,290 ,590 ); (**)
+
+// Text Alignment
+ m_graphics.lineColor(0 ,0 ,0 );
+ m_graphics.line(250.5 - 150 ,150.5 ,250.5 + 150 ,150.5 );
+ m_graphics.line(250.5 ,150.5 - 20 ,250.5 ,150.5 + 20 );
+ m_graphics.line(250.5 - 150 ,200.5 ,250.5 + 150 ,200.5 );
+ m_graphics.line(250.5 ,200.5 - 20 ,250.5 ,200.5 + 20 );
+ m_graphics.line(250.5 - 150 ,250.5 ,250.5 + 150 ,250.5 );
+ m_graphics.line(250.5 ,250.5 - 20 ,250.5 ,250.5 + 20 );
+ m_graphics.line(250.5 - 150 ,300.5 ,250.5 + 150 ,300.5 );
+ m_graphics.line(250.5 ,300.5 - 20 ,250.5 ,300.5 + 20 );
+ m_graphics.line(250.5 - 150 ,350.5 ,250.5 + 150 ,350.5 );
+ m_graphics.line(250.5 ,350.5 - 20 ,250.5 ,350.5 + 20 );
+ m_graphics.line(250.5 - 150 ,400.5 ,250.5 + 150 ,400.5 );
+ m_graphics.line(250.5 ,400.5 - 20 ,250.5 ,400.5 + 20 );
+ m_graphics.line(250.5 - 150 ,450.5 ,250.5 + 150 ,450.5 );
+ m_graphics.line(250.5 ,450.5 - 20 ,250.5 ,450.5 + 20 );
+ m_graphics.line(250.5 - 150 ,500.5 ,250.5 + 150 ,500.5 );
+ m_graphics.line(250.5 ,500.5 - 20 ,250.5 ,500.5 + 20 );
+ m_graphics.line(250.5 - 150 ,550.5 ,250.5 + 150 ,550.5 );
+ m_graphics.line(250.5 ,550.5 - 20 ,250.5 ,550.5 + 20 );
+
+ m_graphics.fillColor(100 ,50 ,50 );
+ m_graphics.noLine;
+ //m_graphics.textHints(false );
+ m_graphics.font(char_ptr(FONT_TIMES ) ,40.0 ,false ,false ,VectorFontCache );
+
+ m_graphics.textAlignment(AlignLeft ,AlignBottom );
+ m_graphics.text(250.0 ,150.0 ,char_ptr(PChar('Left-Bottom' ) ) ,true ,0 ,0 );
+
+ m_graphics.textAlignment(AlignCenter ,AlignBottom );
+ m_graphics.text(250.0 ,200.0 ,char_ptr(PChar('Center-Bottom' ) ) ,true ,0 ,0 );
+
+ m_graphics.textAlignment(AlignRight ,AlignBottom );
+ m_graphics.text(250.0 ,250.0 ,char_ptr(PChar('Right-Bottom' ) ) ,true ,0 ,0 );
+
+ m_graphics.textAlignment(AlignLeft ,AlignCenter );
+ m_graphics.text(250.0 ,300.0 ,char_ptr(PChar('Left-Center' ) ) ,true ,0 ,0 );
+
+ m_graphics.textAlignment(AlignCenter ,AlignCenter );
+ m_graphics.text(250.0 ,350.0 ,char_ptr(PChar('Center-Center' ) ) ,true ,0 ,0 );
+
+ m_graphics.textAlignment(AlignRight ,AlignCenter );
+ m_graphics.text(250.0 ,400.0 ,char_ptr(PChar('Right-Center' ) ) ,true ,0 ,0 );
+
+ m_graphics.textAlignment(AlignLeft ,AlignTop );
+ m_graphics.text(250.0 ,450.0 ,char_ptr(PChar('Left-Top' ) ) ,true ,0 ,0 );
+
+ m_graphics.textAlignment(AlignCenter ,AlignTop );
+ m_graphics.text(250.0 ,500.0 ,char_ptr(PChar('Center-Top' ) ) ,true ,0 ,0 );
+
+ m_graphics.textAlignment(AlignRight ,AlignTop );
+ m_graphics.text(250.0 ,550.0 ,char_ptr(PChar('Right-Top' ) ) ,true ,0 ,0 );
+
+// Gradients (Aqua Buttons)
+//=======================================
+ m_graphics.font(char_ptr(FONT_VERDA ) ,20.0 ,false ,false ,VectorFontCache );
+
+ xb1:=400;
+ yb1:=80;
+ xb2:=xb1 + 150;
+ yb2:=yb1 + 36;
+
+ clr.Construct (0 ,50 ,180 ,180 );
+ m_graphics.fillColor (clr );
+ clr.Construct (0 ,0 ,80 ,255 );
+ m_graphics.lineColor (clr );
+ m_graphics.lineWidth (1.0);
+ m_graphics.roundedRect(xb1 ,yb1 ,xb2 ,yb2 ,12 ,18 );
+
+ clr.Construct (0 ,0 ,0 ,0 );
+ m_graphics.lineColor(clr );
+
+ c1.Construct (100 ,200 ,255 ,255 );
+ c2.Construct (255 ,255 ,255 ,0 );
+ m_graphics.fillLinearGradient(xb1 ,yb1 ,xb1 ,yb1 + 30 ,c1 ,c2 );
+ m_graphics.roundedRect (xb1 + 3 ,yb1 + 2.5 ,xb2 - 3 ,yb1 + 30 ,9 ,18 ,1 ,1 );
+
+ clr.Construct (0 ,0 ,50 ,200 );
+ m_graphics.fillColor(clr );
+ m_graphics.noLine;
+ m_graphics.textAlignment(AlignCenter ,AlignCenter );
+ m_graphics.text(
+ (xb1 + xb2 ) / 2.0 ,
+ (yb1 + yb2 ) / 2.0 ,
+ char_ptr(PChar('Aqua Button' ) ) ,
+ true ,0.0 ,0.0 );
+
+ c1.Construct(0 ,0 ,255 ,0 );
+ c2.Construct(100 ,255 ,255 ,255 );
+ m_graphics.fillLinearGradient(xb1 ,yb2 - 20 ,xb1 ,yb2 - 3 ,c1 ,c2 );
+ m_graphics.roundedRect (xb1 + 3 ,yb2 - 20 ,xb2 - 3 ,yb2 - 2 ,1 ,1 ,9 ,18 );
+
+// Aqua Button Pressed
+ xb1:=400;
+ yb1:=30;
+ xb2:=xb1 + 150;
+ yb2:=yb1 + 36;
+
+ clr.Construct (0 ,50 ,180 ,180 );
+ m_graphics.fillColor (clr );
+ clr.Construct (0 ,0 ,0 ,255 );
+ m_graphics.lineColor (clr );
+ m_graphics.lineWidth (2.0 );
+ m_graphics.roundedRect(xb1 ,yb1 ,xb2 ,yb2 ,12 ,18 );
+
+ clr.Construct (0 ,0 ,0 ,0 );
+ m_graphics.lineColor(clr );
+
+ c1.Construct (60 ,160 ,255 ,255 );
+ c2.Construct (100 ,255 ,255 ,0 );
+ m_graphics.fillLinearGradient(xb1 ,yb1 + 2 ,xb1 ,yb1 + 25 ,c1 ,c2 );
+ m_graphics.roundedRect (xb1 + 3 ,yb1 + 2.5 ,xb2 - 3 ,yb1 + 30 ,9 ,18 ,1 ,1 );
+
+ clr.Construct (0 ,0 ,50 ,255 );
+ m_graphics.fillColor(clr );
+ m_graphics.noLine;
+ m_graphics.textAlignment(AlignCenter ,AlignCenter );
+ m_graphics.text(
+ (xb1 + xb2 ) / 2.0 ,
+ (yb1 + yb2 ) / 2.0 ,
+ char_ptr(PChar('Aqua Pressed' ) ) ,
+ false ,0.0 );
+
+ c1.Construct (0 ,180 ,255 ,0 );
+ c2.Construct (0 ,200 ,255 ,255 );
+ m_graphics.fillLinearGradient(xb1 ,yb2 - 25 ,xb1 ,yb2 - 5 ,c1 ,c2 );
+ m_graphics.roundedRect (xb1 + 3 ,yb2 - 25 ,xb2 - 3 ,yb2 - 2 ,1 ,1 ,9 ,18 );
+
+// Basic Shapes -- Ellipse
+//===========================================
+ m_graphics.lineWidth(3.5 );
+ m_graphics.lineColor(20 ,80 ,80 );
+ m_graphics.fillColor(200 ,255 ,80 ,200 );
+ m_graphics.ellipse (450 ,200 ,50 ,90 );
+
+// Paths
+//===========================================
+ m_graphics.resetPath;
+ m_graphics.fillColor (255 ,0 ,0 ,100 );
+ m_graphics.lineColor (0 ,0 ,255 ,100 );
+ m_graphics.lineWidth (2 );
+ m_graphics.moveTo (300 / 2 ,200 / 2 );
+ m_graphics.horLineRel(-150 / 2 );
+ m_graphics.arcRel (150 / 2 ,150 / 2 ,0 ,true ,false ,150 / 2 ,-150 / 2 );
+ m_graphics.closePolygon;
+ m_graphics.drawPath;
+
+ m_graphics.resetPath;
+ m_graphics.fillColor (255 ,255 ,0 ,100 );
+ m_graphics.lineColor (0 ,0 ,255 ,100 );
+ m_graphics.lineWidth (2 );
+ m_graphics.moveTo (275 / 2 ,175 / 2 );
+ m_graphics.verLineRel(-150 / 2 );
+ m_graphics.arcRel (150 / 2 ,150 / 2 ,0 ,false ,false ,-150 / 2 ,150 / 2 );
+ m_graphics.closePolygon;
+ m_graphics.drawPath;
+
+ m_graphics.resetPath;
+ m_graphics.noFill;
+ m_graphics.lineColor(127 ,0 ,0 );
+ m_graphics.lineWidth(5 );
+ m_graphics.moveTo (600 / 2 ,350 / 2 );
+ m_graphics.lineRel (50 / 2 ,-25 / 2 );
+ m_graphics.arcRel (25 / 2 ,25 / 2 ,deg2Rad(-30 ) ,false ,true ,50 / 2 ,-25 / 2 );
+ m_graphics.lineRel (50 / 2 ,-25 / 2);
+ m_graphics.arcRel (25 / 2 ,50 / 2 ,deg2Rad(-30 ) ,false ,true ,50 / 2 ,-25 / 2 );
+ m_graphics.lineRel (50 / 2 ,-25 / 2 );
+ m_graphics.arcRel (25 / 2 ,75 / 2 ,deg2Rad(-30 ) ,false ,true ,50 / 2 ,-25 / 2 );
+ m_graphics.lineRel (50 ,-25 );
+ m_graphics.arcRel (25 / 2 ,100 / 2 ,deg2Rad(-30 ) ,false ,true ,50 / 2 ,-25 / 2 );
+ m_graphics.lineRel (50 / 2 ,-25 / 2 );
+ m_graphics.drawPath;
+
+// Master Alpha. From now on everything will be translucent
+//===========================================
+ m_graphics.masterAlpha(0.85 );
+
+// Image Transformations
+//===========================================
+ img.Construct(
+ rbuf_img(0 )._buf ,
+ rbuf_img(0 )._width ,
+ rbuf_img(0 )._height ,
+ rbuf_img(0 )._stride );
+
+ m_graphics.imageFilter(Bilinear );
+
+ //m_graphics.imageResample(NoResample );
+ //m_graphics.imageResample(ResampleAlways );
+ m_graphics.imageResample(ResampleOnZoomOut );
+
+// Set the initial image blending operation as BlendDst, that actually
+// does nothing.
+//-----------------
+ m_graphics.imageBlendMode(BlendDst );
+
+// Transform the whole image to the destination rectangle
+//-----------------
+ if m_image = 1 then
+ m_graphics.transformImage(@img ,450 ,200 ,595 ,350 );{1}
+
+// Transform the rectangular part of the image to the destination rectangle
+//-----------------
+ if m_image = 2 then
+ m_graphics.transformImage(
+ @img ,60 ,60 ,img.width - 60 ,img.height - 60 ,
+ 450 ,200 ,595 ,350 );{2}
+
+// Transform the whole image to the destination parallelogram
+//-----------------
+ if m_image = 3 then
+ begin
+ parl[0 ]:=450;
+ parl[1 ]:=200;
+ parl[2 ]:=595;
+ parl[3 ]:=220;
+ parl[4 ]:=575;
+ parl[5 ]:=350;
+
+ m_graphics.transformImage(@img ,@parl[0 ] );{3}
+
+ end;
+
+// Transform the rectangular part of the image to the destination parallelogram
+//-----------------
+ if m_image = 4 then
+ begin
+ parl[0 ]:=450;
+ parl[1 ]:=200;
+ parl[2 ]:=595;
+ parl[3 ]:=220;
+ parl[4 ]:=575;
+ parl[5 ]:=350;
+
+ m_graphics.transformImage(@img ,60 ,60 ,img.width - 60 ,img.height - 60 ,@parl[0 ] );{4}
+
+ end;
+
+// Transform image to the destination path. The scale is determined by a rectangle
+//-----------------
+ if m_image = 5 then
+ begin
+ m_graphics.resetPath;
+ m_graphics.moveTo (450 ,200 );
+ m_graphics.cubicCurveTo (595 ,220 ,575 ,350 ,595 ,350 );
+ m_graphics.lineTo (470 ,340 );
+ m_graphics.transformImagePath(@img ,450 ,200 ,595 ,350 );{5}
+
+ end;
+
+// Transform image to the destination path.
+// The scale is determined by a rectangle
+//-----------------
+ if m_image = 6 then
+ begin
+ m_graphics.resetPath;
+ m_graphics.moveTo (450 ,200 );
+ m_graphics.cubicCurveTo(595 ,220 ,575 ,350 ,595 ,350 );
+ m_graphics.lineTo (470 ,340 );
+ m_graphics.transformImagePath(
+ @img ,60 ,60 ,img.width - 60 ,img.height - 60 ,
+ 450 ,200 ,595 ,350 );{6}
+
+ end;
+
+// Transform image to the destination path.
+// The transformation is determined by a parallelogram
+ if m_image = 7 then
+ begin
+ m_graphics.resetPath;
+ m_graphics.moveTo (450 ,200 );
+ m_graphics.cubicCurveTo(595 ,220 ,575 ,350 ,595 ,350 );
+ m_graphics.lineTo (470 ,340 );
+
+ parl[0 ]:=450;
+ parl[1 ]:=200;
+ parl[2 ]:=595;
+ parl[3 ]:=220;
+ parl[4 ]:=575;
+ parl[5 ]:=350;
+
+ m_graphics.transformImagePath(@img ,@parl[0 ] );{7}
+
+ end;
+
+// Transform the rectangular part of the image to the destination path.
+// The transformation is determined by a parallelogram
+ if m_image = 8 then
+ begin
+ m_graphics.resetPath;
+ m_graphics.moveTo (450 ,200 );
+ m_graphics.cubicCurveTo(595 ,220 ,575 ,350 ,595 ,350 );
+ m_graphics.lineTo (470 ,340 );
+
+ parl[0 ]:=450;
+ parl[1 ]:=200;
+ parl[2 ]:=595;
+ parl[3 ]:=220;
+ parl[4 ]:=575;
+ parl[5 ]:=350;
+
+ m_graphics.transformImagePath(@img ,60 ,60 ,img.width - 60 ,img.height - 60 ,@parl[0 ] );{8}
+
+ end;
+
+// Free Image
+ img.Destruct;
+
+// Add/Sub/Contrast Blending Modes
+ m_graphics.noLine;
+ m_graphics.fillColor(70 ,70 ,0 );
+ m_graphics.blendMode(BlendAdd );
+ m_graphics.ellipse (500 ,280 ,20 ,40 );
+
+ m_graphics.fillColor(255 ,255 ,255 );
+ m_graphics.blendMode(BlendContrast );
+ m_graphics.ellipse (500 + 40 ,280 ,20 ,40 );
+
+// Radial gradient.
+ m_graphics.blendMode (BlendAlpha );
+ c1.Construct (255 ,255 ,0 , 0);
+ c2.Construct (0 ,0 ,127 );
+ c3.Construct (0 ,255 ,0 , 0);
+ m_graphics.fillRadialGradient(400 ,500 ,40 ,c1 ,c2 ,c3 );
+ m_graphics.ellipse (400 ,500 ,40 ,40 );
+
+// More ...
+(* m_graphics.masterAlpha(1 );
+
+ //m_graphics.lineColor(50 ,60 ,70 );
+
+ c1.Construct (255 ,0 ,0 ,255 );
+ c2.Construct (0 ,255 ,0 ,255 );
+ m_graphics.lineLinearGradient(0 ,0 ,500 ,0 ,c1 ,c2 );{}
+
+ m_graphics.fillColor(255 ,0 ,0 );
+ m_graphics.lineJoin (JoinMiter );
+ m_graphics.lineWidth(15 );
+ m_graphics.triangle (10 ,10 ,100 ,20 ,50 ,150 );
+
+ m_graphics.lineJoin (JoinRound );
+ m_graphics.lineWidth(4 );
+ m_graphics.noFill;
+ m_graphics.rectangle(55 ,540 ,135 ,495 );
+
+ m_graphics.masterAlpha(0.5 );
+
+ m_graphics.fillColor(255 ,127 ,65 );
+ m_graphics.star (300 ,300 ,30 ,70 ,55 ,5 );
+ m_graphics.arc (400 ,400 ,30 ,30 ,300 ,1150 );
+
+ m_graphics.lineWidth(20 );
+ m_graphics.lineCap (CapRound );
+ m_graphics.curve (80 ,400 ,90 ,220 ,190 ,390 );
+ m_graphics.curve (80 ,500 ,90 ,320 ,190 ,490 ,310 ,330 );
+
+ poly[0 ]:=400;
+ poly[1 ]:=580;
+
+ poly[2 ]:=530;
+ poly[3 ]:=400;
+
+ poly[4 ]:=590;
+ poly[5 ]:=500;
+
+ poly[6 ]:=450;
+ poly[7 ]:=380;
+
+ poly[8 ]:=490;
+ poly[9 ]:=570;
+
+ poly[10 ]:=420;
+ poly[11 ]:=420;
+
+ m_graphics.fillEvenOdd(false );
+ m_graphics.lineWidth (3 );
+ m_graphics.polygon (@poly[0 ] ,6 );
+
+ m_graphics.lineColor(221 ,160 ,221 );
+ m_graphics.lineWidth(6 );
+ m_graphics.polyline (@poly[0 ] ,6 ); (**)
+
+// TIMER DRAW
+// ----------
+ tm:=elapsed_time;
+
+ m_timer.attach(
+ rbuf_window._buf ,
+ rbuf_window._width ,
+ rbuf_window._height ,
+ rbuf_window._stride );
+
+ m_timer.antiAliasGamma(1.4 );
+
+ m_timer.flipText(not flip_y );
+ m_timer.viewport(
+ 0 ,0 ,600 ,600 ,
+ 0 ,0 ,_width ,_height ,
+ //Anisotropic );
+ XMidYMid );
+
+ Str(tm:0:2 ,timer );
+
+ timer:='Frame time: ' + timer + ' ms';
+
+ fps:=Trunc(1000 / tm );
+
+ Str(fps ,rate );
+
+ timer:=timer + ' (' + rate + ' FPS)';
+
+ m_timer.font(char_ptr(FONT_ARIAL ) ,15.0 ,true ,false ,VectorFontCache );
+ m_timer.noLine;
+ m_timer.fillColor(255 ,0 ,0 );
+ m_timer.text(350 ,8 ,char_ptr(@timer[1 ] ) );
+
+end;
+
+{ ON_MOUSE_MOVE }
+procedure the_application.on_mouse_move;
+begin
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure the_application.on_mouse_button_down;
+begin
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+procedure the_application.on_mouse_button_up;
+begin
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ '"Quick and dirty prototype" of 2D drawing API for AGG.'#13#13 +
+ 'Written and published by Maxim Shemanarev (c) 2005 - 2006. '#13 +
+ 'Ported to Object Pascal by Milan Marusinec (c) 2007.'#13#13 +
+ 'How to play with:'#13#13 +
+ 'Key Down - Rotate clockwise'#13 +
+ 'Key Up - Rotate counterclockwise'#13 +
+ 'Key Right - Next image transformation'#13 +
+ 'Key Left - Previous image transformation'#13 +
+ 'Key Plus - Increase gamma'#13 +
+ 'Key Minus - Decrease gamma' );
+
+ if key = key_down then
+ begin
+ m_angle:=m_angle - angle_step;
+
+ if m_angle < 0 then
+ m_angle:=360 - angle_step;
+
+ force_redraw;
+
+ end;
+
+ if key = key_up then
+ begin
+ m_angle:=m_angle + angle_step;
+
+ if m_angle > 360 then
+ m_angle:=angle_step;
+
+ force_redraw;
+
+ end;
+
+ if key = key_right then
+ begin
+ inc(m_image );
+
+ if m_image > 8 then
+ m_image:=1;
+
+ force_redraw;
+
+ end;
+
+ if key = key_left then
+ begin
+ dec(m_image );
+
+ if m_image < 1 then
+ m_image:=8;
+
+ force_redraw;
+
+ end;
+
+ if key = key_kp_plus then
+ begin
+ m_gamma:=m_gamma + gamma_step;
+
+ Str(m_gamma:0:2 ,m_gmText ); m_gmText:='Gamma: ' + m_gmText;
+
+ force_redraw;
+
+ end;
+
+ if key = key_kp_minus then
+ begin
+ m_gamma:=m_gamma - gamma_step;
+
+ Str(m_gamma:0:2 ,m_gmText ); m_gmText:='Gamma: ' + m_gmText;
+
+ force_redraw;
+
+ end;
+
+end;
+
+VAR
+ app : the_application;
+ buf : array [0..255 ] of char;
+ ext : string[10 ];
+
+ img_name ,p ,n ,x : shortstring;
+
+BEGIN
+ if Agg2DUsesFreeType then
+ begin
+ FONT_TIMES:='times.ttf';
+ FONT_ARIAL:='arial.ttf';
+ FONT_VERDA:='verdana.ttf';
+
+ end;
+
+ app.Construct(pix_format_bgra32 ,flip_y );
+ app.caption_ ('Agg2DDemo (F1-Help)' );
+
+ img_name:='spheres2';
+
+{$IFDEF WIN32 }
+ if ParamCount > 0 then
+ begin
+ spread_name(ParamStr(1 ) ,p ,n ,x );
+
+ img_name:=fold_name(p ,n ,'' );
+
+ end;
+
+{$ENDIF }
+
+ if not app.load_img(0 ,img_name ) then
+ begin
+ img_name:=img_name + #0;
+ ext :=app._img_ext + #0;
+
+ if img_name = 'spheres2'#0 then
+ begin
+ sprintf(@buf[0 ] ,'File not found: %s' ,ptrcomp(@img_name[1 ] ) );
+ sprintf(@buf[StrLen(@buf ) ] ,'%s. '#13'Download http://www.antigrain.com/' ,ptrcomp(@ext[1 ] ) );
+ sprintf(@buf[StrLen(@buf ) ] ,'%s' ,ptrcomp(@img_name[1 ] ) );
+ sprintf(@buf[StrLen(@buf ) ] ,'%s'#13'or copy it from another directory if available.' ,ptrcomp(@ext[1 ] ) );
+
+ end
+ else
+ begin
+ sprintf(@buf[0 ] ,'File not found: %s' ,ptrcomp(@img_name[1 ] ) );
+ sprintf(@buf[StrLen(@buf ) ] ,'%s' ,ptrcomp(@ext[1 ] ) );
+
+ end;
+
+ app.message_(@buf[0 ] );
+
+ end
+ else
+ if app.init(600 ,600 ,window_resize ) then
+ app.run;
+
+ app.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/aa_demo.dpr b/src/corelib/render/software/agg-demos/aa_demo.dpr
new file mode 100644
index 00000000..d2aef70d
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/aa_demo.dpr
@@ -0,0 +1,456 @@
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ aa_demo ;
+
+uses
+ agg_basics ,
+ agg_platform_support ,
+ agg_math ,
+
+ agg_color ,
+ agg_pixfmt ,
+ agg_pixfmt_rgb ,
+
+ agg_ctrl ,
+ agg_slider_ctrl ,
+ agg_cbox_ctrl ,
+
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_rasterizer_scanline_aa ,
+ agg_scanline ,
+ agg_scanline_p ,
+ agg_scanline_u ,
+ agg_render_scanlines ,
+
+ agg_gamma_functions ,
+ agg_path_storage ,
+ agg_conv_stroke ,
+ agg_vertex_source ;
+
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+type
+ square = object
+ m_size : double;
+
+ constructor Construct(size : double );
+
+ procedure draw(ras : rasterizer_scanline_aa_ptr; sl : scanline_ptr; ren : renderer_scanline_ptr; x ,y : double );
+
+ end;
+
+ renderer_enlarged = object(renderer_scanline )
+ m_ras : rasterizer_scanline_aa;
+ m_sl : scanline_u8;
+ m_ren : renderer_scanline_aa_solid_ptr;
+
+ m_square : square;
+ m_color : aggclr;
+ m_size : double;
+
+ constructor Construct(ren : renderer_scanline_aa_solid_ptr; size : double );
+ destructor Destruct;
+
+ procedure color (c : aggclr_ptr ); virtual;
+ procedure prepare(u : unsigned ); virtual;
+ procedure render (sl : scanline_ptr ); virtual;
+
+ end;
+
+ the_application = object(platform_support )
+ m_x ,
+ m_y : array[0..2 ] of double;
+
+ m_dx ,
+ m_dy : double;
+
+ m_idx : int;
+
+ m_slider1 ,
+ m_slider2 : slider_ctrl;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure on_draw; virtual;
+
+ procedure on_mouse_move (x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_up (x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ CONSTRUCT }
+constructor square.Construct;
+begin
+ m_size:=size;
+
+end;
+
+{ DRAW }
+procedure square.Draw;
+begin
+ ras.reset;
+
+ ras.move_to_d(x * m_size ,y * m_size );
+ ras.line_to_d(x * m_size + m_size ,y * m_size );
+ ras.line_to_d(x * m_size + m_size ,y * m_size + m_size );
+ ras.line_to_d(x * m_size ,y * m_size + m_size );
+
+ render_scanlines(ras ,sl ,ren );
+
+end;
+
+{ CONSTRUCT }
+constructor renderer_enlarged.Construct;
+begin
+ m_square.Construct(size );
+
+ m_ras.Construct;
+ m_sl.Construct;
+ m_color.Construct;
+
+ m_ren :=ren;
+ m_size:=size;
+
+end;
+
+{ DESTRUCT }
+destructor renderer_enlarged.Destruct;
+begin
+ m_ras.Destruct;
+ m_sl.Destruct;
+
+end;
+
+{ COLOR }
+procedure renderer_enlarged.color;
+begin
+ m_color:=c^;
+
+end;
+
+{ PREPARE }
+procedure renderer_enlarged.prepare;
+begin
+end;
+
+{ RENDER }
+procedure renderer_enlarged.render;
+var
+ y ,x ,a ,
+ num_pix : int;
+
+ num_spans : unsigned;
+
+ span : span_u8_ptr;
+ covers : int8u_ptr;
+
+ rgba : aggclr;
+
+begin
+ y :=sl.y;
+ num_spans:=sl.num_spans;
+ span :=sl.begin_;
+
+ repeat
+ x :=span.x;
+ covers :=span.covers;
+ num_pix:=span.len;
+
+ repeat
+ a:=shr_int32(covers^ * m_color.a ,8 );
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+
+ rgba.ConstrInt(m_color.r ,m_color.g ,m_color.b ,a );
+ m_ren.color_ (@rgba );
+ m_square.draw (@m_ras ,@m_sl ,m_ren ,x ,y );
+
+ inc(x );
+ dec(num_pix );
+
+ until num_pix = 0;
+
+ dec(num_spans );
+
+ until num_spans = 0;
+
+end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_slider1.Construct(80 ,10 ,600 - 10 ,19 ,not flip_y );
+ m_slider2.Construct(80 ,10 + 20 ,600 - 10 ,19 + 20 ,not flip_y_ );
+
+ m_idx:=-1;
+
+ m_x[0 ]:=57; m_y[0 ]:=100;
+ m_x[1 ]:=369; m_y[1 ]:=170;
+ m_x[2 ]:=143; m_y[2 ]:=310;
+
+ add_ctrl(@m_slider1 );
+ add_ctrl(@m_slider2 );
+
+ m_slider1.range_ (8.0 ,100.0 );
+ m_slider1.num_steps_(23 );
+ m_slider1.value_ (32.0 );
+
+ m_slider2.range_(0.1 ,3.0 );
+ m_slider2.value_(1.0 );
+
+ m_slider1.label_('Pixel size=%1.0f' );
+ m_slider2.label_('Gamma=%4.3f' );
+
+ m_slider1.no_transform;
+ m_slider2.no_transform;
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_slider1.Destruct;
+ m_slider2.Destruct;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ size_mul : int;
+
+ pixf : pixel_formats;
+
+ rb : renderer_base;
+ ren : renderer_scanline_aa_solid;
+ ras : rasterizer_scanline_aa;
+ sl : scanline_u8;
+
+ rgba : aggclr;
+ gm_no : vertex_source;
+ gm_pw : gamma_power;
+
+ ren_en : renderer_enlarged;
+
+ ps : path_storage;
+ pg : conv_stroke;
+
+begin
+// Initialize structures
+ pixfmt_bgr24(pixf ,rbuf_window );
+
+ rb.Construct (@pixf );
+ ren.Construct(@rb );
+
+ rgba.ConstrDbl(1 ,1 ,1 );
+ rb.clear(@rgba );
+
+ sl.Construct;
+ ras.Construct;
+
+// Draw Zoomed Triangle
+ size_mul:=trunc(m_slider1._value );
+
+ gm_pw.Construct(m_slider2._value );
+ ras.gamma (@gm_pw );
+
+ ren_en.Construct(@ren ,size_mul );
+
+ rgba.ConstrInt(0 ,0 ,0 ,255 );
+ ren_en.color (@rgba );
+
+ ras.reset;
+ ras.move_to_d(m_x[0 ] / size_mul ,m_y[0 ] / size_mul );
+ ras.line_to_d(m_x[1 ] / size_mul ,m_y[1 ] / size_mul );
+ ras.line_to_d(m_x[2 ] / size_mul ,m_y[2 ] / size_mul );
+
+ render_scanlines(@ras ,@sl ,@ren_en );
+
+// Draw final triangle bottom-left
+ rgba.ConstrInt(0 ,0 ,0 );
+ ren.color_ (@rgba );
+
+ render_scanlines(@ras ,@sl ,@ren );
+
+// Draw The Supposed Triangle over
+ gm_no.Construct;
+ ras.gamma(@gm_no );
+
+ ps.Construct;
+ pg.Construct(@ps );
+ pg.width_ (2.0 );
+
+ rgba.ConstrInt(0 ,150 ,160 ,200 );
+ ren.color_ (@rgba );
+
+ ps.remove_all;
+ ps.move_to(m_x[0 ] ,m_y[0 ] );
+ ps.line_to(m_x[1 ] ,m_y[1 ] );
+
+ ras.add_path(@pg );
+
+ render_scanlines(@ras ,@sl ,@ren );
+
+ ps.remove_all;
+ ps.move_to(m_x[1 ] ,m_y[1 ] );
+ ps.line_to(m_x[2 ] ,m_y[2 ] );
+
+ ras.add_path(@pg );
+
+ render_scanlines(@ras ,@sl ,@ren );
+
+ ps.remove_all;
+ ps.move_to(m_x[2 ] ,m_y[2 ] );
+ ps.line_to(m_x[0 ] ,m_y[0 ] );
+
+ ras.add_path(@pg );
+
+ render_scanlines(@ras ,@sl ,@ren );
+
+// Render the controls
+ render_ctrl(@ras ,@sl ,@ren ,@m_slider1 );
+ render_ctrl(@ras ,@sl ,@ren ,@m_slider2 );
+
+// Free AGG resources
+ ras.Destruct;
+ sl.Destruct;
+
+ pg.Destruct;
+ ps.Destruct;
+
+ ren_en.Destruct;
+
+end;
+
+{ ON_MOUSE_MOVE }
+procedure the_application.on_mouse_move;
+var
+ dx ,dy : double;
+
+begin
+ if flags and mouse_left <> 0 then
+ begin
+ if m_idx = 3 then
+ begin
+ dx:=x - m_dx;
+ dy:=y - m_dy;
+
+ m_x[1 ]:=m_x[1 ] - (m_x[0 ] - dx );
+ m_y[1 ]:=m_y[1 ] - (m_y[0 ] - dy );
+ m_x[2 ]:=m_x[2 ] - (m_x[0 ] - dx );
+ m_y[2 ]:=m_y[2 ] - (m_y[0 ] - dy );
+ m_x[0 ]:= dx;
+ m_y[0 ]:= dy;
+
+ force_redraw;
+ exit;
+
+ end;
+
+ if m_idx >= 0 then
+ begin
+ m_x[m_idx ]:=x - m_dx;
+ m_y[m_idx ]:=y - m_dy;
+
+ force_redraw;
+
+ end;
+
+ end
+ else
+ on_mouse_button_up(x ,y ,flags );
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure the_application.on_mouse_button_down;
+var
+ i : unsigned;
+
+begin
+ if flags and mouse_left <> 0 then
+ begin
+ i:=0;
+
+ while i < 3 do
+ begin
+ if Sqrt((x - m_x[ i ] ) * (x - m_x[i ] ) + (y - m_y[i ] ) * (y - m_y[i ] ) ) < 10.0 then
+ begin
+ m_dx :=x - m_x[i ];
+ m_dy :=y - m_y[i ];
+ m_idx:=i;
+
+ break;
+
+ end;
+
+ inc(i );
+
+ end;
+
+ if i = 3 then
+ if point_in_triangle(m_x[0 ] ,m_y[0 ] ,m_x[1 ] ,m_y[1 ] ,m_x[2 ] ,m_y[2 ] ,x ,y ) then
+ begin
+ m_dx :=x - m_x[0 ];
+ m_dy :=y - m_y[0 ];
+ m_idx:=3;
+
+ end;
+
+ end;
+
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+procedure the_application.on_mouse_button_up;
+begin
+ m_idx:=-1;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ 'Demonstration of the Anti-Aliasing principle with Subpixel Accuracy.'#13 +
+ 'The triangle is rendered two times, with its "natural" size (at the bottom-left)'#13 +
+ 'and enlarged. To draw the enlarged version there was a special scanline'#13 +
+ 'renderer written (see class renderer_enlarged in the source code).'#13#13+
+ 'How to play with:'#13#13 +
+ 'You can drag the whole triangle as well as each vertex of it.'#13 +
+ 'Also change "Gamma" to see how it affects the quality of Anti-Aliasing.' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+VAR
+ app : the_application;
+
+BEGIN
+ app.Construct(pix_format_bgr24 ,flip_y );
+ app.caption_ ('AGG Example. Anti-Aliasing Demo (F1-Help)' );
+
+ if app.init(600 ,400 ,window_resize ) then
+ app.run;
+
+ app.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/aa_test.dpr b/src/corelib/render/software/agg-demos/aa_test.dpr
new file mode 100644
index 00000000..acb671b5
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/aa_test.dpr
@@ -0,0 +1,804 @@
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ aa_test ;
+
+uses
+ Math ,SysUtils ,
+
+ agg_basics ,
+ agg_platform_support ,
+ agg_color ,
+ agg_pixfmt ,
+ agg_pixfmt_rgb ,
+
+ agg_ctrl ,
+ agg_slider_ctrl ,
+ agg_cbox_ctrl ,
+
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_rasterizer_scanline_aa ,
+ agg_scanline ,
+ agg_scanline_u ,
+ agg_render_scanlines ,
+
+ agg_gamma_lut ,
+ agg_gamma_functions ,
+ agg_vertex_source ,
+ agg_conv_stroke ,
+ agg_conv_dash ,
+ agg_math_stroke ,
+ agg_trans_affine ,
+ agg_span_gradient ,
+ agg_span_interpolator_linear ,
+ agg_span_gouraud_rgba ,
+ agg_span_allocator ,
+ agg_array ,
+ agg_ellipse ;
+
+{$I agg_mode.inc }
+
+const
+ flip_y = false;
+
+type
+ simple_vertex_source = object(vertex_source )
+ m_num_vertices ,
+ m_count : unsigned;
+
+ m_x ,
+ m_y : array[0..7 ] of double;
+ m_cmd : array[0..7 ] of unsigned;
+
+ constructor Construct; overload;
+ constructor Construct(x1 ,y1 ,x2 ,y2 : double ); overload;
+ constructor Construct(x1 ,y1 ,x2 ,y2 ,x3 ,y3 : double ); overload;
+
+ procedure init(x1 ,y1 ,x2 ,y2 : double ); overload;
+ procedure init(x1 ,y1 ,x2 ,y2 ,x3 ,y3 : double ); overload;
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ end;
+
+ dashed_line = object
+ m_ras : rasterizer_scanline_aa_ptr;
+ m_ren : renderer_scanline_aa_solid_ptr;
+ m_sl : scanline_ptr;
+ m_src : simple_vertex_source;
+ m_dash : conv_dash;
+
+ m_stroke ,
+ m_dash_stroke : conv_stroke;
+
+ constructor Construct(ras : rasterizer_scanline_aa_ptr; ren : renderer_scanline_aa_solid_ptr; sl : scanline_ptr );
+ destructor Destruct;
+
+ procedure draw(x1 ,y1 ,x2 ,y2 ,line_width ,dash_length : double );
+
+ end;
+
+ the_application = object(platform_support )
+ m_gamma : gamma_lut;
+
+ m_slider_gamma : slider_ctrl;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure on_draw; virtual;
+
+ procedure on_mouse_move (x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_up (x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ min }
+function min(a ,b : int ) : int;
+begin
+ if a < b then
+ result:=a
+ else
+ result:=b;
+
+end;
+
+{ min_d }
+function min_d(a ,b : double ) : double;
+begin
+ if a < b then
+ result:=a
+ else
+ result:=b;
+
+end;
+
+{ frand }
+function frand(x : double ) : double;
+begin
+ result:=
+ ((((Random($7fff ) shl 15 ) or Random($7fff ) ) and $3FFFFFFF) mod 1000000) * x / 1000000.0;
+
+end;
+
+{ calc_linear_gradient_transform }
+// Calculate the affine transformation matrix for the linear gradient
+// from (x1, y1) to (x2, y2). gradient_d2 is the "base" to scale the
+// gradient. Here d1 must be 0.0, and d2 must equal gradient_d2.
+procedure calc_linear_gradient_transform(
+ x1 ,y1 ,x2 ,y2 : double;
+ mtx : trans_affine_ptr;
+ gradient_d2 : double = 100.0 );
+var
+ dx ,dy : double;
+
+ tas : trans_affine_scaling;
+ tar : trans_affine_rotation;
+ tat : trans_affine_translation;
+
+begin
+ dx:=x2 - x1;
+ dy:=y2 - y1;
+
+ tas.Construct(Sqrt(dx * dx + dy * dy ) / gradient_d2 );
+ tar.Construct(ArcTan2(dy ,dx ) );
+ tat.Construct(x1 + 0.5 ,y1 + 0.5 );
+
+ mtx.reset;
+ mtx.multiply(@tas );
+ mtx.multiply(@tar );
+ mtx.multiply(@tat );
+ mtx.invert;
+
+end;
+
+{ fill_color_array }
+// A simple function to form the gradient color array
+// consisting of 3 colors, "begin", "middle", "end"
+procedure fill_color_array(array_ : pod_auto_array_ptr; begin_ ,end_ : aggclr_ptr );
+var
+ i : unsigned;
+
+begin
+ for i:=0 to 255 do
+ aggclr_ptr(array_.array_operator(i ) )^:=begin_.gradient(end_ ,i / 255.0 );
+
+end;
+
+{ CONSTRUCT }
+constructor simple_vertex_source.Construct;
+begin
+ m_num_vertices:=0;
+ m_count :=0;
+
+ m_cmd[0 ]:=path_cmd_stop;
+
+end;
+
+{ CONSTRUCT }
+constructor simple_vertex_source.Construct(x1 ,y1 ,x2 ,y2 : double );
+begin
+ init(x1 ,y1 ,x2 ,y2 );
+
+end;
+
+{ CONSTRUCT }
+constructor simple_vertex_source.Construct(x1 ,y1 ,x2 ,y2 ,x3 ,y3 : double );
+begin
+ init(x1 ,y1 ,x2 ,y2 ,x3 ,y3 );
+
+end;
+
+{ INIT }
+procedure simple_vertex_source.init(x1 ,y1 ,x2 ,y2 : double );
+begin
+ m_num_vertices:=2;
+ m_count :=0;
+
+ m_x[0 ]:=x1;
+ m_y[0 ]:=y1;
+ m_x[1 ]:=x2;
+ m_y[1 ]:=y2;
+
+ m_cmd[0 ]:=path_cmd_move_to;
+ m_cmd[1 ]:=path_cmd_line_to;
+ m_cmd[2 ]:=path_cmd_stop;
+
+end;
+
+{ INIT }
+procedure simple_vertex_source.init(x1 ,y1 ,x2 ,y2 ,x3 ,y3 : double );
+begin
+ m_num_vertices:=3;
+ m_count :=0;
+
+ m_x[0 ]:=x1;
+ m_y[0 ]:=y1;
+ m_x[1 ]:=x2;
+ m_y[1 ]:=y2;
+ m_x[2 ]:=x3;
+ m_y[2 ]:=y3;
+ m_x[3 ]:=0.0;
+ m_y[3 ]:=0.0;
+ m_x[4 ]:=0.0;
+ m_y[4 ]:=0.0;
+
+ m_cmd[0 ]:=path_cmd_move_to;
+ m_cmd[1 ]:=path_cmd_line_to;
+ m_cmd[2 ]:=path_cmd_line_to;
+ m_cmd[3 ]:=path_cmd_end_poly or path_flags_close;
+ m_cmd[4 ]:=path_cmd_stop;
+
+end;
+
+{ REWIND }
+procedure simple_vertex_source.rewind;
+begin
+ m_count:=0;
+
+end;
+
+{ VERTEX }
+function simple_vertex_source.vertex;
+begin
+ x^:=m_x[m_count ];
+ y^:=m_y[m_count ];
+
+ result:=m_cmd[m_count ];
+
+ inc(m_count );
+
+end;
+
+{ CONSTRUCT }
+constructor dashed_line.Construct;
+begin
+ m_ras:=ras;
+ m_ren:=ren;
+ m_sl :=sl;
+
+ m_src.Construct;
+ m_dash.Construct (@m_src );
+ m_stroke.Construct (@m_src );
+ m_dash_stroke.Construct(@m_dash );
+
+end;
+
+{ DESTRUCT }
+destructor dashed_line.Destruct;
+begin
+ m_dash.Destruct;
+ m_stroke.Destruct;
+ m_dash_stroke.Destruct;
+
+end;
+
+{ DRAW }
+procedure dashed_line.draw;
+begin
+ m_src.init(x1 + 0.5 ,y1 + 0.5 ,x2 + 0.5 ,y2 + 0.5 );
+ m_ras.reset;
+
+ if dash_length > 0.0 then
+ begin
+ m_dash.remove_all_dashes;
+ m_dash.add_dash(dash_length ,dash_length );
+
+ m_dash_stroke.width_ (line_width );
+ m_dash_stroke.line_cap_(round_cap );
+
+ m_ras.add_path(@m_dash_stroke );
+
+ end
+ else
+ begin
+ m_stroke.width_ (line_width );
+ m_stroke.line_cap_(round_cap );
+
+ m_ras.add_path(@m_stroke );
+
+ end;
+
+ render_scanlines(m_ras ,m_sl ,m_ren );
+
+end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_gamma.Construct(1.0 );
+
+ m_slider_gamma.Construct(3 ,3 ,480 - 3 ,8 ,not flip_y_ );
+
+ add_ctrl(@m_slider_gamma );
+
+ m_slider_gamma.range_(0.1 ,3.0 );
+ m_slider_gamma.value_(1.6 );
+ m_slider_gamma.label_('Gamma=%4.3f' );
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_gamma.Destruct;
+
+ m_slider_gamma.Destruct;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ pixf : pixel_formats;
+
+ ren_base : renderer_base;
+ ren_sl : renderer_scanline_aa_solid;
+
+ ras : rasterizer_scanline_aa;
+ sl : scanline_u8;
+
+ rgba ,
+ rgbb : aggclr;
+ gm_pw : gamma_power;
+
+ i : int;
+
+ dash : dashed_line;
+
+ cx ,cy ,n ,x1 ,y1 ,x2 ,y2 : double;
+
+ gradient_func : gradient_x; // The gradient function
+ gradient_mtx : trans_affine; // Affine transformer
+ span_interpolator : span_interpolator_linear; // Span interpolator
+ span_allocator_ : span_allocator; // Span Allocator
+ gradient_colors : pod_auto_array; // The gradient colors
+ span_gradient_ : span_gradient;
+ ren_gradient : renderer_scanline_aa;
+ dash_gradient : dashed_line;
+
+ ell : ellipse;
+
+begin
+// Initialize structures
+ pixfmt_bgr24_gamma(pixf ,rbuf_window ,@m_gamma );
+
+ ren_base.Construct(@pixf );
+ ren_sl.Construct (@ren_base );
+
+ ras.Construct;
+ sl.Construct;
+
+ rgba.ConstrInt(0 ,0 ,0 );
+ ren_base.clear(@rgba );
+
+// gamma correction
+ m_gamma.gamma_(m_slider_gamma._value );
+
+// radial line test
+ dash.Construct(@ras ,@ren_sl ,@sl );
+
+ cx:=_width / 2.0;
+ cy:=_height / 2.0;
+
+ rgba.ConstrDbl(1.0 ,1.0 ,1.0 ,0.2 );
+ ren_sl.color_ (@rgba );
+
+ for i:=180 downto 1 do
+ begin
+ n:=2.0 * pi * i / 180.0;
+
+ if i < 90 then
+ dash.draw(
+ cx + min_d(cx ,cy ) * Sin(n ) ,
+ cy + min_d(cx ,cy ) * Cos(n ) ,
+ cx ,cy ,1.0 ,i )
+ else
+ dash.draw(
+ cx + min_d(cx ,cy ) * Sin(n ) ,
+ cy + min_d(cx ,cy ) * Cos(n ) ,
+ cx ,cy ,1.0 ,0.0 );
+
+ end;
+
+// Initialize gradients
+ gradient_func.Construct;
+ gradient_mtx.Construct;
+ span_interpolator.Construct(@gradient_mtx );
+ span_allocator_.Construct;
+ gradient_colors.Construct(256 ,sizeof(aggclr ) );
+ span_gradient_.Construct(
+ @span_allocator_ ,
+ @span_interpolator ,
+ @gradient_func ,
+ @gradient_colors ,
+ 0 ,100 );
+
+ ren_gradient.Construct (@ren_base ,@span_gradient_ );
+ dash_gradient.Construct(@ras ,@ren_gradient ,@sl );
+
+ ell.Construct;
+
+// Top patterns
+ for i:=1 to 20 do
+ begin
+ rgba.ConstrDbl(1 ,1 ,1 );
+ ren_sl.color_ (@rgba );
+
+ // integral point sizes 1..20
+ ell.init(20 + i * (i + 1 ) + 0.5 ,20.5 ,i / 2.0 ,i / 2.0 ,8 + i );
+
+ ras.reset;
+ ras.add_path(@ell );
+
+ render_scanlines(@ras ,@sl ,@ren_sl );
+
+ // fractional point sizes 0..2
+ ell.init(18 + i * 4 + 0.5 ,33 + 0.5 ,i / 20.0 ,i / 20.0 ,8 );
+
+ ras.reset;
+ ras.add_path(@ell );
+
+ render_scanlines(@ras ,@sl ,@ren_sl );
+
+ // fractional point positioning
+ ell.init(
+ 18 + i * 4 + (i - 1 ) / 10.0 + 0.5 ,
+ 27 + (i - 1 ) / 10.0 + 0.5 ,
+ 0.5 ,0.5 ,8 );
+
+ ras.reset;
+ ras.add_path(@ell );
+
+ render_scanlines(@ras ,@sl ,@ren_sl );
+
+ // integral line widths 1..20
+ rgba.ConstrDbl (1 ,1 ,1 );
+ rgbb.ConstrDbl (i mod 2 ,(i mod 3 ) * 0.5 ,(i mod 5 ) * 0.25 );
+ fill_color_array(@gradient_colors ,@rgba ,@rgbb );
+
+ x1:=20 + i* (i + 1 );
+ y1:=40.5;
+ x2:=20 + i * (i + 1 ) + (i - 1 ) * 4;
+ y2:=100.5;
+
+ calc_linear_gradient_transform(x1 ,y1 ,x2 ,y2 ,@gradient_mtx );
+ dash_gradient.draw (x1 ,y1 ,x2 ,y2 ,i ,0 );
+
+ rgba.ConstrDbl (1 ,0 ,0 );
+ rgbb.ConstrDbl (0 ,0 ,1 );
+ fill_color_array(@gradient_colors ,@rgba ,@rgbb );
+
+ // fractional line lengths H (red/blue)
+ x1:=17.5 + i * 4;
+ y1:=107;
+ x2:=17.5 + i * 4 + i / 6.66666667;
+ y2:=107;
+
+ calc_linear_gradient_transform(x1 ,y1 ,x2 ,y2 ,@gradient_mtx );
+ dash_gradient.draw (x1 ,y1 ,x2 ,y2 ,1.0 ,0 );
+
+ // fractional line lengths V (red/blue)
+ x1:=18 + i * 4;
+ y1:=112.5;
+ x2:=18 + i * 4;
+ y2:=112.5 + i / 6.66666667;
+
+ calc_linear_gradient_transform(x1 ,y1 ,x2 ,y2 ,@gradient_mtx );
+ dash_gradient.draw (x1 ,y1 ,x2 ,y2 ,1.0 ,0 );
+
+ // fractional line positioning (red)
+ rgba.ConstrDbl (1 ,0 ,0 );
+ rgbb.ConstrDbl (1 ,1 ,1 );
+ fill_color_array(@gradient_colors ,@rgba ,@rgbb );
+
+ x1:=21.5;
+ y1:=120 + (i - 1 ) * 3.1;
+ x2:=52.5;
+ y2:=120 + (i - 1 ) * 3.1;
+
+ calc_linear_gradient_transform(x1 ,y1 ,x2 ,y2 ,@gradient_mtx );
+ dash_gradient.draw (x1 ,y1 ,x2 ,y2 ,1.0 ,0 );
+
+ // fractional line width 2..0 (green)
+ rgba.ConstrDbl (0 ,1 ,0 );
+ rgbb.ConstrDbl (1 ,1 ,1 );
+ fill_color_array(@gradient_colors ,@rgba ,@rgbb );
+
+ x1:=52.5;
+ y1:=118 + i * 3;
+ x2:=83.5;
+ y2:=118 + i * 3;
+
+ calc_linear_gradient_transform(x1 ,y1 ,x2 ,y2 ,@gradient_mtx );
+ dash_gradient.draw (x1 ,y1 ,x2 ,y2 ,2.0 - (i - 1 ) / 10.0 ,0 );
+
+ // stippled fractional width 2..0 (blue)
+ rgba.ConstrDbl (0 ,0 ,1 );
+ rgbb.ConstrDbl (1 ,1 ,1 );
+ fill_color_array(@gradient_colors ,@rgba ,@rgbb );
+
+ x1:=83.5;
+ y1:=119 + i * 3;
+ x2:=114.5;
+ y2:=119 + i * 3;
+
+ calc_linear_gradient_transform(x1 ,y1 ,x2 ,y2 ,@gradient_mtx );
+ dash_gradient.draw (x1 ,y1 ,x2 ,y2 ,2.0 - (i - 1 ) / 10.0, 3.0 );
+
+ // integral line width, horz aligned (mipmap test)
+ rgba.ConstrDbl(1 ,1 ,1 );
+ ren_sl.color_ (@rgba );
+
+ if i <= 10 then
+ dash.draw(
+ 125.5 ,119.5 + (i + 2 ) * (i / 2.0 ) ,
+ 135.5 ,119.5 + (i + 2 ) * (i / 2.0 ) ,i ,0.0 );
+
+
+ // fractional line width 0..2, 1 px H
+ //-----------------
+ dash.draw(17.5 + i * 4 ,192 ,18.5 + i * 4 ,192 ,i / 10.0 ,0 );
+
+ // fractional line positioning, 1 px H
+ //-----------------
+ dash.draw(
+ 17.5 + i * 4 + (i - 1 ) / 10.0 ,186 ,
+ 18.5 + i * 4 + (i - 1 ) / 10.0 ,186 ,
+ 1.0 ,0 );
+
+ end;
+
+
+// Triangles
+ for i:=1 to 13 do
+ begin
+ rgba.ConstrDbl (1 ,1 ,1 );
+ rgbb.ConstrDbl (i mod 2 ,(i mod 3 ) * 0.5 ,(i mod 5 ) * 0.25 );
+ fill_color_array(@gradient_colors ,@rgba ,@rgbb );
+
+ calc_linear_gradient_transform(
+ _width - 150 ,
+ _height - 20 - i * (i + 1.5 ) ,
+ _width - 20,
+ _height - 20 - i * (i + 1 ) ,
+ @gradient_mtx );
+
+ ras.reset;
+ ras.move_to_d(_width - 150 ,_height - 20 - i * (i + 1.5 ) );
+ ras.line_to_d(_width - 20 ,_height - 20 - i * (i + 1 ) );
+ ras.line_to_d(_width - 20 ,_height - 20 - i * (i + 2 ) );
+
+ render_scanlines(@ras ,@sl ,@ren_gradient );
+
+ end;
+
+// Reset AA Gamma and render the controls
+ gm_pw.Construct(1.0 );
+ ras.gamma (@gm_pw );
+
+ render_ctrl(@ras ,@sl ,@ren_sl ,@m_slider_gamma );
+
+// Free AGG resources
+ ras.Destruct;
+ sl.Destruct;
+
+ dash.Destruct;
+
+ span_allocator_.Destruct;
+ gradient_colors.Destruct;
+ dash_gradient.Destruct;
+
+end;
+
+{ ON_MOUSE_MOVE }
+procedure the_application.on_mouse_move;
+begin
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure the_application.on_mouse_button_down;
+var
+ pixf : pixel_formats;
+
+ ren_base : renderer_base;
+ ren_sl : renderer_scanline_aa_solid;
+
+ ras : rasterizer_scanline_aa;
+ sl : scanline_u8;
+
+ rgba ,
+ rgbb ,
+ rgbc : aggclr;
+
+ i : int;
+
+ w ,h ,t1 ,t2 ,t3 ,r ,x1 ,y1 ,x2 ,y2 ,x3 ,y3 : double;
+
+ ell : ellipse;
+ buf : array[0..255 ] of char;
+
+ gradient_func : gradient_x; // The gradient function
+ gradient_mtx : trans_affine; // Affine transformer
+ span_interpolator : span_interpolator_linear; // Span interpolator
+ span_allocator_ : span_allocator; // Span Allocator
+ gradient_colors : pod_auto_array; // The gradient colors
+ span_gradient_ : span_gradient;
+ ren_gradient : renderer_scanline_aa;
+ dash_gradient : dashed_line;
+
+ span_gouraud : span_gouraud_rgba;
+ ren_gouraud : renderer_scanline_aa;
+
+begin
+ RandSeed:=123;
+
+// Initialize structures
+ pixfmt_bgr24_gamma(pixf ,rbuf_window ,@m_gamma );
+
+ ren_base.Construct(@pixf );
+ ren_sl.Construct (@ren_base );
+
+ ras.Construct;
+ sl.Construct;
+
+ rgba.ConstrInt(0 ,0 ,0 );
+ ren_base.clear(@rgba );
+
+ w:=_width;
+ h:=_height;
+
+ ell.Construct;
+
+// Points
+ start_timer;
+
+ for i:=0 to 20000 - 1 do
+ begin
+ r:=frand(20.0 ) + 1.0;
+
+ ell.init(frand(w ) ,frand(h ) ,r / 2 ,r / 2 ,trunc(r ) + 10 );
+
+ ras.reset;
+ ras.add_path(@ell );
+
+ render_scanlines(@ras ,@sl ,@ren_sl );
+
+ rgba.ConstrDbl(frand(1.0 ) ,frand(1.0 ) ,frand(1.0 ) ,0.5 + frand(0.5 ) );
+ ren_sl.color_ (@rgba );
+
+ end;
+
+ t1:=elapsed_time;
+
+// Strokes
+ gradient_func.Construct;
+ gradient_mtx.Construct;
+ span_interpolator.Construct(@gradient_mtx );
+ span_allocator_.Construct;
+ gradient_colors.Construct(256 ,sizeof(aggclr ) );
+ span_gradient_.Construct(
+ @span_allocator_ ,
+ @span_interpolator ,
+ @gradient_func ,
+ @gradient_colors ,
+ 0 ,100 );
+
+ ren_gradient.Construct (@ren_base ,@span_gradient_ );
+ dash_gradient.Construct(@ras ,@ren_gradient ,@sl );
+
+ start_timer;
+
+ for i:=0 to 2000 - 1 do
+ begin
+ x1:=frand(w );
+ y1:=frand(h );
+ x2:=x1 + frand(w * 0.5 ) - w * 0.25;
+ y2:=y1 + frand(h * 0.5 ) - h * 0.25;
+
+ rgba.ConstrDbl (frand(1.0 ) ,frand(1.0 ) ,frand(1.0 ) ,0.5 + frand(0.5 ) );
+ rgbb.ConstrDbl (frand(1.0 ) ,frand(1.0 ) ,frand(1.0 ) ,frand(1.0 ) );
+ fill_color_array(@gradient_colors ,@rgba ,@rgbb );
+
+ calc_linear_gradient_transform(x1 ,y1 ,x2 ,y2 ,@gradient_mtx );
+ dash_gradient.draw (x1 ,y1 ,x2 ,y2 ,10.0 ,0 );
+
+ end;
+
+ t2:=elapsed_time;
+
+// Gouraud triangles
+ span_gouraud.Construct(@span_allocator_ );
+ ren_gouraud.Construct (@ren_base ,@span_gouraud );
+
+ start_timer;
+
+ for i:=0 to 2000 - 1 do
+ begin
+ x1:=frand(w );
+ y1:=frand(h );
+ x2:=x1 + frand(w * 0.4 ) - w * 0.2;
+ y2:=y1 + frand(h * 0.4 ) - h * 0.2;
+ x3:=x1 + frand(w * 0.4 ) - w * 0.2;
+ y3:=y1 + frand(h * 0.4 ) - h * 0.2;
+
+ rgba.ConstrDbl (frand(1.0 ) ,frand(1.0 ) ,frand(1.0 ) ,0.5 + frand(0.5 ) );
+ rgbb.ConstrDbl (frand(1.0 ) ,frand(1.0 ) ,frand(1.0 ) ,frand(1.0 ) );
+ rgbc.ConstrDbl (frand(1.0 ) ,frand(1.0 ) ,frand(1.0 ) ,frand(1.0 ) );
+ span_gouraud.colors_ (@rgba ,@rgbb ,@rgbc );
+ span_gouraud.triangle(x1 ,y1 ,x2 ,y2 ,x3 ,y3 ,0.0 );
+
+ ras.add_path(@span_gouraud );
+
+ render_scanlines(@ras ,@sl ,@ren_gouraud );
+
+ end;
+
+ t3:=elapsed_time;
+
+// Test results & Update
+ sprintf (@buf[0 ] ,'Points=%.2fK/sec, '#0 ,20000.0 / t1 );
+ sprintf (@buf[StrLen(@buf[0 ] ) ] ,'Lines=%.2fK/sec, '#0 ,2000.0 / t2 );
+ sprintf (@buf[StrLen(@buf[0 ] ) ] ,'Triangles=%.2fK/sec'#0 ,2000.0 / t3 );
+ message_(@buf[0 ] );
+
+ update_window;
+
+// Free AGG resources
+ ras.Destruct;
+ sl.Destruct;
+
+ span_allocator_.Destruct;
+ gradient_colors.Destruct;
+ dash_gradient.Destruct;
+
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+procedure the_application.on_mouse_button_up;
+begin
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ 'A test of Anti-Aliasing the same as in'#13 +
+ 'http://homepage.mac.com/arekkusu/bugs/invariance'#13 +
+ 'The performance of AGG on a typical P-IV 2GHz is:'#13 +
+ 'Points: 37.46K/sec, Lines: 5.04K/sec, Triangles: 7.43K/sec'#13#13 +
+ 'How to play with:'#13#13 +
+ 'Click any mouse button to run the performance test.'#13+
+ 'Then, after you''ll see the triangles, resize the window'#13 +
+ 'to return to the original rendering.' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+VAR
+ app : the_application;
+
+BEGIN
+ app.Construct(pix_format_bgr24 ,flip_y );
+ app.caption_ ('AGG Example. Anti-Aliasing Test (F1-Help)' );
+
+ if app.init(480 ,350 ,window_resize ) then
+ app.run;
+
+ app.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/alpha_gradient.dpr b/src/corelib/render/software/agg-demos/alpha_gradient.dpr
new file mode 100644
index 00000000..06c52b66
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/alpha_gradient.dpr
@@ -0,0 +1,503 @@
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ alpha_gradient ;
+
+uses
+ agg_basics ,
+ agg_platform_support ,
+
+ agg_color ,
+ agg_pixfmt ,
+ agg_pixfmt_rgb ,
+
+ agg_ctrl ,
+ agg_spline_ctrl ,
+
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_rasterizer_scanline_aa ,
+ agg_scanline ,
+ agg_scanline_u ,
+ agg_render_scanlines ,
+
+ agg_array ,
+ agg_span_gradient ,
+ agg_span_gradient_alpha ,
+ agg_span_interpolator_linear ,
+ agg_span_converter ,
+ agg_span_allocator ,
+ agg_ellipse ,
+ agg_vcgen_stroke ,
+ agg_trans_affine ,
+ agg_math ;
+
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+type
+ the_application = object(platform_support )
+ m_x ,
+ m_y : array[0..2 ] of double;
+ m_dx ,
+ m_dy : double;
+ m_idx : int;
+
+ m_alpha : spline_ctrl;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure fill_color_array(array_ : pod_auto_array_ptr; begin_ ,middle_ ,end_ : aggclr_ptr );
+
+ procedure on_draw; virtual;
+
+ procedure on_mouse_move (x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_up (x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_alpha.Construct(2 ,2 ,200 ,30 ,6 ,not flip_y_ );
+
+ m_idx:=-1;
+
+ m_x[0 ]:=257;
+ m_y[0 ]:=60;
+ m_x[1 ]:=369;
+ m_y[1 ]:=170;
+ m_x[2 ]:=143;
+ m_y[2 ]:=310;
+
+ m_alpha.point_(0 ,0.0 ,0.0);
+ m_alpha.point_(1 ,1.0 / 5.0 ,1.0 - 4.0 / 5.0 );
+ m_alpha.point_(2 ,2.0 / 5.0 ,1.0 - 3.0 / 5.0 );
+ m_alpha.point_(3 ,3.0 / 5.0 ,1.0 - 2.0 / 5.0 );
+ m_alpha.point_(4 ,4.0 / 5.0 ,1.0 - 1.0 / 5.0 );
+ m_alpha.point_(5 ,1.0 ,1.0 );
+
+ m_alpha.update_spline;
+
+ add_ctrl(@m_alpha );
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_alpha.Destruct;
+
+end;
+
+{ FILL_COLOR_ARRAY }
+procedure the_application.fill_color_array;
+var
+ i : unsigned;
+
+begin
+ i:=0;
+
+ while i < 128 do
+ begin
+ aggclr_ptr(array_.array_operator(i ) )^:=
+ begin_.gradient(middle_ ,i / 128.0 );
+
+ inc(i );
+
+ end;
+
+ while i < 256 do
+ begin
+ aggclr_ptr(array_.array_operator(i ) )^:=
+ middle_.gradient(end_ ,(i - 128 ) / 128.0 );
+
+ inc(i );
+
+ end;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+type
+// Gradient shape function (linear, radial, custom, etc)
+ gradient_func_type = gradient_circle;
+
+// Alpha gradient shape function (linear, radial, custom, etc)
+ gradient_alpha_func_type = gradient_xy;
+
+// Span interpolator. This object is used in all span generators
+// that operate with transformations during iterating of the spans,
+// for example, image transformers use the interpolator too.
+ interpolator_type = span_interpolator_linear;
+
+// Span allocator is an object that allocates memory for
+// the array of colors that will be used to render the
+// color spans. One object can be shared between different
+// span generators.
+ span_allocator_type = span_allocator;
+
+// Gradient colors array adaptor
+ gradient_colors_type = pod_auto_array;
+
+// Finally, the gradient span generator working with the color_type
+// color type.
+ span_gradient_type = span_gradient;
+
+// Gradient alpha array adaptor
+ gradient_alpha_type = pod_auto_array;
+
+// The alpha gradient span converter working with the color_type
+// color type.
+ span_gradient_alpha_type = span_gradient_alpha;
+
+// Span converter type
+ span_conv_type = span_converter;
+
+// The gradient (plus span converter) renderer type
+ renderer_gradient_type = renderer_scanline_aa;
+
+var
+ pf : pixel_formats;
+
+ rgba ,
+ rgbb ,
+ rgbc : aggclr;
+
+ ren_base : renderer_base;
+ ren_solid : renderer_scanline_aa_solid;
+
+ sl : scanline_u8;
+ ras : rasterizer_scanline_aa;
+
+ ell : ellipse;
+
+ i ,w ,h : unsigned;
+
+ parallelogram : array[0..5 ] of double;
+
+ tas : trans_affine_scaling;
+ tar : trans_affine_rotation;
+ tat : trans_affine_translation;
+
+ stroke : vcgen_stroke;
+
+// The gradient objects declarations
+ gradient_func : gradient_func_type; // The gradient function
+ alpha_func : gradient_alpha_func_type; // The gradient function
+ gradient_mtx , // Gradient affine transformer
+ alpha_mtx : trans_affine; // Alpha affine transformer
+ span_interpolator , // Span gradient interpolator
+ span_interpolator_alpha : interpolator_type; // Span alpha interpolator
+ span_allocator : span_allocator_type; // Span Allocator
+ color_array : gradient_colors_type; // The gradient colors
+
+ span_gradient : span_gradient_type;
+ alpha_array : gradient_alpha_type;
+ span_gradient_alpha : span_gradient_alpha_type;
+ span_conv : span_conv_type;
+ ren_gradient : renderer_gradient_type;
+
+begin
+// Initialize structures
+ pixfmt_bgr24(pf ,rbuf_window );
+
+ ren_base.Construct (@pf );
+ ren_solid.Construct(@ren_base );
+
+ rgba.ConstrDbl(1 ,1 ,1 );
+ ren_base.clear(@rgba );
+
+ sl.Construct;
+ ras.Construct;
+
+// Draw some background
+ ell.Construct;
+
+ RandSeed:=1234;
+
+ w:=trunc(_width );
+ h:=trunc(_height );
+
+ for i:=0 to 99 do
+ begin
+ ell.init(
+ Random($7fff ) mod w ,Random($7fff ) mod h ,
+ Random($7fff ) mod 60 + 5 ,Random($7fff ) mod 60 + 5 ,50 );
+
+ rgba.ConstrDbl(
+ Random($7fff ) / $7fff ,
+ Random($7fff ) / $7fff ,
+ Random($7fff ) / $7fff ,
+ Random($7fff ) / $7fff / 2.0 );
+
+ ren_solid.color_(@rgba );
+ ras.add_path (@ell);
+ render_scanlines(@ras ,@sl ,@ren_solid );
+
+ end;
+
+ parallelogram[0 ]:=m_x[0 ];
+ parallelogram[1 ]:=m_y[0 ];
+ parallelogram[2 ]:=m_x[1 ];
+ parallelogram[3 ]:=m_y[1 ];
+ parallelogram[4 ]:=m_x[2 ];
+ parallelogram[5 ]:=m_y[2 ];
+
+// The gradient objects initializations
+ gradient_func.Construct;
+ alpha_func.Construct;
+ gradient_mtx.Construct;
+ alpha_mtx.Construct;
+ span_interpolator.Construct (@gradient_mtx );
+ span_interpolator_alpha.Construct(@alpha_mtx );
+ span_allocator.Construct;
+ color_array.Construct(256 ,sizeof(aggclr ) );
+
+// Initialize the gradient span itself.
+// The last two arguments are so called "d1" and "d2"
+// defining two distances in pixels, where the gradient starts
+// and where it ends. The actual meaning of "d1" and "d2" depands
+// on the gradient function.
+ span_gradient.Construct(
+ @span_allocator ,
+ @span_interpolator ,
+ @gradient_func ,
+ @color_array ,0 ,150 );
+
+ alpha_array.Construct(256 ,sizeof(int8u ) );
+
+ span_gradient_alpha.Construct(
+ @span_interpolator_alpha ,
+ @alpha_func ,
+ @alpha_array ,0 ,100 );
+
+// Span converter initialization
+ span_conv.Construct(@span_gradient ,@span_gradient_alpha );
+
+// The gradient renderer
+ ren_gradient.Construct(@ren_base ,@span_conv );
+
+// Finally we can draw a circle
+ tas.Construct(0.75 ,1.2 );
+ tar.Construct(pi / 3.0 );
+ tat.Construct(_width / 2 ,_height / 2 );
+
+ gradient_mtx.multiply(@tas );
+ gradient_mtx.multiply(@tar );
+ gradient_mtx.multiply(@tat );
+ gradient_mtx.invert;
+
+ alpha_mtx.parl_to_rect(@parallelogram ,-100 ,-100 ,100 ,100 );
+
+ rgba.ConstrDbl(0 ,0.19 ,0.19 );
+ rgbb.ConstrDbl(0.7 ,0.7 ,0.19 );
+ rgbc.ConstrDbl(0.31 ,0 ,0 );
+
+ fill_color_array(@color_array ,@rgba ,@rgbb ,@rgbc );
+
+// Fill Alpha array
+ for i:=0 to 255 do
+ int8u_ptr(alpha_array.array_operator(i ) )^:=
+ int8u(trunc(m_alpha._value(i / 255.0 ) * base_mask ) );
+
+ ell.init(_width / 2 ,_height / 2 ,150 ,150 ,100 );
+
+ ras.add_path (@ell);
+ render_scanlines(@ras ,@sl ,@ren_gradient );
+
+// Draw the control points and the parallelogram
+ rgba.ConstrDbl (0 ,0.4 ,0.4 ,0.31 );
+ ren_solid.color_(@rgba );
+
+ ell.init (m_x[0 ] ,m_y[0 ] ,5 ,5 ,20 );
+ ras.add_path (@ell);
+ render_scanlines(@ras ,@sl ,@ren_solid );
+
+ ell.init (m_x[1 ] ,m_y[1 ] ,5 ,5 ,20 );
+ ras.add_path (@ell );
+ render_scanlines(@ras ,@sl ,@ren_solid );
+
+ ell.init (m_x[2 ] ,m_y[2 ] ,5 ,5 ,20 );
+ ras.add_path (@ell );
+ render_scanlines(@ras ,@sl ,@ren_solid );
+
+ stroke.Construct;
+ stroke.add_vertex(m_x[0 ] ,m_y[0 ] ,path_cmd_move_to );
+ stroke.add_vertex(m_x[1 ] ,m_y[1 ] ,path_cmd_line_to );
+ stroke.add_vertex(m_x[2 ] ,m_y[2 ] ,path_cmd_line_to );
+ stroke.add_vertex(m_x[0 ] + m_x[2 ] - m_x[1 ] ,m_y[0 ] + m_y[2 ] - m_y[1 ] ,path_cmd_line_to );
+ stroke.add_vertex(0 ,0 ,path_cmd_end_poly or path_flags_close );
+
+ rgba.ConstrDbl (0 ,0 ,0 );
+ ren_solid.color_(@rgba );
+ ras.add_path (@stroke);
+ render_scanlines(@ras ,@sl ,@ren_solid );
+
+// Render the controls
+ render_ctrl(@ras ,@sl ,@ren_solid ,@m_alpha );
+
+// Free AGG resources
+ sl.Destruct;
+ ras.Destruct;
+
+ span_allocator.Destruct;
+ color_array.Destruct;
+ alpha_array.Destruct;
+
+ stroke.Destruct;
+
+end;
+
+{ ON_MOUSE_MOVE }
+procedure the_application.on_mouse_move;
+var
+ dx ,dy : double;
+
+begin
+ if flags and mouse_left <> 0 then
+ begin
+ if m_idx = 3 then
+ begin
+ dx:=x - m_dx;
+ dy:=y - m_dy;
+
+ m_x[1 ]:=m_x[1 ] - (m_x[0 ] - dx );
+ m_y[1 ]:=m_y[1 ] - (m_y[0 ] - dy );
+ m_x[2 ]:=m_x[2 ] - (m_x[0 ] - dx );
+ m_y[2 ]:=m_y[2 ] - (m_y[0 ] - dy );
+ m_x[0 ]:=dx;
+ m_y[0 ]:=dy;
+
+ force_redraw;
+
+ exit;
+
+ end;
+
+ if m_idx >= 0 then
+ begin
+ m_x[m_idx ]:=x - m_dx;
+ m_y[m_idx ]:=y - m_dy;
+
+ force_redraw;
+
+ end;
+
+ end
+ else
+ on_mouse_button_up(x ,y ,flags );
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure the_application.on_mouse_button_down;
+var
+ i : unsigned;
+
+begin
+ if flags and mouse_left <> 0 then
+ begin
+ i:=0;
+
+ while i < 3 do
+ begin
+ if Sqrt((x - m_x[i ] ) * (x - m_x[i ] ) + (y - m_y[i ] ) * (y - m_y[i ] ) ) < 10.0 then
+ begin
+ m_dx :=x - m_x[i ];
+ m_dy :=y - m_y[i ];
+ m_idx:=i;
+
+ break;
+
+ end;
+
+ inc(i );
+
+ end;
+
+ if i = 3 then
+ if point_in_triangle(
+ m_x[0 ] ,m_y[0 ] ,
+ m_x[1 ] ,m_y[1 ] ,
+ m_x[2 ] ,m_y[2 ] ,x ,y ) then
+ begin
+ m_dx :=x - m_x[0 ];
+ m_dy :=y - m_y[0 ];
+ m_idx:=3;
+
+ end;
+
+ end;
+
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+procedure the_application.on_mouse_button_up;
+begin
+ m_idx:=-1;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+var
+ dx ,dy : double;
+
+begin
+ dx:=0;
+ dy:=0;
+
+ case key of
+ key_left : dx:=-0.1;
+ key_right : dx:= 0.1;
+ key_up : dy:= 0.1;
+ key_down : dy:=-0.1;
+
+ end;
+
+ m_x[0 ]:=m_x[0 ] + dx;
+ m_y[0 ]:=m_y[0 ] + dy;
+ m_x[1 ]:=m_x[1 ] + dx;
+ m_y[1 ]:=m_y[1 ] + dy;
+
+ force_redraw;
+
+ if key = key_f1 then
+ message_(
+ 'The demo shows how to combine any span generator with alpha-channel gradient.'#13#13 +
+ 'How to play with:'#13#13 +
+ 'Use the mouse to move the parallelogram around.'#13 +
+ 'Use the arrow keys to move the parallelogram very precisely.' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+VAR
+ app : the_application;
+
+BEGIN
+ app.Construct(pix_format_bgr24 ,flip_y );
+ app.caption_ ('AGG Example. Alpha channel gradient (F1-Help)' );
+
+ if app.init(400 ,320 ,window_resize ) then
+ app.run;
+
+ app.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/alpha_mask.dpr b/src/corelib/render/software/agg-demos/alpha_mask.dpr
new file mode 100644
index 00000000..cc4dc0be
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/alpha_mask.dpr
@@ -0,0 +1,346 @@
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ alpha_mask ;
+
+uses
+ Math ,
+
+ agg_basics ,
+ agg_platform_support ,
+ agg_color ,
+ agg_pixfmt ,
+ agg_pixfmt_rgb ,
+ agg_pixfmt_gray ,
+
+ agg_rendering_buffer ,
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_rasterizer_scanline_aa ,
+ agg_scanline ,
+ agg_scanline_u ,
+ agg_scanline_p ,
+ agg_render_scanlines ,
+
+ agg_ellipse ,
+ agg_path_storage ,
+ agg_conv_transform ,
+ agg_bounding_rect ,
+ agg_alpha_mask_u8 ,
+ agg_trans_affine ,
+ parse_lion_ ;
+
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+var
+ g_path : path_storage;
+ g_colors : array[0..99 ] of aggclr;
+ g_path_idx : array[0..99 ] of unsigned;
+
+ g_npaths : unsigned;
+
+ g_x1 ,g_y1 ,g_x2 ,g_y2 ,
+ g_base_dx ,g_base_dy ,
+ g_angle ,g_scale ,
+ g_skew_x ,g_skew_y : double;
+
+ g_nclick : int;
+
+ g_alpha_mask_rbuf : rendering_buffer;
+ g_alpha_mask : alpha_mask_gray8;
+ g_rasterizer : rasterizer_scanline_aa;
+
+type
+ the_application = object(platform_support )
+ m_alpha_size : unsigned;
+ m_alpha_buf : char_ptr;
+ m_alpha_rbuf : rendering_buffer;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure generate_alpha_mask(cx ,cy : int );
+
+ procedure on_resize(sx ,sy : int ); virtual;
+ procedure on_draw; virtual;
+
+ procedure transform(width_ ,height_ ,x ,y : double );
+
+ procedure on_mouse_move (x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ _PARSE_LION_ }
+procedure _parse_lion_;
+begin
+ g_npaths:=parse_lion(@g_path ,@g_colors ,@g_path_idx );
+
+ bounding_rect(@g_path ,@g_path_idx ,0 ,g_npaths ,@g_x1 ,@g_y1 ,@g_x2 ,@g_y2 );
+
+ g_base_dx:=(g_x2 - g_x1 ) / 2.0;
+ g_base_dy:=(g_y2 - g_y1 ) / 2.0;
+
+end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_alpha_size:=0;
+ m_alpha_buf :=NIL;
+
+ _parse_lion_;
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ agg_freemem(pointer(m_alpha_buf ) ,m_alpha_size );
+
+end;
+
+{ GENERATE_ALPHA_MASK }
+procedure the_application.generate_alpha_mask;
+var
+ pixf : pixel_formats;
+ rgba : aggclr;
+
+ rb : renderer_base;
+ r : renderer_scanline_aa_solid;
+ sl : scanline_p8;
+
+ ell : ellipse;
+
+ i : unsigned;
+
+begin
+ agg_freemem(pointer(m_alpha_buf ) ,m_alpha_size );
+
+ m_alpha_size:=cx * cy;
+
+ agg_getmem(pointer(m_alpha_buf ) ,m_alpha_size );
+
+ g_alpha_mask_rbuf.attach(int8u_ptr(m_alpha_buf ) ,cx ,cy ,cx );
+
+ pixfmt_gray8(pixf ,@g_alpha_mask_rbuf );
+ rb.Construct(@pixf );
+ r.Construct (@rb );
+ sl.Construct;
+
+ rgba.ConstrInt(0 );
+ rb.clear (@rgba );
+
+ ell.Construct;
+
+ for i:=0 to 9 do
+ begin
+ ell.init(
+ Random($7fff ) mod cx ,
+ Random($7fff ) mod cy ,
+ Random($7fff ) mod 100 + 20 ,
+ Random($7fff ) mod 100 + 20 ,100 );
+
+ g_rasterizer.add_path(@ell );
+
+ rgba.ConstrInt(Random($7fff ) and $FF ,Random($7fff ) and $FF );
+ r.color_ (@rgba );
+
+ render_scanlines(@g_rasterizer ,@sl ,@r );
+
+ end;
+
+ sl.Destruct;
+
+end;
+
+{ ON_RESIZE }
+procedure the_application.on_resize;
+begin
+ generate_alpha_mask(sx ,sy );
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ width_ ,height_ : int;
+
+ pixf : pixel_formats;
+
+ rb : renderer_base;
+ r : renderer_scanline_aa_solid;
+ sl : scanline_u8_am;
+
+ rgba : aggclr;
+ trans : conv_transform;
+
+ mtx : trans_affine;
+ tat : trans_affine_translation;
+ tas : trans_affine_scaling;
+ tar : trans_affine_rotation;
+ taw : trans_affine_skewing;
+
+begin
+ width_ :=rbuf_window._width;
+ height_:=rbuf_window._height;
+
+// Initialize structures
+ pixfmt_bgr24(pixf ,rbuf_window );
+
+ rb.Construct(@pixf );
+ r.Construct (@rb );
+ sl.Construct(@g_alpha_mask );
+
+ rgba.ConstrInt(255 ,255 ,255 );
+ rb.clear (@rgba );
+
+// Transform lion
+ mtx.Construct;
+
+ tat.Construct(-g_base_dx ,-g_base_dy );
+ mtx.multiply (@tat );
+
+ tas.Construct(g_scale ,g_scale );
+ mtx.multiply (@tas );
+
+ tar.Construct(g_angle + pi );
+ mtx.multiply (@tar );
+
+ taw.Construct(g_skew_x / 1000.0 ,g_skew_y / 1000.0 );
+ mtx.multiply (@taw );
+
+ tat.Construct(width_ / 2 ,height_ / 2 );
+ mtx.multiply (@tat );
+
+// This code renders the lion
+ trans.Construct(@g_path ,@mtx );
+
+ render_all_paths(@g_rasterizer ,@sl ,@r ,@trans ,@g_colors ,@g_path_idx ,g_npaths );
+
+// Free AGG resources
+ sl.Destruct;
+
+end;
+
+{ TRANSFORM }
+procedure the_application.transform;
+begin
+ x:=x - width_ / 2;
+ y:=y - height_ / 2;
+
+ g_angle:=ArcTan2(y ,x );
+ g_scale:=Sqrt(y * y + x * x ) / 100.0;
+
+end;
+
+{ ON_MOUSE_MOVE }
+procedure the_application.on_mouse_move;
+begin
+ on_mouse_button_down(x ,y ,flags );
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure the_application.on_mouse_button_down;
+var
+ width_ ,height_ : int;
+
+begin
+ if flags and mouse_left <> 0 then
+ begin
+ width_ :=rbuf_window._width;
+ height_:=rbuf_window._height;
+
+ transform(width_ ,height_ ,x ,y );
+
+ force_redraw;
+
+ end;
+
+ if flags and mouse_right <> 0 then
+ begin
+ g_skew_x:=x;
+ g_skew_y:=y;
+
+ force_redraw;
+
+ end;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ 'Alpha-mask is a simple method of clipping and masking polygons to a number'#13 +
+ 'of other arbitrary polygons. Alpha mask is a buffer that is mixed to the '#13 +
+ 'scanline container and controls the Anti-Aliasing values in it. It''s not the '#13 +
+ 'perfect mechanism of clipping, but it allows you not only to clip the polygons, '#13 +
+ 'but also to change the opacity in certain areas, i.e., the clipping can be '#13 +
+ 'translucent. '#13#13 +
+ 'How to play with:'#13#13 +
+ 'Press and drag the left mouse button to scale and rotate the lion.'#13 +
+ 'Resize the window to generate new alpha-mask.'#13 +
+ 'Use the right mouse button to skew the lion.' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+VAR
+ app : the_application;
+
+BEGIN
+// Rendering
+ g_path.Construct;
+
+ g_npaths:=0;
+
+ g_x1:=0;
+ g_y1:=0;
+ g_x2:=0;
+ g_y2:=0;
+
+ g_base_dx:=0;
+ g_base_dy:=0;
+
+ g_angle:=0;
+ g_scale:=1.0;
+
+ g_skew_x:=0;
+ g_skew_y:=0;
+ g_nclick:=0;
+
+ g_alpha_mask_rbuf.Construct;
+ g_alpha_mask.Construct(@g_alpha_mask_rbuf );
+ g_rasterizer.Construct;
+
+// App
+ app.Construct(pix_format_bgr24 ,flip_y );
+ app.caption_ ('AGG Example. Lion with Alpha-Masking (F1-Help)' );
+
+ if app.init(512 ,400 ,window_resize ) then
+ app.run;
+
+ app.Destruct;
+
+// Free
+ g_path.Destruct;
+ g_alpha_mask_rbuf.Destruct;
+ g_rasterizer.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/alpha_mask2.dpr b/src/corelib/render/software/agg-demos/alpha_mask2.dpr
new file mode 100644
index 00000000..85e68fd2
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/alpha_mask2.dpr
@@ -0,0 +1,584 @@
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ alpha_mask2 ;
+
+{DEFINE AGG_GRAY8 }
+{$DEFINE AGG_BGR24 }
+{DEFINE AGG_RGB24 }
+{DEFINE AGG_BGRA32 }
+{DEFINE AGG_RGBA32 }
+{DEFINE AGG_ARGB32 }
+{DEFINE AGG_ABGR32 }
+{DEFINE AGG_RGB565 }
+{DEFINE AGG_RGB555 }
+
+uses
+ Math ,
+
+ agg_basics ,
+ agg_array ,
+ agg_platform_support ,
+{$IFNDEF AGG_GRAY8 }
+ agg_pixfmt_gray ,
+{$ENDIF }
+ agg_pixfmt_amask_adaptor ,
+
+ agg_ctrl ,
+ agg_slider_ctrl ,
+
+ agg_rasterizer_scanline_aa ,
+ agg_rasterizer_outline_aa ,
+ agg_scanline ,
+ agg_scanline_u ,
+ agg_scanline_p ,
+
+ agg_rendering_buffer ,
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_renderer_outline_aa ,
+ agg_renderer_primitives ,
+ agg_renderer_markers ,
+ agg_render_scanlines ,
+
+ agg_alpha_mask_u8 ,
+ agg_path_storage ,
+ agg_bounding_rect ,
+ agg_trans_affine ,
+ agg_conv_transform ,
+ agg_ellipse ,
+ agg_span_gradient ,
+ agg_span_allocator ,
+ agg_span_interpolator_linear ,
+ parse_lion_
+
+{$I pixel_formats.inc }
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+var
+ g_rasterizer : rasterizer_scanline_aa;
+ g_scanline : scanline_u8;
+
+ g_path : path_storage;
+ g_colors : array[0..99 ] of aggclr;
+ g_path_idx : array[0..99 ] of unsigned;
+
+ g_npaths : unsigned;
+
+ g_x1 ,g_y1 ,g_x2 ,g_y2 ,
+ g_base_dx ,g_base_dy ,
+ g_angle ,g_scale ,
+ g_skew_x ,g_skew_y : double;
+
+ g_nclick : int;
+
+type
+ gradient_linear_color = object(pod_auto_array )
+ m_c1 ,m_c2 ,c : aggclr;
+
+ constructor Construct(c1 ,c2 : aggclr_ptr );
+
+ function size : unsigned; virtual;
+ function array_operator(i : unsigned ) : pointer; virtual;
+
+ procedure colors(c1 ,c2 : aggclr_ptr );
+
+ end;
+
+ the_application = object(platform_support )
+ m_num_cb : slider_ctrl;
+ m_alpha_buf : char_ptr;
+ m_alpha_sz : unsigned;
+ m_alpha_mask : amask_no_clip_gray8;
+
+ m_alpha_mask_rbuf : rendering_buffer;
+ m_slider_value : double;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure generate_alpha_mask(cx ,cy : int );
+
+ procedure on_resize(sx ,sy : int ); virtual;
+ procedure on_draw; virtual;
+
+ procedure transform(width_ ,height_ ,x ,y : double );
+
+ procedure on_mouse_move (x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ CONSTRUCT }
+constructor gradient_linear_color.Construct;
+begin
+ m_c1:=c1^;
+ m_c2:=c2^;
+
+end;
+
+{ SIZE }
+function gradient_linear_color.size;
+begin
+ result:=256;
+
+end;
+
+{ ARRAY_OPERATOR }
+function gradient_linear_color.array_operator;
+begin
+ c.v:=int8u((((m_c2.v - m_c1.v ) * i ) + (m_c1.v shl 8 ) ) shr 8 );
+ c.r:=int8u((((m_c2.r - m_c1.r ) * i ) + (m_c1.r shl 8 ) ) shr 8 );
+ c.g:=int8u((((m_c2.g - m_c1.g ) * i ) + (m_c1.g shl 8 ) ) shr 8 );
+ c.b:=int8u((((m_c2.b - m_c1.b ) * i ) + (m_c1.b shl 8 ) ) shr 8 );
+ c.a:=int8u((((m_c2.a - m_c1.a ) * i ) + (m_c1.a shl 8 ) ) shr 8 );
+
+ result:=@c;
+
+end;
+
+{ COLORS }
+procedure gradient_linear_color.colors;
+begin
+ m_c1:=c1^;
+ m_c2:=c2^;
+
+end;
+
+{ _PARSE_LION_ }
+procedure _parse_lion_;
+begin
+ g_npaths:=parse_lion(@g_path ,@g_colors ,@g_path_idx );
+
+ bounding_rect(@g_path ,@g_path_idx ,0 ,g_npaths ,@g_x1 ,@g_y1 ,@g_x2 ,@g_y2 );
+
+ g_base_dx:=(g_x2 - g_x1 ) / 2.0;
+ g_base_dy:=(g_y2 - g_y1 ) / 2.0;
+
+end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_num_cb.Construct(5 ,5 ,150 ,12 ,not flip_y_ );
+
+ m_alpha_buf:=NIL;
+ m_alpha_sz :=0;
+
+ m_alpha_mask_rbuf.Construct;
+ m_alpha_mask.Construct(@m_alpha_mask_rbuf );
+
+ m_slider_value:=0.0;
+
+ _parse_lion_;
+ add_ctrl(@m_num_cb );
+
+ m_num_cb.range_(5 ,100 );
+ m_num_cb.value_(10 );
+ m_num_cb.label_('N=%.2f' );
+ m_num_cb.no_transform;
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_num_cb.Destruct;
+ m_alpha_mask_rbuf.Destruct;
+
+ agg_freemem(pointer(m_alpha_buf ) ,m_alpha_sz );
+
+end;
+
+{ GENERATE_ALPHA_MASK }
+procedure the_application.generate_alpha_mask;
+var
+ pixf : pixel_formats;
+ rgba : aggclr;
+
+ rb : renderer_base;
+ r : renderer_scanline_aa_solid;
+ sl : scanline_p8;
+
+ ell : ellipse;
+
+ i : int;
+
+begin
+ agg_freemem(pointer(m_alpha_buf ) ,m_alpha_sz );
+
+ m_alpha_sz:=cx * cy;
+
+ agg_getmem(pointer(m_alpha_buf ) ,m_alpha_sz );
+
+ m_alpha_mask_rbuf.attach(int8u_ptr(m_alpha_buf ) ,cx ,cy ,cx );
+
+ pixfmt_gray8(pixf ,@m_alpha_mask_rbuf );
+
+ rb.Construct(@pixf );
+ r.Construct (@rb );
+ sl.Construct;
+
+ rgba.ConstrInt(0 );
+ rb.clear (@rgba );
+
+ ell.Construct;
+
+ RandSeed:=1432;
+
+ i:=0;
+
+ while i < m_num_cb._value do
+ begin
+ ell.init(
+ Random($7fff ) mod cx,
+ Random($7fff ) mod cy,
+ Random($7fff ) mod 100 + 20 ,
+ Random($7fff ) mod 100 + 20 ,100 );
+
+ g_rasterizer.add_path(@ell );
+
+ rgba.ConstrInt((Random($7fff ) and 127 ) + 128 ,(Random($7fff ) and 127) + 128 );
+ r.color_ (@rgba );
+
+ render_scanlines(@g_rasterizer ,@sl ,@r );
+
+ inc(i );
+
+ end;
+
+ sl.Destruct;
+
+end;
+
+{ ON_RESIZE }
+procedure the_application.on_resize;
+begin
+ generate_alpha_mask(sx ,sy );
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ i : unsigned;
+
+ width_ ,height_ ,x ,y : int;
+
+ pf : pixel_formats;
+ pfa : pixfmt_amask_adaptor;
+ r : renderer_base;
+ rb ,
+ rs : renderer_scanline_aa_solid;
+
+ rbase : renderer_base;
+ rgba ,
+ rgbb : aggclr;
+
+ mtx : trans_affine;
+ tat : trans_affine_translation;
+ tas : trans_affine_scaling;
+ tar : trans_affine_rotation;
+ taw : trans_affine_skewing;
+
+ trans : conv_transform;
+
+ m : renderer_markers;
+ w : double;
+
+ profile : line_profile_aa;
+
+ ren : renderer_outline_aa;
+ ras : rasterizer_outline_aa;
+ grm : trans_affine;
+ grf : gradient_circle;
+ grc : gradient_linear_color;
+ ell : ellipse;
+
+ sa : span_allocator;
+ sg : span_gradient;
+ rg : renderer_scanline_aa;
+
+ inter : span_interpolator_linear;
+
+begin
+ width_ :=rbuf_window._width;
+ height_:=rbuf_window._height;
+
+ if m_num_cb._value <> m_slider_value then
+ begin
+ generate_alpha_mask(width_ ,height_ );
+
+ m_slider_value:=m_num_cb._value;
+
+ end;
+
+// Initialize structures
+ pixfmt(pf ,rbuf_window );
+
+ pfa.Construct (@pf ,@m_alpha_mask );
+ r.Construct (@pfa );
+ rbase.Construct(@pf );
+ rs.Construct (@r );
+ rb.Construct (@rbase );
+
+// Transform lion
+ mtx.Construct;
+
+ tat.Construct(-g_base_dx ,-g_base_dy );
+ mtx.multiply (@tat );
+
+ tas.Construct(g_scale ,g_scale );
+ mtx.multiply (@tas );
+
+ tar.Construct(g_angle + pi );
+ mtx.multiply (@tar );
+
+ taw.Construct(g_skew_x / 1000.0 ,g_skew_y / 1000.0 );
+ mtx.multiply (@taw );
+
+ tat.Construct(_width / 2 ,_height / 2 );
+ mtx.multiply (@tat );
+
+ rgba.ConstrDbl(1 ,1 ,1 );
+ rbase.clear (@rgba );
+
+// Render the lion
+ trans.Construct (@g_path ,@mtx );
+ render_all_paths(@g_rasterizer ,@g_scanline ,@rs ,@trans ,@g_colors ,@g_path_idx ,g_npaths );
+
+// Render random Bresenham lines and markers
+ m.Construct(@r );
+
+ for i:=0 to 49 do
+ begin
+ rgba.ConstrInt(
+ Random($7fff ) and $7F ,
+ Random($7fff ) and $7F ,
+ Random($7fff ) and $7F ,
+ (Random($7fff ) and $7F ) + $7F );
+
+ m.line_color_(@rgba );
+
+ rgba.ConstrInt(
+ Random($7fff ) and $7F ,
+ Random($7fff ) and $7F ,
+ Random($7fff ) and $7F ,
+ (Random($7fff ) and $7F ) + $7F );
+
+ m.fill_color_(@rgba );
+
+ m.line(
+ m.coord(Random($7fff ) mod width_ ) ,m.coord(Random($7fff ) mod height_ ) ,
+ m.coord(Random($7fff ) mod width_ ) ,m.coord(Random($7fff ) mod height_ ) );
+
+ m.marker(
+ Random($7fff ) mod width_ ,Random($7fff ) mod height_ ,Random($7fff ) mod 10 + 5 ,
+ marker_e(Random($7fff ) mod int(end_of_markers ) ) );
+
+ end;
+
+// Render random anti-aliased lines
+ w:=5.0;
+
+ profile.Construct;
+ profile.width_(w );
+
+ ren.Construct (@r ,@profile );
+ ras.Construct (@ren );
+ ras.round_cap_(true );
+
+ for i:=0 to 49 do
+ begin
+ rgba.ConstrInt(
+ Random($7fff ) and $7F ,
+ Random($7fff ) and $7F ,
+ Random($7fff ) and $7F ,
+ (Random($7fff ) and $7F ) + $7F );
+
+ ren.color_(@rgba );
+
+ ras.move_to_d(Random($7fff ) mod width_ ,Random($7fff ) mod height_ );
+ ras.line_to_d(Random($7fff ) mod width_ ,Random($7fff ) mod height_ );
+ ras.render (false );
+
+ end;
+
+// Render random circles with gradient
+ grm.Construct;
+ grf.Construct;
+ rgba.ConstrInt(0 ,0 ,0 );
+ rgbb.ConstrInt(0 ,0 ,0 );
+ grc.Construct (@rgba ,@rgbb );
+ ell.Construct;
+ sa.Construct;
+ inter.Construct(@grm );
+
+ sg.Construct(@sa ,@inter ,@grf ,@grc ,0 ,10 );
+ rg.Construct(@r ,@sg );
+
+ for i:=0 to 49 do
+ begin
+ x:=Random($7fff ) mod width_;
+ y:=Random($7fff ) mod height_;
+ w:=Random($7fff ) mod 10 + 5;
+
+ grm.reset;
+
+ tas.Construct(w / 10.0 );
+ grm.multiply (@tas );
+
+ tat.Construct(x ,y );
+ grm.multiply (@tat );
+
+ grm.invert;
+
+ rgba.ConstrInt(255 ,255 ,255 ,0 );
+ rgbb.ConstrInt(
+ Random($7fff ) and $7F ,
+ Random($7fff ) and $7F ,
+ Random($7fff ) and $7F ,255 );
+
+ grc.colors(@rgba ,@rgbb );
+ sg.color_function_(@grc );
+
+ ell.init(x ,y ,w ,w ,32 );
+
+ g_rasterizer.add_path(@ell );
+ render_scanlines (@g_rasterizer ,@g_scanline ,@rg );
+
+ end;
+
+// Render the controls
+ render_ctrl(@g_rasterizer ,@g_scanline ,@rb ,@m_num_cb );
+
+// Free AGG resources
+ pfa.Destruct;
+ profile.Destruct;
+ ras.Destruct;
+ sa.Destruct;
+
+end;
+
+{ TRANSFORM }
+procedure the_application.transform;
+begin
+ x:=x - width_ / 2;
+ y:=y - height_ / 2;
+
+ g_angle:=ArcTan2(y ,x );
+ g_scale:=Sqrt(y * y + x * x ) / 100.0;
+
+end;
+
+{ ON_MOUSE_MOVE }
+procedure the_application.on_mouse_move;
+begin
+ on_mouse_button_down(x ,y ,flags );
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure the_application.on_mouse_button_down;
+var
+ width_ ,height_ : int;
+
+begin
+ if flags and mouse_left <> 0 then
+ begin
+ width_ :=rbuf_window._width;
+ height_:=rbuf_window._height;
+
+ transform(width_ ,height_ ,x ,y );
+
+ force_redraw;
+
+ end;
+
+ if flags and mouse_right <> 0 then
+ begin
+ g_skew_x:=x;
+ g_skew_y:=y;
+
+ force_redraw;
+
+ end;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ 'Another example of alpha-masking. In the "alpha_mask" example the alpha-mask '#13 +
+ 'is applied to the scan line container with unpacked data (scanline_u),'#13 +
+ 'while in this one there a special adapter of a pixel format renderer is used '#13 +
+ '(pixfmt_amask_adaptor). It allows you to use the alpha-mask with all possible '#13 +
+ 'primitives and renderers. Besides, if the alpha-mask buffer is of the same size '#13 +
+ 'as the main rendering buffer (usually it is) we don''t have to perform clipping '#13 +
+ 'for the alpha-mask, because all the primitives are already clipped at the higher '#13 +
+ 'level, see class amask_no_clip_u8. '#13#13 +
+ 'How to play with:'#13#13 +
+ 'Press and drag the left mouse button to scale and rotate the lion and generate '#13 +
+ 'a new set of other primitives.'#13 +
+ 'Change the "N" value to generate a new set of masking ellipses.'#13 +
+ 'Use the right mouse button to skew the lion.' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+VAR
+ app : the_application;
+
+BEGIN
+// Rendering
+ g_rasterizer.Construct;
+ g_scanline.Construct;
+ g_path.Construct;
+
+ g_npaths:=0;
+
+ g_x1:=0;
+ g_y1:=0;
+ g_x2:=0;
+ g_y2:=0;
+
+ g_base_dx:=0;
+ g_base_dy:=0;
+
+ g_angle:=0;
+ g_scale:=1.0;
+
+ g_skew_x:=0;
+ g_skew_y:=0;
+ g_nclick:=0;
+
+// App
+ app.Construct(pix_format ,flip_y );
+ app.caption_ ('AGG Example. Clipping to multiple rectangle regions (F1-Help)' );
+
+ if app.init(512 ,400 ,window_resize ) then
+ app.run;
+
+ app.Destruct;
+
+// Free
+ g_rasterizer.Destruct;
+ g_scanline.Destruct;
+ g_path.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/alpha_mask3.dpr b/src/corelib/render/software/agg-demos/alpha_mask3.dpr
new file mode 100644
index 00000000..d236ced4
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/alpha_mask3.dpr
@@ -0,0 +1,793 @@
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ alpha_mask3 ;
+
+uses
+ SysUtils ,
+
+ agg_basics ,
+ agg_platform_support ,
+
+ agg_color ,
+ agg_pixfmt ,
+ agg_pixfmt_rgb ,
+ agg_pixfmt_gray ,
+
+ agg_ctrl ,
+ agg_slider_ctrl ,
+ agg_cbox_ctrl ,
+ agg_rbox_ctrl ,
+
+ agg_rendering_buffer ,
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_renderer_primitives ,
+ agg_rasterizer_scanline_aa ,
+ agg_scanline ,
+ agg_scanline_p ,
+ agg_render_scanlines ,
+
+ agg_conv_curve ,
+ agg_conv_stroke ,
+ agg_conv_transform ,
+ agg_gsv_text ,
+ agg_pixfmt_amask_adaptor ,
+ agg_alpha_mask_u8 ,
+ agg_vertex_source ,
+ agg_path_storage ,
+ agg_trans_affine ,
+ agg_math_stroke ,
+
+ make_gb_poly_ ,
+ make_arrows_ ;
+
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+type
+ spiral = object(vertex_source )
+ m_x ,
+ m_y ,
+ m_r1 ,
+ m_r2 ,
+ m_step ,
+
+ m_start_angle ,
+
+ m_angle ,
+ m_curr_r ,
+ m_da ,
+ m_dr : double;
+ m_start : boolean;
+
+ constructor Construct(x ,y ,r1 ,r2 ,step : double; start_angle : double = 0 );
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ end;
+
+ the_application = object(platform_support )
+ m_polygons ,
+ m_operation : rbox_ctrl;
+
+ m_alpha_buf : int8u_ptr;
+ m_alpha_aloc : unsigned;
+ m_alpha_mask_rbuf : rendering_buffer;
+ m_alpha_mask : amask_no_clip_gray8;
+
+ m_ras : rasterizer_scanline_aa;
+ m_sl : scanline_p8;
+
+ m_x ,
+ m_y : double;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure draw_text(x ,y : double; str : char_ptr );
+
+ procedure generate_alpha_mask(vs : vertex_source_ptr );
+ procedure perform_rendering (vs : vertex_source_ptr );
+
+ function render : unsigned;
+
+ procedure on_init; virtual;
+ procedure on_draw; virtual;
+
+ procedure on_mouse_move (x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ CONSTRUCT }
+constructor spiral.Construct;
+begin
+ m_x :=x;
+ m_y :=y;
+ m_r1:=r1;
+ m_r2:=r2;
+
+ m_step :=step;
+ m_start_angle:=start_angle;
+ m_angle :=start_angle;
+
+ m_da:=deg2rad(4.0 );
+ m_dr:=m_step / 90.0;
+
+end;
+
+{ REWIND }
+procedure spiral.rewind;
+begin
+ m_angle :=m_start_angle;
+ m_curr_r:=m_r1;
+ m_start :=true;
+
+end;
+
+{ VERTEX }
+function spiral.vertex;
+begin
+ if m_curr_r > m_r2 then
+ begin
+ result:=path_cmd_stop;
+
+ exit;
+
+ end;
+
+ x^:=m_x + Cos(m_angle ) * m_curr_r;
+ y^:=m_y + Sin(m_angle ) * m_curr_r;
+
+ m_curr_r:=m_curr_r + m_dr;
+ m_angle :=m_angle + m_da;
+
+ if m_start then
+ begin
+ m_start:=false;
+
+ result:=path_cmd_move_to;
+
+ end
+ else
+ result:=path_cmd_line_to;
+
+end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_polygons.Construct (5.0 ,5.0 ,5.0 + 205.0 ,110.0 ,not flip_y_ );
+ m_operation.Construct(555.0 ,5.0 ,555.0 + 80.0 ,55.0 ,not flip_y_ );
+
+ m_alpha_buf :=NIL;
+ m_alpha_aloc:=0;
+
+ m_alpha_mask_rbuf.Construct;
+ m_alpha_mask.Construct(@m_alpha_mask_rbuf );
+
+ m_ras.Construct;
+ m_sl.Construct;
+
+ m_x:=0;
+ m_y:=0;
+
+ m_operation.add_item ('AND' );
+ m_operation.add_item ('SUB' );
+ m_operation.cur_item_(0 );
+
+ add_ctrl(@m_operation );
+
+ m_operation.no_transform;
+
+ m_polygons.add_item ('Two Simple Paths' );
+ m_polygons.add_item ('Closed Stroke' );
+ m_polygons.add_item ('Great Britain and Arrows' );
+ m_polygons.add_item ('Great Britain and Spiral' );
+ m_polygons.add_item ('Spiral and Glyph' );
+ m_polygons.cur_item_(3 );
+
+ add_ctrl(@m_polygons );
+
+ m_polygons.no_transform;
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_polygons.Destruct;
+ m_operation.Destruct;
+
+ m_alpha_mask_rbuf.Destruct;
+
+ m_ras.Destruct;
+ m_sl.Destruct;
+
+ agg_freemem(pointer(m_alpha_buf ) ,m_alpha_aloc );
+
+end;
+
+{ DRAW_TEXT }
+procedure the_application.draw_text;
+var
+ pf : pixel_formats;
+ rb : renderer_base;
+ ren : renderer_scanline_aa_solid;
+ txt : gsv_text;
+
+ txt_stroke : conv_stroke;
+
+ rgba : aggclr;
+
+begin
+ pixfmt_bgr24(pf ,rbuf_window );
+
+ rb.Construct (@pf );
+ ren.Construct(@rb );
+
+ txt.Construct;
+
+ txt_stroke.Construct(@txt );
+ txt_stroke.width_ (1.5 );
+ txt_stroke.line_cap_(round_cap );
+
+ txt.size_ (10.0 );
+ txt.start_point_(x ,y );
+ txt.text_ (PChar(str ) );
+
+ m_ras.add_path (@txt_stroke);
+ rgba.ConstrDbl (0.0 ,0.0 ,0.0 );
+ ren.color_ (@rgba );
+ render_scanlines(@m_ras ,@m_sl ,@ren );
+
+ txt.Destruct;
+ txt_stroke.Destruct;
+
+end;
+
+{ GENERATE_ALPHA_MASK }
+procedure the_application.generate_alpha_mask;
+var
+ cx ,cy : unsigned;
+
+ pixf : pixel_formats;
+ gray : aggclr;
+
+ rb : renderer_base;
+ ren : renderer_scanline_aa_solid;
+
+ t1 : double;
+ buf : array[0..99 ] of char;
+
+begin
+ cx:=trunc(_width );
+ cy:=trunc(_height );
+
+ agg_freemem(pointer(m_alpha_buf ) ,m_alpha_aloc );
+
+ m_alpha_aloc:=cx * cy;
+
+ agg_getmem(pointer(m_alpha_buf ) ,m_alpha_aloc );
+
+ m_alpha_mask_rbuf.attach(m_alpha_buf ,cx ,cy ,cx );
+
+ pixfmt_gray8(pixf ,@m_alpha_mask_rbuf );
+
+ rb.Construct (@pixf );
+ ren.Construct(@rb );
+
+ start_timer;
+
+ if m_operation._cur_item = 0 then
+ begin
+ gray.ConstrInt(0 );
+ rb.clear (@gray );
+
+ gray.ConstrInt(255 );
+ ren.color_ (@gray );
+
+ end
+ else
+ begin
+ gray.ConstrInt(255 );
+ rb.clear (@gray );
+
+ gray.ConstrInt(0 );
+ ren.color_ (@gray );
+
+ end;
+
+ m_ras.add_path (vs );
+ render_scanlines(@m_ras ,@m_sl ,@ren );
+
+ t1:=elapsed_time;
+
+ sprintf (@buf[0 ] ,'Generate AlphaMask: %.3fms' ,t1 );
+ draw_text(250 ,20 ,@buf[0 ] );
+
+end;
+
+{ PERFORM_RENDERING }
+procedure the_application.perform_rendering;
+var
+ pixf : pixel_formats;
+ pixfa : pixfmt_amask_adaptor;
+ rbase : renderer_base;
+
+ ren : renderer_scanline_aa_solid;
+ rgba : aggclr;
+
+ t1 : double;
+ buf : array[0..99 ] of char;
+
+begin
+ pixfmt_bgr24(pixf ,rbuf_window );
+
+ pixfa.Construct(@pixf ,@m_alpha_mask );
+ rbase.Construct(@pixfa );
+ ren.Construct (@rbase );
+
+ rgba.ConstrDbl(0.5 ,0.0 ,0 ,0.5 );
+ ren.color_ (@rgba );
+
+ start_timer;
+ m_ras.reset;
+ m_ras.add_path (vs );
+ render_scanlines(@m_ras ,@m_sl ,@ren );
+
+ t1:=elapsed_time;
+
+ sprintf (@buf[0 ] ,'Render with AlphaMask: %.3fms' ,t1 );
+ draw_text(250 ,5 ,@buf[0 ] );
+
+ pixfa.Destruct;
+
+end;
+
+{ RENDER }
+function the_application.render;
+var
+ pf : pixel_formats;
+ rb : renderer_base;
+
+ ren : renderer_scanline_aa_solid;
+ ps1 ,
+ ps2 ,
+
+ gb_poly ,
+ arrows ,
+ glyph : path_storage;
+
+ rgba : aggclr;
+ x ,y : double;
+
+ mtx1 ,
+ mtx2 ,
+ mtx : trans_affine;
+ tat : trans_affine_translation;
+ tas : trans_affine_scaling;
+
+ stroke ,
+ stroke_gb_poly : conv_stroke;
+
+ trans ,
+ trans_gb_poly ,
+ trans_arrows : conv_transform;
+
+ curve : conv_curve;
+
+ sp : spiral;
+
+begin
+ pixfmt_bgr24(pf ,rbuf_window );
+
+ rb.Construct (@pf );
+ ren.Construct(@rb );
+
+ case m_polygons._cur_item of
+ 0 : // Two simple paths
+ begin
+ ps1.Construct;
+ ps2.Construct;
+
+ x:=m_x - _initial_width / 2 + 100;
+ y:=m_y - _initial_height / 2 + 100;
+
+ ps1.move_to(x + 140 ,y + 145 );
+ ps1.line_to(x + 225 ,y + 44 );
+ ps1.line_to(x + 296 ,y + 219 );
+ ps1.close_polygon;
+
+ ps1.line_to(x + 226 ,y + 289 );
+ ps1.line_to(x + 82 ,y + 292 );
+
+ ps1.move_to(x + 220 ,y + 222 );
+ ps1.line_to(x + 363 ,y + 249 );
+ ps1.line_to(x + 265 ,y + 331 );
+
+ ps1.move_to(x + 242 ,y + 243 );
+ ps1.line_to(x + 268 ,y + 309 );
+ ps1.line_to(x + 325 ,y + 261 );
+
+ ps1.move_to(x + 259 ,y + 259 );
+ ps1.line_to(x + 273 ,y + 288 );
+ ps1.line_to(x + 298 ,y + 266 );
+
+ ps2.move_to(100 + 32 ,100 + 77 );
+ ps2.line_to(100 + 473 ,100 + 263 );
+ ps2.line_to(100 + 351 ,100 + 290 );
+ ps2.line_to(100 + 354 ,100 + 374 );
+
+ m_ras.reset;
+ m_ras.add_path (@ps1 );
+ rgba.ConstrDbl (0 ,0 ,0 ,0.1 );
+ ren.color_ (@rgba );
+ render_scanlines(@m_ras ,@m_sl ,@ren );
+
+ m_ras.reset;
+ m_ras.add_path (@ps2 );
+ rgba.ConstrDbl (0 ,0.6 ,0 ,0.1 );
+ ren.color_ (@rgba );
+ render_scanlines(@m_ras ,@m_sl ,@ren );
+
+ generate_alpha_mask(@ps1 );
+ perform_rendering (@ps2 );
+
+ ps1.Destruct;
+ ps2.Destruct;
+
+ end;
+
+ 1 : // Closed stroke
+ begin
+ ps1.Construct;
+ ps2.Construct;
+ stroke.Construct(@ps2 );
+ stroke.width_ (10.0 );
+
+ x:=m_x - _initial_width / 2 + 100;
+ y:=m_y - _initial_height / 2 + 100;
+
+ ps1.move_to(x + 140 ,y + 145 );
+ ps1.line_to(x + 225 ,y + 44 );
+ ps1.line_to(x + 296 ,y + 219 );
+ ps1.close_polygon;
+
+ ps1.line_to(x + 226 ,y + 289 );
+ ps1.line_to(x + 82 ,y + 292 );
+
+ ps1.move_to(x + 220 - 50 ,y + 222 );
+ ps1.line_to(x + 265 - 50 ,y + 331 );
+ ps1.line_to(x + 363 - 50 ,y + 249 );
+ ps1.close_polygon(path_flags_ccw );
+
+ ps2.move_to(100 + 32 ,100 + 77 );
+ ps2.line_to(100 + 473 ,100 + 263 );
+ ps2.line_to(100 + 351 ,100 + 290 );
+ ps2.line_to(100 + 354 ,100 + 374 );
+ ps2.close_polygon;
+
+ m_ras.reset;
+ m_ras.add_path (@ps1 );
+ rgba.ConstrDbl (0 ,0 ,0 ,0.1 );
+ ren.color_ (@rgba );
+ render_scanlines(@m_ras ,@m_sl ,@ren );
+
+ m_ras.reset;
+ m_ras.add_path (@stroke );
+ rgba.ConstrDbl (0 ,0.6 ,0 ,0.1 );
+ ren.color_ (@rgba );
+ render_scanlines(@m_ras ,@m_sl ,@ren );
+
+ generate_alpha_mask(@ps1 );
+ perform_rendering (@stroke );
+
+ ps1.Destruct;
+ ps2.Destruct;
+ stroke.Destruct;
+
+ end;
+
+ 2 : // Great Britain and Arrows
+ begin
+ gb_poly.Construct;
+ arrows.Construct;
+
+ make_gb_poly(@gb_poly );
+ make_arrows (@arrows );
+
+ mtx1.Construct;
+ mtx2.Construct;
+ tat.Construct(-1150 ,-1150 );
+ tas.Construct(2.0 );
+ mtx1.multiply(@tat );
+ mtx1.multiply(@tas );
+
+ mtx2:=mtx1;
+
+ tat.Construct(m_x - _initial_width / 2 ,m_y - _initial_height / 2 );
+
+ mtx2.multiply(@tat );
+
+ trans_gb_poly.Construct(@gb_poly ,@mtx1 );
+ trans_arrows.Construct (@arrows ,@mtx2 );
+
+ m_ras.add_path (@trans_gb_poly );
+ rgba.ConstrDbl (0.5 ,0.5 ,0 ,0.1 );
+ ren.color_ (@rgba );
+ render_scanlines(@m_ras ,@m_sl ,@ren );
+
+ stroke_gb_poly.Construct(@trans_gb_poly );
+ stroke_gb_poly.width_ (0.1);
+ m_ras.add_path (@stroke_gb_poly );
+ rgba.ConstrDbl (0 ,0 ,0 );
+ ren.color_ (@rgba );
+ render_scanlines (@m_ras ,@m_sl ,@ren );
+
+ m_ras.add_path (@trans_arrows );
+ rgba.ConstrDbl (0.0 ,0.5 ,0.5 ,0.1 );
+ ren.color_ (@rgba );
+ render_scanlines(@m_ras ,@m_sl ,@ren );
+
+ generate_alpha_mask(@trans_gb_poly );
+ perform_rendering (@trans_arrows );
+
+ gb_poly.Destruct;
+ arrows.Destruct;
+ stroke_gb_poly.Destruct;
+
+ end;
+
+ 3 : // Great Britain and a Spiral
+ begin
+ sp.Construct (m_x ,m_y ,10 ,150 ,30 ,0.0 );
+ stroke.Construct(@sp );
+ stroke.width_ (15.0 );
+
+ gb_poly.Construct;
+ make_gb_poly(@gb_poly );
+
+ mtx.Construct;
+ tat.Construct(-1150 ,-1150 );
+ tas.Construct(2.0 );
+ mtx.multiply(@tat );
+ mtx.multiply(@tas );
+
+ trans_gb_poly.Construct(@gb_poly ,@mtx );
+
+ m_ras.add_path (@trans_gb_poly );
+ rgba.ConstrDbl (0.5 ,0.5 ,0 ,0.1 );
+ ren.color_ (@rgba );
+ render_scanlines(@m_ras ,@m_sl ,@ren );
+
+ stroke_gb_poly.Construct(@trans_gb_poly );
+ stroke_gb_poly.width_ (0.1 );
+ m_ras.add_path (@stroke_gb_poly );
+ rgba.ConstrDbl (0 ,0 ,0 );
+ ren.color_ (@rgba );
+ render_scanlines (@m_ras ,@m_sl ,@ren );
+
+ m_ras.add_path (@stroke );
+ rgba.ConstrDbl (0.0 ,0.5 ,0.5 ,0.1 );
+ ren.color_ (@rgba );
+ render_scanlines(@m_ras ,@m_sl ,@ren );
+
+ generate_alpha_mask(@trans_gb_poly );
+ perform_rendering (@stroke );
+
+ stroke.Destruct;
+ gb_poly.Destruct;
+ stroke_gb_poly.Destruct;
+
+ end;
+
+ 4 : // Spiral and glyph
+ begin
+ sp.Construct (m_x ,m_y ,10 ,150 ,30 ,0.0 );
+ stroke.Construct(@sp );
+ stroke.width_ (15.0 );
+
+ glyph.Construct;
+ glyph.move_to(28.47 ,6.45 );
+ glyph.curve3 (21.58 ,1.12 ,19.82 ,0.29 );
+ glyph.curve3 (17.19 ,-0.93 ,14.21 ,-0.93 );
+ glyph.curve3 (9.57 ,-0.93 ,6.57 ,2.25 );
+ glyph.curve3 (3.56 ,5.42 ,3.56 ,10.60 );
+ glyph.curve3 (3.56 ,13.87 ,5.03 ,16.26 );
+ glyph.curve3 (7.03 ,19.58 ,11.99 ,22.51 );
+ glyph.curve3 (16.94 ,25.44 ,28.47 ,29.64 );
+ glyph.line_to(28.47 ,31.40 );
+ glyph.curve3 (28.47 ,38.09 ,26.34 ,40.58 );
+ glyph.curve3 (24.22 ,43.07 ,20.17 ,43.07 );
+ glyph.curve3 (17.09 ,43.07 ,15.28 ,41.41 );
+ glyph.curve3 (13.43 ,39.75 ,13.43 ,37.60 );
+ glyph.line_to(13.53 ,34.77 );
+ glyph.curve3 (13.53 ,32.52 ,12.38 ,31.30 );
+ glyph.curve3 (11.23 ,30.08 ,9.38 ,30.08 );
+ glyph.curve3 (7.57 ,30.08 ,6.42 ,31.35 );
+ glyph.curve3 (5.27 ,32.62 ,5.27 ,34.81 );
+ glyph.curve3 (5.27 ,39.01 ,9.57 ,42.53 );
+ glyph.curve3 (13.87 ,46.04 ,21.63 ,46.04 );
+ glyph.curve3 (27.59 ,46.04 ,31.40 ,44.04 );
+ glyph.curve3 (34.28 ,42.53 ,35.64 ,39.31 );
+ glyph.curve3 (36.52 ,37.21 ,36.52 ,30.71 );
+ glyph.line_to(36.52 ,15.53 );
+ glyph.curve3 (36.52 ,9.13 ,36.77 ,7.69 );
+ glyph.curve3 (37.01 ,6.25 ,37.57 ,5.76 );
+ glyph.curve3 (38.13 ,5.27 ,38.87 ,5.27 );
+ glyph.curve3 (39.65 ,5.27 ,40.23 ,5.62 );
+ glyph.curve3 (41.26 ,6.25 ,44.19 ,9.18 );
+ glyph.line_to(44.19 ,6.45 );
+ glyph.curve3 (38.72 ,-0.88 ,33.74 ,-0.88 );
+ glyph.curve3 (31.35 ,-0.88 ,29.93 ,0.78 );
+ glyph.curve3 (28.52 ,2.44 ,28.47 ,6.45 );
+ glyph.close_polygon;
+
+ glyph.move_to(28.47 ,9.62 );
+ glyph.line_to(28.47 ,26.66 );
+ glyph.curve3 (21.09 ,23.73 ,18.95 ,22.51 );
+ glyph.curve3 (15.09 ,20.36 ,13.43 ,18.02 );
+ glyph.curve3 (11.77 ,15.67 ,11.77 ,12.89 );
+ glyph.curve3 (11.77 ,9.38 ,13.87 ,7.06 );
+ glyph.curve3 (15.97 ,4.74 ,18.70 ,4.74 );
+ glyph.curve3 (22.41 ,4.74 ,28.47 ,9.62 );
+ glyph.close_polygon;
+
+ mtx.Construct;
+ tas.Construct(4.0 );
+ tat.Construct(220 ,200 );
+ mtx.multiply(@tas );
+ mtx.multiply(@tat );
+
+ trans.Construct(@glyph ,@mtx );
+ curve.Construct(@trans );
+
+ m_ras.reset;
+ m_ras.add_path (@stroke );
+ rgba.ConstrDbl (0 ,0 ,0 ,0.1 );
+ ren.color_ (@rgba );
+ render_scanlines(@m_ras ,@m_sl ,@ren );
+
+ m_ras.reset;
+ m_ras.add_path (@curve );
+ rgba.ConstrDbl (0 ,0.6 ,0 ,0.1 );
+ ren.color_ (@rgba );
+ render_scanlines(@m_ras ,@m_sl ,@ren );
+
+ generate_alpha_mask(@stroke );
+ perform_rendering (@curve );
+
+ stroke.Destruct;
+ glyph.Destruct;
+ curve.Destruct;
+
+ end;
+
+ end;
+
+end;
+
+{ ON_INIT }
+procedure the_application.on_init;
+begin
+ m_x:=_width / 2.0;
+ m_y:=_height / 2.0;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ pf : pixel_formats;
+
+ rgba : aggclr;
+
+ ren_base : renderer_base;
+ ren_solid : renderer_scanline_aa_solid;
+
+begin
+// Initialize structures
+ pixfmt_bgr24(pf ,rbuf_window );
+
+ ren_base.Construct (@pf );
+ ren_solid.Construct(@ren_base );
+
+ rgba.ConstrDbl(1 ,1 ,1 );
+ ren_base.clear(@rgba );
+
+// Render
+ render;
+
+// Render the controls
+ render_ctrl(@m_ras ,@m_sl ,@ren_solid ,@m_polygons );
+ render_ctrl(@m_ras ,@m_sl ,@ren_solid ,@m_operation );
+
+end;
+
+{ ON_MOUSE_MOVE }
+procedure the_application.on_mouse_move;
+begin
+ if flags and mouse_left <> 0 then
+ begin
+ m_x:=x;
+ m_y:=y;
+
+ force_redraw;
+
+ end;
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure the_application.on_mouse_button_down;
+var
+ buf : array[0..99 ] of char;
+
+begin
+ if flags and mouse_left <> 0 then
+ begin
+ m_x:=x;
+ m_y:=y;
+
+ force_redraw;
+
+ end;
+
+ if flags and mouse_right <> 0 then
+ begin
+ sprintf (@buf[0 ] ,'%d ' ,x );
+ sprintf (@buf[StrLen(@buf ) ] ,'%d' ,y );
+ message_(@buf[0 ] );
+
+ end;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ 'Yet another example of alpha-masking. It simulates arbitrary polygon clipping '#13 +
+ 'similar to "gpc_test". Alpha-Masking allows you to perform only the Intersection '#13 +
+ '(AND) and Difference (SUB) operations, but works much faster that conv_gpc. '#13 +
+ 'Actually, there''re different complexities and different dependencies. '#13 +
+ 'The performance of conv_gpc depends on the number of vertices, while'#13 +
+ 'Alpha-Masking depends on the area of the rendered polygons. Still, with typical '#13 +
+ 'screen resolutions, Alpha-Masking works much faster than General Polygon Clipper. '#13 +
+ 'Compare the timings between "alpha_mask3" and "gpc_test"".'#13#13 +
+ 'How to play with:'#13#13 +
+ 'Use the left mouse button to move the upper shape around.'#13 +
+ 'Use the right mouse button to display a message with current coordinates.' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+VAR
+ app : the_application;
+
+BEGIN
+ app.Construct(pix_format_bgr24 ,flip_y );
+ app.caption_ ('AGG Example. Alpha-Mask as a Polygon Clipper (F1-Help)' );
+
+ if app.init(640 ,520 ,window_resize ) then
+ app.run;
+
+ app.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/arial.ttf b/src/corelib/render/software/agg-demos/arial.ttf
new file mode 100644
index 00000000..ff0815cd
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/arial.ttf
Binary files differ
diff --git a/src/corelib/render/software/agg-demos/bezier_div.dpr b/src/corelib/render/software/agg-demos/bezier_div.dpr
new file mode 100644
index 00000000..115ae034
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/bezier_div.dpr
@@ -0,0 +1,885 @@
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ bezier_div ;
+
+uses
+ Math ,SysUtils ,
+
+ agg_basics ,
+ agg_platform_support ,
+
+ agg_color ,
+ agg_pixfmt ,
+ agg_pixfmt_rgb ,
+
+ agg_ctrl ,
+ agg_slider_ctrl ,
+ agg_rbox_ctrl ,
+ agg_cbox_ctrl ,
+ agg_bezier_ctrl ,
+
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_rasterizer_scanline_aa ,
+ agg_scanline ,
+ agg_scanline_u ,
+ agg_render_scanlines ,
+ agg_renderer_outline_aa ,
+ agg_renderer_outline_image ,
+
+ agg_conv_transform ,
+ agg_conv_stroke ,
+ agg_conv_dash ,
+ agg_pattern_filters_rgba ,
+ agg_arc ,
+ agg_array ,
+ agg_curves ,
+ agg_bezier_arc ,
+ agg_vertex_sequence ,
+ agg_math ,
+ agg_math_stroke ,
+ agg_path_storage ,
+ agg_gsv_text ,
+ agg_ellipse ;
+
+{$I agg_mode.inc }
+{$I- }
+const
+ flip_y = true;
+
+type
+ curve_point_ptr = ^curve_point;
+ curve_point = object
+ x ,y ,dist ,mu : double;
+
+ constructor Construct; overload;
+ constructor Construct(x1 ,y1 ,mu1 : double ); overload;
+
+ end;
+
+ the_application = object(platform_support )
+ m_ctrl_color : aggclr;
+
+ m_curve1 : bezier_ctrl;
+
+ m_angle_tolerance ,
+ m_approximation_scale ,
+ m_cusp_limit ,
+ m_width : slider_ctrl;
+
+ m_show_points ,
+ m_show_outline : cbox_ctrl;
+ m_curve_type ,
+ m_case_type ,
+ m_inner_join ,
+ m_line_join ,
+ m_line_cap : rbox_ctrl;
+
+ m_cur_case_type : int;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ function measure_time(curve : curve_ptr ) : double;
+ function find_point (path : pod_deque_ptr; dist : double; i ,j : unsigned_ptr ) : boolean;
+
+ function calc_max_error(curve : curve_ptr; scale : double; max_angle_error : double_ptr ) : double;
+
+ procedure on_draw; virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+ procedure on_ctrl_change; virtual;
+
+ end;
+
+{ BEZIER4_POINT }
+procedure bezier4_point(
+ x1 ,y1 ,x2 ,y2 ,x3 ,y3 ,x4 ,y4 ,mu : double;
+ x ,y : double_ptr );
+var
+ mum1 ,mum13 ,mu3 : double;
+
+begin
+ mum1 :=1 - mu;
+ mum13:=mum1 * mum1 * mum1;
+ mu3 :=mu * mu * mu;
+
+ x^:=mum13 * x1 + 3 * mu * mum1 * mum1 * x2 + 3 * mu * mu * mum1 * x3 + mu3 * x4;
+ y^:=mum13 * y1 + 3 * mu * mum1 * mum1 * y2 + 3 * mu * mu * mum1 * y3 + mu3 * y4;
+
+end;
+
+{ CONSTRUCT }
+constructor curve_point.Construct;
+begin
+ x :=0;
+ y :=0;
+ dist:=0;
+ mu :=0;
+
+end;
+
+{ CONSTRUCT }
+constructor curve_point.Construct(x1 ,y1 ,mu1 : double );
+begin
+ x :=x1;
+ y :=y1;
+ dist:=0;
+ mu :=mu1;
+
+end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_ctrl_color.ConstrDbl(0 ,0.3 ,0.5 ,0.8 );
+
+ m_angle_tolerance.Construct (5.0 ,5.0 ,240.0 ,12.0 ,not flip_y_ );
+ m_approximation_scale.Construct(5.0 ,17 + 5.0 , 240.0 ,17 + 12.0 ,not flip_y_ );
+ m_cusp_limit.Construct (5.0 ,17 + 17 + 5.0 ,240.0 ,17 + 17 + 12.0 ,not flip_y_ );
+ m_width.Construct (245.0 ,5.0 ,495.0 ,12.0 ,not flip_y_ );
+ m_show_points.Construct (250.0 ,15 + 5 ,'Show Points' ,not flip_y_ );
+ m_show_outline.Construct (250.0 ,30 + 5 ,'Show Stroke Outline' ,not flip_y_ );
+ m_curve_type.Construct (535.0 ,5.0 ,535.0 + 115.0 ,55.0 ,not flip_y_ );
+ m_case_type.Construct (535.0 ,60.0 ,535.0 + 115.0 ,195.0 ,not flip_y_ );
+ m_inner_join.Construct (535.0 ,200.0 ,535.0 + 115.0 ,290.0 ,not flip_y_ );
+ m_line_join.Construct (535.0 ,295.0 ,535.0 + 115.0 ,385.0 ,not flip_y_ );
+ m_line_cap.Construct (535.0 ,395.0 ,535.0 + 115.0 ,455.0 ,not flip_y_ );
+
+ m_cur_case_type:=-1;
+
+ m_curve1.Construct;
+ m_curve1.line_color_(@m_ctrl_color );
+
+ m_curve1.curve_(170 ,424 ,13 ,87 ,488 ,423 ,26 ,333 );
+ //m_curve1.curve_(26.000 ,333.000 ,276.000 ,126.000 ,402.000 ,479.000 ,26.000 ,333.000 ); // Loop with p1==p4
+ //m_curve1.curve_(378.000 ,439.000 ,378.000 ,497.000 ,487.000 ,432.000 ,14.000 ,338.000 ); // Narrow loop
+ //m_curve1.curve_(288.000 ,283.000 ,232.000 ,89.000 ,66.000 ,197.000 ,456.000 ,241.000 ); // Loop
+ //m_curve1.curve_(519.000 ,142.000 ,97.000 ,147.000 ,69.000 ,147.000 ,30.000 ,144.000 ); // Almost straight
+ //m_curve1.curve_(100 ,100 ,200 ,100 ,100 ,200 ,200 ,200 ); // A "Z" case
+ //m_curve1.curve_(150 ,150 ,350 ,150 ,150 ,150 ,350 ,150 ); // Degenerate
+ //m_curve1.curve_(409 ,330 ,300 ,200 ,200 ,200 ,401 ,263 ); // Strange cusp
+ //m_curve1.curve_(129 ,233 ,172 ,320 ,414 ,253 ,344 ,236 ); // Curve cap
+ //m_curve1.curve_(100 ,100 ,100 ,200 ,100 ,100 ,110 ,100 ); // A "boot"
+ //m_curve1.curve_(225 ,150 ,60 ,150 ,460 ,150 ,295 ,150 ); // 2----1----4----3
+ //m_curve1.curve_(162.2 ,248.801 ,162.2 ,248.801 ,266 ,284 ,394 ,335 ); // Coinciding 1-2
+ //m_curve1.curve_(162.200 ,248.801 ,162.200 ,248.801 ,257.000 ,301.000 ,394.000 ,335.000 ); // Coinciding 1-2
+ //m_curve1.curve_(394.000 ,335.000 ,257.000 ,301.000 ,162.200 ,248.801 ,162.200 ,248.801 ); // Coinciding 3-4
+ //m_curve1.curve_(84.200000 ,302.80100 ,84.200000 ,302.80100 ,79.000000 ,292.40100 ,97.001000 ,304.40100 ); // From tiger.svg
+ //m_curve1.curve_(97.001000 ,304.40100 ,79.000000 ,292.40100 ,84.200000 ,302.80100 ,84.200000 ,302.80100 ); // From tiger.svg opposite dir
+ //m_curve1.curve_(475 ,157 ,200 ,100 ,453 ,100 ,222 ,157 ); // Cusp, failure for Adobe SVG
+
+ add_ctrl(@m_curve1 );
+
+ m_curve1.no_transform;
+
+ m_angle_tolerance.label_('Angle Tolerance=%.0f deg' );
+ m_angle_tolerance.range_(0 ,90 );
+ m_angle_tolerance.value_(15 );
+
+ add_ctrl(@m_angle_tolerance );
+
+ m_angle_tolerance.no_transform;
+
+ m_approximation_scale.label_('Approximation Scale=%.3f' );
+ m_approximation_scale.range_(0.1 ,5 );
+ m_approximation_scale.value_(1.0 );
+
+ add_ctrl(@m_approximation_scale );
+
+ m_approximation_scale.no_transform;
+
+ m_cusp_limit.label_('Cusp Limit=%.0f deg' );
+ m_cusp_limit.range_(0 ,90);
+ m_cusp_limit.value_(0 );
+
+ add_ctrl(@m_cusp_limit );
+
+ m_cusp_limit.no_transform;
+
+ m_width.label_('Width=%.2f' );
+ m_width.range_(0.0 ,100 );
+ m_width.value_(50.0 );
+
+ add_ctrl(@m_width );
+
+ m_width.no_transform;
+
+ add_ctrl(@m_show_points );
+
+ m_show_points.no_transform;
+ m_show_points.status_(true );
+
+ add_ctrl(@m_show_outline );
+
+ m_show_outline.no_transform;
+ m_show_outline.status_(true );
+
+ m_curve_type.add_item ('Incremental' );
+ m_curve_type.add_item ('Subdiv' );
+ m_curve_type.cur_item_(1 );
+
+ add_ctrl(@m_curve_type );
+
+ m_curve_type.no_transform;
+
+ m_case_type.text_size_ (7 );
+ m_case_type.text_thickness_(1.0 );
+
+ m_case_type.add_item('Random' );
+ m_case_type.add_item('13---24' );
+ m_case_type.add_item('Smooth Cusp 1' );
+ m_case_type.add_item('Smooth Cusp 2' );
+ m_case_type.add_item('Real Cusp 1' );
+ m_case_type.add_item('Real Cusp 2' );
+ m_case_type.add_item('Fancy Stroke' );
+ m_case_type.add_item('Jaw' );
+ m_case_type.add_item('Ugly Jaw' );
+
+ add_ctrl(@m_case_type );
+
+ m_case_type.no_transform;
+
+ m_inner_join.text_size_(8 );
+
+ m_inner_join.add_item ('Inner Bevel' );
+ m_inner_join.add_item ('Inner Miter' );
+ m_inner_join.add_item ('Inner Jag' );
+ m_inner_join.add_item ('Inner Round' );
+ m_inner_join.cur_item_(3 );
+
+ add_ctrl(@m_inner_join );
+
+ m_inner_join.no_transform;
+
+ m_line_join.text_size_(8 );
+
+ m_line_join.add_item ('Miter Join' );
+ m_line_join.add_item ('Miter Revert' );
+ m_line_join.add_item ('Miter Round' );
+ m_line_join.add_item ('Round Join' );
+ m_line_join.add_item ('Bevel Join' );
+ m_line_join.cur_item_(1 );
+
+ add_ctrl(@m_line_join );
+
+ m_line_join.no_transform;
+
+ m_line_cap.text_size_(8 );
+
+ m_line_cap.add_item ('Butt Cap' );
+ m_line_cap.add_item ('Square Cap' );
+ m_line_cap.add_item ('Round Cap' );
+ m_line_cap.cur_item_(0 );
+
+ add_ctrl(@m_line_cap );
+
+ m_line_cap.no_transform;
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_angle_tolerance.Destruct;
+ m_approximation_scale.Destruct;
+ m_cusp_limit.Destruct;
+ m_width.Destruct;
+ m_show_points.Destruct;
+ m_show_outline.Destruct;
+ m_curve_type.Destruct;
+ m_case_type.Destruct;
+ m_inner_join.Destruct;
+ m_line_join.Destruct;
+ m_line_cap.Destruct;
+ m_curve1.Destruct;
+
+end;
+
+{ MEASURE_TIME }
+function the_application.measure_time;
+var
+ i : int;
+
+ x ,y : double;
+
+begin
+ start_timer;
+
+ for i:=0 to 99 do
+ begin
+ curve.init4(
+ m_curve1._x1 ,m_curve1._y1 ,
+ m_curve1._x2 ,m_curve1._y2 ,
+ m_curve1._x3 ,m_curve1._y3 ,
+ m_curve1._x4 ,m_curve1._y4 );
+
+ curve.rewind(0 );
+
+ while not is_stop(curve.vertex(@x ,@y ) ) do;
+
+ end;
+
+ result:=elapsed_time * 10;
+
+end;
+
+{ FIND_POINT }
+function the_application.find_point;
+var
+ k : int;
+
+begin
+ j^:=path.size - 1;
+ i^:=0;
+
+ while j^ - i^ > 1 do
+ begin
+ k:=shr_int32(i^ + j^ ,1 );
+
+ if dist < vertex_dist_ptr(path.array_operator(k ) ).dist then
+ j^:=k
+ else
+ i^:=k;
+
+ end;
+
+ result:=true;
+
+end;
+
+{ CALC_MAX_ERROR }
+function the_application.calc_max_error;
+var
+ cmd ,i ,idx1 ,idx2 : unsigned;
+
+ x ,y ,curve_dist ,mu ,reference_dist ,max_error ,err ,aerr ,a1 ,a2 ,da : double;
+
+ curve_points ,reference_points : pod_deque;
+
+ vd : vertex_dist;
+ cp : curve_point;
+
+begin
+ curve_points.Construct (sizeof(vertex_dist ) ,8 );
+ reference_points.Construct(sizeof(curve_point ) ,8 );
+
+ curve.approximation_scale_(m_approximation_scale._value * scale );
+
+ curve.init4(
+ m_curve1._x1 ,m_curve1._y1 ,
+ m_curve1._x2 ,m_curve1._y2 ,
+ m_curve1._x3 ,m_curve1._y3 ,
+ m_curve1._x4 ,m_curve1._y4 );
+
+ curve.rewind(0 );
+
+ vd.dist:=0;
+
+ cmd:=curve.vertex(@x ,@y );
+
+ while not is_stop(cmd ) do
+ begin
+ if is_vertex(cmd ) then
+ begin
+ vd.x:=x;
+ vd.y:=y;
+
+ curve_points.add(@vd );
+
+ end;
+
+ cmd:=curve.vertex(@x ,@y );
+
+ end;
+
+ curve_dist:=0;
+
+ i:=1;
+
+ while i < curve_points.size do
+ begin
+ vertex_dist_ptr(curve_points.array_operator(i - 1 ) ).dist:=curve_dist;
+
+ curve_dist:=
+ curve_dist +
+ calc_distance(
+ vertex_dist_ptr(curve_points.array_operator(i - 1 ) ).x ,
+ vertex_dist_ptr(curve_points.array_operator(i - 1 ) ).y ,
+ vertex_dist_ptr(curve_points.array_operator(i ) ).x ,
+ vertex_dist_ptr(curve_points.array_operator(i ) ).y );
+
+ inc(i );
+
+ end;
+
+ vertex_dist_ptr(curve_points.array_operator(curve_points.size - 1 ) ).dist:=curve_dist;
+
+ for i:=0 to 4095 do
+ begin
+ mu:=i / 4095.0;
+
+ bezier4_point(
+ m_curve1._x1 , m_curve1._y1 ,
+ m_curve1._x2 , m_curve1._y2 ,
+ m_curve1._x3 , m_curve1._y3 ,
+ m_curve1._x4 , m_curve1._y4 ,
+ mu ,@x ,@y );
+
+ cp.Construct(x ,y ,mu );
+
+ reference_points.add(@cp );
+
+ end;
+
+ reference_dist:=0;
+
+ i:=1;
+
+ while i < reference_points.size do
+ begin
+ curve_point_ptr(reference_points.array_operator(i - 1 ) ).dist:=reference_dist;
+
+ reference_dist:=
+ reference_dist +
+ calc_distance(
+ curve_point_ptr(reference_points.array_operator(i - 1 ) ).x ,
+ curve_point_ptr(reference_points.array_operator(i - 1 ) ).y ,
+ curve_point_ptr(reference_points.array_operator(i ) ).x ,
+ curve_point_ptr(reference_points.array_operator(i ) ).y );
+
+ inc(i );
+
+ end;
+
+ curve_point_ptr(reference_points.array_operator(reference_points.size - 1 ) ).dist:=reference_dist;
+
+ idx1:=0;
+ idx2:=1;
+
+ max_error:=0;
+
+ i:=0;
+
+ while i < reference_points.size do
+ begin
+ if find_point(
+ @curve_points ,
+ curve_point_ptr(reference_points.array_operator(i ) ).dist ,
+ @idx1 ,@idx2 ) then
+ begin
+ err:=
+ Abs(
+ calc_line_point_distance(
+ vertex_dist_ptr(curve_points.array_operator(idx1 ) ).x ,
+ vertex_dist_ptr(curve_points.array_operator(idx1 ) ).y ,
+ vertex_dist_ptr(curve_points.array_operator(idx2 ) ).x ,
+ vertex_dist_ptr(curve_points.array_operator(idx2 ) ).y ,
+ curve_point_ptr(reference_points.array_operator(i ) ).x ,
+ curve_point_ptr(reference_points.array_operator(i ) ).y ) );
+
+ if err > max_error then
+ max_error:=err;
+
+ end;
+
+ inc(i );
+
+ end;
+
+ aerr:=0;
+
+ i:=2;
+
+ while i < curve_points.size do
+ begin
+ a1:=
+ ArcTan2(
+ vertex_dist_ptr(curve_points.array_operator(i - 1 ) ).y -
+ vertex_dist_ptr(curve_points.array_operator(i - 2 ) ).y ,
+ vertex_dist_ptr(curve_points.array_operator(i - 1 ) ).x -
+ vertex_dist_ptr(curve_points.array_operator(i - 2 ) ).x );
+
+ a2:=
+ ArcTan2(
+ vertex_dist_ptr(curve_points.array_operator(i ) ).y -
+ vertex_dist_ptr(curve_points.array_operator(i - 1 ) ).y ,
+ vertex_dist_ptr(curve_points.array_operator(i ) ).x -
+ vertex_dist_ptr(curve_points.array_operator(i - 1 ) ).x );
+
+ da:=Abs(a1 - a2 );
+
+ if da >= pi then
+ da:=2 * pi - da;
+
+ if da > aerr then
+ aerr:=da;
+
+ inc(i );
+
+ end;
+
+ max_angle_error^:=aerr * 180.0 / pi;
+
+ result:=max_error * scale;
+
+ curve_points.Destruct;
+ reference_points.Destruct;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ ren_base : renderer_base;
+ rgba : aggclr;
+
+ pf : pixel_formats;
+ ren : renderer_scanline_aa_solid;
+ ras : rasterizer_scanline_aa;
+ sl : scanline_u8;
+
+ path : path_storage;
+ curve : curve4;
+ stroke ,
+ stroke2 : conv_stroke;
+
+ ell : ellipse;
+ buf : array[0..511 ] of char;
+
+ t : gsv_text;
+ pt : conv_stroke;
+
+ cmd ,num_points1 : unsigned;
+
+ x ,y ,curve_time ,
+
+ max_angle_error_01 ,
+ max_angle_error_1 ,
+ max_angle_error1 ,
+ max_angle_error_10 ,
+ max_angle_error_100 ,
+
+ max_error_01 ,
+ max_error_1 ,
+ max_error1 ,
+ max_error_10 ,
+ max_error_100 : double;
+
+ a : ellipse;
+
+begin
+// Initialize structures
+ pixfmt_bgr24(pf ,rbuf_window );
+
+ ren_base.Construct(@pf );
+ rgba.ConstrDbl (1.0 ,1.0 ,0.95 );
+ ren_base.clear (@rgba );
+
+ ren.Construct(@ren_base );
+
+ ras.Construct;
+ sl.Construct;
+
+// Render Curve
+ path.Construct;
+
+ curve_time:=0;
+
+ path.remove_all;
+ curve.Construct;
+
+ curve.approximation_method_(curve_approximation_method_e(m_curve_type._cur_item ) );
+ curve.approximation_scale_ (m_approximation_scale._value );
+
+ curve.angle_tolerance_(deg2rad(m_angle_tolerance._value ) );
+ curve.cusp_limit_ (deg2rad(m_cusp_limit._value ) );
+
+ curve_time:=measure_time(@curve );
+
+ max_angle_error_01 :=0;
+ max_angle_error_1 :=0;
+ max_angle_error1 :=0;
+ max_angle_error_10 :=0;
+ max_angle_error_100:=0;
+ max_error_01 :=0;
+ max_error_1 :=0;
+ max_error1 :=0;
+ max_error_10 :=0;
+ max_error_100 :=0;
+
+ max_error_01 :=calc_max_error(@curve ,0.01 ,@max_angle_error_01 );
+ max_error_1 :=calc_max_error(@curve ,0.1 ,@max_angle_error_1 );
+ max_error1 :=calc_max_error(@curve ,1 ,@max_angle_error1 );
+ max_error_10 :=calc_max_error(@curve ,10 ,@max_angle_error_10 );
+ max_error_100:=calc_max_error(@curve ,100 ,@max_angle_error_100 );
+
+ curve.approximation_scale_(m_approximation_scale._value );
+ curve.angle_tolerance_ (deg2rad(m_angle_tolerance._value ) );
+ curve.cusp_limit_ (deg2rad(m_cusp_limit._value ) );
+
+ curve.init4(
+ m_curve1._x1 ,m_curve1._y1 ,
+ m_curve1._x2 ,m_curve1._y2 ,
+ m_curve1._x3 ,m_curve1._y3 ,
+ m_curve1._x4 ,m_curve1._y4 );
+
+ path.add_path(@curve ,0 ,false );
+
+ stroke.Construct(@path );
+ stroke.width_ (m_width._value );
+
+ stroke.line_join_ (m_line_join._cur_item );
+ stroke.line_cap_ (m_line_cap._cur_item );
+ stroke.inner_join_ (m_inner_join._cur_item );
+ stroke.inner_miter_limit_(1.01 );
+
+ ras.add_path (@stroke );
+ rgba.ConstrDbl (0 ,0.5 ,0 ,0.5 );
+ ren.color_ (@rgba );
+ render_scanlines(@ras ,@sl ,@ren );
+
+// Render internal points
+ num_points1:=0;
+
+ path.rewind(0 );
+
+ cmd:=path.vertex(@x ,@y );
+
+ while not is_stop(cmd ) do
+ begin
+ if m_show_points._status then
+ begin
+ ell.Construct(x ,y ,1.5 ,1.5 ,8 );
+
+ ras.add_path (@ell );
+ rgba.ConstrDbl (0 ,0 ,0 ,0.5 );
+ ren.color_ (@rgba );
+ render_scanlines(@ras ,@sl ,@ren );
+
+ end;
+
+ inc(num_points1 );
+
+ cmd:=path.vertex(@x ,@y );
+
+ end;
+
+// Render outline
+ if m_show_outline._status then
+ begin
+ // Draw a stroke of the stroke to see the internals
+ stroke2.Construct(@stroke );
+ ras.add_path (@stroke2 );
+ rgba.ConstrDbl (0 ,0 ,0 ,0.5 );
+ ren.color_ (@rgba);
+ render_scanlines (@ras ,@sl ,@ren );
+
+ end;
+
+// Check ellipse and arc for the number of points
+ {a.Construct (100 ,100 ,m_width.value ,m_width.value ,0 );
+ ras.add_path (@a );
+ rgba.ConstrDbl (0.5 ,0 ,0 ,0.5 );
+ ren.color (@rgba );
+ render_scanlines(@ras ,@sl ,@ren );
+
+ a.rewind(0 );
+
+ cmd:=a.vertex(@x ,@ y);
+
+ while not is_stop(cmd ) do
+ begin
+ if is_vertex(cmd ) then
+ begin
+ ell.Construct (x ,y ,1.5 ,1.5 ,8 );
+ ras.add_path (@ell );
+ rgba.ConstrDbl (0 ,0 ,0 ,0.5 );
+ ren.color (@rgba );
+ render_scanlines(@ras ,@sl ,@ren );
+
+ end;
+
+ cmd:=a.vertex(@x ,@y );
+
+ end;{}
+
+// Render text
+ t.Construct;
+ t.size_(8.0 );
+
+ pt.Construct (@t );
+ pt.line_cap_ (round_cap );
+ pt.line_join_(round_join );
+ pt.width_ (1.5 );
+
+ sprintf(@buf[0 ] ,'Num Points=%d ' ,num_points1 );
+ sprintf(@buf[StrLen(@buf ) ] ,'Time=%.2fmks'#13#13 ,curve_time );
+ sprintf(@buf[StrLen(@buf ) ] ,' Dist Error: x0.01=%.5f ' ,max_error_01 );
+ sprintf(@buf[StrLen(@buf ) ] ,'x0.1=%.5f ' ,max_error_1 );
+ sprintf(@buf[StrLen(@buf ) ] ,'x1=%.5f ' ,max_error1 );
+ sprintf(@buf[StrLen(@buf ) ] ,'x10=%.5f ' ,max_error_10 );
+ sprintf(@buf[StrLen(@buf ) ] ,'x100=%.5f'#13#13 ,max_error_100 );
+ sprintf(@buf[StrLen(@buf ) ] ,'Angle Error: x0.01=%.1f ' ,max_angle_error_01 );
+ sprintf(@buf[StrLen(@buf ) ] ,'x0.1=%.1f ' ,max_angle_error_1 );
+ sprintf(@buf[StrLen(@buf ) ] ,'x1=%.1f ' ,max_angle_error1 );
+ sprintf(@buf[StrLen(@buf ) ] ,'x10=%.1f ' ,max_angle_error_10 );
+ sprintf(@buf[StrLen(@buf ) ] ,'x100=%.1f' ,max_angle_error_100 );
+
+ t.start_point_(10.0 ,85.0 );
+ t.text_ (@buf[0 ] );
+
+ ras.add_path (@pt );
+ rgba.ConstrDbl (0 ,0 ,0 );
+ ren.color_ (@rgba );
+ render_scanlines(@ras ,@sl ,@ren );
+
+// Render the controls
+ render_ctrl(@ras ,@sl ,@ren ,@m_curve1 );
+ render_ctrl(@ras ,@sl ,@ren ,@m_angle_tolerance );
+ render_ctrl(@ras ,@sl ,@ren ,@m_approximation_scale );
+ render_ctrl(@ras ,@sl ,@ren ,@m_cusp_limit );
+ render_ctrl(@ras ,@sl ,@ren ,@m_width );
+ render_ctrl(@ras ,@sl ,@ren ,@m_show_points );
+ render_ctrl(@ras ,@sl ,@ren ,@m_show_outline );
+ render_ctrl(@ras ,@sl ,@ren ,@m_curve_type );
+ render_ctrl(@ras ,@sl ,@ren ,@m_case_type );
+ render_ctrl(@ras ,@sl ,@ren ,@m_inner_join );
+ render_ctrl(@ras ,@sl ,@ren ,@m_line_join );
+ render_ctrl(@ras ,@sl ,@ren ,@m_line_cap );
+
+// Free AGG resources
+ ras.Destruct;
+ sl.Destruct;
+
+ path.Destruct;
+ curve.Destruct;
+ stroke.Destruct;
+ stroke2.Destruct;
+
+ t.Destruct;
+ pt.Destruct;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+var
+ fd : text;
+ buf : array[0..255 ] of char;
+
+begin
+ if key = byte(' ' ) then
+ begin
+ AssignFile(fd ,'coord' );
+ rewrite (fd );
+
+ sprintf(@buf[0 ] ,'%.3f, ' ,m_curve1._x1 );
+ sprintf(@buf[StrLen(@buf ) ] ,'%.3f, ' ,m_curve1._y1 );
+ sprintf(@buf[StrLen(@buf ) ] ,'%.3f, ' ,m_curve1._x2 );
+ sprintf(@buf[StrLen(@buf ) ] ,'%.3f, ' ,m_curve1._y2 );
+ sprintf(@buf[StrLen(@buf ) ] ,'%.3f, ' ,m_curve1._x3 );
+ sprintf(@buf[StrLen(@buf ) ] ,'%.3f, ' ,m_curve1._y3 );
+ sprintf(@buf[StrLen(@buf ) ] ,'%.3f, ' ,m_curve1._x4 );
+ sprintf(@buf[StrLen(@buf ) ] ,'%.3f' ,m_curve1._y4 );
+
+ write(fd ,PChar(@buf[0 ] ) );
+ close(fd );
+
+ end;
+
+ if key = key_f1 then
+ message_(
+ 'Demonstration of new methods of Bezier curve approximation. You can compare '#13 +
+ 'the old, incremental method with adaptive De Casteljau''s subdivion. The new '#13 +
+ 'method uses two criteria to stop subdivision: estimation of distance and estimation '#13 +
+ 'of angle. It gives us perfectly smooth result even for very sharp turns and loops. '#13#13 +
+ 'How to play with:'#13#13 +
+ 'Use the mouse to change the shape of the curve.'#13 +
+ 'Press the spacebar to dump the curve''s coordinates into the "coord" file.' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+{ ON_CTRL_CHANGE }
+procedure the_application.on_ctrl_change;
+var
+ w ,h : int;
+
+begin
+ if m_case_type._cur_item <> m_cur_case_type then
+ begin
+ case m_case_type._cur_item of
+ 0 : //m_case_type.add_item("Random");
+ begin
+ w:=trunc(_width - 120 );
+ h:=trunc(_height - 80 );
+
+ m_curve1.curve_(
+ Random($7fff ) mod w ,Random($7fff ) mod h + 80 ,
+ Random($7fff ) mod w ,Random($7fff ) mod h + 80 ,
+ Random($7fff ) mod w ,Random($7fff ) mod h + 80 ,
+ Random($7fff ) mod w ,Random($7fff ) mod h + 80 );
+
+ end;
+
+ 1 : //m_case_type.add_item("13---24");
+ m_curve1.curve_(150 ,150 ,350 ,150 ,150 ,150 ,350 ,150 );
+
+ 2 : //m_case_type.add_item("Smooth Cusp 1");
+ m_curve1.curve_(50 ,142 ,483 ,251 ,496 ,62 ,26 ,333 );
+
+ 3 : //m_case_type.add_item("Smooth Cusp 2");
+ m_curve1.curve_(50 ,142 ,484 ,251 ,496 ,62 ,26 ,333 );
+
+ 4 : //m_case_type.add_item("Real Cusp 1");
+ m_curve1.curve_(100 ,100 ,300 ,200 ,200 ,200 ,200 ,100 );
+
+ 5 : //m_case_type.add_item("Real Cusp 2");
+ m_curve1.curve_(475 ,157 ,200 ,100 ,453 ,100 ,222 ,157 );
+
+ 6 : //m_case_type.add_item("Fancy Stroke");
+ begin
+ m_curve1.curve_(129 ,233 ,32 ,283 ,258 ,285 ,159 ,232 );
+ m_width.value_ (100 );
+
+ end;
+
+ 7 : //m_case_type.add_item("Jaw");
+ m_curve1.curve_(100 ,100 ,300 ,200 ,264 ,286 ,264 ,284 );
+
+ 8 : //m_case_type.add_item("Ugly Jaw");
+ m_curve1.curve_(100 ,100 ,413 ,304 ,264 ,286 ,264 ,284 );
+
+ end;
+
+ force_redraw;
+
+ m_cur_case_type:=m_case_type._cur_item;
+
+ end;
+
+end;
+
+VAR
+ app : the_application;
+
+BEGIN
+ app.Construct(pix_format_bgr24 ,flip_y );
+ app.caption_ ('AGG Example (F1-Help)' );
+
+ if app.init(655 ,520 ,window_resize ) then
+ app.run;
+
+ app.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/blend_color.dpr b/src/corelib/render/software/agg-demos/blend_color.dpr
new file mode 100644
index 00000000..48a82aff
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/blend_color.dpr
@@ -0,0 +1,843 @@
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ blend_color ;
+
+{DEFINE AGG_GRAY8 }
+{DEFINE AGG_BGR24 }
+{DEFINE AGG_RGB24 }
+{$DEFINE AGG_BGRA32 }
+{DEFINE AGG_RGBA32 }
+{DEFINE AGG_ARGB32 }
+{DEFINE AGG_ABGR32 }
+{DEFINE AGG_RGB565 }
+{DEFINE AGG_RGB555 }
+
+{$IFDEF AGG_GRAY8 }
+{$DEFINE AGG_PF8 }
+{$ELSE }
+ {$IFDEF AGG_BGR24 }
+ {$DEFINE AGG_PF24 }
+ {$ELSE }
+ {$IFDEF AGG_RGB24 }
+ {$DEFINE AGG_PF24 }
+ {$ELSE }
+ {$IFDEF AGG_BGRA32 }
+ {$DEFINE AGG_PF32 }
+ {$ELSE }
+ {$IFDEF AGG_RGBA32 }
+ {$DEFINE AGG_PF32 }
+ {$ELSE }
+ {$IFDEF AGG_ARGB32 }
+ {$DEFINE AGG_PF32 }
+ {$ELSE }
+ {$IFDEF AGG_ABGR32 }
+ {$DEFINE AGG_PF32 }
+ {$ELSE }
+ {$IFDEF AGG_RGB555 }
+ {$DEFINE AGG_PF16 }
+ {$ELSE }
+ {$IFDEF AGG_RGB565 }
+ {$DEFINE AGG_PF16 }
+ {$ELSE }
+ {$ENDIF }
+ {$ENDIF }
+ {$ENDIF }
+ {$ENDIF }
+ {$ENDIF }
+ {$ENDIF }
+ {$ENDIF }
+ {$ENDIF }
+{$ENDIF }
+
+uses
+ agg_basics ,
+{$IFNDEF AGG_PF8 }
+ agg_pixfmt_gray ,
+{$ENDIF }
+{$IFNDEF AGG_PF32 }
+ agg_pixfmt_rgba ,
+{$ENDIF }
+ agg_array ,
+ agg_platform_support ,
+ agg_ctrl ,
+ agg_slider_ctrl ,
+ agg_rbox_ctrl ,
+ agg_cbox_ctrl ,
+ agg_polygon_ctrl ,
+ agg_renderer_base ,
+ agg_rendering_buffer ,
+ agg_rasterizer_scanline_aa ,
+ agg_conv_curve ,
+ agg_conv_contour ,
+ agg_conv_stroke ,
+ agg_conv_transform ,
+ agg_gsv_text ,
+ agg_scanline_p ,
+ agg_renderer_scanline ,
+ agg_bounding_rect ,
+ agg_trans_perspective ,
+ agg_blur ,
+ agg_path_storage ,
+ agg_trans_affine
+
+{$I pixel_formats.inc }
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+ g_gradient_colors : array[0..1023 ] of int8u = (
+
+ 255, 255, 255, 255,
+ 255, 255, 254, 255,
+ 255, 255, 254, 255,
+ 255, 255, 254, 255,
+ 255, 255, 253, 255,
+ 255, 255, 253, 255,
+ 255, 255, 252, 255,
+ 255, 255, 251, 255,
+ 255, 255, 250, 255,
+ 255, 255, 248, 255,
+ 255, 255, 246, 255,
+ 255, 255, 244, 255,
+ 255, 255, 241, 255,
+ 255, 255, 238, 255,
+ 255, 255, 235, 255,
+ 255, 255, 231, 255,
+ 255, 255, 227, 255,
+ 255, 255, 222, 255,
+ 255, 255, 217, 255,
+ 255, 255, 211, 255,
+ 255, 255, 206, 255,
+ 255, 255, 200, 255,
+ 255, 254, 194, 255,
+ 255, 253, 188, 255,
+ 255, 252, 182, 255,
+ 255, 250, 176, 255,
+ 255, 249, 170, 255,
+ 255, 247, 164, 255,
+ 255, 246, 158, 255,
+ 255, 244, 152, 255,
+ 254, 242, 146, 255,
+ 254, 240, 141, 255,
+ 254, 238, 136, 255,
+ 254, 236, 131, 255,
+ 253, 234, 126, 255,
+ 253, 232, 121, 255,
+ 253, 229, 116, 255,
+ 252, 227, 112, 255,
+ 252, 224, 108, 255,
+ 251, 222, 104, 255,
+ 251, 219, 100, 255,
+ 251, 216, 96, 255,
+ 250, 214, 93, 255,
+ 250, 211, 89, 255,
+ 249, 208, 86, 255,
+ 249, 205, 83, 255,
+ 248, 202, 80, 255,
+ 247, 199, 77, 255,
+ 247, 196, 74, 255,
+ 246, 193, 72, 255,
+ 246, 190, 69, 255,
+ 245, 187, 67, 255,
+ 244, 183, 64, 255,
+ 244, 180, 62, 255,
+ 243, 177, 60, 255,
+ 242, 174, 58, 255,
+ 242, 170, 56, 255,
+ 241, 167, 54, 255,
+ 240, 164, 52, 255,
+ 239, 161, 51, 255,
+ 239, 157, 49, 255,
+ 238, 154, 47, 255,
+ 237, 151, 46, 255,
+ 236, 147, 44, 255,
+ 235, 144, 43, 255,
+ 235, 141, 41, 255,
+ 234, 138, 40, 255,
+ 233, 134, 39, 255,
+ 232, 131, 37, 255,
+ 231, 128, 36, 255,
+ 230, 125, 35, 255,
+ 229, 122, 34, 255,
+ 228, 119, 33, 255,
+ 227, 116, 31, 255,
+ 226, 113, 30, 255,
+ 225, 110, 29, 255,
+ 224, 107, 28, 255,
+ 223, 104, 27, 255,
+ 222, 101, 26, 255,
+ 221, 99, 25, 255,
+ 220, 96, 24, 255,
+ 219, 93, 23, 255,
+ 218, 91, 22, 255,
+ 217, 88, 21, 255,
+ 216, 86, 20, 255,
+ 215, 83, 19, 255,
+ 214, 81, 18, 255,
+ 213, 79, 17, 255,
+ 212, 77, 17, 255,
+ 211, 74, 16, 255,
+ 210, 72, 15, 255,
+ 209, 70, 14, 255,
+ 207, 68, 13, 255,
+ 206, 66, 13, 255,
+ 205, 64, 12, 255,
+ 204, 62, 11, 255,
+ 203, 60, 10, 255,
+ 202, 58, 10, 255,
+ 201, 56, 9, 255,
+ 199, 55, 9, 255,
+ 198, 53, 8, 255,
+ 197, 51, 7, 255,
+ 196, 50, 7, 255,
+ 195, 48, 6, 255,
+ 193, 46, 6, 255,
+ 192, 45, 5, 255,
+ 191, 43, 5, 255,
+ 190, 42, 4, 255,
+ 188, 41, 4, 255,
+ 187, 39, 3, 255,
+ 186, 38, 3, 255,
+ 185, 37, 2, 255,
+ 183, 35, 2, 255,
+ 182, 34, 1, 255,
+ 181, 33, 1, 255,
+ 179, 32, 1, 255,
+ 178, 30, 0, 255,
+ 177, 29, 0, 255,
+ 175, 28, 0, 255,
+ 174, 27, 0, 255,
+ 173, 26, 0, 255,
+ 171, 25, 0, 255,
+ 170, 24, 0, 255,
+ 168, 23, 0, 255,
+ 167, 22, 0, 255,
+ 165, 21, 0, 255,
+ 164, 21, 0, 255,
+ 163, 20, 0, 255,
+ 161, 19, 0, 255,
+ 160, 18, 0, 255,
+ 158, 17, 0, 255,
+ 156, 17, 0, 255,
+ 155, 16, 0, 255,
+ 153, 15, 0, 255,
+ 152, 14, 0, 255,
+ 150, 14, 0, 255,
+ 149, 13, 0, 255,
+ 147, 12, 0, 255,
+ 145, 12, 0, 255,
+ 144, 11, 0, 255,
+ 142, 11, 0, 255,
+ 140, 10, 0, 255,
+ 139, 10, 0, 255,
+ 137, 9, 0, 255,
+ 135, 9, 0, 255,
+ 134, 8, 0, 255,
+ 132, 8, 0, 255,
+ 130, 7, 0, 255,
+ 128, 7, 0, 255,
+ 126, 6, 0, 255,
+ 125, 6, 0, 255,
+ 123, 5, 0, 255,
+ 121, 5, 0, 255,
+ 119, 4, 0, 255,
+ 117, 4, 0, 255,
+ 115, 4, 0, 255,
+ 113, 3, 0, 255,
+ 111, 3, 0, 255,
+ 109, 2, 0, 255,
+ 107, 2, 0, 255,
+ 105, 2, 0, 255,
+ 103, 1, 0, 255,
+ 101, 1, 0, 255,
+ 99, 1, 0, 255,
+ 97, 0, 0, 255,
+ 95, 0, 0, 255,
+ 93, 0, 0, 255,
+ 91, 0, 0, 255,
+ 90, 0, 0, 255,
+ 88, 0, 0, 255,
+ 86, 0, 0, 255,
+ 84, 0, 0, 255,
+ 82, 0, 0, 255,
+ 80, 0, 0, 255,
+ 78, 0, 0, 255,
+ 77, 0, 0, 255,
+ 75, 0, 0, 255,
+ 73, 0, 0, 255,
+ 72, 0, 0, 255,
+ 70, 0, 0, 255,
+ 68, 0, 0, 255,
+ 67, 0, 0, 255,
+ 65, 0, 0, 255,
+ 64, 0, 0, 255,
+ 63, 0, 0, 255,
+ 61, 0, 0, 255,
+ 60, 0, 0, 255,
+ 59, 0, 0, 255,
+ 58, 0, 0, 255,
+ 57, 0, 0, 255,
+ 56, 0, 0, 255,
+ 55, 0, 0, 255,
+ 54, 0, 0, 255,
+ 53, 0, 0, 255,
+ 53, 0, 0, 255,
+ 52, 0, 0, 255,
+ 52, 0, 0, 255,
+ 51, 0, 0, 255,
+ 51, 0, 0, 255,
+ 51, 0, 0, 255,
+ 50, 0, 0, 255,
+ 50, 0, 0, 255,
+ 51, 0, 0, 255,
+ 51, 0, 0, 255,
+ 51, 0, 0, 255,
+ 51, 0, 0, 255,
+ 52, 0, 0, 255,
+ 52, 0, 0, 255,
+ 53, 0, 0, 255,
+ 54, 1, 0, 255,
+ 55, 2, 0, 255,
+ 56, 3, 0, 255,
+ 57, 4, 0, 255,
+ 58, 5, 0, 255,
+ 59, 6, 0, 255,
+ 60, 7, 0, 255,
+ 62, 8, 0, 255,
+ 63, 9, 0, 255,
+ 64, 11, 0, 255,
+ 66, 12, 0, 255,
+ 68, 13, 0, 255,
+ 69, 14, 0, 255,
+ 71, 16, 0, 255,
+ 73, 17, 0, 255,
+ 75, 18, 0, 255,
+ 77, 20, 0, 255,
+ 79, 21, 0, 255,
+ 81, 23, 0, 255,
+ 83, 24, 0, 255,
+ 85, 26, 0, 255,
+ 87, 28, 0, 255,
+ 90, 29, 0, 255,
+ 92, 31, 0, 255,
+ 94, 33, 0, 255,
+ 97, 34, 0, 255,
+ 99, 36, 0, 255,
+ 102, 38, 0, 255,
+ 104, 40, 0, 255,
+ 107, 41, 0, 255,
+ 109, 43, 0, 255,
+ 112, 45, 0, 255,
+ 115, 47, 0, 255,
+ 117, 49, 0, 255,
+ 120, 51, 0, 255,
+ 123, 52, 0, 255,
+ 126, 54, 0, 255,
+ 128, 56, 0, 255,
+ 131, 58, 0, 255,
+ 134, 60, 0, 255,
+ 137, 62, 0, 255,
+ 140, 64, 0, 255,
+ 143, 66, 0, 255,
+ 145, 68, 0, 255,
+ 148, 70, 0, 255,
+ 151, 72, 0, 255,
+ 154, 74, 0, 255 );
+
+type
+ the_application = object(platform_support )
+ private
+ m_method ,
+ m_comp_op : rbox_ctrl;
+ m_radius : slider_ctrl;
+
+ m_r ,
+ m_g ,
+ m_b : cbox_ctrl;
+
+ m_shadow_ctrl : polygon_ctrl;
+
+ m_path : path_storage;
+ m_shape : conv_curve;
+
+ m_ras : rasterizer_scanline_aa;
+ m_sl : scanline_p8;
+
+ m_shape_bounds : rect_d;
+
+ m_gray8_buf : pod_array;
+ m_gray8_rbuf ,
+ m_gray8_rbuf2 : rendering_buffer;
+
+ m_color_lut : pod_array;
+
+ public
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure on_resize(sx ,sy : int ); virtual;
+ procedure on_draw; virtual;
+
+ procedure on_mouse_move (x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_up (x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+var
+ shape_mtx : trans_affine;
+
+ tas : trans_affine_scaling;
+ tat : trans_affine_translation;
+
+ i : unsigned;
+ p : int8u_ptr;
+
+ rgba : aggclr;
+
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_method.Construct (10.0 ,10.0 ,130.0 ,55.0 ,not flip_y_ );
+ m_comp_op.Construct(420 + 20.0 ,5.0 ,420 + 140.0 ,395.0 ,not flip_y_ );
+ m_radius.Construct (130 + 10.0 ,10.0 + 4.0 ,130 + 300.0 ,10.0 + 8.0 + 4.0 ,not flip_y_ );
+
+ m_r.Construct(10.0 ,95.0 - 30 ,'Red' ,not flip_y_ );
+ m_g.Construct(10.0 ,110.0 - 30 ,'Green' ,not flip_y_ );
+ m_b.Construct(10.0 ,125.0 - 30 ,'Blue' ,not flip_y_ );
+
+ m_shadow_ctrl.Construct(4 );
+
+ m_path.Construct;
+ m_shape.Construct(@m_path );
+
+ m_ras.Construct;
+ m_sl.Construct;
+
+ m_shape_bounds.Construct;
+
+ m_gray8_buf.Construct(sizeof(int8u ) );
+ m_gray8_rbuf.Construct;
+ m_gray8_rbuf2.Construct;
+
+ m_color_lut.Construct(sizeof(aggclr ) );
+
+ add_ctrl(@m_method );
+
+ m_method.text_size_(8 );
+ m_method.add_item ('Single Color' );
+ m_method.add_item ('Color LUT' );
+ m_method.cur_item_ (1 );
+
+ add_ctrl(@m_radius );
+
+ m_radius.range_(0.0 ,40.0 );
+ m_radius.value_(15.0 );
+ m_radius.label_('Blur Radius=%1.2f' );
+
+ add_ctrl(@m_r );
+ add_ctrl(@m_g );
+ add_ctrl(@m_b );
+
+ m_r.status_(true );
+ m_b.status_(true );
+
+ add_ctrl(@m_comp_op );
+
+ m_comp_op.text_size_(6.6 );
+ m_comp_op.add_item ('no compositions' );
+ m_comp_op.add_item ('clear' );
+ m_comp_op.add_item ('src' );
+ m_comp_op.add_item ('dst' );
+ m_comp_op.add_item ('src-over' );
+ m_comp_op.add_item ('dst-over' );
+ m_comp_op.add_item ('src-in' );
+ m_comp_op.add_item ('dst-in' );
+ m_comp_op.add_item ('src-out' );
+ m_comp_op.add_item ('dst-out' );
+ m_comp_op.add_item ('src-atop' );
+ m_comp_op.add_item ('dst-atop' );
+ m_comp_op.add_item ('xor' );
+ m_comp_op.add_item ('plus' );
+ m_comp_op.add_item ('minus' );
+ m_comp_op.add_item ('multiply' );
+ m_comp_op.add_item ('screen' );
+ m_comp_op.add_item ('overlay' );
+ m_comp_op.add_item ('darken' );
+ m_comp_op.add_item ('lighten' );
+ m_comp_op.add_item ('color-dodge' );
+ m_comp_op.add_item ('color-burn' );
+ m_comp_op.add_item ('hard-light' );
+ m_comp_op.add_item ('soft-light' );
+ m_comp_op.add_item ('difference' );
+ m_comp_op.add_item ('exclusion' );
+ m_comp_op.add_item ('contrast' );
+ m_comp_op.add_item ('invert' );
+ m_comp_op.add_item ('invert-rgb' );
+ m_comp_op.cur_item_ (0 );
+
+ add_ctrl(@m_shadow_ctrl );
+
+ m_shadow_ctrl.in_polygon_check_(true );
+
+ m_path.remove_all;
+ m_path.move_to(28.47 ,6.45 );
+ m_path.curve3 (21.58 ,1.12 ,19.82 ,0.29 );
+ m_path.curve3 (17.19 ,-0.93 ,14.21 ,-0.93 );
+ m_path.curve3 (9.57 ,-0.93 ,6.57 ,2.25 );
+ m_path.curve3 (3.56 ,5.42 ,3.56 ,10.60 );
+ m_path.curve3 (3.56 ,13.87 ,5.03 ,16.26 );
+ m_path.curve3 (7.03 ,19.58 ,11.99 ,22.51 );
+ m_path.curve3 (16.94 ,25.44 ,28.47 ,29.64 );
+ m_path.line_to(28.47 ,31.40 );
+ m_path.curve3 (28.47 ,38.09 ,26.34 ,40.58 );
+ m_path.curve3 (24.22 ,43.07 ,20.17 ,43.07 );
+ m_path.curve3 (17.09 ,43.07 ,15.28 ,41.41 );
+ m_path.curve3 (13.43 ,39.75 ,13.43 ,37.60 );
+ m_path.line_to(13.53 ,34.77 );
+ m_path.curve3 (13.53 ,32.52 ,12.38 ,31.30 );
+ m_path.curve3 (11.23 ,30.08 ,9.38 ,30.08 );
+ m_path.curve3 (7.57 ,30.08 ,6.42 ,31.35 );
+ m_path.curve3 (5.27 ,32.62 ,5.27 ,34.81 );
+ m_path.curve3 (5.27 ,39.01 ,9.57 ,42.53 );
+ m_path.curve3 (13.87 ,46.04 ,21.63 ,46.04 );
+ m_path.curve3 (27.59 ,46.04 ,31.40 ,44.04 );
+ m_path.curve3 (34.28 ,42.53 ,35.64 ,39.31 );
+ m_path.curve3 (36.52 ,37.21 ,36.52 ,30.71 );
+ m_path.line_to(36.52 ,15.53 );
+ m_path.curve3 (36.52 ,9.13 ,36.77 ,7.69 );
+ m_path.curve3 (37.01 ,6.25 ,37.57 ,5.76 );
+ m_path.curve3 (38.13 ,5.27 ,38.87 ,5.27 );
+ m_path.curve3 (39.65 ,5.27 ,40.23 ,5.62 );
+ m_path.curve3 (41.26 ,6.25 ,44.19 ,9.18 );
+ m_path.line_to(44.19 ,6.45 );
+ m_path.curve3 (38.72 ,-0.88 ,33.74 ,-0.88 );
+ m_path.curve3 (31.35 ,-0.88 ,29.93 ,0.78 );
+ m_path.curve3 (28.52 ,2.44 ,28.47 ,6.45 );
+ m_path.close_polygon;
+
+ m_path.move_to(28.47 ,9.62 );
+ m_path.line_to(28.47 ,26.66 );
+ m_path.curve3 (21.09 ,23.73 ,18.95, 22.51 );
+ m_path.curve3 (15.09 ,20.36 ,13.43, 18.02 );
+ m_path.curve3 (11.77 ,15.67 ,11.77, 12.89 );
+ m_path.curve3 (11.77 ,9.38 ,13.87, 7.06 );
+ m_path.curve3 (15.97 ,4.74 ,18.70, 4.74 );
+ m_path.curve3 (22.41 ,4.74 ,28.47, 9.62 );
+ m_path.close_polygon;
+
+ shape_mtx.Construct;
+ tas.Construct (4.0 );
+ shape_mtx.multiply(@tas );
+ tat.Construct (150 ,100 );
+ shape_mtx.multiply(@tat );
+
+ m_path.transform(@shape_mtx );
+
+ bounding_rect_single(
+ @m_shape ,0 ,
+ @m_shape_bounds.x1 ,@m_shape_bounds.y1 ,
+ @m_shape_bounds.x2 ,@m_shape_bounds.y2 );
+
+ m_shadow_ctrl.xn_ptr(0 )^:=m_shape_bounds.x1;
+ m_shadow_ctrl.yn_ptr(0 )^:=m_shape_bounds.y1;
+ m_shadow_ctrl.xn_ptr(1 )^:=m_shape_bounds.x2;
+ m_shadow_ctrl.yn_ptr(1 )^:=m_shape_bounds.y1;
+ m_shadow_ctrl.xn_ptr(2 )^:=m_shape_bounds.x2;
+ m_shadow_ctrl.yn_ptr(2 )^:=m_shape_bounds.y2;
+ m_shadow_ctrl.xn_ptr(3 )^:=m_shape_bounds.x1;
+ m_shadow_ctrl.yn_ptr(3 )^:=m_shape_bounds.y2;
+
+ rgba.ConstrDbl (0 ,0.3 ,0.5 ,0.3 );
+ m_shadow_ctrl.line_color_(@rgba );
+
+ m_color_lut.resize(256 );
+
+ p:=@g_gradient_colors[0 ];
+ i:=0;
+
+ while i < 256 do
+ begin
+ if i > 63 then
+ aggclr_ptr(m_color_lut.array_operator(i ) ).ConstrInt(
+ int8u_ptr(ptrcomp(p ) + 0 * sizeof(int8u ) )^ ,
+ int8u_ptr(ptrcomp(p ) + 1 * sizeof(int8u ) )^ ,
+ int8u_ptr(ptrcomp(p ) + 2 * sizeof(int8u ) )^ ,
+ 255 )
+ else
+ aggclr_ptr(m_color_lut.array_operator(i ) ).ConstrInt(
+ int8u_ptr(ptrcomp(p ) + 0 * sizeof(int8u ) )^ ,
+ int8u_ptr(ptrcomp(p ) + 1 * sizeof(int8u ) )^ ,
+ int8u_ptr(ptrcomp(p ) + 2 * sizeof(int8u ) )^ ,
+ i * 4 );
+
+ //aggclr_ptr(m_color_lut.array_operator(i ) ).premultiply;
+
+ inc(ptrcomp(p ) ,4 * sizeof(int8u ) );
+ inc(i );
+
+ end;
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_method.Destruct;
+ m_comp_op.Destruct;
+ m_radius.Destruct;
+ m_r.Destruct;
+ m_g.Destruct;
+ m_b.Destruct;
+
+ m_shadow_ctrl.Destruct;
+
+ m_path.Destruct;
+ m_shape.Destruct;
+
+ m_ras.Destruct;
+ m_sl.Destruct;
+
+ m_gray8_buf.Destruct;
+ m_gray8_rbuf.Destruct;
+ m_gray8_rbuf2.Destruct;
+
+ m_color_lut.Destruct;
+
+end;
+
+{ ON_RESIZE }
+procedure the_application.on_resize(sx ,sy : int );
+begin
+ m_gray8_buf.resize (sx * sy);
+ m_gray8_rbuf.attach(m_gray8_buf.data ,sx ,sy ,sx );
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ rgba : aggclr;
+ rens : renderer_scanline_aa_solid;
+
+ pixf_gray8 ,pixf ,pixf2 ,pixf_blend : pixel_formats;
+
+ renb_gray8 ,renb ,renb_blend : renderer_base;
+
+ shadow_persp : trans_perspective;
+ shadow_trans : conv_transform;
+
+ bbox ,cl : rect_d;
+
+ tm : double;
+ buf : array[0..63 ] of char;
+ t : gsv_text;
+ st : conv_stroke;
+
+ r ,g ,b : int;
+
+begin
+// Initialize structures
+ m_ras.clip_box(0 ,0 ,_width ,_height );
+
+ pixfmt_gray8(pixf_gray8 ,@m_gray8_rbuf );
+
+ renb_gray8.Construct(@pixf_gray8 );
+
+ rgba.ConstrInt (0 );
+ renb_gray8.clear(@rgba );
+
+// Testing enhanced compositing operations.
+// Uncomment and replace renb.blend_from_* to renb_blend.blend_from_*
+ pixfmt_custom_blend_rgba(pixf_blend ,rbuf_window ,comp_op_adaptor_rgba ,bgra_order );
+ renb_blend.Construct (@pixf_blend );
+
+ if m_comp_op._cur_item > 0 then
+ pixf_blend.comp_op_(m_comp_op._cur_item - 1 );
+
+ pixfmt(pixf ,rbuf_window );
+
+ renb.Construct(@pixf );
+ rens.Construct(@renb );
+
+ rgba.ConstrDbl(1 ,0.95 ,0.95 );
+ renb.clear (@rgba );
+
+ shadow_persp.Construct(
+ m_shape_bounds.x1 ,m_shape_bounds.y1 ,
+ m_shape_bounds.x2 ,m_shape_bounds.y2 ,
+ pointer(m_shadow_ctrl._polygon ) );
+
+ shadow_trans.Construct(@m_shape ,@shadow_persp );
+
+// Render the controls Before
+ render_ctrl(@m_ras ,@m_sl ,@rens ,@m_method );
+ render_ctrl(@m_ras ,@m_sl ,@rens ,@m_radius );
+ render_ctrl(@m_ras ,@m_sl ,@rens ,@m_r );
+ render_ctrl(@m_ras ,@m_sl ,@rens ,@m_g );
+ render_ctrl(@m_ras ,@m_sl ,@rens ,@m_b );
+ render_ctrl(@m_ras ,@m_sl ,@rens ,@m_shadow_ctrl );
+
+ if m_r._status then
+ r:=100
+ else
+ r:=0;
+
+ if m_g._status then
+ g:=100
+ else
+ g:=0;
+
+ if m_b._status then
+ b:=100
+ else
+ b:=0;
+
+ start_timer;
+
+// Render shadow
+ m_ras.add_path(@shadow_trans );
+
+ rgba.ConstrInt (255 );
+ render_scanlines_aa_solid(@m_ras ,@m_sl ,@renb_gray8 ,@rgba );
+
+// Calculate the bounding box and extend it by the blur radius
+ bbox.Construct;
+
+ bounding_rect_single(@shadow_trans ,0 ,@bbox.x1 ,@bbox.y1 ,@bbox.x2 ,@bbox.y2 );
+
+ bbox.x1:=bbox.x1 - m_radius._value;
+ bbox.y1:=bbox.y1 - m_radius._value;
+ bbox.x2:=bbox.x2 + m_radius._value;
+ bbox.y2:=bbox.y2 + m_radius._value;
+
+ cl.Construct(0 ,0 ,_width ,_height );
+
+ if bbox.clip(@cl ) then
+ begin
+ // Create a new pixel renderer and attach it to the main one as a child image.
+ // It returns true if the attachment suceeded. It fails if the rectangle
+ // (bbox) is fully clipped.
+ pixfmt_gray8(pixf2 ,@m_gray8_rbuf2 );
+
+ if pixf2.attach(@pixf_gray8 ,Trunc(bbox.x1 ) ,Trunc(bbox.y1 ) ,Trunc(bbox.x2 ) ,Trunc(bbox.y2 ) ) then
+ stack_blur_gray8(@pixf2 ,uround(m_radius._value ) ,uround(m_radius._value ) );
+
+ if m_method._cur_item = 0 then
+ begin
+ rgba.ConstrInt(r ,g ,b );
+
+ if m_comp_op._cur_item = 0 then
+ renb.blend_from_color(@pixf2 ,@rgba ,NIL ,Trunc(bbox.x1 ) ,Trunc(bbox.y1 ) )
+ else
+ renb_blend.blend_from_color(@pixf2 ,@rgba ,NIL ,Trunc(bbox.x1 ) ,Trunc(bbox.y1 ) );
+
+ end
+ else
+ if m_comp_op._cur_item = 0 then
+ renb.blend_from_lut(@pixf2 ,m_color_lut.data ,NIL ,Trunc(bbox.x1 ) ,Trunc(bbox.y1 ) )
+ else
+ renb_blend.blend_from_lut(@pixf2 ,m_color_lut.data ,NIL ,Trunc(bbox.x1 ) ,Trunc(bbox.y1 ) );
+
+ end;
+
+ tm:=elapsed_time;
+
+// Info
+ t.Construct;
+ t.size_(10.0 );
+
+ st.Construct(@t );
+ st.width_ (1.5 );
+
+ sprintf(@buf[0 ] ,'%3.2f ms' ,tm );
+
+ t.start_point_(140.0 ,30.0 );
+ t.text_ (@buf[0 ] );
+
+ m_ras.add_path(@st );
+
+ rgba.ConstrDbl (0 ,0 , 0 );
+ render_scanlines_aa_solid(@m_ras ,@m_sl ,@renb ,@rgba );
+
+// Render the controls After
+ render_ctrl(@m_ras ,@m_sl ,@rens ,@m_comp_op );
+
+// Free AGG resources
+ t.Destruct;
+ st.Destruct;
+
+end;
+
+{ ON_MOUSE_MOVE }
+procedure the_application.on_mouse_move;
+begin
+ if flags and mouse_left <> 0 then
+ if m_shadow_ctrl.on_mouse_move(x ,y ,false ) then
+ force_redraw;
+
+ if flags and mouse_left = 0 then
+ on_mouse_button_up(x ,y ,flags );
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure the_application.on_mouse_button_down;
+begin
+ if flags and mouse_left <> 0 then
+ if m_shadow_ctrl.on_mouse_button_down(x ,y ) then
+ force_redraw;
+
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+procedure the_application.on_mouse_button_up;
+begin
+ if m_shadow_ctrl.on_mouse_button_up(x ,y ) then
+ force_redraw;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ 'Now you can blur rendered images rather fast!'#13 +
+ 'There two algorithms are used: Stack Blur by Mario Klingemann '#13 +
+ 'and Fast Recursive Gaussian Filter. The speed of both methods'#13 +
+ 'does not depend on the filter radius. Mario''s method works 3-5'#13 +
+ 'times faster; it doesn''t produce exactly Gaussian response,'#13 +
+ 'but pretty fair for most practical purposes. The recursive filter'#13 +
+ 'uses floating point arithmetic and works slower. But it is true'#13 +
+ 'Gaussian filter, with theoretically infinite impulse response.'#13 +
+ 'The radius (actually 2*sigma value) can be fractional and the'#13 +
+ 'filter produces quite adequate result.' );
+
+end;
+
+VAR
+ app : the_application;
+
+BEGIN
+ app.Construct(pix_format ,flip_y );
+ app.caption_ ('AGG Example. Gaussian and Stack Blur (F1-Help)' );
+
+ if app.init(570 ,400 ,0 ) then
+ app.run;
+
+ app.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/blur.dpr b/src/corelib/render/software/agg-demos/blur.dpr
new file mode 100644
index 00000000..a3bb7777
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/blur.dpr
@@ -0,0 +1,492 @@
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ blur ;
+
+uses
+ agg_basics ,
+ agg_platform_support ,
+ agg_ctrl ,
+ agg_slider_ctrl ,
+ agg_rbox_ctrl ,
+ agg_cbox_ctrl ,
+ agg_polygon_ctrl ,
+ agg_color ,
+ agg_pixfmt ,
+ agg_pixfmt_rgb ,
+ agg_pixfmt_rgba ,
+ agg_pixfmt_gray ,
+ agg_renderer_base ,
+ agg_rendering_buffer ,
+ agg_rasterizer_scanline_aa ,
+ agg_conv_curve ,
+ agg_conv_contour ,
+ agg_conv_stroke ,
+ agg_conv_transform ,
+ agg_scanline_p ,
+ agg_render_scanlines ,
+ agg_renderer_scanline ,
+ agg_bounding_rect ,
+ agg_trans_perspective ,
+ agg_path_storage ,
+ agg_trans_affine ,
+ agg_gsv_text ,
+ agg_blur ;
+
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+type
+ the_application = object(platform_support )
+ private
+ m_method : rbox_ctrl;
+ m_radius : slider_ctrl;
+
+ m_shadow_ctrl : polygon_ctrl;
+
+ m_channel_r ,
+ m_channel_g ,
+ m_channel_b ,
+ m_ctrl_bott : cbox_ctrl;
+
+ m_path : path_storage;
+ m_shape : conv_curve;
+
+ m_ras : rasterizer_scanline_aa;
+ m_sl : scanline_p8;
+ m_rbuf2 : rendering_buffer;
+
+ m_stack_blur : stack_blur;
+ m_recursive_blur : recursive_blur;
+
+ m_shape_bounds : rect_d;
+
+ public
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure on_draw; virtual;
+
+ procedure on_mouse_move (x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_up (x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+var
+ mtx : trans_affine;
+ tas : trans_affine_scaling;
+ tat : trans_affine_translation;
+ clr : aggclr;
+
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_method.Construct(10.0 ,10.0 ,150.0 ,85.0 ,not flip_y_ );
+ m_radius.Construct(150 + 10.0 ,10.0 + 4.0 ,130 + 300.0 ,10.0 + 8.0 + 4.0 ,not flip_y_ );
+
+ m_shadow_ctrl.Construct(4 );
+
+ m_channel_r.Construct(10.0 ,95.0 ,'Red' ,not flip_y_ );
+ m_channel_g.Construct(10.0 ,110.0 ,'Green' ,not flip_y_ );
+ m_channel_b.Construct(10.0 ,125.0 ,'Blue' ,not flip_y_ );
+ m_ctrl_bott.Construct(285 ,30 ,'Draw controls first' ,not flip_y_ );
+
+ m_path.Construct;
+ m_shape.Construct(@m_path );
+
+ m_ras.Construct;
+ m_sl.Construct;
+ m_rbuf2.Construct;
+ m_shape_bounds.Construct;
+
+ m_stack_blur.Construct;
+ m_recursive_blur.Construct;
+
+ add_ctrl(@m_method );
+
+ m_method.text_size_(8 );
+ m_method.add_item ('Stack Blur - Fast' );
+ m_method.add_item ('Stack Blur' );
+ m_method.add_item ('Recursive Blur' );
+ m_method.add_item ('Channels' );
+ m_method.cur_item_ (0 );
+ m_method.no_transform;
+
+ add_ctrl(@m_radius );
+
+ m_radius.range_(0.0 ,40.0 );
+ m_radius.value_(15.0 );
+ m_radius.label_('Blur Radius=%1.2f' );
+ m_radius.no_transform;
+
+ add_ctrl(@m_shadow_ctrl );
+
+ m_shadow_ctrl.in_polygon_check_(true );
+ m_shadow_ctrl.no_transform;
+
+ add_ctrl(@m_channel_r );
+
+ m_channel_r.no_transform;
+
+ add_ctrl(@m_channel_g );
+
+ m_channel_g.status_(true );
+ m_channel_g.no_transform;
+
+ add_ctrl(@m_channel_b );
+
+ m_channel_b.no_transform;
+
+ add_ctrl(@m_ctrl_bott );
+
+ m_ctrl_bott.no_transform;
+
+ m_path.remove_all;
+ m_path.move_to(28.47 ,6.45 );
+ m_path.curve3 (21.58 ,1.12 ,19.82 ,0.29 );
+ m_path.curve3 (17.19 ,-0.93 ,14.21 ,-0.93 );
+ m_path.curve3 (9.57 ,-0.93 ,6.57 ,2.25 );
+ m_path.curve3 (3.56 ,5.42 ,3.56 ,10.60 );
+ m_path.curve3 (3.56 ,13.87 ,5.03 ,16.26 );
+ m_path.curve3 (7.03 ,19.58 ,11.99 ,22.51 );
+ m_path.curve3 (16.94 ,25.44 ,28.47 ,29.64 );
+ m_path.line_to(28.47 ,31.40 );
+ m_path.curve3 (28.47 ,38.09 ,26.34 ,40.58 );
+ m_path.curve3 (24.22 ,43.07 ,20.17 ,43.07 );
+ m_path.curve3 (17.09 ,43.07 ,15.28 ,41.41 );
+ m_path.curve3 (13.43 ,39.75 ,13.43 ,37.60 );
+ m_path.line_to(13.53 ,34.77 );
+ m_path.curve3 (13.53 ,32.52 ,12.38 ,31.30 );
+ m_path.curve3 (11.23 ,30.08 ,9.38 ,30.08 );
+ m_path.curve3 (7.57 ,30.08 ,6.42 ,31.35 );
+ m_path.curve3 (5.27 ,32.62 ,5.27 ,34.81 );
+ m_path.curve3 (5.27 ,39.01 ,9.57 ,42.53 );
+ m_path.curve3 (13.87 ,46.04 ,21.63 ,46.04 );
+ m_path.curve3 (27.59 ,46.04 ,31.40 ,44.04 );
+ m_path.curve3 (34.28 ,42.53 ,35.64 ,39.31 );
+ m_path.curve3 (36.52 ,37.21 ,36.52 ,30.71 );
+ m_path.line_to(36.52 ,15.53 );
+ m_path.curve3 (36.52 ,9.13 ,36.77 ,7.69 );
+ m_path.curve3 (37.01 ,6.25 ,37.57 ,5.76 );
+ m_path.curve3 (38.13 ,5.27 ,38.87 ,5.27 );
+ m_path.curve3 (39.65 ,5.27 ,40.23 ,5.62 );
+ m_path.curve3 (41.26 ,6.25 ,44.19 ,9.18 );
+ m_path.line_to(44.19 ,6.45 );
+ m_path.curve3 (38.72 ,-0.88 ,33.74 ,-0.88 );
+ m_path.curve3 (31.35 ,-0.88 ,29.93 ,0.78 );
+ m_path.curve3 (28.52 ,2.44 ,28.47 ,6.45 );
+ m_path.close_polygon;
+
+ m_path.move_to(28.47 ,9.62 );
+ m_path.line_to(28.47 ,26.66 );
+ m_path.curve3 (21.09 ,23.73 ,18.95 ,22.51 );
+ m_path.curve3 (15.09 ,20.36 ,13.43 ,18.02 );
+ m_path.curve3 (11.77 ,15.67 ,11.77 ,12.89 );
+ m_path.curve3 (11.77 ,9.38 ,13.87 ,7.06 );
+ m_path.curve3 (15.97 ,4.74 ,18.70 ,4.74 );
+ m_path.curve3 (22.41 ,4.74 ,28.47 ,9.62 );
+ m_path.close_polygon;
+
+ mtx.Construct;
+ tas.Construct(4.0 );
+ mtx.multiply (@tas );
+ tat.Construct(150 ,100 );
+ mtx.multiply (@tat );
+
+ m_path.transform(@mtx );
+
+ bounding_rect_single(
+ @m_shape ,0 ,
+ @m_shape_bounds.x1 ,@m_shape_bounds.y1 ,
+ @m_shape_bounds.x2 ,@m_shape_bounds.y2 );
+
+ m_shadow_ctrl.xn_ptr(0 )^:=m_shape_bounds.x1;
+ m_shadow_ctrl.yn_ptr(0 )^:=m_shape_bounds.y1;
+ m_shadow_ctrl.xn_ptr(1 )^:=m_shape_bounds.x2;
+ m_shadow_ctrl.yn_ptr(1 )^:=m_shape_bounds.y1;
+ m_shadow_ctrl.xn_ptr(2 )^:=m_shape_bounds.x2;
+ m_shadow_ctrl.yn_ptr(2 )^:=m_shape_bounds.y2;
+ m_shadow_ctrl.xn_ptr(3 )^:=m_shape_bounds.x1;
+ m_shadow_ctrl.yn_ptr(3 )^:=m_shape_bounds.y2;
+
+ clr.ConstrDbl(0 ,0.3 ,0.5 ,0.3 );
+
+ m_shadow_ctrl.line_color_(@clr );
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_method.Destruct;
+ m_radius.Destruct;
+ m_shadow_ctrl.Destruct;
+ m_channel_r.Destruct;
+ m_channel_g.Destruct;
+ m_channel_b.Destruct;
+ m_ctrl_bott.Destruct;
+
+ m_path.Destruct;
+ m_shape.Destruct;
+
+ m_ras.Destruct;
+ m_sl.Destruct;
+ m_rbuf2.Destruct;
+
+ m_stack_blur.Destruct;
+ m_recursive_blur.Destruct;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ pixf ,pixf2 : pixel_formats;
+
+ renb : renderer_base;
+ rens : renderer_scanline_aa_solid;
+ rgba : aggclr;
+
+ shadow_persp : trans_perspective23;
+ shadow_trans : conv_transform;
+
+ bbox : rect_d;
+
+ tm : double;
+
+ buf : array[0..63 ] of char;
+ t : gsv_text;
+ st : conv_stroke;
+
+begin
+// Initialize structures
+ pixfmt_bgr24(pixf ,rbuf_window );
+
+ renb.Construct(@pixf );
+ rens.Construct(@renb );
+ rgba.ConstrDbl(1 ,1 ,1 );
+ renb.clear (@rgba );
+ m_ras.clip_box(0 ,0 ,_width ,_height );
+
+ shadow_persp.Construct(
+ m_shape_bounds.x1 ,m_shape_bounds.y1 ,
+ m_shape_bounds.x2 ,m_shape_bounds.y2 ,
+ m_shadow_ctrl._polygon );
+
+ shadow_trans.Construct(@m_shape ,@shadow_persp );
+
+ if m_ctrl_bott._status then
+ begin
+ render_ctrl(@m_ras ,@m_sl ,@rens ,@m_method );
+ render_ctrl(@m_ras ,@m_sl ,@rens ,@m_radius );
+ render_ctrl(@m_ras ,@m_sl ,@rens ,@m_channel_r );
+ render_ctrl(@m_ras ,@m_sl ,@rens ,@m_channel_g );
+ render_ctrl(@m_ras ,@m_sl ,@rens ,@m_channel_b );
+
+ end;
+
+// Render shadow
+ m_ras.add_path(@shadow_trans );
+
+ rgba.ConstrDbl (0.2 ,0.3 ,0 );
+ rens.color_ (@rgba );
+ render_scanlines(@m_ras ,@m_sl ,@rens );
+
+// Calculate the bounding box and extend it by the blur radius
+ bbox.Construct;
+ bounding_rect_single(@shadow_trans ,0 ,@bbox.x1 ,@bbox.y1 ,@bbox.x2 ,@bbox.y2 );
+
+ bbox.x1:=bbox.x1 - m_radius._value;
+ bbox.y1:=bbox.y1 - m_radius._value;
+ bbox.x2:=bbox.x2 + m_radius._value;
+ bbox.y2:=bbox.y2 + m_radius._value;
+
+ if m_method._cur_item = 2 then
+ begin
+ // The recursive blur method represents the true Gussian Blur,
+ // with theoretically infinite kernel. The restricted window size
+ // results in extra influence of edge pixels. It's impossible to
+ // solve correctly, but extending the right and top areas to another
+ // radius value produces fair result.
+ bbox.x2:=bbox.x2 + m_radius._value;
+ bbox.y2:=bbox.y2 + m_radius._value;
+
+ end;
+
+ start_timer;
+
+ if m_method._cur_item <> 3 then
+ begin
+ // Create a new pixel renderer and attach it to the main one as a child image.
+ // It returns true if the attachment suceeded. It fails if the rectangle
+ // (bbox) is fully clipped.
+ pixfmt_bgr24(pixf2 ,@m_rbuf2 );
+
+ if pixf2.attach(@pixf ,Trunc(bbox.x1 ) ,Trunc(bbox.y1 ) ,Trunc(bbox.x2 ) ,Trunc(bbox.y2 ) ) then
+ // Blur it
+ if m_method._cur_item = 0 then
+ // Faster, but bore specific.
+ // Works only for 8 bits per channel and only with radii <= 254.
+ stack_blur_rgb24(@pixf2 ,uround(m_radius._value ) ,uround(m_radius._value ) )
+
+ else
+ if m_method._cur_item = 1 then
+ // More general method, but 30-40% slower.
+ m_stack_blur.blur(@pixf2 ,uround(m_radius._value ) )
+
+ else
+ // True Gaussian Blur, 3-5 times slower than Stack Blur,
+ // but still constant time of radius. Very sensitive
+ // to precision, doubles are must here.
+ m_recursive_blur.blur(@pixf2 ,m_radius._value );
+
+ end
+ else
+ begin
+ // Blur separate channels
+ if m_channel_r._status then
+ begin
+ pixfmt_gray8_bgr24r(pixf2 ,@m_rbuf2 );
+
+ if pixf2.attach(@pixf ,Trunc(bbox.x1 ) ,Trunc(bbox.y1 ) ,Trunc(bbox.x2 ) ,Trunc(bbox.y2 ) ) then
+ stack_blur_gray8(@pixf2 ,uround(m_radius._value ) ,uround(m_radius._value ) );
+
+ end;
+
+ if m_channel_g._status then
+ begin
+ pixfmt_gray8_bgr24g(pixf2 ,@m_rbuf2 );
+
+ if pixf2.attach(@pixf ,Trunc(bbox.x1 ) ,Trunc(bbox.y1 ) ,Trunc(bbox.x2 ) ,Trunc(bbox.y2 ) ) then
+ stack_blur_gray8(@pixf2 ,uround(m_radius._value ) ,uround(m_radius._value ) );
+
+ end;
+
+ if m_channel_b._status then
+ begin
+ pixfmt_gray8_bgr24b(pixf2 ,@m_rbuf2 );
+
+ if pixf2.attach(@pixf ,Trunc(bbox.x1 ) ,Trunc(bbox.y1 ) ,Trunc(bbox.x2 ) ,Trunc(bbox.y2 ) ) then
+ stack_blur_gray8(@pixf2 ,uround(m_radius._value ) ,uround(m_radius._value ) );
+
+ end;
+
+ end;
+
+ tm:=elapsed_time;
+
+ render_ctrl(@m_ras ,@m_sl ,@rens ,@m_shadow_ctrl );
+
+// Render the shape itself
+ m_ras.add_path(@m_shape );
+
+ rgba.ConstrDbl (0.6 ,0.9 ,0.7 ,0.8 );
+ rens.color_ (@rgba );
+ render_scanlines(@m_ras ,@m_sl ,@rens );
+
+ t.Construct;
+ t.size_ (10.0 );
+ st.Construct (@t );
+ st.width_ (1.5 );
+ sprintf (@buf[0 ] ,'%3.2f ms' ,tm );
+ t.start_point_(150.0, 30.0);
+ t.text_ (@buf[0 ] );
+
+ m_ras.add_path(@st );
+
+ rgba.ConstrDbl (0 ,0 ,0 );
+ rens.color_ (@rgba );
+ render_scanlines(@m_ras ,@m_sl ,@rens );
+
+// Render the controls
+ if not m_ctrl_bott._status then
+ begin
+ render_ctrl(@m_ras ,@m_sl ,@rens ,@m_method );
+ render_ctrl(@m_ras ,@m_sl ,@rens ,@m_radius );
+ render_ctrl(@m_ras ,@m_sl ,@rens ,@m_channel_r );
+ render_ctrl(@m_ras ,@m_sl ,@rens ,@m_channel_g );
+ render_ctrl(@m_ras ,@m_sl ,@rens ,@m_channel_b );
+
+ end;
+
+ render_ctrl(@m_ras ,@m_sl ,@rens ,@m_ctrl_bott );
+
+// Free Method Resources
+ t.Destruct;
+ st.Destruct;
+
+end;
+
+{ ON_MOUSE_MOVE }
+procedure the_application.on_mouse_move;
+begin
+ if flags and mouse_left <> 0 then
+ if m_shadow_ctrl.on_mouse_move(x ,y ,false ) then
+ force_redraw;
+
+ if flags and mouse_left = 0 then
+ on_mouse_button_up(x ,y ,flags );
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure the_application.on_mouse_button_down;
+begin
+ if flags and mouse_left <> 0 then
+ if m_shadow_ctrl.on_mouse_button_down(x ,y ) then
+ force_redraw;
+
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+procedure the_application.on_mouse_button_up;
+begin
+ if m_shadow_ctrl.on_mouse_button_up(x ,y ) then
+ force_redraw;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ 'Now you can blur rendered images rather fast!'#13 +
+ 'There two algorithms are used: Stack Blur by Mario Klingemann '#13 +
+ 'and Fast Recursive Gaussian Filter. The speed of both methods'#13 +
+ 'does not depend on the filter radius. Mario''s method works 3-5'#13 +
+ 'times faster; it doesn''t produce exactly Gaussian response,'#13 +
+ 'but pretty fair for most practical purposes. The recursive filter'#13 +
+ 'uses floating point arithmetic and works slower. But it is true'#13 +
+ 'Gaussian filter, with theoretically infinite impulse response.'#13 +
+ 'The radius (actually 2*sigma value) can be fractional and the'#13 +
+ 'filter produces quite adequate result.' );
+
+end;
+
+VAR
+ app : the_application;
+
+BEGIN
+ app.Construct(pix_format_bgr24 ,flip_y );
+ app.caption_ ('AGG Example. Gaussian and Stack Blur (F1-Help)' );
+
+ if app.init(440 ,330 ,window_resize ) then
+ app.run;
+
+ app.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/bspline.dpr b/src/corelib/render/software/agg-demos/bspline.dpr
new file mode 100644
index 00000000..8f2b7aa0
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/bspline.dpr
@@ -0,0 +1,270 @@
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ bspline ;
+
+{DEFINE AGG_GRAY8 }
+{$DEFINE AGG_BGR24 }
+{DEFINE AGG_RGB24 }
+{DEFINE AGG_BGRA32 }
+{DEFINE AGG_RGBA32 }
+{DEFINE AGG_ARGB32 }
+{DEFINE AGG_ABGR32 }
+{DEFINE AGG_RGB565 }
+{DEFINE AGG_RGB555 }
+
+uses
+ agg_basics ,
+ agg_platform_support ,
+
+ agg_ctrl ,
+ agg_slider_ctrl ,
+ agg_cbox_ctrl ,
+
+ agg_rasterizer_scanline_aa ,
+ agg_scanline ,
+ agg_scanline_p ,
+
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_render_scanlines ,
+
+ agg_conv_bspline ,
+ agg_conv_stroke ,
+ interactive_polygon_
+
+{$I pixel_formats.inc }
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+type
+ the_application = object(platform_support )
+ m_poly : interactive_polygon;
+
+ m_num_points : slider_ctrl;
+
+ m_close : cbox_ctrl;
+ m_flip : int;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure on_init; virtual;
+ procedure on_draw; virtual;
+
+ procedure on_mouse_move(x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_up (x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_poly.Construct(6 ,5.0 );
+
+ m_num_points.Construct(5.0 ,5.0 ,340.0 ,12.0 ,not flip_y_ );
+ m_close.Construct (350 ,5.0 ,'Close' ,not flip_y_ );
+
+ m_flip:=0;
+
+ add_ctrl(@m_close );
+
+ m_num_points.range_(1.0 ,40.0 );
+ m_num_points.value_(20.0 );
+ m_num_points.label_('Number of intermediate Points = %.3f' );
+
+ add_ctrl(@m_num_points );
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_num_points.Destruct;
+ m_close.Destruct;
+
+ m_poly.Destruct;
+
+end;
+
+{ ON_INIT }
+procedure the_application.on_init;
+begin
+ if m_flip <> 0 then
+ begin
+ m_poly.xn_ptr(0 )^:=100;
+ m_poly.yn_ptr(0 )^:=_height - 100;
+ m_poly.xn_ptr(1 )^:=_width - 100;
+ m_poly.yn_ptr(1 )^:=_height - 100;
+ m_poly.xn_ptr(2 )^:=_width - 100;
+ m_poly.yn_ptr(2 )^:=100;
+ m_poly.xn_ptr(3 )^:=100;
+ m_poly.yn_ptr(3 )^:=100;
+
+ end
+ else
+ begin
+ m_poly.xn_ptr(0 )^:=100;
+ m_poly.yn_ptr(0 )^:=100;
+ m_poly.xn_ptr(1 )^:=_width - 100;
+ m_poly.yn_ptr(1 )^:=100;
+ m_poly.xn_ptr(2 )^:=_width - 100;
+ m_poly.yn_ptr(2 )^:=_height - 100;
+ m_poly.xn_ptr(3 )^:=100;
+ m_poly.yn_ptr(3 )^:=_height - 100;
+
+ end;
+
+ m_poly.xn_ptr(4 )^:=_width / 2;
+ m_poly.yn_ptr(4 )^:=_height / 2;
+ m_poly.xn_ptr(5 )^:=_width / 2;
+ m_poly.yn_ptr(5 )^:=_height / 3;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ pixf : pixel_formats;
+
+ rb : renderer_base;
+ r : renderer_scanline_aa_solid;
+ sl : scanline_p8;
+
+ ras : rasterizer_scanline_aa;
+ rgba : aggclr;
+ path : simple_polygon_vertex_source;
+
+ bspline : conv_bspline;
+ stroke : conv_stroke;
+
+begin
+// Initialize structures
+ pixfmt(pixf ,rbuf_window );
+
+ rb.Construct(@pixf );
+ r.Construct (@rb );
+
+ rgba.ConstrDbl(1 ,1 ,1 );
+ rb.clear (@rgba );
+
+ sl.Construct;
+ ras.Construct;
+
+// Draw
+ path.Construct(m_poly.polygon ,m_poly.num_points ,false ,m_close._status );
+
+ bspline.Construct (@path );
+ bspline.interpolation_step_(1.0 / m_num_points._value );
+
+ stroke.Construct(@bspline );
+ stroke.width_ (2.0 );
+
+ rgba.ConstrDbl(0 ,0 ,0 );
+ r.color_ (@rgba );
+
+ ras.add_path(@stroke );
+
+ render_scanlines(@ras ,@sl ,@r );
+
+// Render the "poly" tool
+ rgba.ConstrDbl(0 ,0.3 ,0.5 ,0.6 );
+ r.color_ (@rgba );
+
+ ras.add_path(@m_poly );
+
+ render_scanlines(@ras ,@sl ,@r );
+
+// Render the controls
+ render_ctrl(@ras ,@sl ,@r ,@m_close );
+ render_ctrl(@ras ,@sl ,@r ,@m_num_points );
+
+// Free AGG resources
+ ras.Destruct;
+ sl.Destruct;
+
+ stroke.Destruct;
+ bspline.Destruct;
+ path.Destruct;
+
+end;
+
+{ ON_MOUSE_MOVE }
+procedure the_application.on_mouse_move;
+begin
+ if flags and mouse_left <> 0 then
+ if m_poly.on_mouse_move(x ,y ) then
+ force_redraw;
+
+ if flags and mouse_left = 0 then
+ on_mouse_button_up(x ,y ,flags );
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure the_application.on_mouse_button_down;
+begin
+ if flags and mouse_left <> 0 then
+ if m_poly.on_mouse_button_down(x ,y ) then
+ force_redraw;
+
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+procedure the_application.on_mouse_button_up;
+begin
+ if m_poly.on_mouse_button_up(x ,y ) then
+ force_redraw;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = unsigned(' ' ) then
+ begin
+ m_flip:=m_flip xor 1;
+
+ on_init;
+ force_redraw;
+
+ end;
+
+ if key = key_f1 then
+ message_(
+ 'Demostration of a very simple class of Bi-cubic Spline interpolation.'#13 +
+ 'The class supports extrapolation which is a simple linear function. '#13#13 +
+ 'How to play with:'#13#13 +
+ 'Use the mouse to change curve''s shape.'#13 +
+ 'Press the spacebar to flip the curve. ' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+VAR
+ app : the_application;
+
+BEGIN
+ app.Construct(pix_format ,flip_y );
+ app.caption_ ('AGG Example. BSpline Interpolator(F1-Help)' );
+
+ if app.init(600 ,600 ,window_resize ) then
+ app.run;
+
+ app.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/build-find_compilers_linux b/src/corelib/render/software/agg-demos/build-find_compilers_linux
new file mode 100755
index 00000000..41a833d8
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/build-find_compilers_linux
@@ -0,0 +1,2 @@
+ppc386 -Fu"src;src/ctrl;src/platform/linux;src/util" -Fisrc -FU_debug -Mdelphi -Tlinux -WC -Sg -Se3 -XX -Xs -B -v0i find_compilers_linux.dpr
+
diff --git a/src/corelib/render/software/agg-demos/build-find_compilers_mac b/src/corelib/render/software/agg-demos/build-find_compilers_mac
new file mode 100755
index 00000000..232fc67d
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/build-find_compilers_mac
@@ -0,0 +1,2 @@
+/usr/local/bin/ppcppc -Fu"src;src/ctrl;src/platform/mac;src/util;upi" -Fisrc -FU_debug -k"-framework Carbon -framework QuickTime" -Mdelphi -Tdarwin -WC -Sg -Se3 -XX -Xs -B -v0i find_compilers_mac.dpr
+
diff --git a/src/corelib/render/software/agg-demos/build-upi b/src/corelib/render/software/agg-demos/build-upi
new file mode 100755
index 00000000..bb1edc3f
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/build-upi
@@ -0,0 +1 @@
+/usr/local/bin/ppcppc -FuUPInterfaces -FUupi -Mmacpas -Tdarwin -WC -Sg -Se3 -XX -Xs -B -v0i compile_upi.dpr \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/build-x11 b/src/corelib/render/software/agg-demos/build-x11
new file mode 100755
index 00000000..b42c00e1
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/build-x11
@@ -0,0 +1 @@
+ppc386 -Fu_debug -FU_debug -Mdelphi -Tlinux -WC -Sg -Se3 -Xs -B -v0i compile_x11.dpr \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/circles.dpr b/src/corelib/render/software/agg-demos/circles.dpr
new file mode 100644
index 00000000..151a91e9
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/circles.dpr
@@ -0,0 +1,419 @@
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ circles ;
+
+{DEFINE AGG_GRAY8 }
+{$DEFINE AGG_BGR24 }
+{DEFINE AGG_RGB24 }
+{DEFINE AGG_BGRA32 }
+{DEFINE AGG_RGBA32 }
+{DEFINE AGG_ARGB32 }
+{DEFINE AGG_ABGR32 }
+{DEFINE AGG_RGB565 }
+{DEFINE AGG_RGB555 }
+
+uses
+ agg_basics ,
+ agg_platform_support ,
+
+ agg_ctrl ,
+ agg_slider_ctrl ,
+ agg_scale_ctrl ,
+
+ agg_rasterizer_scanline_aa ,
+ agg_scanline ,
+ agg_scanline_p ,
+
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_render_scanlines ,
+
+ agg_bspline ,
+ agg_ellipse ,
+ agg_conv_transform ,
+ agg_trans_affine ,
+ agg_gsv_text
+
+{$I pixel_formats.inc }
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+ default_num_points = 10000;
+
+ start_width = 400;
+ start_height = 400;
+
+ spline_r_x : array[0..5 ] of double = (0.000000 ,0.200000 ,0.400000 ,0.910484 ,0.957258 ,1.000000 );
+ spline_r_y : array[0..5 ] of double = (1.000000 ,0.800000 ,0.600000 ,0.066667 ,0.169697 ,0.600000 );
+
+ spline_g_x : array[0..5 ] of double = (0.000000 ,0.292244 ,0.485655 ,0.564859 ,0.795607 ,1.000000 );
+ spline_g_y : array[0..5 ] of double = (0.000000 ,0.607260 ,0.964065 ,0.892558 ,0.435571 ,0.000000 );
+
+ spline_b_x : array[0..5 ] of double = (0.000000 ,0.055045 ,0.143034 ,0.433082 ,0.764859 ,1.000000 );
+ spline_b_y : array[0..5 ] of double = (0.385480 ,0.128493 ,0.021416 ,0.271507 ,0.713974 ,1.000000 );
+
+
+type
+ scatter_point_ptr = ^scatter_point;
+ scatter_point = record
+ x ,y ,z : double;
+
+ color : aggclr;
+
+ end;
+
+ the_application = object(platform_support )
+ m_num_points : unsigned;
+ m_points : scatter_point_ptr;
+
+ m_scale_ctrl_z : scale_ctrl;
+ m_slider_ctrl_sel ,
+ m_slider_ctrl_size : slider_ctrl;
+
+ m_spline_r ,
+ m_spline_g ,
+ m_spline_b : bspline;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean; num_points : unsigned );
+ destructor Destruct;
+
+ procedure generate;
+
+ procedure on_init; virtual;
+ procedure on_draw; virtual;
+ procedure on_idle; virtual;
+
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ RANDOM_DBL }
+function random_dbl(start ,end_ : double ) : double;
+var
+ r : unsigned;
+
+begin
+ r:=system.Random($7fff ) and $7FFF;
+
+ result:=r * (end_ - start ) / 32768.0 + start;
+
+end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_num_points:=num_points;
+
+ agg_getmem(pointer(m_points ) ,num_points * sizeof(scatter_point ) );
+
+ m_scale_ctrl_z.Construct (5 ,5 ,start_width - 5 ,12 ,not flip_y_ );
+ m_slider_ctrl_sel.Construct (5 ,20 ,start_width - 5 ,27 ,not flip_y_ );
+ m_slider_ctrl_size.Construct(5 ,35 ,start_width - 5 ,42 ,not flip_y_ );
+
+ m_spline_r.Construct;
+ m_spline_g.Construct;
+ m_spline_b.Construct;
+
+ m_spline_r.init(6 ,@spline_r_x ,@spline_r_y );
+ m_spline_g.init(6 ,@spline_g_x ,@spline_g_y );
+ m_spline_b.init(6 ,@spline_b_x ,@spline_b_y );
+
+ add_ctrl(@m_scale_ctrl_z );
+ add_ctrl(@m_slider_ctrl_sel );
+ add_ctrl(@m_slider_ctrl_size );
+
+ m_slider_ctrl_size.label_('Size' );
+ m_slider_ctrl_sel.label_ ('Selectivity' );
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_spline_r.Destruct;
+ m_spline_g.Destruct;
+ m_spline_b.Destruct;
+
+ m_scale_ctrl_z.Destruct;
+ m_slider_ctrl_sel.Destruct;
+ m_slider_ctrl_size.Destruct;
+
+ agg_freemem(pointer(m_points ) ,m_num_points * sizeof(scatter_point ) );
+
+end;
+
+{ GENERATE }
+procedure the_application.generate;
+var
+ i : unsigned;
+
+ rx ,ry ,z ,x ,y ,dist ,angle : double;
+
+begin
+ rx:=_initial_width / 3.5;
+ ry:=_initial_height / 3.5;
+
+ for i:=0 to m_num_points - 1 do
+ begin
+ z:=random_dbl(0.0, 1.0);
+
+ scatter_point_ptr(ptrcomp(m_points ) + i * sizeof(scatter_point ) ).z:=z;
+
+ x:=Cos(z * 2.0 * pi ) * rx;
+ y:=Sin(z * 2.0 * pi ) * ry;
+
+ dist :=random_dbl(0.0 ,rx / 2.0 );
+ angle:=random_dbl(0.0 ,pi * 2.0 );
+
+ scatter_point_ptr(ptrcomp(m_points ) + i * sizeof(scatter_point ) ).x:=
+ _initial_width / 2.0 + x + Cos(angle ) * dist;
+
+ scatter_point_ptr(ptrcomp(m_points ) + i * sizeof(scatter_point ) ).y:=
+ _initial_height / 2.0 + y + Sin(angle ) * dist;
+
+ scatter_point_ptr(ptrcomp(m_points ) + i * sizeof(scatter_point ) ).color.ConstrDbl(
+ m_spline_r.get(z ) * 0.8 ,
+ m_spline_g.get(z ) * 0.8 ,
+ m_spline_b.get(z ) * 0.8 ,1.0 );
+
+ end;
+
+end;
+
+{ ON_INIT }
+procedure the_application.on_init;
+begin
+ generate;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ pf : rasterizer_scanline_aa;
+ sl : scanline_p8;
+
+ pixf : pixel_formats;
+
+ rb : renderer_base;
+ rs : renderer_scanline_aa_solid;
+ e1 : ellipse;
+ t1 : conv_transform;
+
+ rgba : aggclr;
+
+ i ,n_drawn : unsigned;
+
+ z ,alpha : double;
+
+ buf : array[0..9 ] of char;
+ txt : gsv_text;
+
+ txt_o : gsv_text_outline;
+
+begin
+// Initialize structures
+ pf.Construct;
+ sl.Construct;
+
+ pixfmt(pixf ,rbuf_window );
+
+ rb.Construct(@pixf );
+ rs.Construct(@rb );
+
+ rgba.ConstrDbl(1 ,1 ,1 );
+ rb.clear (@rgba);
+
+// Draw circles
+ e1.Construct;
+ t1.Construct(@e1 ,_trans_affine_resizing );
+
+ n_drawn:=0;
+
+ for i:=0 to m_num_points - 1 do
+ begin
+ z:=scatter_point_ptr(ptrcomp(m_points ) + i * sizeof(scatter_point ) ).z;
+
+ alpha:=1.0;
+
+ if z < m_scale_ctrl_z._value1 then
+ alpha:=
+ 1.0 -
+ (m_scale_ctrl_z._value1 - z) *
+ m_slider_ctrl_sel._value * 100.0;
+
+ if z > m_scale_ctrl_z._value2 then
+ alpha:=
+ 1.0 -
+ (z - m_scale_ctrl_z._value2 ) *
+ m_slider_ctrl_sel._value * 100.0;
+
+ if alpha > 1.0 then
+ alpha:=1.0;
+
+ if alpha < 0.0 then
+ alpha:=0.0;
+
+ if alpha > 0.0 then
+ begin
+ e1.init(
+ scatter_point_ptr(ptrcomp(m_points ) + i * sizeof(scatter_point ) ).x ,
+ scatter_point_ptr(ptrcomp(m_points ) + i * sizeof(scatter_point ) ).y ,
+ m_slider_ctrl_size._value * 5.0 ,
+ m_slider_ctrl_size._value * 5.0 ,8 );
+
+ pf.add_path(@t1 );
+
+ rgba.ConstrMix(
+ scatter_point_ptr(ptrcomp(m_points ) + i * sizeof(scatter_point ) ).color.r ,
+ scatter_point_ptr(ptrcomp(m_points ) + i * sizeof(scatter_point ) ).color.g ,
+ scatter_point_ptr(ptrcomp(m_points ) + i * sizeof(scatter_point ) ).color.b ,
+ alpha );
+
+ rs.color_ (@rgba );
+ render_scanlines(@pf ,@sl ,@rs );
+
+ inc(n_drawn );
+
+ end;
+
+ end;
+
+// Render the controls
+ render_ctrl(@pf ,@sl ,@rs ,@m_scale_ctrl_z );
+ render_ctrl(@pf ,@sl ,@rs ,@m_slider_ctrl_sel );
+ render_ctrl(@pf ,@sl ,@rs ,@m_slider_ctrl_size );
+
+// Render the Text
+ sprintf(@buf[0 ] ,'%08u' ,n_drawn );
+
+ txt.Construct;
+ txt.size_ (15.0);
+ txt.text_ (@buf[0 ] );
+ txt.start_point_(10.0 ,_initial_height - 20.0 );
+
+ txt_o.Construct(@txt ,_trans_affine_resizing );
+
+ pf.add_path(@txt_o );
+
+ rgba.ConstrDbl(0 ,0 ,0 );
+ rs.color_ (@rgba );
+
+ render_scanlines(@pf ,@sl ,@rs );
+
+// Free AGG resources
+ pf.Destruct;
+ sl.Destruct;
+
+ txt.Destruct;
+ txt_o.Destruct;
+
+end;
+
+{ ON_IDLE }
+procedure the_application.on_idle;
+var
+ i : unsigned;
+
+begin
+ for i:=0 to m_num_points - 1 do
+ begin
+ scatter_point_ptr(ptrcomp(m_points ) + i * sizeof(scatter_point ) ).x:=
+ scatter_point_ptr(ptrcomp(m_points ) + i * sizeof(scatter_point ) ).x +
+ random_dbl(0 ,m_slider_ctrl_sel._value ) - m_slider_ctrl_sel._value * 0.5;
+
+ scatter_point_ptr(ptrcomp(m_points ) + i * sizeof(scatter_point ) ).y:=
+ scatter_point_ptr(ptrcomp(m_points ) + i * sizeof(scatter_point ) ).y +
+ random_dbl(0 ,m_slider_ctrl_sel._value ) - m_slider_ctrl_sel._value * 0.5;
+
+ scatter_point_ptr(ptrcomp(m_points ) + i * sizeof(scatter_point ) ).z:=
+ scatter_point_ptr(ptrcomp(m_points ) + i * sizeof(scatter_point ) ).z +
+ random_dbl(0 ,m_slider_ctrl_sel._value * 0.01 ) - m_slider_ctrl_sel._value * 0.005;
+
+ if scatter_point_ptr(ptrcomp(m_points ) + i * sizeof(scatter_point ) ).z < 0.0 then
+ scatter_point_ptr(ptrcomp(m_points ) + i * sizeof(scatter_point ) ).z:= 0.0;
+
+ if scatter_point_ptr(ptrcomp(m_points ) + i * sizeof(scatter_point ) ).z > 1.0 then
+ scatter_point_ptr(ptrcomp(m_points ) + i * sizeof(scatter_point ) ).z:= 1.0;
+
+ end;
+
+ force_redraw;
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure the_application.on_mouse_button_down;
+begin
+ if flags and mouse_left <> 0 then
+ begin
+ generate;
+ force_redraw;
+
+ end;
+
+ if flags and mouse_right <> 0 then
+ wait_mode_(not _wait_mode );
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ 'This example just demonstrates that AGG can be used in different scatter plot '#13 +
+ 'apllications. There''s a number of small circles drawn. You can change '#13 +
+ 'the parameters of drawing, watching for the performance and the number '#13 +
+ 'of circles simultaneously rendered. Note, that the circles are drawn with '#13 +
+ 'high quality, possibly translucent, and with subpixel accuracy.'#13#13 +
+ 'How to play with:'#13#13 +
+ 'Press the left mouse button to generate a new set of points. '#13 +
+ 'Press the right mouse button to make the points randomly change their coordinates.' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+VAR
+ app : the_application;
+ err : integer;
+
+ num_points : unsigned;
+
+BEGIN
+ num_points:=default_num_points;
+
+ if paramcount > 0 then
+ begin
+ val(paramstr(1 ) ,num_points ,err );
+
+ if num_points = 0 then
+ num_points:=default_num_points;
+
+ if num_points > 20000 then
+ num_points:=20000;
+
+ end;
+
+ app.Construct(pix_format ,flip_y ,num_points );
+ app.caption_ ('AGG Drawing random circles - A scatter plot prototype (F1-Help)' );
+
+ if app.init(start_width ,start_height ,window_resize or window_keep_aspect_ratio ) then
+ app.run;
+
+ app.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/compile_upi.dpr b/src/corelib/render/software/agg-demos/compile_upi.dpr
new file mode 100644
index 00000000..c79b5c2c
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/compile_upi.dpr
@@ -0,0 +1,19 @@
+{skip}
+program compile_upi;
+
+uses
+ Math ,
+ SysUtils ,
+ Carbon ,
+ ImageCompression ,
+ QuickTimeComponents ;
+
+BEGIN
+ writeln('For compilation of AggPas on Mac we need the following units:' );
+ writeln(' Math' );
+ writeln(' SysUtils' );
+ writeln(' Carbon' );
+ writeln(' ImageCompression' );
+ writeln(' QuickTimeComponents' );
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/compile_x11.dpr b/src/corelib/render/software/agg-demos/compile_x11.dpr
new file mode 100644
index 00000000..2a98d262
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/compile_x11.dpr
@@ -0,0 +1,27 @@
+{skip}
+program compile_x11;
+
+uses
+ Math ,
+ SysUtils ,
+ CTypes ,
+ X ,
+ Xlib ,
+ Xutil ,
+ Xatom ,
+ keysym ,
+ libc ;
+
+BEGIN
+ writeln('For compilation of AggPas on Linux X11 we need the following units:' );
+ writeln(' Math' );
+ writeln(' SysUtils' );
+ writeln(' CTypes' );
+ writeln(' X' );
+ writeln(' Xlib' );
+ writeln(' Xutil' );
+ writeln(' Xatom' );
+ writeln(' keysym' );
+ writeln(' libc' );
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/component_rendering.dpr b/src/corelib/render/software/agg-demos/component_rendering.dpr
new file mode 100644
index 00000000..2277e46c
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/component_rendering.dpr
@@ -0,0 +1,171 @@
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ component_rendering ;
+
+uses
+ agg_basics ,
+ agg_platform_support ,
+ agg_slider_ctrl ,
+ agg_color ,
+ agg_pixfmt ,
+ agg_pixfmt_gray ,
+ agg_pixfmt_rgb ,
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_rasterizer_scanline_aa ,
+ agg_scanline_p ,
+ agg_render_scanlines ,
+ agg_ctrl ,
+ agg_ellipse ;
+
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+type
+ the_application = object(platform_support )
+ m_alpha : slider_ctrl_ptr;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure on_draw; virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ new(m_alpha ,Construct(5 ,5 ,320 - 5 ,10 + 5 ,not flip_y ) );
+
+ m_alpha.label_('Alpha=%1.0f' );
+ m_alpha.range_(0 ,255 );
+ m_alpha.value_(255 );
+
+ add_ctrl(m_alpha );
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ dispose(m_alpha ,Destruct );
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ pf ,
+ pfr ,
+ pfg ,
+ pfb : pixel_formats;
+
+ rbase ,
+ rbr ,
+ rbg ,
+ rbb : renderer_base;
+
+ r ,
+ rr ,
+ rg ,
+ rb : renderer_scanline_aa_solid;
+
+ ras : rasterizer_scanline_aa;
+ sl : scanline_p8;
+
+ rgba ,
+ gray : aggclr;
+
+ er ,
+ eg ,
+ eb : ellipse;
+
+begin
+// Initialize structures
+ pixfmt_bgr24 (pf ,rbuf_window );
+ pixfmt_gray8_bgr24r(pfr ,rbuf_window );
+ pixfmt_gray8_bgr24g(pfg ,rbuf_window );
+ pixfmt_gray8_bgr24b(pfb ,rbuf_window );
+
+ rbase.Construct(@pf );
+ rbr.Construct (@pfr );
+ rbg.Construct (@pfg );
+ rbb.Construct (@pfb );
+
+ r.Construct (@rbase );
+ rr.Construct(@rbr );
+ rg.Construct(@rbg );
+ rb.Construct(@rbb );
+
+ ras.Construct;
+ sl.Construct;
+
+// Setup colors & background
+ rgba.ConstrDbl(1 ,1 ,1 );
+ gray.ConstrInt(0 ,trunc(m_alpha._value ) );
+
+ rbase.clear(@rgba );
+
+// Draw ellipses
+ er.Construct (_width / 2 - 0.87 * 50 ,_height / 2 - 0.5 * 50 ,100 ,100 ,100 );
+ rr.color_ (@gray );
+ ras.add_path (@er );
+ render_scanlines(@ras ,@sl ,@rr );
+
+ eg.Construct (_width / 2 + 0.87 * 50 ,_height / 2 - 0.5 * 50 ,100 ,100 ,100 );
+ rg.color_ (@gray );
+ ras.add_path (@eg);
+ render_scanlines(@ras ,@sl ,@rg );
+
+ eb.Construct (_width / 2 ,_height / 2 + 50 ,100 ,100 ,100 );
+ rb.color_ (@gray );
+ ras.add_path (@eb );
+ render_scanlines(@ras ,@sl ,@rb );
+
+// Render control
+ render_ctrl(@ras ,@sl ,@r ,m_alpha );
+
+// Free AGG resources
+ ras.Destruct;
+ sl.Destruct;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ 'AGG has a gray-scale renderer that can use any 8-bit color channel '#13 +
+ 'of an RGB or RGBA frame buffer. Most likely it will be used to draw '#13 +
+ 'gray-scale images directly in the alpha-channel.' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+VAR
+ app : the_application;
+
+BEGIN
+ app.Construct(pix_format_bgr24 ,flip_y );
+ app.caption_ ('AGG Example. Component Rendering (F1-Help)' );
+
+ if app.init(320 ,320 ,0 ) then
+ app.run;
+
+ app.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/compositing.dpr b/src/corelib/render/software/agg-demos/compositing.dpr
new file mode 100644
index 00000000..f466692b
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/compositing.dpr
@@ -0,0 +1,576 @@
+{mac_copy:compositing.bmp}
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ compositing ;
+
+uses
+ Math ,SysUtils ,
+
+ agg_basics ,
+ agg_platform_support ,
+
+ agg_color ,
+ agg_pixfmt ,
+ agg_pixfmt_rgba ,
+
+ agg_ctrl ,
+ agg_rbox_ctrl ,
+ agg_slider_ctrl ,
+
+ agg_rendering_buffer ,
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_rasterizer_scanline_aa ,
+ agg_scanline ,
+ agg_scanline_u ,
+ agg_render_scanlines ,
+
+ agg_math ,
+ agg_array ,
+ agg_ellipse ,
+ agg_conv_stroke ,
+ agg_trans_affine ,
+ agg_rounded_rect ,
+ agg_span_gradient ,
+ agg_span_allocator ,
+ agg_gsv_text ,
+ agg_span_interpolator_linear ,
+ file_utils_ ;
+
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+ base_shift = agg_color.base_shift;
+
+type
+ gradient_linear_color = object(array_base )
+ m_c1 ,
+ m_c2 ,
+ m_res : aggclr;
+
+ constructor Construct; overload;
+ constructor Construct(c1 ,c2 : aggclr_ptr ); overload;
+
+ procedure colors(c1 ,c2 : aggclr_ptr );
+
+ function size : unsigned; virtual;
+ function array_operator(i : unsigned ) : pointer; virtual;
+
+ end;
+
+ the_application = object(platform_support )
+ m_alpha_src ,
+ m_alpha_dst : slider_ctrl;
+ m_comp_op : rbox_ctrl;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure render_scene(rbuf : rendering_buffer_ptr; pixf : pixel_formats_ptr );
+
+ procedure on_init; virtual;
+ procedure on_draw; virtual;
+
+ procedure on_mouse_move (x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_up (x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ gradient_affine }
+procedure gradient_affine(var mtx : trans_affine; x1 ,y1 ,x2 ,y2 : double; gradient_d2 : double = 100.0 );
+var
+ dx ,dy : double;
+
+ tas : trans_affine_scaling;
+ tar : trans_affine_rotation;
+ tat : trans_affine_translation;
+
+begin
+ mtx.Construct;
+
+ dx:=x2 - x1;
+ dy:=y2 - y1;
+
+ mtx.reset;
+
+ tas.Construct(Sqrt(dx * dx + dy * dy ) / gradient_d2 ); mtx.multiply(@tas );
+ tar.Construct(ArcTan2(dy ,dx ) ); mtx.multiply(@tar );
+ tat.Construct(x1 ,y1 ); mtx.multiply(@tat );
+
+ mtx.invert;
+
+end;
+
+{ circle }
+procedure circle(rbase : renderer_base_ptr; c1 ,c2 : aggclr_ptr; x1 ,y1 ,x2 ,y2 ,shadow_alpha : double );
+var
+ color_func : gradient_linear_color;
+
+ gradient_func : gradient_x;
+ gradient_mtx : trans_affine;
+ span_gradient_ : span_gradient;
+ ren_gradient : renderer_scanline_aa;
+ ren_solid : renderer_scanline_aa_solid;
+
+ span_interpolator : span_interpolator_linear;
+ span_allocator_ : span_allocator;
+
+ rgba : aggclr;
+
+ ras : rasterizer_scanline_aa;
+ sl : scanline_u8;
+ ell : ellipse;
+
+ r : double;
+
+begin
+ gradient_func.Construct; // The gradient function
+ gradient_affine(gradient_mtx ,x1 ,y1 ,x2 ,y2 ,100 );
+
+ span_interpolator.Construct(@gradient_mtx ); // Span interpolator
+ span_allocator_.Construct; // Span Allocator
+ color_func.Construct(c1 ,c2 );
+
+ span_gradient_.Construct(
+ @span_allocator_ ,
+ @span_interpolator,
+ @gradient_func,
+ @color_func,
+ 0 ,100 );
+
+ ren_gradient.Construct(rbase ,@span_gradient_ );
+ ras.Construct;
+ sl.Construct;
+
+ r:=calc_distance(x1 ,y1 ,x2 ,y2 ) / 2;
+
+ ell.Construct ((x1 + x2 ) / 2 + 5 ,(y1 + y2 ) / 2 - 3 ,r ,r ,100 );
+ ren_solid.Construct(rbase );
+ rgba.ConstrDbl (0.6 ,0.6 ,0.6 ,0.7 * shadow_alpha );
+ ren_solid.color_ (@rgba );
+ ras.add_path (@ell );
+ render_scanlines (@ras ,@sl ,@ren_solid );
+
+ ell.init ((x1 + x2 ) / 2 ,(y1 + y2 ) / 2 ,r ,r ,100 );
+ ras.add_path (@ell );
+ render_scanlines(@ras ,@sl ,@ren_gradient );
+
+// Free
+ ras.Destruct;
+ sl.Destruct;
+ span_allocator_.Destruct;
+
+end;
+
+{ dst_shape }
+procedure dst_shape(rbase : renderer_base_ptr; c1 ,c2 : aggclr_ptr; x1 ,y1 ,x2 ,y2 : double );
+var
+ color_func : gradient_linear_color;
+ shape : rounded_rect;
+
+ gradient_func : gradient_x;
+ gradient_mtx : trans_affine;
+ ren_gradient : renderer_scanline_aa;
+
+ span_interpolator : span_interpolator_linear;
+ span_allocator_ : span_allocator;
+ span_gradient_ : span_gradient;
+
+ ras : rasterizer_scanline_aa;
+ sl : scanline_u8;
+
+begin
+ gradient_func.Construct; // The gradient function
+ gradient_affine(gradient_mtx ,x1 ,y1 ,x2 ,y2 ,100 );
+
+ span_interpolator.Construct(@gradient_mtx); // Span interpolator
+ span_allocator_.Construct; // Span Allocator
+ color_func.Construct(c1 ,c2 );
+
+ span_gradient_.Construct(
+ @span_allocator_ ,
+ @span_interpolator ,
+ @gradient_func ,
+ @color_func ,
+ 0 ,100 );
+
+ ren_gradient.Construct(rbase ,@span_gradient_ );
+ ras.Construct;
+ sl.Construct;
+
+ shape.Construct (x1 ,y1 ,x2 ,y2 ,40 );
+ ras.add_path (@shape );
+ render_scanlines(@ras ,@sl ,@ren_gradient );
+
+// Free
+ ras.Destruct;
+ sl.Destruct;
+ span_allocator_.Destruct;
+
+end;
+
+{ CONSTRUCT }
+constructor gradient_linear_color.Construct;
+begin
+ m_c1.Construct;
+ m_c2.Construct;
+ m_res.Construct;
+
+end;
+
+{ CONSTRUCT }
+constructor gradient_linear_color.Construct(c1 ,c2 : aggclr_ptr );
+begin
+ m_res.Construct;
+
+ m_c1:=c1^;
+ m_c2:=c2^;
+
+end;
+
+{ COLORS }
+procedure gradient_linear_color.colors;
+begin
+ m_c1:=c1^;
+ m_c2:=c2^;
+
+end;
+
+{ SIZE }
+function gradient_linear_color.size;
+begin
+ result:=256
+
+end;
+
+{ ARRAY_OPERATOR }
+function gradient_linear_color.array_operator;
+begin
+ i:=i shl (base_shift - 8 );
+
+ m_res.r:=int8u((((m_c2.r - m_c1.r ) * i ) + (m_c1.r shl base_shift ) ) shr base_shift );
+ m_res.g:=int8u((((m_c2.g - m_c1.g ) * i ) + (m_c1.g shl base_shift ) ) shr base_shift );
+ m_res.b:=int8u((((m_c2.b - m_c1.b ) * i ) + (m_c1.b shl base_shift ) ) shr base_shift );
+ m_res.a:=int8u((((m_c2.a - m_c1.a ) * i ) + (m_c1.a shl base_shift ) ) shr base_shift );
+
+ result:=@m_res;
+
+end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_alpha_src.Construct(5 ,5 ,400 ,11 ,not flip_y_ );
+ m_alpha_dst.Construct(5 ,5 + 15 ,400 ,11 + 15 ,not flip_y_ );
+ m_comp_op.Construct (420 ,5.0 ,420 + 170.0 ,395.0 ,not flip_y_ );
+
+ m_alpha_src.label_('Src Alpha=%.2f' );
+ m_alpha_src.value_(1.0 );
+
+ add_ctrl(@m_alpha_src );
+
+ m_alpha_dst.label_('Dst Alpha=%.2f' );
+ m_alpha_dst.value_(0.75 );
+
+ add_ctrl(@m_alpha_dst );
+
+ m_comp_op.text_size_(7 );
+ m_comp_op.add_item ('clear' );
+ m_comp_op.add_item ('src' );
+ m_comp_op.add_item ('dst' );
+ m_comp_op.add_item ('src-over' );
+ m_comp_op.add_item ('dst-over' );
+ m_comp_op.add_item ('src-in' );
+ m_comp_op.add_item ('dst-in' );
+ m_comp_op.add_item ('src-out' );
+ m_comp_op.add_item ('dst-out' );
+ m_comp_op.add_item ('src-atop' );
+ m_comp_op.add_item ('dst-atop' );
+ m_comp_op.add_item ('xor' );
+ m_comp_op.add_item ('plus' );
+ m_comp_op.add_item ('minus' );
+ m_comp_op.add_item ('multiply' );
+ m_comp_op.add_item ('screen' );
+ m_comp_op.add_item ('overlay' );
+ m_comp_op.add_item ('darken' );
+ m_comp_op.add_item ('lighten' );
+ m_comp_op.add_item ('color-dodge' );
+ m_comp_op.add_item ('color-burn' );
+ m_comp_op.add_item ('hard-light' );
+ m_comp_op.add_item ('soft-light' );
+ m_comp_op.add_item ('difference' );
+ m_comp_op.add_item ('exclusion' );
+ m_comp_op.add_item ('contrast' );
+ m_comp_op.cur_item_(3 );
+
+ add_ctrl(@m_comp_op );
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_alpha_src.Destruct;
+ m_alpha_dst.Destruct;
+ m_comp_op.Destruct;
+
+end;
+
+{ RENDER_SCENE }
+procedure the_application.render_scene;
+var
+ ren_pixf ,px : pixel_formats;
+ renderer ,rb : renderer_base;
+
+ rgba ,rgbb : aggclr;
+
+ v : double;
+
+begin
+ pixfmt_custom_blend_rgba(ren_pixf ,rbuf ,@comp_op_adaptor_rgba ,bgra_order );
+
+ renderer.Construct(@ren_pixf );
+ rb.Construct (pixf );
+
+ pixfmt_bgra32(px ,rbuf_img(1 ) );
+ rb.blend_from(@px ,NIL ,250 ,180 ,unsigned(trunc(m_alpha_src._value * 255 ) ) );
+
+ rgba.ConstrInt($FD ,$F0 ,$6F ,unsigned(trunc(m_alpha_src._value * 255 ) ) );
+ rgbb.ConstrInt($FE ,$9F ,$34 ,unsigned(trunc(m_alpha_src._value * 255 ) ) );
+
+ circle(
+ @rb ,@rgba ,@rgbb ,
+ 70 * 3 ,100 + 24 * 3 ,37 * 3 ,100 + 79 * 3 ,
+ m_alpha_src._value );
+
+ ren_pixf.comp_op_(m_comp_op._cur_item );
+
+ if m_comp_op._cur_item = 25 then // Contrast
+ begin
+ v:=m_alpha_dst._value;
+
+ rgba.ConstrDbl(v ,v ,v );
+
+ dst_shape(
+ @renderer ,
+ @rgba ,@rgba ,
+ 300 + 50 ,100 + 24 * 3 ,107 + 50 ,100 + 79 * 3 );
+
+ end
+ else
+ begin
+ rgba.ConstrInt($7F ,$C1 ,$FF ,unsigned(trunc(m_alpha_dst._value * 255 ) ) );
+ rgbb.ConstrInt($05 ,$00 ,$5F ,unsigned(trunc(m_alpha_dst._value * 255 ) ) );
+
+ dst_shape(
+ @renderer ,
+ @rgba ,@rgbb ,
+ 300 + 50 ,100 + 24 * 3 ,107 + 50 ,100 + 79 * 3 );
+
+ end;
+
+end;
+
+{ ON_INIT }
+procedure the_application.on_init;
+begin
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ pixf ,pixf2 ,pixf_pre : pixel_formats;
+
+ rgba : aggclr;
+
+ rb ,rb2 ,rb_pre : renderer_base;
+
+ ras : rasterizer_scanline_aa;
+ sl : scanline_u8;
+ ren : renderer_scanline_aa_solid;
+
+ y ,x : unsigned;
+
+ tm : double;
+ buf : array[0..63 ] of char;
+ t : gsv_text;
+ pt : conv_stroke;
+
+begin
+// Initialize structures
+ pixfmt_bgra32(pixf ,rbuf_window );
+ rb.Construct (@pixf );
+
+ rgba.ConstrInt(255 ,255 ,255 );
+ rb.clear (@rgba );
+
+ y:=0;
+
+ while y < rb.height do
+ begin
+ x:=((y shr 3 ) and 1) shl 3;
+
+ while x < rb.width do
+ begin
+ rgba.ConstrInt($df ,$df ,$df );
+
+ rb.copy_bar(x ,y ,x + 7 ,y + 7 ,@rgba );
+
+ inc(x ,16 );
+
+ end;
+
+ inc(y ,8 );
+
+ end;
+
+ create_img(0 ,rbuf_window._width ,rbuf_window._height ); // agg_platform_support functionality
+
+ pixfmt_bgra32(pixf2 ,rbuf_img(0 ) );
+ rb2.Construct(@pixf2 );
+
+ rgba.ConstrInt(0 ,0 ,0 ,0 );
+ rb2.clear (@rgba );
+
+ pixfmt_bgra32_pre(pixf_pre ,rbuf_window );
+ rb_pre.Construct (@pixf_pre );
+
+// Render Scene
+ start_timer;
+
+ render_scene(rbuf_img(0 ) ,@pixf2 );
+
+ tm:=elapsed_time;
+
+ rb_pre.blend_from(@pixf2 );
+
+// Render Text
+ ras.Construct;
+ sl.Construct;
+ ren.Construct(@rb );
+
+ t.Construct;
+ t.size_(10.0 );
+
+ pt.Construct(@t );
+ pt.width_ (1.5 );
+
+ sprintf (@buf[0 ] ,'%3.2f ms' ,tm );
+ t.start_point_(10.0 ,35.0 );
+ t.text_ (@buf[0 ] );
+
+ ras.add_path (@pt );
+ rgba.ConstrDbl (0 ,0 ,0 );
+ ren.color_ (@rgba );
+ render_scanlines(@ras ,@sl ,@ren );
+
+// Render the controls
+ render_ctrl(@ras ,@sl ,@ren ,@m_alpha_src );
+ render_ctrl(@ras ,@sl ,@ren ,@m_alpha_dst );
+ render_ctrl(@ras ,@sl ,@ren ,@m_comp_op );
+
+// Free AGG resources
+ ras.Destruct;
+ sl.Destruct;
+
+ t.Destruct;
+ pt.Destruct;
+
+end;
+
+{ ON_MOUSE_MOVE }
+procedure the_application.on_mouse_move;
+begin
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure the_application.on_mouse_button_down;
+begin
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+procedure the_application.on_mouse_button_up;
+begin
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ 'AGG is fully compatible with all SVG 1.2 extended compositing modes. '#13#13 +
+ 'How to play with:'#13#13 +
+ 'Try to change the alpha values of the source an destination images,'#13 +
+ 'to see, how a particular operation composes the resulting image.' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+VAR
+ app : the_application;
+ buf : array [0..255 ] of char;
+ ext : string[10 ];
+
+ img_name ,p ,n ,x : shortstring;
+
+BEGIN
+ app.Construct(pix_format_bgra32 ,flip_y );
+ app.caption_ ('AGG Example. Compositing Modes (F1-Help)' );
+
+ img_name:='compositing';
+
+{$IFDEF WIN32 }
+ if ParamCount > 0 then
+ begin
+ spread_name(ParamStr(1 ) ,p ,n ,x );
+
+ img_name:=fold_name(p ,n ,'' );
+
+ end;
+
+{$ENDIF }
+
+ if not app.load_img(1 ,img_name ) then
+ begin
+ img_name:=img_name + #0;
+ ext :=app._img_ext + #0;
+
+ if img_name = 'compositing'#0 then
+ begin
+ sprintf(@buf[0 ] ,'File not found: %s' ,ptrcomp(@img_name[1 ] ) );
+ sprintf(@buf[StrLen(@buf ) ] ,'%s. '#13'Download http://www.antigrain.com/' ,ptrcomp(@ext[1 ] ) );
+ sprintf(@buf[StrLen(@buf ) ] ,'%s' ,ptrcomp(@img_name[1 ] ) );
+ sprintf(@buf[StrLen(@buf ) ] ,'%s'#13'or copy it from another directory if available.' ,ptrcomp(@ext[1 ] ) );
+
+ end
+ else
+ begin
+ sprintf(@buf[0 ] ,'File not found: %s' ,ptrcomp(@img_name[1 ] ) );
+ sprintf(@buf[StrLen(@buf ) ] ,'%s' ,ptrcomp(@ext[1 ] ) );
+
+ end;
+
+ app.message_(@buf[0 ] );
+
+ end
+ else
+ if app.init(600 ,400 ,window_resize ) then
+ app.run;
+
+ app.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/compositing2.dpr b/src/corelib/render/software/agg-demos/compositing2.dpr
new file mode 100644
index 00000000..20e01e5e
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/compositing2.dpr
@@ -0,0 +1,336 @@
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ compositing2 ;
+
+uses
+ agg_basics ,
+ agg_color ,
+ agg_platform_support ,
+ agg_ctrl ,
+ agg_slider_ctrl ,
+ agg_rbox_ctrl ,
+ agg_rendering_buffer ,
+ agg_rasterizer_scanline_aa ,
+ agg_scanline_u ,
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_render_scanlines ,
+ agg_rounded_rect ,
+ agg_pixfmt ,
+ agg_pixfmt_rgba ,
+ agg_span_allocator ,
+ agg_span_gradient ,
+ agg_gsv_text ,
+ agg_span_interpolator_linear ,
+ agg_array ,
+ agg_trans_affine ,
+ agg_ellipse ,
+ agg_conv_transform ;
+
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+type
+ the_application = object(platform_support )
+ private
+ m_alpha_dst ,
+ m_alpha_src : slider_ctrl;
+ m_comp_op : rbox_ctrl;
+
+ m_ramp1 ,
+ m_ramp2 : pod_auto_array;
+
+ m_ras : rasterizer_scanline_aa;
+ m_sl : scanline_u8;
+
+ public
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure radial_shape(
+ rbase : renderer_base_ptr;
+ colors : array_base_ptr;
+ x1 ,y1 ,x2 ,y2 : double );
+
+ procedure render_scene(rb : renderer_base_ptr );
+
+ procedure on_draw; virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_alpha_dst.Construct(5 ,5 ,400 ,11 ,not flip_y_ );
+ m_alpha_src.Construct(5 ,5 + 15 ,400 ,11 + 15 ,not flip_y_ );
+ m_comp_op.Construct (420 ,5.0 ,420 + 170.0 ,395.0 ,not flip_y_ );
+
+ m_ramp1.Construct(256 ,sizeof(aggclr ) );
+ m_ramp2.Construct(256 ,sizeof(aggclr ) );
+
+ m_ras.Construct;
+ m_sl.Construct;
+
+ m_alpha_dst.label_('Dst Alpha=%.2f' );
+ m_alpha_dst.value_(1.0 );
+
+ add_ctrl(@m_alpha_dst );
+
+ m_alpha_src.label_('Src Alpha=%.2f' );
+ m_alpha_src.value_(1.0 );
+
+ add_ctrl(@m_alpha_src );
+
+ m_comp_op.text_size_(6.8 );
+ m_comp_op.add_item ('clear' );
+ m_comp_op.add_item ('src' );
+ m_comp_op.add_item ('dst' );
+ m_comp_op.add_item ('src-over' );
+ m_comp_op.add_item ('dst-over' );
+ m_comp_op.add_item ('src-in' );
+ m_comp_op.add_item ('dst-in' );
+ m_comp_op.add_item ('src-out' );
+ m_comp_op.add_item ('dst-out' );
+ m_comp_op.add_item ('src-atop' );
+ m_comp_op.add_item ('dst-atop' );
+ m_comp_op.add_item ('xor' );
+ m_comp_op.add_item ('plus' );
+ m_comp_op.add_item ('minus' );
+ m_comp_op.add_item ('multiply' );
+ m_comp_op.add_item ('screen' );
+ m_comp_op.add_item ('overlay' );
+ m_comp_op.add_item ('darken' );
+ m_comp_op.add_item ('lighten' );
+ m_comp_op.add_item ('color-dodge' );
+ m_comp_op.add_item ('color-burn' );
+ m_comp_op.add_item ('hard-light' );
+ m_comp_op.add_item ('soft-light' );
+ m_comp_op.add_item ('difference' );
+ m_comp_op.add_item ('exclusion' );
+ m_comp_op.add_item ('contrast' );
+ m_comp_op.add_item ('invert' );
+ m_comp_op.add_item ('invert-rgb' );
+ m_comp_op.cur_item_ (3 );
+
+ add_ctrl(@m_comp_op );
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_alpha_dst.Destruct;
+ m_alpha_src.Destruct;
+ m_comp_op.Destruct;
+
+ m_ramp1.Destruct;
+ m_ramp2.Destruct;
+
+ m_ras.Destruct;
+ m_sl.Destruct;
+
+end;
+
+{ RADIAL_SHAPE }
+procedure the_application.radial_shape;
+var
+ gradient_func : gradient_radial;
+ gradient_mtx : trans_affine;
+ span_interpolator : span_interpolator_linear;
+ span_allocator_ : span_allocator;
+ span_gradient_ : span_gradient;
+
+ cx ,cy ,r : double;
+
+ tas : trans_affine_scaling;
+ tat : trans_affine_translation;
+
+ ell : ellipse;
+
+ trans : conv_transform;
+
+ rg : renderer_scanline_aa;
+
+begin
+ gradient_func.Construct;
+ gradient_mtx.Construct;
+ span_interpolator.Construct(@gradient_mtx );
+ span_allocator_.Construct;
+ span_gradient_.Construct(
+ @span_allocator_ ,
+ @span_interpolator ,
+ @gradient_func ,
+ colors ,
+ 0 ,100 );
+
+ cx:=(x1 + x2 ) / 2.0;
+ cy:=(y1 + y2 ) / 2.0;
+
+ if (x2 - x1 ) < (y2 - y1 ) then
+ r:=0.5 * (x2 - x1 )
+ else
+ r:=0.5 * (y2 - y1 );
+
+ tas.Construct (r / 100.0 );
+ gradient_mtx.multiply(@tas );
+ tat.Construct (cx ,cy );
+ gradient_mtx.multiply(@tat );
+ gradient_mtx.multiply(_trans_affine_resizing );
+ gradient_mtx.invert;
+
+ ell.Construct (cx ,cy ,r ,r ,100 );
+ trans.Construct(@ell ,_trans_affine_resizing );
+
+ m_ras.add_path(@trans );
+ rg.Construct (rbase ,@span_gradient_ );
+
+ render_scanlines(@m_ras ,@m_sl ,@rg );
+
+ span_allocator_.Destruct;
+ span_gradient_.Destruct;
+
+end;
+
+{ RENDER_SCENE }
+procedure the_application.render_scene;
+var
+ pixf : pixel_formats;
+ ren : renderer_base;
+
+ cx ,cy : double;
+
+begin
+ pixfmt_custom_blend_rgba(pixf ,rbuf_window ,@comp_op_adaptor_rgba ,bgra_order );
+
+ ren.Construct(@pixf );
+
+ pixf.comp_op_(unsigned(comp_op_difference ) );
+ radial_shape (@ren ,@m_ramp1 ,50 ,50 ,50 + 320 ,50 + 320 );
+
+ pixf.comp_op_(m_comp_op._cur_item );
+
+ cx:=50;
+ cy:=50;
+
+ radial_shape(@ren ,@m_ramp2 ,cx + 120 - 70 ,cy + 120 - 70 ,cx + 120 + 70 ,cy + 120 + 70 );
+ radial_shape(@ren ,@m_ramp2 ,cx + 200 - 70 ,cy + 120 - 70 ,cx + 200 + 70 ,cy + 120 + 70 );
+ radial_shape(@ren ,@m_ramp2 ,cx + 120 - 70 ,cy + 200 - 70 ,cx + 120 + 70 ,cy + 200 + 70 );
+ radial_shape(@ren ,@m_ramp2 ,cx + 200 - 70 ,cy + 200 - 70 ,cx + 200 + 70 ,cy + 200 + 70 );
+
+end;
+
+{ generate_color_ramp }
+procedure generate_color_ramp(c : pod_auto_array_ptr; c1 ,c2 ,c3 ,c4 : aggclr_ptr );
+var
+ i : unsigned;
+
+begin
+ i:=0;
+
+ while i < 85 do
+ begin
+ aggclr_ptr(c.array_operator(i ) )^:=c1.gradient(c2 ,i / 85.0 );
+
+ inc(i );
+
+ end;
+
+ while i < 170 do
+ begin
+ aggclr_ptr(c.array_operator(i ) )^:=c2.gradient(c3 ,(i - 85 ) / 85.0 );
+
+ inc(i );
+
+ end;
+
+ while i < 256 do
+ begin
+ aggclr_ptr(c.array_operator(i ) )^:=c3.gradient(c4 ,(i - 170 ) / 85.0 );
+
+ inc(i );
+
+ end;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ pixf : pixel_formats;
+ rgba : aggclr;
+
+ rb : renderer_base;
+ rs : renderer_scanline_aa_solid;
+
+ c1 ,c2 ,c3 ,c4 : aggclr;
+
+begin
+// Initialize structures
+// pixfmt_alpha_blend_rgba(pixf ,rbuf_window ,bgra_order ); {!}
+ pixfmt_bgra32(pixf ,rbuf_window );
+
+ rb.Construct(@pixf );
+ rs.Construct(@rb );
+
+ rgba.ConstrInt(255 ,255 ,255 );
+ rb.clear (@rgba );
+
+// Render
+ c1.ConstrDbl(0 ,0 ,0 ,m_alpha_dst._value );
+ c2.ConstrDbl(0 ,0 ,1 ,m_alpha_dst._value );
+ c3.ConstrDbl(0 ,1 ,0 ,m_alpha_dst._value );
+ c4.ConstrDbl(1 ,0 ,0 ,0 );
+
+ generate_color_ramp(@m_ramp1 ,@c1 ,@c2 ,@c3 ,@c4 );
+
+ c1.ConstrDbl(0 ,0 ,0 ,m_alpha_src._value );
+ c2.ConstrDbl(0 ,0 ,1 ,m_alpha_src._value );
+ c3.ConstrDbl(0 ,1 ,0 ,m_alpha_src._value );
+ c4.ConstrDbl(1 ,0 ,0 ,0 );
+
+ generate_color_ramp(@m_ramp2 ,@c1 ,@c2 ,@c3 ,@c4 );
+
+ render_scene(@rb );
+
+// Render the controls
+ render_ctrl(@m_ras ,@m_sl ,@rs ,@m_alpha_dst );
+ render_ctrl(@m_ras ,@m_sl ,@rs ,@m_alpha_src );
+ render_ctrl(@m_ras ,@m_sl ,@rs ,@m_comp_op );
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ 'Another demo example with extended compositing modes. ' );
+
+end;
+
+VAR
+ app : the_application;
+
+BEGIN
+ app.Construct(pix_format_bgra32 ,flip_y );
+ app.caption_ ('AGG Example. Compositing Modes (F1-Help)' );
+
+ if app.init(600 ,400 ,window_resize or window_keep_aspect_ratio ) then
+ app.run;
+
+ app.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/conv_contour.dpr b/src/corelib/render/software/agg-demos/conv_contour.dpr
new file mode 100644
index 00000000..c06bc9bc
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/conv_contour.dpr
@@ -0,0 +1,274 @@
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ conv_contour_ ;
+
+uses
+ agg_basics ,
+ agg_platform_support ,
+
+ agg_color ,
+ agg_pixfmt ,
+ agg_pixfmt_rgb ,
+
+ agg_ctrl ,
+ agg_rbox_ctrl ,
+ agg_cbox_ctrl ,
+ agg_slider_ctrl ,
+
+ agg_rendering_buffer ,
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_rasterizer_scanline_aa ,
+ agg_scanline_p ,
+ agg_render_scanlines ,
+
+ agg_conv_stroke ,
+ agg_conv_transform ,
+ agg_conv_curve ,
+ agg_conv_contour ,
+ agg_path_storage ,
+ agg_trans_affine ,
+ agg_math_stroke ;
+
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+type
+ the_application = object(platform_support )
+ m_close : rbox_ctrl;
+ m_width : slider_ctrl;
+ m_auto_detect : cbox_ctrl;
+ m_path : path_storage;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure compose_path;
+ procedure on_draw; virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_close.Construct (10.0 ,10.0 ,130.0 ,80.0 ,not flip_y_ );
+ m_width.Construct (130 + 10.0 ,10.0 + 4.0 ,130 + 300.0 ,10.0 + 8.0 + 4.0 ,not flip_y_ );
+ m_auto_detect.Construct(130 + 10.0 ,10.0 + 4.0 + 16.0 ,'Autodetect orientation if not defined' ,not flip_y_ );
+ m_path.Construct;
+
+ add_ctrl(@m_close );
+
+ m_close.add_item ('Close' );
+ m_close.add_item ('Close CW' );
+ m_close.add_item ('Close CCW' );
+ m_close.cur_item_(0 );
+
+ add_ctrl(@m_width );
+
+ m_width.range_(-100.0 ,100.0 );
+ m_width.value_(0.0 );
+ m_width.label_('Width=%1.2f' );
+
+ add_ctrl(@m_auto_detect );
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_close.Destruct;
+ m_width.Destruct;
+ m_auto_detect.Destruct;
+ m_path.Destruct;
+
+end;
+
+{ COMPOSE_PATH }
+procedure the_application.compose_path;
+var
+ flag : unsigned;
+
+begin
+ flag:=0;
+
+ if m_close._cur_item = 1 then
+ flag:=path_flags_cw;
+
+ if m_close._cur_item = 2 then
+ flag:=path_flags_ccw;
+
+ m_path.remove_all;
+
+ m_path.move_to(28.47 ,6.45 );
+ m_path.curve3 (21.58 ,1.12 ,19.82 ,0.29 );
+ m_path.curve3 (17.19 ,-0.93 ,14.21 ,-0.93 );
+ m_path.curve3 (9.57 ,-0.93 ,6.57 ,2.25 );
+ m_path.curve3 (3.56 ,5.42 ,3.56 ,10.60 );
+ m_path.curve3 (3.56 ,13.87 ,5.03 ,16.26 );
+ m_path.curve3 (7.03 ,19.58 ,11.99 ,22.51 );
+ m_path.curve3 (16.94 ,25.44 ,28.47 ,29.64 );
+ m_path.line_to(28.47 ,31.40 );
+ m_path.curve3 (28.47 ,38.09 ,26.34 ,40.58 );
+ m_path.curve3 (24.22 ,43.07 ,20.17 ,43.07 );
+ m_path.curve3 (17.09 ,43.07 ,15.28 ,41.41 );
+ m_path.curve3 (13.43 ,39.75 ,13.43 ,37.60 );
+ m_path.line_to(13.53 ,34.77 );
+ m_path.curve3 (13.53 ,32.52 ,12.38 ,31.30 );
+ m_path.curve3 (11.23 ,30.08 ,9.38 ,30.08 );
+ m_path.curve3 (7.57 ,30.08 ,6.42 ,31.35 );
+ m_path.curve3 (5.27 ,32.62 ,5.27 ,34.81 );
+ m_path.curve3 (5.27 ,39.01 ,9.57 ,42.53 );
+ m_path.curve3 (13.87 ,46.04 ,21.63 ,46.04 );
+ m_path.curve3 (27.59 ,46.04 ,31.40 ,44.04 );
+ m_path.curve3 (34.28 ,42.53 ,35.64 ,39.31 );
+ m_path.curve3 (36.52 ,37.21 ,36.52 ,30.71 );
+ m_path.line_to(36.52 ,15.53 );
+ m_path.curve3 (36.52 ,9.13 ,36.77 ,7.69 );
+ m_path.curve3 (37.01 ,6.25 ,37.57 ,5.76 );
+ m_path.curve3 (38.13 ,5.27 ,38.87 ,5.27 );
+ m_path.curve3 (39.65 ,5.27 ,40.23 ,5.62 );
+ m_path.curve3 (41.26 ,6.25 ,44.19 ,9.18 );
+ m_path.line_to(44.19 ,6.45 );
+ m_path.curve3 (38.72 ,-0.88 ,33.74 ,-0.88 );
+ m_path.curve3 (31.35 ,-0.88 ,29.93 ,0.78 );
+ m_path.curve3 (28.52 ,2.44 ,28.47 ,6.45 );
+
+ m_path.close_polygon(flag );
+
+ m_path.move_to(28.47 ,9.62 );
+ m_path.line_to(28.47 ,26.66 );
+ m_path.curve3 (21.09 ,23.73 ,18.95 ,22.51 );
+ m_path.curve3 (15.09 ,20.36 ,13.43 ,18.02 );
+ m_path.curve3 (11.77 ,15.67 ,11.77 ,12.89 );
+ m_path.curve3 (11.77 ,9.38 ,13.87 ,7.06 );
+ m_path.curve3 (15.97 ,4.74 ,18.70 ,4.74 );
+ m_path.curve3 (22.41 ,4.74 ,28.47 ,9.62 );
+
+ m_path.close_polygon(flag );
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ pixf : pixel_formats;
+ renb : renderer_base;
+ ren : renderer_scanline_aa_solid;
+ rgba : aggclr;
+
+ ras : rasterizer_scanline_aa;
+ sl : scanline_p8;
+
+ mtx : trans_affine;
+ tas : trans_affine_scaling;
+ tat : trans_affine_translation;
+
+ trans : conv_transform;
+ curve : conv_curve;
+
+ contour : conv_contour;
+
+begin
+// Initialize structures
+ pixfmt_bgr24(pixf ,rbuf_window );
+
+ renb.Construct(@pixf );
+ ren.Construct (@renb );
+ rgba.ConstrDbl(1 ,1 ,1 );
+ renb.clear (@rgba );
+
+ ras.Construct;
+ sl.Construct;
+
+// Render
+ mtx.Construct;
+
+ tas.Construct(4.0 );
+ mtx.multiply (@tas );
+
+ tat.Construct(150 ,100 );
+ mtx.multiply (@tat );
+
+ trans.Construct(@m_path ,@mtx );
+ curve.Construct(@trans );
+
+ contour.Construct(@curve );
+
+ contour.width_ (m_width._value );
+ //contour.line_join_ (miter_join );
+ //contour.inner_join_ (miter_join );
+ //contour.inner_miter_limit_ (4.0 );
+ contour.auto_detect_orientation_(m_auto_detect._status );
+
+ compose_path;
+ ras.add_path(@contour );
+
+ rgba.ConstrDbl(0 ,0 ,0 );
+ ren.color_ (@rgba );
+
+ render_scanlines(@ras ,@sl ,@ren );
+
+// Render the controls
+ render_ctrl(@ras ,@sl ,@ren ,@m_close );
+ render_ctrl(@ras ,@sl ,@ren ,@m_width );
+ render_ctrl(@ras ,@sl ,@ren ,@m_auto_detect );
+
+// Free AGG resources
+ ras.Destruct;
+ sl.Destruct;
+
+ curve.Destruct;
+ contour.Destruct;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ 'One of the converters in AGG is conv_contour. It allows you to extend or shrink '#13 +
+ 'polygons. Initially, it was implemented to eliminate the "problem of adjacent edges"'#13 +
+ 'in the SVG Viewer, but it can be very useful in many other applications, for example,'#13 +
+ 'to change the font weight on the fly. The trick here is that the sign (dilation or '#13 +
+ 'shrinking) depends on the vertex order - clockwise or counterclockwise. '#13 +
+ 'In the conv_contour you can control the behavior. Sometimes you need to preserve '#13 +
+ 'the dilation regardless of the initial orientation, sometimes it should depend '#13 +
+ 'on the orientation. The glyph ‘a’ has a "hole" whose orientation differs from '#13 +
+ 'the main contour. To change the "weight" correctly, you need to keep the orientation '#13 +
+ 'as it is originally defined. If you turn "Autodetect orientation…" on, the glyph will '#13 +
+ 'be extended or shrinked incorrectly.'#13#13 +
+ 'How to play with:'#13#13 +
+ 'The radio buttons control the orientation flad assigned to all polygons.'#13 +
+ '"Close" doesn''t add the flag.'#13 +
+ '"Close CW" and "Close CCW" add "clockwise" or "counterclockwise" flag respectively.' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+VAR
+ app : the_application;
+
+BEGIN
+ app.Construct(pix_format_bgr24 ,flip_y );
+ app.caption_ ('AGG Example. Contour Tool & Polygon Orientation (F1-Help)' );
+
+ if app.init(440 ,330 ,0 ) then
+ app.run;
+
+ app.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/conv_dash_marker.dpr b/src/corelib/render/software/agg-demos/conv_dash_marker.dpr
new file mode 100644
index 00000000..5e66755e
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/conv_dash_marker.dpr
@@ -0,0 +1,434 @@
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ conv_dash_marker ;
+
+uses
+ Math ,
+
+ agg_basics ,
+ agg_platform_support ,
+
+ agg_color ,
+ agg_pixfmt ,
+ agg_pixfmt_rgb ,
+
+ agg_ctrl ,
+ agg_slider_ctrl ,
+ agg_rbox_ctrl ,
+ agg_cbox_ctrl ,
+
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_rasterizer_scanline_aa ,
+ agg_scanline ,
+ agg_scanline_u ,
+ agg_render_scanlines ,
+
+ agg_conv_stroke ,
+ agg_conv_dash ,
+ agg_conv_curve ,
+ agg_conv_contour ,
+ agg_conv_smooth_poly1 ,
+ agg_conv_marker ,
+ agg_arrowhead ,
+ agg_vcgen_markers_term ,
+ agg_math ,
+ agg_math_stroke ,
+ agg_path_storage ;
+
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+type
+ the_application = object(platform_support )
+ m_x ,
+ m_y : array[0..2 ] of double;
+ m_dx ,
+ m_dy : double;
+ m_idx : int;
+
+ m_cap : rbox_ctrl;
+ m_width ,
+ m_smooth : slider_ctrl;
+ m_close ,
+ m_even_odd : cbox_ctrl;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure on_init; virtual;
+ procedure on_draw; virtual;
+
+ procedure on_mouse_move (x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_up (x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_cap.Construct (10.0 ,10.0 ,130.0 ,80.0 ,not flip_y_ );
+ m_width.Construct (130 + 10.0 ,10.0 + 4.0 ,130 + 150.0 ,10.0 + 8.0 + 4.0 ,not flip_y_ );
+ m_smooth.Construct (130 + 150.0 + 10.0 ,10.0 + 4.0 ,500 - 10.0 ,10.0 + 8.0 + 4.0 ,not flip_y_ );
+ m_close.Construct (130 + 10.0 ,10.0 + 4.0 + 16.0 ,'Close Polygons' ,not flip_y_ );
+ m_even_odd.Construct(130 + 150.0 + 10.0 ,10.0 + 4.0 + 16.0 ,'Even-Odd Fill' ,not flip_y_ );
+
+ m_idx:=-1;
+
+ m_x[0 ]:=57 + 100;
+ m_y[0 ]:=60;
+ m_x[1 ]:=369 + 100;
+ m_y[1 ]:=170;
+ m_x[2 ]:=143 + 100;
+ m_y[2 ]:=310;
+
+ add_ctrl(@m_cap );
+
+ m_cap.add_item ('Butt Cap' );
+ m_cap.add_item ('Square Cap' );
+ m_cap.add_item ('Round Cap' );
+ m_cap.cur_item_(0 );
+ m_cap.no_transform;
+
+ add_ctrl(@m_width );
+
+ m_width.range_(0.0 ,10.0 );
+ m_width.value_(3.0 );
+ m_width.label_('Width=%1.2f' );
+ m_width.no_transform;
+
+ add_ctrl(@m_smooth );
+
+ m_smooth.range_(0.0 ,2.0 );
+ m_smooth.value_(1.0 );
+ m_smooth.label_('Smooth=%1.2f' );
+ m_smooth.no_transform;
+
+ add_ctrl(@m_close );
+
+ m_close.no_transform;
+
+ add_ctrl(@m_even_odd );
+
+ m_even_odd.no_transform;
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_cap.Destruct;
+ m_width.Destruct;
+ m_smooth.Destruct;
+ m_close.Destruct;
+ m_even_odd.Destruct;
+
+end;
+
+{ ON_INIT }
+procedure the_application.on_init;
+begin
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ pixf : pixel_formats;
+ rgba : aggclr;
+ renb : renderer_base;
+ ren : renderer_scanline_aa_solid;
+ ras : rasterizer_scanline_aa;
+ sl : scanline_u8;
+
+ cap : unsigned;
+ path : path_storage;
+
+ smooth : conv_smooth_poly1;
+
+ smooth_outline : conv_stroke;
+
+ curve : conv_curve;
+ dash : conv_dash;
+ stroke : conv_stroke;
+ arrow : conv_marker;
+ marker : vcgen_markers_term;
+
+ k : double;
+ ah : arrowhead;
+
+begin
+// Initialize structures
+ pixfmt_bgr24(pixf ,rbuf_window );
+
+ renb.Construct(@pixf );
+ ren.Construct (@renb );
+
+ rgba.ConstrDbl(1 ,1 ,1 );
+ renb.clear (@rgba );
+
+ ras.Construct;
+ sl.Construct;
+
+// Render
+ cap:=butt_cap;
+
+ if m_cap._cur_item = 1 then
+ cap:=square_cap;
+
+ if m_cap._cur_item = 2 then
+ cap:=round_cap;
+
+ path.Construct;
+
+ path.move_to(m_x[0 ] ,m_y[0 ] );
+ path.line_to(m_x[1 ] ,m_y[1 ] );
+ path.line_to((m_x[0 ] + m_x[1 ] + m_x[2 ] ) / 3.0 ,(m_y[0 ] + m_y[1 ] + m_y[2 ] ) / 3.0 );
+ path.line_to(m_x[2 ] ,m_y[2 ] );
+
+ if m_close._status then
+ path.close_polygon;
+
+ path.move_to((m_x[0 ] + m_x[1 ] ) / 2 ,(m_y[0 ] + m_y[1 ] ) / 2 );
+ path.line_to((m_x[1 ] + m_x[2 ] ) / 2 ,(m_y[1 ] + m_y[2 ] ) / 2 );
+ path.line_to((m_x[2 ] + m_x[0 ] ) / 2 ,(m_y[2 ] + m_y[0 ] ) / 2 );
+
+ if m_close._status then
+ path.close_polygon;
+
+ if m_even_odd._status then
+ ras.filling_rule(fill_even_odd );
+
+// (1)
+ ras.add_path (@path );
+ rgba.ConstrDbl (0.7 ,0.5 ,0.1 ,0.5 );
+ ren.color_ (@rgba );
+ render_scanlines(@ras ,@sl ,@ren );
+
+// Start of (2, 3, 4)
+ smooth.Construct (@path );
+ smooth.smooth_value_(m_smooth._value );
+
+// (2)
+ ras.add_path (@smooth );
+ rgba.ConstrDbl (0.1 ,0.5 ,0.7 ,0.1 );
+ ren.color_ (@rgba );
+ render_scanlines(@ras ,@sl ,@ren );
+
+// (3)
+ smooth_outline.Construct(@smooth );
+
+ ras.add_path (@smooth_outline );
+ rgba.ConstrDbl (0.0 ,0.6 ,0.0 ,0.8 );
+ ren.color_ (@rgba );
+ render_scanlines(@ras ,@sl ,@ren );
+
+// (4)
+ curve.Construct(@smooth );
+ dash.Construct (@curve );
+
+ marker.Construct;
+ dash.set_markers(@marker );
+
+ stroke.Construct(@dash );
+ stroke.line_cap_(cap);
+ stroke.width_ (m_width._value );
+
+ k:=Power(m_width._value ,0.7 );
+
+ ah.Construct;
+ ah.head_(4 * k ,4 * k ,3 * k ,2 * k );
+
+ if not m_close._status then
+ ah.tail_(1 * k ,1.5 * k ,3 * k ,5 * k );
+
+ arrow.Construct(dash.markers ,@ah );
+
+ dash.add_dash (20.0 ,5.0 );
+ dash.add_dash (5.0 ,5.0 );
+ dash.add_dash (5.0 ,5.0 );
+ dash.dash_start(10 );
+
+ ras.add_path (@stroke );
+ ras.add_path (@arrow );
+ rgba.ConstrDbl (0.0 ,0.0 ,0.0 );
+ ren.color_ (@rgba );
+ render_scanlines(@ras ,@sl ,@ren );
+
+// Render the controls
+ ras.filling_rule(fill_non_zero );
+
+ render_ctrl(@ras ,@sl ,@ren ,@m_cap );
+ render_ctrl(@ras ,@sl ,@ren ,@m_width );
+ render_ctrl(@ras ,@sl ,@ren ,@m_smooth );
+ render_ctrl(@ras ,@sl ,@ren ,@m_close );
+ render_ctrl(@ras ,@sl ,@ren ,@m_even_odd );
+
+// Free AGG resources
+ ras.Destruct;
+ sl.Destruct;
+
+ path.Destruct;
+ smooth.Destruct;
+ smooth_outline.Destruct;
+ curve.Destruct;
+ dash.Destruct;
+ marker.Destruct;
+ stroke.Destruct;
+
+end;
+
+{ ON_MOUSE_MOVE }
+procedure the_application.on_mouse_move;
+var
+ dx ,dy : double;
+
+begin
+ if flags and mouse_left <> 0 then
+ begin
+ if m_idx = 3 then
+ begin
+ dx:=x - m_dx;
+ dy:=y - m_dy;
+
+ m_x[1 ]:=m_x[1 ] - (m_x[0 ] - dx );
+ m_y[1 ]:=m_y[1 ] - (m_y[0 ] - dy );
+ m_x[2 ]:=m_x[2 ] - (m_x[0 ] - dx );
+ m_y[2 ]:=m_y[2 ] - (m_y[0 ] - dy );
+
+ m_x[0 ]:=dx;
+ m_y[0 ]:=dy;
+
+ force_redraw;
+
+ exit;
+
+ end;
+
+ if m_idx >= 0 then
+ begin
+ m_x[m_idx ]:=x - m_dx;
+ m_y[m_idx ]:=y - m_dy;
+
+ force_redraw;
+
+ end;
+
+ end
+ else
+ on_mouse_button_up(x ,y ,flags );
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure the_application.on_mouse_button_down;
+var
+ i : unsigned;
+
+begin
+ if flags and mouse_left <> 0 then
+ begin
+ i:=0;
+
+ while i < 3 do
+ begin
+ if Sqrt((x - m_x[i ] ) * (x - m_x[i ] ) + (y - m_y[i ] ) * (y - m_y[i ] ) ) < 20.0 then
+ begin
+ m_dx :=x - m_x[i ];
+ m_dy :=y - m_y[i ];
+ m_idx:=i;
+
+ break;
+
+ end;
+
+ inc(i );
+
+ end;
+
+ if i = 3 then
+ if point_in_triangle(
+ m_x[0 ] ,m_y[0 ] ,
+ m_x[1 ] ,m_y[1 ] ,
+ m_x[2 ] ,m_y[2 ] ,x ,y ) then
+ begin
+ m_dx :=x - m_x[0 ];
+ m_dy :=y - m_y[0 ];
+ m_idx:=3;
+
+ end;
+
+ end;
+
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+procedure the_application.on_mouse_button_up;
+begin
+ m_idx:=-1;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+var
+ dx ,dy : double;
+
+begin
+ dx:=0;
+ dy:=0;
+
+ case key of
+ key_left : dx:=-0.1;
+ key_right : dx:= 0.1;
+ key_up : dy:= 0.1;
+ key_down : dy:=-0.1;
+
+ end;
+
+ m_x[0 ]:=m_x[0 ] + dx;
+ m_y[0 ]:=m_y[0 ] + dy;
+ m_x[1 ]:=m_x[1 ] + dx;
+ m_y[1 ]:=m_y[1 ] + dy;
+
+ force_redraw;
+
+ if key = key_f1 then
+ message_(
+ 'The example demonstrates rather a complex pipeline that consists of diffrerent '#13 +
+ 'converters, particularly, of the dash generator, marker generator, and of course, '#13 +
+ 'the stroke converter. There is also a converter that allows you to draw smooth '#13 +
+ 'curves based on polygons, see "Interpolation with Bezier Curves" on www.antigrain.com. '#13#13 +
+ 'How to play with:'#13#13 +
+ 'Use the left mouse in the corners of the triangle to move the particular vertices.'#13 +
+ 'Drag and move the whole picture with mouse or arrow keys.' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+VAR
+ app : the_application;
+
+BEGIN
+ app.Construct(pix_format_bgr24 ,flip_y );
+ app.caption_ ('AGG Example. Line Join (F1-Help)' );
+
+ if app.init(500 ,330 ,0 ) then
+ app.run;
+
+ app.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/conv_stroke.dpr b/src/corelib/render/software/agg-demos/conv_stroke.dpr
new file mode 100644
index 00000000..7b8af8e5
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/conv_stroke.dpr
@@ -0,0 +1,405 @@
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ conv_stroke_ ;
+
+uses
+ agg_basics ,
+ agg_platform_support ,
+
+ agg_color ,
+ agg_pixfmt ,
+ agg_pixfmt_rgb ,
+
+ agg_ctrl ,
+ agg_slider_ctrl ,
+ agg_rbox_ctrl ,
+ agg_cbox_ctrl ,
+
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_rasterizer_scanline_aa ,
+ agg_scanline ,
+ agg_scanline_u ,
+ agg_render_scanlines ,
+
+ agg_conv_stroke ,
+ agg_conv_dash ,
+ agg_conv_curve ,
+ agg_conv_contour ,
+ agg_conv_smooth_poly1 ,
+ agg_conv_marker ,
+ agg_arrowhead ,
+ agg_vcgen_markers_term ,
+ agg_math ,
+ agg_math_stroke ,
+ agg_path_storage ;
+
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+type
+ the_application = object(platform_support )
+ m_x ,
+ m_y : array[0..2 ] of double;
+ m_dx ,
+ m_dy : double;
+ m_idx : int;
+
+ m_join ,
+ m_cap : rbox_ctrl;
+
+ m_width ,
+ m_miter_limit : slider_ctrl;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure on_draw; virtual;
+
+ procedure on_mouse_move (x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_up (x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_join.Construct (10.0 ,10.0 ,133.0 ,80.0 ,not flip_y_ );
+ m_cap.Construct (10.0 ,80.0 + 10.0 ,133.0 ,80.0 + 80.0 ,not flip_y_ );
+ m_width.Construct (130 + 10.0 ,10.0 + 4.0 ,500.0 - 10.0 ,10.0 + 8.0 + 4.0 ,not flip_y_ );
+ m_miter_limit.Construct(130 + 10.0 ,20.0 + 10.0 + 4.0 ,500.0 - 10.0 ,20.0 + 10.0 + 8.0 + 4.0 ,not flip_y_ );
+
+ m_idx:=-1;
+
+ m_x[0 ]:=57 + 100;
+ m_y[0 ]:=60;
+ m_x[1 ]:=369 + 100;
+ m_y[1 ]:=170;
+ m_x[2 ]:=143 + 100;
+ m_y[2 ]:=310;
+
+ add_ctrl(@m_join );
+
+ m_join.text_size_ (7.5 );
+ m_join.text_thickness_(1.0 );
+
+ m_join.add_item ('Miter Join' );
+ m_join.add_item ('Miter Join Revert' );
+ m_join.add_item ('Round Join' );
+ m_join.add_item ('Bevel Join' );
+ m_join.cur_item_(2 );
+
+ add_ctrl(@m_cap );
+
+ m_cap.add_item ('Butt Cap' );
+ m_cap.add_item ('Square Cap' );
+ m_cap.add_item ('Round Cap' );
+ m_cap.cur_item_(2 );
+
+ add_ctrl(@m_width );
+
+ m_width.range_(3.0 ,40.0 );
+ m_width.value_(20.0 );
+ m_width.label_('Width=%1.2f' );
+
+ add_ctrl(@m_miter_limit );
+
+ m_miter_limit.range_(1.0 ,10.0 );
+ m_miter_limit.value_(4.0 );
+ m_miter_limit.label_('Miter Limit=%1.2f' );
+
+ m_join.no_transform;
+ m_cap.no_transform;
+ m_width.no_transform;
+ m_miter_limit.no_transform;
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_join.Destruct;
+ m_cap.Destruct;
+ m_width.Destruct;
+ m_miter_limit.Destruct;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ pixf : pixel_formats;
+ rgba : aggclr;
+ renb : renderer_base;
+ ren : renderer_scanline_aa_solid;
+ ras : rasterizer_scanline_aa;
+ sl : scanline_u8;
+
+ cap ,
+ join : unsigned;
+ path : path_storage;
+
+ stroke ,
+ poly1 ,
+ poly2 : conv_stroke;
+
+ poly2_dash : conv_dash;
+
+begin
+// Initialize structures
+ pixfmt_bgr24(pixf ,rbuf_window );
+
+ renb.Construct(@pixf );
+ ren.Construct (@renb );
+
+ rgba.ConstrDbl(1 ,1 ,1 );
+ renb.clear (@rgba );
+
+ ras.Construct;
+ sl.Construct;
+
+// Render
+ path.Construct;
+
+ path.move_to(m_x[0 ] ,m_y[0 ] );
+ path.line_to((m_x[0 ] + m_x[1 ] ) / 2 ,(m_y[0 ] + m_y[1 ] ) / 2 ); // This point is added only to check for numerical stability
+ path.line_to(m_x[1 ] ,m_y[1 ] );
+ path.line_to(m_x[2 ] ,m_y[2 ] );
+ path.line_to(m_x[2 ] ,m_y[2 ] ); // This point is added only to check for numerical stability
+
+ path.move_to((m_x[0 ] + m_x[1 ] ) / 2 ,(m_y[0 ] + m_y[1 ] ) / 2 );
+ path.line_to((m_x[1 ] + m_x[2 ] ) / 2 ,(m_y[1 ] + m_y[2 ] ) / 2 );
+ path.line_to((m_x[2 ] + m_x[0 ] ) / 2 ,(m_y[2 ] + m_y[0 ] ) / 2 );
+ path.close_polygon;
+
+ cap:=butt_cap;
+
+ if m_cap._cur_item = 1 then
+ cap:=square_cap;
+
+ if m_cap._cur_item = 2 then
+ cap:=round_cap;
+
+ join:=miter_join;
+
+ if m_join._cur_item = 1 then
+ join:=miter_join_revert;
+
+ if m_join._cur_item = 2 then
+ join:=round_join;
+
+ if m_join._cur_item = 3 then
+ join:=bevel_join;
+
+// (1)
+ stroke.Construct (@path );
+ stroke.line_join_ (join );
+ stroke.line_cap_ (cap );
+ stroke.miter_limit_(m_miter_limit._value );
+ stroke.width_ (m_width._value );
+
+ ras.add_path (@stroke );
+ rgba.ConstrDbl (0.8 ,0.7 ,0.6 );
+ ren.color_ (@rgba );
+ render_scanlines(@ras ,@sl ,@ren );
+
+// (2)
+ poly1.Construct (@path );
+ poly1.width_ (1.5 );
+ ras.add_path (@poly1 );
+ rgba.ConstrDbl (0 ,0 ,0 );
+ ren.color_ (@rgba );
+ render_scanlines(@ras ,@sl ,@ren );
+
+// (3)
+ poly2_dash.Construct(@stroke );
+ poly2.Construct (@poly2_dash );
+ poly2.miter_limit_ (4.0 );
+ poly2.width_ (m_width._value / 5.0 );
+ poly2.line_cap_ (cap );
+ poly2.line_join_ (join );
+ poly2_dash.add_dash (20.0 ,m_width._value / 2.5 );
+
+ ras.add_path (@poly2 );
+ rgba.ConstrDbl (0 ,0 ,0.3 );
+ ren.color_ (@rgba );
+ render_scanlines(@ras ,@sl ,@ren );
+
+// (4)
+ ras.add_path (@path );
+ rgba.ConstrDbl (0.0 ,0.0 ,0.0 ,0.2 );
+ ren.color_ (@rgba );
+ render_scanlines(@ras ,@sl ,@ren );
+
+// Render the controls
+ render_ctrl(@ras ,@sl ,@ren ,@m_join );
+ render_ctrl(@ras ,@sl ,@ren ,@m_cap );
+ render_ctrl(@ras ,@sl ,@ren ,@m_width );
+ render_ctrl(@ras ,@sl ,@ren ,@m_miter_limit );
+
+// Free AGG resources
+ ras.Destruct;
+ sl.Destruct;
+
+ path.Destruct;
+ stroke.Destruct;
+ poly1.Destruct;
+ poly2_dash.Destruct;
+ poly2.Destruct;
+
+end;
+
+{ ON_MOUSE_MOVE }
+procedure the_application.on_mouse_move;
+var
+ dx ,dy : double;
+
+begin
+ if flags and mouse_left <> 0 then
+ begin
+ if m_idx = 3 then
+ begin
+ dx:=x - m_dx;
+ dy:=y - m_dy;
+
+ m_x[1 ]:=m_x[1 ] - (m_x[0 ] - dx );
+ m_y[1 ]:=m_y[1 ] - (m_y[0 ] - dy );
+ m_x[2 ]:=m_x[2 ] - (m_x[0 ] - dx );
+ m_y[2 ]:=m_y[2 ] - (m_y[0 ] - dy );
+
+ m_x[0 ]:=dx;
+ m_y[0 ]:=dy;
+
+ force_redraw;
+
+ exit;
+
+ end;
+
+ if m_idx >= 0 then
+ begin
+ m_x[m_idx ]:=x - m_dx;
+ m_y[m_idx ]:=y - m_dy;
+
+ force_redraw;
+
+ end;
+
+ end
+ else
+ on_mouse_button_up(x ,y ,flags );
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure the_application.on_mouse_button_down;
+var
+ i : unsigned;
+
+begin
+ if flags and mouse_left <> 0 then
+ begin
+ i:=0;
+
+ while i < 3 do
+ begin
+ if Sqrt((x - m_x[i ] ) * (x - m_x[i ] ) + (y - m_y[i ] ) * (y - m_y[i ] ) ) < 20.0 then
+ begin
+ m_dx :=x - m_x[i ];
+ m_dy :=y - m_y[i ];
+ m_idx:=i;
+
+ break;
+
+ end;
+
+ inc(i );
+
+ end;
+
+ if i = 3 then
+ if point_in_triangle(
+ m_x[0 ] ,m_y[0 ] ,
+ m_x[1 ] ,m_y[1 ] ,
+ m_x[2 ] ,m_y[2 ] ,x ,y ) then
+ begin
+ m_dx :=x - m_x[0 ];
+ m_dy :=y - m_y[0 ];
+ m_idx:=3;
+
+ end;
+
+ end;
+
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+procedure the_application.on_mouse_button_up;
+begin
+ m_idx:=-1;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+var
+ dx ,dy : double;
+
+begin
+ dx:=0;
+ dy:=0;
+
+ case key of
+ key_left : dx:=-0.1;
+ key_right : dx:= 0.1;
+ key_up : dy:= 0.1;
+ key_down : dy:=-0.1;
+
+ end;
+
+ m_x[0 ]:=m_x[0 ] + dx;
+ m_y[0 ]:=m_y[0 ] + dy;
+ m_x[1 ]:=m_x[1 ] + dx;
+ m_y[1 ]:=m_y[1 ] + dy;
+
+ force_redraw;
+
+ if key = key_f1 then
+ message_(
+ 'Another example that demonstrates the power of the custom pipeline concept. '#13 +
+ 'First, we calculate a thick outline (stroke), then generate dashes, and then, '#13 +
+ 'calculate the outlines (strokes) of the dashes again.'#13#13 +
+ 'How to play with:'#13#13 +
+ 'Use the left mouse in the corners of the triangle to move the particular vertices.'#13 +
+ 'Drag and move the whole picture with mouse or arrow keys.' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+VAR
+ app : the_application;
+
+BEGIN
+ app.Construct(pix_format_bgr24 ,flip_y );
+ app.caption_ ('AGG Example. Line Join (F1-Help)' );
+
+ if app.init(500 ,330 ,0 ) then
+ app.run;
+
+ app.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/distortions.dpr b/src/corelib/render/software/agg-demos/distortions.dpr
new file mode 100644
index 00000000..ca0db012
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/distortions.dpr
@@ -0,0 +1,913 @@
+{mac_copy:spheres.bmp}
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ distortions ;
+
+uses
+ SysUtils ,
+
+ agg_basics ,
+ agg_platform_support ,
+
+ agg_color ,
+ agg_pixfmt ,
+ agg_pixfmt_rgb ,
+
+ agg_ctrl ,
+ agg_rbox_ctrl ,
+ agg_slider_ctrl ,
+
+ agg_rendering_buffer ,
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_rasterizer_scanline_aa ,
+ agg_scanline ,
+ agg_scanline_u ,
+ agg_render_scanlines ,
+
+ agg_array ,
+ agg_ellipse ,
+ agg_trans_affine ,
+ agg_conv_transform ,
+ agg_image_filters ,
+ agg_span_allocator ,
+ agg_span_image_filter ,
+ agg_span_image_filter_rgb ,
+ agg_span_interpolator_linear ,
+ agg_span_interpolator_adaptor ,
+ agg_span_gradient ,
+ file_utils_ ;
+
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+ g_gradient_colors : array[0..1023 ] of int8u = (
+
+ 255, 255, 255, 255,
+ 255, 255, 254, 255,
+ 255, 255, 254, 255,
+ 255, 255, 254, 255,
+ 255, 255, 253, 255,
+ 255, 255, 253, 255,
+ 255, 255, 252, 255,
+ 255, 255, 251, 255,
+ 255, 255, 250, 255,
+ 255, 255, 248, 255,
+ 255, 255, 246, 255,
+ 255, 255, 244, 255,
+ 255, 255, 241, 255,
+ 255, 255, 238, 255,
+ 255, 255, 235, 255,
+ 255, 255, 231, 255,
+ 255, 255, 227, 255,
+ 255, 255, 222, 255,
+ 255, 255, 217, 255,
+ 255, 255, 211, 255,
+ 255, 255, 206, 255,
+ 255, 255, 200, 255,
+ 255, 254, 194, 255,
+ 255, 253, 188, 255,
+ 255, 252, 182, 255,
+ 255, 250, 176, 255,
+ 255, 249, 170, 255,
+ 255, 247, 164, 255,
+ 255, 246, 158, 255,
+ 255, 244, 152, 255,
+ 254, 242, 146, 255,
+ 254, 240, 141, 255,
+ 254, 238, 136, 255,
+ 254, 236, 131, 255,
+ 253, 234, 126, 255,
+ 253, 232, 121, 255,
+ 253, 229, 116, 255,
+ 252, 227, 112, 255,
+ 252, 224, 108, 255,
+ 251, 222, 104, 255,
+ 251, 219, 100, 255,
+ 251, 216, 96, 255,
+ 250, 214, 93, 255,
+ 250, 211, 89, 255,
+ 249, 208, 86, 255,
+ 249, 205, 83, 255,
+ 248, 202, 80, 255,
+ 247, 199, 77, 255,
+ 247, 196, 74, 255,
+ 246, 193, 72, 255,
+ 246, 190, 69, 255,
+ 245, 187, 67, 255,
+ 244, 183, 64, 255,
+ 244, 180, 62, 255,
+ 243, 177, 60, 255,
+ 242, 174, 58, 255,
+ 242, 170, 56, 255,
+ 241, 167, 54, 255,
+ 240, 164, 52, 255,
+ 239, 161, 51, 255,
+ 239, 157, 49, 255,
+ 238, 154, 47, 255,
+ 237, 151, 46, 255,
+ 236, 147, 44, 255,
+ 235, 144, 43, 255,
+ 235, 141, 41, 255,
+ 234, 138, 40, 255,
+ 233, 134, 39, 255,
+ 232, 131, 37, 255,
+ 231, 128, 36, 255,
+ 230, 125, 35, 255,
+ 229, 122, 34, 255,
+ 228, 119, 33, 255,
+ 227, 116, 31, 255,
+ 226, 113, 30, 255,
+ 225, 110, 29, 255,
+ 224, 107, 28, 255,
+ 223, 104, 27, 255,
+ 222, 101, 26, 255,
+ 221, 99, 25, 255,
+ 220, 96, 24, 255,
+ 219, 93, 23, 255,
+ 218, 91, 22, 255,
+ 217, 88, 21, 255,
+ 216, 86, 20, 255,
+ 215, 83, 19, 255,
+ 214, 81, 18, 255,
+ 213, 79, 17, 255,
+ 212, 77, 17, 255,
+ 211, 74, 16, 255,
+ 210, 72, 15, 255,
+ 209, 70, 14, 255,
+ 207, 68, 13, 255,
+ 206, 66, 13, 255,
+ 205, 64, 12, 255,
+ 204, 62, 11, 255,
+ 203, 60, 10, 255,
+ 202, 58, 10, 255,
+ 201, 56, 9, 255,
+ 199, 55, 9, 255,
+ 198, 53, 8, 255,
+ 197, 51, 7, 255,
+ 196, 50, 7, 255,
+ 195, 48, 6, 255,
+ 193, 46, 6, 255,
+ 192, 45, 5, 255,
+ 191, 43, 5, 255,
+ 190, 42, 4, 255,
+ 188, 41, 4, 255,
+ 187, 39, 3, 255,
+ 186, 38, 3, 255,
+ 185, 37, 2, 255,
+ 183, 35, 2, 255,
+ 182, 34, 1, 255,
+ 181, 33, 1, 255,
+ 179, 32, 1, 255,
+ 178, 30, 0, 255,
+ 177, 29, 0, 255,
+ 175, 28, 0, 255,
+ 174, 27, 0, 255,
+ 173, 26, 0, 255,
+ 171, 25, 0, 255,
+ 170, 24, 0, 255,
+ 168, 23, 0, 255,
+ 167, 22, 0, 255,
+ 165, 21, 0, 255,
+ 164, 21, 0, 255,
+ 163, 20, 0, 255,
+ 161, 19, 0, 255,
+ 160, 18, 0, 255,
+ 158, 17, 0, 255,
+ 156, 17, 0, 255,
+ 155, 16, 0, 255,
+ 153, 15, 0, 255,
+ 152, 14, 0, 255,
+ 150, 14, 0, 255,
+ 149, 13, 0, 255,
+ 147, 12, 0, 255,
+ 145, 12, 0, 255,
+ 144, 11, 0, 255,
+ 142, 11, 0, 255,
+ 140, 10, 0, 255,
+ 139, 10, 0, 255,
+ 137, 9, 0, 255,
+ 135, 9, 0, 255,
+ 134, 8, 0, 255,
+ 132, 8, 0, 255,
+ 130, 7, 0, 255,
+ 128, 7, 0, 255,
+ 126, 6, 0, 255,
+ 125, 6, 0, 255,
+ 123, 5, 0, 255,
+ 121, 5, 0, 255,
+ 119, 4, 0, 255,
+ 117, 4, 0, 255,
+ 115, 4, 0, 255,
+ 113, 3, 0, 255,
+ 111, 3, 0, 255,
+ 109, 2, 0, 255,
+ 107, 2, 0, 255,
+ 105, 2, 0, 255,
+ 103, 1, 0, 255,
+ 101, 1, 0, 255,
+ 99, 1, 0, 255,
+ 97, 0, 0, 255,
+ 95, 0, 0, 255,
+ 93, 0, 0, 255,
+ 91, 0, 0, 255,
+ 90, 0, 0, 255,
+ 88, 0, 0, 255,
+ 86, 0, 0, 255,
+ 84, 0, 0, 255,
+ 82, 0, 0, 255,
+ 80, 0, 0, 255,
+ 78, 0, 0, 255,
+ 77, 0, 0, 255,
+ 75, 0, 0, 255,
+ 73, 0, 0, 255,
+ 72, 0, 0, 255,
+ 70, 0, 0, 255,
+ 68, 0, 0, 255,
+ 67, 0, 0, 255,
+ 65, 0, 0, 255,
+ 64, 0, 0, 255,
+ 63, 0, 0, 255,
+ 61, 0, 0, 255,
+ 60, 0, 0, 255,
+ 59, 0, 0, 255,
+ 58, 0, 0, 255,
+ 57, 0, 0, 255,
+ 56, 0, 0, 255,
+ 55, 0, 0, 255,
+ 54, 0, 0, 255,
+ 53, 0, 0, 255,
+ 53, 0, 0, 255,
+ 52, 0, 0, 255,
+ 52, 0, 0, 255,
+ 51, 0, 0, 255,
+ 51, 0, 0, 255,
+ 51, 0, 0, 255,
+ 50, 0, 0, 255,
+ 50, 0, 0, 255,
+ 51, 0, 0, 255,
+ 51, 0, 0, 255,
+ 51, 0, 0, 255,
+ 51, 0, 0, 255,
+ 52, 0, 0, 255,
+ 52, 0, 0, 255,
+ 53, 0, 0, 255,
+ 54, 1, 0, 255,
+ 55, 2, 0, 255,
+ 56, 3, 0, 255,
+ 57, 4, 0, 255,
+ 58, 5, 0, 255,
+ 59, 6, 0, 255,
+ 60, 7, 0, 255,
+ 62, 8, 0, 255,
+ 63, 9, 0, 255,
+ 64, 11, 0, 255,
+ 66, 12, 0, 255,
+ 68, 13, 0, 255,
+ 69, 14, 0, 255,
+ 71, 16, 0, 255,
+ 73, 17, 0, 255,
+ 75, 18, 0, 255,
+ 77, 20, 0, 255,
+ 79, 21, 0, 255,
+ 81, 23, 0, 255,
+ 83, 24, 0, 255,
+ 85, 26, 0, 255,
+ 87, 28, 0, 255,
+ 90, 29, 0, 255,
+ 92, 31, 0, 255,
+ 94, 33, 0, 255,
+ 97, 34, 0, 255,
+ 99, 36, 0, 255,
+ 102, 38, 0, 255,
+ 104, 40, 0, 255,
+ 107, 41, 0, 255,
+ 109, 43, 0, 255,
+ 112, 45, 0, 255,
+ 115, 47, 0, 255,
+ 117, 49, 0, 255,
+ 120, 51, 0, 255,
+ 123, 52, 0, 255,
+ 126, 54, 0, 255,
+ 128, 56, 0, 255,
+ 131, 58, 0, 255,
+ 134, 60, 0, 255,
+ 137, 62, 0, 255,
+ 140, 64, 0, 255,
+ 143, 66, 0, 255,
+ 145, 68, 0, 255,
+ 148, 70, 0, 255,
+ 151, 72, 0, 255,
+ 154, 74, 0, 255 );
+
+type
+ periodic_distortion_ptr = ^periodic_distortion;
+ periodic_distortion = object(distortion )
+ m_cx ,
+ m_cy ,
+ m_period ,
+ m_amplitude ,
+ m_phase : double;
+
+ constructor Construct;
+
+ procedure center (x ,y : double );
+ procedure period (v : double );
+ procedure amplitude(v : double );
+ procedure phase (v : double );
+
+ end;
+
+ distortion_wave = object(periodic_distortion )
+ procedure calculate(x ,y : int_ptr ); virtual;
+
+ end;
+
+ distortion_swirl = object(periodic_distortion )
+ procedure calculate(x ,y : int_ptr ); virtual;
+
+ end;
+
+ distortion_swirl_wave = object(periodic_distortion )
+ procedure calculate(x ,y : int_ptr ); virtual;
+
+ end;
+
+ distortion_wave_swirl = object(periodic_distortion )
+ procedure calculate(x ,y : int_ptr ); virtual;
+
+ end;
+
+ the_application = object(platform_support )
+ m_angle ,
+ m_scale ,
+ m_amplitude ,
+ m_period : slider_ctrl;
+ m_distortion : rbox_ctrl;
+
+ m_center_x ,
+ m_center_y ,
+ m_phase : double;
+
+ m_gradient_colors : pod_auto_array;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure on_init; virtual;
+ procedure on_draw; virtual;
+
+ procedure on_mouse_move (x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_idle; virtual;
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ calculate_wave }
+procedure calculate_wave(x ,y : int_ptr; cx ,cy ,period ,amplitude ,phase : double );
+var
+ xd ,yd ,d ,a : double;
+
+begin
+ xd:=x^ / image_subpixel_size - cx;
+ yd:=y^ / image_subpixel_size - cy;
+ d :=Sqrt(xd * xd + yd * yd );
+
+ if d > 1 then
+ begin
+ a :=Cos(d / (16.0 * period ) - phase ) * (1.0 / (amplitude * d ) ) + 1.0;
+ x^:=trunc((xd * a + cx ) * image_subpixel_size );
+ y^:=trunc((yd * a + cy ) * image_subpixel_size );
+
+ end;
+
+end;
+
+{ calculate_swirl }
+procedure calculate_swirl(x ,y : int_ptr; cx ,cy ,amplitude ,phase : double );
+var
+ xd ,yd ,a ,sa ,ca : double;
+
+begin
+ xd:=x^ / image_subpixel_size - cx;
+ yd:=y^ / image_subpixel_size - cy;
+ a :=(100.0 - Sqrt(xd * xd + yd * yd ) ) / 100.0 * (0.1 / -amplitude );
+ sa:=Sin(a - phase / 25.0 );
+ ca:=Cos(a - phase / 25.0 );
+ x^:=trunc((xd * ca - yd * sa + cx ) * image_subpixel_size );
+ y^:=trunc((xd * sa + yd * ca + cy ) * image_subpixel_size );
+
+end;
+
+{ CONSTRUCT }
+constructor periodic_distortion.Construct;
+begin
+ m_cx :=0.0;
+ m_cy :=0.0;
+ m_period :=0.5;
+ m_amplitude:=0.5;
+ m_phase :=0.0;
+
+end;
+
+{ CENTER }
+procedure periodic_distortion.center;
+begin
+ m_cx:=x;
+ m_cy:=y;
+
+end;
+
+{ PERIOD }
+procedure periodic_distortion.period;
+begin
+ m_period:=v;
+
+end;
+
+{ AMPLITUDE }
+procedure periodic_distortion.amplitude;
+begin
+ m_amplitude:=1.0 / v;
+
+end;
+
+{ PHASE }
+procedure periodic_distortion.phase;
+begin
+ m_phase:=v;
+
+end;
+
+{ CALCULATE }
+procedure distortion_wave.calculate;
+begin
+ calculate_wave(x ,y ,m_cx ,m_cy ,m_period ,m_amplitude ,m_phase );
+
+end;
+
+{ CALCULATE }
+procedure distortion_swirl.calculate;
+begin
+ calculate_swirl(x ,y ,m_cx ,m_cy ,m_amplitude ,m_phase );
+
+end;
+
+{ CALCULATE }
+procedure distortion_swirl_wave.calculate;
+begin
+ calculate_swirl(x ,y ,m_cx ,m_cy ,m_amplitude ,m_phase );
+ calculate_wave (x ,y ,m_cx ,m_cy ,m_period ,m_amplitude ,m_phase );
+
+end;
+
+{ CALCULATE }
+procedure distortion_wave_swirl.calculate;
+begin
+ calculate_wave (x ,y ,m_cx ,m_cy ,m_period ,m_amplitude ,m_phase );
+ calculate_swirl(x ,y ,m_cx ,m_cy ,m_amplitude ,m_phase );
+
+end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+var
+ i : unsigned;
+ p : int8u_ptr;
+
+ rgba : aggclr;
+
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_gradient_colors.Construct(256 ,sizeof(aggclr ) );
+
+ m_angle.Construct (5 ,5 ,150 ,12 ,not flip_y_ );
+ m_scale.Construct (5 ,5 + 15 ,150 ,12 + 15 ,not flip_y_ );
+ m_period.Construct (5 + 170 ,5 ,150 + 170 ,12 ,not flip_y_ );
+ m_amplitude.Construct (5 + 170 ,5 + 15 ,150 + 170 ,12 + 15 ,not flip_y_ );
+ m_distortion.Construct(480 ,5 ,600 ,90 ,not flip_y_ );
+
+ m_center_x:=0.0;
+ m_center_y:=0.0;
+ m_phase :=0.0;
+
+ add_ctrl(@m_angle );
+ add_ctrl(@m_scale );
+ add_ctrl(@m_amplitude );
+ add_ctrl(@m_period );
+ add_ctrl(@m_distortion );
+
+ m_angle.label_('Angle=%3.2f' );
+ m_scale.label_('Scale=%3.2f' );
+ m_angle.range_(-180.0 ,180.0 );
+ m_angle.value_(20.0 );
+ m_scale.range_(0.1 ,5.0 );
+ m_scale.value_(1.0 );
+
+ m_amplitude.label_('Amplitude=%3.2f' );
+ m_period.label_ ('Period=%3.2f' );
+ m_amplitude.range_(0.1 ,40.0 );
+ m_period.range_ (0.1 ,2.0 );
+ m_amplitude.value_(10.0 );
+ m_period.value_ (1.0 );
+
+ m_distortion.add_item ('Wave' );
+ m_distortion.add_item ('Swirl' );
+ m_distortion.add_item ('Wave-Swirl' );
+ m_distortion.add_item ('Swirl-Wave' );
+ m_distortion.cur_item_(0 );
+
+ p:=@g_gradient_colors[0 ];
+
+ for i:=0 to 255 do
+ begin
+ rgba.ConstrInt(
+ int8u_ptr(ptrcomp(p ) + 0 * sizeof(int8u ) )^ ,
+ int8u_ptr(ptrcomp(p ) + 1 * sizeof(int8u ) )^ ,
+ int8u_ptr(ptrcomp(p ) + 2 * sizeof(int8u ) )^ ,
+ int8u_ptr(ptrcomp(p ) + 3 * sizeof(int8u ) )^ );
+
+ move(
+ rgba ,
+ m_gradient_colors.array_operator(i )^ ,
+ sizeof(aggclr ) );
+
+ inc(ptrcomp(p ) ,4 * sizeof(int8u ) );
+
+ end;
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_gradient_colors.Destruct;
+
+ m_angle.Destruct;
+ m_scale.Destruct;
+ m_period.Destruct;
+ m_amplitude.Destruct;
+ m_distortion.Destruct;
+
+end;
+
+{ ON_INIT }
+procedure the_application.on_init;
+begin
+ m_center_x:=rbuf_img(0 )._width / 2.0 + 10;
+ m_center_y:=rbuf_img(0 )._height / 2.0 + 10 + 40;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ img_width ,img_height ,cx ,cy ,r : double;
+
+ pixf : pixel_formats;
+ rgba : aggclr;
+
+ rb : renderer_base;
+ rs : renderer_scanline_aa_solid;
+ pf : rasterizer_scanline_aa;
+ sl : scanline_u8;
+ sa : span_allocator;
+ sg : span_image_filter_ptr;
+ fi : image_filter_spline36;
+ ri : renderer_scanline_aa;
+
+ filter : image_filter_ptr;
+
+ interpolator : span_interpolator_adaptor;
+
+ dist : periodic_distortion_ptr;
+ dist_wave : distortion_wave;
+ dist_swirl : distortion_swirl;
+ dist_wave_swirl : distortion_wave_swirl;
+ dist_swirl_wave : distortion_swirl_wave;
+
+ src_mtx ,img_mtx ,gr1_mtx ,gr2_mtx : trans_affine;
+
+ inv : trans_affine;
+ tat : trans_affine_translation;
+ tar : trans_affine_rotation;
+ tas : trans_affine_scaling;
+
+ ell : ellipse;
+ tr ,
+ tr2 : conv_transform;
+
+ gradient_function : gradient_circle;
+ span_gradient_ : span_gradient;
+
+ rg : renderer_scanline_aa;
+
+begin
+ sg :=NIL;
+ filter:=NIL;
+
+// Initialize structures
+ img_width :=rbuf_img(0 )._width;
+ img_height:=rbuf_img(0 )._height;
+
+ pixfmt_bgr24(pixf ,rbuf_window );
+
+ rb.Construct(@pixf );
+ rs.Construct(@rb );
+
+ rgba.ConstrDbl(1.0 ,1.0 ,1.0 );
+ rb.clear (@rgba );
+
+ src_mtx.Construct;
+
+ tat.Construct(-img_width / 2 ,-img_height / 2 ); src_mtx.multiply(@tat );
+ tar.Construct(m_angle._value * pi / 180.0 ); src_mtx.multiply(@tar );
+ tat.Construct(img_width / 2 + 10 ,img_height / 2 + 10 + 40 ); src_mtx.multiply(@tat );
+
+ src_mtx.multiply(_trans_affine_resizing );
+
+ img_mtx.Construct;
+
+ tat.Construct(-img_width / 2 ,-img_height / 2 ); img_mtx.multiply(@tat );
+ tar.Construct(m_angle._value * pi / 180.0); img_mtx.multiply(@tar );
+ tas.Construct(m_scale._value ); img_mtx.multiply(@tas );
+ tat.Construct(img_width / 2 + 10 ,img_height / 2 + 10 + 40 ); img_mtx.multiply(@tat );
+
+ img_mtx.multiply(_trans_affine_resizing );
+ img_mtx.invert;
+
+ sa.Construct;
+
+ dist:=NIL;
+
+ dist_wave.Construct;
+ dist_swirl.Construct;
+ dist_wave_swirl.Construct;
+ dist_swirl_wave.Construct;
+
+ case m_distortion._cur_item of
+ 0 : dist:=@dist_wave;
+ 1 : dist:=@dist_swirl;
+ 2 : dist:=@dist_wave_swirl;
+ 3 : dist:=@dist_swirl_wave;
+
+ end;
+
+ dist.period (m_period._value );
+ dist.amplitude(m_amplitude._value );
+ dist.phase (m_phase );
+
+ cx:=m_center_x;
+ cy:=m_center_y;
+
+ img_mtx.transform(@img_mtx ,@cx ,@cy );
+
+ dist.center(cx ,cy );
+
+ interpolator.Construct(@img_mtx ,dist );
+
+ rgba.ConstrDbl(1 ,1 ,1 ,0 );
+
+// Version without filtering (nearest neighbor)
+{ sg:=new(
+ span_image_filter_rgb_nn_ptr ,
+ Construct(
+ @sa ,rbuf_img(0 ) ,@rgba ,@interpolator ,bgr_order ) );{}
+
+// Version with "hardcoded" bilinear filter
+ sg:=new(
+ span_image_filter_rgb_bilinear_ptr ,
+ Construct(
+ @sa ,rbuf_img(0 ) ,@rgba ,@interpolator ,bgr_order ) );{}
+
+// Version with arbitrary filter
+{ fi.Construct;
+
+ new(filter ,Construct(@fi ) );
+
+ sg:=new(
+ span_image_filter_rgb_ptr ,
+ Construct(
+ @sa ,rbuf_img(0 ) ,@rgba ,@interpolator ,filter ,bgr_order ) );{}
+
+// Render
+ ri.Construct(@rb ,sg );
+ pf.Construct;
+ sl.Construct;
+
+ r:=img_width;
+
+ if img_height < r then
+ r:=img_height;
+
+ ell.Construct(
+ img_width / 2.0 ,img_height / 2.0 ,
+ r / 2.0 - 20.0 ,r / 2.0 - 20.0 ,200 );
+
+ tr.Construct(@ell ,@src_mtx );
+
+ pf.add_path (@tr );
+ render_scanlines(@pf ,@sl ,@ri );
+
+ inv.Construct;
+
+ inv.assign(_trans_affine_resizing );
+
+ inv.invert;
+
+ src_mtx.multiply(@inv );
+
+ tat.Construct(img_width - img_width / 10 ,0.0 ); src_mtx.multiply(@tat );
+
+ src_mtx.multiply(_trans_affine_resizing );
+
+ pf.add_path (@tr );
+ rgba.ConstrInt (0 ,0 ,0 );
+ rs.color_ (@rgba );
+ render_scanlines(@pf ,@sl ,@rs );
+
+ gradient_function.Construct;
+ span_gradient_.Construct(
+ @sa ,@interpolator ,@gradient_function ,@m_gradient_colors ,0 ,180 );
+
+ rg.Construct(@rb ,@span_gradient_ );
+
+ gr1_mtx.Construct;
+
+ tat.Construct(-img_width / 2 ,-img_height / 2 ); gr1_mtx.multiply(@tat );
+ tas.Construct(0.8 ); gr1_mtx.multiply(@tas );
+ tar.Construct(m_angle._value * pi / 180.0 ); gr1_mtx.multiply(@tar );
+ tat.Construct(img_width - img_width / 10 + img_width / 2 + 10 ,img_height / 2 + 10 + 40 ); gr1_mtx.multiply(@tat );
+
+ gr1_mtx.multiply(_trans_affine_resizing );
+
+ gr2_mtx.Construct;
+
+ tar.Construct(m_angle._value * pi / 180.0 ); gr2_mtx.multiply(@tar );
+ tas.Construct(m_scale._value ); gr2_mtx.multiply(@tas );
+ tat.Construct(img_width - img_width / 10 + img_width / 2 + 10 + 50 ,img_height / 2 + 10 + 40 + 50 ); gr2_mtx.multiply(@tat );
+
+ gr2_mtx.multiply(_trans_affine_resizing );
+ gr2_mtx.invert;
+
+ cx:=m_center_x + img_width - img_width / 10;
+ cy:=m_center_y;
+
+ gr2_mtx.transform(@gr2_mtx ,@cx ,@cy );
+
+ dist.center(cx ,cy );
+
+ interpolator.transformer_(@gr2_mtx );
+
+ tr2.Construct(@ell ,@gr1_mtx );
+
+ pf.add_path (@tr2 );
+ render_scanlines(@pf ,@sl ,@rg );
+
+// Render the controls
+ render_ctrl(@pf ,@sl ,@rs ,@m_angle );
+ render_ctrl(@pf ,@sl ,@rs ,@m_scale );
+ render_ctrl(@pf ,@sl ,@rs ,@m_amplitude );
+ render_ctrl(@pf ,@sl ,@rs ,@m_period );
+ render_ctrl(@pf ,@sl ,@rs ,@m_distortion );
+
+// Free AGG resources
+ pf.Destruct;
+ sl.Destruct;
+ sa.Destruct;
+
+ if sg <> NIL then
+ dispose(sg ,Destruct );
+
+ if filter <> NIL then
+ dispose(filter ,Destruct );
+
+end;
+
+{ ON_MOUSE_MOVE }
+procedure the_application.on_mouse_move;
+begin
+ if flags and 1 <> 0 then
+ begin
+ m_center_x:=x;
+ m_center_y:=y;
+
+ force_redraw;
+
+ end;
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure the_application.on_mouse_button_down;
+begin
+ if flags <> 0 then
+ begin
+ m_center_x:=x;
+ m_center_y:=y;
+
+ force_redraw;
+
+ end;
+
+end;
+
+{ ON_IDLE }
+procedure the_application.on_idle;
+begin
+ m_phase:=m_phase + (15.0 * pi / 180.0 );
+
+ if m_phase > pi * 200.0 then
+ m_phase:=m_phase - (pi * 200.0 );
+
+ force_redraw;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ 'To transform an image as well as to define a color gradient you have to write '#13 +
+ 'several declarations. This approach can seem difficult to handle (compared with '#13 +
+ 'one function call), but it''s very flexible. For example, you can add an arbitrary '#13 +
+ 'distortion function. This mechanism is pretty much the same in image transformers '#13 +
+ 'and color gradients.'#13#13 +
+ 'How to play with:'#13#13 +
+ 'Try changing different parameters of the distortions.'#13 +
+ 'Use any mouse button to move the distortion''s epicentre.' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+VAR
+ app : the_application;
+ buf : array [0..255 ] of char;
+ ext : string[10 ];
+
+ img_name ,p ,n ,x : shortstring;
+
+BEGIN
+ app.Construct(pix_format_bgr24 ,flip_y );
+ app.caption_ ('Image and Gradient Distortions (F1-Help)' );
+
+ img_name:='spheres';
+
+{$IFDEF WIN32 }
+ if ParamCount > 0 then
+ begin
+ spread_name(ParamStr(1 ) ,p ,n ,x );
+
+ img_name:=fold_name(p ,n ,'' );
+
+ end;
+
+{$ENDIF }
+
+ if not app.load_img(0 ,img_name ) then
+ begin
+ img_name:=img_name + #0;
+ ext :=app._img_ext + #0;
+
+ if img_name = 'spheres'#0 then
+ begin
+ sprintf(@buf[0 ] ,'File not found: %s' ,ptrcomp(@img_name[1 ] ) );
+ sprintf(@buf[StrLen(@buf ) ] ,'%s. '#13'Download http://www.antigrain.com/' ,ptrcomp(@ext[1 ] ) );
+ sprintf(@buf[StrLen(@buf ) ] ,'%s' ,ptrcomp(@img_name[1 ] ) );
+ sprintf(@buf[StrLen(@buf ) ] ,'%s'#13'or copy it from another directory if available.' ,ptrcomp(@ext[1 ] ) );
+
+ end
+ else
+ begin
+ sprintf(@buf[0 ] ,'File not found: %s' ,ptrcomp(@img_name[1 ] ) );
+ sprintf(@buf[StrLen(@buf ) ] ,'%s' ,ptrcomp(@ext[1 ] ) );
+
+ end;
+
+ app.message_(@buf[0 ] );
+
+ end
+ else
+ if app.init(app.rbuf_img(0 )._width + 300 ,app.rbuf_img(0 )._height + 40 + 20 ,window_resize ) then
+ begin
+ app.wait_mode_(false );
+ app.run;
+
+ end;
+
+ app.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/expat-pas/ascii.inc b/src/corelib/render/software/agg-demos/expat-pas/ascii.inc
new file mode 100755
index 00000000..a0abb31e
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/expat-pas/ascii.inc
@@ -0,0 +1,116 @@
+//----------------------------------------------------------------------------
+// Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
+// and Clark Cooper
+// Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006 Expat maintainers.
+//
+// Expat - Version 2.0.0 Release Milano 0.83 (PasExpat 2.0.0 RM0.83)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.pasports.org/pasexpat
+// Copyright (c) 2006
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 17.05.2006-Milano: Unit port establishment
+//
+{ ascii.inc }
+ ASCII_A = char($41 );
+ ASCII_B = char($42 );
+ ASCII_C = char($43 );
+ ASCII_D = char($44 );
+ ASCII_E = char($45 );
+ ASCII_F = char($46 );
+ ASCII_G = char($47 );
+ ASCII_H = char($48 );
+ ASCII_I = char($49 );
+ ASCII_J = char($4A );
+ ASCII_K = char($4B );
+ ASCII_L = char($4C );
+ ASCII_M = char($4D );
+ ASCII_N = char($4E );
+ ASCII_O = char($4F );
+ ASCII_P = char($50 );
+ ASCII_Q = char($51 );
+ ASCII_R = char($52 );
+ ASCII_S = char($53 );
+ ASCII_T = char($54 );
+ ASCII_U = char($55 );
+ ASCII_V = char($56 );
+ ASCII_W = char($57 );
+ ASCII_X = char($58 );
+ ASCII_Y = char($59 );
+ ASCII_Z = char($5A );
+
+ ASCII_al = char($61 );
+ ASCII_bl = char($62 );
+ ASCII_cl = char($63 );
+ ASCII_dl = char($64 );
+ ASCII_el = char($65 );
+ ASCII_fl = char($66 );
+ ASCII_gl = char($67 );
+ ASCII_hl = char($68 );
+ ASCII_il = char($69 );
+ ASCII_jl = char($6A );
+ ASCII_kl = char($6B );
+ ASCII_ll = char($6C );
+ ASCII_ml = char($6D );
+ ASCII_nl = char($6E );
+ ASCII_ol = char($6F );
+ ASCII_pl = char($70 );
+ ASCII_ql = char($71 );
+ ASCII_rl = char($72 );
+ ASCII_sl = char($73 );
+ ASCII_tl = char($74 );
+ ASCII_ul = char($75 );
+ ASCII_vl = char($76 );
+ ASCII_wl = char($77 );
+ ASCII_xl = char($78 );
+ ASCII_yl = char($79 );
+ ASCII_zl = char($7A );
+
+ ASCII_0 = char($30 );
+ ASCII_1 = char($31 );
+ ASCII_2 = char($32 );
+ ASCII_3 = char($33 );
+ ASCII_4 = char($34 );
+ ASCII_5 = char($35 );
+ ASCII_6 = char($36 );
+ ASCII_7 = char($37 );
+ ASCII_8 = char($38 );
+ ASCII_9 = char($39 );
+
+ ASCII_TAB = char($09 );
+ ASCII_SPACE = char($20 );
+ ASCII_EXCL = char($21 );
+ ASCII_QUOT = char($22 );
+ ASCII_AMP = char($26 );
+ ASCII_APOS = char($27 );
+ ASCII_MINUS = char($2D );
+ ASCII_PERIOD = char($2E );
+ ASCII_COLON = char($3A );
+ ASCII_SEMI = char($3B );
+ ASCII_LT = char($3C );
+ ASCII_EQUALS = char($3D );
+ ASCII_GT = char($3E );
+ ASCII_LSQB = char($5B );
+ ASCII_RSQB = char($5D );
+ ASCII_UNDERSCORE = char($5F );
diff --git a/src/corelib/render/software/agg-demos/expat-pas/asciitab.inc b/src/corelib/render/software/agg-demos/expat-pas/asciitab.inc
new file mode 100755
index 00000000..ca3bec48
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/expat-pas/asciitab.inc
@@ -0,0 +1,67 @@
+//----------------------------------------------------------------------------
+// Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
+// and Clark Cooper
+// Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006 Expat maintainers.
+//
+// Expat - Version 2.0.0 Release Milano 0.83 (PasExpat 2.0.0 RM0.83)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.pasports.org/pasexpat
+// Copyright (c) 2006
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 11.06.2006-Milano: Unit port establishment
+//
+{ asciitab.inc }
+{ $00 } BT_NONXML ,BT_NONXML ,BT_NONXML ,BT_NONXML ,
+{ $04 } BT_NONXML ,BT_NONXML ,BT_NONXML ,BT_NONXML ,
+{ $08 } BT_NONXML ,BT_S ,BT_LF ,BT_NONXML ,
+{ $0C } BT_NONXML ,BT_CR ,BT_NONXML ,BT_NONXML ,
+{ $10 } BT_NONXML ,BT_NONXML ,BT_NONXML ,BT_NONXML ,
+{ $14 } BT_NONXML ,BT_NONXML ,BT_NONXML ,BT_NONXML ,
+{ $18 } BT_NONXML ,BT_NONXML ,BT_NONXML ,BT_NONXML ,
+{ $1C } BT_NONXML ,BT_NONXML ,BT_NONXML ,BT_NONXML ,
+{ $20 } BT_S ,BT_EXCL ,BT_QUOT ,BT_NUM ,
+{ $24 } BT_OTHER ,BT_PERCNT ,BT_AMP ,BT_APOS ,
+{ $28 } BT_LPAR ,BT_RPAR ,BT_AST ,BT_PLUS ,
+{ $2C } BT_COMMA ,BT_MINUS ,BT_NAME ,BT_SOL ,
+{ $30 } BT_DIGIT ,BT_DIGIT ,BT_DIGIT ,BT_DIGIT ,
+{ $34 } BT_DIGIT ,BT_DIGIT ,BT_DIGIT ,BT_DIGIT ,
+{ $38 } BT_DIGIT ,BT_DIGIT ,BT_COLON ,BT_SEMI ,
+{ $3C } BT_LT ,BT_EQUALS ,BT_GT ,BT_QUEST ,
+{ $40 } BT_OTHER ,BT_HEX ,BT_HEX ,BT_HEX ,
+{ $44 } BT_HEX ,BT_HEX ,BT_HEX ,BT_NMSTRT ,
+{ $48 } BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,
+{ $4C } BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,
+{ $50 } BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,
+{ $54 } BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,
+{ $58 } BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,BT_LSQB ,
+{ $5C } BT_OTHER ,BT_RSQB ,BT_OTHER ,BT_NMSTRT ,
+{ $60 } BT_OTHER ,BT_HEX ,BT_HEX ,BT_HEX ,
+{ $64 } BT_HEX ,BT_HEX ,BT_HEX ,BT_NMSTRT ,
+{ $68 } BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,
+{ $6C } BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,
+{ $70 } BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,
+{ $74 } BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,
+{ $78 } BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,BT_OTHER ,
+{ $7C } BT_VERBAR ,BT_OTHER ,BT_OTHER ,BT_OTHER ,
diff --git a/src/corelib/render/software/agg-demos/expat-pas/asciitab_bt_colon_.inc b/src/corelib/render/software/agg-demos/expat-pas/asciitab_bt_colon_.inc
new file mode 100755
index 00000000..9a796a70
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/expat-pas/asciitab_bt_colon_.inc
@@ -0,0 +1,67 @@
+//----------------------------------------------------------------------------
+// Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
+// and Clark Cooper
+// Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006 Expat maintainers.
+//
+// Expat - Version 2.0.0 Release Milano 0.83 (PasExpat 2.0.0 RM0.83)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.pasports.org/pasexpat
+// Copyright (c) 2006
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 11.06.2006-Milano: Unit port establishment
+//
+{ asciitab_bt_colon_.inc }
+{ $00 } BT_NONXML ,BT_NONXML ,BT_NONXML ,BT_NONXML ,
+{ $04 } BT_NONXML ,BT_NONXML ,BT_NONXML ,BT_NONXML ,
+{ $08 } BT_NONXML ,BT_S ,BT_LF ,BT_NONXML ,
+{ $0C } BT_NONXML ,BT_CR ,BT_NONXML ,BT_NONXML ,
+{ $10 } BT_NONXML ,BT_NONXML ,BT_NONXML ,BT_NONXML ,
+{ $14 } BT_NONXML ,BT_NONXML ,BT_NONXML ,BT_NONXML ,
+{ $18 } BT_NONXML ,BT_NONXML ,BT_NONXML ,BT_NONXML ,
+{ $1C } BT_NONXML ,BT_NONXML ,BT_NONXML ,BT_NONXML ,
+{ $20 } BT_S ,BT_EXCL ,BT_QUOT ,BT_NUM ,
+{ $24 } BT_OTHER ,BT_PERCNT ,BT_AMP ,BT_APOS ,
+{ $28 } BT_LPAR ,BT_RPAR ,BT_AST ,BT_PLUS ,
+{ $2C } BT_COMMA ,BT_MINUS ,BT_NAME ,BT_SOL ,
+{ $30 } BT_DIGIT ,BT_DIGIT ,BT_DIGIT ,BT_DIGIT ,
+{ $34 } BT_DIGIT ,BT_DIGIT ,BT_DIGIT ,BT_DIGIT ,
+{ $38 } BT_DIGIT ,BT_DIGIT ,BT_COLON_ ,BT_SEMI ,
+{ $3C } BT_LT ,BT_EQUALS ,BT_GT ,BT_QUEST ,
+{ $40 } BT_OTHER ,BT_HEX ,BT_HEX ,BT_HEX ,
+{ $44 } BT_HEX ,BT_HEX ,BT_HEX ,BT_NMSTRT ,
+{ $48 } BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,
+{ $4C } BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,
+{ $50 } BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,
+{ $54 } BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,
+{ $58 } BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,BT_LSQB ,
+{ $5C } BT_OTHER ,BT_RSQB ,BT_OTHER ,BT_NMSTRT ,
+{ $60 } BT_OTHER ,BT_HEX ,BT_HEX ,BT_HEX ,
+{ $64 } BT_HEX ,BT_HEX ,BT_HEX ,BT_NMSTRT ,
+{ $68 } BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,
+{ $6C } BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,
+{ $70 } BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,
+{ $74 } BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,
+{ $78 } BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,BT_OTHER ,
+{ $7C } BT_VERBAR ,BT_OTHER ,BT_OTHER ,BT_OTHER ,
diff --git a/src/corelib/render/software/agg-demos/expat-pas/expat.pas b/src/corelib/render/software/agg-demos/expat-pas/expat.pas
new file mode 100755
index 00000000..c4c7ddce
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/expat-pas/expat.pas
@@ -0,0 +1,898 @@
+//----------------------------------------------------------------------------
+// Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
+// and Clark Cooper
+// Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006 Expat maintainers.
+//
+// Expat - Version 2.0.0 Release Milano 0.83 (PasExpat 2.0.0 RM0.83)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.pasports.org/pasexpat
+// Copyright (c) 2006
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 01.05.2006-Milano: Unit port establishment
+// 07.06.2006-Milano: porting
+//
+{ expat.pas }
+unit
+ expat ;
+
+INTERFACE
+
+uses
+ expat_basics ,
+ xmltok ,
+ xmlrole ;
+
+{$I expat_mode.inc }
+
+{ TYPES DEFINITION }
+type
+{$I expat_external.inc }
+
+ XML_Parser = ^XML_ParserStruct;
+
+ XML_Bool = int8u;
+
+{ The XML_Status enum gives the possible return values for several API functions. }
+ XML_Status = (XML_STATUS_ERROR ,XML_STATUS_OK ,XML_STATUS_SUSPENDED );
+
+ XML_Error = (
+ XML_ERROR_NONE ,
+ XML_ERROR_NO_MEMORY ,
+ XML_ERROR_SYNTAX ,
+ XML_ERROR_NO_ELEMENTS ,
+ XML_ERROR_INVALID_TOKEN ,
+ XML_ERROR_UNCLOSED_TOKEN ,
+ XML_ERROR_PARTIAL_CHAR ,
+ XML_ERROR_TAG_MISMATCH ,
+ XML_ERROR_DUPLICATE_ATTRIBUTE ,
+ XML_ERROR_JUNK_AFTER_DOC_ELEMENT ,
+ XML_ERROR_PARAM_ENTITY_REF ,
+ XML_ERROR_UNDEFINED_ENTITY ,
+ XML_ERROR_RECURSIVE_ENTITY_REF ,
+ XML_ERROR_ASYNC_ENTITY ,
+ XML_ERROR_BAD_CHAR_REF ,
+ XML_ERROR_BINARY_ENTITY_REF ,
+ XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF ,
+ XML_ERROR_MISPLACED_XML_PI ,
+ XML_ERROR_UNKNOWN_ENCODING ,
+ XML_ERROR_INCORRECT_ENCODING ,
+ XML_ERROR_UNCLOSED_CDATA_SECTION ,
+ XML_ERROR_EXTERNAL_ENTITY_HANDLING ,
+ XML_ERROR_NOT_STANDALONE ,
+ XML_ERROR_UNEXPECTED_STATE ,
+ XML_ERROR_ENTITY_DECLARED_IN_PE ,
+ XML_ERROR_FEATURE_REQUIRES_XML_DTD ,
+ XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING ,
+ { Added in 1.95.7. }
+ XML_ERROR_UNBOUND_PREFIX ,
+ { Added in 1.95.8. }
+ XML_ERROR_UNDECLARING_PREFIX ,
+ XML_ERROR_INCOMPLETE_PE ,
+ XML_ERROR_XML_DECL ,
+ XML_ERROR_TEXT_DECL ,
+ XML_ERROR_PUBLICID ,
+ XML_ERROR_SUSPENDED ,
+ XML_ERROR_NOT_SUSPENDED ,
+ XML_ERROR_ABORTED ,
+ XML_ERROR_FINISHED ,
+ XML_ERROR_SUSPEND_PE ,
+ { Added in 2.0. }
+ XML_ERROR_RESERVED_PREFIX_XML ,
+ XML_ERROR_RESERVED_PREFIX_XMLNS ,
+ XML_ERROR_RESERVED_NAMESPACE_URI );
+
+ XML_Content_Type = (
+ ___SKIP_ZERO____ ,
+ XML_CTYPE_EMPTY ,
+ XML_CTYPE_ANY ,
+ XML_CTYPE_MIXED ,
+ XML_CTYPE_NAME ,
+ XML_CTYPE_CHOICE ,
+ XML_CTYPE_SEQ );
+
+ XML_Content_Quant = (
+ XML_CQUANT_NONE ,
+ XML_CQUANT_OPT ,
+ XML_CQUANT_REP ,
+ XML_CQUANT_PLUS );
+
+ XML_ParamEntityParsing = (
+ XML_PARAM_ENTITY_PARSING_NEVER ,
+ XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE ,
+ XML_PARAM_ENTITY_PARSING_ALWAYS );
+
+{ If type == XML_CTYPE_EMPTY or XML_CTYPE_ANY, then quant will be
+ XML_CQUANT_NONE, and the other fields will be zero or NULL.
+ If type == XML_CTYPE_MIXED, then quant will be NONE or REP and
+ numchildren will contain number of elements that may be mixed in
+ and children point to an array of XML_Content cells that will be
+ all of XML_CTYPE_NAME type with no quantification.
+
+ If type == XML_CTYPE_NAME, then the name points to the name, and
+ the numchildren field will be zero and children will be NULL. The
+ quant fields indicates any quantifiers placed on the name.
+
+ CHOICE and SEQ will have name NULL, the number of children in
+ numchildren and children will point, recursively, to an array
+ of XML_Content cells.
+
+ The EMPTY, ANY, and MIXED types will only occur at top level. }
+ XML_Content_ptr = ^XML_Content;
+
+ XML_cp = record
+ type_ : XML_Content_Type;
+ quant : XML_Content_Quant;
+ name : XML_Char_ptr;
+
+ numchildren : unsigned;
+ children : XML_Content_ptr;
+
+ end;
+
+ XML_Content = XML_cp;
+
+{ This is called for an element declaration. See above for
+ description of the model argument. It's the caller's responsibility
+ to free model when finished with it. }
+ XML_ElementDeclHandler = procedure(userData : pointer; name : XML_Char_ptr; model : XML_Content_ptr );
+
+{ The Attlist declaration handler is called for *each* attribute. So
+ a single Attlist declaration with multiple attributes declared will
+ generate multiple calls to this handler. The "default" parameter
+ may be NULL in the case of the "#IMPLIED" or "#REQUIRED"
+ keyword. The "isrequired" parameter will be true and the default
+ value will be NULL in the case of "#REQUIRED". If "isrequired" is
+ true and default is non-NULL, then this is a "#FIXED" default. }
+ XML_AttlistDeclHandler = procedure(
+ userData : pointer;
+ elname ,attname ,att_type ,dflt : XML_Char_ptr;
+ isrequired : int );
+
+{ The XML declaration handler is called for *both* XML declarations
+ and text declarations. The way to distinguish is that the version
+ parameter will be NULL for text declarations. The encoding
+ parameter may be NULL for XML declarations. The standalone
+ parameter will be -1, 0, or 1 indicating respectively that there
+ was no standalone parameter in the declaration, that it was given
+ as no, or that it was given as yes. }
+ XML_XmlDeclHandler = procedure(userData : pointer; version ,encoding : XML_Char_ptr; standalone : int );
+
+{ This is called for entity declarations. The is_parameter_entity
+ argument will be non-zero if the entity is a parameter entity, zero
+ otherwise.
+
+ For internal entities (<!ENTITY foo "bar">), value will
+ be non-NULL and systemId, publicID, and notationName will be NULL.
+ The value string is NOT nul-terminated; the length is provided in
+ the value_length argument. Since it is legal to have zero-length
+ values, do not use this argument to test for internal entities.
+
+ For external entities, value will be NULL and systemId will be
+ non-NULL. The publicId argument will be NULL unless a public
+ identifier was provided. The notationName argument will have a
+ non-NULL value only for unparsed entity declarations.
+
+ Note that is_parameter_entity can't be changed to XML_Bool, since
+ that would break binary compatibility. }
+ XML_EntityDeclHandler = procedure(
+ userData : pointer;
+ entityName : XML_Char_ptr;
+ is_parameter_entity : int;
+ value : XML_Char_ptr;
+ value_length : int;
+ base ,systemId ,publicId ,notationName : XML_Char_ptr );
+
+{ atts is array of name/value pairs, terminated by 0;
+ names and values are 0 terminated. }
+ XML_StartElementHandler = procedure(userData : pointer; name : XML_Char_ptr; atts : XML_Char_ptr_ptr );
+ XML_EndElementHandler = procedure(userData : pointer; name : XML_Char_ptr );
+
+{ s is not 0 terminated. }
+ XML_CharacterDataHandler = procedure(userData : pointer; s : XML_Char_ptr; len : int );
+
+{ target and data are 0 terminated }
+ XML_ProcessingInstructionHandler = procedure(userData : pointer; target ,data : XML_Char_ptr );
+
+{ data is 0 terminated }
+ XML_CommentHandler = procedure(userData : pointer; data : XML_Char_ptr );
+
+ XML_StartCdataSectionHandler = procedure(userData : pointer );
+ XML_EndCdataSectionHandler = procedure(userData : pointer );
+
+
+{ This is called for any characters in the XML document for which
+ there is no applicable handler. This includes both characters that
+ are part of markup which is of a kind that is not reported
+ (comments, markup declarations), or characters that are part of a
+ construct which could be reported but for which no handler has been
+ supplied. The characters are passed exactly as they were in the XML
+ document except that they will be encoded in UTF-8 or UTF-16.
+ Line boundaries are not normalized. Note that a byte order mark
+ character is not passed to the default handler. There are no
+ guarantees about how characters are divided between calls to the
+ default handler: for example, a comment might be split between
+ multiple calls. }
+ XML_DefaultHandler = procedure(userData : pointer; s : XML_Char_ptr; len : int );
+
+{ This is called for the start of the DOCTYPE declaration, before
+ any DTD or internal subset is parsed. }
+ XML_StartDoctypeDeclHandler = procedure(
+ userData : pointer;
+ doctypeName ,sysid ,pubid : XML_Char_ptr;
+ has_internal_subset : int );
+
+{ This is called for the start of the DOCTYPE declaration when the
+ closing > is encountered, but after processing any external
+ subset. }
+ XML_EndDoctypeDeclHandler = procedure(userData : pointer );
+
+{ OBSOLETE -- OBSOLETE -- OBSOLETE
+ This handler has been superceded by the EntityDeclHandler above.
+ It is provided here for backward compatibility.
+
+ This is called for a declaration of an unparsed (NDATA) entity.
+ The base argument is whatever was set by XML_SetBase. The
+ entityName, systemId and notationName arguments will never be
+ NULL. The other arguments may be. }
+ XML_UnparsedEntityDeclHandler = procedure(
+ userData : pointer;
+ entityName ,base ,systemId ,publicId ,notationName : XML_Char_ptr );
+
+{ This is called for a declaration of notation. The base argument is
+ whatever was set by XML_SetBase. The notationName will never be
+ NULL. The other arguments can be. }
+ XML_NotationDeclHandler = procedure(
+ userData : pointer;
+ notationName ,base ,systemId ,publicId : XML_Char_ptr );
+
+{ When namespace processing is enabled, these are called once for
+ each namespace declaration. The call to the start and end element
+ handlers occur between the calls to the start and end namespace
+ declaration handlers. For an xmlns attribute, prefix will be
+ NULL. For an xmlns="" attribute, uri will be NULL. }
+ XML_StartNamespaceDeclHandler = procedure(userData : pointer; prefix ,uri : XML_Char_ptr );
+ XML_EndNamespaceDeclHandler = procedure(userData : pointer; prefix : XML_Char_ptr );
+
+{ This is called if the document is not standalone, that is, it has an
+ external subset or a reference to a parameter entity, but does not
+ have standalone="yes". If this handler returns XML_STATUS_ERROR,
+ then processing will not continue, and the parser will return a
+ XML_ERROR_NOT_STANDALONE error.
+ If parameter entity parsing is enabled, then in addition to the
+ conditions above this handler will only be called if the referenced
+ entity was actually read. }
+ XML_NotStandaloneHandler = function(userData : pointer ) : int;
+
+{ This is called for a reference to an external parsed general
+ entity. The referenced entity is not automatically parsed. The
+ application can parse it immediately or later using
+ XML_ExternalEntityParserCreate.
+
+ The parser argument is the parser parsing the entity containing the
+ reference; it can be passed as the parser argument to
+ XML_ExternalEntityParserCreate. The systemId argument is the
+ system identifier as specified in the entity declaration; it will
+ not be NULL.
+
+ The base argument is the system identifier that should be used as
+ the base for resolving systemId if systemId was relative; this is
+ set by XML_SetBase; it may be NULL.
+
+ The publicId argument is the public identifier as specified in the
+ entity declaration, or NULL if none was specified; the whitespace
+ in the public identifier will have been normalized as required by
+ the XML spec.
+
+ The context argument specifies the parsing context in the format
+ expected by the context argument to XML_ExternalEntityParserCreate;
+ context is valid only until the handler returns, so if the
+ referenced entity is to be parsed later, it must be copied.
+ context is NULL only when the entity is a parameter entity.
+
+ The handler should return XML_STATUS_ERROR if processing should not
+ continue because of a fatal error in the handling of the external
+ entity. In this case the calling parser will return an
+ XML_ERROR_EXTERNAL_ENTITY_HANDLING error.
+
+ Note that unlike other handlers the first argument is the parser,
+ not userData. }
+ XML_ExternalEntityRefHandler = function(
+ parser : XML_Parser;
+ context ,base ,systemId ,publicId : XML_Char_ptr ) : int;
+
+{ This is called in two situations:
+ 1) An entity reference is encountered for which no declaration
+ has been read *and* this is not an error.
+ 2) An internal entity reference is read, but not expanded, because
+ XML_SetDefaultHandler has been called.
+ Note: skipped parameter entities in declarations and skipped general
+ entities in attribute values cannot be reported, because
+ the event would be out of sync with the reporting of the
+ declarations or attribute values }
+ XML_SkippedEntityHandler = procedure(userData : pointer; entityName : XML_Char_ptr; is_parameter_entity : int );
+
+(* This structure is filled in by the XML_UnknownEncodingHandler to
+ provide information to the parser about encodings that are unknown
+ to the parser.
+
+ The map[b] member gives information about byte sequences whose
+ first byte is b.
+
+ If map[b] is c where c is >= 0, then b by itself encodes the
+ Unicode scalar value c.
+
+ If map[b] is -1, then the byte sequence is malformed.
+
+ If map[b] is -n, where n >= 2, then b is the first byte of an
+ n-byte sequence that encodes a single Unicode scalar value.
+
+ The data member will be passed as the first argument to the convert
+ function.
+
+ The convert function is used to convert multibyte sequences; s will
+ point to a n-byte sequence where map[(unsigned char)*s] == -n. The
+ convert function must return the Unicode scalar value represented
+ by this byte sequence or -1 if the byte sequence is malformed.
+
+ The convert function may be NULL if the encoding is a single-byte
+ encoding, that is if map[b] >= -1 for all bytes b.
+
+ When the parser is finished with the encoding, then if release is
+ not NULL, it will call release passing it the data member; once
+ release has been called, the convert function will not be called
+ again.
+
+ Expat places certain restrictions on the encodings that are supported
+ using this mechanism.
+
+ 1. Every ASCII character that can appear in a well-formed XML document,
+ other than the characters
+
+ $@\^`{}~
+
+ must be represented by a single byte, and that byte must be the
+ same byte that represents that character in ASCII.
+
+ 2. No character may require more than 4 bytes to encode.
+
+ 3. All characters encoded must have Unicode scalar values <=
+ 0xFFFF, (i.e., characters that would be encoded by surrogates in
+ UTF-16 are not allowed). Note that this restriction doesn't
+ apply to the built-in support for UTF-8 and UTF-16.
+
+ 4. No Unicode character may be encoded by more than one distinct
+ sequence of bytes. *)
+ XML_Encoding_ptr = ^XML_Encoding;
+ XML_Encoding = record
+ map : array[0..255 ] of int;
+ data : pointer;
+
+ convert : function (data : pointer; s : char_ptr ) : int;
+ release : procedure(data : pointer );
+
+ end;
+
+{ This is called for an encoding that is unknown to the parser.
+
+ The encodingHandlerData argument is that which was passed as the
+ second argument to XML_SetUnknownEncodingHandler.
+
+ The name argument gives the name of the encoding as specified in
+ the encoding declaration.
+
+ If the callback can provide information about the encoding, it must
+ fill in the XML_Encoding structure, and return XML_STATUS_OK.
+ Otherwise it must return XML_STATUS_ERROR.
+
+ If info does not describe a suitable encoding, then the parser will
+ return an XML_UNKNOWN_ENCODING error. }
+ XML_UnknownEncodingHandler = function(
+ encodingHandlerData : pointer;
+ name : XML_Char_ptr;
+ info : XML_Encoding_ptr ) : int;
+
+
+ XML_Memory_Handling_Suite_ptr = ^XML_Memory_Handling_Suite;
+ XML_Memory_Handling_Suite = record
+ malloc_fcn : function(var ptr : pointer; sz : integer ) : boolean;
+ realloc_fcn : function(var ptr : pointer; old ,sz : integer ) : boolean;
+ free_fcn : function(var ptr : pointer; sz : integer ) : boolean;
+
+ end;
+
+ KEY = XML_Char_ptr;
+
+ NAMED_ptr_ptr = ^NAMED_ptr;
+ NAMED_ptr = ^NAMED;
+ NAMED = record
+ name : KEY;
+ alloc : int;
+
+ end;
+
+ HASH_TABLE_ptr = ^HASH_TABLE;
+ HASH_TABLE = record
+ v : NAMED_ptr_ptr;
+ a : int;
+
+ power : int8u;
+ size ,
+ used : size_t;
+ mem : XML_Memory_Handling_Suite_ptr;
+
+ end;
+
+ ENTITY_ptr = ^ENTITY;
+ ENTITY = record
+ name : XML_Char_ptr;
+ alloc : int;
+
+ textPtr : XML_Char_ptr;
+ textLen , { length in XML_Chars }
+ processed : int; { # of processed bytes - when suspended }
+ systemId ,
+ base ,
+ publicId ,
+ notation : XML_Char_ptr;
+
+ open ,
+ is_param ,
+ is_internal : XML_Bool; { true if declared in internal subset outside PE }
+
+ end;
+
+ OPEN_INTERNAL_ENTITY_ptr = ^OPEN_INTERNAL_ENTITY;
+ OPEN_INTERNAL_ENTITY = record
+ internalEventPtr ,
+ internalEventEndPtr : char_ptr;
+
+ next : OPEN_INTERNAL_ENTITY_ptr;
+ entity : ENTITY_ptr;
+
+ startTagLevel : int;
+ betweenDecl : XML_Bool; { WFC: PE Between Declarations }
+
+ end;
+
+ CONTENT_SCAFFOLD_ptr = ^CONTENT_SCAFFOLD;
+ CONTENT_SCAFFOLD = record
+ type_ : XML_Content_Type;
+ quant : XML_Content_Quant;
+ name : XML_Char_ptr;
+
+ firstchild ,
+ lastchild ,
+ childcnt ,
+ nextsib : int;
+
+ end;
+
+ PREFIX_ptr = ^PREFIX;
+
+ ATTRIBUTE_ID_ptr = ^ATTRIBUTE_ID;
+ ATTRIBUTE_ID = record
+ name : XML_Char_ptr;
+ alloc : int;
+ prefix : PREFIX_ptr;
+
+ maybeTokenized ,
+ xmlns : XML_Bool;
+
+ end;
+
+ DEFAULT_ATTRIBUTE_ptr = ^DEFAULT_ATTRIBUTE;
+ DEFAULT_ATTRIBUTE = record
+ id : ATTRIBUTE_ID_ptr;
+
+ isCdata : XML_Bool;
+ value : XML_Char_ptr;
+
+ end;
+
+ ELEMENT_TYPE_ptr = ^ELEMENT_TYPE;
+ ELEMENT_TYPE = record
+ name : XML_Char_ptr;
+ alloc : int;
+ prefix : PREFIX_ptr;
+ idAtt : ATTRIBUTE_ID_ptr;
+
+ nDefaultAtts ,
+ allocDefaultAtts ,
+ defaultAttsAlloc : int;
+
+ defaultAtts : DEFAULT_ATTRIBUTE_ptr;
+
+ end;
+
+ TAG_NAME_ptr = ^TAG_NAME;
+ TAG_NAME = record
+ str ,
+ localPart ,
+ prefix : XML_Char_ptr;
+ strLen ,
+ uriLen ,
+ prefixLen : int;
+
+ end;
+
+{ TAG represents an open element.
+ The name of the element is stored in both the document and API
+ encodings. The memory buffer 'buf' is a separately-allocated
+ memory area which stores the name. During the XML_Parse()/
+ XMLParseBuffer() when the element is open, the memory for the 'raw'
+ version of the name (in the document encoding) is shared with the
+ document buffer. If the element is open across calls to
+ XML_Parse()/XML_ParseBuffer(), the buffer is re-allocated to
+ contain the 'raw' name as well.
+
+ A parser re-uses these structures, maintaining a list of allocated
+ TAG objects in a free list. }
+ BINDING_ptr_ptr = ^BINDING_ptr;
+ BINDING_ptr = ^BINDING;
+
+ TAG_ptr = ^TAG;
+ TAG = record
+ parent : TAG_ptr; { parent of this element }
+ rawName : char_ptr; { tagName in the original encoding }
+
+ rawNameLength : int;
+
+ name : TAG_NAME; { tagName in the API encoding }
+
+ buf , { buffer for name components }
+ bufEnd : char_ptr; { end of the buffer }
+ alloc : int;
+
+ bindings : BINDING_ptr;
+
+ end;
+
+ BINDING = record
+ prefix : PREFIX_ptr;
+
+ nextTagBinding ,
+ prevPrefixBinding : BINDING_ptr;
+
+ attId : ATTRIBUTE_ID_ptr;
+ uri : XML_Char_ptr;
+
+ uriLen ,
+ uriAlloc : int;
+
+ end;
+
+ PREFIX = record
+ name : XML_Char_ptr;
+ alloc : int;
+ binding : BINDING_ptr;
+
+ end;
+
+ NS_ATT_ptr = ^NS_ATT;
+ NS_ATT = record
+ version ,
+ hash : int32u;
+ uriName : XML_Char_ptr;
+
+ end;
+
+ BLOCK_ptr = ^BLOCK;
+ BLOCK = record
+ next : BLOCK_ptr;
+ size ,
+ alloc : int;
+
+ s : array[0..0 ] of XML_Char;
+
+ end;
+
+ STRING_POOL_ptr = ^STRING_POOL;
+ STRING_POOL = record
+ blocks ,
+ freeBlocks : BLOCK_ptr;
+
+ end_ ,
+ ptr ,
+ start : XML_Char_ptr;
+
+ mem : XML_Memory_Handling_Suite_ptr;
+
+ end;
+
+ DTD_ptr = ^DTD;
+ DTD = record
+ generalEntities ,
+ elementTypes ,
+ attributeIds ,
+ prefixes : HASH_TABLE;
+
+ pool ,
+ entityValuePool : STRING_POOL;
+
+ { false once a parameter entity reference has been skipped }
+ keepProcessing : XML_Bool;
+
+ { true once an internal or external PE reference has been encountered;
+ this includes the reference to an external subset }
+ hasParamEntityRefs ,
+ standalone : XML_Bool;
+
+ {$IFDEF XML_DTD }
+ { indicates if external PE has been read }
+ paramEntityRead : XML_Bool;
+ paramEntities : HASH_TABLE;
+
+ {$ENDIF }
+
+ defaultPrefix : PREFIX;
+
+ { === scaffolding for building content model === }
+ in_eldecl : XML_Bool;
+ scaffold : CONTENT_SCAFFOLD_ptr;
+
+ contentStringLen ,
+ scaffSize ,
+ scaffCount : unsigned;
+
+ scaffLevel : int;
+ scaffIndex : int_ptr;
+ scaffAlloc : int;
+
+ end;
+
+ XML_Parsing = (
+ XML_INITIALIZED ,
+ XML_PARSING_ ,
+ XML_FINISHED ,
+ XML_SUSPENDED );
+
+ XML_ParsingStatus = record
+ parsing : XML_Parsing;
+ finalBuffer : XML_Bool;
+
+ end;
+
+ Processor = function(parser : XML_Parser; start ,end_ : char_ptr; endPtr : char_ptr_ptr ) : XML_Error;
+
+ XML_ParserStruct = record
+ m_userData ,
+ m_handlerArg : pointer;
+
+ m_buffer : char_ptr;
+ m_mem : XML_Memory_Handling_Suite;
+
+ { first character to be parsed }
+ m_bufferPtr : char_ptr;
+
+ { past last character to be parsed }
+ m_bufferEnd : char_ptr;
+
+ { allocated end of buffer }
+ m_bufferLim : char_ptr;
+
+ { the size of the allocated buffer }
+ m_bufferAloc : int;
+
+ m_parseEndByteIndex : XML_Index;
+
+ m_parseEndPtr : char_ptr;
+ m_dataBuf ,
+ m_dataBufEnd : XML_Char_ptr;
+
+ { XML Handlers }
+ m_startElementHandler : XML_StartElementHandler;
+ m_endElementHandler : XML_EndElementHandler;
+ m_characterDataHandler : XML_CharacterDataHandler;
+ m_processingInstructionHandler : XML_ProcessingInstructionHandler;
+ m_commentHandler : XML_CommentHandler;
+ m_startCdataSectionHandler : XML_StartCdataSectionHandler;
+ m_endCdataSectionHandler : XML_EndCdataSectionHandler;
+ m_defaultHandler : XML_DefaultHandler;
+ m_startDoctypeDeclHandler : XML_StartDoctypeDeclHandler;
+ m_endDoctypeDeclHandler : XML_EndDoctypeDeclHandler;
+ m_unparsedEntityDeclHandler : XML_UnparsedEntityDeclHandler;
+ m_notationDeclHandler : XML_NotationDeclHandler;
+ m_startNamespaceDeclHandler : XML_StartNamespaceDeclHandler;
+ m_endNamespaceDeclHandler : XML_EndNamespaceDeclHandler;
+ m_notStandaloneHandler : XML_NotStandaloneHandler;
+ m_externalEntityRefHandler : XML_ExternalEntityRefHandler;
+ m_externalEntityRefHandlerArg : XML_Parser;
+ m_skippedEntityHandler : XML_SkippedEntityHandler;
+ m_unknownEncodingHandler : XML_UnknownEncodingHandler;
+ m_elementDeclHandler : XML_ElementDeclHandler;
+ m_attlistDeclHandler : XML_AttlistDeclHandler;
+ m_entityDeclHandler : XML_EntityDeclHandler;
+ m_xmlDeclHandler : XML_XmlDeclHandler;
+
+ m_encoding : ENCODING_ptr;
+ m_initEncoding : INIT_ENCODING;
+ m_internalEncoding : ENCODING_ptr;
+ m_protocolEncodingName : XML_Char_ptr;
+
+ m_ns ,
+ m_ns_triplets : XML_Bool;
+
+ m_unknownEncodingMem ,
+ m_unknownEncodingData ,
+ m_unknownEncodingHandlerData : pointer;
+ m_unknownEncodingAlloc : int;
+
+ m_unknownEncodingRelease : procedure(void : pointer );
+
+ m_prologState : PROLOG_STATE;
+ m_processor : Processor;
+ m_errorCode : XML_Error;
+ m_eventPtr ,
+ m_eventEndPtr ,
+ m_positionPtr : char_ptr;
+
+ m_openInternalEntities ,
+ m_freeInternalEntities : OPEN_INTERNAL_ENTITY_ptr;
+
+ m_defaultExpandInternalEntities : XML_Bool;
+
+ m_tagLevel : int;
+ m_declEntity : ENTITY_ptr;
+
+ m_doctypeName ,
+ m_doctypeSysid ,
+ m_doctypePubid ,
+ m_declAttributeType ,
+ m_declNotationName ,
+ m_declNotationPublicId : XML_Char_ptr;
+
+ m_declElementType : ELEMENT_TYPE_ptr;
+ m_declAttributeId : ATTRIBUTE_ID_ptr;
+
+ m_declAttributeIsCdata ,
+ m_declAttributeIsId : XML_Bool;
+
+ m_dtd : DTD_ptr;
+
+ m_curBase : XML_Char_ptr;
+
+ m_tagStack ,
+ m_freeTagList : TAG_ptr;
+
+ m_inheritedBindings ,
+ m_freeBindingList : BINDING_ptr;
+
+ m_attsSize ,
+ m_attsAlloc ,
+ m_nsAttsAlloc ,
+ m_nSpecifiedAtts ,
+ m_idAttIndex : int;
+
+ m_atts : ATTRIBUTE_ptr;
+ m_nsAtts : NS_ATT_ptr;
+
+ m_nsAttsVersion : unsigned;
+ m_nsAttsPower : int8u;
+
+ m_position : POSITION;
+ m_tempPool ,
+ m_temp2Pool : STRING_POOL;
+
+ m_groupConnector : char_ptr;
+ m_groupSize ,
+ m_groupAlloc : unsigned;
+
+ m_namespaceSeparator : XML_Char;
+
+ m_parentParser : XML_Parser;
+ m_parsingStatus : XML_ParsingStatus;
+
+ {$IFDEF XML_DTD }
+ m_isParamEntity ,
+ m_useForeignDTD : XML_Bool;
+
+ m_paramEntityParsing : XML_ParamEntityParsing;
+
+ {$ENDIF }
+
+ end;
+
+{ GLOBAL CONSTANTS }
+const
+ XML_TRUE = 1;
+ XML_FALSE = 0;
+
+
+{ GLOBAL PROCEDURES }
+{ Constructs a new parser; encoding is the encoding specified by the
+ external protocol or NIL if there is none specified. }
+ function XML_ParserCreate(const encoding : XML_Char_ptr ) : XML_Parser;
+
+{ Constructs a new parser using the memory management suite referred to
+ by memsuite. If memsuite is NULL, then use the standard library memory
+ suite. If namespaceSeparator is non-NULL it creates a parser with
+ namespace processing as described above. The character pointed at
+ will serve as the namespace separator.
+
+ All further memory operations used for the created parser will come from
+ the given suite. }
+ function XML_ParserCreate_MM(
+ encoding : XML_Char_ptr;
+ memsuite : XML_Memory_Handling_Suite_ptr;
+ namespaceSeparator : XML_Char_ptr ) : XML_Parser;
+
+{ This value is passed as the userData argument to callbacks. }
+ procedure XML_SetUserData(parser : XML_Parser; userData : pointer );
+
+ procedure XML_SetElementHandler(
+ parser : XML_Parser;
+ start : XML_StartElementHandler;
+ end_ : XML_EndElementHandler );
+
+ procedure XML_SetCharacterDataHandler(
+ parser : XML_Parser;
+ handler : XML_CharacterDataHandler );
+
+{ Parses some input. Returns XML_STATUS_ERROR if a fatal error is
+ detected. The last call to XML_Parse must have isFinal true; len
+ may be zero for this call (or any other).
+
+ Though the return values for these functions has always been
+ described as a Boolean value, the implementation, at least for the
+ 1.95.x series, has always returned exactly one of the XML_Status
+ values. }
+ function XML_Parse(parser : XML_Parser; const s : char_ptr; len ,isFinal : int ) : XML_Status;
+
+{ If XML_Parse or XML_ParseBuffer have returned XML_STATUS_ERROR, then
+ XML_GetErrorCode returns information about the error. }
+ function XML_GetErrorCode(parser : XML_Parser ) : XML_Error;
+
+{ Returns a string describing the error. }
+ function XML_ErrorString(code : XML_Error ) : XML_LChar_ptr;
+
+{ These functions return information about the current parse
+ location. They may be called from any callback called to report
+ some parse event; in this case the location is the location of the
+ first of the sequence of characters that generated the event. When
+ called from callbacks generated by declarations in the document
+ prologue, the location identified isn't as neatly defined, but will
+ be within the relevant markup. When called outside of the callback
+ functions, the position indicated will be just past the last parse
+ event (regardless of whether there was an associated callback).
+
+ They may also be called after returning from a call to XML_Parse
+ or XML_ParseBuffer. If the return value is XML_STATUS_ERROR then
+ the location is the location of the character at which the error
+ was detected; otherwise the location is the location of the last
+ parse event, as described above. }
+ function XML_GetCurrentLineNumber(parser : XML_Parser ) : XML_Size;
+
+{ Frees memory used by the parser. }
+ procedure XML_ParserFree(parser : XML_Parser );
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{$I xmlparse.inc }
+
+END.
+
+
diff --git a/src/corelib/render/software/agg-demos/expat-pas/expat_basics.pas b/src/corelib/render/software/agg-demos/expat-pas/expat_basics.pas
new file mode 100755
index 00000000..9ef5c0b3
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/expat-pas/expat_basics.pas
@@ -0,0 +1,218 @@
+//----------------------------------------------------------------------------
+// Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
+// and Clark Cooper
+// Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006 Expat maintainers.
+//
+// Expat - Version 2.0.0 Release Milano 0.83 (PasExpat 2.0.0 RM0.83)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.pasports.org/pasexpat
+// Copyright (c) 2006
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 10.05.2006-Milano: Unit port establishment
+//
+{ expat_basics.pas }
+unit
+ expat_basics ;
+
+INTERFACE
+
+{$I expat_mode.inc }
+
+{ GLOBAL PROCEDURES }
+ function expat_getmem (var ptr : pointer; sz : integer ) : boolean;
+ function expat_realloc(var ptr : pointer; old ,sz : integer ) : boolean;
+ function expat_freemem(var ptr : pointer; sz : integer ) : boolean;
+
+ procedure NoP;
+
+// SHR for signed integers is differently implemented in pascal compilers
+// than in c++ compilers. On the assembler level, c++ is using the SAR and
+// pascal is using SHR. That gives completely different result, when the
+// number is negative. We have to be compatible with c++ implementation,
+// thus instead of directly using SHR we emulate c++ solution.
+ function shr_int8 (i ,shift : shortint ) : shortint;
+ function shr_int16(i ,shift : smallint ) : smallint;
+ function shr_int32(i ,shift : longint ) : longint;
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ EXPAT_GETMEM }
+function expat_getmem;
+begin
+ result:=false;
+
+ try
+ getmem(ptr ,sz );
+
+ result:=true;
+
+ except
+ ptr:=NIL;
+
+ end;
+
+end;
+
+{ EXPAT_REALLOC }
+function expat_realloc;
+var
+ nb : pointer;
+ max : integer;
+
+begin
+ if expat_getmem(nb ,sz ) then
+ begin
+ max:=old;
+
+ if max > sz then
+ max:=sz;
+
+ move(ptr^ ,nb^ ,max );
+
+ expat_freemem(ptr ,old );
+
+ ptr :=nb;
+ result:=true;
+
+ end
+ else
+ result:=false;
+
+end;
+
+{ EXPAT_FREEMEM }
+function expat_freemem;
+begin
+ if ptr = NIL then
+ result:=true
+
+ else
+ try
+ freemem(ptr ,sz );
+
+ ptr :=NIL;
+ result:=true;
+
+ except
+ result:=false;
+
+ end;
+
+end;
+
+{ NOP }
+procedure NoP;
+begin
+end;
+
+{ SHR_INT8 }
+function shr_int8;
+begin
+{$IFDEF EXPAT_CPU_386 }
+ asm
+ mov al ,byte ptr [i ]
+ mov cl ,byte ptr [shift ]
+ sar al ,cl
+ mov byte ptr [result ] ,al
+
+ end;
+
+{$ENDIF }
+
+{$IFDEF EXPAT_CPU_PPC }
+ asm
+ lbz r2,i
+ extsb r2,r2
+ lbz r3,shift
+ extsb r3,r3
+ sraw r2,r2,r3
+ extsb r2,r2
+ stb r2,result
+
+ end;
+
+{$ENDIF }
+
+end;
+
+{ SHR_INT16 }
+function shr_int16;
+begin
+{$IFDEF EXPAT_CPU_386 }
+ asm
+ mov ax ,word ptr [i ]
+ mov cx ,word ptr [shift ]
+ sar ax ,cl
+ mov word ptr [result ] ,ax
+
+ end;
+
+{$ENDIF }
+
+{$IFDEF EXPAT_CPU_PPC }
+ asm
+ lha r2,i
+ lha r3,shift
+ sraw r2,r2,r3
+ extsh r2,r2
+ sth r2,result
+
+ end;
+
+{$ENDIF }
+
+end;
+
+{ SHR_INT32 }
+function shr_int32;
+begin
+{$IFDEF EXPAT_CPU_386 }
+ asm
+ mov eax ,dword ptr [i ]
+ mov ecx ,dword ptr [shift ]
+ sar eax ,cl
+ mov dword ptr [result ] ,eax
+
+ end;
+
+{$ENDIF }
+
+{$IFDEF EXPAT_CPU_PPC }
+ asm
+ lwz r3,i
+ lwz r2,shift
+ sraw r3,r3,r2
+ stw r3,result
+
+ end;
+
+{$ENDIF }
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg-demos/expat-pas/expat_external.inc b/src/corelib/render/software/agg-demos/expat-pas/expat_external.inc
new file mode 100755
index 00000000..3d5089b8
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/expat-pas/expat_external.inc
@@ -0,0 +1,147 @@
+//----------------------------------------------------------------------------
+// Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
+// and Clark Cooper
+// Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006 Expat maintainers.
+//
+// Expat - Version 2.0.0 Release Milano 0.83 (PasExpat 2.0.0 RM0.83)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.pasports.org/pasexpat
+// Copyright (c) 2006
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 03.05.2006-Milano: Unit port establishment
+//
+{ expat_external.inc }
+(* General Integer Types *)
+ int8 = shortint;
+ int8u = byte;
+ int16 = smallint;
+ int16u = word;
+ int32 = longint;
+ int32u = longword;
+ int64 = system.int64;
+
+{$IFDEF FPC }
+ int64u = qword;
+
+{$ELSE }
+ int64u = system.int64;
+
+{$ENDIF }
+
+(* General Character Types *)
+ char8 = char;
+ char16 = int16u;
+ char32 = int32u;
+
+(* C/C++ compatibility Types *)
+ int = int32;
+ unsigned = int32u;
+ size_t = int32u;
+
+(* Pascal Pointer Computation Type *)
+{$IFDEF CPU64 }
+ ptrcomp = system.int64;
+
+{$ELSE }
+ ptrcomp = integer;
+
+{$ENDIF }
+
+(* Type Pointers *)
+ int8_ptr = ^int8;
+ int8_ptr_ptr = ^int8_ptr;
+
+ int8u_ptr = ^int8u;
+ int8u_ptr_ptr = ^int8u_ptr;
+
+ int16_ptr = ^int16;
+ int16_ptr_ptr = ^int16_ptr;
+
+ int16u_ptr = ^int16u;
+ int16u_ptr_ptr = ^int16u_ptr;
+
+ int32_ptr = ^int32;
+ int32_ptr_ptr = ^int32_ptr;
+
+ int32u_ptr = ^int32u;
+ int32u_ptr_ptr = ^int32u_ptr;
+
+ int64_ptr = ^int64;
+ int64_ptr_ptr = ^int64_ptr;
+
+ int64u_ptr = ^int64u;
+ int64u_ptr_ptr = ^int64u_ptr;
+
+ char8_ptr = ^char8;
+ char8_ptr_ptr = ^char8_ptr;
+
+ char16_ptr = ^char16;
+ char16_ptr_ptr = ^char16_ptr;
+
+ char32_ptr = ^char32;
+ char32_ptr_ptr = ^char32_ptr;
+
+ int_ptr = ^int;
+ int_ptr_ptr = ^int_ptr;
+
+ unsigned_ptr = ^unsigned;
+ unsigned_ptr_ptr = ^unsigned_ptr;
+
+ char_ptr = ^char;
+ char_ptr_ptr = ^char_ptr;
+
+(* Expat Types *)
+{$IFDEF XML_UNICODE } // Information is UTF-16 encoded.
+{$IFDEF XML_UNICODE_WCHAR_T }
+ XML_Char = int16u;
+ XML_LChar = int16u;
+
+{$ELSE }
+ XML_Char = word;
+ XML_LChar = char;
+
+{$ENDIF }
+
+{$ELSE } // Information is UTF-8 encoded.
+ XML_Char = char;
+ XML_LChar = char;
+
+{$ENDIF }
+
+ XML_Char_ptr = ^XML_Char;
+ XML_LChar_ptr = ^XML_LChar;
+
+ XML_Char_ptr_ptr = ^XML_Char_ptr;
+
+{$IFDEF XML_LARGE_SIZE } // Use large integers for file/stream positions.
+ XML_Index = int64;
+ XML_Size = int64u;
+
+{$ELSE }
+ XML_Index = longint;
+ XML_Size = longword;
+
+{$ENDIF }
+
diff --git a/src/corelib/render/software/agg-demos/expat-pas/expat_external.pas b/src/corelib/render/software/agg-demos/expat-pas/expat_external.pas
new file mode 100755
index 00000000..0d936abb
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/expat-pas/expat_external.pas
@@ -0,0 +1,52 @@
+//----------------------------------------------------------------------------
+// Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
+// and Clark Cooper
+// Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006 Expat maintainers.
+//
+// Expat - Version 2.0.0 Release Milano 0.83 (PasExpat 2.0.0 RM0.83)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.pasports.org/pasexpat
+// Copyright (c) 2006
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 03.05.2006-Milano: Unit port establishment
+//
+{ expat_external.pas }
+unit
+ expat_external ;
+
+INTERFACE
+
+{$I expat_mode.inc }
+
+{ TYPES DEFINITION }
+type
+{$I expat_external.inc }
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+
+END.
+
diff --git a/src/corelib/render/software/agg-demos/expat-pas/expat_mode.inc b/src/corelib/render/software/agg-demos/expat-pas/expat_mode.inc
new file mode 100755
index 00000000..e6422fe8
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/expat-pas/expat_mode.inc
@@ -0,0 +1,92 @@
+//
+// PasExpat 2.0.0 RM0.83 compiler options configuration file
+//
+
+{DEFINE EXPAT_DEBUG }
+
+//----------------------------------------------------------------------------
+
+{DEFINE XML_UNICODE_WCHAR_T }
+{DEFINE XML_LARGE_SIZE }
+{DEFINE XML_MIN_SIZE }
+
+//----- PLATFORM DEPENDENT CONFIG --------------------------------------------
+
+{IFDEF WIN32 }
+ {$I winconfig.inc }
+
+{ENDIF }
+
+//----------------------------------------------------------------------------
+{$IFDEF XML_UNICODE_WCHAR_T }
+ {$DEFINE XML_UNICODE }
+
+{$ENDIF }
+
+{$IFDEF CPUPOWERPC }
+ {$DEFINE EXPAT_CPU_PPC }
+
+{$ENDIF }
+
+{$IFDEF CPUI386 }
+ {$DEFINE EXPAT_CPU_386 }
+
+{$ENDIF }
+
+{$IFDEF CPU386 }
+ {$DEFINE EXPAT_CPU_386 }
+
+{$ENDIF }
+
+{$IFDEF FPC }
+ {$MODE DELPHI }
+
+{$ENDIF }
+
+//----------------------------------------------------------------------------
+{$IFDEF EXPAT_DEBUG }
+ {$DEFINE EXPAT_FULL_DEBUG }
+
+{$ENDIF }
+
+//----------------------------------------------------------------------------
+{ SWITCHES CONFIGURATION }
+{$IFNDEF FPC }
+ {$A- }{ Fields alignment OFF }
+ {$F+ }{ Far code generation }
+{$ENDIF }
+
+{$B- }{ Complete boolean evaluation }
+{$V- }{ String type checking }
+{$X+ }{ Extended syntax }
+
+{$IFDEF EXPAT_FULL_DEBUG }
+ {$R+ }{ Range checking }
+ {$I+ }{ IO checking }
+ {$Q+ }{ Overflow checking }
+
+ {$IFNDEF FPC }
+ {$O- }{ Code Optimization }
+ {$ENDIF }
+
+ {$D+ }{ Debug Info ON }
+ {$Y+ }{ References Info ON }
+
+{$ELSE }
+ {$R- }{ Range checking }
+ {$I- }{ IO checking }
+ {$Q- }{ Overflow checking }
+
+ { Code Optimization }
+ {$IFNDEF FPC }
+ {$IFDEF EXPAT_OPTIMIZE }
+ {$O+ }
+ {$ELSE }
+ {$O- }
+ {$ENDIF }
+ {$ENDIF }
+
+ {$D- }{ Debug Info OFF }
+ {$Y- }{ References Info OFF }
+
+{$ENDIF }
diff --git a/src/corelib/render/software/agg-demos/expat-pas/iasciitab.inc b/src/corelib/render/software/agg-demos/expat-pas/iasciitab.inc
new file mode 100755
index 00000000..620240cf
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/expat-pas/iasciitab.inc
@@ -0,0 +1,69 @@
+//----------------------------------------------------------------------------
+// Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
+// and Clark Cooper
+// Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006 Expat maintainers.
+//
+// Expat - Version 2.0.0 Release Milano 0.83 (PasExpat 2.0.0 RM0.83)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.pasports.org/pasexpat
+// Copyright (c) 2006
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 17.05.2006-Milano: Unit port establishment
+//
+{ iasciitab.inc }
+{ Like asciitab.h, except that $D has code BT_S rather than BT_CR }
+{ $00 } BT_NONXML ,BT_NONXML ,BT_NONXML ,BT_NONXML ,
+{ $04 } BT_NONXML ,BT_NONXML ,BT_NONXML ,BT_NONXML ,
+{ $08 } BT_NONXML ,BT_S ,BT_LF ,BT_NONXML ,
+{ $0C } BT_NONXML ,BT_S ,BT_NONXML ,BT_NONXML ,
+{ $10 } BT_NONXML ,BT_NONXML ,BT_NONXML ,BT_NONXML ,
+{ $14 } BT_NONXML ,BT_NONXML ,BT_NONXML ,BT_NONXML ,
+{ $18 } BT_NONXML ,BT_NONXML ,BT_NONXML ,BT_NONXML ,
+{ $1C } BT_NONXML ,BT_NONXML ,BT_NONXML ,BT_NONXML ,
+{ $20 } BT_S ,BT_EXCL ,BT_QUOT ,BT_NUM ,
+{ $24 } BT_OTHER ,BT_PERCNT ,BT_AMP ,BT_APOS ,
+{ $28 } BT_LPAR ,BT_RPAR ,BT_AST ,BT_PLUS ,
+{ $2C } BT_COMMA ,BT_MINUS ,BT_NAME ,BT_SOL ,
+{ $30 } BT_DIGIT ,BT_DIGIT ,BT_DIGIT ,BT_DIGIT ,
+{ $34 } BT_DIGIT ,BT_DIGIT ,BT_DIGIT ,BT_DIGIT ,
+{ $38 } BT_DIGIT ,BT_DIGIT ,BT_COLON ,BT_SEMI ,
+{ $3C } BT_LT ,BT_EQUALS ,BT_GT ,BT_QUEST ,
+{ $40 } BT_OTHER ,BT_HEX ,BT_HEX ,BT_HEX ,
+{ $44 } BT_HEX ,BT_HEX ,BT_HEX ,BT_NMSTRT ,
+{ $48 } BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,
+{ $4C } BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,
+{ $50 } BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,
+{ $54 } BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,
+{ $58 } BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,BT_LSQB ,
+{ $5C } BT_OTHER ,BT_RSQB ,BT_OTHER ,BT_NMSTRT ,
+{ $60 } BT_OTHER ,BT_HEX ,BT_HEX ,BT_HEX ,
+{ $64 } BT_HEX ,BT_HEX ,BT_HEX ,BT_NMSTRT ,
+{ $68 } BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,
+{ $6C } BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,
+{ $70 } BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,
+{ $74 } BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,
+{ $78 } BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,BT_OTHER ,
+{ $7C } BT_VERBAR ,BT_OTHER ,BT_OTHER ,BT_OTHER ,
+
diff --git a/src/corelib/render/software/agg-demos/expat-pas/iasciitab_bt_colon_.inc b/src/corelib/render/software/agg-demos/expat-pas/iasciitab_bt_colon_.inc
new file mode 100755
index 00000000..c38172f2
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/expat-pas/iasciitab_bt_colon_.inc
@@ -0,0 +1,68 @@
+//----------------------------------------------------------------------------
+// Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
+// and Clark Cooper
+// Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006 Expat maintainers.
+//
+// Expat - Version 2.0.0 Release Milano 0.83 (PasExpat 2.0.0 RM0.83)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.pasports.org/pasexpat
+// Copyright (c) 2006
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 17.05.2006-Milano: Unit port establishment
+//
+{ iasciitab_bt_colon_.inc }
+{ Like asciitab.h, except that $D has code BT_S rather than BT_CR }
+{ $00 } BT_NONXML ,BT_NONXML ,BT_NONXML ,BT_NONXML ,
+{ $04 } BT_NONXML ,BT_NONXML ,BT_NONXML ,BT_NONXML ,
+{ $08 } BT_NONXML ,BT_S ,BT_LF ,BT_NONXML ,
+{ $0C } BT_NONXML ,BT_S ,BT_NONXML ,BT_NONXML ,
+{ $10 } BT_NONXML ,BT_NONXML ,BT_NONXML ,BT_NONXML ,
+{ $14 } BT_NONXML ,BT_NONXML ,BT_NONXML ,BT_NONXML ,
+{ $18 } BT_NONXML ,BT_NONXML ,BT_NONXML ,BT_NONXML ,
+{ $1C } BT_NONXML ,BT_NONXML ,BT_NONXML ,BT_NONXML ,
+{ $20 } BT_S ,BT_EXCL ,BT_QUOT ,BT_NUM ,
+{ $24 } BT_OTHER ,BT_PERCNT ,BT_AMP ,BT_APOS ,
+{ $28 } BT_LPAR ,BT_RPAR ,BT_AST ,BT_PLUS ,
+{ $2C } BT_COMMA ,BT_MINUS ,BT_NAME ,BT_SOL ,
+{ $30 } BT_DIGIT ,BT_DIGIT ,BT_DIGIT ,BT_DIGIT ,
+{ $34 } BT_DIGIT ,BT_DIGIT ,BT_DIGIT ,BT_DIGIT ,
+{ $38 } BT_DIGIT ,BT_DIGIT ,BT_COLON_ ,BT_SEMI ,
+{ $3C } BT_LT ,BT_EQUALS ,BT_GT ,BT_QUEST ,
+{ $40 } BT_OTHER ,BT_HEX ,BT_HEX ,BT_HEX ,
+{ $44 } BT_HEX ,BT_HEX ,BT_HEX ,BT_NMSTRT ,
+{ $48 } BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,
+{ $4C } BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,
+{ $50 } BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,
+{ $54 } BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,
+{ $58 } BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,BT_LSQB ,
+{ $5C } BT_OTHER ,BT_RSQB ,BT_OTHER ,BT_NMSTRT ,
+{ $60 } BT_OTHER ,BT_HEX ,BT_HEX ,BT_HEX ,
+{ $64 } BT_HEX ,BT_HEX ,BT_HEX ,BT_NMSTRT ,
+{ $68 } BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,
+{ $6C } BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,
+{ $70 } BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,
+{ $74 } BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,
+{ $78 } BT_NMSTRT ,BT_NMSTRT ,BT_NMSTRT ,BT_OTHER ,
+{ $7C } BT_VERBAR ,BT_OTHER ,BT_OTHER ,BT_OTHER ,
diff --git a/src/corelib/render/software/agg-demos/expat-pas/readme.txt b/src/corelib/render/software/agg-demos/expat-pas/readme.txt
new file mode 100755
index 00000000..351a5f9a
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/expat-pas/readme.txt
@@ -0,0 +1,104 @@
+================================================================================
+
+ Expat XML Parser - version 2.0.0
+ Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
+ and Clark Cooper
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006 Expat maintainers.
+
+ Expat - Version 2.0.0 Release Milano 0.83 (PasExpat 2.0.0 RM0.83)
+ Pascal Port By: Milan Marusinec alias Milano
+ milan@marusinec.sk
+ http://www.pasports.org/pasexpat
+ Copyright (c) 2006
+
+================================================================================
+ Introduction
+================================================================================
+
+ Expat is an XML parser library written in C. It is a stream-oriented parser
+ in which an application registers handlers for things the parser might find
+ in the XML document (like start tags).
+
+ Read more at: http://expat.sourceforge.net
+
+ This version of Expat library is the Object Pascal one and this Readme Note
+ is dealing with issues mainly around the Pascal version.
+
+================================================================================
+ Compilation matrix
+================================================================================
+
+ Expat can be currently compiled on the platforms with compilers
+ according to the following matrix:
+
+ +----------------------+---------------------+---------------------+
+ | Platform / Compiler | Free Pascal (FPC) | Delphi (Borland) |
+ +======================+=====================+=====================+
+ | Windows Win32 API | versions 2.0 and up | versions 2.0 and up |
+ +----------------------+---------------------+---------------------+
+ | Linux X11 | versions 2.0 and up | * no support * |
+ +----------------------+---------------------+---------------------+
+ | Mac OS X Carbon | versions 2.0 and up | * no support * |
+ +----------------------+---------------------+---------------------+
+
+================================================================================
+ Port comments
+================================================================================
+
+ The Object Pascal version (PasExpat) was created for the main reason of having
+ a pascal version of the library when porting the SVG demo example in the AggPas
+ porting project, which was dependant on Expat for C.
+
+ This port is based on the C version 2.0.0, which was officialy released
+ on 11 January 2006.
+
+ PasExpat port is the pure manual work. There were used no c_to_pascal conversion
+ utilities and the port is the native-one, which means it uses no external dll
+ bindings - it's all just the native pascal code.
+
+ This Pascal library is an unfinished version marked as 0.83, which means
+ it is approximately 83% of the functionality of the original C library.
+
+ To use the library, just include the "expat" keyword into the uses clause.
+
+ General Pascal port Issues
+ ==========================
+
+ Source code comment marks:
+
+ Here and there around the PasExpat source code, following comment marks
+ can be found:
+
+ {untested} - unit or procedure/function, which was ported but not tested
+
+ {not_implemented} - procedure/function, which was not ported, because
+ related features were not implemented in port
+
+ {hack} - marks some nonstandard solution
+
+ {..} - part of the code, which is unfinished.
+
+ Compiling mode:
+
+ The "expat_mode.inc" is the main compiler mode configuration file.
+ The only one item, you would wish to change is the EXPAT_DEBUG conditional,
+ which turns on/off the debug mode compilation settings. With the
+ EXPAT_DEBUG not defined the range checking for example is turned off,
+ which should lead to building the faster and smallest code.
+
+================================================================================
+ What's next
+================================================================================
+
+ As I said, this version is rather unfinished but sufficient for the AggPas
+ SVG demo to work. In the near future, I am not gonna finish it, but if someone
+ would need it with full functionality, I suggest to pick up this 0.83 release
+ and finish the port.
+
+
+ All for now
+ Yours Milano
+
+================================================================================
+ End of file
+================================================================================
diff --git a/src/corelib/render/software/agg-demos/expat-pas/utf8tab.inc b/src/corelib/render/software/agg-demos/expat-pas/utf8tab.inc
new file mode 100755
index 00000000..d05f745b
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/expat-pas/utf8tab.inc
@@ -0,0 +1,67 @@
+//----------------------------------------------------------------------------
+// Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
+// and Clark Cooper
+// Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006 Expat maintainers.
+//
+// Expat - Version 2.0.0 Release Milano 0.83 (PasExpat 2.0.0 RM0.83)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.pasports.org/pasexpat
+// Copyright (c) 2006
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 17.05.2006-Milano: Unit port establishment
+//
+{ utf8tab.inc }
+{ $80 } BT_TRAIL ,BT_TRAIL ,BT_TRAIL ,BT_TRAIL ,
+{ $84 } BT_TRAIL ,BT_TRAIL ,BT_TRAIL ,BT_TRAIL ,
+{ $88 } BT_TRAIL ,BT_TRAIL ,BT_TRAIL ,BT_TRAIL ,
+{ $8C } BT_TRAIL ,BT_TRAIL ,BT_TRAIL ,BT_TRAIL ,
+{ $90 } BT_TRAIL ,BT_TRAIL ,BT_TRAIL ,BT_TRAIL ,
+{ $94 } BT_TRAIL ,BT_TRAIL ,BT_TRAIL ,BT_TRAIL ,
+{ $98 } BT_TRAIL ,BT_TRAIL ,BT_TRAIL ,BT_TRAIL ,
+{ $9C } BT_TRAIL ,BT_TRAIL ,BT_TRAIL ,BT_TRAIL ,
+{ $A0 } BT_TRAIL ,BT_TRAIL ,BT_TRAIL ,BT_TRAIL ,
+{ $A4 } BT_TRAIL ,BT_TRAIL ,BT_TRAIL ,BT_TRAIL ,
+{ $A8 } BT_TRAIL ,BT_TRAIL ,BT_TRAIL ,BT_TRAIL ,
+{ $AC } BT_TRAIL ,BT_TRAIL ,BT_TRAIL ,BT_TRAIL ,
+{ $B0 } BT_TRAIL ,BT_TRAIL ,BT_TRAIL ,BT_TRAIL ,
+{ $B4 } BT_TRAIL ,BT_TRAIL ,BT_TRAIL ,BT_TRAIL ,
+{ $B8 } BT_TRAIL ,BT_TRAIL ,BT_TRAIL ,BT_TRAIL ,
+{ $BC } BT_TRAIL ,BT_TRAIL ,BT_TRAIL ,BT_TRAIL ,
+{ $C0 } BT_LEAD2 ,BT_LEAD2 ,BT_LEAD2 ,BT_LEAD2 ,
+{ $C4 } BT_LEAD2 ,BT_LEAD2 ,BT_LEAD2 ,BT_LEAD2 ,
+{ $C8 } BT_LEAD2 ,BT_LEAD2 ,BT_LEAD2 ,BT_LEAD2 ,
+{ $CC } BT_LEAD2 ,BT_LEAD2 ,BT_LEAD2 ,BT_LEAD2 ,
+{ $D0 } BT_LEAD2 ,BT_LEAD2 ,BT_LEAD2 ,BT_LEAD2 ,
+{ $D4 } BT_LEAD2 ,BT_LEAD2 ,BT_LEAD2 ,BT_LEAD2 ,
+{ $D8 } BT_LEAD2 ,BT_LEAD2 ,BT_LEAD2 ,BT_LEAD2 ,
+{ $DC } BT_LEAD2 ,BT_LEAD2 ,BT_LEAD2 ,BT_LEAD2 ,
+{ $E0 } BT_LEAD3 ,BT_LEAD3 ,BT_LEAD3 ,BT_LEAD3 ,
+{ $E4 } BT_LEAD3 ,BT_LEAD3 ,BT_LEAD3 ,BT_LEAD3 ,
+{ $E8 } BT_LEAD3 ,BT_LEAD3 ,BT_LEAD3 ,BT_LEAD3 ,
+{ $EC } BT_LEAD3 ,BT_LEAD3 ,BT_LEAD3 ,BT_LEAD3 ,
+{ $F0 } BT_LEAD4 ,BT_LEAD4 ,BT_LEAD4 ,BT_LEAD4 ,
+{ $F4 } BT_LEAD4 ,BT_NONXML ,BT_NONXML ,BT_NONXML ,
+{ $F8 } BT_NONXML ,BT_NONXML ,BT_NONXML ,BT_NONXML ,
+{ $FC } BT_NONXML ,BT_NONXML ,BT_MALFORM ,BT_MALFORM
diff --git a/src/corelib/render/software/agg-demos/expat-pas/winconfig.inc b/src/corelib/render/software/agg-demos/expat-pas/winconfig.inc
new file mode 100755
index 00000000..2b5b01d3
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/expat-pas/winconfig.inc
@@ -0,0 +1,52 @@
+//----------------------------------------------------------------------------
+// Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
+// and Clark Cooper
+// Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006 Expat maintainers.
+//
+// Expat - Version 2.0.0 Release Milano 0.83 (PasExpat 2.0.0 RM0.83)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.pasports.org/pasexpat
+// Copyright (c) 2006
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 18.05.2006-Milano: Unit port establishment
+//
+{ winconfig.inc }
+{$DEFINE XML_NS }
+{$DEFINE XML_DTD }
+{$DEFINE XML_CONTEXT_BYTES }
+
+{ Windows has memmove() available. }
+{$DEFINE HAVE_MEMMOVE }
+
+{ We will assume all Windows platforms are little endian }
+{$DEFINE BYTEORDER_1234 }
+
+const
+ _XML_NS = 1;
+ _XML_DTD = 1;
+
+ _XML_CONTEXT_BYTES = 1024;
+ _BYTEORDER = 1234;
+
diff --git a/src/corelib/render/software/agg-demos/expat-pas/xmlparse.inc b/src/corelib/render/software/agg-demos/expat-pas/xmlparse.inc
new file mode 100755
index 00000000..a27a73eb
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/expat-pas/xmlparse.inc
@@ -0,0 +1,6475 @@
+//----------------------------------------------------------------------------
+// Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
+// and Clark Cooper
+// Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006 Expat maintainers.
+//
+// Expat - Version 2.0.0 Release Milano 0.83 (PasExpat 2.0.0 RM0.83)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.pasports.org/pasexpat
+// Copyright (c) 2006
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 03.05.2006-Milano: Unit port establishment
+// 02.06.2006-Milano: porting
+// 06.06.2006-Milano: -"-
+// 07.06.2006-Milano: doProlog
+// 08.06.2006-Milano: doProlog finished, porting
+// 09.06.2006-Milano: porting
+// 12.06.2006-Milano: -"-
+// 14.06.2006-Milano: -"-
+// 15.06.2006-Milano: doContent
+// 16.06.2006-Milano: porting, storeAtts
+// 17.06.2006-Milano: -"-
+// 20.06.2006-Milano: epilogProcessor, porting
+// 22.06.2006-Milano: appendAttributeValue
+//
+{ xmlparse.inc }
+{$Q- }
+{$R- }
+function poolStoreString(pool : STRING_POOL_ptr; enc : ENCODING_ptr; ptr ,end_ : char_ptr ) : XML_Char_ptr; forward;
+procedure poolFinish (pool : STRING_POOL_ptr ); forward;
+procedure poolClear (pool : STRING_POOL_ptr ); forward;
+procedure poolDestroy (pool : STRING_POOL_ptr ); forward;
+function poolAppendChar (pool : STRING_POOL_ptr; c : char ) : int; forward;
+
+function reportProcessingInstruction(parser : XML_Parser; enc : ENCODING_ptr; start ,end_ : char_ptr ) : int; forward;
+function reportComment (parser : XML_Parser; enc : ENCODING_ptr; start ,end_ : char_ptr ) : int; forward;
+
+function getAttributeId(parser : XML_Parser; enc : ENCODING_ptr; start ,end_ : char_ptr ) : ATTRIBUTE_ID_ptr; forward;
+
+function storeAttributeValue(
+ parser : XML_Parser; enc : ENCODING_ptr; isCdata : XML_Bool;
+ ptr ,end_ : char_ptr; pool : STRING_POOL_ptr ) : XML_Error; forward;
+
+const
+ implicitContext : array[0..40 ] of XML_Char = (
+ 'x' ,'m' ,'l' ,'=' ,'h' ,'t' ,'t' ,'p' ,':' ,'/' ,'/' ,
+ 'w' ,'w' ,'w' ,'.' ,'w' ,'3' ,'.' ,'o' ,'r' ,'g' ,'/' ,
+ 'X' ,'M' ,'L' ,'/' ,'1' ,'9' ,'9' ,'8' ,'/' ,
+ 'n' ,'a' ,'m' ,'e' ,'s' ,'p' ,'a' ,'c' ,'e' ,#0 );
+
+ INIT_TAG_BUF_SIZE = 32; { must be a multiple of sizeof(XML_Char) }
+ INIT_DATA_BUF_SIZE = 1024;
+ INIT_ATTS_SIZE = 16;
+ INIT_ATTS_VERSION = $FFFFFFFF;
+ INIT_BLOCK_SIZE = 1024;
+ INIT_BUFFER_SIZE = 1024;
+
+ EXPAND_SPARE = 24;
+
+ INIT_SCAFFOLD_ELEMENTS = 32;
+
+ INIT_POWER = 6;
+
+type
+ ICHAR_ptr_ptr = ^ICHAR_ptr;
+ ICHAR_ptr = ^ICHAR;
+
+{$IFDEF XML_UNICODE }
+ ICHAR = int16u;
+
+{$ELSE }
+ ICHAR = char;
+
+{$ENDIF }
+
+ HASH_TABLE_ITER_ptr = ^HASH_TABLE_ITER;
+ HASH_TABLE_ITER = record
+ p ,
+ end_ : NAMED_ptr_ptr;
+
+ end;
+
+const
+{$IFDEF XML_UNICODE }
+ XML_ENCODE_MAX = XML_UTF16_ENCODE_MAX;
+
+{$ELSE }
+ XML_ENCODE_MAX = XML_UTF8_ENCODE_MAX;
+
+{$ENDIF }
+
+{ memcmp }
+function memcmp(p1 ,p2 : int8u_ptr; l : int ) : int;
+begin
+ while l > 0 do
+ begin
+ if p1^ <> p2^ then
+ begin
+ result:=p1^ - p2^;
+
+ exit;
+
+ end;
+
+ dec(l );
+ inc(ptrcomp(p1 ) );
+ inc(ptrcomp(p2 ) );
+
+ end;
+
+ result:=0;
+
+end;
+
+{ CHAR_HASH }
+{ Basic character hash algorithm, taken from Python's string hash:
+ h = h * 1000003 ^ character, the constant being a prime number. }
+function CHAR_HASH(h : int32u; c : XML_Char ) : int32u;
+begin
+{$IFDEF XML_UNICODE }
+ result:=(h * $F4243 ) xor int16u(c );
+
+{$ELSE }
+ result:=(h * $F4243 ) xor int8u(c );
+
+{$ENDIF }
+
+end;
+
+{ MUST_CONVERT }
+function MUST_CONVERT(enc : ENCODING_ptr; s : char_ptr ) : int;
+begin
+{$IFDEF XML_UNICODE }
+ result:=
+ int(
+ not boolean(enc.isUtf16 ) or
+ boolean(int32u(s ) and 1 ) );
+
+{$ELSE }
+ result:=int(not boolean(enc.isUtf8 ) );
+
+{$ENDIF }
+
+end;
+
+{ For probing (after a collision) we need a step size relative prime
+ to the hash table size, which is a power of 2. We use double-hashing,
+ since we can calculate a second hash value cheaply by taking those bits
+ of the first hash value that were discarded (masked out) when the table
+ index was calculated: index:=hash and mask, where mask:=table.size - 1.
+ We limit the maximum step size to table.size div 4 (mask shr 2 ) and make
+ it odd, since odd numbers are always relative prime to a power of 2. }
+{ SECOND_HASH }
+function SECOND_HASH(hash ,mask : int32u; power : int8u ) : int8u;
+begin
+ result:=((hash and not mask ) shr (power - 1 ) ) and (mask shr 2 );
+
+end;
+
+{ PROBE_STEP }
+function PROBE_STEP(hash ,mask : int32u; power : int8u ) : int8u;
+begin
+ result:=SECOND_HASH(hash, mask, power) or 1;
+
+end;
+
+{ XML_T }
+function XML_T(x : char ) : XML_Char;
+begin
+ result:=x;
+
+end;
+
+{ XML_L }
+function XML_L(x : char ) : XML_Char;
+begin
+ result:=x;
+
+end;
+
+{ ROUND_UP }
+{ Round up n to be a multiple of sz, where sz is a power of 2. }
+function ROUND_UP(n ,sz : int ) : int;
+begin
+ result:=(n + (sz - 1 ) ) and not(sz - 1 );
+
+end;
+
+{ XmlConvert }
+procedure XmlConvert(enc : ENCODING_ptr; fromP ,fromLim ,toP ,toLim : pointer );
+begin
+{$IFDEF XML_UNICODE }
+ XmlUtf16Convert(enc ,fromP ,fromLim ,toP ,toLim );
+
+{$ELSE }
+ XmlUtf8Convert(enc ,fromP ,fromLim ,toP ,toLim );
+
+{$ENDIF }
+
+end;
+
+{ XmlEncode }
+function XmlEncode(charNumber : int; buf : pointer ) : int;
+begin
+{$IFDEF XML_UNICODE }
+ result:=XmlUtf16Encode(charNumber ,buf );
+
+{$ELSE }
+ result:=XmlUtf8Encode(charNumber ,buf );
+
+{$ENDIF }
+
+end;
+
+{ poolInit }
+procedure poolInit(pool : STRING_POOL_ptr; ms : XML_Memory_Handling_Suite_ptr );
+begin
+ pool.blocks :=NIL;
+ pool.freeBlocks:=NIL;
+ pool.start :=NIL;
+ pool.ptr :=NIL;
+ pool.end_ :=NIL;
+ pool.mem :=ms;
+
+end;
+
+{ hashTableDestroy }
+procedure hashTableDestroy(table : HASH_TABLE_ptr );
+var
+ i : size_t;
+
+begin
+ i:=0;
+
+ while i < table.size do
+ begin
+ if NAMED_ptr_ptr(ptrcomp(table.v ) + i * sizeof(NAMED_ptr ) )^ <> NIL then
+ table.mem.free_fcn(
+ pointer(NAMED_ptr_ptr(ptrcomp(table.v ) + i * sizeof(NAMED_ptr ) )^ ) ,
+ NAMED_ptr_ptr(ptrcomp(table.v ) + i * sizeof(NAMED_ptr ) )^^.alloc );
+
+ inc(i );
+
+ end;
+
+ table.mem.free_fcn(pointer(table.v ) ,table.a );
+
+end;
+
+{ hashTableInit }
+procedure hashTableInit(p : HASH_TABLE_ptr; ms : XML_Memory_Handling_Suite_ptr );
+begin
+ p.power:=0;
+ p.size :=0;
+ p.used :=0;
+ p.v :=NIL;
+ p.mem :=ms;
+
+end;
+
+{ hashTableIterInit }
+procedure hashTableIterInit(iter : HASH_TABLE_ITER_ptr; table : HASH_TABLE_ptr );
+begin
+ iter.p :=table.v;
+ iter.end_:=NAMED_ptr_ptr(ptrcomp(iter.p ) + table.size * sizeof(NAMED_ptr ) );
+
+end;
+
+{ hashTableIterNext }
+function hashTableIterNext(iter : HASH_TABLE_ITER_ptr ) : NAMED_ptr;
+var
+ tem : NAMED_ptr;
+
+begin
+ while iter.p <> iter.end_ do
+ begin
+ tem:=iter.p^;
+
+ inc(ptrcomp(iter.p ) ,sizeof(NAMED_ptr ) );
+
+ if tem <> NIL then
+ begin
+ result:=tem;
+
+ exit;
+
+ end;
+
+ end;
+
+ result:=NIL;
+
+end;
+
+{ dtdCreate }
+function dtdCreate(ms : XML_Memory_Handling_Suite_ptr ) : DTD_ptr;
+var
+ p : DTD_ptr;
+
+begin
+ ms.malloc_fcn(pointer(p ) ,sizeof(DTD ) );
+
+ if p = NIL then
+ begin
+ result:=p;
+
+ exit;
+
+ end;
+
+ poolInit(@p.pool ,ms );
+ poolInit(@p.entityValuePool ,ms );
+
+ hashTableInit(@p.generalEntities ,ms );
+ hashTableInit(@p.elementTypes ,ms );
+ hashTableInit(@p.attributeIds ,ms );
+ hashTableInit(@p.prefixes ,ms );
+
+{$IFDEF XML_DTD }
+ p.paramEntityRead:=XML_FALSE;
+
+ hashTableInit(@p.paramEntities ,ms );
+
+{$ENDIF }
+
+ p.defaultPrefix.name :=NIL;
+ p.defaultPrefix.binding:=NIL;
+
+ p.in_eldecl :=XML_FALSE;
+ p.scaffIndex :=NIL;
+ p.scaffAlloc :=0;
+ p.scaffold :=NIL;
+ p.scaffLevel :=0;
+ p.scaffSize :=0;
+ p.scaffCount :=0;
+ p.contentStringLen:=0;
+
+ p.keepProcessing :=XML_TRUE;
+ p.hasParamEntityRefs:=XML_FALSE;
+ p.standalone :=XML_FALSE;
+
+ result:=p;
+
+end;
+
+{ dtdDestroy }
+procedure dtdDestroy(p : DTD_ptr; isDocEntity : XML_Bool; ms : XML_Memory_Handling_Suite_ptr );
+var
+ iter : HASH_TABLE_ITER;
+
+ e : ELEMENT_TYPE_ptr;
+
+begin
+ hashTableIterInit(@iter ,@p.elementTypes );
+
+ repeat
+ e:=ELEMENT_TYPE_ptr(hashTableIterNext(@iter ) );
+
+ if e = NIL then
+ break;
+
+ if e.allocDefaultAtts <> 0 then
+ ms.free_fcn(pointer(e.defaultAtts ) ,e.defaultAttsAlloc );
+
+ until false;
+
+ hashTableDestroy(@p.generalEntities );
+
+{$IFDEF XML_DTD }
+ hashTableDestroy(@p.paramEntities );
+
+{$ENDIF }
+
+ hashTableDestroy(@p.elementTypes );
+ hashTableDestroy(@p.attributeIds );
+ hashTableDestroy(@p.prefixes );
+
+ poolDestroy(@p.pool );
+ poolDestroy(@p.entityValuePool );
+
+ if isDocEntity <> 0 then
+ begin
+ ms.free_fcn(pointer(p.scaffIndex ) ,p.scaffAlloc );
+ ms.free_fcn(pointer(p.scaffold ) ,sizeof(CONTENT_SCAFFOLD ) );
+
+ end;
+
+ ms.free_fcn(pointer(p ) ,sizeof(DTD ) );
+
+end;
+
+{ handleUnknownEncoding {..}
+function handleUnknownEncoding(parser : XML_Parser; encodingName : XML_Char_ptr ) : XML_Error;
+begin
+end;
+
+{ initializeEncoding }
+function initializeEncoding(parser : XML_Parser ) : XML_Error;
+var
+ s : char_ptr;
+ ok : int;
+
+begin
+{$IFDEF XML_UNICODE {..}
+
+
+{$ELSE }
+ s:=pointer(parser.m_protocolEncodingName );
+
+{$ENDIF }
+
+ if parser.m_ns <> 0 then
+ ok:=XmlInitEncodingNS(@parser.m_initEncoding ,@parser.m_encoding ,pointer(s ) )
+ else
+ ok:=XmlInitEncoding(@parser.m_initEncoding ,@parser.m_encoding ,pointer(s ) );
+
+ if ok <> 0 then
+ result:=XML_ERROR_NONE
+ else
+ result:=handleUnknownEncoding(parser ,parser.m_protocolEncodingName );
+
+end;
+
+{ reportDefault {..}
+procedure reportDefault(parser : XML_Parser; enc : ENCODING_ptr; start ,end_ : char_ptr );
+begin
+end;
+
+{ getContext {..}
+function getContext(parser : XML_Parser ) : XML_Char_ptr;
+begin
+end;
+
+{ processXmlDecl }
+function processXmlDecl(parser : XML_Parser; isGeneralTextEntity : int; s ,next : char_ptr ) : XML_Error;
+var
+ encodingName ,version ,versionend : char_ptr;
+
+ storedEncName ,storedversion : XML_Char_ptr;
+
+ newEncoding : ENCODING_ptr;
+
+ standalone ,ok : int;
+
+ result_ : XML_Error;
+
+begin
+ encodingName :=NIL;
+ storedEncName:=NIL;
+ newEncoding :=NIL;
+ version :=NIL;
+ storedversion:=NIL;
+ standalone :=-1;
+
+ if parser.m_ns <> 0 then
+ ok:=
+ XmlParseXmlDeclNS(
+ isGeneralTextEntity ,parser.m_encoding ,pointer(s ) ,pointer(next ) ,
+ @parser.m_eventPtr ,@version ,@versionend ,@encodingName ,
+ @newEncoding ,@standalone )
+ else
+ ok:=
+ XmlParseXmlDecl(
+ isGeneralTextEntity ,parser.m_encoding ,pointer(s ) ,pointer(next ) ,
+ @parser.m_eventPtr ,@version ,@versionend ,@encodingName ,
+ @newEncoding ,@standalone );
+
+ if ok = 0 then
+ if isGeneralTextEntity <> 0 then
+ begin
+ result:=XML_ERROR_TEXT_DECL;
+
+ exit;
+
+ end
+ else
+ begin
+ result:=XML_ERROR_XML_DECL;
+
+ exit;
+
+ end;
+
+ if (isGeneralTextEntity = 0 ) and
+ (standalone = 1 ) then
+ begin
+ parser.m_dtd.standalone:=XML_TRUE;
+
+ {$IFDEF XML_DTD }
+ if parser.m_paramEntityParsing = XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE then
+ parser.m_paramEntityParsing:=XML_PARAM_ENTITY_PARSING_NEVER;
+
+ {$ENDIF }
+
+ end;
+
+ if @parser.m_xmlDeclHandler <> NIL then
+ begin
+ if encodingName <> NIL then
+ begin
+ storedEncName:=
+ poolStoreString(
+ @parser.m_temp2Pool ,
+ parser.m_encoding ,
+ encodingName,
+ char_ptr(ptrcomp(encodingName ) + XmlNameLength(parser.m_encoding ,pointer(encodingName ) ) ) );
+
+ if storedEncName = NIL then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ poolFinish(@parser.m_temp2Pool );
+
+ end;
+
+ if version <> NIL then
+ begin
+ storedversion:=
+ poolStoreString(
+ @parser.m_temp2Pool ,
+ parser.m_encoding ,
+ version ,
+ char_ptr(ptrcomp(versionend ) - parser.m_encoding.minBytesPerChar ) );
+
+ if storedversion = NIL then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ end;
+
+ parser.m_xmlDeclHandler(
+ parser.m_handlerArg ,storedversion ,storedEncName ,standalone );
+
+ end
+ else
+ if @parser.m_defaultHandler <> NIL then
+ reportDefault(parser ,parser.m_encoding ,s ,next );
+
+ if parser.m_protocolEncodingName = NIL then
+ begin
+ if newEncoding <> NIL then
+ begin
+ if newEncoding.minBytesPerChar <> parser.m_encoding.minBytesPerChar then
+ begin
+ parser.m_eventPtr:=encodingName;
+
+ result:=XML_ERROR_INCORRECT_ENCODING;
+
+ exit;
+
+ end;
+
+ parser.m_encoding:=newEncoding;
+
+ end
+ else
+ if encodingName <> NIL then
+ begin
+ if storedEncName = NIL then
+ begin
+ storedEncName:=
+ poolStoreString(
+ @parser.m_temp2Pool ,parser.m_encoding ,encodingName ,
+ char_ptr(ptrcomp(encodingName ) + XmlNameLength(parser.m_encoding ,pointer(encodingName ) ) ) );
+
+ if storedEncName = NIL then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ end;
+
+ result_:=handleUnknownEncoding(parser ,storedEncName );
+
+ poolClear(@parser.m_temp2Pool );
+
+ if result_ = XML_ERROR_UNKNOWN_ENCODING then
+ parser.m_eventPtr:=encodingName;
+
+ result:=result_;
+
+ exit;
+
+ end;
+
+ end;
+
+ if (storedEncName <> NIL ) or
+ (storedversion <> NIL ) then
+ poolClear(@parser.m_temp2Pool );
+
+ result:=XML_ERROR_NONE;
+
+end;
+
+{ poolClear }
+procedure poolClear(pool : STRING_POOL_ptr );
+var
+ p ,tem : BLOCK_ptr;
+
+begin
+ if pool.freeBlocks = NIL then
+ pool.freeBlocks:=pool.blocks
+
+ else
+ begin
+ p:=pool.blocks;
+
+ while p <> NIL do
+ begin
+ tem :=p.next;
+ p.next :=pool.freeBlocks;
+ pool.freeBlocks:=p;
+ p :=tem;
+
+ end;
+
+ end;
+
+ pool.blocks:=NIL;
+ pool.start :=NIL;
+ pool.ptr :=NIL;
+ pool.end_ :=NIL;
+
+end;
+
+{ poolDestroy }
+procedure poolDestroy(pool : STRING_POOL_ptr );
+var
+ p ,tem : BLOCK_ptr;
+
+begin
+ p:=pool.blocks;
+
+ while p <> NIL do
+ begin
+ tem:=p.next;
+
+ pool.mem.free_fcn(pointer(p ) ,p.alloc );
+
+ p:=tem;
+
+ end;
+
+ p:=pool.freeBlocks;
+
+ while p <> NIL do
+ begin
+ tem:=p.next;
+
+ pool.mem.free_fcn(pointer(p ) ,p.alloc );
+
+ p:=tem;
+
+ end;
+
+end;
+
+{ poolGrow }
+function poolGrow(pool : STRING_POOL_ptr ) : XML_Bool;
+var
+ tem : BLOCK_ptr;
+
+ blockSize : int;
+
+begin
+ if pool.freeBlocks <> NIL then
+ begin
+ if pool.start = NIL then
+ begin
+ pool.blocks :=pool.freeBlocks;
+ pool.freeBlocks :=pool.freeBlocks.next;
+ pool.blocks.next:=NIL;
+
+ pool.start:=@pool.blocks.s;
+ pool.end_ :=XML_Char_ptr(ptrcomp(pool.start ) + pool.blocks.size * sizeof(XML_Char ) );
+ pool.ptr :=pool.start;
+
+ result:=XML_TRUE;
+
+ exit;
+
+ end;
+
+ if ptrcomp(pool.end_ ) - ptrcomp(pool.start ) < pool.freeBlocks.size then
+ begin
+ tem:=pool.freeBlocks.next;
+
+ pool.freeBlocks.next:=pool.blocks;
+ pool.blocks :=pool.freeBlocks;
+ pool.freeBlocks :=tem;
+
+ move(
+ pool.start^ ,
+ pointer(@pool.blocks.s )^ ,
+ ptrcomp(pool.end_ ) - ptrcomp(pool.start ) );
+
+ pool.ptr :=XML_Char_ptr(ptrcomp(@pool.blocks.s ) + ptrcomp(pool.ptr ) - ptrcomp(pool.start ) );
+ pool.start:=@pool.blocks.s;
+ pool.end_ :=XML_Char_ptr(ptrcomp(pool.start ) + pool.blocks.size * sizeof(XML_Char ) );
+
+ result:=XML_TRUE;
+
+ exit;
+
+ end;
+
+ end;
+
+ if (pool.blocks <> NIL ) and
+ (pool.start = @pool.blocks.s ) then
+ begin
+ blockSize:=(ptrcomp(pool.end_ ) - ptrcomp(pool.start ) ) * 2 div sizeof(XML_Char );
+
+ pool.mem.realloc_fcn(
+ pointer(pool.blocks ) ,
+ pool.blocks.alloc ,
+ (sizeof(BLOCK_ptr ) + sizeof(int ) * 2 ) + blockSize * sizeof(XML_Char ) );
+
+ if pool.blocks = NIL then
+ begin
+ result:=XML_FALSE;
+
+ exit;
+
+ end
+ else
+ pool.blocks.alloc:=(sizeof(BLOCK_ptr ) + sizeof(int ) * 2 ) + blockSize * sizeof(XML_Char );
+
+ pool.blocks.size:=blockSize;
+
+ pool.ptr :=XML_Char_ptr(ptrcomp(@pool.blocks.s ) + (ptrcomp(pool.ptr ) - ptrcomp(pool.start ) ) );
+ pool.start:=@pool.blocks.s;
+ pool.end_ :=XML_Char_ptr(ptrcomp(pool.start ) + blockSize * sizeof(XML_Char ) );
+
+ end
+ else
+ begin
+ blockSize:=(ptrcomp(pool.end_ ) - ptrcomp(pool.start ) ) div sizeof(XML_Char );
+
+ if blockSize < INIT_BLOCK_SIZE then
+ blockSize:=INIT_BLOCK_SIZE
+ else
+ blockSize:=blockSize * 2;
+
+ pool.mem.malloc_fcn(
+ pointer(tem ) ,
+ (sizeof(BLOCK_ptr ) + sizeof(int ) * 2 ) + blockSize * sizeof(XML_Char ) );
+
+ if tem = NIL then
+ begin
+ result:=XML_FALSE;
+
+ exit;
+
+ end;
+
+ tem.size :=blockSize;
+ tem.alloc:=(sizeof(BLOCK_ptr ) + sizeof(int ) * 2 ) + blockSize * sizeof(XML_Char );
+ tem.next :=pool.blocks;
+
+ pool.blocks:=tem;
+
+ if pool.ptr <> pool.start then
+ move(
+ pool.start^ ,
+ pointer(@tem.s )^ ,
+ ptrcomp(pool.ptr ) - ptrcomp(pool.start ) );
+
+ pool.ptr :=XML_Char_ptr(ptrcomp(@tem.s ) + (ptrcomp(pool.ptr ) - ptrcomp(pool.start ) ) * sizeof(XML_Char ) );
+ pool.start:=@tem.s;
+ pool.end_ :=XML_Char_ptr(ptrcomp(@tem.s ) + blockSize * sizeof(XML_Char ) );
+
+ end;
+
+ result:=XML_TRUE;
+
+end;
+
+{ poolAppend }
+function poolAppend(pool : STRING_POOL_ptr; enc : ENCODING_ptr; ptr ,end_ : char_ptr ) : XML_Char_ptr;
+begin
+ if (pool.ptr = NIL ) and
+ (poolGrow(pool ) = 0 ) then
+ begin
+ result:=NIL;
+
+ exit;
+
+ end;
+
+ repeat
+ XmlConvert(
+ enc ,@ptr ,end_ ,
+ ICHAR_ptr_ptr(@pool.ptr ) ,
+ ICHAR_ptr(pool.end_ ) );
+
+ if ptr = end_ then
+ break;
+
+ if poolGrow(pool ) = 0 then
+ result:=NIL;
+
+ until false;
+
+ result:=pool.start;
+
+end;
+
+{ poolStoreString }
+function poolStoreString(pool : STRING_POOL_ptr; enc : ENCODING_ptr; ptr ,end_ : char_ptr ) : XML_Char_ptr;
+begin
+ if poolAppend(pool ,enc ,ptr ,end_ ) = NIL then
+ begin
+ result:=NIL;
+
+ exit;
+
+ end;
+
+ if (pool.ptr = pool.end_ ) and
+ (poolGrow(pool ) = 0 ) then
+ begin
+ result:=NIL;
+
+ exit;
+
+ end;
+
+ pool.ptr^:=XML_Char(0 );
+
+ inc(ptrcomp(pool.ptr ) );
+
+ result:=pool.start;
+
+end;
+
+{ poolCopyString }
+function poolCopyString(pool : STRING_POOL_ptr; s : XML_Char_ptr ) : XML_Char_ptr;
+label
+ _w0 ;
+
+begin
+ goto _w0;
+
+ while s^ <> XML_Char(0 ) do
+ begin
+ _w0:
+ if poolAppendChar(pool ,s^ ) = 0 then
+ begin
+ result:=NIL;
+
+ exit;
+
+ end;
+
+ inc(ptrcomp(s ) ,sizeof(XML_Char ) );
+
+ end;
+
+ s:=pool.start;
+
+ poolFinish(pool );
+
+ result:=s;
+
+end;
+
+{ poolAppendString {..}
+function poolAppendString(pool : STRING_POOL_ptr; s : XML_Char_ptr ) : XML_Char_ptr;
+begin
+end;
+
+{ poolStart }
+function poolStart(pool : STRING_POOL_ptr ) : XML_Char_ptr;
+begin
+ result:=pool.start;
+
+end;
+
+{ poolLength }
+function poolLength(pool : STRING_POOL_ptr ) : int;
+begin
+ result:=ptrcomp(pool.ptr ) - ptrcomp(pool.start );
+
+end;
+
+{ poolChop }
+procedure poolChop(pool : STRING_POOL_ptr );
+begin
+ dec(ptrcomp(pool.ptr ) ,sizeof(XML_Char ) );
+
+end;
+
+{ poolLastChar }
+function poolLastChar(pool : STRING_POOL_ptr ) : XML_Char;
+begin
+ result:=XML_Char_ptr(ptrcomp(pool.ptr ) - 1 * sizeof(XML_Char ) )^;
+
+end;
+
+{ poolDiscard }
+procedure poolDiscard(pool : STRING_POOL_ptr );
+begin
+ pool.ptr:=pool.start;
+
+end;
+
+{ poolFinish }
+procedure poolFinish(pool : STRING_POOL_ptr );
+begin
+ pool.start:=pool.ptr;
+
+end;
+
+{ poolAppendChar }
+function poolAppendChar(pool : STRING_POOL_ptr; c : char ) : int;
+begin
+ if (pool.ptr = pool.end_ ) and
+ (poolGrow(pool ) = 0 ) then
+ result:=0
+ else
+ begin
+ pool.ptr^:=c;
+
+ inc(ptrcomp(pool.ptr ) );
+
+ result:=1;
+
+ end;
+
+end;
+
+{ keyeq }
+function keyeq(s1 ,s2 : KEY ) : XML_Bool;
+begin
+ while s1^ = s2^ do
+ begin
+ if s1^ = #0 then
+ begin
+ result:=XML_TRUE;
+
+ exit;
+
+ end;
+
+ inc(ptrcomp(s1 ) ,sizeof(XML_Char ) );
+ inc(ptrcomp(s2 ) ,sizeof(XML_Char ) );
+
+ end;
+
+ result:=XML_FALSE;
+
+end;
+
+{ hash }
+function hash(s : KEY ) : int32u;
+var
+ h : int32u;
+
+begin
+ h:=0;
+
+ while s^ <> XML_Char(0 ) do
+ begin
+ h:=CHAR_HASH(h ,s^ );
+
+ inc(ptrcomp(s ) ,sizeof(XML_Char ) );
+
+ end;
+
+ result:=h;
+
+end;
+
+{ lookup }
+function lookup(table : HASH_TABLE_ptr; name : KEY; createSize : size_t ) : NAMED_ptr;
+var
+ i ,tsize ,newSize ,j : size_t;
+
+ h ,mask ,newMask ,newHash : int32u;
+
+ step ,newPower : int8u;
+
+ newV : NAMED_ptr_ptr;
+
+begin
+ if table.size = 0 then
+ begin
+ if createSize = 0 then
+ begin
+ result:=NIL;
+
+ exit;
+
+ end;
+
+ table.power:=INIT_POWER;
+
+ { table->size is a power of 2 }
+ table.size:=size_t(1 shl INIT_POWER );
+
+ tsize:=table.size * sizeof(NAMED_ptr );
+
+ table.mem.malloc_fcn(pointer(table.v ) ,tsize );
+
+ if table.v = NIL then
+ begin
+ table.size:=0;
+
+ result:=NIL;
+
+ exit;
+
+ end
+ else
+ table.a:=tsize;
+
+ fillchar(table.v^ ,tsize ,0 );
+
+ i:=hash(name ) and (table.size - 1 );
+
+ end
+ else
+ begin
+ h :=hash(name );
+ mask:=table.size - 1;
+ step:=0;
+ i :=h and mask;
+
+ while NAMED_ptr_ptr(ptrcomp(table.v ) + i * sizeof(NAMED_ptr ) )^ <> NIL do
+ begin
+ if keyeq(
+ name ,
+ NAMED_ptr_ptr(ptrcomp(table.v ) + i * sizeof(NAMED_ptr ) )^^.name ) <> 0 then
+ begin
+ result:=NAMED_ptr_ptr(ptrcomp(table.v ) + i * sizeof(NAMED_ptr ) )^;
+
+ exit;
+
+ end;
+
+ if step = 0 then
+ step:=PROBE_STEP(h ,mask ,table.power );
+
+ if i < step then
+ inc(i ,table.size - step )
+ else
+ dec(i ,step );
+
+ end;
+
+ if createSize = 0 then
+ begin
+ result:=NIL;
+
+ exit;
+
+ end;
+
+ { check for overflow (table is half full) }
+ if table.used shr (table.power - 1 ) <> 0 then
+ begin
+ newPower:=table.power + 1;
+ newSize :=size_t(1 shl newPower );
+ newMask :=newSize - 1;
+ tsize :=newSize * sizeof(NAMED_ptr );
+
+ table.mem.malloc_fcn(pointer(newV ) ,tsize );
+
+ if newV = NIL then
+ begin
+ result:=NIL;
+
+ exit;
+
+ end;
+
+ fillchar(newV^ ,tsize ,0 );
+
+ i:=0;
+
+ while i < table.size do
+ begin
+ if NAMED_ptr_ptr(ptrcomp(table.v ) + i * sizeof(NAMED_ptr ) )^ <> NIL then
+ begin
+ newHash:=hash(NAMED_ptr_ptr(ptrcomp(table.v ) + i * sizeof(NAMED_ptr ) )^^.name );
+ j :=newHash and newMask;
+ step :=0;
+
+ while NAMED_ptr_ptr(ptrcomp(newV ) + j * sizeof(NAMED_ptr ) )^ <> NIL do
+ begin
+ if step = 0 then
+ step:=PROBE_STEP(newHash ,newMask ,newPower );
+
+ if j < step then
+ inc(j ,newSize - step )
+ else
+ dec(j ,step );
+
+ end;
+
+ NAMED_ptr_ptr(ptrcomp(newV ) + j * sizeof(NAMED_ptr ) )^:=
+ NAMED_ptr_ptr(ptrcomp(table.v ) + i * sizeof(NAMED_ptr ) )^;
+
+ end;
+
+ inc(i );
+
+ end;
+
+ table.mem.free_fcn(pointer(table.v ) ,table.a );
+
+ table.v :=newV;
+ table.a :=tsize;
+ table.power:=newPower;
+ table.size :=newSize;
+
+ i :=h and newMask;
+ step:=0;
+
+ while NAMED_ptr_ptr(ptrcomp(table.v ) + i * sizeof(NAMED_ptr ) )^ <> NIL do
+ begin
+ if step = 0 then
+ step:=PROBE_STEP(h ,newMask ,newPower );
+
+ if i < step then
+ inc(i ,newSize - step )
+ else
+ dec(i ,step );
+
+ end;
+
+ end;
+
+ end;
+
+ table.mem.malloc_fcn(
+ pointer(NAMED_ptr_ptr(ptrcomp(table.v ) + i * sizeof(NAMED_ptr ) )^ ) ,
+ createSize );
+
+ if NAMED_ptr_ptr(ptrcomp(table.v ) + i * sizeof(NAMED_ptr ) )^ = NIL then
+ begin
+ result:=NIL;
+
+ exit;
+
+ end;
+
+ fillchar(NAMED_ptr_ptr(ptrcomp(table.v ) + i * sizeof(NAMED_ptr ) )^^ ,createSize ,0 );
+
+ NAMED_ptr_ptr(ptrcomp(table.v ) + i * sizeof(NAMED_ptr ) )^^.name :=name;
+ NAMED_ptr_ptr(ptrcomp(table.v ) + i * sizeof(NAMED_ptr ) )^^.alloc:=createSize;
+
+ inc(table.used );
+
+ result:=NAMED_ptr_ptr(ptrcomp(table.v ) + i * sizeof(NAMED_ptr ) )^;
+
+end;
+
+{ normalizePublicId }
+procedure normalizePublicId(publicId : XML_Char_ptr );
+var
+ p ,s : XML_Char_ptr;
+
+begin
+ p:=publicId;
+ s:=publicId;
+
+ while s^ <> XML_Char(0 ) do
+ begin
+ case s^ of
+ XML_Char($20 ) ,XML_Char($D ) ,XML_Char($A ) :
+ if (p <> publicId ) and
+ (XML_Char_ptr(ptrcomp(p ) -1 * sizeof(XML_Char ) )^ <> XML_Char($20 ) ) then
+ begin
+ p^:=XML_Char($20 );
+
+ inc(ptrcomp(p ) ,sizeof(XML_Char ) );
+
+ end;
+
+ else
+ begin
+ p^:=s^;
+
+ inc(ptrcomp(p ) ,sizeof(XML_Char ) );
+
+ end;
+
+ end;
+
+ inc(ptrcomp(s ) ,sizeof(XML_Char ) );
+
+ end;
+
+ if (p <> publicId ) and
+ (XML_Char_ptr(ptrcomp(p ) -1 * sizeof(XML_Char ) )^ = XML_Char($20 ) ) then
+ dec(ptrcomp(p ) ,sizeof(XML_Char ) );
+
+ p^:=XML_T(#0 );
+
+end;
+
+{ setElementTypePrefix {..}
+function setElementTypePrefix(parser : XML_Parser; elementType : ELEMENT_TYPE_ptr ) : int;
+begin
+end;
+
+{ addBinding {..}
+{ addBinding overwrites the value of prefix.binding without checking.
+ Therefore one must keep track of the old value outside of addBinding. }
+function addBinding(
+ parser : XML_Parser; prefix : PREFIX_ptr; attId : ATTRIBUTE_ID_ptr;
+ uri : XML_Char_ptr; bindingsPtr : BINDING_ptr_ptr ) : XML_Error;
+begin
+end;
+
+{ storeRawNames }
+{ Initially tag.rawName always points into the parse buffer;
+ for those TAG instances opened while the current parse buffer was
+ processed, and not yet closed, we need to store tag.rawName in a more
+ permanent location, since the parse buffer is about to be discarded. }
+function storeRawNames(parser : XML_Parser ) : XML_Bool;
+var
+ tag : TAG_ptr;
+
+ bufSize ,nameLen : int;
+
+ rawNameBuf ,temp : char_ptr;
+
+begin
+ tag:=parser.m_tagStack;
+
+ while tag <> NIL do
+ begin
+ nameLen :=sizeof(XML_Char ) * (tag.name.strLen + 1 );
+ rawNameBuf:=char_ptr(ptrcomp(tag.buf ) + nameLen );
+
+ { Stop if already stored. Since tagStack is a stack, we can stop
+ at the first entry that has already been copied; everything
+ below it in the stack is already been accounted for in a
+ previous call to this function. }
+ if tag.rawName = rawNameBuf then
+ break;
+
+ { For re-use purposes we need to ensure that the
+ size of tag.buf is a multiple of sizeof(XML_Char ). }
+ bufSize:=nameLen + ROUND_UP(tag.rawNameLength ,sizeof(XML_Char ) );
+
+ if bufSize > ptrcomp(tag.bufEnd ) - ptrcomp(tag.buf ) then
+ begin
+ if parser.m_mem.realloc_fcn(pointer(tag.buf ) ,tag.alloc ,bufSize ) then
+ temp:=tag.buf
+ else
+ temp:=NIL;
+
+ if temp = NIL then
+ begin
+ result:=XML_FALSE;
+
+ exit;
+
+ end;
+
+ tag.alloc:=bufSize;
+
+ { if tag.name.str points to tag.buf (only when namespace
+ processing is off) then we have to update it }
+ if tag.name.str = XML_Char_ptr(tag.buf ) then
+ tag.name.str:=XML_Char_ptr(temp );
+
+ { if tag->name.localPart is set (when namespace processing is on)
+ then update it as well, since it will always point into tag->buf }
+ if tag.name.localPart <> NIL then
+ tag.name.localPart:=
+ XML_Char_ptr(
+ ptrcomp(temp ) +
+ (ptrcomp(tag.name.localPart ) - ptrcomp(tag.buf ) ) );
+
+ tag.buf :=temp;
+ tag.bufEnd:=char_ptr(ptrcomp(temp ) + bufSize );
+ rawNameBuf:=char_ptr(ptrcomp(temp ) + nameLen );
+
+ end;
+
+ move(tag.rawName^ ,rawNameBuf^ ,tag.rawNameLength );
+
+ tag.rawName:=rawNameBuf;
+ tag :=tag.parent;
+
+ end;
+
+ result:=XML_TRUE;
+
+end;
+
+{ storeAtts }
+{ Precondition: all arguments must be non-NULL;
+ Purpose:
+ - normalize attributes
+ - check attributes for well-formedness
+ - generate namespace aware attribute names (URI, prefix)
+ - build list of attributes for startElementHandler
+ - default attributes
+ - process namespace declarations (check and report them)
+ - generate namespace aware element name (URI, prefix) }
+function storeAtts(
+ parser : XML_Parser; enc : ENCODING_ptr;
+ attStr : char_ptr; tagNamePtr : TAG_NAME_ptr;
+ bindingsPtr : BINDING_ptr_ptr ) : XML_Error;
+var
+ dtd : DTD_ptr;
+
+ elementType : ELEMENT_TYPE_ptr;
+
+ nDefaultAtts ,attIndex ,prefixLen ,i ,n ,nPrefixes ,oldAttsSize ,j ,nsAttsSize : int;
+
+ version ,uriHash ,mask : int32u;
+
+ step : int8u;
+
+ appAtts : XML_Char_ptr_ptr; { the attribute list for the application }
+
+ uri ,localPart ,name ,s ,s1 ,s2 : XML_Char_ptr;
+
+ c : XML_Char;
+
+ binding ,b : BINDING_ptr;
+
+ attId ,id : ATTRIBUTE_ID_ptr;
+
+ result_ : XML_Error;
+
+ isCdata : XML_Bool;
+
+ da : DEFAULT_ATTRIBUTE_ptr;
+
+ p : TAG_ptr;
+
+label
+ _w0 ,_w1 ;
+
+begin
+ dtd:=parser.m_dtd; { save one level of indirection }
+
+ attIndex :=0;
+ nPrefixes:=0;
+
+{ lookup the element type name }
+ elementType:=
+ ELEMENT_TYPE_ptr(lookup(
+ @dtd.elementTypes ,tagNamePtr.str ,0 ) );
+
+ if elementType = NIL then
+ begin
+ name:=poolCopyString(@dtd.pool ,tagNamePtr.str );
+
+ if name = NIL then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ elementType:=
+ ELEMENT_TYPE_ptr(lookup(
+ @dtd.elementTypes ,name ,sizeof(ELEMENT_TYPE ) ) );
+
+ if elementType = NIL then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ if (parser.m_ns <> 0 ) and
+ (setElementTypePrefix(parser ,elementType ) = 0 ) then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ end;
+
+ nDefaultAtts:=elementType.nDefaultAtts;
+
+{ get the attributes from the tokenizer }
+ n:=XmlGetAttributes(enc ,pointer(attStr ) ,parser.m_attsSize ,parser.m_atts );
+
+ if n + nDefaultAtts > parser.m_attsSize then
+ begin
+ oldAttsSize :=parser.m_attsSize;
+ parser.m_attsSize:=n + nDefaultAtts + INIT_ATTS_SIZE;
+
+ if not parser.m_mem.realloc_fcn(
+ pointer(parser.m_atts ) ,
+ parser.m_attsAlloc ,
+ parser.m_attsSize * sizeof(ATTRIBUTE ) ) then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end
+ else
+ parser.m_attsAlloc:=parser.m_attsSize * sizeof(ATTRIBUTE );
+
+ if n > oldAttsSize then
+ XmlGetAttributes(enc ,pointer(attStr ) ,n ,parser.m_atts );
+
+ end;
+
+ appAtts:=XML_Char_ptr_ptr(parser.m_atts );
+
+ i:=0;
+
+ while i < n do
+ begin
+ { add the name and value to the attribute list }
+ attId:=
+ getAttributeId(
+ parser ,enc ,
+ pointer(ATTRIBUTE_ptr(ptrcomp(parser.m_atts ) + i * sizeof(ATTRIBUTE ) )^.name ) ,
+ pointer(
+ ptrcomp(ATTRIBUTE_ptr(ptrcomp(parser.m_atts ) + i * sizeof(ATTRIBUTE ) )^.name ) +
+ XmlNameLength(enc ,ATTRIBUTE_ptr(ptrcomp(parser.m_atts ) + i * sizeof(ATTRIBUTE ) )^.name ) ) );
+
+ if attId = NIL then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ { Detect duplicate attributes by their QNames. This does not work when
+ namespace processing is turned on and different prefixes for the same
+ namespace are used. For this case we have a check further down. }
+ if XML_Char_ptr(ptrcomp(attId.name ) - 1 * sizeof(XML_Char ) )^ <> XML_Char(0 ) then
+ begin
+ if enc = parser.m_encoding then
+ parser.m_eventPtr:=pointer(ATTRIBUTE_ptr(ptrcomp(parser.m_atts ) + i * sizeof(ATTRIBUTE ) )^.name );
+
+ result:=XML_ERROR_DUPLICATE_ATTRIBUTE;
+
+ exit;
+
+ end;
+
+ XML_Char_ptr(ptrcomp(attId.name ) - 1 * sizeof(XML_Char ) )^:=XML_Char(1 );
+
+ XML_Char_ptr_ptr(ptrcomp(appAtts ) + attIndex * sizeof(XML_Char_ptr ) )^:=attId.name;
+
+ inc(attIndex );
+
+ if ATTRIBUTE_ptr(ptrcomp(parser.m_atts ) + i * sizeof(ATTRIBUTE ) )^.normalized = #0 then
+ begin
+ isCdata:=XML_TRUE;
+
+ { figure out whether declared as other than CDATA }
+ if attId.maybeTokenized <> 0 then
+ begin
+ j:=0;
+
+ while j < nDefaultAtts do
+ begin
+ if attId = DEFAULT_ATTRIBUTE_ptr(ptrcomp(elementType.defaultAtts ) + j * sizeof(DEFAULT_ATTRIBUTE ) )^.id then
+ begin
+ isCdata:=DEFAULT_ATTRIBUTE_ptr(ptrcomp(elementType.defaultAtts ) + j * sizeof(DEFAULT_ATTRIBUTE ) )^.isCdata;
+
+ break;
+
+ end;
+
+ inc(j );
+
+ end;
+
+ end;
+
+ { normalize the attribute value }
+ result_:=
+ storeAttributeValue(
+ parser ,enc ,isCdata ,
+ pointer(ATTRIBUTE_ptr(ptrcomp(parser.m_atts ) + i * sizeof(ATTRIBUTE ) )^.valuePtr ) ,
+ pointer(ATTRIBUTE_ptr(ptrcomp(parser.m_atts ) + i * sizeof(ATTRIBUTE ) )^.valueEnd ) ,
+ @parser.m_tempPool );
+
+ if result_ <> XML_Error(0 ) then
+ begin
+ result:=result_;
+
+ exit;
+
+ end;
+
+ XML_Char_ptr_ptr(ptrcomp(appAtts ) + attIndex * sizeof(XML_Char_ptr ) )^:=poolStart(@parser.m_tempPool );
+
+ poolFinish(@parser.m_tempPool );
+
+ end
+ else
+ begin
+ { the value did not need normalizing }
+ XML_Char_ptr_ptr(ptrcomp(appAtts ) + attIndex * sizeof(XML_Char_ptr ) )^:=
+ poolStoreString(
+ @parser.m_tempPool ,enc ,
+ pointer(ATTRIBUTE_ptr(ptrcomp(parser.m_atts ) + i * sizeof(ATTRIBUTE ) )^.valuePtr ) ,
+ pointer(ATTRIBUTE_ptr(ptrcomp(parser.m_atts ) + i * sizeof(ATTRIBUTE ) )^.valueEnd ) );
+
+ if XML_Char_ptr_ptr(ptrcomp(appAtts ) + attIndex * sizeof(XML_Char_ptr ) )^ = NIL then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ poolFinish(@parser.m_tempPool );
+
+ end;
+
+ { handle prefixed attribute names }
+ if attId.prefix <> NIL then
+ if attId.xmlns <> 0 then
+ begin
+ { deal with namespace declarations here }
+ result_:=
+ addBinding(
+ parser ,attId.prefix ,attId ,
+ XML_Char_ptr_ptr(ptrcomp(appAtts ) + attIndex * sizeof(XML_Char_ptr ) )^ ,
+ bindingsPtr );
+
+ if result_ <> XML_Error(0 ) then
+ begin
+ result:=result_;
+
+ exit;
+
+ end;
+
+ dec(attIndex );
+
+ end
+ else
+ begin
+ { deal with other prefixed names later }
+ inc(attIndex );
+ inc(nPrefixes );
+
+ XML_Char_ptr(ptrcomp(attId.name ) - 1 * sizeof(XML_Char ) )^:=XML_Char(2 );
+
+ end
+ else
+ inc(attIndex );
+
+ inc(i );
+
+ end;
+
+{ set-up for XML_GetSpecifiedAttributeCount and XML_GetIdAttributeIndex }
+ parser.m_nSpecifiedAtts:=attIndex;
+
+ if (elementType.idAtt <> NIL ) and
+ (XML_Char_ptr(ptrcomp(elementType.idAtt.name ) - 1 * sizeof(XML_Char ) )^ <> XML_Char(0 ) ) then
+ begin
+ i:=0;
+
+ while i < attIndex do
+ begin
+ if XML_Char_ptr_ptr(ptrcomp(appAtts ) + i * sizeof(XML_Char_ptr ) )^ = elementType.idAtt.name then
+ begin
+ parser.m_idAttIndex:=i;
+
+ break;
+
+ end;
+
+ inc(i ,2 );
+
+ end;
+
+ end
+ else
+ parser.m_idAttIndex:=-1;
+
+{ do attribute defaulting }
+ i:=0;
+
+ while i < nDefaultAtts do
+ begin
+ da:=DEFAULT_ATTRIBUTE_ptr(ptrcomp(elementType.defaultAtts ) + i * sizeof(DEFAULT_ATTRIBUTE ) );
+
+ if (XML_Char_ptr(ptrcomp(da.id.name ) - 1 * sizeof(XML_Char ) )^ = XML_Char(0 ) ) and
+ (da.value <> NIL ) then
+ if da.id.prefix <> NIL then
+ if da.id.xmlns <> 0 then
+ begin
+ result_:=
+ addBinding(
+ parser ,da.id.prefix ,da.id ,
+ da.value ,bindingsPtr );
+
+ if result_ <> XML_Error(0 ) then
+ begin
+ result:=result_;
+
+ exit;
+
+ end;
+
+ end
+ else
+ begin
+ XML_Char_ptr(ptrcomp(da.id.name ) - 1 * sizeof(XML_Char ) )^:=XML_Char(2 );
+
+ inc(nPrefixes );
+
+ XML_Char_ptr_ptr(ptrcomp(appAtts ) + attIndex * sizeof(XML_Char_ptr ) )^:=da.id.name;
+
+ inc(attIndex );
+
+ XML_Char_ptr_ptr(ptrcomp(appAtts ) + attIndex * sizeof(XML_Char_ptr ) )^:=da.value;
+
+ inc(attIndex );
+
+ end
+ else
+ begin
+ XML_Char_ptr(ptrcomp(da.id.name ) - 1 * sizeof(XML_Char ) )^:=XML_Char(1 );
+
+ XML_Char_ptr_ptr(ptrcomp(appAtts ) + attIndex * sizeof(XML_Char_ptr ) )^:=da.id.name;
+
+ inc(attIndex );
+
+ XML_Char_ptr_ptr(ptrcomp(appAtts ) + attIndex * sizeof(XML_Char_ptr ) )^:=da.value;
+
+ inc(attIndex );
+
+ end;
+
+ inc(i );
+
+ end;
+
+ XML_Char_ptr_ptr(ptrcomp(appAtts ) + attIndex * sizeof(XML_Char_ptr ) )^:=NIL;
+
+{ expand prefixed attribute names, check for duplicates,
+ and clear flags that say whether attributes were specified }
+ i:=0;
+
+ if nPrefixes <> 0 then
+ begin
+ { j = hash table index }
+ version :=parser.m_nsAttsVersion;
+ nsAttsSize:=1 shl parser.m_nsAttsPower;
+
+ { size of hash table must be at least 2 * (# of prefixed attributes) }
+ if shr_int32(nPrefixes shl 1 ,parser.m_nsAttsPower ) <> 0 then{ true for nsAttsPower = 0 }
+ begin
+ { hash table size must also be a power of 2 and >= 8 }
+ while shr_int32(nPrefixes ,parser.m_nsAttsPower ) <> 0 do
+ inc(parser.m_nsAttsPower );
+
+ if parser.m_nsAttsPower < 3 then
+ parser.m_nsAttsPower:=3;
+
+ nsAttsSize:=1 shl parser.m_nsAttsPower;
+
+ if not parser.m_mem.realloc_fcn(
+ pointer(parser.m_nsAtts ) ,
+ parser.m_nsAttsAlloc ,
+ nsAttsSize * sizeof(NS_ATT ) ) then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end
+ else
+ parser.m_nsAttsAlloc:=nsAttsSize * sizeof(NS_ATT );
+
+ version:=0; { force re-initialization of nsAtts hash table }
+
+ end;
+
+ { using a version flag saves us from initializing nsAtts every time }
+ if version = 0 then { initialize version flags when version wraps around }
+ begin
+ version:=INIT_ATTS_VERSION;
+
+ j:=nsAttsSize;
+
+ while j <> 0 do
+ begin
+ dec(j );
+
+ NS_ATT_ptr(ptrcomp(parser.m_nsAtts ) + j * sizeof(NS_ATT ) )^.version:=version;
+
+ end;
+
+ end;
+
+ dec(version );
+
+ parser.m_nsAttsVersion:=version;
+
+ { expand prefixed names and check for duplicates }
+ while i < attIndex do
+ begin
+ s:=XML_Char_ptr_ptr(ptrcomp(appAtts ) + i * sizeof(XML_Char_ptr ) )^;
+
+ if XML_Char_ptr(ptrcomp(s ) - 1 * sizeof(XML_Char ) )^ = XML_Char(2 ) then { prefixed }
+ begin
+ uriHash:=0;
+
+ XML_Char_ptr(ptrcomp(s ) - 1 * sizeof(XML_Char ) )^:=XML_Char(0 ); { clear flag }
+
+ id:=ATTRIBUTE_ID_ptr(lookup(@dtd.attributeIds ,s ,0 ) );
+ b :=id.prefix.binding;
+
+ if b = NIL then
+ begin
+ result:=XML_ERROR_UNBOUND_PREFIX;
+
+ exit;
+
+ end;
+
+ { as we expand the name we also calculate its hash value }
+ j:=0;
+
+ while j < b.uriLen do
+ begin
+ c:=XML_Char_ptr(ptrcomp(b.uri ) + j * sizeof(XML_Char ) )^;
+
+ if poolAppendChar(@parser.m_tempPool ,c ) = 0 then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ uriHash:=CHAR_HASH(uriHash ,c );
+
+ inc(j );
+
+ end;
+
+ while s^ <> XML_T(':' ) do
+ inc(ptrcomp(s ) ,sizeof(XML_Char ) );
+
+ goto _w0;
+
+ while s^ <> XML_Char(0 ) do { copies null terminator }
+ begin
+ _w0:
+ c:=s^;
+
+ if poolAppendChar(@parser.m_tempPool ,s^ ) = 0 then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ uriHash:=CHAR_HASH(uriHash ,c );
+
+ inc(ptrcomp(s ) ,sizeof(XML_Char ) );
+
+ end;
+
+ { Check hash table for duplicate of expanded name (uriName).
+ Derived from code in lookup(HASH_TABLE *table, ...). }
+ step:=0;
+ mask:=nsAttsSize - 1;
+ j :=uriHash and mask; { index into hash table }
+
+ while NS_ATT_ptr(ptrcomp(parser.m_nsAtts ) + j * sizeof(NS_ATT ) )^.version = version do
+ begin
+ { for speed we compare stored hash values first }
+ if uriHash = NS_ATT_ptr(ptrcomp(parser.m_nsAtts ) + j * sizeof(NS_ATT ) )^.hash then
+ begin
+ s1:=poolStart(@parser.m_tempPool );
+ s2:=NS_ATT_ptr(ptrcomp(parser.m_nsAtts ) + j * sizeof(NS_ATT ) )^.uriName;
+
+ { s1 is null terminated, but not s2 }
+ while (s1^ = s2^ ) and
+ (s1^ <> XML_Char(0 ) ) do
+ begin
+ inc(ptrcomp(s1 ) ,sizeof(XML_Char ) );
+ inc(ptrcomp(s2 ) ,sizeof(XML_Char ) );
+
+ end;
+
+ if s1^ = XML_Char(0 ) then
+ begin
+ result:=XML_ERROR_DUPLICATE_ATTRIBUTE;
+
+ exit;
+
+ end;
+
+ end;
+
+ if step = 0 then
+ step:=PROBE_STEP(uriHash ,mask ,parser.m_nsAttsPower );
+
+ if j < step then
+ inc(j ,nsAttsSize - step )
+ else
+ dec(j ,step );
+
+ end;
+
+ if parser.m_ns_triplets <> 0 then { append namespace separator and prefix }
+ begin
+ XML_Char_ptr(ptrcomp(parser.m_tempPool.ptr ) - 1 * sizeof(XML_Char ) )^:=parser.m_namespaceSeparator;
+
+ s:=b.prefix.name;
+
+ goto _w1;
+
+ while s^ <> XML_Char(0 ) do
+ begin
+ _w1:
+ if poolAppendChar(@parser.m_tempPool ,s^ ) = 0 then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ inc(ptrcomp(s ) ,sizeof(XML_Char ) );
+
+ end;
+
+ end;
+
+ { store expanded name in attribute list }
+ s:=poolStart(@parser.m_tempPool );
+
+ poolFinish(@parser.m_tempPool );
+
+ XML_Char_ptr_ptr(ptrcomp(appAtts ) + i * sizeof(XML_Char_ptr ) )^:=s;
+
+ { fill empty slot with new version, uriName and hash value }
+ NS_ATT_ptr(ptrcomp(parser.m_nsAtts ) + j * sizeof(NS_ATT ) )^.version:=version;
+ NS_ATT_ptr(ptrcomp(parser.m_nsAtts ) + j * sizeof(NS_ATT ) )^.hash :=uriHash;
+ NS_ATT_ptr(ptrcomp(parser.m_nsAtts ) + j * sizeof(NS_ATT ) )^.uriName:=s;
+
+ dec(nPrefixes );
+
+ if nPrefixes = 0 then
+ begin
+ inc(i ,2 );
+
+ break;
+
+ end;
+
+ end
+ else { not prefixed }
+ XML_Char_ptr(ptrcomp(s ) - 1 * sizeof(XML_Char ) )^:=XML_Char(0 ); { clear flag }
+
+ inc(i ,2 );
+
+ end;
+
+ end;
+
+{ clear flags for the remaining attributes }
+ while i < attIndex do
+ begin
+ XML_Char_ptr(
+ ptrcomp(
+ XML_Char_ptr_ptr(ptrcomp(appAtts ) + i * sizeof(XML_Char_ptr ) )^ )
+ - 1 * sizeof(XML_Char ) )^:=XML_Char(0 );
+
+ inc(i ,2 );
+
+ end;
+
+ binding:=bindingsPtr^;
+
+ while binding <> NIL do
+ begin
+ XML_Char_ptr(ptrcomp(binding.attId.name ) - 1 * sizeof(XML_Char ) )^:=XML_Char(0 );
+
+ binding:=binding.nextTagBinding;
+
+ end;
+
+ if parser.m_ns = 0 then
+ begin
+ result:=XML_ERROR_NONE;
+
+ exit;
+
+ end;
+
+{ expand the element type name }
+ if elementType.prefix <> NIL then
+ begin
+ binding:=elementType.prefix.binding;
+
+ if binding = NIL then
+ begin
+ result:=XML_ERROR_UNBOUND_PREFIX;
+
+ exit;
+
+ end;
+
+ localPart:=tagNamePtr.str;
+
+ while localPart^ <> XML_T(':' ) do
+ inc(ptrcomp(localPart ) ,sizeof(XML_Char ) );
+
+ end
+ else
+ if dtd.defaultPrefix.binding <> NIL then
+ begin
+ binding :=dtd.defaultPrefix.binding;
+ localPart:=tagNamePtr.str;
+
+ end
+ else
+ begin
+ result:=XML_ERROR_NONE;
+
+ exit;
+
+ end;
+
+ prefixLen:=0;
+
+ if (parser.m_ns_triplets <> 0 ) and
+ (binding.prefix.name <> NIL ) then
+ begin
+ while XML_Char_ptr(ptrcomp(binding.prefix.name ) + prefixLen * sizeof(XML_Char ) )^ <> XML_Char(0 ) do
+ inc(prefixLen );
+
+ inc(prefixLen ); { prefixLen includes null terminator }
+
+ end;
+
+ tagNamePtr.localPart:=localPart;
+ tagNamePtr.uriLen :=binding.uriLen;
+ tagNamePtr.prefix :=binding.prefix.name;
+ tagNamePtr.prefixLen:=prefixLen;
+
+ i:=0;
+
+ while XML_Char_ptr(ptrcomp(localPart ) + i * sizeof(XML_Char ) )^ <> XML_Char(0 ) do
+ inc(i );
+
+ inc(i ); { i includes null terminator }
+
+ n:=i + binding.uriLen + prefixLen;
+
+ if n > binding.uriAlloc then
+ begin
+ parser.m_mem.malloc_fcn(pointer(uri ) ,(n + EXPAND_SPARE ) * sizeof(XML_Char ) );
+
+ if uri = NIL then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ j:=binding.uriAlloc;
+
+ binding.uriAlloc:=n + EXPAND_SPARE;
+
+ move(
+ binding.uri^ ,
+ uri^ ,
+ binding.uriLen * sizeof(XML_Char ) );
+
+ p:=parser.m_tagStack;
+
+ while p <> NIL do
+ begin
+ if p.name.str = binding.uri then
+ p.name.str:=uri;
+
+ p:=p.parent;
+
+ end;
+
+ parser.m_mem.free_fcn(pointer(binding.uri ) ,j * sizeof(XML_Char ) );
+
+ binding.uri:=uri;
+
+ end;
+
+{ if namespaceSeparator != '\0' then uri includes it already }
+ uri:=XML_Char_ptr(ptrcomp(binding.uri ) + binding.uriLen * sizeof(XML_Char ) );
+
+ move(
+ localPart^ ,
+ uri^ ,
+ i * sizeof(XML_Char ) );
+
+{ we always have a namespace separator between localPart and prefix }
+ if prefixLen <> 0 then
+ begin
+ inc(ptrcomp(uri ) ,(i - 1 ) * sizeof(XML_Char ) );
+
+ uri^:=parser.m_namespaceSeparator; { replace null terminator }
+
+ move(
+ binding.prefix.name^ ,
+ XML_Char_ptr(ptrcomp(uri ) + 1 * sizeof(XML_Char ) )^ ,
+ prefixLen * sizeof(XML_Char ) );
+
+ end;
+
+ tagNamePtr.str:=binding.uri;
+
+ result:=XML_ERROR_NONE;
+
+end;
+
+{ processInternalEntity {..}
+function processInternalEntity(parser : XML_Parser; entity : ENTITY_ptr; betweenDecl : XML_Bool ) : XML_Error;
+begin
+end;
+
+{ epilogProcessor }
+function epilogProcessor(parser : XML_Parser; s ,end_ : char_ptr; nextPtr : char_ptr_ptr ) : XML_Error;
+var
+ next : char_ptr;
+
+ tok : int;
+
+begin
+ parser.m_processor:=@epilogProcessor;
+ parser.m_eventPtr :=s;
+
+ repeat
+ next:=NIL;
+ tok :=XmlPrologTok(parser.m_encoding ,pointer(s ) ,pointer(end_ ) ,@next );
+
+ parser.m_eventEndPtr:=next;
+
+ case tok of
+ -XML_TOK_PROLOG_S :
+ begin
+ if @parser.m_defaultHandler <> NIL then
+ begin
+ reportDefault(parser ,parser.m_encoding ,s ,next );
+
+ if parser.m_parsingStatus.parsing = XML_FINISHED then
+ begin
+ result:=XML_ERROR_ABORTED;
+
+ exit;
+
+ end;
+
+ end;
+
+ nextPtr^:=next;
+ result :=XML_ERROR_NONE;
+
+ exit;
+
+ end;
+
+ XML_TOK_NONE :
+ begin
+ nextPtr^:=s;
+ result :=XML_ERROR_NONE;
+
+ exit;
+
+ end;
+
+ XML_TOK_PROLOG_S :
+ if @parser.m_defaultHandler <> NIL then
+ reportDefault(parser ,parser.m_encoding ,s ,next );
+
+ XML_TOK_PI :
+ if reportProcessingInstruction(parser ,parser.m_encoding ,s ,next ) = 0 then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ XML_TOK_COMMENT :
+ if reportComment(parser ,parser.m_encoding ,s ,next ) = 0 then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ XML_TOK_INVALID :
+ begin
+ parser.m_eventPtr:=next;
+
+ result:=XML_ERROR_INVALID_TOKEN;
+
+ exit;
+
+ end;
+
+ XML_TOK_PARTIAL :
+ begin
+ if parser.m_parsingStatus.finalBuffer = 0 then
+ begin
+ nextPtr^:=s;
+ result :=XML_ERROR_NONE;
+
+ exit;
+
+ end;
+
+ result:=XML_ERROR_UNCLOSED_TOKEN;
+
+ exit;
+
+ end;
+
+ XML_TOK_PARTIAL_CHAR :
+ begin
+ if parser.m_parsingStatus.finalBuffer = 0 then
+ begin
+ nextPtr^:=s;
+ result :=XML_ERROR_NONE;
+
+ exit;
+
+ end;
+
+ result:=XML_ERROR_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ else
+ begin
+ result:=XML_ERROR_JUNK_AFTER_DOC_ELEMENT;
+
+ exit;
+
+ end;
+
+ end;
+
+ parser.m_eventPtr:=next;
+
+ s:=next;
+
+ case parser.m_parsingStatus.parsing of
+ XML_SUSPENDED :
+ begin
+ nextPtr^:=next;
+ result :=XML_ERROR_NONE;
+
+ exit;
+
+ end;
+
+ XML_FINISHED :
+ begin
+ result:=XML_ERROR_ABORTED;
+
+ exit;
+
+ end;
+
+ end;
+
+ until false;
+
+end;
+
+{ doCdataSection {..}
+{ startPtr gets set to non-null if the section is closed, and to null if
+ the section is not yet closed. }
+function doCdataSection(
+ parser : XML_Parser;
+ enc : ENCODING_ptr;
+ startPtr : char_ptr_ptr;
+ end_ : char_ptr;
+ nextPtr : char_ptr_ptr;
+ haveMore : XML_Bool ) : XML_Error;
+begin
+end;
+
+{ cdataSectionProcessor {..}
+{ The idea here is to avoid using stack for each CDATA section when
+ the whole file is parsed with one call. }
+function cdataSectionProcessor(parser : XML_Parser; start ,end_ : char_ptr; endPtr : char_ptr_ptr ) : XML_Error;
+begin
+end;
+
+{ doContent }
+function doContent(
+ parser : XML_Parser;
+ startTagLevel : int;
+ enc : ENCODING_ptr;
+ s ,end_ : char_ptr;
+ nextPtr : char_ptr_ptr;
+ haveMore : XML_Bool ) : XML_Error;
+var
+ dtd : DTD_ptr;
+
+ eventPP ,eventEndPP : char_ptr_ptr;
+
+ next ,rawNameEnd ,fromPtr ,temp ,rawName : char_ptr;
+
+ tok ,bufSize ,convLen ,len ,n : int;
+
+ c ,ch : XML_Char;
+
+ name ,context ,toPtr ,localPart ,prefix ,uri : XML_Char_ptr;
+
+ entity : ENTITY_ptr;
+
+ result_ : XML_Error;
+
+ tag : TAG_ptr;
+
+ bindings ,b : BINDING_ptr;
+
+ noElmHandlers : XML_Bool;
+
+ name_ : TAG_NAME;
+
+ buf : array[0..XML_ENCODE_MAX - 1 ] of XML_Char;
+
+ dataPtr : ICHAR_ptr;
+
+label
+ _break ;
+
+begin
+{ save one level of indirection }
+ dtd:=parser.m_dtd;
+
+ if enc = parser.m_encoding then
+ begin
+ eventPP :=@parser.m_eventPtr;
+ eventEndPP:=@parser.m_eventEndPtr;
+
+ end
+ else
+ begin
+ eventPP :=@parser.m_openInternalEntities.internalEventPtr;
+ eventEndPP:=@parser.m_openInternalEntities.internalEventEndPtr;
+
+ end;
+
+ eventPP^:=s;
+
+ repeat
+ next:=s; { XmlContentTok doesn't always set the last arg }
+
+ tok:=XmlContentTok(enc ,pointer(s ) ,pointer(end_ ) ,@next );
+
+ eventEndPP^:=next;
+
+ case tok of
+ XML_TOK_TRAILING_CR :
+ begin
+ if haveMore <> 0 then
+ begin
+ nextPtr^:=s;
+ result :=XML_ERROR_NONE;
+
+ exit;
+
+ end;
+
+ eventEndPP^:=end_;
+
+ if @parser.m_characterDataHandler <> NIL then
+ begin
+ c:=XML_Char($A );
+
+ parser.m_characterDataHandler(parser.m_handlerArg ,@c ,1 );
+
+ end
+ else
+ if @parser.m_defaultHandler <> NIL then
+ reportDefault(parser ,enc ,s ,end_ );
+
+ { We are at the end of the final buffer, should we check for
+ XML_SUSPENDED, XML_FINISHED? }
+ if startTagLevel = 0 then
+ begin
+ result:=XML_ERROR_NO_ELEMENTS;
+
+ exit;
+
+ end;
+
+ if parser.m_tagLevel <> startTagLevel then
+ begin
+ result:=XML_ERROR_ASYNC_ENTITY;
+
+ exit;
+
+ end;
+
+ nextPtr^:=end_;
+ result :=XML_ERROR_NONE;
+
+ exit;
+
+ end;
+
+ XML_TOK_NONE :
+ begin
+ if haveMore <> 0 then
+ begin
+ nextPtr^:=s;
+ result :=XML_ERROR_NONE;
+
+ exit;
+
+ end;
+
+ if startTagLevel > 0 then
+ begin
+ if parser.m_tagLevel <> startTagLevel then
+ begin
+ result:=XML_ERROR_ASYNC_ENTITY;
+
+ exit;
+
+ end;
+
+ nextPtr^:=s;
+ result :=XML_ERROR_NONE;
+
+ exit;
+
+ end;
+
+ result:=XML_ERROR_NO_ELEMENTS;
+
+ exit;
+
+ end;
+
+ XML_TOK_INVALID :
+ begin
+ eventPP^:=next;
+ result :=XML_ERROR_INVALID_TOKEN;
+
+ exit;
+
+ end;
+
+ XML_TOK_PARTIAL :
+ begin
+ if haveMore <> 0 then
+ begin
+ nextPtr^:=s;
+ result :=XML_ERROR_NONE;
+
+ exit;
+
+ end;
+
+ result:=XML_ERROR_UNCLOSED_TOKEN;
+
+ exit;
+
+ end;
+
+ XML_TOK_PARTIAL_CHAR :
+ begin
+ if haveMore <> 0 then
+ begin
+ nextPtr^:=s;
+ result :=XML_ERROR_NONE;
+
+ exit;
+
+ end;
+
+ result:=XML_ERROR_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ XML_TOK_ENTITY_REF :
+ begin
+ ch:=
+ XML_Char(XmlPredefinedEntityName(
+ enc ,
+ pointer(ptrcomp(s ) + enc.minBytesPerChar ) ,
+ pointer(ptrcomp(next ) - enc.minBytesPerChar ) ) );
+
+ if ch <> XML_Char(0 ) then
+ begin
+ if @parser.m_characterDataHandler <> NIL then
+ parser.m_characterDataHandler(parser.m_handlerArg ,@ch ,1 )
+ else
+ if @parser.m_defaultHandler <> NIL then
+ reportDefault(parser ,enc ,s ,next );
+
+ goto _break;
+
+ end;
+
+ name:=
+ poolStoreString(
+ @dtd.pool ,enc ,
+ char_ptr(ptrcomp(s ) + enc.minBytesPerChar ) ,
+ char_ptr(ptrcomp(next ) - enc.minBytesPerChar ) );
+
+ if name = NIL then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ entity:=ENTITY_ptr(lookup(@dtd.generalEntities ,name ,0 ) );
+
+ poolDiscard(@dtd.pool );
+
+ { First, determine if a check for an existing declaration is needed;
+ if yes, check that the entity exists, and that it is internal,
+ otherwise call the skipped entity or default handler. }
+ if (dtd.hasParamEntityRefs = 0 ) or
+ (dtd.standalone <> 0 ) then
+ if entity = NIL then
+ begin
+ result:=XML_ERROR_UNDEFINED_ENTITY;
+
+ exit;
+
+ end
+ else
+ if entity.is_internal = 0 then
+ begin
+ result:=XML_ERROR_ENTITY_DECLARED_IN_PE;
+
+ exit;
+
+ end
+ else
+ else
+ if entity = NIL then
+ begin
+ if @parser.m_skippedEntityHandler <> NIL then
+ parser.m_skippedEntityHandler(parser.m_handlerArg ,name ,0 )
+ else
+ if @parser.m_defaultHandler <> NIL then
+ reportDefault(parser ,enc ,s ,next );
+
+ goto _break;
+
+ end;
+
+ if entity.open <> 0 then
+ begin
+ result:=XML_ERROR_RECURSIVE_ENTITY_REF;
+
+ exit;
+
+ end;
+
+ if entity.notation <> NIL then
+ begin
+ result:=XML_ERROR_BINARY_ENTITY_REF;
+
+ exit;
+
+ end;
+
+ if entity.textPtr <> NIL then
+ begin
+ if parser.m_defaultExpandInternalEntities <> 0 then
+ begin
+ if @parser.m_skippedEntityHandler <> NIL then
+ parser.m_skippedEntityHandler(parser.m_handlerArg ,entity.name ,0 )
+ else
+ if @parser.m_defaultHandler <> NIL then
+ reportDefault(parser ,enc ,s ,next );
+
+ goto _break;
+
+ end;
+
+ result_:=processInternalEntity(parser ,entity ,XML_FALSE );
+
+ if result_ <> XML_ERROR_NONE then
+ begin
+ result:=result_;
+
+ exit;
+
+ end;
+
+ end
+ else
+ if @parser.m_externalEntityRefHandler <> NIL then
+ begin
+ entity.open:=XML_TRUE;
+ context :=getContext(parser );
+ entity.open:=XML_FALSE;
+
+ if context = NIL then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ if parser.m_externalEntityRefHandler(
+ parser.m_externalEntityRefHandlerArg ,
+ context ,
+ entity.base ,
+ entity.systemId ,
+ entity.publicId ) = 0 then
+ begin
+ result:=XML_ERROR_EXTERNAL_ENTITY_HANDLING;
+
+ exit;
+
+ end;
+
+ poolDiscard(@parser.m_tempPool );
+
+ end
+ else
+ if @parser.m_defaultHandler <> NIL then
+ reportDefault(parser ,enc ,s ,next );
+
+ end;
+
+ XML_TOK_START_TAG_NO_ATTS ,XML_TOK_START_TAG_WITH_ATTS :
+ begin
+ if parser.m_freeTagList <> NIL then
+ begin
+ tag:=parser.m_freeTagList;
+
+ parser.m_freeTagList:=parser.m_freeTagList.parent;
+
+ end
+ else
+ begin
+ parser.m_mem.malloc_fcn(pointer(tag ) ,sizeof(expat.TAG ) );
+
+ if tag = NIL then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ parser.m_mem.malloc_fcn(pointer(tag.buf ) ,INIT_TAG_BUF_SIZE );
+
+ if tag.buf = NIL then
+ begin
+ parser.m_mem.free_fcn(pointer(tag ) ,sizeof(expat.TAG ) );
+
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end
+ else
+ tag.alloc:=INIT_TAG_BUF_SIZE;
+
+ tag.bufEnd:=char_ptr(ptrcomp(tag.buf ) + INIT_TAG_BUF_SIZE );
+
+ end;
+
+ tag.bindings :=NIL;
+ tag.parent :=parser.m_tagStack;
+ parser.m_tagStack :=tag;
+ tag.name.localPart:=NIL;
+ tag.name.prefix :=NIL;
+ tag.rawName :=char_ptr(ptrcomp(s ) + enc.minBytesPerChar );
+ tag.rawNameLength :=XmlNameLength(enc ,pointer(tag.rawName ) );
+
+ inc(parser.m_tagLevel );
+
+ rawNameEnd:=char_ptr(ptrcomp(tag.rawName ) + tag.rawNameLength );
+ fromPtr :=tag.rawName;
+ toPtr :=XML_Char_ptr(tag.buf );
+
+ repeat
+ XmlConvert(
+ enc ,
+ @fromPtr ,rawNameEnd ,
+ ICHAR_ptr_ptr(@toPtr ) ,ICHAR_ptr(ptrcomp(tag.bufEnd ) - 1 ) );
+
+ convLen:=(ptrcomp(toPtr ) - ptrcomp(tag.buf ) ) div sizeof(XML_Char );
+
+ if fromPtr = rawNameEnd then
+ begin
+ tag.name.strLen:=convLen;
+
+ break;
+
+ end;
+
+ bufSize:=(ptrcomp(tag.bufEnd ) - ptrcomp(tag.buf ) ) shl 1;
+
+ parser.m_mem.realloc_fcn(pointer(tag.buf ) ,tag.alloc ,bufSize );
+
+ if temp = NIL then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end
+ else
+ tag.alloc:=bufSize;
+
+ tag.buf :=temp;
+ tag.bufEnd:=char_ptr(ptrcomp(temp ) + bufSize );
+
+ toPtr:=XML_Char_ptr(ptrcomp(temp ) + convLen );
+
+ until false;
+
+ tag.name.str:=XML_Char_ptr(tag.buf );
+
+ toPtr^ :=XML_T(#0 );
+ result_:=storeAtts(parser ,enc ,s ,@tag.name ,@tag.bindings );
+
+ if result_ <> XML_Error(0 ) then
+ begin
+ result:=result_;
+
+ exit;
+
+ end;
+
+ if @parser.m_startElementHandler <> NIL then
+ parser.m_startElementHandler(
+ parser.m_handlerArg ,tag.name.str ,
+ XML_Char_ptr_ptr(parser.m_atts ) )
+ else
+ if @parser.m_defaultHandler <> NIL then
+ reportDefault(parser ,enc ,s ,next );
+
+ poolClear(@parser.m_tempPool );
+
+ end;
+
+ XML_TOK_EMPTY_ELEMENT_NO_ATTS ,XML_TOK_EMPTY_ELEMENT_WITH_ATTS :
+ begin
+ rawName :=char_ptr(ptrcomp(s ) + enc.minBytesPerChar );
+ bindings :=NIL;
+ noElmHandlers:=XML_TRUE;
+
+ name_.str:=
+ poolStoreString(
+ @parser.m_tempPool ,enc ,rawName ,
+ char_ptr(ptrcomp(rawName ) + XmlNameLength(enc ,pointer(rawName ) ) ) );
+
+ if name_.str = NIL then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ poolFinish(@parser.m_tempPool );
+
+ result_:=storeAtts(parser ,enc ,s ,@name_ ,@bindings );
+
+ if result_ <> XML_Error(0 ) then
+ begin
+ result:=result_;
+
+ exit;
+
+ end;
+
+ poolFinish(@parser.m_tempPool );
+
+ if @parser.m_startElementHandler <> NIL then
+ begin
+ parser.m_startElementHandler(
+ parser.m_handlerArg ,name_.str ,XML_Char_ptr_ptr(parser.m_atts ) );
+
+ noElmHandlers:=XML_FALSE;
+
+ end;
+
+ if @parser.m_endElementHandler <> NIL then
+ begin
+ if @parser.m_startElementHandler <> NIL then
+ eventPP^:=eventEndPP^;
+
+ parser.m_endElementHandler(parser.m_handlerArg ,name_.str );
+
+ noElmHandlers:=XML_FALSE;
+
+ end;
+
+ if (noElmHandlers <> 0 ) and
+ (@parser.m_defaultHandler <> NIL ) then
+ reportDefault(parser ,enc ,s ,next );
+
+ poolClear(@parser.m_tempPool );
+
+ while bindings <> NIL do
+ begin
+ b:=bindings;
+
+ if @parser.m_endNamespaceDeclHandler <> NIL then
+ parser.m_endNamespaceDeclHandler(parser.m_handlerArg ,b.prefix.name );
+
+ bindings :=bindings.nextTagBinding;
+ b.nextTagBinding:=parser.m_freeBindingList;
+
+ parser.m_freeBindingList:=b;
+ b.prefix.binding :=b.prevPrefixBinding;
+
+ end;
+
+ if parser.m_tagLevel = 0 then
+ begin
+ result:=epilogProcessor(parser ,next ,end_ ,nextPtr );
+
+ exit;
+
+ end;
+
+ end;
+
+ XML_TOK_END_TAG :
+ if parser.m_tagLevel = startTagLevel then
+ begin
+ result:=XML_ERROR_ASYNC_ENTITY;
+
+ exit;
+
+ end
+ else
+ begin
+ tag :=parser.m_tagStack;
+ parser.m_tagStack :=tag.parent;
+ tag.parent :=parser.m_freeTagList;
+ parser.m_freeTagList:=tag;
+
+ rawName:=char_ptr(ptrcomp(s ) + enc.minBytesPerChar * 2 );
+ len :=XmlNameLength(enc ,pointer(rawName ) );
+
+ if (len <> tag.rawNameLength ) or
+ (memcmp(pointer(tag.rawName ) ,pointer(rawName ) ,len ) <> 0 ) then
+ begin
+ eventPP^:=rawName;
+ result :=XML_ERROR_TAG_MISMATCH;
+
+ exit;
+
+ end;
+
+ dec(parser.m_tagLevel );
+
+ if @parser.m_endElementHandler <> NIL then
+ begin
+ localPart:=tag.name.localPart;
+
+ if (parser.m_ns <> 0 ) and
+ (localPart <> NIL ) then
+ begin
+ { localPart and prefix may have been overwritten in
+ tag->name.str, since this points to the binding->uri
+ buffer which gets re-used; so we have to add them again }
+ uri:=XML_Char_ptr(ptrcomp(tag.name.str ) + tag.name.uriLen );
+
+ { don't need to check for space - already done in storeAtts() }
+ while localPart^ <> XML_Char(0 ) do
+ begin
+ uri^:=localPart^;
+
+ inc(ptrcomp(uri ) ,sizeof(XML_Char ) );
+ inc(ptrcomp(localPart ) ,sizeof(XML_Char ) );
+
+ end;
+
+ prefix:=XML_Char_ptr(tag.name.prefix );
+
+ if (parser.m_ns_triplets <> 0 ) and
+ (prefix <> NIL ) then
+ begin
+ uri^:=parser.m_namespaceSeparator;
+
+ inc(ptrcomp(uri ) ,sizeof(XML_Char ) );
+
+ while prefix^ <> XML_Char(0 ) do
+ begin
+ uri^:=prefix^;
+
+ inc(ptrcomp(uri ) ,sizeof(XML_Char ) );
+ inc(ptrcomp(prefix ) ,sizeof(XML_Char ) );
+
+ end;
+
+ end;
+
+ uri^:=XML_T(#0 );
+
+ end;
+
+ parser.m_endElementHandler(parser.m_handlerArg ,tag.name.str );
+
+ end
+ else
+ if @parser.m_defaultHandler <> NIL then
+ reportDefault(parser ,enc ,s ,next );
+
+ while tag.bindings <> NIL do
+ begin
+ b:=tag.bindings;
+
+ if @parser.m_endNamespaceDeclHandler <> NIL then
+ parser.m_endNamespaceDeclHandler(parser.m_handlerArg ,b.prefix.name );
+
+ tag.bindings :=tag.bindings.nextTagBinding;
+ b.nextTagBinding :=parser.m_freeBindingList;
+ parser.m_freeBindingList:=b;
+ b.prefix.binding :=b.prevPrefixBinding;
+
+ end;
+
+ if parser.m_tagLevel = 0 then
+ begin
+ result:=epilogProcessor(parser ,next ,end_ ,nextPtr );
+
+ exit;
+
+ end;
+
+ end;
+
+ XML_TOK_CHAR_REF :
+ begin
+ n:=XmlCharRefNumber(enc ,pointer(s ) );
+
+ if n < 0 then
+ begin
+ result:=XML_ERROR_BAD_CHAR_REF;
+
+ exit;
+
+ end;
+
+ if @parser.m_characterDataHandler <> NIL then
+ parser.m_characterDataHandler(
+ parser.m_handlerArg ,@buf[0 ] ,
+ XmlEncode(n ,ICHAR_ptr(@buf ) ) )
+ else
+ if @parser.m_defaultHandler <> NIL then
+ reportDefault(parser ,enc ,s ,next );
+
+ end;
+
+ XML_TOK_XML_DECL :
+ begin
+ result:=XML_ERROR_MISPLACED_XML_PI;
+
+ exit;
+
+ end;
+
+ XML_TOK_DATA_NEWLINE :
+ if @parser.m_characterDataHandler <> NIL then
+ begin
+ c:=XML_Char($A );
+
+ parser.m_characterDataHandler(parser.m_handlerArg ,@c ,1 );
+
+ end
+ else
+ if @parser.m_defaultHandler <> NIL then
+ reportDefault(parser ,enc ,s ,next );
+
+ XML_TOK_CDATA_SECT_OPEN :
+ begin
+ if @parser.m_startCdataSectionHandler <> NIL then
+ parser.m_startCdataSectionHandler(parser.m_handlerArg )
+ {$IFDEF 0 }
+ { Suppose you doing a transformation on a document that involves
+ changing only the character data. You set up a defaultHandler
+ and a characterDataHandler. The defaultHandler simply copies
+ characters through. The characterDataHandler does the
+ transformation and writes the characters out escaping them as
+ necessary. This case will fail to work if we leave out the
+ following two lines (because & and < inside CDATA sections will
+ be incorrectly escaped).
+
+ However, now we have a start/endCdataSectionHandler, so it seems
+ easier to let the user deal with this. }
+ else
+ if @parser.m_characterDataHandler <> NIL then
+ parser.m_characterDataHandler(parser.m_handlerArg ,parser.m_dataBuf ,0 )
+ {$ENDIF }
+ else
+ if @parser.m_defaultHandler <> NIL then
+ reportDefault(parser ,enc ,s ,next );
+
+ result_:=doCdataSection(parser ,enc ,@next ,end_ ,nextPtr ,haveMore );
+
+ if result_ <> XML_ERROR_NONE then
+ begin
+ result:=result_;
+
+ exit;
+
+ end
+ else
+ if next = NIL then
+ begin
+ parser.m_processor:=@cdataSectionProcessor;
+
+ result:=result_;
+
+ exit;
+
+ end;
+
+ end;
+
+ XML_TOK_TRAILING_RSQB :
+ begin
+ if haveMore <> 0 then
+ begin
+ nextPtr^:=s;
+ result :=XML_ERROR_NONE;
+
+ exit;
+
+ end;
+
+ if @parser.m_characterDataHandler <> NIL then
+ if MUST_CONVERT(enc ,s ) <> 0 then
+ begin
+ dataPtr:=ICHAR_ptr(parser.m_dataBuf );
+
+ XmlConvert(enc ,@s ,end_ ,@dataPtr ,ICHAR_ptr(parser.m_dataBufEnd ) );
+
+ parser.m_characterDataHandler(
+ parser.m_handlerArg ,
+ parser.m_dataBuf ,
+ (ptrcomp(dataPtr ) - ptrcomp(parser.m_dataBuf ) ) div sizeof(ICHAR ) );
+
+ end
+ else
+ parser.m_characterDataHandler(
+ parser.m_handlerArg ,
+ XML_Char_ptr(s ) ,
+ (ptrcomp(end_ ) - ptrcomp(s ) ) div sizeof(XML_Char ) )
+ else
+ if @parser.m_defaultHandler <> NIL then
+ reportDefault(parser ,enc ,s ,end_ );
+
+ { We are at the end of the final buffer, should we check for
+ XML_SUSPENDED, XML_FINISHED? }
+ if startTagLevel = 0 then
+ begin
+ eventPP^:=end_;
+ result :=XML_ERROR_NO_ELEMENTS;
+
+ exit;
+
+ end;
+
+ if parser.m_tagLevel <> startTagLevel then
+ begin
+ eventPP^:=end_;
+ result :=XML_ERROR_ASYNC_ENTITY;
+
+ exit;
+
+ end;
+
+ nextPtr^:=end_;
+ result :=XML_ERROR_NONE;
+
+ exit;
+
+ end;
+
+ XML_TOK_DATA_CHARS :
+ if @parser.m_characterDataHandler <> NIL then
+ if MUST_CONVERT(enc ,s ) <> 0 then
+ repeat
+ dataPtr:=ICHAR_ptr(parser.m_dataBuf );
+
+ XmlConvert(enc ,@s ,next ,@dataPtr ,ICHAR_ptr(parser.m_dataBufEnd ) );
+
+ eventEndPP^:=s;
+
+ parser.m_characterDataHandler(
+ parser.m_handlerArg ,
+ parser.m_dataBuf ,
+ (ptrcomp(dataPtr ) - ptrcomp(parser.m_dataBuf ) ) div sizeof(ICHAR ) );
+
+ if s = next then
+ break;
+
+ eventPP^:=s;
+
+ until false
+ else
+ parser.m_characterDataHandler(
+ parser.m_handlerArg ,
+ XML_Char_ptr(s ) ,
+ (ptrcomp(next ) - ptrcomp(s ) ) div sizeof(XML_Char ) )
+
+ else
+ if @parser.m_defaultHandler <> NIL then
+ reportDefault(parser ,enc ,s ,next );
+
+ XML_TOK_PI :
+ if reportProcessingInstruction(parser ,enc ,s ,next ) = 0 then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ XML_TOK_COMMENT :
+ if reportComment(parser ,enc ,s ,next ) = 0 then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ else
+ if @parser.m_defaultHandler <> NIL then
+ reportDefault(parser ,enc ,s ,next );
+
+ end;
+
+ _break:
+ eventPP^:=next;
+ s :=next;
+
+ case parser.m_parsingStatus.parsing of
+ XML_SUSPENDED:
+ begin
+ nextPtr^:=next;
+ result :=XML_ERROR_NONE;
+
+ exit;
+
+ end;
+
+ XML_FINISHED:
+ begin
+ result:=XML_ERROR_ABORTED;
+
+ exit;
+
+ end;
+
+ end;
+
+ until false;
+
+{ not reached }
+
+end;
+
+{ contentProcessor }
+function contentProcessor(parser : XML_Parser; start ,end_ : char_ptr; endPtr : char_ptr_ptr ) : XML_Error;
+var
+ result_ : XML_Error;
+
+begin
+ result_:=
+ doContent(
+ parser ,0 ,parser.m_encoding ,start ,end_ ,
+ endPtr ,XML_Bool(not parser.m_parsingStatus.finalBuffer ) );
+
+ if result_ = XML_ERROR_NONE then
+ if storeRawNames(parser ) = 0 then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ result:=result_;
+
+end;
+
+{ getElementType {..}
+function getElementType(parser : XML_Parser; enc : ENCODING_ptr; ptr ,end_ : char_ptr ) : ELEMENT_TYPE_ptr;
+begin
+end;
+
+{ getAttributeId }
+function getAttributeId(parser : XML_Parser; enc : ENCODING_ptr; start ,end_ : char_ptr ) : ATTRIBUTE_ID_ptr;
+var
+ dtd : DTD_ptr;
+
+ id : ATTRIBUTE_ID_ptr;
+
+ name : XML_Char_ptr;
+
+ i ,j : int;
+
+begin
+{ save one level of indirection }
+ dtd:=parser.m_dtd;
+
+ if poolAppendChar(@dtd.pool ,XML_T(#0 ) ) = 0 then
+ begin
+ result:=NIL;
+
+ exit;
+
+ end;
+
+ name:=poolStoreString(@dtd.pool ,enc ,start ,end_ );
+
+ if name = NIL then
+ begin
+ result:=NIL;
+
+ exit;
+
+ end;
+
+{ skip quotation mark - its storage will be re-used (like in name[-1]) }
+ inc(ptrcomp(name ) ,sizeof(XML_Char ) );
+
+ id:=ATTRIBUTE_ID_ptr(lookup(@dtd.attributeIds ,name ,sizeof(ATTRIBUTE_ID ) ) );
+
+ if id = NIL then
+ begin
+ result:=NIL;
+
+ exit;
+
+ end;
+
+ if id.name <> name then
+ poolDiscard(@dtd.pool )
+
+ else
+ begin
+ poolFinish(@dtd.pool );
+
+ if parser.m_ns = 0 then
+ else
+ if (XML_Char_ptr(ptrcomp(name ) + 0 * sizeof(XML_Char ) )^ = XML_T('x' ) ) and
+ (XML_Char_ptr(ptrcomp(name ) + 1 * sizeof(XML_Char ) )^ = XML_T('m' ) ) and
+ (XML_Char_ptr(ptrcomp(name ) + 2 * sizeof(XML_Char ) )^ = XML_T('l' ) ) and
+ (XML_Char_ptr(ptrcomp(name ) + 3 * sizeof(XML_Char ) )^ = XML_T('n' ) ) and
+ (XML_Char_ptr(ptrcomp(name ) + 4 * sizeof(XML_Char ) )^ = XML_T('s' ) ) and
+ ((XML_Char_ptr(ptrcomp(name ) + 5 * sizeof(XML_Char ) )^ = XML_T(#0 ) ) or
+ (XML_Char_ptr(ptrcomp(name ) + 5 * sizeof(XML_Char ) )^ = XML_T(':' ) ) ) then
+ begin
+ if XML_Char_ptr(ptrcomp(name ) + 5 * sizeof(XML_Char ) )^ = XML_T(#0 ) then
+ id.prefix:=@dtd.defaultPrefix
+ else
+ id.prefix:=PREFIX_ptr(lookup(@dtd.prefixes ,XML_Char_ptr(ptrcomp(name ) + 6 * sizeof(XML_Char ) ) ,sizeof(PREFIX ) ) );
+
+ id.xmlns:=XML_TRUE;
+
+ end
+ else
+ begin
+ i:=0;
+
+ while XML_Char_ptr(ptrcomp(name ) + i * sizeof(XML_Char ) )^ <> XML_Char(0 ) do
+ begin
+ { attributes without prefix are *not* in the default namespace }
+ if XML_Char_ptr(ptrcomp(name ) + i * sizeof(XML_Char ) )^ = XML_T(':' ) then
+ begin
+ j:=0;
+
+ while j < i do
+ begin
+ if poolAppendChar(@dtd.pool ,XML_Char_ptr(ptrcomp(name ) + j * sizeof(XML_Char ) )^ ) = 0 then
+ begin
+ result:=NIL;
+
+ exit;
+
+ end;
+
+ inc(j );
+
+ end;
+
+ if poolAppendChar(@dtd.pool ,XML_T(#0 ) ) = 0 then
+ begin
+ result:=NIL;
+
+ exit;
+
+ end;
+
+ id.prefix:=
+ PREFIX_ptr(
+ lookup(@dtd.prefixes ,poolStart(@dtd.pool ) ,sizeof(PREFIX ) ) );
+
+ if id.prefix.name = poolStart(@dtd.pool ) then
+ poolFinish(@dtd.pool )
+ else
+ poolDiscard(@dtd.pool );
+
+ break;
+
+ end;
+
+ inc(i );
+
+ end;
+
+ end;
+
+ end;
+
+ result:=id;
+
+end;
+
+{ defineAttribute {..}
+function defineAttribute(
+ type_ : ELEMENT_TYPE_ptr; attId : ATTRIBUTE_ID_ptr;
+ isCdata ,isId : XML_Bool; value : XML_Char_ptr; parser : XML_Parser ) : int;
+begin
+end;
+
+{ appendAttributeValue }
+function appendAttributeValue(
+ parser : XML_Parser; enc : ENCODING_ptr; isCdata : XML_Bool;
+ ptr ,end_ : char_ptr; pool : STRING_POOL_ptr ) : XML_Error;
+var
+ dtd : DTD_ptr;
+
+ next : char_ptr;
+
+ tok ,i ,n : int;
+
+ buf : array[0..XML_ENCODE_MAX - 1 ] of XML_Char;
+
+ name ,textEnd : XML_Char_ptr;
+
+ entity : ENTITY_ptr;
+
+ checkEntityDecl : char;
+
+ ch : XML_Char;
+
+ result_ : XML_Error;
+
+label
+ _break ,_go0 ;
+
+begin
+{ save one level of indirection }
+ dtd:=parser.m_dtd;
+
+ repeat
+ tok:=XmlAttributeValueTok(enc ,pointer(ptr ) ,pointer(end_ ) ,@next );
+
+ case tok of
+ XML_TOK_NONE :
+ begin
+ result:=XML_ERROR_NONE;
+
+ exit;
+
+ end;
+
+ XML_TOK_INVALID :
+ begin
+ if enc = parser.m_encoding then
+ parser.m_eventPtr:=next;
+
+ result:=XML_ERROR_INVALID_TOKEN;
+
+ end;
+
+ XML_TOK_PARTIAL :
+ begin
+ if enc = parser.m_encoding then
+ parser.m_eventPtr:=ptr;
+
+ result:=XML_ERROR_INVALID_TOKEN;
+
+ end;
+
+ XML_TOK_CHAR_REF :
+ begin
+ n:=XmlCharRefNumber(enc ,pointer(ptr ) );
+
+ if n < 0 then
+ begin
+ if enc = parser.m_encoding then
+ parser.m_eventPtr:=ptr;
+
+ result:=XML_ERROR_BAD_CHAR_REF;
+
+ end;
+
+ if (isCdata = 0 ) and
+ (n = $20 ) and { space }
+ ((poolLength(pool ) = 0 ) or
+ (poolLastChar(pool ) = XML_Char($20 ) ) ) then
+ goto _break;
+
+ n:=XmlEncode(n ,ICHAR_ptr(buf ) );
+
+ if n = 0 then
+ begin
+ if enc = parser.m_encoding then
+ parser.m_eventPtr:=ptr;
+
+ result:=XML_ERROR_BAD_CHAR_REF;
+
+ exit;
+
+ end;
+
+ i:=0;
+
+ while i < n do
+ begin
+ if poolAppendChar(pool ,buf[i ] ) = 0 then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ inc(i );
+
+ end;
+
+ end;
+
+ XML_TOK_DATA_CHARS :
+ if poolAppend(pool ,enc ,ptr ,next ) = NIL then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ XML_TOK_TRAILING_CR :
+ begin
+ next:=char_ptr(ptrcomp(ptr ) + enc.minBytesPerChar );
+
+ goto _go0;
+
+ end;
+
+ XML_TOK_ATTRIBUTE_VALUE_S ,XML_TOK_DATA_NEWLINE :
+ _go0:
+ begin
+ if (isCdata = 0 ) and
+ ((poolLength(pool ) = 0 ) or
+ (poolLastChar(pool ) = XML_Char($20 ) ) ) then
+ goto _break;
+
+ if poolAppendChar(pool ,char($20 ) ) = 0 then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ end;
+
+ XML_TOK_ENTITY_REF :
+ begin
+ ch:=
+ XML_Char(
+ XmlPredefinedEntityName(
+ enc ,
+ pointer(char_ptr(ptrcomp(ptr ) + enc.minBytesPerChar ) ) ,
+ pointer(char_ptr(ptrcomp(next ) - enc.minBytesPerChar ) ) ) );
+
+ if ch <> XML_Char(0 ) then
+ begin
+ if poolAppendChar(pool, ch) = 0 then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ goto _break;
+
+ end;
+
+ name:=
+ poolStoreString(
+ @parser.m_temp2Pool ,enc ,
+ char_ptr(ptrcomp(ptr ) + enc.minBytesPerChar ) ,
+ char_ptr(ptrcomp(next ) - enc.minBytesPerChar ) );
+
+ if name = NIL then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ entity:=ENTITY_ptr(lookup(@parser.m_dtd.generalEntities ,name ,0 ) );
+
+ poolDiscard(@parser.m_temp2Pool );
+
+ { First, determine if a check for an existing declaration is needed;
+ if yes, check that the entity exists, and that it is internal. }
+ if pool = @parser.m_dtd.pool then { are we called from prolog? }
+ begin
+ if dtd.standalone <> 0 then
+ checkEntityDecl:=char(parser.m_openInternalEntities = NIL )
+ else
+ checkEntityDecl:=char(dtd.hasParamEntityRefs = 0 );
+
+ {$IFDEF XML_DTD }
+ checkEntityDecl:=char((checkEntityDecl <> #0 ) and (parser.m_prologState.documentEntity <> 0 ) )
+
+ {$ENDIF }
+
+ end
+ else { if pool = @tempPool: we are called from content }
+ checkEntityDecl:=char((dtd.hasParamEntityRefs = 0 ) or (dtd.standalone <> 0 ) );
+
+ if checkEntityDecl <> #0 then
+ if entity = NIL then
+ begin
+ result:=XML_ERROR_UNDEFINED_ENTITY;
+
+ exit;
+
+ end
+ else
+ if entity.is_internal = 0 then
+ begin
+ result:=XML_ERROR_ENTITY_DECLARED_IN_PE;
+
+ exit;
+
+ end
+ else
+ else
+ if entity = NIL then
+ { Cannot report skipped entity here - see comments on
+ skippedEntityHandler.
+ if @parser.m_skippedEntityHandler <> NIL then
+ parser.m_skippedEntityHandler(parser.m_handlerArg ,name ,0 ); }
+ { Cannot call the default handler because this would be
+ out of sync with the call to the startElementHandler.
+ if (pool = @parser.m_tempPool ) and
+ (@parser.m_defaultHandler <> NIL ) then
+ reportDefault(parser ,enc ,ptr ,next ); }
+ goto _break;
+
+ if entity.open <> 0 then
+ begin
+ if enc = parser.m_encoding then
+ parser.m_eventPtr:=ptr;
+
+ result:=XML_ERROR_RECURSIVE_ENTITY_REF;
+
+ exit;
+
+ end;
+
+ if entity.notation <> NIL then
+ begin
+ if enc = parser.m_encoding then
+ parser.m_eventPtr:=ptr;
+
+ result:=XML_ERROR_BINARY_ENTITY_REF;
+
+ exit;
+
+ end;
+
+ if entity.textPtr = NIL then
+ begin
+ if enc = parser.m_encoding then
+ parser.m_eventPtr:=ptr;
+
+ result:=XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
+
+ exit;
+
+ end
+ else
+ begin
+ textEnd:=XML_Char_ptr(ptrcomp(entity.textPtr ) + entity.textLen * sizeof(XML_Char ) );
+
+ entity.open:=XML_TRUE;
+
+ result_:=
+ appendAttributeValue(
+ parser ,parser.m_internalEncoding ,isCdata ,
+ char_ptr(entity.textPtr ) ,
+ char_ptr(textEnd ) ,pool );
+
+ entity.open:=XML_FALSE;
+
+ if result_ <> XML_Error(0 ) then
+ begin
+ result:=result_;
+
+ exit;
+
+ end;
+
+ end;
+
+ end;
+
+ else
+ begin
+ if enc = parser.m_encoding then
+ parser.m_eventPtr:=ptr;
+
+ result:=XML_ERROR_UNEXPECTED_STATE;
+
+ exit;
+
+ end;
+
+ end;
+
+ _break:
+ ptr:=next;
+
+ until false;
+
+{ not reached }
+
+end;
+
+{ storeAttributeValue }
+function storeAttributeValue(
+ parser : XML_Parser; enc : ENCODING_ptr; isCdata : XML_Bool;
+ ptr ,end_ : char_ptr; pool : STRING_POOL_ptr ) : XML_Error;
+var
+ result_ : XML_Error;
+
+begin
+ result_:=appendAttributeValue(parser ,enc ,isCdata ,ptr ,end_ ,pool );
+
+ if result_ <> XML_Error(0 ) then
+ begin
+ result:=result_;
+
+ exit;
+
+ end;
+
+ if (isCdata = 0 ) and
+ (poolLength(pool ) <> 0 ) and
+ (poolLastChar(pool ) = XML_Char($20 ) ) then
+ poolChop(pool );
+
+ if poolAppendChar(pool ,XML_T(#0 ) ) = 0 then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ result:=XML_ERROR_NONE;
+
+end;
+
+{ storeEntityValue {..}
+function storeEntityValue(parser : XML_Parser; enc : ENCODING_ptr; start ,end_ : char_ptr ) : XML_Error;
+begin
+end;
+
+{ doIgnoreSection {..}
+{ startPtr gets set to non-null is the section is closed, and to null
+ if the section is not yet closed. }
+function doIgnoreSection(
+ parser : XML_Parser;
+ enc : ENCODING_ptr;
+ startPtr : char_ptr_ptr;
+ end_ : char_ptr;
+ nextPtr : char_ptr_ptr;
+ haveMore : XML_Bool ) : XML_Error;
+begin
+end;
+
+{ ignoreSectionProcessor {..}
+{ The idea here is to avoid using stack for each IGNORE section when
+ the whole file is parsed with one call. }
+function ignoreSectionProcessor(parser : XML_Parser; start ,end_ : char_ptr; endPtr : char_ptr_ptr ) : XML_Error;
+begin
+end;
+
+{ nextScaffoldPart {..}
+function nextScaffoldPart(parser : XML_Parser ) : int;
+begin
+end;
+
+{ build_model {..}
+function build_model(parser : XML_Parser ) : XML_Content_ptr;
+begin
+end;
+
+{ reportProcessingInstruction {..}
+function reportProcessingInstruction(parser : XML_Parser; enc : ENCODING_ptr; start ,end_ : char_ptr ) : int;
+begin
+end;
+
+{ normalizeLines {..}
+procedure normalizeLines(s : XML_Char_ptr );
+begin
+end;
+
+{ reportComment }
+function reportComment(parser : XML_Parser; enc : ENCODING_ptr; start ,end_ : char_ptr ) : int;
+var
+ data : XML_Char_ptr;
+
+begin
+ if @parser.m_commentHandler = NIL then
+ begin
+ if @parser.m_defaultHandler <> NIL then
+ reportDefault(parser ,enc ,start ,end_ );
+
+ result:=1;
+
+ exit;
+
+ end;
+
+ data:=
+ poolStoreString(
+ @parser.m_tempPool ,enc ,
+ char_ptr(ptrcomp(start ) + enc.minBytesPerChar * 4 ) ,
+ char_ptr(ptrcomp(end_ ) - enc.minBytesPerChar * 3 ) );
+
+ if data = NIL then
+ begin
+ result:=0;
+
+ exit;
+
+ end;
+
+ normalizeLines(data );
+
+ parser.m_commentHandler(parser.m_handlerArg ,data );
+
+ poolClear(@parser.m_tempPool );
+
+ result:=1;
+
+end;
+
+{ doProlog }
+function doProlog(
+ parser : XML_Parser;
+ enc : ENCODING_ptr;
+ s ,end_ : char_ptr;
+ tok : int;
+ next : char_ptr;
+ nextPtr : char_ptr_ptr;
+ haveMore : XML_Bool ) : XML_Error;
+const
+{$IFDEF XML_DTD }
+ externalSubsetName : array[0..1 ] of XML_Char = ('#' ,#0 );
+
+{$ENDIF }
+
+ atypeCDATA : array[0..5 ] of XML_Char = ('C' ,'D' ,'A' ,'T' ,'A' ,#0 );
+ atypeID : array[0..2 ] of XML_Char = ('I' ,'D' ,#0 );
+ atypeIDREF : array[0..5 ] of XML_Char = ('I' ,'D' ,'R' ,'E' ,'F' ,#0 );
+ atypeIDREFS : array[0..6 ] of XML_Char = ('I' ,'D' ,'R' ,'E' ,'F' ,'S' ,#0 );
+ atypeENTITY : array[0..6 ] of XML_Char = ('E' ,'N' ,'T' ,'I' ,'T' ,'Y' ,#0 );
+ atypeENTITIES : array[0..8 ] of XML_Char = ('E' ,'N' ,'T' ,'I' ,'T' ,'I' ,'E' ,'S',#0 );
+ atypeNMTOKEN : array[0..7 ] of XML_Char = ('N' ,'M' ,'T' ,'O' ,'K' ,'E' ,'N' ,#0 );
+ atypeNMTOKENS : array[0..8 ] of XML_Char = ('N' ,'M' ,'T' ,'O' ,'K' ,'E' ,'N' ,'S',#0 );
+ notationPrefix : array[0..8 ] of XML_Char = ('N' ,'O' ,'T' ,'A' ,'T' ,'I' ,'O' ,'N',#0 );
+ enumValueSep : array[0..1 ] of XML_Char = ('|' ,#0 );
+ enumValueStart : array[0..1 ] of XML_Char = ('(' ,#0 );
+
+var
+ dtd : DTD_ptr;
+
+ eventPP ,eventEndPP : char_ptr_ptr;
+
+ quant : XML_Content_Quant;
+
+ role ,myindex ,nameLen : int;
+
+ handleDefault ,hadParamEntityRefs ,ok ,betweenDecl : XML_Bool;
+
+ result_ : XML_Error;
+
+ tem ,prefix ,attVal ,name ,systemId : XML_Char_ptr;
+
+ entity : ENTITY_ptr;
+
+ ctemp ,nxt : char_ptr;
+
+ itemp : int_ptr;
+
+ content ,model : XML_Content_ptr;
+
+ el : ELEMENT_TYPE_ptr;
+
+label
+ _break ,_go0 ,_go1 ,
+ alreadyChecked ,checkAttListDeclHandler ,elementContent ,closeGroup ;
+
+begin
+{ save one level of indirection }
+ dtd:=parser.m_dtd;
+
+ if enc = parser.m_encoding then
+ begin
+ eventPP :=@parser.m_eventPtr;
+ eventEndPP:=@parser.m_eventEndPtr;
+
+ end
+ else
+ begin
+ eventPP :=@parser.m_openInternalEntities.internalEventPtr;
+ eventEndPP:=@parser.m_openInternalEntities.internalEventEndPtr;
+
+ end;
+
+ repeat
+ handleDefault:=XML_TRUE;
+ eventPP^ :=s;
+ eventEndPP^ :=next;
+
+ if tok <= 0 then
+ begin
+ if (haveMore <> 0 ) and
+ (tok <> XML_TOK_INVALID ) then
+ begin
+ nextPtr^:=s;
+ result :=XML_ERROR_NONE;
+
+ exit;
+
+ end;
+
+ case tok of
+ XML_TOK_INVALID :
+ begin
+ eventPP^:=next;
+ result :=XML_ERROR_INVALID_TOKEN;
+
+ exit;
+
+ end;
+
+ XML_TOK_PARTIAL :
+ begin
+ result:=XML_ERROR_UNCLOSED_TOKEN;
+
+ exit;
+
+ end;
+
+ XML_TOK_PARTIAL_CHAR :
+ begin
+ result:=XML_ERROR_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ XML_TOK_NONE :
+ begin
+ {$IFDEF XML_DTD }
+ { for internal PE NOT referenced between declarations }
+ if (enc <> parser.m_encoding ) and
+ (parser.m_openInternalEntities.betweenDecl = 0 ) then
+ begin
+ nextPtr^:=s;
+ result :=XML_ERROR_NONE;
+
+ exit;
+
+ end;
+
+ { WFC: PE Between Declarations - must check that PE contains
+ complete markup, not only for external PEs, but also for
+ internal PEs if the reference occurs between declarations. }
+ if (parser.m_isParamEntity <> 0 ) or
+ (enc <> parser.m_encoding ) then
+ begin
+ if XmlTokenRole(@parser.m_prologState ,XML_TOK_NONE ,pointer(end_ ) ,pointer(end_ ) ,enc ) = XML_ROLE_ERROR then
+ begin
+ result:=XML_ERROR_INCOMPLETE_PE;
+
+ exit;
+
+ end;
+
+ nextPtr^:=s;
+ result :=XML_ERROR_NONE;
+
+ exit;
+
+ end;
+
+ {$ENDIF }
+
+ result:=XML_ERROR_NO_ELEMENTS;
+
+ exit;
+
+ end;
+
+ else
+ begin
+ tok :=-tok;
+ next:=end_;
+
+ end;
+
+ end;
+
+ end;
+
+ role:=XmlTokenRole(@parser.m_prologState ,tok ,pointer(s ) ,pointer(next ) ,enc );
+
+ case role of
+ XML_ROLE_XML_DECL :
+ begin
+ result_:=processXmlDecl(parser ,0 ,s ,next );
+
+ if result_ <> XML_ERROR_NONE then
+ begin
+ result:=result_;
+
+ exit;
+
+ end;
+
+ enc:=parser.m_encoding;
+
+ handleDefault:=XML_FALSE;
+
+ end;
+
+ XML_ROLE_DOCTYPE_NAME :
+ begin
+ if @parser.m_startDoctypeDeclHandler <> NIL then
+ begin
+ parser.m_doctypeName:=poolStoreString(@parser.m_tempPool ,enc ,s ,next );
+
+ if parser.m_doctypeName = NIL then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ poolFinish(@parser.m_tempPool );
+
+ parser.m_doctypePubid:=NIL;
+ handleDefault :=XML_FALSE;
+
+ end;
+
+ parser.m_doctypeSysid:=NIL; { always initialize to NULL }
+
+ end;
+
+ XML_ROLE_DOCTYPE_INTERNAL_SUBSET :
+ if @parser.m_startDoctypeDeclHandler <> NIL then
+ begin
+ parser.m_startDoctypeDeclHandler(
+ parser.m_handlerArg ,parser.m_doctypeName ,
+ parser.m_doctypeSysid ,parser.m_doctypePubid ,1 );
+
+ parser.m_doctypeName:=NIL;
+
+ poolClear(@parser.m_tempPool );
+
+ handleDefault:=XML_FALSE;
+
+ end;
+
+ {$IFDEF XML_DTD }
+ XML_ROLE_TEXT_DECL :
+ begin
+ result_:=processXmlDecl(parser ,1 ,s ,next );
+
+ if result_ <> XML_ERROR_NONE then
+ begin
+ result:=result_;
+
+ exit;
+
+ end;
+
+ enc :=parser.m_encoding;
+ handleDefault:=XML_FALSE;
+
+ end;
+
+ {$ENDIF }
+
+ XML_ROLE_DOCTYPE_PUBLIC_ID :
+ begin
+ {$IFDEF XML_DTD }
+ parser.m_useForeignDTD:=XML_FALSE;
+ parser.m_declEntity :=
+ ENTITY_ptr(
+ lookup(@dtd.paramEntities ,@externalSubsetName[0 ] ,sizeof(expat.ENTITY ) ) );
+
+ if parser.m_declEntity = NIL then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ {$ENDIF }
+ dtd.hasParamEntityRefs:=XML_TRUE;
+
+ if @parser.m_startDoctypeDeclHandler <> NIL then
+ begin
+ if XmlIsPublicId(enc ,pointer(s ) ,pointer(next ) ,pointer(eventPP ) ) = 0 then
+ begin
+ result:=XML_ERROR_PUBLICID;
+
+ exit;
+
+ end;
+
+ parser.m_doctypePubid:=
+ poolStoreString(
+ @parser.m_tempPool ,enc ,
+ char_ptr(ptrcomp(s ) + enc.minBytesPerChar ) ,
+ char_ptr(ptrcomp(next ) - enc.minBytesPerChar ) );
+
+ if parser.m_doctypePubid = NIL then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ normalizePublicId(XML_Char_ptr(parser.m_doctypePubid ) );
+ poolFinish (@parser.m_tempPool );
+
+ handleDefault:=XML_FALSE;
+
+ goto alreadyChecked;
+
+ end;
+
+ { fall through }
+ goto _go0;
+
+ end;
+
+ XML_ROLE_ENTITY_PUBLIC_ID :
+ _go0:
+ begin
+ if XmlIsPublicId(enc ,pointer(s ) ,pointer(next ) ,pointer(eventPP ) ) = 0 then
+ begin
+ result:=XML_ERROR_PUBLICID;
+
+ exit;
+
+ end;
+
+ alreadyChecked:
+ if (dtd.keepProcessing <> 0 ) and
+ (parser.m_declEntity <> NIL ) then
+ begin
+ tem:=
+ poolStoreString(
+ @dtd.pool ,enc ,
+ char_ptr(ptrcomp(s ) + enc.minBytesPerChar ) ,
+ char_ptr(ptrcomp(next ) - enc.minBytesPerChar ) );
+
+ if tem = NIL then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ normalizePublicId(tem );
+
+ parser.m_declEntity.publicId:=tem;
+
+ poolFinish(@dtd.pool );
+
+ if @parser.m_entityDeclHandler <> NIL then
+ handleDefault:=XML_FALSE;
+
+ end;
+
+ end;
+
+ XML_ROLE_DOCTYPE_CLOSE :
+ begin
+ if parser.m_doctypeName <> NIL then
+ begin
+ parser.m_startDoctypeDeclHandler(
+ parser.m_handlerArg ,parser.m_doctypeName ,
+ parser.m_doctypeSysid ,parser.m_doctypePubid ,0 );
+
+ poolClear(@parser.m_tempPool );
+
+ handleDefault:=XML_FALSE;
+
+ end;
+
+ { doctypeSysid will be non-NULL in the case of a previous
+ XML_ROLE_DOCTYPE_SYSTEM_ID, even if startDoctypeDeclHandler
+ was not set, indicating an external subset }
+ {$IFDEF XML_DTD }
+ if (parser.m_doctypeSysid <> NIL ) or
+ (parser.m_useForeignDTD <> 0 ) then
+ begin
+ hadParamEntityRefs :=dtd.hasParamEntityRefs;
+ dtd.hasParamEntityRefs:=XML_TRUE;
+
+ if (parser.m_paramEntityParsing <> XML_ParamEntityParsing(0 ) ) and
+ (@parser.m_externalEntityRefHandler <> NIL ) then
+ begin
+ entity:=
+ ENTITY_ptr(
+ lookup(@dtd.paramEntities ,@externalSubsetName[0 ] ,sizeof(expat.ENTITY ) ) );
+
+ if entity = NIL then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ if parser.m_useForeignDTD <> 0 then
+ entity.base:=parser.m_curBase;
+
+ dtd.paramEntityRead:=XML_FALSE;
+
+ if parser.m_externalEntityRefHandler(
+ parser.m_externalEntityRefHandlerArg ,0 ,
+ entity.base ,
+ entity.systemId ,
+ entity.publicId ) = 0 then
+ begin
+ result:=XML_ERROR_EXTERNAL_ENTITY_HANDLING;
+
+ exit;
+
+ end;
+
+ if dtd.paramEntityRead <> 0 then
+ if (dtd.standalone = 0 ) and
+ (@parser.m_notStandaloneHandler <> NIL ) and
+ (parser.m_notStandaloneHandler(parser.m_handlerArg ) = 0 ) then
+ begin
+ result:=XML_ERROR_NOT_STANDALONE;
+
+ exit;
+
+ end
+ else
+ else
+ { if we didn't read the foreign DTD then this means that there
+ is no external subset and we must reset dtd.hasParamEntityRefs }
+ if parser.m_doctypeSysid = NIL then
+ dtd.hasParamEntityRefs:=hadParamEntityRefs;
+
+ { end of DTD - no need to update dtd.keepProcessing }
+
+ end;
+
+ parser.m_useForeignDTD:=XML_FALSE;
+
+ end;
+
+ {$ENDIF }
+ if @parser.m_endDoctypeDeclHandler <> NIL then
+ begin
+ parser.m_endDoctypeDeclHandler(parser.m_handlerArg );
+
+ handleDefault:=XML_FALSE;
+
+ end;
+
+ end;
+
+ XML_ROLE_INSTANCE_START :
+ begin
+ {$IFDEF XML_DTD }
+ { if there is no DOCTYPE declaration then now is the
+ last chance to read the foreign DTD }
+ if parser.m_useForeignDTD <> 0 then
+ begin
+ hadParamEntityRefs :=dtd.hasParamEntityRefs;
+ dtd.hasParamEntityRefs:=XML_TRUE;
+
+ if (parser.m_paramEntityParsing <> XML_ParamEntityParsing(0 ) ) and
+ (@parser.m_externalEntityRefHandler <> NIL ) then
+ begin
+ entity:=
+ ENTITY_ptr(
+ lookup(@dtd.paramEntities ,@externalSubsetName[0 ] ,sizeof(expat.ENTITY ) ) );
+
+ if entity = NIL then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ entity.base :=parser.m_curBase;
+ dtd.paramEntityRead:=XML_FALSE;
+
+ if parser.m_externalEntityRefHandler(
+ parser.m_externalEntityRefHandlerArg ,0 ,
+ entity.base ,
+ entity.systemId ,
+ entity.publicId ) = 0 then
+ begin
+ result:=XML_ERROR_EXTERNAL_ENTITY_HANDLING;
+
+ exit;
+
+ end;
+
+ if dtd.paramEntityRead <> 0 then
+ if (dtd.standalone = 0 ) and
+ (@parser.m_notStandaloneHandler <> NIL ) and
+ (parser.m_notStandaloneHandler(parser.m_handlerArg ) = 0 ) then
+ begin
+ result:=XML_ERROR_NOT_STANDALONE;
+
+ exit;
+
+ end
+ else
+ else
+ { if we didn't read the foreign DTD then this means that there
+ is no external subset and we must reset dtd.hasParamEntityRefs }
+ dtd.hasParamEntityRefs:=hadParamEntityRefs;
+
+ { end of DTD - no need to update dtd.keepProcessing }
+
+ end;
+
+ end;
+
+ {$ENDIF }
+ parser.m_processor:=@contentProcessor;
+
+ result:=contentProcessor(parser ,s ,end_ ,nextPtr );
+
+ exit;
+
+ end;
+
+ XML_ROLE_ATTLIST_ELEMENT_NAME :
+ begin
+ parser.m_declElementType:=getElementType(parser ,enc ,s ,next );
+
+ if parser.m_declElementType = NIL then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ goto checkAttListDeclHandler;
+
+ end;
+
+ XML_ROLE_ATTRIBUTE_NAME :
+ begin
+ parser.m_declAttributeId:=getAttributeId(parser ,enc ,s ,next );
+
+ if parser.m_declAttributeId = NIL then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ parser.m_declAttributeIsCdata:=XML_FALSE;
+ parser.m_declAttributeType :=NIL;
+ parser.m_declAttributeIsId :=XML_FALSE;
+
+ goto checkAttListDeclHandler;
+
+ end;
+
+ XML_ROLE_ATTRIBUTE_TYPE_CDATA :
+ begin
+ parser.m_declAttributeIsCdata:=XML_TRUE;
+ parser.m_declAttributeType :=@atypeCDATA[0 ];
+
+ goto checkAttListDeclHandler;
+
+ end;
+
+ XML_ROLE_ATTRIBUTE_TYPE_ID :
+ begin
+ parser.m_declAttributeIsId:=XML_TRUE;
+ parser.m_declAttributeType:=@atypeID[0 ];
+
+ goto checkAttListDeclHandler;
+
+ end;
+
+ XML_ROLE_ATTRIBUTE_TYPE_IDREF :
+ begin
+ parser.m_declAttributeType:=@atypeIDREF[0 ];
+
+ goto checkAttListDeclHandler;
+
+ end;
+
+ XML_ROLE_ATTRIBUTE_TYPE_IDREFS :
+ begin
+ parser.m_declAttributeType:=@atypeIDREFS[0 ];
+
+ goto checkAttListDeclHandler;
+
+ end;
+
+ XML_ROLE_ATTRIBUTE_TYPE_ENTITY :
+ begin
+ parser.m_declAttributeType:=@atypeENTITY[0 ];
+
+ goto checkAttListDeclHandler;
+
+ end;
+
+ XML_ROLE_ATTRIBUTE_TYPE_ENTITIES :
+ begin
+ parser.m_declAttributeType:=@atypeENTITIES[0 ];
+
+ goto checkAttListDeclHandler;
+
+ end;
+
+ XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN :
+ begin
+ parser.m_declAttributeType:=@atypeNMTOKEN[0 ];
+
+ goto checkAttListDeclHandler;
+
+ end;
+
+ XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS :
+ begin
+ parser.m_declAttributeType:=@atypeNMTOKENS[0 ];
+
+ checkAttListDeclHandler:
+ if (dtd.keepProcessing <> 0 ) and
+ (@parser.m_attlistDeclHandler <> NIL ) then
+ handleDefault:=XML_FALSE;
+
+ end;
+
+ XML_ROLE_ATTRIBUTE_ENUM_VALUE ,XML_ROLE_ATTRIBUTE_NOTATION_VALUE :
+ if (dtd.keepProcessing <> 0 ) and
+ (@parser.m_attlistDeclHandler <> NIL ) then
+ begin
+ if parser.m_declAttributeType <> NIL then
+ prefix:=@enumValueSep[0 ]
+
+ else
+ if role = XML_ROLE_ATTRIBUTE_NOTATION_VALUE then
+ prefix:=@notationPrefix[0 ]
+ else
+ prefix:=@enumValueStart[0 ];
+
+ if poolAppendString(@parser.m_tempPool ,prefix ) = NIL then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ if poolAppend(@parser.m_tempPool ,enc ,s ,next ) = NIL then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ parser.m_declAttributeType:=parser.m_tempPool.start;
+
+ handleDefault:=XML_FALSE;
+
+ end;
+
+ XML_ROLE_IMPLIED_ATTRIBUTE_VALUE ,XML_ROLE_REQUIRED_ATTRIBUTE_VALUE :
+ if dtd.keepProcessing <> 0 then
+ begin
+ if defineAttribute(
+ parser.m_declElementType ,parser.m_declAttributeId ,
+ parser.m_declAttributeIsCdata ,parser.m_declAttributeIsId ,
+ 0 ,parser ) = 0 then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ if (@parser.m_attlistDeclHandler <> NIL ) and
+ (parser.m_declAttributeType <> NIL ) then
+ begin
+ if (parser.m_declAttributeType^ = XML_T('(' ) ) or
+ ((parser.m_declAttributeType^ = XML_T('N' ) ) and
+ (XML_Char_ptr(ptrcomp(parser.m_declAttributeType ) + 1 )^ = XML_T('O' ) ) ) then
+ begin
+ { Enumerated or Notation type }
+ if (poolAppendChar(@parser.m_tempPool ,XML_T(')' ) ) = 0 ) or
+ (poolAppendChar(@parser.m_tempPool ,XML_T(#0 ) ) = 0 ) then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ parser.m_declAttributeType:=parser.m_tempPool.start;
+
+ poolFinish(@parser.m_tempPool );
+
+ end;
+
+ eventEndPP^:=s;
+
+ parser.m_attlistDeclHandler(
+ parser.m_handlerArg ,parser.m_declElementType.name ,
+ parser.m_declAttributeId.name ,parser.m_declAttributeType ,
+ 0 ,int(role = XML_ROLE_REQUIRED_ATTRIBUTE_VALUE ) );
+
+ poolClear(@parser.m_tempPool );
+
+ handleDefault:=XML_FALSE;
+
+ end;
+
+ end;
+
+ XML_ROLE_DEFAULT_ATTRIBUTE_VALUE ,XML_ROLE_FIXED_ATTRIBUTE_VALUE :
+ if dtd.keepProcessing <> 0 then
+ begin
+ result_:=
+ storeAttributeValue(
+ parser ,enc ,parser.m_declAttributeIsCdata ,
+ char_ptr(ptrcomp(s ) + enc.minBytesPerChar ) ,
+ char_ptr(ptrcomp(next ) - enc.minBytesPerChar ) ,
+ @dtd.pool );
+
+ if result_ <> XML_Error(0 ) then
+ begin
+ result:=result_;
+
+ exit;
+
+ end;
+
+ attVal:=poolStart(@dtd.pool );
+
+ poolFinish(@dtd.pool );
+
+ { ID attributes aren't allowed to have a default }
+ if defineAttribute(
+ parser.m_declElementType ,parser.m_declAttributeId ,
+ parser.m_declAttributeIsCdata ,XML_FALSE ,attVal ,parser ) = 0 then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ if (@parser.m_attlistDeclHandler <> NIL ) and
+ (parser.m_declAttributeType <> NIL ) then
+ begin
+ if (parser.m_declAttributeType^ = XML_T('(' ) ) or
+ ((parser.m_declAttributeType^ = XML_T('N' ) ) and
+ (XML_Char_ptr(ptrcomp(parser.m_declAttributeType ) + 1 )^ = XML_T('O' ) ) ) then
+ begin
+ { Enumerated or Notation type }
+ if (poolAppendChar(@parser.m_tempPool ,XML_T(')' ) ) = 0 ) or
+ (poolAppendChar(@parser.m_tempPool ,XML_T(#0 ) ) = 0 ) then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ parser.m_declAttributeType:=parser.m_tempPool.start;
+
+ poolFinish(@parser.m_tempPool );
+
+ end;
+
+ eventEndPP^:=s;
+
+ parser.m_attlistDeclHandler(
+ parser.m_handlerArg ,parser.m_declElementType.name ,
+ parser.m_declAttributeId.name ,parser.m_declAttributeType ,
+ attVal ,int(role = XML_ROLE_FIXED_ATTRIBUTE_VALUE ) );
+
+ poolClear(@parser.m_tempPool );
+
+ handleDefault:=XML_FALSE;
+
+ end;
+
+ end;
+
+ XML_ROLE_ENTITY_VALUE :
+ if dtd.keepProcessing <> 0 then
+ begin
+ result_:=
+ storeEntityValue(
+ parser ,enc ,
+ char_ptr(ptrcomp(s ) + enc.minBytesPerChar ) ,
+ char_ptr(ptrcomp(next ) - enc.minBytesPerChar ) );
+
+ if parser.m_declEntity <> NIL then
+ begin
+ parser.m_declEntity.textPtr:=poolStart(@dtd.entityValuePool );
+ parser.m_declEntity.textLen:=poolLength(@dtd.entityValuePool );
+
+ poolFinish(@dtd.entityValuePool );
+
+ if @parser.m_entityDeclHandler <> NIL then
+ begin
+ eventEndPP^:=s;
+
+ parser.m_entityDeclHandler(
+ parser.m_handlerArg ,
+ parser.m_declEntity.name,
+ parser.m_declEntity.is_param,
+ parser.m_declEntity.textPtr,
+ parser.m_declEntity.textLen,
+ parser.m_curBase ,0 ,0 ,0 );
+
+ handleDefault:=XML_FALSE;
+
+ end;
+
+ end
+ else
+ poolDiscard(@dtd.entityValuePool );
+
+ if result_ <> XML_ERROR_NONE then
+ begin
+ result:=result_;
+
+ exit;
+
+ end;
+
+ end;
+
+ XML_ROLE_DOCTYPE_SYSTEM_ID :
+ begin
+ {$IFDEF XML_DTD }
+ parser.m_useForeignDTD:=XML_FALSE;
+
+ {$ENDIF }
+
+ dtd.hasParamEntityRefs:=XML_TRUE;
+
+ if @parser.m_startDoctypeDeclHandler <> NIL then
+ begin
+ parser.m_doctypeSysid:=
+ poolStoreString(
+ @parser.m_tempPool ,enc ,
+ char_ptr(ptrcomp(s ) + enc.minBytesPerChar ) ,
+ char_ptr(ptrcomp(next ) - enc.minBytesPerChar ) );
+
+ if parser.m_doctypeSysid = NIL then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ poolFinish(@parser.m_tempPool );
+
+ handleDefault:=XML_FALSE;
+
+ end
+ {$IFDEF XML_DTD }
+ else
+ { use externalSubsetName to make doctypeSysid non-NULL
+ for the case where no startDoctypeDeclHandler is set }
+ parser.m_doctypeSysid:=@externalSubsetName[0 ];
+
+ {$ELSE }; {$ENDIF }
+
+ if (dtd.standalone = 0 ) and
+ {$IFDEF XML_DTD }
+ (parser.m_paramEntityParsing = XML_ParamEntityParsing(0 ) ) and
+ {$ENDIF }
+ (@parser.m_notStandaloneHandler <> NIL ) and
+ (parser.m_notStandaloneHandler(parser.m_handlerArg ) = 0 ) then
+ begin
+ result:=XML_ERROR_NOT_STANDALONE;
+
+ exit;
+
+ end;
+
+ {$IFNDEF XML_DTD }
+ {$ELSE }
+ if parser.m_declEntity = NIL then
+ begin
+ parser.m_declEntity:=
+ ENTITY_ptr(
+ lookup(
+ @dtd.paramEntities ,@externalSubsetName[0 ] ,sizeof(expat.ENTITY ) ) );
+
+ if parser.m_declEntity = NIL then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ parser.m_declEntity.publicId:=NIL;
+
+ end;
+
+ {$ENDIF }
+ { fall through }
+ goto _go1;
+
+ end;
+
+ XML_ROLE_ENTITY_SYSTEM_ID :
+ _go1:
+ if (dtd.keepProcessing <> 0 ) and
+ (parser.m_declEntity <> NIL ) then
+ begin
+ parser.m_declEntity.systemId:=
+ poolStoreString(
+ @dtd.pool ,enc ,
+ char_ptr(ptrcomp(s ) + enc.minBytesPerChar ) ,
+ char_ptr(ptrcomp(next ) - enc.minBytesPerChar ) );
+
+ if parser.m_declEntity.systemId = NIL then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ parser.m_declEntity.base:=parser.m_curBase;
+
+ poolFinish(@dtd.pool );
+
+ if @parser.m_entityDeclHandler <> NIL then
+ handleDefault:=XML_FALSE;
+
+ end;
+
+ XML_ROLE_ENTITY_COMPLETE :
+ if (dtd.keepProcessing <> 0 ) and
+ (parser.m_declEntity <> NIL ) and
+ (@parser.m_entityDeclHandler <> NIL ) then
+ begin
+ eventEndPP^:=s;
+
+ parser.m_entityDeclHandler(
+ parser.m_handlerArg ,
+ parser.m_declEntity.name ,
+ parser.m_declEntity.is_param ,
+ 0 ,0 ,
+ parser.m_declEntity.base ,
+ parser.m_declEntity.systemId ,
+ parser.m_declEntity.publicId ,
+ 0 );
+
+ handleDefault:=XML_FALSE;
+
+ end;
+
+ XML_ROLE_ENTITY_NOTATION_NAME :
+ if (dtd.keepProcessing <> 0 ) and
+ (parser.m_declEntity <> NIL ) then
+ begin
+ parser.m_declEntity.notation:=poolStoreString(@dtd.pool ,enc ,s ,next );
+
+ if parser.m_declEntity.notation = NIL then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ poolFinish(@dtd.pool );
+
+ if @parser.m_unparsedEntityDeclHandler <> NIL then
+ begin
+ eventEndPP^:=s;
+
+ parser.m_unparsedEntityDeclHandler(
+ parser.m_handlerArg ,
+ parser.m_declEntity.name ,
+ parser.m_declEntity.base ,
+ parser.m_declEntity.systemId ,
+ parser.m_declEntity.publicId ,
+ parser.m_declEntity.notation );
+
+ handleDefault:=XML_FALSE;
+
+ end
+ else
+ if @parser.m_entityDeclHandler <> NIL then
+ begin
+ eventEndPP^:=s;
+
+ parser.m_entityDeclHandler(
+ parser.m_handlerArg ,
+ parser.m_declEntity.name ,
+ 0 ,0 ,0 ,
+ parser.m_declEntity.base,
+ parser.m_declEntity.systemId ,
+ parser.m_declEntity.publicId ,
+ parser.m_declEntity.notation );
+
+ handleDefault:=XML_FALSE;
+
+ end;
+
+ end;
+
+ XML_ROLE_GENERAL_ENTITY_NAME :
+ begin
+ if XmlPredefinedEntityName(enc ,pointer(s ) ,pointer(next ) ) <> 0 then
+ begin
+ parser.m_declEntity:=NIL;
+
+ goto _break;
+
+ end;
+
+ if dtd.keepProcessing <> 0 then
+ begin
+ name:=poolStoreString(@dtd.pool ,enc ,s ,next );
+
+ if name = NIL then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ parser.m_declEntity:=
+ ENTITY_ptr(
+ lookup(@dtd.generalEntities ,name ,sizeof(expat.ENTITY ) ) );
+
+ if parser.m_declEntity = NIL then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ if parser.m_declEntity.name <> name then
+ begin
+ poolDiscard(@dtd.pool );
+
+ parser.m_declEntity:=NIL;
+
+ end
+ else
+ begin
+ poolFinish(@dtd.pool );
+
+ parser.m_declEntity.publicId:=NIL;
+ parser.m_declEntity.is_param:=XML_FALSE;
+
+ { if we have a parent parser or are reading an internal parameter
+ entity, then the entity declaration is not considered "internal" }
+ parser.m_declEntity.is_internal:=
+ XML_Bool(
+ not ((parser.m_parentParser <> NIL ) or
+ (parser.m_openInternalEntities <> NIL ) ) );
+
+ if @parser.m_entityDeclHandler <> NIL then
+ handleDefault:=XML_FALSE;
+
+ end;
+
+ end
+ else
+ begin
+ poolDiscard(@dtd.pool );
+
+ parser.m_declEntity:=NIL;
+
+ end;
+
+ end;
+
+ XML_ROLE_PARAM_ENTITY_NAME :
+ {$IFDEF XML_DTD }
+ if dtd.keepProcessing <> 0 then
+ begin
+ name:=poolStoreString(@dtd.pool ,enc ,s ,next );
+
+ if name <> NIL then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ parser.m_declEntity:=
+ ENTITY_ptr(
+ lookup(@dtd.paramEntities ,name ,sizeof(expat.ENTITY ) ) );
+
+ if parser.m_declEntity = NIL then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ if parser.m_declEntity.name <> name then
+ begin
+ poolDiscard(@dtd.pool );
+
+ parser.m_declEntity:=NIL;
+
+ end
+ else
+ begin
+ poolFinish(@dtd.pool );
+
+ parser.m_declEntity.publicId:=NIL;
+ parser.m_declEntity.is_param:=XML_TRUE;
+
+ { if we have a parent parser or are reading an internal parameter
+ entity, then the entity declaration is not considered "internal" }
+ parser.m_declEntity.is_internal:=
+ XML_Bool(
+ not((parser.m_parentParser <> NIL ) or
+ (parser.m_openInternalEntities <> NIL ) ) );
+
+ if @parser.m_entityDeclHandler <> NIL then
+ handleDefault:=XML_FALSE;
+
+ end;
+
+ end
+ else
+ begin
+ poolDiscard(@dtd.pool );
+
+ parser.m_declEntity:=NIL;
+
+ end;
+
+ {$ELSE }
+ parser.m_declEntity:=NIL;
+
+ {$ENDIF }
+
+ XML_ROLE_NOTATION_NAME :
+ begin
+ parser.m_declNotationPublicId:=NIL;
+ parser.m_declNotationName :=NIL;
+
+ if @parser.m_notationDeclHandler <> NIL then
+ begin
+ parser.m_declNotationName:=poolStoreString(@parser.m_tempPool ,enc ,s ,next );
+
+ if parser.m_declNotationName = NIL then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ poolFinish(@parser.m_tempPool );
+
+ handleDefault:=XML_FALSE;
+
+ end;
+
+ end;
+
+ XML_ROLE_NOTATION_PUBLIC_ID :
+ begin
+ if XmlIsPublicId(enc ,pointer(s ) ,pointer(next ) ,pointer(eventPP ) ) = 0 then
+ begin
+ result:=XML_ERROR_PUBLICID;
+
+ exit;
+
+ end;
+
+ if parser.m_declNotationName <> NIL then { means notationDeclHandler <> NIL }
+ begin
+ tem:=
+ poolStoreString(
+ @parser.m_tempPool ,
+ enc ,
+ char_ptr(ptrcomp(s ) + enc.minBytesPerChar ) ,
+ char_ptr(ptrcomp(next ) - enc.minBytesPerChar ) );
+
+ if tem = NIL then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ normalizePublicId(tem );
+
+ parser.m_declNotationPublicId:=tem;
+
+ poolFinish(@parser.m_tempPool );
+
+ handleDefault:=XML_FALSE;
+
+ end;
+
+ end;
+
+ XML_ROLE_NOTATION_SYSTEM_ID :
+ begin
+ if (parser.m_declNotationName <> NIL ) and
+ (@parser.m_notationDeclHandler <> NIL ) then
+ begin
+ systemId:=
+ poolStoreString(
+ @parser.m_tempPool ,enc ,
+ char_ptr(ptrcomp(s ) + enc.minBytesPerChar ) ,
+ char_ptr(ptrcomp(next ) - enc.minBytesPerChar ) );
+
+ if systemId = NIL then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ eventEndPP^:=s;
+
+ parser.m_notationDeclHandler(
+ parser.m_handlerArg ,
+ parser.m_declNotationName ,
+ parser.m_curBase ,
+ systemId ,
+ parser.m_declNotationPublicId );
+
+ handleDefault:=XML_FALSE;
+
+ end;
+
+ poolClear(@parser.m_tempPool );
+
+ end;
+
+ XML_ROLE_NOTATION_NO_SYSTEM_ID :
+ begin
+ if (parser.m_declNotationPublicId <> NIL ) and
+ (@parser.m_notationDeclHandler <> NIL ) then
+ begin
+ eventEndPP^:=s;
+
+ parser.m_notationDeclHandler(
+ parser.m_handlerArg ,
+ parser.m_declNotationName ,
+ parser.m_curBase ,
+ 0 ,
+ parser.m_declNotationPublicId );
+
+ handleDefault:=XML_FALSE;
+
+ end;
+
+ poolClear(@parser.m_tempPool );
+
+ end;
+
+ XML_ROLE_ERROR :
+ case tok of
+ XML_TOK_PARAM_ENTITY_REF :
+ { PE references in internal subset are
+ not allowed within declarations. }
+ begin
+ result:=XML_ERROR_PARAM_ENTITY_REF;
+
+ exit;
+
+ end;
+
+ XML_TOK_XML_DECL :
+ begin
+ result:=XML_ERROR_MISPLACED_XML_PI;
+
+ exit;
+
+ end;
+
+ else
+ begin
+ result:=XML_ERROR_SYNTAX;
+
+ exit;
+
+ end;
+
+ end;
+
+ {$IFDEF XML_DTD }
+ XML_ROLE_IGNORE_SECT :
+ begin
+ if @parser.m_defaultHandler <> NIL then
+ reportDefault(parser ,enc ,s ,next );
+
+ handleDefault:=XML_FALSE;
+
+ result_:=doIgnoreSection(parser ,enc ,@next ,end_ ,nextPtr ,haveMore );
+
+ if result_ <> XML_ERROR_NONE then
+ begin
+ result:=result_;
+
+ exit;
+
+ end
+ else
+ if next = NIL then
+ begin
+ parser.m_processor:=@ignoreSectionProcessor;
+
+ result:=result_;
+
+ exit;
+
+ end;
+
+ end;
+
+ {$ENDIF }
+
+ XML_ROLE_GROUP_OPEN :
+ begin
+ if parser.m_prologState.level >= parser.m_groupSize then
+ if parser.m_groupSize <> 0 then
+ begin
+ parser.m_groupSize:=parser.m_groupSize * 2;
+
+ if parser.m_mem.realloc_fcn(
+ pointer(parser.m_groupConnector ) ,
+ parser.m_groupAlloc ,
+ parser.m_groupSize ) then
+ parser.m_groupAlloc:=parser.m_groupSize
+
+ else
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ if dtd.scaffIndex <> NIL then
+ if parser.m_mem.realloc_fcn(
+ pointer(dtd.scaffIndex ) ,
+ dtd.scaffAlloc ,
+ parser.m_groupSize * sizeof(int ) ) then
+ dtd.scaffAlloc:=parser.m_groupSize * sizeof(int )
+
+ else
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ end
+ else
+ begin
+ parser.m_groupSize:=32;
+
+ if parser.m_mem.malloc_fcn(
+ pointer(parser.m_groupConnector ) ,
+ parser.m_groupSize ) then
+ parser.m_groupAlloc:=parser.m_groupSize
+
+ else
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ end;
+
+ char_ptr(ptrcomp(parser.m_groupConnector ) + parser.m_prologState.level )^:=#0;
+
+ if dtd.in_eldecl <> 0 then
+ begin
+ myindex:=nextScaffoldPart(parser );
+
+ if myindex < 0 then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ int_ptr(ptrcomp(dtd.scaffIndex ) + dtd.scaffLevel * sizeof(int ) )^:=myindex;
+
+ inc(dtd.scaffLevel );
+
+ CONTENT_SCAFFOLD_ptr(ptrcomp(dtd.scaffold ) + myindex * sizeof(CONTENT_SCAFFOLD ) )^.type_:=XML_CTYPE_SEQ;
+
+ if @parser.m_elementDeclHandler <> NIL then
+ handleDefault:=XML_FALSE;
+
+ end;
+
+ end;
+
+ XML_ROLE_GROUP_SEQUENCE :
+ begin
+ if char_ptr(ptrcomp(parser.m_groupConnector ) + parser.m_prologState.level )^ = '|' then
+ begin
+ result:=XML_ERROR_SYNTAX;
+
+ exit;
+
+ end;
+
+ char_ptr(ptrcomp(parser.m_groupConnector ) + parser.m_prologState.level )^:=',';
+
+ if (dtd.in_eldecl <> 0 ) and
+ (@parser.m_elementDeclHandler <> NIL ) then
+ handleDefault:=XML_FALSE;
+
+ end;
+
+ XML_ROLE_GROUP_CHOICE :
+ begin
+ if char_ptr(ptrcomp(parser.m_groupConnector ) + parser.m_prologState.level )^ = ',' then
+ begin
+ result:=XML_ERROR_SYNTAX;
+
+ exit;
+
+ end;
+
+ if (dtd.in_eldecl <> 0 ) and
+ (char_ptr(ptrcomp(parser.m_groupConnector ) + parser.m_prologState.level )^ <> #0 ) and
+ (CONTENT_SCAFFOLD_ptr(
+ ptrcomp(dtd.scaffold ) +
+ int_ptr(ptrcomp(dtd.scaffIndex ) + (dtd.scaffLevel - 1 ) * sizeof(int ) )^ *
+ sizeof(CONTENT_SCAFFOLD ) )^.type_ <> XML_CTYPE_MIXED ) then
+ begin
+ CONTENT_SCAFFOLD_ptr(
+ ptrcomp(dtd.scaffold ) +
+ int_ptr(ptrcomp(dtd.scaffIndex ) + (dtd.scaffLevel - 1 ) * sizeof(int ) )^ *
+ sizeof(CONTENT_SCAFFOLD ) )^.type_:=XML_CTYPE_CHOICE;
+
+ if @parser.m_elementDeclHandler <> NIL then
+ handleDefault:=XML_FALSE;
+
+ end;
+
+ char_ptr(ptrcomp(parser.m_groupConnector ) + parser.m_prologState.level )^:='|';
+
+ end;
+
+ XML_ROLE_PARAM_ENTITY_REF {$IFDEF XML_DTD } ,XML_ROLE_INNER_PARAM_ENTITY_REF : {$ELSE }: {$ENDIF }
+ begin
+ {$IFDEF XML_DTD }
+ dtd.hasParamEntityRefs:=XML_TRUE;
+
+ if parser.m_paramEntityParsing = XML_ParamEntityParsing(0 ) then
+ dtd.keepProcessing:=dtd.standalone
+
+ else
+ begin
+ name:=
+ poolStoreString(
+ @dtd.pool ,enc ,
+ char_ptr(ptrcomp(s ) + enc.minBytesPerChar ) ,
+ char_ptr(ptrcomp(next ) - enc.minBytesPerChar ) );
+
+ if name = NIL then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ entity:=ENTITY_ptr(lookup(@dtd.paramEntities ,name ,0 ) );
+
+ poolDiscard(@dtd.pool );
+
+ { first, determine if a check for an existing declaration is needed;
+ if yes, check that the entity exists, and that it is internal,
+ otherwise call the skipped entity handler }
+ if dtd.standalone <> 0 then
+ ok:=XML_Bool(parser.m_openInternalEntities = NIL )
+ else
+ ok:=XML_Bool(dtd.hasParamEntityRefs = 0 );
+
+ if (parser.m_prologState.documentEntity <> 0 ) and
+ (ok <> 0 ) then
+ if entity = NIL then
+ begin
+ result:=XML_ERROR_UNDEFINED_ENTITY;
+
+ exit;
+
+ end
+ else
+ if entity.is_internal = 0 then
+ begin
+ result:=XML_ERROR_ENTITY_DECLARED_IN_PE;
+
+ exit;
+
+ end
+ else
+ else
+ if entity = NIL then
+ begin
+ dtd.keepProcessing:=dtd.standalone;
+
+ { cannot report skipped entities in declarations }
+ if (role = XML_ROLE_PARAM_ENTITY_REF ) and
+ (@parser.m_skippedEntityHandler <> NIL ) then
+ begin
+ parser.m_skippedEntityHandler(parser.m_handlerArg ,name ,1 );
+
+ handleDefault:=XML_FALSE;
+
+ end;
+
+ goto _break;
+
+ end;
+
+ if entity.open <> 0 then
+ begin
+ result:=XML_ERROR_RECURSIVE_ENTITY_REF;
+
+ exit;
+
+ end;
+
+ if entity.textPtr <> NIL then
+ begin
+ if role = XML_ROLE_PARAM_ENTITY_REF then
+ betweenDecl:=XML_TRUE
+ else
+ betweenDecl:=XML_FALSE;
+
+ result_:=processInternalEntity(parser ,entity ,betweenDecl );
+
+ if result_ <> XML_ERROR_NONE then
+ begin
+ result:=result_;
+
+ exit;
+
+ end;
+
+ handleDefault:=XML_FALSE;
+
+ goto _break;
+
+ end;
+
+ if @parser.m_externalEntityRefHandler <> NIL then
+ begin
+ dtd.paramEntityRead:=XML_FALSE;
+ entity.open :=XML_TRUE;
+
+ if parser.m_externalEntityRefHandler(
+ parser.m_externalEntityRefHandlerArg ,
+ 0 ,
+ entity.base ,
+ entity.systemId ,
+ entity.publicId ) = 0 then
+ begin
+ entity.open:=XML_FALSE;
+
+ result:=XML_ERROR_EXTERNAL_ENTITY_HANDLING;
+
+ exit;
+
+ end;
+
+ entity.open :=XML_FALSE;
+ handleDefault:=XML_FALSE;
+
+ if dtd.paramEntityRead = 0 then
+ begin
+ dtd.keepProcessing:=dtd.standalone;
+
+ goto _break;
+
+ end;
+
+ end
+ else
+ begin
+ dtd.keepProcessing:=dtd.standalone;
+
+ goto _break;
+
+ end;
+
+ end;
+
+ {$ENDIF }
+
+ if (dtd.standalone = 0 ) and
+ (@parser.m_notStandaloneHandler <> NIL ) and
+ (parser.m_notStandaloneHandler(parser.m_handlerArg ) = 0 ) then
+ begin
+ result:=XML_ERROR_NOT_STANDALONE;
+
+ exit;
+
+ end;
+
+ end;
+
+ { Element declaration stuff }
+ XML_ROLE_ELEMENT_NAME :
+ if @parser.m_elementDeclHandler <> NIL then
+ begin
+ parser.m_declElementType:=getElementType(parser ,enc ,s ,next );
+
+ if parser.m_declElementType = NIL then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ dtd.scaffLevel:=0;
+ dtd.scaffCount:=0;
+ dtd.in_eldecl :=XML_TRUE;
+ handleDefault :=XML_FALSE;
+
+ end;
+
+ XML_ROLE_CONTENT_ANY ,XML_ROLE_CONTENT_EMPTY :
+ if dtd.in_eldecl <> 0 then
+ begin
+ if @parser.m_elementDeclHandler <> NIL then
+ begin
+ parser.m_mem.malloc_fcn(pointer(content ) ,sizeof(XML_Content ) );
+
+ if content = NIL then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ content.quant :=XML_CQUANT_NONE;
+ content.name :=NIL;
+ content.numchildren:=0;
+ content.children :=NIL;
+
+ if role = XML_ROLE_CONTENT_ANY then
+ content.type_:=XML_CTYPE_ANY
+ else
+ content.type_:=XML_CTYPE_EMPTY;
+
+ eventEndPP^:=s;
+
+ parser.m_elementDeclHandler(
+ parser.m_handlerArg ,parser.m_declElementType.name ,content );
+
+ handleDefault:=XML_FALSE;
+
+ end;
+
+ dtd.in_eldecl:=XML_FALSE;
+
+ end;
+
+ XML_ROLE_CONTENT_PCDATA :
+ if dtd.in_eldecl <> 0 then
+ begin
+ CONTENT_SCAFFOLD_ptr(
+ ptrcomp(dtd.scaffold ) +
+ int_ptr(ptrcomp(dtd.scaffIndex ) + (dtd.scaffLevel - 1 ) * sizeof(int ) )^ *
+ sizeof(CONTENT_SCAFFOLD ) )^.type_:=XML_CTYPE_MIXED;
+
+ if @parser.m_elementDeclHandler <> NIL then
+ handleDefault:=XML_FALSE;
+
+ end;
+
+ XML_ROLE_CONTENT_ELEMENT :
+ begin
+ quant:=XML_CQUANT_NONE;
+
+ goto elementContent;
+
+ end;
+
+ XML_ROLE_CONTENT_ELEMENT_OPT :
+ begin
+ quant:=XML_CQUANT_OPT;
+
+ goto elementContent;
+
+ end;
+
+ XML_ROLE_CONTENT_ELEMENT_REP :
+ begin
+ quant:=XML_CQUANT_REP;
+
+ goto elementContent;
+
+ end;
+
+ XML_ROLE_CONTENT_ELEMENT_PLUS :
+ begin
+ quant:=XML_CQUANT_PLUS;
+
+ elementContent:
+ if dtd.in_eldecl <> 0 then
+ begin
+ if quant = XML_CQUANT_NONE then
+ nxt:=next
+ else
+ nxt:=char_ptr(ptrcomp(next ) - enc.minBytesPerChar );
+
+ myindex:=nextScaffoldPart(parser );
+
+ if myindex < 0 then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ CONTENT_SCAFFOLD_ptr(
+ ptrcomp(dtd.scaffold ) +
+ myindex * sizeof(CONTENT_SCAFFOLD ) )^.type_:=XML_CTYPE_NAME;
+
+ CONTENT_SCAFFOLD_ptr(
+ ptrcomp(dtd.scaffold ) +
+ myindex * sizeof(CONTENT_SCAFFOLD ) )^.quant:=quant;
+
+ el:=getElementType(parser ,enc ,s ,nxt );
+
+ if el = NIL then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ name:=el.name;
+
+ CONTENT_SCAFFOLD_ptr(
+ ptrcomp(dtd.scaffold ) +
+ myindex * sizeof(CONTENT_SCAFFOLD ) )^.name:=name;
+
+ nameLen:=0;
+
+ while XML_Char_ptr(ptrcomp(name ) + nameLen )^ <> XML_Char(0 ) do
+ inc(nameLen );
+
+ inc(dtd.contentStringLen ,nameLen );
+
+ if @parser.m_elementDeclHandler <> NIL then
+ handleDefault:=XML_FALSE;
+
+ end;
+
+ end;
+
+ XML_ROLE_GROUP_CLOSE :
+ begin
+ quant:=XML_CQUANT_NONE;
+
+ goto closeGroup;
+
+ end;
+
+ XML_ROLE_GROUP_CLOSE_OPT :
+ begin
+ quant:=XML_CQUANT_OPT;
+
+ goto closeGroup;
+
+ end;
+
+ XML_ROLE_GROUP_CLOSE_REP :
+ begin
+ quant:=XML_CQUANT_REP;
+
+ goto closeGroup;
+
+ end;
+
+ XML_ROLE_GROUP_CLOSE_PLUS :
+ begin
+ quant:=XML_CQUANT_PLUS;
+
+ closeGroup:
+ if dtd.in_eldecl <> 0 then
+ begin
+ if @parser.m_elementDeclHandler <> NIL then
+ handleDefault:=XML_FALSE;
+
+ dec(dtd.scaffLevel );
+
+ CONTENT_SCAFFOLD_ptr(
+ ptrcomp(dtd.scaffold ) +
+ int_ptr(ptrcomp(dtd.scaffIndex ) + dtd.scaffLevel * sizeof(int ) )^ *
+ sizeof(CONTENT_SCAFFOLD) )^.quant:=quant;
+
+ if dtd.scaffLevel = 0 then
+ begin
+ if handleDefault = 0 then
+ begin
+ model:=build_model(parser );
+
+ if model = NIL then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ eventEndPP^:=s;
+
+ parser.m_elementDeclHandler(
+ parser.m_handlerArg ,
+ parser.m_declElementType.name ,model );
+
+ end;
+
+ dtd.in_eldecl :=XML_FALSE;
+ dtd.contentStringLen:=0;
+
+ end;
+
+ end;
+
+ end; { End element declaration stuff }
+
+ XML_ROLE_PI :
+ begin
+ if reportProcessingInstruction(parser ,enc ,s ,next ) = 0 then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ handleDefault:=XML_FALSE;
+
+ end;
+
+ XML_ROLE_COMMENT :
+ begin
+ if reportComment(parser ,enc ,s ,next ) = 0 then
+ begin
+ result:=XML_ERROR_NO_MEMORY;
+
+ exit;
+
+ end;
+
+ handleDefault:=XML_FALSE;
+
+ end;
+
+ XML_ROLE_NONE :
+ case tok of
+ XML_TOK_BOM :
+ handleDefault:=XML_FALSE;
+
+ end;
+
+ XML_ROLE_DOCTYPE_NONE :
+ if @parser.m_startDoctypeDeclHandler <> NIL then
+ handleDefault:=XML_FALSE;
+
+ XML_ROLE_ENTITY_NONE :
+ if (dtd.keepProcessing <> 0 ) and
+ (@parser.m_entityDeclHandler <> NIL ) then
+ handleDefault:=XML_FALSE;
+
+ XML_ROLE_NOTATION_NONE :
+ if @parser.m_notationDeclHandler <> NIL then
+ handleDefault:=XML_FALSE;
+
+ XML_ROLE_ATTLIST_NONE :
+ if (dtd.keepProcessing <> 0 ) and
+ (@parser.m_attlistDeclHandler <> NIL ) then
+ handleDefault:=XML_FALSE;
+
+ XML_ROLE_ELEMENT_NONE :
+ if @parser.m_elementDeclHandler <> NIL then
+ handleDefault:=XML_FALSE;
+
+ end; { end of big case }
+
+ _break:
+ if (handleDefault = XML_TRUE ) and
+ (@parser.m_defaultHandler <> NIL ) then
+ reportDefault(parser ,enc ,s ,next );
+
+ case parser.m_parsingStatus.parsing of
+ XML_SUSPENDED :
+ begin
+ nextPtr^:=next;
+ result :=XML_ERROR_NONE;
+
+ exit;
+
+ end;
+
+ XML_FINISHED :
+ begin
+ result:=XML_ERROR_ABORTED;
+
+ exit;
+
+ end;
+
+ else
+ begin
+ s :=next;
+ tok:=XmlPrologTok(enc ,pointer(s ) ,pointer(end_ ) ,@next );
+
+ end;
+
+ end;
+
+ until false;
+
+{ not reached }
+
+end;
+
+{ prologProcessor }
+function prologProcessor(parser : XML_Parser; s ,end_ : char_ptr; nextPtr : char_ptr_ptr ) : XML_Error;
+var
+ next : char_ptr;
+ tok : int;
+
+begin
+ next:=s;
+ tok :=XmlPrologTok(parser.m_encoding ,pointer(s ) ,pointer(end_ ) ,@next );
+
+ result:=
+ doProlog(
+ parser ,parser.m_encoding ,s ,end_ ,tok ,next ,
+ nextPtr ,XML_Bool(not parser.m_parsingStatus.finalBuffer ) );
+
+end;
+
+{ prologInitProcessor }
+function prologInitProcessor(parser : XML_Parser; s ,end_ : char_ptr; nextPtr : char_ptr_ptr ) : XML_Error;
+var
+ result_ : XML_Error;
+
+begin
+ result_:=initializeEncoding(parser );
+
+ if result_ <> XML_ERROR_NONE then
+ begin
+ result:=result_;
+
+ exit;
+
+ end;
+
+ parser.m_processor:=@prologProcessor;
+
+ result:=prologProcessor(parser ,s ,end_ ,nextPtr );
+
+end;
+
+{ parserInit }
+procedure parserInit(parser : XML_Parser; encodingName : XML_Char_ptr );
+begin
+ parser.m_processor:=@prologInitProcessor;
+
+ XmlPrologStateInit(@parser.m_prologState );
+
+ if encodingName <> NIL then
+ parser.m_protocolEncodingName:=poolCopyString(@parser.m_tempPool ,encodingName )
+ else
+ parser.m_protocolEncodingName:=NIL;
+
+ parser.m_curBase:=NIL;
+
+ XmlInitEncoding(@parser.m_initEncoding ,@parser.m_encoding ,0 );
+
+ parser.m_userData :=NIL;
+ parser.m_handlerArg:=NIL;
+
+ parser.m_startElementHandler :=NIL;
+ parser.m_endElementHandler :=NIL;
+ parser.m_characterDataHandler :=NIL;
+ parser.m_processingInstructionHandler:=NIL;
+ parser.m_commentHandler :=NIL;
+ parser.m_startCdataSectionHandler :=NIL;
+ parser.m_endCdataSectionHandler :=NIL;
+ parser.m_defaultHandler :=NIL;
+ parser.m_startDoctypeDeclHandler :=NIL;
+ parser.m_endDoctypeDeclHandler :=NIL;
+ parser.m_unparsedEntityDeclHandler :=NIL;
+ parser.m_notationDeclHandler :=NIL;
+ parser.m_startNamespaceDeclHandler :=NIL;
+ parser.m_endNamespaceDeclHandler :=NIL;
+ parser.m_notStandaloneHandler :=NIL;
+ parser.m_externalEntityRefHandler :=NIL;
+ parser.m_externalEntityRefHandlerArg :=parser;
+ parser.m_skippedEntityHandler :=NIL;
+ parser.m_elementDeclHandler :=NIL;
+ parser.m_attlistDeclHandler :=NIL;
+ parser.m_entityDeclHandler :=NIL;
+ parser.m_xmlDeclHandler :=NIL;
+
+ parser.m_bufferPtr:=parser.m_buffer;
+ parser.m_bufferEnd:=parser.m_buffer;
+
+ parser.m_parseEndByteIndex:=0;
+ parser.m_parseEndPtr :=NIL;
+
+ parser.m_declElementType:=NIL;
+ parser.m_declAttributeId:=NIL;
+ parser.m_declEntity :=NIL;
+
+ parser.m_doctypeName :=NIL;
+ parser.m_doctypeSysid:=NIL;
+ parser.m_doctypePubid:=NIL;
+
+ parser.m_declAttributeType :=NIL;
+ parser.m_declNotationName :=NIL;
+ parser.m_declNotationPublicId:=NIL;
+ parser.m_declAttributeIsCdata:=XML_FALSE;
+ parser.m_declAttributeIsId :=XML_FALSE;
+
+ fillchar(parser.m_position ,sizeof(POSITION ) ,0 );
+
+ parser.m_errorCode:=XML_ERROR_NONE;
+
+ parser.m_eventPtr :=NIL;
+ parser.m_eventEndPtr:=NIL;
+ parser.m_positionPtr:=NIL;
+
+ parser.m_openInternalEntities :=NIL;
+ parser.m_defaultExpandInternalEntities:=XML_TRUE;
+
+ parser.m_tagLevel :=0;
+ parser.m_tagStack :=NIL;
+ parser.m_inheritedBindings:=NIL;
+ parser.m_nSpecifiedAtts :=0;
+
+ parser.m_unknownEncodingMem :=NIL;
+ parser.m_unknownEncodingRelease:=NIL;
+ parser.m_unknownEncodingData :=NIL;
+ parser.m_unknownEncodingAlloc :=0;
+
+ parser.m_parentParser :=NIL;
+ parser.m_parsingStatus.parsing:=XML_INITIALIZED;
+
+{$IFDEF XML_DTD }
+ parser.m_isParamEntity:=XML_FALSE;
+ parser.m_useForeignDTD:=XML_FALSE;
+
+ parser.m_paramEntityParsing:=XML_PARAM_ENTITY_PARSING_NEVER;
+
+{$ENDIF }
+
+end;
+
+{ parserCreate }
+function parserCreate(
+ encodingName : XML_Char_ptr;
+ memsuite : XML_Memory_Handling_Suite_ptr;
+ nameSep : XML_Char_ptr;
+ dtd : DTD_ptr ) : XML_Parser;
+var
+ parser : XML_Parser;
+ mtemp : XML_Memory_Handling_Suite_ptr;
+
+begin
+ parser:=NIL;
+
+ if memsuite <> NIL then
+ begin
+ memsuite.malloc_fcn(pointer(parser ) ,sizeof(XML_ParserStruct ) );
+
+ if parser <> NIL then
+ begin
+ mtemp:=@parser.m_mem;
+
+ mtemp.malloc_fcn :=memsuite.malloc_fcn;
+ mtemp.realloc_fcn:=memsuite.realloc_fcn;
+ mtemp.free_fcn :=memsuite.free_fcn;
+
+ end;
+
+ end
+ else
+ begin
+ expat_getmem(pointer(parser ) ,sizeof(XML_ParserStruct ) );
+
+ if parser <> NIL then
+ begin
+ mtemp:=@parser.m_mem;
+
+ mtemp.malloc_fcn :=@expat_getmem;
+ mtemp.realloc_fcn:=@expat_realloc;
+ mtemp.free_fcn :=@expat_freemem;
+
+ end;
+
+ end;
+
+ if parser = NIL then
+ begin
+ result:=NIL;
+
+ exit;
+
+ end;
+
+ parser.m_buffer :=NIL;
+ parser.m_bufferLim:=NIL;
+ parser.m_attsSize :=INIT_ATTS_SIZE;
+
+ parser.m_attsAlloc :=0;
+ parser.m_nsAttsAlloc:=0;
+
+ parser.m_mem.malloc_fcn(pointer(parser.m_atts ) ,parser.m_attsSize * sizeof(ATTRIBUTE ) );
+
+ if parser.m_atts = NIL then
+ begin
+ parser.m_mem.free_fcn(pointer(parser ) ,sizeof(XML_ParserStruct ) );
+
+ result:=NIL;
+
+ exit;
+
+ end
+ else
+ parser.m_attsAlloc:=parser.m_attsSize * sizeof(ATTRIBUTE );
+
+ parser.m_mem.malloc_fcn(pointer(parser.m_dataBuf ) ,INIT_DATA_BUF_SIZE * sizeof(XML_Char ) );
+
+ if parser.m_dataBuf = NIL then
+ begin
+ parser.m_mem.free_fcn(pointer(parser.m_atts ) ,parser.m_attsAlloc );
+ parser.m_mem.free_fcn(pointer(parser ) ,sizeof(XML_ParserStruct ) );
+
+ result:=NIL;
+
+ exit;
+
+ end;
+
+ parser.m_dataBufEnd:=XML_Char_ptr(ptrcomp(parser.m_dataBuf ) + INIT_DATA_BUF_SIZE );
+
+ if dtd <> NIL then
+ parser.m_dtd:=dtd
+ else
+ begin
+ parser.m_dtd:=dtdCreate(@parser.m_mem );
+
+ if parser.m_dtd = NIL then
+ begin
+ parser.m_mem.free_fcn(pointer(parser.m_dataBuf ) ,INIT_DATA_BUF_SIZE * sizeof(XML_Char ) );
+ parser.m_mem.free_fcn(pointer(parser.m_atts ) ,parser.m_attsAlloc );
+ parser.m_mem.free_fcn(pointer(parser ) ,sizeof(XML_ParserStruct ) );
+
+ result:=NIL;
+
+ exit;
+
+ end;
+
+ end;
+
+ parser.m_freeBindingList :=NIL;
+ parser.m_freeTagList :=NIL;
+ parser.m_freeInternalEntities:=NIL;
+
+ parser.m_groupSize :=0;
+ parser.m_groupAlloc :=0;
+ parser.m_groupConnector:=NIL;
+
+ parser.m_unknownEncodingHandler :=NIL;
+ parser.m_unknownEncodingHandlerData:=NIL;
+
+ parser.m_namespaceSeparator:='!';
+
+ parser.m_ns :=XML_FALSE;
+ parser.m_ns_triplets:=XML_FALSE;
+
+ parser.m_nsAtts :=NIL;
+ parser.m_nsAttsVersion:=0;
+ parser.m_nsAttsPower :=0;
+
+ poolInit (@parser.m_tempPool ,@parser.m_mem );
+ poolInit (@parser.m_temp2Pool ,@parser.m_mem );
+ parserInit(parser ,encodingName );
+
+ if (encodingName <> NIL ) and
+ (parser.m_protocolEncodingName = NIL ) then
+ begin
+ XML_ParserFree(parser );
+
+ result:=NIL;
+
+ exit;
+
+ end;
+
+ if nameSep <> NIL then
+ begin
+ parser.m_ns:=XML_TRUE;
+
+ parser.m_internalEncoding :=XmlGetInternalEncodingNS;
+ parser.m_namespaceSeparator:=nameSep^;
+
+ end
+ else
+ parser.m_internalEncoding:=XmlGetInternalEncoding;
+
+ result:=parser;
+
+end;
+
+{ setContext {..}
+function setContext(parser : XML_Parser; context : XML_Char_ptr ) : XML_Bool;
+begin
+end;
+
+{ XML_PARSERCREATE }
+function XML_ParserCreate;
+begin
+ result:=XML_ParserCreate_MM(encoding ,NIL ,NIL );
+
+end;
+
+{ XML_PARSER_CREATE_MM }
+function XML_ParserCreate_MM;
+var
+ parser : XML_Parser;
+
+begin
+ parser:=parserCreate(encoding ,memsuite ,namespaceSeparator ,NIL );
+
+ if (parser <> NIL ) and
+ (parser.m_ns <> 0 ) then
+ { implicit context only set for root parser, since child
+ parsers (i.e. external entity parsers) will inherit it }
+ if not setContext(parser ,@implicitContext[0 ] ) <> 0 then
+ begin
+ XML_ParserFree(parser );
+
+ result:=NIL;
+
+ exit;
+
+ end;
+
+ result:=parser;
+
+end;
+
+{ XML_SETUSERDATA }
+procedure XML_SetUserData;
+begin
+ if parser.m_handlerArg = parser.m_userData then
+ begin
+ parser.m_handlerArg:=userData;
+ parser.m_userData :=userData;
+
+ end
+ else
+ parser.m_userData:=userData;
+
+end;
+
+{ XML_SETELEMENTHANDLER }
+procedure XML_SetElementHandler;
+begin
+ parser.m_startElementHandler:=start;
+ parser.m_endElementHandler :=end_;
+
+end;
+
+{ XML_SETCHARACTERDATAHANDLER }
+procedure XML_SetCharacterDataHandler;
+begin
+ parser.m_characterDataHandler:=handler;
+
+end;
+
+{ XML_GetBuffer }
+function XML_GetBuffer(parser : XML_Parser; len : int ) : pointer;
+var
+ neededSize ,keep ,offset ,bufferSize : int;
+
+ newBuf : char_ptr;
+
+begin
+ case parser.m_parsingStatus.parsing of
+ XML_SUSPENDED :
+ begin
+ parser.m_errorCode:=XML_ERROR_SUSPENDED;
+
+ result:=NIL;
+
+ exit;
+
+ end;
+
+ XML_FINISHED :
+ begin
+ parser.m_errorCode:=XML_ERROR_FINISHED;
+
+ result:=NIL;
+
+ exit;
+
+ end;
+
+ end;
+
+ if len > ptrcomp(parser.m_bufferLim ) - ptrcomp(parser.m_bufferEnd ) then
+ begin
+ { FIXME avoid integer overflow }
+ neededSize:=len + (ptrcomp(parser.m_bufferEnd ) - ptrcomp(parser.m_bufferPtr ) );
+
+ {$IFDEF XML_CONTEXT_BYTES }
+ keep:=ptrcomp(parser.m_bufferPtr ) - ptrcomp(parser.m_buffer );
+
+ if keep > _XML_CONTEXT_BYTES then
+ keep:=_XML_CONTEXT_BYTES;
+
+ inc(neededSize ,keep );
+
+ {$ENDIF }
+
+ if neededSize <= ptrcomp(parser.m_bufferLim ) - ptrcomp(parser.m_buffer ) then
+ begin
+ {$IFDEF XML_CONTEXT_BYTES }
+ if keep < ptrcomp(parser.m_bufferPtr ) - ptrcomp(parser.m_buffer ) then
+ begin
+ offset:=ptrcomp(parser.m_bufferPtr ) - ptrcomp(parser.m_buffer ) - keep;
+
+ move(
+ char_ptr(ptrcomp(parser.m_buffer ) + offset )^ ,
+ parser.m_buffer^ ,
+ ptrcomp(parser.m_bufferEnd ) - ptrcomp(parser.m_bufferPtr ) + keep );
+
+ dec(ptrcomp(parser.m_bufferEnd ) ,offset );
+ dec(ptrcomp(parser.m_bufferPtr ) ,offset );
+
+ end;
+
+ {$ELSE }
+ move(
+ parser.m_bufferPtr^ ,
+ parser.m_buffer^ ,
+ ptrcomp(parser.m_bufferEnd ) - ptrcomp(parser.m_bufferPtr ) );
+
+ parser.m_bufferEnd:=char_ptr(ptrcomp(parser.m_buffer ) + (ptrcomp(parser.m_bufferEnd ) - ptrcomp(parser.m_bufferPtr ) ) );
+ parser.m_bufferPtr:=parser.m_buffer;
+
+ {$ENDIF }
+
+ end
+ else
+ begin
+ bufferSize:=ptrcomp(parser.m_bufferLim ) - ptrcomp(parser.m_bufferPtr );
+
+ if bufferSize = 0 then
+ bufferSize:=INIT_BUFFER_SIZE;
+
+ repeat
+ bufferSize:=bufferSize * 2;
+
+ until bufferSize >= neededSize;
+
+ parser.m_mem.malloc_fcn(pointer(newBuf ) ,bufferSize );
+
+ if newBuf = NIL then
+ begin
+ parser.m_errorCode:=XML_ERROR_NO_MEMORY;
+
+ result:=NIL;
+
+ exit;
+
+ end;
+
+ parser.m_bufferLim :=char_ptr(ptrcomp(newBuf ) + bufferSize );
+
+ {$IFDEF XML_CONTEXT_BYTES }
+ if parser.m_bufferPtr <> NIL then
+ begin
+ keep:=ptrcomp(parser.m_bufferPtr ) - ptrcomp(parser.m_buffer );
+
+ if keep > _XML_CONTEXT_BYTES then
+ keep:=_XML_CONTEXT_BYTES;
+
+ move(
+ char_ptr(ptrcomp(parser.m_bufferPtr ) - keep )^ ,
+ newBuf^ ,
+ ptrcomp(parser.m_bufferEnd ) - ptrcomp(parser.m_bufferPtr ) + keep );
+
+ expat_freemem(pointer(parser.m_buffer ) ,parser.m_bufferAloc );
+
+ parser.m_buffer :=newBuf;
+ parser.m_bufferAloc:=bufferSize;
+
+ parser.m_bufferEnd:=
+ char_ptr(
+ ptrcomp(parser.m_buffer ) +
+ (ptrcomp(parser.m_bufferEnd ) - ptrcomp(parser.m_bufferPtr ) ) +
+ keep );
+
+ parser.m_bufferPtr:=char_ptr(ptrcomp(parser.m_buffer ) + keep );
+
+ end
+ else
+ begin
+ parser.m_bufferEnd :=char_ptr(ptrcomp(newBuf ) + (ptrcomp(parser.m_bufferEnd ) - ptrcomp(parser.m_bufferPtr ) ) );
+ parser.m_buffer :=newBuf;
+ parser.m_bufferPtr :=newBuf;
+ parser.m_bufferAloc:=bufferSize;
+
+ end;
+
+ {$ELSE }
+ if parser.m_bufferPtr <> NIL then
+ begin
+ move(
+ parser.m_bufferPtr^ ,
+ newBuf^ ,
+ ptrcomp(parser.m_bufferEnd ) - ptrcomp(parser.m_bufferPtr ) );
+
+ expat_freemem(pointer(parser.m_buffer ) ,parser.m_bufferAloc );
+
+ end;
+
+ parser.m_bufferEnd :=char_ptr(ptrcomp(newBuf ) + (ptrcomp(parser.m_bufferEnd ) - ptrcomp(parser.m_bufferPtr ) ) );
+ parser.m_buffer :=newBuf;
+ parser.m_bufferPtr :=newBuf;
+ parser.m_bufferAloc:=bufferSize;
+
+ {$ENDIF }
+
+ end;
+
+ end;
+
+ result:=parser.m_bufferEnd;
+
+end;
+
+{ errorProcessor }
+function errorProcessor(parser : XML_Parser; s ,end_ : char_ptr; nextPtr : char_ptr_ptr ) : XML_Error;
+begin
+ result:=parser.m_errorCode;
+
+end;
+
+{ XML_ParseBuffer }
+function XML_ParseBuffer(parser : XML_Parser; len ,isFinal : int ) : XML_Status;
+var
+ start : char_ptr;
+ result_ : XML_Status;
+
+begin
+ result_:=XML_STATUS_OK;
+
+ case parser.m_parsingStatus.parsing of
+ XML_SUSPENDED :
+ begin
+ parser.m_errorCode:=XML_ERROR_SUSPENDED;
+
+ result:=XML_STATUS_ERROR;
+
+ exit;
+
+ end;
+
+ XML_FINISHED :
+ begin
+ parser.m_errorCode:=XML_ERROR_FINISHED;
+
+ result:=XML_STATUS_ERROR;
+
+ exit;
+
+ end;
+
+ else
+ parser.m_parsingStatus.parsing:=XML_PARSING_;
+
+ end;
+
+ start :=parser.m_bufferPtr;
+ parser.m_positionPtr:=start;
+
+ inc(ptrcomp(parser.m_bufferEnd ) ,len );
+
+ parser.m_parseEndPtr:=parser.m_bufferEnd;
+
+ inc(ptrcomp(parser.m_parseEndByteIndex ) ,len );
+
+ parser.m_parsingStatus.finalBuffer:=XML_Bool(isFinal );
+
+ parser.m_errorCode:=parser.m_processor(parser ,start ,parser.m_parseEndPtr ,@parser.m_bufferPtr );
+
+ if parser.m_errorCode <> XML_ERROR_NONE then
+ begin
+ parser.m_eventEndPtr:=parser.m_eventPtr;
+ parser.m_processor :=@errorProcessor;
+
+ result:=XML_STATUS_ERROR;
+
+ exit;
+
+ end
+ else
+ case parser.m_parsingStatus.parsing of
+ XML_SUSPENDED :
+ result_:=XML_STATUS_SUSPENDED;
+
+ XML_INITIALIZED ,XML_PARSING_ :
+ if isFinal <> 0 then
+ begin
+ parser.m_parsingStatus.parsing:=XML_FINISHED;
+
+ result:=result_;
+
+ exit;
+
+ end;
+
+ else
+ { should not happen }
+ NoP;
+
+ end;
+
+ parser.m_encoding.updatePosition(
+ parser.m_encoding ,
+ pointer(parser.m_positionPtr ) ,
+ pointer(parser.m_bufferPtr ) ,@parser.m_position );
+
+ parser.m_positionPtr:=parser.m_bufferPtr;
+
+ result:=result_;
+
+end;
+
+{ XML_PARSE {..}
+function XML_Parse;
+var
+ buff : pointer;
+
+begin
+ case parser.m_parsingStatus.parsing of
+ XML_SUSPENDED :
+ begin
+ parser.m_errorCode:=XML_ERROR_SUSPENDED;
+
+ result:=XML_STATUS_ERROR;
+
+ exit;
+
+ end;
+
+ XML_FINISHED :
+ begin
+ parser.m_errorCode:=XML_ERROR_FINISHED;
+
+ result:=XML_STATUS_ERROR;
+
+ exit;
+
+ end;
+
+ else
+ parser.m_parsingStatus.parsing:=XML_PARSING_;
+
+ end;
+
+ if len = 0 then
+ begin
+ NoP;
+
+ end
+{$IFNDEF XML_CONTEXT_BYTES }
+ else
+ if parser.m_bufferPtr = parser.m_bufferEnd then
+ begin
+ NoP;
+
+ end
+
+{$ENDIF }
+ else
+ begin
+ buff:=XML_GetBuffer(parser ,len );
+
+ if buff = NIL then
+ result:=XML_STATUS_ERROR
+
+ else
+ begin
+ move(s^ ,buff^ ,len );
+
+ result:=XML_ParseBuffer(parser ,len ,isFinal );
+
+ end;
+
+ end;
+
+end;
+
+{ XML_GETERRORCODE {..}
+function XML_GetErrorCode;
+begin
+end;
+
+{ XML_ERRORSTRING {..}
+function XML_ErrorString;
+begin
+end;
+
+{ XML_GETCURRENTLINENUMBER {..}
+function XML_GetCurrentLineNumber;
+begin
+end;
+
+{ destroyBindings }
+procedure destroyBindings(bindings : BINDING_ptr; parser : XML_Parser );
+var
+ b : BINDING_ptr;
+
+begin
+ repeat
+ b:=bindings;
+
+ if b = NIL then
+ break;
+
+ bindings:=b.nextTagBinding;
+
+ parser.m_mem.free_fcn(pointer(b.uri ) ,b.uriAlloc );
+ parser.m_mem.free_fcn(pointer(b ) ,sizeof(expat.BINDING ) );
+
+ until false;
+
+end;
+
+{ XML_PARSERFREE }
+procedure XML_ParserFree;
+var
+ tagList ,p : TAG_ptr;
+
+ entityList ,openEntity : OPEN_INTERNAL_ENTITY_ptr;
+
+begin
+ if parser = NIL then
+ exit;
+
+{ free tagStack and freeTagList }
+ tagList:=parser.m_tagStack;
+
+ repeat
+ if tagList = NIL then
+ begin
+ if parser.m_freeTagList = NIL then
+ break;
+
+ tagList:=parser.m_freeTagList;
+
+ parser.m_freeTagList:=NIL;
+
+ end;
+
+ p :=tagList;
+ tagList:=tagList.parent;
+
+ parser.m_mem.free_fcn(pointer(p.buf ) ,p.alloc );
+ destroyBindings (p.bindings ,parser );
+ parser.m_mem.free_fcn(pointer(p ) ,sizeof(expat.TAG ) );
+
+ until false;
+
+{ free openInternalEntities and freeInternalEntities }
+ entityList:=parser.m_openInternalEntities;
+
+ repeat
+ if entityList = NIL then
+ begin
+ if parser.m_freeInternalEntities = NIL then
+ break;
+
+ entityList:=parser.m_freeInternalEntities;
+
+ parser.m_freeInternalEntities:=NIL;
+
+ end;
+
+ openEntity:=entityList;
+ entityList:=entityList.next;
+
+ parser.m_mem.free_fcn(pointer(openEntity ) ,sizeof(OPEN_INTERNAL_ENTITY ) );
+
+ until false;
+
+ destroyBindings(parser.m_freeBindingList ,parser );
+ destroyBindings(parser.m_inheritedBindings ,parser );
+
+ poolDestroy(@parser.m_tempPool );
+ poolDestroy(@parser.m_temp2Pool );
+
+{$IFDEF XML_DTD }
+{ external parameter entity parsers share the DTD structure
+ parser->m_dtd with the root parser, so we must not destroy it }
+ if (parser.m_isParamEntity = 0 ) and
+ (parser.m_dtd <> NIL ) then
+{$ELSE }
+ if parser.m_dtd <> NIL then{$ENDIF }
+ dtdDestroy(parser.m_dtd ,XML_Bool(parser.m_parentParser = NIL ),@parser.m_mem );
+
+ parser.m_mem.free_fcn(pointer(parser.m_atts ) ,parser.m_attsAlloc );
+ parser.m_mem.free_fcn(pointer(parser.m_groupConnector ) ,parser.m_groupAlloc );
+ parser.m_mem.free_fcn(pointer(parser.m_buffer ) ,parser.m_bufferAloc );
+ parser.m_mem.free_fcn(pointer(parser.m_dataBuf ) ,INIT_DATA_BUF_SIZE * sizeof(XML_Char ) );
+ parser.m_mem.free_fcn(pointer(parser.m_nsAtts ) ,parser.m_nsAttsAlloc );
+ parser.m_mem.free_fcn(pointer(parser.m_unknownEncodingMem ) ,parser.m_unknownEncodingAlloc );
+
+ if @parser.m_unknownEncodingRelease <> NIL then
+ parser.m_unknownEncodingRelease(parser.m_unknownEncodingData );
+
+ parser.m_mem.free_fcn(pointer(parser ) ,sizeof(XML_ParserStruct ) );
+
+end;
+
diff --git a/src/corelib/render/software/agg-demos/expat-pas/xmlrole.pas b/src/corelib/render/software/agg-demos/expat-pas/xmlrole.pas
new file mode 100755
index 00000000..0acdb28a
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/expat-pas/xmlrole.pas
@@ -0,0 +1,659 @@
+//----------------------------------------------------------------------------
+// Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
+// and Clark Cooper
+// Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006 Expat maintainers.
+//
+// Expat - Version 2.0.0 Release Milano 0.83 (PasExpat 2.0.0 RM0.83)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.pasports.org/pasexpat
+// Copyright (c) 2006
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 10.05.2006-Milano: Unit port establishment
+// 08.06.2006-Milano: porting
+//
+{ xmlrole.pas }
+unit
+ xmlrole ;
+
+INTERFACE
+
+uses
+ expat_basics ,
+ expat_external ,
+ xmltok ;
+
+{$I expat_mode.inc }
+
+{ TYPES DEFINITION }
+const
+ XML_ROLE_ERROR = -1;
+ XML_ROLE_NONE = 0;
+ XML_ROLE_XML_DECL = XML_ROLE_NONE + 1;
+ XML_ROLE_INSTANCE_START = XML_ROLE_XML_DECL + 1;
+ XML_ROLE_DOCTYPE_NONE = XML_ROLE_INSTANCE_START + 1;
+ XML_ROLE_DOCTYPE_NAME = XML_ROLE_DOCTYPE_NONE + 1;
+ XML_ROLE_DOCTYPE_SYSTEM_ID = XML_ROLE_DOCTYPE_NAME + 1;
+ XML_ROLE_DOCTYPE_PUBLIC_ID = XML_ROLE_DOCTYPE_SYSTEM_ID + 1;
+ XML_ROLE_DOCTYPE_INTERNAL_SUBSET = XML_ROLE_DOCTYPE_PUBLIC_ID + 1;
+ XML_ROLE_DOCTYPE_CLOSE = XML_ROLE_DOCTYPE_INTERNAL_SUBSET + 1;
+ XML_ROLE_GENERAL_ENTITY_NAME = XML_ROLE_DOCTYPE_CLOSE + 1;
+ XML_ROLE_PARAM_ENTITY_NAME = XML_ROLE_GENERAL_ENTITY_NAME + 1;
+ XML_ROLE_ENTITY_NONE = XML_ROLE_PARAM_ENTITY_NAME + 1;
+ XML_ROLE_ENTITY_VALUE = XML_ROLE_ENTITY_NONE + 1;
+ XML_ROLE_ENTITY_SYSTEM_ID = XML_ROLE_ENTITY_VALUE + 1;
+ XML_ROLE_ENTITY_PUBLIC_ID = XML_ROLE_ENTITY_SYSTEM_ID + 1;
+ XML_ROLE_ENTITY_COMPLETE = XML_ROLE_ENTITY_PUBLIC_ID + 1;
+ XML_ROLE_ENTITY_NOTATION_NAME = XML_ROLE_ENTITY_COMPLETE + 1;
+ XML_ROLE_NOTATION_NONE = XML_ROLE_ENTITY_NOTATION_NAME + 1;
+ XML_ROLE_NOTATION_NAME = XML_ROLE_NOTATION_NONE + 1;
+ XML_ROLE_NOTATION_SYSTEM_ID = XML_ROLE_NOTATION_NAME + 1;
+ XML_ROLE_NOTATION_NO_SYSTEM_ID = XML_ROLE_NOTATION_SYSTEM_ID + 1;
+ XML_ROLE_NOTATION_PUBLIC_ID = XML_ROLE_NOTATION_NO_SYSTEM_ID + 1;
+ XML_ROLE_ATTRIBUTE_NAME = XML_ROLE_NOTATION_PUBLIC_ID + 1;
+ XML_ROLE_ATTRIBUTE_TYPE_CDATA = XML_ROLE_ATTRIBUTE_NAME + 1;
+ XML_ROLE_ATTRIBUTE_TYPE_ID = XML_ROLE_ATTRIBUTE_TYPE_CDATA + 1;
+ XML_ROLE_ATTRIBUTE_TYPE_IDREF = XML_ROLE_ATTRIBUTE_TYPE_ID + 1;
+ XML_ROLE_ATTRIBUTE_TYPE_IDREFS = XML_ROLE_ATTRIBUTE_TYPE_IDREF + 1;
+ XML_ROLE_ATTRIBUTE_TYPE_ENTITY = XML_ROLE_ATTRIBUTE_TYPE_IDREFS + 1;
+ XML_ROLE_ATTRIBUTE_TYPE_ENTITIES = XML_ROLE_ATTRIBUTE_TYPE_ENTITY + 1;
+ XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN = XML_ROLE_ATTRIBUTE_TYPE_ENTITIES + 1;
+ XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS = XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN + 1;
+ XML_ROLE_ATTRIBUTE_ENUM_VALUE = XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS + 1;
+ XML_ROLE_ATTRIBUTE_NOTATION_VALUE = XML_ROLE_ATTRIBUTE_ENUM_VALUE + 1;
+ XML_ROLE_ATTLIST_NONE = XML_ROLE_ATTRIBUTE_NOTATION_VALUE + 1;
+ XML_ROLE_ATTLIST_ELEMENT_NAME = XML_ROLE_ATTLIST_NONE + 1;
+ XML_ROLE_IMPLIED_ATTRIBUTE_VALUE = XML_ROLE_ATTLIST_ELEMENT_NAME + 1;
+ XML_ROLE_REQUIRED_ATTRIBUTE_VALUE = XML_ROLE_IMPLIED_ATTRIBUTE_VALUE + 1;
+ XML_ROLE_DEFAULT_ATTRIBUTE_VALUE = XML_ROLE_REQUIRED_ATTRIBUTE_VALUE + 1;
+ XML_ROLE_FIXED_ATTRIBUTE_VALUE = XML_ROLE_DEFAULT_ATTRIBUTE_VALUE + 1;
+ XML_ROLE_ELEMENT_NONE = XML_ROLE_FIXED_ATTRIBUTE_VALUE + 1;
+ XML_ROLE_ELEMENT_NAME = XML_ROLE_ELEMENT_NONE + 1;
+ XML_ROLE_CONTENT_ANY = XML_ROLE_ELEMENT_NAME + 1;
+ XML_ROLE_CONTENT_EMPTY = XML_ROLE_CONTENT_ANY + 1;
+ XML_ROLE_CONTENT_PCDATA = XML_ROLE_CONTENT_EMPTY + 1;
+ XML_ROLE_GROUP_OPEN = XML_ROLE_CONTENT_PCDATA + 1;
+ XML_ROLE_GROUP_CLOSE = XML_ROLE_GROUP_OPEN + 1;
+ XML_ROLE_GROUP_CLOSE_REP = XML_ROLE_GROUP_CLOSE + 1;
+ XML_ROLE_GROUP_CLOSE_OPT = XML_ROLE_GROUP_CLOSE_REP + 1;
+ XML_ROLE_GROUP_CLOSE_PLUS = XML_ROLE_GROUP_CLOSE_OPT + 1;
+ XML_ROLE_GROUP_CHOICE = XML_ROLE_GROUP_CLOSE_PLUS + 1;
+ XML_ROLE_GROUP_SEQUENCE = XML_ROLE_GROUP_CHOICE + 1;
+ XML_ROLE_CONTENT_ELEMENT = XML_ROLE_GROUP_SEQUENCE + 1;
+ XML_ROLE_CONTENT_ELEMENT_REP = XML_ROLE_CONTENT_ELEMENT + 1;
+ XML_ROLE_CONTENT_ELEMENT_OPT = XML_ROLE_CONTENT_ELEMENT_REP + 1;
+ XML_ROLE_CONTENT_ELEMENT_PLUS = XML_ROLE_CONTENT_ELEMENT_OPT + 1;
+ XML_ROLE_PI = XML_ROLE_CONTENT_ELEMENT_PLUS + 1;
+ XML_ROLE_COMMENT = XML_ROLE_PI + 1;
+
+{$IFDEF XML_DTD }
+ XML_ROLE_TEXT_DECL = XML_ROLE_COMMENT + 1;
+ XML_ROLE_IGNORE_SECT = XML_ROLE_TEXT_DECL + 1;
+ XML_ROLE_INNER_PARAM_ENTITY_REF = XML_ROLE_IGNORE_SECT + 1;
+ XML_ROLE_PARAM_ENTITY_REF = XML_ROLE_INNER_PARAM_ENTITY_REF + 1;
+
+{$ELSE }
+ XML_ROLE_PARAM_ENTITY_REF = XML_ROLE_COMMENT + 1;
+
+{$ENDIF }
+
+type
+ PROLOG_STATE_ptr = ^PROLOG_STATE;
+ PROLOG_STATE = record
+ handler : function(state : PROLOG_STATE_ptr; tok : int; ptr ,end_ : char_ptr; enc : ENCODING_ptr ) : int;
+
+ level : unsigned;
+ role_none : int;
+
+ {$IFDEF XML_DTD }
+ includeLevel : unsigned;
+ documentEntity ,
+ inEntityValue : int;
+
+ {$ENDIF }
+
+ end;
+
+{ GLOBAL PROCEDURES }
+ procedure XmlPrologStateInit(state : PROLOG_STATE_ptr );
+ function XmlTokenRole (state : PROLOG_STATE_ptr; tok : int; ptr ,end_ : char_ptr; enc : ENCODING_ptr ) : int;
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+const
+{$I ascii.inc }
+
+{ Doesn't check:
+
+ that ,| are not mixed in a model group
+ content of literals }
+
+ KW_ANY : array[0..3 ] of char = (
+ ASCII_A ,ASCII_N ,ASCII_Y ,#0 );
+
+ KW_ATTLIST : array[0..7 ] of char = (
+ ASCII_A ,ASCII_T ,ASCII_T ,ASCII_L ,ASCII_I ,ASCII_S ,ASCII_T ,#0 );
+
+ KW_CDATA : array[0..5 ] of char = (
+ ASCII_C ,ASCII_D ,ASCII_A ,ASCII_T ,ASCII_A ,#0 );
+
+ KW_DOCTYPE : array[0..7 ] of char = (
+ ASCII_D ,ASCII_O ,ASCII_C ,ASCII_T ,ASCII_Y ,ASCII_P ,ASCII_E ,#0 );
+
+ KW_ELEMENT : array[0..7 ] of char = (
+ ASCII_E ,ASCII_L ,ASCII_E ,ASCII_M ,ASCII_E ,ASCII_N ,ASCII_T ,#0 );
+
+ KW_EMPTY : array[0..5 ] of char = (
+ ASCII_E ,ASCII_M ,ASCII_P ,ASCII_T ,ASCII_Y ,#0 );
+
+ KW_ENTITIES : array[0..8 ] of char = (
+ ASCII_E ,ASCII_N ,ASCII_T ,ASCII_I ,ASCII_T ,ASCII_I ,ASCII_E ,ASCII_S ,
+ #0 );
+
+ KW_ENTITY : array[0..6 ] of char = (
+ ASCII_E ,ASCII_N ,ASCII_T ,ASCII_I ,ASCII_T ,ASCII_Y ,#0 );
+
+ KW_FIXED : array[0..5 ] of char = (
+ ASCII_F ,ASCII_I ,ASCII_X ,ASCII_E ,ASCII_D ,#0 );
+
+ KW_ID : array[0..2 ] of char = (
+ ASCII_I ,ASCII_D ,#0 );
+
+ KW_IDREF : array[0..5 ] of char = (
+ ASCII_I ,ASCII_D ,ASCII_R ,ASCII_E ,ASCII_F ,#0 );
+
+ KW_IDREFS : array[0..6 ] of char = (
+ ASCII_I ,ASCII_D ,ASCII_R ,ASCII_E ,ASCII_F ,ASCII_S ,#0 );
+
+ KW_IGNORE : array[0..6 ] of char = (
+ ASCII_I ,ASCII_G ,ASCII_N ,ASCII_O ,ASCII_R ,ASCII_E ,#0 );
+
+ KW_IMPLIED : array[0..7 ] of char = (
+ ASCII_I ,ASCII_M ,ASCII_P ,ASCII_L ,ASCII_I ,ASCII_E ,ASCII_D ,#0 );
+
+ KW_INCLUDE : array[0..7 ] of char = (
+ ASCII_I ,ASCII_N ,ASCII_C ,ASCII_L ,ASCII_U ,ASCII_D ,ASCII_E ,#0 );
+
+ KW_NDATA : array[0..5 ] of char = (
+ ASCII_N ,ASCII_D ,ASCII_A ,ASCII_T ,ASCII_A ,#0 );
+
+ KW_NMTOKEN : array[0..7 ] of char = (
+ ASCII_N ,ASCII_M ,ASCII_T ,ASCII_O ,ASCII_K ,ASCII_E ,ASCII_N ,#0 );
+
+ KW_NMTOKENS : array[0..8 ] of char = (
+ ASCII_N ,ASCII_M ,ASCII_T ,ASCII_O ,ASCII_K ,ASCII_E ,ASCII_N ,ASCII_S ,
+ #0 );
+
+ KW_NOTATION : array[0..8 ] of char = (
+ ASCII_N ,ASCII_O ,ASCII_T ,ASCII_A ,ASCII_T ,ASCII_I ,ASCII_O ,ASCII_N ,
+ #0 );
+
+ KW_PCDATA : array[0..6 ] of char = (
+ ASCII_P ,ASCII_C ,ASCII_D ,ASCII_A ,ASCII_T ,ASCII_A ,#0 );
+
+ KW_PUBLIC : array[0..6 ] of char = (
+ ASCII_P ,ASCII_U ,ASCII_B ,ASCII_L ,ASCII_I ,ASCII_C ,#0 );
+
+ KW_REQUIRED : array[0..8 ] of char = (
+ ASCII_R ,ASCII_E ,ASCII_Q ,ASCII_U ,ASCII_I ,ASCII_R ,ASCII_E ,ASCII_D ,
+ #0 );
+
+ KW_SYSTEM : array[0..6 ] of char = (
+ ASCII_S ,ASCII_Y ,ASCII_S ,ASCII_T ,ASCII_E ,ASCII_M ,#0 );
+
+
+{ UNIT IMPLEMENTATION }
+{ MIN_BYTES_PER_CHAR }
+function MIN_BYTES_PER_CHAR(enc : ENCODING_ptr ) : int;
+begin
+ result:=enc.minBytesPerChar;
+
+end;
+
+{ error }
+function error(state : PROLOG_STATE_ptr; tok : int; ptr ,end_ : char_ptr; enc : ENCODING_ptr ) : int;
+begin
+ result:=XML_ROLE_NONE;
+
+end;
+
+{ common {..}
+function common(state : PROLOG_STATE_ptr; tok : int ) : int;
+begin
+end;
+
+{ internalSubset {..}
+function internalSubset(state : PROLOG_STATE_ptr; tok : int; ptr ,end_ : char_ptr; enc : ENCODING_ptr ) : int;
+begin
+end;
+
+{ prolog2 }
+function prolog2(state : PROLOG_STATE_ptr; tok : int; ptr ,end_ : char_ptr; enc : ENCODING_ptr ) : int;
+begin
+ case tok of
+ XML_TOK_PROLOG_S :
+ begin
+ result:=XML_ROLE_NONE;
+
+ exit;
+
+ end;
+
+ XML_TOK_PI :
+ begin
+ result:=XML_ROLE_PI;
+
+ exit;
+
+ end;
+
+ XML_TOK_COMMENT :
+ begin
+ result:=XML_ROLE_COMMENT;
+
+ exit;
+
+ end;
+
+ XML_TOK_INSTANCE_START :
+ begin
+ state.handler:=@error;
+
+ result:=XML_ROLE_INSTANCE_START;
+
+ exit;
+
+ end;
+
+ end;
+
+ result:=common(state ,tok );
+
+end;
+
+{ doctype4 }
+function doctype4(state : PROLOG_STATE_ptr; tok : int; ptr ,end_ : char_ptr; enc : ENCODING_ptr ) : int;
+begin
+ case tok of
+ XML_TOK_PROLOG_S :
+ begin
+ result:=XML_ROLE_DOCTYPE_NONE;
+
+ exit;
+
+ end;
+
+ XML_TOK_OPEN_BRACKET :
+ begin
+ state.handler:=@internalSubset;
+
+ result:=XML_ROLE_DOCTYPE_INTERNAL_SUBSET;
+
+ exit;
+
+ end;
+
+ XML_TOK_DECL_CLOSE :
+ begin
+ state.handler:=@prolog2;
+
+ result:=XML_ROLE_DOCTYPE_CLOSE;
+
+ exit;
+
+ end;
+
+ end;
+
+ result:=common(state ,tok );
+
+end;
+
+{ doctype3 }
+function doctype3(state : PROLOG_STATE_ptr; tok : int; ptr ,end_ : char_ptr; enc : ENCODING_ptr ) : int;
+begin
+ case tok of
+ XML_TOK_PROLOG_S :
+ begin
+ result:=XML_ROLE_DOCTYPE_NONE;
+
+ exit;
+
+ end;
+
+ XML_TOK_LITERAL :
+ begin
+ state.handler:=@doctype4;
+
+ result:=XML_ROLE_DOCTYPE_SYSTEM_ID;
+
+ exit;
+
+ end;
+
+ end;
+
+ result:=common(state ,tok );
+
+end;
+
+{ doctype2 }
+function doctype2(state : PROLOG_STATE_ptr; tok : int; ptr ,end_ : char_ptr; enc : ENCODING_ptr ) : int;
+begin
+ case tok of
+ XML_TOK_PROLOG_S :
+ begin
+ result:=XML_ROLE_DOCTYPE_NONE;
+
+ exit;
+
+ end;
+
+ XML_TOK_LITERAL :
+ begin
+ state.handler:=@doctype3;
+
+ result:=XML_ROLE_DOCTYPE_PUBLIC_ID;
+
+ exit;
+
+ end;
+
+ end;
+
+ result:=common(state ,tok );
+
+end;
+
+{ doctype1 }
+function doctype1(state : PROLOG_STATE_ptr; tok : int; ptr ,end_ : char_ptr; enc : ENCODING_ptr ) : int;
+begin
+ case tok of
+ XML_TOK_PROLOG_S :
+ begin
+ result:=XML_ROLE_DOCTYPE_NONE;
+
+ exit;
+
+ end;
+
+ XML_TOK_OPEN_BRACKET :
+ begin
+ state.handler:=@internalSubset;
+
+ result:=XML_ROLE_DOCTYPE_INTERNAL_SUBSET;
+
+ exit;
+
+ end;
+
+ XML_TOK_DECL_CLOSE :
+ begin
+ state.handler:=@prolog2;
+
+ result:=XML_ROLE_DOCTYPE_CLOSE;
+
+ exit;
+
+ end;
+
+ XML_TOK_NAME :
+ begin
+ if XmlNameMatchesAscii(enc ,ptr ,end_ ,@KW_SYSTEM[0 ] ) <> 0 then
+ begin
+ state.handler:=@doctype3;
+
+ result:=XML_ROLE_DOCTYPE_NONE;
+
+ exit;
+
+ end;
+
+ if XmlNameMatchesAscii(enc ,ptr ,end_ ,@KW_PUBLIC[0 ] ) <> 0 then
+ begin
+ state.handler:=@doctype2;
+
+ result:=XML_ROLE_DOCTYPE_NONE;
+
+ exit;
+
+ end;
+
+ end;
+
+ end;
+
+ result:=common(state ,tok );
+
+end;
+
+{ doctype0 }
+function doctype0(state : PROLOG_STATE_ptr; tok : int; ptr ,end_ : char_ptr; enc : ENCODING_ptr ) : int;
+begin
+ case tok of
+ XML_TOK_PROLOG_S :
+ begin
+ result:=XML_ROLE_DOCTYPE_NONE;
+
+ exit;
+
+ end;
+
+ XML_TOK_NAME ,XML_TOK_PREFIXED_NAME :
+ begin
+ state.handler:=@doctype1;
+
+ result:=XML_ROLE_DOCTYPE_NAME;
+
+ exit;
+
+ end;
+
+ end;
+
+ result:=common(state ,tok );
+
+end;
+
+{ prolog1 }
+function prolog1(state : PROLOG_STATE_ptr; tok : int; ptr ,end_ : char_ptr; enc : ENCODING_ptr ) : int;
+begin
+ case tok of
+ XML_TOK_PROLOG_S :
+ begin
+ result:=XML_ROLE_NONE;
+
+ exit;
+
+ end;
+
+ XML_TOK_PI :
+ begin
+ result:=XML_ROLE_PI;
+
+ exit;
+
+ end;
+
+ XML_TOK_COMMENT :
+ begin
+ result:=XML_ROLE_COMMENT;
+
+ exit;
+
+ end;
+
+ XML_TOK_BOM :
+ begin
+ result:=XML_ROLE_NONE;
+
+ exit;
+
+ end;
+
+ XML_TOK_DECL_OPEN :
+ if XmlNameMatchesAscii(
+ enc ,
+ char_ptr(ptrcomp(ptr ) + 2 * MIN_BYTES_PER_CHAR(enc ) ) ,
+ end_ ,
+ @KW_DOCTYPE[0 ] ) = 0 then
+ else
+ begin
+ state.handler:=@doctype0;
+
+ result:=XML_ROLE_DOCTYPE_NONE;
+
+ exit;
+
+ end;
+
+ XML_TOK_INSTANCE_START :
+ begin
+ state.handler:=@error;
+
+ result:=XML_ROLE_INSTANCE_START;
+
+ exit;
+
+ end;
+
+ end;
+
+ result:=common(state ,tok );
+
+end;
+
+{ prolog0 }
+function prolog0(state : PROLOG_STATE_ptr; tok : int; ptr ,end_ : char_ptr; enc : ENCODING_ptr ) : int;
+label
+ _break ;
+
+begin
+ case tok of
+ XML_TOK_PROLOG_S :
+ begin
+ state.handler:=@prolog1;
+
+ result:=XML_ROLE_NONE;
+
+ exit;
+
+ end;
+
+ XML_TOK_XML_DECL :
+ begin
+ state.handler:=@prolog1;
+
+ result:=XML_ROLE_XML_DECL;
+
+ exit;
+
+ end;
+
+ XML_TOK_PI :
+ begin
+ state.handler:=@prolog1;
+
+ result:=XML_ROLE_PI;
+
+ exit;
+
+ end;
+
+ XML_TOK_COMMENT :
+ begin
+ state.handler:=@prolog1;
+
+ result:=XML_ROLE_COMMENT;
+
+ exit;
+
+ end;
+
+ XML_TOK_BOM :
+ begin
+ result:=XML_ROLE_NONE;
+
+ exit;
+
+ end;
+
+ XML_TOK_DECL_OPEN :
+ begin
+ if XmlNameMatchesAscii(
+ enc ,
+ char_ptr(ptrcomp(ptr ) + 2 * MIN_BYTES_PER_CHAR(enc ) ) ,
+ end_ ,
+ @KW_DOCTYPE[0 ] ) = 0 then
+ goto _break;
+
+ state.handler:=@doctype0;
+
+ result:=XML_ROLE_DOCTYPE_NONE;
+
+ exit;
+
+ end;
+
+ XML_TOK_INSTANCE_START :
+ begin
+ state.handler:=@error;
+
+ result:=XML_ROLE_INSTANCE_START;
+
+ exit;
+
+ end;
+
+ end;
+
+_break:
+ result:=common(state ,tok );
+
+end;
+
+{ XMLPROLOGSTATEINIT }
+procedure XmlPrologStateInit;
+begin
+ state.handler:=@prolog0;
+
+{$IFDEF XML_DTD }
+ state.documentEntity:=1;
+ state.includeLevel :=0;
+ state.inEntityValue :=0;
+
+{$ENDIF }
+
+end;
+
+{ XMLTOKENROLE }
+function XmlTokenRole;
+begin
+ result:=state.handler(state ,tok ,ptr ,end_ ,enc );
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg-demos/expat-pas/xmltok.pas b/src/corelib/render/software/agg-demos/expat-pas/xmltok.pas
new file mode 100755
index 00000000..4f501777
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/expat-pas/xmltok.pas
@@ -0,0 +1,1598 @@
+//----------------------------------------------------------------------------
+// Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
+// and Clark Cooper
+// Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006 Expat maintainers.
+//
+// Expat - Version 2.0.0 Release Milano 0.83 (PasExpat 2.0.0 RM0.83)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.pasports.org/pasexpat
+// Copyright (c) 2006
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 10.05.2006-Milano: Unit port establishment
+// 17.05.2006-Milano: Interface part
+// 06.06.2006-Milano: porting
+// 07.06.2006-Milano: -"-
+// 09.06.2006-Milano: -"-
+// 22.06.2006-Milano: -"-
+//
+{ xmltok.pas }
+unit
+ xmltok ;
+
+INTERFACE
+
+uses
+ expat_basics ,
+ expat_external ;
+
+{$I expat_mode.inc }
+
+{ CONSTANTS DEFINITION }
+const
+{ The following token may be returned by XmlContentTok }
+ XML_TOK_TRAILING_RSQB = -5; { ] or ]] at the end of the scan; might be
+ start of illegal ]]> sequence }
+
+{ The following tokens may be returned by both XmlPrologTok and XmlContentTok. }
+ XML_TOK_NONE = -4; { The string to be scanned is empty }
+ XML_TOK_TRAILING_CR = -3; { A CR at the end of the scan;
+ might be part of CRLF sequence }
+ XML_TOK_PARTIAL_CHAR = -2; { only part of a multibyte sequence }
+ XML_TOK_PARTIAL = -1; { only part of a token }
+ XML_TOK_INVALID = 0;
+
+{ The following tokens are returned by XmlContentTok; some are also
+ returned by XmlAttributeValueTok, XmlEntityTok, XmlCdataSectionTok. }
+ XML_TOK_START_TAG_WITH_ATTS = 1;
+ XML_TOK_START_TAG_NO_ATTS = 2;
+ XML_TOK_EMPTY_ELEMENT_WITH_ATTS = 3; { empty element tag <e/> }
+ XML_TOK_EMPTY_ELEMENT_NO_ATTS = 4;
+ XML_TOK_END_TAG = 5;
+ XML_TOK_DATA_CHARS = 6;
+ XML_TOK_DATA_NEWLINE = 7;
+ XML_TOK_CDATA_SECT_OPEN = 8;
+ XML_TOK_ENTITY_REF = 9;
+ XML_TOK_CHAR_REF = 10; { numeric character reference }
+
+{ The following tokens may be returned by both XmlPrologTok and XmlContentTok. }
+ XML_TOK_PI = 11; { processing instruction }
+ XML_TOK_XML_DECL = 12; { XML decl or text decl }
+ XML_TOK_COMMENT = 13;
+ XML_TOK_BOM = 14; { Byte order mark }
+
+{ The following tokens are returned only by XmlPrologTok }
+ XML_TOK_PROLOG_S = 15;
+ XML_TOK_DECL_OPEN = 16; { <!foo }
+ XML_TOK_DECL_CLOSE = 17; { > }
+ XML_TOK_NAME = 18;
+ XML_TOK_NMTOKEN = 19;
+ XML_TOK_POUND_NAME = 20; { #name }
+ XML_TOK_OR = 21; { | }
+ XML_TOK_PERCENT = 22;
+ XML_TOK_OPEN_PAREN = 23;
+ XML_TOK_CLOSE_PAREN = 24;
+ XML_TOK_OPEN_BRACKET = 25;
+ XML_TOK_CLOSE_BRACKET = 26;
+ XML_TOK_LITERAL = 27;
+ XML_TOK_PARAM_ENTITY_REF = 28;
+ XML_TOK_INSTANCE_START = 29;
+
+{ The following occur only in element type declarations }
+ XML_TOK_NAME_QUESTION = 30; { name? }
+ XML_TOK_NAME_ASTERISK = 31; { name* }
+ XML_TOK_NAME_PLUS = 32; { name+ }
+ XML_TOK_COND_SECT_OPEN = 33; { <![ }
+ XML_TOK_COND_SECT_CLOSE = 34; { ]]> }
+ XML_TOK_CLOSE_PAREN_QUESTION = 35; { )? }
+ XML_TOK_CLOSE_PAREN_ASTERISK = 36; { )* }
+ XML_TOK_CLOSE_PAREN_PLUS = 37; { )+ }
+ XML_TOK_COMMA = 38;
+
+{ The following token is returned only by XmlAttributeValueTok }
+ XML_TOK_ATTRIBUTE_VALUE_S = 39;
+
+{ The following token is returned only by XmlCdataSectionTok }
+ XML_TOK_CDATA_SECT_CLOSE = 40;
+
+{ With namespace processing this is returned by XmlPrologTok for a
+ name with a colon. }
+ XML_TOK_PREFIXED_NAME = 41;
+
+{$IFDEF XML_DTD }
+ XML_TOK_IGNORE_SECT = 42;
+
+{$ENDIF }
+
+{$IFDEF XML_DTD }
+ XML_N_STATES = 4;
+
+{$ELSE }
+ XML_N_STATES = 3;
+
+{$ENDIF }
+
+ XML_PROLOG_STATE = 0;
+ XML_CONTENT_STATE = 1;
+ XML_CDATA_SECTION_STATE = 2;
+
+{$IFDEF XML_DTD }
+ XML_IGNORE_SECTION_STATE = 3;
+
+{$ENDIF }
+
+ XML_N_LITERAL_TYPES = 2;
+ XML_ATTRIBUTE_VALUE_LITERAL = 0;
+ XML_ENTITY_VALUE_LITERAL = 1;
+
+{ The size of the buffer passed to XmlUtf8Encode must be at least this. }
+ XML_UTF8_ENCODE_MAX = 4;
+
+{ The size of the buffer passed to XmlUtf16Encode must be at least this. }
+ XML_UTF16_ENCODE_MAX = 2;
+
+{ TYPES DEFINITION }
+type
+ POSITION_ptr = ^POSITION;
+ POSITION = record
+ { first line and first column are 0 not 1 }
+ lineNumber ,
+ columnNumber : XML_Size;
+
+ end;
+
+ ATTRIBUTE_ptr = ^ATTRIBUTE;
+ ATTRIBUTE = record
+ name ,
+ valuePtr ,
+ valueEnd : char_ptr;
+ normalized : char;
+
+ end;
+
+ ENCODING_ptr_ptr = ^ENCODING_ptr;
+ ENCODING_ptr = ^ENCODING;
+
+ SCANNER = function(p1 : ENCODING_ptr; p2 ,p3 : char_ptr; p4 : char_ptr_ptr ) : int;
+
+ ENCODING = record
+ scanners : array[0..XML_N_STATES - 1 ] of SCANNER;
+ literalScanners : array[0..XML_N_LITERAL_TYPES - 1 ] of SCANNER;
+
+ sameName : function (p1 : ENCODING_ptr; p2 ,p3 : char_ptr ) : int;
+ nameMatchesAscii : function (p1 : ENCODING_ptr; p2 ,p3 ,p4 : char_ptr ) : int;
+ nameLength : function (p1 : ENCODING_ptr; p2 : char_ptr ) : int;
+ skipS : function (p1 : ENCODING_ptr; p2 : char_ptr ) : char_ptr;
+ getAtts : function (enc : ENCODING_ptr; ptr : char_ptr; attsMax : int; atts : ATTRIBUTE_ptr ) : int;
+ charRefNumber : function (enc : ENCODING_ptr; ptr : char_ptr ) : int;
+ predefinedEntityName : function (p1 : ENCODING_ptr; p2 ,p3 : char_ptr ) : int;
+ updatePosition : procedure(p1 : ENCODING_ptr; ptr ,end_ : char_ptr; p4 : POSITION_ptr );
+ isPublicId : function (enc : ENCODING_ptr; ptr ,end_ : char_ptr; badPtr : char_ptr_ptr ) : int;
+ utf8Convert : procedure(enc : ENCODING_ptr; fromP : char_ptr_ptr; fromLim : char_ptr; toP : char_ptr_ptr; toLim : char_ptr );
+ utf16Convert : procedure(enc : ENCODING_ptr; fromP : char_ptr_ptr; fromLim : char_ptr; toP : int16u_ptr_ptr; toLim : int16u_ptr );
+
+ minBytesPerChar : int;
+
+ isUtf8 ,
+ isUtf16 : char;
+
+ end;
+
+ INIT_ENCODING_ptr = ^INIT_ENCODING;
+ INIT_ENCODING = record
+ initEnc : ENCODING;
+ encPtr : ENCODING_ptr_ptr;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+ function XmlInitEncoding (p : INIT_ENCODING_ptr; encPtr : ENCODING_ptr_ptr; name : char_ptr ) : int;
+ function XmlInitEncodingNS(p : INIT_ENCODING_ptr; encPtr : ENCODING_ptr_ptr; name : char_ptr ) : int;
+
+ function XmlGetInternalEncoding : ENCODING_ptr;
+ function XmlGetInternalEncodingNS : ENCODING_ptr;
+
+ function XmlTok_ (enc : ENCODING_ptr; state : int; ptr, end_ : char_ptr; nextTokPtr : char_ptr_ptr ) : int;
+ function XmlPrologTok (enc : ENCODING_ptr; ptr, end_ : char_ptr; nextTokPtr : char_ptr_ptr ) : int;
+ function XmlContentTok(enc : ENCODING_ptr; ptr, end_ : char_ptr; nextTokPtr : char_ptr_ptr ) : int;
+ function XmlIsPublicId(enc : ENCODING_ptr; ptr ,end_ : char_ptr; badPtr : char_ptr_ptr ) : int;
+
+ procedure XmlUtf8Convert (enc : ENCODING_ptr; fromP : char_ptr_ptr; fromLim : char_ptr; toP : char_ptr_ptr; toLim : char_ptr );
+ procedure XmlUtf16Convert(enc : ENCODING_ptr; fromP : char_ptr_ptr; fromLim : char_ptr; toP : int16u_ptr_ptr; toLim : int16u_ptr );
+
+ function XmlUtf8Encode (charNumber : int; buf : char_ptr ) : int;
+ function XmlUtf16Encode(charNumber : int; buf : int16u_ptr ) : int;
+
+{ This is used for performing a 2nd-level tokenization on the content
+ of a literal that has already been returned by XmlTok. }
+ function XmlLiteralTok (enc : ENCODING_ptr; literalType : int; ptr ,end_ : char_ptr; nextTokPtr : char_ptr_ptr ) : int;
+ function XmlAttributeValueTok (enc : ENCODING_ptr; ptr ,end_ : char_ptr; nextTokPtr : char_ptr_ptr ) : int;
+ function XmlEntityValueTok (enc : ENCODING_ptr; ptr ,end_ : char_ptr; nextTokPtr : char_ptr_ptr ) : int;
+ function XmlSameName (enc : ENCODING_ptr; ptr1 ,ptr2 : char_ptr ) : int;
+ function XmlNameMatchesAscii (enc : ENCODING_ptr; ptr1 ,end1 ,ptr2 : char_ptr ) : int;
+ function XmlNameLength (enc : ENCODING_ptr; ptr : char_ptr ) : int;
+ function XmlGetAttributes (enc : ENCODING_ptr; ptr : char_ptr; attsMax : int; atts : ATTRIBUTE_ptr ) : int;
+ function XmlCharRefNumber (enc : ENCODING_ptr; ptr : char_ptr ) : int;
+ function XmlPredefinedEntityName(enc : ENCODING_ptr; ptr ,end_ : char_ptr ) : int;
+
+ function XmlParseXmlDecl(
+ isGeneralTextEntity : int;
+ enc : ENCODING_ptr;
+ ptr ,end_ : char_ptr;
+ badPtr ,versionPtr ,versionEndPtr ,encodingNamePtr : char_ptr_ptr;
+ namedEncodingPtr : ENCODING_ptr_ptr;
+ standalonePtr : int_ptr ) : int;
+
+ function XmlParseXmlDeclNS(
+ isGeneralTextEntity : int;
+ enc : ENCODING_ptr;
+ ptr ,end_ : char_ptr;
+ badPtr ,versionPtr ,versionEndPtr ,encodingNamePtr : char_ptr_ptr;
+ namedEncodingPtr : ENCODING_ptr_ptr;
+ standalonePtr : int_ptr ) : int;
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+type
+ encodingFinder_func = function(enc : ENCODING_ptr; ptr ,end_ : char_ptr ) : ENCODING_ptr;
+
+const
+{$I ascii.inc }
+
+ KW_version : array[0..7 ] of char = (
+ ASCII_vl ,ASCII_el ,ASCII_rl ,ASCII_sl ,ASCII_il ,ASCII_ol ,ASCII_nl ,#0 );
+
+ KW_encoding : array[0..8 ] of char = (
+ ASCII_el ,ASCII_nl ,ASCII_cl ,ASCII_ol ,ASCII_dl ,ASCII_il ,ASCII_nl ,ASCII_gl ,#0 );
+
+ KW_standalone : array[0..10 ] of char = (
+ ASCII_sl ,ASCII_tl ,ASCII_al ,ASCII_nl ,ASCII_dl ,ASCII_al ,ASCII_ll ,ASCII_ol ,
+ ASCII_nl ,ASCII_el ,#0 );
+
+ KW_yes : array[0..3 ] of char = (ASCII_yl ,ASCII_el ,ASCII_sl ,#0 );
+
+ KW_no : array[0..2 ] of char = (ASCII_nl ,ASCII_ol ,#0 );
+
+{ MINBPC }
+function MINBPC(enc : ENCODING_ptr ) : int;
+begin
+{$IFDEF XML_MIN_SIZE }
+ result:=enc.minBytesPerChar;
+
+{$ELSE }
+ result:=1;
+
+{$ENDIF }
+
+end;
+
+{ utf8_toUtf8 }{unicode}
+procedure utf8_toUtf8(enc : ENCODING_ptr; fromP : char_ptr_ptr; fromLim : char_ptr; toP : char_ptr_ptr; toLim : char_ptr );
+var
+ to_ ,from : char_ptr;
+
+begin
+{ Avoid copying partial characters. }
+ if ptrcomp(fromLim ) - ptrcomp(fromP^ ) > ptrcomp(toLim ) - ptrcomp(toP^) then
+ begin
+ fromLim:=char_ptr(ptrcomp(fromP^ ) + (ptrcomp(toLim ) - ptrcomp(toP^ ) ) );
+
+ while ptrcomp(fromLim ) > ptrcomp(fromP^ ) do
+ begin
+ if int8u(char_ptr(ptrcomp(fromLim ) -1 )^ ) and $c0 <> $80 then
+ break;
+
+ dec(ptrcomp(fromLim ) );
+
+ end;
+
+ end;
+
+ to_ :=toP^;
+ from:=fromP^;
+
+ while ptrcomp(from ) <> ptrcomp(fromLim ) do
+ begin
+ to_^:=from^;
+
+ inc(ptrcomp(from ) );
+ inc(ptrcomp(to_ ) );
+
+ end;
+
+ fromP^:=from;
+ toP^ :=to_;
+
+end;
+
+{ utf8_toUtf16 {..}{unicode}
+procedure utf8_toUtf16(enc : ENCODING_ptr; fromP : char_ptr_ptr; fromLim : char_ptr; toP : int16u_ptr_ptr; toLim : int16u_ptr );
+begin
+end;
+
+{ sb_byteType {..}
+function sb_byteType(enc : ENCODING_ptr; p : char_ptr ) : int;
+begin
+end;
+
+{ isNever }
+function isNever(enc : ENCODING_ptr; p : char_ptr ) : int;
+begin
+ result:=0;
+
+end;
+
+{ sb_byteToAscii }
+function sb_byteToAscii(enc : ENCODING_ptr; p : char_ptr ) : int;
+begin
+ result:=int(p^ );
+
+end;
+
+{ sb_charMatches }
+function sb_charMatches(enc : ENCODING_ptr; p : char_ptr; c : int ) : int;
+begin
+ result:=int(int(p^ ) = c );
+
+end;
+
+{ utf8_isName2 {..}
+function utf8_isName2(enc : ENCODING_ptr; p : char_ptr ) : int;
+begin
+end;
+
+{ utf8_isName3 {..}
+function utf8_isName3(enc : ENCODING_ptr; p : char_ptr ) : int;
+begin
+end;
+
+{ utf8_isNmstrt2 {..}
+function utf8_isNmstrt2(enc : ENCODING_ptr; p : char_ptr ) : int;
+begin
+end;
+
+{ utf8_isNmstrt3 {..}
+function utf8_isNmstrt3(enc : ENCODING_ptr; p : char_ptr ) : int;
+begin
+end;
+
+{ utf8_isInvalid2 {..}
+function utf8_isInvalid2(enc : ENCODING_ptr; p : char_ptr ) : int;
+begin
+end;
+
+{ utf8_isInvalid3 {..}
+function utf8_isInvalid3(enc : ENCODING_ptr; p : char_ptr ) : int;
+begin
+end;
+
+{ utf8_isInvalid4 {..}
+function utf8_isInvalid4(enc : ENCODING_ptr; p : char_ptr ) : int;
+begin
+end;
+
+{ LOCAL VARIABLES & CONSTANTS }
+type
+ normal_encoding_ptr = ^normal_encoding;
+ normal_encoding = record
+ enc : ENCODING;
+ type_ : array[0..255 ] of int8u;
+
+ {$IFDEF XML_MIN_SIZE }
+ byteType : function(p1 : ENCODING_ptr; p2 : char_ptr ) : int;
+ isNameMin : function(p1 : ENCODING_ptr; p2 : char_ptr ) : int;
+ isNmstrtMin : function(p1 : ENCODING_ptr; p2 : char_ptr ) : int;
+ byteToAscii : function(p1 : ENCODING_ptr; p2 : char_ptr ) : int;
+ charMatches : function(p1 : ENCODING_ptr; p2 : char_ptr; p3 : int ) : int;
+
+ {$ENDIF }
+ isName2 : function(p1 : ENCODING_ptr; p2 : char_ptr ) : int;
+ isName3 : function(p1 : ENCODING_ptr; p2 : char_ptr ) : int;
+ isName4 : function(p1 : ENCODING_ptr; p2 : char_ptr ) : int;
+ isNmstrt2 : function(p1 : ENCODING_ptr; p2 : char_ptr ) : int;
+ isNmstrt3 : function(p1 : ENCODING_ptr; p2 : char_ptr ) : int;
+ isNmstrt4 : function(p1 : ENCODING_ptr; p2 : char_ptr ) : int;
+ isInvalid2 : function(p1 : ENCODING_ptr; p2 : char_ptr ) : int;
+ isInvalid3 : function(p1 : ENCODING_ptr; p2 : char_ptr ) : int;
+ isInvalid4 : function(p1 : ENCODING_ptr; p2 : char_ptr ) : int;
+
+ end;
+
+const
+ BT_NONXML = 0;
+ BT_MALFORM = 1;
+ BT_LT = 2;
+ BT_AMP = 3;
+ BT_RSQB = 4;
+ BT_LEAD2 = 5;
+ BT_LEAD3 = 6;
+ BT_LEAD4 = 7;
+ BT_TRAIL = 8;
+ BT_CR = 9;
+ BT_LF = 10;
+ BT_GT = 11;
+ BT_QUOT = 12;
+ BT_APOS = 13;
+ BT_EQUALS = 14;
+ BT_QUEST = 15;
+ BT_EXCL = 16;
+ BT_SOL = 17;
+ BT_SEMI = 18;
+ BT_NUM = 19;
+ BT_LSQB = 20;
+ BT_S = 21;
+ BT_NMSTRT = 22;
+ BT_COLON = 23;
+ BT_HEX = 24;
+ BT_DIGIT = 25;
+ BT_NAME = 26;
+ BT_MINUS = 27;
+ BT_OTHER = 28; { known not to be a name or name start character }
+ BT_NONASCII = 29; { might be a name or name start character }
+ BT_PERCNT = 30;
+ BT_LPAR = 31;
+ BT_RPAR = 32;
+ BT_AST = 33;
+ BT_PLUS = 34;
+ BT_COMMA = 35;
+ BT_VERBAR = 36;
+
+ BT_COLON_ = BT_NMSTRT;
+
+{ BYTE_TYPE }
+function BYTE_TYPE(enc : ENCODING_ptr; p : char_ptr ) : int;
+begin
+{$IFDEF XML_MIN_SIZE }
+ result:=normal_encoding_ptr(enc ).byteType(enc ,p );
+
+{$ELSE }
+ result:=normal_encoding_ptr(enc ).type_[int8u(p^ ) ];
+
+{$ENDIF }
+
+end;
+
+{ BYTE_TO_ASCII }
+function BYTE_TO_ASCII(enc : ENCODING_ptr; p : char_ptr ) : int;
+begin
+{$IFDEF XML_MIN_SIZE }
+ result:=normal_encoding_ptr(enc ).byteToAscii(enc ,p );
+
+{$ELSE }
+ result:=int8u_ptr(p )^;
+
+{$ENDIF }
+
+end;
+
+{ CHAR_MATCHES }
+function CHAR_MATCHES(enc : ENCODING_ptr; p : char_ptr; c : int ) : int;
+begin
+{$IFDEF XML_MIN_SIZE }
+ result:=normal_encoding_ptr(enc ).charMatches(enc ,p ,c );
+
+{$ELSE }
+ result:=int(int8u_ptr(p )^ = c );
+
+{$ENDIF }
+
+end;
+
+{ IS_NAME_CHAR }
+function IS_NAME_CHAR(enc : ENCODING_ptr; p : char_ptr; n : int ) : int;
+begin
+ case n of
+ 2 : result:=normal_encoding_ptr(enc ).isName2(enc ,p );
+ 3 : result:=normal_encoding_ptr(enc ).isName3(enc ,p );
+ 4 : result:=normal_encoding_ptr(enc ).isName4(enc ,p );
+
+ end;
+
+end;
+
+{ IS_NMSTRT_CHAR }
+function IS_NMSTRT_CHAR(enc : ENCODING_ptr; p : char_ptr; n : int ) : int;
+begin
+ case n of
+ 2 : result:=normal_encoding_ptr(enc ).isNmstrt2(enc ,p );
+ 3 : result:=normal_encoding_ptr(enc ).isNmstrt3(enc ,p );
+ 4 : result:=normal_encoding_ptr(enc ).isNmstrt4(enc ,p );
+
+ end;
+
+end;
+
+{ IS_INVALID_CHAR }
+function IS_INVALID_CHAR(enc : ENCODING_ptr; p : char_ptr; n : int ) : int;
+begin
+ case n of
+ 2 : result:=normal_encoding_ptr(enc ).isInvalid2(enc ,p );
+ 3 : result:=normal_encoding_ptr(enc ).isInvalid3(enc ,p );
+ 4 : result:=normal_encoding_ptr(enc ).isInvalid4(enc ,p );
+
+ end;
+
+end;
+
+{ IS_NAME_CHAR_MINBPC }
+function IS_NAME_CHAR_MINBPC(enc : ENCODING_ptr; p : char_ptr ) : int;
+begin
+{$IFDEF XML_MIN_SIZE }
+ result:=normal_encoding_ptr(enc ).isNameMin(enc ,p );
+
+{$ELSE }
+ result:=0;
+
+{$ENDIF }
+
+end;
+
+{ IS_NMSTRT_CHAR_MINBPC }
+function IS_NMSTRT_CHAR_MINBPC(enc : ENCODING_ptr; p : char_ptr ) : int;
+begin
+{$IFDEF XML_MIN_SIZE }
+ result:=normal_encoding_ptr(enc ).isNmstrtMin(enc ,p );
+
+{$ELSE }
+ result:=0;
+
+{$ENDIF }
+
+end;
+
+{ INIT_ENC_INDEX }
+function INIT_ENC_INDEX(enc : INIT_ENCODING_ptr ) : int;
+begin
+ result:=int(enc.initEnc.isUtf16 );
+
+end;
+
+{ SET_INIT_ENC_INDEX }
+procedure SET_INIT_ENC_INDEX(enc : INIT_ENCODING_ptr; i : int );
+begin
+ enc.initEnc.isUtf16:=char(i );
+
+end;
+
+{$I xmltok_impl.inc }
+
+const
+{$IFDEF XML_NS }
+ utf8_encoding_ns : normal_encoding = (
+ enc:(scanners :(normal_prologTok ,normal_contentTok ,normal_cdataSectionTok {$IFDEF XML_DTD },normal_ignoreSectionTok {$ENDIF } );
+ literalScanners:(normal_attributeValueTok ,normal_entityValueTok );
+
+ sameName :normal_sameName;
+ nameMatchesAscii :normal_nameMatchesAscii;
+ nameLength :normal_nameLength;
+ skipS :normal_skipS;
+ getAtts :normal_getAtts;
+ charRefNumber :normal_charRefNumber;
+ predefinedEntityName:normal_predefinedEntityName;
+ updatePosition :normal_updatePosition;
+ isPublicId :normal_isPublicId;
+ utf8Convert :utf8_toUtf8;
+ utf16Convert :utf8_toUtf16;
+
+ minBytesPerChar:1;
+
+ isUtf8 :#1;
+ isUtf16:#0 );
+ type_:({$I asciitab.inc}
+ {$I utf8tab.inc});
+
+ {$IFDEF XML_MIN_SIZE }
+ byteType :sb_byteType;
+ isNameMin :isNever;
+ isNmstrtMin:isNever;
+ byteToAscii:sb_byteToAscii;
+ charMatches:sb_charMatches;
+
+ {$ENDIF }
+
+ isName2 :utf8_isName2;
+ isName3 :utf8_isName3;
+ isName4 :isNever;
+ isNmstrt2 :utf8_isNmstrt2;
+ isNmstrt3 :utf8_isNmstrt3;
+ isNmstrt4 :isNever;
+ isInvalid2:utf8_isInvalid2;
+ isInvalid3:utf8_isInvalid3;
+ isInvalid4:utf8_isInvalid4 );
+
+{$ENDIF }
+
+ utf8_encoding : normal_encoding = (
+ enc:(scanners :(normal_prologTok ,normal_contentTok ,normal_cdataSectionTok {$IFDEF XML_DTD },normal_ignoreSectionTok {$ENDIF } );
+ literalScanners:(normal_attributeValueTok ,normal_entityValueTok );
+
+ sameName :normal_sameName;
+ nameMatchesAscii :normal_nameMatchesAscii;
+ nameLength :normal_nameLength;
+ skipS :normal_skipS;
+ getAtts :normal_getAtts;
+ charRefNumber :normal_charRefNumber;
+ predefinedEntityName:normal_predefinedEntityName;
+ updatePosition :normal_updatePosition;
+ isPublicId :normal_isPublicId;
+ utf8Convert :utf8_toUtf8;
+ utf16Convert :utf8_toUtf16;
+
+ minBytesPerChar:1;
+
+ isUtf8 :#1;
+ isUtf16:#0 );
+ type_:({$I asciitab_bt_colon_.inc}
+ {$I utf8tab.inc});
+
+ {$IFDEF XML_MIN_SIZE }
+ byteType :sb_byteType;
+ isNameMin :isNever;
+ isNmstrtMin:isNever;
+ byteToAscii:sb_byteToAscii;
+ charMatches:sb_charMatches;
+
+ {$ENDIF }
+
+ isName2 :utf8_isName2;
+ isName3 :utf8_isName3;
+ isName4 :isNever;
+ isNmstrt2 :utf8_isNmstrt2;
+ isNmstrt3 :utf8_isNmstrt3;
+ isNmstrt4 :isNever;
+ isInvalid2:utf8_isInvalid2;
+ isInvalid3:utf8_isInvalid3;
+ isInvalid4:utf8_isInvalid4 );
+
+{$IFDEF XML_NS }
+ internal_utf8_encoding_ns : normal_encoding = (
+ enc:(scanners :(normal_prologTok ,normal_contentTok ,normal_cdataSectionTok {$IFDEF XML_DTD },normal_ignoreSectionTok {$ENDIF } );
+ literalScanners:(normal_attributeValueTok ,normal_entityValueTok );
+
+ sameName :normal_sameName;
+ nameMatchesAscii :normal_nameMatchesAscii;
+ nameLength :normal_nameLength;
+ skipS :normal_skipS;
+ getAtts :normal_getAtts;
+ charRefNumber :normal_charRefNumber;
+ predefinedEntityName:normal_predefinedEntityName;
+ updatePosition :normal_updatePosition;
+ isPublicId :normal_isPublicId;
+ utf8Convert :utf8_toUtf8;
+ utf16Convert :utf8_toUtf16;
+
+ minBytesPerChar:1;
+
+ isUtf8 :#1;
+ isUtf16:#0 );
+ type_:({$I iasciitab.inc}
+ {$I utf8tab.inc});
+
+ {$IFDEF XML_MIN_SIZE }
+ byteType :sb_byteType;
+ isNameMin :isNever;
+ isNmstrtMin:isNever;
+ byteToAscii:sb_byteToAscii;
+ charMatches:sb_charMatches;
+
+ {$ENDIF }
+
+ isName2 :utf8_isName2;
+ isName3 :utf8_isName3;
+ isName4 :isNever;
+ isNmstrt2 :utf8_isNmstrt2;
+ isNmstrt3 :utf8_isNmstrt3;
+ isNmstrt4 :isNever;
+ isInvalid2:utf8_isInvalid2;
+ isInvalid3:utf8_isInvalid3;
+ isInvalid4:utf8_isInvalid4 );
+
+{$ENDIF }
+
+ internal_utf8_encoding : normal_encoding = (
+ enc:(scanners :(normal_prologTok ,normal_contentTok ,normal_cdataSectionTok {$IFDEF XML_DTD },normal_ignoreSectionTok {$ENDIF } );
+ literalScanners:(normal_attributeValueTok ,normal_entityValueTok );
+
+ sameName :normal_sameName;
+ nameMatchesAscii :normal_nameMatchesAscii;
+ nameLength :normal_nameLength;
+ skipS :normal_skipS;
+ getAtts :normal_getAtts;
+ charRefNumber :normal_charRefNumber;
+ predefinedEntityName:normal_predefinedEntityName;
+ updatePosition :normal_updatePosition;
+ isPublicId :normal_isPublicId;
+ utf8Convert :utf8_toUtf8;
+ utf16Convert :utf8_toUtf16;
+
+ minBytesPerChar:1;
+
+ isUtf8 :#1;
+ isUtf16:#0 );
+ type_:({$I iasciitab_bt_colon_.inc}
+ {$I utf8tab.inc});
+
+ {$IFDEF XML_MIN_SIZE }
+ byteType :sb_byteType;
+ isNameMin :isNever;
+ isNmstrtMin:isNever;
+ byteToAscii:sb_byteToAscii;
+ charMatches:sb_charMatches;
+
+ {$ENDIF }
+
+ isName2 :utf8_isName2;
+ isName3 :utf8_isName3;
+ isName4 :isNever;
+ isNmstrt2 :utf8_isNmstrt2;
+ isNmstrt3 :utf8_isNmstrt3;
+ isNmstrt4 :isNever;
+ isInvalid2:utf8_isInvalid2;
+ isInvalid3:utf8_isInvalid3;
+ isInvalid4:utf8_isInvalid4 );
+
+{$IFDEF XML_NS }
+ latin1_encoding_ns : normal_encoding = ();{..}
+
+{$ENDIF }
+
+ latin1_encoding : normal_encoding = ();{..}
+
+{$IFDEF XML_NS }
+ ascii_encoding_ns : normal_encoding = ();{..}
+
+{$ENDIF }
+
+ ascii_encoding : normal_encoding = ();{..}
+
+{$IFDEF XML_NS }
+ little2_encoding_ns : normal_encoding = ();{..}
+
+{$ENDIF }
+
+ little2_encoding : normal_encoding = ();{..}
+
+{$IFDEF XML_NS }
+ big2_encoding_ns : normal_encoding = ();{..}
+
+{$ENDIF }
+
+ big2_encoding : normal_encoding = ();{..}
+
+{ If this enumeration is changed, getEncodingIndex and encodings
+ must also be changed. }
+ UNKNOWN_ENC = -1;
+ ISO_8859_1_ENC = 0;
+ US_ASCII_ENC = 1;
+ UTF_8_ENC = 2;
+ UTF_16_ENC = 3;
+ UTF_16BE_ENC = 4;
+ UTF_16LE_ENC = 5;
+ NO_ENC = 6; { must match encodingNames up to here }
+
+ KW_ISO_8859_1 : array[0..10 ] of char = (
+ ASCII_I ,ASCII_S ,ASCII_O ,ASCII_MINUS ,ASCII_8 ,ASCII_8 ,ASCII_5 ,ASCII_9 ,
+ ASCII_MINUS ,ASCII_1 ,#0 );
+
+ KW_US_ASCII : array[0..8 ] of char = (
+ ASCII_U ,ASCII_S ,ASCII_MINUS ,ASCII_A ,ASCII_S ,ASCII_C ,ASCII_I ,ASCII_I ,
+ #0 );
+
+ KW_UTF_8 : array[0..5 ] of char = (
+ ASCII_U ,ASCII_T ,ASCII_F ,ASCII_MINUS ,ASCII_8 ,#0 );
+
+ KW_UTF_16 : array[0..6 ] of char = (
+ ASCII_U ,ASCII_T ,ASCII_F ,ASCII_MINUS ,ASCII_1 ,ASCII_6 ,#0 );
+
+ KW_UTF_16BE : array[0..8 ] of char = (
+ ASCII_U ,ASCII_T ,ASCII_F ,ASCII_MINUS ,ASCII_1 ,ASCII_6 ,ASCII_B ,ASCII_E ,
+ #0 );
+
+ KW_UTF_16LE : array[0..8 ] of char = (
+ ASCII_U ,ASCII_T ,ASCII_F ,ASCII_MINUS ,ASCII_1 ,ASCII_6 ,ASCII_L ,ASCII_E ,
+ #0 );
+
+{ UNIT IMPLEMENTATION }
+{ streqci }
+function streqci(s1 ,s2 : char_ptr ) : int;
+var
+ c1 ,c2 : char;
+
+begin
+ repeat
+ c1:=s1^;
+ c2:=s2^;
+
+ inc(ptrcomp(s1 ) );
+ inc(ptrcomp(s2 ) );
+
+ if (ASCII_al <= c1 ) and
+ (c1 <= ASCII_zl ) then
+ inc(byte(c1 ) ,byte(ASCII_A ) - byte(ASCII_al ) );
+
+ if (ASCII_al <= c2 ) and
+ (c2 <= ASCII_zl ) then
+ inc(byte(c2 ) ,byte(ASCII_A ) - byte(ASCII_al ) );
+
+ if c1 <> c2 then
+ begin
+ result:=0;
+
+ exit;
+
+ end;
+
+ if (c1 = #0 ) or
+ (c2 = #0 ) then
+ break;
+
+ until false;
+
+ result:=1;
+
+end;
+
+{ initUpdatePosition {..}
+procedure initUpdatePosition(enc : ENCODING_ptr; ptr ,end_ : char_ptr; pos : POSITION_ptr );
+begin
+end;
+
+{ getEncodingIndex }
+function getEncodingIndex(name : char_ptr ) : int;
+const
+ encodingNames : array[0..5 ] of char_ptr = (
+ @KW_ISO_8859_1 ,
+ @KW_US_ASCII ,
+ @KW_UTF_8 ,
+ @KW_UTF_16 ,
+ @KW_UTF_16BE ,
+ @KW_UTF_16LE );
+
+var
+ i : int;
+
+begin
+ if name = NIL then
+ result:=NO_ENC
+ else
+ begin
+ i:=0;
+
+ while i < sizeof(encodingNames ) div sizeof(encodingNames[0 ] ) do
+ begin
+ if streqci(name ,encodingNames[i ] ) <> 0 then
+ begin
+ result:=i;
+
+ exit;
+
+ end;
+
+ inc(i );
+
+ end;
+
+ result:=UNKNOWN_ENC;
+
+ end;
+
+end;
+
+{ initScan }
+{ This is what detects the encoding. encodingTable maps from
+ encoding indices to encodings; int8u(enc.initEnc.isUtf16 ) is the index of
+ the external (protocol) specified encoding; state is
+ XML_CONTENT_STATE if we're parsing an external text entity, and
+ XML_PROLOG_STATE otherwise. }
+function initScan(
+ encodingTable : ENCODING_ptr_ptr;
+ enc : INIT_ENCODING_ptr;
+ state : int;
+ ptr ,end_ : char_ptr;
+ nextTokPtr : char_ptr_ptr ) : int;
+var
+ encPtr : ENCODING_ptr_ptr;
+
+ e : int;
+
+label
+ _003C ,_esc ;
+
+begin
+ if ptr = end_ then
+ begin
+ result:=XML_TOK_NONE;
+
+ exit;
+
+ end;
+
+ encPtr:=enc.encPtr;
+
+{ only a single byte available for auto-detection }
+ if ptrcomp(ptr ) + 1 = ptrcomp(end_ ) then
+ begin
+ {$IFNDEF XML_DTD } { FIXME }
+ { a well-formed document entity must have more than one byte }
+ if state <> XML_CONTENT_STATE then
+ begin
+ result:=XML_TOK_PARTIAL;
+
+ exit;
+
+ end;
+
+ {$ENDIF }
+ { so we're parsing an external text entity... }
+ { if UTF-16 was externally specified, then we need at least 2 bytes }
+ case INIT_ENC_INDEX(enc ) of
+ UTF_16_ENC ,UTF_16LE_ENC ,UTF_16BE_ENC :
+ begin
+ result:=XML_TOK_PARTIAL;
+
+ exit;
+
+ end;
+
+ end;
+
+ case int8u(ptr^ ) of
+ $FE ,$FF ,$EF : { possibly first byte of UTF-8 BOM }
+ if (INIT_ENC_INDEX(enc ) = ISO_8859_1_ENC ) and
+ (state = XML_CONTENT_STATE ) then
+ else
+ goto _003C;
+
+ $00 ,$3C : { fall through }
+ _003C:
+ begin
+ result:=XML_TOK_PARTIAL;
+
+ exit;
+
+ end;
+
+ end;
+
+ end
+ else
+ case (ptrcomp(ptr^ ) shl 8 ) or int8u_ptr(ptrcomp(ptr ) + 1 )^ of
+ $FEFF :
+ if (INIT_ENC_INDEX(enc ) = ISO_8859_1_ENC ) and
+ (state = XML_CONTENT_STATE ) then
+ else
+ begin
+ nextTokPtr^:=char_ptr(ptrcomp(ptr ) + 2 );
+ encPtr^ :=ENCODING_ptr_ptr(ptrcomp(encodingTable ) + UTF_16BE_ENC * sizeof(ENCODING_ptr ) )^;
+
+ result:=XML_TOK_BOM;
+
+ exit;
+
+ end;
+
+ { 00 3C is handled in the default case }
+ $3C00 :
+ if ((INIT_ENC_INDEX(enc ) = UTF_16BE_ENC ) or
+ (INIT_ENC_INDEX(enc ) = UTF_16_ENC ) ) and
+ (state = XML_CONTENT_STATE ) then
+ else
+ begin
+ encPtr^:=ENCODING_ptr_ptr(ptrcomp(encodingTable ) + UTF_16LE_ENC * sizeof(ENCODING_ptr ) )^;
+ result :=XmlTok_(encPtr^ ,state ,ptr ,end_ ,nextTokPtr );
+
+ exit;
+
+ end;
+
+ $FFFE :
+ if (INIT_ENC_INDEX(enc ) = ISO_8859_1_ENC ) and
+ (state = XML_CONTENT_STATE ) then
+ else
+ begin
+ nextTokPtr^:=char_ptr(ptrcomp(ptr ) + 2 );
+ encPtr^ :=ENCODING_ptr_ptr(ptrcomp(encodingTable ) + UTF_16LE_ENC * sizeof(ENCODING_ptr ) )^;
+
+ result:=XML_TOK_BOM;
+
+ exit;
+
+ end;
+
+ { Maybe a UTF-8 BOM (EF BB BF) }
+ { If there's an explicitly specified (external) encoding
+ of ISO-8859-1 or some flavour of UTF-16
+ and this is an external text entity,
+ don't look for the BOM,
+ because it might be a legal data. }
+ $EFBB :
+ begin
+ if state = XML_CONTENT_STATE then
+ begin
+ e:=INIT_ENC_INDEX(enc );
+
+ if (e = ISO_8859_1_ENC ) or
+ (e = UTF_16BE_ENC ) or
+ (e = UTF_16LE_ENC ) or
+ (e = UTF_16_ENC ) then
+ goto _esc;
+
+ end;
+
+ if ptrcomp(ptr ) + 2 = ptrcomp(end_ ) then
+ begin
+ result:=XML_TOK_PARTIAL;
+
+ exit;
+
+ end;
+
+ if int8u_ptr(ptrcomp(ptr ) + 2 )^ = $BF then
+ begin
+ nextTokPtr^:=char_ptr(ptrcomp(ptr ) + 3 );
+ encPtr^ :=ENCODING_ptr_ptr(ptrcomp(encodingTable ) + UTF_8_ENC * sizeof(ENCODING_ptr ) )^;
+
+ result:=XML_TOK_BOM;
+
+ exit;
+
+ end;
+
+ end;
+
+ else
+ { 0 isn't a legal data character. Furthermore a document
+ entity can only start with ASCII characters. So the only
+ way this can fail to be big-endian UTF-16 if it it's an
+ external parsed general entity that's labelled as
+ UTF-16LE. }
+ if ptr^ = #0 then
+ begin
+ if (state = XML_CONTENT_STATE ) and
+ (INIT_ENC_INDEX(enc ) = UTF_16LE_ENC ) then
+ goto _esc;
+
+ encPtr^:=ENCODING_ptr_ptr(ptrcomp(encodingTable ) + UTF_16BE_ENC * sizeof(ENCODING_ptr ) )^;
+ result :=XmlTok_(encPtr^ ,state ,ptr ,end_ ,nextTokPtr );
+
+ exit;
+
+ end
+ else
+ { We could recover here in the case:
+ - parsing an external entity
+ - second byte is 0
+ - no externally specified encoding
+ - no encoding declaration
+ by assuming UTF-16LE. But we don't, because this would mean when
+ presented just with a single byte, we couldn't reliably determine
+ whether we needed further bytes. }
+ if int8u_ptr(ptrcomp(ptr ) + 1 )^ = 0 then
+ begin
+ if state = XML_CONTENT_STATE then
+ goto _esc;
+
+ encPtr^:=ENCODING_ptr_ptr(ptrcomp(encodingTable ) + UTF_16LE_ENC * sizeof(ENCODING_ptr ) )^;
+ result :=XmlTok_(encPtr^ ,state ,ptr ,end_ ,nextTokPtr );
+
+ end;
+
+ end;
+
+_esc:
+ encPtr^:=ENCODING_ptr_ptr(ptrcomp(encodingTable ) + INIT_ENC_INDEX(enc ) * sizeof(ENCODING_ptr ) )^;
+ result :=XmlTok_(encPtr^ ,state ,ptr ,end_ ,nextTokPtr );
+
+end;
+
+{ toAscii }
+function toAscii(enc : ENCODING_ptr; ptr ,end_ : char_ptr ) : int;
+var
+ buf : array[0..0 ] of char;
+
+ p : char_ptr;
+
+begin
+ p:=@buf[0 ];
+
+ XmlUtf8Convert(enc ,@ptr ,end_ ,@p ,char_ptr(ptrcomp(p ) + 1 ) );
+
+ if p = @buf[0 ] then
+ result:=-1
+ else
+ result:=int(buf[0 ] );
+
+end;
+
+{ isSpace }
+function isSpace(c : int ) : int;
+begin
+ case c of
+ $20 ,$D ,$A ,$9 :
+ result:=1;
+
+ else
+ result:=0;
+
+ end;
+
+end;
+
+{ parsePseudoAttribute }
+{ Return 1 if there's just optional white space or there's an S
+ followed by name=val. }
+function parsePseudoAttribute(
+ enc : ENCODING_ptr;
+ ptr ,end_ : char_ptr;
+ namePtr ,nameEndPtr ,valPtr ,nextTokPtr : char_ptr_ptr ) : int;
+var
+ c : int;
+
+ open : char;
+
+begin
+ if ptr = end_ then
+ begin
+ namePtr^:=NIL;
+ result :=1;
+
+ exit;
+
+ end;
+
+ if isSpace(toAscii(enc ,ptr ,end_ ) ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=0;
+
+ exit;
+
+ end;
+
+ repeat
+ inc(ptrcomp(ptr ) ,enc.minBytesPerChar );
+
+ until isSpace(toAscii(enc ,ptr ,end_ ) ) = 0;
+
+ if ptr = end_ then
+ begin
+ namePtr^:=NIL;
+ result :=1;
+
+ exit;
+
+ end;
+
+ namePtr^:=ptr;
+
+ repeat
+ c:=toAscii(enc ,ptr ,end_ );
+
+ if c = -1 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=0;
+
+ exit;
+
+ end;
+
+ if c = int(ASCII_EQUALS ) then
+ begin
+ nameEndPtr^:=ptr;
+
+ break;
+
+ end;
+
+ if isSpace(c ) <> 0 then
+ begin
+ nameEndPtr^:=ptr;
+
+ repeat
+ inc(ptrcomp(ptr ) ,enc.minBytesPerChar );
+
+ c:=toAscii(enc ,ptr ,end_ );
+
+ until isSpace(c ) = 0;
+
+ if c <> int(ASCII_EQUALS ) then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=0;
+
+ exit;
+
+ end;
+
+ break;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,enc.minBytesPerChar );
+
+ until false;
+
+ if ptr = namePtr^ then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=0;
+
+ exit;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,enc.minBytesPerChar );
+
+ c:=toAscii(enc ,ptr ,end_ );
+
+ while isSpace(c ) <> 0 do
+ begin
+ inc(ptrcomp(ptr ) ,enc.minBytesPerChar );
+
+ c:=toAscii(enc ,ptr ,end_ );
+
+ end;
+
+ if (c <> int(ASCII_QUOT ) ) and
+ (c <> int(ASCII_APOS ) ) then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=0;
+
+ exit;
+
+ end;
+
+ open:=char(c );
+
+ inc(ptrcomp(ptr ) ,enc.minBytesPerChar );
+
+ valPtr^:=ptr;
+
+ repeat
+ c:=toAscii(enc ,ptr ,end_ );
+
+ if c = int(open ) then
+ break;
+
+ if not((int(ASCII_al ) <= c ) and (c <= int(ASCII_zl ) ) ) and
+ not((int(ASCII_A ) <= c ) and (c <= int(ASCII_Z ) ) ) and
+ not((int(ASCII_0 ) <= c ) and (c <= int(ASCII_9 ) ) ) and
+ (c <> int(ASCII_PERIOD ) ) and
+ (c <> int(ASCII_MINUS ) ) and
+ (c <> int(ASCII_UNDERSCORE ) ) then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=0;
+
+ exit;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,enc.minBytesPerChar );
+
+ until false;
+
+ nextTokPtr^:=char_ptr(ptrcomp(ptr ) + enc.minBytesPerChar );
+
+ result:=1;
+
+end;
+
+{ doParseXmlDecl }
+function doParseXmlDecl(
+ encodingFinder : encodingFinder_func;
+ isGeneralTextEntity : int;
+ enc : ENCODING_ptr;
+ ptr ,end_ : char_ptr;
+ badPtr ,versionPtr ,versionEndPtr ,encodingName : char_ptr_ptr;
+ encoding : ENCODING_ptr_ptr;
+ standalone : int_ptr ) : int;
+var
+ val ,name ,nameEnd : char_ptr;
+
+ c : int;
+
+begin
+ val :=NIL;
+ name :=NIL;
+ nameEnd:=NIL;
+
+ inc(ptrcomp(ptr ) ,5 * enc.minBytesPerChar );
+ dec(ptrcomp(end_ ) ,2 * enc.minBytesPerChar );
+
+ if (parsePseudoAttribute(enc ,ptr ,end_ ,@name ,@nameEnd ,@val ,@ptr ) = 0 ) or
+ (name = NIL ) then
+ begin
+ badPtr^:=ptr;
+ result :=0;
+
+ exit;
+
+ end;
+
+ if XmlNameMatchesAscii(enc ,name ,nameEnd ,@KW_version[0 ] ) = 0 then
+ if isGeneralTextEntity = 0 then
+ begin
+ badPtr^:=name;
+ result :=0;
+
+ exit;
+
+ end
+ else
+ else
+ begin
+ if versionPtr <> NIL then
+ versionPtr^:=val;
+
+ if versionEndPtr <> NIL then
+ versionEndPtr^:=ptr;
+
+ if parsePseudoAttribute(enc ,ptr ,end_ ,@name ,@nameEnd ,@val ,@ptr ) = 0 then
+ begin
+ badPtr^:=ptr;
+ result :=0;
+
+ exit;
+
+ end;
+
+ if name = NIL then
+ begin
+ if isGeneralTextEntity <> 0 then
+ begin
+ { a TextDecl must have an EncodingDecl }
+
+ badPtr^:=ptr;
+ result :=0;
+
+ exit;
+
+ end;
+
+ result:=1;
+
+ exit;
+
+ end;
+
+ end;
+
+ if XmlNameMatchesAscii(enc ,name ,nameEnd ,@KW_encoding[0 ] ) <> 0 then
+ begin
+ c:=toAscii(enc ,val ,end_ );
+
+ if not((int(ASCII_al ) <= c ) and (c <= int(ASCII_zl ) ) ) and
+ not((int(ASCII_A ) <= c ) and (c <= int(ASCII_Z ) ) ) then
+ begin
+ badPtr^:=val;
+ result :=0;
+
+ exit;
+
+ end;
+
+ if encodingName <> NIL then
+ encodingName^:=val;
+
+ if encoding <> NIL then
+ encoding^:=encodingFinder(enc ,val ,char_ptr(ptrcomp(ptr ) - enc.minBytesPerChar ) );
+
+ if parsePseudoAttribute(enc ,ptr ,end_ ,@name ,@nameEnd ,@val ,@ptr ) = 0 then
+ begin
+ badPtr^:=ptr;
+ result :=0;
+
+ exit;
+
+ end;
+
+ if name <> NIL then
+ begin
+ result:=1;
+
+ exit;
+
+ end;
+
+ end;
+
+ if (XmlNameMatchesAscii(enc ,name ,nameEnd ,@KW_standalone[0 ] ) = 0 ) or
+ (isGeneralTextEntity <> 0 ) then
+ begin
+ badPtr^:=name;
+ result :=0;
+
+ exit;
+
+ end;
+
+ if XmlNameMatchesAscii(enc ,val ,char_ptr(ptrcomp(ptr ) - enc.minBytesPerChar ) ,@KW_yes[0 ] ) <> 0 then
+ if standalone <> NIL then
+ standalone^:=1
+ else
+ else
+ if XmlNameMatchesAscii(enc ,val ,char_ptr(ptrcomp(ptr ) - enc.minBytesPerChar ) ,@KW_no[0 ] ) <> 0 then
+ if standalone <> NIL then
+ standalone^:=0
+ else
+ else
+ begin
+ badPtr^:=val;
+ result :=0;
+
+ exit;
+
+ end;
+
+ while isSpace(toAscii(enc ,ptr ,end_ ) ) <> 0 do
+ inc(ptrcomp(ptr ) ,enc.minBytesPerChar );
+
+ if ptr <> end_ then
+ begin
+ badPtr^:=ptr;
+ result :=0;
+
+ exit;
+
+ end;
+
+ result:=1;
+
+end;
+
+{$I xmltok_ns.inc }
+
+{ XMLTOK_ }
+function XmlTok_;
+begin
+ result:=enc.scanners[state ](enc ,ptr ,end_ ,nextTokPtr );
+
+end;
+
+{ XMLPROLOGTOK }
+function XmlPrologTok;
+begin
+ result:=XmlTok_(enc ,XML_PROLOG_STATE ,ptr ,end_ ,nextTokPtr );
+
+end;
+
+{ XMLCONTENTTOK }
+function XmlContentTok;
+begin
+ result:=XmlTok_(enc ,XML_CONTENT_STATE ,ptr ,end_ ,nextTokPtr );
+
+end;
+
+{ XMLISPUBLICID }
+function XmlIsPublicId;
+begin
+ result:=enc.isPublicId(enc ,ptr ,end_ ,badPtr );
+
+end;
+
+{ XMLUTF8CONVERT }
+procedure XmlUtf8Convert;
+begin
+ enc.utf8Convert(enc ,fromP ,fromLim ,toP ,toLim );
+
+end;
+
+{ XMLUTF16CONVERT }
+procedure XmlUtf16Convert;
+begin
+ enc.utf16Convert(enc ,fromP ,fromLim ,toP ,toLim );
+
+end;
+
+{ XMLUTF8ENCODE {..}{unicode}
+function XmlUtf8Encode;
+begin
+end;
+
+{ XMLUTF16ENCODE {..}{unicode}
+function XmlUtf16Encode;
+begin
+end;
+
+{ XMLLITERALTOK }
+function XmlLiteralTok;
+begin
+ result:=enc.literalScanners[literalType ](enc ,ptr ,end_ ,nextTokPtr );
+
+end;
+
+{ XMLATTRIBUTEVALUETOK }
+function XmlAttributeValueTok;
+begin
+ result:=XmlLiteralTok(enc ,XML_ATTRIBUTE_VALUE_LITERAL ,ptr ,end_ ,nextTokPtr );
+
+end;
+
+{ XMLENTITYVALUETOK }
+function XmlEntityValueTok;
+begin
+ result:=XmlLiteralTok(enc ,XML_ENTITY_VALUE_LITERAL ,ptr ,end_ ,nextTokPtr );
+
+end;
+
+{ XMLSAMENAME }
+function XmlSameName;
+begin
+ result:=enc.sameName(enc ,ptr1 ,ptr2 );
+
+end;
+
+{ XMLNAMEMATCHESASCII }
+function XmlNameMatchesAscii;
+begin
+ result:=enc.nameMatchesAscii(enc ,ptr1 ,end1 ,ptr2 );
+
+end;
+
+{ XMLNAMELENGTH }
+function XmlNameLength;
+begin
+ result:=enc.nameLength(enc ,ptr );
+
+end;
+
+{ XMLGETATTRIBUTES }
+function XmlGetAttributes;
+begin
+ result:=enc.getAtts(enc ,ptr ,attsMax ,atts );
+
+end;
+
+{ XMLCHARREFNUMBER }
+function XmlCharRefNumber;
+begin
+ result:=enc.charRefNumber(enc ,ptr );
+
+end;
+
+{ XMLPREDEFINEDENTITYNAME }
+function XmlPredefinedEntityName;
+begin
+ result:=enc.predefinedEntityName(enc ,ptr ,end_ );
+
+end;
+
+{ XMLPARSEXMLDECLNS {..}
+function XmlParseXmlDeclNS;
+begin
+end;
+
+END.
+
+{unicode}
+
diff --git a/src/corelib/render/software/agg-demos/expat-pas/xmltok_impl.inc b/src/corelib/render/software/agg-demos/expat-pas/xmltok_impl.inc
new file mode 100755
index 00000000..25403e96
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/expat-pas/xmltok_impl.inc
@@ -0,0 +1,4176 @@
+//----------------------------------------------------------------------------
+// Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
+// and Clark Cooper
+// Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006 Expat maintainers.
+//
+// Expat - Version 2.0.0 Release Milano 0.83 (PasExpat 2.0.0 RM0.83)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.pasports.org/pasexpat
+// Copyright (c) 2006
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 17.05.2006-Milano: Unit port establishment
+// 02.06.2006-Milano: porting
+// 05.06.2006-Milano: -"-
+// 06.06.2006-Milano: -"-
+// 12.06.2006-Milano: -"-
+// 15.06.2006-Milano: normal_contentTok
+// 16.06.2006-Milano: -"-, porting
+// 17.06.2006-Milano: -"-
+// 21.06.2006-Milano: -"-
+// 22.06.2006-Milano: -"-
+//
+{ xmltok_impl.inc }
+{$Q- }
+{$R- }
+{ normal_scanRef {..}
+function normal_scanRef(enc : ENCODING_ptr; ptr ,end_ : char_ptr; nextTokPtr : char_ptr_ptr ) : int;
+begin
+end;
+
+{ normal_scanAtts }
+function normal_scanAtts(enc : ENCODING_ptr; ptr ,end_ : char_ptr; nextTokPtr : char_ptr_ptr ) : int;
+var
+{$IFDEF XML_NS }
+ hadColon : int;
+
+{$ENDIF }
+
+ t ,open ,tok : int;
+
+label
+ _bt0 ,_bt1 ,_bte ,sol ,gt ,_bt2 ;
+
+begin
+{$IFDEF XML_NS }
+ hadColon:=0;
+
+{$ENDIF }
+
+ while ptr <> end_ do
+ case BYTE_TYPE(enc ,ptr ) of
+ {#define CHECK_NAME_CASES}
+ BT_NONASCII :
+ if IS_NAME_CHAR_MINBPC(enc ,ptr ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end
+ else
+ goto _bt0;
+
+ BT_NMSTRT ,BT_HEX ,BT_DIGIT ,BT_NAME ,BT_MINUS :
+ _bt0:
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ BT_LEAD2 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 2 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if IS_NAME_CHAR(enc ,ptr ,2 ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,2 );
+
+ end;
+
+ BT_LEAD3 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 3 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if IS_NAME_CHAR(enc ,ptr ,3 ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,3 );
+
+ end;
+
+ BT_LEAD4 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 4 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if IS_NAME_CHAR(enc ,ptr ,4 ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,4 );
+
+ end;
+
+ {CHECK_NAME_CASES #define}
+
+ {$IFDEF XML_NS }
+ BT_COLON :
+ begin
+ if hadColon <> 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ hadColon:=1;
+
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ if ptr <> end_ then
+ begin
+ result:=XML_TOK_PARTIAL;
+
+ exit;
+
+ end;
+
+ case BYTE_TYPE(enc ,ptr ) of
+ {#define CHECK_NMSTRT_CASES}
+ BT_NONASCII :
+ if IS_NMSTRT_CHAR_MINBPC(enc ,ptr ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end
+ else
+ goto _bt1;
+
+ BT_NMSTRT ,BT_HEX :
+ _bt1:
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ BT_LEAD2 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 2 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if not IS_NMSTRT_CHAR(enc ,ptr ,2 ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,2 );
+
+ end;
+
+ BT_LEAD3 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 3 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if not IS_NMSTRT_CHAR(enc ,ptr ,3 ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,3 );
+
+ end;
+
+ BT_LEAD4 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 4 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if not IS_NMSTRT_CHAR(enc ,ptr ,4 ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,4 );
+
+ end;
+
+ {CHECK_NMSTRT_CASES #define}
+
+ else
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ end;
+
+ end;
+
+ {$ENDIF }
+
+ BT_S ,BT_CR ,BT_LF :
+ begin
+ repeat
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ if ptr <> end_ then
+ result:=XML_TOK_PARTIAL;
+
+ t:=BYTE_TYPE(enc ,ptr );
+
+ if t = BT_EQUALS then
+ break;
+
+ case t of
+ BT_S ,BT_LF ,BT_CR :
+ break;
+
+ else
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ end;
+
+ until false;
+
+ { fall through }
+ goto _bte;
+
+ end;
+
+ BT_EQUALS :
+ _bte:
+ begin
+ {$IFDEF XML_NS }
+ hadColon:=0;
+
+ {$ENDIF }
+
+ repeat
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ if ptr = end_ then
+ begin
+ result:=XML_TOK_PARTIAL;
+
+ exit;
+
+ end;
+
+ open:=BYTE_TYPE(enc ,ptr );
+
+ if (open = BT_QUOT ) or
+ (open = BT_APOS ) then
+ break;
+
+ case open of
+ BT_S ,BT_LF ,BT_CR :
+ else
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ end;
+
+ until false;
+
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ { in attribute value }
+ repeat
+ if ptr = end_ then
+ begin
+ result:=XML_TOK_PARTIAL;
+
+ exit;
+
+ end;
+
+ t:=BYTE_TYPE(enc ,ptr );
+
+ if t = open then
+ break;
+
+ case t of
+ {#define INVALID_CASES}
+ BT_LEAD2 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 2 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if IS_INVALID_CHAR(enc ,ptr ,2 ) <> 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,2 );
+
+ end;
+
+ BT_LEAD3 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 3 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if IS_INVALID_CHAR(enc ,ptr ,3 ) <> 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,3 );
+
+ end;
+
+ BT_LEAD4 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 4 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if IS_INVALID_CHAR(enc ,ptr ,4 ) <> 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,4 );
+
+ end;
+
+ BT_NONXML ,BT_MALFORM ,BT_TRAIL :
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ {INVALID_CASES #define}
+
+ BT_AMP :
+ begin
+ tok:=normal_scanRef(enc ,char_ptr(ptrcomp(ptr ) + MINBPC(enc ) ) ,end_ ,@ptr );
+
+ if tok <= 0 then
+ begin
+ if tok = XML_TOK_INVALID then
+ nextTokPtr^:=ptr;
+
+ result:=tok;
+
+ exit;
+
+ end;
+
+ end;
+
+ BT_LT :
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ else
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ end;
+
+ until false;
+
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ if ptr = end_ then
+ begin
+ result:=XML_TOK_PARTIAL;
+
+ exit;
+
+ end;
+
+ case BYTE_TYPE(enc ,ptr ) of
+ BT_SOL :
+ goto sol;
+
+ BT_GT :
+ goto gt;
+
+ BT_S ,BT_CR ,BT_LF :
+ else
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ end;
+
+ { ptr points to closing quote }
+ repeat
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ if ptr = end_ then
+ begin
+ result:=XML_TOK_PARTIAL;
+
+ exit;
+
+ end;
+
+ case BYTE_TYPE(enc ,ptr ) of
+ {#define CHECK_NMSTRT_CASES}
+ BT_NONASCII :
+ if IS_NMSTRT_CHAR_MINBPC(enc ,ptr ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end
+ else
+ goto _bt2;
+
+ BT_NMSTRT ,BT_HEX :
+ _bt2:
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ BT_LEAD2 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 2 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if not IS_NMSTRT_CHAR(enc ,ptr ,2 ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,2 );
+
+ end;
+
+ BT_LEAD3 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 3 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if not IS_NMSTRT_CHAR(enc ,ptr ,3 ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,3 );
+
+ end;
+
+ BT_LEAD4 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 4 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if not IS_NMSTRT_CHAR(enc ,ptr ,4 ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,4 );
+
+ end;
+
+ {CHECK_NMSTRT_CASES #define}
+
+ BT_S ,BT_CR ,BT_LF :
+ continue;
+
+ BT_GT :
+ gt:
+ begin
+ nextTokPtr^:=char_ptr(ptrcomp(ptr ) + MINBPC(enc ) );
+
+ result:=XML_TOK_START_TAG_WITH_ATTS;
+
+ exit;
+
+ end;
+
+ BT_SOL :
+ sol:
+ begin
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ if ptr = end_ then
+ begin
+ result:=XML_TOK_PARTIAL;
+
+ exit;
+
+ end;
+
+ if CHAR_MATCHES(enc ,ptr ,int(ASCII_GT ) ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ nextTokPtr^:=char_ptr(ptrcomp(ptr ) + MINBPC(enc ) );
+
+ result:=XML_TOK_EMPTY_ELEMENT_WITH_ATTS;
+
+ exit;
+
+ end;
+
+ else
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ end;
+
+ break;
+
+ until false;
+
+ end;
+
+ else
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ end;
+
+ result:=XML_TOK_PARTIAL;
+
+end;
+
+{ normal_scanEndTag }
+{ ptr points to character following "</" }
+function normal_scanEndTag(enc : ENCODING_ptr; ptr ,end_ : char_ptr; nextTokPtr : char_ptr_ptr ) : int;
+label
+ _bt0 ,_bt1 ;
+
+begin
+ if ptr = end_ then
+ begin
+ result:=XML_TOK_PARTIAL;
+
+ exit;
+
+ end;
+
+ case BYTE_TYPE(enc ,ptr ) of
+ {#define CHECK_NMSTRT_CASES}
+ BT_NONASCII :
+ if IS_NMSTRT_CHAR_MINBPC(enc ,ptr ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end
+ else
+ goto _bt0;
+
+ BT_NMSTRT ,BT_HEX :
+ _bt0:
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ BT_LEAD2 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 2 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if not IS_NMSTRT_CHAR(enc ,ptr ,2 ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,2 );
+
+ end;
+
+ BT_LEAD3 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 3 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if not IS_NMSTRT_CHAR(enc ,ptr ,3 ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,3 );
+
+ end;
+
+ BT_LEAD4 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 4 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if not IS_NMSTRT_CHAR(enc ,ptr ,4 ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,4 );
+
+ end;
+
+ {CHECK_NMSTRT_CASES #define}
+
+ else
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ end;
+
+ while ptr <> end_ do
+ case BYTE_TYPE(enc ,ptr ) of
+ {#define CHECK_NAME_CASES}
+ BT_NONASCII :
+ if IS_NAME_CHAR_MINBPC(enc ,ptr ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end
+ else
+ goto _bt1;
+
+ BT_NMSTRT ,BT_HEX ,BT_DIGIT ,BT_NAME ,BT_MINUS :
+ _bt1:
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ BT_LEAD2 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 2 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if IS_NAME_CHAR(enc ,ptr ,2 ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,2 );
+
+ end;
+
+ BT_LEAD3 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 3 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if IS_NAME_CHAR(enc ,ptr ,3 ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,3 );
+
+ end;
+
+ BT_LEAD4 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 4 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if IS_NAME_CHAR(enc ,ptr ,4 ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,4 );
+
+ end;
+
+ {CHECK_NAME_CASES #define}
+
+ BT_S ,BT_CR ,BT_LF :
+ begin
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ while ptr <> end_ do
+ begin
+ case BYTE_TYPE(enc ,ptr ) of
+ BT_GT :
+ begin
+ nextTokPtr^:=char_ptr(ptrcomp(ptr ) + MINBPC(enc ) );
+
+ result:=XML_TOK_END_TAG;
+
+ exit;
+
+ end;
+
+ BT_S ,BT_CR ,BT_LF :
+ else
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ end;
+
+ result:=XML_TOK_PARTIAL;
+
+ exit;
+
+ end;
+
+ {$IFDEF XML_NS }
+ BT_COLON :
+ { no need to check qname syntax here,
+ since end-tag must match exactly }
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ {$ENDIF }
+
+ BT_GT :
+ begin
+ nextTokPtr^:=char_ptr(ptrcomp(ptr ) + MINBPC(enc ) );
+
+ result:=XML_TOK_END_TAG;
+
+ exit;
+
+ end;
+
+ else
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ end;
+
+ result:=XML_TOK_PARTIAL;
+
+end;
+
+{ normal_scanComment }
+{ ptr points to character following "<!-" }
+function normal_scanComment(enc : ENCODING_ptr; ptr ,end_ : char_ptr; nextTokPtr : char_ptr_ptr ) : int;
+begin
+ if ptr <> end_ then
+ begin
+ if CHAR_MATCHES(enc ,ptr ,int(ASCII_MINUS ) ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ while ptr <> end_ do
+ case BYTE_TYPE(enc ,ptr ) of
+ {#define INVALID_CASES}
+ BT_LEAD2 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 2 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if IS_INVALID_CHAR(enc ,ptr ,2 ) <> 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,2 );
+
+ end;
+
+ BT_LEAD3 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 3 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if IS_INVALID_CHAR(enc ,ptr ,3 ) <> 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,3 );
+
+ end;
+
+ BT_LEAD4 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 4 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if IS_INVALID_CHAR(enc ,ptr ,4 ) <> 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,4 );
+
+ end;
+
+ BT_NONXML ,BT_MALFORM ,BT_TRAIL :
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ {INVALID_CASES #define}
+
+ BT_MINUS :
+ begin
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ if ptr = end_ then
+ begin
+ result:=XML_TOK_PARTIAL;
+
+ exit;
+
+ end;
+
+ if CHAR_MATCHES(enc ,ptr ,int(ASCII_MINUS ) ) <> 0 then
+ begin
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ if ptr = end_ then
+ begin
+ result:=XML_TOK_PARTIAL;
+
+ exit;
+
+ end;
+
+ if CHAR_MATCHES(enc ,ptr ,int(ASCII_GT ) ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ nextTokPtr^:=char_ptr(ptrcomp(ptr ) + MINBPC(enc ) );
+
+ result:=XML_TOK_COMMENT;
+
+ exit;
+
+ end;
+
+ end;
+
+ else
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ end;
+
+ end;
+
+ result:=XML_TOK_PARTIAL;
+
+end;
+
+{ normal_scanCdataSection {..}
+function normal_scanCdataSection(enc : ENCODING_ptr; ptr ,end_ : char_ptr; nextTokPtr : char_ptr_ptr ) : int;
+begin
+end;
+
+{ normal_checkPiTarget }
+function normal_checkPiTarget(enc : ENCODING_ptr; ptr ,end_ : char_ptr; tokPtr : int_ptr ) : int;
+var
+ upper : int;
+
+begin
+ upper :=0;
+ tokPtr^:=XML_TOK_PI;
+
+ if ptrcomp(end_ ) - ptrcomp(ptr ) <> MINBPC(enc ) * 3 then
+ begin
+ result:=1;
+
+ exit;
+
+ end;
+
+ case BYTE_TO_ASCII(enc ,ptr ) of
+ int(ASCII_X ) :
+ upper:=1;
+
+ int(ASCII_xl ) :
+ else
+ begin
+ result:=1;
+
+ exit;
+
+ end;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ case BYTE_TO_ASCII(enc ,ptr ) of
+ int(ASCII_M ) :
+ upper:=1;
+
+ int(ASCII_ml ) :
+ else
+ begin
+ result:=1;
+
+ exit;
+
+ end;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ case BYTE_TO_ASCII(enc ,ptr ) of
+ int(ASCII_L ) :
+ upper:=1;
+
+ int(ASCII_ll ) :
+ else
+ begin
+ result:=1;
+
+ exit;
+
+ end;
+
+ end;
+
+ if upper <> 0 then
+ begin
+ result:=0;
+
+ exit;
+
+ end;
+
+ tokPtr^:=XML_TOK_XML_DECL;
+ result :=1;
+
+end;
+
+{ normal_scanPi }
+{ ptr points to character following "<?" }
+function normal_scanPi(enc : ENCODING_ptr; ptr ,end_ : char_ptr; nextTokPtr : char_ptr_ptr ) : int;
+var
+ tok : int;
+
+ target : char_ptr;
+
+label
+ _bt0 ,_bt1 ,_else ;
+
+begin
+ target:=ptr;
+
+ if ptr = end_ then
+ begin
+ result:=XML_TOK_PARTIAL;
+
+ exit;
+
+ end;
+
+ case BYTE_TYPE(enc ,ptr ) of
+ {#define CHECK_NMSTRT_CASES}
+ BT_NONASCII :
+ if IS_NMSTRT_CHAR_MINBPC(enc ,ptr ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end
+ else
+ goto _bt0;
+
+ BT_NMSTRT ,BT_HEX :
+ _bt0:
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ BT_LEAD2 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 2 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if not IS_NMSTRT_CHAR(enc ,ptr ,2 ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,2 );
+
+ end;
+
+ BT_LEAD3 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 3 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if not IS_NMSTRT_CHAR(enc ,ptr ,3 ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,3 );
+
+ end;
+
+ BT_LEAD4 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 4 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if not IS_NMSTRT_CHAR(enc ,ptr ,4 ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,4 );
+
+ end;
+
+ {CHECK_NMSTRT_CASES #define}
+
+ else
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ end;
+
+ while ptr <> end_ do
+ case BYTE_TYPE(enc ,ptr ) of
+ {#define CHECK_NAME_CASES}
+ BT_NONASCII :
+ if IS_NAME_CHAR_MINBPC(enc ,ptr ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end
+ else
+ goto _bt1;
+
+ BT_NMSTRT ,BT_HEX ,BT_DIGIT ,BT_NAME ,BT_MINUS :
+ _bt1:
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ BT_LEAD2 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 2 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if IS_NAME_CHAR(enc ,ptr ,2 ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,2 );
+
+ end;
+
+ BT_LEAD3 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 3 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if IS_NAME_CHAR(enc ,ptr ,3 ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,3 );
+
+ end;
+
+ BT_LEAD4 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 4 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if IS_NAME_CHAR(enc ,ptr ,4 ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,4 );
+
+ end;
+
+ {CHECK_NAME_CASES #define}
+
+ BT_S ,BT_CR ,BT_LF :
+ begin
+ if normal_checkPiTarget(enc ,target ,ptr ,@tok ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ while ptr <> end_ do
+ case BYTE_TYPE(enc ,ptr ) of
+ {#define INVALID_CASES}
+ BT_LEAD2 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 2 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if IS_INVALID_CHAR(enc ,ptr ,2 ) <> 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,2 );
+
+ end;
+
+ BT_LEAD3 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 3 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if IS_INVALID_CHAR(enc ,ptr ,3 ) <> 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,3 );
+
+ end;
+
+ BT_LEAD4 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 4 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if IS_INVALID_CHAR(enc ,ptr ,4 ) <> 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,4 );
+
+ end;
+
+ BT_NONXML ,BT_MALFORM ,BT_TRAIL :
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ {INVALID_CASES #define}
+
+ BT_QUEST :
+ begin
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ if ptr = end_ then
+ begin
+ result:=XML_TOK_PARTIAL;
+
+ exit;
+
+ end;
+
+ if CHAR_MATCHES(enc ,ptr ,int(ASCII_GT ) ) <> 0 then
+ begin
+ nextTokPtr^:=char_ptr(ptrcomp(ptr ) + MINBPC(enc ) );
+
+ result:=tok;
+
+ exit;
+
+ end;
+
+ end;
+
+ else
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ end;
+
+ result:=XML_TOK_PARTIAL;
+
+ exit;
+
+ end;
+
+ BT_QUEST :
+ begin
+ if normal_checkPiTarget(enc ,target ,ptr ,@tok ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ if ptr = end_ then
+ begin
+ result:=XML_TOK_PARTIAL;
+
+ exit;
+
+ end;
+
+ if CHAR_MATCHES(enc ,ptr ,int(ASCII_GT ) ) <> 0 then
+ begin
+ nextTokPtr^:=char_ptr(ptrcomp(ptr ) + MINBPC(enc ) );
+
+ result:=tok;
+
+ exit;
+
+ end;
+
+ { fall through }
+ goto _else;
+
+ end;
+
+ else
+ begin
+ _else:
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ end;
+
+ result:=XML_TOK_PARTIAL;
+
+end;
+
+{ normal_scanLt }
+{ ptr points to character following "<" }
+function normal_scanLt(enc : ENCODING_ptr; ptr ,end_ : char_ptr; nextTokPtr : char_ptr_ptr ) : int;
+{$IFDEF XML_NS }
+var
+ hadColon : int;
+
+{$ENDIF }
+
+label
+ _bt0 ,_bt1 ,_bt2 ,_bt3 ,gt ,sol ;
+
+begin
+ if ptr = end_ then
+ begin
+ result:=XML_TOK_PARTIAL;
+
+ exit;
+
+ end;
+
+ case BYTE_TYPE(enc ,ptr ) of
+ {#define CHECK_NMSTRT_CASES}
+ BT_NONASCII :
+ if IS_NMSTRT_CHAR_MINBPC(enc ,ptr ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end
+ else
+ goto _bt0;
+
+ BT_NMSTRT ,BT_HEX :
+ _bt0:
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ BT_LEAD2 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 2 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if not IS_NMSTRT_CHAR(enc ,ptr ,2 ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,2 );
+
+ end;
+
+ BT_LEAD3 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 3 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if not IS_NMSTRT_CHAR(enc ,ptr ,3 ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,3 );
+
+ end;
+
+ BT_LEAD4 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 4 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if not IS_NMSTRT_CHAR(enc ,ptr ,4 ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,4 );
+
+ end;
+
+ {CHECK_NMSTRT_CASES #define}
+
+ BT_EXCL :
+ begin
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ if ptr = end_ then
+ begin
+ result:=XML_TOK_PARTIAL;
+
+ exit;
+
+ end;
+
+ case BYTE_TYPE(enc ,ptr ) of
+ BT_MINUS:
+ begin
+ result:=normal_scanComment(enc ,char_ptr(ptrcomp(ptr ) + MINBPC(enc ) ) ,end_ ,nextTokPtr );
+
+ exit;
+
+ end;
+
+ BT_LSQB:
+ begin
+ result:=normal_scanCdataSection(enc ,char_ptr(ptrcomp(ptr ) + MINBPC(enc ) ) ,end_ ,nextTokPtr );
+
+ exit;
+
+ end;
+
+ end;
+
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ BT_QUEST :
+ begin
+ result:=normal_scanPi(enc ,char_ptr(ptrcomp(ptr ) + MINBPC(enc ) ) ,end_ ,nextTokPtr );
+
+ exit;
+
+ end;
+
+ BT_SOL :
+ begin
+ result:=normal_scanEndTag(enc ,char_ptr(ptrcomp(ptr ) + MINBPC(enc ) ) ,end_ ,nextTokPtr );
+
+ exit;
+
+ end;
+
+ else
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ end;
+
+{$IFDEF XML_NS }
+ hadColon:=0;
+
+{$ENDIF }
+
+{ we have a start-tag }
+ while ptr <> end_ do
+ case BYTE_TYPE(enc ,ptr ) of
+ {#define CHECK_NAME_CASES}
+ BT_NONASCII :
+ if IS_NAME_CHAR_MINBPC(enc ,ptr ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end
+ else
+ goto _bt1;
+
+ BT_NMSTRT ,BT_HEX ,BT_DIGIT ,BT_NAME ,BT_MINUS :
+ _bt1:
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ BT_LEAD2 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 2 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if IS_NAME_CHAR(enc ,ptr ,2 ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,2 );
+
+ end;
+
+ BT_LEAD3 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 3 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if IS_NAME_CHAR(enc ,ptr ,3 ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,3 );
+
+ end;
+
+ BT_LEAD4 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 4 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if IS_NAME_CHAR(enc ,ptr ,4 ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,4 );
+
+ end;
+
+ {CHECK_NAME_CASES #define}
+
+ {$IFDEF XML_NS }
+ BT_COLON :
+ begin
+ if hadColon <> 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ hadColon:=1;
+
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ if ptr = end_ then
+ begin
+ result:=XML_TOK_PARTIAL;
+
+ exit;
+
+ end;
+
+ case BYTE_TYPE(enc ,ptr ) of
+ {#define CHECK_NMSTRT_CASES}
+ BT_NONASCII :
+ if IS_NMSTRT_CHAR_MINBPC(enc ,ptr ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end
+ else
+ goto _bt2;
+
+ BT_NMSTRT ,BT_HEX :
+ _bt2:
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ BT_LEAD2 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 2 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if not IS_NMSTRT_CHAR(enc ,ptr ,2 ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,2 );
+
+ end;
+
+ BT_LEAD3 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 3 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if not IS_NMSTRT_CHAR(enc ,ptr ,3 ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,3 );
+
+ end;
+
+ BT_LEAD4 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 4 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if not IS_NMSTRT_CHAR(enc ,ptr ,4 ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,4 );
+
+ end;
+
+ {CHECK_NMSTRT_CASES #define}
+
+ else
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ end;
+
+ end;
+
+ {$ENDIF }
+
+ BT_S ,BT_CR ,BT_LF :
+ begin
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ while ptr <> end_ do
+ begin
+ case BYTE_TYPE(enc ,ptr ) of
+ {#define CHECK_NMSTRT_CASES}
+ BT_NONASCII :
+ if IS_NMSTRT_CHAR_MINBPC(enc ,ptr ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end
+ else
+ goto _bt3;
+
+ BT_NMSTRT ,BT_HEX :
+ _bt3:
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ BT_LEAD2 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 2 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if not IS_NMSTRT_CHAR(enc ,ptr ,2 ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,2 );
+
+ end;
+
+ BT_LEAD3 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 3 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if not IS_NMSTRT_CHAR(enc ,ptr ,3 ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,3 );
+
+ end;
+
+ BT_LEAD4 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 4 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if not IS_NMSTRT_CHAR(enc ,ptr ,4 ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,4 );
+
+ end;
+
+ {CHECK_NMSTRT_CASES #define}
+
+ BT_GT :
+ goto gt;
+
+ BT_SOL :
+ goto sol;
+
+ BT_S ,BT_CR ,BT_LF :
+ begin
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ continue;
+
+ end;
+
+ else
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ end;
+
+ result:=normal_scanAtts(enc ,ptr ,end_ ,nextTokPtr );
+
+ exit;
+
+ end;
+
+ result:=XML_TOK_PARTIAL;
+
+ exit;
+
+ end;
+
+ BT_GT :
+ gt:
+ begin
+ nextTokPtr^:=char_ptr(ptrcomp(ptr ) + MINBPC(enc ) );
+
+ result:=XML_TOK_START_TAG_NO_ATTS;
+
+ exit;
+
+ end;
+
+ BT_SOL :
+ sol:
+ begin
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ if ptr <> end_ then
+ begin
+ result:=XML_TOK_PARTIAL;
+
+ exit;
+
+ end;
+
+ if CHAR_MATCHES(enc ,ptr ,int(ASCII_GT ) ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ nextTokPtr^:=char_ptr(ptrcomp(ptr ) + MINBPC(enc ) );
+
+ result:=XML_TOK_EMPTY_ELEMENT_NO_ATTS;
+
+ exit;
+
+ end;
+
+ else
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ end;
+
+ result:=XML_TOK_PARTIAL;
+
+end;
+
+{ normal_scanDecl }
+{ ptr points to character following "<!" }
+function normal_scanDecl(enc : ENCODING_ptr; ptr ,end_ : char_ptr; nextTokPtr : char_ptr_ptr ) : int;
+label
+ _fall0 ;
+
+begin
+ if ptr = end_ then
+ begin
+ result:=XML_TOK_PARTIAL;
+
+ exit;
+
+ end;
+
+ case BYTE_TYPE(enc ,ptr ) of
+ BT_MINUS :
+ begin
+ result:=normal_scanComment(enc ,char_ptr(ptrcomp(ptr ) + MINBPC(enc ) ) ,end_ ,nextTokPtr );
+
+ exit;
+
+ end;
+
+ BT_LSQB :
+ begin
+ nextTokPtr^:=char_ptr(ptrcomp(ptr ) + MINBPC(enc ) );
+
+ result:=XML_TOK_COND_SECT_OPEN;
+
+ exit;
+
+ end;
+
+ BT_NMSTRT ,BT_HEX:
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ else
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ end;
+
+ while ptr <> end_ do
+ case BYTE_TYPE(enc ,ptr ) of
+ BT_PERCNT :
+ begin
+ if ptrcomp(ptr ) + MINBPC(enc ) = ptrcomp(end_ ) then
+ begin
+ result:=XML_TOK_PARTIAL;
+
+ exit;
+
+ end;
+
+ { don't allow <!ENTITY% foo "whatever"> }
+ case BYTE_TYPE(enc ,char_ptr(ptrcomp(ptr ) + MINBPC(enc ) ) ) of
+ BT_S ,BT_CR ,BT_LF ,BT_PERCNT :
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ end;
+
+ { fall through }
+ goto _fall0;
+
+ end;
+
+ BT_S ,BT_CR ,BT_LF :
+ _fall0:
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_DECL_OPEN;
+
+ exit;
+
+ end;
+
+ BT_NMSTRT ,BT_HEX :
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ else
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ end;
+
+ result:=XML_TOK_PARTIAL;
+
+end;
+
+{ scanPercent {..}
+{ ptr points to character following "%" }
+function scanPercent(enc : ENCODING_ptr; ptr ,end_ : char_ptr; nextTokPtr : char_ptr_ptr ) : int;
+begin
+end;
+
+{ scanPoundName {..}
+function scanPoundName(enc : ENCODING_ptr; ptr ,end_ : char_ptr; nextTokPtr : char_ptr_ptr ) : int;
+begin
+end;
+
+{ normal_scanLit }
+function normal_scanLit(
+ open : int; enc : ENCODING_ptr;
+ ptr ,end_ : char_ptr;
+ nextTokPtr : char_ptr_ptr ) : int;
+var
+ t : int;
+
+label
+ _break ;
+
+begin
+ while ptr <> end_ do
+ begin
+ t:=BYTE_TYPE(enc ,ptr );
+
+ case t of
+ {#define INVALID_CASES}
+ BT_LEAD2 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 2 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if IS_INVALID_CHAR(enc ,ptr ,2 ) <> 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,2 );
+
+ end;
+
+ BT_LEAD3 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 3 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if IS_INVALID_CHAR(enc ,ptr ,3 ) <> 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,3 );
+
+ end;
+
+ BT_LEAD4 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 4 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if IS_INVALID_CHAR(enc ,ptr ,4 ) <> 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,4 );
+
+ end;
+
+ BT_NONXML ,BT_MALFORM ,BT_TRAIL :
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ {INVALID_CASES #define}
+
+ BT_QUOT ,BT_APOS :
+ begin
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ if t <> open then
+ goto _break;
+
+ if ptr = end_ then
+ begin
+ result:=-XML_TOK_LITERAL;
+
+ exit;
+
+ end;
+
+ nextTokPtr^:=ptr;
+
+ case BYTE_TYPE(enc ,ptr ) of
+ BT_S ,BT_CR ,BT_LF ,BT_GT ,BT_PERCNT ,BT_LSQB :
+ begin
+ result:=XML_TOK_LITERAL;
+
+ exit;
+
+ end;
+
+ else
+ begin
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ end;
+
+ end;
+
+ else
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ end;
+
+ _break:
+ end;
+
+ result:=XML_TOK_PARTIAL;
+
+end;
+
+{ normal_prologTok }
+function normal_prologTok(enc : ENCODING_ptr; ptr ,end_ : char_ptr; nextTokPtr : char_ptr_ptr ) : int;
+var
+ tok : int;
+
+ n : size_t;
+
+label
+ _bt_s ,_else ,_else2 ,_bt0 ,_bt1 ;
+
+begin
+ if ptr = end_ then
+ begin
+ result:=XML_TOK_NONE;
+
+ exit;
+
+ end;
+
+ if MINBPC(enc ) > 1 then
+ begin
+ n:=ptrcomp(end_ ) - ptrcomp(ptr );
+
+ if n and (MINBPC(enc ) - 1 ) <> 0 then
+ begin
+ n:=n and not(MINBPC(enc ) - 1 );
+
+ if n = 0 then
+ begin
+ result:=XML_TOK_PARTIAL;
+
+ exit;
+
+ end;
+
+ end_:=char_ptr(ptrcomp(ptr ) + n );
+
+ end;
+
+ end;
+
+ case BYTE_TYPE(enc ,ptr ) of
+ BT_QUOT :
+ begin
+ result:=normal_scanLit(BT_QUOT ,enc ,char_ptr(ptrcomp(ptr ) + MINBPC(enc ) ) ,end_ ,nextTokPtr );
+
+ exit;
+
+ end;
+
+ BT_APOS :
+ begin
+ result:=normal_scanLit(BT_APOS ,enc ,char_ptr(ptrcomp(ptr ) + MINBPC(enc ) ) ,end_ ,nextTokPtr );
+
+ exit;
+
+ end;
+
+ BT_LT :
+ begin
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ if ptr = end_ then
+ begin
+ result:=XML_TOK_PARTIAL;
+
+ exit;
+
+ end;
+
+ case BYTE_TYPE(enc ,ptr ) of
+ BT_EXCL :
+ begin
+ result:=normal_scanDecl(enc ,char_ptr(ptrcomp(ptr ) + MINBPC(enc ) ) ,end_ ,nextTokPtr );
+
+ exit;
+
+ end;
+
+ BT_QUEST :
+ begin
+ result:=normal_scanPi(enc ,char_ptr(ptrcomp(ptr ) + MINBPC(enc ) ) ,end_ ,nextTokPtr );
+
+ exit;
+
+ end;
+
+ BT_NMSTRT ,BT_HEX ,BT_NONASCII ,BT_LEAD2 ,BT_LEAD3 ,BT_LEAD4 :
+ begin
+ nextTokPtr^:=char_ptr(ptrcomp(ptr ) - MINBPC(enc ) );
+
+ result:=XML_TOK_INSTANCE_START;
+
+ exit;
+
+ end;
+
+ end;
+
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ BT_CR :
+ if ptrcomp(ptr ) + MINBPC(enc ) = ptrcomp(end_ ) then
+ begin
+ nextTokPtr^:=end_;
+
+ { indicate that this might be part of a CR/LF pair }
+ result:=-XML_TOK_PROLOG_S;
+
+ exit;
+
+ end
+ else
+ { fall through }
+ goto _bt_s;
+
+ BT_S ,BT_LF :
+ _bt_s:
+ begin
+ repeat
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ if ptr = end_ then
+ break;
+
+ case BYTE_TYPE(enc ,ptr ) of
+ BT_CR :
+ { don't split CR/LF pair }
+ if ptrcomp(ptr ) + MINBPC(enc ) <> ptrcomp(end_ ) then
+ else
+ { fall through }
+ goto _else;
+
+ BT_S ,BT_LF :
+ else
+ begin
+ _else:
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_PROLOG_S;
+
+ exit;
+
+ end;
+
+ end;
+
+ until false;
+
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_PROLOG_S;
+
+ exit;
+
+ end;
+
+ BT_PERCNT :
+ begin
+ result:=scanPercent(enc ,char_ptr(ptrcomp(ptr ) + MINBPC(enc ) ) ,end_ ,nextTokPtr );
+
+ exit;
+
+ end;
+
+ BT_COMMA :
+ begin
+ nextTokPtr^:=char_ptr(ptrcomp(ptr ) + MINBPC(enc ) );
+
+ result:=XML_TOK_COMMA;
+
+ exit;
+
+ end;
+
+ BT_LSQB :
+ begin
+ nextTokPtr^:=char_ptr(ptrcomp(ptr ) + MINBPC(enc ) );
+
+ result:=XML_TOK_OPEN_BRACKET;
+
+ exit;
+
+ end;
+
+ BT_RSQB :
+ begin
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ if ptr = end_ then
+ begin
+ result:=-XML_TOK_CLOSE_BRACKET;
+
+ exit;
+
+ end;
+
+ if CHAR_MATCHES(enc ,ptr ,int(ASCII_RSQB ) ) <> 0 then
+ begin
+ if ptrcomp(ptr ) + MINBPC(enc ) = ptrcomp(end_ ) then
+ begin
+ result:=XML_TOK_PARTIAL;
+
+ exit;
+
+ end;
+
+ if CHAR_MATCHES(enc ,char_ptr(ptrcomp(ptr ) + MINBPC(enc ) ) ,int(ASCII_GT ) ) <> 0 then
+ begin
+ nextTokPtr^:=char_ptr(ptrcomp(ptr ) + 2 * MINBPC(enc ) );
+
+ result:=XML_TOK_COND_SECT_CLOSE;
+
+ exit;
+
+ end;
+
+ end;
+
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_CLOSE_BRACKET;
+
+ exit;
+
+ end;
+
+ BT_LPAR :
+ begin
+ nextTokPtr^:=char_ptr(ptrcomp(ptr ) + MINBPC(enc ) );
+
+ result:=XML_TOK_OPEN_PAREN;
+
+ exit;
+
+ end;
+
+ BT_RPAR :
+ begin
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ if ptr = end_ then
+ begin
+ result:=-XML_TOK_CLOSE_PAREN;
+
+ exit;
+
+ end;
+
+ case BYTE_TYPE(enc ,ptr ) of
+ BT_AST :
+ begin
+ nextTokPtr^:=char_ptr(ptrcomp(ptr ) + MINBPC(enc ) );
+
+ result:=XML_TOK_CLOSE_PAREN_ASTERISK;
+
+ exit;
+
+ end;
+
+ BT_QUEST :
+ begin
+ nextTokPtr^:=char_ptr(ptrcomp(ptr ) + MINBPC(enc ) );
+
+ result:=XML_TOK_CLOSE_PAREN_QUESTION;
+
+ exit;
+
+ end;
+
+ BT_PLUS :
+ begin
+ nextTokPtr^:=char_ptr(ptrcomp(ptr ) + MINBPC(enc ) );
+
+ result:=XML_TOK_CLOSE_PAREN_PLUS;
+
+ exit;
+
+ end;
+
+ BT_CR ,BT_LF ,BT_S ,BT_GT ,BT_COMMA ,BT_VERBAR ,BT_RPAR :
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_CLOSE_PAREN;
+
+ exit;
+
+ end;
+
+ end;
+
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ BT_VERBAR :
+ begin
+ nextTokPtr^:=char_ptr(ptrcomp(ptr ) + MINBPC(enc ) );
+
+ result:=XML_TOK_OR;
+
+ exit;
+
+ end;
+
+ BT_GT :
+ begin
+ nextTokPtr^:=char_ptr(ptrcomp(ptr ) + MINBPC(enc ) );
+
+ result:=XML_TOK_DECL_CLOSE;
+
+ exit;
+
+ end;
+
+ BT_NUM :
+ begin
+ result:=scanPoundName(enc ,char_ptr(ptrcomp(ptr ) + MINBPC(enc ) ) ,end_ ,nextTokPtr );
+
+ exit;
+
+ end;
+
+ BT_LEAD2 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 2 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if IS_NMSTRT_CHAR(enc ,ptr ,2 ) <> 0 then
+ begin
+ inc(ptrcomp(ptr ) ,2 );
+
+ tok:=XML_TOK_NAME;
+
+ end
+ else
+ if IS_NAME_CHAR(enc ,ptr ,2 ) <> 0 then
+ begin
+ inc(ptrcomp(ptr ) ,2 );
+
+ tok:=XML_TOK_NMTOKEN;
+
+ end
+ else
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ end;
+
+ BT_LEAD3 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 3 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if IS_NMSTRT_CHAR(enc ,ptr ,3 ) <> 0 then
+ begin
+ inc(ptrcomp(ptr ) ,3 );
+
+ tok:=XML_TOK_NAME;
+
+ end
+ else
+ if IS_NAME_CHAR(enc ,ptr ,3 ) <> 0 then
+ begin
+ inc(ptrcomp(ptr ) ,3 );
+
+ tok:=XML_TOK_NMTOKEN;
+
+ end
+ else
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ end;
+
+ BT_LEAD4 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 4 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if IS_NMSTRT_CHAR(enc ,ptr ,4 ) <> 0 then
+ begin
+ inc(ptrcomp(ptr ) ,4 );
+
+ tok:=XML_TOK_NAME;
+
+ end
+ else
+ if IS_NAME_CHAR(enc ,ptr ,4 ) <> 0 then
+ begin
+ inc(ptrcomp(ptr ) ,4 );
+
+ tok:=XML_TOK_NMTOKEN;
+
+ end
+ else
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ end;
+
+ BT_NMSTRT ,BT_HEX :
+ begin
+ tok:=XML_TOK_NAME;
+
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ end;
+
+ BT_DIGIT ,BT_NAME ,BT_MINUS {$IFDEF XML_NS } ,BT_COLON : {$ELSE }: {$ENDIF }
+ begin
+ tok:=XML_TOK_NMTOKEN;
+
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ end;
+
+ BT_NONASCII :
+ if IS_NMSTRT_CHAR_MINBPC(enc ,ptr ) <> 0 then
+ begin
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ tok:=XML_TOK_NAME;
+
+ end
+ else
+ if IS_NAME_CHAR_MINBPC(enc ,ptr ) <> 0 then
+ begin
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ tok:=XML_TOK_NMTOKEN;
+
+ end
+ else
+ { fall through }
+ goto _else2;
+
+ else
+ begin
+ _else2:
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ end;
+
+ while ptr <> end_ do
+ case BYTE_TYPE(enc ,ptr ) of
+ {#define CHECK_NAME_CASES}
+ BT_NONASCII :
+ if IS_NAME_CHAR_MINBPC(enc ,ptr ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end
+ else
+ goto _bt0;
+
+ BT_NMSTRT ,BT_HEX ,BT_DIGIT ,BT_NAME ,BT_MINUS :
+ _bt0:
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ BT_LEAD2 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 2 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if IS_NAME_CHAR(enc ,ptr ,2 ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,2 );
+
+ end;
+
+ BT_LEAD3 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 3 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if IS_NAME_CHAR(enc ,ptr ,3 ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,3 );
+
+ end;
+
+ BT_LEAD4 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 4 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if IS_NAME_CHAR(enc ,ptr ,4 ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,4 );
+
+ end;
+
+ {CHECK_NAME_CASES #define}
+
+ BT_GT ,BT_RPAR ,BT_COMMA ,BT_VERBAR ,BT_LSQB ,BT_PERCNT ,
+ BT_S ,BT_CR ,BT_LF :
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=tok;
+
+ exit;
+
+ end;
+
+ {$IFDEF XML_NS }
+ BT_COLON :
+ begin
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ case tok of
+ XML_TOK_NAME :
+ begin
+ if ptr = end_ then
+ begin
+ result:=XML_TOK_PARTIAL;
+
+ exit;
+
+ end;
+
+ tok:=XML_TOK_PREFIXED_NAME;
+
+ case BYTE_TYPE(enc ,ptr ) of
+ {#define CHECK_NAME_CASES}
+ BT_NONASCII :
+ if IS_NAME_CHAR_MINBPC(enc ,ptr ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end
+ else
+ goto _bt1;
+
+ BT_NMSTRT ,BT_HEX ,BT_DIGIT ,BT_NAME ,BT_MINUS :
+ _bt1:
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ BT_LEAD2 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 2 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if IS_NAME_CHAR(enc ,ptr ,2 ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,2 );
+
+ end;
+
+ BT_LEAD3 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 3 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if IS_NAME_CHAR(enc ,ptr ,3 ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,3 );
+
+ end;
+
+ BT_LEAD4 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 4 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if IS_NAME_CHAR(enc ,ptr ,4 ) = 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,4 );
+
+ end;
+
+ {CHECK_NAME_CASES #define}
+
+ else
+ tok:=XML_TOK_NMTOKEN;
+
+ end;
+
+ end;
+
+ XML_TOK_PREFIXED_NAME :
+ tok:=XML_TOK_NMTOKEN;
+
+ end;
+
+ end;
+
+ {$ENDIF }
+
+ BT_PLUS :
+ begin
+ if tok = XML_TOK_NMTOKEN then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ nextTokPtr^:=char_ptr(ptrcomp(ptr ) + MINBPC(enc ) );
+
+ result:=XML_TOK_NAME_PLUS;
+
+ exit;
+
+ end;
+
+ BT_AST :
+ begin
+ if tok = XML_TOK_NMTOKEN then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ nextTokPtr^:=char_ptr(ptrcomp(ptr ) + MINBPC(enc ) );
+
+ result:=XML_TOK_NAME_ASTERISK;
+
+ exit;
+
+ end;
+
+ BT_QUEST :
+ begin
+ if tok = XML_TOK_NMTOKEN then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ nextTokPtr^:=char_ptr(ptrcomp(ptr ) + MINBPC(enc ) );
+
+ result:=XML_TOK_NAME_QUESTION;
+
+ exit;
+
+ end;
+
+ else
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ end;
+
+ result:=-tok;
+
+end;
+
+{ normal_contentTok }
+function normal_contentTok(enc : ENCODING_ptr; ptr ,end_ : char_ptr; nextTokPtr : char_ptr_ptr ) : int;
+var
+ n : size_t;
+
+label
+ _break ,_go0 ,_break2 ;
+
+begin
+ if ptr = end_ then
+ begin
+ result:=XML_TOK_NONE;
+
+ exit;
+
+ end;
+
+ if MINBPC(enc ) > 1 then
+ begin
+ n:=ptrcomp(end_ ) - ptrcomp(ptr );
+
+ if n and (MINBPC(enc ) - 1 ) <> 0 then
+ begin
+ n:=n and not(MINBPC(enc ) - 1 );
+
+ if n = 0 then
+ begin
+ result:=XML_TOK_PARTIAL;
+
+ exit;
+
+ end;
+
+ end_:=char_ptr(ptrcomp(ptr ) + n );
+
+ end;
+
+ end;
+
+ case BYTE_TYPE(enc ,ptr ) of
+ BT_LT :
+ begin
+ result:=normal_scanLt(enc ,char_ptr(ptrcomp(ptr ) + MINBPC(enc ) ) ,end_ ,nextTokPtr );
+
+ exit;
+
+ end;
+
+ BT_AMP :
+ begin
+ result:=normal_scanRef(enc ,char_ptr(ptrcomp(ptr ) + MINBPC(enc ) ) ,end_ ,nextTokPtr );
+
+ exit;
+
+ end;
+
+ BT_CR :
+ begin
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ if ptr = end_ then
+ begin
+ result:=XML_TOK_TRAILING_CR;
+
+ exit;
+
+ end;
+
+ if BYTE_TYPE(enc ,ptr ) = BT_LF then
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_DATA_NEWLINE;
+
+ exit;
+
+ end;
+
+ BT_LF :
+ begin
+ nextTokPtr^:=char_ptr(ptrcomp(ptr ) + MINBPC(enc ) );
+
+ result:=XML_TOK_DATA_NEWLINE;
+
+ exit;
+
+ end;
+
+ BT_RSQB :
+ begin
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ if ptr = end_ then
+ begin
+ result:=XML_TOK_TRAILING_RSQB;
+
+ exit;
+
+ end;
+
+ if CHAR_MATCHES(enc ,ptr ,int(ASCII_RSQB ) ) = 0 then
+ goto _break;
+
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ if ptr = end_ then
+ begin
+ result:=XML_TOK_TRAILING_RSQB;
+
+ exit;
+
+ end;
+
+ if CHAR_MATCHES(enc ,ptr ,int(ASCII_GT ) ) = 0 then
+ begin
+ dec(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ goto _break;
+
+ end;
+
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ {#define INVALID_CASES}
+ BT_LEAD2 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 2 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if IS_INVALID_CHAR(enc ,ptr ,2 ) <> 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,2 );
+
+ end;
+
+ BT_LEAD3 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 3 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if IS_INVALID_CHAR(enc ,ptr ,3 ) <> 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,3 );
+
+ end;
+
+ BT_LEAD4 :
+ begin
+ if ptrcomp(end_ ) - ptrcomp(ptr ) < 4 then
+ begin
+ result:=XML_TOK_PARTIAL_CHAR;
+
+ exit;
+
+ end;
+
+ if IS_INVALID_CHAR(enc ,ptr ,4 ) <> 0 then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,4 );
+
+ end;
+
+ BT_NONXML ,BT_MALFORM ,BT_TRAIL :
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ {INVALID_CASES #define}
+
+ else
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ end;
+
+_break:
+ while ptr <> end_ do
+ case BYTE_TYPE(enc ,ptr ) of
+ BT_LEAD2 :
+ begin
+ if (ptrcomp(end_ ) - ptrcomp(ptr ) < 2 ) or
+ (IS_INVALID_CHAR(enc ,ptr ,2 ) <> 0 ) then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_DATA_CHARS;
+
+ exit;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,2 );
+
+ end;
+
+ BT_LEAD3 :
+ begin
+ if (ptrcomp(end_ ) - ptrcomp(ptr ) < 3 ) or
+ (IS_INVALID_CHAR(enc ,ptr ,3 ) <> 0 ) then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_DATA_CHARS;
+
+ exit;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,3 );
+
+ end;
+
+ BT_LEAD4 :
+ begin
+ if (ptrcomp(end_ ) - ptrcomp(ptr ) < 4 ) or
+ (IS_INVALID_CHAR(enc ,ptr ,4 ) <> 0 ) then
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_DATA_CHARS;
+
+ exit;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,4 );
+
+ end;
+
+ BT_RSQB :
+ begin
+ if ptrcomp(ptr ) + MINBPC(enc ) <> ptrcomp(end_ ) then
+ begin
+ if CHAR_MATCHES(enc ,char_ptr(ptrcomp(ptr ) + MINBPC(enc ) ) ,int(ASCII_RSQB ) ) = 0 then
+ begin
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ goto _break2;
+
+ end;
+
+ if ptrcomp(ptr ) + 2 * MINBPC(enc ) <> ptrcomp(end_ ) then
+ begin
+ if CHAR_MATCHES(enc ,char_ptr(ptrcomp(ptr ) + 2 * MINBPC(enc ) ) ,int(ASCII_GT ) ) = 0 then
+ begin
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ goto _break2;
+
+ end;
+
+ nextTokPtr^:=char_ptr(ptrcomp(ptr ) + 2 * MINBPC(enc ) );
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ end;
+
+ { fall through }
+ goto _go0;
+
+ end;
+
+ BT_AMP ,BT_LT ,BT_NONXML ,BT_MALFORM ,BT_TRAIL ,BT_CR ,BT_LF :
+ _go0:
+ begin
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_DATA_CHARS;
+
+ exit;
+
+ end;
+
+ else
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ end;
+
+_break2:
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_DATA_CHARS;
+
+end;
+
+{ normal_cdataSectionTok {..}
+function normal_cdataSectionTok(enc : ENCODING_ptr; ptr ,end_ : char_ptr; nextTokPtr : char_ptr_ptr ) : int;
+begin
+end;
+
+{ normal_ignoreSectionTok {..}
+function normal_ignoreSectionTok(enc : ENCODING_ptr; ptr ,end_ : char_ptr; nextTokPtr : char_ptr_ptr ) : int;
+begin
+end;
+
+{ normal_attributeValueTok }
+function normal_attributeValueTok(enc : ENCODING_ptr; ptr ,end_ : char_ptr; nextTokPtr : char_ptr_ptr ) : int;
+var
+ start : char_ptr;
+
+begin
+ if ptr = end_ then
+ begin
+ result:=XML_TOK_NONE;
+
+ exit;
+
+ end;
+
+ start:=ptr;
+
+ while ptr <> end_ do
+ case BYTE_TYPE(enc ,ptr ) of
+ BT_LEAD2 :
+ inc(ptrcomp(ptr ) ,2 );
+
+ BT_LEAD3 :
+ inc(ptrcomp(ptr ) ,3 );
+
+ BT_LEAD4 :
+ inc(ptrcomp(ptr ) ,4 );
+
+ BT_AMP :
+ begin
+ if ptr = start then
+ begin
+ result:=normal_scanRef(enc ,char_ptr(ptrcomp(ptr ) + MINBPC(enc ) ) ,end_ ,nextTokPtr );
+
+ exit;
+
+ end;
+
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_DATA_CHARS;
+
+ exit;
+
+ end;
+
+ BT_LT :
+ begin
+ { this is for inside entity references }
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_INVALID;
+
+ exit;
+
+ end;
+
+ BT_LF :
+ begin
+ if ptr = start then
+ begin
+ nextTokPtr^:=char_ptr(ptrcomp(ptr ) + MINBPC(enc ) );
+
+ result:=XML_TOK_DATA_NEWLINE;
+
+ exit;
+
+ end;
+
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_DATA_CHARS;
+
+ exit;
+
+ end;
+
+ BT_CR :
+ begin
+ if ptr = start then
+ begin
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ if ptr = end_ then
+ begin
+ result:=XML_TOK_TRAILING_CR;
+
+ exit;
+
+ end;
+
+ if BYTE_TYPE(enc ,ptr ) = BT_LF then
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_DATA_NEWLINE;
+
+ exit;
+
+ end;
+
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_DATA_CHARS;
+
+ exit;
+
+ end;
+
+ BT_S :
+ begin
+ if ptr = start then
+ begin
+ nextTokPtr^:=char_ptr(ptrcomp(ptr ) + MINBPC(enc ) );
+
+ result:=XML_TOK_ATTRIBUTE_VALUE_S;
+
+ exit;
+
+ end;
+
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_DATA_CHARS;
+
+ exit;
+
+ end;
+
+ else
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ end;
+
+ nextTokPtr^:=ptr;
+
+ result:=XML_TOK_DATA_CHARS;
+
+end;
+
+{ normal_entityValueTok {..}
+function normal_entityValueTok(enc : ENCODING_ptr; ptr ,end_ : char_ptr; nextTokPtr : char_ptr_ptr ) : int;
+begin
+end;
+
+{ normal_sameName {..}
+function normal_sameName(enc : ENCODING_ptr; ptr1 ,ptr2 : char_ptr ) : int;
+begin
+end;
+
+{ normal_nameMatchesAscii }
+function normal_nameMatchesAscii(enc : ENCODING_ptr; ptr1 ,end1 ,ptr2 : char_ptr ) : int;
+begin
+ while ptr2^ <> #0 do
+ begin
+ if ptr1 = end1 then
+ begin
+ result:=0;
+
+ exit;
+
+ end;
+
+ if CHAR_MATCHES(enc ,ptr1 ,int(ptr2^ ) ) = 0 then
+ begin
+ result:=0;
+
+ exit;
+
+ end;
+
+ inc(ptrcomp(ptr1 ) ,MINBPC(enc ) );
+ inc(ptrcomp(ptr2 ) );
+
+ end;
+
+ result:=int(ptr1 = end1 );
+
+end;
+
+{ normal_nameLength }
+function normal_nameLength(enc : ENCODING_ptr; ptr : char_ptr ) : int;
+var
+ start : char_ptr;
+
+begin
+ start:=ptr;
+
+ repeat
+ case BYTE_TYPE(enc ,ptr ) of
+ BT_LEAD2 :
+ inc(ptrcomp(ptr ) ,2 );
+
+ BT_LEAD3 :
+ inc(ptrcomp(ptr ) ,3 );
+
+ BT_LEAD4 :
+ inc(ptrcomp(ptr ) ,4 );
+
+ BT_NONASCII ,BT_NMSTRT ,{$IFDEF XML_NS }BT_COLON ,{$ENDIF }
+ BT_HEX ,BT_DIGIT ,BT_NAME ,BT_MINUS :
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ else
+ begin
+ result:=ptrcomp(ptr ) - ptrcomp(start );
+
+ exit;
+
+ end;
+
+ end;
+
+ until false;
+
+end;
+
+{ normal_skipS {..}
+function normal_skipS(enc : ENCODING_ptr; ptr : char_ptr ) : char_ptr;
+begin
+end;
+
+{ normal_getAtts }
+{ This must only be called for a well-formed start-tag or empty
+ element tag. Returns the number of attributes. Pointers to the
+ first attsMax attributes are stored in atts. }
+function normal_getAtts(enc : ENCODING_ptr; ptr : char_ptr; attsMax : int; atts : ATTRIBUTE_ptr ) : int;
+type
+ state_enum = (other ,inName ,inValue );
+
+var
+ state : state_enum;
+
+ nAtts ,open : int;
+
+begin
+ state:=inName;
+ nAtts:=0;
+ open :=0; { defined when state = inValue;
+ initialization just to shut up compilers }
+
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ repeat
+ case BYTE_TYPE(enc ,ptr ) of
+ BT_LEAD2 :
+ begin
+ if state = other then
+ begin
+ if nAtts < attsMax then
+ begin
+ ATTRIBUTE_ptr(ptrcomp(atts ) + nAtts * sizeof(ATTRIBUTE ) )^.name :=ptr;
+ ATTRIBUTE_ptr(ptrcomp(atts ) + nAtts * sizeof(ATTRIBUTE ) )^.normalized:=#1;
+
+ end;
+
+ state:=inName;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,2 - MINBPC(enc ) );
+
+ end;
+
+ BT_LEAD3 :
+ begin
+ if state = other then
+ begin
+ if nAtts < attsMax then
+ begin
+ ATTRIBUTE_ptr(ptrcomp(atts ) + nAtts * sizeof(ATTRIBUTE ) )^.name :=ptr;
+ ATTRIBUTE_ptr(ptrcomp(atts ) + nAtts * sizeof(ATTRIBUTE ) )^.normalized:=#1;
+
+ end;
+
+ state:=inName;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,3 - MINBPC(enc ) );
+
+ end;
+
+ BT_LEAD4 :
+ begin
+ if state = other then
+ begin
+ if nAtts < attsMax then
+ begin
+ ATTRIBUTE_ptr(ptrcomp(atts ) + nAtts * sizeof(ATTRIBUTE ) )^.name :=ptr;
+ ATTRIBUTE_ptr(ptrcomp(atts ) + nAtts * sizeof(ATTRIBUTE ) )^.normalized:=#1;
+
+ end;
+
+ state:=inName;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,4 - MINBPC(enc ) );
+
+ end;
+
+ BT_NONASCII ,BT_NMSTRT ,BT_HEX :
+ if state = other then
+ begin
+ if nAtts < attsMax then
+ begin
+ ATTRIBUTE_ptr(ptrcomp(atts ) + nAtts * sizeof(ATTRIBUTE ) )^.name :=ptr;
+ ATTRIBUTE_ptr(ptrcomp(atts ) + nAtts * sizeof(ATTRIBUTE ) )^.normalized:=#1;
+
+ end;
+
+ state:=inName;
+
+ end;
+
+ BT_QUOT :
+ if state <> inValue then
+ begin
+ if nAtts < attsMax then
+ ATTRIBUTE_ptr(ptrcomp(atts ) + nAtts * sizeof(ATTRIBUTE ) )^.valuePtr:=char_ptr(ptrcomp(ptr ) + MINBPC(enc ) );
+
+ state:=inValue;
+ open :=BT_QUOT;
+
+ end
+ else
+ if open = BT_QUOT then
+ begin
+ state:=other;
+
+ if nAtts < attsMax then
+ ATTRIBUTE_ptr(ptrcomp(atts ) + nAtts * sizeof(ATTRIBUTE ) )^.valueEnd:=ptr;
+
+ inc(nAtts );
+
+ end;
+
+ BT_APOS :
+ if state <> inValue then
+ begin
+ if nAtts < attsMax then
+ ATTRIBUTE_ptr(ptrcomp(atts ) + nAtts * sizeof(ATTRIBUTE ) )^.valuePtr:=char_ptr(ptrcomp(ptr ) + MINBPC(enc ) );
+
+ state:=inValue;
+ open :=BT_APOS;
+
+ end
+ else
+ if open = BT_APOS then
+ begin
+ state:=other;
+
+ if nAtts < attsMax then
+ ATTRIBUTE_ptr(ptrcomp(atts ) + nAtts * sizeof(ATTRIBUTE ) )^.valueEnd:=ptr;
+
+ inc(nAtts );
+
+ end;
+
+ BT_AMP :
+ if nAtts < attsMax then
+ ATTRIBUTE_ptr(ptrcomp(atts ) + nAtts * sizeof(ATTRIBUTE ) )^.normalized:=#0;
+
+ BT_S :
+ if state = inName then
+ state:=other
+ else
+ if (state = inValue ) and
+ (nAtts < attsMax ) and
+ (ATTRIBUTE_ptr(ptrcomp(atts ) + nAtts * sizeof(ATTRIBUTE ) )^.normalized <> #0 ) and
+ ((ptr = ATTRIBUTE_ptr(ptrcomp(atts ) + nAtts * sizeof(ATTRIBUTE ) )^.valuePtr ) or
+ (BYTE_TO_ASCII(enc ,ptr ) <> int(ASCII_SPACE ) ) or
+ (BYTE_TO_ASCII(enc ,char_ptr(ptrcomp(ptr ) + MINBPC(enc ) ) ) = int(ASCII_SPACE ) ) or
+ (BYTE_TYPE(enc ,char_ptr(ptrcomp(ptr ) + MINBPC(enc ) ) ) = open ) ) then
+ ATTRIBUTE_ptr(ptrcomp(atts ) + nAtts * sizeof(ATTRIBUTE ) )^.normalized:=#0;
+
+ BT_CR ,BT_LF :
+ { This case ensures that the first attribute name is counted
+ Apart from that we could just change state on the quote. }
+ if state = inName then
+ state:=other
+ else
+ if (state = inValue ) and
+ (nAtts < attsMax ) then
+ ATTRIBUTE_ptr(ptrcomp(atts ) + nAtts * sizeof(ATTRIBUTE ) )^.normalized:=#0;
+
+ BT_GT ,BT_SOL :
+ if state <> inValue then
+ begin
+ result:=nAtts;
+
+ exit;
+
+ end;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ until false;
+
+{ not reached }
+
+end;
+
+{ normal_charRefNumber {..}
+function normal_charRefNumber(enc : ENCODING_ptr; ptr : char_ptr ) : int;
+begin
+end;
+
+{ normal_predefinedEntityName {..}
+function normal_predefinedEntityName(enc : ENCODING_ptr; ptr ,end_ : char_ptr ) : int;
+begin
+end;
+
+{ normal_updatePosition }
+procedure normal_updatePosition(enc : ENCODING_ptr; ptr ,end_ : char_ptr; pos : POSITION_ptr );
+begin
+ while ptr <> end_ do
+ begin
+ case BYTE_TYPE(enc ,ptr ) of
+ BT_LEAD2 :
+ inc(ptrcomp(ptr ) ,2 );
+
+ BT_LEAD3 :
+ inc(ptrcomp(ptr ) ,3 );
+
+ BT_LEAD4 :
+ inc(ptrcomp(ptr ) ,4 );
+
+ BT_LF :
+ begin
+ pos.columnNumber:=XML_Size(-1 );
+
+ inc(pos.lineNumber );
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ end;
+
+ BT_CR :
+ begin
+ inc(pos.lineNumber );
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ if (ptr <> end_ ) and
+ (BYTE_TYPE(enc ,ptr ) = BT_LF ) then
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ pos.columnNumber:=XML_Size(-1 );
+
+ end;
+
+ else
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ end;
+
+ inc(pos.columnNumber );
+
+ end;
+
+end;
+
+{ normal_isPublicId }
+function normal_isPublicId(enc : ENCODING_ptr; ptr ,end_ : char_ptr; badPtr : char_ptr_ptr ) : int;
+label
+ _else ;
+
+begin
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+ dec(ptrcomp(end_ ) ,MINBPC(enc ) );
+
+ while ptr <> end_ do
+ begin
+ case BYTE_TYPE(enc ,ptr ) of
+ BT_S :
+ if CHAR_MATCHES(enc ,ptr ,int(ASCII_TAB ) ) <> 0 then
+ begin
+ badPtr^:=ptr;
+ result :=0;
+
+ exit;
+
+ end;
+
+ BT_NAME ,BT_NMSTRT :
+ if BYTE_TO_ASCII(enc ,ptr ) and not $7f = 0 then
+ else
+ goto _else;
+
+ BT_DIGIT ,BT_HEX ,BT_MINUS ,BT_APOS ,BT_LPAR ,BT_RPAR ,BT_PLUS ,BT_COMMA ,
+ BT_SOL ,BT_EQUALS ,BT_QUEST ,BT_CR ,BT_LF ,BT_SEMI ,BT_EXCL ,BT_AST ,BT_PERCNT ,
+ BT_NUM {$IFDEF XML_NS } ,BT_COLON : {$ELSE } : {$ENDIF }
+ else
+ _else:
+ case BYTE_TO_ASCII(enc ,ptr ) of
+ $24 , { $ }
+ $40 : { @ }
+ else
+ begin
+ badPtr^:=ptr;
+ result :=0;
+
+ exit;
+
+ end;
+
+ end;
+
+ end;
+
+ inc(ptrcomp(ptr ) ,MINBPC(enc ) );
+
+ end;
+
+ result:=1;
+
+end;
+
diff --git a/src/corelib/render/software/agg-demos/expat-pas/xmltok_ns.inc b/src/corelib/render/software/agg-demos/expat-pas/xmltok_ns.inc
new file mode 100755
index 00000000..d3196b15
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/expat-pas/xmltok_ns.inc
@@ -0,0 +1,176 @@
+//----------------------------------------------------------------------------
+// Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
+// and Clark Cooper
+// Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006 Expat maintainers.
+//
+// Expat - Version 2.0.0 Release Milano 0.83 (PasExpat 2.0.0 RM0.83)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.pasports.org/pasexpat
+// Copyright (c) 2006
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 17.05.2006-Milano: Unit port establishment
+// 02.06.2006-Milano: porting
+// 09.06.2006-Milano: -"-
+//
+{ xmltok_ns.inc }
+const
+{$IFDEF XML_NS }
+ encodingsNS : array[0..6 ] of ENCODING_ptr = (
+ @latin1_encoding_ns.enc ,
+ @ascii_encoding_ns.enc ,
+ @utf8_encoding_ns.enc ,
+ @big2_encoding_ns.enc ,
+ @big2_encoding_ns.enc ,
+ @little2_encoding_ns.enc ,
+ @utf8_encoding_ns.enc ); { NO_ENC }
+
+{$ENDIF }
+
+ encodings : array[0..6 ] of ENCODING_ptr = (
+ @latin1_encoding.enc ,
+ @ascii_encoding.enc ,
+ @utf8_encoding.enc ,
+ @big2_encoding.enc ,
+ @big2_encoding.enc ,
+ @little2_encoding.enc ,
+ @utf8_encoding.enc ); { NO_ENC }
+
+{ initScanProlog }
+function initScanProlog(enc : ENCODING_ptr; ptr ,end_ : char_ptr; nextTokPtr : char_ptr_ptr ) : int;
+begin
+ result:=initScan(@encodings ,INIT_ENCODING_ptr(enc ) ,XML_PROLOG_STATE ,ptr ,end_ ,nextTokPtr );
+
+end;
+
+{ initScanContent {..}
+function initScanContent(enc : ENCODING_ptr; ptr ,end_ : char_ptr; nextTokPtr : char_ptr_ptr ) : int;
+begin
+end;
+
+{ XMLINITENCODING }
+function XmlInitEncoding;
+var
+ i : int;
+
+begin
+ i:=getEncodingIndex(name );
+
+ if i = UNKNOWN_ENC then
+ begin
+ result:=0;
+
+ exit;
+
+ end;
+
+ SET_INIT_ENC_INDEX(p ,i );
+
+ p.initEnc.scanners[XML_PROLOG_STATE ]:=@initScanProlog;
+ p.initEnc.scanners[XML_CONTENT_STATE ]:=@initScanContent;
+
+ p.initEnc.updatePosition:=@initUpdatePosition;
+
+ p.encPtr:=encPtr;
+ encPtr^ :=@p.initEnc;
+
+ result:=1;
+
+end;
+
+{ XMLINITENCODINGNS }
+function XmlInitEncodingNS;
+begin
+end;
+
+{ XmlGetUtf8InternalEncoding }
+function XmlGetUtf8InternalEncoding : ENCODING_ptr;
+begin
+ result:=@internal_utf8_encoding.enc;
+
+end;
+
+{ XmlGetUtf16InternalEncoding {..}
+function XmlGetUtf16InternalEncoding : ENCODING_ptr;
+begin
+end;
+
+{ XMLGETINTERNALENCODING }
+function XmlGetInternalEncoding;
+begin
+{$IFDEF XML_UNICODE }
+ result:=XmlGetUtf16InternalEncoding;
+
+{$ELSE }
+ result:=XmlGetUtf8InternalEncoding;
+
+{$ENDIF }
+
+end;
+
+{ XmlGetUtf8InternalEncodingNS {..}
+function XmlGetUtf8InternalEncodingNS : ENCODING_ptr;
+begin
+end;
+
+{ XmlGetUtf16InternalEncodingNS {..}
+function XmlGetUtf16InternalEncodingNS : ENCODING_ptr;
+begin
+end;
+
+{ XMLGETINTERNALENCODINGNS }
+function XmlGetInternalEncodingNS;
+begin
+{$IFDEF XML_UNICODE }
+ result:=XmlGetUtf16InternalEncodingNS;
+
+{$ELSE }
+ result:=XmlGetUtf8InternalEncodingNS;
+
+{$ENDIF }
+
+end;
+
+{ findEncoding {..}
+function findEncoding(enc : ENCODING_ptr; ptr ,end_ : char_ptr ) : ENCODING_ptr;
+begin
+end;
+
+{ XMLPARSEXMLDECL }
+function XmlParseXmlDecl;
+begin
+ result:=
+ doParseXmlDecl(
+ @findEncoding ,
+ isGeneralTextEntity ,
+ enc ,ptr ,end_ ,
+ badPtr ,
+ versionPtr ,
+ versionEndPtr ,
+ encodingNamePtr ,
+ namedEncodingPtr ,
+ standalonePtr );
+
+end;
+
diff --git a/src/corelib/render/software/agg-demos/expat-wrap/expat.pas b/src/corelib/render/software/agg-demos/expat-wrap/expat.pas
new file mode 100755
index 00000000..585f1e08
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/expat-wrap/expat.pas
@@ -0,0 +1,1024 @@
+{**************************************************************************}
+{ }
+{ This C DLL header file first (automatic) conversion generated by: }
+{ HeadConv 4.0 (c) 2000 by Bob Swart (aka Dr.Bob - www.drbob42.com) }
+{ Final Delphi-Jedi (Darth) command-line units edition }
+{ }
+{ Generated Date: 10/02/2001 }
+{ Generated Time: 11:22:30 }
+{ }
+{**************************************************************************}
+//
+// Extensive hand editing and correcting by Danny Heijl
+// Feb 10, 2001 Danny.Heijl@pandora.be
+//
+// Adapted for working with Windows and Kylix Open Edtion on Linux
+// Jul 29, 2001 Danny.Heijl@pandora.be
+//
+// Further Modifications and naming changes by Karl Waclawek
+// Oct. 25, 2001 karl@waclawek.net
+//
+// Added include file directive for "expat.inc", by Karl Waclawek
+// March 11, 2002 karl@waclawek.net
+//
+// Added support for new API members in Expat 1.95.5 and 1.95.6
+// Jan. 29, 2003 karl@waclawek.net
+//
+// Adjusted for Expat 2.0.0 on Win/Linux/Mac [see {milano}]
+// Jan. 3, 2007 milan@marusinec.sk
+
+{ Notes
+ * For UTF-16 output, Expat must have been compiled with
+ XML_UNICODE and possibly XML_UNICODE_WCHAR_T defined,
+ matching exactly the status of these conditionals here
+}
+
+unit Expat;
+
+interface
+
+{$IFDEF MSWINDOWS}
+uses
+ Windows;
+{$ENDIF}
+
+const
+{$IFDEF XML_UNICODE}
+ LIBPOSTFIX = 'w';
+{$ELSE}
+ LIBPOSTFIX = '';
+{$ENDIF}
+
+{$IFDEF LINUX }
+ EXPATLIB = 'libexpat' + LIBPOSTFIX + '.so';
+
+{$ELSE}
+ EXPATLIB = 'libexpat' + LIBPOSTFIX + '.dll';
+
+{$ENDIF}{milano}
+
+
+{= > EXPAT.H <=}
+
+{+// }
+{-Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd }
+{-See the file COPYING for copying permission. }
+{= }
+
+// for compatibility with C enum :
+
+{$MINENUMSIZE 4}
+
+type
+ TXMLParser = Pointer;
+ PXMLParser = ^TXMLParser;
+ PPXMLParser = ^PXMLParser;
+
+ XML_Parser = TXMLParser;
+
+{ The XML_Status enum gives the possible return values for several API functions. }
+ XML_Status = (XML_STATUS_ERROR ,XML_STATUS_OK ,XML_STATUS_SUSPENDED );
+
+{$IFDEF XML_UNICODE} {+// Information is UTF-16 encoded.*/ }
+ TXMLChar = WideChar;
+ PXMLChar = PWideChar;
+ {$IFDEF XML_UNICODE_WCHAR_T}
+ TXMLLChar = WideChar;
+ PXMLLChar = PWideChar;
+ {$ELSE}
+ TXMLLChar = Char;
+ PXMLLChar = PChar;
+ {$ENDIF}
+{$ELSE} {+// Information is UTF-8 encoded.*/ }
+ TXMLChar = Char;
+ TXMLLChar = Char;
+ PXMLChar = PChar;
+ PXMLLChar = PChar;
+{$ENDIF}
+ //PXMLChar = ^TXMLChar;
+ //PXMLLChar = ^TXMLLChar;
+
+ TXMLContentType = (
+ XML_CTYPE_ILLEGAL, //dummy, to make XML_CTYPE_EMPTY = 1
+ XML_CTYPE_EMPTY,
+ XML_CTYPE_ANY,
+ XML_CTYPE_MIXED,
+ XML_CTYPE_NAME,
+ XML_CTYPE_CHOICE,
+ XML_CTYPE_SEQ);
+
+ TXMLContentQuant = (
+ XML_CQUANT_NONE,
+ XML_CQUANT_OPT,
+ XML_CQUANT_REP,
+ XML_CQUANT_PLUS);
+
+ {+// If type == XML_CTYPE_EMPTY or XML_CTYPE_ANY, then quant will be }
+ {- XML_CQUANT_NONE, and the other fields will be zero or NULL. }
+ {- If type == XML_CTYPE_MIXED, then quant will be NONE or REP and }
+ {- numchildren will contain number of elements that may be mixed in }
+ {- and children point to an array of XMLContent cells that will be }
+ {- all of XML_CTYPE_NAME type with no quantification. }
+
+ {- If type == XML_CTYPE_NAME, then the name points to the name, and }
+ {- the numchildren field will be zero and children will be NULL. The }
+ {- quant fields indicates any quantifiers placed on the name. }
+
+ {- CHOICE and SEQ will have name NULL, the number of children in }
+ {- numchildren and children will point, recursively, to an array }
+ {- of XMLContent cells. }
+
+ {- The EMPTY, ANY, and MIXED types will only occur at top level. }
+ {= }
+ PXMLContent = ^TXMLContent;
+ PXMLContents = ^TXMLContents;
+ TXMLCp = packed record
+ Type_: TXMLContentType;
+ Quant: TXMLContentQuant;
+ Name: PXMLChar;
+ NumChildren:Cardinal;
+ Children: PXMLContents;
+ end;
+ TXMLContent = TXMLCp;
+ TXMLContents = packed array[0.. (MaxInt div SizeOf(TXMLContent)) - 1] of TXMLContent;
+
+
+ {+// This is called for an element declaration. See above for }
+ {- description of the model argument. It's the caller's responsibility }
+ {- to free model when finished with it. }
+ {= }
+ TXMLElementDeclhandler = procedure(
+ UserData: Pointer;
+ const Name: PXMLChar;
+ Model: PXMLContent); cdecl;
+
+procedure XMLSetElementDeclhandler(
+ Parser: TXMLParser;
+ ElDecl: TXMLElementDeclHandler); cdecl;
+
+type
+ {+// }
+ {- The Attlist declaration handler is called for*each* attribute. So }
+ {- a single Attlist declaration with multiple attributes declared will }
+ {- generate multiple calls to this handler. The "default" parameter }
+ { may be NULL in the case of the "#IMPLIED" or "#REQUIRED" keyword. }
+ {- The "isrequired" parameter will be true and the default value will }
+ { be NULL in the case of "#REQUIRED". If "isrequired" is true and }
+ { default is non-NULL, then this is a "#FIXED" default. }
+ {= }
+ TXMLAttlistDeclHandler = procedure(
+ UserData: Pointer;
+ const ElName: PXMLChar;
+ const Attname, AttType, Dflt: PXMLChar;
+ IsRequired: Integer); cdecl;
+
+procedure XMLSetAttlistDeclHandler(
+ Parser: TXMLParser;
+ AttDecl: TXMLAttlistDeclHandler); cdecl;
+
+type
+ {+// The XML declaration handler is called for*both* XML declarations and }
+ {- text declarations. The way to distinguish is that the version parameter }
+ {- will be null for text declarations. The encoding parameter may be null }
+ {- for XML declarations. The standalone parameter will be -1, 0, or 1 }
+ {- indicating respectively that there was no standalone parameter in }
+ {- the declaration, that it was given as no, or that it was given as yes. }
+ {= }
+ TXMLXmlDeclHandler = procedure(
+ UserData: Pointer;
+ const Version, Encoding: PXMLChar;
+ Standalone: Integer); cdecl;
+
+procedure XMLSetXmlDeclHandler(
+ Parser: TXMLParser;
+ XmlDecl: TXMLXMLdeclHandler); cdecl;
+
+{+// Constructs a new Parser; encoding is the encoding specified by the external }
+{= protocol or null if there is none specified. }
+function XML_ParserCreate(const Encoding: PXMLChar): TXMLParser; cdecl;
+
+{+// Constructs a new Parser and namespace processor. Element type names }
+{- and attribute names that belong to a namespace will be expanded; }
+{- unprefixed attribute names are never expanded; unprefixed element type }
+{- names are expanded only if there is a default namespace. The expanded }
+{- name is the concatenation of the namespace URI, the namespace separator character, }
+{- and the local part of the name. If the namespace separator is '\0' then }
+{- the namespace URI and the local part will be concatenated without any }
+{- separator. When a namespace is not declared, the name and prefix will be }
+{= passed through without expansion. }
+function XMLParserCreateNS(
+ const Encoding: PXMLChar;
+ NamespaceSeparator: TXMLChar): TXMLParser; cdecl;
+
+{+// Constructs a new Parser using the memory management suit referred to }
+{- by memsuite. If memsuite is NULL, then use the standard library memory }
+{- suite. If namespaceSeparator is non-NULL it creates a Parser with }
+{- namespace processing as described above. The character pointed at }
+{- will serve as the namespace separator. }
+
+{- All further memory operations used for the created Parser will come from }
+{- the given suite. }
+{= }
+type
+ TMallocFcn = function(Size: Integer): Pointer; cdecl;
+ TReallocFcn = function(Ptr: Pointer; Size: Integer): Pointer; cdecl;
+ TFreeFcn = procedure(Ptr: Pointer); cdecl;
+
+ PXMLMemoryHandlingSuite = ^TXMLMemoryHandlingSuite;
+ TXMLMemoryHandlingSuite = packed record
+ MallocFcn: TMallocFcn;
+ ReallocFcn: TReallocFcn;
+ FreeFcn: TFReeFcn;
+ end;
+
+function XMLParserCreateMM(
+ const Encoding: PXMLChar;
+ const MemSuite: PXMLMemoryHandlingSuite;
+ const NamespaceSeparator: PXMLChar): TXMLParser; cdecl;
+
+{+// Prepare a parser object to be re-used. This is particularly }
+{- valuable when memory allocation overhead is disproportionatly high, }
+{- such as when a large number of small documnents need to be parsed. }
+{- All handlers are cleared from the parser, except for the }
+{- unknownEncodingHandler. The parser's external state is re-initialized }
+{= except for the values of ns, ns_triplets and useForeignDTD. }
+(*function XMLParserReset(
+ Parser: TXMLParser;
+ const Encoding: PXMLChar): Integer;*){milano}
+
+type
+ {+// attrs is array of name/value pairs, terminated by 0; }
+ {= names and values are 0 terminated. }
+ TAttrs = array[0..(MaxInt div SizeOf(PXMLChar)) - 1] of PXMLChar;
+ PAttrs = ^TAttrs;
+
+ TXMLStartElementHandler = procedure(
+ UserData: Pointer;
+ const Name: PXMLChar;
+ const Atts: TAttrs); cdecl;
+
+ TXMLEndElementHandler = procedure(
+ UserData: Pointer;
+ const Name: PXMLChar); cdecl;
+
+ {+// s is not 0 terminated.*/ }
+ TXMLCharacterDataHandler = procedure(
+ UserData: Pointer;
+ const S: PXMLChar;
+ Len: integer); cdecl;
+
+ {+// target and data are 0 terminated*/ }
+ TXMLProcessingInstructionHandler = procedure(
+ UserData: Pointer;
+ const Target: PXMLChar;
+ const Data: PXMLChar); cdecl;
+
+ {+// data is 0 terminated*/ }
+ TXMLCommentHandler = procedure(
+ UserData: Pointer;
+ const Data: PXMLChar); cdecl;
+
+ TXMLStartCdataSectionHandler = procedure(UserData: Pointer); cdecl;
+ TXMLEndCdataSectionHandler = procedure(UserData: Pointer); cdecl;
+
+ {+// This is called for any characters in the XML document for }
+ {- which there is no applicable handler. This includes both }
+ {- characters that are part of markup which is of a kind that is }
+ {- not reported (comments, markup declarations), or characters }
+ {- that are part of a construct which could be reported but }
+ {- for which no handler has been supplied. The characters are passed }
+ {- exactly as they were in the XML document except that }
+ {- they will be encoded in UTF-8. Line boundaries are not normalized. }
+ {- Note that a byte order mark character is not passed to the default handler. }
+ {- There are no guarantees about how characters are divided between calls }
+ {- to the default handler: for example, a comment might be split between }
+ {= multiple calls. }
+ TXMLDefaultHandler = procedure(
+ UserData: Pointer;
+ const S: PXMLChar;
+ Len: Integer); cdecl;
+
+ {+// This is called for the start of the DOCTYPE declaration, before }
+ {= any DTD or internal subset is parsed. }
+ TXMLStartDoctypeDeclHandler = procedure(
+ UserData: Pointer;
+ const DoctypeName: PXMLChar;
+ const SysId: PXMLChar;
+ const PubId: PXMLChar;
+ HasInternalSubset: Integer); cdecl;
+
+ {+// This is called for the start of the DOCTYPE declaration when the }
+ {= closing > is encountered, but after processing any external subset. }
+ TXMLEndDoctypeDeclHandler = procedure(UserData: Pointer); cdecl;
+
+ {+// This is called for entity declarations. The is_parameter_entity }
+ {- argument will be non-zero if the entity is a parameter entity, zero }
+ {- otherwise. }
+
+ {- For internal entities (<!ENTITY foo "bar">), value will }
+ {- be non-null and systemId, publicID, and notationName will be null. }
+ {- The value string is NOT null terminated; the length is provided in }
+ {- the value_length argument. Since it is legal to have zero-length }
+ {- values, do not use this argument to test for internal entities. }
+
+ {- For external entities, value will be null and systemId will be non-null. }
+ {- The publicId argument will be null unless a public identifier was }
+ {- provided. The notationName argument will have a non-null value only }
+ {- for unparsed entity declarations. }
+ {= }
+ TXMLEntityDeclHandler = procedure(
+ UserData: Pointer;
+ const EntityName: PXMLChar;
+ IsParameterEntity: Integer;
+ const Value: PXMLChar;
+ ValueLength: Integer;
+ const Base: PXMLChar;
+ const SystemId: PXMLChar;
+ const PublicId: PXMLChar;
+ const NotationName: PXMLChar); cdecl;
+
+procedure XMLSetEntityDeclHandler(
+ Parser: TXMLParser;
+ Handler: TXMLEntityDeclHandler); cdecl;
+
+type
+ {+// OBSOLETE -- OBSOLETE -- OBSOLETE }
+ {- This handler has been superceded by the EntityDeclHandler above. }
+ {- It is provided here for backward compatibility. }
+ {- This is called for a declaration of an unparsed (NDATA) }
+ {- entity. The base argument is whatever was set by XMLSetBase. }
+ {- The entityName, systemId and notationName arguments will never be null. }
+ {= The other arguments may be. }
+ TXMLUnparsedEntityDeclHandler = procedure(
+ UserData: Pointer;
+ const EntityName: PXMLChar;
+ const Base: PXMLChar;
+ const SystemId: PXMLChar;
+ const PublicId: PXMLChar;
+ const NotationName: PXMLChar); cdecl;
+
+ {+// This is called for a declaration of notation. }
+ {- The base argument is whatever was set by XMLSetBase. }
+ {= The notationName will never be null. The other arguments can be. }
+ TXMLNotationDeclHandler = procedure(
+ UserData: Pointer;
+ const NotationName: PXMLChar;
+ const Base: PXMLChar;
+ const SystemId: PXMLChar;
+ const PublicId: PXMLChar); cdecl;
+
+ {+// When namespace processing is enabled, these are called once for }
+ {- each namespace declaration. The call to the start and end element }
+ {- handlers occur between the calls to the start and end namespace }
+ {- declaration handlers. For an xmlns attribute, prefix will be null. }
+ {= For an xmlns="" attribute, uri will be null. }
+ TXMLStartNamespaceDeclHandler = procedure(
+ UserData: pointer;
+ const Prefix: PXMLChar;
+ const Uri: PXMLChar); cdecl;
+
+ TXMLEndNamespaceDeclHandler = procedure(
+ UserData: Pointer;
+ const Prefix: PXMLChar); cdecl;
+
+ {+// This is called if the document is not standalone (it has an }
+ {- external subset or a reference to a parameter entity, but does not }
+ {- have standalone="yes"). If this handler returns 0, then processing }
+ {- will not continue, and the Parser will return a }
+ {= XML_ERROR_NOT_STANDALONE error. }
+ TXMLNotStandaloneHandler = function(UserData: Pointer): Integer; cdecl;
+
+ {+// This is called for a reference to an external parsed general entity. }
+ {- The referenced entity is not automatically parsed. }
+ {- The application can parse it immediately or later using }
+ {- XMLExternalEntityParserCreate. }
+ {- The Parser argument is the Parser parsing the entity containing the reference; }
+ {- it can be passed as the Parser argument to XMLExternalEntityParserCreate. }
+ {- The systemId argument is the system identifier as specified in the entity declaration; }
+ {- it will not be null. }
+ {- The base argument is the system identifier that should be used as the base for }
+ {- resolving systemId if systemId was relative; this is set by XMLSetBase; }
+ {- it may be null. }
+ {- The publicId argument is the public identifier as specified in the entity declaration, }
+ {- or null if none was specified; the whitespace in the public identifier }
+ {- will have been normalized as required by the XML spec. }
+ {- The context argument specifies the parsing context in the format }
+ {- expected by the context argument to }
+ {- XMLExternalEntityParserCreate; context is valid only until the handler }
+ {- returns, so if the referenced entity is to be parsed later, it must be copied. }
+ {- The handler should return 0 if processing should not continue because of }
+ {- a fatal error in the handling of the external entity. }
+ {- In this case the calling Parser will return an XML_ERROR_EXTERNAL_ENTITY_HANDLING }
+ {- error. }
+ {= Note that unlike other handlers the first argument is the Parser, not UserData. }
+ TXMLExternalEntityRefHandler = function(
+ Parser: TXMLParser;
+ const Context: PXMLChar;
+ const Base: PXMLChar;
+ const SystemId: PXMLChar;
+ const PublicId: PXMLChar): Integer; cdecl;
+
+ {+// This is called in two situations: }
+ {- 1) An entity reference is encountered for which no declaration }
+ {- has been read *and* this is not an error. }
+ {- 2) An internal entity reference is read, but not expanded, because }
+ {= XML_SetDefaultHandler has been called. }
+ TXMLSkippedEntityHandler = procedure(
+ UserData: Pointer;
+ const EntityName: PXMLChar;
+ IsParameterEntity: Integer); cdecl;
+
+ {+// This structure is filled in by the XMLUnknownEncodingHandler }
+ {- to provide information to the Parser about encodings that are unknown }
+ {- to the Parser. }
+ {- The map[b] member gives information about byte sequences }
+ {- whose first byte is b. }
+ {- If map[b] is c where c is >= 0, then b by itself encodes the Unicode scalar value c. }
+ {- If map[b] is -1, then the byte sequence is malformed. }
+ {- If map[b] is -n, where n >= 2, then b is the first byte of an n-byte }
+ {- sequence that encodes a single Unicode scalar value. }
+ {- The data member will be passed as the first argument to the convert function. }
+ {- The convert function is used to convert multibyte sequences; }
+ {- s will point to a n-byte sequence where map[(unsigned char)*s] == -n. }
+ {- The convert function must return the Unicode scalar value }
+ {- represented by this byte sequence or -1 if the byte sequence is malformed. }
+ {- The convert function may be null if the encoding is a single-byte encoding, }
+ {- that is if map[b] >= -1 for all bytes b. }
+ {- When the Parser is finished with the encoding, then if release is not null, }
+ {- it will call release passing it the data member; }
+ {- once release has been called, the convert function will not be called again. }
+
+ {- Expat places certain restrictions on the encodings that are supported }
+ {- using this mechanism. }
+
+ {- 1. Every ASCII character that can appear in a well-formed XML document, }
+ {- other than the characters }
+
+ (* $@\^`{}~ *)
+
+ {- must be represented by a single byte, and that byte must be the }
+ {- same byte that represents that character in ASCII. }
+
+ {- 2. No character may require more than 4 bytes to encode. }
+
+ {- 3. All characters encoded must have Unicode scalar values <= 0xFFFF, }
+ {- (ie characters that would be encoded by surrogates in UTF-16 }
+ {- are not allowed). Note that this restriction doesn't apply to }
+ {- the built-in support for UTF-8 and UTF-16. }
+
+ {- 4. No Unicode character may be encoded by more than one distinct sequence }
+ {= of bytes. }
+ TConvertEncoding = function(Data: Pointer; S: Pchar): Integer; cdecl;
+ TReleaseEncoding = procedure(Data: Pointer); cdecl;
+
+ PXMLEncoding = ^TXMLEncoding;
+ TXMLEncoding = packed record
+ Map: array[0..255] of Integer;
+ Data: Pointer;
+ Convert: TConvertEncoding;
+ Release: TReleaseEncoding;
+ end;
+
+ {+// This is called for an encoding that is unknown to the Parser. }
+ {- The encodingHandlerData argument is that which was passed as the }
+ {- second argument to XMLSetUnknownEncodingHandler. }
+ {- The name argument gives the name of the encoding as specified in }
+ {- the encoding declaration. }
+ {- If the callback can provide information about the encoding, }
+ {- it must fill in the XMLEncoding structure, and return 1. }
+ {- Otherwise it must return 0. }
+ {- If info does not describe a suitable encoding, }
+ {= then the Parser will return an XML_UNKNOWN_ENCODING error. }
+ TXMLUnknownEncodingHandler = function(
+ EncodingHandlerData: Pointer;
+ const Name: PXMLChar;
+ Info: PXMLEncoding): Integer; cdecl;
+
+procedure XML_SetElementHandler(
+ Parser: TXMLParser;
+ Start: TXMLStartElementHandler;
+ End_: TXMLEndElementHandler); cdecl;
+
+procedure XMLSetStartElementhandler(
+ Parser: TXMLParser;
+ Handler: TXMLStartElementHandler); cdecl;
+
+procedure XMLSetEndElementHandler(
+ Parser: TXMLParser;
+ Handler: TXMLEndElementHandler); cdecl;
+
+procedure XML_SetCharacterDataHandler(
+ Parser: TXMLParser;
+ Handler: TXMLCharacterDataHandler); cdecl;
+
+procedure XMLSetProcessingInstructionHandler(
+ Parser: TXMLParser;
+ Handler: TXMLProcessingInstructionHandler); cdecl;
+
+procedure XMLSetCommentHandler(
+ Parser: TXMLParser;
+ Handler: TXMLCommentHandler); cdecl;
+
+procedure XMLSetCdataSectionHandler(
+ Parser: TXMLParser;
+ Start: TXMLStartCdataSectionHandler;
+ End_: TXMLEndCdataSectionHandler); cdecl;
+
+procedure XMLSetStartCdataSectionHandler(
+ Parser: TXMLParser;
+ Start: TXMLStartCdataSectionHandler); cdecl;
+
+procedure XMLSetEndCdataSectionHandler(
+ Parser: TXMLParser;
+ End_: TXMLEndCdataSectionHandler); cdecl;
+
+{+// This sets the default handler and also inhibits expansion of internal entities. }
+{- The entity references will be passed to the default handler, or to the
+{= skipped entity handler, if one is set. }
+procedure XMLSetdefaultHandler(
+ Parser: TXMLParser;
+ Handler: TXMLDefaultHandler); cdecl;
+
+{+// This sets the default handler but does not inhibit expansion of internal entities. }
+{= The entity reference will not be passed to the default handler. }
+procedure XMLSetDefaultHandlerExpand(
+ Parser: TXMLParser;
+ Handler: TXMLDefaultHandler); cdecl;
+
+procedure XMLSetDoctypeDeclHandler(
+ Parser: TXMLParser;
+ Start: TXMLStartDoctypeDeclHandler;
+ End_: TXMLEndDoctypeDeclHandler); cdecl;
+
+procedure XMLSetStartDoctypeDeclHandler(
+ Parser: TXMLParser;
+ Start: TXMLStartDoctypeDeclHandler); cdecl;
+
+procedure XMLSetEndDoctypeDeclHandler(
+ Parser: TXMLParser;
+ End_: TXMLEndDoctypeDeclHandler); cdecl;
+
+procedure XMLSetUnparsedEntityDeclHandler(
+ Parser: TXMLParser;
+ Handler: TXMLUnparsedEntityDeclHandler); cdecl;
+
+procedure XMLSetNotationDeclHandler(
+ Parser: TXMLParser;
+ Handler: TXMLNotationDeclHandler); cdecl;
+
+procedure XMLSetNameSpaceDeclHandler(
+ Parser: TXMLParser;
+ Start: TXMLStartNamespaceDeclHandler;
+ End_: TXMLEndNamespaceDeclHandler); cdecl;
+
+procedure XMLSetStartNameSpaceDeclHandler(
+ Parser: TXMLParser;
+ Start: TXMLStartNamespaceDeclHandler); cdecl;
+
+procedure XMLSetEndNameSpaceDeclHandler(
+ Parser: TXMLParser;
+ End_: TXMLEndNamespaceDeclHandler); cdecl;
+
+procedure XMLSetNotstandaloneHandler(
+ Parser: TXMLParser;
+ Handler: TXMLNotStandaloneHandler); cdecl;
+
+procedure XMLSetExternalEntityRefHandler(
+ Parser: TXMLParser;
+ Handler: TXMLExternalEntityRefHandler); cdecl;
+
+{+// If a non-null value for arg is specified here, then it will be passed }
+{- as the first argument to the external entity ref handler instead }
+{= of the Parser object. }
+procedure XMLSetExternalEntityRefHandlerArg(
+ Parser: TXMLParser;
+ Arg: Pointer); cdecl;
+
+procedure XMLSetSkippedEntityHandler(
+ Parser: TXMLParser;
+ Handler: TXMLSkippedEntityHandler); cdecl;
+
+{ EncodingHandlerData works like UserData }
+procedure XMLSetUnknownEncodingHandler(
+ Parser: TXMLPARSER;
+ Handler: TXMLUnknownEncodingHandler;
+ EncodingHandlerData: Pointer); cdecl;
+
+{+// This can be called within a handler for a start element, end element, }
+{- processing instruction or character data. It causes the corresponding }
+{= markup to be passed to the default handler. }
+procedure XMLDefaultCurrent(Parser: TXMLParser); cdecl;
+
+{+// If do_nst is non-zero, and namespace processing is in effect, and }
+{- a name has a prefix (i.e. an explicit namespace qualifier) then }
+{- that name is returned as a triplet in a single }
+{- string separated by the separator character specified when the Parser }
+{- was created: URI + sep + local_name + sep + prefix. }
+
+{- If do_nst is zero, then namespace information is returned in the }
+{- default manner (URI + sep + local_name) whether or not the names }
+{- has a prefix. }
+{= }
+procedure XMLSetReturnNSTriplet(
+ Parser: TXMLParser;
+ DoNst: Integer); cdecl;
+
+{+// This value is passed as the UserData argument to callbacks.*/ }
+procedure XML_SetUserData(
+ Parser: TXMLParser;
+ UserData: Pointer); cdecl;
+
+{+// Returns the last value set by XMLSetUserData or null.*/ }
+{ #define XMLGetUserData(Parser) (*(void **)(Parser)) }
+function XMLGetUserData(Parser: TXMLParser): Pointer;
+
+{+// This is equivalent to supplying an encoding argument }
+{- to XMLParserCreate. It must not be called after XMLParse }
+{= or XMLParseBuffer. }
+function XMLSetEncoding(
+ Parser: TXMLParser;
+ const Encoding: PXMLChar): Integer; cdecl;
+
+{+// If this function is called, then the Parser will be passed }
+{- as the first argument to callbacks instead of UserData. }
+{= The UserData will still be accessible using XMLGetUserData. }
+procedure XMLUseParserAsHandlerArg(Parser: TXMLParser); cdecl;
+
+{+// If useDTD == XML_TRUE is passed to this function, then the parser }
+{- will assume that there is an external subset, even if none is }
+{- specified in the document. In such a case the parser will call the }
+{- externalEntityRefHandler with a value of NULL for the systemId }
+{- argument (the publicId and context arguments will be NULL as well). }
+{- Note: If this function is called, then this must be done before }
+{- the first call to XML_Parse or XML_ParseBuffer, since it will }
+{- have no effect after that. Returns }
+{- XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING. }
+{- Note: If the document does not have a DOCTYPE declaration at all, }
+{- then startDoctypeDeclHandler and endDoctypeDeclHandler will not }
+{- be called, despite an external subset being parsed. }
+{- Note: If XML_DTD is not defined when Expat is compiled, returns }
+{= XML_ERROR_FEATURE_REQUIRES_XML_DTD. }
+procedure XMLUseForeignDTD(
+ Parser: TXMLParser;
+ useDTD: ByteBool); cdecl;
+
+{+// Sets the base to be used for resolving relative URIs in system identifiers in }
+{- declarations. Resolving relative identifiers is left to the application: }
+{- this value will be passed through as the base argument to the }
+{- XMLExternalEntityRefHandler, XMLNotationDeclHandler }
+{- and XMLUnparsedEntityDeclHandler. The base argument will be copied. }
+{= Returns zero if out of memory, non-zero otherwise. }
+function XMLSetBase(
+ Parser: TXMLParser;
+ const Base: PXMLChar): Integer; cdecl;
+
+function XMLGetBase(Parser: TXMLParser): PXMLChar; cdecl;
+
+{+// Returns the number of the attribute/value pairs passed in last call }
+{- to the XMLStartElementHandler that were specified in the start-tag }
+{- rather than defaulted. Each attribute/value pair counts as 2; thus }
+{- this correspondds to an index into the atts array passed to the }
+{= XMLStartElementHandler. }
+function XMLGetSpecifiedAttributeCount(Parser: TXMLParser): Integer; cdecl;
+
+{+// Returns the index of the ID attribute passed in the last call to }
+{- XMLStartElementHandler, or -1 if there is no ID attribute. Each }
+{- attribute/value pair counts as 2; thus this correspondds to an index }
+{= into the atts array passed to the XMLStartElementHandler. }
+function XMLGetIdAttributeIndex(Parser: TXMLParser): Integer; cdecl;
+
+{+// Parses some input. Returns 0 if a fatal error is detected. }
+{- The last call to XMLParse must have isFinal true; }
+{= len may be zero for this call (or any other). }
+function XML_Parse(
+ Parser: TXMLParser;
+ const S: PChar;
+ Len: Integer;
+ IsFinal: Integer): XML_Status; cdecl;
+
+function XMLGetBuffer(
+ Parser: TXMLParser;
+ Len: Integer): Pointer; cdecl;
+
+function XMLParseBuffer(
+ Parser: TXMLParser;
+ Len: Integer;
+ IsFinal: Integer): Integer; cdecl;
+
+{+// Creates an XMLParser object that can parse an external general entity; }
+{- context is a '\0'-terminated string specifying the parse context; }
+{- encoding is a '\0'-terminated string giving the name of the externally specified encoding, }
+{- or null if there is no externally specified encoding. }
+{- The context string consists of a sequence of tokens separated by formfeeds (\f); }
+{- a token consisting of a name specifies that the general entity of the name }
+{- is open; a token of the form prefix=uri specifies the namespace for a particular }
+{- prefix; a token of the form =uri specifies the default namespace. }
+{- This can be called at any point after the first call to an ExternalEntityRefHandler }
+{- so longer as the Parser has not yet been freed. }
+{- The new Parser is completely independent and may safely be used in a separate thread. }
+{- The handlers and UserData are initialized from the Parser argument. }
+{= Returns 0 if out of memory. Otherwise returns a new XMLParser object. }
+function XMLExternalEntityParserCreate(
+ Parser: TXMLParser;
+ const Context: PXMLChar;
+ const Encoding: PXMLChar): TXMLParser; cdecl;
+
+type
+ TXMLParamEntityParsing = (
+ XML_PARAM_ENTITY_PARSING_NEVER,
+ XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE,
+ XML_PARAM_ENTITY_PARSING_ALWAYS);
+
+{+// Controls parsing of parameter entities (including the external DTD }
+{- subset). If parsing of parameter entities is enabled, then references }
+{- to external parameter entities (including the external DTD subset) }
+{- will be passed to the handler set with }
+{- XMLSetExternalEntityRefHandler. The context passed will be 0. }
+{- Unlike external general entities, external parameter entities can only }
+{- be parsed synchronously. If the external parameter entity is to be }
+{- parsed, it must be parsed during the call to the external entity ref }
+{- handler: the complete sequence of XMLExternalEntityParserCreate, }
+{- XMLParse/XMLParseBuffer and XMLParserFree calls must be made during }
+{- this call. After XMLExternalEntityParserCreate has been called to }
+{- create the Parser for the external parameter entity (context must be 0 }
+{- for this call), it is illegal to make any calls on the old Parser }
+{- until XMLParserFree has been called on the newly created Parser. If }
+{- the library has been compiled without support for parameter entity }
+{- parsing (ie without XML_DTD being defined), then }
+{- XMLSetParamEntityParsing will return 0 if parsing of parameter }
+{= entities is requested; otherwise it will return non-zero. }
+function XMLSetParamEntityParsing(
+ Parser: TXMLParser;
+ Parsing: TXMLParamEntityParsing): Integer; cdecl;
+
+type
+ TXMLError = (
+ XML_ERROR_NONE,
+ XML_ERROR_NO_MEMORY,
+ XML_ERROR_SYNTAX,
+ XML_ERROR_NO_ELEMENTS,
+ XML_ERROR_INVALID_TOKEN,
+ XML_ERROR_UNCLOSED_TOKEN,
+ XML_ERROR_PARTIAL_CHAR,
+ XML_ERROR_TAG_MISMATCH,
+ XML_ERROR_DUPLICATE_ATTRIBUTE,
+ XML_ERROR_JUNK_AFTER_DOC_ELEMENT,
+ XML_ERROR_PARAM_ENTITY_REF,
+ XML_ERROR_UNDEFINED_ENTITY,
+ XML_ERROR_RECURSIVE_ENTITY_REF,
+ XML_ERROR_ASYNC_ENTITY,
+ XML_ERROR_BAD_CHAR_REF,
+ XML_ERROR_BINARY_ENTITY_REF,
+ XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF,
+ XML_ERROR_MISPLACED_XML_PI,
+ XML_ERROR_UNKNOWN_ENCODING,
+ XML_ERROR_INCORRECT_ENCODING,
+ XML_ERROR_UNCLOSED_CDATA_SECTION,
+ XML_ERROR_EXTERNAL_ENTITY_HANDLING,
+ XML_ERROR_NOT_STANDALONE,
+ XML_ERROR_UNEXPECTED_STATE);
+
+ XML_Error = TXMLError;
+
+{+// If XMLParse or XMLParseBuffer have returned 0, then XMLGetErrorCode );
+{= returns information about the error. }
+function XML_GetErrorCode(Parser: TXMLParser): TXMLError; cdecl;
+
+{+// These functions return information about the current parse location. );
+{- They may be called when XMLParse or XMLParseBuffer return 0; }
+{- in this case the location is the location of the character at which }
+{- the error was detected. }
+{- They may also be called from any other callback called to report }
+{- some parse event; in this the location is the location of the first }
+{= of the sequence of characters that generated the event. }
+function XML_GetCurrentLineNumber(Parser: TXMLParser): Integer; cdecl;
+function XMLGetCurrentColumnNumber(Parser: TXMLParser): Integer; cdecl;
+function XMLGetCurrentByteIndex(Parser: TXMLParser): Longint; cdecl;
+
+{+// Return the number of bytes in the current event. }
+{= Returns 0 if the event is in an internal entity. }
+function XMLGetCurrentByteCount(Parser: TXMLParser): Integer; cdecl;
+
+{+// If XML_CONTEXT_BYTES is defined, returns the input buffer, sets }
+{- the integer pointed to by offset to the offset within this buffer }
+{- of the current parse position, and sets the integer pointed to by size }
+{- to the size of this buffer (the number of input bytes). Otherwise }
+{- returns a null pointer. Also returns a null pointer if a parse isn't active. }
+
+{- NOTE: The character pointer returned should not be used outside }
+{= the handler that makes the call. }
+function XMLGetInputContext(
+ Parser: TXMLParser;
+ var Offset: Integer;
+ var Size: Integer): PChar; cdecl;
+
+{+// For backwards compatibility with previous versions. }
+// #define XMLGetErrorLineNumber XMLGetCurrentLineNumber
+// #define XMLGetErrorColumnNumber XMLGetCurrentColumnNumber
+// #define XMLGetErrorByteIndex XMLGetCurrentByteIndex
+
+{+// Frees memory used by the Parser. }
+procedure XML_ParserFree(Parser: TXMLParser); cdecl;
+
+{+// Returns a string describing the error. }
+function XML_ErrorString(Code: Integer): PXMLLChar; cdecl;
+
+{+// Return a string containing the version number of this expat }
+function XMLExpatVersion: PXMLLChar; cdecl;
+
+type
+ TXMLExpatVersion = packed record
+ Major: Longint;
+ Minor: Longint;
+ Micro: Longint;
+ end;
+
+{+// Return a TXMLExpatVersion record with version details }
+function XMLExpatVersionInfo: TXMLExpatVersion; cdecl;
+
+type
+ {+// Added in Expat 1.95.5. }
+ TXMLFeature = (
+ XML_FEATURE_END,
+ XML_FEATURE_UNICODE,
+ XML_FEATURE_UNICODE_WCHAR_T,
+ XML_FEATURE_DTD,
+ XML_FEATURE_CONTEXT_BYTES,
+ XML_FEATURE_MIN_SIZE,
+ XML_FEATURE_SIZEOF_XML_CHAR,
+ XML_FEATURE_SIZEOF_XML_LCHAR);
+ {+// Additional features must be added to the end of this enum. }
+
+ PXMLFeatureInfo = ^TXMLFeatureInfo;
+ TXMLFeatureInfo = packed record
+ Feature: TXMLFeature;
+ Name: PXMLLChar;
+ Value: Longint
+ end;
+
+ PXMLFeatureList = ^TXMLFeatureList;
+ TXMLFeatureList = packed array[0.. (MaxInt div SizeOf(TXMLFeatureInfo)) - 1]
+ of TXMLFeatureInfo;
+
+{+// Return a list feature macro descriptions }
+function XMLGetFeatureList: PXMLFeatureList; cdecl;
+
+{+// Frees the content model passed to the element declaration handler }
+procedure XMLFreeContentModel(Parser: TXMLParser; Model: PXMLContent); cdecl;
+
+{+// Exposing the memory handling functions used in Expat }
+function XMLMemMalloc(
+ Parser: TXMLParser;
+ Size: Longword): Pointer; cdecl;
+function XMLMemRealloc(
+ Parser: TXMLParser;
+ Ptr: Pointer;
+ Size: Longword): Pointer; cdecl;
+procedure XMLMemFree(
+ Parser: TXMLParser;
+ Ptr: Pointer); cdecl;
+
+
+implementation
+
+{ XML_GetUserData is defined as a macro in Expat:
+ #define XML_GetUserData(Parser) (*(void **)(Parser))
+ So we can't call an API function, but we can duplicate what it does }
+type
+ PPointer = ^Pointer;
+
+function XMLGetUserData(Parser: TXMLParser): Pointer;
+ begin
+ Result := PPointer(Parser)^;
+ end;
+
+procedure XMLDefaultCurrent;
+ external EXPATLIB name 'XML_DefaultCurrent';
+function XML_ErrorString;
+ external EXPATLIB name 'XML_ErrorString';
+function XMLExpatVersion;
+ external EXPATLIB name 'XML_ExpatVersion';
+function XMLExpatVersionInfo;
+ external EXPATLIB name 'XML_ExpatVersionInfo';
+function XMLExternalEntityParserCreate;
+ external EXPATLIB name 'XML_ExternalEntityParserCreate';
+function XMLGetBase;
+ external EXPATLIB name 'XML_GetBase';
+function XMLGetBuffer;
+ external EXPATLIB name 'XML_GetBuffer';
+function XMLGetCurrentByteCount;
+ external EXPATLIB name 'XML_GetCurrentByteCount';
+function XMLGetCurrentByteIndex;
+ external EXPATLIB name 'XML_GetCurrentByteIndex';
+function XMLGetCurrentColumnNumber;
+ external EXPATLIB name 'XML_GetCurrentColumnNumber';
+function XML_GetCurrentLineNumber;
+ external EXPATLIB name 'XML_GetCurrentLineNumber';
+function XML_GetErrorCode;
+ external EXPATLIB name 'XML_GetErrorCode';
+function XMLGetIdAttributeIndex;
+ external EXPATLIB name 'XML_GetIdAttributeIndex';
+function XMLGetInputContext;
+ external EXPATLIB name 'XML_GetInputContext';
+function XMLGetSpecifiedAttributeCount;
+ external EXPATLIB name 'XML_GetSpecifiedAttributeCount';
+function XML_Parse;
+ external EXPATLIB name 'XML_Parse';
+function XMLParseBuffer;
+ external EXPATLIB name 'XML_ParseBuffer';
+function XML_ParserCreate;
+ external EXPATLIB name 'XML_ParserCreate';
+function XMLParserCreateNS;
+ external EXPATLIB name 'XML_ParserCreateNS';
+function XMLParserCreateMM;
+ external EXPATLIB name 'XML_ParserCreate_MM';
+procedure XML_ParserFree;
+ external EXPATLIB name 'XML_ParserFree';
+procedure XMLSetAttlistDeclHandler;
+ external EXPATLIB name 'XML_SetAttlistDeclHandler';
+function XMLSetBase;
+ external EXPATLIB name 'XML_SetBase';
+procedure XMLSetCdataSectionHandler;
+ external EXPATLIB name 'XML_SetCdataSectionHandler';
+procedure XML_SetCharacterDataHandler;
+ external EXPATLIB name 'XML_SetCharacterDataHandler';
+procedure XMLSetCommentHandler;
+ external EXPATLIB name 'XML_SetCommentHandler';
+procedure XMLSetDefaultHandler;
+ external EXPATLIB name 'XML_SetDefaultHandler';
+procedure XMLSetDefaultHandlerExpand;
+ external EXPATLIB name 'XML_SetDefaultHandlerExpand';
+procedure XMLSetDoctypeDeclHandler;
+ external EXPATLIB name 'XML_SetDoctypeDeclHandler';
+procedure XMLSetElementDeclHandler;
+ external EXPATLIB name 'XML_SetElementDeclHandler';
+procedure XML_SetElementHandler;
+ external EXPATLIB name 'XML_SetElementHandler';
+function XMLSetEncoding;
+ external EXPATLIB name 'XML_SetEncoding';
+procedure XMLSetEndCdataSectionHandler;
+ external EXPATLIB name 'XML_SetEndCdataSectionHandler';
+procedure XMLSetEndDoctypeDeclHandler;
+ external EXPATLIB name 'XML_SetEndDoctypeDeclHandler';
+procedure XMLSetEndElementHandler;
+ external EXPATLIB name 'XML_SetEndElementHandler';
+procedure XMLSetEndNamespaceDeclHandler;
+ external EXPATLIB name 'XML_SetEndNamespaceDeclHandler';
+procedure XMLSetEntityDeclHandler;
+ external EXPATLIB name 'XML_SetEntityDeclHandler';
+procedure XMLSetExternalEntityRefHandler;
+ external EXPATLIB name 'XML_SetExternalEntityRefHandler';
+procedure XMLSetExternalEntityRefHandlerArg;
+ external EXPATLIB name 'XML_SetExternalEntityRefHandlerArg';
+procedure XMLSetNamespaceDeclHandler;
+ external EXPATLIB name 'XML_SetNamespaceDeclHandler';
+procedure XMLSetNotStandaloneHandler;
+ external EXPATLIB name 'XML_SetNotStandaloneHandler';
+procedure XMLSetNotationDeclHandler;
+ external EXPATLIB name 'XML_SetNotationDeclHandler';
+function XMLSetParamEntityParsing;
+ external EXPATLIB name 'XML_SetParamEntityParsing';
+procedure XMLSetProcessingInstructionHandler;
+ external EXPATLIB name 'XML_SetProcessingInstructionHandler';
+procedure XMLSetReturnNSTriplet;
+ external EXPATLIB name 'XML_SetReturnNSTriplet';
+procedure XMLSetStartCdataSectionHandler;
+ external EXPATLIB name 'XML_SetStartCdataSectionHandler';
+procedure XMLSetStartDoctypeDeclHandler;
+ external EXPATLIB name 'XML_SetStartDoctypeDeclHandler';
+procedure XMLSetStartElementHandler;
+ external EXPATLIB name 'XML_SetStartElementHandler';
+procedure XMLSetStartNamespaceDeclHandler;
+ external EXPATLIB name 'XML_SetStartNamespaceDeclHandler';
+procedure XMLSetUnknownEncodingHandler;
+ external EXPATLIB name 'XML_SetUnknownEncodingHandler';
+procedure XMLSetUnparsedEntityDeclHandler;
+ external EXPATLIB name 'XML_SetUnparsedEntityDeclHandler';
+procedure XML_SetUserData;
+ external EXPATLIB name 'XML_SetUserData';
+procedure XMLSetXmlDeclHandler;
+ external EXPATLIB name 'XML_SetXmlDeclHandler';
+procedure XMLUseParserAsHandlerArg;
+ external EXPATLIB name 'XML_UseParserAsHandlerArg';
+// added with version 1.95.3
+(*function XMLParserReset;
+ external EXPATLIB name 'XML_ParserReset';*){milano}
+procedure XMLSetSkippedEntityHandler;
+ external EXPATLIB name 'XML_SetSkippedEntityHandler';
+// added with version 1.95.5
+function XMLGetFeatureList;
+ external EXPATLIB name 'XML_GetFeatureList';
+procedure XMLUseForeignDTD;
+ external EXPATLIB name 'XML_UseForeignDTD';
+// added with version 1.95.6
+procedure XMLFreeContentModel;
+ external EXPATLIB name 'XML_FreeContentModel';
+function XMLMemMalloc;
+ external EXPATLIB name 'XML_MemMalloc';
+function XMLMemRealloc;
+ external EXPATLIB name 'XML_MemRealloc';
+procedure XMLMemFree;
+ external EXPATLIB name 'XML_MemFree';
+
+
+end.
diff --git a/src/corelib/render/software/agg-demos/expat-wrap/linux/ReadMe_Linux.txt b/src/corelib/render/software/agg-demos/expat-wrap/linux/ReadMe_Linux.txt
new file mode 100755
index 00000000..6524b3af
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/expat-wrap/linux/ReadMe_Linux.txt
@@ -0,0 +1,33 @@
+ How to build Expat under Linux
+ (tested on RedHat 7.3)
+
+1) After having extracted expat-1.95.6.tar to the expat directory,
+ or checked the 1.95.6 release out of the CVS repository, run
+ the configure script "./buildconf.sh" from the build directory.
+ This will need autoconf 2.52 or later and libtool 1.4 installed,
+ which are not part of the standard installation of RedHat 7.3!
+
+2a) Build for UTF8 output:
+ From the build directory) run "./configure", followed by "make",
+ then change to root (su root) and run "make install".
+
+2b) Build for UTF16 output:
+ - maybe run "make clean" first
+ - for 16 bit wchar_t output (incl. version and message strings),
+ run
+ ./configure CFLAGS="-g -O2 -fshort-wchar" CPPFLAGS=-DXML_UNICODE_WCHAR_T
+ or for unsigned short output (but version and message strings as 8bit chars),
+ run
+ ./configure CPPFLAGS=-DXML_UNICODE
+ - Then edit the MakeFile: change "LIBRARY = libexpat.la" to
+ "LIBRARY = libexpatw.la"
+ - Finally, run "make buildlib" and "make installlib"
+ (the latter with root privileges)
+
+Notes:
+ - The libraries are installed as: "libexpat.so" (UTF8) and "libexpatw.so" (UTF16),
+ which are usually symlinks pointing to the active version of Expat, which
+ in this case would be "libexpat.so.0.4.0" and "libexpatw.so.0.4.0".
+ - don't forget to run /sbin/ldconfig to configure the dynamic linker
+ - one can combine two of the steps by running "make buildlib LIBRARY=libexpatw.la"
+
diff --git a/src/corelib/render/software/agg-demos/expat-wrap/linux/libexpat.la b/src/corelib/render/software/agg-demos/expat-wrap/linux/libexpat.la
new file mode 100755
index 00000000..10e0c353
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/expat-wrap/linux/libexpat.la
@@ -0,0 +1,32 @@
+# libexpat.la - a libtool library file
+# Generated by ltmain.sh - GNU libtool 1.4.2 (1.922.2.54 2001/09/11 03:33:37)
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# The name that we can dlopen(3).
+dlname='libexpat.so.0'
+
+# Names of this library.
+library_names='libexpat.so.0.4.0 libexpat.so.0 libexpat.so'
+
+# The name of the static archive.
+old_library='libexpat.a'
+
+# Libraries that this one depends upon.
+dependency_libs=''
+
+# Version information for libexpat.
+current=4
+age=4
+revision=0
+
+# Is this an already installed library?
+installed=yes
+
+# Files to dlopen/dlpreopen
+dlopen=''
+dlpreopen=''
+
+# Directory that this library needs to be installed in:
+libdir='/usr/local/lib'
diff --git a/src/corelib/render/software/agg-demos/expat-wrap/linux/libexpat.so.0.4.0 b/src/corelib/render/software/agg-demos/expat-wrap/linux/libexpat.so.0.4.0
new file mode 100755
index 00000000..b150c37a
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/expat-wrap/linux/libexpat.so.0.4.0
Binary files differ
diff --git a/src/corelib/render/software/agg-demos/expat-wrap/linux/libexpatw.la b/src/corelib/render/software/agg-demos/expat-wrap/linux/libexpatw.la
new file mode 100755
index 00000000..6b98d48f
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/expat-wrap/linux/libexpatw.la
@@ -0,0 +1,32 @@
+# libexpatw.la - a libtool library file
+# Generated by ltmain.sh - GNU libtool 1.4.2 (1.922.2.54 2001/09/11 03:33:37)
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# The name that we can dlopen(3).
+dlname='libexpatw.so.0'
+
+# Names of this library.
+library_names='libexpatw.so.0.4.0 libexpatw.so.0 libexpatw.so'
+
+# The name of the static archive.
+old_library='libexpatw.a'
+
+# Libraries that this one depends upon.
+dependency_libs=''
+
+# Version information for libexpatw.
+current=4
+age=4
+revision=0
+
+# Is this an already installed library?
+installed=yes
+
+# Files to dlopen/dlpreopen
+dlopen=''
+dlpreopen=''
+
+# Directory that this library needs to be installed in:
+libdir='/usr/local/lib'
diff --git a/src/corelib/render/software/agg-demos/expat-wrap/linux/libexpatw.so.0.4.0 b/src/corelib/render/software/agg-demos/expat-wrap/linux/libexpatw.so.0.4.0
new file mode 100755
index 00000000..5d828ed9
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/expat-wrap/linux/libexpatw.so.0.4.0
Binary files differ
diff --git a/src/corelib/render/software/agg-demos/find_compilers_linux.dpr b/src/corelib/render/software/agg-demos/find_compilers_linux.dpr
new file mode 100644
index 00000000..5411146b
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/find_compilers_linux.dpr
@@ -0,0 +1,489 @@
+{target:linux}
+{linux_console_app}
+//
+// AggPas 2.4 RM3 Helper utility application
+// Milan Marusinec alias Milano (c) 2006 - 2008
+//
+program
+ find_compilers_linux ;
+
+uses
+ SysUtils ,
+ agg_basics ,
+ file_utils_ ,
+ libc ;
+
+{$I agg_mode.inc }
+{$- }
+type
+ src_key = record
+ key ,
+ val : string[99 ];
+
+ end;
+
+const
+ key_max = 99;
+ pool_max = 65536;
+ make_max = 99;
+
+ fpc_comp = 'ppc386';
+ fpc_libs = '-Fu"src;src/ctrl;src/platform/linux;src/util;src/svg;expat-wrap"';
+ fpc_incl = '-Fisrc';
+ fpc_outd = '-FU_debug';
+ fpc_conf = '-Mdelphi -Tlinux -Sg -Se3 -XX -Xs -B -v0i';
+ fpc_gapp = '-WG';
+ fpc_capp = '-WC';
+
+var
+ key_array : array[0..key_max - 1 ] of src_key;
+ key_count ,
+ key_lastx : unsigned;
+ key_scanx : shortstring;
+
+ pool_buff : pointer;
+ pool_aloc ,
+ pool_size : unsigned;
+
+ make_array : array[0..make_max - 1 ] of string[99 ];
+ make_count : unsigned;
+
+{ WRPOOL }
+procedure WrPool(str : shortstring; crlf : boolean = false );
+begin
+ if crlf then
+ str:=str + #10;
+
+ if pool_size + length(str ) < pool_aloc then
+ begin
+ System.move(
+ str[1 ] ,
+ pointer(ptrcomp(pool_buff ) + pool_size )^ ,
+ length(str ) );
+
+ inc(pool_size ,length(str ) );
+
+ end;
+
+end;
+
+{ WRFILE }
+function WrFile(fname : shortstring ) : boolean;
+var
+ df : file;
+ wr : int;
+
+begin
+ result:=false;
+
+ AssignFile(df ,fname );
+ rewrite (df ,1 );
+
+ if IOResult = 0 then
+ begin
+ blockwrite(df ,pool_buff^ ,pool_size ,wr );
+ close (df );
+
+ fname:=fname + #0;
+
+ libc.chmod(
+ PChar(@fname[1 ] ) ,
+ S_IRWXU or S_IRWXG or S_IROTH or S_IWOTH );
+
+ if pool_size = wr then
+ result:=true;
+
+ end;
+
+end;
+
+{ NEXTKEY }
+function NextKey(var val : shortstring ) : boolean;
+begin
+ result:=false;
+
+ while key_lastx < key_count do
+ begin
+ inc(key_lastx );
+
+ if cmp_str(key_array[key_lastx - 1 ].key ) = key_scanx then
+ begin
+ val :=key_array[key_lastx - 1 ].val;
+ result:=true;
+
+ break;
+
+ end;
+
+ end;
+
+end;
+
+{ FIRSTKEY }
+function FirstKey(key : shortstring; var val : shortstring ) : boolean;
+begin
+ key_lastx:=0;
+ key_scanx:=cmp_str(key );
+
+ result:=NextKey(val );
+
+end;
+
+{ LOADKEYS }
+procedure LoadKeys(buff : char_ptr; size : int );
+type
+ e_scan = (expect_lp ,load_key ,load_val ,next_ln ,expect_crlf );
+
+var
+ scan : e_scan;
+ key ,
+ val : shortstring;
+
+procedure add_key;
+begin
+ if key_count < key_max then
+ begin
+ key_array[key_count ].key:=key;
+ key_array[key_count ].val:=val;
+
+ inc(key_count );
+
+ end;
+
+ key:='';
+ val:='';
+
+end;
+
+begin
+ key_count:=0;
+
+ scan:=expect_lp;
+ key :='';
+ val :='';
+
+ while size > 0 do
+ begin
+ case scan of
+ expect_lp :
+ case buff^ of
+ '{' :
+ scan:=load_key;
+
+ else
+ break;
+
+ end;
+
+ load_key :
+ case buff^ of
+ #13 ,#10 :
+ break;
+
+ ':' :
+ scan:=load_val;
+
+ '}' :
+ begin
+ add_key;
+
+ scan:=next_ln;
+
+ end;
+
+ else
+ key:=key + buff^;
+
+ end;
+
+ load_val :
+ case buff^ of
+ #13 ,#10 :
+ break;
+
+ '}' :
+ begin
+ add_key;
+
+ scan:=next_ln;
+
+ end;
+
+ else
+ val:=val + buff^;
+
+ end;
+
+ next_ln :
+ case buff^ of
+ #13 ,#10 :
+ scan:=expect_crlf;
+
+ ' ' :
+ else
+ break;
+
+ end;
+
+ expect_crlf :
+ case buff^ of
+ '{' :
+ scan:=load_key;
+
+ #13 ,#10 :
+ else
+ break;
+
+ end;
+
+ end;
+
+ dec(size );
+ inc(ptrcomp(buff ) );
+
+ end;
+
+end;
+
+{ WRITECOMPILESCRIPT }
+function WriteCompileScript(name ,ext : shortstring ) : boolean;
+var
+ cp : shortstring;
+
+begin
+ result:=false;
+
+// Create the script in memory
+ pool_size:=0;
+
+ WrPool(fpc_comp + ' ' );
+ WrPool(fpc_libs + ' ' );
+ WrPool(fpc_incl + ' ' );
+ WrPool(fpc_outd + ' ' );
+ WrPool(fpc_conf + ' ' );
+
+ if FirstKey('linux_console_app' ,cp ) then
+ WrPool(fpc_capp + ' ' )
+ else
+ WrPool(fpc_gapp + ' ' );
+
+ WrPool(name + ext ,true );
+
+
+// WriteFile
+ name:='compile-' + name;
+
+ if WrFile(name ) then
+ begin
+ if make_count < make_max then
+ begin
+ make_array[make_count ]:=name;
+
+ inc(make_count );
+
+ end;
+
+ result:=true;
+
+ end;
+
+end;
+
+{ CREATECOMPILESCRIPT }
+procedure CreateCompileScript(name ,ext : shortstring );
+var
+ loaded : boolean;
+
+ target ,value : shortstring;
+
+ lf : file;
+ fs ,
+ ls : int;
+ bf : pointer;
+
+begin
+ write(' ' ,name ,ext ,' ... ' );
+
+// Open Source .DPR file
+ AssignFile(lf ,name + ext );
+ reset (lf ,1 );
+
+ if IOResult = 0 then
+ begin
+ loaded:=false;
+
+ // Load DPR keys
+ fs:=filesize(lf );
+
+ if (fs > 0 ) and
+ agg_getmem(bf ,fs ) then
+ begin
+ blockread(lf ,bf^ ,fs ,ls );
+
+ if fs = ls then
+ begin
+ loaded:=true;
+
+ LoadKeys(bf ,fs );
+
+ end;
+
+ agg_freemem(bf ,fs );
+
+ end;
+
+ // Close DPR
+ close(lf );
+
+ // Create compilation script
+ if loaded then
+ begin
+ if FirstKey('skip' ,value ) then
+ writeln('to be not included -> skipped' )
+ else
+ begin
+ target:='linux';
+
+ FirstKey('target' ,target );
+
+ if cmp_str(target ) = cmp_str('linux' ) then
+ if WriteCompileScript(name ,ext ) then
+ writeln('OK' )
+ else
+ writeln('Failed to generate compile script !' )
+ else
+ writeln('different target (' ,target ,') -> skipped' );
+
+ end;
+
+ end
+ else
+ writeln('Failed to read the source file !' );
+
+ end
+ else
+ writeln('Failed to open !' );
+
+end;
+
+{ PROCESSOBJECT }
+procedure ProcessObject(found : shortstring );
+var
+ file_path ,file_name ,file_ext : shortstring;
+
+begin
+ spread_name(found ,file_path ,file_name ,file_ext );
+
+ if cmp_str(file_ext ) = cmp_str('.dpr' ) then
+ CreateCompileScript(file_name ,file_ext );
+
+end;
+
+{ ITERATEFOLDER }
+procedure IterateFolder(inFolder : shortstring );
+var
+ dp : libc.PDIR;
+ ep : libc.Pdirent;
+
+begin
+ inFolder:=inFolder + #0;
+
+ dp:=libc.opendir(PChar(@inFolder[1 ] ) );
+
+ if dp <> NIL then
+ begin
+ repeat
+ ep:=libc.readdir(dp );
+
+ if ep <> NIL then
+ ProcessObject(strpas(ep.d_name ) );
+
+ until ep = NIL;
+
+ libc.closedir(dp );
+
+ end;
+
+end;
+
+{ CREATEMAKEFILE }
+procedure CreateMakeFile;
+var
+ i : unsigned;
+
+begin
+ pool_size:=0;
+
+ i:=0;
+
+ while i < make_count do
+ begin
+ WrPool('./' + make_array[i ] ,true );
+
+ inc(i );
+
+ end;
+
+ WrFile('compile_make_all' );
+
+end;
+
+{ SCANDEMOS }
+procedure ScanDemos;
+begin
+ IterateFolder('./' );
+ writeln;
+
+ if make_count > 0 then
+ begin
+ CreateMakeFile;
+
+ writeln('SUCCESS: FPC compilation script files were created' );
+ writeln(' for the AggPas demos listed above.' );
+ writeln;
+ writeln(' To compile the demos, run Terminal, change to the current' );
+ writeln(' directory and type "./compile_make_all"' );
+ writeln(' or "./compile-xxx", where "xxx" is the name of the demo.' );
+
+ end
+ else
+ writeln('MESSAGE: No AggPas demo files were found in current folder !' );
+
+ writeln;
+
+end;
+
+BEGIN
+ writeln;
+ writeln('*************************************************************' );
+ writeln('* Welcome to the AggPas 2.4 RM3 vector graphics library. *' );
+ writeln('*************************************************************' );
+ writeln('* *' );
+ writeln('* This helper utility will generate the compilation script *' );
+ writeln('* files with current paths and options needed to compile *' );
+ writeln('* properly all the AggPas demos on your Linux station. *' );
+ writeln('* *' );
+ writeln('* Currently the Free Pascal compiler is supported. *' );
+ writeln('* (www.freepascal.org) *' );
+ writeln('* *' );
+ writeln('*************************************************************' );
+ writeln;
+ writeln('[Press ENTER key to continue ...]' );
+ writeln;
+ readln;
+
+ if agg_getmem(pool_buff ,pool_max ) then
+ begin
+ pool_aloc :=pool_max;
+ pool_size :=0;
+ make_count:=0;
+
+ ScanDemos;
+
+ agg_freemem(pool_buff ,pool_aloc );
+
+ end
+ else
+ writeln('ERROR: Not enough memory for the pool buffer !' );
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/find_compilers_mac.dpr b/src/corelib/render/software/agg-demos/find_compilers_mac.dpr
new file mode 100644
index 00000000..706af2f7
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/find_compilers_mac.dpr
@@ -0,0 +1,662 @@
+{target:mac}
+{mac_console_app}
+//
+// AggPas 2.4 RM3 Helper utility application
+// Milan Marusinec alias Milano (c) 2006 - 2008
+//
+program
+ find_compilers_mac ;
+
+uses
+ SysUtils ,
+ agg_basics ,
+ file_utils_ ,
+ Carbon ;
+
+{$I agg_mode.inc }
+
+type
+ src_key = record
+ key ,
+ val : string[99 ];
+
+ end;
+
+const
+ key_max = 99;
+ pool_max = 65536;
+ make_max = 99;
+
+ fpc_comp = '/usr/local/bin/ppcppc';
+ fpc_libs = '-Fu"src;src/ctrl;src/platform/mac;src/util;src/svg;upi;expat-wrap"';
+ fpc_incl = '-Fisrc';
+ fpc_outd = '-FU_debug';
+ fpc_frmw = '-k"-framework Carbon -framework QuickTime"';
+ fpc_conf = '-Mdelphi -Tdarwin -Sg -Se3 -XX -Xs -B -v0i';
+ fpc_capp = '-WC';
+ fpc_gapp = '-WG';
+
+var
+ key_array : array[0..key_max - 1 ] of src_key;
+ key_count ,
+ key_lastx : unsigned;
+ key_scanx : shortstring;
+
+ pool_buff : pointer;
+ pool_aloc ,
+ pool_size : unsigned;
+
+ make_array : array[0..make_max - 1 ] of string[99 ];
+ make_count : unsigned;
+
+{ WRPOOL }
+procedure WrPool(str : shortstring; crlf : boolean = false );
+begin
+ if crlf then
+ str:=str + #10;
+
+ if pool_size + length(str ) < pool_aloc then
+ begin
+ System.move(
+ str[1 ] ,
+ pointer(ptrcomp(pool_buff ) + pool_size )^ ,
+ length(str ) );
+
+ inc(pool_size ,length(str ) );
+
+ end;
+
+end;
+
+{ WRFILE }
+function WrFile(destDir : FSRefPtr; name : shortstring ) : boolean;
+var
+ i : unsigned;
+
+ ossState : OSStatus;
+ ossError : OSErr;
+ forkName ,
+ destName : HFSUniStr255;
+ dstFSRef : FSRef;
+ forkRef : SInt16;
+ written : ByteCount;
+ catInfo : FSCatalogInfo;
+
+begin
+ result:=false;
+
+// Fill in Unicode name
+ for i:=1 to length(name ) do
+ destName.unicode[i - 1 ]:=byte(name[i ] );
+
+ destName.length:=length(name );
+
+// Write the script to file
+ ossError:=FSCreateFileUnicode(destDir^ ,destName.length ,destName.unicode[0 ] ,kFSCatInfoNone ,NIL ,@dstFSRef ,NIL );
+
+ if ossError = noErr then
+ begin
+ FSGetDataForkName(forkName );
+
+ ossError:=FSOpenFork(dstFSRef ,forkName.length ,forkName.unicode[0 ] ,fsWrPerm ,forkRef );
+
+ if ossError = noErr then
+ begin
+ ossError:=FSWriteFork(forkRef ,fsFromStart + noCacheBit ,0 ,pool_size ,pool_buff ,written );
+
+ FSCloseFork(forkRef );
+
+ if (ossError = noErr ) and
+ (pool_size = written ) then
+
+ else
+ exit;
+
+ end
+ else
+ begin write('[FSOpenFork:' ,ossError ,'] ' ); exit; end;
+
+ end
+ else
+ if ossError = dupFNErr then
+ else
+ begin write('[FSCreateFileUnicode:' ,ossError ,'] ' ); exit; end;
+
+// Set The File permissions
+ CatInfo.permissions[0 ]:=0;
+ CatInfo.permissions[1 ]:=0;
+ CatInfo.permissions[2 ]:=0;
+ CatInfo.permissions[3 ]:=0;
+
+ FSPermissionInfoPtr(@CatInfo.permissions ).mode:=999;
+
+ ossError:=FSSetCatalogInfo(dstFSRef ,kFSCatInfoPermissions ,CatInfo );
+
+// OK
+ result:=true;
+
+end;
+
+{ NEXTKEY }
+function NextKey(var val : shortstring ) : boolean;
+begin
+ result:=false;
+
+ while key_lastx < key_count do
+ begin
+ inc(key_lastx );
+
+ if cmp_str(key_array[key_lastx - 1 ].key ) = key_scanx then
+ begin
+ val :=key_array[key_lastx - 1 ].val;
+ result:=true;
+
+ break;
+
+ end;
+
+ end;
+
+end;
+
+{ FIRSTKEY }
+function FirstKey(key : shortstring; var val : shortstring ) : boolean;
+begin
+ key_lastx:=0;
+ key_scanx:=cmp_str(key );
+
+ result:=NextKey(val );
+
+end;
+
+{ LOADKEYS }
+procedure LoadKeys(buff : char_ptr; size : SInt64 );
+type
+ e_scan = (expect_lp ,load_key ,load_val ,next_ln ,expect_crlf );
+
+var
+ scan : e_scan;
+ key ,
+ val : shortstring;
+
+procedure add_key;
+begin
+ if key_count < key_max then
+ begin
+ key_array[key_count ].key:=key;
+ key_array[key_count ].val:=val;
+
+ inc(key_count );
+
+ end;
+
+ key:='';
+ val:='';
+
+end;
+
+begin
+ key_count:=0;
+
+ scan:=expect_lp;
+ key :='';
+ val :='';
+
+ while size > 0 do
+ begin
+ case scan of
+ expect_lp :
+ case buff^ of
+ '{' :
+ scan:=load_key;
+
+ else
+ break;
+
+ end;
+
+ load_key :
+ case buff^ of
+ #13 ,#10 :
+ break;
+
+ ':' :
+ scan:=load_val;
+
+ '}' :
+ begin
+ add_key;
+
+ scan:=next_ln;
+
+ end;
+
+ else
+ key:=key + buff^;
+
+ end;
+
+ load_val :
+ case buff^ of
+ #13 ,#10 :
+ break;
+
+ '}' :
+ begin
+ add_key;
+
+ scan:=next_ln;
+
+ end;
+
+ else
+ val:=val + buff^;
+
+ end;
+
+ next_ln :
+ case buff^ of
+ #13 ,#10 :
+ scan:=expect_crlf;
+
+ ' ' :
+ else
+ break;
+
+ end;
+
+ expect_crlf :
+ case buff^ of
+ '{' :
+ scan:=load_key;
+
+ #13 ,#10 :
+ else
+ break;
+
+ end;
+
+ end;
+
+ dec(size );
+ inc(ptrcomp(buff ) );
+
+ end;
+
+end;
+
+{ WRITECOMPILESCRIPT }
+function WriteCompileScript(destDir : FSRefPtr; name ,ext : shortstring ) : boolean;
+var
+ cp ,fp ,fn ,fx : shortstring;
+
+begin
+ result:=false;
+
+// Create the script in memory
+ pool_size:=0;
+
+ WrPool(fpc_comp + ' ' );
+ WrPool(fpc_libs + ' ' );
+ WrPool(fpc_incl + ' ' );
+ WrPool(fpc_outd + ' ' );
+ WrPool(fpc_frmw + ' ' );
+ WrPool(fpc_conf + ' ' );
+
+ if FirstKey('mac_console_app' ,cp ) then
+ WrPool(fpc_capp + ' ' )
+ else
+ WrPool(fpc_gapp + ' ' );
+
+ WrPool(name + ext ,true );
+
+ if not FirstKey('mac_console_app' ,cp ) then
+ begin
+ WrPool('mkdir -p ' + name + '.app/Contents/MacOS' ,true );
+ WrPool('mv -f ' + name + ' ' + name + '.app/Contents/MacOS/' + name ,true );
+
+ end;
+
+ if FirstKey('mac_copy' ,cp ) then
+ repeat
+ spread_name(cp ,fp ,fn ,fx );
+
+ if cmp_str(fx ) = cmp_str('.bmp' ) then
+ WrPool('cp -f bmp/' + cp + ' ' + name + '.app/Contents/MacOS/' + cp ,true )
+ else
+ if cmp_str(fx ) = cmp_str('.svg' ) then
+ WrPool('cp -f svg/' + cp + ' ' + name + '.app/Contents/MacOS/' + cp ,true );
+
+ until not NextKey(cp );
+
+// WriteFile
+ name:='compile-' + name;
+
+ if WrFile(destDir ,name ) then
+ begin
+ if make_count < make_max then
+ begin
+ make_array[make_count ]:=name;
+
+ inc(make_count );
+
+ end;
+
+ result:=true;
+
+ end;
+
+end;
+
+{ CREATECOMPILESCRIPT }
+procedure CreateCompileScript(destDir : FSRefPtr; name ,ext : shortstring; inRef : FSRefPtr );
+var
+ loaded : boolean;
+
+ ossError : OSStatus;
+ forkName : HFSUniStr255;
+ forkSize : SInt64;
+ forkRef : SInt16;
+ forkBuff : pointer;
+ forkLoad : ByteCount;
+
+ target ,value : shortstring;
+
+begin
+ write(' ' ,name ,ext ,' ... ' );
+
+// Open Source .DPR file
+ FSGetDataForkName(forkName );
+
+ ossError:=FSOpenFork(inRef^ ,forkName.length ,forkName.unicode[0 ] ,fsRdPerm ,forkRef );
+
+ if ossError = noErr then
+ begin
+ loaded:=false;
+
+ // Load DPR keys
+ FSGetForkSize(forkRef ,forkSize );
+
+ if (forkSize > 0 ) and
+ agg_getmem(forkBuff ,forkSize ) then
+ begin
+ ossError:=FSReadFork(forkRef ,fsAtMark + noCacheMask ,0 ,forkSize ,forkBuff ,forkLoad );
+
+ if (ossError = noErr ) and
+ (forkSize = forkLoad ) then
+ begin
+ loaded:=true;
+
+ LoadKeys(forkBuff ,forkSize );
+
+ end;
+
+ agg_freemem(forkBuff ,forkSize );
+
+ end;
+
+ // Close DPR
+ FSCloseFork(forkRef );
+
+ // Create compilation script
+ if loaded then
+ begin
+ if FirstKey('skip' ,value ) then
+ writeln('to be not included -> skipped' )
+ else
+ begin
+ target:='mac';
+
+ FirstKey('target' ,target );
+
+ if cmp_str(target ) = cmp_str('mac' ) then
+ if WriteCompileScript(destDir ,name ,ext ) then
+ writeln('OK' )
+ else
+ writeln('Failed to generate compile script !' )
+ else
+ writeln('different target (' ,target ,') -> skipped' );
+
+ end;
+
+ end
+ else
+ writeln('Failed to read the source file !' );
+
+ end
+ else
+ writeln('Failed to open !' );
+
+end;
+
+{ PROCESSOBJECT }
+procedure ProcessObject(destDir : FSRefPtr; inCatInfo : FSCatalogInfoPtr; inRef : FSRefPtr; inSpec : FSSpecPtr );
+var
+ file_path ,file_name ,file_ext : shortstring;
+
+begin
+ if inCatInfo.nodeFlags and kFSNodeIsDirectoryMask = kFSNodeIsDirectoryMask then
+ else
+ begin
+ spread_name(inSpec.name ,file_path ,file_name ,file_ext );
+
+ if cmp_str(file_ext ) = cmp_str('.dpr' ) then
+ CreateCompileScript(destDir ,file_name ,file_ext ,inRef );
+
+ end;
+
+end;
+
+{ ITERATEFOLDER }
+function IterateFolder(var inFolder : FSRef ) : OSStatus;
+var
+ kRequestCountPerIteration : size_t;
+
+ outStatus : OSStatus;
+
+ kCatalogInfoBitmap : FSCatalogInfoBitmap;
+
+ iterator : FSIterator;
+
+ catalogInfoArray : FSCatalogInfoPtr;
+
+ FSRefArray : FSRefPtr;
+ FSSpecArray : FSSpecPtr;
+
+ actualCount : ItemCount;
+
+ index : UInt32;
+
+ changed : boolean;
+
+begin
+ kRequestCountPerIteration:=((4096 * 4 ) div sizeof(FSCatalogInfo ) );
+
+// Get permissions and node flags and Finder info
+//
+// For maximum performance, specify in the catalog
+// bitmap only the information you need to know
+ kCatalogInfoBitmap:=kFSCatInfoNodeFlags or kFSCatInfoFinderInfo;
+
+// On each iteration of the do-while loop, retrieve this
+// number of catalog infos
+//
+// We use the number of FSCatalogInfos that will fit in
+// exactly four VM pages (#113). This is a good balance
+// between the iteration I/O overhead and the risk of
+// incurring additional I/O from additional memory
+// allocation
+
+// Create an iterator
+ outStatus:=FSOpenIterator(inFolder ,kFSIterateFlat ,iterator );
+
+ if outStatus = noErr then
+ begin
+ // Allocate storage for the returned information
+ agg_getmem(pointer(catalogInfoArray ) ,sizeof(FSCatalogInfo ) * kRequestCountPerIteration );
+ agg_getmem(pointer(FSRefArray ) ,sizeof(FSRef ) * kRequestCountPerIteration );
+ agg_getmem(pointer(FSSpecArray ) ,sizeof(FSSpec ) * kRequestCountPerIteration );
+
+ if catalogInfoArray = NIL then
+ outStatus:=memFullErr
+
+ else
+ begin
+ // Request information about files in the given directory,
+ // until we get a status code back from the File Manager
+ repeat
+ changed:=false;
+
+ outStatus:=
+ FSGetCatalogInfoBulk(
+ iterator ,
+ kRequestCountPerIteration ,
+ actualCount ,
+ changed ,
+ kCatalogInfoBitmap ,
+ catalogInfoArray ,
+ FSRefArray ,
+ FSSpecArray ,
+ NIL );
+
+ // Process all items received
+ if (outStatus = noErr ) or
+ (outStatus = errFSNoMoreItems ) then
+ for index:=0 to actualCount - 1 do
+ ProcessObject(
+ @inFolder ,
+ FSCatalogInfoPtr(
+ ptrcomp(catalogInfoArray ) +
+ index * sizeof(FSCatalogInfo ) ) ,
+ FSRefPtr(
+ ptrcomp(FSRefarray ) +
+ index * sizeof(FSRef ) ) ,
+ FSSpecPtr(
+ ptrcomp(FSSpecArray ) +
+ index * sizeof(FSSpec ) ) );
+
+ until outStatus <> noErr;
+
+ // errFSNoMoreItems tells us we have successfully processed all
+ // items in the directory -- not really an error
+ if outStatus = errFSNoMoreItems then
+ outStatus:=noErr;
+
+ // Free the array memory
+ agg_freemem(pointer(catalogInfoArray ) ,sizeof(FSCatalogInfo ) * kRequestCountPerIteration );
+ agg_freemem(pointer(FSRefArray ) ,sizeof(FSRef ) * kRequestCountPerIteration );
+ agg_freemem(pointer(FSSpecArray ) ,sizeof(FSSpec ) * kRequestCountPerIteration );
+
+ end;
+
+ end;
+
+ FSCloseIterator(iterator );
+
+ result:=outStatus;
+
+end;
+
+{ CREATEMAKEFILE }
+procedure CreateMakeFile(destDir : FSRefPtr );
+var
+ i : unsigned;
+
+begin
+ pool_size:=0;
+
+ i:=0;
+
+ while i < make_count do
+ begin
+ WrPool('./' + make_array[i ] ,true );
+
+ inc(i );
+
+ end;
+
+ WrFile(destDir ,'compile_make_all' );
+
+end;
+
+{ SCANDEMOS }
+procedure ScanDemos;
+var
+ outStatus : OSStatus;
+ folderRef : FSRef;
+ fileSpecs : FSSpec;
+
+begin
+ outStatus:=FSMakeFSSpec(0 ,0 ,'' ,fileSpecs );
+
+ if outStatus = noErr then
+ begin
+ outStatus:=FSpMakeFSRef(fileSpecs ,folderRef );
+
+ if outStatus = noErr then
+ begin
+ outStatus:=IterateFolder(folderRef );
+
+ writeln;
+
+ if make_count > 0 then
+ begin
+ CreateMakeFile(@folderRef );
+
+ writeln('SUCCESS: FPC compilation script files were created' );
+ writeln(' for the AggPas demos listed above.' );
+ writeln;
+ writeln(' To compile the demos, run Terminal, change to the current' );
+ writeln(' directory and type "./compile_make_all"' );
+ writeln(' or "./compile-xxx", where "xxx" is the name of the demo.' );
+
+ end
+ else
+ writeln('MESSAGE: No AggPas demo files were found in current folder !' );
+
+ end
+ else
+ writeln('ERROR: Failed to create FSRef structure for the current folder !' );
+
+ end
+ else
+ writeln('ERROR: Failed to search for files in the current folder !' );
+
+ writeln;
+
+end;
+
+BEGIN
+ writeln;
+ writeln('*************************************************************' );
+ writeln('* Welcome to the AggPas 2.4 RM3 vector graphics library. *' );
+ writeln('*************************************************************' );
+ writeln('* *' );
+ writeln('* This helper utility will generate the compilation script *' );
+ writeln('* files with current paths and options needed to compile *' );
+ writeln('* properly all the AggPas demos on your Mac. *' );
+ writeln('* *' );
+ writeln('* Currently the Free Pascal compiler is supported. *' );
+ writeln('* (www.freepascal.org) *' );
+ writeln('* *' );
+ writeln('*************************************************************' );
+ writeln;
+ writeln('[Press ENTER key to continue ...]' );
+ writeln;
+ readln;
+
+ if agg_getmem(pool_buff ,pool_max ) then
+ begin
+ pool_aloc :=pool_max;
+ pool_size :=0;
+ make_count:=0;
+
+ ScanDemos;
+
+ agg_freemem(pool_buff ,pool_aloc );
+
+ end
+ else
+ writeln('ERROR: Not enough memory for the pool buffer !' );
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/find_compilers_win.dpr b/src/corelib/render/software/agg-demos/find_compilers_win.dpr
new file mode 100644
index 00000000..6f4fec54
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/find_compilers_win.dpr
@@ -0,0 +1,1496 @@
+{target:win}
+//
+// AggPas 2.4 RM3 Demo application
+// Milan Marusinec alias Milano (c) 2006 - 2008
+// Note: Press F1 key on run to see more info about this demo
+//
+program
+ find_compilers_win ;
+
+uses
+ SysUtils ,Windows ,
+
+ agg_basics ,
+ agg_platform_support ,
+
+ agg_color ,
+ agg_pixfmt ,
+ agg_pixfmt_rgb ,
+
+ agg_ctrl ,
+ agg_cbox_ctrl ,
+ agg_rbox_ctrl ,
+
+ agg_rendering_buffer ,
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_rasterizer_scanline_aa ,
+ agg_scanline ,
+ agg_scanline_u ,
+ agg_render_scanlines ,
+
+ agg_gsv_text ,
+ agg_conv_stroke ,
+ file_utils_ ;
+
+{$I agg_mode.inc }
+{$I- }
+type
+ src_key = record
+ key ,
+ val : string[99 ];
+
+ end;
+
+const
+ flip_y = true;
+
+ g_appl = 'AggPas';
+ g_full = 'AggPas 2.4 RM3 vector graphics library';
+
+ g_agg_paths = 'src;src\ctrl;src\platform\win;src\util;src\svg;gpc;expat-wrap';
+ g_inc_paths = 'src';
+ g_out_paths = '_debug';
+
+ g_delphi_config = '-CG -B -H- -W-';
+ g_fpc_config = '-Mdelphi -Twin32 -WG -Sg -Se3 -CX -XX -Xs -B -Op3 -v0i';
+
+ g_max = 20;
+ g_max_demos = 100;
+
+ key_max = 99;
+
+var
+ g_lock ,g_image : boolean;
+
+ g_found ,g_num_demos : unsigned;
+
+ g_search_results : array[0..g_max - 1 ] of shortstring;
+
+ g_demos : array[0..g_max_demos - 1 ] of string[99 ];
+
+ key_array : array[0..key_max - 1 ] of src_key;
+ key_count ,
+ key_lastx : unsigned;
+ key_scanx : shortstring;
+
+type
+ the_application_ptr = ^the_application;
+
+ dialog_ptr = ^dialog;
+
+ func_action = function(appl : the_application_ptr; sender : dialog_ptr ) : boolean;
+
+ user_action_ptr = ^user_action;
+ user_action = record
+ func : func_action;
+ ctrl : rbox_ctrl;
+
+ end;
+
+ user_choice = record
+ ctrl : cbox_ctrl;
+ attr : shortstring;
+
+ end;
+
+ dlg_status_e = (ds_none ,ds_define ,ds_ready ,ds_waiting_input ,ds_running );
+
+ dialog = object
+ m_appl : the_application_ptr;
+ m_info : PChar;
+ m_text : char_ptr;
+ m_tx_x ,
+ m_tx_y : double;
+ m_aloc ,
+ m_size : unsigned;
+ m_clri ,
+ m_clrt : aggclr;
+
+ m_status : dlg_status_e;
+
+ m_actions : array[0..4 ] of user_action;
+ m_choices : array[0..25 ] of user_choice;
+
+ m_num_actions ,
+ m_num_choices : unsigned;
+
+ m_cur_action : user_action_ptr;
+
+ m_waiting : func_action;
+
+ constructor Construct(appl : the_application_ptr; info : PChar; clr : aggclr_ptr = NIL );
+ destructor Destruct;
+
+ procedure set_waiting(act : func_action );
+
+ procedure add_action(name : PChar; act : func_action; x1 ,y1 ,x2 ,y2 : double );
+ procedure add_choice(name ,attr : PChar; x ,y : double; status : boolean = false );
+
+ procedure change_text(text : PChar; x ,y : double; clr : aggclr_ptr = NIL );
+ procedure append_text(text : PChar );
+
+ function add_controls : boolean;
+ procedure set_next_status(status : dlg_status_e = ds_none );
+
+ function find_cur_action : boolean;
+ function call_cur_action : boolean;
+ procedure call_waiting;
+
+ end;
+
+ the_application = object(platform_support )
+ m_dlg_welcome ,
+ m_dlg_set_drives ,
+ m_dlg_searching ,
+ m_dlg_not_found ,
+ m_dlg_found_some : dialog;
+
+ m_cur_dlg : dialog_ptr;
+
+ m_ras : rasterizer_scanline_aa;
+ m_sl : scanline_u8;
+
+ m_Thread : THandle;
+ m_ApplID : LongWord;
+ m_DoQuit : boolean;
+ m_ShLast ,
+ m_DoShow : shortstring;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure draw_text(x ,y : double; msg : PChar; clr : aggclr_ptr = NIL );
+
+ procedure on_init; virtual;
+ procedure on_draw; virtual;
+
+ procedure on_ctrl_change; virtual;
+ procedure on_idle; virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ NEXTKEY }
+function NextKey(var val : shortstring ) : boolean;
+begin
+ result:=false;
+
+ while key_lastx < key_count do
+ begin
+ inc(key_lastx );
+
+ if cmp_str(key_array[key_lastx - 1 ].key ) = key_scanx then
+ begin
+ val:=key_array[key_lastx - 1 ].val;
+
+ result:=true;
+
+ break;
+
+ end;
+
+ end;
+
+end;
+
+{ FIRSTKEY }
+function FirstKey(key : shortstring; var val : shortstring ) : boolean;
+begin
+ key_lastx:=0;
+ key_scanx:=cmp_str(key );
+
+ result:=NextKey(val );
+
+end;
+
+{ LOADKEYS }
+procedure LoadKeys(buff : char_ptr; size : int );
+type
+ e_scan = (expect_lp ,load_key ,load_val ,next_ln ,expect_crlf );
+
+var
+ scan : e_scan;
+ key ,
+ val : shortstring;
+
+procedure add_key;
+begin
+ if key_count < key_max then
+ begin
+ key_array[key_count ].key:=key;
+ key_array[key_count ].val:=val;
+
+ inc(key_count );
+
+ end;
+
+ key:='';
+ val:='';
+
+end;
+
+begin
+ key_count:=0;
+
+ scan:=expect_lp;
+ key :='';
+ val :='';
+
+ while size > 0 do
+ begin
+ case scan of
+ expect_lp :
+ case buff^ of
+ '{' :
+ scan:=load_key;
+
+ else
+ break;
+
+ end;
+
+ load_key :
+ case buff^ of
+ #13 ,#10 :
+ break;
+
+ ':' :
+ scan:=load_val;
+
+ '}' :
+ begin
+ add_key;
+
+ scan:=next_ln;
+
+ end;
+
+ else
+ key:=key + buff^;
+
+ end;
+
+ load_val :
+ case buff^ of
+ #13 ,#10 :
+ break;
+
+ '}' :
+ begin
+ add_key;
+
+ scan:=next_ln;
+
+ end;
+
+ else
+ val:=val + buff^;
+
+ end;
+
+ next_ln :
+ case buff^ of
+ #13 ,#10 :
+ scan:=expect_crlf;
+
+ ' ' :
+ else
+ break;
+
+ end;
+
+ expect_crlf :
+ case buff^ of
+ '{' :
+ scan:=load_key;
+
+ #13 ,#10 :
+ else
+ break;
+
+ end;
+
+ end;
+
+ dec(size );
+ inc(ptrcomp(buff ) );
+
+ end;
+
+end;
+
+{ CONSTRUCT }
+constructor dialog.Construct;
+begin
+ m_clri.ConstrDbl(0 ,0 ,0 );
+ m_clrt.ConstrDbl(0 ,0 ,0 );
+
+ m_appl:=appl;
+ m_info:=info;
+ m_text:=NIL;
+ m_tx_x:=0;
+ m_tx_y:=0;
+ m_aloc:=0;
+ m_size:=0;
+
+ if clr <> NIL then
+ m_clri:=clr^;
+
+ m_status:=ds_define;
+
+ m_num_actions:=0;
+ m_num_choices:=0;
+
+ m_cur_action:=NIL;
+ m_waiting :=NIL;
+
+end;
+
+{ DESTRUCT }
+destructor dialog.Destruct;
+var
+ i : unsigned;
+
+begin
+ if m_text <> NIL then
+ agg_freemem(pointer(m_text ) ,m_aloc );
+
+ if m_num_actions > 0 then
+ for i:=0 to m_num_actions - 1 do
+ m_actions[i ].ctrl.Destruct;
+
+ if m_num_choices > 0 then
+ for i:=0 to m_num_choices - 1 do
+ m_choices[i ].ctrl.Destruct;
+
+end;
+
+{ SET_WAITING }
+procedure dialog.set_waiting;
+begin
+ m_waiting:=@act;
+
+end;
+
+{ ADD_ACTION }
+procedure dialog.add_action;
+begin
+ case m_status of
+ ds_define ,ds_ready :
+ if m_num_actions < 5 then
+ begin
+ m_actions[m_num_actions ].ctrl.Construct(x1 ,y1 ,x2 ,y2 ,not flip_y );
+ m_actions[m_num_actions ].ctrl.add_item (name );
+
+ m_actions[m_num_actions ].func:=@act;
+
+ inc(m_num_actions );
+
+ set_next_status(ds_ready );
+
+ end;
+
+ end;
+
+end;
+
+{ ADD_CHOICE }
+procedure dialog.add_choice;
+begin
+ case m_status of
+ ds_define ,ds_ready :
+ if m_num_choices < 26 then
+ begin
+ m_choices[m_num_choices ].ctrl.Construct(x ,y ,name ,not flip_y );
+ m_choices[m_num_choices ].ctrl.status_ (status );
+
+ m_choices[m_num_choices ].attr:=StrPas(attr ) + #0;
+
+ inc(m_num_choices );
+
+ end;
+
+ end;
+
+end;
+
+{ CHANGE_TEXT }
+procedure dialog.change_text;
+begin
+ if StrLen(text ) + 1 > m_aloc then
+ begin
+ agg_freemem(pointer(m_text ) ,m_aloc );
+
+ m_aloc:=StrLen(text ) + 1;
+
+ agg_getmem(pointer(m_text ) ,m_aloc );
+
+ end;
+
+ move(text[0 ] ,m_text^ ,StrLen(text ) + 1 );
+
+ m_size:=StrLen(text );
+ m_tx_x:=x;
+ m_tx_y:=y;
+
+ if clr <> NIL then
+ m_clrt:=clr^;
+
+end;
+
+{ APPEND_TEXT }
+procedure dialog.append_text;
+var
+ new_text : char_ptr;
+ new_aloc : unsigned;
+
+begin
+ if StrLen(text ) + m_size + 1 > m_aloc then
+ begin
+ new_aloc:=StrLen(text ) + m_size + 1;
+
+ agg_getmem(pointer(new_text ) ,new_aloc );
+
+ move(m_text^ ,new_text^ ,m_size );
+
+ agg_freemem(pointer(m_text ) ,m_aloc );
+
+ m_aloc:=new_aloc;
+ m_text:=new_text;
+
+ end;
+
+ move(text[0 ] ,char_ptr(ptrcomp(m_text ) + m_size )^ ,StrLen(text ) + 1 );
+
+ inc(m_size ,StrLen(text ) );
+
+end;
+
+{ ADD_CONTROLS }
+function dialog.add_controls;
+var
+ i : unsigned;
+
+begin
+ result:=false;
+
+ case m_status of
+ ds_ready :
+ begin
+ m_appl.m_ctrls.Destruct;
+ m_appl.m_ctrls.Construct;
+
+ if m_num_actions > 0 then
+ for i:=0 to m_num_actions - 1 do
+ m_appl.add_ctrl(@m_actions[i ].ctrl );
+
+ if m_num_choices > 0 then
+ for i:=0 to m_num_choices - 1 do
+ m_appl.add_ctrl(@m_choices[i ] );
+
+ set_next_status;
+
+ result:=true;
+
+ end;
+
+ end;
+
+end;
+
+{ SET_NEXT_STATUS }
+procedure dialog.set_next_status;
+begin
+ if status <> ds_none then
+ m_status:=status
+ else
+ case m_status of
+ ds_define :
+ m_status:=ds_ready;
+
+ ds_ready :
+ m_status:=ds_waiting_input;
+
+ ds_waiting_input :
+ m_status:=ds_running;
+
+ end;
+
+end;
+
+{ FIND_CUR_ACTION }
+function dialog.find_cur_action;
+var
+ i : unsigned;
+
+begin
+ result:=false;
+
+ case m_status of
+ ds_waiting_input :
+ if m_num_actions > 0 then
+ for i:=0 to m_num_actions - 1 do
+ if m_actions[i ].ctrl._cur_item = 0 then
+ begin
+ m_cur_action:=@m_actions[i ];
+
+ result:=true;
+
+ exit;
+
+ end;
+
+ end;
+
+end;
+
+{ CALL_CUR_ACTION }
+// result of true means, that this was the last call
+function dialog.call_cur_action;
+begin
+ result:=false;
+
+ case m_status of
+ ds_running :
+ if m_cur_action <> NIL then
+ result:=m_cur_action.func(m_appl ,@self );
+
+ end;
+
+end;
+
+{ CALL_WAITING }
+procedure dialog.call_waiting;
+begin
+ if @m_waiting <> NIL then
+ m_waiting(m_appl ,@self );
+
+end;
+
+{ create_delphi }
+procedure create_delphi(batch_file ,comp_path ,project : shortstring );
+var
+ command : AnsiString;
+
+ suffix ,file_path ,file_name ,file_ext : shortstring;
+
+ df : text;
+
+begin
+// Compose the units path string
+ spread_name(comp_path ,file_path ,file_name ,file_ext );
+
+ command:=dir_str(file_path );
+
+ spread_name(command ,file_path ,suffix ,file_ext );
+
+ suffix:=file_path + 'lib';
+
+// Compose the command string
+ command:='"' + comp_path + 'dcc32.exe" ';
+ command:=command + '-U"' + suffix + '";';
+ command:=command + g_agg_paths + ' ';
+ command:=command + '-I' + g_inc_paths + ' ';
+ command:=command + '-N' + g_out_paths + ' ';
+ command:=command + g_delphi_config + ' ';
+ command:=command + project;
+
+// Create the file
+ AssignFile(df ,batch_file );
+ rewrite (df );
+ writeln (df ,command );
+ close (df );
+
+end;
+
+{ create_fpc }
+procedure create_fpc(batch_file ,comp_path ,project : shortstring );
+var
+ command : AnsiString;
+
+ suffix ,file_path ,file_name ,file_ext : shortstring;
+
+ df : text;
+
+begin
+// Compose the units path string
+ spread_name(comp_path ,file_path ,file_name ,file_ext );
+
+ command:=dir_str(file_path );
+
+ spread_name(command ,file_path ,suffix ,file_ext );
+
+ command:=dir_str(file_path );
+
+ spread_name(command ,file_path ,file_name ,file_ext );
+
+ suffix:=file_path + 'units\' + suffix;
+
+// Compose the command string
+ command:='"' + comp_path + 'ppc386.exe" ';
+ command:=command + '-FD"' + suffix + '" ';
+ command:=command + '-Fu' + g_agg_paths + ' ';
+ command:=command + '-Fi' + g_inc_paths + ' ';
+ command:=command + '-FU' + g_out_paths + ' ';
+ command:=command + g_fpc_config + ' ';
+ command:=command + project;
+
+// Create the file
+ AssignFile(df ,batch_file );
+ rewrite (df );
+ writeln (df ,command );
+ close (df );
+
+end;
+
+{ create_batch_files }
+procedure create_batch_files(project : shortstring; var del ,fpc : unsigned );
+var
+ i ,del_cnt ,fpc_cnt : unsigned;
+
+ batch ,batch_path ,comp_path ,file_path ,comp_name ,file_name ,file_ext : shortstring;
+
+ df : text;
+
+begin
+ spread_name(ParamStr(0 ) ,batch_path ,file_name ,file_ext );
+
+ del_cnt:=1;
+ fpc_cnt:=1;
+
+ for i:=0 to g_found - 1 do
+ begin
+ spread_name(g_search_results[i ] ,comp_path ,comp_name ,file_ext );
+ spread_name(project ,file_path ,file_name ,file_ext );
+
+ if cmp_str(comp_name ) = cmp_str('dcc32' ) then
+ begin
+ // Make batch for Delphi
+ if del_cnt = 1 then
+ batch:=''
+ else
+ str(del_cnt ,batch );
+
+ batch:='delphi' + batch + '-' + file_name;
+ batch:=fold_name(batch_path ,batch ,'*.bat' );
+
+ create_delphi(batch ,comp_path ,project );
+
+ // Make file
+ if del_cnt = 1 then
+ file_ext:=''
+ else
+ str(del_cnt ,file_ext );
+
+ file_ext :='delphi' + file_ext + '_make_all';
+ file_name:=fold_name(batch_path ,file_ext ,'*.bat' );
+
+ AssignFile(df ,file_name );
+
+ if del = 0 then
+ rewrite(df )
+ else
+ append(df );
+
+ file_ext:='call "' + batch + '"';
+
+ writeln(df ,file_ext );
+ close (df );
+
+ inc(del_cnt );
+
+ end
+ else
+ begin
+ // Make batch for FreePascal
+ if fpc_cnt = 1 then
+ batch:=''
+ else
+ str(fpc_cnt ,batch );
+
+ batch:='fpc' + batch + '-' + file_name;
+ batch:=fold_name(batch_path ,batch ,'*.bat' );
+
+ create_fpc(batch ,comp_path ,project );
+
+ // Make file
+ if fpc_cnt = 1 then
+ file_ext:=''
+ else
+ str(fpc_cnt ,file_ext );
+
+ file_ext :='fpc' + file_ext + '_make_all';
+ file_name:=fold_name(batch_path ,file_ext ,'*.bat' );
+
+ AssignFile(df ,file_name );
+
+ if fpc = 0 then
+ rewrite(df )
+ else
+ append(df );
+
+ file_ext:='call "' + batch + '"';
+
+ writeln(df ,file_ext );
+ close (df );
+
+ inc(fpc_cnt );
+
+ end;
+
+ end;
+
+ inc(del ,del_cnt - 1 );
+ inc(fpc ,fpc_cnt - 1 );
+
+end;
+
+{ action_configure }
+function action_configure(appl : the_application_ptr; sender : dialog_ptr ) : boolean;
+var
+ i : unsigned;
+
+ text : shortstring;
+ rgba : aggclr;
+
+ del ,fpc : unsigned;
+
+begin
+ rgba.ConstrDbl(0 ,0.5 ,0 );
+
+ appl.m_dlg_searching.change_text('Creating appropriate batch files ...' ,10 ,320 ,@rgba );
+ appl.force_redraw;
+
+// Setup the final text
+ rgba.ConstrDbl(0 ,0.5 ,0 );
+
+ appl.m_dlg_found_some.change_text('' ,10 ,385 ,@rgba );
+
+ for i:=0 to g_found - 1 do
+ begin
+ str(i + 1 ,text );
+
+ text:='(' + text + ') ' + g_search_results[i ] + #13#0;
+
+ appl.m_dlg_found_some.append_text(@text[1 ] );
+
+ end;
+
+// Create the batch files
+ if g_num_demos > 0 then
+ begin
+ appl.m_dlg_found_some.append_text(
+ #13 +
+ 'Appropriate batch files for compiling the ' + g_appl + ' demos were created'#13 +
+ 'in the directory, from which this helper utility was run.' );
+
+ del:=0;
+ fpc:=0;
+
+ for i:=0 to g_num_demos - 1 do
+ create_batch_files(g_demos[i ] ,del ,fpc );
+
+ if del > 0 then
+ appl.m_dlg_found_some.append_text(
+ #13#13 +
+ 'Note: For the Delphi compiler, which was found on your system,'#13 +
+ 'helper utility assumes, that the system libraries needed for'#13 +
+ 'successful compilation are located in the parallel directory'#13 +
+ '"..\lib" of the particular Delphi compiler path.' );
+
+ if fpc > 0 then
+ appl.m_dlg_found_some.append_text(
+ #13#13 +
+ 'Note: For the Free Pascal compiler, which was found on your system,'#13 +
+ 'helper utility assumes, that the system libraries needed for'#13 +
+ 'successful compilation are located in the parallel directory'#13 +
+ '"..\units\i386-win32" of the particular Free Pascal compiler path.' );
+
+ end
+ else
+ appl.m_dlg_found_some.append_text(
+ #13 +
+ 'NO batch files for compiling the ' + g_appl + ' demos'#13 +
+ 'were created in the directory, from which this helper'#13 +
+ 'utility was run, because no *.dpr projects were found.' );
+
+// Refresh
+ appl.force_redraw;
+
+end;
+
+{ action_set_drives }
+function action_set_drives(appl : the_application_ptr; sender : dialog_ptr ) : boolean;
+var
+ letter ,
+ path ,
+ drive : shortstring;
+
+ drive_type ,i ,count : unsigned;
+
+begin
+// Scan for drives in the system
+ letter:='C';
+ count :=0;
+
+ for i:=1 to 24 do
+ begin
+ path :=letter + ':\'#0;
+ drive:='';
+
+ drive_type:=GetDriveType(@path[1 ] );
+
+ case drive_type of
+ DRIVE_FIXED : drive:='fixed harddrive';
+ DRIVE_REMOVABLE : drive:='removable drive';
+ DRIVE_REMOTE : drive:='network or remote drive';
+ DRIVE_CDROM : drive:='CD-ROM drive';
+ DRIVE_RAMDISK : drive:='RAM disk';
+
+ end;
+
+ if drive <> '' then
+ begin
+ drive:=' ' + StrPas(@path[1 ] ) + ' (' + drive + ')' + #0;
+
+ appl.m_dlg_set_drives.add_choice(@drive[1 ] ,@path[1 ] ,30 ,360 - count * 30 ,count = 0 );
+
+ inc(count );
+
+ end;
+
+ inc(byte(letter[1 ] ) );
+
+ end;
+
+ appl.m_cur_dlg:=@appl.m_dlg_set_drives;
+
+// OK Done
+ result:=true;
+
+end;
+
+{ action_while_search }
+function action_while_search(appl : the_application_ptr; sender : dialog_ptr ) : boolean;
+var
+ text : shortstring;
+ rgba : aggclr;
+
+begin
+ while g_lock do;
+
+ g_lock:=true;
+
+ if appl.m_ShLast <> appl.m_DoShow then
+ begin
+ str(g_found ,text );
+
+ text:=
+ ' ' + appl.m_DoShow + #13#13 +
+ 'Compilers found: ' + text + #0;
+
+ //rgba.ConstrDbl(0 ,0 ,0.5 );
+
+ appl.m_dlg_searching.change_text(@text[1 ] ,10 ,320 );
+ appl.force_redraw;
+
+ appl.m_ShLast:=appl.m_DoShow;
+
+ end;
+
+ g_lock:=false;
+
+end;
+
+{ process_file }
+function process_file(file_name : shortstring ) : boolean;
+begin
+ if g_found < g_max then
+ begin
+ g_search_results[g_found ]:=file_name;
+
+ inc(g_found );
+
+ end;
+
+end;
+
+{ scan_files }
+function scan_files(files : shortstring; appl : the_application_ptr ) : boolean;
+var
+ SR : TSearchRec;
+ err : integer;
+
+ find ,file_path ,file_name ,file_ext : shortstring;
+
+begin
+ result:=false;
+
+{ Scan dirs and go further }
+ spread_name(files ,file_path ,file_name ,file_ext );
+
+ while g_lock do;
+
+ g_lock:=true;
+
+ appl.m_DoShow:=file_path;
+
+ g_lock:=false;
+
+ err:=SysUtils.FindFirst(str_dir(file_path ) + '*' ,faDirectory ,SR );
+
+ while err = 0 do
+ begin
+ if appl.m_DoQuit then
+ begin
+ SysUtils.FindClose(SR );
+
+ exit;
+
+ end;
+
+ if (SR.Name <> '.' ) and
+ (SR.Name <> '..' ) and
+ (SR.Attr and faDirectory = faDirectory ) then
+ begin
+ spread_name(files ,file_path ,file_name ,file_ext );
+
+ if not scan_files(fold_name(str_dir(file_path ) + SR.Name + '\' ,file_name ,file_ext ) ,appl ) then
+ exit;
+
+ end;
+
+ err:=SysUtils.FindNext(SR );
+
+ end;
+
+ SysUtils.FindClose(SR );
+
+{ Scan files for Delphi compiler }
+ find:=fold_name(file_path ,'dcc32' ,'*.exe' );
+
+ err:=SysUtils.FindFirst(find ,faArchive ,SR );
+
+ while err = 0 do
+ begin
+ if appl.m_DoQuit then
+ begin
+ SysUtils.FindClose(SR );
+
+ exit;
+
+ end;
+
+ process_file(fold_name(files ,SR.Name ,SR.Name ) );
+
+ err:=SysUtils.FindNext(SR );
+
+ end;
+
+ SysUtils.FindClose(SR );
+
+{ Scan files for FPC compiler }
+ find:=fold_name(file_path ,'ppc386' ,'*.exe' );
+
+ err:=SysUtils.FindFirst(find ,faArchive ,SR );
+
+ while err = 0 do
+ begin
+ if appl.m_DoQuit then
+ begin
+ SysUtils.FindClose(SR );
+
+ exit;
+
+ end;
+
+ process_file(fold_name(files ,SR.Name ,SR.Name ) );
+
+ err:=SysUtils.FindNext(SR );
+
+ end;
+
+ SysUtils.FindClose(SR );
+
+{ OK }
+ scan_files:=true;
+
+end;
+
+{ FnSearch }
+procedure FnSearch(appl : the_application_ptr );
+var
+ i : unsigned;
+
+begin
+ appl.m_ShLast:='';
+ appl.m_DoShow:='';
+
+ g_found:=0;
+
+// OK, Go through selected drives and issue search
+ appl.m_dlg_searching.set_waiting(@action_while_search );
+
+ if appl.m_dlg_set_drives.m_num_choices > 0 then
+ for i:=0 to appl.m_dlg_set_drives.m_num_choices - 1 do
+ if appl.m_dlg_set_drives.m_choices[i ].ctrl._status then
+ if not scan_files(appl.m_dlg_set_drives.m_choices[i ].attr ,appl ) then
+ break;
+
+ appl.m_dlg_searching.set_waiting(NIL );
+
+// Were we forced to quit ?
+ if appl.m_DoQuit then
+ NoP;
+
+// Depending on the search result activate the next user dialog
+ if g_found > 0 then
+ begin
+ action_configure(appl ,NIL );
+
+ appl.m_cur_dlg:=@appl.m_dlg_found_some;
+
+ end
+ else
+ appl.m_cur_dlg:=@appl.m_dlg_not_found;
+
+end;
+
+{ ThSearch }
+function ThSearch(Parameter : pointer ): integer;
+begin
+{ Synchronize }
+ while the_application_ptr(Parameter ).m_Thread = 0 do;
+
+{ Call Thread }
+ FnSearch(Parameter );
+
+{ Exit }
+ the_application_ptr(Parameter ).m_Thread:=0;
+ the_application_ptr(Parameter ).m_ApplID:=0;
+
+{ Done }
+ EndThread(0 );
+
+end;
+
+{ action_begin_search }
+function action_begin_search(appl : the_application_ptr; sender : dialog_ptr ) : boolean;
+var
+ i : unsigned;
+
+begin
+ result:=false;
+
+// Check, if we have drives to search
+ if appl.m_dlg_set_drives.m_num_choices > 0 then
+ for i:=0 to appl.m_dlg_set_drives.m_num_choices - 1 do
+ if appl.m_dlg_set_drives.m_choices[i ].ctrl._status then
+ begin
+ result:=true;
+
+ break;
+
+ end;
+
+ if not result then
+ begin
+ appl.m_dlg_set_drives.m_actions[0 ].ctrl.cur_item_(-1 );
+ appl.m_dlg_set_drives.set_next_status(ds_waiting_input );
+ appl.force_redraw;
+
+ exit;
+
+ end;
+
+// Go on to search dialog
+ appl.m_cur_dlg:=@appl.m_dlg_searching;
+
+// Start Up the search thread
+ appl.m_Thread:=BeginThread(NIL ,65536 ,ThSearch ,appl ,0 ,appl.m_ApplID );
+
+end;
+
+{ action_stop_search }
+function action_stop_search(appl : the_application_ptr; sender : dialog_ptr ) : boolean;
+begin
+ appl.m_DoQuit:=true;
+
+end;
+
+{ action_exit }
+function action_exit(appl : the_application_ptr; sender : dialog_ptr ) : boolean;
+begin
+ appl.quit;
+
+end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+var
+ rgba : aggclr;
+
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_sl.Construct;
+ m_ras.Construct;
+
+ m_cur_dlg:=NIL;
+
+ m_Thread:=0;
+ m_ApplID:=0;
+ m_DoQuit:=false;
+ m_ShLast:='';
+ m_DoShow:='';
+
+// Welcome dialog
+ m_dlg_welcome.Construct(
+ @self ,
+ 'Welcome to the ' + g_full + '.'#13 +
+ ''#13 +
+ 'This helper utility will scan your system to search'#13 +
+ 'for all available Object Pascal compilers.'#13 +
+ ''#13 +
+ 'It will also create appropriate batch files with current'#13 +
+ 'paths and options needed to compile properly all'#13 +
+ 'the ' + g_appl + ' demos.'#13+
+ ''#13 +
+ 'Currently Delphi and Free Pascal compilers are supported.' );
+
+ m_dlg_welcome.add_action('Continue' ,@action_set_drives ,480 ,15 ,580 ,45 );
+
+// Set drives to search on dialog
+ m_dlg_set_drives.Construct(
+ @self ,
+ 'Please select, on which drives of your system should'#13 +
+ 'this helper utility perform search for Object Pascal compilers:' );
+
+ m_dlg_set_drives.add_action('Continue' ,@action_begin_search ,480 ,15 ,580 ,45 );
+
+// Wait, searching dialog
+ m_dlg_searching.Construct(
+ @self ,
+ 'Please wait ...'#13 +
+ ''#13 +
+ 'Helper utility is searching for Object Pascal compilers'#13 +
+ 'on the drives, you have selected.' );
+
+ m_dlg_searching.add_action('Stop searching' ,@action_stop_search ,440 ,15 ,580 ,45 );
+
+// Found nothing dialog
+ rgba.ConstrInt(255 ,0 ,0 );
+
+ m_dlg_not_found.Construct(
+ @self ,
+ 'I am sorry, but NO Object Pascal compilers were found'#13 +
+ 'on your system.'#13 +
+ ''#13 +
+ 'Please install Delphi or FreePascal'#13+
+ 'and then rerun this utility.'#13#13+
+ 'http://www.borland.com'#13#13 +
+ '- or - '#13#13 +
+ 'http://www.freepascal.org' ,
+ @rgba );
+
+ m_dlg_not_found.add_action('Exit' ,@action_exit ,500 ,15 ,580 ,45 );
+
+// Compilers found dialog
+ rgba.ConstrDbl(0 ,0.5 ,0 );
+
+ m_dlg_found_some.Construct(
+ @self ,
+ 'Following Object Pascal compilers were found your system:' ,
+ @rgba );
+
+ m_dlg_found_some.add_action('Exit' ,@action_exit ,500 ,15 ,580 ,45 );
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ while m_Thread <> 0 do
+ m_DoQuit:=true;
+
+ inherited Destruct;
+
+ m_sl.Destruct;
+ m_ras.Destruct;
+
+ m_dlg_welcome.Destruct;
+ m_dlg_set_drives.Destruct;
+ m_dlg_searching.Destruct;
+ m_dlg_not_found.Destruct;
+ m_dlg_found_some.Destruct;
+
+end;
+
+{ DRAW_TEXT }
+procedure the_application.draw_text;
+var
+ pixf : pixel_formats;
+ rgba : aggclr;
+
+ rb : renderer_base;
+ rs : renderer_scanline_aa_solid;
+
+ t : gsv_text;
+ pt : conv_stroke;
+
+begin
+ pixfmt_bgr24(pixf ,rbuf_window );
+
+ rb.Construct(@pixf );
+ rs.Construct(@rb );
+
+ t.Construct;
+ t.size_ (9.5 );
+ t.line_space_(10 );
+
+ pt.Construct(@t );
+ pt.width_ (1.2 );
+
+ t.start_point_(x ,y );
+ t.text_ (msg );
+
+ if clr <> NIL then
+ rs.color_(clr )
+ else
+ begin
+ rgba.ConstrDbl(0 ,0 ,0 );
+ rs.color_ (@rgba );
+
+ end;
+
+ m_ras.add_path (@pt );
+ render_scanlines(@m_ras ,@m_sl ,@rs );
+
+ t.Destruct;
+ pt.Destruct;
+
+end;
+
+{ ON_INIT }
+procedure the_application.on_init;
+var
+ SR : TSearchRec;
+ err : integer;
+
+ find ,file_path ,file_name ,file_ext : shortstring;
+
+ cf : file;
+ bf : pointer;
+ sz : integer;
+
+ target ,get : shortstring;
+
+begin
+ wait_mode_(false );
+
+// Load the list of current projects
+ g_num_demos:=0;
+
+ spread_name(ParamStr(0 ) ,file_path ,file_name ,file_ext );
+
+ find:=fold_name(file_path ,'*' ,'*.dpr' );
+ err :=SysUtils.FindFirst(find ,faArchive ,SR );
+
+ while err = 0 do
+ begin
+ // Load keys from the source file
+ key_count:=0;
+
+ get:=fold_name(file_path ,SR.Name ,SR.Name );
+
+ AssignFile(cf ,SR.Name );
+ reset (cf ,1 );
+
+ if IOResult = 0 then
+ begin
+ sz:=System.FileSize(cf );
+
+ if agg_getmem(bf ,sz ) then
+ begin
+ blockread (cf ,bf^ ,sz );
+ LoadKeys (bf ,sz );
+ agg_freemem(bf ,sz );
+
+ end;
+
+ close(cf );
+
+ end;
+
+ target:='win';
+
+ FirstKey('target' ,target );
+
+ // Add To List
+ if (cmp_str(target ) <> cmp_str('win' ) ) or
+ FirstKey('skip' ,get ) then
+
+ else
+ if g_num_demos < g_max_demos then
+ begin
+ g_demos[g_num_demos ]:=fold_name('' ,SR.Name ,SR.Name );
+
+ inc(g_num_demos );
+
+ end;
+
+ err:=SysUtils.FindNext(SR );
+
+ end;
+
+ SysUtils.FindClose(SR );
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ pixf : pixel_formats;
+ rgba : aggclr;
+
+ rb : renderer_base;
+ rs : renderer_scanline_aa_solid;
+
+ i ,plus : unsigned;
+
+begin
+// Initialize structures
+ pixfmt_bgr24(pixf ,rbuf_window );
+
+ rb.Construct(@pixf );
+ rs.Construct(@rb );
+
+ rgba.ConstrDbl(1 ,1 ,1 );
+ rb.clear (@rgba );
+
+// Render Dialog
+ if m_cur_dlg <> NIL then
+ case m_cur_dlg.m_status of
+ ds_waiting_input ,ds_running :
+ begin
+ // Render logo if has one
+ plus:=0;
+
+ if (m_cur_dlg = @m_dlg_welcome ) and
+ g_image then
+ begin
+ rb.copy_from(rbuf_img(1 ) ,NIL ,6 ,330 );
+
+ plus:=rbuf_img(1 )._height + 20;
+
+ end;
+
+ // Render base text
+ draw_text(10 ,420 - plus ,m_cur_dlg.m_info ,@m_cur_dlg.m_clri );
+
+ // Render dynamic text
+ if m_cur_dlg.m_text <> NIL then
+ draw_text(
+ m_cur_dlg.m_tx_x ,
+ m_cur_dlg.m_tx_y ,
+ PChar(m_cur_dlg.m_text ) ,
+ @m_cur_dlg.m_clrt );
+
+ // Render choices
+ if m_cur_dlg.m_num_choices > 0 then
+ for i:=0 to m_cur_dlg.m_num_choices - 1 do
+ render_ctrl(@m_ras ,@m_sl ,@rs ,@m_cur_dlg.m_choices[i ] );
+
+ // Render actions
+ if m_cur_dlg.m_num_actions > 0 then
+ for i:=0 to m_cur_dlg.m_num_actions - 1 do
+ render_ctrl(@m_ras ,@m_sl ,@rs ,@m_cur_dlg.m_actions[i ].ctrl );
+
+ end;
+
+ end;
+
+end;
+
+{ ON_CTRL_CHANGE }
+procedure the_application.on_ctrl_change;
+begin
+ if m_cur_dlg <> NIL then
+ case m_cur_dlg.m_status of
+ ds_waiting_input :
+ if m_cur_dlg.find_cur_action then
+ m_cur_dlg.set_next_status;
+
+ end;
+
+end;
+
+{ ON_IDLE }
+procedure the_application.on_idle;
+begin
+ if m_cur_dlg = NIL then
+ begin
+ m_cur_dlg:=@m_dlg_welcome;
+
+ if m_cur_dlg.m_status <> ds_ready then
+ m_cur_dlg:=NIL;
+
+ end
+ else
+ case m_cur_dlg.m_status of
+ ds_ready :
+ if m_cur_dlg.add_controls then
+ force_redraw;
+
+ ds_waiting_input :
+ m_cur_dlg.call_waiting;
+
+ ds_running :
+ if m_cur_dlg.call_cur_action then
+ NoP;
+
+ end;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ 'This is just an AggPas library helper utility which has nothing to do'#13 +
+ 'with demonstrating any of graphical possibilities of AGG.'#13#13 +
+ 'Author of this pascal port (Milano) recomends to proceed with this utility'#13 +
+ 'on your system right after unpacking the archive, because it will'#13 +
+ 'scan your computer for all available Object Pascal compilers and'#13 +
+ 'it will create the up-to-date working batch files for fompiling the library demos.'#13#13 +
+ 'In the welcome screen of this utility, there is a logo for the AGG library,'#13 +
+ 'which was designed and proposed by Milano. It has the meaning of spiral primitive'#13 +
+ 'upon the interactive polygon control, which should mean in "translation" that'#13 +
+ '"With AGG the possibilities are endless (the spiral) and custom adjustments'#13 +
+ 'are easy possible. (interactive polygon)".' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+VAR
+ app : the_application;
+
+BEGIN
+ g_lock :=false;
+ g_image:=false;
+
+ app.Construct(pix_format_bgr24 ,flip_y );
+ app.caption_ (g_appl + ' Startup utility (F1-Help)' );
+
+ if app.load_img(1 ,'aggpas_logo' ) then
+ g_image:=true;
+
+ if app.init(600 ,450 ,0 ) then
+ app.run;
+
+ app.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/flash_rasterizer.dpr b/src/corelib/render/software/agg-demos/flash_rasterizer.dpr
new file mode 100644
index 00000000..c0cf14c4
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/flash_rasterizer.dpr
@@ -0,0 +1,1006 @@
+{mac_copy:shapes.txt}
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ flash_rasterizer ;
+
+uses
+ SysUtils ,
+ agg_basics ,
+ agg_array ,
+ agg_color ,
+ agg_platform_support ,
+ agg_rendering_buffer ,
+ agg_trans_viewport ,
+ agg_path_storage ,
+ agg_conv_transform ,
+ agg_conv_curve ,
+ agg_conv_stroke ,
+ agg_gsv_text ,
+ agg_scanline_u ,
+ agg_scanline_bin ,
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_render_scanlines ,
+ agg_rasterizer_scanline_aa ,
+ agg_rasterizer_compound_aa ,
+ agg_span_allocator ,
+ agg_gamma_lut ,
+ agg_pixfmt ,
+ agg_pixfmt_rgba ,
+ agg_bounding_rect ,
+ agg_vertex_source ,
+ agg_trans_affine ,
+ agg_math ,
+ agg_math_stroke ,
+ file_utils_ ;
+
+{$I agg_mode.inc }
+
+const
+ flip_y = false;
+
+type
+ path_style_ptr = ^path_style;
+ path_style = record
+ path_id : unsigned;
+
+ left_fill ,
+ right_fill ,
+ line : int;
+
+ end;
+
+ compound_shape = object(vertex_source )
+ private
+ m_path : path_storage;
+ m_affine : trans_affine;
+ m_curve : conv_curve;
+ m_trans : conv_transform;
+ m_styles : pod_bvector;
+
+ m_x1 ,
+ m_y1 ,
+ m_x2 ,
+ m_y2 : double;
+
+ m_fd : api_file;
+
+ public
+ constructor Construct;
+ destructor Destruct; virtual;
+
+ function open(fname : AnsiString ) : boolean;
+ function read_next : boolean;
+
+ function operator_array(i : unsigned ) : unsigned; virtual;
+ function paths : unsigned;
+ function style(i : unsigned ) : path_style_ptr;
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ function scale : double; overload;
+ procedure scale(w ,h : double ); overload;
+
+ procedure approximation_scale(s : double );
+
+ function hit_test(x ,y ,r : double ) : int;
+
+ procedure modify_vertex(i : unsigned; x ,y : double );
+
+ end;
+
+// Testing class, color provider and span generator
+ test_styles = object(style_handler )
+ private
+ m_solid_colors ,
+ m_gradient : aggclr_ptr;
+
+ public
+ constructor Construct(solid_colors ,gradient : aggclr_ptr );
+
+ function is_solid(style : unsigned ) : boolean; virtual;
+ function color (style : unsigned ) : aggclr_ptr; virtual;
+
+ procedure generate_span(span : aggclr_ptr; x ,y : int; len ,style : unsigned ); virtual;
+
+ end;
+
+ the_application = object(platform_support )
+ private
+ m_shape : compound_shape;
+ m_colors : array[0..99 ] of aggclr;
+ m_scale : trans_affine;
+ m_gamma : gamma_lut;
+ m_gradient : pod_array;
+
+ m_point_idx ,
+ m_hit_x ,
+ m_hit_y : int;
+
+ public
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ function open(fname : AnsiString ) : boolean;
+ procedure read_next;
+
+ procedure on_draw; virtual;
+
+ procedure on_mouse_move (x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_up (x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ CONSTRUCT }
+constructor compound_shape.Construct;
+begin
+ m_path.Construct;
+ m_affine.Construct;
+ m_curve.Construct (@m_path );
+ m_trans.Construct (@m_curve ,@m_affine );
+ m_styles.Construct(sizeof(path_style ) );
+
+end;
+
+{ DESTRUCT }
+destructor compound_shape.Destruct;
+begin
+ m_path.Destruct;
+ m_curve.Destruct;
+ m_styles.Destruct;
+
+ if m_fd.isOpened then
+ api_close_file(m_fd );
+
+end;
+
+{ OPEN }
+function compound_shape.open(fname : AnsiString ) : boolean;
+begin
+ result:=api_open_file(m_fd ,fname );
+
+end;
+
+{ fgets }
+function fgets(buf : char_ptr; max : int; var f : api_file ) : char_ptr;
+var
+ read : int;
+
+begin
+ result:=buf;
+
+ while max > 1 do
+ begin
+ if not api_read_file(f ,buf ,1 ,read ) then
+ begin
+ result:=NIL;
+
+ exit;
+
+ end;
+
+ if read = 0 then
+ if buf = result then
+ begin
+ result:=NIL;
+
+ exit;
+
+ end
+ else
+ break;
+
+ case buf^ of
+ #13 ,#10 ,#9 :
+ break;
+
+ end;
+
+ dec(max );
+ inc(ptrcomp(buf ) ,read );
+
+ end;
+
+ if max >= 1 then
+ buf^:=#0;
+
+end;
+
+var
+ g_buff : char_ptr;
+
+{ strtok }
+function strtok(buff : char_ptr ) : char_ptr;
+begin
+ result:=NIL;
+
+ if buff <> NIL then
+ g_buff:=buff;
+
+ while (g_buff <> NIL ) and
+ (g_buff^ <> #0 ) do
+ begin
+ if result = NIL then
+ result:=g_buff;
+
+ case g_buff^ of
+ ' ' ,#13 ,#10 :
+ begin
+ g_buff^:=#0;
+
+ inc(ptrcomp(g_buff ) );
+
+ break;
+
+ end;
+
+ end;
+
+ inc(ptrcomp(g_buff ) );
+
+ end;
+
+end;
+
+{ READ_NEXT }
+function compound_shape.read_next : boolean;
+var
+ ax ,ay ,cx ,cy : double;
+
+ buf : array[0..1023 ] of char;
+
+ ts : char_ptr;
+
+ style_ : path_style;
+
+ code : int;
+
+begin
+ m_path.remove_all;
+ m_styles.remove_all;
+
+ if m_fd.isOpened then
+ begin
+ repeat
+ if fgets(@buf[0 ] ,1022 ,m_fd ) = NIL then
+ begin
+ result:=false;
+
+ exit;
+
+ end;
+
+ if buf[0 ] = '=' then
+ break;
+
+ until false;
+
+ while fgets(@buf[0 ] ,1022 ,m_fd ) <> NIL do
+ begin
+ if buf[0 ] = '!' then
+ break;
+
+ if buf[0 ] = 'P' then
+ begin
+ // BeginPath
+ style_.path_id:=m_path.start_new_path;
+
+ ts:=strtok(@buf[0 ] ); // Path;
+ ts:=strtok(NIL ); // left_style
+
+ Val(PChar(ts ) ,style_.left_fill ,code );
+
+ ts:=strtok(NIL ); // right_style
+
+ Val(PChar(ts ) ,style_.right_fill ,code );
+
+ ts:=strtok(NIL ); // line_style
+
+ Val(PChar(ts ) ,style_.line ,code );
+
+ ts:=strtok(NIL ); // ax
+
+ Val(PChar(ts ) ,ax ,code );
+
+ ts:=strtok(NIL ); // ay
+
+ Val(PChar(ts ) ,ay ,code );
+
+ m_path.move_to(ax ,ay );
+ m_styles.add (@style_ );
+
+ end;
+
+ if buf[0 ] = 'C' then
+ begin
+ ts:=strtok(@buf[0 ] ); // Curve;
+ ts:=strtok(NIl ); // cx
+
+ Val(PChar(ts ) ,cx ,code );
+
+ ts:=strtok(NIL ); // cy
+
+ Val(PChar(ts ) ,cy ,code );
+
+ ts:=strtok(NIL ); // ax
+
+ Val(PChar(ts ) ,ax ,code );
+
+ ts:=strtok(NIL ); // ay
+
+ Val(PChar(ts ) ,ay ,code );
+
+ m_path.curve3(cx ,cy ,ax ,ay );
+
+ end;
+
+ if buf[0 ] = 'L' then
+ begin
+ ts:=strtok(@buf[0 ] ); // Line;
+ ts:=strtok(NIL ); // ax
+
+ Val(PChar(ts ) ,ax ,code );
+
+ ts:=strtok(NIL ); // ay
+
+ Val(PChar(ts ) ,ay ,code );
+
+ m_path.line_to(ax ,ay );
+
+ end;
+
+ if buf[0 ] = '<' then
+ begin
+ // EndPath
+ end;
+
+ end;
+
+ result:=true;
+
+ end
+ else
+ result:=false;
+
+end;
+
+{ OPERATOR_ARRAY }
+function compound_shape.operator_array(i : unsigned ) : unsigned;
+begin
+ result:=path_style_ptr(m_styles.array_operator(i ) )^.path_id;
+
+end;
+
+{ PATHS }
+function compound_shape.paths : unsigned;
+begin
+ result:=m_styles.size;
+
+end;
+
+{ STYLE }
+function compound_shape.style(i : unsigned ) : path_style_ptr;
+begin
+ result:=path_style_ptr(m_styles.array_operator(i ) );
+
+end;
+
+{ REWIND }
+procedure compound_shape.rewind(path_id : unsigned );
+begin
+ m_trans.rewind(path_id );
+
+end;
+
+{ VERTEX }
+function compound_shape.vertex(x ,y : double_ptr ) : unsigned;
+begin
+ result:=m_trans.vertex(x ,y );
+
+end;
+
+{ SCALE }
+function compound_shape.scale : double;
+begin
+ result:=m_affine.scale;
+
+end;
+
+{ SCALE }
+procedure compound_shape.scale(w ,h : double );
+var
+ x1 ,y1 ,x2 ,y2 : double;
+
+ vp : trans_viewport;
+
+begin
+ m_affine.reset;
+
+ bounding_rect_vs(
+ @m_path ,@self ,0 ,m_styles.size ,
+ @x1 ,@y1 ,@x2 ,@y2 );
+
+ if (x1 < x2 ) and
+ (y1 < y2 ) then
+ begin
+ vp.Construct;
+ vp.preserve_aspect_ratio(0.5 ,0.5 ,aspect_ratio_meet );
+
+ vp.world_viewport (x1 ,y1 ,x2 ,y2 );
+ vp.device_viewport(0 ,0 ,w ,h );
+ vp.to_affine (@m_affine );
+
+ end;
+
+ m_curve.approximation_scale_(m_affine.scale );
+
+end;
+
+{ APPROXIMATION_SCALE }
+procedure compound_shape.approximation_scale(s : double );
+begin
+ m_curve.approximation_scale_(m_affine.scale * s );
+
+end;
+
+{ HIT_TEST }
+function compound_shape.hit_test(x ,y ,r : double ) : int;
+var
+ i ,cmd : unsigned;
+ vx ,vy : double;
+
+begin
+ m_affine.inverse_transform(@m_affine ,@x ,@y );
+
+ r:=r / m_affine.scale;
+ i:=0;
+
+ while i < m_path.total_vertices do
+ begin
+ cmd:=m_path.vertex_(i ,@vx ,@vy );
+
+ if is_vertex(cmd ) then
+ if calc_distance(x ,y ,vx ,vy ) <= r then
+ begin
+ result:=i;
+
+ exit;
+
+ end;
+
+ inc(i );
+
+ end;
+
+ result:=-1;
+
+end;
+
+{ MODIFY_VERTEX }
+procedure compound_shape.modify_vertex(i : unsigned; x ,y : double );
+begin
+ m_affine.inverse_transform(@m_affine ,@x ,@y );
+ m_path.modify_vertex (i ,x ,y );
+
+end;
+
+{ CONSTRUCT }
+constructor test_styles.Construct(solid_colors ,gradient : aggclr_ptr );
+begin
+ m_solid_colors:=solid_colors;
+ m_gradient :=gradient;
+
+end;
+
+{ IS_SOLID }
+// Suppose that style=1 is a gradient
+function test_styles.is_solid(style : unsigned ) : boolean;
+begin
+ result:=style <> 1; //true;
+
+end;
+
+{ COLOR }
+// Just returns a color
+function test_styles.color(style : unsigned ) : aggclr_ptr;
+begin
+ result:=aggclr_ptr(ptrcomp(m_solid_colors ) + style * sizeof(aggclr ) );
+
+end;
+
+{ GENERATE_SPAN }
+// Generate span. In our test case only one style (style=1)
+// can be a span generator, so that, parameter "style"
+// isn't used here.
+procedure test_styles.generate_span(span : aggclr_ptr; x ,y : int; len ,style : unsigned );
+begin
+ move(
+ aggclr_ptr(ptrcomp(m_gradient ) + x * sizeof(aggclr ) )^ ,
+ span^ ,
+ sizeof(aggclr ) * len );
+
+end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+var
+ i : unsigned;
+
+ c1 ,c2 ,c3 : int;
+
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_shape.Construct;
+ m_scale.Construct;
+ m_gamma.Construct_;
+ m_gradient.Construct(sizeof(aggclr ) );
+
+ m_gamma.gamma_(2.0 );
+
+ m_point_idx:=-1;
+ m_hit_x :=-1;
+ m_hit_y :=-1;
+
+ i:=0;
+
+ while i < 100 do
+ begin
+ c1:=rand and $FF;
+ c2:=rand and $FF;
+ c3:=rand and $FF;
+
+ m_colors[i ].ConstrInt(c3 ,c2 ,c1 ,230 );
+
+ m_colors[i ].apply_gamma_dir(@m_gamma );
+ m_colors[i ].premultiply;
+
+ inc(i );
+
+ end;
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_shape.Destruct;
+ m_gamma.Destruct;
+ m_gradient.Destruct;
+
+end;
+
+{ OPEN }
+function the_application.open(fname : AnsiString ) : boolean;
+begin
+ result:=m_shape.open(full_file_name(fname ) );
+
+end;
+
+{ READ_NEXT }
+procedure the_application.read_next;
+begin
+ m_shape.read_next;
+ m_shape.scale(_width ,_height );
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ pixf : pixel_formats;
+
+ rgba ,c1 ,c2 : aggclr;
+
+ ren_base : renderer_base;
+
+ ren : renderer_scanline_aa_solid;
+ ras : rasterizer_scanline_aa;
+
+ rasc : rasterizer_compound_aa_dbl;
+
+ sl : scanline_u8;
+ sl_bin : scanline_bin;
+
+ i ,w : unsigned;
+
+ shape : conv_transform;
+ stroke : conv_stroke;
+
+ style_handler : test_styles;
+
+ alloc : span_allocator;
+
+ tfill ,tstroke : double;
+
+ draw_strokes : boolean;
+
+ buf : array[0..255 ] of char;
+
+ t : gsv_text;
+ ts : conv_stroke;
+
+begin
+// Initialize structures
+ pixfmt_bgra32_pre(pixf ,rbuf_window );
+
+ ren_base.Construct(@pixf );
+
+ rgba.ConstrDbl(1.0 ,1.0 ,0.95 );
+ ren_base.clear(@rgba );
+
+ ren.Construct(@ren_base );
+
+ w:=Trunc(_width );
+
+ m_gradient.resize(w );
+
+ c1.ConstrInt(255 ,0 ,0 ,180 );
+ c2.ConstrInt(0 ,0 ,255 ,180 );
+
+ i:=0;
+
+ while i < w do
+ begin
+ aggclr_ptr(m_gradient.array_operator(i ) )^:=c1.gradient(@c2 ,i / _width );
+
+ aggclr_ptr(m_gradient.array_operator(i ) ).premultiply;
+
+ inc(i );
+
+ end;
+
+ ras.Construct;
+ rasc.Construct;
+
+ sl.Construct;
+ sl_bin.Construct;
+
+ shape.Construct (@m_shape ,@m_scale );
+ stroke.Construct(@shape );
+
+ style_handler.Construct(@m_colors[0 ] ,m_gradient.data );
+
+ alloc.Construct;
+
+ m_shape.approximation_scale(m_scale.scale );
+
+// Fill shape
+ rasc.clip_box(0 ,0 ,_width ,_height );
+ rasc.reset;
+// rasc.filling_rule(fill_even_odd );
+
+ start_timer;
+
+ i:=0;
+
+ while i < m_shape.paths do
+ begin
+ if (m_shape.style(i ).left_fill >= 0 ) or
+ (m_shape.style(i ).right_fill >= 0 ) then
+ begin
+ rasc.styles(
+ m_shape.style(i ).left_fill ,
+ m_shape.style(i ).right_fill );
+
+ rasc.add_path(@shape ,m_shape.style(i ).path_id );
+
+ end;
+
+ inc(i );
+
+ end;
+
+ render_scanlines_compound(@rasc ,@sl ,@sl_bin ,@ren_base ,@alloc ,@style_handler );
+
+ tfill:=elapsed_time();
+
+// Hit-test test
+ draw_strokes:=true;
+
+ if (m_hit_x >= 0 ) and
+ (m_hit_y >= 0 ) then
+ if rasc.hit_test(m_hit_x ,m_hit_y ) then
+ draw_strokes:=false;
+
+// Draw strokes
+ start_timer;
+
+ if draw_strokes then
+ begin
+ ras.clip_box(0 ,0 ,_width ,_height );
+
+ stroke.width_ (Sqrt(m_scale.scale ) );
+ stroke.line_join_(round_join );
+ stroke.line_cap_ (round_cap );
+
+ i:=0;
+
+ while i < m_shape.paths do
+ begin
+ ras.reset;
+
+ if m_shape.style(i ).line >= 0 then
+ begin
+ ras.add_path(@stroke ,m_shape.style(i).path_id );
+
+ rgba.ConstrInt (0 ,0 ,0 ,128 );
+ ren.color_ (@rgba );
+ render_scanlines(@ras ,@sl ,@ren );
+
+ end;
+
+ inc(i );
+
+ end;
+
+ end;
+
+ tstroke:=elapsed_time;
+
+// Render Text
+ t.Construct;
+ t.size_(8.0 );
+ t.flip_(true );
+
+ ts.Construct(@t );
+ ts.width_ (1.6 );
+ ts.line_cap_(round_cap );
+
+ sprintf(@buf[0 ] ,'Fill=%.2fms ' ,tfill );
+ sprintf(@buf[StrLen(@buf ) ] ,'(%dFPS) ' ,Trunc(1000.0 / tfill ) );
+ sprintf(@buf[StrLen(@buf ) ] ,'Stroke=%.2fms ' ,tstroke );
+ sprintf(@buf[StrLen(@buf ) ] ,'(%dFPS) ' ,Trunc(1000.0 / tstroke ) );
+ sprintf(@buf[StrLen(@buf ) ] ,'Total=%.2fms ' ,tfill + tstroke );
+ sprintf(@buf[StrLen(@buf ) ] ,
+ '(%dFPS)'#13#13 +
+ 'Space: Next Shape'#13#13 +
+ '+/- : ZoomIn/ZoomOut (with respect to the mouse pointer)' ,
+ Trunc(1000.0 / (tfill + tstroke ) ) );
+
+ t.start_point_(10.0 ,20.0 );
+ t.text_ (@buf[0 ] );
+
+ ras.add_path (@ts );
+ rgba.ConstrDbl(0 ,0 ,0 );
+ ren.color_ (@rgba );
+
+ render_scanlines(@ras ,@sl ,@ren );
+
+// Gamma adjust
+ if m_gamma._gamma <> 1.0 then
+ pixf.apply_gamma_inv(@m_gamma ,bgra_order );
+
+// Free AGG resources
+ ras.Destruct;
+ rasc.Destruct;
+ sl.Destruct;
+ sl_bin.Destruct;
+
+ shape.Destruct;
+ stroke.Destruct;
+
+ alloc.Destruct;
+
+ t.Destruct;
+ ts.Destruct;
+
+end;
+
+{ ON_MOUSE_MOVE }
+procedure the_application.on_mouse_move;
+var
+ xd ,yd : double;
+
+begin
+ if flags and 3 = 0 then
+ on_mouse_button_up(x ,y ,flags )
+
+ else
+ if m_point_idx >= 0 then
+ begin
+ xd:=x;
+ yd:=y;
+
+ m_scale.inverse_transform(@m_scale ,@xd ,@yd );
+ m_shape.modify_vertex (m_point_idx ,xd ,yd );
+
+ force_redraw;
+
+ end;
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure the_application.on_mouse_button_down;
+var
+ xd ,yd ,r : double;
+
+begin
+ if flags and 1 <> 0 then
+ begin
+ xd:=x;
+ yd:=y;
+ r :=4.0 / m_scale.scale;
+
+ m_scale.inverse_transform(@m_scale ,@xd ,@yd );
+
+ m_point_idx:=m_shape.hit_test(xd ,yd ,r );
+
+ force_redraw;
+
+ end;
+
+ if flags and 2 <> 0 then
+ begin
+ m_hit_x:=x;
+ m_hit_y:=y;
+
+ force_redraw;
+
+ end;
+
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+procedure the_application.on_mouse_button_up;
+begin
+ m_point_idx:=-1;
+ m_hit_x :=-1;
+ m_hit_y :=-1;
+
+ force_redraw;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+var
+ tat : trans_affine_translation;
+ tas : trans_affine_scaling;
+ tar : trans_affine_rotation;
+
+begin
+ if key = key_f1 then
+ message_(
+ 'Demonstration of Flash compound shape rasterizer. The rasterizer accepts '#13 +
+ 'vectorial data in a form of Flash paths, that is, with two fill styles, '#13 +
+ 'fill on the left and fill on the right of the path. Then it produces a number '#13 +
+ 'of scanlines with corresponding styles and requests for the colors and/or '#13 +
+ 'gradients, images, etc. The algorithm takes care of anti-aliasing and perfect '#13 +
+ 'stitching between fill areas.'#13#13 +
+ 'How to play with:'#13#13 +
+ 'Space = Load next shape'#13 +
+ '+ & - Key = ZoomIn/ZoomOut (with respect to the mouse pointer)'#13 +
+ 'Right & Left Key = Rotate (with respect to the mouse pointer)'#13 +
+ 'Left click & drag to modify shape points' );
+
+ if key = unsigned(' ' ) then
+ begin
+ m_shape.read_next;
+ m_shape.scale(_width ,_height );
+ force_redraw;
+
+ end;
+
+ if (key = unsigned('+' ) ) or
+ (key = key_kp_plus ) then
+ begin
+ tat.Construct (-x ,-y );
+ m_scale.multiply(@tat );
+ tas.Construct (1.1 );
+ m_scale.multiply(@tas );
+ tat.Construct (x ,y );
+ m_scale.multiply(@tat );
+
+ force_redraw;
+
+ end;
+
+ if (key = unsigned('-' ) ) or
+ (key = key_kp_minus ) then
+ begin
+ tat.Construct (-x ,-y );
+ m_scale.multiply(@tat );
+ tas.Construct (1 / 1.1 );
+ m_scale.multiply(@tas );
+ tat.Construct (x ,y );
+ m_scale.multiply(@tat );
+
+ force_redraw;
+
+ end;
+
+ if key = key_left then
+ begin
+ tat.Construct (-x ,-y );
+ m_scale.multiply(@tat );
+ tar.Construct (-pi / 20.0 );
+ m_scale.multiply(@tar );
+ tat.Construct (x ,y );
+ m_scale.multiply(@tat );
+
+ force_redraw;
+
+ end;
+
+ if key = key_right then
+ begin
+ tat.Construct (-x ,-y );
+ m_scale.multiply(@tat );
+ tar.Construct (pi / 20.0 );
+ m_scale.multiply(@tar );
+ tat.Construct (x ,y );
+ m_scale.multiply(@tat );
+
+ force_redraw;
+
+ end;
+
+end;
+
+VAR
+ app : the_application;
+ buf : array[0..255 ] of char;
+
+ fname ,p ,n ,x : shortstring;
+
+BEGIN
+ app.Construct(pix_format_bgra32 ,flip_y );
+ app.caption_ ('AGG Example - Flash Rasterizer (F1-Help)' );
+
+ fname:='shapes.txt';
+
+{$IFDEF WIN32 }
+ if ParamCount > 0 then
+ begin
+ spread_name(ParamStr(1 ) ,p ,n ,x );
+
+ fname:=fold_name(p ,n ,x );
+
+ end;
+
+{$ENDIF }
+
+ if not app.open(fname ) then
+ begin
+ fname:=fname + #0;
+
+ if StrComp(@fname[1 ] ,'shapes.txt'#0 ) = 0 then
+ begin
+ sprintf(@buf[0 ] ,'File not found: %s. '#13 ,unsigned(@fname[1 ] ) );
+ sprintf(
+ @buf[StrLen(@buf ) ] ,
+ 'Download http://www.antigrain.com/%s'#13 +
+ 'or copy it from another directory if available.' ,
+ unsigned(@fname[1 ] ) );
+
+ end
+ else
+ sprintf(@buf[0 ] ,'File not found: %s' ,unsigned(@fname[1 ] ) );
+
+ app.message_(@buf[0 ] );
+
+ end
+ else
+ if app.init(655 ,520 ,window_resize ) then
+ begin
+ app.read_next;
+ app.run;
+
+ end;
+
+ app.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/flash_rasterizer2.dpr b/src/corelib/render/software/agg-demos/flash_rasterizer2.dpr
new file mode 100644
index 00000000..e29f6536
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/flash_rasterizer2.dpr
@@ -0,0 +1,983 @@
+{mac_copy:shapes.txt}
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ flash_rasterizer2 ;
+
+uses
+ SysUtils ,
+ agg_basics ,
+ agg_array ,
+ agg_color ,
+ agg_platform_support ,
+ agg_rendering_buffer ,
+ agg_trans_viewport ,
+ agg_path_storage ,
+ agg_conv_transform ,
+ agg_conv_curve ,
+ agg_conv_stroke ,
+ agg_gsv_text ,
+ agg_scanline_u ,
+ agg_scanline_bin ,
+ agg_renderer_scanline ,
+ agg_rasterizer_outline_aa ,
+ agg_rasterizer_scanline_aa ,
+ agg_span_allocator ,
+ agg_gamma_lut ,
+ agg_pixfmt ,
+ agg_pixfmt_rgba ,
+ agg_bounding_rect ,
+ agg_vertex_source ,
+ agg_trans_affine ,
+ agg_math ,
+ agg_math_stroke ,
+ agg_renderer_base ,
+ agg_render_scanlines ,
+ file_utils_ ;
+
+{$I agg_mode.inc }
+
+const
+ flip_y = false;
+
+type
+ path_style_ptr = ^path_style;
+ path_style = record
+ path_id : unsigned;
+
+ left_fill ,
+ right_fill ,
+ line : int;
+
+ end;
+
+ compound_shape = object(vertex_source )
+ private
+ m_path : path_storage;
+ m_affine : trans_affine;
+ m_curve : conv_curve;
+ m_trans : conv_transform;
+ m_styles : pod_bvector;
+
+ m_x1 ,
+ m_y1 ,
+ m_x2 ,
+ m_y2 : double;
+
+ m_min_style ,
+ m_max_style : int;
+
+ m_fd : api_file;
+
+ public
+ constructor Construct;
+ destructor Destruct; virtual;
+
+ function open(fname : AnsiString ) : boolean;
+ function read_next : boolean;
+
+ function operator_array(i : unsigned ) : unsigned; virtual;
+ function paths : unsigned;
+ function style(i : unsigned ) : path_style_ptr;
+
+ function min_style : int;
+ function max_style : int;
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ function scale : double; overload;
+ procedure scale(w ,h : double ); overload;
+
+ procedure approximation_scale(s : double );
+
+ function hit_test(x ,y ,r : double ) : int;
+
+ procedure modify_vertex(i : unsigned; x ,y : double );
+
+ end;
+
+ the_application = object(platform_support )
+ private
+ m_shape : compound_shape;
+ m_colors : array[0..99 ] of aggclr;
+ m_scale : trans_affine;
+ m_gamma : gamma_lut;
+
+ m_point_idx : int;
+
+ public
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ function open(fname : AnsiString ) : boolean;
+ procedure read_next;
+
+ procedure on_draw; virtual;
+
+ procedure on_mouse_move (x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_up (x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ CONSTRUCT }
+constructor compound_shape.Construct;
+begin
+ m_path.Construct;
+ m_affine.Construct;
+ m_curve.Construct (@m_path );
+ m_trans.Construct (@m_curve ,@m_affine );
+ m_styles.Construct(sizeof(path_style ) );
+
+ m_min_style:=$7FFFFFFF;
+ m_max_style:=-$7FFFFFFF;
+
+end;
+
+{ DESTRUCT }
+destructor compound_shape.Destruct;
+begin
+ m_path.Destruct;
+ m_curve.Destruct;
+ m_styles.Destruct;
+
+ if m_fd.isOpened then
+ api_close_file(m_fd );
+
+end;
+
+{ OPEN }
+function compound_shape.open(fname : AnsiString ) : boolean;
+begin
+ result:=api_open_file(m_fd ,fname );
+
+end;
+
+{ fgets }
+function fgets(buf : char_ptr; max : int; var f : api_file ) : char_ptr;
+var
+ read : int;
+
+begin
+ result:=buf;
+
+ while max > 1 do
+ begin
+ if not api_read_file(f ,buf ,1 ,read ) then
+ begin
+ result:=NIL;
+
+ exit;
+
+ end;
+
+ if read = 0 then
+ if buf = result then
+ begin
+ result:=NIL;
+
+ exit;
+
+ end
+ else
+ break;
+
+ case buf^ of
+ #13 ,#10 ,#9 :
+ break;
+
+ end;
+
+ dec(max );
+ inc(ptrcomp(buf ) ,read );
+
+ end;
+
+ if max >= 1 then
+ buf^:=#0;
+
+end;
+
+var
+ g_buff : char_ptr;
+
+{ strtok }
+function strtok(buff : char_ptr ) : char_ptr;
+begin
+ result:=NIL;
+
+ if buff <> NIL then
+ g_buff:=buff;
+
+ while (g_buff <> NIL ) and
+ (g_buff^ <> #0 ) do
+ begin
+ if result = NIL then
+ result:=g_buff;
+
+ case g_buff^ of
+ ' ' ,#13 ,#10 :
+ begin
+ g_buff^:=#0;
+
+ inc(ptrcomp(g_buff ) );
+
+ break;
+
+ end;
+
+ end;
+
+ inc(ptrcomp(g_buff ) );
+
+ end;
+
+end;
+
+{ READ_NEXT }
+function compound_shape.read_next : boolean;
+var
+ ax ,ay ,cx ,cy : double;
+
+ buf : array[0..1023 ] of char;
+
+ ts : char_ptr;
+
+ style_ : path_style;
+
+ code : int;
+
+begin
+ m_path.remove_all;
+ m_styles.remove_all;
+
+ m_min_style:=$7FFFFFFF;
+ m_max_style:=-$7FFFFFFF;
+
+ if m_fd.isOpened then
+ begin
+ repeat
+ if fgets(@buf[0 ] ,1022 ,m_fd ) = NIL then
+ begin
+ result:=false;
+
+ exit;
+
+ end;
+
+ if buf[0 ] = '=' then
+ break;
+
+ until false;
+
+ while fgets(@buf[0 ] ,1022 ,m_fd ) <> NIL do
+ begin
+ if buf[0 ] = '!' then
+ break;
+
+ if buf[0 ] = 'P' then
+ begin
+ // BeginPath
+ style_.path_id:=m_path.start_new_path;
+
+ ts:=strtok(@buf[0 ] ); // Path;
+ ts:=strtok(NIL ); // left_style
+
+ Val(PChar(ts ) ,style_.left_fill ,code );
+
+ ts:=strtok(NIL ); // right_style
+
+ Val(PChar(ts ) ,style_.right_fill ,code );
+
+ ts:=strtok(NIL ); // line_style
+
+ Val(PChar(ts ) ,style_.line ,code );
+
+ ts:=strtok(NIL ); // ax
+
+ Val(PChar(ts ) ,ax ,code );
+
+ ts:=strtok(NIL ); // ay
+
+ Val(PChar(ts ) ,ay ,code );
+
+ m_path.move_to(ax ,ay );
+ m_styles.add (@style_ );
+
+ if style_.left_fill >= 0 then
+ begin
+ if style_.left_fill < m_min_style then
+ m_min_style:=style_.left_fill;
+
+ if style_.left_fill > m_max_style then
+ m_max_style:=style_.left_fill;
+
+ end;
+
+ if style_.right_fill >= 0 then
+ begin
+ if style_.right_fill < m_min_style then
+ m_min_style:=style_.right_fill;
+
+ if style_.right_fill > m_max_style then
+ m_max_style:=style_.right_fill;
+
+ end;
+
+ end;
+
+ if buf[0 ] = 'C' then
+ begin
+ ts:=strtok(@buf[0 ] ); // Curve;
+ ts:=strtok(NIl ); // cx
+
+ Val(PChar(ts ) ,cx ,code );
+
+ ts:=strtok(NIL ); // cy
+
+ Val(PChar(ts ) ,cy ,code );
+
+ ts:=strtok(NIL ); // ax
+
+ Val(PChar(ts ) ,ax ,code );
+
+ ts:=strtok(NIL ); // ay
+
+ Val(PChar(ts ) ,ay ,code );
+
+ m_path.curve3(cx ,cy ,ax ,ay );
+
+ end;
+
+ if buf[0 ] = 'L' then
+ begin
+ ts:=strtok(@buf[0 ] ); // Line;
+ ts:=strtok(NIL ); // ax
+
+ Val(PChar(ts ) ,ax ,code );
+
+ ts:=strtok(NIL ); // ay
+
+ Val(PChar(ts ) ,ay ,code );
+
+ m_path.line_to(ax ,ay );
+
+ end;
+
+ if buf[0 ] = '<' then
+ begin
+ // EndPath
+ end;
+
+ end;
+
+ result:=true;
+
+ end
+ else
+ result:=false;
+
+end;
+
+{ OPERATOR_ARRAY }
+function compound_shape.operator_array(i : unsigned ) : unsigned;
+begin
+ result:=path_style_ptr(m_styles.array_operator(i ) )^.path_id;
+
+end;
+
+{ PATHS }
+function compound_shape.paths : unsigned;
+begin
+ result:=m_styles.size;
+
+end;
+
+{ STYLE }
+function compound_shape.style(i : unsigned ) : path_style_ptr;
+begin
+ result:=path_style_ptr(m_styles.array_operator(i ) );
+
+end;
+
+{ MIN_STYLE }
+function compound_shape.min_style : int;
+begin
+ result:=m_min_style;
+
+end;
+
+{ MAX_STYLE }
+function compound_shape.max_style : int;
+begin
+ result:=m_max_style;
+
+end;
+
+{ REWIND }
+procedure compound_shape.rewind(path_id : unsigned );
+begin
+ m_trans.rewind(path_id );
+
+end;
+
+{ VERTEX }
+function compound_shape.vertex(x ,y : double_ptr ) : unsigned;
+begin
+ result:=m_trans.vertex(x ,y );
+
+end;
+
+{ SCALE }
+function compound_shape.scale : double;
+begin
+ result:=m_affine.scale;
+
+end;
+
+{ SCALE }
+procedure compound_shape.scale(w ,h : double );
+var
+ x1 ,y1 ,x2 ,y2 : double;
+
+ vp : trans_viewport;
+
+begin
+ m_affine.reset;
+
+ bounding_rect_vs(
+ @m_path ,@self ,0 ,m_styles.size ,
+ @x1 ,@y1 ,@x2 ,@y2 );
+
+ if (x1 < x2 ) and
+ (y1 < y2 ) then
+ begin
+ vp.Construct;
+ vp.preserve_aspect_ratio(0.5 ,0.5 ,aspect_ratio_meet );
+
+ vp.world_viewport (x1 ,y1 ,x2 ,y2 );
+ vp.device_viewport(0 ,0 ,w ,h );
+ vp.to_affine (@m_affine );
+
+ end;
+
+ m_curve.approximation_scale_(m_affine.scale );
+
+end;
+
+{ APPROXIMATION_SCALE }
+procedure compound_shape.approximation_scale(s : double );
+begin
+ m_curve.approximation_scale_(m_affine.scale * s );
+
+end;
+
+{ HIT_TEST }
+function compound_shape.hit_test(x ,y ,r : double ) : int;
+var
+ i ,cmd : unsigned;
+ vx ,vy : double;
+
+begin
+ m_affine.inverse_transform(@m_affine ,@x ,@y );
+
+ r:=r / m_affine.scale;
+ i:=0;
+
+ while i < m_path.total_vertices do
+ begin
+ cmd:=m_path.vertex_(i ,@vx ,@vy );
+
+ if is_vertex(cmd ) then
+ if calc_distance(x ,y ,vx ,vy ) <= r then
+ begin
+ result:=i;
+
+ exit;
+
+ end;
+
+ inc(i );
+
+ end;
+
+ result:=-1;
+
+end;
+
+{ MODIFY_VERTEX }
+procedure compound_shape.modify_vertex(i : unsigned; x ,y : double );
+begin
+ m_affine.inverse_transform(@m_affine ,@x ,@y );
+ m_path.modify_vertex (i ,x ,y );
+
+end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+var
+ i : unsigned;
+
+ c1 ,c2 ,c3 : int;
+
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_shape.Construct;
+ m_scale.Construct;
+ m_gamma.Construct_;
+
+ m_gamma.gamma_(2.0 );
+
+ m_point_idx:=-1;
+
+ i:=0;
+
+ while i < 100 do
+ begin
+ c1:=rand and $FF;
+ c2:=rand and $FF;
+ c3:=rand and $FF;
+
+ m_colors[i ].ConstrInt(c3 ,c2 ,c1 ,230 );
+
+ m_colors[i ].apply_gamma_dir(@m_gamma );
+ m_colors[i ].premultiply;
+
+ inc(i );
+
+ end;
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_shape.Destruct;
+ m_gamma.Destruct;
+
+end;
+
+{ OPEN }
+function the_application.open(fname : AnsiString ) : boolean;
+begin
+ result:=m_shape.open(full_file_name(fname ) );
+
+end;
+
+{ READ_NEXT }
+procedure the_application.read_next;
+begin
+ m_shape.read_next;
+ m_shape.scale(_width ,_height );
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ pixf : pixel_formats;
+ rgba : aggclr;
+
+ ren_base : renderer_base;
+
+ ren : renderer_scanline_aa_solid;
+ ras : rasterizer_scanline_aa;
+ sl : scanline_u8;
+
+ shape : conv_transform;
+ stroke : conv_stroke;
+
+ i : unsigned;
+ s : int;
+
+ tmp_path : path_storage;
+
+ style : path_style_ptr;
+
+ tfill ,tstroke : double;
+
+ buf : array[0..255 ] of char;
+
+ t : gsv_text;
+ ts : conv_stroke;
+
+begin
+// Initialize structures
+ pixfmt_bgra32_pre(pixf ,rbuf_window );
+
+ ren_base.Construct(@pixf );
+
+ rgba.ConstrDbl(1.0 ,1.0 ,0.95 );
+ ren_base.clear(@rgba );
+
+ ren.Construct(@ren_base );
+ ras.Construct;
+ sl.Construct;
+
+ shape.Construct (@m_shape ,@m_scale );
+ stroke.Construct(@shape );
+
+ m_shape.approximation_scale(m_scale.scale );
+
+ tmp_path.Construct;
+
+{ ras.clip_box(0 ,0 ,_width ,_height ); {!}
+
+// This is an alternative method of Flash rasterization.
+// We decompose the compound shape into separate paths
+// and select the ones that fit the given style (left or right).
+// So that, we form a sub-shape and draw it as a whole.
+//
+// Here the regular scanline rasterizer is used, but it doesn't
+// automatically close the polygons. So that, the rasterizer
+// actually works with a set of polylines instead of polygons.
+// Of course, the data integrity must be preserved, that is,
+// the polylines must eventually form a closed contour
+// (or a set of closed contours). So that, first we set
+// auto_close(false);
+//
+// The second important thing is that one path can be rasterized
+// twice, if it has both, left and right fill. Sometimes the
+// path has equal left and right fill, so that, the same path
+// will be added twice even for a single sub-shape. If the
+// rasterizer can tolerate these degenerates you can add them,
+// but it's also fine just to omit them.
+//
+// The third thing is that for one side (left or right)
+// you should invert the direction of the paths.
+//
+// The main disadvantage of this method is imperfect stitching
+// of the adjacent polygons. The problem can be solved if we use
+// compositing operation "plus" instead of alpha-blend. But
+// in this case we are forced to use an RGBA buffer, clean it with
+// zero, rasterize using "plus" operation, and then alpha-blend
+// the result over the final scene. It can be too expensive.
+//------------------------------------------------------------
+ ras.auto_close (false );
+ ras.filling_rule(fill_even_odd );
+
+ start_timer;
+
+ s:=m_shape.min_style;
+
+ while s <= m_shape.max_style do
+ begin
+ ras.reset;
+
+ i:=0;
+
+ while i < m_shape.paths do
+ begin
+ style:=m_shape.style(i );
+
+ if style.left_fill <> style.right_fill then
+ begin
+ if style.left_fill = s then
+ ras.add_path(@shape ,style.path_id );
+
+ if style.right_fill = s then
+ begin
+ tmp_path.remove_all;
+ tmp_path.concat_path (@shape ,style.path_id );
+ tmp_path.invert_polygon(0 );
+
+ ras.add_path(@tmp_path );
+
+ end;
+
+ end;
+
+ inc(i );
+
+ end;
+
+ ren.color_ (@m_colors[s ] );
+ render_scanlines(@ras ,@sl ,@ren );
+
+ inc(s );
+
+ end;
+
+ tfill:=elapsed_time;
+
+ ras.auto_close (true );
+ ras.filling_rule(fill_non_zero );
+
+// Draw strokes
+ start_timer;
+
+ stroke.width_ (Sqrt(m_scale.scale ) );
+ stroke.line_join_(round_join );
+ stroke.line_cap_ (round_cap );
+
+ i:=0;
+
+ while i < m_shape.paths do
+ begin
+ ras.reset;
+
+ if path_style_ptr(m_shape.style(i ) ).line >= 0 then
+ begin
+ ras.add_path(@stroke ,path_style_ptr(m_shape.style(i ) ).path_id );
+
+ rgba.ConstrInt(0 ,0 ,0 ,128 );
+ ren.color_ (@rgba );
+
+ render_scanlines(@ras ,@sl ,@ren );
+
+ end;
+
+ inc(i );
+
+ end;
+
+ tstroke:=elapsed_time;
+
+// Render Text
+ t.Construct;
+ t.size_(8.0 );
+ t.flip_(true );
+
+ ts.Construct(@t );
+ ts.width_ (1.6 );
+ ts.line_cap_(round_cap );
+
+ sprintf(@buf[0 ] ,'Fill=%.2fms ' ,tfill );
+ sprintf(@buf[StrLen(@buf ) ] ,'(%dFPS) ' ,Trunc(1000.0 / tfill ) );
+ sprintf(@buf[StrLen(@buf ) ] ,'Stroke=%.2fms ' ,tstroke );
+ sprintf(@buf[StrLen(@buf ) ] ,'(%dFPS) ' ,Trunc(1000.0 / tstroke ) );
+ sprintf(@buf[StrLen(@buf ) ] ,'Total=%.2fms ' ,tfill + tstroke );
+ sprintf(@buf[StrLen(@buf ) ] ,
+ '(%dFPS)'#13#13 +
+ 'Space: Next Shape'#13#13 +
+ '+/- : ZoomIn/ZoomOut (with respect to the mouse pointer)' ,
+ Trunc(1000.0 / (tfill + tstroke ) ) );
+
+ t.start_point_(10.0 ,20.0 );
+ t.text_ (@buf[0 ] );
+
+ ras.add_path (@ts );
+ rgba.ConstrDbl(0 ,0 ,0 );
+ ren.color_ (@rgba );
+
+ render_scanlines(@ras ,@sl ,@ren );
+
+// Gamma adjust
+ if m_gamma._gamma <> 1.0 then
+ pixf.apply_gamma_inv(@m_gamma ,bgra_order );
+
+// Free AGG resources
+ ras.Destruct;
+ sl.Destruct;
+
+ shape.Destruct;
+ stroke.Destruct;
+
+ tmp_path.Destruct;
+
+ t.Destruct;
+ ts.Destruct;
+
+end;
+
+{ ON_MOUSE_MOVE }
+procedure the_application.on_mouse_move;
+var
+ xd ,yd : double;
+
+begin
+ if flags and 1 = 0 then
+ on_mouse_button_up(x ,y ,flags )
+ else
+ if m_point_idx >= 0 then
+ begin
+ xd:=x;
+ yd:=y;
+
+ m_scale.inverse_transform(@m_scale ,@xd ,@yd );
+ m_shape.modify_vertex (m_point_idx ,xd ,yd );
+
+ force_redraw;
+
+ end;
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure the_application.on_mouse_button_down;
+var
+ xd ,yd ,r : double;
+
+begin
+ if flags and 1 <> 0 then
+ begin
+ xd:=x;
+ yd:=y;
+ r :=4.0 / m_scale.scale;
+
+ m_scale.inverse_transform(@m_scale ,@xd ,@yd );
+
+ m_point_idx:=m_shape.hit_test(xd ,yd ,r );
+
+ force_redraw;
+
+ end;
+
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+procedure the_application.on_mouse_button_up;
+begin
+ m_point_idx:=-1;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+var
+ tat : trans_affine_translation;
+ tas : trans_affine_scaling;
+ tar : trans_affine_rotation;
+
+begin
+ if key = key_f1 then
+ message_(
+ 'Another possible way to render Flash compound shapes. The idea behind '#13 +
+ 'it is prety simple. You just use the regular rasterizer, but in a mode when'#13 +
+ 'it doesn''t automatically close the contours. Every compound shape is'#13 +
+ 'decomposed into a number of single shapes that are rasterized '#13 +
+ 'and rendered separately.'#13#13 +
+ 'How to play with:'#13#13 +
+ 'Space = Load next shape'#13 +
+ '+ & - Key = ZoomIn/ZoomOut (with respect to the mouse pointer)'#13 +
+ 'Right & Left Key = Rotate (with respect to the mouse pointer)'#13 +
+ 'Left click & drag to modify shape points' );
+
+ if key = unsigned(' ' ) then
+ begin
+ m_shape.read_next;
+ m_shape.scale(_width ,_height );
+ force_redraw;
+
+ end;
+
+ if (key = unsigned('+' ) ) or
+ (key = key_kp_plus ) then
+ begin
+ tat.Construct (-x ,-y );
+ m_scale.multiply(@tat );
+ tas.Construct (1.1 );
+ m_scale.multiply(@tas );
+ tat.Construct (x ,y );
+ m_scale.multiply(@tat );
+
+ force_redraw;
+
+ end;
+
+ if (key = unsigned('-' ) ) or
+ (key = key_kp_minus ) then
+ begin
+ tat.Construct (-x ,-y );
+ m_scale.multiply(@tat );
+ tas.Construct (1 / 1.1 );
+ m_scale.multiply(@tas );
+ tat.Construct (x ,y );
+ m_scale.multiply(@tat );
+
+ force_redraw;
+
+ end;
+
+ if key = key_left then
+ begin
+ tat.Construct (-x ,-y );
+ m_scale.multiply(@tat );
+ tar.Construct (-pi / 20.0 );
+ m_scale.multiply(@tar );
+ tat.Construct (x ,y );
+ m_scale.multiply(@tat );
+
+ force_redraw;
+
+ end;
+
+ if key = key_right then
+ begin
+ tat.Construct (-x ,-y );
+ m_scale.multiply(@tat );
+ tar.Construct (pi / 20.0 );
+ m_scale.multiply(@tar );
+ tat.Construct (x ,y );
+ m_scale.multiply(@tat );
+
+ force_redraw;
+
+ end;
+
+end;
+
+VAR
+ app : the_application;
+ buf : array[0..255 ] of char;
+
+ fname ,p ,n ,x : shortstring;
+
+BEGIN
+ app.Construct(pix_format_bgra32 ,flip_y );
+ app.caption_ ('AGG Example - Flash Rasterizer with separate rendering (F1-Help)' );
+
+ fname:='shapes.txt';
+
+{$IFDEF WIN32 }
+ if ParamCount > 0 then
+ begin
+ spread_name(ParamStr(1 ) ,p ,n ,x );
+
+ fname:=fold_name(p ,n ,x );
+
+ end;
+
+{$ENDIF }
+
+ if not app.open(fname ) then
+ begin
+ fname:=fname + #0;
+
+ if StrComp(@fname[1 ] ,'shapes.txt'#0 ) = 0 then
+ begin
+ sprintf(@buf[0 ] ,'File not found: %s. '#13 ,unsigned(@fname[1 ] ) );
+ sprintf(
+ @buf[StrLen(@buf ) ] ,
+ 'Download http://www.antigrain.com/%s'#13 +
+ 'or copy it from another directory if available.' ,
+ unsigned(@fname[1 ] ) );
+
+ end
+ else
+ sprintf(@buf[0 ] ,'File not found: %s' ,unsigned(@fname[1 ] ) );
+
+ app.message_(@buf[0 ] );
+
+ end
+ else
+ if app.init(655 ,520 ,window_resize ) then
+ begin
+ app.read_next;
+ app.run;
+
+ end;
+
+ app.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/freetype_test.dpr b/src/corelib/render/software/agg-demos/freetype_test.dpr
new file mode 100644
index 00000000..14ff1b6b
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/freetype_test.dpr
@@ -0,0 +1,698 @@
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ freetype_test ;
+
+uses
+ SysUtils ,
+
+ agg_basics ,
+ agg_platform_support ,
+
+ agg_color ,
+ agg_pixfmt ,
+ agg_pixfmt_rgb ,
+
+ agg_ctrl ,
+ agg_slider_ctrl ,
+ agg_cbox_ctrl ,
+ agg_rbox_ctrl ,
+
+ agg_rendering_buffer ,
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_renderer_primitives ,
+ agg_rasterizer_scanline_aa ,
+ agg_scanline ,
+ agg_scanline_u ,
+ agg_scanline_bin ,
+ agg_render_scanlines ,
+
+ agg_trans_affine ,
+ agg_curves ,
+ agg_conv_curve ,
+ agg_conv_contour ,
+ agg_gamma_lut ,
+ agg_gamma_functions ,
+ agg_font_freetype ,
+ agg_font_cache_manager ;
+
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+ angle_step = 0.5;
+
+ text_ : PChar =
+ //'0123456789ABCDEFGHIJKLMNOPRSTUVWXYZabcdefghijklmnoprstuvwxyz ' +
+ //'[ BRAVO ][ VALUE ] [ T.W.Lewis ] [ Kerning Examples ] ' +
+ 'Anti-Grain Geometry is designed as a set of loosely coupled ' +
+ 'algorithms and class templates united with a common idea, ' +
+ 'so that all the components can be easily combined. Also, ' +
+ 'the template based design allows you to replace any part of ' +
+ 'the library without the necessity to modify a single byte in ' +
+ 'the existing code. ' +
+ 'AGG is designed keeping in mind extensibility and flexibility. ' +
+ 'Basically I just wanted to create a toolkit that would allow me ' +
+ '(and anyone else) to add new fancy algorithms very easily. ' +
+ 'AGG does not dictate you any style of its use, you are free to ' +
+ 'use any part of it. However, AGG is often associated with a tool ' +
+ 'for rendering images in memory. That is not quite true, but it can ' +
+ 'be a good starting point in studying. The tutorials describe the ' +
+ 'use of AGG starting from the low level functionality that deals with ' +
+ 'frame buffers and pixels. Then you will gradually understand how to ' +
+ 'abstract different parts of the library and how to use them separately. ' +
+ 'Remember, the raster picture is often not the only thing you want to ' +
+ 'obtain, you will probably want to print your graphics with highest ' +
+ 'possible quality and in this case you can easily combine the "vectorial" ' +
+ 'part of the library with some API like Windows GDI, having a common ' +
+ 'external interface. If that API can render multi-polygons with non-zero ' +
+ 'and even-odd filling rules it''s all you need to incorporate AGG into ' +
+ 'your application. For example, Windows API PolyPolygon perfectly fits ' +
+ 'these needs, except certain advanced things like gradient filling, ' +
+ 'Gouraud shading, image transformations, and so on. Or, as an alternative, ' +
+ 'you can use all AGG algorithms producing high resolution pixel images and ' +
+ 'then to send the result to the printer as a pixel map.' +
+ 'Below is a typical brief scheme of the AGG rendering pipeline. ' +
+ 'Please note that any component between the Vertex Source ' +
+ 'and Screen Output is not mandatory. It all depends on your ' +
+ 'particular needs. For example, you can use your own rasterizer, ' +
+ 'based on Windows API. In this case you won''t need the AGG rasterizer ' +
+ 'and renderers. Or, if you need to draw only lines, you can use the ' +
+ 'AGG outline rasterizer that has certain restrictions but works faster. ' +
+ 'The number of possibilities is endless. ' +
+ 'Vertex Source is some object that produces polygons or polylines as ' +
+ 'a set of consecutive 2D vertices with commands like MoveTo, LineTo. ' +
+ 'It can be a container or some other object that generates vertices ' +
+ 'on demand. ' +
+ 'Coordinate conversion pipeline consists of a number of coordinate ' +
+ 'converters. It always works with vectorial data (X,Y) represented ' +
+ 'as floating point numbers (double). For example, it can contain an ' +
+ 'affine transformer, outline (stroke) generator, some marker ' +
+ 'generator (like arrowheads/arrowtails), dashed lines generator, ' +
+ 'and so on. The pipeline can have branches and you also can have ' +
+ 'any number of different pipelines. You also can write your own ' +
+ 'converter and include it into the pipeline. ' +
+ 'Scanline Rasterizer converts vectorial data into a number of ' +
+ 'horizontal scanlines. The scanlines usually (but not obligatory) ' +
+ 'carry information about Anti-Aliasing as coverage values. ' +
+ 'Renderers render scanlines, sorry for the tautology. The simplest ' +
+ 'example is solid filling. The renderer just adds a color to the ' +
+ 'scanline and writes the result into the rendering buffer. ' +
+ 'More complex renderers can produce multi-color result, ' +
+ 'like gradients, Gouraud shading, image transformations, ' +
+ 'patterns, and so on. Rendering Buffer is a buffer in memory ' +
+ 'that will be displayed afterwards. Usually but not obligatory ' +
+ 'it contains pixels in format that fits your video system. ' +
+ 'For example, 24 bits B-G-R, 32 bits B-G-R-A, or 15 ' +
+ 'bits R-G-B-555 for Windows. But in general, there''re no ' +
+ 'restrictions on pixel formats or color space if you write ' +
+ 'your own low level class that supports that format. ' +
+ 'Colors in AGG appear only in renderers, that is, when you ' +
+ 'actually put some data to the rendering buffer. In general, ' +
+ 'there''s no general purpose structure or class like color, ' +
+ 'instead, AGG always operates with concrete color space. ' +
+ 'There are plenty of color spaces in the world, like RGB, ' +
+ 'HSV, CMYK, etc., and all of them have certain restrictions. ' +
+ 'For example, the RGB color space is just a poor subset of ' +
+ 'colors that a human eye can recognize. If you look at the full ' +
+ 'CIE Chromaticity Diagram, you will see that the RGB triangle ' +
+ 'is just a little part of it. ' +
+ 'In other words there are plenty of colors in the real world ' +
+ 'that cannot be reproduced with RGB, CMYK, HSV, etc. Any color ' +
+ 'space except the one existing in Nature is restrictive. Thus, ' +
+ 'it was decided not to introduce such an object like color in ' +
+ 'order not to restrict the possibilities in advance. Instead, ' +
+ 'there are objects that operate with concrete color spaces. ' +
+ 'Currently there are agg::rgba and agg::rgba8 that operate ' +
+ 'with the most popular RGB color space (strictly speaking there''s ' +
+ 'RGB plus Alpha). The RGB color space is used with different ' +
+ 'pixel formats, like 24-bit RGB or 32-bit RGBA with different ' +
+ 'order of color components. But the common property of all of ' +
+ 'them is that they are essentially RGB. Although, AGG doesn''t ' +
+ 'explicitly support any other color spaces, there is at least ' +
+ 'a potential possibility of adding them. It means that all ' +
+ 'class and function templates that depend on the color type ' +
+ 'are parameterized with the ColorT argument. ' +
+ 'Basically, AGG operates with coordinates of the output device. ' +
+ 'On your screen there are pixels. But unlike many other libraries ' +
+ 'and APIs AGG initially supports Subpixel Accuracy. It means ' +
+ 'that the coordinates are represented as doubles, where fractional ' +
+ 'values actually take effect. AGG doesn''t have an embedded ' +
+ 'conversion mechanism from world to screen coordinates in order ' +
+ 'not to restrict your freedom. It''s very important where and when ' +
+ 'you do that conversion, so, different applications can require ' +
+ 'different approaches. AGG just provides you a transformer of ' +
+ 'that kind, namely, that can convert your own view port to the ' +
+ 'device one. And it''s your responsibility to include it into ' +
+ 'the proper place of the pipeline. You can also write your ' +
+ 'own very simple class that will allow you to operate with ' +
+ 'millimeters, inches, or any other physical units. ' +
+ 'Internally, the rasterizers use integer coordinates of the ' +
+ 'format 24.8 bits, that is, 24 bits for the integer part and 8 ' +
+ 'bits for the fractional one. In other words, all the internal ' +
+ 'coordinates are multiplied by 256. If you intend to use AGG in ' +
+ 'some embedded system that has inefficient floating point ' +
+ 'processing, you still can use the rasterizers with their ' +
+ 'integer interfaces. Although, you won''t be able to use the ' +
+ 'floating point coordinate pipelines in this case. ';
+
+var
+ font_flip_y : boolean;
+ font_name : AnsiString;
+
+type
+ the_application = object(platform_support )
+ m_ren_type : rbox_ctrl;
+
+ m_height ,
+ m_width ,
+ m_weight ,
+ m_gamma : slider_ctrl;
+
+ m_hinting ,
+ m_kerning ,
+ m_performance : cbox_ctrl;
+
+ m_feng : font_engine_freetype_int32;
+ m_fman : font_cache_manager;
+
+ m_old_height : double;
+ m_gamma_lut : gamma_lut;
+
+ // Pipeline to process the vectors glyph paths (curves + contour)
+ m_curves : conv_curve;
+ m_contour : conv_contour;
+
+ m_angle : double;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ function draw_text(
+ ras : rasterizer_scanline_aa_ptr;
+ sl : scanline_ptr;
+ ren_solid : renderer_scanline_aa_solid_ptr;
+ ren_bin : renderer_scanline_bin_solid_ptr ) : unsigned;
+
+ procedure on_draw; virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+ procedure on_ctrl_change; virtual;
+
+ end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_ren_type.Construct (5.0 ,5.0 ,5.0 + 150.0 ,110.0 ,not flip_y_ );
+ m_height.Construct (160 ,10.0 ,640 - 5.0 ,18.0 ,not flip_y_ );
+ m_width.Construct (160 ,30.0 ,640 - 5.0 ,38.0 ,not flip_y_ );
+ m_weight.Construct (160 ,50.0 ,640 - 5.0 ,58.0 ,not flip_y_ );
+ m_gamma.Construct (260 ,70.0 ,640 - 5.0 ,78.0 ,not flip_y_ );
+ m_hinting.Construct (160 ,65.0 ,'Hinting' ,not flip_y_ );
+ m_kerning.Construct (160 ,80.0 ,'Kerning' ,not flip_y_ );
+ m_performance.Construct(160 ,95.0 ,'Test Performance' ,not flip_y_ );
+
+ m_feng.Construct;
+ m_fman.Construct(@m_feng );
+
+ m_old_height:=0.0;
+
+ m_gamma_lut.Construct_(8 ,16 );
+ m_curves.Construct (m_fman.path_adaptor );
+ m_contour.Construct (@m_curves );
+
+ m_ren_type.add_item ('Native Mono' );
+ m_ren_type.add_item ('Native Gray 8' );
+ m_ren_type.add_item ('Outline' );
+ m_ren_type.add_item ('AGG Mono' );
+ m_ren_type.add_item ('AGG Gray 8' );
+ m_ren_type.cur_item_(1 );
+
+ add_ctrl(@m_ren_type );
+
+ m_ren_type.no_transform;
+
+ m_height.label_('Font Height=%.2f' );
+ m_height.range_(8, 32);
+ m_height.value_(18 );
+
+ m_height.num_steps_ (32 - 8 );
+ m_height.text_thickness_(1.5 );
+
+ add_ctrl(@m_height );
+
+ m_height.no_transform;
+
+ m_width.label_('Font Width=%.2f' );
+ m_width.range_(8 ,32 );
+ m_width.value_(18 );
+
+ m_width.num_steps_ (32 - 8 );
+ m_width.text_thickness_(1.5 );
+
+ add_ctrl(@m_width );
+
+ m_width.no_transform;
+
+ m_weight.label_('Font Weight=%.2f' );
+ m_weight.range_(-1 ,1 );
+
+ m_weight.text_thickness_(1.5 );
+
+ add_ctrl(@m_weight );
+
+ m_weight.no_transform;
+
+ m_gamma.label_('Gamma=%.2f' );
+ m_gamma.range_(0.1 ,2.0 );
+ m_gamma.value_(1.0 );
+
+ m_gamma.text_thickness_(1.5 );
+
+ add_ctrl(@m_gamma );
+
+ m_gamma.no_transform;
+
+ add_ctrl(@m_hinting );
+
+ m_hinting.status_(true );
+ m_hinting.no_transform;
+
+ add_ctrl(@m_kerning );
+
+ m_kerning.status_(true );
+ m_kerning.no_transform;
+
+ add_ctrl(@m_performance );
+
+ m_performance.no_transform;
+
+ m_curves.approximation_scale_ (2.0 );
+ m_contour.auto_detect_orientation_(false );
+
+ m_angle:=0;
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_ren_type.Destruct;
+ m_height.Destruct;
+ m_width.Destruct;
+ m_weight.Destruct;
+ m_gamma.Destruct;
+ m_hinting.Destruct;
+ m_kerning.Destruct;
+ m_performance.Destruct;
+
+ m_feng.Destruct;
+ m_fman.Destruct;
+
+ m_gamma_lut.Destruct;
+ m_curves.Destruct;
+ m_contour.Destruct;
+
+end;
+
+{ DRAW_TEXT }
+function the_application.draw_text;
+var
+ gren : glyph_rendering;
+
+ num_glyphs : unsigned;
+
+ mtx : trans_affine;
+ taw : trans_affine_skewing;
+ tar : trans_affine_rotation;
+ tat : trans_affine_translation;
+
+ x ,y0 ,y : double;
+
+ p : int8u_ptr;
+
+ rgba : aggclr;
+ glyph : glyph_cache_ptr;
+
+begin
+ gren:=glyph_ren_native_mono;
+
+ case m_ren_type._cur_item of
+ 0 : gren:=glyph_ren_native_mono;
+ 1 : gren:=glyph_ren_native_gray8;
+ 2 : gren:=glyph_ren_outline;
+ 3 : gren:=glyph_ren_agg_mono;
+ 4 : gren:=glyph_ren_agg_gray8;
+
+ end;
+
+ num_glyphs:=0;
+
+ m_contour.width_(-m_weight._value * m_height._value * 0.05 );
+
+ if m_feng.load_font(@font_name[1 ] ,0 ,gren ) then
+ begin
+ m_feng.hinting_(m_hinting._status );
+ m_feng.height_ (m_height._value );
+ m_feng.width_ (m_width._value );
+ m_feng.flip_y_ (font_flip_y);
+
+ mtx.Construct;
+
+ if m_angle <> 0 then
+ begin
+ tar.Construct(deg2rad(m_angle ) );
+ mtx.multiply (@tar );
+
+ end;
+
+ //taw.Construct(-0.4 ,0 ); mtx.multiply(@taw );
+ //tat.Construct(1 ,0 ); mtx.multiply(@tat );
+
+ m_feng.transform_(@mtx );
+
+ x :=10.0;
+ y0:=_height - m_height._value - 10.0;
+ y :=y0;
+ p :=@text_[0 ];
+
+ while p^ <> 0 do
+ begin
+ glyph:=m_fman.glyph(p^ );
+
+ if glyph <> NIL then
+ begin
+ if m_kerning._status then
+ m_fman.add_kerning(@x ,@y );
+
+ if x >= _width - m_height._value then
+ begin
+ x :=10.0;
+ y0:=y0 - m_height._value;
+
+ if y0 <= 120 then
+ break;
+
+ y:=y0;
+
+ end;
+
+ m_fman.init_embedded_adaptors(glyph ,x ,y );
+
+ case glyph.data_type of
+ glyph_data_mono :
+ begin
+ rgba.ConstrInt(0 ,0 ,0 );
+ ren_bin.color_(@rgba );
+
+ render_scanlines(
+ m_fman.mono_adaptor ,
+ m_fman.mono_scanline ,
+ ren_bin );
+
+ end;
+
+ glyph_data_gray8 :
+ begin
+ rgba.ConstrInt (0 ,0 ,0 );
+ ren_solid.color_(@rgba );
+
+ render_scanlines(
+ m_fman.gray8_adaptor ,
+ m_fman.gray8_scanline ,
+ ren_solid );
+
+ end;
+
+ glyph_data_outline :
+ begin
+ ras.reset;
+
+ if Abs(m_weight._value ) <= 0.01 then
+ // For the sake of efficiency skip the
+ // contour converter if the weight is about zero.
+ ras.add_path(@m_curves )
+ else
+ ras.add_path(@m_contour );
+
+ rgba.ConstrInt (0 ,0 ,0 );
+ ren_solid.color_(@rgba );
+
+ render_scanlines(ras ,sl ,ren_solid );
+
+ end;
+
+ end;
+
+ // increment pen position
+ x:=x + glyph.advance_x;
+ y:=y + glyph.advance_y;
+
+ inc(num_glyphs );
+
+ end;
+
+ inc(ptrcomp(p ) ,sizeof(int8u ) );
+
+ end;
+
+ end
+ else
+ message_(
+ 'Please copy file timesi.ttf to the current directory'#13 +
+ 'or download it from http://www.antigrain.com/timesi.zip' );
+
+ result:=num_glyphs;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ pf : pixel_formats;
+
+ rgba : aggclr;
+
+ ren_base : renderer_base;
+ ren_solid : renderer_scanline_aa_solid;
+ ren_bin : renderer_scanline_bin_solid;
+
+ sl : scanline_u8;
+ ras : rasterizer_scanline_aa;
+
+ gm_th : gamma_threshold;
+ gm_no : gamma_none;
+ gm_pw : gamma_power;
+
+begin
+// Initialize structures
+ pixfmt_bgr24_gamma(pf ,rbuf_window ,@m_gamma_lut );
+
+ ren_base.Construct (@pf );
+ ren_solid.Construct(@ren_base );
+ ren_bin.Construct (@ren_base );
+
+ rgba.ConstrDbl(1 ,1 ,1 );
+ ren_base.clear(@rgba );
+
+ sl.Construct;
+ ras.Construct;
+
+ if m_height._value <> m_old_height then
+ begin
+ m_old_height:=m_height._value;
+
+ m_width.value_(m_old_height );
+
+ end;
+
+// Setup Gamma
+ if m_ren_type._cur_item = 3 then
+ begin
+ // When rendering in mono format,
+ // Set threshold gamma = 0.5
+ gm_th.Construct(m_gamma._value / 2.0 );
+ m_feng.gamma_ (@gm_th );
+
+ end
+ else
+ begin
+ gm_no.Construct;
+ m_feng.gamma_(@gm_no );
+
+ m_gamma_lut.gamma_(m_gamma._value );
+
+ end;
+
+ if m_ren_type._cur_item = 2 then
+ begin
+ // For outline cache set gamma for the rasterizer
+ gm_pw.Construct(m_gamma._value );
+ ras.gamma (@gm_pw );
+
+ end;
+
+// Render the text
+ draw_text(@ras ,@sl ,@ren_solid ,@ren_bin );
+
+// Render the controls
+ gm_pw.Construct(1.0 );
+ ras.gamma (@gm_pw );
+
+ render_ctrl(@ras ,@sl ,@ren_solid ,@m_ren_type );
+ render_ctrl(@ras ,@sl ,@ren_solid ,@m_height );
+ render_ctrl(@ras ,@sl ,@ren_solid ,@m_width );
+ render_ctrl(@ras ,@sl ,@ren_solid ,@m_weight );
+ render_ctrl(@ras ,@sl ,@ren_solid ,@m_gamma );
+ render_ctrl(@ras ,@sl ,@ren_solid ,@m_hinting );
+ render_ctrl(@ras ,@sl ,@ren_solid ,@m_kerning );
+ render_ctrl(@ras ,@sl ,@ren_solid ,@m_performance );
+
+// Free AGG resources
+ sl.Destruct;
+ ras.Destruct;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = byte(' ' ) then
+ begin
+ font_flip_y:=not font_flip_y;
+
+ force_redraw;
+
+ end;
+
+ if key = key_kp_minus then
+ begin
+ m_angle:=m_angle + angle_step;
+
+ if m_angle > 360 then
+ m_angle:=0;
+
+ force_redraw;
+
+ end;
+
+ if key = key_kp_plus then
+ begin
+ m_angle:=m_angle - angle_step;
+
+ if m_angle < 0 then
+ m_angle:=360 - angle_step;
+
+ force_redraw;
+
+ end;
+
+ if key = key_f1 then
+ message_(
+ 'This example demonstrates the use of the FreeType font engine with cache. '#13 +
+ 'Cache can keep three types of data, vector path, Anti-Aliased scanline shape, '#13 +
+ 'and monochrome scanline shape. In case of caching scanline shapes the speed '#13 +
+ 'is pretty good and comparable with Windows hardware accelerated font rendering.'#13#13 +
+ 'How to play with:'#13#13 +
+ 'Press the spacebar to flip the text vertically.'#13#13 +
+ 'Key Plus - Increase font angle (not for Natives)'#13 +
+ 'Key Minus - Decrease font angle (not for Natives)' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+{ ON_CTRL_CHANGE }
+procedure the_application.on_ctrl_change;
+var
+ pf : pixel_formats;
+
+ rgba : aggclr;
+
+ ren_base : renderer_base;
+ ren_solid : renderer_scanline_aa_solid;
+ ren_bin : renderer_scanline_bin_solid;
+
+ sl : scanline_u8;
+ ras : rasterizer_scanline_aa;
+
+ num_glyphs ,i : unsigned;
+
+ t : double;
+
+ buf : array[0..99 ] of char;
+
+begin
+ if m_performance._status then
+ begin
+ pixfmt_bgr24_gamma(pf ,rbuf_window ,@m_gamma_lut );
+
+ ren_base.Construct (@pf );
+ ren_solid.Construct(@ren_base );
+ ren_bin.Construct (@ren_base );
+
+ rgba.ConstrDbl(1 ,1 ,1 );
+ ren_base.clear(@rgba );
+
+ sl.Construct;
+ ras.Construct;
+
+ num_glyphs:=0;
+
+ start_timer;
+
+ for i:=0 to 49 do
+ inc(num_glyphs ,draw_text(@ras ,@sl ,@ren_solid ,@ren_bin ) );
+
+ t:=elapsed_time;
+
+ sprintf(@buf[0 ] ,'Glyphs=%u, ' ,num_glyphs );
+ sprintf(@buf[StrLen(@buf ) ] ,'Time=%.3fms, ' ,t );
+ sprintf(@buf[StrLen(@buf ) ] ,'%.3f glyps/sec, ' ,(num_glyphs / t ) * 1000.0 );
+ sprintf(@buf[StrLen(@buf ) ] ,'%.3f microsecond/glyph' , (t / num_glyphs) * 1000.0);
+
+ message_(@buf[0 ] );
+
+ m_performance.status_(false );
+
+ force_redraw;
+
+ sl.Destruct;
+ ras.Destruct;
+
+ end;
+
+end;
+
+VAR
+ app : the_application;
+
+BEGIN
+ font_flip_y:=false;
+ font_name :='timesi.ttf';
+
+{$IFDEF WIN32 }
+ if ParamCount > 0 then
+ font_name:=ParamStr(1 );
+
+{$ENDIF }
+
+ app.Construct(pix_format_bgr24 ,flip_y );
+ app.caption_ ('AGG Example. Rendering Fonts with FreeType (F1-Help)' );
+
+ if app.init(640 ,520 ,window_resize ) then
+ app.run;
+
+ app.Destruct;
+
+END.
diff --git a/src/corelib/render/software/agg-demos/gamma_correction.dpr b/src/corelib/render/software/agg-demos/gamma_correction.dpr
new file mode 100644
index 00000000..37c26d3d
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/gamma_correction.dpr
@@ -0,0 +1,323 @@
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ gamma_correction ;
+
+{$DEFINE AGG_BGR24 }
+{DEFINE AGG_RGB24 }
+{DEFINE AGG_RGB565 }
+{DEFINE AGG_RGB555 }
+
+uses
+ agg_basics ,
+ agg_platform_support ,
+
+ agg_ctrl ,
+ agg_slider_ctrl ,
+
+ agg_rasterizer_scanline_aa ,
+ agg_scanline ,
+ agg_scanline_u ,
+
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_render_scanlines ,
+
+ agg_gamma_lut ,
+ agg_gamma_functions ,
+ agg_path_storage ,
+ agg_conv_stroke ,
+ agg_ellipse
+
+{$I pixel_formats.inc }
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+type
+ the_application = object(platform_support )
+ m_thickness ,
+ m_gamma ,
+ m_contrast : slider_ctrl;
+
+ m_rx ,
+ m_ry : double;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure on_init; virtual;
+ procedure on_draw; virtual;
+
+ procedure on_mouse_move (x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_thickness.Construct(5 ,5 ,400 - 5 ,11 ,not flip_y_ );
+ m_gamma.Construct (5 ,5 + 15 ,400 - 5 ,11 + 15 ,not flip_y_ );
+ m_contrast.Construct (5 ,5 + 30 ,400 - 5 ,11 + 30 ,not flip_y_ );
+
+ add_ctrl(@m_thickness );
+ add_ctrl(@m_gamma );
+ add_ctrl(@m_contrast );
+
+ m_thickness.label_('Thickness=%3.2f' );
+ m_gamma.label_ ('Gamma=%3.2f' );
+ m_contrast.label_ ('Contrast' );
+
+ m_thickness.range_(0.0 ,3.0 );
+ m_gamma.range_ (0.5 ,3.0 );
+ m_contrast.range_ (0.0 ,1.0 );
+
+ m_thickness.value_(1.0 );
+ m_gamma.value_ (1.0 );
+ m_contrast.value_ (1.0 );
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_thickness.Destruct;
+ m_gamma.Destruct;
+ m_contrast.Destruct;
+
+end;
+
+{ ON_INIT }
+procedure the_application.on_init;
+begin
+ m_rx:=_width / 3.0;
+ m_ry:=_height / 3.0;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ g ,dark ,light ,x ,y ,v ,gval ,dy : double;
+
+ i : unsigned;
+
+ gamma : gamma_lut;
+ pixf : pixel_formats;
+
+ renb : renderer_base;
+ ren : renderer_scanline_aa_solid;
+
+ ras : rasterizer_scanline_aa;
+ sl : scanline_u8;
+
+ rgba : aggclr;
+ path : path_storage;
+
+ gm_pw : gamma_power;
+ gpoly ,
+ poly : conv_stroke;
+ ell : ellipse;
+
+begin
+// Initialize structures
+ g:=m_gamma._value;
+
+ gamma.Construct(g );
+
+ pixfmt_gamma(pixf ,rbuf_window ,@gamma );
+
+ renb.Construct(@pixf );
+ ren.Construct (@renb );
+
+ rgba.ConstrDbl(1 ,1 ,1 );
+ renb.clear (@rgba );
+
+ dark :=1.0 - m_contrast._value;
+ light:=m_contrast._value;
+
+ rgba.ConstrDbl(dark ,dark ,dark );
+ renb.copy_bar (0 ,0 ,trunc(_width ) div 2 ,trunc(_height ) ,@rgba );
+
+ rgba.ConstrDbl(light ,light ,light );
+ renb.copy_bar (trunc(_width ) div 2 + 1 ,0 ,trunc(_width ) ,trunc(_height ) ,@rgba );
+
+ rgba.ConstrDbl(1.0 ,dark ,dark );
+ renb.copy_bar (0 ,trunc(_height ) div 2 + 1 ,trunc(_width ) ,trunc(_height ) ,@rgba );
+
+ ras.Construct;
+ sl.Construct;
+
+// Graph line
+ path.Construct;
+
+ x:=(_width - 256.0 ) / 2.0;
+ y:=50.0;
+
+ for i:=0 to 255 do
+ begin
+ v:=i / 255.0;
+
+ gm_pw.Construct(g );
+
+ gval:=gm_pw.func_operator_gamma(v );
+ dy :=gval * 255.0;
+
+ if i = 0 then
+ path.move_to(x + i ,y + dy )
+ else
+ path.line_to(x + i ,y + dy );
+
+ end;
+
+ gpoly.Construct(@path );
+ gpoly.width_ (2.0 );
+
+ ras.reset;
+ ras.add_path(@gpoly );
+
+ rgba.ConstrInt(80 ,127 ,80 );
+ ren.color_ (@rgba );
+
+ render_scanlines(@ras ,@sl ,@ren );
+
+// Ellipses
+ ell.Construct (_width / 2 ,_height / 2 ,m_rx ,m_ry ,150 );
+ poly.Construct(@ell );
+ poly.width_ (m_thickness._value );
+
+ ras.reset;
+ ras.add_path(@poly );
+
+ rgba.ConstrInt(255 ,0 ,0 );
+ ren.color_ (@rgba );
+
+ render_scanlines(@ras ,@sl ,@ren );
+
+
+ ell.init(_width / 2 ,_height / 2 ,m_rx - 5.0 ,m_ry - 5.0 ,150 );
+
+ ras.reset;
+ ras.add_path(@poly );
+
+ rgba.ConstrInt(0 ,255 ,0 );
+ ren.color_ (@rgba );
+
+ render_scanlines(@ras ,@sl ,@ren );
+
+
+ ell.init(_width / 2 ,_height / 2 ,m_rx - 10.0 ,m_ry - 10.0 ,150 );
+
+ ras.reset;
+ ras.add_path(@poly );
+
+ rgba.ConstrInt(0 ,0 ,255 );
+ ren.color_ (@rgba );
+
+ render_scanlines(@ras ,@sl ,@ren );
+
+
+ ell.init(_width / 2 ,_height / 2 ,m_rx - 15.0 ,m_ry - 15.0 ,150 );
+
+ ras.reset;
+ ras.add_path(@poly );
+
+ rgba.ConstrInt(0 ,0 ,0 );
+ ren.color_ (@rgba );
+
+ render_scanlines(@ras ,@sl ,@ren );
+
+
+ ell.init(_width / 2 ,_height / 2 ,m_rx - 20.0 ,m_ry - 20.0 ,150 );
+
+ ras.reset;
+ ras.add_path(@poly );
+
+ rgba.ConstrInt(255 ,255 ,255 );
+ ren.color_ (@rgba );
+
+ render_scanlines(@ras ,@sl ,@ren );
+
+// Render the controls
+ render_ctrl(@ras ,@sl ,@ren ,@m_thickness );
+ render_ctrl(@ras ,@sl ,@ren ,@m_gamma );
+ render_ctrl(@ras ,@sl ,@ren ,@m_contrast );
+
+// Free AGG resources
+ ras.Destruct;
+ sl.Destruct;
+ path.Destruct;
+
+ gamma.Destruct;
+ gpoly.Destruct;
+ poly.Destruct;
+
+end;
+
+{ ON_MOUSE_MOVE }
+procedure the_application.on_mouse_move;
+begin
+ on_mouse_button_down(x ,y ,flags );
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure the_application.on_mouse_button_down;
+begin
+ if flags and mouse_left <> 0 then
+ begin
+ m_rx:=Abs(_width / 2 - x );
+ m_ry:=Abs(_height / 2 - y );
+
+ force_redraw;
+
+ end;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ 'Anti-Aliasing is very tricky because everything depends. Particularly, having '#13 +
+ 'straight linear dependence "pixel coverage" -> "brightness" may be not the best. '#13 +
+ 'It depends on the type of display (CRT, LCD), contrast, black-on-white vs '#13 +
+ 'white-on-black, it even depends on your personal vision. There are no linear '#13 +
+ 'dependencies in this World. This example demonstrates the importance of so called '#13 +
+ 'Gamma Correction in Anti-Aliasing. There a traditional power function is used, '#13 +
+ 'in terms of C++ it''s brighness = pow(brighness, gamma). Note, that if you improve '#13 +
+ 'the quality on the white side, it becomes worse on the black side and vice versa.'#13 +
+ #13#13 +
+ 'How to play with:'#13#13 +
+ 'Change "Gamma" and see how the quality changes.'#13 +
+ 'Use the left mouse button to resize the circles.' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+VAR
+ app : the_application;
+
+BEGIN
+ app.Construct(pix_format ,flip_y );
+ app.caption_ ('AGG Example. Thin red ellipse (F1-Help)' );
+
+ if app.init(400 ,320 ,0 ) then
+ app.run;
+
+ app.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/gamma_ctrl.dpr b/src/corelib/render/software/agg-demos/gamma_ctrl.dpr
new file mode 100644
index 00000000..2b9c496e
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/gamma_ctrl.dpr
@@ -0,0 +1,400 @@
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ gamma_ctrl_ ;
+
+{DEFINE AGG_GRAY8 }
+{$DEFINE AGG_BGR24 }
+{DEFINE AGG_RGB24 }
+{DEFINE AGG_BGRA32 }
+{DEFINE AGG_RGBA32 }
+{DEFINE AGG_ARGB32 }
+{DEFINE AGG_ABGR32 }
+{DEFINE AGG_RGB565 }
+{DEFINE AGG_RGB555 }
+
+uses
+ agg_basics ,
+ agg_platform_support ,
+
+ agg_ctrl ,
+ agg_gamma_ctrl ,
+
+ agg_rasterizer_scanline_aa ,
+ agg_scanline ,
+ agg_scanline_p ,
+
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_render_scanlines ,
+
+ agg_gsv_text ,
+ agg_conv_stroke ,
+ agg_conv_transform ,
+ agg_path_storage ,
+ agg_ellipse ,
+ agg_trans_affine
+
+{$I pixel_formats.inc }
+{$I agg_mode.inc }
+{$I- }
+const
+ flip_y = true;
+
+var
+ g_ctrl : gamma_ctrl;
+
+type
+ the_application = object(platform_support )
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure on_init; virtual;
+ procedure on_draw; virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ READ_GAMMA }
+procedure read_gamma(fname : shortstring );
+var
+ fd : text;
+
+ kx1 ,ky1 ,kx2 ,ky2 : double;
+
+begin
+ assignfile(fd ,fname );
+ reset (fd );
+
+ readln(fd ,kx1 );
+ readln(fd ,ky1 );
+ readln(fd ,kx2 );
+ readln(fd ,ky2 );
+
+ g_ctrl.values(kx1 ,ky1 ,kx2 ,ky2 );
+
+ close(fd );
+
+end;
+
+{ WRITE_GAMMA_BIN }
+procedure write_gamma_bin(fname : shortstring );
+var
+ fd : file;
+
+ gamma : char_ptr;
+
+begin
+ gamma:=g_ctrl.gamma;
+
+ assignfile(fd ,fname );
+ rewrite (fd ,1 );
+ blockwrite(fd ,gamma^ ,256 );
+ close (fd );
+
+end;
+
+{ WRITE_GAMMA_TXT }
+procedure write_gamma_txt(fname : shortstring );
+var
+ fd : text;
+
+ gamma : char_ptr;
+ i ,j : int;
+
+ kx1 ,ky1 ,kx2 ,ky2 : double;
+
+begin
+ gamma:=g_ctrl.gamma;
+
+ assignfile(fd ,fname );
+ rewrite (fd );
+
+ g_ctrl.values(@kx1 ,@ky1 ,@kx2 ,@ky2 );
+
+ writeln(fd ,kx1:1:3 );
+ writeln(fd ,ky1:1:3 );
+ writeln(fd ,kx2:1:3 );
+ writeln(fd ,ky2:1:3 );
+
+ for i:=0 to 15 do
+ begin
+ for j:= 0 to 15 do
+ write(fd ,int8u_ptr(ptrcomp(gamma ) + i * 16 + j )^:3 ,',' );
+
+ writeln(fd );
+
+ end;
+
+ close(fd );
+
+end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ add_ctrl(@g_ctrl );
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ write_gamma_txt('gamma.txt' );
+ write_gamma_bin('gamma.bin' );
+
+end;
+
+{ ON_INIT }
+procedure the_application.on_init;
+begin
+ read_gamma('gamma.txt' );
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ ewidth ,ecenter : double;
+
+ i : int;
+
+ pixf : pixel_formats;
+
+ rb : renderer_base;
+ r : renderer_scanline_aa_solid;
+
+ ras : rasterizer_scanline_aa;
+ sl : scanline_p8;
+
+ rgba : aggclr;
+ elli : ellipse;
+ poly : conv_stroke;
+ tpoly : conv_transform;
+
+ mtx : trans_affine;
+ tas : trans_affine_skewing;
+ tar : trans_affine_rotation;
+ tat : trans_affine_translation;
+
+ text : gsv_text;
+ text1 : gsv_text_outline;
+ path : path_storage;
+ trans : conv_transform;
+
+begin
+// Initialize structures
+ ewidth :=_initial_width / 2 - 10;
+ ecenter:=_initial_width / 2;
+
+ pixfmt(pixf ,rbuf_window );
+
+ rb.Construct(@pixf );
+ r.Construct (@rb );
+
+ rgba.ConstrDbl(1 ,1 ,1 );
+ rb.clear (@rgba );
+
+ g_ctrl.text_size_(10.0 ,12.0 );
+
+ ras.Construct;
+ sl.Construct;
+
+// Render the controls
+ render_ctrl(@ras ,@sl ,@r ,@g_ctrl );
+
+ ras.gamma(@g_ctrl );
+
+// Ellipses
+ elli.Construct;
+ poly.Construct (@elli );
+ tpoly.Construct(@poly ,_trans_affine_resizing );
+
+ rgba.ConstrInt(0 ,0 ,0 );
+ r.color_ (@rgba );
+
+ elli.init (ecenter ,220 ,ewidth ,15 ,100 );
+ poly.width_ (2.0 );
+ ras.add_path(@tpoly ,0 );
+
+ render_scanlines(@ras ,@sl ,@r );
+
+ elli.init (ecenter ,220 ,11 ,11 ,100 );
+ poly.width_ (2.0 );
+ ras.add_path(@tpoly ,0 );
+
+ render_scanlines(@ras ,@sl ,@r );
+
+ rgba.ConstrInt(127 ,127 ,127 );
+ r.color_ (@rgba );
+
+ elli.init (ecenter ,260 ,ewidth ,15 ,100 );
+ poly.width_ (2.0 );
+ ras.add_path(@tpoly ,0 );
+
+ render_scanlines(@ras ,@sl ,@r );
+
+ elli.init (ecenter ,260 ,11 ,11 ,100 );
+ poly.width_ (2.0 );
+ ras.add_path(@tpoly ,0 );
+
+ render_scanlines(@ras ,@sl ,@r );
+
+ rgba.ConstrInt(192 ,192 ,192 );
+ r.color_ (@rgba );
+
+ elli.init (ecenter ,300 ,ewidth ,15 ,100 );
+ poly.width_ (2.0 );
+ ras.add_path(@tpoly ,0 );
+
+ render_scanlines(@ras ,@sl ,@r );
+
+ elli.init (ecenter ,300 ,11 ,11 ,100 );
+ poly.width_ (2.0 );
+ ras.add_path(@tpoly ,0 );
+
+ render_scanlines(@ras ,@sl ,@r );
+
+ rgba.ConstrDbl(0.0 ,0.0 ,0.4 );
+ r.color_ (@rgba );
+
+ elli.init (ecenter ,340 ,ewidth ,15.5 ,100 );
+ poly.width_ (1.0 );
+ ras.add_path(@tpoly ,0 );
+
+ render_scanlines(@ras ,@sl ,@r );
+
+ elli.init (ecenter ,340 ,10.5 ,10.5 ,100 );
+ poly.width_ (1.0 );
+ ras.add_path(@tpoly ,0 );
+
+ render_scanlines(@ras ,@sl ,@r );
+
+ elli.init (ecenter ,380 ,ewidth ,15.5 ,100 );
+ poly.width_ (0.4 );
+ ras.add_path(@tpoly ,0 );
+
+ render_scanlines(@ras ,@sl ,@r );
+
+ elli.init (ecenter ,380 ,10.5 ,10.5 ,100 );
+ poly.width_ (0.4 );
+ ras.add_path(@tpoly ,0 );
+
+ render_scanlines(@ras ,@sl ,@r );
+
+ elli.init (ecenter ,420 ,ewidth ,15.5 ,100 );
+ poly.width_ (0.1 );
+ ras.add_path(@tpoly ,0 );
+
+ render_scanlines(@ras ,@sl ,@r );
+
+ elli.init (ecenter ,420 ,10.5 ,10.5 ,100 );
+ poly.width_ (0.1 );
+ ras.add_path(@tpoly ,0 );
+
+ render_scanlines(@ras ,@sl ,@r );
+
+// Text
+ mtx.Construct;
+ tas.Construct(0.15 ,0.0 );
+ mtx.Multiply (@tas );
+ mtx.Multiply (_trans_affine_resizing );
+
+ text.Construct;
+ text1.Construct(@text ,@mtx );
+
+ text.text_ ('Text 2345' );
+ text.size_ (50 ,20 );
+ text1.width_ (2.0 );
+ text.start_point_(320 ,10 );
+
+ rgba.ConstrDbl(0.0 ,0.5 ,0.0 );
+ r.color_ (@rgba );
+
+ ras.add_path (@text1 ,0 );
+ render_scanlines(@ras ,@sl ,@r );
+
+// Triangled circle
+ rgba.ConstrDbl(0.5 ,0.0 ,0.0 );
+ r.color_ (@rgba );
+
+ path.Construct;
+ path.move_to(30 ,-1.0 );
+ path.line_to(60 ,0.0 );
+ path.line_to(30 ,1.0 );
+
+ path.move_to(27 ,-1.0 );
+ path.line_to(10 ,0.0 );
+ path.line_to(27 ,1.0 );
+
+ trans.Construct(@path ,@mtx );
+
+ for i:=0 to 34 do
+ begin
+ tar.Construct(i / 35.0 * pi * 2.0 );
+ tat.construct(400 ,130 );
+
+ mtx.reset;
+ mtx.multiply(@tar );
+ mtx.multiply(@tat );
+ mtx.multiply(_trans_affine_resizing );
+
+ ras.add_path (@trans ,0 );
+ render_scanlines(@ras ,@sl ,@r );
+
+ end;
+
+// Free AGG resources
+ ras.Destruct;
+ sl.Destruct;
+
+ poly.Destruct;
+ text.Destruct;
+ text1.Destruct;
+ path.Destruct;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ 'This is another experiment with gamma correction. See also Gamma Correction. '#13 +
+ 'I presumed that we can do better than with a traditional power function. '#13 +
+ 'So, I created a special control to have an arbitrary gamma function. '#13 +
+ 'The conclusion is that we can really achieve a better visual result with '#13 +
+ 'this control, but still, in practice, the traditional power function is good '#13 +
+ 'enough too.'#13#13 +
+ 'How to play with:'#13#13 +
+ 'Feel free to change the gamma curve. The shape you''ll set up, will be'#13 +
+ 'stored in external file "gamma.txt".' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+VAR
+ app : the_application;
+
+BEGIN
+ g_ctrl.Construct(10.0 ,10.0 ,300.0 ,200.0 ,not flip_y );
+
+ app.Construct(pix_format ,flip_y );
+ app.caption_ ('Anti-Aliasing Gamma Correction (F1-Help)' );
+
+ if app.init(500 ,400 ,window_resize ) then
+ app.run;
+
+ app.Destruct;
+ g_ctrl.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/gouraud.dpr b/src/corelib/render/software/agg-demos/gouraud.dpr
new file mode 100644
index 00000000..261bae77
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/gouraud.dpr
@@ -0,0 +1,453 @@
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ gouraud ;
+
+{DEFINE AGG_GRAY8 }
+{$DEFINE AGG_BGR24 }
+{DEFINE AGG_RGB24 }
+{DEFINE AGG_BGRA32 }
+{DEFINE AGG_RGBA32 }
+{DEFINE AGG_ARGB32 }
+{DEFINE AGG_ABGR32 }
+{DEFINE AGG_RGB565 }
+{DEFINE AGG_RGB555 }
+
+uses
+ agg_basics ,
+ agg_platform_support ,
+
+ agg_ctrl ,
+ agg_slider_ctrl ,
+
+ agg_rasterizer_scanline_aa ,
+ agg_scanline ,
+ agg_scanline_u ,
+ agg_scanline_p ,
+
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_render_scanlines ,
+
+ agg_math ,
+ agg_dda_line ,
+ agg_span_allocator ,
+ agg_span_gouraud_rgba ,
+ agg_span_gouraud_gray ,
+ agg_span_solid ,
+ agg_vertex_source ,
+ agg_gamma_functions
+
+{$I pixel_formats.inc }
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+type
+ the_application = object(platform_support )
+ m_x ,
+ m_y : array[0..2 ] of double;
+
+ m_dx ,
+ m_dy : double;
+
+ m_idx : int;
+
+ m_dilation ,
+ m_gamma ,
+ m_alpha : slider_ctrl;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure render_gouraud(sl : scanline_ptr; ras : rasterizer_scanline_aa_ptr );
+
+ procedure on_draw; virtual;
+
+ procedure on_mouse_move (x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_up (x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_dilation.Construct(5 ,5 ,400 - 5 ,11 ,not flip_y_ );
+ m_gamma.Construct (5 ,5 + 15 ,400 - 5 ,11 + 15 ,not flip_y_ );
+ m_alpha.Construct (5 ,5 + 30 ,400 - 5 ,11 + 30 ,not flip_y_ );
+
+ m_idx:=-1;
+
+ m_x[0 ]:=57; m_y[0 ]:=60;
+ m_x[1 ]:=369; m_y[1 ]:=170;
+ m_x[2 ]:=143; m_y[2 ]:=310;
+
+ add_ctrl(@m_dilation );
+ add_ctrl(@m_gamma );
+ add_ctrl(@m_alpha );
+
+ m_dilation.label_('Dilation=%3.2f' );
+ m_gamma.label_ ('Linear gamma=%3.2f' );
+ m_alpha.label_ ('Opacity=%3.2f' );
+
+ m_dilation.value_(0.175 );
+ m_gamma.value_ (0.809 );
+ m_alpha.value_ (1.0 );
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_dilation.Destruct;
+ m_gamma.Destruct;
+ m_alpha.Destruct;
+
+end;
+
+{ RENDER_GOURAUD }
+procedure the_application.render_gouraud;
+var
+ alpha ,brc ,d ,xc ,yc ,x1 ,y1 ,x2 ,y2 ,x3 ,y3 : double;
+
+ pf : pixel_formats;
+
+{$IFDEF AGG_GRAY8 }
+ span_gen : span_gouraud_gray;
+
+{$ELSE }
+ span_gen : span_gouraud_rgba;
+
+{$ENDIF }
+
+ ren_base : renderer_base;
+ span_alloc : span_allocator;
+ ren_gouraud : renderer_scanline_aa;
+
+ gm_li : gamma_linear;
+
+ rgba ,
+ rgbb ,
+ rgbc : aggclr;
+
+begin
+ alpha:=m_alpha._value;
+ brc :=1;
+
+// Initialize structures
+ pixfmt(pf ,rbuf_window );
+
+ ren_base.Construct (@pf );
+ span_alloc.Construct;
+ span_gen.Construct (@span_alloc );
+ ren_gouraud.Construct(@ren_base ,@span_gen );
+
+ gm_li.Construct(0.0 ,m_gamma._value );
+ ras.gamma (@gm_li );
+
+ d:=m_dilation._value;
+
+// Single triangle
+{ rgba.ConstrDbl (1 ,0 ,0 ,alpha );
+ rgbb.ConstrDbl (0 ,1 ,0 ,alpha );
+ rgbc.ConstrDbl (0 ,0 ,1 ,alpha );
+ span_gen.colors (@rgba ,@rgbb ,@rgbc );
+ span_gen.triangle(m_x[0 ] ,m_y[0 ] ,m_x[1 ] ,m_y[1 ] ,m_x[2 ] ,m_y[2 ] ,d );
+
+ ras.add_path (@span_gen);
+ render_scanlines(ras ,sl ,@ren_gouraud );{}
+
+// Six triangles
+ xc:=(m_x[0 ] + m_x[1 ] + m_x[2 ] ) / 3.0;
+ yc:=(m_y[0 ] + m_y[1 ] + m_y[2 ] ) / 3.0;
+
+ x1:=(m_x[1 ] + m_x[0 ] ) / 2 - (xc - (m_x[1 ] + m_x[0 ] ) / 2 );
+ y1:=(m_y[1 ] + m_y[0 ] ) / 2 - (yc - (m_y[1 ] + m_y[0 ] ) / 2 );
+
+ x2:=(m_x[2 ] + m_x[1 ] ) / 2 - (xc - (m_x[2 ] + m_x[1 ] ) / 2 );
+ y2:=(m_y[2 ] + m_y[1 ] ) / 2 - (yc - (m_y[2 ] + m_y[1 ] ) / 2 );
+
+ x3:=(m_x[0 ] + m_x[2 ] ) / 2 - (xc - (m_x[0 ] + m_x[2 ] ) / 2 );
+ y3:=(m_y[0 ] + m_y[2 ] ) / 2 - (yc - (m_y[0 ] + m_y[2 ] ) / 2 );
+
+ rgba.ConstrDbl (1 ,0 ,0 ,alpha );
+ rgbb.ConstrDbl (0 ,1 ,0 ,alpha );
+ rgbc.ConstrDbl (brc ,brc ,brc ,alpha );
+ span_gen.colors_ (@rgba ,@rgbb ,@rgbc );
+ span_gen.triangle(m_x[0 ] ,m_y[0 ] ,m_x[1 ] ,m_y[1 ] ,xc ,yc ,d );
+
+ ras.add_path (@span_gen );
+ render_scanlines(ras ,sl ,@ren_gouraud );
+
+ rgba.ConstrDbl (0 ,1 ,0 ,alpha );
+ rgbb.ConstrDbl (0 ,0 ,1 ,alpha );
+ rgbc.ConstrDbl (brc ,brc ,brc ,alpha );
+ span_gen.colors_ (@rgba ,@rgbb ,@rgbc );
+ span_gen.triangle(m_x[1 ] ,m_y[1 ] ,m_x[2 ] ,m_y[2 ] ,xc ,yc ,d );
+
+ ras.add_path (@span_gen );
+ render_scanlines(ras ,sl ,@ren_gouraud );
+
+ rgba.ConstrDbl (0 ,0 ,1 ,alpha );
+ rgbb.ConstrDbl (1 ,0 ,0 ,alpha );
+ rgbc.ConstrDbl (brc ,brc ,brc ,alpha );
+ span_gen.colors_ (@rgba ,@rgbb ,@rgbc );
+ span_gen.triangle(m_x[2 ] ,m_y[2 ] ,m_x[0 ] ,m_y[0 ] ,xc ,yc ,d );
+
+ ras.add_path (@span_gen );
+ render_scanlines(ras ,sl ,@ren_gouraud );
+
+ brc:=1 - brc;
+
+ rgba.ConstrDbl (1 ,0 ,0 ,alpha );
+ rgbb.ConstrDbl (0 ,1 ,0 ,alpha );
+ rgbc.ConstrDbl (brc ,brc ,brc ,alpha );
+ span_gen.colors_ (@rgba ,@rgbb ,@rgbc );
+ span_gen.triangle(m_x[0 ] ,m_y[0 ] ,m_x[1 ] ,m_y[1 ] ,x1 ,y1 ,d );
+
+ ras.add_path (@span_gen );
+ render_scanlines(ras ,sl ,@ren_gouraud );
+
+ rgba.ConstrDbl (0 ,1 ,0 ,alpha );
+ rgbb.ConstrDbl (0 ,0 ,1 ,alpha );
+ rgbc.ConstrDbl (brc ,brc ,brc ,alpha );
+ span_gen.colors_ (@rgba ,@rgbb ,@rgbc );
+ span_gen.triangle(m_x[1 ] ,m_y[1 ] ,m_x[2 ] ,m_y[2 ] ,x2 ,y2 ,d );
+
+ ras.add_path (@span_gen);
+ render_scanlines(ras ,sl ,@ren_gouraud );
+
+ rgba.ConstrDbl (0 ,0 ,1 ,alpha );
+ rgbb.ConstrDbl (1 ,0 ,0 ,alpha );
+ rgbc.ConstrDbl (brc ,brc ,brc ,alpha );
+ span_gen.colors_ (@rgba ,@rgbb ,@rgbc );
+ span_gen.triangle(m_x[2 ] ,m_y[2 ] ,m_x[0 ] ,m_y[0 ] ,x3 ,y3 ,d );
+
+ ras.add_path (@span_gen );
+ render_scanlines(ras ,sl ,@ren_gouraud );{}
+
+// Free AGG resources
+ span_alloc.Destruct;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ pf : pixel_formats;
+
+ ren_base : renderer_base;
+ ren_solid : renderer_scanline_aa_solid;
+
+ ras : rasterizer_scanline_aa;
+ sl : scanline_u8;
+
+ rgba : aggclr;
+ gm_no : vertex_source;
+
+begin
+// Initialize structures
+ pixfmt(pf ,rbuf_window );
+
+ ren_base.Construct (@pf );
+ ren_solid.Construct(@ren_base );
+
+ rgba.ConstrDbl(1 ,1 ,1 );
+ ren_base.clear(@rgba );
+
+ sl.Construct;
+ ras.Construct;
+
+// Render gouraud
+ render_gouraud(@sl ,@ras );
+
+// Render the controls
+ gm_no.Construct;
+ ras.gamma(@gm_no );
+
+ render_ctrl(@ras ,@sl ,@ren_solid ,@m_dilation );
+ render_ctrl(@ras ,@sl ,@ren_solid ,@m_gamma );
+ render_ctrl(@ras ,@sl ,@ren_solid ,@m_alpha );
+
+// Free AGG resources
+ sl.Destruct;
+ ras.Destruct;
+
+end;
+
+{ ON_MOUSE_MOVE }
+procedure the_application.on_mouse_move;
+var
+ dx ,dy : double;
+
+begin
+ if flags and mouse_left <> 0 then
+ begin
+ if m_idx = 3 then
+ begin
+ dx:=x - m_dx;
+ dy:=y - m_dy;
+
+ m_x[1 ]:=m_x[1 ] - (m_x[0 ] - dx );
+ m_y[1 ]:=m_y[1 ] - (m_y[0 ] - dy );
+ m_x[2 ]:=m_x[2 ] - (m_x[0 ] - dx );
+ m_y[2 ]:=m_y[2 ] - (m_y[0 ] - dy );
+ m_x[0 ]:=dx;
+ m_y[0 ]:=dy;
+
+ force_redraw;
+ exit;
+
+ end;
+
+ if m_idx >= 0 then
+ begin
+ m_x[m_idx ]:=x - m_dx;
+ m_y[m_idx ]:=y - m_dy;
+
+ force_redraw;
+
+ end;
+
+ end
+ else
+ on_mouse_button_up(x ,y ,flags );
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure the_application.on_mouse_button_down;
+var
+ i : unsigned;
+
+ sl : scanline_u8;
+ ras : rasterizer_scanline_aa;
+ buf : array[0..99 ] of char;
+
+begin
+ if flags and mouse_right <> 0 then
+ begin
+ sl.Construct;
+ ras.Construct;
+
+ start_timer;
+
+ for i:=0 to 99 do
+ render_gouraud(@sl ,@ras );
+
+ sprintf (@buf[0 ] ,'Time=%2.2f ms' ,elapsed_time );
+ message_(@buf[0 ] );
+
+ sl.Destruct;
+ ras.Destruct;
+
+ end;
+
+ if flags and mouse_left <> 0 then
+ begin
+ i:=0;
+
+ while i < 3 do
+ begin
+ if Sqrt((x-m_x[i ] ) * (x-m_x[i ] ) + (y-m_y[i ] ) * (y-m_y[i ] ) ) < 10.0 then
+ begin
+ m_dx :=x - m_x[i ];
+ m_dy :=y - m_y[i ];
+ m_idx:=i;
+
+ break;
+
+ end;
+
+ inc(i );
+
+ end;
+
+ if i = 3 then
+ if point_in_triangle(m_x[0 ] ,m_y[0 ] ,m_x[1 ] ,m_y[1 ] ,m_x[2 ] ,m_y[2 ] ,x ,y ) then
+ begin
+ m_dx :=x - m_x[0 ];
+ m_dy :=y - m_y[0 ];
+ m_idx:=3;
+
+ end;
+
+ end;
+
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+procedure the_application.on_mouse_button_up;
+begin
+ m_idx:=-1;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+var
+ dx ,dy : double;
+
+begin
+ dx:=0;
+ dy:=0;
+
+ case key of
+ key_left : dx:=0.1;
+ key_right : dx:=0.1;
+ key_up : dy:=0.1;
+ key_down : dy:=-0.1;
+
+ end;
+
+ m_x[0 ]:=m_x[0 ] + dx;
+ m_y[0 ]:=m_y[0 ] + dy;
+ m_x[1 ]:=m_x[1 ] + dx;
+ m_y[1 ]:=m_y[1 ] + dy;
+
+ force_redraw;
+
+ if key = key_f1 then
+ message_(
+ 'Gouraud shading. It''s a simple method of interpolating colors in a triangle. '#13 +
+ 'There''s no "cube" drawn, there''re just 6 triangles. You define a triangle '#13 +
+ 'and colors in its vertices. When rendering, the colors will be linearly interpolated. '#13 +
+ 'But there''s a problem that appears when drawing adjacent triangles with Anti-Aliasing.'#13 +
+ 'Anti-Aliased polygons do not "dock" to each other correctly, there visual artifacts '#13 +
+ 'at the edges appear. I call it "the problem of adjacent edges". AGG has a simple '#13 +
+ 'mechanism that allows you to get rid of the artifacts, just dilating the polygons '#13 +
+ 'and/or changing the gamma-correction value. But it''s tricky, because the values '#13 +
+ 'depend on the opacity of the polygons. In this example you can change the opacity, '#13 +
+ 'the dilation value and gamma.'#13#13 +
+ 'How to play with:'#13#13 +
+ 'Use the left mouse button to drag the Red, Green and Blue corners of the "cube".'#13 +
+ 'Use the right mouse button to issue a performance test (100x).' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+VAR
+ app : the_application;
+
+BEGIN
+ app.Construct(pix_format ,flip_y );
+ app.caption_ ('AGG Example. Gouraud Shading (F1-Help)' );
+
+ if app.init(400 ,320 ,window_resize ) then
+ app.run;
+
+ app.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/gouraud_mesh.dpr b/src/corelib/render/software/agg-demos/gouraud_mesh.dpr
new file mode 100644
index 00000000..9a6f506c
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/gouraud_mesh.dpr
@@ -0,0 +1,983 @@
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ gouraud_mesh ;
+
+uses
+ SysUtils ,
+ agg_basics ,
+ agg_color ,
+ agg_array ,
+ agg_math ,
+ agg_math_stroke ,
+ agg_platform_support ,
+ agg_ctrl ,
+ agg_slider_ctrl ,
+ agg_bezier_ctrl ,
+ agg_rbox_ctrl ,
+ agg_cbox_ctrl ,
+ agg_renderer_base ,
+ agg_rendering_buffer ,
+ agg_conv_transform ,
+ agg_conv_stroke ,
+ agg_conv_clip_polyline ,
+ agg_scanline_u ,
+ agg_scanline_bin ,
+ agg_renderer_scanline ,
+ agg_rasterizer_outline_aa ,
+ agg_rasterizer_scanline_aa ,
+ agg_span_allocator ,
+ agg_span_gouraud_rgba ,
+ agg_gamma_lut ,
+ agg_arc ,
+ agg_bezier_arc ,
+ agg_pixfmt ,
+ agg_pixfmt_rgb ,
+ agg_pixfmt_rgba ,
+ agg_bounding_rect ,
+ agg_vpgen_clip_polygon ,
+ agg_rasterizer_compound_aa ,
+ agg_gsv_text ;
+
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+type
+ mesh_point_ptr = ^mesh_point;
+ mesh_point = object
+ x ,y ,dx ,dy : double;
+ color ,dc : aggclr;
+
+ constructor Construct; overload;
+ constructor Construct(x_ ,y_ ,dx_ ,dy_ : double; c ,dc_ : aggclr_ptr ); overload;
+
+ end;
+
+ mesh_triangle_ptr = ^mesh_triangle;
+ mesh_triangle = object
+ p1 ,p2 ,p3 : unsigned;
+
+ constructor Construct; overload;
+ constructor Construct(i ,j ,k : unsigned ); overload;
+
+ end;
+
+ mesh_edge_ptr = ^mesh_edge;
+ mesh_edge = object
+ p1 ,p2 : unsigned;
+ tl ,tr : int;
+
+ constructor Construct; overload;
+ constructor Construct(p1_ ,p2_ : unsigned; tl_ ,tr_ : int ); overload;
+
+ end;
+
+ mesh_ctrl_ptr = ^mesh_ctrl;
+ mesh_ctrl = object
+ m_cols ,
+ m_rows : unsigned;
+
+ m_drag_idx : int;
+
+ m_drag_dx ,
+ m_drag_dy ,
+ m_cell_w ,
+ m_cell_h ,
+ m_start_x ,
+ m_start_y : double;
+
+ m_vertices ,
+ m_triangles ,
+ m_edges : pod_bvector;
+
+ constructor Construct;
+ destructor Destruct;
+
+ procedure generate(
+ cols ,rows : unsigned;
+ cell_w ,cell_h ,start_x ,start_y : double );
+
+ procedure randomize_points(delta : double );
+ procedure rotate_colors;
+
+ function on_mouse_button_down(x ,y : double; flags : unsigned ) : boolean;
+ function on_mouse_move (x ,y : double; flags : unsigned ) : boolean;
+ function on_mouse_button_up (x ,y : double; flags : unsigned ) : boolean;
+
+ function num_vertices : unsigned;
+ function vertex(i : unsigned ) : mesh_point_ptr; overload;
+ function vertex(x ,y : unsigned ) : mesh_point_ptr; overload;
+
+ function num_triangles : unsigned;
+ function triangle(i : unsigned ) : mesh_triangle_ptr;
+
+ function num_edges : unsigned;
+ function edge(i : unsigned ) : mesh_edge_ptr;
+
+ end;
+
+ styles_gouraud = object(style_handler )
+ m_triangles : pod_bvector;
+
+ m_rgba : aggclr;
+
+ constructor Construct(mesh : mesh_ctrl_ptr; gamma : gamma_ptr );
+ destructor Destruct;
+
+ function is_solid(style : unsigned ) : boolean; virtual;
+ function color (style : unsigned ) : aggclr_ptr; virtual;
+
+ procedure generate_span(span : aggclr_ptr; x ,y : int; len ,style : unsigned ); virtual;
+
+ end;
+
+ the_application = object(platform_support )
+ m_mesh : mesh_ctrl;
+ m_gamma : gamma_lut;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure on_init; virtual;
+ procedure on_draw; virtual;
+
+ procedure on_mouse_move(x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_up (x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+ procedure on_idle; virtual;
+ procedure on_ctrl_change; virtual;
+
+ end;
+
+{ random }
+function random_(v1 ,v2 : double ) : double;
+begin
+ result:=(v2 - v1 ) * (rand mod 1000 ) / 999.0 + v1;
+
+end;
+
+{ CONSTRUCT }
+constructor mesh_point.Construct;
+begin
+ x :=0;
+ y :=0;
+ dx:=0;
+ dy:=0;
+
+ color.Construct;
+ dc.Construct;
+
+end;
+
+{ CONSTRUCT }
+constructor mesh_point.Construct(x_ ,y_ ,dx_ ,dy_ : double; c ,dc_ : aggclr_ptr );
+begin
+ x :=x_;
+ y :=y_;
+ dx:=dx_;
+ dy:=dy_;
+
+ color.Construct(c );
+ dc.Construct(dc_ );
+
+end;
+
+{ CONSTRUCT }
+constructor mesh_triangle.Construct;
+begin
+ p1:=0;
+ p2:=0;
+ p3:=0;
+
+end;
+
+{ CONSTRUCT }
+constructor mesh_triangle.Construct(i ,j ,k : unsigned );
+begin
+ p1:=i;
+ p2:=j;
+ p3:=k;
+
+end;
+
+{ CONSTRUCT }
+constructor mesh_edge.Construct;
+begin
+ p1:=0;
+ p2:=0;
+ tl:=0;
+ tr:=0;
+
+end;
+
+{ CONSTRUCT }
+constructor mesh_edge.Construct(p1_ ,p2_ : unsigned; tl_ ,tr_ : int );
+begin
+ p1:=p1_;
+ p2:=p2_;
+ tl:=tl_;
+ tr:=tr_;
+
+end;
+
+{ CONSTRUCT }
+constructor mesh_ctrl.Construct;
+begin
+ m_vertices.Construct(sizeof(mesh_point ) );
+ m_triangles.Construct(sizeof(mesh_triangle ) );
+ m_edges.Construct(sizeof(mesh_edge ) );
+
+ m_cols:=0;
+ m_rows:=0;
+
+ m_drag_idx:=-1;
+ m_drag_dx :=0;
+ m_drag_dy :=0;
+
+end;
+
+{ DESTRUCT }
+destructor mesh_ctrl.Destruct;
+begin
+ m_vertices.Destruct;
+ m_triangles.Destruct;
+ m_edges.Destruct;
+
+end;
+
+{ GENERATE }
+procedure mesh_ctrl.generate(
+ cols ,rows : unsigned;
+ cell_w ,cell_h ,start_x ,start_y : double );
+var
+ i ,j : unsigned;
+
+ x ,dx ,dy : double;
+
+ p1 ,p2 ,p3 ,p4 ,curr_cell ,left_cell ,bott_cell ,
+
+ curr_t1 ,curr_t2 ,left_t1 ,left_t2 ,bott_t1 ,bott_t2 : int;
+
+ c ,dc : aggclr;
+
+ c1 ,c2 ,c3 : int8u;
+
+ mp : mesh_point;
+ mt : mesh_triangle;
+ me : mesh_edge;
+
+begin
+ m_cols :=cols;
+ m_rows :=rows;
+ m_cell_w:=cell_w;
+ m_cell_h:=cell_h;
+
+ m_start_x:=start_x;
+ m_start_y:=start_y;
+
+ m_vertices.remove_all;
+
+ i:=0;
+
+ while i < m_rows do
+ begin
+ x:=start_x;
+ j:=0;
+
+ while j < m_cols do
+ begin
+ dx:=random_(-0.5 ,0.5 );
+ dy:=random_(-0.5 ,0.5 );
+
+ c1:=rand and $FF;
+ c2:=rand and $FF;
+ c3:=rand and $FF;
+
+ c.ConstrInt (c3 ,c2 ,c1 );
+
+ c1:=rand and 1;
+ c2:=rand and 1;
+ c3:=rand and 1;
+
+ dc.ConstrInt(c3 ,c2 ,c1 );
+
+ mp.Construct (x ,start_y ,dx ,dy ,@c ,@dc );
+ m_vertices.add(@mp );
+
+ x:=x + cell_w;
+
+ inc(j );
+
+ end;
+
+ start_y:=start_y + cell_h;
+
+ inc(i );
+
+ end;
+
+// 4---3
+// |t2/|
+// | / |
+// |/t1|
+// 1---2
+ m_triangles.remove_all;
+ m_edges.remove_all;
+
+ i:=0;
+
+ while i < m_rows - 1 do
+ begin
+ j:=0;
+
+ while j < m_cols - 1 do
+ begin
+ p1:=i * m_cols + j;
+ p2:=p1 + 1;
+ p3:=p2 + m_cols;
+ p4:=p1 + m_cols;
+
+ mt.Construct (p1 ,p2 ,p3 );
+ m_triangles.add(@mt );
+ mt.Construct (p3 ,p4 ,p1 );
+ m_triangles.add(@mt );
+
+ curr_cell:=i * (m_cols - 1 ) + j;
+
+ if j <> 0 then
+ left_cell:=int(curr_cell - 1 )
+ else
+ left_cell:=-1;
+
+ if i <> 0 then
+ bott_cell:=int(curr_cell - (m_cols - 1 ) )
+ else
+ bott_cell:=-1;
+
+ curr_t1:=curr_cell * 2;
+ curr_t2:=curr_t1 + 1;
+
+ if left_cell >= 0 then
+ left_t1:=left_cell * 2
+ else
+ left_t1:=-1;
+
+ if left_cell >= 0 then
+ left_t2:=left_t1 + 1
+ else
+ left_t2:=-1;
+
+ if bott_cell >= 0 then
+ bott_t1:=bott_cell * 2
+ else
+ bott_t1:=-1;
+
+ if bott_cell >= 0 then
+ bott_t2:=bott_t1 + 1
+ else
+ bott_t2:=-1;
+
+ me.Construct(p1 ,p2 ,curr_t1 ,bott_t2 );
+ m_edges.add (@me );
+ me.Construct(p1 ,p3 ,curr_t2 ,curr_t1 );
+ m_edges.add (@me );
+ me.Construct(p1 ,p4 ,left_t1 ,curr_t2 );
+ m_edges.add (@me );
+
+ if j = m_cols - 2 then // Last column
+ begin
+ me.Construct(p2 ,p3 ,curr_t1 ,-1 );
+ m_edges.add (@me );
+
+ end;
+
+ if i = m_rows - 2 then // Last row
+ begin
+ me.Construct(p3 ,p4 ,curr_t2 ,-1 );
+ m_edges.add (@me );
+
+ end;
+
+ inc(j );
+
+ end;
+
+ inc(i );
+
+ end;
+
+end;
+
+{ RANDOMIZE_POINTS }
+procedure mesh_ctrl.randomize_points(delta : double );
+var
+ i ,j : unsigned;
+
+ xc ,yc ,x1 ,y1 ,x2 ,y2 : double;
+
+ p : mesh_point_ptr;
+
+begin
+ i:=0;
+
+ while i < m_rows do
+ begin
+ j:=0;
+
+ while j < m_cols do
+ begin
+ xc:=j * m_cell_w + m_start_x;
+ yc:=i * m_cell_h + m_start_y;
+ x1:=xc - m_cell_w / 4;
+ y1:=yc - m_cell_h / 4;
+ x2:=xc + m_cell_w / 4;
+ y2:=yc + m_cell_h / 4;
+
+ p:=vertex(j ,i );
+
+ p.x:=p.x + p.dx;
+ p.y:=p.y + p.dy;
+
+ if p.x < x1 then
+ begin
+ p.x :=x1;
+ p.dx:=-p.dx;
+
+ end;
+
+ if p.y < y1 then
+ begin
+ p.y :=y1;
+ p.dy:=-p.dy;
+
+ end;
+
+ if p.x > x2 then
+ begin
+ p.x :=x2;
+ p.dx:=-p.dx;
+
+ end;
+
+ if p.y > y2 then
+ begin
+ p.y :=y2;
+ p.dy:=-p.dy;
+
+ end;
+
+ inc(j );
+
+ end;
+
+ inc(i );
+
+ end;
+
+end;
+
+{ ROTATE_COLORS }
+procedure mesh_ctrl.rotate_colors;
+var
+ i : unsigned;
+
+ c ,dc : aggclr_ptr;
+
+ r ,g ,b : int;
+
+begin
+ i:=1;
+
+ while i < m_vertices.size do
+ begin
+ c :=@mesh_point_ptr(m_vertices.array_operator(i ) ).color;
+ dc:=@mesh_point_ptr(m_vertices.array_operator(i ) ).dc;
+
+ if dc.r <> 0 then
+ r:=c.r + 5
+ else
+ r:=c.r - 5;
+
+ if dc.g <> 0 then
+ g:=c.g + 5
+ else
+ g:=c.g - 5;
+
+ if dc.b <> 0 then
+ b:=c.b + 5
+ else
+ b:=c.b - 5;
+
+ if r < 0 then
+ begin
+ r :=0;
+ dc.r:=dc.r xor 1;
+
+ end;
+
+ if r > 255 then
+ begin
+ r :=255;
+ dc.r:=dc.r xor 1;
+
+ end;
+
+ if g < 0 then
+ begin
+ g :=0;
+ dc.g:=dc.g xor 1;
+
+ end;
+
+ if g > 255 then
+ begin
+ g :=255;
+ dc.g:=dc.g xor 1;
+
+ end;
+
+ if b < 0 then
+ begin
+ b :=0;
+ dc.b:=dc.b xor 1;
+
+ end;
+
+ if b > 255 then
+ begin
+ b := 255;
+ dc.b:=dc.b xor 1;
+
+ end;
+
+ c.r:=r;
+ c.g:=g;
+ c.b:=b;
+
+ inc(i );
+
+ end;
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+function mesh_ctrl.on_mouse_button_down(x ,y : double; flags : unsigned ) : boolean;
+var
+ i : unsigned;
+
+begin
+ if flags and 1 <> 0 then
+ begin
+ i:=0;
+
+ while i < m_vertices.size do
+ begin
+ if calc_distance(
+ x ,y ,
+ mesh_point_ptr(m_vertices.array_operator(i ) ).x ,
+ mesh_point_ptr(m_vertices.array_operator(i ) ).y ) < 5 then
+ begin
+ m_drag_idx:=i;
+
+ m_drag_dx:=x - mesh_point_ptr(m_vertices.array_operator(i ) ).x;
+ m_drag_dy:=y - mesh_point_ptr(m_vertices.array_operator(i ) ).y;
+
+ result:=true;
+
+ exit;
+
+ end;
+
+ inc(i );
+
+ end;
+
+ end;
+
+ result:=false;
+
+end;
+
+{ ON_MOUSE_MOVE }
+function mesh_ctrl.on_mouse_move(x ,y : double; flags : unsigned ) : boolean;
+begin
+ if flags and 1 <> 0 then
+ begin
+ if m_drag_idx >= 0 then
+ begin
+ mesh_point_ptr(m_vertices.array_operator(m_drag_idx ) ).x:=x - m_drag_dx;
+ mesh_point_ptr(m_vertices.array_operator(m_drag_idx ) ).y:=y - m_drag_dy;
+
+ result:=true;
+
+ exit;
+
+ end;
+
+ end
+ else
+ begin
+ result:=on_mouse_button_up(x ,y ,flags );
+
+ exit;
+
+ end;
+
+ result:=false;
+
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+function mesh_ctrl.on_mouse_button_up(x ,y : double; flags : unsigned ) : boolean;
+begin
+ result :=m_drag_idx >= 0;
+ m_drag_idx:=-1;
+
+end;
+
+{ NUM_VERTICES }
+function mesh_ctrl.num_vertices : unsigned;
+begin
+ result:=m_vertices.size;
+
+end;
+
+{ VERTEX }
+function mesh_ctrl.vertex(i : unsigned ) : mesh_point_ptr;
+begin
+ result:=m_vertices.array_operator(i );
+
+end;
+
+{ VERTEX }
+function mesh_ctrl.vertex(x ,y : unsigned ) : mesh_point_ptr;
+begin
+ result:=m_vertices.array_operator(y * m_rows + x );
+
+end;
+
+{ NUM_TRIANGLES }
+function mesh_ctrl.num_triangles : unsigned;
+begin
+ result:=m_triangles.size;
+
+end;
+
+{ TRIANGLE }
+function mesh_ctrl.triangle(i : unsigned ) : mesh_triangle_ptr;
+begin
+ result:=m_triangles.array_operator(i );
+
+end;
+
+{ NUM_EDGES }
+function mesh_ctrl.num_edges : unsigned;
+begin
+ result:=m_edges.size;
+
+end;
+
+{ EDGE }
+function mesh_ctrl.edge(i : unsigned ) : mesh_edge_ptr;
+begin
+ result:=m_edges.array_operator(i );
+
+end;
+
+{ CONSTRUCT }
+constructor styles_gouraud.Construct(mesh : mesh_ctrl_ptr; gamma : gamma_ptr );
+var
+ i : unsigned;
+ t : mesh_triangle_ptr;
+
+ p1 ,p2 ,p3 : mesh_point_ptr;
+ c1 ,c2 ,c3 : aggclr;
+
+ gouraud : span_gouraud_rgba;
+
+begin
+ m_triangles.Construct(sizeof(span_gouraud_rgba ) );
+ m_rgba.ConstrInt (0 ,0 ,0 ,0 );
+
+ i:=0;
+
+ while i < mesh.num_triangles do
+ begin
+ t :=mesh.triangle(i );
+ p1:=mesh.vertex (t.p1 );
+ p2:=mesh.vertex (t.p2 );
+ p3:=mesh.vertex (t.p3 );
+
+ c1.Construct(@p1.color );
+ c2.Construct(@p2.color );
+ c3.Construct(@p3.color );
+
+ c1.apply_gamma_dir(gamma );
+ c2.apply_gamma_dir(gamma );
+ c2.apply_gamma_dir(gamma );
+
+ gouraud.Construct_(
+ @c1 ,@c2 ,@c3 ,
+ p1.x ,p1.y ,
+ p2.x ,p2.y ,
+ p3.x ,p3.y );
+
+ gouraud.prepare_;
+ m_triangles.add(@gouraud );
+
+ inc(i );
+
+ end;
+
+end;
+
+{ DESTRUCT }
+destructor styles_gouraud.Destruct;
+begin
+ m_triangles.Destruct;
+
+end;
+
+{ IS_SOLID }
+function styles_gouraud.is_solid(style : unsigned ) : boolean;
+begin
+ result:=false;
+
+end;
+
+{ COLOR }
+function styles_gouraud.color(style : unsigned ) : aggclr_ptr;
+begin
+ result:=@m_rgba;
+
+end;
+
+{ GENERATE_SPAN }
+procedure styles_gouraud.generate_span(span : aggclr_ptr; x ,y : int; len ,style : unsigned );
+begin
+ span_gouraud_rgba_ptr(
+ m_triangles.array_operator(style ) ).generate_(span ,x ,y ,len );
+
+end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_mesh.Construct;
+ m_gamma.Construct_;
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_mesh.Destruct;
+ m_gamma.Destruct;
+
+// m_gamma.gamma_(2.0 );
+
+end;
+
+{ ON_INIT }
+procedure the_application.on_init;
+begin
+ m_mesh.generate(20 ,20 ,17 ,17 ,40 ,40 );
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ pf : pixel_formats;
+
+ rgba : aggclr;
+
+ ren_base : renderer_base;
+
+ ren : renderer_scanline_aa_solid;
+ ras : rasterizer_scanline_aa;
+
+ sl : scanline_u8;
+ sl_bin : scanline_bin;
+
+ rasc : rasterizer_compound_aa_int;
+ alloc : span_allocator;
+
+ styles : styles_gouraud;
+
+ i : unsigned;
+ e : mesh_edge_ptr;
+
+ p1 ,p2 : mesh_point_ptr;
+
+ tm : double;
+ buf : array[0..255 ] of char;
+
+ t : gsv_text;
+ pt : conv_stroke_math;
+
+begin
+// Initialize structures
+ pixfmt_bgra32_pre(pf ,rbuf_window );
+
+ ren_base.Construct(@pf );
+
+ rgba.ConstrInt(0 ,0 ,0 );
+ ren_base.clear(@rgba );
+ ren.Construct (@ren_base );
+
+ ras.Construct;
+ sl.Construct;
+ sl_bin.Construct;
+
+ rasc.Construct;
+ alloc.Construct;
+
+ styles.Construct(@m_mesh ,@m_gamma );
+
+ start_timer;
+ rasc.reset;
+
+//rasc.clip_box(40 ,40 ,_width - 40 ,_height - 40 );
+
+ i:=0;
+
+ while i < m_mesh.num_edges do
+ begin
+ e :=m_mesh.edge (i );
+ p1:=m_mesh.vertex(e.p1 );
+ p2:=m_mesh.vertex(e.p2 );
+
+ rasc.styles (e.tl ,e.tr );
+ rasc.move_to_d(p1.x ,p1.y );
+ rasc.line_to_d(p2.x ,p2.y );
+
+ inc(i );
+
+ end;
+
+ render_scanlines_compound(@rasc ,@sl ,@sl_bin ,@ren_base ,@alloc ,@styles );
+
+// Info
+ tm:=elapsed_time;
+
+ t.Construct;
+ t.size_(10.0 );
+
+ pt.Construct (@t );
+ pt.width_ (1.5 );
+ pt.line_cap_ (round_cap );
+ pt.line_join_(round_join );
+
+ sprintf(@buf[0 ] ,'%3.2f ms, ' ,tm );
+ sprintf(@buf[StrLen(@buf ) ] ,'%d triangles, ' ,m_mesh.num_triangles );
+ sprintf(@buf[StrLen(@buf ) ] ,'%.0f tri/sec' ,m_mesh.num_triangles / tm * 1000.0 );
+
+ t.start_point_(10.0 ,10.0 );
+ t.text_ (@buf[0 ] );
+
+ ras.add_path (@pt );
+ rgba.ConstrDbl(1 ,1 ,1 );
+
+ render_scanlines_aa_solid(@ras ,@sl ,@ren_base ,@rgba );
+
+ if m_gamma._gamma <> 1.0 then
+ pf.apply_gamma_inv(@m_gamma ,bgra_order );
+
+// Free AGG resources
+ ras.Destruct;
+ sl.Destruct;
+ sl_bin.Destruct;
+
+ rasc.Destruct;
+ alloc.Destruct;
+
+ styles.Destruct;
+
+ t.Destruct;
+ pt.Destruct;
+
+end;
+
+{ ON_MOUSE_MOVE }
+procedure the_application.on_mouse_move;
+begin
+ if m_mesh.on_mouse_move(x ,y ,flags ) then
+ force_redraw;
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure the_application.on_mouse_button_down;
+begin
+ if m_mesh.on_mouse_button_down(x ,y ,flags ) then
+ force_redraw;
+
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+procedure the_application.on_mouse_button_up;
+begin
+ if m_mesh.on_mouse_button_up(x ,y ,flags ) then
+ force_redraw;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ 'Yet another example that demonstrates the power of compound shape rasterization. '#13 +
+ 'Here we create a mesh of triangles and render them in one pass with multiple Gouraud '#13 +
+ 'shaders (span_gouraud_rgba). The example demonstrates perfect Anti-Aliasing '#13 +
+ 'and perfect triangle stitching (seamless edges) at the same time.'#13#13 +
+ 'How to play with:'#13#13 +
+ 'You can modify the points of the mesh by left mouse click and drag.' );
+
+end;
+
+{ ON_IDLE }
+procedure the_application.on_idle;
+begin
+ m_mesh.randomize_points(1.0 );
+ m_mesh.rotate_colors;
+ force_redraw;
+
+end;
+
+{ ON_CTRL_CHANGE }
+procedure the_application.on_ctrl_change;
+begin
+end;
+
+VAR
+ app : the_application;
+
+BEGIN
+ app.Construct(pix_format_bgra32 ,flip_y );
+ app.caption_ ('AGG Example. (F1-Help)' );
+
+ if app.init(400 ,400 ,0 ) then
+ begin
+ app.wait_mode_(false );
+ app.run;
+
+ end;
+
+ app.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/gpc/copying.txt b/src/corelib/render/software/agg-demos/gpc/copying.txt
new file mode 100755
index 00000000..5f1e6bc4
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/gpc/copying.txt
@@ -0,0 +1,22 @@
+
+ http://www.cs.man.ac.uk/aig/staff/alan/software/
+
+Author: Alan Murta (email: gpc@cs.man.ac.uk)
+Version: 2.31
+Date: 4th June 1999
+
+Copyright: (C) 1997-1999, Advanced Interfaces Group,
+ University of Manchester.
+
+ This software is free for non-commercial use. It may be copied,
+ modified, and redistributed provided that this copyright notice
+ is preserved on all copies. The intellectual property rights of
+ the algorithms used reside with the University of Manchester
+ Advanced Interfaces Group.
+
+ You may not use this software, in whole or in part, in support
+ of any commercial product without the express consent of the
+ author.
+
+ There is no warranty or other guarantee of fitness of this
+ software for any purpose. It is provided solely "as is".
diff --git a/src/corelib/render/software/agg-demos/gpc/gpc.pas b/src/corelib/render/software/agg-demos/gpc/gpc.pas
new file mode 100755
index 00000000..3e8541e5
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/gpc/gpc.pas
@@ -0,0 +1,1965 @@
+(*
+===========================================================================
+
+Project: Generic Polygon Clipper
+
+ A new algorithm for calculating the difference, intersection,
+ exclusive-or or union of arbitrary polygon sets.
+
+File: gpc.pas
+Author: Alan Murta (gpc@cs.man.ac.uk)
+Version: 2.30
+Date: 17th October 1998
+
+Pascal port by: Stefan Schedel (Stefan.Schedel@loewe.de)
+
+Copyright: (C) 1997, Advanced Interfaces Group, University of Manchester.
+ All rights reserved.
+
+ This software may be freely copied, modified, and redistributed
+ provided that this copyright notice is preserved on all copies.
+ The intellectual property rights of the algorithms used reside
+ with the University of Manchester Advanced Interfaces Group.
+
+ You may not distribute this software, in whole or in part, as
+ part of any commercial product without the express consent of
+ the author.
+
+ There is no warranty or other guarantee of fitness of this
+ software for any purpose. It is provided solely "as is".
+
+===========================================================================
+*)
+
+unit GPC;
+
+interface
+uses
+ Windows;
+//===========================================================================
+// Constants
+//===========================================================================
+
+const
+ Version = 'GPC_VERSION "2.30"';
+ GPC_EPSILON : double = 2.2204460492503131E-16; { from float.h }
+
+//===========================================================================
+// Public Data Types
+//===========================================================================
+
+type
+
+ Tgpc_op = { Set operation type }
+ (
+ GPC_DIFF, { Difference }
+ GPC_INT, { Intersection }
+ GPC_XOR, { Exclusive or }
+ GPC_UNION { Union }
+ );
+
+ Tgpc_vertex = record { Polygon vertex structure }
+ x : double; { Vertex x component }
+ y : double; { vertex y component }
+ end;
+
+ Pgpc_vertex_array = ^Tgpc_vertex_array; { Helper Type for indexing }
+ Tgpc_vertex_array = array[0.. MaxInt div sizeof(Tgpc_vertex) - 1] of Tgpc_vertex;
+
+ Pgpc_vertex_list = ^Tgpc_vertex_list; { Vertex list structure }
+ Tgpc_vertex_list = record
+ num_vertices : integer; { Number of vertices in list }
+ vertex : Pgpc_vertex_array; { Vertex array pointer }
+ end;
+
+ PIntegerArray = ^TIntegerArray;
+ TIntegerArray = array[0..MaxInt div sizeof(Integer) - 1] of Integer;
+
+ Pgpc_vertex_list_array = ^Tgpc_vertex_list_array; { Helper Type for indexing }
+ Tgpc_vertex_list_array = array[0.. MaxInt div sizeof(Tgpc_vertex) - 1] of Tgpc_vertex_list;
+
+ Pgpc_polygon = ^Tgpc_polygon;
+ Tgpc_polygon = record { Polygon set structure }
+ num_contours : integer; { Number of contours in polygon }
+ hole : PIntegerArray; { Hole / external contour flags }
+ contour : Pgpc_vertex_list_array; { Contour array pointer }
+ end;
+
+ Pgpc_tristrip = ^Tgpc_tristrip; { Tristrip set structure }
+ Tgpc_tristrip = record
+ num_strips : integer; { Number of tristrips }
+ strip : Pgpc_vertex_list_array; { Tristrip array pointer }
+ end;
+
+
+
+//===========================================================================
+// Public Function Prototypes
+//===========================================================================
+
+
+procedure gpc_read_polygon (var f : text; p : Pgpc_polygon);
+
+procedure gpc_write_polygon (var f : text; p : Pgpc_polygon);
+
+procedure gpc_add_contour (polygon : Pgpc_polygon;
+ contour : Pgpc_vertex_list;
+ hole : integer);
+
+procedure gpc_polygon_clip (set_operation : Tgpc_op;
+ subject_polygon : Pgpc_polygon;
+ clip_polygon : Pgpc_polygon;
+ result_polygon : Pgpc_polygon);
+
+procedure gpc_free_polygon (polygon : Pgpc_polygon);
+
+procedure gpc_free_tristrip (tristrip : Pgpc_tristrip);
+
+
+
+
+implementation
+
+uses
+ SysUtils,
+ Math;
+
+
+
+//===========================================================================
+// Constants
+//===========================================================================
+
+const
+ DBL_MAX : double = MaxDouble;
+
+ DBL_DIG = 15;
+
+ FFALSE = 0;
+ FTRUE = 1;
+
+ LEFT = 0;
+ RIGHT = 1;
+
+ ABOVE = 0;
+ BELOW = 1;
+
+ CLIP = 0;
+ SUBJ = 1;
+
+ INVERT_TRISTRIPS = FALSE;
+
+
+
+//===========================================================================
+// Private Data Types
+//===========================================================================
+
+type
+ Tvertex_type =
+ ( { Edge intersection classes }
+ NUL, { Empty non-intersection }
+ EMX, { External maximum }
+ ELI, { External left intermediate }
+ TED, { Top edge }
+ ERI, { External right intermediate }
+ RED, { Right edge }
+ IMM, { Internal maximum and minimum }
+ IMN, { Internal minimum }
+ EMN, { External minimum }
+ EMM, { External maximum and minimum }
+ LED, { Left edge }
+ ILI, { Internal left intermediate }
+ BED, { Bottom edge }
+ IRI, { Internal right intermediate }
+ IMX, { Internal maximum }
+ FUL { Full non-intersection }
+ );
+
+Th_state = { Horizontal edge states }
+ (
+ NH, { No horizontal edge }
+ BH, { Bottom horizontal edge }
+ TH { Top horizontal edge }
+ );
+
+Tbundle_state =
+ (
+ UNBUNDLED,
+ BUNDLE_HEAD,
+ BUNDLE_TAIL
+ );
+
+ PPvertex_node = ^Pvertex_node;
+ Pvertex_node = ^Tvertex_node; { Internal vertex list datatype }
+ Tvertex_node = record
+ x : double; { X coordinate component }
+ y : double; { Y coordinate component }
+ next : Pvertex_node; { Pointer to next vertex in list }
+ end;
+
+ Pvertex_node_array = ^Tvertex_node_array; { Helper type for indexing }
+ Tvertex_node_array = array[0..1] of Pvertex_node;
+
+
+ PPpolygon_node = ^Ppolygon_node;
+ Ppolygon_node = ^Tpolygon_node;
+ Tpolygon_node = record
+ active : integer;
+ hole : integer;
+ v : array[0..1] of Pvertex_node;
+ Next : Ppolygon_node;
+ proxy : Ppolygon_node;
+ end;
+
+ PPedge_node = ^Pedge_node;
+ Pedge_node = ^Tedge_node;
+ Tedge_node = record
+ vertex : Tgpc_vertex; { Piggy-backed contour vertex data }
+ bot : Tgpc_vertex; { Edge lower (x, y) coordinate }
+ top : Tgpc_vertex; { Edge upper (x, y) coordinate }
+ xb : double; { Scanbeam bottom x coordinate }
+ xt : double; { Scanbeam top x coordinate }
+ dx : double; { Change in x for a unit y increase }
+ typ : integer; { Clip / subject edge flag }
+ bundle : array[0..1, 0..1] of integer;{ Bundle edge flags }
+ bside : array[0..1] of integer; { Bundle left / right indicators }
+ bstate : array[0..1] of Tbundle_state;{ Edge bundle state }
+ outp : array[0..1] of Ppolygon_node;{ Output polygon / tristrip pointer }
+ prev : Pedge_node; { Previous edge in the AET }
+ next : Pedge_node; { Next edge in the AET }
+ pred : Pedge_node; { Edge connected at the lower end }
+ succ : Pedge_node; { Edge connected at the upper end }
+ next_bound : Pedge_node; { Pointer to next bound in LMT }
+ end;
+
+ PPedge_node_array = ^Pedge_node_array;
+ Pedge_node_array = ^Tedge_node_array;
+ Tedge_node_array = array[0..MaxInt div sizeof(Tedge_node) - 1] of Tedge_node;
+
+ PPlmt_node = ^Plmt_node;
+ Plmt_node = ^Tlmt_node;
+ Tlmt_node = record { Local minima table }
+ y : double; { Y coordinate at local minimum }
+ first_bound: Pedge_node; { Pointer to bound list }
+ next : Plmt_node; { Pointer to next local minimum }
+ end;
+
+ PPsb_tree = ^Psb_tree;
+ Psb_tree = ^Tsb_tree;
+ Tsb_tree = record { Scanbeam tree }
+ y : double; { Scanbeam node y value }
+ less : Psb_tree; { Pointer to nodes with lower y }
+ more : Psb_tree; { Pointer to nodes with higher y }
+ end;
+
+
+ PPit_node = ^Pit_node;
+ Pit_node = ^Tit_node; { Intersection table }
+ Tit_node = record
+ ie : array[0..1] of Pedge_node;{ Intersecting edge (bundle) pair }
+ point : Tgpc_vertex; { Point of intersection }
+ next : Pit_node; { The next intersection table node }
+ end;
+
+ PPst_node = ^Pst_node;
+ Pst_node = ^Tst_node; { Sorted edge table }
+ Tst_node = record
+ edge : Pedge_node; { Pointer to AET edge }
+ xb : double; { Scanbeam bottom x coordinate }
+ xt : double; { Scanbeam top x coordinate }
+ dx : double; { Change in x for a unit y increase }
+ prev : Pst_node; { Previous edge in sorted list }
+ end;
+
+ Pbbox = ^Tbbox;
+ Tbbox = record { Contour axis-aligned bounding box }
+ xmin : double; { Minimum x coordinate }
+ ymin : double; { Minimum y coordinate }
+ xmax : double; { Maximum x coordinate }
+ ymax : double; { Maximum y coordinate }
+ end;
+
+ PbboxArray = ^TbboxArray;
+ TbboxArray = array[0..MaxInt div sizeof(Tbbox) - 1] of Tbbox;
+
+ PDoubleArray = ^TDoubleArray;
+ TDoubleArray = array[0..MaxInt div sizeof(double) - 1] of double;
+
+
+
+//===========================================================================
+// C Macros, defined as function for PASCAL
+//===========================================================================
+
+function EQ(a, b : double) : boolean; begin EQ := abs(a - b) <= gpc_epsilon end;
+function NE(a, b : double) : boolean; begin NE := abs(a - b) > gpc_epsilon end;
+function GT(a, b : double) : boolean; begin GT := (a - b) > gpc_epsilon end;
+function LT(a, b : double) : boolean; begin LT := (b - a) > gpc_epsilon end;
+function GE(a, b : double) : boolean; begin GE := not LT(a, b) end;
+function LE(a, b : double) : boolean; begin LE := not GT(a, b) end;
+
+function PREV_INDEX(i, n : integer) : integer; begin PREV_INDEX := ((i - 1 + n) mod n); end;
+function NEXT_INDEX(i, n : integer) : integer; begin NEXT_INDEX := ((i + 1) mod n); end;
+function OPTIMAL(v : Pgpc_vertex_array; i, n : integer) : boolean;
+begin
+ OPTIMAL := NE(v[PREV_INDEX(i, n)].y, v[i].y) or NE(v[NEXT_INDEX(i, n)].y, v[i].y);
+end;
+
+function FWD_MIN(v : Pedge_node_array; i, n : integer) : boolean;
+begin
+ FWD_MIN := GE(v[PREV_INDEX(i, n)].vertex.y, v[i].vertex.y) and GT(v[NEXT_INDEX(i, n)].vertex.y, v[i].vertex.y);
+end;
+
+function NOT_FMAX(v : Pedge_node_array; i, n : integer) : boolean;
+begin
+ NOT_FMAX := GT(v[NEXT_INDEX(i, n)].vertex.y, v[i].vertex.y);
+end;
+
+function REV_MIN(v : Pedge_node_array; i, n : integer) : boolean;
+begin
+ REV_MIN := GT(v[PREV_INDEX(i, n)].vertex.y, v[i].vertex.y) and GE(v[NEXT_INDEX(i, n)].vertex.y, v[i].vertex.y);
+end;
+
+
+function NOT_RMAX(v : Pedge_node_array; i, n : integer) : boolean;
+begin
+ NOT_RMAX := GT(v[PREV_INDEX(i, n)].vertex.y, v[i].vertex.y);
+end;
+
+
+procedure MALLOC(var p : pointer; b : integer; s : string);
+begin
+ GetMem(p, b); if (p = nil) and (b <> 0) then raise Exception.Create(s);
+end;
+
+
+procedure add_vertex(var p : Pvertex_node; x, y : double);
+begin
+ if p = nil then
+ begin
+ MALLOC(pointer(p), sizeof(Tvertex_node), 'tristrip vertex creation');
+ p.x := x;
+ p.y := y;
+ p.next := nil;
+ end
+ else
+ { Head further down the list }
+ add_vertex(p.next, x, y);
+end;
+
+
+procedure VERTEX(var e : Pedge_node; p, s : integer; var x, y : double);
+begin
+ add_vertex(e.outp[p].v[s], x, y);
+ Inc(e.outp[p].active);
+end;
+
+
+procedure P_EDGE(var d, e : Pedge_node; p : integer; var i, j : double);
+begin
+ d := e;
+ repeat d := d.prev until d.outp[p] = nil;
+ i := d.bot.x + d.dx * (j - d.bot.y);
+end;
+
+procedure N_EDGE(var d, e : Pedge_node; p : integer; var i, j : double);
+begin
+ d := e;
+ repeat d := d.next; until d.outp[p] = nil;
+ i := d.bot.x + d.dx * (j - d.bot.y);
+end;
+
+
+procedure Free(var p : pointer);
+begin
+ FreeMem(p); p := nil;
+end;
+
+
+procedure CFree(var p : pointer);
+begin
+ if p <> nil then Free(p);
+end;
+
+
+
+//===========================================================================
+// Global Data
+//===========================================================================
+
+
+
+{ Horizontal edge state transitions within scanbeam boundary }
+const
+ next_h_state : array[0..2, 0..5] of Th_state =
+ { ABOVE BELOW CROSS }
+ { L R L R L R }
+ { NH } ((BH, TH, TH, BH, NH, NH),
+ { BH } (NH, NH, NH, NH, TH, TH),
+ { TH } (NH, NH, NH, NH, BH, BH));
+
+
+
+
+//===========================================================================
+// Private Functions
+//===========================================================================
+
+
+procedure reset_it(var it : Pit_node);
+var
+ itn : Pit_node;
+begin
+ while (it <> nil) do
+ begin
+ itn := it.next;
+ Free(pointer(it));
+ it := itn;
+ end;
+end;
+
+
+procedure reset_lmt(var lmt : Plmt_node);
+var
+ lmtn : Plmt_node;
+begin
+ while lmt <> nil do
+ begin
+ lmtn := lmt^.next;
+ Free(pointer(lmt));
+ lmt := lmtn;
+ end;
+end;
+
+
+procedure insert_bound(b : PPedge_node_array; e : Pedge_node_array);
+var
+ existing_bound : pointer;
+begin
+ if b^ = nil then
+ begin
+ { Link node e to the tail of the list }
+ b^ := e;
+ end
+ else
+ begin
+ { Do primary sort on the x field }
+ if (LT(e[0].bot.x, b^[0].bot.x)) then
+ begin
+ { Insert a new node mid-list }
+ existing_bound := b^;
+ b^ := e;
+ b^[0].next_bound := existing_bound;
+ end
+ else
+ begin
+ if (EQ(e[0].bot.x, b^[0].bot.x)) then
+ begin
+ { Do secondary sort on the dx field }
+ if (LT(e[0].dx, b^[0].dx)) then
+ begin
+ { Insert a new node mid-list }
+ existing_bound := b^;
+ b^ := e;
+ b^[0].next_bound := existing_bound;
+ end
+ else
+ begin
+ { Head further down the list }
+ insert_bound(@(b^[0].next_bound), e);
+ end;
+ end
+ else
+ begin
+ { Head further down the list }
+ insert_bound(@(b^[0].next_bound), e);
+ end;
+ end;
+ end;
+end;
+
+
+function bound_list(var lmt : Plmt_node; y : double) : PPedge_node_array;
+var
+ existing_node : Plmt_node;
+begin
+ if lmt = nil then
+ begin
+ { Add node onto the tail end of the LMT }
+ MALLOC(pointer(lmt), sizeof(Tlmt_node), 'LMT insertion');
+ lmt.y := y;
+ lmt.first_bound := nil;
+ lmt.next := nil;
+ result := @lmt.first_bound;
+ end
+ else
+ if LT(y, lmt.y) then
+ begin
+ { Insert a new LMT node before the current node }
+ existing_node := lmt;
+ MALLOC(pointer(lmt), sizeof(Tlmt_node), 'LMT insertion');
+ lmt.y := y;
+ lmt.first_bound := nil;
+ lmt.next := existing_node;
+ result := @lmt.first_bound;
+ end
+ else
+ if EQ(y, lmt.y) then
+ { Use this existing LMT node }
+ Result := @lmt.first_bound
+ else
+ { Head further up the LMT }
+ Result := bound_list(lmt.next, y);
+end;
+
+
+procedure add_to_sbtree(var entries : integer; var sbtree : Psb_tree; var y : double);
+begin
+ if sbtree = nil then
+ begin
+ { Add a new tree node here }
+ MALLOC(pointer(sbtree), sizeof(Tsb_tree), 'scanbeam tree insertion');
+ sbtree.y := y;
+ sbtree.less := nil;
+ sbtree.more := nil;
+ Inc(entries);
+ end
+ else
+ begin
+ if GT(sbtree.y, y) then
+ begin
+ { Head into the 'less' sub-tree }
+ add_to_sbtree(entries, sbtree.less, y);
+ end
+ else
+ begin
+ if LT(sbtree.y, y) then
+ begin
+ { Head into the 'more' sub-tree }
+ add_to_sbtree(entries, sbtree.more, y);
+ end;
+ end;
+ end;
+end;
+
+
+procedure build_sbt(var entries : integer; var sbt : TDoubleArray; sbtree : Psb_tree);
+begin
+ if sbtree.less <> nil then
+ build_sbt(entries, sbt, sbtree.less);
+ sbt[entries] := sbtree.y;
+ Inc(entries);
+ if sbtree.more <> nil then
+ build_sbt(entries, sbt, sbtree.more);
+end;
+
+
+procedure free_sbtree(var sbtree : Psb_tree);
+begin
+ if sbtree <> nil then
+ begin
+ free_sbtree(sbtree.less);
+ free_sbtree(sbtree.more);
+ Free(pointer(sbtree));
+ end;
+end;
+
+
+function count_optimal_vertices(c : Tgpc_vertex_list) : integer;
+var
+ i : integer;
+begin
+ Result := 0;
+
+ { Ignore non-contributing contours }
+ if c.num_vertices > 0 then
+ begin
+ for i := 0 to c.num_vertices - 1 do
+ { Ignore superfluous vertices embedded in horizontal edges }
+ if OPTIMAL(c.vertex, i, c.num_vertices) then Inc(Result);
+ end;
+end;
+
+
+function build_lmt(var lmt : Plmt_node; var sbtree : Psb_tree; var sbt_entries : integer;
+ p : Pgpc_polygon; typ : integer; op : Tgpc_op) : Pedge_node_array;
+
+var
+ c, i, min, max, num_edges, v, num_vertices : integer;
+ total_vertices, e_index : integer;
+ e, edge_table : Pedge_node_array;
+begin
+ total_vertices := 0; e_index := 0;
+
+ for c := 0 to p.num_contours - 1 do
+ Inc(total_vertices, count_optimal_vertices(p.contour[c]));
+
+ { Create the entire input polygon edge table in one go }
+ MALLOC(pointer(edge_table), total_vertices * sizeof(Tedge_node),
+ 'edge table creation');
+
+ for c := 0 to p.num_contours - 1 do
+ begin
+ if p.contour[c].num_vertices < 0 then
+ begin
+ { Ignore the non-contributing contour and repair the vertex count }
+ p.contour[c].num_vertices := -p.contour[c].num_vertices;
+ end
+ else
+ begin
+ { Perform contour optimisation }
+ num_vertices := 0;
+ for i := 0 to p.contour[c].num_vertices - 1 do
+ if (OPTIMAL(p.contour[c].vertex, i, p.contour[c].num_vertices)) then
+ begin
+ edge_table[num_vertices].vertex.x := p.contour[c].vertex[i].x;
+ edge_table[num_vertices].vertex.y := p.contour[c].vertex[i].y;
+
+ { Record vertex in the scanbeam table }
+ add_to_sbtree(sbt_entries, sbtree, edge_table[num_vertices].vertex.y);
+
+ Inc(num_vertices);
+ end;
+
+ { Do the contour forward pass }
+ for min := 0 to num_vertices - 1 do
+ begin
+ { If a forward local minimum... }
+ if FWD_MIN(edge_table, min, num_vertices) then
+ begin
+ { Search for the next local maximum... }
+ num_edges := 1;
+ max := NEXT_INDEX(min, num_vertices);
+ while (NOT_FMAX(edge_table, max, num_vertices)) do
+ begin
+ Inc(num_edges);
+ max := NEXT_INDEX(max, num_vertices);
+ end;
+
+ { Build the next edge list }
+ e := @edge_table[e_index];
+ Inc(e_index, num_edges);
+ v := min;
+ e[0].bstate[BELOW] := UNBUNDLED;
+ e[0].bundle[BELOW][CLIP] := FFALSE;
+ e[0].bundle[BELOW][SUBJ] := FFALSE;
+ for i := 0 to num_edges - 1 do
+ begin
+ e[i].xb := edge_table[v].vertex.x;
+ e[i].bot.x := edge_table[v].vertex.x;
+ e[i].bot.y := edge_table[v].vertex.y;
+
+ v := NEXT_INDEX(v, num_vertices);
+
+ e[i].top.x := edge_table[v].vertex.x;
+ e[i].top.y := edge_table[v].vertex.y;
+ e[i].dx := (edge_table[v].vertex.x - e[i].bot.x) /
+ (e[i].top.y - e[i].bot.y);
+ e[i].typ := typ;
+ e[i].outp[ABOVE] := nil;
+ e[i].outp[BELOW] := nil;
+ e[i].next := nil;
+ e[i].prev := nil;
+ if (num_edges > 1) and (i < (num_edges - 1)) then e[i].succ := @e[i + 1] else
+ e[i].succ := nil;
+ if (num_edges > 1) and (i > 0) then e[i].pred := @e[i - 1] else e[i].pred := nil;
+ e[i].next_bound := nil;
+ if op = GPC_DIFF then e[i].bside[CLIP] := RIGHT else e[i].bside[CLIP] := LEFT;
+ e[i].bside[SUBJ] := LEFT;
+ end;
+ insert_bound(bound_list(lmt, edge_table[min].vertex.y), e);
+ end;
+ end;
+
+ { Do the contour reverse pass }
+ for min := 0 to num_vertices - 1 do
+ begin
+ { If a reverse local minimum... }
+ if REV_MIN(edge_table, min, num_vertices) then
+ begin
+ { Search for the previous local maximum... }
+ num_edges := 1;
+ max := PREV_INDEX(min, num_vertices);
+ while NOT_RMAX(edge_table, max, num_vertices) do
+ begin
+ Inc(num_edges);
+ max := PREV_INDEX(max, num_vertices);
+ end;
+
+ { Build the previous edge list }
+ e := @edge_table[e_index];
+ Inc(e_index, num_edges);
+ v := min;
+ e[0].bstate[BELOW] := UNBUNDLED;
+ e[0].bundle[BELOW][CLIP] := FFALSE;
+ e[0].bundle[BELOW][SUBJ] := FFALSE;
+ for i := 0 to num_edges - 1 do
+ begin
+ e[i].xb := edge_table[v].vertex.x;
+ e[i].bot.x := edge_table[v].vertex.x;
+ e[i].bot.y := edge_table[v].vertex.y;
+
+ v := PREV_INDEX(v, num_vertices);
+
+ e[i].top.x := edge_table[v].vertex.x;
+ e[i].top.y := edge_table[v].vertex.y;
+ e[i].dx := (edge_table[v].vertex.x - e[i].bot.x) /
+ (e[i].top.y - e[i].bot.y);
+ e[i].typ := typ;
+ e[i].outp[ABOVE] := nil;
+ e[i].outp[BELOW] := nil;
+ e[i].next := nil;
+ e[i].prev := nil;
+ if (num_edges > 1) and (i < (num_edges - 1)) then e[i].succ := @e[i + 1] else
+ e[i].succ := nil;
+ if (num_edges > 1) and (i > 0) then e[i].pred := @e[i - 1] else e[i].pred := nil;
+ e[i].next_bound := nil;
+ if op = GPC_DIFF then e[i].bside[CLIP] := RIGHT else e[i].bside[CLIP] := LEFT;
+ e[i].bside[SUBJ] := LEFT;
+ end;
+ insert_bound(bound_list(lmt, edge_table[min].vertex.y), e);
+ end;
+ end;
+ end;
+ end;
+ Result := edge_table;
+end;
+
+
+
+procedure add_edge_to_aet(var aet : Pedge_node; edge : Pedge_node; prev : Pedge_node);
+begin
+ if aet = nil then
+ begin
+ { Append edge onto the tail end of the AET }
+ aet := edge;
+ edge.prev := prev;
+ edge.next := nil;
+ end
+ else
+ begin
+ { Do primary sort on the xb field }
+ if LT(edge.xb, aet.xb) then
+ begin
+ { Insert edge here (before the AET edge) }
+ edge.prev := prev;
+ edge.next := aet;
+ aet.prev := edge;
+ aet := edge;
+ end
+ else
+ begin
+ if EQ(edge.xb, aet.xb) then
+ begin
+ { Do secondary sort on the dx field }
+ if LT(edge.dx, aet.dx) then
+ begin
+ { Insert edge here (before the AET edge) }
+ edge.prev := prev;
+ edge.next := aet;
+ aet.prev := edge;
+ aet := edge;
+ end
+ else
+ begin
+ { Head further into the AET }
+ add_edge_to_aet(aet.next, edge, aet);
+ end;
+ end
+ else
+ begin
+ { Head further into the AET }
+ add_edge_to_aet(aet.next, edge, aet);
+ end;
+ end;
+ end;
+end;
+
+
+
+procedure add_intersection(var it : Pit_node; edge0, edge1 : Pedge_node; x, y : double);
+var
+ existing_node : Pit_node;
+begin
+
+ if it = nil then
+ begin
+ { Append a new node to the tail of the list }
+ MALLOC(pointer(it), sizeof(Tit_node), 'IT insertion');
+ it.ie[0] := edge0;
+ it.ie[1] := edge1;
+ it.point.x := x;
+ it.point.y := y;
+ it.next := nil;
+ end
+ else
+ begin
+ if GT(it.point.y, y) then
+ begin
+ { Insert a new node mid-list }
+ existing_node := it;
+ MALLOC(pointer(it), sizeof(Tit_node), 'IT insertion');
+ it.ie[0] := edge0;
+ it.ie[1] := edge1;
+ it.point.x := x;
+ it.point.y := y;
+ it.next := existing_node;
+ end
+ else
+ { Head further down the list }
+ add_intersection(it.next, edge0, edge1, x, y);
+ end;
+end;
+
+
+
+procedure add_st_edge(var st : Pst_node; var it : Pit_node; edge : Pedge_node; dy : double);
+var
+ existing_node : Pst_node;
+ den, x, y, r : double;
+begin
+ if st = nil then
+ begin
+ { Append edge onto the tail end of the ST }
+ MALLOC(pointer(st), sizeof(Tst_node), 'ST insertion');
+ st.edge := edge;
+ st.xb := edge.xb;
+ st.xt := edge.xt;
+ st.dx := edge.dx;
+ st.prev := nil;
+ end
+ else
+ begin
+ den := (st.xt - st.xb) - (edge.xt - edge.xb);
+
+ { If new edge and ST edge don't cross }
+ if (GE(edge.xt, st.xt) or EQ(edge.dx, st.dx) or EQ(den, 0.0)) then
+ begin
+ { No intersection - insert edge here (before the ST edge) }
+ existing_node := st;
+ MALLOC(pointer(st), sizeof(Tst_node), 'ST insertion');
+ st.edge := edge;
+ st.xb := edge.xb;
+ st.xt := edge.xt;
+ st.dx := edge.dx;
+ st.prev := existing_node;
+ end
+ else
+ begin
+ { Compute intersection between new edge and ST edge }
+ r := (edge.xb - st.xb) / den;
+ x := st.xb + r * (st.xt - st.xb);
+ y := r * dy;
+
+ { Insert the edge pointers and the intersection point in the IT }
+ add_intersection(it, st.edge, edge, x, y);
+
+ { Head further into the ST }
+ add_st_edge(st.prev, it, edge, dy);
+
+ end;
+ end;
+end;
+
+
+
+procedure build_intersection_table(var it : Pit_node; aet : Pedge_node; dy : double);
+var
+ st, stp : Pst_node;
+ edge : Pedge_node;
+begin
+
+ { Build intersection table for the current scanbeam }
+ reset_it(it);
+ st := nil;
+
+ { Process each AET edge }
+ edge := aet;
+ while edge <> nil do
+ begin
+ if (edge.bstate[ABOVE] = BUNDLE_HEAD) or
+ (edge.bundle[ABOVE][CLIP] <> 0) or (edge.bundle[ABOVE][SUBJ] <> 0) then
+ add_st_edge(st, it, edge, dy);
+ edge := edge.next;
+ end;
+
+ { Free the sorted edge table }
+ while st <> nil do
+ begin
+ stp := st.prev;
+ Free(pointer(st));
+ st := stp;
+ end;
+end;
+
+
+
+function count_contours(polygon : Ppolygon_node) : integer;
+var
+ nv : integer;
+ v, nextv : Pvertex_node;
+begin
+
+ Result := 0;
+ while polygon <> nil do
+ begin
+ if polygon.active <> 0 then
+ begin
+ { Count the vertices in the current contour }
+ nv := 0;
+ v := polygon.proxy.v[LEFT];
+ while v <> nil do begin Inc(nv); v := v.next; end;
+
+ { Record valid vertex counts in the active field }
+ if (nv > 2) then
+ begin
+ polygon.active := nv;
+ Inc(Result);
+ end
+ else
+ begin
+ { Invalid contour: just free the heap }
+ v := polygon.proxy.v[LEFT];
+ while v <> nil do begin nextv := v.next; FREE(pointer(v)); v := nextv; end;
+ polygon.active := 0;
+ end;
+ end;
+
+ polygon := polygon.next;
+ end;
+end;
+
+
+procedure add_left(p : Ppolygon_node; x, y : double);
+var
+ nv : Pvertex_node;
+begin
+ { Create a new vertex node and set its fields }
+ MALLOC(pointer(nv), sizeof(Tvertex_node), 'vertex node creation');
+ nv.x := x;
+ nv.y := y;
+
+ { Add vertex nv to the left end of the polygon's vertex list }
+ nv.next := P.proxy.v[LEFT];
+
+ { Update proxy[LEFT] to point to nv }
+ P.proxy.v[LEFT] := nv;
+end;
+
+
+procedure merge_left(P : Ppolygon_node; Q :Ppolygon_node; list : Ppolygon_node);
+var
+ target : Ppolygon_node;
+begin
+ { Label contour as a hole }
+ q.proxy.hole := FTRUE;
+
+ if P.proxy <> Q.proxy then
+ begin
+ { Assign P's vertex list to the left end of Q's list }
+ P.proxy.v[RIGHT].next := Q.proxy.v[LEFT];
+ Q.proxy.v[LEFT] := P.proxy.v[LEFT];
+
+ { Redirect any P->proxy references to Q->proxy }
+ target := P.proxy;
+ while list <> nil do
+ begin
+ if list.proxy = target then
+ begin
+ list.active := FFALSE;
+ list.proxy := Q.proxy;
+ end;
+ list := list.next;
+ end;
+ end;
+end;
+
+
+procedure add_right(P : Ppolygon_node; x, y : double);
+var
+ nv : Pvertex_node;
+begin
+
+ { Create a new vertex node and set its fields }
+ MALLOC(pointer(nv), sizeof(Tvertex_node), 'vertex node creation');
+ nv.x := x;
+ nv.y := y;
+ nv.next := nil;
+
+ { Add vertex nv to the right end of the polygon's vertex list }
+ P.proxy.v[RIGHT].next := nv;
+
+ { Update proxy.v[RIGHT] to point to nv }
+ P.proxy.v[RIGHT] := nv;
+end;
+
+
+procedure merge_right(P : Ppolygon_node; Q : Ppolygon_node; list : Ppolygon_node);
+var
+ target : PPolygon_node;
+begin
+ { Label contour as external }
+ Q.proxy.hole := FFALSE;
+
+ if P.proxy <> Q.proxy then
+ begin
+ { Assign P's vertex list to the right end of Q's list }
+ Q.proxy.v[RIGHT].next := P.proxy.v[LEFT];
+ Q.proxy.v[RIGHT] := P.proxy.v[RIGHT];
+
+ { Redirect any P->proxy references to Q->proxy }
+ target := P.proxy;
+ while list <> nil do
+ begin
+ if list.proxy = target then
+ begin
+ list.active := FFALSE;
+ list.proxy := Q.proxy;
+ end;
+ list := list.next;
+ end;
+ end;
+end;
+
+
+procedure add_local_min(P : PPpolygon_node; edge : Pedge_node; x, y : double);
+var
+ nv : Pvertex_node;
+ existing_min : Ppolygon_node;
+begin
+ existing_min := p^;
+
+ MALLOC(pointer(P^), sizeof(Tpolygon_node), 'polygon node creation');
+
+ { Create a new vertex node and set its fields }
+ MALLOC(pointer(nv), sizeof(Tvertex_node), 'vertex node creation');
+ nv.x := x;
+ nv.y := y;
+ nv.next := nil;
+
+ { Initialise proxy to point to p itself }
+ p^.proxy := P^;
+ p^.active := FTRUE;
+ p^.next := existing_min;
+
+ { Make v[LEFT] and v[RIGHT] point to new vertex nv }
+ p^.v[LEFT] := nv;
+ p^.v[RIGHT] := nv;
+
+ { Assign polygon p to the edge }
+ edge.outp[ABOVE] := p^;
+end;
+
+
+function count_tristrips(tn : Ppolygon_node) : integer;
+begin
+ Result := 0;
+
+ while tn <> nil do
+ begin
+ if tn.active > 2 then Inc(Result);
+ tn := tn.next;
+ end;
+end;
+
+(*
+procedure add_vertex(t : PPvertex_node; x, y : double)
+begin
+ if t^ <> nil then
+ begin
+ MALLOC(t^, sizeof(Tvertex_node), ttristrip vertex creationt');
+ t^.x := x;
+ t^.y := y;
+ t^.next := nil;
+ end
+ else
+ { Head further down the list }
+ add_vertex(@t^.next, x, y);
+end;
+*)
+
+procedure new_tristrip(var tn : Ppolygon_node; edge : Pedge_node; x, y : double);
+begin
+ if tn = nil then
+ begin
+ MALLOC(pointer(tn), sizeof(Tpolygon_node), 'tristrip node creation');
+ tn.next := nil;
+ tn.v[LEFT] := nil;
+ tn.v[RIGHT] := nil;
+ tn.active := 1;
+ add_vertex(tn.v[LEFT], x, y);
+ edge.outp[ABOVE] := tn;
+ end
+ else
+ { Head further down the list }
+ new_tristrip(tn.next, edge, x, y);
+end;
+
+
+function create_contour_bboxes(p : Pgpc_polygon) : PbboxArray;
+var
+ c, v : integer;
+begin
+ MALLOC(pointer(Result), p.num_contours * sizeof(Tbbox), 'Bounding box creation');
+
+ { Construct contour bounding boxes }
+ for c := 0 to p.num_contours - 1 do
+ begin
+ { Initialise bounding box extent }
+ Result[c].xmin := DBL_MAX;
+ Result[c].ymin := DBL_MAX;
+ Result[c].xmax := -DBL_MAX;
+ Result[c].ymax := -DBL_MAX;
+
+ for v := 0 to p.contour[c].num_vertices - 1 do
+ begin
+ { Adjust bounding Result }
+ if (p.contour[c].vertex[v].x < Result[c].xmin) then
+ Result[c].xmin := p.contour[c].vertex[v].x;
+ if (p.contour[c].vertex[v].y < Result[c].ymin) then
+ Result[c].ymin := p.contour[c].vertex[v].y;
+ if (p.contour[c].vertex[v].x > Result[c].xmax) then
+ Result[c].xmax := p.contour[c].vertex[v].x;
+ if (p.contour[c].vertex[v].y > Result[c].ymax) then
+ Result[c].ymax := p.contour[c].vertex[v].y;
+ end;
+ end;
+end;
+
+
+procedure minimax_test(subj : Pgpc_polygon; clip : Pgpc_polygon; op : Tgpc_op);
+var
+ s_bbox, c_bbox : PbboxArray;
+ s, c : integer;
+ o_table : PIntegerArray;
+ overlap : integer;
+begin
+ s_bbox := create_contour_bboxes(subj);
+ c_bbox := create_contour_bboxes(clip);
+
+ MALLOC(pointer(o_table), subj.num_contours * clip.num_contours * sizeof(Integer),
+ 'overlap table creation');
+
+ { Check all subject contour bounding boxes against clip boxes }
+ for s := 0 to subj.num_contours - 1 do
+ for c := 0 to clip.num_contours - 1 do
+ o_table[c * subj.num_contours + s] := integer(
+ (not(LT(s_bbox[s].xmax, c_bbox[c].xmin) or
+ GT(s_bbox[s].xmin, c_bbox[c].xmax))) and
+ (not(LT(s_bbox[s].ymax, c_bbox[c].ymin) or
+ GT(s_bbox[s].ymin, c_bbox[c].ymax))));
+
+ { For each clip contour, search for any subject contour overlaps }
+ for c := 0 to clip.num_contours - 1 do
+ begin
+ overlap := 0; s := 0;
+ while (overlap = 0) and (s < subj.num_contours) do
+ begin
+ overlap := o_table[c * subj.num_contours + s];
+ Inc(s);
+ end;
+
+ if overlap = 0 then
+ { Flag non contributing status by negating vertex count }
+ clip.contour[c].num_vertices := -clip.contour[c].num_vertices;
+ end;
+
+ if (op = GPC_INT) then
+ begin
+ { For each subject contour, search for any clip contour overlaps }
+ for s := 0 to subj.num_contours - 1 do
+ begin
+ overlap := 0; c := 0;
+ while (overlap = 0) and (c < clip.num_contours) do
+ begin
+ overlap := o_table[c * subj.num_contours + s];
+ Inc(c);
+ end;
+
+ if overlap = 0 then
+ { Flag non contributing status by negating vertex count }
+ subj.contour[s].num_vertices := -subj.contour[s].num_vertices;
+ end;
+ end;
+
+ FREE(pointer(s_bbox));
+ FREE(pointer(c_bbox));
+ FREE(pointer(o_table));
+end;
+
+
+//===========================================================================
+// Public Functions
+//===========================================================================
+
+
+procedure gpc_free_polygon(Polygon : Pgpc_polygon);
+var
+ c : integer;
+begin
+ for c := 0 to Polygon.num_contours - 1 do
+ CFree(pointer(Polygon.contour[c].vertex));
+
+ CFree(pointer(Polygon.hole));
+ CFree(pointer(Polygon.contour));
+ Polygon.num_contours := 0;
+end;
+
+
+procedure gpc_read_polygon(var f : text; p : Pgpc_polygon);
+var
+ c, v : integer;
+begin
+ readln(f, p.num_contours);
+ MALLOC(pointer(p.contour), p.num_contours * sizeof(Tgpc_vertex_list), 'contour creation');
+ for c := 0 to p.num_contours - 1 do
+ begin
+ readln(f, p.contour[c].num_vertices);
+ MALLOC(pointer(p.contour[c].vertex), p.contour[c].num_vertices * sizeof(Tgpc_vertex), 'vertex creation');
+ for v := 0 to p.contour[c].num_vertices - 1 do
+ begin
+ read(f, p.contour[c].vertex[v].x);
+ readln(f, p.contour[c].vertex[v].y);
+ end;
+ end;
+end;
+
+
+procedure gpc_write_polygon(var f : text; p : Pgpc_polygon);
+var
+ c, v : integer;
+begin
+ writeln(f, p.num_contours);
+ for c := 0 to p.num_contours - 1 do
+ begin
+ writeln(f, p.contour[c].num_vertices);
+ for v := 0 to p.contour[c].num_vertices - 1 do
+ writeln(f, p.contour[c].vertex[v].x:20:DBL_DIG , ' ' , p.contour[c].vertex[v].y:20:DBL_DIG);
+ end;
+end;
+
+
+procedure gpc_add_contour(polygon : Pgpc_polygon; contour : Pgpc_vertex_list; hole : integer);
+var
+ c, v : integer;
+ extended_hole : PIntegerArray;
+ extended_contour : Pgpc_vertex_list_array;
+begin
+
+ { Create an extended hole array }
+ MALLOC(pointer(extended_hole), (polygon.num_contours + 1)
+ * sizeof(integer), 'contour hole addition');
+
+ { Create an extended contour array }
+ MALLOC(pointer(extended_contour), (polygon.num_contours + 1)
+ * sizeof(Tgpc_vertex_list), 'contour addition');
+
+ { Copy the old contour into the extended contour array }
+ for c := 0 to polygon.num_contours - 1 do
+ begin
+ extended_hole[c] := polygon.hole[c];
+ extended_contour[c] := polygon.contour[c];
+ end;
+
+ { Copy the new contour onto the end of the extended contour array }
+ c := polygon.num_contours;
+ extended_hole[c] := hole;
+ extended_contour[c].num_vertices := contour.num_vertices;
+ MALLOC(pointer(extended_contour[c].vertex), contour.num_vertices
+ * sizeof(Tgpc_vertex), 'contour addition');
+ for v := 0 to contour.num_vertices - 1 do
+ extended_contour[c].vertex[v] := contour.vertex[v];
+
+ { Dispose of the old contour }
+ CFREE(pointer(polygon.contour));
+ CFREE(pointer(polygon.hole));
+
+ { Update the polygon information }
+ Inc(polygon.num_contours);
+ polygon.hole := extended_hole;
+ polygon.contour := extended_contour;
+end;
+
+
+procedure gpc_polygon_clip(set_operation : Tgpc_op; subject_polygon : Pgpc_polygon;
+ clip_polygon : Pgpc_polygon; result_polygon : Pgpc_polygon);
+
+var
+ sbtree : Psb_tree;
+ it, intersect : Pit_node;
+ edge, prev_edge, next_edge, succ_edge : Pedge_node;
+ e0, e1 : Pedge_node;
+ aet : Pedge_node;
+ c_heap, s_heap : Pedge_node_array;
+ lmt, local_min : Plmt_node;
+ out_poly, P, Q, poly, npoly, cf : Ppolygon_node;
+ vtx, nv : Pvertex_node;
+ horiz : array[0..1] of Th_state;
+ inn, exists, parity : array[0..1] of integer;
+ c, v, contributing, search, scanbeam : integer;
+ sbt_entries, _class, bl, br, tl, tr : integer;
+ sbt : PDoubleArray;
+ xb, px, yb, yt, dy, ix, iy : double;
+begin
+ edge := nil;
+ sbtree := nil; it := nil; aet := nil; lmt := nil;
+ out_poly := nil; cf := nil;
+ inn[0] := LEFT; inn[1] := LEFT;
+ exists[0] := LEFT; exists[1] := LEFT;
+ parity[0] := LEFT; parity[1] := LEFT;
+ scanbeam := 0; sbt_entries := 0;
+ sbt := nil;
+
+ { Test for trivial NULL result cases }
+ if ((subject_polygon.num_contours = 0) and (clip_polygon.num_contours = 0))
+ or ((subject_polygon.num_contours = 0) and ((set_operation = GPC_INT) or (set_operation = GPC_DIFF)))
+ or ((clip_polygon.num_contours = 0) and (set_operation = GPC_INT)) then
+ begin
+ result_polygon.num_contours := 0;
+ result_polygon.hole := nil;
+ result_polygon.contour := nil;
+ exit;
+ end;
+
+ { Identify potentialy contributing contours }
+ if (((set_operation = GPC_INT) or (set_operation = GPC_DIFF))
+ and (subject_polygon.num_contours > 0) and (clip_polygon.num_contours > 0)) then
+ minimax_test(subject_polygon, clip_polygon, set_operation);
+
+ { Build LMT }
+ if subject_polygon.num_contours > 0 then
+ s_heap := build_lmt(lmt, sbtree, sbt_entries, subject_polygon, SUBJ, set_operation);
+ if clip_polygon.num_contours > 0 then
+ c_heap := build_lmt(lmt, sbtree, sbt_entries, clip_polygon, CLIP, set_operation);
+
+ { Return a NULL result if no contours contribute }
+ if lmt = nil then
+ begin
+ result_polygon.num_contours := 0;
+ result_polygon.hole := nil;
+ result_polygon.contour := nil;
+ reset_lmt(lmt);
+ FREE(pointer(s_heap));
+ FREE(pointer(c_heap));
+ exit;
+ end;
+
+ { Build scanbeam table from scanbeam tree }
+ MALLOC(pointer(sbt), sbt_entries * sizeof(double), 'sbt creation');
+ build_sbt(scanbeam, sbt^, sbtree);
+ scanbeam := 0;
+ free_sbtree(sbtree);
+
+ { Allow pointer re-use without causing memory leak }
+ if subject_polygon = result_polygon then
+ gpc_free_polygon(subject_polygon);
+ if clip_polygon = result_polygon then
+ gpc_free_polygon(clip_polygon);
+
+ { Invert clip polygon for difference operation }
+ if set_operation = GPC_DIFF then
+ parity[CLIP] := RIGHT;
+
+ local_min := lmt;
+
+ { Process each scanbeam }
+ while (scanbeam < sbt_entries) do
+ begin
+ { Set yb and yt to the bottom and top of the scanbeam }
+ yb := sbt[scanbeam]; Inc(scanbeam);
+ if scanbeam < sbt_entries then
+ begin
+ yt := sbt[scanbeam];
+ dy := yt - yb;
+ end;
+
+ { === SCANBEAM BOUNDARY PROCESSING ================================ }
+
+ { If LMT node corresponding to yb exists }
+ if local_min <> nil then
+ begin
+ if EQ(local_min.y, yb) then
+ begin
+ { Add edges starting at this local minimum to the AET }
+ edge := local_min.first_bound;
+ while edge <> nil do
+ begin
+ add_edge_to_aet(aet, edge, nil);
+ edge := edge.next_bound;
+ end;
+ local_min := local_min.next;
+ end;
+ end;
+
+ { Set dummy previous x value }
+ px := -DBL_MAX;
+
+ { Create bundles within AET }
+ e0 := aet;
+ e1 := aet;
+
+ { Set up bundle fields of first edge }
+ aet.bundle[ABOVE][integer(aet.typ <> 0)] := integer(NE(aet.top.y, yb));
+ aet.bundle[ABOVE][integer(aet.typ = 0)] := FFALSE;
+ aet.bstate[ABOVE] := UNBUNDLED;
+
+ next_edge := aet.next;
+
+ while next_edge <> nil do
+ begin
+ { Set up bundle fields of next edge }
+ next_edge.bundle[ABOVE][next_edge.typ] := integer(NE(next_edge.top.y, yb));
+ next_edge.bundle[ABOVE][integer(next_edge.typ = 0)] := FFALSE;
+ next_edge.bstate[ABOVE] := UNBUNDLED;
+
+ { Bundle edges above the scanbeam boundary if they coincide }
+ if next_edge.bundle[ABOVE][next_edge.typ] <> 0 then
+ begin
+ if (EQ(e0.xb, next_edge.xb) and EQ(e0.dx, next_edge.dx)
+ and NE(e0.top.y, yb)) then
+ begin
+ next_edge.bundle[ABOVE][next_edge.typ] := next_edge.bundle[ABOVE][next_edge.typ] xor
+ e0.bundle[ABOVE][ next_edge.typ];
+ next_edge.bundle[ABOVE][integer(next_edge.typ = 0)] :=
+ e0.bundle[ABOVE][integer(next_edge.typ = 0)];
+ next_edge.bstate[ABOVE] := BUNDLE_HEAD;
+ e0.bundle[ABOVE][CLIP] := FFALSE;
+ e0.bundle[ABOVE][SUBJ] := FFALSE;
+ e0.bstate[ABOVE] := BUNDLE_TAIL;
+ end;
+ e0 := next_edge;
+ end;
+ next_edge := next_edge.next;
+ end;
+
+ horiz[CLIP] := NH;
+ horiz[SUBJ] := NH;
+
+ { Process each edge at this scanbeam boundary }
+ edge := aet;
+ while edge <> nil do
+ begin
+ exists[CLIP] := edge.bundle[ABOVE][CLIP] +
+ (edge.bundle[BELOW][CLIP] shl 1);
+ exists[SUBJ] := edge.bundle[ABOVE][SUBJ] +
+ (edge.bundle[BELOW][SUBJ] shl 1);
+
+ if (exists[CLIP] <> 0) or (exists[SUBJ] <> 0) then
+ begin
+ { Set bundle side }
+ edge.bside[CLIP] := parity[CLIP];
+ edge.bside[SUBJ] := parity[SUBJ];
+
+ { Determine contributing status and quadrant occupancies }
+ case set_operation of
+ GPC_DIFF,
+ GPC_INT: begin
+ contributing := integer( ((exists[CLIP] <> 0) and ((parity[SUBJ] <> 0) or (horiz[SUBJ] <> NH)))
+ or ((exists[SUBJ] <> 0) and ((parity[CLIP] <> 0) or (horiz[CLIP] <> NH)))
+ or ((exists[CLIP] <> 0) and (exists[SUBJ] <> 0) and (parity[CLIP] = parity[SUBJ])));
+ br := integer((parity[CLIP] <> 0) and (parity[SUBJ] <> 0));
+ bl := integer( ((parity[CLIP] xor edge.bundle[ABOVE][CLIP]) <> 0)
+ and ((parity[SUBJ] xor edge.bundle[ABOVE][SUBJ]) <> 0));
+ tr := integer( ((parity[CLIP] xor integer(horiz[CLIP] <> NH)) <> 0)
+ and ((parity[SUBJ] xor integer(horiz[SUBJ] <> NH)) <> 0));
+ tl := integer( ((parity[CLIP] xor integer(horiz[CLIP] <> NH) xor edge.bundle[BELOW][CLIP]) <> 0)
+ and ((parity[SUBJ] xor integer(horiz[SUBJ] <> NH) xor edge.bundle[BELOW][SUBJ]) <> 0));
+ end;
+
+ GPC_XOR: begin
+ contributing := integer((exists[CLIP] <> 0) or (exists[SUBJ] <> 0));
+ br := integer(parity[CLIP] xor parity[SUBJ]);
+ bl := integer( ((parity[CLIP] xor edge.bundle[ABOVE][CLIP]) <> 0)
+ xor ((parity[SUBJ] xor edge.bundle[ABOVE][SUBJ]) <> 0));
+ tr := integer( ((parity[CLIP] xor integer(horiz[CLIP] <> NH)) <> 0)
+ xor ((parity[SUBJ] xor integer(horiz[SUBJ] <> NH)) <> 0));
+ tl := integer( ((parity[CLIP] xor integer(horiz[CLIP] <> NH) xor edge.bundle[BELOW][CLIP]) <> 0)
+ xor ((parity[SUBJ] xor integer(horiz[SUBJ] <> NH) xor edge.bundle[BELOW][SUBJ]) <> 0));
+ end;
+
+ GPC_UNION: begin
+ contributing := integer( ((exists[CLIP] <> 0) and ((parity[SUBJ] = 0) or (horiz[SUBJ] <> NH)))
+ or ((exists[SUBJ] <> 0) and ((parity[CLIP] = 0) or (horiz[CLIP] <> NH)))
+ or ((exists[CLIP] <> 0) and (exists[SUBJ] <> 0) and (parity[CLIP] = parity[SUBJ])));
+
+ br := integer((parity[CLIP] <> 0) or (parity[SUBJ] <> 0));
+ bl := integer( ((parity[CLIP] xor edge.bundle[ABOVE][CLIP]) <> 0)
+ or ((parity[SUBJ] xor edge.bundle[ABOVE][SUBJ]) <> 0));
+ tr := integer( ((parity[CLIP] xor integer(horiz[CLIP] <> NH)) <> 0)
+ or ((parity[SUBJ] xor integer(horiz[SUBJ] <> NH)) <> 0));
+ tl := integer( ((parity[CLIP] xor integer(horiz[CLIP] <> NH) xor edge.bundle[BELOW][CLIP]) <> 0)
+ or ((parity[SUBJ] xor integer(horiz[SUBJ] <> NH) xor edge.bundle[BELOW][SUBJ]) <> 0));
+ end;
+ end; { case }
+
+ { Update parity }
+(* parity[CLIP] := integer((parity[CLIP] <> 0) xor (edge.bundle[ABOVE][CLIP] <> 0));
+ parity[SUBJ] := integer((parity[SUBJ] <> 0) xor (edge.bundle[ABOVE][SUBJ] <> 0));
+ *)
+ parity[CLIP] := parity[CLIP] xor edge.bundle[ABOVE][CLIP];
+ parity[SUBJ] := parity[SUBJ] xor edge.bundle[ABOVE][SUBJ];
+
+ { Update horizontal state }
+ if exists[CLIP] <> 0 then
+ horiz[CLIP] :=
+ next_h_state[integer(horiz[CLIP])]
+ [((exists[CLIP] - 1) shl 1) + parity[CLIP]];
+ if exists[SUBJ] <> 0 then
+ horiz[SUBJ] :=
+ next_h_state[integer(horiz[SUBJ])]
+ [((exists[SUBJ] - 1) shl 1) + parity[SUBJ]];
+
+ _class := tr + (tl shl 1) + (br shl 2) + (bl shl 3);
+
+ if contributing <> 0 then
+ begin
+ xb := edge.xb;
+
+ case Tvertex_type(_class) of
+ EMN,
+ IMN: begin
+ add_local_min(@out_poly, edge, xb, yb);
+ px := xb;
+ cf := edge.outp[ABOVE];
+ end;
+ ERI: begin
+ if NE(xb, px) then
+ begin
+ add_right(cf, xb, yb);
+ px := xb;
+ end;
+ edge.outp[ABOVE] := cf;
+ cf := nil;
+ end;
+ ELI: begin
+ add_left(edge.outp[BELOW], xb, yb);
+ px := xb;
+ cf := edge.outp[BELOW];
+ end;
+ EMX: begin
+ if NE(xb, px) then
+ begin
+ add_left(cf, xb, yb);
+ px := xb;
+ end;
+ merge_right(cf, edge.outp[BELOW], out_poly);
+ cf := nil;
+ end;
+ ILI: begin
+ if NE(xb, px) then
+ begin
+ add_left(cf, xb, yb);
+ px := xb;
+ end;
+ edge.outp[ABOVE] := cf;
+ cf := nil;
+ end;
+ IRI: begin
+ add_right(edge.outp[BELOW], xb, yb);
+ px := xb;
+ cf := edge.outp[BELOW];
+ edge.outp[BELOW] := nil;
+ end;
+ IMX: begin
+ if NE(xb, px) then
+ begin
+ add_right(cf, xb, yb);
+ px := xb;
+ end;
+ merge_left(cf, edge.outp[BELOW], out_poly);
+ cf := nil;
+ edge.outp[BELOW] := nil;
+ end;
+ IMM: begin
+ if NE(xb, px) then
+ begin
+ add_right(cf, xb, yb);
+ px := xb;
+ end;
+ merge_left(cf, edge.outp[BELOW], out_poly);
+ edge.outp[BELOW] := nil;
+ add_local_min(@out_poly, edge, xb, yb);
+ cf := edge.outp[ABOVE];
+ end;
+ EMM: begin
+ if NE(xb, px) then
+ begin
+ add_left(cf, xb, yb);
+ px := xb;
+ end;
+ merge_right(cf, edge.outp[BELOW], out_poly);
+ edge.outp[BELOW] := nil;
+ add_local_min(@out_poly, edge, xb, yb);
+ cf := edge.outp[ABOVE];
+ end;
+ LED: begin
+ if EQ(edge.bot.y, yb) then
+ add_left(edge.outp[BELOW], xb, yb);
+ edge.outp[ABOVE] := edge.outp[BELOW];
+ px := xb;
+ end;
+ RED: begin
+ if EQ(edge.bot.y, yb) then
+ add_right(edge.outp[BELOW], xb, yb);
+ edge.outp[ABOVE] := edge.outp[BELOW];
+ px := xb;
+ end;
+ else
+ end; { End of case }
+ end; { End of contributing conditional }
+ end; { End of edge exists conditional }
+ edge := edge.next;
+ end; { End of AET loop }
+
+ { Delete terminating edges from the AET, otherwise compute xt }
+ edge := aet;
+ while edge <> nil do
+ begin
+ if EQ(edge.top.y, yb) then
+ begin
+ prev_edge := edge.prev;
+ next_edge := edge.next;
+ if prev_edge <> nil then
+ prev_edge.next := next_edge
+ else
+ aet := next_edge;
+ if next_edge <> nil then
+ next_edge.prev := prev_edge;
+
+ { Copy bundle head state to the adjacent tail edge if required }
+ if (edge.bstate[BELOW] = BUNDLE_HEAD) and (prev_edge <> nil) then
+ begin
+ if prev_edge.bstate[BELOW] = BUNDLE_TAIL then
+ begin
+ prev_edge.outp[BELOW] := edge.outp[BELOW];
+ prev_edge.bstate[BELOW] := UNBUNDLED;
+ if prev_edge.prev <> nil then
+ if prev_edge.prev.bstate[BELOW] = BUNDLE_TAIL then
+ prev_edge.bstate[BELOW] := BUNDLE_HEAD;
+ end;
+ end;
+ end
+ else
+ begin
+ if EQ(edge.top.y, yt) then
+ edge.xt := edge.top.x
+ else
+ edge.xt := edge.bot.x + edge.dx * (yt - edge.bot.y);
+ end;
+
+ edge := edge.next;
+ end;
+
+ if scanbeam < sbt_entries then
+ begin
+ { === SCANBEAM INTERIOR PROCESSING ============================== }
+
+ build_intersection_table(it, aet, dy);
+
+ { Process each node in the intersection table }
+ intersect := it;
+ while intersect <> nil do
+ begin
+ e0 := intersect.ie[0];
+ e1 := intersect.ie[1];
+
+ { Only generate output for contributing intersections }
+ if ((e0.bundle[ABOVE][CLIP] <> 0) or (e0.bundle[ABOVE][SUBJ] <> 0))
+ and ((e1.bundle[ABOVE][CLIP] <> 0) or (e1.bundle[ABOVE][SUBJ] <> 0)) then
+ begin
+ P := e0.outp[ABOVE];
+ Q := e1.outp[ABOVE];
+ ix := intersect.point.x;
+ iy := intersect.point.y + yb;
+
+ inn[CLIP] := integer( ((e0.bundle[ABOVE][CLIP] <> 0) and (e0.bside[CLIP] = 0))
+ or ((e1.bundle[ABOVE][CLIP] <> 0) and (e1.bside[CLIP] <> 0))
+ or ((e0.bundle[ABOVE][CLIP] = 0) and (e1.bundle[ABOVE][CLIP] = 0)
+ and (e0.bside[CLIP] <> 0) and (e1.bside[CLIP] <> 0)));
+
+ inn[SUBJ] := integer( ((e0.bundle[ABOVE][SUBJ] <> 0) and (e0.bside[SUBJ] = 0))
+ or ((e1.bundle[ABOVE][SUBJ] <> 0) and (e1.bside[SUBJ] <> 0))
+ or ((e0.bundle[ABOVE][SUBJ] = 0) and (e1.bundle[ABOVE][SUBJ] = 0)
+ and (e0.bside[SUBJ] <> 0) and (e1.bside[SUBJ] <> 0)));
+
+ { Determine quadrant occupancies }
+ case set_operation of
+
+ GPC_DIFF,
+ GPC_INT: begin
+ tr := integer((inn[CLIP] <> 0) and (inn[SUBJ] <> 0));
+ tl := integer( ((inn[CLIP] xor e1.bundle[ABOVE][CLIP]) <> 0)
+ and ((inn[SUBJ] xor e1.bundle[ABOVE][SUBJ]) <> 0));
+ br := integer( ((inn[CLIP] xor e0.bundle[ABOVE][CLIP]) <> 0)
+ and ((inn[SUBJ] xor e0.bundle[ABOVE][SUBJ]) <> 0));
+ bl := integer( ((inn[CLIP] xor e1.bundle[ABOVE][CLIP] xor e0.bundle[ABOVE][CLIP]) <> 0)
+ and ((inn[SUBJ] xor e1.bundle[ABOVE][SUBJ] xor e0.bundle[ABOVE][SUBJ]) <> 0));
+ end;
+
+ GPC_XOR: begin
+ tr := integer((inn[CLIP] <> 0) xor (inn[SUBJ] <> 0));
+ tl := integer( (inn[CLIP] xor e1.bundle[ABOVE][CLIP])
+ xor (inn[SUBJ] xor e1.bundle[ABOVE][SUBJ]));
+ br := integer( (inn[CLIP] xor e0.bundle[ABOVE][CLIP])
+ xor (inn[SUBJ] xor e0.bundle[ABOVE][SUBJ]));
+ bl := integer( (inn[CLIP] xor e1.bundle[ABOVE][CLIP] xor e0.bundle[ABOVE][CLIP])
+ xor (inn[SUBJ] xor e1.bundle[ABOVE][SUBJ] xor e0.bundle[ABOVE][SUBJ]));
+ end;
+
+ GPC_UNION: begin
+ tr := integer((inn[CLIP] <> 0) or (inn[SUBJ] <> 0));
+ tl := integer( ((inn[CLIP] xor e1.bundle[ABOVE][CLIP]) <> 0)
+ or ((inn[SUBJ] xor e1.bundle[ABOVE][SUBJ]) <> 0));
+ br := integer( ((inn[CLIP] xor e0.bundle[ABOVE][CLIP]) <> 0)
+ or ((inn[SUBJ] xor e0.bundle[ABOVE][SUBJ]) <> 0));
+ bl := integer( ((inn[CLIP] xor e1.bundle[ABOVE][CLIP] xor e0.bundle[ABOVE][CLIP]) <> 0)
+ or ((inn[SUBJ] xor e1.bundle[ABOVE][SUBJ] xor e0.bundle[ABOVE][SUBJ]) <> 0));
+ end;
+ end; { case }
+
+ _class := tr + (tl shl 1) + (br shl 2) + (bl shl 3);
+
+ case Tvertex_type(_class) of
+ EMN: begin
+ add_local_min(@out_poly, e0, ix, iy);
+ e1.outp[ABOVE] := e0.outp[ABOVE];
+ end;
+ ERI: begin
+ if P <> nil then
+ begin
+ add_right(P, ix, iy);
+ e1.outp[ABOVE] := P;
+ e0.outp[ABOVE] := nil;
+ end;
+ end;
+ ELI: begin
+ if Q <> nil then
+ begin
+ add_left(Q, ix, iy);
+ e0.outp[ABOVE] := Q;
+ e1.outp[ABOVE] := nil;
+ end;
+ end;
+ EMX: begin
+ if (P <> nil) and (Q <> nil) then
+ begin
+ add_left(P, ix, iy);
+ merge_right(P, Q, out_poly);
+ e0.outp[ABOVE] := nil;
+ e1.outp[ABOVE] := nil;
+ end;
+ end;
+ IMN: begin
+ add_local_min(@out_poly, e0, ix, iy);
+ e1.outp[ABOVE] := e0.outp[ABOVE];
+ end;
+ ILI: begin
+ if P <> nil then
+ begin
+ add_left(P, ix, iy);
+ e1.outp[ABOVE] := P;
+ e0.outp[ABOVE] := nil;
+ end;
+ end;
+ IRI: begin
+ if Q <> nil then
+ begin
+ add_right(Q, ix, iy);
+ e0.outp[ABOVE] := Q;
+ e1.outp[ABOVE] := nil;
+ end;
+ end;
+ IMX: begin
+ if (P <> nil) and (Q <> nil) then
+ begin
+ add_right(P, ix, iy);
+ merge_left(P, Q, out_poly);
+ e0.outp[ABOVE] := nil;
+ e1.outp[ABOVE] := nil;
+ end;
+ end;
+ IMM: begin
+ if (P <> nil) and (Q <> nil) then
+ begin
+ add_right(P, ix, iy);
+ merge_left(P, Q, out_poly);
+ add_local_min(@out_poly, e0, ix, iy);
+ e1.outp[ABOVE] := e0.outp[ABOVE];
+ end;
+ end;
+ EMM: begin
+ if (P <> nil) and (Q <> nil) then
+ begin
+ add_left(P, ix, iy);
+ merge_right(P, Q, out_poly);
+ add_local_min(@out_poly, e0, ix, iy);
+ e1.outp[ABOVE] := e0.outp[ABOVE];
+ end;
+ end;
+ else
+ end; { End of case }
+ end; { End of contributing intersection conditional }
+
+ { Swap bundle sides in response to edge crossing }
+ if (e0.bundle[ABOVE][CLIP] <> 0) then
+ e1.bside[CLIP] := integer(e1.bside[CLIP] = 0);
+ if (e1.bundle[ABOVE][CLIP] <> 0) then
+ e0.bside[CLIP] := integer(e0.bside[CLIP] = 0);
+ if (e0.bundle[ABOVE][SUBJ] <> 0) then
+ e1.bside[SUBJ] := integer(e1.bside[SUBJ] = 0);
+ if (e1.bundle[ABOVE][SUBJ] <> 0) then
+ e0.bside[SUBJ] := integer(e0.bside[SUBJ] = 0);
+
+ { Swap e0 and e1 bundles in the AET }
+ prev_edge := e0.prev;
+ next_edge := e1.next;
+ if next_edge <> nil then
+ next_edge.prev := e0;
+
+ if e0.bstate[ABOVE] = BUNDLE_HEAD then
+ begin
+ search := FTRUE;
+ while search <> 0 do
+ begin
+ prev_edge := prev_edge.prev;
+ if prev_edge <> nil then
+ begin
+ if prev_edge.bstate[ABOVE] <> BUNDLE_TAIL then
+ search := FFALSE;
+ end
+ else
+ search := FFALSE;
+ end;
+ end;
+ if prev_edge = nil then
+ begin
+ aet.prev := e1;
+ e1.next := aet;
+ aet := e0.next;
+ end
+ else
+ begin
+ prev_edge.next.prev := e1;
+ e1.next := prev_edge.next;
+ prev_edge.next := e0.next;
+ end;
+ e0.next.prev := prev_edge;
+ e1.next.prev := e1;
+ e0.next := next_edge;
+
+ intersect := intersect.next;
+ end; { End of IT loop}
+
+ { Prepare for next scanbeam }
+ edge := aet;
+ while edge <> nil do
+ begin
+ next_edge := edge.next;
+ succ_edge := edge.succ;
+
+ if EQ(edge.top.y, yt) and (succ_edge <> nil) then
+ begin
+ { Replace AET edge by its successor }
+ succ_edge.outp[BELOW] := edge.outp[ABOVE];
+ succ_edge.bstate[BELOW] := edge.bstate[ABOVE];
+ succ_edge.bundle[BELOW][CLIP] := edge.bundle[ABOVE][CLIP];
+ succ_edge.bundle[BELOW][SUBJ] := edge.bundle[ABOVE][SUBJ];
+ prev_edge := edge.prev;
+ if prev_edge <> nil then
+ prev_edge.next := succ_edge
+ else
+ aet := succ_edge;
+ if next_edge <> nil then
+ next_edge.prev := succ_edge;
+ succ_edge.prev := prev_edge;
+ succ_edge.next := next_edge;
+ end
+ else
+ begin
+ { Update this edge }
+ edge.outp[BELOW] := edge.outp[ABOVE];
+ edge.bstate[BELOW] := edge.bstate[ABOVE];
+ edge.bundle[BELOW][CLIP] := edge.bundle[ABOVE][CLIP];
+ edge.bundle[BELOW][SUBJ] := edge.bundle[ABOVE][SUBJ];
+ edge.xb := edge.xt;
+ end;
+ edge.outp[ABOVE] := nil;
+ edge := next_edge;
+ end;
+ end;
+ end; { === END OF SCANBEAM PROCESSING ================================== }
+
+ { Generate result polygon from out_poly }
+ result_polygon.contour := nil;
+ result_polygon.num_contours := count_contours(out_poly);
+ if result_polygon.num_contours > 0 then
+ begin
+ MALLOC(pointer(result_polygon.hole), result_polygon.num_contours
+ * sizeof(Integer), 'hole flag table creation');
+ MALLOC(pointer(result_polygon.contour), result_polygon.num_contours
+ * sizeof(Tgpc_vertex_list), 'contour creation');
+ poly := out_poly;
+ c := 0;
+
+ while poly <> nil do
+ begin
+ npoly := poly.next;
+ if poly.active <> 0 then
+ begin
+ result_polygon.hole[c] := poly.proxy.hole;
+ result_polygon.contour[c].num_vertices := poly.active;
+ MALLOC(pointer(result_polygon.contour[c].vertex),
+ result_polygon.contour[c].num_vertices * sizeof(Tgpc_vertex),
+ 'vertex creation');
+
+ v := result_polygon.contour[c].num_vertices - 1;
+ vtx := poly.proxy.v[LEFT];
+ while vtx <> nil do
+ begin
+ nv := vtx.next;
+ result_polygon.contour[c].vertex[v].x := vtx.x;
+ result_polygon.contour[c].vertex[v].y := vtx.y;
+ FREE(pointer(vtx));
+ Dec(v);
+ vtx := nv;
+ end;
+ Inc(c);
+ end;
+ FREE(pointer(poly));
+ poly := npoly;
+ end;
+ end;
+
+ { Tidy up }
+ reset_it(it);
+ reset_lmt(lmt);
+ FREE(pointer(c_heap));
+ FREE(pointer(s_heap));
+ FREE(pointer(sbt));
+end;
+
+
+procedure gpc_free_tristrip(tristrip : Pgpc_tristrip);
+var
+ s : integer;
+begin
+ for s := 0 to tristrip.num_strips - 1 do
+ CFREE(pointer(tristrip.strip[s].vertex));
+ CFREE(pointer(tristrip.strip));
+ tristrip.num_strips := 0;
+end;
+
+
+
+
+
+
+
+//===========================================================================
+// End of file: gpc.pas
+//===========================================================================
+
+
+end.
+
diff --git a/src/corelib/render/software/agg-demos/gpc/versions.txt b/src/corelib/render/software/agg-demos/gpc/versions.txt
new file mode 100755
index 00000000..0b877b62
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/gpc/versions.txt
@@ -0,0 +1,123 @@
+
+Generic Polygon Clipper (gpc) Revision History
+==============================================
+
+
+v2.32 17th Dec 2004
+---------------------
+ Fixed occasional memory leak occurring when processing some
+ degenerate polygon arrangements.
+ Added explicit type casting to memory allocator in support of
+ increased code portability.
+
+v2.31 4th Jun 1999
+---------------------
+ Separated edge merging measure based on a user-defined GPC_EPSILON
+ value from general numeric equality testing and ordering, which now
+ uses direct arithmetic comparison rather an EPSILON based proximity
+ test.
+ Fixed problem with numerical equality test during construction of
+ local minima and scanbeam tables, leading to occasional crash.
+ Fixed hole array memory leak in gpc_add_contour.
+ Fixed uninitialised hole field bug in gpc_polygon_clip result.
+
+v2.30 11th Apr 1999
+---------------------
+ Major re-write.
+ Minor API change: additional 'hole' array field added to gpc_polygon
+ datatype to indicate which constituent contours are internal holes,
+ and which form external boundaries.
+ Minor API change: additional 'hole' argument to gpc_add_contour
+ to indicate whether the new contour is a hole or external contour.
+ Minor API change: additional parameter to gpc_read_polygon and
+ gpc_write_polygon to indicate whether or not to read or write
+ contour hole flags.
+ Fixed NULL pointer bug in add/merge left/right operations.
+ Fixed numerical problem in intersection table generation.
+ Fixed zero byte malloc problem.
+ Fixed problem producing occasional 2 vertex contours.
+ Added bounding box test optimisations.
+ Simplified edge bundle creation, detection of scanbeam internal
+ edge intersections and tristrip scanbeam boundary code.
+ Renamed 'class' variable to be C++ friendly.
+
+v2.22 17th Oct 1998
+---------------------
+ Re-implemented edge interpolation and intersection calculations
+ to improve numerical robustness.
+ Simplified setting of GPC_EPSILON.
+
+v2.21 19th Aug 1998
+---------------------
+ Fixed problem causing occasional incorrect output when processing
+ self-intersecting polygons (bow-ties etc).
+ Removed bug which may lead to non-generation of uppermost triangle
+ in tristrip output.
+
+v2.20 26th May 1998
+---------------------
+ Major re-write.
+ Added exclusive-or polygon set operation.
+ Replaced table-based processing of edge intersections with
+ rule-based system.
+ Replaced two-pass approach to scanbeam interior processing with
+ single pass method.
+
+v2.10a 14th May 1998
+---------------------
+ Minor bug-fixes to counter some v2.10 reliability problems.
+
+v2.10 11th May 1998
+---------------------
+ Major re-write.
+ Incorporated edge bundle processing of AET to overcome coincident
+ edge problems present in previous releases.
+ Replaced Vatti's method for processing scanbeam interior regions
+ with an adapted version of the scanbeam boundary processing
+ algorithm.
+
+v2.02 16th Apr 1998 (unreleased)
+----------------------------------
+ Fixed internal minimum vertex duplication in gpc_polygon_clip
+ result.
+ Improved line intersection code discourage superfluous
+ intersections near line ends.
+ Removed limited precision number formatting in gpc_write_polygon.
+ Modification to allow subject or clip polygon to be reused as the
+ result in gpc_polygon_clip without memory leakage.
+
+v2.01 23rd Feb 1998
+---------------------
+ Removed bug causing duplicated vertices in output polygon.
+ Fixed scanbeam table index overrun problem.
+
+v2.00 25th Nov 1997
+---------------------
+ Major re-write.
+ Replaced temporary horizontal edge work-around (using tilting)
+ with true horizontal edge handling.
+ Trapezoidal output replaced by tristrips.
+ gpc_op constants now feature a `GPC_' prefix.
+ Data structures now passed by reference to gpc functions.
+ Replaced AET search by proxy addressing in polygon table.
+ Eliminated most (all?) coincident vertex / edge crashes.
+
+v1.02 18th Oct 1997 (unreleased)
+----------------------------------
+ Significantly reduced number of mallocs in build_lmt.
+ Scanbeam table now built using heapsort rather than insertion
+ sort.
+
+v1.01 12th Oct 1997
+---------------------
+ Fixed memory leak during output polygon build in
+ gpc_clip_polygon.
+ Removed superfluous logfile debug code.
+ Commented out malloc counts.
+ Added missing horizontal edge tilt-correction code in
+ gpc_clip_polygon.
+
+v1.00 8th Oct 1997
+--------------------
+ First release.
+
diff --git a/src/corelib/render/software/agg-demos/gpc_test.dpr b/src/corelib/render/software/agg-demos/gpc_test.dpr
new file mode 100644
index 00000000..e09f2936
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/gpc_test.dpr
@@ -0,0 +1,962 @@
+{target:win}
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ gpc_test ;
+
+uses
+ SysUtils ,
+
+ agg_basics ,
+ agg_platform_support ,
+
+ agg_color ,
+ agg_pixfmt ,
+ agg_pixfmt_rgb ,
+
+ agg_ctrl ,
+ agg_slider_ctrl ,
+ agg_cbox_ctrl ,
+ agg_rbox_ctrl ,
+
+ agg_rendering_buffer ,
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_renderer_primitives ,
+ agg_rasterizer_scanline_aa ,
+ agg_scanline ,
+ agg_scanline_u ,
+ agg_scanline_p ,
+ agg_render_scanlines ,
+
+ agg_math_stroke ,
+ agg_path_storage ,
+ agg_span_solid ,
+ agg_conv_curve ,
+ agg_conv_stroke ,
+ agg_conv_transform ,
+ agg_conv_clip_polygon ,
+ agg_conv_gpc ,
+ agg_gsv_text ,
+ agg_trans_affine ,
+ agg_vertex_source ,
+
+ make_gb_poly_ ,
+ make_arrows_ ;
+
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+type
+ spiral = object(vertex_source )
+ m_x ,
+ m_y ,
+ m_r1 ,
+ m_r2 ,
+ m_step ,
+
+ m_start_angle ,
+
+ m_angle ,
+ m_curr_r ,
+ m_da ,
+ m_dr : double;
+ m_start : boolean;
+
+ constructor Construct(x ,y ,r1 ,r2 ,step : double; start_angle : double = 0 );
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ end;
+
+ conv_poly_counter = object(vertex_source )
+ m_src : vertex_source_ptr;
+
+ m_contours ,
+ m_points : unsigned;
+
+ constructor Construct(src : vertex_source_ptr );
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ end;
+
+ the_application = object(platform_support )
+ m_polygons ,
+ m_operation : rbox_ctrl;
+
+ m_x ,
+ m_y : double;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure perform_rendering(
+ sl : scanline_ptr;
+ ras : rasterizer_scanline_ptr;
+ ren : renderer_scanline_ptr;
+ gpc : conv_gpc_ptr );
+
+ function render_gpc(sl : scanline_ptr; ras : rasterizer_scanline_ptr ) : unsigned;
+
+ procedure on_init; virtual;
+ procedure on_draw; virtual;
+
+ procedure on_mouse_move (x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ procedure stress_test;
+
+ end;
+
+{ CONSTRUCT }
+constructor spiral.Construct;
+begin
+ m_x :=x;
+ m_y :=y;
+ m_r1:=r1;
+ m_r2:=r2;
+
+ m_step :=step;
+ m_start_angle:=start_angle;
+ m_angle :=start_angle;
+
+ m_da:=deg2rad(4.0 );
+ m_dr:=m_step / 90.0;
+
+end;
+
+{ REWIND }
+procedure spiral.rewind;
+begin
+ m_angle :=m_start_angle;
+ m_curr_r:=m_r1;
+ m_start :=true;
+
+end;
+
+{ VERTEX }
+function spiral.vertex;
+begin
+ if m_curr_r > m_r2 then
+ begin
+ result:=path_cmd_stop;
+
+ exit;
+
+ end;
+
+ x^:=m_x + Cos(m_angle ) * m_curr_r;
+ y^:=m_y + Sin(m_angle ) * m_curr_r;
+
+ m_curr_r:=m_curr_r + m_dr;
+ m_angle :=m_angle + m_da;
+
+ if m_start then
+ begin
+ m_start:=false;
+
+ result:=path_cmd_move_to;
+
+ end
+ else
+ result:=path_cmd_line_to;
+
+end;
+
+{ CONSTRUCT }
+constructor conv_poly_counter.Construct;
+begin
+ m_src:=src;
+
+ m_contours:=0;
+ m_points :=0;
+
+end;
+
+{ REWIND }
+procedure conv_poly_counter.rewind;
+begin
+ m_contours:=0;
+ m_points :=0;
+
+ m_src.rewind(path_id );
+
+end;
+
+{ VERTEX }
+function conv_poly_counter.vertex;
+var
+ cmd : unsigned;
+
+begin
+ cmd:=m_src.vertex(x ,y );
+
+ if is_vertex(cmd ) then
+ inc(m_points );
+
+ if is_move_to(cmd ) then
+ inc(m_contours );
+
+ result:=cmd;
+
+end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_polygons.Construct (5.0 ,5.0 ,5.0 + 205.0 ,110.0 ,not flip_y_ );
+ m_operation.Construct(555.0 ,5.0 ,555.0 + 80.0 ,130.0 ,not flip_y_ );
+
+ m_operation.add_item ('None' );
+ m_operation.add_item ('OR' );
+ m_operation.add_item ('AND' );
+ m_operation.add_item ('XOR' );
+ m_operation.add_item ('A-B' );
+ m_operation.add_item ('B-A' );
+ m_operation.cur_item_(2 );
+
+ add_ctrl(@m_operation );
+
+ m_polygons.add_item ('Two Simple Paths' );
+ m_polygons.add_item ('Closed Stroke' );
+ m_polygons.add_item ('Great Britain and Arrows' );
+ m_polygons.add_item ('Great Britain and Spiral' );
+ m_polygons.add_item ('Spiral and Glyph' );
+ m_polygons.cur_item_(3 );
+
+ add_ctrl(@m_polygons );
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_polygons.Destruct;
+ m_operation.Destruct;
+
+end;
+
+{ PERFORM_RENDERING }
+procedure the_application.perform_rendering;
+var
+ counter : conv_poly_counter;
+
+ t1 ,t2 ,x ,y : double;
+
+ cmd : unsigned;
+ buf : array[0..99 ] of char;
+
+ rgba : aggclr;
+ txt : gsv_text;
+
+ txt_stroke : conv_stroke;
+
+begin
+ if m_operation._cur_item > 0 then
+ begin
+ // Render clipped polygon
+ ras.reset;
+
+ case m_operation._cur_item of
+ 1: gpc.operation(gpc_or );
+ 2: gpc.operation(gpc_and );
+ 3: gpc.operation(gpc_xor );
+ 4: gpc.operation(gpc_a_minus_b );
+ 5: gpc.operation(gpc_b_minus_a );
+
+ end;
+
+ counter.Construct(gpc );
+
+ start_timer;
+ counter.rewind(0 );
+
+ t1:=elapsed_time;
+
+ ras.reset;
+ start_timer;
+
+ cmd:=counter.vertex(@x ,@y );
+
+ while not is_stop(cmd ) do
+ begin
+ ras.add_vertex(x ,y ,cmd );
+
+ cmd:=counter.vertex(@x ,@y );
+
+ end;
+
+ rgba.ConstrDbl (0.5 ,0.0 ,0 ,0.5 );
+ ren.color_ (@rgba );
+ render_scanlines(ras ,sl ,ren );
+
+ t2:=elapsed_time;
+
+ // Render information text
+ sprintf(@buf[0 ] ,'Contours: %d ' ,counter.m_contours );
+ sprintf(@buf[StrLen(@buf ) ] ,'Points: %d' ,counter.m_points );
+
+ txt.Construct;
+ txt_stroke.Construct(@txt );
+
+ txt_stroke.width_ (1.5 );
+ txt_stroke.line_cap_(round_cap );
+ txt.size_ (10.0 );
+ txt.start_point_ (250 ,5 );
+ txt.text_ (@buf[0 ] );
+
+ ras.add_path (@txt_stroke );
+ rgba.ConstrDbl (0.0 ,0.0 ,0.0 );
+ ren.color_ (@rgba );
+ render_scanlines(ras ,sl ,ren );
+
+ sprintf(@buf[0 ] ,'GPC=%.3fms ' ,t1 );
+ sprintf(@buf[StrLen(buf ) ] ,'Render=%.3fms' ,t2 );
+
+ txt.start_point_(250 ,20 );
+ txt.text_ (@buf[0 ] );
+
+ ras.add_path (@txt_stroke );
+ rgba.ConstrDbl (0.0 ,0.0 ,0.0 );
+ ren.color_ (@rgba );
+ render_scanlines(ras ,sl ,ren );
+
+ // Free
+ txt.Destruct;
+ txt_stroke.Destruct;
+
+ end;
+
+end;
+
+{ RENDER_GPC }
+function the_application.render_gpc;
+var
+ pf : pixel_formats;
+ rb : renderer_base;
+
+ ren : renderer_scanline_aa_solid;
+ ps1 ,
+ ps2 ,
+
+ gb_poly ,
+ arrows ,
+ glyph : path_storage;
+
+ rgba : aggclr;
+ x ,y : double;
+
+ mtx1 ,
+ mtx2 ,
+ mtx : trans_affine;
+ tat : trans_affine_translation;
+ tas : trans_affine_scaling;
+
+ stroke ,
+ stroke_gb_poly : conv_stroke;
+
+ trans ,
+ trans_gb_poly ,
+ trans_arrows : conv_transform;
+
+ curve : conv_curve;
+
+ sp : spiral;
+ gpc : conv_gpc;
+
+begin
+ pixfmt_bgr24(pf ,rbuf_window );
+
+ rb.Construct (@pf );
+ ren.Construct(@rb );
+
+ case m_polygons._cur_item of
+ 0 : // Two simple paths
+ begin
+ ps1.Construct;
+ ps2.Construct;
+
+ gpc.Construct(@ps1 ,@ps2 );
+
+ x:=m_x - _initial_width / 2 + 100;
+ y:=m_y - _initial_height / 2 + 100;
+
+ ps1.move_to(x + 140 ,y + 145 );
+ ps1.line_to(x + 225 ,y + 44 );
+ ps1.line_to(x + 296 ,y + 219 );
+ ps1.close_polygon;
+
+ ps1.line_to(x + 226 ,y + 289 );
+ ps1.line_to(x + 82 ,y + 292 );
+
+ ps1.move_to(x + 220 ,y + 222 );
+ ps1.line_to(x + 363 ,y + 249 );
+ ps1.line_to(x + 265 ,y + 331 );
+
+ ps1.move_to(x + 242 ,y + 243 );
+ ps1.line_to(x + 268 ,y + 309 );
+ ps1.line_to(x + 325 ,y + 261 );
+
+ ps1.move_to(x + 259 ,y + 259 );
+ ps1.line_to(x + 273 ,y + 288 );
+ ps1.line_to(x + 298 ,y + 266 );
+
+ ps2.move_to(100 + 32 ,100 + 77 );
+ ps2.line_to(100 + 473 ,100 + 263 );
+ ps2.line_to(100 + 351 ,100 + 290 );
+ ps2.line_to(100 + 354 ,100 + 374 );
+
+ ras.reset;
+ ras.add_path (@ps1 );
+ rgba.ConstrDbl (0 ,0 ,0 ,0.1 );
+ ren.color_ (@rgba );
+ render_scanlines(ras ,sl ,@ren );
+
+ ras.reset;
+ ras.add_path (@ps2 );
+ rgba.ConstrDbl (0 ,0.6 ,0 ,0.1 );
+ ren.color_ (@rgba );
+ render_scanlines(ras ,sl ,@ren );
+
+ perform_rendering(sl ,ras ,@ren ,@gpc );
+
+ ps1.Destruct;
+ ps2.Destruct;
+ gpc.Destruct;
+
+ end;
+
+ 1 : // Closed stroke
+ begin
+ ps1.Construct;
+ ps2.Construct;
+ stroke.Construct(@ps2 );
+ stroke.width_ (10.0 );
+
+ gpc.Construct(@ps1 ,@stroke );
+
+ x:=m_x - _initial_width / 2 + 100;
+ y:=m_y - _initial_height / 2 + 100;
+
+ ps1.move_to(x + 140 ,y + 145 );
+ ps1.line_to(x + 225 ,y + 44 );
+ ps1.line_to(x + 296 ,y + 219 );
+ ps1.close_polygon;
+
+ ps1.line_to(x + 226 ,y + 289 );
+ ps1.line_to(x + 82 ,y + 292 );
+
+ ps1.move_to(x + 220 - 50 ,y + 222 );
+ ps1.line_to(x + 265 - 50 ,y + 331 );
+ ps1.line_to(x + 363 - 50 ,y + 249 );
+ ps1.close_polygon(path_flags_ccw );
+
+ ps2.move_to(100 + 32 ,100 + 77 );
+ ps2.line_to(100 + 473 ,100 + 263 );
+ ps2.line_to(100 + 351 ,100 + 290 );
+ ps2.line_to(100 + 354 ,100 + 374 );
+ ps2.close_polygon;
+
+ ras.reset;
+ ras.add_path (@ps1 );
+ rgba.ConstrDbl (0 ,0 ,0 ,0.1 );
+ ren.color_ (@rgba );
+ render_scanlines(ras ,sl ,@ren );
+
+ ras.reset;
+ ras.add_path (@stroke );
+ rgba.ConstrDbl (0 ,0.6 ,0 ,0.1 );
+ ren.color_ (@rgba );
+ render_scanlines(ras ,sl ,@ren );
+
+ perform_rendering(sl ,ras ,@ren ,@gpc );
+
+ ps1.Destruct;
+ ps2.Destruct;
+ stroke.Destruct;
+ gpc.Destruct;
+
+ end;
+
+ 2 : // Great Britain and Arrows
+ begin
+ gb_poly.Construct;
+ arrows.Construct;
+
+ make_gb_poly(@gb_poly );
+ make_arrows (@arrows );
+
+ mtx1.Construct;
+ mtx2.Construct;
+ tat.Construct(-1150 ,-1150 );
+ tas.Construct(2.0 );
+ mtx1.multiply(@tat );
+ mtx1.multiply(@tas );
+
+ mtx2:=mtx1;
+
+ tat.Construct(m_x - _initial_width / 2 ,m_y - _initial_height / 2 );
+
+ mtx2.multiply(@tat );
+
+ trans_gb_poly.Construct(@gb_poly ,@mtx1 );
+ trans_arrows.Construct (@arrows ,@mtx2 );
+
+ gpc.Construct(@trans_gb_poly ,@trans_arrows );
+
+ ras.add_path (@trans_gb_poly );
+ rgba.ConstrDbl (0.5 ,0.5 ,0 ,0.1 );
+ ren.color_ (@rgba );
+ render_scanlines(ras ,sl ,@ren );
+
+ stroke_gb_poly.Construct(@trans_gb_poly );
+ stroke_gb_poly.width_ (0.1);
+ ras.add_path (@stroke_gb_poly );
+ rgba.ConstrDbl (0 ,0 ,0 );
+ ren.color_ (@rgba );
+ render_scanlines (ras ,sl ,@ren );
+
+ ras.add_path (@trans_arrows );
+ rgba.ConstrDbl (0.0 ,0.5 ,0.5 ,0.1 );
+ ren.color_ (@rgba );
+ render_scanlines(ras ,sl ,@ren );
+
+ perform_rendering(sl ,ras ,@ren ,@gpc );
+
+ gb_poly.Destruct;
+ arrows.Destruct;
+ stroke_gb_poly.Destruct;
+ gpc.Destruct;
+
+ end;
+
+ 3 : // Great Britain and a Spiral
+ begin
+ sp.Construct (m_x ,m_y ,10 ,150 ,30 ,0.0 );
+ stroke.Construct(@sp );
+ stroke.width_ (15.0 );
+
+ gb_poly.Construct;
+ make_gb_poly(@gb_poly );
+
+ mtx.Construct;
+ tat.Construct(-1150 ,-1150 );
+ tas.Construct(2.0 );
+ mtx.multiply(@tat );
+ mtx.multiply(@tas );
+
+ trans_gb_poly.Construct(@gb_poly ,@mtx );
+
+ gpc.Construct(@trans_gb_poly ,@stroke );
+
+ ras.add_path (@trans_gb_poly );
+ rgba.ConstrDbl (0.5 ,0.5 ,0 ,0.1 );
+ ren.color_ (@rgba );
+ render_scanlines(ras ,sl ,@ren );
+
+ stroke_gb_poly.Construct(@trans_gb_poly );
+ stroke_gb_poly.width_ (0.1 );
+ ras.add_path (@stroke_gb_poly );
+ rgba.ConstrDbl (0 ,0 ,0 );
+ ren.color_ (@rgba );
+ render_scanlines (ras ,sl ,@ren );
+
+ ras.add_path (@stroke );
+ rgba.ConstrDbl (0.0 ,0.5 ,0.5 ,0.1 );
+ ren.color_ (@rgba );
+ render_scanlines(ras ,sl ,@ren );
+
+ perform_rendering(sl ,ras ,@ren ,@gpc );
+
+ stroke.Destruct;
+ gb_poly.Destruct;
+ stroke_gb_poly.Destruct;
+ gpc.Destruct;
+
+ end;
+
+ 4 : // Spiral and glyph
+ begin
+ sp.Construct (m_x ,m_y ,10 ,150 ,30 ,0.0 );
+ stroke.Construct(@sp );
+ stroke.width_ (15.0 );
+
+ glyph.Construct;
+ glyph.move_to(28.47 ,6.45 );
+ glyph.curve3 (21.58 ,1.12 ,19.82 ,0.29 );
+ glyph.curve3 (17.19 ,-0.93 ,14.21 ,-0.93 );
+ glyph.curve3 (9.57 ,-0.93 ,6.57 ,2.25 );
+ glyph.curve3 (3.56 ,5.42 ,3.56 ,10.60 );
+ glyph.curve3 (3.56 ,13.87 ,5.03 ,16.26 );
+ glyph.curve3 (7.03 ,19.58 ,11.99 ,22.51 );
+ glyph.curve3 (16.94 ,25.44 ,28.47 ,29.64 );
+ glyph.line_to(28.47 ,31.40 );
+ glyph.curve3 (28.47 ,38.09 ,26.34 ,40.58 );
+ glyph.curve3 (24.22 ,43.07 ,20.17 ,43.07 );
+ glyph.curve3 (17.09 ,43.07 ,15.28 ,41.41 );
+ glyph.curve3 (13.43 ,39.75 ,13.43 ,37.60 );
+ glyph.line_to(13.53 ,34.77 );
+ glyph.curve3 (13.53 ,32.52 ,12.38 ,31.30 );
+ glyph.curve3 (11.23 ,30.08 ,9.38 ,30.08 );
+ glyph.curve3 (7.57 ,30.08 ,6.42 ,31.35 );
+ glyph.curve3 (5.27 ,32.62 ,5.27 ,34.81 );
+ glyph.curve3 (5.27 ,39.01 ,9.57 ,42.53 );
+ glyph.curve3 (13.87 ,46.04 ,21.63 ,46.04 );
+ glyph.curve3 (27.59 ,46.04 ,31.40 ,44.04 );
+ glyph.curve3 (34.28 ,42.53 ,35.64 ,39.31 );
+ glyph.curve3 (36.52 ,37.21 ,36.52 ,30.71 );
+ glyph.line_to(36.52 ,15.53 );
+ glyph.curve3 (36.52 ,9.13 ,36.77 ,7.69 );
+ glyph.curve3 (37.01 ,6.25 ,37.57 ,5.76 );
+ glyph.curve3 (38.13 ,5.27 ,38.87 ,5.27 );
+ glyph.curve3 (39.65 ,5.27 ,40.23 ,5.62 );
+ glyph.curve3 (41.26 ,6.25 ,44.19 ,9.18 );
+ glyph.line_to(44.19 ,6.45 );
+ glyph.curve3 (38.72 ,-0.88 ,33.74 ,-0.88 );
+ glyph.curve3 (31.35 ,-0.88 ,29.93 ,0.78 );
+ glyph.curve3 (28.52 ,2.44 ,28.47 ,6.45 );
+ glyph.close_polygon;
+
+ glyph.move_to(28.47 ,9.62 );
+ glyph.line_to(28.47 ,26.66 );
+ glyph.curve3 (21.09 ,23.73 ,18.95 ,22.51 );
+ glyph.curve3 (15.09 ,20.36 ,13.43 ,18.02 );
+ glyph.curve3 (11.77 ,15.67 ,11.77 ,12.89 );
+ glyph.curve3 (11.77 ,9.38 ,13.87 ,7.06 );
+ glyph.curve3 (15.97 ,4.74 ,18.70 ,4.74 );
+ glyph.curve3 (22.41 ,4.74 ,28.47 ,9.62 );
+ glyph.close_polygon;
+
+ mtx.Construct;
+ tas.Construct(4.0 );
+ tat.Construct(220 ,200 );
+ mtx.multiply(@tas );
+ mtx.multiply(@tat );
+
+ trans.Construct(@glyph ,@mtx );
+ curve.Construct(@trans );
+
+ gpc.Construct(@stroke ,@curve );
+
+ ras.reset;
+ ras.add_path (@stroke );
+ rgba.ConstrDbl (0 ,0 ,0 ,0.1 );
+ ren.color_ (@rgba );
+ render_scanlines(ras ,sl ,@ren );
+
+ ras.reset;
+ ras.add_path (@curve );
+ rgba.ConstrDbl (0 ,0.6 ,0 ,0.1 );
+ ren.color_ (@rgba );
+ render_scanlines(ras ,sl ,@ren );
+
+ perform_rendering(sl ,ras ,@ren ,@gpc );
+
+ stroke.Destruct;
+ glyph.Destruct;
+ curve.Destruct;
+ gpc.Destruct;
+
+ end;
+
+ end;
+
+ result:=0;
+
+end;
+
+{ ON_INIT }
+procedure the_application.on_init;
+begin
+ m_x:=_width / 2.0;
+ m_y:=_height / 2.0;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ pf : pixel_formats;
+
+ rgba : aggclr;
+
+ ren_base : renderer_base;
+ ren_solid : renderer_scanline_aa_solid;
+
+ sl : scanline_u8;
+ ras : rasterizer_scanline_aa;
+
+begin
+// Initialize structures
+ pixfmt_bgr24(pf ,rbuf_window );
+
+ ren_base.Construct (@pf );
+ ren_solid.Construct(@ren_base );
+
+ rgba.ConstrDbl(1 ,1 ,1 );
+ ren_base.clear(@rgba );
+
+ sl.Construct;
+ ras.Construct;
+
+// Render
+ render_gpc(@sl ,@ras );
+
+// Render the controls
+ render_ctrl(@ras ,@sl ,@ren_solid ,@m_polygons );
+ render_ctrl(@ras ,@sl ,@ren_solid ,@m_operation );
+
+// Free AGG resources
+ sl.Destruct;
+ ras.Destruct;
+
+end;
+
+{ ON_MOUSE_MOVE }
+procedure the_application.on_mouse_move;
+begin
+ if flags and mouse_left <> 0 then
+ begin
+ m_x:=x;
+ m_y:=y;
+
+ force_redraw;
+
+ end;
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure the_application.on_mouse_button_down;
+var
+ buf : array[0..99 ] of char;
+
+begin
+ if flags and mouse_left <> 0 then
+ begin
+ m_x:=x;
+ m_y:=y;
+
+ force_redraw;
+
+ end;
+
+ if flags and mouse_right <> 0 then
+ begin
+ sprintf (@buf[0 ] ,'%d ' ,x );
+ sprintf (@buf[StrLen(@buf ) ] ,'%d' ,y );
+ message_(@buf[0 ] );
+
+ end;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ case key of
+ byte('t' ) ,
+ byte('T' ) :
+ stress_test;
+
+ end;
+
+ if key = key_f1 then
+ message_(
+ 'General Polygon Clipper by Alan Murta is the most reliable implementation of the '#13 +
+ 'polygon boolean algebra. It implements Bala R. Vatti''s algorithm of arbitrary '#13 +
+ 'polygon clipping and allows you to calculate the Union, Intersection, Difference, '#13 +
+ 'and Exclusive OR between two poly-polygons (i.e., polygonal areas consisted of '#13 +
+ 'several contours). AGG has a simple wrapper class that can be used in the coordinate '#13 +
+ 'conversion pipeline. The implementation by Alan Murta has restrictions of using it '#13 +
+ 'in commercial software, so that, please contact the author to settle the legal issues. '#13 +
+ 'The example demonstrates the use of GPC. Note, that all operations are done in the '#13 +
+ 'vectorial representation of the contours before rendering.'#13#13 +
+ 'How to play with:'#13#13 +
+ 'You can drag one polygon with the left mouse button pressed.'#13 +
+ 'Press the "T" key to perform the random polygon clipping stress testing.'#13 +
+ '(may take some time)' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+{ STRESS_TEST }
+// Stress-test.
+// Works quite well on random polygons, no crashes, no memory leaks!
+// Sometimes takes long to produce the result
+procedure the_application.stress_test;
+
+{ random }
+function random(min ,max : double ) : double;
+var
+ r : int;
+
+begin
+ r:=(System.Random($7fff ) shl 15 ) or System.Random($7fff );
+
+ result:=$FFFFFFF + 1;
+ result:=((r and $FFFFFFF) / result ) * (max - min ) + min;
+
+end;
+
+var
+ sl : scanline_u8;
+ ras : rasterizer_scanline_aa;
+
+ pf : pixel_formats;
+
+ ren_base : renderer_base;
+ ren_solid : renderer_scanline_aa_solid;
+
+ ps1 ,ps2 : path_storage;
+
+ gpc : conv_gpc;
+ rgba : aggclr;
+
+ i ,num_poly1 ,num_poly2 ,j ,k ,np ,op: unsigned;
+
+ buf : array[0..99 ] of char;
+ txt : gsv_text;
+
+ txt_stroke : conv_stroke;
+
+begin
+ sl.Construct;
+ ras.Construct;
+
+ pixfmt_bgr24(pf ,rbuf_window );
+
+ ren_base.Construct (@pf );
+ ren_solid.Construct(@ren_base );
+
+ ps1.Construct;
+ ps2.Construct;
+ gpc.Construct(@ps1 ,@ps2 );
+
+ txt.Construct;
+ txt_stroke.Construct(@txt );
+
+ txt_stroke.width_ (1.5 );
+ txt_stroke.line_cap_(round_cap );
+ txt.size_ (10.0 );
+ txt.start_point_ (5 ,5 );
+
+ for i:=0 to 999 do
+ begin
+ rgba.ConstrDbl(1 ,1 ,1 );
+ ren_base.clear(@rgba );
+
+ num_poly1:=System.Random($7fff ) mod 10 + 1;
+ num_poly2:=System.Random($7fff ) mod 10 + 1;
+
+ ps1.remove_all;
+ ps2.remove_all;
+
+ for j:=0 to num_poly1 - 1 do
+ begin
+ ps1.move_to(random(0 ,_width ) ,random(0 ,_height ) );
+
+ np:=System.Random($7fff ) mod 20 + 2;
+
+ for k:=0 to np - 1 do
+ ps1.line_to(random(0 ,_width ) ,random(0 ,_height ) );
+
+ end;
+
+ for j:=0 to num_poly2 - 1 do
+ begin
+ ps2.move_to(random(0 ,_width ) ,random(0 ,_height ) );
+
+ np:=System.Random($7fff ) mod 20 + 2;
+
+ for k:=0 to np - 1 do
+ ps2.line_to(random(0 ,_width ) ,random(0 ,_height ) );
+
+ end;
+
+ op:=System.Random($7fff ) mod 5;
+
+ case op of
+ 0 :
+ gpc.operation(gpc_or );
+
+ 1 :
+ gpc.operation(gpc_and );
+
+ 2 :
+ gpc.operation(gpc_xor );
+
+ 3 :
+ gpc.operation(gpc_a_minus_b );
+
+ else
+ gpc.operation(gpc_b_minus_a );
+
+ end;
+
+ // Clipping result
+ ras.add_path (@gpc );
+ rgba.ConstrDbl (0.5 ,0.0 ,0 ,0.5 );
+ ren_solid.color_(@rgba );
+ render_scanlines(@ras ,@sl ,@ren_solid );
+
+ // Counter display
+ sprintf (@buf[0 ] ,'%d / 1000' ,i + 1 );
+ txt.text_(@buf[0 ] );
+
+ txt.start_point_(5 ,5 );
+
+ ras.add_path (@txt_stroke );
+ rgba.ConstrDbl (0.0 ,0.0 ,0.0 );
+ ren_solid.color_(@rgba );
+ render_scanlines(@ras ,@sl ,@ren_solid );
+
+ // Refresh
+ update_window;
+
+ end;
+
+ message_('Done' );
+
+ ps1.Destruct;
+ ps2.Destruct;
+ gpc.Destruct;
+
+ sl.Destruct;
+ ras.Destruct;
+
+ txt.Destruct;
+ txt_stroke.Destruct;
+
+ force_redraw;
+
+end;
+
+VAR
+ app : the_application;
+
+BEGIN
+ app.Construct(pix_format_bgr24 ,flip_y );
+ app.caption_ ('AGG Example. General Polygon Clipping - GPC (F1-Help)' );
+
+ if app.init(640 ,520 ,window_resize ) then
+ app.run;
+
+ app.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/gradient_focal.dpr b/src/corelib/render/software/agg-demos/gradient_focal.dpr
new file mode 100644
index 00000000..365ae885
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/gradient_focal.dpr
@@ -0,0 +1,437 @@
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ gradient_focal ;
+
+uses
+ agg_basics ,
+ agg_platform_support ,
+ agg_ctrl ,
+ agg_slider_ctrl ,
+ agg_cbox_ctrl ,
+ agg_rendering_buffer ,
+ agg_rasterizer_scanline_aa ,
+ agg_scanline_u ,
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_span_allocator ,
+ agg_span_gradient ,
+ agg_gamma_lut ,
+ agg_span_interpolator_linear ,
+ agg_pixfmt ,
+ agg_pixfmt_rgb ,
+ agg_color ,
+ agg_trans_affine ,
+ agg_render_scanlines ,
+ agg_ellipse ,
+ agg_conv_stroke ,
+ agg_conv_transform ,
+ agg_gsv_text ,
+ agg_gradient_lut ;
+
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+type
+ the_application = object(platform_support )
+ private
+ m_gamma : slider_ctrl;
+ m_extend ,
+ m_frwave : cbox_ctrl;
+
+ m_scanline : scanline_u8;
+ m_rasterizer : rasterizer_scanline_aa;
+ m_alloc : span_allocator;
+
+ m_gradient_lut : gradient_lut;
+ m_gamma_lut : gamma_lut;
+
+ m_mouse_x ,
+ m_mouse_y ,
+ m_old_gamma : double;
+
+ public
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure build_gradient_lut;
+
+ procedure on_init; virtual;
+ procedure on_draw; virtual;
+
+ procedure on_mouse_move(x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+ procedure on_ctrl_change; virtual;
+
+ end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_gamma.Construct(5.0 ,5.0 ,340.0 ,12.0 ,not flip_y_ );
+ m_extend.Construct(10 ,25 ,'Extended radial focus' ,not flip_y_ );
+ m_frwave.Construct(10 ,45 ,'Wavelength radial' ,not flip_y_ );
+
+ m_scanline.Construct;
+ m_rasterizer.Construct;
+ m_alloc.Construct;
+ m_gradient_lut.Construct(1024 );
+ m_gamma_lut.Construct_;
+
+ m_mouse_x:=200;
+ m_mouse_y:=200;
+
+ m_gamma.range_(0.5 ,2.5 );
+ m_gamma.value_(1.8 );
+ m_gamma.label_('Gamma = %.3f' );
+
+ add_ctrl(@m_gamma );
+
+ m_gamma.no_transform;
+
+ m_gamma_lut.gamma_(m_gamma._value );
+
+ add_ctrl(@m_extend );
+
+ m_extend.no_transform;
+
+ add_ctrl(@m_frwave );
+
+ m_frwave.no_transform;
+
+ m_old_gamma:=m_gamma._value;
+
+ build_gradient_lut;
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_gamma.Destruct;
+ m_extend.Destruct;
+ m_frwave.Destruct;
+
+ m_scanline.Destruct;
+ m_rasterizer.Destruct;
+ m_alloc.Destruct;
+ m_gradient_lut.Destruct;
+ m_gamma_lut.Destruct;
+
+end;
+
+{ BUILD_GRADIENT_LUT }
+procedure the_application.build_gradient_lut;
+var
+ rgba : aggclr;
+
+begin
+ m_gradient_lut.remove_all;
+
+ if not m_frwave._status then
+ begin
+ rgba.ConstrInt (m_gamma_lut.dir(0 ) ,m_gamma_lut.dir(255 ) ,m_gamma_lut.dir(0 ) );
+ m_gradient_lut.add_color(0.0 ,@rgba );
+
+ rgba.ConstrInt (m_gamma_lut.dir(120 ) ,m_gamma_lut.dir(0 ) ,m_gamma_lut.dir(0 ) );
+ m_gradient_lut.add_color(0.2 ,@rgba );
+
+ rgba.ConstrInt (m_gamma_lut.dir(120 ) ,m_gamma_lut.dir(120 ) ,m_gamma_lut.dir(0 ) );
+ m_gradient_lut.add_color(0.7 ,@rgba );
+
+ rgba.ConstrInt (m_gamma_lut.dir(0 ) ,m_gamma_lut.dir(0 ) ,m_gamma_lut.dir(255 ) );
+ m_gradient_lut.add_color(1.0 ,@rgba );
+
+ end
+ else
+ begin
+ rgba.from_wavelength (380 ,m_gamma._value );
+ m_gradient_lut.add_color(0.0 ,@rgba );
+
+ rgba.from_wavelength (420 ,m_gamma._value );
+ m_gradient_lut.add_color(0.1 ,@rgba );
+
+ rgba.from_wavelength (460 ,m_gamma._value );
+ m_gradient_lut.add_color(0.2 ,@rgba );
+
+ rgba.from_wavelength (500 ,m_gamma._value );
+ m_gradient_lut.add_color(0.3 ,@rgba );
+
+ rgba.from_wavelength (540 ,m_gamma._value );
+ m_gradient_lut.add_color(0.4 ,@rgba );
+
+ rgba.from_wavelength (580 ,m_gamma._value );
+ m_gradient_lut.add_color(0.5 ,@rgba );
+
+ rgba.from_wavelength (620 ,m_gamma._value );
+ m_gradient_lut.add_color(0.6 ,@rgba );
+
+ rgba.from_wavelength (660 ,m_gamma._value );
+ m_gradient_lut.add_color(0.7 ,@rgba );
+
+ rgba.from_wavelength (700 ,m_gamma._value );
+ m_gradient_lut.add_color(0.8 ,@rgba );
+
+ rgba.from_wavelength (740 ,m_gamma._value );
+ m_gradient_lut.add_color(0.9 ,@rgba );
+
+ rgba.from_wavelength (780 ,m_gamma._value );
+ m_gradient_lut.add_color(1.0 ,@rgba );
+
+ end;
+
+ m_gradient_lut.build_lut;
+
+end;
+
+{ ON_INIT }
+procedure the_application.on_init;
+begin
+ m_mouse_y:=_initial_height / 2;
+ m_mouse_x:=_initial_width / 2;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ pixf : pixel_formats;
+ rgba : aggclr;
+
+ rb : renderer_base;
+ rs : renderer_scanline_aa_solid;
+ rg : renderer_scanline_aa;
+
+ e : ellipse;
+
+ estr : conv_stroke;
+ etrans : conv_transform;
+
+ cx ,cy ,r ,fx ,fy ,tm : double;
+
+ gf_std : gradient_radial_focus;
+ gf_ext : gradient_radial_focus_extended;
+
+ gradient_adaptor : gradient_reflect_adaptor;
+
+ gradient_mtx : trans_affine;
+
+ the_interpolator : span_interpolator_linear;
+
+ the_gradient : span_gradient;
+
+ buf : array[0..63 ] of char;
+
+ t : gsv_text;
+ pt : conv_stroke;
+
+begin
+// Initialize structures
+ pixfmt_bgr24(pixf ,rbuf_window );
+
+ rb.Construct(@pixf );
+ rs.Construct(@rb );
+
+ rgba.ConstrDbl(1 ,1 ,1 );
+ rb.clear (@rgba );
+
+// Gradient center. All gradient functions assume the
+// center being in the origin (0,0) and you can't
+// change it. But you can apply arbitrary transformations
+// to the gradient (see below).
+ cx:=_initial_width / 2;
+ cy:=_initial_height / 2;
+ r :=100;
+
+// Focal center. Defined in the gradient coordinates,
+// that is, with respect to the origin (0,0)
+ fx:=m_mouse_x - cx;
+ fy:=m_mouse_y - cy;
+
+ if m_extend._status then
+ begin
+ gf_ext.Construct (r ,fx ,fy );
+ gradient_adaptor.Construct(@gf_ext );
+
+ end
+ else
+ begin
+ gf_std.Construct (r ,fx ,fy );
+ gradient_adaptor.Construct(@gf_std );
+
+ end;
+
+ gradient_mtx.Construct;
+
+// Making the affine matrix. Move to (cx,cy),
+// apply the resizing transformations and invert
+// the matrix. Gradients and images always assume the
+// inverse transformations.
+ gradient_mtx.translate(cx ,cy );
+ gradient_mtx.multiply (_trans_affine_resizing );
+ gradient_mtx.invert;
+
+ the_interpolator.Construct(@gradient_mtx );
+ the_gradient.Construct(
+ @m_alloc ,
+ @the_interpolator ,
+ @gradient_adaptor ,
+ @m_gradient_lut ,
+ 0 ,r );
+
+// Form the simple rectangle
+ m_rasterizer.reset;
+ m_rasterizer.move_to_d(0 ,0 );
+ m_rasterizer.line_to_d(_width ,0 );
+ m_rasterizer.line_to_d(_width ,_height );
+ m_rasterizer.line_to_d(0 ,_height );
+
+// Render the gradient to the whole screen and measure the time
+ start_timer;
+
+ rg.Construct (@rb ,@the_gradient );
+ render_scanlines(@m_rasterizer ,@m_scanline ,@rg );
+
+ tm:=elapsed_time;
+
+// Draw the transformed circle that shows the gradient boundary
+ e.Construct (cx ,cy ,r ,r );
+ estr.Construct (@e );
+ etrans.Construct(@estr ,_trans_affine_resizing );
+
+ m_rasterizer.add_path(@etrans );
+
+ rgba.ConstrDbl(1 ,1 ,1 );
+ rs.color_ (@rgba );
+
+ render_scanlines(@m_rasterizer ,@m_scanline ,@rs );
+
+// Show the gradient time
+ t.Construct;
+ t.size_(10.0 );
+
+ pt.Construct(@t );
+ pt.width_ (1.5 );
+
+ sprintf(@buf[0 ] ,'%3.2f ms' ,tm );
+
+ t.start_point_(25.0 ,70.0 );
+ t.text_ (@buf[0 ] );
+
+ m_rasterizer.add_path(@pt );
+
+ rgba.ConstrDbl(0 ,0 ,0 );
+ rs.color_ (@rgba );
+
+ render_scanlines(@m_rasterizer ,@m_scanline ,@rs );
+
+// Render the controls
+ render_ctrl(@m_rasterizer ,@m_scanline ,@rs ,@m_gamma );
+ render_ctrl(@m_rasterizer ,@m_scanline ,@rs ,@m_extend );
+ render_ctrl(@m_rasterizer ,@m_scanline ,@rs ,@m_frwave );
+
+// Apply the inverse gamma to the whole buffer
+// (transform the colors to the perceptually uniform space)
+ pixf.apply_gamma_inv(@m_gamma_lut ,bgr_order );
+
+// Free AGG resources
+ the_gradient.Destruct;
+ estr.Destruct;
+ t.Destruct;
+ pt.Destruct;
+
+end;
+
+{ ON_MOUSE_MOVE }
+procedure the_application.on_mouse_move;
+var
+ tar : trans_affine_ptr;
+
+begin
+ if flags and mouse_left <> 0 then
+ begin
+ m_mouse_x:=x;
+ m_mouse_y:=y;
+
+ tar:=_trans_affine_resizing;
+
+ tar.inverse_transform(tar ,@m_mouse_x ,@m_mouse_y );
+
+ force_redraw;
+
+ end;
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure the_application.on_mouse_button_down;
+var
+ tar : trans_affine_ptr;
+
+begin
+ if flags and mouse_left <> 0 then
+ begin
+ m_mouse_x:=x;
+ m_mouse_y:=y;
+
+ tar:=_trans_affine_resizing;
+
+ tar.inverse_transform(tar ,@m_mouse_x ,@m_mouse_y );
+
+ force_redraw;
+
+ end;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ 'This demo evolved from testing code and performance measurements. '#13 +
+ 'In particular, it shows you how to calculate the parameters'#13 +
+ 'of a radial gradient with a separate focal point, considering '#13 +
+ 'arbitrary affine transformations. In this example window resizing '#13 +
+ 'transformations are taken into account. It also demonstrates '#13 +
+ 'the use case of gradient_lut and gamma correction.' );
+
+end;
+
+{ ON_CTRL_CHANGE }
+procedure the_application.on_ctrl_change;
+begin
+ m_gamma_lut.gamma_(m_gamma._value );
+
+ build_gradient_lut;
+
+ m_old_gamma:=m_gamma._value;
+
+end;
+
+VAR
+ app : the_application;
+
+BEGIN
+ app.Construct(pix_format_bgr24 ,flip_y );
+ app.caption_ ('AGG Example. PDF linear and radial gradients (F1-Help)' );
+
+ if app.init(600 ,400 ,window_resize ) then
+ app.run;
+
+ app.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/gradients.dpr b/src/corelib/render/software/agg-demos/gradients.dpr
new file mode 100644
index 00000000..9b73dd9f
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/gradients.dpr
@@ -0,0 +1,728 @@
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ gradients ;
+
+{DEFINE AGG_GRAY8 }
+{$DEFINE AGG_BGR24 }
+{DEFINE AGG_RGB24 }
+{DEFINE AGG_BGRA32 }
+{DEFINE AGG_RGBA32 }
+{DEFINE AGG_ARGB32 }
+{DEFINE AGG_ABGR32 }
+{DEFINE AGG_RGB565 }
+{DEFINE AGG_RGB555 }
+
+uses
+ Math ,SysUtils ,
+
+ agg_basics ,
+ agg_platform_support ,
+
+ agg_ctrl ,
+ agg_spline_ctrl ,
+ agg_rbox_ctrl ,
+ agg_gamma_ctrl ,
+
+ agg_rasterizer_scanline_aa ,
+ agg_scanline ,
+ agg_scanline_u ,
+ agg_scanline_p ,
+
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_render_scanlines ,
+
+ agg_array ,
+ agg_conv_transform ,
+ agg_span_gradient ,
+ agg_span_interpolator_linear ,
+ agg_span_allocator ,
+ agg_trans_affine ,
+ agg_ellipse
+
+{$I pixel_formats.inc }
+{$I agg_mode.inc }
+{$I- }
+const
+ flip_y = true;
+
+ center_x : double = 350;
+ center_y : double = 280;
+
+type
+ color_function_profile = object(array_base )
+ m_colors : aggclr_ptr;
+ m_profile : int8u_ptr;
+
+ constructor Construct(colors : aggclr_ptr; profile : int8u_ptr );
+
+ function size : unsigned; virtual;
+ function array_operator(i : unsigned ) : pointer; virtual;
+
+ end;
+
+ the_application = object(platform_support )
+ m_profile : gamma_ctrl;
+ m_spline_r ,
+ m_spline_g ,
+ m_spline_b ,
+ m_spline_a : spline_ctrl;
+ m_rbox : rbox_ctrl;
+
+ m_pdx ,
+ m_pdy ,
+ m_center_x ,
+ m_center_y ,
+ m_scale ,
+ m_prev_scale ,
+ m_angle ,
+ m_prev_angle ,
+ m_scale_x ,
+ m_prev_scale_x ,
+ m_scale_y ,
+ m_prev_scale_y : double;
+ m_mouse_move : boolean;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure on_draw; virtual;
+
+ procedure on_mouse_move (x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_up (x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ CONSTRUCT }
+constructor color_function_profile.Construct;
+begin
+ m_colors :=colors;
+ m_profile:=profile;
+
+end;
+
+{ SIZE }
+function color_function_profile.size;
+begin
+ result:=256;
+
+end;
+
+{ ARRAY_OPERATOR }
+function color_function_profile.array_operator;
+begin
+ result:=
+ aggclr_ptr(
+ ptrcomp(m_colors ) +
+ int8u_ptr(ptrcomp(m_profile ) + i * sizeof(int8u ) )^ * sizeof(aggclr ) );
+
+end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+var
+ rgba : aggclr;
+
+ fd : text;
+ err : integer;
+
+ x ,y ,x2 ,y2 ,t : double;
+
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_profile.Construct (10.0 ,10.0 ,200.0 ,170.0 - 5.0 ,not flip_y_ );
+ m_spline_r.Construct(210 ,10 ,210 + 250 ,5 + 40 ,6 ,not flip_y_ );
+ m_spline_g.Construct(210 ,10 + 40 ,210 + 250 ,5 + 80 ,6 ,not flip_y_ );
+ m_spline_b.Construct(210 ,10 + 80 ,210 + 250 ,5 + 120 ,6 ,not flip_y_ );
+ m_spline_a.Construct(210 ,10 + 120 ,210 + 250 ,5 + 160 ,6 ,not flip_y_ );
+ m_rbox.Construct (10.0 ,180.0 ,200.0 ,300.0 ,not flip_y_ );
+
+ m_pdx:=0.0;
+ m_pdy:=0.0;
+
+ m_center_x:=center_x;
+ m_center_y:=center_y;
+
+ m_scale :=1.0;
+ m_prev_scale :=1.0;
+ m_angle :=0.0;
+ m_prev_angle :=0.0;
+ m_scale_x :=1.0;
+ m_prev_scale_x:=1.0;
+ m_scale_y :=1.0;
+ m_prev_scale_y:=1.0;
+
+ m_mouse_move:=false;
+
+ add_ctrl(@m_profile );
+ add_ctrl(@m_spline_r );
+ add_ctrl(@m_spline_g );
+ add_ctrl(@m_spline_b );
+ add_ctrl(@m_spline_a );
+ add_ctrl(@m_rbox );
+
+ m_profile.border_width_(2.0 ,2.0 );
+
+ rgba.ConstrDbl (1.0 ,0.8 ,0.8 );
+ m_spline_r.background_color_(@rgba );
+ rgba.ConstrDbl (0.8 ,1.0 ,0.8 );
+ m_spline_g.background_color_(@rgba );
+ rgba.ConstrDbl (0.8 ,0.8 ,1.0 );
+ m_spline_b.background_color_(@rgba );
+ rgba.ConstrDbl (1.0 ,1.0 ,1.0 );
+ m_spline_a.background_color_(@rgba );
+
+ m_spline_r.border_width_(1.0 ,2.0 );
+ m_spline_g.border_width_(1.0 ,2.0 );
+ m_spline_b.border_width_(1.0 ,2.0 );
+ m_spline_a.border_width_(1.0 ,2.0 );
+ m_rbox.border_width_ (2.0 ,2.0 );
+
+ m_spline_r.point_(0 ,0.0 ,1.0 );
+ m_spline_r.point_(1 ,1.0 / 5.0 ,1.0 - 1.0 / 5.0 );
+ m_spline_r.point_(2 ,2.0 / 5.0 ,1.0 - 2.0 / 5.0 );
+ m_spline_r.point_(3 ,3.0 / 5.0 ,1.0 - 3.0 / 5.0 );
+ m_spline_r.point_(4 ,4.0 / 5.0 ,1.0 - 4.0 / 5.0 );
+ m_spline_r.point_(5 ,1.0 ,0.0 );
+ m_spline_r.update_spline;
+
+ m_spline_g.point_(0 ,0.0 ,1.0 );
+ m_spline_g.point_(1 ,1.0 / 5.0 ,1.0 - 1.0 / 5.0 );
+ m_spline_g.point_(2 ,2.0 / 5.0 ,1.0 - 2.0 / 5.0 );
+ m_spline_g.point_(3 ,3.0 / 5.0 ,1.0 - 3.0 / 5.0 );
+ m_spline_g.point_(4 ,4.0 / 5.0 ,1.0 - 4.0 / 5.0 );
+ m_spline_g.point_(5 ,1.0 ,0.0 );
+ m_spline_g.update_spline;
+
+ m_spline_b.point_(0 ,0.0 ,1.0 );
+ m_spline_b.point_(1 ,1.0 / 5.0 ,1.0 - 1.0 / 5.0 );
+ m_spline_b.point_(2 ,2.0 / 5.0 ,1.0 - 2.0 / 5.0 );
+ m_spline_b.point_(3 ,3.0 / 5.0 ,1.0 - 3.0 / 5.0 );
+ m_spline_b.point_(4 ,4.0 / 5.0 ,1.0 - 4.0 / 5.0 );
+ m_spline_b.point_(5 ,1.0 ,0.0 );
+ m_spline_b.update_spline;
+
+ m_spline_a.point_(0 ,0.0 ,1.0 );
+ m_spline_a.point_(1 ,1.0 / 5.0 , 1.0 );
+ m_spline_a.point_(2 ,2.0 / 5.0 , 1.0 );
+ m_spline_a.point_(3 ,3.0 / 5.0 , 1.0 );
+ m_spline_a.point_(4 ,4.0 / 5.0 , 1.0 );
+ m_spline_a.point_(5 ,1.0 ,1.0 );
+ m_spline_a.update_spline;
+
+ m_rbox.add_item ('Circular' );
+ m_rbox.add_item ('Diamond' );
+ m_rbox.add_item ('Linear' );
+ m_rbox.add_item ('XY' );
+ m_rbox.add_item ('sqrt(XY)' );
+ m_rbox.add_item ('Conic' );
+ m_rbox.cur_item_(0 );
+
+ err:=IOResult;
+
+ AssignFile(fd ,'settings.dat' );
+ reset (fd );
+
+ err:=IOResult;
+
+ if err = 0 then
+ begin
+ readln(fd ,t ); m_center_x:=t;
+ readln(fd ,t ); m_center_y:=t;
+ readln(fd ,t ); m_scale:=t;
+ readln(fd ,t ); m_angle:=t;
+ readln(fd ,x );
+ readln(fd ,y ); m_spline_r.point_(0 ,x ,y );
+ readln(fd ,x );
+ readln(fd ,y ); m_spline_r.point_(1 ,x ,y );
+ readln(fd ,x );
+ readln(fd ,y ); m_spline_r.point_(2 ,x ,y );
+ readln(fd ,x );
+ readln(fd ,y ); m_spline_r.point_(3 ,x ,y );
+ readln(fd ,x );
+ readln(fd ,y ); m_spline_r.point_(4 ,x ,y );
+ readln(fd ,x );
+ readln(fd ,y ); m_spline_r.point_(5 ,x ,y );
+ readln(fd ,x );
+ readln(fd ,y ); m_spline_g.point_(0 ,x ,y );
+ readln(fd ,x );
+ readln(fd ,y ); m_spline_g.point_(1 ,x ,y );
+ readln(fd ,x );
+ readln(fd ,y ); m_spline_g.point_(2 ,x ,y );
+ readln(fd ,x );
+ readln(fd ,y ); m_spline_g.point_(3 ,x ,y );
+ readln(fd ,x );
+ readln(fd ,y ); m_spline_g.point_(4 ,x ,y );
+ readln(fd ,x );
+ readln(fd ,y ); m_spline_g.point_(5 ,x ,y );
+ readln(fd ,x );
+ readln(fd ,y ); m_spline_b.point_(0 ,x ,y );
+ readln(fd ,x );
+ readln(fd ,y ); m_spline_b.point_(1 ,x ,y );
+ readln(fd ,x );
+ readln(fd ,y ); m_spline_b.point_(2 ,x ,y );
+ readln(fd ,x );
+ readln(fd ,y ); m_spline_b.point_(3 ,x ,y );
+ readln(fd ,x );
+ readln(fd ,y ); m_spline_b.point_(4 ,x ,y );
+ readln(fd ,x );
+ readln(fd ,y ); m_spline_b.point_(5 ,x ,y );
+ readln(fd ,x );
+ readln(fd ,y ); m_spline_a.point_(0 ,x ,y );
+ readln(fd ,x );
+ readln(fd ,y ); m_spline_a.point_(1 ,x ,y );
+ readln(fd ,x );
+ readln(fd ,y ); m_spline_a.point_(2 ,x ,y );
+ readln(fd ,x );
+ readln(fd ,y ); m_spline_a.point_(3 ,x ,y );
+ readln(fd ,x );
+ readln(fd ,y ); m_spline_a.point_(4 ,x ,y );
+ readln(fd ,x );
+ readln(fd ,y ); m_spline_a.point_(5 ,x ,y );
+
+ m_spline_r.update_spline;
+ m_spline_g.update_spline;
+ m_spline_b.update_spline;
+ m_spline_a.update_spline;
+
+ readln(fd ,x );
+ readln(fd ,y );
+ readln(fd ,x2 );
+ readln(fd ,y2 );
+
+ m_profile.values(x ,y ,x2 ,y2 );
+
+ close(fd );
+
+ end;
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+var
+ fd : text;
+
+ x1 ,y1 ,x2 ,y2 : double;
+
+begin
+ AssignFile(fd ,'settings.dat' );
+ rewrite (fd );
+
+ writeln(fd ,m_center_x:0:6 );
+ writeln(fd ,m_center_y:0:6 );
+ writeln(fd ,m_scale:0:6 );
+ writeln(fd ,m_angle:0:6 );
+ writeln(fd ,m_spline_r._x(0 ):0:6 );
+ writeln(fd ,m_spline_r._y(0 ):0:6 );
+ writeln(fd ,m_spline_r._x(1 ):0:6 );
+ writeln(fd ,m_spline_r._y(1 ):0:6 );
+ writeln(fd ,m_spline_r._x(2 ):0:6 );
+ writeln(fd ,m_spline_r._y(2 ):0:6 );
+ writeln(fd ,m_spline_r._x(3 ):0:6 );
+ writeln(fd ,m_spline_r._y(3 ):0:6 );
+ writeln(fd ,m_spline_r._x(4 ):0:6 );
+ writeln(fd ,m_spline_r._y(4 ):0:6 );
+ writeln(fd ,m_spline_r._x(5 ):0:6 );
+ writeln(fd ,m_spline_r._y(5 ):0:6 );
+ writeln(fd ,m_spline_g._x(0 ):0:6 );
+ writeln(fd ,m_spline_g._y(0 ):0:6 );
+ writeln(fd ,m_spline_g._x(1 ):0:6 );
+ writeln(fd ,m_spline_g._y(1 ):0:6 );
+ writeln(fd ,m_spline_g._x(2 ):0:6 );
+ writeln(fd ,m_spline_g._y(2 ):0:6 );
+ writeln(fd ,m_spline_g._x(3 ):0:6 );
+ writeln(fd ,m_spline_g._y(3 ):0:6 );
+ writeln(fd ,m_spline_g._x(4 ):0:6 );
+ writeln(fd ,m_spline_g._y(4 ):0:6 );
+ writeln(fd ,m_spline_g._x(5 ):0:6 );
+ writeln(fd ,m_spline_g._y(5 ):0:6 );
+ writeln(fd ,m_spline_b._x(0 ):0:6 );
+ writeln(fd ,m_spline_b._y(0 ):0:6 );
+ writeln(fd ,m_spline_b._x(1 ):0:6 );
+ writeln(fd ,m_spline_b._y(1 ):0:6 );
+ writeln(fd ,m_spline_b._x(2 ):0:6 );
+ writeln(fd ,m_spline_b._y(2 ):0:6 );
+ writeln(fd ,m_spline_b._x(3 ):0:6 );
+ writeln(fd ,m_spline_b._y(3 ):0:6 );
+ writeln(fd ,m_spline_b._x(4 ):0:6 );
+ writeln(fd ,m_spline_b._y(4 ):0:6 );
+ writeln(fd ,m_spline_b._x(5 ):0:6 );
+ writeln(fd ,m_spline_b._y(5 ):0:6 );
+ writeln(fd ,m_spline_a._x(0 ):0:6 );
+ writeln(fd ,m_spline_a._y(0 ):0:6 );
+ writeln(fd ,m_spline_a._x(1 ):0:6 );
+ writeln(fd ,m_spline_a._y(1 ):0:6 );
+ writeln(fd ,m_spline_a._x(2 ):0:6 );
+ writeln(fd ,m_spline_a._y(2 ):0:6 );
+ writeln(fd ,m_spline_a._x(3 ):0:6 );
+ writeln(fd ,m_spline_a._y(3 ):0:6 );
+ writeln(fd ,m_spline_a._x(4 ):0:6 );
+ writeln(fd ,m_spline_a._y(4 ):0:6 );
+ writeln(fd ,m_spline_a._x(5 ):0:6 );
+ writeln(fd ,m_spline_a._y(5 ):0:6 );
+
+ m_profile.values(@x1 ,@y1 ,@x2 ,@y2 );
+
+ writeln(fd ,x1:0:6 );
+ writeln(fd ,y1:0:6 );
+ writeln(fd ,x2:0:6 );
+ writeln(fd ,y2:0:6 );
+
+ close(fd );
+
+ inherited Destruct;
+
+ m_profile.Destruct;
+ m_spline_r.Destruct;
+ m_spline_g.Destruct;
+ m_spline_b.Destruct;
+ m_spline_a.Destruct;
+ m_rbox.Destruct;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ pf : rasterizer_scanline_aa;
+ sl : scanline_u8;
+ rb : renderer_base;
+ r : renderer_scanline_aa_solid;
+
+ pixf : pixel_formats;
+ rgba : aggclr;
+
+ ini_scale : double;
+
+ color_profile : array[0..255 ] of aggclr;
+
+ mtx1 ,mtx_g1 : trans_affine;
+
+ tas : trans_affine_scaling;
+ tar : trans_affine_rotation;
+ tat : trans_affine_translation;
+
+ e1 : ellipse;
+ i : int;
+ t1 : conv_transform;
+
+ gr_circle : gradient_radial;
+ gr_diamond : gradient_diamond;
+ gr_x : gradient_x;
+ gr_xy : gradient_xy;
+ gr_sqrt_xy : gradient_sqrt_xy;
+ gr_conic : gradient_conic;
+
+ gr_ptr : gradient_reflect_adaptor;
+
+ span_alloc : span_allocator;
+ colors : color_function_profile;
+ inter : span_interpolator_linear;
+ span_gen : span_gradient;
+
+ r1 : renderer_scanline_aa;
+
+begin
+// Initialize structures
+ pf.Construct;
+ sl.Construct;
+
+ pixfmt(pixf ,rbuf_window );
+
+ rb.Construct(@pixf );
+ r.Construct (@rb );
+
+ rgba.ConstrDbl(0 ,0 ,0 );
+ rb.clear (@rgba );
+
+// Render the controls
+ m_profile.text_size_(8.0 );
+
+ render_ctrl(@pf ,@sl ,@r ,@m_profile );
+ render_ctrl(@pf ,@sl ,@r ,@m_spline_r );
+ render_ctrl(@pf ,@sl ,@r ,@m_spline_g );
+ render_ctrl(@pf ,@sl ,@r ,@m_spline_b );
+ render_ctrl(@pf ,@sl ,@r ,@m_spline_a );
+ render_ctrl(@pf ,@sl ,@r ,@m_rbox );
+
+// Render
+ ini_scale:=1.0;
+
+ mtx1.Construct;
+
+ tas.Construct(ini_scale ,ini_scale ); mtx1.multiply(@tas );
+ tar.Construct(deg2rad(0.0 ) ); mtx1.multiply(@tar );
+ tat.Construct(center_x ,center_y ); mtx1.multiply(@tat );
+
+ mtx1.multiply(_trans_affine_resizing );
+
+ e1.Construct;
+ e1.init(0.0 ,0.0 ,110.0 ,110.0 ,64 );
+
+ mtx_g1.Construct;
+
+ tas.Construct(ini_scale ,ini_scale ); mtx_g1.multiply(@tas );
+ tas.Construct(m_scale ,m_scale ); mtx_g1.multiply(@tas );
+ tas.Construct(m_scale_x ,m_scale_y ); mtx_g1.multiply(@tas );
+ tar.Construct(m_angle ); mtx_g1.multiply(@tar );
+ tat.Construct(m_center_x ,m_center_y ); mtx_g1.multiply(@tat );
+
+ mtx_g1.multiply(_trans_affine_resizing );
+ mtx_g1.invert;
+
+ for i:=0 to 255 do
+ begin
+ rgba.ConstrDbl(
+ double_ptr(ptrcomp(m_spline_r._spline ) + i * sizeof(double ) )^ ,
+ double_ptr(ptrcomp(m_spline_g._spline ) + i * sizeof(double ) )^ ,
+ double_ptr(ptrcomp(m_spline_b._spline ) + i * sizeof(double ) )^ ,
+ double_ptr(ptrcomp(m_spline_a._spline ) + i * sizeof(double ) )^ );
+
+ color_profile[i ]:=rgba;
+
+ end;
+
+ t1.Construct(@e1 ,@mtx1 );
+
+ case m_rbox._cur_item of
+ 0 :
+ begin
+ gr_circle.Construct;
+ gr_ptr.Construct(@gr_circle );
+
+ end;
+
+ 1 :
+ begin
+ gr_diamond.Construct;
+ gr_ptr.Construct(@gr_diamond );
+
+ end;
+
+ 2 :
+ begin
+ gr_x.Construct;
+ gr_ptr.Construct(@gr_x );
+
+ end;
+
+ 3 :
+ begin
+ gr_xy.Construct;
+ gr_ptr.Construct(@gr_xy );
+
+ end;
+
+ 4 :
+ begin
+ gr_sqrt_xy.Construct;
+ gr_ptr.Construct(@gr_sqrt_xy );
+
+ end;
+
+ 5 :
+ begin
+ gr_conic.Construct;
+ gr_ptr.Construct(@gr_conic );
+
+ end;
+
+ end;
+
+ span_alloc.Construct;
+ colors.Construct (@color_profile ,int8u_ptr(m_profile.gamma ) );
+ inter.Construct (@mtx_g1);
+ span_gen.Construct(@span_alloc ,@inter ,@gr_ptr ,@colors ,0 ,150 );
+ r1.construct (@rb ,@span_gen );
+
+ pf.add_path (@t1 );
+ render_scanlines(@pf ,@sl ,@r1 );
+
+// Free AGG resources
+ pf.Destruct;
+ sl.Destruct;
+
+ span_alloc.Destruct;
+
+end;
+
+{ ON_MOUSE_MOVE }
+procedure the_application.on_mouse_move;
+var
+ x2 ,y2 ,dx ,dy : double;
+
+begin
+ if m_mouse_move then
+ begin
+ x2:=x;
+ y2:=y;
+
+ _trans_affine_resizing.inverse_transform(_trans_affine_resizing ,@x2 ,@y2 );
+
+ if flags and kbd_ctrl <> 0 then
+ begin
+ dx:=x2 - m_center_x;
+ dy:=y2 - m_center_y;
+
+ m_scale_x:=m_prev_scale_x * dx / m_pdx;
+ m_scale_y:=m_prev_scale_y * dy / m_pdy;
+
+ force_redraw;
+
+ end
+ else
+ begin
+ if flags and mouse_left <> 0 then
+ begin
+ m_center_x:=x2 + m_pdx;
+ m_center_y:=y2 + m_pdy;
+
+ force_redraw;
+
+ end;
+
+ if flags and mouse_right <> 0 then
+ begin
+ dx:=x2 - m_center_x;
+ dy:=y2 - m_center_y;
+
+ m_scale:=
+ m_prev_scale *
+ Sqrt(dx * dx + dy * dy ) /
+ Sqrt(m_pdx * m_pdx + m_pdy * m_pdy );
+
+ m_angle:=m_prev_angle + ArcTan2(dy ,dx ) - ArcTan2(m_pdy ,m_pdx );
+
+ force_redraw;
+
+ end;
+
+ end;
+
+ end;
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure the_application.on_mouse_button_down;
+var
+ x2 ,y2 : double;
+
+begin
+ m_mouse_move:=true;
+
+ x2:=x;
+ y2:=y;
+
+ _trans_affine_resizing.inverse_transform(_trans_affine_resizing ,@x2 ,@y2 );
+
+ m_pdx:=m_center_x - x2;
+ m_pdy:=m_center_y - y2;
+
+ m_prev_scale :=m_scale;
+ m_prev_angle :=m_angle + pi;
+ m_prev_scale_x:=m_scale_x;
+ m_prev_scale_y:=m_scale_y;
+
+ force_redraw;
+
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+procedure the_application.on_mouse_button_up;
+begin
+ m_mouse_move:=false;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+var
+ i : int;
+ fd : text;
+
+ buf : array[0..511 ] of char;
+ rgba : aggclr;
+
+begin
+ if key = byte(' ' ) then
+ begin
+ AssignFile(fd ,'colors.dat' );
+ rewrite (fd );
+
+ for i:=0 to 255 do
+ begin
+ rgba.ConstrDbl(
+ double_ptr(ptrcomp(m_spline_r._spline ) + i * sizeof(double ) )^ ,
+ double_ptr(ptrcomp(m_spline_g._spline ) + i * sizeof(double ) )^ ,
+ double_ptr(ptrcomp(m_spline_b._spline ) + i * sizeof(double ) )^ ,
+ double_ptr(ptrcomp(m_spline_a._spline ) + i * sizeof(double ) )^ );
+
+ sprintf(@buf[0 ] ,' %3d, ' ,rgba.r );
+ sprintf(@buf[StrLen(@buf ) ] ,'%3d, ' ,rgba.g );
+ sprintf(@buf[StrLen(@buf ) ] ,'%3d, ' ,rgba.b );
+ sprintf(@buf[StrLen(@buf ) ] ,'%3d,' ,rgba.a );
+
+ writeln(fd ,PChar(@buf[0 ] ) );
+
+ end;
+
+ close(fd );
+
+ AssignFile(fd ,'profile.dat' );
+ rewrite (fd );
+
+ for i:=0 to 255 do
+ begin
+ sprintf(@buf[0 ] ,'%3d, ' ,int8u_ptr(ptrcomp(m_profile.gamma ) + i * sizeof(int8u ) )^ );
+
+ write(fd ,PChar(@buf[0 ] ) );
+
+ if (i and $F) = $F then
+ writeln(fd );
+
+ end;
+
+ close(fd );
+
+ end;
+
+ if key = key_f1 then
+ message_(
+ 'This "sphere" is rendered with color gradients only. Initially there was an idea '#13 +
+ 'to compensate so called Mach Bands effect. To do so I added a gradient profile '#13 +
+ 'functor. Then the concept was extended to set a color profile. As a result you '#13 +
+ 'can render simple geometrical objects in 2D looking like 3D ones. In this example '#13 +
+ 'you can construct your own color profile and select the gradient function. '#13 +
+ 'There''re not so many gradient functions in AGG, but you can easily add your own.'#13#13 +
+ 'How to play with:'#13#13 +
+ 'Use the left mouse button to drag the "gradient".'#13 +
+ 'Use the right mouse button to scale and rotate the "gradient".'#13 +
+ 'Press the spacebar to write down the "colors.dat" file.' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+VAR
+ app : the_application;
+
+BEGIN
+ app.Construct(pix_format ,flip_y );
+ app.caption_ ('AGG gradients with Mach bands compensation (F1-Help)' );
+
+ if app.init(512 ,400 ,window_resize or window_hw_buffer ) then
+ app.run;
+
+ app.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/gradients_contour.dpr b/src/corelib/render/software/agg-demos/gradients_contour.dpr
new file mode 100644
index 00000000..4327c041
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/gradients_contour.dpr
@@ -0,0 +1,1907 @@
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+// To flood England (4 colors):
+//
+// C2: 512 D2: 226
+// C1: 17 D1: 0
+//
+program
+ gradients_contour ;
+
+uses
+ SysUtils ,Math ,
+
+ agg_basics ,
+ agg_array ,
+ agg_platform_support ,
+
+ agg_color ,
+ agg_pixfmt ,
+ agg_pixfmt_rgb ,
+ agg_pixfmt_gray ,
+
+ agg_ctrl ,
+ agg_slider_ctrl ,
+ agg_cbox_ctrl ,
+ agg_rbox_ctrl ,
+
+ agg_rendering_buffer ,
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_renderer_primitives ,
+ agg_rasterizer_scanline_aa ,
+ agg_scanline ,
+ agg_scanline_u ,
+ agg_scanline_p ,
+ agg_render_scanlines ,
+
+ agg_conv_curve ,
+ agg_conv_stroke ,
+ agg_conv_transform ,
+ agg_gsv_text ,
+ agg_pixfmt_amask_adaptor ,
+ agg_alpha_mask_u8 ,
+ agg_vertex_source ,
+ agg_path_storage ,
+ agg_trans_affine ,
+ agg_math_stroke ,
+ agg_bounding_rect ,
+ agg_gradient_lut ,
+ agg_span_allocator ,
+ agg_span_gradient ,
+ agg_span_gradient_image ,
+ agg_span_gradient_contour ,
+ agg_span_interpolator_linear ,
+
+ make_gb_poly_ ,
+ make_arrows_ ;
+
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+type
+ gradient_conic_angle = object(gradient )
+ function calculate(x ,y ,d : int ) : int; virtual;
+
+ end;
+
+ spiral = object(vertex_source )
+ m_x ,
+ m_y ,
+ m_r1 ,
+ m_r2 ,
+ m_step ,
+
+ m_start_angle ,
+
+ m_angle ,
+ m_curr_r ,
+ m_da ,
+ m_dr : double;
+ m_start : boolean;
+
+ constructor Construct(x ,y ,r1 ,r2 ,step : double; start_angle : double = 0 );
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ end;
+
+ the_application = object(platform_support )
+ m_polygons ,
+ m_gradient : rbox_ctrl;
+
+ m_stroke ,
+ m_refl : cbox_ctrl;
+
+ m_c1 ,
+ m_c2 ,
+ m_d1 ,
+ m_d2 ,
+ m_clrs : slider_ctrl;
+
+ m_ras : rasterizer_scanline_aa;
+ m_sl : scanline_u8;
+
+ m_gamma : double;
+
+ m_colors02 ,
+ m_colors03 ,
+ m_colors04 ,
+ m_colors05 ,
+ m_colors06 ,
+ m_colors07 ,
+ m_colors08 ,
+ m_colors09 ,
+ m_colors10 ,
+ m_colors11 : gradient_lut;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure draw_text(x ,y : double; str : char_ptr );
+
+ procedure perform_rendering(vs : vertex_source_ptr; contour : path_storage_ptr );
+ function render : unsigned;
+
+ procedure on_draw; virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ CALCULATE }
+function gradient_conic_angle.calculate;
+var
+ res : double;
+
+begin
+ res:=ArcTan2(y ,x );
+
+ if res < 0 then
+ result:=Abs(1600 - trunc(Abs(res ) * d / pi / 2 ) )
+ else
+ result:=trunc(res * d / pi / 2 )
+
+end;
+
+{ CONSTRUCT }
+constructor spiral.Construct;
+begin
+ m_x :=x;
+ m_y :=y;
+ m_r1:=r1;
+ m_r2:=r2;
+
+ m_step :=step;
+ m_start_angle:=start_angle;
+ m_angle :=start_angle;
+
+ m_da:=deg2rad(4.0 );
+ m_dr:=m_step / 90.0;
+
+end;
+
+{ REWIND }
+procedure spiral.rewind;
+begin
+ m_angle :=m_start_angle;
+ m_curr_r:=m_r1;
+ m_start :=true;
+
+end;
+
+{ VERTEX }
+function spiral.vertex;
+begin
+ if m_curr_r > m_r2 then
+ begin
+ result:=path_cmd_stop;
+
+ exit;
+
+ end;
+
+ x^:=m_x + Cos(m_angle ) * m_curr_r;
+ y^:=m_y + Sin(m_angle ) * m_curr_r;
+
+ m_curr_r:=m_curr_r + m_dr;
+ m_angle :=m_angle + m_da;
+
+ if m_start then
+ begin
+ m_start:=false;
+
+ result:=path_cmd_move_to;
+
+ end
+ else
+ result:=path_cmd_line_to;
+
+end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+var
+ rgba : aggclr;
+
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_polygons.Construct(5.0 ,5.0 ,5.0 + 130.0 ,90.0 ,not flip_y_ );
+ m_gradient.Construct(145.0 ,5.0 ,220.0 + 80.0 ,90.0 ,not flip_y_ );
+ m_stroke.Construct (305.0 ,77.0 ,'Bitmap Gradient' ,not flip_y_ );
+ m_refl.Construct (440.0 ,77.0 ,'Reflect' ,not flip_y_ );
+ m_c1.Construct (310.0 ,10.0 ,400.0 ,16.0 ,not flip_y_ );
+ m_c2.Construct (310.0 ,30.0 ,400.0 ,36.0 ,not flip_y_ );
+ m_d1.Construct (410.0 ,10.0 ,500.0 ,16.0 ,not flip_y_ );
+ m_d2.Construct (410.0 ,30.0 ,500.0 ,36.0 ,not flip_y_ );
+ m_clrs.Construct (310.0 ,50.0 ,500.0 ,58.0 ,not flip_y_ );
+
+ m_ras.Construct;
+ m_sl.Construct;
+
+ m_gradient.add_item ('Contour' );
+ m_gradient.add_item ('Auto Contour' );
+ m_gradient.add_item ('Assymetric Conic' );
+ m_gradient.add_item ('Flat Fill' );
+ m_gradient.cur_item_(1 );
+
+ add_ctrl(@m_gradient );
+
+ m_gradient.no_transform;
+
+ m_polygons.add_item ('Simple Path' );
+ m_polygons.add_item ('Great Britain' );
+ m_polygons.add_item ('Spiral' );
+ m_polygons.add_item ('Glyph' );
+ m_polygons.cur_item_(0 );
+
+ add_ctrl(@m_polygons );
+
+ m_polygons.no_transform;
+
+ add_ctrl(@m_stroke );
+
+ m_stroke.status_(false );
+
+ m_stroke.no_transform;
+
+ add_ctrl(@m_refl );
+
+ m_refl.status_(true );
+
+ m_refl.no_transform;
+
+ add_ctrl(@m_c1 );
+
+ m_c1.label_('C1=%1.0f' );
+ m_c1.range_(0.0 ,512.0 );
+ m_c1.value_(0.0 );
+ m_c1.no_transform;
+
+ add_ctrl(@m_c2 );
+
+ m_c2.label_('C2=%1.0f' );
+ m_c2.range_(0.0 ,512.0 );
+ m_c2.value_(512.0 );
+ m_c2.no_transform;
+
+ add_ctrl(@m_d1 );
+
+ m_d1.label_('D1=%1.0f' );
+ m_d1.range_(0.0 ,512.0 );
+ m_d1.value_(0.0 );
+ m_d1.no_transform;
+
+ add_ctrl(@m_d2 );
+
+ m_d2.label_('D2=%1.0f' );
+ m_d2.range_(0.0 ,512.0 );
+ m_d2.value_(100.0 );
+ m_d2.no_transform;
+
+ add_ctrl(@m_clrs );
+
+ m_clrs.label_('Colors=%1.0f' );
+ m_clrs.range_(2.0 ,11.0 );
+ m_clrs.value_(2.0 );
+ m_clrs.num_steps_(9 );
+ m_clrs.no_transform;
+
+{ 2 colors gradient }
+ m_colors02.Construct(1024 );
+ m_colors02.remove_all;
+
+ rgba.ConstrInt (178 ,34 ,34 );
+ m_colors02.add_color(0.0 ,@rgba );
+
+ rgba.ConstrInt (255 ,255 ,0 );
+ m_colors02.add_color(1.0 ,@rgba );
+
+ m_colors02.build_lut;
+
+{ 3 colors gradient }
+ m_colors03.Construct(1024 );
+ m_colors03.remove_all;
+
+ rgba.ConstrInt (245 ,233 ,131 );
+ m_colors03.add_color(0.0 ,@rgba );
+
+ rgba.ConstrInt (146 ,35 ,219 );
+ m_colors03.add_color(0.5 ,@rgba );
+
+ rgba.ConstrInt (255 ,35 ,0 );
+ m_colors03.add_color(1.0 ,@rgba );
+
+ m_colors03.build_lut;
+
+{ 4 colors gradient }
+ m_colors04.Construct(1024 );
+ m_colors04.remove_all;
+
+ rgba.ConstrInt (0 ,255 ,0 );
+ m_colors04.add_color(1.0 ,@rgba );
+
+ rgba.ConstrInt (120 ,0 ,0 );
+ m_colors04.add_color(0.7 ,@rgba );
+
+ rgba.ConstrInt (120 ,120 ,0 );
+ m_colors04.add_color(0.2 ,@rgba );
+
+ rgba.ConstrInt (0 ,0 ,255 );
+ m_colors04.add_color(0.0 ,@rgba );
+
+ m_colors04.build_lut;
+
+{ 5 colors gradient }
+ m_colors05.Construct(1024 );
+ m_colors05.remove_all;
+
+ rgba.ConstrInt (230 ,188 ,106 );
+ m_colors05.add_color(0.2 ,@rgba );
+
+ rgba.ConstrInt (207 ,148 ,31 );
+ m_colors05.add_color(0.4 ,@rgba );
+
+ rgba.ConstrInt (69 ,56 ,30 );
+ m_colors05.add_color(0.6 ,@rgba );
+
+ rgba.ConstrInt (43 ,33 ,13 );
+ m_colors05.add_color(0.8 ,@rgba );
+
+ rgba.ConstrInt (227 ,221 ,209 );
+ m_colors05.add_color(1.0 ,@rgba );
+
+ m_colors05.build_lut;
+
+{ 6 colors gradient }
+ m_colors06.Construct(1024 );
+ m_colors06.remove_all;
+
+ rgba.ConstrInt (125 ,99 ,255 );
+ m_colors06.add_color(0.0 ,@rgba );
+
+ rgba.ConstrInt (118 ,79 ,210 );
+ m_colors06.add_color(0.2 ,@rgba );
+
+ rgba.ConstrInt (105 ,58 ,81 );
+ m_colors06.add_color(0.4 ,@rgba );
+
+ rgba.ConstrInt (217 ,74 ,102 );
+ m_colors06.add_color(0.6 ,@rgba );
+
+ rgba.ConstrInt (242 ,148 ,90 );
+ m_colors06.add_color(0.8 ,@rgba );
+
+ rgba.ConstrInt (242 ,200 ,102 );
+ m_colors06.add_color(1.0 ,@rgba );
+
+ m_colors06.build_lut;
+
+{ 7 colors gradient }
+ m_colors07.Construct(1024 );
+ m_colors07.remove_all;
+
+ rgba.ConstrInt (216 ,237 ,232 );
+ m_colors07.add_color(0.0 ,@rgba );
+
+ rgba.ConstrInt (196 ,214 ,226 );
+ m_colors07.add_color(0.16 ,@rgba );
+
+ rgba.ConstrInt (175 ,194 ,217 );
+ m_colors07.add_color(0.32 ,@rgba );
+
+ rgba.ConstrInt (155 ,176 ,210 );
+ m_colors07.add_color(0.48 ,@rgba );
+
+ rgba.ConstrInt (140 ,162 ,202 );
+ m_colors07.add_color(0.64 ,@rgba );
+
+ rgba.ConstrInt (130 ,149 ,193 );
+ m_colors07.add_color(0.80 ,@rgba );
+
+ rgba.ConstrInt (72 ,102 ,165 );
+ m_colors07.add_color(1.0 ,@rgba );
+
+ m_colors07.build_lut;
+
+{ 8 colors gradient }
+ m_colors08.Construct(1024 );
+ m_colors08.remove_all;
+
+ rgba.ConstrInt (255 ,223 ,168 );
+ m_colors08.add_color(0.0 ,@rgba );
+
+ rgba.ConstrInt (255 ,199 ,162 );
+ m_colors08.add_color(0.14 ,@rgba );
+
+ rgba.ConstrInt (255 ,175 ,156 );
+ m_colors08.add_color(0.28 ,@rgba );
+
+ rgba.ConstrInt (255 ,151 ,151 );
+ m_colors08.add_color(0.42 ,@rgba );
+
+ rgba.ConstrInt (255 ,127 ,145 );
+ m_colors08.add_color(0.56 ,@rgba );
+
+ rgba.ConstrInt (255 ,104 ,140 );
+ m_colors08.add_color(0.70 ,@rgba );
+
+ rgba.ConstrInt (255 ,80 ,133 );
+ m_colors08.add_color(0.84 ,@rgba );
+
+ rgba.ConstrInt (255 ,56 ,128 );
+ m_colors08.add_color(1.0 ,@rgba );
+
+ m_colors08.build_lut;
+
+{ 9 colors gradient }
+ m_colors09.Construct(1024 );
+ m_colors09.remove_all;
+
+ rgba.ConstrInt (255 ,4 ,163 );
+ m_colors09.add_color(0.0 ,@rgba );
+
+ rgba.ConstrInt (255 ,4 ,109 );
+ m_colors09.add_color(0.125 ,@rgba );
+
+ rgba.ConstrInt (255 ,4 ,46 );
+ m_colors09.add_color(0.25 ,@rgba );
+
+ rgba.ConstrInt (255 ,75 ,75 );
+ m_colors09.add_color(0.375 ,@rgba );
+
+ rgba.ConstrInt (255 ,120 ,83 );
+ m_colors09.add_color(0.5 ,@rgba );
+
+ rgba.ConstrInt (255 ,143 ,83 );
+ m_colors09.add_color(0.625 ,@rgba );
+
+ rgba.ConstrInt (255 ,180 ,83 );
+ m_colors09.add_color(0.75 ,@rgba );
+
+ rgba.ConstrInt (255 ,209 ,83 );
+ m_colors09.add_color(0.875 ,@rgba );
+
+ rgba.ConstrInt (255 ,246 ,83 );
+ m_colors09.add_color(1.0 ,@rgba );
+
+ m_colors09.build_lut;
+
+{ 10 colors gradient }
+ m_colors10.Construct(1024 );
+ m_colors10.remove_all;
+
+ rgba.ConstrInt (255 ,0 ,0 );
+ m_colors10.add_color(0.0 ,@rgba );
+
+ rgba.ConstrInt (255 ,198 ,198 );
+ m_colors10.add_color(0.11 ,@rgba );
+
+ rgba.ConstrInt (255 ,255 ,0 );
+ m_colors10.add_color(0.22 ,@rgba );
+
+ rgba.ConstrInt (255 ,255 ,226 );
+ m_colors10.add_color(0.33 ,@rgba );
+
+ rgba.ConstrInt (85 ,85 ,255 );
+ m_colors10.add_color(0.44 ,@rgba );
+
+ rgba.ConstrInt (226 ,226 ,255 );
+ m_colors10.add_color(0.55 ,@rgba );
+
+ rgba.ConstrInt (28 ,255 ,28 );
+ m_colors10.add_color(0.66 ,@rgba );
+
+ rgba.ConstrInt (226 ,255 ,226 );
+ m_colors10.add_color(0.77 ,@rgba );
+
+ rgba.ConstrInt (255 ,72 ,255 );
+ m_colors10.add_color(0.88 ,@rgba );
+
+ rgba.ConstrInt (255 ,227 ,255 );
+ m_colors10.add_color(1.0 ,@rgba );
+
+ m_colors10.build_lut;
+
+{ 11 colors gradient }
+ m_colors11.Construct(1024 );
+ m_colors11.remove_all;
+
+ m_gamma:=1.8;
+
+ rgba.from_wavelength(380 ,m_gamma );
+ m_colors11.add_color(0.0 ,@rgba );
+
+ rgba.from_wavelength(420 ,m_gamma );
+ m_colors11.add_color(0.1 ,@rgba );
+
+ rgba.from_wavelength(460 ,m_gamma );
+ m_colors11.add_color(0.2 ,@rgba );
+
+ rgba.from_wavelength(500 ,m_gamma );
+ m_colors11.add_color(0.3 ,@rgba );
+
+ rgba.from_wavelength(540 ,m_gamma );
+ m_colors11.add_color(0.4 ,@rgba );
+
+ rgba.from_wavelength(580 ,m_gamma );
+ m_colors11.add_color(0.5 ,@rgba );
+
+ rgba.from_wavelength(620 ,m_gamma );
+ m_colors11.add_color(0.6 ,@rgba );
+
+ rgba.from_wavelength(660 ,m_gamma );
+ m_colors11.add_color(0.7 ,@rgba );
+
+ rgba.from_wavelength(700 ,m_gamma );
+ m_colors11.add_color(0.8 ,@rgba );
+
+ rgba.from_wavelength(740 ,m_gamma );
+ m_colors11.add_color(0.9 ,@rgba );
+
+ rgba.from_wavelength(780 ,m_gamma );
+ m_colors11.add_color(1.0 ,@rgba );
+
+ m_colors11.build_lut;
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_polygons.Destruct;
+ m_gradient.Destruct;
+ m_stroke.Destruct;
+ m_refl.Destruct;
+ m_c1.Destruct;
+ m_c2.Destruct;
+ m_d1.Destruct;
+ m_d2.Destruct;
+ m_clrs.Destruct;
+
+ m_ras.Destruct;
+ m_sl.Destruct;
+
+ m_colors02.Destruct;
+ m_colors03.Destruct;
+ m_colors04.Destruct;
+ m_colors05.Destruct;
+ m_colors06.Destruct;
+ m_colors07.Destruct;
+ m_colors08.Destruct;
+ m_colors09.Destruct;
+ m_colors10.Destruct;
+ m_colors11.Destruct;
+
+end;
+
+{ DRAW_TEXT }
+procedure the_application.draw_text;
+var
+ pf : pixel_formats;
+ rb : renderer_base;
+ ren : renderer_scanline_aa_solid;
+ txt : gsv_text;
+
+ txt_stroke : conv_stroke;
+
+ rgba : aggclr;
+
+begin
+ pixfmt_bgr24(pf ,rbuf_window );
+
+ rb.Construct (@pf );
+ ren.Construct(@rb );
+
+ txt.Construct;
+
+ txt_stroke.Construct(@txt );
+ txt_stroke.width_ (1.5 );
+ txt_stroke.line_cap_(round_cap );
+
+ txt.size_ (10.0 );
+ txt.start_point_(x ,y );
+ txt.text_ (PChar(str ) );
+
+ m_ras.add_path (@txt_stroke);
+ rgba.ConstrDbl (0.0 ,0.0 ,0.0 );
+ ren.color_ (@rgba );
+ render_scanlines(@m_ras ,@m_sl ,@ren );
+
+ txt.Destruct;
+ txt_stroke.Destruct;
+
+end;
+
+const
+ puzzle : array[0..16383 ] of byte = (
+ $02,$51,$AE,$FF,$00,$5C,$B0,$FF,$0A,$85,$FF,$FF,$3B,$87,$95,$FF,$28,$27,$12,$FF,
+ $5C,$6F,$03,$FF,$88,$AD,$08,$FF,$90,$AC,$00,$FF,$8E,$AC,$00,$FF,$8B,$AE,$00,$FF,
+ $8C,$AD,$00,$FF,$9E,$BE,$05,$FF,$A5,$C7,$2B,$FF,$5A,$89,$67,$FF,$17,$45,$52,$FF,
+ $00,$36,$80,$FF,$03,$53,$AA,$FF,$00,$54,$A4,$FF,$00,$52,$B1,$FF,$04,$55,$B1,$FF,
+ $00,$50,$AC,$FF,$00,$52,$A9,$FF,$00,$4F,$98,$FF,$00,$43,$84,$FF,$00,$48,$9C,$FF,
+ $06,$55,$A4,$FF,$03,$4F,$A5,$FF,$01,$50,$AC,$FF,$00,$54,$AE,$FF,$05,$4E,$AD,$FF,
+ $01,$54,$BA,$FF,$00,$51,$AC,$FF,$00,$51,$AC,$FF,$03,$52,$AF,$FF,$00,$50,$B1,$FF,
+ $03,$4F,$AF,$FF,$04,$4F,$AA,$FF,$00,$56,$A7,$FF,$00,$55,$AE,$FF,$05,$4E,$B5,$FF,
+ $00,$53,$A9,$FF,$00,$52,$A4,$FF,$00,$51,$AF,$FF,$01,$53,$A7,$FF,$01,$53,$A9,$FF,
+ $04,$51,$AB,$FF,$03,$58,$B2,$FF,$00,$74,$F6,$FF,$14,$79,$D1,$FF,$34,$49,$22,$FF,
+ $5D,$75,$00,$FF,$8A,$B0,$01,$FF,$8F,$A4,$00,$FF,$8E,$B0,$02,$FF,$8B,$AC,$07,$FF,
+ $8D,$AC,$00,$FF,$C0,$D9,$04,$FF,$91,$CF,$2E,$FF,$11,$39,$43,$FF,$00,$28,$58,$FF,
+ $00,$4C,$99,$FF,$00,$54,$AA,$FF,$00,$50,$A9,$FF,$03,$53,$AA,$FF,$05,$52,$AE,$FF,
+ $00,$59,$B0,$FF,$00,$72,$EE,$FF,$35,$76,$92,$FF,$2C,$2C,$12,$FF,$64,$7A,$00,$FF,
+ $89,$B0,$00,$FF,$88,$AE,$00,$FF,$91,$AD,$00,$FF,$84,$AD,$06,$FF,$8F,$AE,$0A,$FF,
+ $9D,$BB,$00,$FF,$BE,$F0,$13,$FF,$57,$8D,$76,$FF,$08,$2E,$41,$FF,$01,$44,$8A,$FF,
+ $00,$52,$A8,$FF,$01,$4F,$B3,$FF,$05,$4D,$95,$FF,$00,$40,$7E,$FF,$04,$3F,$8F,$FF,
+ $0C,$41,$8F,$FF,$00,$20,$3E,$FF,$00,$07,$12,$FF,$08,$23,$4E,$FF,$00,$3D,$8C,$FF,
+ $00,$58,$A8,$FF,$03,$56,$A6,$FF,$04,$50,$B0,$FF,$03,$51,$A6,$FF,$04,$51,$AB,$FF,
+ $00,$53,$A6,$FF,$00,$52,$AC,$FF,$04,$56,$A2,$FF,$04,$55,$AE,$FF,$02,$53,$AE,$FF,
+ $00,$50,$AC,$FF,$00,$53,$A6,$FF,$06,$50,$A7,$FF,$06,$50,$A5,$FF,$01,$52,$AE,$FF,
+ $01,$55,$B5,$FF,$00,$55,$B1,$FF,$02,$4F,$AB,$FF,$07,$52,$B7,$FF,$00,$4F,$AC,$FF,
+ $00,$51,$A5,$FF,$01,$6D,$D0,$FF,$01,$72,$D8,$FF,$2B,$45,$20,$FF,$3E,$4C,$00,$FF,
+ $82,$A6,$08,$FF,$8E,$AA,$00,$FF,$8B,$AD,$01,$FF,$8C,$AD,$00,$FF,$8D,$AE,$00,$FF,
+ $A3,$CD,$00,$FF,$B6,$F7,$17,$FF,$34,$6C,$6B,$FF,$01,$16,$2B,$FF,$04,$31,$6C,$FF,
+ $00,$47,$9B,$FF,$00,$58,$A9,$FF,$06,$50,$A9,$FF,$00,$45,$87,$FF,$00,$4D,$98,$FF,
+ $03,$56,$B2,$FF,$31,$60,$6A,$FF,$44,$55,$0F,$FF,$70,$97,$00,$FF,$8B,$B1,$00,$FF,
+ $8D,$AA,$02,$FF,$8E,$AB,$03,$FF,$8D,$AD,$02,$FF,$89,$AB,$0C,$FF,$93,$BA,$09,$FF,
+ $C2,$EB,$37,$FF,$3B,$77,$91,$FF,$05,$3A,$6E,$FF,$00,$4F,$99,$FF,$00,$53,$A7,$FF,
+ $00,$51,$A0,$FF,$07,$37,$83,$FF,$0C,$26,$41,$FF,$00,$21,$46,$FF,$16,$56,$71,$FF,
+ $32,$6B,$65,$FF,$14,$27,$2D,$FF,$00,$08,$02,$FF,$00,$1B,$29,$FF,$00,$38,$82,$FF,
+ $00,$50,$A8,$FF,$01,$55,$AB,$FF,$07,$53,$B3,$FF,$00,$51,$A3,$FF,$06,$52,$B4,$FF,
+ $00,$58,$A8,$FF,$00,$4F,$AB,$FF,$00,$4D,$B9,$FF,$07,$51,$B2,$FF,$06,$52,$AA,$FF,
+ $03,$50,$B8,$FF,$09,$49,$A0,$FF,$00,$3C,$7B,$FF,$00,$2F,$62,$FF,$02,$27,$5E,$FF,
+ $04,$30,$5D,$FF,$00,$38,$74,$FF,$00,$48,$9D,$FF,$04,$56,$AC,$FF,$02,$51,$AE,$FF,
+ $06,$67,$D0,$FF,$00,$67,$E5,$FF,$40,$5C,$45,$FF,$49,$54,$06,$FF,$78,$9D,$00,$FF,
+ $8E,$B0,$00,$FF,$8B,$AB,$00,$FF,$8B,$A9,$00,$FF,$8E,$AD,$09,$FF,$93,$B3,$0A,$FF,
+ $CD,$FD,$07,$FF,$AB,$E7,$4B,$FF,$29,$49,$58,$FF,$01,$0E,$17,$FF,$0A,$23,$42,$FF,
+ $00,$30,$69,$FF,$00,$46,$90,$FF,$01,$12,$2C,$FF,$00,$24,$56,$FF,$19,$52,$70,$FF,
+ $4A,$72,$3E,$FF,$74,$92,$0C,$FF,$84,$A9,$00,$FF,$8D,$A9,$00,$FF,$91,$AC,$05,$FF,
+ $8D,$AE,$05,$FF,$8A,$A7,$00,$FF,$90,$B5,$05,$FF,$9C,$C9,$0A,$FF,$A8,$C3,$34,$FF,
+ $13,$4B,$70,$FF,$00,$35,$5D,$FF,$00,$49,$92,$FF,$02,$4D,$9E,$FF,$07,$51,$98,$FF,
+ $16,$57,$7F,$FF,$29,$59,$5D,$FF,$47,$6C,$39,$FF,$93,$BC,$2F,$FF,$D0,$FF,$15,$FF,
+ $CF,$F7,$36,$FF,$5E,$85,$59,$FF,$07,$10,$1F,$FF,$07,$0A,$29,$FF,$00,$43,$84,$FF,
+ $03,$56,$B2,$FF,$04,$49,$A4,$FF,$00,$55,$A9,$FF,$00,$55,$B6,$FF,$01,$50,$AF,$FF,
+ $08,$55,$AF,$FF,$00,$58,$A6,$FF,$02,$56,$AE,$FF,$00,$50,$AA,$FF,$00,$53,$B6,$FF,
+ $0A,$40,$6C,$FF,$00,$18,$2C,$FF,$02,$09,$0F,$FF,$04,$00,$02,$FF,$04,$02,$05,$FF,
+ $04,$0B,$15,$FF,$00,$18,$37,$FF,$03,$42,$85,$FF,$00,$55,$AF,$FF,$00,$6E,$CE,$FF,
+ $17,$68,$A9,$FF,$42,$5D,$28,$FF,$69,$7D,$00,$FF,$82,$A7,$01,$FF,$8B,$AD,$00,$FF,
+ $8A,$AC,$00,$FF,$90,$AD,$05,$FF,$8A,$AC,$00,$FF,$8B,$AE,$00,$FF,$A3,$CE,$00,$FF,
+ $CF,$F8,$30,$FF,$AE,$D0,$57,$FF,$31,$5F,$45,$FF,$01,$15,$2D,$FF,$00,$14,$1F,$FF,
+ $03,$0C,$2B,$FF,$28,$5E,$68,$FF,$3E,$78,$50,$FF,$74,$AA,$3A,$FF,$82,$A2,$19,$FF,
+ $85,$A5,$02,$FF,$87,$B0,$00,$FF,$8E,$AF,$00,$FF,$8B,$A8,$02,$FF,$8B,$AE,$00,$FF,
+ $8B,$B0,$01,$FF,$94,$B8,$00,$FF,$B1,$D8,$01,$FF,$AA,$C5,$2A,$FF,$1E,$46,$5F,$FF,
+ $0C,$2D,$4C,$FF,$07,$3D,$85,$FF,$16,$56,$79,$FF,$1B,$59,$72,$FF,$4B,$83,$52,$FF,
+ $93,$B9,$2E,$FF,$AD,$CA,$10,$FF,$A8,$CB,$00,$FF,$B0,$D8,$06,$FF,$CD,$FF,$03,$FF,
+ $D1,$FF,$11,$FF,$7D,$A2,$42,$FF,$04,$08,$14,$FF,$00,$24,$51,$FF,$00,$53,$AE,$FF,
+ $06,$54,$A7,$FF,$05,$51,$B1,$FF,$00,$53,$A1,$FF,$00,$50,$AC,$FF,$00,$52,$B2,$FF,
+ $00,$51,$AB,$FF,$03,$53,$A8,$FF,$01,$56,$B0,$FF,$0B,$5A,$95,$FF,$21,$49,$48,$FF,
+ $36,$4A,$2F,$FF,$5F,$78,$25,$FF,$6C,$A2,$42,$FF,$53,$8F,$5C,$FF,$33,$4A,$36,$FF,
+ $00,$05,$00,$FF,$00,$21,$40,$FF,$07,$43,$81,$FF,$00,$4B,$9D,$FF,$1A,$41,$3E,$FF,
+ $3D,$4F,$05,$FF,$7B,$98,$00,$FF,$89,$AD,$05,$FF,$8E,$AA,$0A,$FF,$8B,$AE,$00,$FF,
+ $8D,$AD,$04,$FF,$8A,$AB,$00,$FF,$90,$AE,$00,$FF,$84,$B6,$00,$FF,$AC,$D7,$03,$FF,
+ $DA,$FA,$1D,$FF,$B7,$F7,$49,$FF,$8C,$BA,$72,$FF,$4D,$78,$6F,$FF,$3B,$6D,$54,$FF,
+ $D6,$FF,$1A,$FF,$B4,$E0,$11,$FF,$A3,$D0,$03,$FF,$91,$B4,$00,$FF,$8B,$AC,$00,$FF,
+ $8F,$AC,$04,$FF,$8D,$A9,$00,$FF,$8F,$AE,$00,$FF,$8B,$AB,$02,$FF,$8B,$AA,$06,$FF,
+ $8D,$B3,$00,$FF,$A9,$D4,$00,$FF,$D3,$FE,$2A,$FF,$72,$A9,$43,$FF,$05,$33,$40,$FF,
+ $0D,$40,$6D,$FF,$33,$74,$8A,$FF,$5B,$82,$53,$FF,$95,$B6,$0F,$FF,$9C,$C4,$0B,$FF,
+ $87,$B7,$00,$FF,$8A,$B3,$00,$FF,$89,$A9,$00,$FF,$92,$B4,$00,$FF,$CE,$F4,$03,$FF,
+ $D0,$FF,$17,$FF,$0F,$29,$28,$FF,$05,$1D,$39,$FF,$00,$48,$A0,$FF,$00,$55,$AD,$FF,
+ $09,$50,$AC,$FF,$03,$52,$AF,$FF,$08,$53,$AE,$FF,$00,$52,$AE,$FF,$00,$4D,$B5,$FF,
+ $00,$5E,$B2,$FF,$11,$77,$CB,$FF,$33,$71,$6E,$FF,$57,$6C,$0F,$FF,$87,$A5,$00,$FF,
+ $9E,$CF,$02,$FF,$C4,$F7,$06,$FF,$CA,$FF,$0E,$FF,$DA,$FE,$22,$FF,$7C,$9C,$31,$FF,
+ $0E,$40,$73,$FF,$00,$3C,$83,$FF,$1A,$5D,$65,$FF,$4C,$5B,$06,$FF,$66,$79,$05,$FF,
+ $87,$A6,$02,$FF,$89,$AB,$00,$FF,$8F,$AC,$04,$FF,$8E,$B0,$00,$FF,$87,$A9,$00,$FF,
+ $8E,$AD,$07,$FF,$8F,$AB,$09,$FF,$90,$AC,$00,$FF,$93,$AF,$02,$FF,$A8,$CE,$00,$FF,
+ $BF,$F6,$07,$FF,$CD,$FF,$06,$FF,$DA,$FB,$14,$FF,$D2,$FF,$20,$FF,$99,$BF,$00,$FF,
+ $98,$B3,$02,$FF,$92,$AA,$00,$FF,$89,$A8,$04,$FF,$8D,$AF,$00,$FF,$8A,$AF,$00,$FF,
+ $89,$AA,$03,$FF,$90,$A9,$07,$FF,$8E,$AF,$00,$FF,$8F,$A9,$00,$FF,$89,$AF,$00,$FF,
+ $92,$BB,$05,$FF,$B7,$E3,$08,$FF,$C0,$F7,$28,$FF,$76,$B8,$7B,$FF,$55,$7F,$73,$FF,
+ $8E,$BA,$27,$FF,$93,$BF,$0A,$FF,$88,$A9,$00,$FF,$8D,$A8,$01,$FF,$8B,$AA,$04,$FF,
+ $89,$AE,$00,$FF,$90,$B1,$0A,$FF,$8B,$A8,$00,$FF,$9C,$D1,$00,$FF,$CE,$FB,$00,$FF,
+ $3A,$59,$4A,$FF,$00,$07,$00,$FF,$04,$3C,$79,$FF,$01,$53,$A9,$FF,$00,$51,$AB,$FF,
+ $00,$54,$B1,$FF,$00,$4F,$A9,$FF,$01,$56,$A7,$FF,$04,$53,$B2,$FF,$00,$62,$C8,$FF,
+ $28,$7A,$B4,$FF,$47,$66,$2D,$FF,$6A,$80,$04,$FF,$81,$A6,$00,$FF,$8E,$B0,$00,$FF,
+ $9C,$B0,$03,$FF,$95,$B9,$01,$FF,$C0,$EF,$01,$FF,$CD,$F7,$00,$FF,$B8,$DF,$20,$FF,
+ $AA,$CE,$26,$FF,$9E,$C5,$14,$FF,$9D,$BB,$01,$FF,$8D,$AC,$00,$FF,$8D,$AB,$00,$FF,
+ $8E,$AF,$00,$FF,$8B,$AD,$00,$FF,$8E,$AC,$00,$FF,$8E,$AC,$00,$FF,$8D,$AD,$00,$FF,
+ $84,$AC,$00,$FF,$93,$B1,$04,$FF,$83,$B0,$00,$FF,$8D,$A4,$00,$FF,$85,$B2,$00,$FF,
+ $92,$B6,$00,$FF,$99,$C1,$00,$FF,$99,$BC,$00,$FF,$88,$AF,$08,$FF,$8E,$AB,$01,$FF,
+ $8E,$AD,$00,$FF,$8A,$AE,$02,$FF,$8E,$AE,$03,$FF,$89,$A7,$00,$FF,$8D,$B4,$01,$FF,
+ $87,$AC,$00,$FF,$8C,$AD,$00,$FF,$89,$AD,$05,$FF,$8C,$AD,$00,$FF,$94,$A8,$09,$FF,
+ $96,$B6,$00,$FF,$BE,$DA,$00,$FF,$BE,$FB,$00,$FF,$B5,$DE,$00,$FF,$97,$BF,$00,$FF,
+ $8E,$B8,$00,$FF,$89,$B0,$00,$FF,$8F,$AE,$08,$FF,$90,$AB,$00,$FF,$8F,$AD,$00,$FF,
+ $8A,$AA,$00,$FF,$8C,$AD,$04,$FF,$99,$B2,$00,$FF,$CF,$FF,$0C,$FF,$48,$78,$46,$FF,
+ $02,$07,$0B,$FF,$00,$36,$7F,$FF,$07,$51,$B0,$FF,$00,$54,$A9,$FF,$03,$4F,$AD,$FF,
+ $01,$52,$AD,$FF,$05,$51,$AF,$FF,$00,$55,$B1,$FF,$02,$70,$EB,$FF,$38,$74,$98,$FF,
+ $3D,$48,$03,$FF,$76,$9C,$08,$FF,$97,$B7,$00,$FF,$88,$AE,$00,$FF,$91,$A8,$00,$FF,
+ $8C,$B1,$01,$FF,$88,$AF,$00,$FF,$91,$B4,$00,$FF,$AB,$D9,$00,$FF,$B0,$DE,$00,$FF,
+ $A5,$CE,$06,$FF,$8E,$B7,$05,$FF,$8D,$AE,$09,$FF,$91,$AC,$00,$FF,$8A,$A9,$03,$FF,
+ $87,$AF,$01,$FF,$8E,$AB,$01,$FF,$8F,$A8,$06,$FF,$8B,$AD,$00,$FF,$90,$AD,$00,$FF,
+ $86,$AC,$00,$FF,$90,$AC,$02,$FF,$94,$AC,$00,$FF,$8B,$AB,$00,$FF,$90,$AD,$03,$FF,
+ $89,$AB,$00,$FF,$94,$AB,$03,$FF,$8A,$B0,$00,$FF,$90,$AC,$02,$FF,$91,$AC,$00,$FF,
+ $8B,$A6,$00,$FF,$8E,$AF,$00,$FF,$8C,$AF,$00,$FF,$8A,$AD,$00,$FF,$8A,$AA,$07,$FF,
+ $8D,$AF,$00,$FF,$8E,$AB,$01,$FF,$8E,$AA,$00,$FF,$88,$AC,$04,$FF,$89,$AE,$00,$FF,
+ $8B,$AC,$00,$FF,$91,$AD,$03,$FF,$8B,$AB,$00,$FF,$83,$A4,$00,$FF,$86,$A2,$02,$FF,
+ $89,$A3,$02,$FF,$85,$A4,$00,$FF,$84,$A5,$00,$FF,$8D,$AE,$00,$FF,$8D,$AA,$00,$FF,
+ $8C,$AC,$09,$FF,$8F,$B8,$00,$FF,$C2,$ED,$08,$FF,$49,$63,$4A,$FF,$00,$1A,$2D,$FF,
+ $00,$44,$85,$FF,$01,$4D,$AD,$FF,$00,$55,$AB,$FF,$01,$52,$AB,$FF,$04,$4F,$B5,$FF,
+ $03,$51,$A6,$FF,$00,$5D,$AA,$FF,$0D,$84,$FF,$FF,$4A,$79,$73,$FF,$1D,$29,$00,$FF,
+ $6B,$80,$07,$FF,$8F,$AF,$02,$FF,$84,$B1,$00,$FF,$8F,$AC,$04,$FF,$90,$AA,$00,$FF,
+ $8E,$AE,$01,$FF,$8A,$AD,$00,$FF,$8B,$AC,$05,$FF,$8D,$B0,$00,$FF,$8A,$AE,$00,$FF,
+ $8A,$AD,$00,$FF,$8C,$AD,$04,$FF,$8E,$AC,$00,$FF,$8A,$AB,$04,$FF,$8E,$B1,$00,$FF,
+ $8E,$A8,$06,$FF,$91,$AD,$03,$FF,$89,$AB,$00,$FF,$8D,$A9,$00,$FF,$8F,$AD,$00,$FF,
+ $8D,$AC,$08,$FF,$8A,$AB,$06,$FF,$8C,$AD,$00,$FF,$8D,$AE,$00,$FF,$8A,$AA,$00,$FF,
+ $8E,$AD,$07,$FF,$88,$AE,$03,$FF,$8D,$AD,$02,$FF,$8B,$A8,$02,$FF,$8E,$B0,$04,$FF,
+ $8A,$AF,$00,$FF,$89,$A6,$00,$FF,$93,$AC,$08,$FF,$93,$AB,$00,$FF,$8E,$AD,$07,$FF,
+ $84,$AA,$00,$FF,$8C,$B1,$00,$FF,$91,$AE,$08,$FF,$8F,$AB,$00,$FF,$83,$A4,$0B,$FF,
+ $7A,$9C,$00,$FF,$69,$85,$00,$FF,$52,$6B,$03,$FF,$47,$5E,$04,$FF,$54,$70,$00,$FF,
+ $62,$7E,$05,$FF,$75,$90,$03,$FF,$8C,$AD,$00,$FF,$89,$AA,$03,$FF,$82,$A9,$00,$FF,
+ $90,$A9,$0F,$FF,$85,$A6,$0F,$FF,$25,$47,$49,$FF,$00,$29,$5D,$FF,$03,$4C,$99,$FF,
+ $04,$51,$AD,$FF,$01,$55,$AB,$FF,$04,$4F,$B4,$FF,$00,$56,$B0,$FF,$03,$4F,$A7,$FF,
+ $04,$5A,$BD,$FF,$08,$7F,$FF,$FF,$46,$7E,$71,$FF,$1B,$19,$04,$FF,$5D,$7C,$00,$FF,
+ $8A,$AB,$00,$FF,$8E,$AC,$00,$FF,$8B,$AA,$04,$FF,$8C,$B2,$00,$FF,$86,$AA,$00,$FF,
+ $8B,$AC,$05,$FF,$8C,$AD,$06,$FF,$8E,$AD,$00,$FF,$93,$A8,$0D,$FF,$8A,$AF,$07,$FF,
+ $85,$AC,$00,$FF,$8C,$AD,$00,$FF,$91,$B0,$00,$FF,$89,$AA,$00,$FF,$8A,$AD,$00,$FF,
+ $89,$AB,$00,$FF,$8F,$B0,$01,$FF,$8C,$AC,$00,$FF,$8E,$AC,$00,$FF,$8E,$AB,$03,$FF,
+ $8B,$AB,$00,$FF,$93,$AE,$01,$FF,$8B,$A8,$02,$FF,$8D,$B0,$00,$FF,$8A,$AB,$00,$FF,
+ $8B,$AB,$00,$FF,$88,$AA,$00,$FF,$90,$B1,$00,$FF,$8F,$A8,$02,$FF,$89,$AA,$00,$FF,
+ $8A,$B5,$06,$FF,$87,$B1,$00,$FF,$8C,$AB,$00,$FF,$93,$A9,$00,$FF,$8C,$A9,$00,$FF,
+ $8C,$AB,$05,$FF,$8A,$A8,$00,$FF,$86,$A9,$00,$FF,$71,$93,$01,$FF,$5F,$7E,$00,$FF,
+ $3D,$49,$0B,$FF,$35,$40,$16,$FF,$3F,$57,$0B,$FF,$37,$4D,$0D,$FF,$1C,$28,$00,$FF,
+ $3C,$48,$0A,$FF,$56,$68,$04,$FF,$64,$7C,$04,$FF,$52,$6B,$10,$FF,$57,$7E,$2F,$FF,
+ $46,$71,$43,$FF,$1D,$55,$70,$FF,$08,$46,$93,$FF,$01,$4F,$A1,$FF,$05,$53,$A5,$FF,
+ $03,$56,$A4,$FF,$00,$4D,$AC,$FF,$02,$4D,$B2,$FF,$00,$54,$AB,$FF,$03,$59,$B0,$FF,
+ $05,$85,$FF,$FF,$44,$8B,$79,$FF,$01,$12,$00,$FF,$53,$6D,$00,$FF,$88,$A3,$00,$FF,
+ $93,$A9,$06,$FF,$8E,$AC,$00,$FF,$8D,$AB,$00,$FF,$90,$AC,$00,$FF,$90,$AC,$09,$FF,
+ $89,$B1,$01,$FF,$73,$98,$00,$FF,$75,$95,$03,$FF,$7F,$99,$00,$FF,$85,$A3,$05,$FF,
+ $8B,$AF,$07,$FF,$93,$B2,$00,$FF,$8D,$A9,$06,$FF,$8B,$B2,$01,$FF,$89,$AE,$00,$FF,
+ $8D,$AA,$00,$FF,$83,$B3,$00,$FF,$8C,$AD,$00,$FF,$90,$AC,$02,$FF,$8A,$AA,$00,$FF,
+ $90,$AA,$09,$FF,$89,$AF,$00,$FF,$88,$AE,$01,$FF,$91,$AA,$06,$FF,$86,$A5,$02,$FF,
+ $83,$A9,$00,$FF,$85,$AE,$00,$FF,$88,$AD,$05,$FF,$8E,$AF,$00,$FF,$8D,$A8,$03,$FF,
+ $8F,$AC,$06,$FF,$8D,$AC,$06,$FF,$8B,$AE,$0A,$FF,$8C,$AD,$00,$FF,$8B,$B1,$02,$FF,
+ $89,$AC,$00,$FF,$74,$94,$0D,$FF,$56,$6E,$00,$FF,$56,$7A,$20,$FF,$31,$59,$50,$FF,
+ $00,$59,$B3,$FF,$00,$76,$FF,$FF,$2C,$89,$B5,$FF,$3F,$5E,$3F,$FF,$24,$34,$19,$FF,
+ $22,$2E,$00,$FF,$2E,$3D,$14,$FF,$35,$64,$5A,$FF,$19,$67,$8D,$FF,$0D,$5A,$92,$FF,
+ $05,$53,$93,$FF,$04,$4D,$AB,$FF,$03,$4F,$AF,$FF,$02,$52,$AB,$FF,$00,$52,$AA,$FF,
+ $02,$55,$B5,$FF,$08,$54,$AA,$FF,$00,$50,$B0,$FF,$00,$56,$AE,$FF,$01,$77,$FB,$FF,
+ $3A,$94,$D2,$FF,$22,$2B,$10,$FF,$2E,$2B,$00,$FF,$57,$78,$03,$FF,$7A,$99,$00,$FF,
+ $7D,$A6,$00,$FF,$8B,$B1,$0C,$FF,$86,$A5,$02,$FF,$80,$9A,$00,$FF,$61,$75,$00,$FF,
+ $4E,$62,$0D,$FF,$52,$75,$1B,$FF,$46,$51,$03,$FF,$4A,$51,$0B,$FF,$6E,$8E,$00,$FF,
+ $89,$B0,$00,$FF,$8F,$AD,$00,$FF,$8C,$AC,$00,$FF,$90,$AF,$00,$FF,$8D,$AB,$00,$FF,
+ $86,$AC,$00,$FF,$91,$AA,$04,$FF,$8A,$AC,$00,$FF,$8A,$AE,$02,$FF,$85,$A4,$00,$FF,
+ $7B,$9E,$00,$FF,$74,$98,$00,$FF,$84,$9B,$05,$FF,$3C,$45,$06,$FF,$54,$68,$07,$FF,
+ $74,$92,$00,$FF,$85,$A1,$00,$FF,$90,$AB,$06,$FF,$8B,$AB,$00,$FF,$8B,$AE,$00,$FF,
+ $8B,$AB,$00,$FF,$84,$AA,$00,$FF,$91,$B0,$00,$FF,$90,$B4,$0A,$FF,$90,$A8,$08,$FF,
+ $6D,$8A,$1C,$FF,$2A,$48,$48,$FF,$0D,$59,$AF,$FF,$00,$73,$D8,$FF,$00,$5C,$B6,$FF,
+ $07,$71,$E9,$FF,$00,$86,$F9,$FF,$0A,$8E,$F2,$FF,$24,$78,$D2,$FF,$2A,$5C,$8F,$FF,
+ $14,$5E,$8F,$FF,$00,$64,$CA,$FF,$09,$72,$DB,$FF,$02,$63,$C2,$FF,$00,$53,$AD,$FF,
+ $02,$51,$AD,$FF,$06,$55,$B4,$FF,$00,$53,$AD,$FF,$00,$4E,$AA,$FF,$00,$53,$AF,$FF,
+ $02,$4C,$AB,$FF,$06,$55,$B1,$FF,$03,$52,$B1,$FF,$02,$75,$F2,$FF,$29,$91,$FF,$FF,
+ $40,$84,$99,$FF,$38,$42,$1D,$FF,$20,$30,$03,$FF,$3D,$49,$0B,$FF,$4F,$6A,$00,$FF,
+ $56,$71,$00,$FF,$5B,$73,$03,$FF,$4B,$5D,$13,$FF,$37,$47,$20,$FF,$23,$46,$6E,$FF,
+ $1F,$74,$AB,$FF,$30,$5B,$3F,$FF,$17,$22,$00,$FF,$47,$5A,$09,$FF,$7B,$9E,$02,$FF,
+ $8B,$AC,$00,$FF,$8B,$AE,$00,$FF,$8F,$AA,$00,$FF,$8C,$AA,$0A,$FF,$94,$A9,$04,$FF,
+ $94,$AB,$05,$FF,$81,$A5,$00,$FF,$6F,$95,$02,$FF,$51,$68,$00,$FF,$38,$46,$08,$FF,
+ $2B,$38,$0A,$FF,$28,$2F,$05,$FF,$2C,$35,$1A,$FF,$18,$20,$0B,$FF,$38,$4C,$05,$FF,
+ $61,$81,$06,$FF,$81,$A5,$00,$FF,$90,$AD,$07,$FF,$8C,$AA,$00,$FF,$8A,$AF,$00,$FF,
+ $93,$AF,$05,$FF,$89,$A7,$00,$FF,$9F,$D4,$00,$FF,$A7,$CF,$31,$FF,$42,$77,$4B,$FF,
+ $08,$40,$6F,$FF,$00,$54,$AA,$FF,$00,$56,$B7,$FF,$00,$50,$AB,$FF,$00,$58,$B9,$FF,
+ $06,$68,$C9,$FF,$00,$68,$DE,$FF,$09,$86,$FF,$FF,$00,$6E,$DE,$FF,$02,$55,$BB,$FF,
+ $03,$56,$B6,$FF,$00,$58,$BE,$FF,$00,$59,$B2,$FF,$02,$50,$B2,$FF,$00,$52,$A3,$FF,
+ $01,$51,$A8,$FF,$00,$55,$A7,$FF,$02,$54,$AA,$FF,$01,$51,$A8,$FF,$02,$54,$A8,$FF,
+ $05,$4E,$AA,$FF,$00,$54,$A4,$FF,$00,$57,$B2,$FF,$00,$76,$F1,$FF,$0A,$88,$EE,$FF,
+ $3C,$94,$D3,$FF,$46,$7E,$71,$FF,$44,$61,$31,$FF,$40,$5C,$29,$FF,$49,$65,$28,$FF,
+ $54,$84,$54,$FF,$4D,$94,$82,$FF,$20,$67,$93,$FF,$06,$60,$C0,$FF,$00,$87,$FF,$FF,
+ $36,$85,$C8,$FF,$32,$50,$2C,$FF,$47,$58,$11,$FF,$7B,$9B,$00,$FF,$8B,$AC,$00,$FF,
+ $8A,$B0,$05,$FF,$90,$AC,$00,$FF,$8B,$AC,$00,$FF,$87,$AB,$00,$FF,$8B,$B0,$00,$FF,
+ $8D,$B3,$06,$FF,$52,$74,$38,$FF,$30,$5D,$48,$FF,$33,$61,$5E,$FF,$35,$5A,$52,$FF,
+ $2E,$4F,$32,$FF,$05,$7C,$DA,$FF,$2B,$64,$81,$FF,$2B,$33,$1E,$FF,$38,$40,$05,$FF,
+ $68,$88,$00,$FF,$90,$AE,$01,$FF,$8D,$A9,$00,$FF,$8C,$B1,$01,$FF,$88,$AF,$00,$FF,
+ $90,$AB,$00,$FF,$B0,$D7,$00,$FF,$C7,$E2,$35,$FF,$2E,$5A,$4B,$FF,$00,$33,$62,$FF,
+ $01,$53,$A5,$FF,$02,$51,$AD,$FF,$09,$50,$A8,$FF,$04,$50,$B2,$FF,$01,$4F,$A1,$FF,
+ $02,$5A,$B4,$FF,$00,$63,$CA,$FF,$00,$67,$BD,$FF,$03,$5D,$B5,$FF,$00,$4D,$A8,$FF,
+ $05,$54,$B1,$FF,$00,$54,$AE,$FF,$02,$4D,$B2,$FF,$00,$53,$AA,$FF,$04,$50,$B0,$FF,
+ $00,$51,$AF,$FF,$04,$51,$AB,$FF,$01,$51,$B0,$FF,$00,$51,$AB,$FF,$04,$59,$AC,$FF,
+ $00,$52,$A8,$FF,$00,$52,$B7,$FF,$01,$5E,$AE,$FF,$0A,$76,$DB,$FF,$00,$6E,$E9,$FF,
+ $04,$7B,$FD,$FF,$00,$74,$E7,$FF,$00,$76,$D7,$FF,$00,$68,$C8,$FF,$00,$6C,$DF,$FF,
+ $00,$76,$EE,$FF,$00,$6C,$C9,$FF,$00,$5A,$BA,$FF,$01,$69,$E6,$FF,$25,$73,$B1,$FF,
+ $41,$5F,$2B,$FF,$5B,$74,$18,$FF,$87,$A6,$02,$FF,$8F,$A8,$06,$FF,$87,$AC,$04,$FF,
+ $8F,$AC,$04,$FF,$8C,$AF,$00,$FF,$89,$AD,$03,$FF,$90,$BD,$08,$FF,$7D,$AA,$0F,$FF,
+ $19,$48,$72,$FF,$00,$5D,$AD,$FF,$02,$7C,$FF,$FF,$01,$7E,$FF,$FF,$02,$82,$FF,$FF,
+ $00,$7A,$FF,$FF,$17,$89,$F9,$FF,$29,$71,$BB,$FF,$32,$52,$21,$FF,$43,$4D,$08,$FF,
+ $7A,$9D,$00,$FF,$88,$AD,$08,$FF,$92,$AA,$00,$FF,$88,$AB,$06,$FF,$93,$AF,$00,$FF,
+ $9D,$CD,$00,$FF,$CB,$F8,$2B,$FF,$29,$55,$58,$FF,$01,$28,$51,$FF,$08,$4E,$A6,$FF,
+ $00,$54,$AD,$FF,$00,$52,$AC,$FF,$02,$56,$B0,$FF,$00,$52,$AC,$FF,$00,$50,$B4,$FF,
+ $02,$55,$B5,$FF,$00,$59,$B1,$FF,$00,$51,$B4,$FF,$09,$51,$B7,$FF,$02,$4E,$A4,$FF,
+ $00,$55,$B0,$FF,$00,$53,$A9,$FF,$00,$54,$A3,$FF,$07,$4F,$B1,$FF,$03,$51,$B5,$FF,
+ $02,$50,$A3,$FF,$00,$54,$AD,$FF,$03,$51,$B3,$FF,$00,$50,$AD,$FF,$06,$53,$AD,$FF,
+ $07,$52,$AF,$FF,$00,$51,$AE,$FF,$01,$4D,$AB,$FF,$00,$54,$AE,$FF,$00,$5A,$B4,$FF,
+ $05,$62,$CA,$FF,$00,$64,$C8,$FF,$02,$5E,$B5,$FF,$00,$4F,$B2,$FF,$00,$55,$AF,$FF,
+ $05,$4E,$B7,$FF,$00,$4F,$B4,$FF,$00,$6F,$D8,$FF,$37,$62,$8C,$FF,$27,$32,$10,$FF,
+ $5C,$7E,$06,$FF,$8B,$AD,$00,$FF,$94,$A7,$00,$FF,$8F,$B2,$00,$FF,$8A,$A7,$00,$FF,
+ $8A,$AF,$00,$FF,$99,$B6,$00,$FF,$A2,$D5,$14,$FF,$5A,$76,$4E,$FF,$06,$24,$56,$FF,
+ $04,$46,$94,$FF,$00,$53,$B1,$FF,$00,$59,$B2,$FF,$00,$73,$D6,$FF,$00,$59,$B9,$FF,
+ $01,$72,$DA,$FF,$0B,$84,$F9,$FF,$30,$72,$92,$FF,$25,$32,$00,$FF,$60,$72,$06,$FF,
+ $82,$A4,$05,$FF,$8B,$AD,$00,$FF,$8C,$AA,$00,$FF,$8D,$AE,$05,$FF,$A6,$CD,$00,$FF,
+ $AE,$F9,$2A,$FF,$43,$72,$62,$FF,$07,$28,$5D,$FF,$00,$53,$9E,$FF,$05,$51,$B1,$FF,
+ $00,$55,$AB,$FF,$03,$52,$AE,$FF,$05,$55,$AE,$FF,$00,$53,$AB,$FF,$00,$51,$AC,$FF,
+ $00,$53,$AF,$FF,$00,$52,$AE,$FF,$07,$4F,$B1,$FF,$00,$53,$B5,$FF,$01,$53,$A7,$FF,
+ $00,$54,$A5,$FF,$00,$51,$AB,$FF,$00,$54,$B3,$FF,$02,$52,$B1,$FF,$03,$54,$B0,$FF,
+ $00,$53,$A8,$FF,$00,$54,$AE,$FF,$02,$51,$AD,$FF,$01,$51,$AA,$FF,$00,$54,$AB,$FF,
+ $00,$52,$AC,$FF,$07,$54,$B0,$FF,$00,$4E,$AB,$FF,$00,$55,$B1,$FF,$05,$54,$B1,$FF,
+ $04,$4D,$A9,$FF,$00,$54,$B0,$FF,$04,$51,$AD,$FF,$07,$4F,$B3,$FF,$00,$53,$B1,$FF,
+ $03,$58,$B5,$FF,$00,$74,$E8,$FF,$2D,$63,$87,$FF,$2C,$32,$18,$FF,$69,$82,$03,$FF,
+ $8B,$AC,$00,$FF,$91,$AE,$00,$FF,$87,$B0,$00,$FF,$8D,$AB,$00,$FF,$8D,$AC,$08,$FF,
+ $A9,$CE,$0E,$FF,$BF,$E6,$35,$FF,$59,$69,$4C,$FF,$0A,$2B,$56,$FF,$00,$47,$94,$FF,
+ $00,$53,$AA,$FF,$03,$54,$B0,$FF,$02,$4F,$A7,$FF,$00,$54,$AB,$FF,$00,$52,$B1,$FF,
+ $00,$79,$EC,$FF,$1D,$7D,$C7,$FF,$33,$40,$15,$FF,$40,$52,$00,$FF,$78,$9D,$00,$FF,
+ $90,$AB,$00,$FF,$8B,$B1,$00,$FF,$8D,$A2,$05,$FF,$9E,$C3,$04,$FF,$C0,$ED,$16,$FF,
+ $60,$8F,$5B,$FF,$04,$37,$79,$FF,$00,$58,$A7,$FF,$05,$51,$B1,$FF,$02,$51,$AE,$FF,
+ $00,$50,$A9,$FF,$00,$50,$AB,$FF,$00,$51,$AB,$FF,$01,$53,$A9,$FF,$02,$53,$AE,$FF,
+ $00,$52,$AF,$FF,$00,$52,$AD,$FF,$02,$51,$AE,$FF,$02,$51,$B0,$FF,$04,$51,$A9,$FF,
+ $08,$54,$AA,$FF,$06,$4E,$B0,$FF,$06,$4C,$AC,$FF,$02,$4F,$A7,$FF,$00,$53,$B1,$FF,
+ $00,$50,$AC,$FF,$06,$53,$AF,$FF,$06,$51,$AE,$FF,$01,$52,$AD,$FF,$01,$52,$AE,$FF,
+ $03,$4D,$AC,$FF,$04,$4E,$AD,$FF,$01,$52,$AD,$FF,$00,$52,$B3,$FF,$00,$52,$AC,$FF,
+ $02,$53,$AF,$FF,$00,$52,$A8,$FF,$00,$54,$AE,$FF,$00,$53,$B0,$FF,$00,$5D,$BA,$FF,
+ $0B,$7D,$D5,$FF,$3F,$7C,$5B,$FF,$38,$47,$06,$FF,$76,$93,$05,$FF,$8D,$AD,$00,$FF,
+ $8D,$A9,$00,$FF,$88,$AF,$00,$FF,$8E,$AC,$00,$FF,$8D,$AD,$00,$FF,$A3,$C9,$00,$FF,
+ $C6,$ED,$38,$FF,$4E,$6D,$4D,$FF,$00,$1D,$39,$FF,$04,$4B,$99,$FF,$00,$51,$AA,$FF,
+ $02,$56,$AE,$FF,$00,$50,$AF,$FF,$08,$55,$AF,$FF,$03,$50,$AC,$FF,$00,$73,$DC,$FF,
+ $13,$7A,$D6,$FF,$44,$58,$27,$FF,$4E,$69,$02,$FF,$80,$9A,$01,$FF,$8E,$AF,$00,$FF,
+ $8B,$B1,$00,$FF,$90,$AA,$08,$FF,$92,$B1,$00,$FF,$B3,$DD,$0D,$FF,$60,$8D,$4A,$FF,
+ $01,$41,$71,$FF,$00,$49,$9A,$FF,$01,$51,$AA,$FF,$07,$4F,$B3,$FF,$02,$53,$AF,$FF,
+ $00,$51,$B4,$FF,$04,$52,$B7,$FF,$06,$50,$AF,$FF,$05,$4E,$AC,$FF,$05,$50,$AD,$FF,
+ $00,$54,$A5,$FF,$04,$4F,$AA,$FF,$00,$52,$AE,$FF,$00,$54,$B0,$FF,$00,$55,$AD,$FF,
+ $00,$55,$A5,$FF,$01,$56,$A9,$FF,$02,$53,$AE,$FF,$01,$50,$AF,$FF,$00,$53,$AD,$FF,
+ $00,$4E,$AB,$FF,$06,$52,$B4,$FF,$00,$4F,$AD,$FF,$00,$55,$AC,$FF,$00,$55,$A8,$FF,
+ $00,$53,$A9,$FF,$00,$55,$AC,$FF,$00,$52,$AE,$FF,$00,$55,$A9,$FF,$00,$52,$B0,$FF,
+ $02,$53,$AC,$FF,$03,$55,$A9,$FF,$01,$4F,$B3,$FF,$02,$5C,$B4,$FF,$10,$78,$CD,$FF,
+ $33,$65,$5A,$FF,$36,$45,$0A,$FF,$75,$93,$01,$FF,$8C,$AE,$00,$FF,$8E,$A9,$02,$FF,
+ $8A,$B0,$05,$FF,$8E,$AB,$01,$FF,$8C,$AD,$00,$FF,$AA,$CF,$03,$FF,$CB,$F4,$2E,$FF,
+ $54,$83,$59,$FF,$01,$1B,$3E,$FF,$01,$42,$82,$FF,$04,$54,$AD,$FF,$00,$4D,$AF,$FF,
+ $01,$55,$AF,$FF,$03,$4F,$AF,$FF,$01,$55,$AD,$FF,$00,$69,$DC,$FF,$16,$68,$A0,$FF,
+ $47,$56,$11,$FF,$75,$97,$02,$FF,$84,$A1,$09,$FF,$88,$AE,$01,$FF,$87,$AC,$00,$FF,
+ $8F,$AC,$00,$FF,$8D,$B9,$02,$FF,$9C,$C5,$13,$FF,$68,$B0,$40,$FF,$0F,$3C,$65,$FF,
+ $00,$44,$85,$FF,$04,$52,$A7,$FF,$01,$51,$A8,$FF,$00,$55,$A7,$FF,$00,$53,$A5,$FF,
+ $00,$53,$A6,$FF,$00,$53,$A6,$FF,$00,$51,$A9,$FF,$00,$53,$AF,$FF,$00,$55,$B1,$FF,
+ $00,$53,$AD,$FF,$00,$52,$A8,$FF,$02,$53,$AE,$FF,$00,$4E,$AB,$FF,$02,$54,$AA,$FF,
+ $00,$53,$AD,$FF,$00,$53,$B3,$FF,$00,$50,$A7,$FF,$00,$57,$AA,$FF,$00,$50,$AC,$FF,
+ $04,$54,$B5,$FF,$01,$52,$AE,$FF,$02,$54,$AA,$FF,$02,$53,$A5,$FF,$03,$50,$A8,$FF,
+ $05,$4F,$AE,$FF,$0B,$51,$B0,$FF,$09,$50,$A8,$FF,$00,$55,$AA,$FF,$00,$53,$AD,$FF,
+ $03,$54,$A6,$FF,$00,$58,$BD,$FF,$0D,$62,$A5,$FF,$1E,$62,$A3,$FF,$34,$5A,$5D,$FF,
+ $50,$63,$14,$FF,$79,$97,$01,$FF,$8D,$AF,$01,$FF,$90,$AE,$01,$FF,$8A,$AE,$06,$FF,
+ $8C,$A9,$00,$FF,$8B,$AC,$00,$FF,$9A,$BF,$00,$FF,$C9,$F2,$2C,$FF,$63,$96,$4B,$FF,
+ $03,$1A,$3C,$FF,$04,$37,$76,$FF,$00,$51,$AF,$FF,$03,$54,$AD,$FF,$00,$50,$AB,$FF,
+ $00,$52,$AE,$FF,$00,$56,$AB,$FF,$08,$65,$E6,$FF,$30,$68,$69,$FF,$53,$5A,$00,$FF,
+ $82,$A7,$00,$FF,$82,$AE,$01,$FF,$90,$AE,$00,$FF,$8D,$AE,$09,$FF,$87,$AA,$00,$FF,
+ $91,$B8,$03,$FF,$89,$B5,$08,$FF,$89,$D7,$12,$FF,$18,$4C,$71,$FF,$00,$3C,$73,$FF,
+ $02,$51,$B6,$FF,$00,$50,$A9,$FF,$05,$51,$B1,$FF,$04,$53,$B0,$FF,$01,$55,$AF,$FF,
+ $00,$53,$B0,$FF,$00,$53,$AD,$FF,$00,$53,$A9,$FF,$03,$50,$AC,$FF,$00,$58,$A3,$FF,
+ $00,$4F,$A8,$FF,$03,$4D,$A6,$FF,$04,$4F,$AA,$FF,$01,$54,$B4,$FF,$00,$53,$AF,$FF,
+ $00,$54,$AB,$FF,$05,$51,$AF,$FF,$02,$53,$AC,$FF,$01,$52,$AB,$FF,$00,$4E,$A3,$FF,
+ $03,$53,$A8,$FF,$01,$51,$A6,$FF,$00,$53,$AB,$FF,$00,$57,$B1,$FF,$00,$52,$B1,$FF,
+ $00,$51,$AF,$FF,$06,$50,$A9,$FF,$01,$52,$AD,$FF,$04,$4D,$B3,$FF,$06,$50,$BB,$FF,
+ $00,$70,$D3,$FF,$16,$81,$B7,$FF,$34,$68,$5C,$FF,$46,$69,$27,$FF,$7C,$9B,$02,$FF,
+ $88,$A9,$02,$FF,$8E,$AF,$08,$FF,$8C,$AD,$00,$FF,$89,$AB,$00,$FF,$8E,$AC,$00,$FF,
+ $8E,$AE,$03,$FF,$90,$B5,$03,$FF,$C1,$EA,$14,$FF,$8D,$B9,$2E,$FF,$00,$17,$2F,$FF,
+ $00,$28,$56,$FF,$00,$51,$AB,$FF,$04,$51,$A9,$FF,$07,$54,$AE,$FF,$00,$50,$AC,$FF,
+ $00,$55,$AC,$FF,$1A,$60,$A8,$FF,$47,$68,$31,$FF,$66,$7B,$00,$FF,$7E,$A7,$00,$FF,
+ $87,$AD,$00,$FF,$92,$AA,$00,$FF,$8E,$B0,$00,$FF,$8A,$B4,$00,$FF,$97,$AF,$01,$FF,
+ $89,$B1,$12,$FF,$A3,$D0,$04,$FF,$30,$84,$6C,$FF,$00,$32,$69,$FF,$00,$51,$A5,$FF,
+ $00,$57,$B0,$FF,$02,$4E,$AE,$FF,$00,$4F,$B0,$FF,$00,$51,$B1,$FF,$06,$53,$AF,$FF,
+ $05,$50,$A3,$FF,$00,$43,$8A,$FF,$04,$34,$7C,$FF,$04,$26,$4B,$FF,$05,$22,$40,$FF,
+ $01,$22,$41,$FF,$00,$34,$66,$FF,$00,$43,$8E,$FF,$04,$50,$A4,$FF,$01,$51,$A8,$FF,
+ $00,$52,$AC,$FF,$07,$4F,$B3,$FF,$00,$50,$A9,$FF,$02,$51,$9C,$FF,$00,$43,$88,$FF,
+ $00,$34,$7A,$FF,$01,$41,$88,$FF,$00,$42,$8D,$FF,$00,$4A,$98,$FF,$01,$54,$B4,$FF,
+ $03,$54,$AF,$FF,$05,$50,$AD,$FF,$02,$52,$A9,$FF,$00,$50,$B3,$FF,$00,$6A,$C3,$FF,
+ $0C,$7A,$D1,$FF,$35,$5F,$49,$FF,$3A,$52,$04,$FF,$7F,$9F,$00,$FF,$8A,$AC,$00,$FF,
+ $8D,$AD,$04,$FF,$8B,$AD,$00,$FF,$8C,$AC,$01,$FF,$8D,$AD,$04,$FF,$8B,$AA,$04,$FF,
+ $8F,$B4,$04,$FF,$B3,$DC,$00,$FF,$D7,$FF,$31,$FF,$12,$30,$2E,$FF,$00,$24,$3E,$FF,
+ $00,$52,$A3,$FF,$09,$55,$B3,$FF,$00,$4E,$A7,$FF,$00,$55,$B2,$FF,$0E,$61,$A7,$FF,
+ $3E,$66,$44,$FF,$64,$7D,$08,$FF,$80,$A2,$03,$FF,$89,$B1,$00,$FF,$92,$AA,$0A,$FF,
+ $90,$AE,$01,$FF,$8A,$A9,$05,$FF,$8C,$AD,$04,$FF,$93,$B5,$00,$FF,$90,$AC,$00,$FF,
+ $A4,$CD,$05,$FF,$6A,$AA,$38,$FF,$05,$31,$60,$FF,$01,$40,$8D,$FF,$00,$4A,$97,$FF,
+ $04,$48,$91,$FF,$05,$55,$AA,$FF,$00,$51,$A6,$FF,$01,$42,$82,$FF,$03,$40,$6D,$FF,
+ $0A,$45,$65,$FF,$2D,$52,$5B,$FF,$27,$4F,$51,$FF,$22,$3D,$38,$FF,$19,$2F,$3C,$FF,
+ $08,$2B,$4B,$FF,$00,$2C,$4B,$FF,$00,$2A,$4F,$FF,$01,$3B,$7B,$FF,$04,$52,$A5,$FF,
+ $00,$4F,$B2,$FF,$00,$53,$B4,$FF,$03,$51,$A4,$FF,$00,$32,$69,$FF,$00,$1B,$30,$FF,
+ $0C,$24,$28,$FF,$07,$22,$35,$FF,$01,$1D,$45,$FF,$00,$28,$5A,$FF,$00,$3B,$75,$FF,
+ $00,$43,$8C,$FF,$01,$52,$A4,$FF,$03,$53,$B2,$FF,$03,$57,$AD,$FF,$0D,$56,$9A,$FF,
+ $27,$36,$23,$FF,$3F,$4A,$06,$FF,$67,$7F,$03,$FF,$7F,$9E,$00,$FF,$84,$A3,$00,$FF,
+ $85,$A6,$00,$FF,$8D,$AE,$00,$FF,$8E,$AE,$01,$FF,$8C,$AE,$00,$FF,$86,$AB,$00,$FF,
+ $9C,$BF,$03,$FF,$CE,$FE,$08,$FF,$5E,$84,$5B,$FF,$05,$28,$48,$FF,$01,$49,$93,$FF,
+ $00,$50,$A2,$FF,$00,$54,$B4,$FF,$04,$6C,$C1,$FF,$2F,$71,$93,$FF,$6A,$79,$10,$FF,
+ $7F,$A4,$00,$FF,$8F,$AB,$01,$FF,$91,$AF,$01,$FF,$8B,$A8,$00,$FF,$87,$AE,$00,$FF,
+ $92,$AE,$01,$FF,$80,$A3,$00,$FF,$80,$A5,$00,$FF,$77,$9D,$00,$FF,$8F,$B4,$02,$FF,
+ $87,$A4,$16,$FF,$01,$21,$30,$FF,$00,$2D,$52,$FF,$00,$21,$3D,$FF,$02,$1C,$35,$FF,
+ $00,$30,$6E,$FF,$02,$3D,$83,$FF,$26,$4E,$5A,$FF,$47,$75,$47,$FF,$65,$9F,$39,$FF,
+ $9E,$CC,$23,$FF,$C0,$ED,$20,$FF,$B7,$E0,$00,$FF,$B4,$E5,$0D,$FF,$85,$C1,$2E,$FF,
+ $50,$7E,$4F,$FF,$08,$23,$34,$FF,$00,$27,$5C,$FF,$00,$4C,$9A,$FF,$00,$56,$B2,$FF,
+ $02,$61,$CB,$FF,$00,$52,$B3,$FF,$1D,$59,$7E,$FF,$4A,$71,$45,$FF,$5D,$83,$2E,$FF,
+ $62,$8B,$4F,$FF,$30,$5C,$4B,$FF,$0A,$29,$48,$FF,$14,$3B,$5C,$FF,$0A,$32,$4B,$FF,
+ $00,$29,$5B,$FF,$00,$31,$6C,$FF,$03,$3E,$84,$FF,$1B,$46,$4D,$FF,$1F,$26,$16,$FF,
+ $2C,$2E,$00,$FF,$27,$33,$05,$FF,$43,$51,$04,$FF,$43,$54,$06,$FF,$47,$59,$03,$FF,
+ $59,$6F,$02,$FF,$63,$79,$0A,$FF,$6A,$85,$00,$FF,$7D,$9C,$00,$FF,$89,$A4,$07,$FF,
+ $BD,$F1,$00,$FF,$60,$88,$54,$FF,$00,$25,$46,$FF,$05,$40,$84,$FF,$00,$53,$A8,$FF,
+ $00,$5A,$B4,$FF,$00,$77,$D5,$FF,$38,$74,$36,$FF,$45,$4C,$00,$FF,$6F,$85,$07,$FF,
+ $77,$A1,$00,$FF,$80,$A5,$00,$FF,$86,$A7,$00,$FF,$85,$A4,$00,$FF,$79,$9A,$01,$FF,
+ $6A,$7D,$07,$FF,$4F,$69,$08,$FF,$53,$69,$00,$FF,$5B,$74,$0C,$FF,$60,$88,$28,$FF,
+ $0D,$25,$27,$FF,$0B,$34,$50,$FF,$22,$4B,$47,$FF,$0F,$2B,$2F,$FF,$3B,$5A,$21,$FF,
+ $6D,$8F,$42,$FF,$97,$BC,$1E,$FF,$B2,$D7,$0D,$FF,$A9,$D9,$00,$FF,$A1,$CD,$00,$FF,
+ $A7,$CC,$00,$FF,$92,$C1,$00,$FF,$A4,$CE,$00,$FF,$C9,$F1,$05,$FF,$C1,$F0,$02,$FF,
+ $4A,$75,$25,$FF,$03,$24,$4D,$FF,$00,$4B,$9D,$FF,$03,$53,$AA,$FF,$00,$69,$E0,$FF,
+ $17,$65,$AD,$FF,$73,$9B,$16,$FF,$A6,$CC,$05,$FF,$C3,$EE,$0B,$FF,$CB,$FF,$00,$FF,
+ $CD,$FE,$02,$FF,$A9,$D6,$17,$FF,$87,$BF,$20,$FF,$66,$97,$56,$FF,$31,$83,$6D,$FF,
+ $31,$6D,$6E,$FF,$4B,$8D,$7F,$FF,$74,$99,$25,$FF,$53,$89,$2B,$FF,$1C,$3D,$20,$FF,
+ $16,$31,$3A,$FF,$16,$5E,$77,$FF,$36,$71,$6F,$FF,$42,$62,$31,$FF,$3E,$47,$1C,$FF,
+ $1E,$29,$09,$FF,$29,$30,$00,$FF,$4B,$58,$09,$FF,$60,$76,$00,$FF,$75,$8E,$0E,$FF,
+ $35,$4D,$19,$FF,$00,$22,$48,$FF,$04,$43,$93,$FF,$00,$4F,$AA,$FF,$01,$58,$B7,$FF,
+ $10,$8D,$F9,$FF,$34,$77,$A4,$FF,$33,$46,$19,$FF,$3B,$48,$03,$FF,$4C,$69,$00,$FF,
+ $59,$74,$00,$FF,$5B,$6E,$00,$FF,$64,$7E,$00,$FF,$54,$6B,$10,$FF,$41,$5A,$18,$FF,
+ $49,$69,$3A,$FF,$54,$8F,$63,$FF,$48,$96,$86,$FF,$2E,$92,$CD,$FF,$33,$76,$90,$FF,
+ $53,$83,$37,$FF,$99,$CA,$30,$FF,$A0,$D0,$24,$FF,$9F,$CF,$0B,$FF,$AA,$DC,$00,$FF,
+ $99,$C1,$00,$FF,$8F,$B0,$01,$FF,$8B,$B1,$00,$FF,$8B,$AE,$0C,$FF,$92,$A8,$00,$FF,
+ $8E,$AA,$00,$FF,$8D,$B2,$00,$FF,$91,$B4,$02,$FF,$7D,$AB,$0A,$FF,$1E,$3C,$1A,$FF,
+ $03,$28,$5C,$FF,$00,$53,$A5,$FF,$01,$50,$AD,$FF,$00,$74,$EF,$FF,$10,$64,$AA,$FF,
+ $3D,$4A,$2E,$FF,$5C,$6D,$03,$FF,$81,$A9,$00,$FF,$94,$B7,$01,$FF,$99,$BF,$00,$FF,
+ $A4,$C9,$00,$FF,$B7,$E0,$00,$FF,$C8,$EF,$02,$FF,$BB,$F2,$01,$FF,$BF,$F0,$00,$FF,
+ $C2,$FB,$00,$FF,$CF,$F6,$00,$FF,$A4,$DB,$35,$FF,$32,$7A,$86,$FF,$02,$46,$99,$FF,
+ $00,$70,$EB,$FF,$00,$7F,$FF,$FF,$15,$88,$FB,$FF,$42,$97,$CE,$FF,$4C,$8B,$78,$FF,
+ $35,$60,$2B,$FF,$43,$59,$10,$FF,$4C,$61,$26,$FF,$27,$47,$30,$FF,$03,$37,$4F,$FF,
+ $00,$45,$81,$FF,$00,$4F,$9E,$FF,$00,$58,$B1,$FF,$01,$64,$C2,$FF,$00,$72,$E5,$FF,
+ $09,$85,$FF,$FF,$1E,$77,$D1,$FF,$48,$73,$48,$FF,$4F,$5C,$16,$FF,$4C,$59,$24,$FF,
+ $42,$59,$25,$FF,$54,$73,$3A,$FF,$4C,$85,$5A,$FF,$1F,$73,$98,$FF,$0E,$6D,$CB,$FF,
+ $00,$75,$EF,$FF,$03,$77,$FE,$FF,$00,$7C,$F8,$FF,$4D,$AD,$A2,$FF,$70,$8D,$17,$FF,
+ $85,$A4,$09,$FF,$8C,$B4,$00,$FF,$8B,$B2,$01,$FF,$86,$A5,$01,$FF,$90,$AF,$00,$FF,
+ $8F,$AF,$06,$FF,$8F,$AC,$06,$FF,$8A,$AE,$00,$FF,$8C,$B0,$06,$FF,$93,$AB,$00,$FF,
+ $92,$B0,$02,$FF,$8B,$AB,$0C,$FF,$4A,$85,$55,$FF,$12,$4A,$6F,$FF,$0A,$47,$98,$FF,
+ $00,$54,$A9,$FF,$00,$53,$A9,$FF,$00,$71,$E3,$FF,$00,$6B,$BE,$FF,$25,$25,$0D,$FF,
+ $27,$35,$00,$FF,$71,$92,$00,$FF,$8B,$B0,$0A,$FF,$90,$AE,$00,$FF,$8B,$AB,$08,$FF,
+ $8F,$AB,$00,$FF,$96,$B4,$00,$FF,$98,$B6,$08,$FF,$9B,$BE,$02,$FF,$98,$BB,$00,$FF,
+ $AF,$D1,$08,$FF,$AA,$EA,$1A,$FF,$3A,$5F,$4D,$FF,$00,$30,$6C,$FF,$00,$58,$AA,$FF,
+ $00,$5C,$B0,$FF,$00,$69,$DF,$FF,$06,$83,$FF,$FF,$12,$90,$F7,$FF,$0A,$76,$D8,$FF,
+ $37,$98,$CF,$FF,$3D,$99,$D8,$FF,$1F,$72,$B4,$FF,$02,$4D,$90,$FF,$00,$44,$8F,$FF,
+ $00,$48,$9F,$FF,$00,$53,$AB,$FF,$00,$5B,$AE,$FF,$02,$56,$B6,$FF,$07,$6B,$CB,$FF,
+ $03,$76,$F3,$FF,$09,$86,$FC,$FF,$1C,$98,$BE,$FF,$20,$7A,$B9,$FF,$20,$79,$B1,$FF,
+ $0E,$78,$CE,$FF,$0A,$6B,$C9,$FF,$01,$65,$BD,$FF,$0F,$55,$B4,$FF,$03,$52,$B1,$FF,
+ $00,$54,$B3,$FF,$04,$76,$F0,$FF,$25,$89,$E1,$FF,$4D,$71,$33,$FF,$41,$4F,$00,$FF,
+ $6A,$86,$00,$FF,$82,$A5,$03,$FF,$91,$AC,$00,$FF,$8D,$A9,$00,$FF,$89,$AB,$00,$FF,
+ $91,$AE,$00,$FF,$8A,$AC,$00,$FF,$84,$B1,$00,$FF,$93,$B3,$00,$FF,$9E,$BE,$00,$FF,
+ $70,$8D,$16,$FF,$13,$55,$6D,$FF,$00,$56,$A2,$FF,$00,$4F,$B0,$FF,$03,$50,$AA,$FF,
+ $00,$52,$B6,$FF,$02,$69,$E0,$FF,$00,$7A,$F8,$FF,$32,$48,$31,$FF,$07,$15,$00,$FF,
+ $61,$79,$00,$FF,$87,$AB,$03,$FF,$8D,$A8,$03,$FF,$8E,$AF,$00,$FF,$8C,$A6,$04,$FF,
+ $8A,$AD,$00,$FF,$87,$AE,$05,$FF,$87,$AD,$08,$FF,$8C,$B3,$00,$FF,$9F,$C3,$00,$FF,
+ $84,$BE,$2C,$FF,$1C,$4B,$69,$FF,$00,$3C,$79,$FF,$00,$52,$9E,$FF,$04,$4E,$A3,$FF,
+ $00,$52,$B2,$FF,$00,$5C,$B7,$FF,$00,$67,$C2,$FF,$01,$73,$E5,$FF,$00,$73,$DD,$FF,
+ $00,$73,$EB,$FF,$07,$76,$EC,$FF,$04,$62,$C2,$FF,$00,$51,$A0,$FF,$05,$53,$A5,$FF,
+ $03,$52,$AF,$FF,$05,$50,$B5,$FF,$00,$55,$AC,$FF,$00,$51,$AE,$FF,$00,$59,$AE,$FF,
+ $06,$71,$D3,$FF,$00,$67,$DE,$FF,$00,$68,$E1,$FF,$08,$78,$DA,$FF,$00,$6C,$CB,$FF,
+ $03,$55,$B9,$FF,$00,$55,$B3,$FF,$00,$51,$A7,$FF,$02,$4C,$AF,$FF,$04,$52,$B7,$FF,
+ $00,$58,$B0,$FF,$00,$78,$EC,$FF,$20,$76,$B3,$FF,$26,$38,$28,$FF,$40,$55,$00,$FF,
+ $73,$94,$00,$FF,$91,$AA,$08,$FF,$90,$AA,$08,$FF,$8B,$AF,$07,$FF,$8F,$AD,$00,$FF,
+ $89,$AB,$00,$FF,$8B,$A8,$02,$FF,$9D,$C3,$00,$FF,$A0,$CA,$10,$FF,$33,$52,$42,$FF,
+ $00,$34,$63,$FF,$00,$50,$A0,$FF,$02,$4F,$A7,$FF,$06,$55,$B4,$FF,$01,$50,$AD,$FF,
+ $00,$63,$BE,$FF,$00,$81,$F9,$FF,$38,$78,$9C,$FF,$10,$15,$00,$FF,$51,$6D,$00,$FF,
+ $8C,$A8,$00,$FF,$8D,$AF,$00,$FF,$8A,$AD,$00,$FF,$8D,$AC,$06,$FF,$91,$AE,$00,$FF,
+ $89,$AD,$03,$FF,$8E,$A9,$04,$FF,$91,$B9,$00,$FF,$A2,$CB,$05,$FF,$4E,$82,$5C,$FF,
+ $13,$37,$5B,$FF,$00,$46,$8A,$FF,$00,$51,$AF,$FF,$04,$53,$AF,$FF,$03,$51,$A6,$FF,
+ $03,$4F,$A7,$FF,$04,$4D,$A9,$FF,$03,$53,$AA,$FF,$01,$54,$B2,$FF,$00,$53,$B3,$FF,
+ $00,$56,$B4,$FF,$00,$5B,$B7,$FF,$00,$56,$B8,$FF,$02,$4F,$B7,$FF,$02,$51,$B0,$FF,
+ $00,$53,$A3,$FF,$00,$57,$A5,$FF,$02,$51,$AD,$FF,$00,$54,$B6,$FF,$00,$4F,$A9,$FF,
+ $08,$55,$A7,$FF,$00,$4C,$AE,$FF,$00,$55,$B3,$FF,$00,$55,$A4,$FF,$04,$56,$AA,$FF,
+ $00,$50,$AA,$FF,$00,$56,$AC,$FF,$05,$58,$B6,$FF,$00,$53,$AC,$FF,$07,$52,$AD,$FF,
+ $00,$6F,$D5,$FF,$21,$89,$E2,$FF,$36,$68,$5F,$FF,$2F,$40,$14,$FF,$67,$85,$00,$FF,
+ $84,$9F,$02,$FF,$90,$AD,$00,$FF,$88,$B1,$00,$FF,$8C,$AA,$00,$FF,$8E,$AE,$0F,$FF,
+ $8D,$AD,$00,$FF,$A1,$CB,$07,$FF,$8D,$B9,$30,$FF,$10,$3A,$60,$FF,$05,$38,$79,$FF,
+ $05,$52,$AA,$FF,$08,$52,$AB,$FF,$00,$53,$B1,$FF,$05,$53,$B5,$FF,$00,$58,$AC,$FF,
+ $00,$7B,$FA,$FF,$28,$7C,$D2,$FF,$28,$32,$1A,$FF,$44,$5B,$03,$FF,$88,$A2,$01,$FF,
+ $87,$A9,$00,$FF,$8A,$AF,$00,$FF,$8B,$AD,$01,$FF,$8D,$A9,$00,$FF,$87,$AD,$00,$FF,
+ $8F,$AC,$00,$FF,$8E,$B7,$03,$FF,$A2,$CC,$20,$FF,$32,$6C,$60,$FF,$00,$2A,$5A,$FF,
+ $00,$4B,$92,$FF,$02,$53,$AF,$FF,$02,$50,$B2,$FF,$03,$52,$B9,$FF,$00,$52,$B3,$FF,
+ $00,$56,$AD,$FF,$00,$50,$A9,$FF,$00,$4E,$AA,$FF,$05,$52,$AC,$FF,$05,$52,$AC,$FF,
+ $05,$52,$AC,$FF,$05,$52,$AC,$FF,$04,$51,$A9,$FF,$01,$55,$AB,$FF,$00,$56,$A7,$FF,
+ $04,$50,$B0,$FF,$04,$4C,$B0,$FF,$08,$53,$AE,$FF,$02,$51,$AE,$FF,$00,$4F,$AB,$FF,
+ $03,$55,$AB,$FF,$00,$4E,$AF,$FF,$03,$4F,$AF,$FF,$01,$50,$AC,$FF,$00,$52,$AA,$FF,
+ $00,$53,$AD,$FF,$00,$4F,$A9,$FF,$00,$59,$A4,$FF,$01,$4C,$A9,$FF,$03,$6F,$CA,$FF,
+ $13,$7B,$DE,$FF,$31,$7E,$9C,$FF,$3C,$55,$11,$FF,$51,$6A,$05,$FF,$88,$A8,$05,$FF,
+ $8F,$AD,$00,$FF,$88,$AF,$00,$FF,$8B,$AB,$02,$FF,$8F,$AD,$00,$FF,$8B,$B5,$00,$FF,
+ $AB,$D8,$03,$FF,$79,$A6,$41,$FF,$09,$34,$47,$FF,$00,$37,$7D,$FF,$00,$4F,$B2,$FF,
+ $01,$54,$B0,$FF,$00,$51,$AC,$FF,$01,$51,$B4,$FF,$02,$52,$A9,$FF,$00,$75,$FB,$FF,
+ $2A,$7B,$CC,$FF,$35,$4C,$2F,$FF,$38,$49,$03,$FF,$7E,$9E,$00,$FF,$8C,$AC,$00,$FF,
+ $8E,$AB,$01,$FF,$91,$A9,$09,$FF,$8F,$AC,$02,$FF,$8A,$AC,$00,$FF,$8D,$AF,$03,$FF,
+ $A2,$CA,$07,$FF,$96,$BB,$37,$FF,$23,$54,$74,$FF,$00,$39,$82,$FF,$01,$4C,$9F,$FF,
+ $0A,$4C,$A3,$FF,$00,$53,$A4,$FF,$00,$54,$AE,$FF,$00,$51,$AA,$FF,$02,$53,$A5,$FF,
+ $00,$53,$A9,$FF,$06,$55,$B1,$FF,$00,$4E,$AE,$FF,$00,$52,$B2,$FF,$03,$52,$AE,$FF,
+ $00,$51,$A5,$FF,$00,$55,$A6,$FF,$00,$53,$AC,$FF,$04,$53,$B2,$FF,$02,$53,$AE,$FF,
+ $00,$52,$A7,$FF,$03,$52,$B7,$FF,$00,$52,$A8,$FF,$00,$55,$AE,$FF,$01,$54,$A4,$FF,
+ $03,$50,$AC,$FF,$00,$55,$B0,$FF,$01,$50,$B5,$FF,$00,$54,$A5,$FF,$07,$52,$AF,$FF,
+ $02,$4D,$B3,$FF,$04,$53,$B0,$FF,$04,$4E,$AD,$FF,$00,$5A,$B8,$FF,$06,$73,$D2,$FF,
+ $1E,$7C,$BA,$FF,$35,$4F,$22,$FF,$47,$5F,$00,$FF,$78,$9A,$00,$FF,$8F,$A8,$04,$FF,
+ $8A,$B1,$00,$FF,$8B,$AC,$00,$FF,$90,$AB,$04,$FF,$95,$B2,$02,$FF,$C1,$EE,$00,$FF,
+ $77,$A7,$44,$FF,$05,$21,$2D,$FF,$00,$35,$62,$FF,$02,$4F,$A9,$FF,$00,$57,$A7,$FF,
+ $05,$4E,$AA,$FF,$00,$4F,$AB,$FF,$00,$57,$A6,$FF,$00,$68,$E3,$FF,$34,$81,$D3,$FF,
+ $3A,$4C,$34,$FF,$32,$4C,$0B,$FF,$75,$91,$00,$FF,$8F,$AD,$00,$FF,$89,$B0,$00,$FF,
+ $8C,$A9,$00,$FF,$87,$AF,$00,$FF,$8F,$AB,$00,$FF,$87,$B2,$00,$FF,$AF,$D9,$09,$FF,
+ $6B,$95,$43,$FF,$06,$40,$65,$FF,$01,$49,$9B,$FF,$00,$53,$A7,$FF,$05,$4F,$AE,$FF,
+ $00,$59,$AF,$FF,$03,$4F,$A7,$FF,$05,$51,$AF,$FF,$01,$51,$B2,$FF,$02,$51,$B0,$FF,
+ $00,$53,$A8,$FF,$05,$51,$B1,$FF,$04,$4E,$AF,$FF,$01,$52,$AB,$FF,$00,$56,$AA,$FF,
+ $00,$52,$B0,$FF,$04,$50,$B2,$FF,$05,$50,$AD,$FF,$00,$51,$A9,$FF,$07,$53,$AB,$FF,
+ $00,$52,$A6,$FF,$00,$53,$B4,$FF,$01,$4F,$B1,$FF,$05,$53,$A8,$FF,$00,$54,$AF,$FF,
+ $00,$52,$B2,$FF,$00,$50,$B0,$FF,$03,$52,$AE,$FF,$04,$4F,$AC,$FF,$00,$54,$AE,$FF,
+ $00,$53,$AD,$FF,$02,$51,$B6,$FF,$00,$5A,$B7,$FF,$0C,$67,$AD,$FF,$13,$75,$D6,$FF,
+ $32,$58,$4B,$FF,$3C,$47,$03,$FF,$78,$9D,$00,$FF,$8B,$AC,$05,$FF,$8E,$AA,$00,$FF,
+ $8A,$AC,$00,$FF,$8E,$AF,$06,$FF,$93,$B4,$01,$FF,$B7,$DC,$00,$FF,$AC,$DB,$3D,$FF,
+ $20,$46,$39,$FF,$00,$25,$45,$FF,$04,$3E,$90,$FF,$01,$53,$A5,$FF,$03,$51,$B6,$FF,
+ $03,$50,$AC,$FF,$02,$57,$A8,$FF,$01,$68,$DF,$FF,$29,$87,$CF,$FF,$44,$63,$44,$FF,
+ $4F,$59,$12,$FF,$79,$9B,$00,$FF,$91,$AE,$04,$FF,$8B,$AC,$00,$FF,$8B,$AD,$00,$FF,
+ $88,$AF,$00,$FF,$90,$AD,$05,$FF,$99,$AF,$02,$FF,$AF,$E2,$0B,$FF,$2E,$5E,$46,$FF,
+ $00,$29,$5A,$FF,$00,$53,$A6,$FF,$02,$51,$BA,$FF,$00,$54,$AF,$FF,$00,$51,$AC,$FF,
+ $05,$51,$AF,$FF,$00,$53,$AB,$FF,$00,$54,$AC,$FF,$04,$50,$AE,$FF,$04,$4E,$AD,$FF,
+ $04,$51,$AB,$FF,$00,$4F,$AC,$FF,$00,$56,$AF,$FF,$02,$4F,$BB,$FF,$00,$59,$A9,$FF,
+ $06,$52,$AA,$FF,$04,$50,$B2,$FF,$00,$51,$AC,$FF,$00,$52,$AC,$FF,$03,$55,$A9,$FF,
+ $00,$53,$A3,$FF,$01,$51,$AA,$FF,$04,$50,$B0,$FF,$00,$53,$AA,$FF,$00,$51,$A3,$FF,
+ $00,$53,$AF,$FF,$00,$52,$A9,$FF,$04,$4D,$A9,$FF,$00,$50,$AC,$FF,$00,$54,$AE,$FF,
+ $02,$5C,$BC,$FF,$0A,$60,$B7,$FF,$0E,$59,$92,$FF,$00,$77,$D3,$FF,$2B,$64,$5E,$FF,
+ $29,$37,$02,$FF,$73,$93,$02,$FF,$8D,$AD,$02,$FF,$91,$AD,$01,$FF,$88,$AD,$00,$FF,
+ $8B,$AE,$00,$FF,$91,$AD,$01,$FF,$A3,$CC,$02,$FF,$D1,$FD,$20,$FF,$70,$99,$57,$FF,
+ $0B,$21,$1E,$FF,$00,$27,$48,$FF,$00,$31,$59,$FF,$04,$3F,$8F,$FF,$00,$48,$9F,$FF,
+ $00,$52,$A1,$FF,$04,$5B,$BC,$FF,$08,$6A,$C5,$FF,$43,$59,$44,$FF,$52,$76,$0A,$FF,
+ $86,$A3,$00,$FF,$85,$AB,$00,$FF,$8F,$AC,$02,$FF,$8F,$AD,$00,$FF,$8A,$A9,$03,$FF,
+ $89,$B1,$00,$FF,$95,$C0,$11,$FF,$91,$BA,$36,$FF,$20,$41,$50,$FF,$08,$33,$81,$FF,
+ $04,$56,$AC,$FF,$05,$4D,$A1,$FF,$04,$4F,$AA,$FF,$05,$55,$AA,$FF,$02,$4A,$9F,$FF,
+ $00,$46,$8B,$FF,$03,$4E,$92,$FF,$00,$42,$89,$FF,$00,$46,$8B,$FF,$00,$4E,$9D,$FF,
+ $01,$52,$AB,$FF,$0B,$52,$AE,$FF,$02,$52,$B1,$FF,$00,$4A,$A2,$FF,$01,$51,$A6,$FF,
+ $00,$54,$AA,$FF,$05,$55,$B4,$FF,$00,$51,$AE,$FF,$00,$50,$AE,$FF,$00,$50,$A9,$FF,
+ $07,$53,$AB,$FF,$01,$51,$AA,$FF,$00,$52,$AA,$FF,$0A,$45,$A1,$FF,$02,$37,$87,$FF,
+ $00,$37,$5C,$FF,$07,$39,$78,$FF,$04,$3C,$86,$FF,$03,$4E,$88,$FF,$02,$56,$B0,$FF,
+ $0D,$64,$C5,$FF,$0D,$4E,$8E,$FF,$01,$77,$D7,$FF,$31,$6B,$5D,$FF,$35,$48,$06,$FF,
+ $7D,$99,$08,$FF,$8D,$AE,$00,$FF,$8E,$AC,$00,$FF,$8D,$AF,$03,$FF,$8A,$AB,$00,$FF,
+ $87,$AD,$00,$FF,$93,$B4,$03,$FF,$B7,$E9,$0C,$FF,$DA,$FF,$2C,$FF,$6B,$91,$6C,$FF,
+ $1A,$2C,$3A,$FF,$00,$17,$26,$FF,$00,$10,$22,$FF,$00,$13,$2E,$FF,$00,$1C,$34,$FF,
+ $01,$26,$5A,$FF,$04,$34,$64,$FF,$45,$52,$26,$FF,$71,$92,$00,$FF,$94,$B2,$02,$FF,
+ $88,$AF,$00,$FF,$8C,$A9,$03,$FF,$86,$AD,$00,$FF,$90,$B4,$00,$FF,$91,$B4,$00,$FF,
+ $AB,$D4,$14,$FF,$7B,$94,$5D,$FF,$08,$27,$44,$FF,$00,$39,$78,$FF,$03,$52,$B1,$FF,
+ $00,$50,$AC,$FF,$04,$55,$AE,$FF,$00,$41,$7C,$FF,$00,$25,$40,$FF,$05,$1F,$52,$FF,
+ $04,$20,$45,$FF,$00,$19,$30,$FF,$00,$0C,$13,$FF,$00,$1D,$44,$FF,$00,$50,$84,$FF,
+ $00,$4C,$AE,$FF,$00,$53,$A3,$FF,$00,$59,$AD,$FF,$00,$57,$B7,$FF,$03,$4F,$AD,$FF,
+ $00,$4F,$A2,$FF,$08,$54,$B6,$FF,$00,$55,$B2,$FF,$00,$52,$A8,$FF,$05,$52,$AA,$FF,
+ $00,$50,$AB,$FF,$00,$47,$8C,$FF,$01,$2C,$3F,$FF,$00,$10,$1A,$FF,$04,$09,$0D,$FF,
+ $00,$03,$14,$FF,$00,$0E,$1D,$FF,$00,$1A,$36,$FF,$00,$42,$8D,$FF,$05,$6C,$C8,$FF,
+ $08,$53,$97,$FF,$0B,$4D,$9B,$FF,$3D,$64,$2F,$FF,$62,$75,$02,$FF,$85,$A4,$01,$FF,
+ $8B,$AD,$00,$FF,$89,$A9,$00,$FF,$8D,$AD,$02,$FF,$90,$AC,$00,$FF,$94,$AB,$03,$FF,
+ $88,$B1,$00,$FF,$97,$B3,$00,$FF,$BA,$E8,$00,$FF,$DA,$FE,$2A,$FF,$B1,$D9,$52,$FF,
+ $78,$91,$58,$FF,$2F,$5B,$44,$FF,$24,$3F,$38,$FF,$18,$36,$38,$FF,$21,$49,$4B,$FF,
+ $4E,$6F,$40,$FF,$74,$A0,$05,$FF,$8A,$A5,$00,$FF,$8C,$A8,$00,$FF,$8F,$A9,$0A,$FF,
+ $8B,$AC,$03,$FF,$8C,$AD,$06,$FF,$8D,$A7,$00,$FF,$9C,$BA,$00,$FF,$B2,$E9,$1E,$FF,
+ $6A,$9C,$5D,$FF,$00,$29,$28,$FF,$05,$25,$5E,$FF,$00,$42,$88,$FF,$00,$4C,$97,$FF,
+ $00,$36,$81,$FF,$21,$45,$55,$FF,$32,$4A,$3A,$FF,$3C,$64,$49,$FF,$40,$6E,$54,$FF,
+ $4D,$73,$4C,$FF,$06,$07,$0B,$FF,$00,$01,$02,$FF,$05,$21,$49,$FF,$00,$47,$93,$FF,
+ $04,$54,$A9,$FF,$05,$4F,$A6,$FF,$00,$4F,$AE,$FF,$00,$51,$AF,$FF,$00,$52,$AA,$FF,
+ $07,$51,$AA,$FF,$00,$51,$A8,$FF,$00,$51,$A7,$FF,$00,$58,$B9,$FF,$01,$5C,$AD,$FF,
+ $14,$40,$67,$FF,$1C,$2F,$3D,$FF,$39,$5A,$2D,$FF,$5D,$85,$49,$FF,$49,$76,$4B,$FF,
+ $2B,$4A,$4C,$FF,$00,$07,$0E,$FF,$00,$23,$3D,$FF,$05,$57,$A0,$FF,$0A,$59,$92,$FF,
+ $23,$41,$39,$FF,$5C,$77,$04,$FF,$86,$9F,$03,$FF,$88,$AB,$00,$FF,$8E,$AF,$00,$FF,
+ $8D,$AA,$00,$FF,$8A,$AA,$01,$FF,$8E,$AE,$01,$FF,$8A,$AB,$06,$FF,$89,$AF,$00,$FF,
+ $8C,$AE,$02,$FF,$96,$B4,$06,$FF,$A4,$DC,$00,$FF,$D0,$FF,$07,$FF,$D2,$FC,$16,$FF,
+ $DC,$FE,$35,$FF,$DA,$FB,$38,$FF,$D0,$FF,$21,$FF,$B9,$E1,$1E,$FF,$9B,$C6,$14,$FF,
+ $8E,$B5,$00,$FF,$88,$AD,$07,$FF,$8E,$AD,$00,$FF,$8B,$AF,$03,$FF,$89,$AD,$03,$FF,
+ $8F,$AB,$01,$FF,$91,$AE,$00,$FF,$9A,$BC,$03,$FF,$BA,$F0,$16,$FF,$A8,$E8,$4B,$FF,
+ $1F,$46,$57,$FF,$04,$1C,$38,$FF,$00,$1D,$45,$FF,$06,$3B,$7F,$FF,$2D,$70,$76,$FF,
+ $69,$9F,$41,$FF,$B6,$E3,$28,$FF,$C2,$EF,$22,$FF,$CC,$FB,$23,$FF,$D5,$FF,$19,$FF,
+ $CB,$E6,$39,$FF,$2B,$45,$2C,$FF,$00,$01,$00,$FF,$07,$1D,$44,$FF,$00,$47,$92,$FF,
+ $02,$51,$B6,$FF,$01,$55,$AB,$FF,$03,$52,$B1,$FF,$02,$52,$AB,$FF,$00,$4F,$AC,$FF,
+ $00,$53,$B1,$FF,$01,$56,$A7,$FF,$00,$61,$CC,$FF,$1B,$64,$A9,$FF,$41,$58,$20,$FF,
+ $5F,$7E,$07,$FF,$8D,$B3,$00,$FF,$BD,$EF,$02,$FF,$D0,$FD,$0C,$FF,$D0,$FF,$1C,$FF,
+ $88,$BD,$2D,$FF,$18,$49,$74,$FF,$02,$44,$98,$FF,$4A,$9C,$6B,$FF,$6C,$8C,$11,$FF,
+ $80,$A3,$00,$FF,$8B,$AF,$05,$FF,$8D,$B0,$00,$FF,$8E,$AD,$00,$FF,$90,$AB,$04,$FF,
+ $8C,$AC,$01,$FF,$87,$AE,$00,$FF,$90,$AC,$00,$FF,$8B,$AD,$00,$FF,$8A,$AC,$00,$FF,
+ $91,$AA,$06,$FF,$8D,$A7,$00,$FF,$97,$B4,$00,$FF,$9B,$BD,$04,$FF,$A1,$CF,$0D,$FF,
+ $A9,$CE,$02,$FF,$A4,$D0,$01,$FF,$96,$B3,$03,$FF,$89,$B1,$00,$FF,$8D,$AB,$00,$FF,
+ $89,$AF,$02,$FF,$90,$AB,$06,$FF,$89,$AB,$00,$FF,$8C,$B1,$01,$FF,$8F,$AB,$00,$FF,
+ $8A,$AC,$00,$FF,$90,$BA,$01,$FF,$AD,$D0,$02,$FF,$D5,$FF,$11,$FF,$B2,$E6,$46,$FF,
+ $6C,$99,$5E,$FF,$57,$73,$4B,$FF,$70,$96,$41,$FF,$A8,$CE,$2B,$FF,$A9,$CA,$00,$FF,
+ $9C,$B9,$00,$FF,$9E,$BB,$00,$FF,$99,$B8,$00,$FF,$B6,$DD,$06,$FF,$D4,$FD,$01,$FF,
+ $C2,$E6,$3C,$FF,$07,$22,$35,$FF,$06,$0F,$36,$FF,$00,$44,$8A,$FF,$00,$52,$A8,$FF,
+ $05,$50,$AB,$FF,$00,$53,$B0,$FF,$02,$53,$AE,$FF,$01,$51,$B2,$FF,$00,$4E,$B0,$FF,
+ $00,$5A,$BB,$FF,$19,$79,$CF,$FF,$49,$76,$7B,$FF,$5A,$6C,$00,$FF,$70,$93,$00,$FF,
+ $8E,$B3,$03,$FF,$8A,$B4,$00,$FF,$A1,$B9,$09,$FF,$B9,$DE,$00,$FF,$C4,$F4,$00,$FF,
+ $B3,$DE,$13,$FF,$A7,$D3,$0A,$FF,$AD,$D4,$00,$FF,$9B,$BE,$0A,$FF,$8B,$B2,$00,$FF,
+ $87,$AB,$01,$FF,$8E,$AE,$01,$FF,$8A,$A8,$00,$FF,$8D,$AD,$04,$FF,$8E,$B0,$01,$FF,
+ $89,$AE,$00,$FF,$8A,$AE,$02,$FF,$8A,$AA,$00,$FF,$91,$AE,$08,$FF,$8A,$AF,$00,$FF,
+ $8F,$AC,$06,$FF,$8B,$AB,$00,$FF,$8E,$A8,$00,$FF,$97,$A8,$02,$FF,$87,$AC,$00,$FF,
+ $8E,$AB,$05,$FF,$89,$A9,$00,$FF,$92,$AB,$0F,$FF,$8F,$AD,$00,$FF,$8A,$A6,$00,$FF,
+ $8D,$AA,$02,$FF,$94,$AF,$02,$FF,$8B,$A8,$00,$FF,$92,$AB,$09,$FF,$8E,$AC,$00,$FF,
+ $82,$AA,$00,$FF,$90,$BB,$00,$FF,$A3,$CD,$00,$FF,$CB,$F8,$05,$FF,$D1,$FF,$14,$FF,
+ $BE,$EA,$11,$FF,$A0,$CB,$09,$FF,$8F,$B5,$00,$FF,$8F,$AD,$00,$FF,$8E,$AF,$00,$FF,
+ $93,$AF,$03,$FF,$8F,$AD,$00,$FF,$86,$B6,$00,$FF,$B1,$E2,$00,$FF,$CC,$FF,$04,$FF,
+ $41,$87,$51,$FF,$00,$07,$11,$FF,$02,$30,$61,$FF,$00,$54,$AA,$FF,$04,$4E,$AD,$FF,
+ $02,$52,$A7,$FF,$00,$54,$A4,$FF,$04,$52,$B4,$FF,$01,$51,$A6,$FF,$00,$73,$CC,$FF,
+ $33,$8A,$B7,$FF,$4A,$61,$2B,$FF,$51,$69,$00,$FF,$82,$A7,$02,$FF,$8B,$B2,$00,$FF,
+ $8C,$AF,$0A,$FF,$8B,$AD,$00,$FF,$8B,$B3,$03,$FF,$93,$B7,$00,$FF,$AB,$CD,$00,$FF,
+ $93,$BD,$00,$FF,$94,$B5,$02,$FF,$92,$AB,$00,$FF,$89,$AA,$00,$FF,$8E,$AE,$01,$FF,
+ $8E,$AB,$01,$FF,$8B,$AD,$01,$FF,$8C,$B0,$06,$FF,$89,$AA,$00,$FF,$8F,$AA,$03,$FF,
+ $8C,$AB,$05,$FF,$91,$AC,$00,$FF,$89,$AB,$00,$FF,$89,$AE,$00,$FF,$8E,$AB,$01,$FF,
+ $8C,$AD,$00,$FF,$88,$B3,$02,$FF,$88,$AD,$00,$FF,$89,$AF,$00,$FF,$8E,$AD,$00,$FF,
+ $8C,$AE,$02,$FF,$8A,$AA,$00,$FF,$8D,$AE,$00,$FF,$8D,$AF,$00,$FF,$8A,$B1,$06,$FF,
+ $88,$AA,$00,$FF,$92,$AD,$00,$FF,$87,$AD,$00,$FF,$8D,$AF,$00,$FF,$95,$AB,$0A,$FF,
+ $8C,$AB,$00,$FF,$8B,$AA,$06,$FF,$94,$B1,$00,$FF,$9D,$C1,$00,$FF,$93,$B4,$01,$FF,
+ $8C,$B7,$00,$FF,$8D,$AE,$05,$FF,$8F,$AB,$01,$FF,$86,$AD,$00,$FF,$87,$AD,$02,$FF,
+ $8D,$AA,$00,$FF,$8E,$AF,$00,$FF,$92,$B3,$00,$FF,$D0,$FE,$05,$FF,$7F,$A1,$40,$FF,
+ $04,$09,$0F,$FF,$00,$33,$60,$FF,$02,$56,$B8,$FF,$00,$50,$A9,$FF,$04,$58,$BA,$FF,
+ $00,$52,$AE,$FF,$03,$53,$AC,$FF,$03,$51,$B5,$FF,$01,$77,$F5,$FF,$40,$99,$BB,$FF,
+ $33,$3E,$1E,$FF,$41,$55,$00,$FF,$7C,$9B,$02,$FF,$8C,$AF,$00,$FF,$91,$AB,$02,$FF,
+ $86,$AC,$00,$FF,$95,$AA,$03,$FF,$82,$AF,$00,$FF,$8D,$AE,$00,$FF,$8A,$AB,$00,$FF,
+ $8C,$AC,$00,$FF,$8E,$AB,$03,$FF,$89,$B1,$01,$FF,$8E,$A9,$00,$FF,$8E,$AF,$06,$FF,
+ $8B,$AC,$00,$FF,$93,$AA,$04,$FF,$84,$AF,$00,$FF,$8D,$AA,$04,$FF,$8D,$AE,$00,$FF,
+ $8D,$AE,$00,$FF,$8D,$A8,$01,$FF,$8E,$A8,$06,$FF,$8A,$B0,$03,$FF,$92,$A9,$01,$FF,
+ $84,$B0,$00,$FF,$8A,$AC,$00,$FF,$8B,$AA,$04,$FF,$8B,$B1,$06,$FF,$86,$AC,$01,$FF,
+ $8E,$AD,$00,$FF,$8F,$AA,$03,$FF,$86,$AA,$02,$FF,$8C,$AF,$00,$FF,$92,$AA,$00,$FF,
+ $87,$AD,$00,$FF,$8F,$AB,$01,$FF,$92,$AD,$00,$FF,$89,$AE,$00,$FF,$87,$AC,$06,$FF,
+ $94,$A7,$00,$FF,$8D,$A6,$00,$FF,$72,$91,$07,$FF,$5C,$74,$00,$FF,$5D,$6F,$03,$FF,
+ $70,$96,$05,$FF,$89,$B1,$00,$FF,$8E,$AB,$03,$FF,$8F,$AC,$04,$FF,$8D,$A8,$00,$FF,
+ $88,$AF,$00,$FF,$8F,$B3,$00,$FF,$BC,$F0,$07,$FF,$7F,$99,$36,$FF,$00,$10,$1F,$FF,
+ $00,$32,$5F,$FF,$07,$53,$B5,$FF,$00,$51,$AB,$FF,$00,$57,$B8,$FF,$00,$50,$A5,$FF,
+ $00,$53,$AE,$FF,$00,$50,$A5,$FF,$02,$7C,$FB,$FF,$3C,$95,$B3,$FF,$2C,$31,$00,$FF,
+ $40,$54,$00,$FF,$74,$90,$07,$FF,$8A,$AA,$00,$FF,$8F,$A8,$04,$FF,$8E,$AA,$00,$FF,
+ $89,$AF,$00,$FF,$8C,$AD,$04,$FF,$90,$A6,$00,$FF,$8A,$B3,$0C,$FF,$8D,$AB,$00,$FF,
+ $90,$AC,$02,$FF,$84,$AB,$00,$FF,$91,$B0,$00,$FF,$8D,$AC,$00,$FF,$87,$A9,$00,$FF,
+ $8C,$AE,$02,$FF,$8D,$AE,$07,$FF,$8F,$AC,$00,$FF,$8E,$AC,$00,$FF,$8B,$AA,$04,$FF,
+ $8E,$AD,$00,$FF,$8F,$AC,$02,$FF,$86,$B0,$00,$FF,$90,$A7,$01,$FF,$8C,$B1,$01,$FF,
+ $91,$AC,$00,$FF,$8E,$AC,$00,$FF,$8F,$A6,$00,$FF,$91,$AE,$00,$FF,$8B,$AD,$00,$FF,
+ $8A,$AC,$00,$FF,$8C,$AE,$00,$FF,$89,$AD,$03,$FF,$8D,$AB,$00,$FF,$8C,$AD,$00,$FF,
+ $8D,$A9,$00,$FF,$8F,$A9,$00,$FF,$8D,$AD,$02,$FF,$86,$B2,$00,$FF,$7D,$A7,$00,$FF,
+ $59,$72,$17,$FF,$34,$3F,$15,$FF,$14,$17,$02,$FF,$00,$02,$07,$FF,$2B,$30,$00,$FF,
+ $6A,$7D,$00,$FF,$84,$A8,$00,$FF,$8A,$B3,$01,$FF,$8C,$AE,$02,$FF,$91,$AC,$05,$FF,
+ $92,$B6,$00,$FF,$B2,$E3,$15,$FF,$47,$5F,$47,$FF,$02,$22,$39,$FF,$02,$40,$89,$FF,
+ $00,$50,$A1,$FF,$02,$56,$B0,$FF,$03,$53,$AA,$FF,$07,$51,$B0,$FF,$01,$52,$AD,$FF,
+ $03,$51,$A6,$FF,$00,$7B,$FF,$FF,$2A,$92,$C7,$FF,$22,$2A,$13,$FF,$1D,$29,$00,$FF,
+ $6E,$86,$00,$FF,$8B,$B3,$03,$FF,$87,$AD,$00,$FF,$8D,$AE,$00,$FF,$8F,$AB,$01,$FF,
+ $8D,$AA,$00,$FF,$8B,$B1,$02,$FF,$81,$A2,$00,$FF,$7A,$9B,$06,$FF,$78,$92,$00,$FF,
+ $6F,$85,$00,$FF,$72,$8F,$01,$FF,$82,$A4,$00,$FF,$91,$AD,$0B,$FF,$91,$AD,$00,$FF,
+ $8F,$AC,$00,$FF,$88,$AB,$00,$FF,$88,$AC,$02,$FF,$8E,$B1,$00,$FF,$8D,$AA,$00,$FF,
+ $92,$AD,$00,$FF,$8E,$AF,$00,$FF,$87,$A0,$07,$FF,$76,$9D,$00,$FF,$7C,$9B,$02,$FF,
+ $75,$A3,$00,$FF,$83,$A2,$00,$FF,$90,$AC,$00,$FF,$8C,$AA,$0A,$FF,$8B,$AE,$00,$FF,
+ $8A,$B0,$05,$FF,$89,$AB,$00,$FF,$93,$A7,$07,$FF,$91,$AC,$05,$FF,$8E,$B0,$00,$FF,
+ $8A,$AD,$09,$FF,$88,$A7,$01,$FF,$93,$B6,$00,$FF,$6F,$9A,$2F,$FF,$3B,$72,$52,$FF,
+ $1D,$60,$7A,$FF,$22,$61,$8A,$FF,$1D,$43,$56,$FF,$0C,$1B,$00,$FF,$28,$37,$0C,$FF,
+ $47,$58,$00,$FF,$6E,$83,$00,$FF,$75,$9C,$01,$FF,$79,$96,$00,$FF,$8B,$AA,$06,$FF,
+ $80,$A8,$13,$FF,$18,$34,$37,$FF,$01,$2C,$4F,$FF,$03,$48,$93,$FF,$00,$55,$A7,$FF,
+ $00,$52,$AE,$FF,$02,$50,$A5,$FF,$02,$50,$B2,$FF,$00,$52,$A6,$FF,$01,$56,$A9,$FF,
+ $00,$7A,$ED,$FF,$31,$93,$EE,$FF,$43,$56,$38,$FF,$0C,$0F,$04,$FF,$3E,$4F,$01,$FF,
+ $7F,$96,$00,$FF,$81,$A5,$00,$FF,$88,$B1,$00,$FF,$95,$A7,$07,$FF,$90,$AC,$00,$FF,
+ $7B,$9C,$07,$FF,$65,$77,$07,$FF,$63,$7D,$10,$FF,$35,$5D,$21,$FF,$43,$55,$17,$FF,
+ $44,$4F,$0A,$FF,$67,$84,$04,$FF,$8F,$AD,$00,$FF,$8B,$A6,$00,$FF,$8A,$AA,$00,$FF,
+ $8F,$B2,$00,$FF,$8D,$A9,$00,$FF,$8E,$AE,$03,$FF,$89,$AA,$01,$FF,$89,$AC,$00,$FF,
+ $73,$95,$0D,$FF,$52,$6C,$07,$FF,$28,$34,$0E,$FF,$23,$22,$03,$FF,$26,$25,$07,$FF,
+ $42,$54,$00,$FF,$5D,$78,$03,$FF,$7D,$9D,$00,$FF,$8F,$AB,$08,$FF,$91,$A9,$00,$FF,
+ $91,$AD,$01,$FF,$88,$AD,$05,$FF,$89,$AC,$00,$FF,$8A,$AC,$00,$FF,$89,$AF,$04,$FF,
+ $8D,$B2,$00,$FF,$AD,$D0,$00,$FF,$58,$7E,$4D,$FF,$19,$5C,$86,$FF,$00,$6A,$DF,$FF,
+ $00,$88,$FD,$FF,$0E,$8B,$F7,$FF,$32,$77,$A0,$FF,$20,$39,$1C,$FF,$00,$01,$0E,$FF,
+ $0E,$17,$02,$FF,$3A,$49,$12,$FF,$46,$55,$02,$FF,$50,$5C,$14,$FF,$30,$48,$28,$FF,
+ $11,$38,$59,$FF,$08,$40,$8A,$FF,$01,$4E,$9E,$FF,$02,$57,$B1,$FF,$00,$51,$AF,$FF,
+ $03,$53,$AA,$FF,$00,$53,$A8,$FF,$01,$50,$AC,$FF,$00,$51,$9F,$FF,$04,$70,$D5,$FF,
+ $28,$92,$FF,$FF,$4B,$90,$C9,$FF,$2D,$52,$27,$FF,$24,$2B,$00,$FF,$3C,$4B,$08,$FF,
+ $54,$67,$0B,$FF,$56,$74,$02,$FF,$5A,$72,$04,$FF,$65,$86,$04,$FF,$37,$56,$06,$FF,
+ $19,$59,$7C,$FF,$32,$7C,$85,$FF,$16,$59,$90,$FF,$20,$56,$78,$FF,$26,$33,$17,$FF,
+ $44,$52,$00,$FF,$80,$A7,$00,$FF,$8D,$AE,$07,$FF,$89,$AC,$08,$FF,$8F,$AA,$00,$FF,
+ $8D,$AE,$00,$FF,$89,$AA,$03,$FF,$86,$A6,$05,$FF,$77,$95,$03,$FF,$53,$6F,$18,$FF,
+ $45,$6C,$35,$FF,$2B,$47,$4B,$FF,$20,$3A,$1D,$FF,$10,$13,$00,$FF,$01,$12,$02,$FF,
+ $15,$1B,$01,$FF,$4F,$55,$00,$FF,$7C,$9B,$02,$FF,$8A,$AF,$00,$FF,$8C,$AA,$00,$FF,
+ $87,$B0,$00,$FF,$8C,$AF,$0A,$FF,$8E,$AA,$00,$FF,$8D,$AB,$00,$FF,$9A,$C1,$04,$FF,
+ $A6,$CC,$27,$FF,$26,$4F,$7B,$FF,$04,$3C,$77,$FF,$00,$56,$B0,$FF,$00,$6D,$D2,$FF,
+ $00,$6F,$EC,$FF,$0A,$84,$FF,$FF,$3A,$96,$D7,$FF,$49,$73,$4B,$FF,$18,$22,$0A,$FF,
+ $0E,$0F,$00,$FF,$1B,$1C,$0C,$FF,$19,$2F,$3A,$FF,$01,$26,$52,$FF,$03,$41,$8A,$FF,
+ $00,$51,$AD,$FF,$00,$52,$AD,$FF,$00,$51,$A3,$FF,$01,$52,$AE,$FF,$00,$50,$AE,$FF,
+ $00,$53,$B3,$FF,$01,$53,$A7,$FF,$00,$55,$A8,$FF,$02,$59,$C2,$FF,$00,$6F,$F1,$FF,
+ $11,$93,$F3,$FF,$38,$93,$E6,$FF,$47,$89,$87,$FF,$3D,$61,$31,$FF,$4E,$5B,$16,$FF,
+ $3E,$52,$0B,$FF,$49,$63,$22,$FF,$54,$90,$76,$FF,$2E,$6F,$69,$FF,$05,$61,$C4,$FF,
+ $0A,$7B,$D7,$FF,$0F,$64,$C1,$FF,$14,$79,$D3,$FF,$30,$5D,$48,$FF,$39,$45,$05,$FF,
+ $70,$96,$05,$FF,$8B,$AB,$00,$FF,$8D,$AD,$00,$FF,$8B,$AB,$00,$FF,$8D,$AD,$04,$FF,
+ $91,$B8,$00,$FF,$83,$A7,$11,$FF,$3F,$60,$35,$FF,$10,$45,$67,$FF,$11,$74,$CF,$FF,
+ $0C,$7F,$FF,$FF,$06,$87,$FC,$FF,$2A,$8C,$E3,$FF,$47,$93,$91,$FF,$2E,$4C,$26,$FF,
+ $18,$1C,$0D,$FF,$43,$61,$00,$FF,$7E,$A0,$03,$FF,$91,$A8,$02,$FF,$89,$AC,$00,$FF,
+ $8D,$AA,$02,$FF,$8C,$AC,$00,$FF,$8E,$AE,$03,$FF,$AC,$D7,$01,$FF,$9B,$C7,$2C,$FF,
+ $06,$42,$88,$FF,$01,$3E,$7F,$FF,$08,$50,$B4,$FF,$01,$51,$B4,$FF,$07,$5A,$C0,$FF,
+ $02,$6F,$EE,$FF,$05,$87,$FF,$FF,$0C,$8C,$FA,$FF,$49,$A8,$DE,$FF,$4C,$8D,$91,$FF,
+ $24,$73,$84,$FF,$10,$59,$9D,$FF,$02,$4D,$90,$FF,$00,$50,$A0,$FF,$00,$56,$A9,$FF,
+ $06,$53,$AF,$FF,$07,$50,$AE,$FF,$02,$58,$AF,$FF,$00,$59,$BB,$FF,$03,$53,$B2,$FF,
+ $00,$50,$AA,$FF,$00,$51,$A6,$FF,$04,$52,$A7,$FF,$00,$5C,$BB,$FF,$00,$68,$C4,$FF,
+ $02,$71,$F6,$FF,$03,$7D,$FF,$FF,$08,$85,$FD,$FF,$0B,$72,$CE,$FF,$02,$64,$BD,$FF,
+ $0A,$65,$B8,$FF,$02,$72,$FA,$FF,$00,$6C,$D9,$FF,$00,$56,$BA,$FF,$0B,$66,$C3,$FF,
+ $09,$61,$B8,$FF,$18,$7A,$B9,$FF,$3B,$6D,$52,$FF,$4C,$5C,$1B,$FF,$77,$9A,$00,$FF,
+ $90,$AD,$00,$FF,$90,$AC,$02,$FF,$85,$AE,$00,$FF,$8F,$A8,$02,$FF,$A8,$D2,$02,$FF,
+ $98,$C6,$32,$FF,$27,$4B,$57,$FF,$00,$34,$77,$FF,$00,$6A,$C7,$FF,$00,$6E,$E4,$FF,
+ $01,$76,$E0,$FF,$04,$7A,$F5,$FF,$00,$85,$FE,$FF,$28,$93,$F3,$FF,$2A,$54,$60,$FF,
+ $29,$2E,$00,$FF,$58,$70,$00,$FF,$7E,$A5,$00,$FF,$98,$AE,$01,$FF,$93,$AE,$07,$FF,
+ $8C,$AD,$06,$FF,$86,$AC,$00,$FF,$A7,$D4,$00,$FF,$9C,$C2,$1F,$FF,$01,$46,$67,$FF,
+ $00,$42,$83,$FF,$00,$56,$AF,$FF,$02,$50,$B2,$FF,$06,$54,$9F,$FF,$00,$58,$AF,$FF,
+ $00,$67,$C6,$FF,$03,$74,$EC,$FF,$02,$7F,$FF,$FF,$00,$80,$F8,$FF,$00,$76,$F1,$FF,
+ $00,$62,$D1,$FF,$00,$57,$B6,$FF,$00,$55,$AF,$FF,$00,$53,$AD,$FF,$04,$4D,$A9,$FF,
+ $05,$4C,$B4,$FF,$00,$52,$A9,$FF,$00,$5C,$B6,$FF,$00,$4F,$AE,$FF,$09,$54,$A5,$FF,
+ $05,$45,$9F,$FF,$00,$52,$A6,$FF,$00,$59,$A6,$FF,$01,$50,$AF,$FF,$09,$53,$AC,$FF,
+ $00,$58,$B0,$FF,$00,$6E,$CF,$FF,$00,$6A,$CF,$FF,$04,$64,$CA,$FF,$02,$58,$AF,$FF,
+ $03,$4F,$B1,$FF,$00,$52,$B9,$FF,$00,$5E,$B2,$FF,$0B,$57,$AB,$FF,$01,$5E,$AC,$FF,
+ $32,$66,$8B,$FF,$50,$66,$37,$FF,$70,$87,$15,$FF,$82,$AA,$00,$FF,$88,$AD,$00,$FF,
+ $8D,$AB,$00,$FF,$8D,$AC,$08,$FF,$8F,$AD,$00,$FF,$AE,$DD,$01,$FF,$AA,$D2,$60,$FF,
+ $25,$49,$49,$FF,$00,$2A,$54,$FF,$00,$54,$A8,$FF,$03,$53,$B6,$FF,$00,$4F,$AC,$FF,
+ $04,$53,$BC,$FF,$00,$69,$CB,$FF,$03,$85,$FF,$FF,$34,$90,$F7,$FF,$29,$49,$22,$FF,
+ $2B,$2D,$08,$FF,$7A,$9E,$00,$FF,$87,$AB,$03,$FF,$85,$AA,$00,$FF,$8F,$B0,$00,$FF,
+ $8C,$AF,$00,$FF,$A4,$CE,$08,$FF,$A9,$C9,$28,$FF,$0B,$3E,$69,$FF,$05,$38,$77,$FF,
+ $00,$51,$A9,$FF,$00,$53,$AD,$FF,$00,$55,$AE,$FF,$06,$50,$B1,$FF,$02,$51,$B0,$FF,
+ $00,$59,$B3,$FF,$02,$69,$D0,$FF,$00,$6E,$D4,$FF,$01,$61,$C5,$FF,$00,$5E,$B0,$FF,
+ $02,$4D,$A8,$FF,$02,$51,$AE,$FF,$00,$56,$AF,$FF,$00,$53,$AE,$FF,$02,$54,$AA,$FF,
+ $01,$52,$AE,$FF,$04,$50,$A6,$FF,$00,$52,$B2,$FF,$09,$55,$B3,$FF,$01,$4C,$9F,$FF,
+ $00,$4A,$9A,$FF,$01,$50,$AC,$FF,$01,$51,$B0,$FF,$00,$53,$AF,$FF,$01,$51,$B4,$FF,
+ $00,$5B,$B8,$FF,$03,$58,$B5,$FF,$02,$52,$B3,$FF,$03,$54,$AD,$FF,$01,$53,$A7,$FF,
+ $00,$57,$BE,$FF,$05,$57,$BA,$FF,$12,$58,$96,$FF,$1E,$64,$98,$FF,$2E,$4A,$4D,$FF,
+ $4F,$67,$0F,$FF,$80,$A7,$00,$FF,$91,$AC,$05,$FF,$8D,$A9,$00,$FF,$8A,$AE,$04,$FF,
+ $8F,$AD,$00,$FF,$8F,$AB,$01,$FF,$B5,$DE,$06,$FF,$C6,$E1,$56,$FF,$18,$40,$4C,$FF,
+ $00,$2B,$51,$FF,$01,$53,$A7,$FF,$05,$4F,$AE,$FF,$00,$52,$AC,$FF,$00,$55,$AE,$FF,
+ $04,$51,$AD,$FF,$02,$5F,$C6,$FF,$02,$78,$F6,$FF,$32,$6E,$66,$FF,$2B,$35,$01,$FF,
+ $6B,$94,$00,$FF,$90,$AC,$02,$FF,$88,$AD,$00,$FF,$92,$B0,$00,$FF,$85,$AA,$02,$FF,
+ $9D,$BC,$06,$FF,$AB,$E8,$0F,$FF,$1C,$51,$71,$FF,$00,$31,$63,$FF,$01,$54,$A4,$FF,
+ $00,$53,$A6,$FF,$00,$54,$AE,$FF,$00,$52,$B2,$FF,$00,$55,$A8,$FF,$01,$52,$AD,$FF,
+ $01,$50,$AC,$FF,$04,$52,$B4,$FF,$00,$51,$AC,$FF,$00,$54,$AB,$FF,$00,$51,$AE,$FF,
+ $04,$55,$B0,$FF,$03,$52,$B1,$FF,$00,$4E,$AF,$FF,$02,$53,$AE,$FF,$00,$53,$B3,$FF,
+ $00,$52,$AC,$FF,$00,$55,$AD,$FF,$00,$58,$B4,$FF,$00,$51,$A9,$FF,$01,$52,$A3,$FF,
+ $04,$54,$AD,$FF,$02,$53,$AE,$FF,$04,$51,$A9,$FF,$09,$50,$AC,$FF,$00,$53,$A8,$FF,
+ $03,$55,$AB,$FF,$00,$51,$A4,$FF,$00,$54,$A7,$FF,$03,$54,$AF,$FF,$00,$50,$A1,$FF,
+ $07,$5E,$A1,$FF,$1B,$66,$A7,$FF,$36,$73,$74,$FF,$2E,$49,$16,$FF,$64,$7B,$06,$FF,
+ $83,$A8,$02,$FF,$8D,$AA,$00,$FF,$8F,$AD,$00,$FF,$89,$AD,$05,$FF,$8A,$AB,$00,$FF,
+ $8E,$AD,$00,$FF,$AB,$D4,$00,$FF,$CF,$EC,$46,$FF,$1F,$50,$4C,$FF,$00,$14,$46,$FF,
+ $00,$4C,$99,$FF,$02,$4E,$AC,$FF,$00,$54,$AC,$FF,$00,$50,$A5,$FF,$00,$54,$B1,$FF,
+ $00,$55,$B6,$FF,$01,$7B,$FF,$FF,$30,$65,$87,$FF,$3E,$47,$10,$FF,$78,$9A,$07,$FF,
+ $90,$AD,$03,$FF,$8E,$AC,$00,$FF,$8D,$A3,$02,$FF,$8D,$AF,$00,$FF,$97,$B5,$07,$FF,
+ $B3,$E4,$0C,$FF,$22,$4F,$79,$FF,$00,$28,$58,$FF,$00,$4B,$9D,$FF,$07,$51,$AA,$FF,
+ $04,$50,$B0,$FF,$00,$51,$AD,$FF,$00,$51,$B1,$FF,$00,$51,$AB,$FF,$00,$51,$B1,$FF,
+ $03,$54,$B0,$FF,$03,$54,$B0,$FF,$09,$4F,$B1,$FF,$01,$51,$AA,$FF,$00,$51,$A3,$FF,
+ $00,$52,$A8,$FF,$00,$55,$AA,$FF,$00,$55,$A6,$FF,$00,$51,$AA,$FF,$00,$55,$B2,$FF,
+ $00,$58,$A1,$FF,$00,$5A,$B0,$FF,$00,$53,$AB,$FF,$06,$54,$A9,$FF,$01,$50,$AC,$FF,
+ $00,$52,$AE,$FF,$00,$54,$AD,$FF,$00,$55,$AF,$FF,$05,$50,$B5,$FF,$08,$50,$B6,$FF,
+ $01,$51,$B0,$FF,$00,$53,$B3,$FF,$04,$4E,$AF,$FF,$0F,$59,$A0,$FF,$0E,$5F,$8E,$FF,
+ $2C,$74,$AE,$FF,$43,$70,$51,$FF,$4B,$61,$0F,$FF,$7B,$91,$02,$FF,$8A,$AB,$02,$FF,
+ $90,$AA,$0B,$FF,$8E,$AD,$00,$FF,$8B,$B0,$01,$FF,$8C,$AC,$03,$FF,$8D,$AB,$00,$FF,
+ $A7,$CF,$00,$FF,$DA,$FD,$2D,$FF,$1B,$4A,$52,$FF,$06,$0B,$1F,$FF,$00,$43,$8A,$FF,
+ $04,$52,$B4,$FF,$00,$52,$A8,$FF,$05,$50,$AB,$FF,$00,$55,$A5,$FF,$00,$50,$B3,$FF,
+ $00,$72,$F8,$FF,$3A,$68,$5D,$FF,$48,$59,$00,$FF,$8D,$AE,$00,$FF,$8A,$AB,$00,$FF,
+ $8A,$B0,$03,$FF,$8C,$AE,$02,$FF,$8C,$AF,$00,$FF,$90,$B2,$06,$FF,$B8,$DA,$07,$FF,
+ $23,$86,$67,$FF,$00,$28,$50,$FF,$02,$47,$94,$FF,$02,$51,$B0,$FF,$01,$50,$AF,$FF,
+ $04,$54,$AD,$FF,$04,$53,$B2,$FF,$03,$55,$AB,$FF,$03,$54,$AF,$FF,$00,$53,$A6,$FF,
+ $00,$52,$AC,$FF,$01,$53,$A7,$FF,$00,$57,$AA,$FF,$00,$54,$AE,$FF,$02,$53,$AF,$FF,
+ $00,$52,$AE,$FF,$01,$4D,$AB,$FF,$06,$4D,$A7,$FF,$03,$53,$A8,$FF,$03,$56,$B2,$FF,
+ $01,$53,$B6,$FF,$00,$4F,$AE,$FF,$01,$50,$AC,$FF,$03,$51,$B3,$FF,$05,$54,$B3,$FF,
+ $03,$53,$AA,$FF,$00,$50,$A9,$FF,$00,$51,$AC,$FF,$00,$50,$A7,$FF,$00,$53,$AE,$FF,
+ $01,$5B,$BB,$FF,$04,$55,$AE,$FF,$14,$5F,$A3,$FF,$0F,$57,$89,$FF,$27,$67,$8D,$FF,
+ $3F,$5C,$3E,$FF,$6B,$81,$03,$FF,$88,$A1,$00,$FF,$8C,$AD,$06,$FF,$8E,$AB,$01,$FF,
+ $8D,$AC,$00,$FF,$8A,$AE,$02,$FF,$8C,$AE,$00,$FF,$90,$AD,$07,$FF,$96,$BF,$00,$FF,
+ $D5,$FF,$13,$FF,$4C,$72,$65,$FF,$02,$04,$00,$FF,$00,$2F,$65,$FF,$03,$4F,$AF,$FF,
+ $01,$52,$AB,$FF,$03,$53,$AC,$FF,$04,$52,$B6,$FF,$01,$5C,$AB,$FF,$0E,$6B,$C8,$FF,
+ $3F,$58,$3A,$FF,$58,$73,$00,$FF,$8F,$AC,$02,$FF,$8B,$AC,$03,$FF,$8D,$AA,$02,$FF,
+ $8B,$AC,$00,$FF,$8C,$AD,$00,$FF,$87,$AC,$07,$FF,$BD,$ED,$0B,$FF,$71,$B9,$65,$FF,
+ $0D,$41,$66,$FF,$01,$46,$8B,$FF,$00,$55,$B2,$FF,$00,$55,$A5,$FF,$02,$54,$A8,$FF,
+ $02,$50,$A3,$FF,$02,$4E,$AC,$FF,$03,$54,$A6,$FF,$00,$51,$AC,$FF,$00,$53,$B3,$FF,
+ $01,$51,$B4,$FF,$00,$52,$AF,$FF,$01,$4F,$B1,$FF,$07,$51,$B0,$FF,$00,$54,$AF,$FF,
+ $01,$54,$B2,$FF,$06,$55,$B1,$FF,$00,$51,$AB,$FF,$04,$56,$BA,$FF,$01,$51,$B0,$FF,
+ $00,$53,$A4,$FF,$00,$52,$A2,$FF,$00,$53,$AD,$FF,$00,$4E,$AA,$FF,$03,$50,$A8,$FF,
+ $03,$53,$B2,$FF,$00,$57,$B1,$FF,$03,$53,$A8,$FF,$00,$52,$AC,$FF,$02,$5B,$B7,$FF,
+ $0D,$5F,$B1,$FF,$0D,$58,$92,$FF,$22,$5D,$7D,$FF,$29,$50,$57,$FF,$4A,$63,$2A,$FF,
+ $7A,$99,$00,$FF,$8F,$B0,$01,$FF,$8B,$B0,$01,$FF,$8C,$AE,$00,$FF,$8E,$AF,$00,$FF,
+ $8D,$AE,$07,$FF,$8A,$AB,$00,$FF,$8F,$AB,$01,$FF,$8B,$B4,$00,$FF,$CD,$FF,$06,$FF,
+ $AA,$CF,$5D,$FF,$00,$07,$07,$FF,$00,$1E,$3B,$FF,$01,$4C,$9F,$FF,$00,$51,$AF,$FF,
+ $02,$52,$A7,$FF,$00,$51,$AE,$FF,$0D,$59,$A4,$FF,$15,$49,$5F,$FF,$43,$57,$10,$FF,
+ $77,$93,$02,$FF,$8B,$A8,$00,$FF,$8B,$B1,$00,$FF,$89,$AE,$00,$FF,$89,$B0,$00,$FF,
+ $88,$AD,$00,$FF,$89,$AB,$00,$FF,$A5,$D1,$02,$FF,$75,$DF,$3F,$FF,$16,$52,$6C,$FF,
+ $00,$35,$75,$FF,$00,$4F,$AE,$FF,$05,$53,$A8,$FF,$06,$53,$AD,$FF,$02,$51,$AE,$FF,
+ $02,$51,$B8,$FF,$01,$55,$AF,$FF,$02,$51,$AE,$FF,$04,$50,$AE,$FF,$04,$52,$A5,$FF,
+ $01,$53,$9F,$FF,$04,$4F,$A0,$FF,$05,$4E,$AA,$FF,$00,$52,$AB,$FF,$00,$53,$A8,$FF,
+ $05,$52,$AC,$FF,$04,$50,$B0,$FF,$00,$58,$B2,$FF,$00,$51,$A4,$FF,$00,$49,$8C,$FF,
+ $02,$44,$80,$FF,$07,$44,$87,$FF,$05,$45,$8D,$FF,$00,$49,$96,$FF,$00,$51,$AA,$FF,
+ $03,$4E,$AB,$FF,$04,$51,$A9,$FF,$00,$55,$AC,$FF,$03,$5B,$B4,$FF,$13,$66,$B2,$FF,
+ $23,$72,$99,$FF,$35,$70,$6C,$FF,$32,$4D,$2E,$FF,$60,$7C,$0D,$FF,$85,$AA,$00,$FF,
+ $89,$AD,$01,$FF,$84,$A9,$00,$FF,$8D,$AF,$01,$FF,$89,$A9,$00,$FF,$8E,$AE,$03,$FF,
+ $8C,$AB,$07,$FF,$8C,$AA,$00,$FF,$8F,$B6,$01,$FF,$C4,$F8,$02,$FF,$DA,$FF,$34,$FF,
+ $29,$47,$47,$FF,$02,$1A,$32,$FF,$01,$46,$91,$FF,$00,$52,$AD,$FF,$03,$50,$BA,$FF,
+ $03,$6D,$C3,$FF,$36,$63,$8D,$FF,$3B,$4D,$23,$FF,$62,$81,$00,$FF,$89,$A4,$00,$FF,
+ $8F,$AC,$02,$FF,$89,$AE,$00,$FF,$91,$A7,$00,$FF,$95,$AD,$00,$FF,$8F,$AB,$08,$FF,
+ $92,$AD,$00,$FF,$89,$B2,$00,$FF,$B6,$E5,$09,$FF,$40,$7A,$51,$FF,$09,$31,$65,$FF,
+ $00,$4B,$91,$FF,$01,$4E,$96,$FF,$00,$4A,$8E,$FF,$00,$47,$98,$FF,$00,$46,$8D,$FF,
+ $00,$39,$7C,$FF,$00,$2F,$60,$FF,$02,$28,$57,$FF,$00,$25,$3E,$FF,$00,$27,$55,$FF,
+ $01,$35,$67,$FF,$02,$43,$85,$FF,$04,$52,$9D,$FF,$01,$57,$AA,$FF,$00,$50,$B1,$FF,
+ $00,$53,$AD,$FF,$00,$5B,$B7,$FF,$00,$58,$BA,$FF,$00,$3F,$87,$FF,$03,$20,$42,$FF,
+ $00,$0C,$1F,$FF,$00,$19,$32,$FF,$00,$1F,$43,$FF,$05,$29,$5B,$FF,$00,$39,$7E,$FF,
+ $02,$4A,$96,$FF,$01,$58,$B5,$FF,$06,$5F,$BD,$FF,$0E,$62,$AB,$FF,$24,$75,$AC,$FF,
+ $1C,$59,$6C,$FF,$1F,$39,$1E,$FF,$53,$69,$00,$FF,$67,$85,$03,$FF,$66,$82,$07,$FF,
+ $65,$7E,$08,$FF,$65,$7D,$01,$FF,$69,$85,$00,$FF,$7B,$97,$04,$FF,$83,$A7,$00,$FF,
+ $87,$A6,$02,$FF,$8A,$AC,$00,$FF,$A4,$CE,$00,$FF,$D0,$FA,$1A,$FF,$52,$82,$68,$FF,
+ $06,$17,$35,$FF,$00,$40,$89,$FF,$03,$57,$AF,$FF,$00,$5B,$B5,$FF,$1C,$82,$D6,$FF,
+ $62,$83,$32,$FF,$7B,$91,$12,$FF,$84,$A9,$00,$FF,$8B,$AC,$00,$FF,$8C,$AC,$01,$FF,
+ $8A,$AC,$00,$FF,$8C,$AE,$00,$FF,$8C,$A5,$00,$FF,$87,$AF,$00,$FF,$86,$9F,$05,$FF,
+ $87,$A0,$00,$FF,$9E,$D7,$00,$FF,$54,$81,$24,$FF,$00,$18,$40,$FF,$00,$27,$5A,$FF,
+ $00,$27,$5E,$FF,$00,$25,$53,$FF,$08,$36,$67,$FF,$13,$49,$6D,$FF,$16,$48,$6B,$FF,
+ $21,$4F,$5F,$FF,$2D,$52,$58,$FF,$24,$3F,$36,$FF,$1A,$32,$3E,$FF,$0F,$3B,$3E,$FF,
+ $00,$2E,$4F,$FF,$00,$22,$5F,$FF,$03,$3A,$7B,$FF,$01,$4A,$A8,$FF,$07,$54,$AE,$FF,
+ $02,$5A,$B4,$FF,$05,$65,$CB,$FF,$06,$53,$97,$FF,$26,$49,$4B,$FF,$39,$4C,$2C,$FF,
+ $41,$63,$4B,$FF,$17,$36,$38,$FF,$02,$0D,$1F,$FF,$00,$10,$28,$FF,$00,$2B,$52,$FF,
+ $00,$42,$8D,$FF,$0D,$52,$97,$FF,$19,$5A,$76,$FF,$1E,$5D,$7E,$FF,$25,$51,$5C,$FF,
+ $3D,$49,$09,$FF,$2B,$32,$00,$FF,$27,$30,$1D,$FF,$3C,$4B,$20,$FF,$3B,$46,$1B,$FF,
+ $1F,$27,$10,$FF,$43,$54,$06,$FF,$5B,$73,$01,$FF,$71,$93,$00,$FF,$74,$95,$00,$FF,
+ $7C,$99,$03,$FF,$84,$A4,$05,$FF,$BD,$EB,$16,$FF,$3D,$74,$4D,$FF,$04,$15,$31,$FF,
+ $01,$44,$8A,$FF,$00,$51,$AC,$FF,$00,$69,$CC,$FF,$10,$64,$AD,$FF,$5D,$75,$07,$FF,
+ $78,$9A,$08,$FF,$90,$AB,$00,$FF,$86,$AF,$00,$FF,$8C,$AC,$03,$FF,$8E,$AC,$00,$FF,
+ $84,$AE,$04,$FF,$8A,$A6,$00,$FF,$79,$AB,$00,$FF,$7A,$9C,$00,$FF,$6F,$84,$00,$FF,
+ $81,$98,$12,$FF,$49,$63,$24,$FF,$07,$22,$37,$FF,$18,$43,$53,$FF,$24,$48,$46,$FF,
+ $30,$4E,$32,$FF,$58,$7D,$2D,$FF,$7C,$A8,$39,$FF,$87,$BB,$2A,$FF,$9F,$D3,$28,$FF,
+ $AF,$E3,$1C,$FF,$A6,$D7,$19,$FF,$9C,$C5,$13,$FF,$8B,$C2,$1F,$FF,$48,$6E,$3D,$FF,
+ $08,$0E,$24,$FF,$00,$1B,$28,$FF,$00,$45,$83,$FF,$03,$52,$B1,$FF,$00,$5C,$B1,$FF,
+ $02,$6C,$D9,$FF,$31,$7B,$7E,$FF,$73,$9E,$2A,$FF,$AD,$E7,$16,$FF,$BA,$F1,$22,$FF,
+ $A3,$E1,$38,$FF,$46,$9E,$64,$FF,$1E,$4A,$4B,$FF,$13,$35,$37,$FF,$16,$38,$54,$FF,
+ $17,$54,$70,$FF,$30,$6C,$6D,$FF,$4B,$74,$4C,$FF,$4A,$71,$32,$FF,$59,$75,$0E,$FF,
+ $25,$34,$15,$FF,$0D,$2B,$29,$FF,$1A,$58,$7F,$FF,$2C,$82,$A3,$FF,$2F,$76,$78,$FF,
+ $32,$52,$2D,$FF,$3A,$47,$01,$FF,$37,$47,$08,$FF,$3E,$55,$00,$FF,$55,$64,$09,$FF,
+ $54,$6A,$06,$FF,$69,$8D,$11,$FF,$22,$41,$3C,$FF,$01,$34,$61,$FF,$06,$50,$A7,$FF,
+ $00,$52,$A5,$FF,$00,$6A,$E4,$FF,$26,$75,$9E,$FF,$36,$46,$07,$FF,$50,$59,$0A,$FF,
+ $6F,$97,$00,$FF,$87,$A3,$01,$FF,$81,$A3,$04,$FF,$79,$9E,$00,$FF,$80,$A8,$0A,$FF,
+ $74,$90,$00,$FF,$5E,$73,$00,$FF,$4F,$6B,$00,$FF,$42,$68,$1D,$FF,$66,$8A,$40,$FF,
+ $45,$70,$66,$FF,$36,$5D,$3E,$FF,$58,$84,$25,$FF,$74,$A8,$44,$FF,$7C,$A7,$19,$FF,
+ $90,$B7,$0C,$FF,$9A,$CA,$12,$FF,$92,$BB,$07,$FF,$98,$BD,$00,$FF,$9D,$C6,$14,$FF,
+ $9F,$BE,$00,$FF,$98,$BB,$00,$FF,$BD,$EE,$06,$FF,$BB,$F4,$2B,$FF,$64,$8A,$4D,$FF,
+ $0A,$2F,$49,$FF,$00,$35,$81,$FF,$03,$53,$AA,$FF,$00,$62,$C7,$FF,$03,$73,$F3,$FF,
+ $42,$74,$57,$FF,$52,$71,$00,$FF,$8F,$B8,$02,$FF,$AE,$D8,$00,$FF,$C0,$ED,$00,$FF,
+ $B6,$FA,$29,$FF,$98,$E1,$32,$FF,$88,$BC,$34,$FF,$79,$A3,$33,$FF,$83,$BD,$33,$FF,
+ $8B,$C5,$33,$FF,$94,$C2,$2B,$FF,$99,$D4,$20,$FF,$67,$9A,$35,$FF,$42,$72,$62,$FF,
+ $0C,$41,$6D,$FF,$00,$4F,$AB,$FF,$02,$78,$E4,$FF,$0C,$8B,$F6,$FF,$2D,$91,$CC,$FF,
+ $4D,$92,$80,$FF,$48,$78,$46,$FF,$48,$6D,$39,$FF,$5A,$7C,$26,$FF,$4D,$75,$2C,$FF,
+ $17,$41,$4D,$FF,$00,$32,$5C,$FF,$00,$44,$99,$FF,$00,$53,$B1,$FF,$00,$51,$B5,$FF,
+ $00,$6D,$E0,$FF,$0C,$8B,$F4,$FF,$2D,$6F,$63,$FF,$3D,$49,$0B,$FF,$41,$4F,$00,$FF,
+ $48,$52,$09,$FF,$52,$67,$00,$FF,$60,$72,$02,$FF,$5C,$71,$00,$FF,$54,$72,$1C,$FF,
+ $56,$83,$40,$FF,$58,$8F,$7C,$FF,$2B,$81,$9C,$FF,$21,$8B,$E3,$FF,$2B,$A1,$D3,$FF,
+ $43,$8E,$77,$FF,$4F,$73,$29,$FF,$69,$8B,$12,$FF,$7D,$9A,$02,$FF,$8C,$AC,$0B,$FF,
+ $8B,$B0,$00,$FF,$94,$B7,$01,$FF,$91,$B5,$0B,$FF,$91,$B7,$00,$FF,$93,$B3,$00,$FF,
+ $97,$BB,$01,$FF,$9B,$BE,$00,$FF,$BA,$E0,$01,$FF,$8A,$B0,$0B,$FF,$12,$3A,$46,$FF,
+ $00,$39,$7C,$FF,$03,$52,$AF,$FF,$00,$64,$C2,$FF,$00,$70,$F0,$FF,$34,$4F,$40,$FF,
+ $20,$24,$01,$FF,$75,$91,$08,$FF,$91,$B5,$00,$FF,$9C,$BA,$04,$FF,$A0,$CC,$00,$FF,
+ $AC,$DB,$01,$FF,$AB,$D1,$08,$FF,$AB,$D5,$09,$FF,$A4,$D0,$0B,$FF,$A2,$CE,$09,$FF,
+ $AB,$D6,$00,$FF,$C6,$F8,$00,$FF,$76,$A6,$43,$FF,$12,$59,$79,$FF,$0C,$50,$91,$FF,
+ $03,$4F,$A3,$FF,$00,$59,$B3,$FF,$00,$6F,$D3,$FF,$00,$76,$F0,$FF,$00,$77,$FE,$FF,
+ $05,$81,$FB,$FF,$11,$79,$D2,$FF,$2A,$8C,$E5,$FF,$2F,$8F,$E5,$FF,$0C,$62,$C7,$FF,
+ $00,$4C,$84,$FF,$00,$4B,$91,$FF,$00,$53,$9E,$FF,$00,$55,$AF,$FF,$07,$5B,$BB,$FF,
+ $00,$72,$EB,$FF,$0A,$82,$FC,$FF,$01,$74,$CF,$FF,$2B,$7D,$79,$FF,$3D,$62,$2F,$FF,
+ $41,$60,$25,$FF,$4A,$6E,$26,$FF,$3D,$71,$4B,$FF,$15,$5B,$A1,$FF,$00,$72,$D9,$FF,
+ $00,$78,$F0,$FF,$00,$70,$DC,$FF,$00,$6F,$EF,$FF,$08,$86,$FF,$FF,$1F,$7F,$B9,$FF,
+ $4F,$73,$35,$FF,$68,$80,$00,$FF,$92,$AF,$07,$FF,$87,$A8,$00,$FF,$8E,$A8,$06,$FF,
+ $90,$AE,$00,$FF,$8A,$AE,$04,$FF,$8C,$AB,$00,$FF,$8D,$AF,$00,$FF,$85,$A8,$04,$FF,
+ $8F,$B4,$02,$FF,$7A,$9A,$08,$FF,$38,$5C,$2C,$FF,$00,$35,$49,$FF,$00,$47,$88,$FF,
+ $02,$50,$B2,$FF,$00,$5B,$BA,$FF,$04,$76,$FD,$FF,$33,$62,$5C,$FF,$0C,$0E,$00,$FF,
+ $5C,$74,$04,$FF,$83,$AC,$00,$FF,$8B,$B2,$01,$FF,$8F,$B6,$05,$FF,$9E,$B0,$04,$FF,
+ $96,$B0,$00,$FF,$95,$B7,$01,$FF,$96,$B6,$00,$FF,$90,$B3,$00,$FF,$9D,$BF,$08,$FF,
+ $C5,$EB,$04,$FF,$4D,$76,$30,$FF,$0B,$35,$4B,$FF,$05,$3F,$89,$FF,$00,$4F,$A4,$FF,
+ $00,$53,$A6,$FF,$01,$55,$AF,$FF,$01,$56,$B0,$FF,$02,$56,$B8,$FF,$06,$5A,$BA,$FF,
+ $00,$6D,$D4,$FF,$00,$6B,$E8,$FF,$00,$69,$E4,$FF,$00,$71,$DB,$FF,$00,$54,$BB,$FF,
+ $00,$4B,$A8,$FF,$02,$52,$A9,$FF,$01,$4F,$B1,$FF,$00,$4F,$A8,$FF,$00,$5B,$BB,$FF,
+ $07,$62,$CD,$FF,$02,$74,$F1,$FF,$02,$87,$FD,$FF,$24,$92,$F3,$FF,$1E,$7A,$CD,$FF,
+ $22,$7D,$B6,$FF,$0A,$6D,$CA,$FF,$04,$55,$B1,$FF,$00,$54,$BB,$FF,$00,$50,$AA,$FF,
+ $05,$50,$B5,$FF,$06,$56,$B5,$FF,$00,$69,$DF,$FF,$09,$61,$B8,$FF,$44,$62,$2E,$FF,
+ $73,$93,$01,$FF,$88,$B4,$00,$FF,$8D,$B6,$02,$FF,$8E,$A9,$04,$FF,$8A,$AA,$01,$FF,
+ $8C,$AD,$00,$FF,$8F,$AB,$00,$FF,$85,$AF,$05,$FF,$93,$B1,$03,$FF,$86,$A7,$00,$FF,
+ $68,$87,$2A,$FF,$2A,$54,$62,$FF,$02,$33,$76,$FF,$0A,$51,$A9,$FF,$00,$52,$A9,$FF,
+ $00,$5B,$B5,$FF,$00,$7C,$F6,$FF,$2C,$8C,$B2,$FF,$17,$26,$05,$FF,$41,$51,$00,$FF,
+ $86,$A7,$00,$FF,$8A,$AB,$00,$FF,$8A,$AA,$01,$FF,$8C,$AE,$00,$FF,$8B,$B0,$00,$FF,
+ $8A,$B0,$05,$FF,$8E,$A9,$00,$FF,$8F,$AD,$00,$FF,$98,$C1,$03,$FF,$92,$BC,$28,$FF,
+ $2D,$5F,$66,$FF,$05,$31,$4E,$FF,$00,$37,$7D,$FF,$00,$4B,$99,$FF,$07,$55,$AA,$FF,
+ $00,$4D,$AA,$FF,$00,$51,$A6,$FF,$00,$55,$AF,$FF,$00,$4F,$AB,$FF,$02,$4F,$AB,$FF,
+ $01,$4E,$AA,$FF,$00,$58,$A7,$FF,$00,$5C,$B0,$FF,$03,$58,$B5,$FF,$01,$55,$B8,$FF,
+ $00,$54,$AD,$FF,$00,$51,$AC,$FF,$01,$52,$AE,$FF,$00,$57,$AF,$FF,$07,$51,$B0,$FF,
+ $00,$4E,$B3,$FF,$00,$60,$C6,$FF,$03,$74,$D4,$FF,$00,$71,$DB,$FF,$00,$6F,$CF,$FF,
+ $01,$56,$B0,$FF,$06,$53,$A3,$FF,$00,$51,$AC,$FF,$03,$52,$AF,$FF,$07,$51,$A6,$FF,
+ $00,$55,$A5,$FF,$00,$73,$DD,$FF,$11,$65,$AE,$FF,$31,$40,$19,$FF,$63,$7D,$00,$FF,
+ $88,$BA,$01,$FF,$87,$AD,$00,$FF,$8E,$AD,$00,$FF,$8B,$B0,$01,$FF,$8A,$A7,$00,$FF,
+ $91,$AF,$01,$FF,$8E,$B4,$00,$FF,$A7,$D1,$03,$FF,$6B,$A1,$31,$FF,$25,$62,$5D,$FF,
+ $06,$56,$AD,$FF,$06,$54,$A9,$FF,$01,$55,$AD,$FF,$01,$51,$AA,$FF,$01,$56,$B3,$FF,
+ $00,$73,$FE,$FF,$0C,$86,$FF,$FF,$24,$43,$31,$FF,$22,$23,$01,$FF,$78,$8D,$00,$FF,
+ $91,$AC,$00,$FF,$90,$AD,$05,$FF,$89,$B1,$01,$FF,$82,$A9,$00,$FF,$89,$B0,$00,$FF,
+ $8F,$A9,$08,$FF,$90,$AD,$00,$FF,$A8,$D8,$08,$FF,$6E,$97,$5D,$FF,$16,$4B,$75,$FF,
+ $02,$38,$74,$FF,$00,$44,$8D,$FF,$00,$48,$9E,$FF,$04,$4C,$B0,$FF,$09,$52,$B1,$FF,
+ $03,$55,$AB,$FF,$00,$51,$AB,$FF,$02,$52,$AB,$FF,$04,$56,$AC,$FF,$04,$53,$B2,$FF,
+ $00,$53,$AF,$FF,$00,$4F,$A9,$FF,$05,$50,$AD,$FF,$06,$51,$B6,$FF,$00,$52,$AC,$FF,
+ $00,$52,$A2,$FF,$00,$55,$A6,$FF,$04,$54,$A9,$FF,$00,$52,$A5,$FF,$00,$57,$B0,$FF,
+ $01,$4F,$B4,$FF,$02,$52,$A9,$FF,$00,$51,$A3,$FF,$07,$4F,$B1,$FF,$00,$55,$AD,$FF,
+ $05,$55,$B6,$FF,$00,$51,$AC,$FF,$01,$50,$AF,$FF,$05,$50,$AB,$FF,$00,$52,$B3,$FF,
+ $00,$6B,$E8,$FF,$1D,$7B,$B8,$FF,$1B,$23,$0E,$FF,$4B,$54,$03,$FF,$85,$AE,$00,$FF,
+ $8F,$AF,$02,$FF,$8E,$AB,$00,$FF,$89,$B0,$00,$FF,$8F,$AA,$03,$FF,$89,$AB,$00,$FF,
+ $95,$B3,$03,$FF,$B1,$E6,$00,$FF,$4A,$79,$73,$FF,$0E,$41,$6C,$FF,$03,$53,$AA,$FF,
+ $00,$51,$B1,$FF,$00,$56,$A9,$FF,$06,$4F,$AD,$FF,$05,$52,$AE,$FF,$02,$6C,$D0,$FF,
+ $00,$78,$FB,$FF,$39,$6B,$6A,$FF,$1C,$20,$05,$FF,$66,$7B,$02,$FF,$90,$AA,$09,$FF,
+ $85,$AC,$00,$FF,$8B,$A7,$00,$FF,$95,$B3,$05,$FF,$89,$A8,$02,$FF,$8C,$AF,$00,$FF,
+ $91,$B8,$00,$FF,$91,$BC,$24,$FF,$45,$71,$62,$FF,$0A,$39,$4B,$FF,$00,$3B,$79,$FF,
+ $00,$4B,$9F,$FF,$00,$52,$AB,$FF,$00,$59,$AC,$FF,$00,$53,$B0,$FF,$00,$52,$AC,$FF,
+ $00,$53,$A4,$FF,$00,$52,$B8,$FF,$02,$4C,$AD,$FF,$05,$50,$AB,$FF,$00,$51,$A8,$FF,
+ $00,$5B,$AC,$FF,$04,$4F,$B5,$FF,$04,$4D,$AB,$FF,$04,$50,$AE,$FF,$08,$51,$B0,$FF,
+ $05,$4E,$AD,$FF,$00,$51,$B1,$FF,$00,$51,$AF,$FF,$02,$4C,$A5,$FF,$07,$56,$A5,$FF,
+ $00,$50,$A5,$FF,$06,$56,$AD,$FF,$00,$52,$AC,$FF,$00,$50,$B1,$FF,$04,$54,$A9,$FF,
+ $01,$54,$B2,$FF,$00,$52,$AD,$FF,$03,$52,$AF,$FF,$07,$53,$A9,$FF,$00,$68,$D7,$FF,
+ $15,$8E,$F9,$FF,$19,$3F,$42,$FF,$31,$31,$00,$FF,$84,$9F,$04,$FF,$87,$A8,$00,$FF,
+ $92,$AB,$07,$FF,$89,$AC,$00,$FF,$91,$AE,$00,$FF,$88,$AC,$02,$FF,$9A,$B9,$03,$FF,
+ $A4,$D2,$27,$FF,$1B,$53,$62,$FF,$00,$34,$67,$FF,$00,$5A,$A0,$FF,$00,$52,$AF,$FF,
+ $00,$57,$A7,$FF,$05,$4D,$B9,$FF,$00,$50,$AC,$FF,$00,$66,$CB,$FF,$08,$86,$F4,$FF,
+ $48,$8E,$96,$FF,$1D,$29,$13,$FF,$55,$71,$02,$FF,$8C,$AA,$00,$FF,$8C,$B0,$06,$FF,
+ $8F,$AD,$00,$FF,$89,$A9,$00,$FF,$8F,$AD,$00,$FF,$8A,$B6,$00,$FF,$94,$BB,$24,$FF,
+ $7B,$A7,$48,$FF,$2B,$65,$67,$FF,$11,$42,$60,$FF,$00,$42,$8A,$FF,$09,$52,$A1,$FF,
+ $03,$4D,$AC,$FF,$01,$51,$A8,$FF,$01,$52,$AD,$FF,$03,$53,$B6,$FF,$00,$52,$A6,$FF,
+ $02,$52,$AB,$FF,$00,$57,$AF,$FF,$04,$54,$A9,$FF,$04,$51,$AD,$FF,$00,$4E,$AB,$FF,
+ $03,$53,$AA,$FF,$00,$57,$A9,$FF,$00,$54,$AC,$FF,$00,$51,$AA,$FF,$00,$51,$AF,$FF,
+ $08,$53,$AE,$FF,$00,$55,$A8,$FF,$00,$56,$B0,$FF,$00,$53,$AE,$FF,$00,$4E,$B9,$FF,
+ $00,$50,$AF,$FF,$01,$53,$A9,$FF,$03,$54,$A6,$FF,$06,$4E,$B4,$FF,$00,$4F,$A4,$FF,
+ $01,$56,$B1,$FF,$00,$53,$AE,$FF,$03,$4F,$A5,$FF,$01,$6D,$DC,$FF,$07,$82,$F9,$FF,
+ $2F,$7F,$98,$FF,$3B,$46,$02,$FF,$6E,$83,$00,$FF,$88,$B0,$02,$FF,$8D,$A8,$01,$FF,
+ $8E,$AE,$05,$FF,$8F,$AB,$00,$FF,$8C,$AE,$02,$FF,$AD,$DA,$03,$FF,$94,$B9,$1C,$FF,
+ $17,$3C,$73,$FF,$05,$34,$7A,$FF,$03,$52,$A1,$FF,$0B,$4C,$B0,$FF,$00,$54,$AE,$FF,
+ $00,$53,$A6,$FF );
+
+{ PERFORM_RENDERING }
+procedure the_application.perform_rendering;
+var
+ pf : pixel_formats;
+ rb : renderer_base;
+ rs : renderer_scanline_aa_solid;
+ ren : renderer_scanline_aa;
+
+ rgba : aggclr;
+ path : path_storage;
+
+ x1 ,y1 ,x2 ,y2 ,scale ,d1 ,d2 : double;
+
+ ide ,mtx : trans_affine;
+
+ tas : trans_affine_scaling;
+
+ tat ,gmt : trans_affine_translation;
+
+ t1 ,t2 : conv_transform;
+
+ gimag : gradient_image;
+ gcont : ^gradient_contour;
+ gcona : gradient_conic_angle;
+
+ al : span_allocator;
+ sg : span_gradient;
+
+ interpolator : span_interpolator_linear;
+
+ gfunction : gradient_ptr;
+ cfunction : array_base_ptr;
+
+ gr_ref : gradient_reflect_adaptor;
+ stroke : conv_stroke;
+ bitmap : pointer;
+
+begin
+ pixfmt_bgr24(pf ,rbuf_window );
+
+ rb.Construct(@pf );
+ rs.Construct(@rb );
+
+ gcont:=NIL;
+
+ if bounding_rect_single(vs ,0 ,@x1 ,@y1 ,@x2 ,@y2 ) then
+ begin
+ { Create Path }
+ scale:=(_width - 120 ) / (x2 - x1 );
+
+ if scale > (_height - 120 ) / (y2 - y1 ) then
+ scale:=(_height - 120 ) / (y2 - y1 );
+
+ mtx.Construct;
+ tat.Construct(-x1 ,-y1 ); mtx.multiply(@tat );
+ tas.Construct(scale ,scale ); mtx.multiply(@tas );
+ t1.Construct (vs ,@mtx );
+
+ tat.Construct(100 ,105 );
+ t2.Construct (@t1 ,@tat );
+
+ path.Construct;
+ path.add_path(@t1 );
+
+ { Color function }
+ case trunc(m_clrs._value ) of
+ 2 :
+ cfunction:=@m_colors02;
+
+ 3 :
+ cfunction:=@m_colors03;
+
+ 4 :
+ cfunction:=@m_colors04;
+
+ 5 :
+ cfunction:=@m_colors05;
+
+ 6 :
+ cfunction:=@m_colors06;
+
+ 7 :
+ cfunction:=@m_colors07;
+
+ 8 :
+ cfunction:=@m_colors08;
+
+ 9 :
+ cfunction:=@m_colors09;
+
+ 10 :
+ cfunction:=@m_colors10;
+
+ else
+ cfunction:=@m_colors11;
+
+ end;
+
+ { Create Gradient Function }
+ gfunction:=NIL;
+
+ gmt.Construct(0 ,0 );
+
+ d1:=0;
+ d2:=100;
+
+ case m_gradient._cur_item of
+ // contour
+ 0 ,1 :
+ begin
+ new(gcont ,Construct );
+
+ gcont.frame(0 );
+ gcont.d1(m_c1._value );
+ gcont.d2(m_c2._value );
+
+ gmt.multiply(@tat );
+
+ case m_gradient._cur_item of
+ // contour
+ 0 :
+ if gcont.contour_create(contour ) <> NIL then
+ gfunction:=gcont;
+
+ // auto contour
+ else
+ if gcont.contour_create(@path ) <> NIL then
+ gfunction:=gcont;
+
+ end;
+
+ d1:=m_d1._value;
+ d2:=m_d2._value;
+
+ end;
+
+ // assymetric conic
+ 2 :
+ begin
+ gcona.Construct;
+
+ gfunction:=@gcona;
+
+ gmt.Construct(270 ,300 );
+
+ end;
+
+ end;
+
+ { Render }
+ if gfunction <> NIL then
+ begin
+ ide.Construct;
+ ide.multiply(@gmt );
+ ide.invert;
+
+ interpolator.Construct(@ide );
+
+ if m_refl._status then
+ begin
+ gr_ref.Construct(gfunction );
+
+ gfunction:=@gr_ref;
+
+ end;
+
+ al.Construct;
+ sg.Construct(
+ @al ,
+ @interpolator ,
+ gfunction ,
+ cfunction ,
+ d1 ,d2 );
+
+ ren.Construct(@rb ,@sg );
+
+ m_ras.reset;
+ m_ras.add_path (@t2 );
+ render_scanlines(@m_ras ,@m_sl ,@ren ); {}
+
+ al.Destruct;
+
+ end
+ else
+ begin
+ m_ras.reset;
+ m_ras.add_path (@t2 );
+ rgba.ConstrDbl (0 ,0.6 ,0 ,0.5 );
+ rs.color_ (@rgba );
+ render_scanlines(@m_ras ,@m_sl ,@rs );
+
+ end;
+
+ { Stroke }
+ if m_stroke._status then
+ begin
+ gimag.Construct;
+
+ bitmap:=gimag.image_create(64 ,64 );
+
+ if bitmap <> NIL then
+ begin
+ move(puzzle[0 ] ,bitmap^ ,64 * 64 * 4 );
+
+ stroke.Construct(@t2 );
+ stroke.width_ (10.0 );
+
+ ide.Construct;
+
+ case m_gradient._cur_item of
+ 0 ,1 :
+ begin
+ ide.multiply(@mtx );
+ ide.multiply(@gmt );
+
+ end;
+
+ end;
+
+ ide.invert;
+
+ interpolator.Construct(@ide );
+
+ al.Construct;
+ sg.Construct(
+ @al ,
+ @interpolator ,
+ @gimag ,
+ gimag.color_function ,
+ d1 ,d2 );
+
+ ren.Construct(@rb ,@sg );
+
+ m_ras.reset;
+ m_ras.add_path (@stroke );
+ render_scanlines(@m_ras ,@m_sl ,@ren );
+
+ al.Destruct;
+
+ stroke.Destruct;
+
+ end;
+
+ gimag.Destruct;
+
+ end;
+
+ { Free }
+ path.Destruct;
+
+ if gcont <> NIL then
+ dispose(gcont ,Destruct );
+
+ end;
+
+end;
+
+{ RENDER }
+function the_application.render;
+var
+ star ,
+ gb_poly ,
+ glyph : path_storage;
+
+ stroke : conv_stroke;
+ curve : conv_curve;
+
+ sp : spiral;
+
+begin
+ star.Construct;
+
+ star.move_to(12 ,40 );
+ star.line_to(52 ,40 );
+ star.line_to(72 ,6 );
+ star.line_to(92 ,40 );
+ star.line_to(132 ,40 );
+ star.line_to(112 ,76 );
+ star.line_to(132 ,112 );
+ star.line_to(92 ,112 );
+ star.line_to(72 ,148 );
+ star.line_to(52 ,112 );
+ star.line_to(12 ,112 );
+ star.line_to(32 ,76 );
+ star.close_polygon;
+
+ case m_polygons._cur_item of
+ 0 : // Simple path
+ perform_rendering(@star ,@star );
+
+ 1 : // Great Britain
+ begin
+ gb_poly.Construct;
+
+ make_gb_poly(@gb_poly );
+
+ perform_rendering(@gb_poly ,@star );
+
+ gb_poly.Destruct;
+
+ end;
+
+ 2 : // Spiral
+ begin
+ sp.Construct (0 ,0 ,10 ,150 ,30 ,0.0 );
+ stroke.Construct(@sp );
+ stroke.width_ (22.0 );
+
+ perform_rendering(@stroke ,@star );
+
+ stroke.Destruct;
+
+ end;
+
+ 3 : // Glyph
+ begin
+ glyph.Construct;
+ glyph.move_to(28.47 ,6.45 );
+ glyph.curve3 (21.58 ,1.12 ,19.82 ,0.29 );
+ glyph.curve3 (17.19 ,-0.93 ,14.21 ,-0.93 );
+ glyph.curve3 (9.57 ,-0.93 ,6.57 ,2.25 );
+ glyph.curve3 (3.56 ,5.42 ,3.56 ,10.60 );
+ glyph.curve3 (3.56 ,13.87 ,5.03 ,16.26 );
+ glyph.curve3 (7.03 ,19.58 ,11.99 ,22.51 );
+ glyph.curve3 (16.94 ,25.44 ,28.47 ,29.64 );
+ glyph.line_to(28.47 ,31.40 );
+ glyph.curve3 (28.47 ,38.09 ,26.34 ,40.58 );
+ glyph.curve3 (24.22 ,43.07 ,20.17 ,43.07 );
+ glyph.curve3 (17.09 ,43.07 ,15.28 ,41.41 );
+ glyph.curve3 (13.43 ,39.75 ,13.43 ,37.60 );
+ glyph.line_to(13.53 ,34.77 );
+ glyph.curve3 (13.53 ,32.52 ,12.38 ,31.30 );
+ glyph.curve3 (11.23 ,30.08 ,9.38 ,30.08 );
+ glyph.curve3 (7.57 ,30.08 ,6.42 ,31.35 );
+ glyph.curve3 (5.27 ,32.62 ,5.27 ,34.81 );
+ glyph.curve3 (5.27 ,39.01 ,9.57 ,42.53 );
+ glyph.curve3 (13.87 ,46.04 ,21.63 ,46.04 );
+ glyph.curve3 (27.59 ,46.04 ,31.40 ,44.04 );
+ glyph.curve3 (34.28 ,42.53 ,35.64 ,39.31 );
+ glyph.curve3 (36.52 ,37.21 ,36.52 ,30.71 );
+ glyph.line_to(36.52 ,15.53 );
+ glyph.curve3 (36.52 ,9.13 ,36.77 ,7.69 );
+ glyph.curve3 (37.01 ,6.25 ,37.57 ,5.76 );
+ glyph.curve3 (38.13 ,5.27 ,38.87 ,5.27 );
+ glyph.curve3 (39.65 ,5.27 ,40.23 ,5.62 );
+ glyph.curve3 (41.26 ,6.25 ,44.19 ,9.18 );
+ glyph.line_to(44.19 ,6.45 );
+ glyph.curve3 (38.72 ,-0.88 ,33.74 ,-0.88 );
+ glyph.curve3 (31.35 ,-0.88 ,29.93 ,0.78 );
+ glyph.curve3 (28.52 ,2.44 ,28.47 ,6.45 );
+ glyph.close_polygon;
+
+ glyph.move_to(28.47 ,9.62 );
+ glyph.line_to(28.47 ,26.66 );
+ glyph.curve3 (21.09 ,23.73 ,18.95 ,22.51 );
+ glyph.curve3 (15.09 ,20.36 ,13.43 ,18.02 );
+ glyph.curve3 (11.77 ,15.67 ,11.77 ,12.89 );
+ glyph.curve3 (11.77 ,9.38 ,13.87 ,7.06 );
+ glyph.curve3 (15.97 ,4.74 ,18.70 ,4.74 );
+ glyph.curve3 (22.41 ,4.74 ,28.47 ,9.62 );
+ glyph.close_polygon;
+
+ curve.Construct(@glyph );
+
+ curve.approximation_scale_(10 );
+
+ perform_rendering(@curve ,@star );
+
+ glyph.Destruct;
+ curve.Destruct;
+
+ end;
+
+ end;
+
+ star.Destruct;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ pf : pixel_formats;
+
+ rgba : aggclr;
+
+ ren_base : renderer_base;
+ ren_solid : renderer_scanline_aa_solid;
+
+begin
+// Initialize structures
+ pixfmt_bgr24(pf ,rbuf_window );
+
+ ren_base.Construct (@pf );
+ ren_solid.Construct(@ren_base );
+
+ rgba.ConstrDbl(1 ,1 ,1 );
+ ren_base.clear(@rgba );
+
+// Render
+ render;
+
+// Render the controls
+ render_ctrl(@m_ras ,@m_sl ,@ren_solid ,@m_polygons );
+ render_ctrl(@m_ras ,@m_sl ,@ren_solid ,@m_gradient );
+ render_ctrl(@m_ras ,@m_sl ,@ren_solid ,@m_stroke );
+ render_ctrl(@m_ras ,@m_sl ,@ren_solid ,@m_refl );
+ render_ctrl(@m_ras ,@m_sl ,@ren_solid ,@m_c1 );
+ render_ctrl(@m_ras ,@m_sl ,@ren_solid ,@m_c2 );
+ render_ctrl(@m_ras ,@m_sl ,@ren_solid ,@m_d1 );
+ render_ctrl(@m_ras ,@m_sl ,@ren_solid ,@m_d2 );
+ render_ctrl(@m_ras ,@m_sl ,@ren_solid ,@m_clrs );
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ 'Here are some more gradient functions. Firstly the Contour gradient, makes'#13 +
+ 'color transitions from shape defined by an arbitrary (in fact any) path.'#13 +
+ 'It computes so called Distance Transform (DT) from image produced by only'#13 +
+ 'stroking the path, which is then the source of color level in the underlying'#13 +
+ 'gradient function. Contour gradient can be used in two forms. One is to define '#13 +
+ 'shape for contour different from shape of object being drawn. Second is to'#13 +
+ 'use the same shape for contour and for drawing (AutoContour).'#13#13 +
+
+ 'Assymetric conic gradient (also called angle) is the same as conic, but the ray'#13 +
+ 'of light with color transitions going counter clockwise travels whole circle'#13 +
+ 'instead of just half (as with conic).'#13#13 +
+
+ 'Bitmap gradient is very similar to pattern fill, but works in the framework of'#13 +
+ 'gradient functions interfaces. Because of that all interpolator transformations'#13 +
+ 'from gradient span generator can be applied to this kind of fill.'#13#13 +
+
+ 'How to play with:'#13#13 +
+
+ 'Try to fiddle with C1,C2 & D1,D2 parameters to see, how interestingly'#13 +
+ 'the gradient transitions changes (each time a new DT is computed).'#13 +
+ 'DT is reused when the color ramp changes.'#13#13 +
+
+ 'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+VAR
+ app : the_application;
+
+BEGIN
+ app.Construct(pix_format_bgr24 ,flip_y );
+ app.caption_ ('AGG Example. More gradients: Contour, Bitmap & Assymetric Conic (F1-Help)' );
+
+ if app.init(520 ,520 ,window_resize ) then
+ app.run;
+
+ app.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/graph_test.dpr b/src/corelib/render/software/agg-demos/graph_test.dpr
new file mode 100644
index 00000000..275574f3
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/graph_test.dpr
@@ -0,0 +1,1591 @@
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ graph_test ;
+
+uses
+ SysUtils ,
+
+ agg_basics ,
+ agg_platform_support ,
+
+ agg_color ,
+ agg_pixfmt ,
+ agg_pixfmt_rgb ,
+
+ agg_ctrl ,
+ agg_slider_ctrl ,
+ agg_cbox_ctrl ,
+ agg_rbox_ctrl ,
+
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_renderer_primitives ,
+ agg_rasterizer_scanline_aa ,
+ agg_rasterizer_outline ,
+ agg_scanline ,
+ agg_scanline_p ,
+ agg_scanline_u ,
+ agg_render_scanlines ,
+
+ agg_array ,
+ agg_curves ,
+ agg_ellipse ,
+ agg_vertex_source ,
+ agg_conv_stroke ,
+ agg_conv_dash ,
+ agg_conv_curve ,
+ agg_conv_contour ,
+ agg_conv_marker ,
+ agg_conv_shorten_path ,
+ agg_conv_marker_adaptor ,
+ agg_conv_concat ,
+ agg_arrowhead ,
+ agg_vcgen_markers_term ,
+ agg_span_allocator ,
+ agg_span_gradient ,
+ agg_span_interpolator_linear ,
+ agg_gamma_functions ,
+ agg_trans_affine ;
+
+{$I agg_mode.inc }
+{$I- }
+const
+ flip_y = true;
+
+type
+ base_renderer = renderer_base;
+ primitives_renderer = renderer_primitives;
+ solid_renderer = renderer_scanline_aa_solid;
+ draft_renderer = renderer_scanline_bin_solid;
+ gradient_function = gradient_radial_d;
+ interpolator = span_interpolator_linear;
+ gradient_span_gen = span_gradient;
+ gradient_span_alloc = span_allocator;
+ gradient_renderer = renderer_scanline_aa;
+ scanline_rasterizer = rasterizer_scanline_aa;
+ outline_rasterizer = rasterizer_outline;
+
+ node_ptr = ^node;
+ node = object
+ x ,y : double;
+
+ constructor Construct; overload;
+ constructor Construct(x_ ,y_ : double ); overload;
+
+ end;
+
+ edge_ptr = ^edge;
+ edge = object
+ node1 ,node2 : int;
+
+ constructor Construct; overload;
+ constructor Construct(n1 ,n2 : int ); overload;
+
+ end;
+
+ graph = object
+ m_num_nodes ,
+ m_num_edges : int;
+
+ m_nodes : node_ptr;
+ m_edges : edge_ptr;
+
+ constructor Construct(num_nodes ,num_edges : int );
+ destructor Destruct;
+
+ function get_num_nodes : int;
+ function get_num_edges : int;
+
+ function get_node(idx : int; w ,h : double ) : node;
+ function get_edge(idx : int ) : edge;
+
+ end;
+
+ line = object(vertex_source )
+ x1 ,y1 ,x2 ,y2 : double;
+
+ f : int;
+
+ constructor Construct(x1_ ,y1_ ,x2_ ,y2_ : double );
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ end;
+
+ curve = object(vertex_source )
+ c : curve4;
+
+ constructor Construct(x1 ,y1 ,x2 ,y2 : double; k : double = 0.5 );
+ destructor Destruct; virtual;
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ end;
+
+ stroke_draft_simple = object(vertex_source )
+ s : vertex_source_ptr;
+
+ constructor Construct(src : vertex_source_ptr );
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ end;
+
+ stroke_draft_arrow = object(vertex_source )
+ s : conv_marker_adaptor;
+ ah : arrowhead;
+ m : conv_marker;
+ ma : vcgen_markers_term;
+ c : conv_concat;
+
+ constructor Construct(src : vertex_source_ptr; w : double );
+ destructor Destruct; virtual;
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ end;
+
+ stroke_fine_simple = object(vertex_source )
+ s : conv_stroke;
+
+ constructor Construct(src : vertex_source_ptr; w : double );
+ destructor Destruct; virtual;
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ end;
+
+ stroke_fine_arrow = object(vertex_source )
+ s : conv_stroke;
+ ah : arrowhead;
+ m : conv_marker;
+ ma : vcgen_markers_term;
+ c : conv_concat;
+
+ constructor Construct(src : vertex_source_ptr; w : double );
+ destructor Destruct; virtual;
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ end;
+
+ dash_stroke_draft_simple = object(vertex_source )
+ d : conv_dash;
+
+ constructor Construct(src : vertex_source_ptr; dash_len ,gap_len ,w : double );
+ destructor Destruct; virtual;
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ end;
+
+ dash_stroke_draft_arrow = object(vertex_source )
+ d : conv_dash;
+ ah : arrowhead;
+ m : conv_marker;
+ ma : vcgen_markers_term;
+ c : conv_concat;
+
+ constructor Construct(src : vertex_source_ptr; dash_len ,gap_len ,w : double );
+ destructor Destruct; virtual;
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ end;
+
+ dash_stroke_fine_simple = object(vertex_source )
+ d : conv_dash;
+ s : conv_stroke;
+
+ constructor Construct(src : vertex_source_ptr; dash_len ,gap_len ,w : double );
+ destructor Destruct; virtual;
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ end;
+
+ dash_stroke_fine_arrow = object(vertex_source )
+ d : conv_dash;
+ s : conv_stroke;
+ ah : arrowhead;
+ m : conv_marker;
+ ma : vcgen_markers_term;
+ c : conv_concat;
+
+ constructor Construct(src : vertex_source_ptr; dash_len ,gap_len ,w : double );
+ destructor Destruct; virtual;
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ end;
+
+{ stroke_draft = stroke_draft_simple;
+ dash_stroke_draft = dash_stroke_draft_simple;
+ stroke_fine = stroke_fine_simple;
+ dash_stroke_fine = dash_stroke_fine_simple;{}
+
+ stroke_draft = stroke_draft_arrow;
+ dash_stroke_draft = dash_stroke_draft_arrow;
+ stroke_fine = stroke_fine_arrow;
+ dash_stroke_fine = dash_stroke_fine_arrow;{}
+
+ the_application = object(platform_support )
+ m_type : rbox_ctrl;
+ m_width : slider_ctrl;
+
+ m_benchmark ,
+ m_draw_nodes ,
+ m_draw_edges ,
+ m_draft ,
+ m_translucent : cbox_ctrl;
+
+ m_gradient_colors : pod_auto_array;
+
+ m_graph : graph;
+ m_draw : int;
+ m_sl : scanline_u8;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure draw_nodes_draft;
+ procedure draw_nodes_fine(ras : rasterizer_scanline_ptr );
+
+ procedure render_edge_fine(
+ ras : rasterizer_scanline_ptr;
+ ren_fine ,
+ ren_draft : renderer_scanline_ptr;
+ src : vertex_source_ptr );
+
+ procedure draw_lines_draft;
+ procedure draw_curves_draft;
+ procedure draw_dashes_draft;
+
+ procedure draw_lines_fine(
+ ras : rasterizer_scanline_ptr;
+ solid ,
+ draft : renderer_scanline_ptr );
+
+ procedure draw_curves_fine(
+ ras : rasterizer_scanline_ptr;
+ solid ,
+ draft : renderer_scanline_ptr );
+
+ procedure draw_dashes_fine(
+ ras : rasterizer_scanline_ptr;
+ solid ,
+ draft : renderer_scanline_ptr );
+
+ procedure draw_polygons(
+ ras : rasterizer_scanline_ptr;
+ solid ,
+ draft : renderer_scanline_ptr );
+
+ procedure draw_scene(
+ ras : rasterizer_scanline_ptr;
+ solid ,
+ draft : renderer_scanline_ptr );
+
+ procedure on_draw; virtual;
+ procedure on_ctrl_change; virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ CONSTRUCT }
+constructor node.Construct;
+begin
+ x:=0;
+ y:=0;
+
+end;
+
+{ CONSTRUCT }
+constructor node.Construct(x_ ,y_ : double );
+begin
+ x:=x_;
+ y:=y_;
+
+end;
+
+{ CONSTRUCT }
+constructor edge.Construct;
+begin
+ node1:=0;
+ node2:=0;
+
+end;
+
+{ CONSTRUCT }
+constructor edge.Construct(n1 ,n2 : int );
+begin
+ node1:=n1;
+ node2:=n2;
+
+end;
+
+{ CONSTRUCT }
+constructor graph.Construct;
+var
+ i : int;
+ n : node_ptr;
+ e : edge_ptr;
+
+begin
+ m_num_nodes:=num_nodes;
+ m_num_edges:=num_edges;
+
+ agg_getmem(pointer(m_nodes ) ,m_num_nodes * sizeof(node ) );
+ agg_getmem(pointer(m_edges ) ,m_num_edges * sizeof(edge ) );
+
+ RandSeed:=100;
+
+ for i:=0 to m_num_nodes - 1 do
+ begin
+ n:=node_ptr(ptrcomp(m_nodes ) + i * sizeof(node ) );
+
+ n.x:=(Random($7fff ) / $7fff ) * 0.75 + 0.2;
+ n.y:=(Random($7fff ) / $7fff ) * 0.85 + 0.1;
+
+ end;
+
+ i:=0;
+
+ while i < m_num_edges do
+ begin
+ e:=edge_ptr(ptrcomp(m_edges ) + i * sizeof(edge ) );
+
+ e.node1:=Random($7fff ) mod m_num_nodes;
+ e.node2:=Random($7fff ) mod m_num_nodes;
+
+ if e.node1 = e.node2 then
+ dec(i );
+
+ inc(i );
+
+ end;
+
+end;
+
+{ DESTRUCT }
+destructor graph.Destruct;
+begin
+ agg_freemem(pointer(m_nodes ) ,m_num_nodes * sizeof(node ) );
+ agg_freemem(pointer(m_edges ) ,m_num_edges * sizeof(edge ) );
+
+end;
+
+{ GET_NUM_NODES }
+function graph.get_num_nodes;
+begin
+ result:=m_num_nodes;
+
+end;
+
+{ GET_NUM_EDGES }
+function graph.get_num_edges;
+begin
+ result:=m_num_edges;
+
+end;
+
+{ GET_NODE }
+function graph.get_node;
+var
+ p : node;
+
+begin
+ p.Construct;
+
+ if idx < m_num_nodes then
+ begin
+ p:=node_ptr(ptrcomp(m_nodes ) + idx * sizeof(node ) )^;
+
+ p.x:=p.x * w;
+ p.y:=p.y * h;
+
+ end;
+
+ result:=p;
+
+end;
+
+{ GET_EDGE }
+function graph.get_edge;
+var
+ b : edge;
+
+begin
+ b.Construct;
+
+ if idx < m_num_edges then
+ b:=edge_ptr(ptrcomp(m_edges ) + idx * sizeof(edge ) )^;
+
+ result:=b;
+
+end;
+
+{ CONSTRUCT }
+constructor line.Construct;
+begin
+ x1:=x1_;
+ y1:=y1_;
+ x2:=x2_;
+ y2:=y2_;
+ f :=0;
+
+end;
+
+{ REWIND }
+procedure line.rewind;
+begin
+ f:=0;
+
+end;
+
+{ VERTEX }
+function line.vertex;
+begin
+ if f = 0 then
+ begin
+ inc(f );
+
+ x^:=x1;
+ y^:=y1;
+
+ result:=path_cmd_move_to;
+
+ exit;
+
+ end;
+
+ if f = 1 then
+ begin
+ inc(f );
+
+ x^:=x2;
+ y^:=y2;
+
+ result:=path_cmd_line_to;
+
+ exit;
+
+ end;
+
+ result:=path_cmd_stop;
+
+end;
+
+{ CONSTRUCT }
+constructor curve.Construct;
+begin
+ c.Construct;
+ c.init4(
+ x1 ,y1 ,
+ x1 - (y2 - y1 ) * k ,
+ y1 + (x2 - x1 ) * k ,
+ x2 + (y2 - y1 ) * k ,
+ y2 - (x2 - x1 ) * k ,
+ x2 ,y2 );
+
+end;
+
+{ DESTRUCT }
+destructor curve.Destruct;
+begin
+ c.Destruct;
+
+end;
+
+{ REWIND }
+procedure curve.rewind;
+begin
+ c.rewind(path_id );
+
+end;
+
+{ VERTEX }
+function curve.vertex;
+begin
+ result:=c.vertex(x ,y );
+
+end;
+
+{ CONSTRUCT }
+constructor stroke_draft_simple.Construct;
+begin
+ s:=src;
+
+end;
+
+{ REWIND }
+procedure stroke_draft_simple.rewind;
+begin
+ s.rewind(path_id );
+
+end;
+
+{ VERTEX }
+function stroke_draft_simple.vertex;
+begin
+ s.vertex(x ,y );
+
+end;
+
+{ CONSTRUCT }
+constructor stroke_draft_arrow.Construct;
+begin
+ s.Construct(src );
+ ma.Construct;
+ s.set_markers(@ma );
+ ah.Construct;
+ m.Construct(s.markers ,@ah );
+ c.Construct(@s ,@m );
+
+ ah.head_ (0 ,10 ,5 ,0 );
+ s.shorten_(10.0 );
+
+end;
+
+{ DESTRUCT }
+destructor stroke_draft_arrow.Destruct;
+begin
+ s.Destruct;
+ ma.Destruct;
+
+end;
+
+{ REWIND }
+procedure stroke_draft_arrow.rewind;
+begin
+ c.rewind(path_id );
+
+end;
+
+{ VERTEX }
+function stroke_draft_arrow.vertex;
+begin
+ result:=c.vertex(x ,y );
+
+end;
+
+{ CONSTRUCT }
+constructor stroke_fine_simple.Construct;
+begin
+ s.Construct(src );
+ s.width_ (w );
+
+end;
+
+{ DESTRUCT }
+destructor stroke_fine_simple.Destruct;
+begin
+ s.Destruct;
+
+end;
+
+{ REWIND }
+procedure stroke_fine_simple.rewind;
+begin
+ s.rewind(path_id );
+
+end;
+
+{ VERTEX }
+function stroke_fine_simple.vertex;
+begin
+ result:=s.vertex(x ,y );
+
+end;
+
+{ CONSTRUCT }
+constructor stroke_fine_arrow.Construct;
+begin
+ s.Construct(src );
+ ma.Construct;
+ s.set_markers(@ma );
+ ah.Construct;
+ m.Construct(s.markers ,@ah );
+ c.Construct(@s ,@m );
+
+ s.width_ (w );
+ ah.head_ (0 ,10 ,5 ,0 );
+ s.shorten_(w * 2.0 );
+
+end;
+
+{ DESTRUCT }
+destructor stroke_fine_arrow.Destruct;
+begin
+ s.Destruct;
+ ma.Destruct;
+
+end;
+
+{ REWIND }
+procedure stroke_fine_arrow.rewind;
+begin
+ c.rewind(path_id );
+
+end;
+
+{ VERTEX }
+function stroke_fine_arrow.vertex;
+begin
+ result:=c.vertex(x ,y );
+
+end;
+
+{ CONSTRUCT }
+constructor dash_stroke_draft_simple.Construct;
+begin
+ d.Construct(src );
+ d.add_dash (dash_len ,gap_len );
+
+end;
+
+{ DESTRUCT }
+destructor dash_stroke_draft_simple.Destruct;
+begin
+ d.Destruct;
+
+end;
+
+{ REWIND }
+procedure dash_stroke_draft_simple.rewind;
+begin
+ d.rewind(path_id );
+
+end;
+
+{ VERTEX }
+function dash_stroke_draft_simple.vertex;
+begin
+ result:=d.vertex(x ,y );
+
+end;
+
+{ CONSTRUCT }
+constructor dash_stroke_draft_arrow.Construct;
+begin
+ d.Construct(src );
+ ma.Construct;
+ d.set_markers(@ma );
+ ah.Construct;
+ m.Construct(d.markers ,@ah );
+ c.Construct(@d ,@m );
+
+ d.add_dash(dash_len ,gap_len );
+
+ ah.head_ (0 ,10 ,5 ,0 );
+ d.shorten_(10.0 );
+
+end;
+
+{ DESTRUCT }
+destructor dash_stroke_draft_arrow.Destruct;
+begin
+ d.Destruct;
+ ma.Destruct;
+
+end;
+
+{ REWIND }
+procedure dash_stroke_draft_arrow.rewind;
+begin
+ c.rewind(path_id );
+
+end;
+
+{ VERTEX }
+function dash_stroke_draft_arrow.vertex;
+begin
+ result:=c.vertex(x ,y );
+
+end;
+
+{ CONSTRUCT }
+constructor dash_stroke_fine_simple.Construct;
+begin
+ d.Construct(src );
+ s.Construct(@d );
+
+ d.add_dash(dash_len ,gap_len );
+ s.width_ (w );
+
+end;
+
+{ DESTRUCT }
+destructor dash_stroke_fine_simple.Destruct;
+begin
+ d.Destruct;
+ s.Destruct;
+
+end;
+
+{ REWIND }
+procedure dash_stroke_fine_simple.rewind;
+begin
+ s.rewind(path_id );
+
+end;
+
+{ VERTEX }
+function dash_stroke_fine_simple.vertex;
+begin
+ result:=s.vertex(x ,y );
+
+end;
+
+{ CONSTRUCT }
+constructor dash_stroke_fine_arrow.Construct;
+begin
+ d.Construct(src );
+ ma.Construct;
+ d.set_markers(@ma );
+ s.Construct(@d );
+ ah.Construct;
+ m.Construct(d.markers ,@ah );
+ c.Construct(@s ,@m );
+
+ d.add_dash(dash_len ,gap_len );
+ s.width_ (w );
+ ah.head_ (0 ,10 ,5 ,0 );
+ d.shorten_(w * 2.0 );
+
+end;
+
+{ DESTRUCT }
+destructor dash_stroke_fine_arrow.Destruct;
+begin
+ d.Destruct;
+ s.Destruct;
+ ma.Destruct;
+
+end;
+
+{ REWIND }
+procedure dash_stroke_fine_arrow.rewind;
+begin
+ c.rewind(path_id );
+
+end;
+
+{ VERTEX }
+function dash_stroke_fine_arrow.vertex;
+begin
+ result:=c.vertex(x ,y );
+
+end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+var
+ i : int;
+
+ c1 ,c2 : aggclr;
+
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_type.Construct (-1 ,-1 ,-1 ,-1 ,not flip_y_ );
+ m_width.Construct(110 + 80 ,8.0 ,110 + 200.0 + 80 ,8.0 + 7.0 ,not flip_y_ );
+
+ m_benchmark.Construct (110 + 200 + 80 + 8 ,8.0 - 2.0 ,'Benchmark' ,not flip_y_ );
+ m_draw_nodes.Construct (110 + 200 + 80 + 8 ,8.0 - 2.0 + 15.0 ,'Draw Nodes' ,not flip_y_ );
+ m_draw_edges.Construct (200 + 200 + 80 + 8 ,8.0 - 2.0 + 15.0 ,'Draw Edges' ,not flip_y_ );
+ m_draft.Construct (200 + 200 + 80 + 8 ,8.0 - 2.0 ,'Draft Mode' ,not flip_y_ );
+ m_translucent.Construct(110 + 80 ,8.0 - 2.0 + 15.0 ,'Translucent Mode' ,not flip_y_ );
+
+ m_graph.Construct(200 ,100 );
+ m_sl.Construct;
+
+ m_draw:=3;
+
+ m_gradient_colors.Construct(256 ,sizeof(aggclr ) );
+
+ add_ctrl(@m_type );
+
+ m_type.text_size_(8.0 );
+ m_type.add_item ('Solid lines' );
+ m_type.add_item ('Bezier curves' );
+ m_type.add_item ('Dashed curves' );
+ m_type.add_item ('Poygons AA' );
+ m_type.add_item ('Poygons Bin' );
+ m_type.cur_item_ (0 );
+
+ add_ctrl(@m_width );
+
+ m_width.num_steps_(20 );
+ m_width.range_ (0.0 ,5.0 );
+ m_width.value_ (2.0 );
+ m_width.label_ ('Width=%1.2f' );
+
+ m_benchmark.text_size_ (8.0 );
+ m_draw_nodes.text_size_(8.0 );
+ m_draft.text_size_ (8.0 );
+ m_draw_nodes.status_ (true );
+ m_draw_edges.status_ (true );
+
+ add_ctrl(@m_benchmark );
+ add_ctrl(@m_draw_nodes );
+ add_ctrl(@m_draw_edges );
+ add_ctrl(@m_draft );
+ add_ctrl(@m_translucent );
+
+ c1.ConstrDbl(1 ,1 ,0 ,0.25 );
+ c2.ConstrDbl(0 ,0 ,1 );
+
+ for i:=0 to 255 do
+ aggclr_ptr(
+ m_gradient_colors.array_operator(i ) )^:=c1.gradient(@c2 ,i / 255.0 );
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_type.Destruct;
+ m_width.Destruct;
+
+ m_benchmark.Destruct;
+ m_draw_nodes.Destruct;
+ m_draw_edges.Destruct;
+ m_draft.Destruct;
+ m_translucent.Destruct;
+
+ m_graph.Destruct;
+ m_sl.Destruct;
+ m_gradient_colors.Destruct;
+
+end;
+
+{ DRAW_NODES_DRAFT }
+procedure the_application.draw_nodes_draft;
+var
+ pixf : pixel_formats;
+
+ rb : base_renderer;
+ prim : primitives_renderer;
+
+ i : int;
+ n : node;
+
+begin
+ pixfmt_bgr24 (pixf ,rbuf_window );
+ rb.Construct (@pixf );
+ prim.Construct(@rb );
+
+ i:=0;
+
+ while i < m_graph.get_num_nodes do
+ begin
+ n:=m_graph.get_node(i ,_width ,_height );
+
+ prim.fill_color_ (aggclr_ptr(m_gradient_colors.array_operator(147 ) ) );
+ prim.line_color_ (aggclr_ptr(m_gradient_colors.array_operator(255 ) ) );
+ prim.outlined_ellipse(trunc(n.x ) ,trunc(n.y ) ,10 ,10 );
+ prim.fill_color_ (aggclr_ptr(m_gradient_colors.array_operator(50 ) ) );
+ prim.solid_ellipse (trunc(n.x ) ,trunc(n.y ) ,4 ,4 );
+
+ inc(i );
+
+ end;
+
+end;
+
+{ DRAW_NODES_FINE }
+procedure the_application.draw_nodes_fine;
+var
+ pixf : pixel_formats;
+
+ sa : gradient_span_alloc;
+ rb : base_renderer;
+ gf : gradient_function;
+ sg : gradient_span_gen;
+
+ i : int;
+ n : node;
+
+ ell : ellipse;
+ mtx : trans_affine;
+ tas : trans_affine_scaling;
+ tat : trans_affine_translation;
+ ren : gradient_renderer;
+
+ inter : interpolator;
+
+ x ,y : double;
+
+begin
+ sa.Construct;
+ pixfmt_bgr24(pixf ,rbuf_window );
+ rb.Construct(@pixf );
+
+ i:=0;
+
+ while i < m_graph.get_num_nodes do
+ begin
+ n:=m_graph.get_node(i ,_width ,_height );
+
+ ell.Construct(n.x ,n.y ,5.0 * m_width._value ,5.0 * m_width._value );
+
+ case m_draw of
+ 0 :
+ begin
+ ell.rewind(0);
+
+ while not is_stop(ell.vertex(@x ,@y ) ) do;
+
+ end;
+
+ 1 :
+ begin
+ ras.reset;
+ ras.add_path(@ell );
+
+ end;
+
+ 2 :
+ begin
+ ras.reset;
+ ras.add_path(@ell );
+ ras.sort;
+
+ end;
+
+ 3 :
+ begin
+ gf.Construct;
+ mtx.Construct;
+ tas.Construct(m_width._value / 2.0 ); mtx.multiply(@tas );
+ tat.Construct(n.x ,n.y ); mtx.multiply(@tat );
+ mtx.invert;
+ inter.Construct(@mtx );
+ sg.Construct (@sa ,@inter ,@gf ,@m_gradient_colors ,0.0 ,10.0 );
+ ren.Construct(@rb ,@sg );
+
+ ras.add_path (@ell);
+ render_scanlines(ras ,@m_sl ,@ren );
+
+ end;
+
+ end;
+
+ inc(i );
+
+ end;
+
+ sa.Destruct;
+
+end;
+
+{ RENDER_EDGE_FINE }
+procedure the_application.render_edge_fine;
+var
+ rgba : aggclr;
+ x ,y : double;
+
+ r ,g ,b ,a : int;
+
+begin
+ case m_draw of
+ 0 :
+ begin
+ src.rewind(0 );
+
+ while not is_stop(src.vertex(@x ,@y ) ) do;
+
+ end;
+
+ 1 :
+ begin
+ ras.reset;
+ ras.add_path(src );
+
+ end;
+
+ 2 :
+ begin
+ ras.reset;
+ ras.add_path(src );
+ ras.sort;
+
+ end;
+
+ 3 :
+ begin
+ r:=Random($7fff ) and $7F;
+ g:=Random($7fff ) and $7F;
+ b:=Random($7fff ) and $7F;
+ a:=255;
+
+ if m_translucent._status then
+ a:=80;
+
+ ras.add_path(src );
+
+ if m_type._cur_item < 4 then
+ begin
+ rgba.ConstrInt (r ,g ,b ,a );
+ ren_fine.color_ (@rgba );
+ render_scanlines(ras ,@m_sl ,ren_fine );
+
+ end
+ else
+ begin
+ rgba.ConstrInt (r ,g ,b ,a );
+ ren_draft.color_(@rgba );
+ render_scanlines(ras ,@m_sl ,ren_draft );
+
+ end;
+
+ end;
+
+ end;
+
+end;
+
+{ DRAW_LINES_DRAFT }
+procedure the_application.draw_lines_draft;
+var
+ pixf : pixel_formats;
+ prim : primitives_renderer;
+ rgba : aggclr;
+
+ rb : base_renderer;
+ ras : outline_rasterizer;
+
+ i ,r ,g ,b ,a : int;
+
+ l : line;
+ s : stroke_draft;
+ e : edge;
+ n1 ,
+ n2 : node;
+
+begin
+ pixfmt_bgr24(pixf ,rbuf_window );
+
+ rb.Construct (@pixf );
+ prim.Construct(@rb );
+ ras.Construct (@prim );
+
+ i:=0;
+
+ while i < m_graph.get_num_edges do
+ begin
+ e :=m_graph.get_edge(i );
+ n1:=m_graph.get_node(e.node1 ,_width ,_height );
+ n2:=m_graph.get_node(e.node2 ,_width ,_height );
+
+ l.Construct(n1.x ,n1.y ,n2.x ,n2.y );
+ s.Construct(@l ,m_width._value );
+
+ r:=Random($7fff ) and $7F;
+ g:=Random($7fff ) and $7F;
+ b:=Random($7fff ) and $7F;
+ a:=255;
+
+ if m_translucent._status then
+ a:=80;
+
+ rgba.ConstrInt (r ,g ,b ,a );
+ prim.line_color_(@rgba );
+ ras.add_path (@s );
+
+ s.Destruct;
+
+ inc(i );
+
+ end;
+
+end;
+
+{ DRAW_CURVES_DRAFT }
+procedure the_application.draw_curves_draft;
+var
+ pixf : pixel_formats;
+ prim : primitives_renderer;
+ rgba : aggclr;
+
+ rb : base_renderer;
+ ras : outline_rasterizer;
+
+ i ,r ,g ,b ,a : int;
+
+ c : curve;
+ s : stroke_draft;
+ e : edge;
+ n1 ,
+ n2 : node;
+
+begin
+ pixfmt_bgr24(pixf ,rbuf_window );
+
+ rb.Construct (@pixf );
+ prim.Construct(@rb );
+ ras.Construct (@prim );
+
+ i:=0;
+
+ while i < m_graph.get_num_edges do
+ begin
+ e :=m_graph.get_edge(i );
+ n1:=m_graph.get_node(e.node1 ,_width ,_height );
+ n2:=m_graph.get_node(e.node2 ,_width ,_height );
+
+ c.Construct(n1.x ,n1.y ,n2.x ,n2.y );
+ s.Construct(@c ,m_width._value );
+
+ r:=Random($7fff ) and $7F;
+ g:=Random($7fff ) and $7F;
+ b:=Random($7fff ) and $7F;
+ a:=255;
+
+ if m_translucent._status then
+ a:=80;
+
+ rgba.ConstrInt (r ,g ,b ,a );
+ prim.line_color_(@rgba );
+ ras.add_path (@s );
+
+ c.Destruct;
+ s.Destruct;
+
+ inc(i );
+
+ end;
+
+end;
+
+{ DRAW_DASHES_DRAFT }
+procedure the_application.draw_dashes_draft;
+var
+ pixf : pixel_formats;
+ prim : primitives_renderer;
+ rgba : aggclr;
+
+ rb : base_renderer;
+ ras : outline_rasterizer;
+
+ i ,r ,g ,b ,a : int;
+
+ c : curve;
+ s : dash_stroke_draft;
+ e : edge;
+ n1 ,
+ n2 : node;
+
+begin
+ pixfmt_bgr24(pixf ,rbuf_window );
+
+ rb.Construct (@pixf );
+ prim.Construct(@rb );
+ ras.Construct (@prim );
+
+ i:=0;
+
+ while i < m_graph.get_num_edges do
+ begin
+ e :=m_graph.get_edge(i );
+ n1:=m_graph.get_node(e.node1 ,_width ,_height );
+ n2:=m_graph.get_node(e.node2 ,_width ,_height );
+
+ c.Construct(n1.x ,n1.y ,n2.x ,n2.y );
+ s.Construct(@c ,6.0 ,3.0 ,m_width._value );
+
+ r:=Random($7fff ) and $7F;
+ g:=Random($7fff ) and $7F;
+ b:=Random($7fff ) and $7F;
+ a:=255;
+
+ if m_translucent._status then
+ a:=80;
+
+ rgba.ConstrInt (r ,g ,b ,a );
+ prim.line_color_(@rgba );
+ ras.add_path (@s );
+
+ c.Destruct;
+ s.Destruct;
+
+ inc(i );
+
+ end;
+
+end;
+
+{ DRAW_LINES_FINE }
+procedure the_application.draw_lines_fine;
+var
+ i : int;
+ b : edge;
+ l : line;
+ s : stroke_fine;
+
+ n1 ,n2 : node;
+
+begin
+ i:=0;
+
+ while i < m_graph.get_num_edges do
+ begin
+ b :=m_graph.get_edge(i );
+ n1:=m_graph.get_node(b.node1 ,_width ,_height );
+ n2:=m_graph.get_node(b.node2 ,_width ,_height );
+
+ l.Construct(n1.x ,n1.y ,n2.x ,n2.y );
+ s.Construct(@l ,m_width._value );
+
+ render_edge_fine(ras ,solid ,draft ,@s );
+
+ s.Destruct;
+
+ inc(i );
+
+ end;
+
+end;
+
+{ DRAW_CURVES_FINE }
+procedure the_application.draw_curves_fine;
+var
+ i : int;
+ b : edge;
+ c : curve;
+ s : stroke_fine;
+
+ n1 ,n2 : node;
+
+begin
+ i:=0;
+
+ while i < m_graph.get_num_edges do
+ begin
+ b :=m_graph.get_edge(i );
+ n1:=m_graph.get_node(b.node1 ,_width ,_height );
+ n2:=m_graph.get_node(b.node2 ,_width ,_height );
+
+ c.Construct(n1.x ,n1.y ,n2.x ,n2.y );
+ s.Construct(@c ,m_width._value );
+
+ render_edge_fine(ras ,solid ,draft ,@s );
+
+ c.Destruct;
+ s.Destruct;
+
+ inc(i );
+
+ end;
+
+end;
+
+{ DRAW_DASHES_FINE }
+procedure the_application.draw_dashes_fine;
+var
+ i : int;
+ b : edge;
+ c : curve;
+ s : dash_stroke_fine;
+
+ n1 ,n2 : node;
+
+begin
+ i:=0;
+
+ while i < m_graph.get_num_edges do
+ begin
+ b :=m_graph.get_edge(i );
+ n1:=m_graph.get_node(b.node1 ,_width ,_height );
+ n2:=m_graph.get_node(b.node2 ,_width ,_height );
+
+ c.Construct(n1.x ,n1.y ,n2.x ,n2.y );
+ s.Construct(@c ,6.0 ,3.0 ,m_width._value );
+
+ render_edge_fine(ras ,solid ,draft ,@s );
+
+ c.Destruct;
+ s.Destruct;
+
+ inc(i );
+
+ end;
+
+end;
+
+{ DRAW_POLYGONS }
+procedure the_application.draw_polygons;
+var
+ i : int;
+ b : edge;
+ c : curve;
+
+ n1 ,n2 : node;
+
+ gm_no : gamma_none;
+ gm_th : gamma_threshold;
+
+begin
+ if m_type._cur_item = 4 then
+ begin
+ gm_th.Construct(0.5 );
+ ras.gamma (@gm_th );
+
+ end;
+
+ i:=0;
+
+ while i < m_graph.get_num_edges do
+ begin
+ b :=m_graph.get_edge(i );
+ n1:=m_graph.get_node(b.node1 ,_width ,_height );
+ n2:=m_graph.get_node(b.node2 ,_width ,_height );
+
+ c.Construct(n1.x ,n1.y ,n2.x ,n2.y );
+
+ render_edge_fine(ras ,solid ,draft ,@c );
+
+ c.Destruct;
+
+ inc(i );
+
+ end;
+
+ gm_no.Construct;
+ ras.gamma(@gm_no );
+
+end;
+
+{ DRAW_SCENE }
+procedure the_application.draw_scene;
+var
+ gm_no : gamma_none;
+
+begin
+ gm_no.Construct;
+ ras.gamma(@gm_no );
+
+ RandSeed:=100;
+
+ if m_draw_nodes._status then
+ if m_draft._status then
+ draw_nodes_draft
+ else
+ draw_nodes_fine(ras );
+
+ if m_draw_edges._status then
+ if m_draft._status then
+ case m_type._cur_item of
+ 0 : draw_lines_draft;
+ 1 : draw_curves_draft;
+ 2 : draw_dashes_draft;
+
+ end
+ else
+ case m_type._cur_item of
+ 0 :
+ draw_lines_fine(ras ,solid ,draft );
+
+ 1 :
+ draw_curves_fine(ras ,solid ,draft );
+
+ 2 :
+ draw_dashes_fine(ras ,solid ,draft );
+
+ 3 ,4 :
+ draw_polygons(ras ,solid ,draft );
+
+ end;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ pixf : pixel_formats;
+ rgba : aggclr;
+
+ ras : scanline_rasterizer;
+ rb : base_renderer;
+
+ solid : solid_renderer;
+ draft : draft_renderer;
+
+begin
+// Initialize structures
+ ras.Construct;
+
+ pixfmt_bgr24(pixf ,rbuf_window );
+
+ rb.Construct (@pixf );
+ solid.Construct(@rb );
+ draft.Construct(@rb );
+
+ rgba.ConstrDbl(1 ,1 ,1 );
+ rb.clear (@rgba );
+
+// Render
+ draw_scene(@ras ,@solid ,@draft );
+
+// Render the controls
+ ras.filling_rule(fill_non_zero );
+
+ render_ctrl(@ras ,@m_sl ,@solid ,@m_type );
+ render_ctrl(@ras ,@m_sl ,@solid ,@m_width );
+ render_ctrl(@ras ,@m_sl ,@solid ,@m_benchmark );
+ render_ctrl(@ras ,@m_sl ,@solid ,@m_draw_nodes );
+ render_ctrl(@ras ,@m_sl ,@solid ,@m_draw_edges );
+ render_ctrl(@ras ,@m_sl ,@solid ,@m_draft );
+ render_ctrl(@ras ,@m_sl ,@solid ,@m_translucent );
+
+// Free AGG resources
+ ras.Destruct;
+
+end;
+
+{ ON_CTRL_CHANGE }
+procedure the_application.on_ctrl_change;
+var
+ pixf : pixel_formats;
+
+ i : int;
+ fd : text;
+
+ ras : scanline_rasterizer;
+ rb : base_renderer;
+
+ solid : solid_renderer;
+ draft : draft_renderer;
+
+ buf : array[0..255 ] of char;
+ times : array[0..4 ] of double;
+
+begin
+ if m_benchmark._status then
+ begin
+ on_draw;
+ update_window;
+
+ ras.Construct;
+
+ pixfmt_bgr24(pixf ,rbuf_window );
+
+ rb.Construct (@pixf );
+ solid.Construct(@rb );
+ draft.Construct(@rb );
+
+ if m_draft._status then
+ begin
+ start_timer;
+
+ for i:=0 to 9 do
+ draw_scene(@ras ,@solid ,@draft );
+
+ sprintf(@buf[0 ] ,'%3.3f milliseconds' ,elapsed_time );
+
+ end
+ else
+ begin
+ m_draw:=0;
+
+ while m_draw < 4 do
+ begin
+ start_timer;
+
+ for i:=0 to 9 do
+ draw_scene(@ras ,@solid ,@draft );
+
+ times[m_draw ]:=elapsed_time;
+
+ inc(m_draw );
+
+ end;
+
+ m_draw:=3;
+
+ times[4 ]:=times[3 ];
+ times[3 ]:=times[3 ] - times[2 ];
+ times[2 ]:=times[2 ] - times[1 ];
+ times[1 ]:=times[1 ] - times[0 ];
+
+ AssignFile(fd ,'benchmark' );
+ rewrite (fd );
+
+ sprintf(@buf[0 ] ,'%10.3f ' ,times[0 ] );
+ sprintf(@buf[StrLen(@buf ) ] ,'%10.3f ' ,times[1 ] );
+ sprintf(@buf[StrLen(@buf ) ] ,'%10.3f ' ,times[2 ] );
+ sprintf(@buf[StrLen(@buf ) ] ,'%10.3f ' ,times[3 ] );
+ sprintf(@buf[StrLen(@buf ) ] ,'%10.3f' ,times[4 ] );
+
+ writeln(fd ,PChar(@buf[0 ] ) );
+ close (fd );
+
+ sprintf(@buf[0 ] ,' pipeline add_path sort render total'#13'%10.3f ' ,times[0 ] );
+ sprintf(@buf[StrLen(@buf ) ] ,'%10.3f ' ,times[1 ] );
+ sprintf(@buf[StrLen(@buf ) ] ,'%10.3f ' ,times[2 ] );
+ sprintf(@buf[StrLen(@buf ) ] ,'%10.3f ' ,times[3 ] );
+ sprintf(@buf[StrLen(@buf ) ] ,'%10.3f' ,times[4 ] );
+
+ end;
+
+ message_(@buf[0 ] );
+
+ m_benchmark.status_(false );
+ force_redraw;
+
+ ras.Destruct;
+
+ end;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ 'Yet another example of the "general" kind. It was used mostly to compare '#13 +
+ 'the performance of different steps of rendering in order to see the weaknesses. '#13 +
+ 'The WIn GDI+ analog of it looks worse and works slower. Try "GDI_graph_test.zip"'#13 +
+ '(from www.antigrain.com/demo) and compare it with the AGG one. '#13 +
+ 'The most disappointing thing in GDI+ is that it cannot draw Bezier curves correctly. '#13#13 +
+ 'How to play with:'#13#13 +
+ 'Run the GDI+ example, choose menu Image/Bezier curves, expand the window to '#13 +
+ 'about 1000x1000 pixels, and then gradually change the size of the window. You will '#13 +
+ 'see that some curves miss the destination points (the centers of the node circles).' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+VAR
+ app : the_application;
+
+BEGIN
+ app.Construct(pix_format_bgr24 ,flip_y );
+ app.caption_ ('AGG Example. Line Join (F1-Help)' );
+
+ if app.init(600 + 100 ,500 + 30 ,window_resize ) then
+ app.run;
+
+ app.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/idea.dpr b/src/corelib/render/software/agg-demos/idea.dpr
new file mode 100644
index 00000000..1aaeae91
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/idea.dpr
@@ -0,0 +1,517 @@
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ idea ;
+
+{DEFINE AGG_GRAY8 }
+{$DEFINE AGG_BGR24 }
+{DEFINE AGG_RGB24 }
+{DEFINE AGG_BGRA32 }
+{DEFINE AGG_RGBA32 }
+{DEFINE AGG_ARGB32 }
+{DEFINE AGG_ABGR32 }
+{DEFINE AGG_RGB565 }
+{DEFINE AGG_RGB555 }
+
+uses
+ Math ,
+
+ agg_basics ,
+ agg_platform_support ,
+
+ agg_ctrl ,
+ agg_slider_ctrl ,
+ agg_cbox_ctrl ,
+
+ agg_rasterizer_scanline_aa ,
+ agg_scanline ,
+ agg_scanline_p ,
+
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_render_scanlines ,
+
+ agg_gamma_functions ,
+ agg_path_storage ,
+ agg_trans_affine ,
+ agg_conv_stroke ,
+ agg_conv_transform ,
+ agg_vertex_source
+
+{$I pixel_formats.inc }
+{$I agg_mode.inc }
+
+const
+ flip_y = false;
+
+type
+ path_attributes = object
+ index : unsigned;
+
+ fill_color ,
+ stroke_color : aggclr;
+ stroke_width : double;
+
+ constructor Construct; overload;
+ constructor Construct(idx : unsigned; fill ,stroke : aggclr_ptr; width : double ); overload;
+
+ end;
+
+const
+ g_poly_bulb : array[0..39 ] of double = (
+ -6 ,-67 ,-6 ,-71 ,-7 ,-74 ,-8 ,-76 ,-10 ,-79 ,
+ -10 ,-82 ,-9 ,-84 ,-6 ,-86 ,-4 ,-87 ,-2 ,-86 ,
+ -1 ,-86 ,1 ,-84 ,2 ,-82 ,2 ,-79 ,0 ,-77 ,
+ -2 ,-73 ,-2 ,-71 ,-2 ,-69 ,-3 ,-67 ,-4 ,-65 );
+
+ g_poly_beam1 : array[0..9 ] of double = (
+ -14 ,-84 ,-22 ,-85 ,-23 ,-87 ,-22 ,-88 ,-21 ,-88 );
+
+ g_poly_beam2 : array[0..9 ] of double = (
+ -10 ,-92 ,-14 ,-96 ,-14 ,-98 ,-12 ,-99 ,-11 ,-97 );
+
+ g_poly_beam3 : array[0..9 ] of double = (
+ -1 ,-92 ,-2 ,-98 ,0 ,-100 ,2 ,-100 ,1 ,-98 );
+
+ g_poly_beam4 : array[0..9 ] of double = (
+ 5 ,-89 ,11 ,-94 ,13 ,-93 ,13 ,-92 ,12 ,-91 );
+
+ g_poly_fig1 : array[0..41 ] of double = (
+ 1 ,-48 ,-3 ,-54 ,-7 ,-58 ,-12 ,-58 ,-17 ,-55 ,
+ -20 ,-52 ,-21 ,-47 ,-20 ,-40 ,-17 ,-33 ,-11 ,-28 ,
+ -6 ,-26 ,-2 ,-25 ,2 ,-26 ,4 ,-28 ,5 ,-33 ,
+ 5 ,-39 ,3 ,-44 ,12 ,-48 ,12 ,-50 ,12 ,-51 ,
+ 3 ,-46 );
+
+ g_poly_fig2 : array[0..75 ] of double = (
+ 11 ,-27 ,6 ,-23 ,4 ,-22 ,3 ,-19 ,5 ,-16 ,
+ 6 ,-15 ,11 ,-17 ,19 ,-23 ,25 ,-30 ,32 ,-38 ,
+ 32 ,-41 ,32 ,-50 ,30 ,-64 ,32 ,-72 ,32 ,-75 ,
+ 31 ,-77 ,28 ,-78 ,26 ,-80 ,28 ,-87 ,27 ,-89 ,
+ 25 ,-88 ,24 ,-79 ,24 ,-76 ,23 ,-75 ,20 ,-76 ,
+ 17 ,-76 ,17 ,-74 ,19 ,-73 ,22 ,-73 ,24 ,-71 ,
+ 26 ,-69 ,27 ,-64 ,28 ,-55 ,28 ,-47 ,28 ,-40 ,
+ 26 ,-38 ,20 ,-33 ,14 ,-30 );
+
+ g_poly_fig3 : array[0..69 ] of double = (
+ -6 ,-20 ,-9 ,-21 ,-15 ,-21 ,-20 ,-17 ,-28 ,-8 ,
+ -32 ,-1 ,-32 ,1 ,-30 ,6 ,-26 ,8 ,-20 ,10 ,
+ -16 ,12 ,-14 ,14 ,-15 ,16 ,-18 ,20 ,-22 ,20 ,
+ -25 ,19 ,-27 ,20 ,-26 ,22 ,-23 ,23 ,-18 ,23 ,
+ -14 ,22 ,-11 ,20 ,-10 ,17 ,-9 ,14 ,-11 ,11 ,
+ -16 ,9 ,-22 ,8 ,-26 ,5 ,-28 ,2 ,-27 ,-2 ,
+ -23 ,-8 ,-19 ,-11 ,-12 ,-14 ,-6 ,-15 ,-6 ,-18 );
+
+ g_poly_fig4 : array[0..39 ] of double = (
+ 11 ,-6 ,8 ,-16 ,5 ,-21 ,-1 ,-23 ,-7 ,-22 ,
+ -10 ,-17 ,-9 ,-10 ,-8 ,0 ,-8 ,10 ,-10 ,18 ,
+ -11 ,22 ,-10 ,26 ,-7 ,28 ,-3 ,30 ,0 ,31 ,
+ 5 ,31 ,10 ,27 ,14 ,18 ,14 ,11 ,11 ,2 );
+
+ g_poly_fig5 : array[0..55 ] of double = (
+ 0 ,22 ,-5 ,21 ,-8 ,22 ,-9 ,26 ,-8 ,49 ,
+ -8 ,54 ,-10 ,64 ,-10 ,75 ,-9 ,81 ,-10 ,84 ,
+ -16 ,89 ,-18 ,95 ,-18 ,97 ,-13 ,100 ,-12 ,99 ,
+ -12 ,95 ,-10 ,90 ,-8 ,87 ,-6 ,86 ,-4 ,83 ,
+ -3 ,82 ,-5 ,80 ,-6 ,79 ,-7 ,74 ,-6 ,63 ,
+ -3 ,52 ,0 ,42 ,1 ,31 );
+
+ g_poly_fig6 : array[0..61 ] of double = (
+ 12 ,31 ,12 ,24 ,8 ,21 ,3 ,21 ,2 ,24 ,
+ 3 ,30 ,5 ,40 ,8 ,47 ,10 ,56 ,11 ,64 ,
+ 11 ,71 ,10 ,76 ,8 ,77 ,8 ,79 ,10 ,81 ,
+ 13 ,82 ,17 ,82 ,26 ,84 ,28 ,87 ,32 ,86 ,
+ 33 ,81 ,32 ,80 ,25 ,79 ,17 ,79 ,14 ,79 ,
+ 13 ,76 ,14 ,72 ,14 ,64 ,13 ,55 ,12 ,44 ,
+ 12 ,34 );
+
+var
+ g_npaths : unsigned;
+ g_pflag : filling_rule_e;
+ g_angle : double;
+
+ g_attr : array[0..2 ] of path_attributes;
+ g_path : path_storage;
+
+ g_rasterizer : rasterizer_scanline_aa;
+ g_scanline : scanline_p8;
+
+//AGG_POLY_SIZE: sizeof(p ) / (sizeof(double ) * 2
+
+type
+ the_application = object(platform_support )
+ m_dx ,
+ m_dy : double;
+
+ m_rotate ,
+ m_even_odd ,
+ m_draft ,
+ m_roundoff : cbox_ctrl;
+
+ m_angle_delta : slider_ctrl;
+ m_redraw_flag : boolean;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure on_init; virtual;
+ procedure on_resize(sx ,sy : int ); virtual;
+ procedure on_draw; virtual;
+
+ procedure on_idle; virtual;
+ procedure on_ctrl_change; virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ trans_roundoff }
+procedure trans_roundoff(this : trans_affine_ptr; x ,y : double_ptr );
+begin
+ x^:=Floor(x^ + 0.5 );
+ y^:=Floor(y^ + 0.5 );
+
+end;
+
+{ CONSTRUCT }
+constructor path_attributes.Construct;
+begin
+ fill_color.Construct;
+ stroke_color.Construct;
+
+ index :=0;
+ stroke_width:=0;
+
+end;
+
+{ CONSTRUCT }
+constructor path_attributes.Construct(idx : unsigned; fill ,stroke : aggclr_ptr; width : double );
+begin
+ index :=idx;
+ fill_color :=fill^;
+ stroke_color:=stroke^;
+ stroke_width:=width;
+
+end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+var
+ rgbs ,
+ rgbf : aggclr;
+
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+// Controls
+ m_rotate.Construct (10 ,3 ,'Rotate' ,not flip_y_ );
+ m_even_odd.Construct(60 ,3 ,'Even-Odd' ,not flip_y_ );
+ m_draft.Construct (130 ,3 ,'Draft' ,not flip_y_ );
+ m_roundoff.Construct(175 ,3 ,'Roundoff' ,not flip_y_ );
+
+ m_angle_delta.Construct(10 ,21 ,250-10 ,27 ,not flip_y_ );
+ m_angle_delta.label_ ('Step=%4.3f degree' );
+
+ m_redraw_flag:=true;
+
+ m_rotate.text_size_ (7 );
+ m_even_odd.text_size_(7 );
+ m_draft.text_size_ (7 );
+ m_roundoff.text_size_(7 );
+
+ add_ctrl(@m_rotate );
+ add_ctrl(@m_even_odd );
+ add_ctrl(@m_draft );
+ add_ctrl(@m_roundoff );
+ add_ctrl(@m_angle_delta );
+
+ m_angle_delta.value_(0.01 );
+
+// Polygon
+ rgbf.ConstrInt(255 ,255 ,0 );
+ rgbs.ConstrInt(0 ,0 ,0 );
+
+ g_attr[g_npaths ].Construct(
+ g_path.start_new_path ,
+ @rgbf ,@rgbs ,1.0 );
+
+ inc(g_npaths );
+
+ g_path.add_poly(@g_poly_bulb[0 ] ,sizeof(g_poly_bulb ) div (sizeof(double ) * 2 ) ,false ,path_flags_close );
+
+ rgbf.ConstrInt(255 ,255 ,200 );
+ rgbs.ConstrInt(90 ,0 ,0 );
+
+ g_attr[g_npaths ].Construct(
+ g_path.start_new_path ,
+ @rgbf ,@rgbs ,0.7 );
+
+ inc(g_npaths );
+
+ g_path.add_poly(@g_poly_beam1[0 ] ,sizeof(g_poly_beam1 ) div (sizeof(double ) * 2 ) ,false ,path_flags_close );
+ g_path.add_poly(@g_poly_beam2[0 ] ,sizeof(g_poly_beam2 ) div (sizeof(double ) * 2 ) ,false ,path_flags_close );
+ g_path.add_poly(@g_poly_beam3[0 ] ,sizeof(g_poly_beam3 ) div (sizeof(double ) * 2 ) ,false ,path_flags_close );
+ g_path.add_poly(@g_poly_beam4[0 ] ,sizeof(g_poly_beam4 ) div (sizeof(double ) * 2 ) ,false ,path_flags_close );
+
+ rgbf.ConstrInt(0 ,0 ,0 );
+ rgbs.ConstrInt(0 ,0 ,0 );
+
+ g_attr[g_npaths ].Construct(
+ g_path.start_new_path ,
+ @rgbf ,@rgbs ,0.0 );
+
+ inc(g_npaths );
+
+ g_path.add_poly(@g_poly_fig1[0 ] ,sizeof(g_poly_fig1 ) div (sizeof(double ) * 2 ) );
+ g_path.add_poly(@g_poly_fig2[0 ] ,sizeof(g_poly_fig2 ) div (sizeof(double ) * 2 ) );
+ g_path.add_poly(@g_poly_fig3[0 ] ,sizeof(g_poly_fig3 ) div (sizeof(double ) * 2 ) );
+ g_path.add_poly(@g_poly_fig4[0 ] ,sizeof(g_poly_fig4 ) div (sizeof(double ) * 2 ) );
+ g_path.add_poly(@g_poly_fig5[0 ] ,sizeof(g_poly_fig5 ) div (sizeof(double ) * 2 ) );
+ g_path.add_poly(@g_poly_fig6[0 ] ,sizeof(g_poly_fig6 ) div (sizeof(double ) * 2 ) );
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_rotate.Destruct;
+ m_even_odd.Destruct;
+ m_draft.Destruct;
+ m_roundoff.Destruct;
+
+ m_angle_delta.Destruct;
+
+end;
+
+{ ON_INIT }
+procedure the_application.on_init;
+begin
+ m_dx:=rbuf_window._width;
+ m_dy:=rbuf_window._height;
+
+end;
+
+{ ON_RESIZE }
+procedure the_application.on_resize;
+begin
+ m_redraw_flag:=true;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ pixf : pixel_formats;
+
+ rbase : renderer_base;
+
+ r : renderer_scanline_aa_solid;
+ rb : renderer_scanline_bin_solid;
+
+ rgba : aggclr;
+
+ gm_no : vertex_source;
+ gm_th : gamma_threshold;
+
+ mtx : trans_affine;
+ tar : trans_affine_rotation;
+ tat : trans_affine_translation;
+ tas : trans_affine_scaling;
+
+ roundoff : trans_affine;
+
+ fill ,fill_roundoff : conv_transform;
+
+ stroke ,stroke_roundoff : conv_stroke;
+
+ i : unsigned;
+
+begin
+// Initialize structures
+ pixfmt(pixf ,rbuf_window );
+
+ rbase.Construct(@pixf );
+ r.Construct (@rbase );
+ rb.Construct (@rbase );
+
+ roundoff.Construct(@trans_roundoff );
+
+// Render the controls
+ if m_redraw_flag then
+ begin
+ gm_no.Construct;
+ g_rasterizer.gamma(@gm_no );
+
+ rgba.ConstrInt(255 ,255 ,255 );
+ rbase.clear (@rgba );
+
+ g_rasterizer.filling_rule(fill_non_zero );
+
+ render_ctrl(@g_rasterizer ,@g_scanline ,@r ,@m_rotate );
+ render_ctrl(@g_rasterizer ,@g_scanline ,@r ,@m_even_odd );
+ render_ctrl(@g_rasterizer ,@g_scanline ,@r ,@m_draft );
+ render_ctrl(@g_rasterizer ,@g_scanline ,@r ,@m_roundoff );
+ render_ctrl(@g_rasterizer ,@g_scanline ,@r ,@m_angle_delta );
+
+ m_redraw_flag:=false;
+
+ end
+ else
+ begin
+ rgba.ConstrInt(255 ,255 ,255 );
+ rbase.copy_bar(
+ 0 ,trunc(32.0 * rbuf_window._height / m_dy ) ,
+ rbuf_window._width ,rbuf_window._height ,
+ @rgba );
+
+ end;
+
+
+// Draft mode
+ if m_draft._status then
+ begin
+ gm_th.Construct (0.4 );
+ g_rasterizer.gamma(@gm_th );
+
+ end;
+
+// Rotate polygon
+ tar.Construct(g_angle * pi / 180.0 );
+ tat.Construct(m_dx / 2 ,m_dy / 2 + 10 );
+ tas.Construct(rbuf_window._width / m_dx ,rbuf_window._height / m_dy );
+
+ mtx.Construct;
+ mtx.reset;
+ mtx.multiply(@tar );
+ mtx.multiply(@tat );
+ mtx.multiply(@tas );
+
+ fill.Construct (@g_path ,@mtx );
+ fill_roundoff.Construct(@fill ,@roundoff );
+
+ stroke.Construct (@fill );
+ stroke_roundoff.Construct(@fill_roundoff );
+
+ if m_even_odd._status then
+ g_pflag:=fill_even_odd
+ else
+ g_pflag:=fill_non_zero;
+
+// Render polygon
+ for i:=0 to g_npaths - 1 do
+ begin
+ g_rasterizer.filling_rule(g_pflag );
+
+ r.color_ (@g_attr[i ].fill_color );
+ rb.color_(@g_attr[i ].fill_color );
+
+ if m_roundoff._status then
+ g_rasterizer.add_path(@fill_roundoff ,g_attr[i ].index )
+ else
+ g_rasterizer.add_path(@fill ,g_attr[i ].index );
+
+ if m_draft._status then
+ render_scanlines(@g_rasterizer ,@g_scanline ,@rb )
+ else
+ render_scanlines(@g_rasterizer ,@g_scanline ,@r );
+
+ if g_attr[i ].stroke_width > 0.001 then
+ begin
+ r.color_ (@g_attr[i ].stroke_color );
+ rb.color_(@g_attr[i ].stroke_color );
+
+ stroke.width_ (g_attr[i ].stroke_width * mtx.scale );
+ stroke_roundoff.width_(g_attr[i ].stroke_width * mtx.scale );
+
+ if m_roundoff._status then
+ g_rasterizer.add_path(@stroke_roundoff ,g_attr[i ].index )
+ else
+ g_rasterizer.add_path(@stroke ,g_attr[i ].index );
+
+ if m_draft._status then
+ render_scanlines(@g_rasterizer ,@g_scanline ,@rb )
+ else
+ render_scanlines(@g_rasterizer ,@g_scanline ,@r );
+
+ end;
+
+ end;
+
+// Free AGG resources
+ stroke.Destruct;
+ stroke_roundoff.Destruct;
+
+end;
+
+{ ON_IDLE }
+procedure the_application.on_idle;
+begin
+ g_angle:=g_angle + m_angle_delta._value;
+
+ if g_angle > 360.0 then
+ g_angle:=g_angle - 360.0;
+
+ force_redraw;
+
+end;
+
+{ ON_CTRL_CHANGE }
+procedure the_application.on_ctrl_change;
+begin
+ wait_mode_(not m_rotate._status );
+
+ m_redraw_flag:=true;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ 'The polygons for this "idea" were taken from the book "Dynamic HTML in Action" '#13 +
+ 'by Eric Schurman. An example of using Microsoft Direct Animation can be found here: '#13 +
+ '"http://www.antigrain.com/demo/ideaDA.html." If you use Microsoft Internet Explorer '#13 +
+ 'you can compare the quality of rendering in AGG and Microsoft Direct Animation. '#13 +
+ 'Note that even when you click "Rotate with High Quality", you will see it "jitters". '#13 +
+ 'It''s because there are actually no Subpixel Accuracy used in the Microsoft Direct '#13 +
+ 'Animation.In the AGG example, there''s no jitter even in the "Draft" (low quality) '#13 +
+ 'mode. You can see the simulated jittering if you turn on the "Roundoff" mode, in which '#13 +
+ 'there integer pixel coordinated are used. As for the performance, note, that the image '#13 +
+ 'in AGG is rotated with step of 0.01 degree (initially), while in the Direct Animation '#13 +
+ 'Example the angle step is 0.1 degree.' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+VAR
+ app : the_application;
+
+BEGIN
+ g_npaths:=0;
+ g_pflag :=fill_non_zero;
+ g_angle :=0.0;
+
+ g_path.Construct;
+ g_rasterizer.Construct;
+ g_scanline.Construct;
+
+ app.Construct(pix_format ,flip_y );
+ app.caption_ ('AGG Example. Idea (F1-Help)' );
+
+ if app.init(250 ,280 ,window_resize ) then
+ app.run;
+
+ app.Destruct;
+
+ g_rasterizer.Destruct;
+ g_scanline.Destruct;
+ g_path.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/image1.dpr b/src/corelib/render/software/agg-demos/image1.dpr
new file mode 100644
index 00000000..48dd3ef1
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/image1.dpr
@@ -0,0 +1,295 @@
+{mac_copy:spheres.bmp}
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ image1 ;
+
+{$DEFINE AGG_BGR24 }
+
+uses
+ SysUtils ,
+
+ agg_basics ,
+ agg_platform_support ,
+
+ agg_ctrl ,
+ agg_slider_ctrl ,
+
+ agg_rasterizer_scanline_aa ,
+ agg_scanline ,
+ agg_scanline_u ,
+
+ agg_rendering_buffer ,
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_render_scanlines ,
+
+ agg_ellipse ,
+ agg_trans_affine ,
+ agg_conv_transform ,
+ agg_span_allocator ,
+ agg_span_interpolator_linear ,
+ agg_span_image_filter ,
+ agg_span_image_filter_rgb ,
+ agg_span_image_filter_rgba ,
+ agg_span_image_filter_gray ,
+ agg_image_filters ,
+ file_utils_
+
+{$I pixel_formats.inc }
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+type
+ the_application = object(platform_support )
+ m_angle ,
+ m_scale : slider_ctrl;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure on_draw; virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_angle.Construct(5 ,5 ,300 ,12 ,not flip_y_ );
+ m_scale.Construct(5 ,5 + 15 ,300 ,12 + 15 ,not flip_y_ );
+
+ add_ctrl(@m_angle );
+ add_ctrl(@m_scale );
+
+ m_angle.label_('Angle=%3.2f' );
+ m_scale.label_('Scale=%3.2f' );
+ m_angle.range_(-180.0 ,180.0 );
+ m_angle.value_(0.0 );
+ m_scale.range_(0.1 ,5.0 );
+ m_scale.value_(1.0 );
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_angle.Destruct;
+ m_scale.Destruct;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ pixf ,pixf_pre : pixel_formats;
+
+ rgba : aggclr;
+
+ rb ,rb_pre : renderer_base;
+
+ rs : renderer_scanline_aa_solid;
+ pf : rasterizer_scanline_aa;
+ sl : scanline_u8;
+ sa : span_allocator;
+ sg : span_image_filter_ptr;
+ ri : renderer_scanline_aa;
+ tr : conv_transform;
+ fi : image_filter;
+
+ filter : image_filter_base_ptr;
+
+ interpolator : span_interpolator_linear;
+
+ src_mtx ,img_mtx : trans_affine;
+
+ tat : trans_affine_translation;
+ tar : trans_affine_rotation;
+ tas : trans_affine_scaling;
+
+ ell : ellipse;
+
+ r : double;
+
+begin
+ sg :=NIL;
+ filter:=NIL;
+
+// Initialize structures
+ pixfmt (pixf ,rbuf_window );
+ pixfmt_pre(pixf_pre ,rbuf_window );
+
+ rb.Construct (@pixf );
+ rb_pre.Construct(@pixf_pre );
+ rs.Construct (@rb );
+
+ rgba.ConstrDbl(1.0 ,1.0 ,1.0 );
+ rb.clear (@rgba );
+
+ pf.Construct;
+ sl.Construct;
+
+// Calc
+ src_mtx.Construct;
+
+ tat.Construct(-_initial_width / 2 - 10 ,-_initial_height / 2 - 20 - 10 ); src_mtx.multiply(@tat );
+ tar.Construct(m_angle._value * pi / 180.0 ); src_mtx.multiply(@tar );
+ tas.Construct(m_scale._value ); src_mtx.multiply(@tas );
+ tat.Construct(_initial_width / 2 ,_initial_height / 2 + 20 ); src_mtx.multiply(@tat );
+
+ src_mtx.multiply(_trans_affine_resizing );
+
+ img_mtx.Construct;
+
+ tat.Construct(-_initial_width / 2 + 10 ,-_initial_height / 2 + 20 + 10 ); img_mtx.multiply(@tat );
+ tar.Construct(m_angle._value * pi / 180.0 ); img_mtx.multiply(@tar );
+ tas.Construct(m_scale._value ); img_mtx.multiply(@tas );
+ tat.Construct(_initial_width / 2 ,_initial_height / 2 + 20 ); img_mtx.multiply(@tat );
+
+ img_mtx.multiply(_trans_affine_resizing );
+ img_mtx.invert;
+
+ sa.Construct;
+ interpolator.Construct(@img_mtx );
+
+ rgba.ConstrPre(0 ,0.4 ,0 ,0.5 );
+
+// Version without filtering (nearest neighbor)
+{ sg:=new(
+ span_image_filter_rgb_nn_ptr ,
+ Construct(@sa ,rbuf_img(0 ) ,@rgba ,@interpolator ,component_order ) );{}
+
+// Version with "hardcoded" bilinear filter
+ sg:=new(
+ span_image_filter_rgb_bilinear_ptr ,
+ Construct(@sa ,rbuf_img(0 ) ,@rgba ,@interpolator ,component_order ) );{}
+
+// Version with arbitrary filter
+{ filter:=new(image_filter_mitchell_ptr ,Construct );
+
+ fi.Construct(filter );
+ sg:=new(
+ span_image_filter_rgb_ptr ,
+ Construct(@sa ,rbuf_img(0 ) ,@rgba ,@interpolator ,@fi ,component_order ) );{}
+
+// Render
+ ri.Construct(@rb_pre ,sg );
+
+ r:=_initial_width;
+
+ if _initial_height - 60 < r then
+ r:=_initial_height - 60;
+
+ ell.Construct(
+ _initial_width / 2.0 + 10 ,
+ _initial_height / 2.0 + 20 + 10 ,
+ r / 2.0 + 16.0 ,
+ r / 2.0 + 16.0 ,200 );
+
+ tr.Construct(@ell ,@src_mtx );
+
+ pf.add_path (@tr );
+ render_scanlines(@pf ,@sl ,@ri );
+
+// Render the controls
+ render_ctrl(@pf ,@sl ,@rs ,@m_angle );
+ render_ctrl(@pf ,@sl ,@rs ,@m_scale );
+
+// Free AGG resources
+ pf.Destruct;
+ sl.Destruct;
+
+ sa.Destruct;
+
+ if sg <> NIL then
+ dispose(sg ,Destruct );
+
+ if filter <> NIL then
+ begin
+ dispose(filter );
+
+ fi.Destruct;
+
+ end;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ 'This is the first example with the new "reincarnation" of the image transformation '#13 +
+ 'algorithms. The example allows you to rotate and scale the image with respect to '#13 +
+ 'its center. Also, the image is scaled when resizing the window.'#13#13 +
+ 'How to play with:'#13#13 +
+ 'Try to recompile the source code with different image filtering methods.' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+VAR
+ app : the_application;
+ buf : array [0..255 ] of char;
+ ext : string[10 ];
+
+ img_name ,p ,n ,x : shortstring;
+
+BEGIN
+ app.Construct(pix_format ,flip_y );
+ app.caption_ ('Image Affine Transformations with filtering (F1-Help)' );
+
+ img_name:='spheres';
+
+{$IFDEF WIN32 }
+ if ParamCount > 0 then
+ begin
+ spread_name(ParamStr(1 ) ,p ,n ,x );
+
+ img_name:=fold_name(p ,n ,'' );
+
+ end;
+
+{$ENDIF }
+
+ if not app.load_img(0 ,img_name ) then
+ begin
+ img_name:=img_name + #0;
+ ext :=app._img_ext + #0;
+
+ if img_name = 'spheres'#0 then
+ begin
+ sprintf(@buf[0 ] ,'File not found: %s' ,ptrcomp(@img_name[1 ] ) );
+ sprintf(@buf[StrLen(@buf ) ] ,'%s. '#13'Download http://www.antigrain.com/' ,ptrcomp(@ext[1 ] ) );
+ sprintf(@buf[StrLen(@buf ) ] ,'%s' ,ptrcomp(@img_name[1 ] ) );
+ sprintf(@buf[StrLen(@buf ) ] ,'%s'#13'or copy it from another directory if available.' ,ptrcomp(@ext[1 ] ) );
+
+ end
+ else
+ begin
+ sprintf(@buf[0 ] ,'File not found: %s' ,ptrcomp(@img_name[1 ] ) );
+ sprintf(@buf[StrLen(@buf ) ] ,'%s' ,ptrcomp(@ext[1 ] ) );
+
+ end;
+
+ app.message_(@buf[0 ] );
+
+ end
+ else
+ if app.init(app.rbuf_img(0 )._width + 20 ,app.rbuf_img(0 )._height + 40 + 20 ,window_resize ) then
+ app.run;
+
+ app.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/image_alpha.dpr b/src/corelib/render/software/agg-demos/image_alpha.dpr
new file mode 100644
index 00000000..b0845946
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/image_alpha.dpr
@@ -0,0 +1,351 @@
+{mac_copy:spheres.bmp}
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ image_alpha ;
+
+uses
+ SysUtils ,
+
+ agg_basics ,
+ agg_platform_support ,
+
+ agg_color ,
+ agg_pixfmt ,
+ agg_pixfmt_rgb ,
+
+ agg_ctrl ,
+ agg_spline_ctrl ,
+
+ agg_rendering_buffer ,
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_rasterizer_scanline_aa ,
+ agg_scanline ,
+ agg_scanline_u ,
+ agg_render_scanlines ,
+
+ agg_ellipse ,
+ agg_trans_affine ,
+ agg_conv_transform ,
+ agg_span_image_filter_rgb ,
+ agg_span_interpolator_linear ,
+ agg_span_converter ,
+ agg_span_allocator ,
+ file_utils_ ;
+
+{$I agg_mode.inc }
+{$I- }
+const
+ flip_y = true;
+
+ array_size = 256 * 3;
+
+type
+ span_conv_brightness_alpha_rgb8 = object(span_convertor )
+ m_alpha_array : int8u_ptr;
+
+ constructor Construct(alpha_array : int8u_ptr );
+
+ procedure convert(span : aggclr_ptr; x ,y : int; len : unsigned ); virtual;
+
+ end;
+
+ the_application = object(platform_support )
+ m_alpha : spline_ctrl;
+
+ m_x ,
+ m_y ,
+ m_rx ,
+ m_ry : array[0..49 ] of double;
+
+ m_colors : array[0..49 ] of aggclr;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure on_init; virtual;
+ procedure on_draw; virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ CONSTRUCT }
+constructor span_conv_brightness_alpha_rgb8.Construct;
+begin
+ m_alpha_array:=alpha_array;
+
+end;
+
+{ CONVERT }
+procedure span_conv_brightness_alpha_rgb8.convert;
+begin
+ repeat
+ span.a:=
+ int8u_ptr(
+ ptrcomp(m_alpha_array ) +
+ (span.r + span.g + span.b ) * sizeof(int8u ) )^;
+
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_alpha.Construct(2 ,2 ,200 ,30 ,6 ,not flip_y_ );
+
+ m_alpha.value_(0 ,1.0 );
+ m_alpha.value_(1 ,1.0 );
+ m_alpha.value_(2 ,1.0 );
+ m_alpha.value_(3 ,0.5 );
+ m_alpha.value_(4 ,0.5 );
+ m_alpha.value_(5 ,1.0 );
+ m_alpha.update_spline;
+
+ add_ctrl(@m_alpha );
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_alpha.Destruct;
+
+end;
+
+{ ON_INIT }
+procedure the_application.on_init;
+var
+ i : int;
+
+begin
+ for i:=0 to 49 do
+ begin
+ m_x [i ]:=Random($7fff ) mod trunc(_width );
+ m_y [i ]:=Random($7fff ) mod trunc(_height );
+ m_rx[i ]:=Random($7fff ) mod 60 + 10;
+ m_ry[i ]:=Random($7fff ) mod 60 + 10;
+
+ m_colors[i ].ConstrInt(
+ Random($7fff ) and $FF ,
+ Random($7fff ) and $FF ,
+ Random($7fff ) and $FF ,
+ Random($7fff ) and $FF );
+
+ end;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ pixf : pixel_formats;
+ rgba : aggclr;
+
+ rb : renderer_base;
+ rs : renderer_scanline_aa_solid;
+ sa : span_allocator;
+ sg : span_image_filter_rgb_bilinear;
+ sc : span_converter;
+ ri : renderer_scanline_aa;
+ sl : scanline_u8;
+ tr : conv_transform;
+
+ ras : rasterizer_scanline_aa;
+ ell : ellipse;
+
+ interpolator : span_interpolator_linear;
+
+ src_mtx ,img_mtx : trans_affine;
+
+ tat : trans_affine_translation;
+ tar : trans_affine_rotation;
+
+ i : unsigned;
+
+ brightness_alpha_array : array[0..array_size - 1 ] of int8u;
+
+ color_alpha : span_conv_brightness_alpha_rgb8;
+
+begin
+// Initialize structures
+ pixfmt_bgr24(pixf ,rbuf_window );
+
+ rb.Construct(@pixf );
+ rs.Construct(@rb );
+
+ rgba.ConstrDbl(1.0 ,1.0 ,1.0 );
+ rb.clear (@rgba );
+
+// Compute
+ src_mtx.Construct;
+
+ tat.Construct(-_initial_width / 2 ,-_initial_height / 2 ); src_mtx.multiply(@tat );
+ tar.Construct(10.0 * pi / 180.0 ); src_mtx.multiply(@tar );
+ tat.Construct(_initial_width / 2 ,_initial_height / 2 ); src_mtx.multiply(@tat );
+
+ src_mtx.multiply(_trans_affine_resizing );
+
+ img_mtx.Construct;
+ img_mtx.assign(@src_mtx );
+ img_mtx.invert;
+
+ for i:=0 to array_size - 1 do
+ brightness_alpha_array[i ]:=
+ int8u(trunc(m_alpha._value(i / array_size ) * 255.0 ) );
+
+ color_alpha.Construct(@brightness_alpha_array );
+
+// Render
+ sa.Construct;
+ interpolator.Construct(@img_mtx );
+
+ rgba.ConstrDbl(1 ,1 ,1 ,0 );
+ sg.Construct (@sa ,rbuf_img(0 ) ,@rgba ,@interpolator ,bgr_order );
+
+ sc.Construct(@sg ,@color_alpha );
+ ri.Construct(@rb ,@sc );
+
+ ell.Construct;
+ ras.Construct;
+ sl.Construct;
+
+ for i:=0 to 49 do
+ begin
+ ell.init (m_x[i ] ,m_y[i ] ,m_rx[i ] ,m_ry[i ] ,50 );
+ rs.color_(@m_colors[i ] );
+
+ ras.add_path (@ell );
+ render_scanlines(@ras ,@sl ,@rs );
+
+ end;
+
+ ell.init(
+ _initial_width / 2.0 ,
+ _initial_height / 2.0 ,
+ _initial_width / 1.9 ,
+ _initial_height / 1.9 ,200 );
+
+ tr.Construct (@ell ,@src_mtx );
+ ras.add_path (@tr );
+ render_scanlines(@ras ,@sl ,@ri );
+
+// Render the controls
+ render_ctrl(@ras ,@sl ,@rs ,@m_alpha );
+
+// Free AGG resources
+ ras.Destruct;
+ sl.Destruct;
+
+ sa.Destruct;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+var
+ fd : text;
+
+ i ,alpha : int;
+
+begin
+ if key = byte(' ' ) then
+ begin
+ AssignFile(fd ,'alpha' );
+ rewrite (fd );
+
+ for i:=0 to array_size - 1 do
+ begin
+ alpha:=
+ int8u(trunc(m_alpha._value(i / array_size ) * 255.0 ) );
+
+ if i mod 32 = 0 then
+ writeln(fd );
+
+ write(fd ,alpha:3 ,', ' );
+
+ end;
+
+ close(fd );
+
+ end;
+
+ if key = key_f1 then
+ message_(
+ 'A very powerful feature that allows you to simulate the alpha-channel on the basis '#13 +
+ 'of some functioon. In this example it''s brightness, but it can be of any complexity. '#13 +
+ 'In the example you can form the brightness function and watch for the translucency.'#13#13 +
+ 'How to play with:'#13#13 +
+ 'Resize the windows to move the image over the background.'#13 +
+ 'Press the spacebar to write down file "alpha" with current alpha values.' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+VAR
+ app : the_application;
+ buf : array [0..255 ] of char;
+ ext : string[10 ];
+
+ img_name ,p ,n ,x : shortstring;
+
+BEGIN
+ app.Construct(pix_format_bgr24 ,flip_y );
+ app.caption_ ('Image Affine Transformations with Alpha-function (F1-Help)' );
+
+ img_name:='spheres';
+
+{$IFDEF WIN32 }
+ if ParamCount > 0 then
+ begin
+ spread_name(ParamStr(1 ) ,p ,n ,x );
+
+ img_name:=fold_name(p ,n ,'' );
+
+ end;
+
+{$ENDIF }
+
+ if not app.load_img(0 ,img_name ) then
+ begin
+ img_name:=img_name + #0;
+ ext :=app._img_ext + #0;
+
+ if img_name = 'spheres'#0 then
+ begin
+ sprintf(@buf[0 ] ,'File not found: %s' ,ptrcomp(@img_name[1 ] ) );
+ sprintf(@buf[StrLen(@buf ) ] ,'%s. '#13'Download http://www.antigrain.com/' ,ptrcomp(@ext[1 ] ) );
+ sprintf(@buf[StrLen(@buf ) ] ,'%s' ,ptrcomp(@img_name[1 ] ) );
+ sprintf(@buf[StrLen(@buf ) ] ,'%s'#13'or copy it from another directory if available.' ,ptrcomp(@ext[1 ] ) );
+
+ end
+ else
+ begin
+ sprintf(@buf[0 ] ,'File not found: %s' ,ptrcomp(@img_name[1 ] ) );
+ sprintf(@buf[StrLen(@buf ) ] ,'%s' ,ptrcomp(@ext[1 ] ) );
+
+ end;
+
+ app.message_(@buf[0 ] );
+
+ end
+ else
+ if app.init(app.rbuf_img(0 )._width ,app.rbuf_img(0 )._height ,window_resize ) then
+ app.run;
+
+ app.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/image_filters.dpr b/src/corelib/render/software/agg-demos/image_filters.dpr
new file mode 100644
index 00000000..73a60778
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/image_filters.dpr
@@ -0,0 +1,616 @@
+{mac_copy:spheres.bmp}
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ image_filters ;
+
+uses
+ SysUtils ,
+
+ agg_basics ,
+ agg_platform_support ,
+
+ agg_color ,
+ agg_pixfmt ,
+ agg_pixfmt_rgb ,
+
+ agg_ctrl ,
+ agg_slider_ctrl ,
+ agg_rbox_ctrl ,
+ agg_cbox_ctrl ,
+
+ agg_rendering_buffer ,
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_rasterizer_scanline_aa ,
+ agg_scanline ,
+ agg_scanline_u ,
+ agg_scanline_p ,
+ agg_render_scanlines ,
+
+ agg_ellipse ,
+ agg_trans_affine ,
+ agg_conv_transform ,
+ agg_conv_stroke ,
+ agg_span_allocator ,
+ agg_span_interpolator_linear ,
+ agg_span_image_filter ,
+ agg_span_image_filter_rgb ,
+ agg_image_filters ,
+ agg_gsv_text ,
+ file_utils_ ;
+
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+ pixfmt : define_pixfmt = pixfmt_bgr24;
+ pixfmt_pre : define_pixfmt = pixfmt_bgr24_pre;
+
+type
+ the_application = object(platform_support )
+ m_radius ,
+ m_step : slider_ctrl;
+ m_filters : rbox_ctrl;
+ m_normalize ,
+ m_run ,
+ m_single_step ,
+ m_refresh : cbox_ctrl;
+
+ m_cur_angle : double;
+ m_cur_filter ,
+ m_num_steps : int;
+
+ m_num_pix ,
+ m_time1 ,
+ m_time2 : double;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure on_draw; virtual;
+
+ procedure transform_image(angle : double );
+
+ procedure on_ctrl_change; virtual;
+ procedure on_idle; virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+var
+ rgba : aggclr;
+
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_step.Construct (115 ,5 ,400 ,11 ,not flip_y_ );
+ m_radius.Construct (115 ,5 + 15 ,400 ,11 + 15 ,not flip_y_ );
+ m_filters.Construct (0.0 ,0.0 ,110.0 ,210.0 ,not flip_y_ );
+ m_normalize.Construct (8.0 ,215.0 ,'Normalize Filter' ,not flip_y_ );
+ m_run.Construct (8.0 ,245.0 ,'RUN Test!' ,not flip_y_ );
+ m_single_step.Construct(8.0 ,230.0 ,'Single Step' ,not flip_y_ );
+ m_refresh.Construct (8.0 ,265.0 ,'Refresh' ,not flip_y_ );
+
+ m_cur_angle :=0.0;
+ m_cur_filter:=1;
+ m_num_steps :=0;
+
+ m_num_pix:=0.0;
+ m_time1 :=0;
+ m_time2 :=0;
+
+ add_ctrl(@m_radius );
+ add_ctrl(@m_step );
+ add_ctrl(@m_filters );
+ add_ctrl(@m_run );
+ add_ctrl(@m_single_step );
+ add_ctrl(@m_normalize );
+ add_ctrl(@m_refresh );
+
+ m_run.text_size_ (7.5 );
+ m_single_step.text_size_(7.5 );
+ m_normalize.text_size_ (7.5 );
+ m_refresh.text_size_ (7.5 );
+ m_normalize.status_ (true );
+
+ m_radius.label_('Filter Radius=%.3f' );
+ m_step.label_ ('Step=%3.2f' );
+ m_radius.range_(2.0 ,8.0 );
+ m_radius.value_(4.0 );
+ m_step.range_ (1.0 ,10.0 );
+ m_step.value_ (5.0 );
+
+ m_filters.add_item ('simple (NN)' );
+ m_filters.add_item ('bilinear' );
+ m_filters.add_item ('bicubic' );
+ m_filters.add_item ('spline16' );
+ m_filters.add_item ('spline36' );
+ m_filters.add_item ('hanning' );
+ m_filters.add_item ('hamming' );
+ m_filters.add_item ('hermite' );
+ m_filters.add_item ('kaiser' );
+ m_filters.add_item ('quadric' );
+ m_filters.add_item ('catrom' );
+ m_filters.add_item ('gaussian' );
+ m_filters.add_item ('bessel' );
+ m_filters.add_item ('mitchell' );
+ m_filters.add_item ('sinc' );
+ m_filters.add_item ('lanczos' );
+ m_filters.add_item ('blackman' );
+ m_filters.cur_item_(1 );
+
+ m_filters.border_width_ (0 ,0 );
+ rgba.ConstrDbl (0.0 ,0.0 ,0.0 ,0.1 );
+ m_filters.background_color_(@rgba );
+ m_filters.text_size_ (6.0 );
+ m_filters.text_thickness_ (0.85 );
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_step.Destruct;
+ m_radius.Destruct;
+ m_filters.Destruct;
+ m_normalize.Destruct;
+ m_run.Destruct;
+ m_single_step.Destruct;
+ m_refresh.Destruct;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ pixf : pixel_formats;
+ rgba : aggclr;
+
+ rb : renderer_base;
+ rs : renderer_scanline_aa_solid;
+
+ ras : rasterizer_scanline_aa;
+ sl : scanline_p8;
+
+ t : gsv_text;
+ pt : conv_stroke;
+
+ buf : array[0..63 ] of char;
+
+begin
+// Initialize structures
+ pixfmt(pixf ,rbuf_window );
+
+ rb.Construct(@pixf );
+ rs.Construct(@rb );
+
+ rgba.ConstrDbl(1.0 ,1.0 ,1.0 );
+ rb.clear (@rgba );
+ rb.copy_from (rbuf_img(0 ) ,NIL ,110 ,35 );
+
+ ras.Construct;
+ sl.Construct;
+
+// Text
+ sprintf(@buf[0 ] ,'NSteps=%d' ,m_num_steps );
+
+ t.Construct;
+ t.start_point_(10.0 ,295.0 );
+ t.size_ (10.0 );
+ t.text_ (@buf[0 ] );
+
+ pt.Construct(@t );
+ pt.width_ (1.5 );
+
+ ras.add_path (@pt );
+ rgba.ConstrDbl (0 ,0 ,0 );
+ rs.color_ (@rgba );
+ render_scanlines(@ras ,@sl ,@rs );
+
+// Time
+ if (m_time1 <> m_time2 ) and
+ (m_num_pix > 0.0 ) then
+ begin
+ sprintf(@buf[0 ] ,'%3.2f Kpix/sec' ,m_num_pix / (m_time2 - m_time1 ) );
+
+ t.start_point_ (10.0 ,310.0 );
+ t.text_ (@buf[0 ] );
+ ras.add_path (@pt );
+ render_scanlines(@ras ,@sl ,@rs );
+
+ end;
+
+// Render the controls
+ if m_filters._cur_item >= 14 then
+ render_ctrl(@ras ,@sl ,@rs ,@m_radius );
+
+ render_ctrl(@ras ,@sl ,@rs ,@m_step );
+ render_ctrl(@ras ,@sl ,@rs ,@m_filters );
+ render_ctrl(@ras ,@sl ,@rs ,@m_run );
+ render_ctrl(@ras ,@sl ,@rs ,@m_normalize );
+ render_ctrl(@ras ,@sl ,@rs ,@m_single_step );
+ render_ctrl(@ras ,@sl ,@rs ,@m_refresh );
+
+// Free AGG resources
+ ras.Destruct;
+ sl.Destruct;
+
+ t.Destruct;
+ pt.Destruct;
+
+end;
+
+{ TRANSFORM_IMAGE }
+procedure the_application.transform_image;
+var
+ width_ ,height_ : double;
+ pixf ,pixf_pre : pixel_formats;
+
+ rb ,rb_pre : renderer_base;
+
+ rgba : aggclr;
+
+ ras : rasterizer_scanline_aa;
+ ell : ellipse;
+
+ sl : scanline_u8;
+ sa : span_allocator;
+ tr : conv_transform;
+ fi : image_filter_base_ptr;
+ sg : span_image_filter_ptr;
+ ri : renderer_scanline_aa;
+
+ filter : image_filter_lut;
+
+ interpolator : span_interpolator_linear;
+
+ src_mtx ,img_mtx : trans_affine;
+
+ tat : trans_affine_translation;
+ tar : trans_affine_rotation;
+
+ r : double;
+
+ norm : boolean;
+
+begin
+ fi:=NIL;
+ sg:=NIL;
+
+// Initialize
+ width_ :=rbuf_img(0 )._width;
+ height_:=rbuf_img(0 )._height;
+
+ pixfmt (pixf ,rbuf_img(0 ) );
+ pixfmt_pre(pixf_pre , rbuf_img(0 ) );
+
+ rb.Construct (@pixf );
+ rb_pre.Construct(@pixf_pre );
+
+ rgba.ConstrDbl(1.0 ,1.0 ,1.0 );
+ rb.clear (@rgba );
+
+ ras.Construct;
+ sl.Construct;
+ sa.Construct;
+
+ src_mtx.Construct;
+
+ tat.Construct(-width_ / 2.0 ,-height_ / 2.0 ); src_mtx.multiply(@tat );
+ tar.Construct(angle * pi / 180.0 ); src_mtx.multiply(@tar );
+ tat.Construct(width_ / 2.0 ,height_ / 2.0 ); src_mtx.multiply(@tat );
+
+ img_mtx.Construct;
+
+ img_mtx:=src_mtx;
+
+ img_mtx.invert;
+
+ r:=width_;
+
+ if height_ < r then
+ r:=height_;
+
+ r:=r * 0.5;
+ r:=r - 4.0;
+
+ ell.Construct(width_ / 2.0 ,height_ / 2.0 ,r ,r ,200 );
+ tr.Construct (@ell ,@src_mtx );
+
+ m_num_pix:=m_num_pix + (r * r * pi );
+
+ interpolator.Construct(@img_mtx );
+
+ filter.Construct;
+
+ norm:=m_normalize._status;
+
+ rgba.ConstrDbl(0 ,0 ,0 ,0 );
+
+// Render
+ case m_filters._cur_item of
+ 0 :
+ begin
+ sg:=new(
+ span_image_filter_rgb_nn_ptr ,
+ Construct(
+ @sa ,rbuf_img(1 ) ,@rgba ,@interpolator ,bgr_order ) );
+
+ ri.Construct (@rb_pre ,sg );
+ ras.add_path (@tr );
+ render_scanlines(@ras ,@sl ,@ri );
+
+ end;
+
+ 1 :
+ begin
+ sg:=new(
+ span_image_filter_rgb_bilinear_ptr ,
+ Construct(
+ @sa ,rbuf_img(1) ,@rgba ,@interpolator ,bgr_order ) );
+
+ ri.Construct (@rb_pre ,sg );
+ ras.add_path (@tr );
+ render_scanlines(@ras ,@sl ,@ri );
+
+ end;
+
+ 5 ,6 ,7 :
+ begin
+ case m_filters._cur_item of
+ 5 : fi:=new(image_filter_hanning_ptr ,Construct );
+ 6 : fi:=new(image_filter_hamming_ptr ,Construct );
+ 7 : fi:=new(image_filter_hermite_ptr ,Construct );
+
+ end;
+
+ filter.calculate(fi ,norm );
+
+ sg:=new(
+ span_image_filter_rgb_2x2_ptr ,
+ Construct(
+ @sa ,rbuf_img(1) ,@rgba ,@interpolator ,@filter ,bgr_order ) );
+
+ ri.Construct (@rb_pre ,sg );
+ ras.add_path (@tr );
+ render_scanlines(@ras ,@sl ,@ri );
+
+ end;
+
+ 2 ,3 ,4 ,8 ,9 ,10 ,11 ,12 ,13 ,14 ,15 ,16 :
+ begin
+ case m_filters._cur_item of
+ 2 : fi:=new(image_filter_bicubic_ptr ,Construct );
+ 3 : fi:=new(image_filter_spline16_ptr ,Construct );
+ 4 : fi:=new(image_filter_spline36_ptr ,Construct );
+ 8 : fi:=new(image_filter_kaiser_ptr ,Construct );
+ 9 : fi:=new(image_filter_quadric_ptr ,Construct );
+ 10 : fi:=new(image_filter_catrom_ptr ,Construct );
+ 11 : fi:=new(image_filter_gaussian_ptr ,Construct );
+ 12 : fi:=new(image_filter_bessel_ptr ,Construct );
+ 13 : fi:=new(image_filter_mitchell_ptr ,Construct );
+ 14 : fi:=new(image_filter_sinc_ptr ,Construct(m_radius._value ) );
+ 15 : fi:=new(image_filter_lanczos_ptr ,Construct(m_radius._value ) );
+ 16 : fi:=new(image_filter_blackman_ptr ,Construct(m_radius._value ) );
+
+ end;
+
+ filter.calculate(fi ,norm );
+
+ sg:=new(
+ span_image_filter_rgb_ptr ,
+ Construct(
+ @sa ,rbuf_img(1) ,@rgba ,@interpolator ,@filter ,bgr_order ) );
+
+ ri.Construct (@rb_pre ,sg );
+ ras.add_path (@tr );
+ render_scanlines(@ras ,@sl ,@ri );
+
+ end;
+
+ end;
+
+// Free
+ ras.Destruct;
+ sl.Destruct;
+ sa.Destruct;
+
+ filter.Destruct;
+
+ if sg <> NIL then
+ dispose(sg ,Destruct );
+
+ if fi <> NIL then
+ dispose(fi );
+
+end;
+
+{ ON_CTRL_CHANGE }
+procedure the_application.on_ctrl_change;
+begin
+ if m_single_step._status then
+ begin
+ m_cur_angle:=m_cur_angle + m_step._value;
+
+ copy_img_to_img(1 ,0 );
+ transform_image(m_step._value );
+
+ inc(m_num_steps );
+
+ force_redraw;
+
+ m_single_step.status_(false );
+
+ end;
+
+ if m_run._status then
+ begin
+ start_timer;
+
+ m_time1:=elapsed_time;
+ m_time2:=m_time1;
+
+ m_num_pix:=0.0;
+
+ wait_mode_(false );
+
+ end;
+
+ if m_refresh._status or
+ (m_filters._cur_item <> m_cur_filter ) then
+ begin
+ start_timer;
+
+ m_time1:=0;
+ m_time2:=0;
+
+ m_num_pix :=0.0;
+ m_cur_angle:=0.0;
+
+ copy_img_to_img(1 ,2 );
+ transform_image(0.0 );
+
+ m_refresh.status_(false );
+
+ m_cur_filter:=m_filters._cur_item;
+ m_num_steps :=0;
+
+ force_redraw;
+
+ end;
+
+end;
+
+{ ON_IDLE }
+procedure the_application.on_idle;
+begin
+ if m_run._status then
+ begin
+ if m_cur_angle < 360.0 then
+ begin
+ m_cur_angle:=m_cur_angle + m_step._value;
+
+ copy_img_to_img(1 ,0 );
+ start_timer;
+ transform_image(m_step._value );
+
+ m_time2:=m_time2 + elapsed_time;
+
+ inc(m_num_steps );
+
+ end
+ else
+ begin
+ m_cur_angle:=0.0;
+
+ wait_mode_ (true );
+ m_run.status_(false );
+
+ end;
+
+ force_redraw;
+
+ end
+ else
+ wait_mode_(true );
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ 'The image transformer algorithm can work with different interpolation filters, '#13 +
+ 'such as Bilinear, Bicubic, Sinc, Blackman. The example demonstrates the difference '#13 +
+ 'in quality between different filters. When switch the "Run Test" on, the image '#13 +
+ 'starts rotating. But at each step there is the previously rotated image taken, '#13 +
+ 'so the quality degrades. This degradation as well as the performance depend on '#13 +
+ 'the type of the interpolation filter.' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+VAR
+ app : the_application;
+ buf : array [0..255 ] of char;
+ ext : string[10 ];
+
+ img_name ,p ,n ,x : shortstring;
+
+ w ,h : unsigned;
+
+BEGIN
+ app.Construct(pix_format_bgr24 ,flip_y );
+ app.caption_ ('Image transformation filters comparison (F1-Help)' );
+
+ img_name:='spheres';
+
+{$IFDEF WIN32 }
+ if ParamCount > 0 then
+ begin
+ spread_name(ParamStr(1 ) ,p ,n ,x );
+
+ img_name:=fold_name(p ,n ,'' );
+
+ end;
+
+{$ENDIF }
+
+ if not app.load_img(0 ,img_name ) then
+ begin
+ img_name:=img_name + #0;
+ ext :=app._img_ext + #0;
+
+ if img_name = 'spheres'#0 then
+ begin
+ sprintf(@buf[0 ] ,'File not found: %s' ,ptrcomp(@img_name[1 ] ) );
+ sprintf(@buf[StrLen(@buf ) ] ,'%s. '#13'Download http://www.antigrain.com/' ,ptrcomp(@ext[1 ] ) );
+ sprintf(@buf[StrLen(@buf ) ] ,'%s' ,ptrcomp(@img_name[1 ] ) );
+ sprintf(@buf[StrLen(@buf ) ] ,'%s'#13'or copy it from another directory if available.' ,ptrcomp(@ext[1 ] ) );
+
+ end
+ else
+ begin
+ sprintf(@buf[0 ] ,'File not found: %s' ,ptrcomp(@img_name[1 ] ) );
+ sprintf(@buf[StrLen(@buf ) ] ,'%s' ,ptrcomp(@ext[1 ] ) );
+
+ end;
+
+ app.message_(@buf[0 ] );
+
+ end
+ else
+ begin
+ app.copy_img_to_img(1 ,0 );
+ app.copy_img_to_img(2 ,0 );
+ app.transform_image(0.0 );
+
+ w:=app.rbuf_img(0 )._width + 110;
+ h:=app.rbuf_img(0 )._height + 40;
+
+ if w < 305 then
+ w:=305;
+
+ if h < 325 then
+ h:=325;
+
+ if app.init(w ,h ,0 ) then
+ app.run;
+
+ end;
+
+ app.Destruct;
+
+END.
diff --git a/src/corelib/render/software/agg-demos/image_filters2.dpr b/src/corelib/render/software/agg-demos/image_filters2.dpr
new file mode 100644
index 00000000..3f90bef5
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/image_filters2.dpr
@@ -0,0 +1,412 @@
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ image_filters2 ;
+
+uses
+ SysUtils ,
+
+ agg_basics ,
+ agg_platform_support ,
+
+ agg_color ,
+ agg_pixfmt ,
+ agg_pixfmt_rgb ,
+
+ agg_ctrl ,
+ agg_slider_ctrl ,
+ agg_rbox_ctrl ,
+ agg_cbox_ctrl ,
+
+ agg_rendering_buffer ,
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_rasterizer_scanline_aa ,
+ agg_scanline ,
+ agg_scanline_u ,
+ agg_scanline_p ,
+ agg_render_scanlines ,
+
+ agg_ellipse ,
+ agg_trans_affine ,
+ agg_conv_transform ,
+ agg_conv_stroke ,
+ agg_span_allocator ,
+ agg_span_interpolator_linear ,
+ agg_span_image_filter ,
+ agg_span_image_filter_rgb ,
+ agg_image_filters ,
+ agg_gsv_text ,
+ agg_gamma_lut ,
+ agg_path_storage ;
+
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+ g_image : array[0..47 ] of int8u = (
+
+ 0,255,0, 0,0,255, 255,255,255, 255,0,0,
+ 255,0,0, 0,0,0, 255,255,255, 255,255,255,
+ 255,255,255, 255,255,255, 0,0,255, 255,0,0,
+ 0,0,255, 255,255,255, 0,0,0, 0,255,0 );
+
+type
+ the_application = object(platform_support )
+ m_gamma ,
+ m_radius : slider_ctrl;
+
+ m_filters : rbox_ctrl;
+ m_normalize : cbox_ctrl;
+
+ m_cur_angle : double;
+ m_cur_filter ,
+ m_num_steps : int;
+
+ m_num_pix ,
+ m_time1 ,
+ m_time2 : double;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure on_draw; virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+var
+ rgba : aggclr;
+
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_gamma.Construct (115 ,5 ,500 - 5 ,11 ,not flip_y_ );
+ m_radius.Construct (115 ,5 + 15 ,500 - 5 ,11 + 15 ,not flip_y_ );
+ m_filters.Construct (0.0 ,0.0 ,110.0 ,210.0 ,not flip_y_ );
+ m_normalize.Construct(8.0 ,215.0 ,'Normalize Filter' ,not flip_y_ );
+
+ m_cur_angle :=0.0;
+ m_cur_filter:=1;
+ m_num_steps :=0;
+
+ m_num_pix:=0.0;
+ m_time1 :=0;
+ m_time2 :=0;
+
+ add_ctrl(@m_gamma );
+ add_ctrl(@m_radius );
+ add_ctrl(@m_filters );
+ add_ctrl(@m_normalize );
+
+ m_normalize.text_size_(7.5 );
+ m_normalize.status_ (true );
+
+ m_radius.label_('Filter Radius=%.3f' );
+ m_radius.range_(2.0 ,8.0 );
+ m_radius.value_(4.0 );
+
+ m_gamma.label_('Gamma=%.3f' );
+ m_gamma.range_(0.5 ,3.0 );
+ m_gamma.value_(1.0 );
+
+ m_filters.add_item ('simple (NN)' );
+ m_filters.add_item ('bilinear' );
+ m_filters.add_item ('bicubic' );
+ m_filters.add_item ('spline16' );
+ m_filters.add_item ('spline36' );
+ m_filters.add_item ('hanning' );
+ m_filters.add_item ('hamming' );
+ m_filters.add_item ('hermite' );
+ m_filters.add_item ('kaiser' );
+ m_filters.add_item ('quadric' );
+ m_filters.add_item ('catrom' );
+ m_filters.add_item ('gaussian' );
+ m_filters.add_item ('bessel' );
+ m_filters.add_item ('mitchell' );
+ m_filters.add_item ('sinc' );
+ m_filters.add_item ('lanczos' );
+ m_filters.add_item ('blackman' );
+ m_filters.cur_item_(1 );
+
+ m_filters.border_width_ (0 ,0 );
+ rgba.ConstrDbl (0.0 ,0.0 ,0.0 ,0.1 );
+ m_filters.background_color_(@rgba );
+ m_filters.text_size_ (6.0 );
+ m_filters.text_thickness_ (0.85 );
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_gamma.Destruct;
+ m_radius.Destruct;
+ m_filters.Destruct;
+ m_normalize.Destruct;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+const
+ para : array[0..7 ] of double = (200 ,40 ,200 + 300 ,40 ,200 + 300 ,40 + 300 ,200 ,40 + 300 );
+
+var
+ pixf : pixel_formats;
+ rgba : aggclr;
+
+ rb : renderer_base;
+ rs : renderer_scanline_aa_solid;
+ sl : scanline_u8;
+ sa : span_allocator;
+ ri : renderer_scanline_aa;
+ sg : span_image_filter_ptr;
+ fi : image_filter_base_ptr;
+
+ ras : rasterizer_scanline_aa;
+
+ norm : boolean;
+
+ gamma : gamma_lut;
+ stroke : conv_stroke;
+ filter : image_filter_lut;
+
+ img_rbuf : rendering_buffer;
+ img_mtx : trans_affine;
+ weights : int16_ptr;
+
+ interpolator : span_interpolator_linear;
+
+ x_start ,x_end ,y_start ,y_end ,x_center ,x ,ys ,radius ,dx ,dy ,xs : double;
+
+ i ,n ,nn : unsigned;
+
+ p : path_storage;
+
+begin
+ sg:=NIL;
+ fi:=NIL;
+
+// Initialize structures
+ pixfmt_bgr24(pixf ,rbuf_window );
+
+ rb.Construct(@pixf );
+ rs.Construct(@rb );
+
+ rgba.ConstrDbl(1.0 ,1.0 ,1.0 );
+ rb.clear (@rgba );
+ rb.copy_from (rbuf_img(0 ) ,0 ,110 ,35 );
+
+ ras.Construct;
+ sl.Construct;
+ img_rbuf.Construct(@g_image[0 ] ,4 ,4 ,4 * 3 );
+
+// Render
+ img_mtx.Construct(@para[0 ] ,0 ,0 ,4 ,4 );
+
+ interpolator.Construct(@img_mtx );
+ sa.Construct;
+
+ ras.reset;
+ ras.move_to_d(para[0 ] ,para[1 ] );
+ ras.line_to_d(para[2 ] ,para[3 ] );
+ ras.line_to_d(para[4 ] ,para[5 ] );
+ ras.line_to_d(para[6 ] ,para[7 ] );
+
+ rgba.ConstrDbl(1 ,1 ,1 );
+ filter.Construct;
+
+ case m_filters._cur_item of
+ 0 :
+ begin
+ sg:=new(
+ span_image_filter_rgb_nn_ptr ,
+ Construct(
+ @sa ,@img_rbuf ,@rgba ,@interpolator ,bgr_order ) );
+
+ ri.Construct (@rb ,sg );
+ render_scanlines(@ras ,@sl ,@ri );
+
+ end;
+
+ 1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 ,11 ,12 ,13 ,14 ,15 ,16 :
+ begin
+ norm:=m_normalize._status;
+
+ case m_filters._cur_item of
+ 1 : fi:=new(image_filter_bilinear_ptr ,Construct );
+ 2 : fi:=new(image_filter_bicubic_ptr ,Construct );
+ 3 : fi:=new(image_filter_spline16_ptr ,Construct );
+ 4 : fi:=new(image_filter_spline36_ptr ,Construct );
+ 5 : fi:=new(image_filter_hanning_ptr ,Construct );
+ 6 : fi:=new(image_filter_hamming_ptr ,Construct );
+ 7 : fi:=new(image_filter_hermite_ptr ,Construct );
+ 8 : fi:=new(image_filter_kaiser_ptr ,Construct );
+ 9 : fi:=new(image_filter_quadric_ptr ,Construct );
+ 10 : fi:=new(image_filter_catrom_ptr ,Construct );
+ 11 : fi:=new(image_filter_gaussian_ptr ,Construct );
+ 12 : fi:=new(image_filter_bessel_ptr ,Construct );
+ 13 : fi:=new(image_filter_mitchell_ptr ,Construct );
+ 14 : fi:=new(image_filter_sinc_ptr ,Construct(m_radius._value ) );
+ 15 : fi:=new(image_filter_lanczos_ptr ,Construct(m_radius._value ) );
+ 16 : fi:=new(image_filter_blackman_ptr ,Construct(m_radius._value ) );
+
+ end;
+
+ filter.calculate(fi ,norm );
+
+ sg:=new(
+ span_image_filter_rgb_ptr ,
+ Construct(
+ @sa ,@img_rbuf ,@rgba ,@interpolator ,@filter ,bgr_order ) );
+
+ ri.Construct (@rb ,sg );
+ render_scanlines(@ras ,@sl ,@ri );
+
+ // Draw Graph
+ gamma.Construct (m_gamma._value );
+ pixf.apply_gamma_inv(@gamma ,bgr_order );
+
+ x_start :=5.0;
+ x_end :=195.0;
+ y_start :=235.0;
+ y_end :=_initial_height - 5.0;
+ x_center:=(x_start + x_end ) / 2;
+
+ p.Construct;
+ stroke.Construct(@p );
+ stroke.width_ (0.8 );
+
+ for i:=0 to 16 do
+ begin
+ x:=x_start + (x_end - x_start ) * i / 16.0;
+
+ p.remove_all;
+ p.move_to(x + 0.5 ,y_start );
+ p.line_to(x + 0.5 ,y_end );
+
+ ras.add_path(@stroke);
+
+ if i = 8 then
+ rgba.ConstrInt(0 ,0 ,0 ,255 )
+ else
+ rgba.ConstrInt(0 ,0 ,0 ,100 );
+
+ rs.color_ (@rgba );
+ render_scanlines(@ras ,@sl ,@rs );
+
+ end;
+
+ ys:=y_start + (y_end - y_start ) / 6.0;
+
+ p.remove_all;
+ p.move_to(x_start ,ys );
+ p.line_to(x_end ,ys );
+
+ ras.add_path (@stroke);
+ rgba.ConstrInt (0 ,0 ,0 );
+ rs.color_ (@rgba );
+ render_scanlines(@ras ,@sl ,@rs );
+
+ radius:=filter.radius;
+
+ n :=trunc(radius * 256 * 2 );
+ dx:=(x_end - x_start ) * radius / 8.0;
+ dy:=y_end - ys;
+
+ weights:=filter.weight_array;
+
+ xs:=(x_end + x_start ) / 2.0 - (filter.diameter * (x_end - x_start ) / 32.0 );
+ nn:=filter.diameter * 256;
+
+ p.remove_all();
+ p.move_to(xs + 0.5 ,ys + dy * int16_ptr(weights )^ / image_filter_size );
+
+ i:=1;
+
+ while i < nn do
+ begin
+ p.line_to(
+ xs + dx * i / n + 0.5 ,
+ ys + dy * int16_ptr(ptrcomp(weights ) + i * sizeof(int16 ) )^ / image_filter_size );
+
+ inc(i );
+
+ end;
+
+ ras.add_path (@stroke );
+ rgba.ConstrInt (100 ,0 ,0 );
+ rs.color_ (@rgba );
+ render_scanlines(@ras ,@sl ,@rs );
+
+ // Free
+ gamma.Destruct;
+ p.Destruct;
+ stroke.Destruct;
+
+ end;
+
+ end;
+
+// Render the controls
+ render_ctrl(@ras ,@sl ,@rs ,@m_gamma );
+
+ if m_filters._cur_item >= 14 then
+ render_ctrl(@ras ,@sl ,@rs ,@m_radius );
+
+ render_ctrl(@ras ,@sl ,@rs ,@m_filters );
+ render_ctrl(@ras ,@sl ,@rs ,@m_normalize );
+
+// Free AGG resources
+ ras.Destruct;
+ sl.Destruct;
+ img_rbuf.Destruct;
+
+ sa.Destruct;
+ filter.Destruct;
+
+ if sg <> NIL then
+ dispose(sg ,Destruct );
+
+ if fi <> NIL then
+ dispose(fi );
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ 'Another example that demonstrates the difference of image filters. '#13 +
+ 'It just displays a simple 4x4 pixels image with huge zoom. '#13 +
+ 'You can see how different filters affect the result. '#13 +
+ 'Also see how gamma correction works.' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+VAR
+ app : the_application;
+
+BEGIN
+ app.Construct(pix_format_bgr24 ,flip_y );
+ app.caption_ ('Image transformation filters comparison (F1-Help)' );
+
+ if app.init(500 ,340 ,0 ) then
+ app.run;
+
+ app.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/image_fltr_graph.dpr b/src/corelib/render/software/agg-demos/image_fltr_graph.dpr
new file mode 100644
index 00000000..e90d93a3
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/image_fltr_graph.dpr
@@ -0,0 +1,516 @@
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ image_fltr_graph ;
+
+uses
+ Math ,
+
+ agg_basics ,
+ agg_platform_support ,
+
+ agg_color ,
+ agg_pixfmt ,
+ agg_pixfmt_rgb ,
+
+ agg_ctrl ,
+ agg_slider_ctrl ,
+ agg_rbox_ctrl ,
+ agg_cbox_ctrl ,
+
+ agg_rendering_buffer ,
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_rasterizer_scanline_aa ,
+ agg_scanline ,
+ agg_scanline_u ,
+ agg_scanline_p ,
+ agg_render_scanlines ,
+
+ agg_ellipse ,
+ agg_trans_affine ,
+ agg_conv_transform ,
+ agg_conv_stroke ,
+ agg_span_allocator ,
+ agg_span_interpolator_linear ,
+ agg_span_image_filter ,
+ agg_span_image_filter_rgb ,
+ agg_image_filters ,
+ agg_path_storage ;
+
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+type
+ filter_adaptor_ptr = ^filter_adaptor;
+ filter_adaptor = object
+ m_filter : image_filter_base_ptr;
+
+ constructor Construct(filter : image_filter_base_ptr );
+ destructor Destruct;
+
+ function radius : double;
+ function calc_weight(x : double ) : double;
+
+ procedure set_radius(r : double );
+
+ end;
+
+ the_application = object(platform_support )
+ m_radius : slider_ctrl;
+ m_bilinear ,
+ m_bicubic ,
+ m_spline16 ,
+ m_spline36 ,
+ m_hanning ,
+ m_hamming ,
+ m_hermite ,
+ m_kaiser ,
+ m_quadric ,
+ m_catrom ,
+ m_gaussian ,
+ m_bessel ,
+ m_mitchell ,
+ m_sinc ,
+ m_lanczos ,
+ m_blackman : cbox_ctrl;
+
+ m_filters : array[0..31 ] of cbox_ctrl_ptr;
+
+ m_filter_bilinear ,
+ m_filter_bicubic ,
+ m_filter_spline16 ,
+ m_filter_spline36 ,
+ m_filter_hanning ,
+ m_filter_hamming ,
+ m_filter_hermite ,
+ m_filter_kaiser ,
+ m_filter_quadric ,
+ m_filter_catrom ,
+ m_filter_gaussian ,
+ m_filter_bessel ,
+ m_filter_mitchell ,
+ m_filter_sinc ,
+ m_filter_lanczos ,
+ m_filter_blackman : filter_adaptor;
+
+ m_filter_func : array[0..31 ] of filter_adaptor_ptr;
+ m_num_filters : unsigned;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure on_draw; virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ CONSTRUCT }
+constructor filter_adaptor.Construct;
+begin
+ m_filter:=filter;
+
+end;
+
+{ DESTRUCT }
+destructor filter_adaptor.Destruct;
+begin
+ if m_filter <> NIL then
+ dispose(m_filter );
+
+end;
+
+{ RADIUS }
+function filter_adaptor.radius;
+begin
+ if m_filter <> NIL then
+ result:=m_filter.radius
+ else
+ result:=0;
+
+end;
+
+{ CALC_WEIGHT }
+function filter_adaptor.calc_weight;
+begin
+ if m_filter <> NIL then
+ result:=m_filter.calc_weight(Abs(x ) )
+ else
+ result:=0;
+
+end;
+
+{ SET_RADIUS }
+procedure filter_adaptor.set_radius;
+begin
+ if m_filter <> NIL then
+ m_filter.set_radius(r );
+
+end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+var
+ i : unsigned;
+
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_radius.Construct (5.0 ,5.0 ,780 - 5 ,10.0 ,not flip_y_ );
+ m_bilinear.Construct(8.0 ,30.0 + 15 * 0 ,'bilinear' ,not flip_y_ );
+ m_bicubic.Construct (8.0 ,30.0 + 15 * 1 ,'bicubic ' ,not flip_y_ );
+ m_spline16.Construct(8.0 ,30.0 + 15 * 2 ,'spline16' ,not flip_y_ );
+ m_spline36.Construct(8.0 ,30.0 + 15 * 3 ,'spline36' ,not flip_y_ );
+ m_hanning.Construct (8.0 ,30.0 + 15 * 4 ,'hanning ' ,not flip_y_ );
+ m_hamming.Construct (8.0 ,30.0 + 15 * 5 ,'hamming ' ,not flip_y_ );
+ m_hermite.Construct (8.0 ,30.0 + 15 * 6 ,'hermite ' ,not flip_y_ );
+ m_kaiser.Construct (8.0 ,30.0 + 15 * 7 ,'kaiser ' ,not flip_y_ );
+ m_quadric.Construct (8.0 ,30.0 + 15 * 8 ,'quadric ' ,not flip_y_ );
+ m_catrom.Construct (8.0 ,30.0 + 15 * 9 ,'catrom ' ,not flip_y_ );
+ m_gaussian.Construct(8.0 ,30.0 + 15 * 10 ,'gaussian' ,not flip_y_ );
+ m_bessel.Construct (8.0 ,30.0 + 15 * 11 ,'bessel ' ,not flip_y_ );
+ m_mitchell.Construct(8.0 ,30.0 + 15 * 12 ,'mitchell' ,not flip_y_ );
+ m_sinc.Construct (8.0 ,30.0 + 15 * 13 ,'sinc ' ,not flip_y_ );
+ m_lanczos.Construct (8.0 ,30.0 + 15 * 14 ,'lanczos ' ,not flip_y_ );
+ m_blackman.Construct(8.0 ,30.0 + 15 * 15 ,'blackman' ,not flip_y_ );
+
+ m_filter_bilinear.Construct(new(image_filter_bilinear_ptr ,Construct ) );
+ m_filter_bicubic.Construct (new(image_filter_bicubic_ptr ,Construct ) );
+ m_filter_spline16.Construct(new(image_filter_spline16_ptr ,Construct ) );
+ m_filter_spline36.Construct(new(image_filter_spline36_ptr ,Construct ) );
+ m_filter_hanning.Construct (new(image_filter_hanning_ptr ,Construct ) );
+ m_filter_hamming.Construct (new(image_filter_hamming_ptr ,Construct ) );
+ m_filter_hermite.Construct (new(image_filter_hermite_ptr ,Construct ) );
+ m_filter_kaiser.Construct (new(image_filter_kaiser_ptr ,Construct ) );
+ m_filter_quadric.Construct (new(image_filter_quadric_ptr ,Construct ) );
+ m_filter_catrom.Construct (new(image_filter_catrom_ptr ,Construct ) );
+ m_filter_gaussian.Construct(new(image_filter_gaussian_ptr ,Construct ) );
+ m_filter_bessel.Construct (new(image_filter_bessel_ptr ,Construct ) );
+ m_filter_mitchell.Construct(new(image_filter_mitchell_ptr ,Construct ) );
+ m_filter_sinc.Construct (new(image_filter_sinc_ptr ,Construct(2.0 ) ) );
+ m_filter_lanczos.Construct (new(image_filter_lanczos_ptr ,Construct(2.0 ) ) );
+ m_filter_blackman.Construct(new(image_filter_blackman_ptr ,Construct(2.0 ) ) );
+
+ m_num_filters:=0;
+
+ m_filters[m_num_filters ]:=@m_bilinear; inc(m_num_filters );
+ m_filters[m_num_filters ]:=@m_bicubic; inc(m_num_filters );
+ m_filters[m_num_filters ]:=@m_spline16; inc(m_num_filters );
+ m_filters[m_num_filters ]:=@m_spline36; inc(m_num_filters );
+ m_filters[m_num_filters ]:=@m_hanning; inc(m_num_filters );
+ m_filters[m_num_filters ]:=@m_hamming; inc(m_num_filters );
+ m_filters[m_num_filters ]:=@m_hermite; inc(m_num_filters );
+ m_filters[m_num_filters ]:=@m_kaiser; inc(m_num_filters );
+ m_filters[m_num_filters ]:=@m_quadric; inc(m_num_filters );
+ m_filters[m_num_filters ]:=@m_catrom; inc(m_num_filters );
+ m_filters[m_num_filters ]:=@m_gaussian; inc(m_num_filters );
+ m_filters[m_num_filters ]:=@m_bessel; inc(m_num_filters );
+ m_filters[m_num_filters ]:=@m_mitchell; inc(m_num_filters );
+ m_filters[m_num_filters ]:=@m_sinc; inc(m_num_filters );
+ m_filters[m_num_filters ]:=@m_lanczos; inc(m_num_filters );
+ m_filters[m_num_filters ]:=@m_blackman; inc(m_num_filters );
+
+ i:=0;
+
+ m_filter_func[i ]:=@m_filter_bilinear; inc(i );
+ m_filter_func[i ]:=@m_filter_bicubic; inc(i );
+ m_filter_func[i ]:=@m_filter_spline16; inc(i );
+ m_filter_func[i ]:=@m_filter_spline36; inc(i );
+ m_filter_func[i ]:=@m_filter_hanning; inc(i );
+ m_filter_func[i ]:=@m_filter_hamming; inc(i );
+ m_filter_func[i ]:=@m_filter_hermite; inc(i );
+ m_filter_func[i ]:=@m_filter_kaiser; inc(i );
+ m_filter_func[i ]:=@m_filter_quadric; inc(i );
+ m_filter_func[i ]:=@m_filter_catrom; inc(i );
+ m_filter_func[i ]:=@m_filter_gaussian; inc(i );
+ m_filter_func[i ]:=@m_filter_bessel; inc(i );
+ m_filter_func[i ]:=@m_filter_mitchell; inc(i );
+ m_filter_func[i ]:=@m_filter_sinc; inc(i );
+ m_filter_func[i ]:=@m_filter_lanczos; inc(i );
+ m_filter_func[i ]:=@m_filter_blackman; inc(i );
+
+ for i:=0 to m_num_filters - 1 do
+ add_ctrl(m_filters[i ] );
+
+ m_radius.range_(2.0 ,8.0 );
+ m_radius.value_(4.0 );
+ m_radius.label_('Radius=%.3f' );
+
+ add_ctrl(@m_radius );
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_radius.Destruct;
+ m_bilinear.Destruct;
+ m_bicubic.Destruct;
+ m_spline16.Destruct;
+ m_spline36.Destruct;
+ m_hanning.Destruct;
+ m_hamming.Destruct;
+ m_hermite.Destruct;
+ m_kaiser.Destruct;
+ m_quadric.Destruct;
+ m_catrom.Destruct;
+ m_gaussian.Destruct;
+ m_bessel.Destruct;
+ m_mitchell.Destruct;
+ m_sinc.Destruct;
+ m_lanczos.Destruct;
+ m_blackman.Destruct;
+
+ m_filter_bilinear.Destruct;
+ m_filter_bicubic.Destruct;
+ m_filter_spline16.Destruct;
+ m_filter_spline36.Destruct;
+ m_filter_hanning.Destruct;
+ m_filter_hamming.Destruct;
+ m_filter_hermite.Destruct;
+ m_filter_kaiser.Destruct;
+ m_filter_quadric.Destruct;
+ m_filter_catrom.Destruct;
+ m_filter_gaussian.Destruct;
+ m_filter_bessel.Destruct;
+ m_filter_mitchell.Destruct;
+ m_filter_sinc.Destruct;
+ m_filter_lanczos.Destruct;
+ m_filter_blackman.Destruct;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ pixf : pixel_formats;
+ rgba : aggclr;
+
+ rb : renderer_base;
+ rs : renderer_scanline_aa_solid;
+ sl : scanline_p8;
+
+ ras : rasterizer_scanline_aa;
+
+ normalized : image_filter_lut;
+ weights : int16_ptr;
+
+ x_start ,x_end ,y_start ,y_end ,x_center ,x ,y ,ys ,radius ,dy ,xs ,dx ,sum ,xf : double;
+
+ xfract ,ir : int;
+
+ i ,j ,n ,xint ,nn : unsigned;
+
+ p : path_storage;
+ pl : conv_stroke;
+ tr : conv_transform;
+
+begin
+// Initialize structures
+ pixfmt_bgr24(pixf ,rbuf_window );
+
+ rb.Construct(@pixf );
+ rs.Construct(@rb );
+
+ rgba.ConstrDbl(1.0 ,1.0 ,1.0 );
+ rb.clear (@rgba );
+
+ ras.Construct;
+ sl.Construct;
+
+// Render
+ x_start :=125.0;
+ x_end :=_initial_width - 15.0;
+ y_start :=10.0;
+ y_end :=_initial_height - 10.0;
+ x_center:=(x_start + x_end ) / 2;
+
+ p.Construct;
+ pl.Construct(@p );
+ tr.Construct(@pl ,_trans_affine_resizing );
+
+ for i:=0 to 15 do
+ begin
+ x:=x_start + (x_end - x_start ) * i / 16.0;
+
+ p.remove_all;
+ p.move_to(x + 0.5 ,y_start );
+ p.line_to(x + 0.5 ,y_end );
+
+ ras.add_path(@tr );
+
+ if i = 8 then
+ rgba.ConstrInt(0 ,0 ,0 ,255 )
+ else
+ rgba.ConstrInt(0 ,0 ,0 ,100 );
+
+ rs.color_ (@rgba );
+ render_scanlines(@ras ,@sl ,@rs );
+
+ end;
+
+ ys:=y_start + (y_end - y_start ) / 6.0;
+
+ p.remove_all;
+ p.move_to (x_start ,ys );
+ p.line_to (x_end ,ys );
+ ras.add_path (@tr );
+ rgba.ConstrInt (0 ,0 ,0 );
+ rs.color_ (@rgba );
+ render_scanlines(@ras ,@sl ,@rs );
+
+ pl.width_(1.0 );
+
+ for i:=0 to m_num_filters - 1 do
+ if m_filters[i ]._status then
+ begin
+ m_filter_func[i ].set_radius(m_radius._value );
+
+ radius:=m_filter_func[i ].radius;
+
+ n :=trunc(radius * 256 * 2 );
+ dy:=y_end - ys;
+
+ xs:=(x_end + x_start ) / 2.0 - (radius * (x_end - x_start ) / 16.0 );
+ dx:=(x_end - x_start ) * radius / 8.0;
+
+ p.remove_all;
+ p.move_to(xs + 0.5 ,ys + dy * m_filter_func[i ].calc_weight(-radius ) );
+
+ j:=1;
+
+ while j < n do
+ begin
+ p.line_to(
+ xs + dx * j / n + 0.5 ,
+ ys + dy * m_filter_func[i ].calc_weight(j / 256.0 - radius ) );
+
+ inc(j );
+
+ end;
+
+ ras.add_path (@tr );
+ rgba.ConstrInt (100 ,0 ,0 );
+ rs.color_ (@rgba );
+ render_scanlines(@ras ,@sl ,@rs );
+
+ p.remove_all;
+
+ ir:=trunc(Ceil(radius ) + 0.1 );
+
+ for xint:=0 to 255 do
+ begin
+ sum:=0;
+
+ xfract:=-ir;
+
+ while xfract < ir do
+ begin
+ xf:=xint / 256.0 + xfract;
+
+ if (xf >= -radius ) or
+ (xf <= radius ) then
+ sum:=sum + m_filter_func[i ].calc_weight(xf );
+
+ inc(xfract );
+
+ end;
+
+ x:=x_center + ((-128.0 + xint ) / 128.0 ) * radius * (x_end - x_start ) / 16.0;
+ y:=ys + sum * 256 - 256;
+
+ if xint = 0 then
+ p.move_to(x ,y )
+ else
+ p.line_to(x ,y );
+
+ end;
+
+ ras.add_path (@tr );
+ rgba.ConstrInt (0 ,100 ,0 );
+ rs.color_ (@rgba );
+ render_scanlines(@ras ,@sl ,@rs );
+
+ normalized.Construct(m_filter_func[i ].m_filter );
+
+ weights:=normalized.weight_array;
+
+ xs:=(x_end + x_start ) / 2.0 - (normalized.diameter * (x_end - x_start ) / 32.0 );
+ nn:=normalized.diameter * 256;
+
+ p.remove_all;
+ p.move_to(xs + 0.5 ,ys + dy * int16_ptr(weights )^ / image_filter_size );
+
+ j:=1;
+
+ while j < nn do
+ begin
+ p.line_to(
+ xs + dx * j / n + 0.5 ,
+ ys + dy * int16_ptr(ptrcomp(weights ) + j * sizeof(int16 ) )^ / image_filter_size );
+
+ inc(j );
+
+ end;
+
+ ras.add_path (@tr );
+ rgba.ConstrInt (0 ,0 ,100 ,255 );
+ rs.color_ (@rgba );
+ render_scanlines(@ras ,@sl ,@rs );
+
+ // Free
+ normalized.Destruct;
+
+ end;
+
+// Render the controls
+ for i:=0 to m_num_filters - 1 do
+ render_ctrl(@ras ,@sl ,@rs ,m_filters[i ] );
+
+ if m_sinc._status or
+ m_lanczos._status or
+ m_blackman._status then
+ render_ctrl(@ras ,@sl ,@rs ,@m_radius );
+
+// Free AGG resources
+ ras.Destruct;
+ sl.Destruct;
+
+ p.Destruct;
+ pl.Destruct;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ 'Demonstration of the shapes of different interpolation filters. '#13 +
+ 'Just in case if you are curious.' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+VAR
+ app : the_application;
+
+BEGIN
+ app.Construct(pix_format_bgr24 ,flip_y );
+ app.caption_ ('Image filters'' shape comparison (F1-Help)' );
+
+ if app.init(780 ,300 ,window_resize ) then
+ app.run;
+
+ app.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/image_perspective.dpr b/src/corelib/render/software/agg-demos/image_perspective.dpr
new file mode 100644
index 00000000..bbbf62f3
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/image_perspective.dpr
@@ -0,0 +1,452 @@
+{mac_copy:spheres.bmp}
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ image_perspective ;
+
+uses
+ Math ,SysUtils ,
+
+ agg_basics ,
+ agg_platform_support ,
+
+ agg_color ,
+ agg_pixfmt ,
+ agg_pixfmt_rgba ,
+
+ agg_ctrl ,
+ agg_rbox_ctrl ,
+
+ agg_rendering_buffer ,
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_rasterizer_scanline_aa ,
+ agg_scanline ,
+ agg_scanline_u ,
+ agg_render_scanlines ,
+
+ agg_path_storage ,
+ agg_conv_transform ,
+ agg_conv_stroke ,
+ agg_trans_affine ,
+ agg_trans_bilinear ,
+ agg_trans_perspective ,
+ agg_span_interpolator_linear ,
+ agg_span_interpolator_trans ,
+ agg_span_subdiv_adaptor ,
+ agg_span_image_filter ,
+ agg_span_image_filter_rgba ,
+ agg_span_allocator ,
+ agg_image_filters ,
+ agg_gsv_text ,
+ interactive_polygon_ ,
+ file_utils_ ;
+
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+var
+ g_x1 ,
+ g_y1 ,
+ g_x2 ,
+ g_y2 : double;
+
+ g_rasterizer : rasterizer_scanline_aa;
+ g_scanline : scanline_u8;
+
+type
+ the_application = object(platform_support )
+ m_quad : interactive_polygon;
+ m_trans_type : rbox_ctrl;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure on_init; virtual;
+ procedure on_draw; virtual;
+
+ procedure on_mouse_move (x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_up (x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_quad.Construct (4 ,5.0 );
+ m_trans_type.Construct(420 ,5.0 ,420 + 170.0 ,70.0 ,not flip_y_ );
+
+ m_trans_type.add_item ('Affine Parallelogram' );
+ m_trans_type.add_item ('Bilinear' );
+ m_trans_type.add_item ('Perspective' );
+ m_trans_type.cur_item_(2 );
+
+ add_ctrl(@m_trans_type );
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_quad.Destruct;
+ m_trans_type.Destruct;
+
+end;
+
+{ ON_INIT }
+procedure the_application.on_init;
+var
+ x1 ,y1 ,x2 ,y2 ,dx ,dy : double;
+
+begin
+ g_x1:=0.0;
+ g_y1:=0.0;
+ g_x2:=rbuf_img(0 )._width;
+ g_y2:=rbuf_img(0 )._height;
+
+ x1:=g_x1;// * 100.0;
+ y1:=g_y1;// * 100.0;
+ x2:=g_x2;// * 100.0;
+ y2:=g_y2;// * 100.0;
+
+ dx:=_width / 2.0 - (x2 - x1 ) / 2.0;
+ dy:=_height / 2.0 - (y2 - y1 ) / 2.0;
+
+{ m_quad.xn_ptr(0 )^:=Floor(x1 + dx + 50 );
+ m_quad.yn_ptr(0 )^:=Floor(y1 + dy + 50 );
+ m_quad.xn_ptr(1 )^:=Floor(x2 + dx );
+ m_quad.yn_ptr(1 )^:=Floor(y1 + dy );
+ m_quad.xn_ptr(2 )^:=Floor(x2 + dx );
+ m_quad.yn_ptr(2 )^:=Floor(y2 + dy );
+ m_quad.xn_ptr(3 )^:=Floor(x1 + dx );
+ m_quad.yn_ptr(3 )^:=Floor(y2 + dy ); {}
+
+ m_quad.xn_ptr(0 )^:=100 + 50;
+ m_quad.yn_ptr(0 )^:=100 + 50;
+ m_quad.xn_ptr(1 )^:=_width - 100;
+ m_quad.yn_ptr(1 )^:=100;
+ m_quad.xn_ptr(2 )^:=_width - 100;
+ m_quad.yn_ptr(2 )^:=_height - 100;
+ m_quad.xn_ptr(3 )^:=100;
+ m_quad.yn_ptr(3 )^:=_height - 100;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ pixf ,pixf_pre : pixel_formats;
+
+ rb ,rb_pre : renderer_base;
+
+ rgba : aggclr;
+
+ r : renderer_scanline_aa_solid;
+ sa : span_allocator;
+ tr : trans_affine;
+ sg : span_image_filter_ptr;
+ ri : renderer_scanline_aa;
+
+ trb : trans_bilinear;
+ trp : trans_perspective;
+
+ interpolator : span_interpolator_linear;
+ interp_trans : span_interpolator_trans;
+ subdiv_adaptor : span_subdiv_adaptor;
+
+ filter_kernel : image_filter_hermite;
+ filter : image_filter_lut;
+
+ tm : double;
+ buf : array[0..63 ] of char;
+ t : gsv_text;
+ pt : conv_stroke;
+
+begin
+ sg:=NIL;
+
+// Initialize structures
+ pixfmt_bgra32 (pixf ,rbuf_window );
+ pixfmt_bgra32_pre(pixf_pre ,rbuf_window );
+
+ rb.Construct (@pixf );
+ rb_pre.Construct(@pixf_pre );
+ r.Construct (@rb );
+
+ rgba.ConstrDbl(1 ,1 ,1 );
+ rb.clear (@rgba );
+
+ if m_trans_type._cur_item = 0 then
+ begin
+ // For the affine parallelogram transformations we
+ // calculate the 4-th (implicit) point of the parallelogram
+ m_quad.xn_ptr(3 )^:=m_quad.xn(0 ) + (m_quad.xn(2 ) - m_quad.xn(1 ) );
+ m_quad.yn_ptr(3 )^:=m_quad.yn(0 ) + (m_quad.yn(2 ) - m_quad.yn(1 ) );
+
+ end;
+
+// Render the "quad" tool
+ g_rasterizer.add_path(@m_quad );
+
+ rgba.ConstrDbl (0 ,0.3 ,0.5 ,0.6 );
+ r.color_ (@rgba );
+ render_scanlines(@g_rasterizer ,@g_scanline ,@r );
+
+// Prepare the polygon to rasterize. Here we need to fill
+// the destination (transformed) polygon.
+ g_rasterizer.clip_box(0 ,0 ,_width ,_height );
+ g_rasterizer.reset;
+ g_rasterizer.move_to_d(m_quad.xn(0 ) ,m_quad.yn(0 ) );
+ g_rasterizer.line_to_d(m_quad.xn(1 ) ,m_quad.yn(1 ) );
+ g_rasterizer.line_to_d(m_quad.xn(2 ) ,m_quad.yn(2 ) );
+ g_rasterizer.line_to_d(m_quad.xn(3 ) ,m_quad.yn(3 ) );
+
+ sa.Construct;
+ filter_kernel.Construct;
+ filter.Construct(@filter_kernel ,false );
+
+ rgba.ConstrPre(0 ,0 ,0 ,0 );
+
+ start_timer;
+
+ case m_trans_type._cur_item of
+ 0 :
+ begin
+ // Note that we consruct an affine matrix that transforms
+ // a parallelogram to a rectangle, i.e., it's inverted.
+ // It's actually the same as:
+ // tr(g_x1, g_y1, g_x2, g_y2, m_triangle.polygon());
+ // tr.invert();
+ tr.Construct(parallelo_ptr(m_quad.polygon ) ,g_x1 ,g_y1 ,g_x2 ,g_y2 );
+
+ // Also note that we can use the linear interpolator instead of
+ // arbitrary span_interpolator_trans. It works much faster,
+ // but the transformations must be linear and parellel.
+ interpolator.Construct(@tr );
+
+ sg:=new(
+ span_image_filter_rgba_nn_ptr ,
+ Construct(
+ @sa ,rbuf_img(0 ) ,@rgba ,@interpolator ,bgra_order ) );
+
+ ri.Construct (@rb_pre ,sg );
+ render_scanlines(@g_rasterizer ,@g_scanline ,@ri );
+
+ end;
+
+ 1 :
+ begin
+ trb.Construct(m_quad.polygon ,g_x1 ,g_y1 ,g_x2 ,g_y2 );
+
+ if trb.is_valid then
+ begin
+ interpolator.Construct(@trb );
+
+ sg:=new(
+ span_image_filter_rgba_2x2_ptr ,
+ Construct(
+ @sa ,rbuf_img(0 ) ,@rgba ,@interpolator ,@filter ,bgra_order ) );
+
+ ri.Construct (@rb_pre ,sg );
+ render_scanlines(@g_rasterizer ,@g_scanline ,@ri );
+
+ end;
+
+ end;
+
+ 2 :
+ begin
+ trp.Construct(pointer(m_quad.polygon ) ,g_x1 ,g_y1 ,g_x2 ,g_y2 );
+
+ if trp.is_valid then
+ begin
+ // interpolator.Construct (@trp );
+ // subdiv_adaptor.Construct(@interpolator );
+
+ interp_trans.Construct(@trp );
+
+ sg:=new(
+ span_image_filter_rgba_2x2_ptr ,
+ Construct(
+ @sa ,rbuf_img(0 ) ,@rgba ,@interp_trans ,@filter ,bgra_order ) );
+
+ ri.Construct (@rb_pre ,sg );
+ render_scanlines(@g_rasterizer ,@g_scanline ,@ri );
+
+ end;
+
+ end;
+
+ end;
+
+// Render Text
+ tm:=elapsed_time;
+
+ t.Construct;
+ t.size_(10.0 );
+
+ pt.Construct(@t );
+ pt.width_ (1.5 );
+
+ sprintf (@buf[0 ] ,'%3.2f ms' ,tm );
+ t.start_point_(10.0 ,10.0 );
+ t.text_ (@buf[0 ] );
+
+ g_rasterizer.add_path(@pt );
+
+ rgba.ConstrDbl (0 ,0 ,0 );
+ r.color_ (@rgba );
+ render_scanlines(@g_rasterizer ,@g_scanline ,@r );
+
+// Render the controls
+ render_ctrl(@g_rasterizer ,@g_scanline ,@r ,@m_trans_type );
+
+// Free AGG resources
+ sa.Destruct;
+ filter.Destruct;
+
+ if sg <> NIL then
+ dispose(sg ,Destruct );
+
+ t.Destruct;
+ pt.Destruct;
+
+end;
+
+{ ON_MOUSE_MOVE }
+procedure the_application.on_mouse_move;
+begin
+ if flags and mouse_left <> 0 then
+ if m_quad.on_mouse_move(x ,y ) then
+ force_redraw;
+
+ if flags and mouse_left = 0 then
+ on_mouse_button_up(x ,y ,flags );
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure the_application.on_mouse_button_down;
+var
+ buf : array[0..99 ] of char;
+
+begin
+ if flags and mouse_left <> 0 then
+ if m_quad.on_mouse_button_down(x ,y ) then
+ force_redraw;
+
+ if flags and mouse_right <> 0 then
+ begin
+ sprintf (@buf[0 ] ,'%d ' ,x );
+ sprintf (@buf[StrLen(@buf ) ] ,'%d' ,y );
+ message_(@buf[0 ] );
+
+ end;
+
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+procedure the_application.on_mouse_button_up;
+begin
+ if m_quad.on_mouse_button_up(x ,y ) then
+ force_redraw;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ 'Image perspective transformations. There are two types of arbitrary quadrangle '#13 +
+ 'transformations, Perspective and Bilinear. The image transformer always uses '#13 +
+ 'reverse transformations, and there is a problem. The Perspective transformations '#13 +
+ 'are perfectly reversible, so they work correctly with images, but the Bilinear '#13 +
+ 'transformer behave somehow strange. It can transform a rectangle to a quadrangle, '#13 +
+ 'but not vice versa. In this example you can see this effect, when the edges of '#13 +
+ 'the image "sag". I''d highly appreciate if someone could help me with math for '#13 +
+ 'transformations similar to Bilinear ones, but correctly reversible (i.e., that '#13 +
+ 'can transform an arbitrary quadrangle to a rectangle). The bilinear transformations '#13 +
+ 'are simple, see agg_trans_bilinear.h and agg_simul_eq.h' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+VAR
+ app : the_application;
+ buf : array [0..255 ] of char;
+ ext : string[10 ];
+
+ img_name ,p ,n ,x : shortstring;
+
+BEGIN
+ g_x1:=0;
+ g_y1:=0;
+ g_x2:=0;
+ g_y2:=0;
+
+ g_rasterizer.Construct;
+ g_scanline.Construct;
+
+ app.Construct(pix_format_bgra32 ,flip_y );
+ app.caption_ ('AGG Example. Image Perspective Transformations (F1-Help)' );
+
+ img_name:='spheres';
+
+{$IFDEF WIN32 }
+ if ParamCount > 0 then
+ begin
+ spread_name(ParamStr(1 ) ,p ,n ,x );
+
+ img_name:=fold_name(p ,n ,'' );
+
+ end;
+
+{$ENDIF }
+
+ if not app.load_img(0 ,img_name ) then
+ begin
+ img_name:=img_name + #0;
+ ext :=app._img_ext + #0;
+
+ if img_name = 'spheres'#0 then
+ begin
+ sprintf(@buf[0 ] ,'File not found: %s' ,ptrcomp(@img_name[1 ] ) );
+ sprintf(@buf[StrLen(@buf ) ] ,'%s. '#13'Download http://www.antigrain.com/' ,ptrcomp(@ext[1 ] ) );
+ sprintf(@buf[StrLen(@buf ) ] ,'%s' ,ptrcomp(@img_name[1 ] ) );
+ sprintf(@buf[StrLen(@buf ) ] ,'%s'#13'or copy it from another directory if available.' ,ptrcomp(@ext[1 ] ) );
+
+ end
+ else
+ begin
+ sprintf(@buf[0 ] ,'File not found: %s' ,ptrcomp(@img_name[1 ] ) );
+ sprintf(@buf[StrLen(@buf ) ] ,'%s' ,ptrcomp(@ext[1 ] ) );
+
+ end;
+
+ app.message_(@buf[0 ] );
+
+ end
+ else
+ if app.init(600 ,600 ,window_resize ) then
+ app.run;
+
+ app.Destruct;
+
+ g_rasterizer.Destruct;
+ g_scanline.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/image_resample.dpr b/src/corelib/render/software/agg-demos/image_resample.dpr
new file mode 100644
index 00000000..5d4688e6
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/image_resample.dpr
@@ -0,0 +1,579 @@
+{mac_copy:spheres.bmp}
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ image_resample ;
+
+uses
+ Math ,SysUtils ,
+
+ agg_basics ,
+ agg_platform_support ,
+
+ agg_color ,
+ agg_pixfmt ,
+ agg_pixfmt_rgba ,
+
+ agg_ctrl ,
+ agg_rbox_ctrl ,
+ agg_slider_ctrl ,
+
+ agg_rendering_buffer ,
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_rasterizer_scanline_aa ,
+ agg_scanline ,
+ agg_scanline_u ,
+ agg_render_scanlines ,
+
+ agg_path_storage ,
+ agg_conv_transform ,
+ agg_conv_stroke ,
+ agg_trans_affine ,
+ agg_trans_perspective ,
+ agg_span_interpolator_linear ,
+ agg_span_interpolator_trans ,
+ agg_span_interpolator_persp ,
+ agg_span_subdiv_adaptor ,
+ agg_span_image_filter ,
+ agg_span_image_filter_rgba ,
+ agg_span_image_resample ,
+ agg_span_image_resample_rgba ,
+ agg_span_allocator ,
+ agg_image_filters ,
+ agg_gsv_text ,
+ agg_gamma_lut ,
+ interactive_polygon_ ,
+ file_utils_ ;
+
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+ base_shift = agg_color.base_shift;
+
+var
+ g_x1 ,
+ g_y1 ,
+ g_x2 ,
+ g_y2 : double;
+
+ global_offset : int;
+
+ g_rasterizer : rasterizer_scanline_aa;
+ g_scanline : scanline_u8;
+
+ img_name ,p ,n ,x : shortstring;
+
+type
+ the_application = object(platform_support )
+ m_gamma_lut : gamma_lut;
+ m_quad : interactive_polygon;
+ m_trans_type : rbox_ctrl;
+ m_gamma ,
+ m_blur : slider_ctrl;
+ m_old_gamma : double;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure on_init; virtual;
+ procedure on_draw; virtual;
+
+ procedure on_mouse_move (x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_up (x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_gamma_lut.Construct(2.0 ,base_shift ,base_shift );
+ m_quad.Construct (4 ,5.0 );
+
+ m_trans_type.Construct(400 ,5.0 ,430 + 170.0 ,100.0 ,not flip_y_ );
+ m_gamma.Construct (5.0 ,5.0 + 15 * 0 ,400-5 ,10.0 + 15 * 0 ,not flip_y_ );
+ m_blur.Construct (5.0 ,5.0 + 15 * 1 ,400-5 ,10.0 + 15 * 1 ,not flip_y_ );
+
+ m_old_gamma:=2.0;
+
+ m_trans_type.text_size_(7 );
+ m_trans_type.add_item ('Affine No Resample' );
+ m_trans_type.add_item ('Affine Resample' );
+ m_trans_type.add_item ('Perspective No Resample LERP' );
+ m_trans_type.add_item ('Perspective No Resample Exact' );
+ m_trans_type.add_item ('Perspective Resample LERP' );
+ m_trans_type.add_item ('Perspective Resample Exact' );
+ m_trans_type.cur_item_ (4 );
+
+ add_ctrl(@m_trans_type );
+
+ m_gamma.range_(0.5 ,3.0 );
+ m_gamma.value_(2.0 );
+ m_gamma.label_('Gamma=%.3f' );
+
+ add_ctrl(@m_gamma );
+
+ m_blur.range_(0.5, 2.0);
+ m_blur.value_(1.0 );
+ m_blur.label_('Blur=%.3f' );
+
+ add_ctrl(@m_blur );
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_gamma_lut.Destruct;
+ m_quad.Destruct;
+
+ m_trans_type.Destruct;
+ m_gamma.Destruct;
+ m_blur.Destruct;
+
+end;
+
+{ ON_INIT }
+procedure the_application.on_init;
+var
+ x1 ,y1 ,x2 ,y2 ,dx ,dy : double;
+
+ pixf : pixel_formats;
+
+begin
+ g_x1:=0.0;
+ g_y1:=0.0;
+ g_x2:=rbuf_img(0 )._width;
+ g_y2:=rbuf_img(0 )._height;
+
+ x1:=g_x1;// * 100.0;
+ y1:=g_y1;// * 100.0;
+ x2:=g_x2;// * 100.0;
+ y2:=g_y2;// * 100.0;
+
+ dx:=_width / 2.0 - (x2 - x1 ) / 2.0;
+ dy:=_height / 2.0 - (y2 - y1 ) / 2.0;
+
+ m_quad.xn_ptr(0 )^:=Floor(x1 + dx );
+ m_quad.yn_ptr(0 )^:=Floor(y1 + dy );// - 150;
+ m_quad.xn_ptr(1 )^:=Floor(x2 + dx );
+ m_quad.yn_ptr(1 )^:=Floor(y1 + dy );// - 110;
+ m_quad.xn_ptr(2 )^:=Floor(x2 + dx );
+ m_quad.yn_ptr(2 )^:=Floor(y2 + dy );// - 300;
+ m_quad.xn_ptr(3 )^:=Floor(x1 + dx );
+ m_quad.yn_ptr(3 )^:=Floor(y2 + dy );// - 200;
+
+ pixfmt_bgra32(pixf ,rbuf_img(0 ) );
+
+ pixf.apply_gamma_dir(@m_gamma_lut ,bgra_order );
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ pixf ,pixf_pre : pixel_formats;
+
+ rb ,rb_pre : renderer_base;
+
+ rgba : aggclr;
+
+ r : renderer_scanline_aa_solid;
+ b : int;
+
+ sa : span_allocator;
+ tr : trans_affine;
+ sg : span_image_filter_ptr;
+ ri : renderer_scanline_aa;
+
+ trp : trans_perspective23;
+
+ interpolator : span_interpolator_linear;
+ interpsubdiv : span_interpolator_linear_subdiv;
+ interp_trans : span_interpolator_trans;
+ interp_plerp : span_interpolator_persp_lerp;
+ interp_exact : span_interpolator_persp_exact;
+ subdiv_adaptor : span_subdiv_adaptor;
+
+ filter_kernel : image_filter_hanning;
+ filter : image_filter_lut;
+
+ tm : double;
+ buf : array[0..63 ] of char;
+ t : gsv_text;
+ pt : conv_stroke;
+
+begin
+ sg:=NIL;
+
+ if m_gamma._value <> m_old_gamma then
+ begin
+ m_gamma_lut.gamma_(m_gamma._value );
+
+ load_img(0 ,img_name );
+
+ pixfmt_bgra32(pixf ,rbuf_img(0 ) );
+
+ pixf.apply_gamma_dir(@m_gamma_lut ,bgra_order );
+
+ m_old_gamma:=m_gamma._value;
+
+ end;
+
+// Initialize structures
+ pixfmt_bgra32 (pixf ,rbuf_window );
+ pixfmt_bgra32_pre(pixf_pre ,rbuf_window );
+
+ rb.Construct (@pixf );
+ rb_pre.Construct(@pixf_pre );
+
+ r.Construct(@rb );
+
+ rgba.ConstrDbl(1 ,1 ,1 );
+ rb.clear (@rgba );
+
+ if m_trans_type._cur_item < 2 then
+ begin
+ // For the affine parallelogram transformations we
+ // calculate the 4-th (implicit) point of the parallelogram
+ m_quad.xn_ptr(3 )^:=m_quad.xn(0 ) + (m_quad.xn(2 ) - m_quad.xn(1 ) );
+ m_quad.yn_ptr(3 )^:=m_quad.yn(0 ) + (m_quad.yn(2 ) - m_quad.yn(1 ) );
+
+ end;
+
+// Render the "quad" tool and controls
+ g_rasterizer.add_path(@m_quad );
+
+ rgba.ConstrDbl (0 ,0.3 ,0.5 ,0.1 );
+ r.color_ (@rgba );
+ render_scanlines(@g_rasterizer ,@g_scanline ,@r );
+
+// Prepare the polygon to rasterize. Here we need to fill
+// the destination (transformed) polygon.
+ g_rasterizer.clip_box(0 ,0 ,_width ,_height );
+ g_rasterizer.reset;
+
+ b:=0;
+
+ g_rasterizer.move_to_d(m_quad.xn(0 ) - b ,m_quad.yn(0 ) - b );
+ g_rasterizer.line_to_d(m_quad.xn(1 ) + b ,m_quad.yn(1 ) - b );
+ g_rasterizer.line_to_d(m_quad.xn(2 ) + b ,m_quad.yn(2 ) + b );
+ g_rasterizer.line_to_d(m_quad.xn(3 ) - b ,m_quad.yn(3 ) + b );
+
+ sa.Construct;
+ filter_kernel.Construct;
+ filter.Construct(@filter_kernel ,true );
+
+ rgba.ConstrPre(0 ,0 ,0 ,0 );
+
+ start_timer;
+
+ case m_trans_type._cur_item of
+ 0 :
+ begin
+ tr.Construct(parallelo_ptr(m_quad.polygon ) ,g_x1 ,g_y1 ,g_x2 ,g_y2 );
+
+ interpolator.Construct(@tr );
+
+ sg:=new(
+ span_image_filter_rgba_2x2_ptr ,
+ Construct(
+ @sa ,rbuf_img(0 ) ,@rgba ,@interpolator ,@filter ,bgra_order ) );
+
+ ri.Construct (@rb_pre ,sg );
+ render_scanlines(@g_rasterizer ,@g_scanline ,@ri );
+
+ end;
+
+ 1 :
+ begin
+ tr.Construct(parallelo_ptr(m_quad.polygon ) ,g_x1 ,g_y1 ,g_x2 ,g_y2 );
+
+ interpolator.Construct(@tr );
+
+ sg:=new(
+ span_image_resample_rgba_affine_ptr ,
+ Construct(
+ @sa ,rbuf_img(0 ) ,@rgba ,@interpolator ,@filter ,bgra_order ) );
+
+ span_image_resample_ptr(sg ).blur_(m_blur._value );
+
+ ri.Construct (@rb_pre ,sg );
+ render_scanlines(@g_rasterizer ,@g_scanline ,@ri );
+
+ end;
+
+ 2 :
+ begin
+ trp.Construct(m_quad.polygon ,g_x1 ,g_y1 ,g_x2 ,g_y2 );
+
+ if trp.is_valid then
+ begin
+ interpsubdiv.Construct(@trp );
+
+ sg:=new(
+ span_image_filter_rgba_2x2_ptr ,
+ Construct(
+ @sa ,rbuf_img(0 ) ,@rgba ,@interpsubdiv ,@filter ,bgra_order ) );
+
+ ri.Construct (@rb_pre ,sg );
+ render_scanlines(@g_rasterizer ,@g_scanline ,@ri );
+
+ end;
+
+ end;
+
+ 3 :
+ begin
+ trp.Construct(m_quad.polygon ,g_x1 ,g_y1 ,g_x2 ,g_y2 );
+
+ if trp.is_valid then
+ begin
+ interp_trans.Construct(@trp );
+
+ sg:=new(
+ span_image_filter_rgba_2x2_ptr ,
+ Construct(
+ @sa ,rbuf_img(0 ) ,@rgba ,@interp_trans ,@filter ,bgra_order ) );
+
+ ri.Construct (@rb_pre ,sg );
+ render_scanlines(@g_rasterizer ,@g_scanline ,@ri );
+
+ end;
+
+ end;
+
+ 4 :
+ begin
+ interp_plerp.Construct (m_quad.polygon ,g_x1 ,g_y1 ,g_x2 ,g_y2 );
+ subdiv_adaptor.Construct(@interp_plerp );
+
+ if interp_plerp.is_valid then
+ begin
+ sg:=new(
+ span_image_resample_rgba_ptr ,
+ Construct(
+ @sa ,rbuf_img(0 ) ,@rgba ,@subdiv_adaptor ,@filter ,bgra_order ) );
+
+ span_image_resample_ptr(sg ).blur_(m_blur._value );
+
+ ri.Construct (@rb_pre ,sg );
+ render_scanlines(@g_rasterizer ,@g_scanline ,@ri );
+
+ end;
+
+ end;
+
+ 5 :
+ begin
+ interp_exact.Construct (m_quad.polygon ,g_x1 ,g_y1 ,g_x2 ,g_y2 );
+ subdiv_adaptor.Construct(@interp_exact );
+
+ if interp_exact.is_valid then
+ begin
+ sg:=new(
+ span_image_resample_rgba_ptr ,
+ Construct(
+ @sa ,rbuf_img(0 ) ,@rgba ,@subdiv_adaptor ,@filter ,bgra_order ) );
+
+ span_image_resample_ptr(sg ).blur_(m_blur._value );
+
+ ri.Construct (@rb_pre ,sg );
+ render_scanlines(@g_rasterizer ,@g_scanline ,@ri );
+
+ end;
+
+ end;
+
+ end;
+
+// Render Text
+ tm:=elapsed_time;
+
+ pixf.apply_gamma_inv(@m_gamma_lut ,bgra_order );
+
+ t.Construct;
+ t.size_(10.0 );
+
+ pt.Construct(@t );
+ pt.width_ (1.5 );
+
+ sprintf (@buf[0 ] ,'%3.2f ms' ,tm );
+ t.start_point_(10.0 ,70.0 );
+ t.text_ (@buf[0 ] );
+
+ g_rasterizer.add_path(@pt );
+
+ rgba.ConstrDbl (0 ,0 ,0 );
+ r.color_ (@rgba );
+ render_scanlines(@g_rasterizer ,@g_scanline ,@r );
+
+// Render the controls
+ render_ctrl(@g_rasterizer ,@g_scanline ,@r ,@m_trans_type );
+ render_ctrl(@g_rasterizer ,@g_scanline ,@r ,@m_gamma );
+ render_ctrl(@g_rasterizer ,@g_scanline ,@r ,@m_blur );
+
+// Free AGG resources
+ sa.Destruct;
+ filter.Destruct;
+
+ if sg <> NIL then
+ dispose(sg ,Destruct );
+
+ t.Destruct;
+ pt.Destruct;
+
+end;
+
+{ ON_MOUSE_MOVE }
+procedure the_application.on_mouse_move;
+begin
+ if flags and mouse_left <> 0 then
+ if m_quad.on_mouse_move(x ,y ) then
+ force_redraw;
+
+ if flags and mouse_left = 0 then
+ on_mouse_button_up(x ,y ,flags );
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure the_application.on_mouse_button_down;
+begin
+ if flags and mouse_left <> 0 then
+ if m_quad.on_mouse_button_down(x ,y ) then
+ force_redraw;
+
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+procedure the_application.on_mouse_button_up;
+begin
+ if m_quad.on_mouse_button_up(x ,y ) then
+ force_redraw;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+var
+ cx ,cy : double;
+
+ tr : trans_affine;
+ tar : trans_affine_rotation;
+ tat : trans_affine_translation;
+
+begin
+ if key = byte(' ' ) then
+ begin
+ cx:=(m_quad.xn(0 ) + m_quad.xn(1 ) + m_quad.xn(2 ) + m_quad.xn(3 ) ) / 4;
+ cy:=(m_quad.yn(0 ) + m_quad.yn(1 ) + m_quad.yn(2 ) + m_quad.yn(3 ) ) / 4;
+
+ tr.Construct;
+ tat.construct(-cx ,-cy );
+
+ tr:=tat;
+
+ tar.Construct(pi / 20{2.0} ); tr.multiply(@tar );
+ tat.Construct(cx ,cy ); tr.multiply(@tat );
+
+ tr.transform(@tr ,m_quad.xn_ptr(0 ) ,m_quad.yn_ptr(0 ) );
+ tr.transform(@tr ,m_quad.xn_ptr(1 ) ,m_quad.yn_ptr(1 ) );
+ tr.transform(@tr ,m_quad.xn_ptr(2 ) ,m_quad.yn_ptr(2 ) );
+ tr.transform(@tr ,m_quad.xn_ptr(3 ) ,m_quad.yn_ptr(3 ) );
+
+ force_redraw;
+
+ end;
+
+ if key = key_f1 then
+ message_(
+ 'The demonstration of image transformations with resampling. '#13 +
+ 'You can see the difference in quality between regular image transformers and '#13 +
+ 'the ones with resampling. Of course, image tranformations with resampling work '#13 +
+ 'slower because they provide the best possible quality.'#13#13 +
+ 'How to play with:'#13#13 +
+ 'Use the left mouse button to manipulate with image.'#13 +
+ 'Press the spacebar to rotate the image by 1/20 of pi.' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+VAR
+ app : the_application;
+ buf : array [0..255 ] of char;
+ ext : string[10 ];
+
+BEGIN
+ g_x1:=0;
+ g_y1:=0;
+ g_x2:=0;
+ g_y2:=0;
+
+ global_offset:=0;
+
+ g_rasterizer.Construct;
+ g_scanline.Construct;
+
+ app.Construct(pix_format_bgra32 ,flip_y );
+ app.caption_ ('AGG Example. Image Transformations with Resampling (F1-Help)' );
+
+ img_name:='spheres';
+
+{$IFDEF WIN32 }
+ if ParamCount > 0 then
+ begin
+ spread_name(ParamStr(1 ) ,p ,n ,x );
+
+ img_name:=fold_name(p ,n ,'' );
+
+ end;
+
+{$ENDIF }
+
+ if not app.load_img(0 ,img_name ) then
+ begin
+ img_name:=img_name + #0;
+ ext :=app._img_ext + #0;
+
+ if img_name = 'spheres'#0 then
+ begin
+ sprintf(@buf[0 ] ,'File not found: %s' ,ptrcomp(@img_name[1 ] ) );
+ sprintf(@buf[StrLen(@buf ) ] ,'%s. '#13'Download http://www.antigrain.com/' ,ptrcomp(@ext[1 ] ) );
+ sprintf(@buf[StrLen(@buf ) ] ,'%s' ,ptrcomp(@img_name[1 ] ) );
+ sprintf(@buf[StrLen(@buf ) ] ,'%s'#13'or copy it from another directory if available.' ,ptrcomp(@ext[1 ] ) );
+
+ end
+ else
+ begin
+ sprintf(@buf[0 ] ,'File not found: %s' ,ptrcomp(@img_name[1 ] ) );
+ sprintf(@buf[StrLen(@buf ) ] ,'%s' ,ptrcomp(@ext[1 ] ) );
+
+ end;
+
+ app.message_(@buf[0 ] );
+
+ end
+ else
+ if app.init(600 ,600 ,window_resize ) then
+ app.run;
+
+ app.Destruct;
+
+ g_rasterizer.Destruct;
+ g_scanline.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/image_transforms.dpr b/src/corelib/render/software/agg-demos/image_transforms.dpr
new file mode 100644
index 00000000..5bff20ca
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/image_transforms.dpr
@@ -0,0 +1,635 @@
+{mac_copy:spheres.bmp}
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ image_transforms ;
+
+uses
+ SysUtils ,
+
+ agg_basics ,
+ agg_platform_support ,
+
+ agg_color ,
+ agg_pixfmt ,
+ agg_pixfmt_rgba ,
+
+ agg_ctrl ,
+ agg_cbox_ctrl ,
+ agg_rbox_ctrl ,
+ agg_slider_ctrl ,
+
+ agg_rendering_buffer ,
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_rasterizer_scanline_aa ,
+ agg_scanline ,
+ agg_scanline_u ,
+ agg_render_scanlines ,
+
+ agg_ellipse ,
+ agg_path_storage ,
+ agg_trans_affine ,
+ agg_conv_transform ,
+ agg_conv_stroke ,
+ agg_image_filters ,
+ agg_span_allocator ,
+ agg_span_image_filter ,
+ agg_span_image_filter_rgba ,
+ agg_span_interpolator_linear ,
+ file_utils_ ;
+
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+type
+ the_application = object(platform_support )
+ m_polygon_angle ,
+ m_polygon_scale ,
+
+ m_image_angle ,
+ m_image_scale : slider_ctrl;
+
+ m_rotate_polygon ,
+ m_rotate_image : cbox_ctrl;
+
+ m_example : rbox_ctrl;
+
+ m_image_center_x ,
+ m_image_center_y ,
+
+ m_polygon_cx ,
+ m_polygon_cy ,
+ m_image_cx ,
+ m_image_cy ,
+
+ m_dx ,
+ m_dy : double;
+ m_flag : int;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure create_star(ps : path_storage_ptr );
+
+ procedure on_init; virtual;
+ procedure on_draw; virtual;
+
+ procedure on_mouse_move (x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_up (x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_ctrl_change; virtual;
+ procedure on_idle; virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_polygon_angle.Construct (5 ,5 ,145 ,11 ,not flip_y_ );
+ m_polygon_scale.Construct (5 ,5 + 14 ,145 ,12 + 14 ,not flip_y_ );
+ m_image_angle.Construct (155 ,5 ,300 ,12 ,not flip_y_ );
+ m_image_scale.Construct (155 ,5 + 14 ,300 ,12 + 14 ,not flip_y_ );
+ m_rotate_polygon.Construct(5 ,5 + 14 + 14 ,'Rotate Polygon' ,not flip_y_ );
+ m_rotate_image.Construct (5 ,5 + 14 + 14 + 14 ,'Rotate Image' ,not flip_y_ );
+ m_example.Construct (-3.0 ,14 + 14 + 14 + 14 ,-3.0 ,14 + 14 + 14 + 14 ,not flip_y_ );
+
+ m_flag:=0;
+
+ add_ctrl(@m_polygon_angle );
+ add_ctrl(@m_polygon_scale );
+ add_ctrl(@m_image_angle );
+ add_ctrl(@m_image_scale );
+ add_ctrl(@m_rotate_polygon );
+ add_ctrl(@m_rotate_image );
+ add_ctrl(@m_example );
+
+ m_polygon_angle.label_('Polygon Angle=%3.2f' );
+ m_polygon_scale.label_('Polygon Scale=%3.2f' );
+ m_polygon_angle.range_(-180.0 ,180.0 );
+ m_polygon_scale.range_(0.1 ,5.0 );
+ m_polygon_scale.value_(1.0 );
+
+ m_image_angle.label_('Image Angle=%3.2f' );
+ m_image_scale.label_('Image Scale=%3.2f' );
+ m_image_angle.range_(-180.0, 180.0);
+ m_image_scale.range_(0.1 ,5.0 );
+ m_image_scale.value_(1.0 );
+
+ m_example.add_item ('0' );
+ m_example.add_item ('1' );
+ m_example.add_item ('2' );
+ m_example.add_item ('3' );
+ m_example.add_item ('4' );
+ m_example.add_item ('5' );
+ m_example.add_item ('6' );
+ m_example.cur_item_(0 );
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_polygon_angle.Destruct;
+ m_polygon_scale.Destruct;
+ m_image_angle.Destruct;
+ m_image_scale.Destruct;
+ m_rotate_polygon.Destruct;
+ m_rotate_image.Destruct;
+ m_example.Destruct;
+
+end;
+
+{ CREATE_STAR }
+procedure the_application.create_star;
+var
+ r ,r1 ,r2 ,a ,dx ,dy : double;
+
+ nr ,i : unsigned;
+
+begin
+ r:=_initial_width;
+
+ if _initial_height < r then
+ r:=_initial_height;
+
+ r1:=r / 3 - 8.0;
+ r2:=r1 / 1.45;
+ nr:=14;
+
+ for i:=0 to nr - 1 do
+ begin
+ a :=pi * 2.0 * i / nr - pi / 2.0;
+ dx:=Cos(a );
+ dy:=Sin(a );
+
+ if i and 1 <> 0 then
+ ps.line_to(m_polygon_cx + dx * r1 ,m_polygon_cy + dy * r1 )
+ else
+ if i <> 0 then
+ ps.line_to(m_polygon_cx + dx * r2 ,m_polygon_cy + dy * r2 )
+ else
+ ps.move_to(m_polygon_cx + dx * r2 ,m_polygon_cy + dy * r2 );
+
+ end;
+
+end;
+
+{ ON_INIT }
+procedure the_application.on_init;
+begin
+ m_image_center_x:=_initial_width / 2.0;
+ m_image_center_y:=_initial_height / 2.0;
+
+ m_polygon_cx:=_initial_width / 2.0;
+ m_image_cx :=m_polygon_cx;
+ m_polygon_cy:=_initial_height / 2.0;
+ m_image_cy :=m_polygon_cy;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ pixf : pixel_formats;
+ rgba : aggclr;
+
+ rb : renderer_base;
+ rs : renderer_scanline_aa_solid;
+ pf : rasterizer_scanline_aa;
+ sl : scanline_u8;
+ ps : path_storage;
+ tr : conv_transform;
+ e1 ,
+ e2 : ellipse;
+ c1 : conv_stroke;
+ sa : span_allocator;
+ sg : span_image_filter_ptr;
+ ri : renderer_scanline_aa;
+ fi : image_filter_base_ptr;
+
+ filter : image_filter_ptr;
+
+ interpolator : span_interpolator_linear;
+
+ image_mtx ,polygon_mtx : trans_affine;
+
+ tat : trans_affine_translation;
+ tar : trans_affine_rotation;
+ tas : trans_affine_scaling;
+
+begin
+ sg:=NIL;
+ fi:=NIL;
+
+ filter:=NIL;
+
+// Initialize structures
+ pixfmt_bgra32(pixf ,rbuf_window );
+
+ rb.Construct(@pixf );
+ rs.Construct(@rb );
+
+ rgba.ConstrDbl(1.0 ,1.0 ,1.0 );
+ rb.clear (@rgba );
+
+ image_mtx.Construct;
+ polygon_mtx.Construct;
+
+ tat.Construct(-m_polygon_cx ,-m_polygon_cy ); polygon_mtx.multiply(@tat );
+ tar.Construct(m_polygon_angle._value * pi / 180.0 ); polygon_mtx.multiply(@tar );
+ tas.Construct(m_polygon_scale._value ); polygon_mtx.multiply(@tas );
+ tat.construct(m_polygon_cx ,m_polygon_cy ); polygon_mtx.multiply(@tat );
+
+ case m_example._cur_item of
+ // --------------(Example 1)
+ 1 :
+ begin
+ tat.Construct(-m_image_center_x ,-m_image_center_y ); image_mtx.multiply(@tat );
+ tar.Construct(m_polygon_angle._value * pi / 180.0 ); image_mtx.multiply(@tar );
+ tas.Construct(m_polygon_scale._value ); image_mtx.multiply(@tas );
+ tat.Construct(m_polygon_cx ,m_polygon_cy ); image_mtx.multiply(@tat );
+
+ image_mtx.invert;
+
+ end;
+
+ // --------------(Example 2)
+ 2 :
+ begin
+ tat.Construct(-m_image_center_x ,-m_image_center_y ); image_mtx.multiply(@tat );
+ tar.Construct(m_image_angle._value * pi / 180.0 ); image_mtx.multiply(@tar );
+ tas.Construct(m_image_scale._value ); image_mtx.multiply(@tas );
+ tat.Construct(m_image_cx ,m_image_cy ); image_mtx.multiply(@tat );
+
+ image_mtx.invert;
+
+ end;
+
+ // --------------(Example 3)
+ 3 :
+ begin
+ tat.Construct(-m_image_center_x ,-m_image_center_y ); image_mtx.multiply(@tat );
+ tar.Construct(m_image_angle._value * pi / 180.0 ); image_mtx.multiply(@tar );
+ tas.Construct(m_image_scale._value ); image_mtx.multiply(@tas );
+ tat.Construct(m_polygon_cx ,m_polygon_cy ); image_mtx.multiply(@tat );
+
+ image_mtx.invert;
+
+ end;
+
+ // --------------(Example 4)
+ 4 :
+ begin
+ tat.Construct(-m_image_cx ,-m_image_cy ); image_mtx.multiply(@tat );
+ tar.Construct(m_polygon_angle._value * pi / 180.0 ); image_mtx.multiply(@tar );
+ tas.Construct(m_polygon_scale._value ); image_mtx.multiply(@tas );
+ tat.Construct(m_polygon_cx ,m_polygon_cy ); image_mtx.multiply(@tat );
+
+ image_mtx.invert;
+
+ end;
+
+ // --------------(Example 5)
+ 5 :
+ begin
+ tat.Construct(-m_image_center_x ,-m_image_center_y ); image_mtx.multiply(@tat );
+ tar.Construct(m_image_angle._value * pi / 180.0 ); image_mtx.multiply(@tar );
+ tar.Construct(m_polygon_angle._value * pi / 180.0 ); image_mtx.multiply(@tar );
+ tas.Construct(m_image_scale._value ); image_mtx.multiply(@tas );
+ tas.Construct(m_polygon_scale._value ); image_mtx.multiply(@tas );
+ tat.Construct(m_image_cx ,m_image_cy ); image_mtx.multiply(@tat );
+
+ image_mtx.invert;
+
+ end;
+
+ // --------------(Example 6)
+ 6 :
+ begin
+ tat.Construct(-m_image_cx ,-m_image_cy ); image_mtx.multiply(@tat );
+ tar.Construct(m_image_angle._value * pi / 180.0 ); image_mtx.multiply(@tar );
+ tas.Construct(m_image_scale._value ); image_mtx.multiply(@tas );
+ tat.Construct(m_image_cx ,m_image_cy ); image_mtx.multiply(@tat );
+
+ image_mtx.invert;
+
+ end;
+
+ // --------------(Example 0, Identity matrix)
+ else
+ NoP;
+
+ end;
+
+ interpolator.Construct(@image_mtx );
+ sa.Construct;
+
+ rgba.ConstrDbl(1 ,1 ,1 ,0 );
+
+// nearest neighbor
+{ sg:=new(
+ span_image_filter_rgba_nn_ptr ,
+ Construct(
+ @sa ,rbuf_img(0 ) ,@rgba ,@interpolator ,bgra_order ) );{}
+
+// "hardcoded" bilinear filter
+ sg:=new(
+ span_image_filter_rgba_bilinear_ptr ,
+ Construct(
+ @sa ,rbuf_img(0 ) ,@rgba ,@interpolator ,bgra_order ) );{}
+
+// arbitrary filter
+{ fi :=new(image_filter_spline36_ptr ,Construct );
+ filter:=new(image_filter_ptr ,Construct(fi ) );
+
+ sg:=new(
+ span_image_filter_rgba_ptr ,
+ Construct(
+ @sa ,rbuf_img(0 ) ,@rgba ,@interpolator ,filter ,bgra_order ) );{}
+
+// Render
+ ri.Construct(@rb ,sg );
+
+ pf.Construct;
+ sl.Construct;
+ ps.Construct;
+
+ create_star(@ps );
+
+ tr.Construct(@ps ,@polygon_mtx );
+
+ pf.add_path (@tr );
+ render_scanlines(@pf ,@sl ,@ri );
+
+ e1.Construct(m_image_cx ,m_image_cy ,5 ,5 ,20 );
+ e2.Construct(m_image_cx ,m_image_cy ,2 ,2 ,20 );
+ c1.Construct(@e1 );
+
+ rgba.ConstrDbl (0.7 ,0.8 ,0 );
+ rs.color_ (@rgba );
+ pf.add_path (@e1);
+ render_scanlines(@pf ,@sl ,@rs );
+
+ rgba.ConstrDbl (0 ,0 ,0 );
+ rs.color_ (@rgba );
+ pf.add_path (@c1 );
+ render_scanlines(@pf ,@sl ,@rs );
+
+ pf.add_path (@e2 );
+ render_scanlines(@pf ,@sl ,@rs );
+
+// Render the controls
+ render_ctrl(@pf ,@sl ,@rs ,@m_polygon_angle );
+ render_ctrl(@pf ,@sl ,@rs ,@m_polygon_scale );
+ render_ctrl(@pf ,@sl ,@rs ,@m_image_angle );
+ render_ctrl(@pf ,@sl ,@rs ,@m_image_scale );
+ render_ctrl(@pf ,@sl ,@rs ,@m_rotate_polygon );
+ render_ctrl(@pf ,@sl ,@rs ,@m_rotate_image );
+ render_ctrl(@pf ,@sl ,@rs ,@m_example );
+
+// Free AGG resources
+ pf.Destruct;
+ sl.Destruct;
+ ps.Destruct;
+
+ sa.Destruct;
+
+ if sg <> NIL then
+ dispose(sg ,Destruct );
+
+ if fi <> NIL then
+ dispose(fi );
+
+ if filter <> NIL then
+ dispose(filter ,Destruct );
+
+ c1.Destruct;
+
+end;
+
+{ ON_MOUSE_MOVE }
+procedure the_application.on_mouse_move;
+begin
+ if flags and mouse_left <> 0 then
+ begin
+ if m_flag = 1 then
+ begin
+ m_image_cx:=x - m_dx;
+ m_image_cy:=y - m_dy;
+
+ force_redraw;
+
+ end;
+
+ if m_flag = 2 then
+ begin
+ m_polygon_cx:=x - m_dx;
+ m_polygon_cy:=y - m_dy;
+
+ force_redraw;
+
+ end;
+
+ end
+ else
+ on_mouse_button_up(x ,y ,flags );
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure the_application.on_mouse_button_down;
+var
+ pf : rasterizer_scanline_aa;
+ ps : path_storage;
+ tr : conv_transform;
+
+ polygon_mtx : trans_affine;
+
+ tat : trans_affine_translation;
+ tar : trans_affine_rotation;
+ tas : trans_affine_scaling;
+
+begin
+ if flags and mouse_left <> 0 then
+ if Sqrt(
+ (x - m_image_cx ) * (x - m_image_cx ) +
+ (y - m_image_cy ) * (y - m_image_cy ) ) < 5.0 then
+ begin
+ m_dx:=x - m_image_cx;
+ m_dy:=y - m_image_cy;
+
+ m_flag:=1;
+
+ end
+ else
+ begin
+ pf.Construct;
+ polygon_mtx.Construct;
+
+ tat.Construct(-m_polygon_cx ,-m_polygon_cy ); polygon_mtx.multiply(@tat );
+ tar.Construct(m_polygon_angle._value * pi / 180.0 ); polygon_mtx.multiply(@tar );
+ tas.Construct(m_polygon_scale._value ,m_polygon_scale._value ); polygon_mtx.multiply(@tas );
+ tat.Construct(m_polygon_cx ,m_polygon_cy ); polygon_mtx.multiply(@tat );
+
+ ps.Construct;
+
+ create_star(@ps );
+
+ tr.Construct(@ps ,@polygon_mtx );
+ pf.add_path (@tr );
+
+ if pf.hit_test(x ,y ) then
+ begin
+ m_dx:=x - m_polygon_cx;
+ m_dy:=y - m_polygon_cy;
+
+ m_flag:=2;
+
+ end;
+
+ pf.Destruct;
+ ps.Destruct;
+
+ end;
+
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+procedure the_application.on_mouse_button_up;
+begin
+ m_flag:=0;
+
+end;
+
+{ ON_CTRL_CHANGE }
+procedure the_application.on_ctrl_change;
+begin
+ if m_rotate_polygon._status or
+ m_rotate_image._status then
+ wait_mode_(false )
+ else
+ wait_mode_(true );
+
+ force_redraw;
+
+end;
+
+{ ON_IDLE }
+procedure the_application.on_idle;
+var
+ redraw : boolean;
+
+begin
+ redraw:=false;
+
+ if m_rotate_polygon._status then
+ begin
+ m_polygon_angle.value_(m_polygon_angle._value + 0.5 );
+
+ if m_polygon_angle._value >= 180.0 then
+ m_polygon_angle.value_(m_polygon_angle._value - 360.0 );
+
+ redraw:=true;
+
+ end;
+
+ if m_rotate_image._status then
+ begin
+ m_image_angle.value_(m_image_angle._value + 0.5 );
+
+ if m_image_angle._value >= 180.0 then
+ m_image_angle.value_(m_image_angle._value - 360.0 );
+
+ redraw:=true;
+
+ end;
+
+ if redraw then
+ force_redraw;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ 'Affine transformations of the images. The examples demonstrates how to construct '#13 +
+ 'the affine transformer matrix for different cases. '#13 +
+ 'See the "image_transforms.txt" file for details. '#13 +
+ 'Now there are methods in trans_affine that allow you to construct transformations '#13 +
+ 'from an arbitrary parallelogram to another parallelogram. It''s very convenient and easy.'#13#13 +
+ 'How to play with:'#13#13 +
+ 'Use the left mouse button change the centre of rotation or move the polygon shape.' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+VAR
+ app : the_application;
+ buf : array [0..255 ] of char;
+ ext : string[10 ];
+
+ img_name ,p ,n ,x : shortstring;
+
+BEGIN
+ app.Construct(pix_format_bgra32 ,flip_y );
+ app.caption_ ('Image Affine Transformations with filtering (F1-Help)' );
+
+ img_name:='spheres';
+
+{$IFDEF WIN32 }
+ if ParamCount > 0 then
+ begin
+ spread_name(ParamStr(1 ) ,p ,n ,x );
+
+ img_name:=fold_name(p ,n ,'' );
+
+ end;
+
+{$ENDIF }
+
+ if not app.load_img(0 ,img_name ) then
+ begin
+ img_name:=img_name + #0;
+ ext :=app._img_ext + #0;
+
+ if img_name = 'spheres'#0 then
+ begin
+ sprintf(@buf[0 ] ,'File not found: %s' ,ptrcomp(@img_name[1 ] ) );
+ sprintf(@buf[StrLen(@buf ) ] ,'%s. '#13'Download http://www.antigrain.com/' ,ptrcomp(@ext[1 ] ) );
+ sprintf(@buf[StrLen(@buf ) ] ,'%s' ,ptrcomp(@img_name[1 ] ) );
+ sprintf(@buf[StrLen(@buf ) ] ,'%s'#13'or copy it from another directory if available.' ,ptrcomp(@ext[1 ] ) );
+
+ end
+ else
+ begin
+ sprintf(@buf[0 ] ,'File not found: %s' ,ptrcomp(@img_name[1 ] ) );
+ sprintf(@buf[StrLen(@buf ) ] ,'%s' ,ptrcomp(@ext[1 ] ) );
+
+ end;
+
+ app.message_(@buf[0 ] );
+
+ end
+ else
+ if app.init(app.rbuf_img(0 )._width ,app.rbuf_img(0 )._height ,0 ) then
+ app.run;
+
+ app.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/image_transforms.txt b/src/corelib/render/software/agg-demos/image_transforms.txt
new file mode 100644
index 00000000..be8a98e8
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/image_transforms.txt
@@ -0,0 +1,189 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.0
+// Copyright (C) 2002 Maxim Shemanarev (McSeem)
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//----------------------------------------------------------------------------
+
+IMPORTANT!
+Download http://www.antigrain.com/spheres.bmp before running this example.
+
+
+Using affine transformations for images looks tricky, but it's not, especially
+when you understand the main idea. You can apply any affine transformations
+to images of any size and draw any part of the image.
+
+This example demonstrates the ideas of constructing affine matrices for
+images. The example contains 6 variants of scaling/rotation/translation
+matrices. Also, there are the following important variables:
+
+m_polygon_angle;
+m_polygon_scale;
+
+m_image_angle;
+m_image_scale;
+
+m_image_center_x;
+m_image_center_y;
+
+m_polygon_cx;
+m_polygon_cy;
+
+m_image_cx;
+m_image_cy;
+
+
+Variables m_polygon_... refer to the source path (star) that will be used to
+transform the image, variables m_image_... refer to the image parametres.
+Actually, different variants of transformations use different variables
+(in some cases m_polygon_... is used to create the image affine matrix).
+The meaning of the variables is the following:
+
+m_polygon_angle;
+m_polygon_scale;
+
+Are actually two slider controls on the left.
+
+m_polygon_cx;
+m_polygon_cy;
+
+Are the center of the "star", that is the geometric center of the source path.
+You can drag the "star" with the left mouse button.
+
+m_image_angle;
+m_image_scale;
+
+are two respective sliders on the right.
+
+m_image_cx;
+m_image_cy;
+
+are the coordinates of the green marker. The marker can also be dragged.
+
+m_image_center_x;
+m_image_center_y;
+
+are the center of the image. You can consider them as constants.
+In certain cases it's easier to understand the idea when we have some
+"reference point", like the center or the origin of the axes.
+
+The image transformation matrix doesn't depend on anything else.
+It means that the code above the line "// --------------(Example 0)":
+
+ polygon_mtx *= agg::trans_affine_translation(-m_polygon_cx, -m_polygon_cy);
+ polygon_mtx *= agg::trans_affine_rotation(m_polygon_angle.value() * agg::pi / 180.0);
+ polygon_mtx *= agg::trans_affine_scaling(m_polygon_scale.value());
+ polygon_mtx *= agg::trans_affine_translation(m_polygon_cx, m_polygon_cy);
+
+affects only the drawn path. So, the only way to shift, rotate, or scale the
+image is to use the image affine matrix (image_mtx in this example).
+
+Another important thing is that due to the nature of the algorithm you
+have to use the inverse transformations. The algorithm takes the
+coordinates of every destination pixel, applies the transformations and
+obtains the coordinates of the pixel to pick it up from the source image.
+The coordinates of the destination pixels are always known and they have
+regular, pixel accuracy. After transforming they usually fall somewhere "
+between" pixels. This fact allows us to apply anti-aliasing filters like
+bilinear, bicubic, sinc, blackman, etc. After filtering we know the value of the
+destination pixel and we can put it in its place. This is why the algorithm
+uses the inverse affine matrix. In other words you prepare the transformation
+matrix as usual and then invret it before using:
+
+ image_mtx *= agg::trans_affine_translation(-m_image_center_x, -m_image_center_y);
+ image_mtx *= agg::trans_affine_rotation(m_polygon_angle.value() * agg::pi / 180.0);
+ image_mtx *= agg::trans_affine_scaling(m_polygon_scale.value());
+ image_mtx *= agg::trans_affine_translation(m_polygon_cx, m_polygon_cy);
+ image_mtx.invert();
+
+This code illustrates the behaviour when we have synchronous transformations
+of the source path and the image.
+
+Well, let us return to example 0. Here we have a "star" that can be dragged with
+the left mouse button, a small round green marker, and four sliders.
+The marker and the sliders on the right don't affect anything. As it was said,
+this example simply copies pixels from the source image to the destination canvas.
+
+Example 1. The marker and the image sliders on the right still
+don't work, but now the image is moved, scaled, and rotated syncronously with
+the "star". We simply take the reference point, which is m_image_center_x(y),
+rotate and scale the image around it, and then, translate the image to
+m_polygon_cx(cy).
+
+
+Example 2 is the same as 1 but instead of using "m_polygon_..." parameters we
+use "m_image_..." ones, so the marker and the sliders on the right now work
+independently. In other words you can control the image and the "star" separately.
+ image_mtx *= agg::trans_affine_translation(-m_image_center_x, -m_image_center_y);
+ image_mtx *= agg::trans_affine_rotation(m_image_angle.value() * agg::pi / 180.0);
+ image_mtx *= agg::trans_affine_scaling(m_image_scale.value());
+ image_mtx *= agg::trans_affine_translation(m_image_cx, m_image_cy);
+ image_mtx.invert();
+
+
+Example 3 is the same as the above but instead of using "m_image_cx(cy)" we use
+m_polygon_cx(cy). So that, the image is rotated and scaled around its center,
+but the marker doesn't have any effect.
+ image_mtx *= agg::trans_affine_translation(-m_image_center_x, -m_image_center_y);
+ image_mtx *= agg::trans_affine_rotation(m_image_angle.value() * agg::pi / 180.0);
+ image_mtx *= agg::trans_affine_scaling(m_image_scale.value());
+ image_mtx *= agg::trans_affine_translation(m_polygon_cx, m_polygon_cy);
+ image_mtx.invert();
+
+
+Example 4 is the same as 1, but we use m_image_cx(cy) as the source point
+in the image. So, the image sliders don't work, the image is transformed
+synchronously with the path, but we are able to choose the source point for
+image transformations. That is the idea: we take the source point in the
+image, perform the transformations around it and then move this source
+point to the center of the "star".
+ image_mtx *= agg::trans_affine_translation(-m_image_cx, -m_image_cy);
+ image_mtx *= agg::trans_affine_rotation(m_polygon_angle.value() * agg::pi / 180.0);
+ image_mtx *= agg::trans_affine_scaling(m_polygon_scale.value());
+ image_mtx *= agg::trans_affine_translation(m_polygon_cx, m_polygon_cy);
+ image_mtx.invert();
+
+
+Example 5 is the same as 2, but there we have a combination of the scaling
+and rotation of the "star" and the image.
+ image_mtx *= agg::trans_affine_translation(-m_image_center_x, -m_image_center_y);
+ image_mtx *= agg::trans_affine_rotation(m_image_angle.value() * agg::pi / 180.0);
+ image_mtx *= agg::trans_affine_rotation(m_polygon_angle.value() * agg::pi / 180.0);
+ image_mtx *= agg::trans_affine_scaling(m_image_scale.value());
+ image_mtx *= agg::trans_affine_scaling(m_polygon_scale.value());
+ image_mtx *= agg::trans_affine_translation(m_image_cx, m_image_cy);
+ image_mtx.invert();
+BTW, code above can be simplified like this:
+ image_mtx *= agg::trans_affine_translation(-m_image_center_x, -m_image_center_y);
+ image_mtx *= agg::trans_affine_rotation(m_image_angle.value() * agg::pi / 180.0 +
+ m_polygon_angle.value() * agg::pi / 180.0);
+ image_mtx *= agg::trans_affine_scaling(m_image_scale.value() * m_polygon_scale.value());
+ image_mtx *= agg::trans_affine_translation(m_image_cx, m_image_cy);
+ image_mtx.invert();
+
+
+Finally, example 5 is probably not very interesting in practice, but still, it
+can simplify understanding of the idea. This example uses only m_image_...
+parameters. It shifts the image from m_image_cx(cy) to the origin (0,0), then
+applies rotation and scaling, and finally, shifts the image back. So that,
+point m_image_cx(cy) is simply the center of the transformations. When the
+image angle is 0.0 and the scale is 1.0 dragging this point doesn't have any
+effect.
+ image_mtx *= agg::trans_affine_translation(-m_image_cx, -m_image_cy);
+ image_mtx *= agg::trans_affine_rotation(m_image_angle.value() * agg::pi / 180.0);
+ image_mtx *= agg::trans_affine_scaling(m_image_scale.value());
+ image_mtx *= agg::trans_affine_translation(m_image_cx, m_image_cy);
+ image_mtx.invert();
+
+
+Many thank to you if you read it and many special thanks if you could understand
+something. :-)
+
diff --git a/src/corelib/render/software/agg-demos/interactive_polygon_.pas b/src/corelib/render/software/agg-demos/interactive_polygon_.pas
new file mode 100644
index 00000000..37c7a3bf
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/interactive_polygon_.pas
@@ -0,0 +1,638 @@
+unit
+ interactive_polygon_ ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ Math ,
+ agg_basics ,
+ agg_conv_stroke ,
+ agg_ellipse ,
+ agg_vertex_source ;
+
+{ TYPES DEFINITION }
+type
+ simple_polygon_vertex_source = object(vertex_source )
+ m_polygon : double_ptr;
+
+ m_num_points ,
+ m_vertex : unsigned;
+
+ m_roundoff ,
+ m_close : boolean;
+
+ constructor Construct(polygon : double_ptr; np : unsigned; roundoff : boolean = false; close : boolean = true );
+
+ procedure close_(f : boolean );
+ function _close : boolean;
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ end;
+
+ interactive_polygon = object(vertex_source )
+ m_polygon : double_ptr;
+ m_num_points : unsigned;
+
+ m_node ,
+ m_edge : int;
+
+ m_vs : simple_polygon_vertex_source;
+
+ m_stroke : conv_stroke;
+ m_ellipse : ellipse;
+
+ m_point_radius : double;
+ m_status : unsigned;
+
+ m_dx ,
+ m_dy : double;
+
+ constructor Construct(np : unsigned; point_radius : double );
+ destructor Destruct; virtual;
+
+ function num_points : unsigned;
+
+ function xn(n : unsigned ) : double;
+ function yn(n : unsigned ) : double;
+
+ function xn_ptr(n : unsigned ) : double_ptr;
+ function yn_ptr(n : unsigned ) : double_ptr;
+
+ function polygon : double_ptr;
+
+ function _node : int;
+ procedure node_(n : int );
+
+ function _close : boolean;
+ procedure close_(f : boolean );
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ function on_mouse_move(x ,y : double ) : boolean;
+
+ function on_mouse_button_down(x ,y : double ) : boolean;
+ function on_mouse_button_up(x ,y : double ) : boolean;
+
+ function check_edge(i : unsigned; x ,y : double ) : boolean;
+
+ function point_in_polygon(tx ,ty : double ) : boolean;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor simple_polygon_vertex_source.Construct;
+begin
+ inherited Construct;
+
+ m_polygon :=polygon;
+ m_num_points:=np;
+
+ m_vertex :=0;
+ m_roundoff:=roundoff;
+ m_close :=close;
+
+end;
+
+{ CLOSE_ }
+procedure simple_polygon_vertex_source.close_;
+begin
+ m_close:=f;
+
+end;
+
+{ _CLOSE }
+function simple_polygon_vertex_source._close;
+begin
+ result:=m_close;
+
+end;
+
+{ REWIND }
+procedure simple_polygon_vertex_source.rewind;
+begin
+ m_vertex:=0;
+
+end;
+
+{ VERTEX }
+function simple_polygon_vertex_source.vertex;
+begin
+ if m_vertex > m_num_points then
+ begin
+ result:=path_cmd_stop;
+
+ exit;
+
+ end;
+
+ if m_vertex = m_num_points then
+ begin
+ inc(m_vertex );
+
+ if m_close then
+ result:=path_cmd_end_poly or path_flags_close
+ else
+ result:=path_cmd_end_poly or 0;
+
+ exit;
+
+ end;
+
+ x^:=double_ptr(ptrcomp(m_polygon ) + (m_vertex * 2 ) * sizeof(double ) )^;
+ y^:=double_ptr(ptrcomp(m_polygon ) + (m_vertex * 2 + 1 ) * sizeof(double ) )^;
+
+ if m_roundoff then
+ begin
+ x^:=Floor(x^ ) + 0.5;
+ y^:=Floor(y^ ) + 0.5;
+
+ end;
+
+ inc(m_vertex );
+
+ if m_vertex = 1 then
+ result:=path_cmd_move_to
+ else
+ result:=path_cmd_line_to;
+
+end;
+
+{ CONSTRUCT }
+constructor interactive_polygon.Construct;
+begin
+ inherited Construct;
+
+ agg_getmem(pointer(m_polygon ) ,np * 2 * sizeof(double ) );
+
+ m_num_points:=np;
+
+ m_node:=-1;
+ m_edge:=-1;
+
+ m_vs.Construct (m_polygon ,m_num_points ,false );
+ m_stroke.Construct(@m_vs );
+ m_ellipse.Construct;
+
+ m_point_radius:=point_radius;
+ m_status :=0;
+
+ m_dx:=0.0;
+ m_dy:=0.0;
+
+ m_stroke.width_(1.0 );
+
+end;
+
+{ DESTRUCT }
+destructor interactive_polygon.Destruct;
+begin
+ agg_freemem(pointer(m_polygon ) ,m_num_points * 2 * sizeof(double ) );
+
+ m_stroke.Destruct;
+
+end;
+
+{ NUM_POINTS }
+function interactive_polygon.num_points;
+begin
+ result:=m_num_points;
+
+end;
+
+{ XN }
+function interactive_polygon.xn;
+begin
+ result:=double_ptr(ptrcomp(m_polygon ) + (n * 2 ) * sizeof(double ) )^;
+
+end;
+
+{ YN }
+function interactive_polygon.yn;
+begin
+ result:=double_ptr(ptrcomp(m_polygon ) + (n * 2 + 1 ) * sizeof(double ) )^;
+
+end;
+
+{ XN_PTR }
+function interactive_polygon.xn_ptr;
+begin
+ result:=double_ptr(ptrcomp(m_polygon ) + (n * 2 ) * sizeof(double ) );
+
+end;
+
+{ YN_PTR }
+function interactive_polygon.yn_ptr;
+begin
+ result:=double_ptr(ptrcomp(m_polygon ) + (n * 2 + 1 ) * sizeof(double ) );
+
+end;
+
+{ POLYGON }
+function interactive_polygon.polygon;
+begin
+ result:=m_polygon;
+
+end;
+
+{ _NODE }
+function interactive_polygon._node;
+begin
+ result:=m_node;
+
+end;
+
+{ NODE_ }
+procedure interactive_polygon.node_;
+begin
+ m_node:=n;
+
+end;
+
+{ _CLOSE }
+function interactive_polygon._close;
+begin
+ result:=m_vs._close;
+
+end;
+
+{ CLOSE_ }
+procedure interactive_polygon.close_;
+begin
+ m_vs.close_(f );
+
+end;
+
+{ REWIND }
+procedure interactive_polygon.rewind;
+begin
+ m_status:=0;
+
+ m_stroke.rewind(0 );
+
+end;
+
+{ VERTEX }
+function interactive_polygon.vertex;
+var
+ r : double;
+
+ cmd : unsigned;
+
+begin
+ cmd:=path_cmd_stop;
+ r :=m_point_radius;
+
+ if m_status = 0 then
+ begin
+ cmd:=m_stroke.vertex(x ,y );
+
+ if not is_stop(cmd ) then
+ begin
+ result:=cmd;
+
+ exit;
+
+ end;
+
+ if (m_node >= 0 ) and
+ (m_node = int(m_status ) ) then
+ r:=r * 1.2;
+
+ m_ellipse.init(xn(m_status ) ,yn(m_status ) ,r ,r ,32 );
+
+ inc(m_status );
+
+ end;
+
+ cmd:=m_ellipse.vertex(x ,y );
+
+ if not is_stop(cmd ) then
+ begin
+ result:=cmd;
+
+ exit;
+
+ end;
+
+ if m_status >= m_num_points then
+ begin
+ result:=path_cmd_stop;
+
+ exit;
+
+ end;
+
+ if (m_node >= 0 ) and
+ (m_node = int(m_status ) ) then
+ r:=r * 1.2;
+
+ m_ellipse.init(xn(m_status ) ,yn(m_status ) ,r ,r ,32 );
+
+ inc(m_status );
+
+ result:=m_ellipse.vertex(x ,y );
+
+end;
+
+{ ON_MOUSE_MOVE }
+function interactive_polygon.on_mouse_move;
+var
+ ret : boolean;
+
+ i ,n1 ,n2 : unsigned;
+
+ dx ,dy : double;
+
+begin
+ ret:=false;
+
+ if m_node = int(m_num_points ) then
+ begin
+ dx:=x - m_dx;
+ dy:=y - m_dy;
+
+ for i:=0 to m_num_points - 1 do
+ begin
+ xn_ptr(i )^:=xn_ptr(i )^ + dx;
+ yn_ptr(i )^:=yn_ptr(i )^ + dy;
+
+ end;
+
+ m_dx:=x;
+ m_dy:=y;
+
+ ret:=true;
+
+ end
+ else
+ if m_edge >= 0 then
+ begin
+ n1:=m_edge;
+ n2:=(n1 + m_num_points - 1 ) mod m_num_points;
+
+ dx:=x - m_dx;
+ dy:=y - m_dy;
+
+ xn_ptr(n1 )^:=xn_ptr(n1 )^ + dx;
+ yn_ptr(n1 )^:=yn_ptr(n1 )^ + dy;
+ xn_ptr(n2 )^:=xn_ptr(n2 )^ + dx;
+ yn_ptr(n2 )^:=yn_ptr(n2 )^ + dy;
+
+ m_dx:=x;
+ m_dy:=y;
+
+ ret:=true;
+
+ end
+ else
+ if m_node >= 0 then
+ begin
+ xn_ptr(m_node )^:=x - m_dx;
+ yn_ptr(m_node )^:=y - m_dy;
+
+ ret:=true;
+
+ end;
+
+ result:=ret;
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+function interactive_polygon.on_mouse_button_down;
+var
+ i : unsigned;
+
+ ret : boolean;
+
+begin
+ ret:=false;
+
+ m_node:=-1;
+ m_edge:=-1;
+
+ for i:=0 to m_num_points - 1 do
+ if Sqrt((x - xn(i ) ) * (x - xn(i ) ) + (y - yn(i ) ) * (y - yn(i ) ) ) < m_point_radius then
+ begin
+ m_dx:=x - xn(i );
+ m_dy:=y - yn(i );
+
+ m_node:=int(i );
+
+ ret:=true;
+
+ break;
+
+ end;
+
+ if not ret then
+ for i:=0 to m_num_points - 1 do
+ if check_edge(i ,x ,y ) then
+ begin
+ m_dx:=x;
+ m_dy:=y;
+
+ m_edge:=int(i );
+
+ ret:=true;
+
+ break;
+
+ end;
+
+ if not ret then
+ if point_in_polygon(x ,y ) then
+ begin
+ m_dx:=x;
+ m_dy:=y;
+
+ m_node:=int(m_num_points );
+
+ ret:=true;
+
+ end;
+
+ result:=ret;
+
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+function interactive_polygon.on_mouse_button_up;
+var
+ ret : boolean;
+
+begin
+ ret:=(m_node >= 0 ) or (m_edge >= 0 );
+
+ m_node:=-1;
+ m_edge:=-1;
+ result:=ret;
+
+end;
+
+{ CHECK_EDGE }
+function interactive_polygon.check_edge;
+var
+ ret : boolean;
+
+ n1 ,n2 : unsigned;
+
+ x1 ,y1 ,x2 ,y2 ,dx ,dy ,x3 ,y3 ,x4 ,y4 ,den ,u1 ,xi ,yi : double;
+
+begin
+ ret:=false;
+
+ n1:= i;
+ n2:= (i + m_num_points - 1 ) mod m_num_points;
+
+ x1:=xn(n1 );
+ y1:=yn(n1 );
+ x2:=xn(n2 );
+ y2:=yn(n2 );
+
+ dx:=x2 - x1;
+ dy:=y2 - y1;
+
+ if Sqrt(dx * dx + dy * dy ) > 0.0000001 then
+ begin
+ x3:=x;
+ y3:=y;
+ x4:=x3 - dy;
+ y4:=y3 + dx;
+
+ den:=(y4 - y3 ) * (x2 - x1 ) - (x4 - x3 ) * (y2 - y1 );
+ u1 :=((x4 - x3 ) * (y1 - y3 ) - (y4 - y3 ) * (x1 - x3 ) ) / den;
+
+ xi:=x1 + u1 * (x2 - x1);
+ yi:=y1 + u1 * (y2 - y1);
+
+ dx:=xi - x;
+ dy:=yi - y;
+
+ if (u1 > 0.0 ) and
+ (u1 < 1.0 ) and
+ (Sqrt(dx * dx + dy * dy ) <= m_point_radius ) then
+ ret:=true;
+
+ end;
+
+ result:=ret;
+
+end;
+
+{ POINT_IN_POLYGON }
+//======= Crossings Multiply algorithm of InsideTest ========================
+//
+// By Eric Haines, 3D/Eye Inc, erich@eye.com
+//
+// This version is usually somewhat faster than the original published in
+// Graphics Gems IV; by turning the division for testing the X axis crossing
+// into a tricky multiplication test this part of the test became faster,
+// which had the additional effect of making the test for "both to left or
+// both to right" a bit slower for triangles than simply computing the
+// intersection each time. The main increase is in triangle testing speed,
+// which was about 15% faster; all other polygon complexities were pretty much
+// the same as before. On machines where division is very expensive (not the
+// case on the HP 9000 series on which I tested) this test should be much
+// faster overall than the old code. Your mileage may (in fact, will) vary,
+// depending on the machine and the test data, but in general I believe this
+// code is both shorter and faster. This test was inspired by unpublished
+// Graphics Gems submitted by Joseph Samosky and Mark Haigh-Hutchinson.
+// Related work by Samosky is in:
+//
+// Samosky, Joseph, "SectionView: A system for interactively specifying and
+// visualizing sections through three-dimensional medical image data",
+// M.S. Thesis, Department of Electrical Engineering and Computer Science,
+// Massachusetts Institute of Technology, 1993.
+//
+// Shoot a test ray along +X axis. The strategy is to compare vertex Y values
+// to the testing point's Y and quickly discard edges which are entirely to one
+// side of the test ray. Note that CONVEX and WINDING code can be added as
+// for the CrossingsTest() code; it is left out here for clarity.
+//
+// Input 2D polygon _pgon_ with _numverts_ number of vertices and test point
+// _point_, returns 1 if inside, 0 if outside.
+function interactive_polygon.point_in_polygon;
+var
+ j ,k : unsigned;
+
+ yflag0 ,yflag1 ,inside_flag : int;
+
+ vtx0 ,vty0 ,vtx1 ,vty1 : double;
+
+begin
+ if m_num_points < 3 then
+ begin
+ result:=false;
+
+ exit;
+
+ end;
+
+ vtx0:=xn(m_num_points - 1 );
+ vty0:=yn(m_num_points - 1 );
+
+// get test bit for above/below X axis
+ yflag0:=int(vty0 >= ty );
+
+ vtx1:=xn(0 );
+ vty1:=yn(0 );
+
+ inside_flag:=0;
+
+ for j:=1 to m_num_points do
+ begin
+ yflag1:=int(vty1 >= ty );
+
+ // Check if endpoints straddle (are on opposite sides) of X axis
+ // (i.e. the Y's differ); if so, +X ray could intersect this edge.
+ // The old test also checked whether the endpoints are both to the
+ // right or to the left of the test point. However, given the faster
+ // intersection point computation used below, this test was found to
+ // be a break-even proposition for most polygons and a loser for
+ // triangles (where 50% or more of the edges which survive this test
+ // will cross quadrants and so have to have the X intersection computed
+ // anyway). I credit Joseph Samosky with inspiring me to try dropping
+ // the "both left or both right" part of my code.
+ if yflag0 <> yflag1 then
+ // Check intersection of pgon segment with +X ray.
+ // Note if >= point's X; if so, the ray hits it.
+ // The division operation is avoided for the ">=" test by checking
+ // the sign of the first vertex wrto the test point; idea inspired
+ // by Joseph Samosky's and Mark Haigh-Hutchinson's different
+ // polygon inclusion tests.
+ if int((vty1 - ty ) * (vtx0 - vtx1 ) >= (vtx1 - tx ) * (vty0 - vty1 ) ) = yflag1 then
+ inside_flag:=inside_flag xor 1;
+
+ // Move to the next pair of vertices, retaining info as possible.
+ yflag0:=yflag1;
+
+ vtx0:=vtx1;
+ vty0:=vty1;
+
+ if j >= m_num_points then
+ k:=j - m_num_points
+ else
+ k:=j;
+
+ vtx1:=xn(k );
+ vty1:=yn(k );
+
+ end;
+
+ result:=inside_flag <> 0;
+
+end;
+
+END.
diff --git a/src/corelib/render/software/agg-demos/line_patterns.dpr b/src/corelib/render/software/agg-demos/line_patterns.dpr
new file mode 100644
index 00000000..1f13d8f8
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/line_patterns.dpr
@@ -0,0 +1,489 @@
+{mac_copy:1.bmp}
+{mac_copy:2.bmp}
+{mac_copy:3.bmp}
+{mac_copy:4.bmp}
+{mac_copy:5.bmp}
+{mac_copy:6.bmp}
+{mac_copy:7.bmp}
+{mac_copy:8.bmp}
+{mac_copy:9.bmp}
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ line_patterns ;
+
+uses
+ SysUtils ,
+
+ agg_basics ,
+ agg_platform_support ,
+
+ agg_color ,
+ agg_pixfmt ,
+ agg_pixfmt_rgb ,
+
+ agg_ctrl ,
+ agg_slider_ctrl ,
+ agg_bezier_ctrl ,
+
+ agg_rendering_buffer ,
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_renderer_outline_aa ,
+ agg_renderer_outline_image ,
+ agg_rasterizer_scanline_aa ,
+ agg_rasterizer_outline_aa ,
+ agg_scanline ,
+ agg_scanline_p ,
+ agg_render_scanlines ,
+
+ agg_pattern_filters_rgba ,
+ agg_conv_stroke ,
+ agg_conv_transform ,
+ agg_conv_clip_polyline ,
+ agg_vertex_source ;
+
+{$I agg_mode.inc }
+{$I- }
+const
+ flip_y = true;
+
+ brightness_to_alpha : array[0..256 * 3 - 1 ] of int8u = (
+
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 254, 254, 254,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 253, 253,
+ 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 252,
+ 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 251, 251, 251, 251, 251,
+ 251, 251, 251, 251, 250, 250, 250, 250, 250, 250, 250, 250, 249, 249, 249, 249,
+ 249, 249, 249, 248, 248, 248, 248, 248, 248, 248, 247, 247, 247, 247, 247, 246,
+ 246, 246, 246, 246, 246, 245, 245, 245, 245, 245, 244, 244, 244, 244, 243, 243,
+ 243, 243, 243, 242, 242, 242, 242, 241, 241, 241, 241, 240, 240, 240, 239, 239,
+ 239, 239, 238, 238, 238, 238, 237, 237, 237, 236, 236, 236, 235, 235, 235, 234,
+ 234, 234, 233, 233, 233, 232, 232, 232, 231, 231, 230, 230, 230, 229, 229, 229,
+ 228, 228, 227, 227, 227, 226, 226, 225, 225, 224, 224, 224, 223, 223, 222, 222,
+ 221, 221, 220, 220, 219, 219, 219, 218, 218, 217, 217, 216, 216, 215, 214, 214,
+ 213, 213, 212, 212, 211, 211, 210, 210, 209, 209, 208, 207, 207, 206, 206, 205,
+ 204, 204, 203, 203, 202, 201, 201, 200, 200, 199, 198, 198, 197, 196, 196, 195,
+ 194, 194, 193, 192, 192, 191, 190, 190, 189, 188, 188, 187, 186, 186, 185, 184,
+ 183, 183, 182, 181, 180, 180, 179, 178, 177, 177, 176, 175, 174, 174, 173, 172,
+ 171, 171, 170, 169, 168, 167, 166, 166, 165, 164, 163, 162, 162, 161, 160, 159,
+ 158, 157, 156, 156, 155, 154, 153, 152, 151, 150, 149, 148, 148, 147, 146, 145,
+ 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129,
+ 128, 128, 127, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113,
+ 112, 111, 110, 109, 108, 107, 106, 105, 104, 102, 101, 100, 99, 98, 97, 96,
+ 95, 94, 93, 91, 90, 89, 88, 87, 86, 85, 84, 82, 81, 80, 79, 78,
+ 77, 75, 74, 73, 72, 71, 70, 69, 67, 66, 65, 64, 63, 61, 60, 59,
+ 58, 57, 56, 54, 53, 52, 51, 50, 48, 47, 46, 45, 44, 42, 41, 40,
+ 39, 37, 36, 35, 34, 33, 31, 30, 29, 28, 27, 25, 24, 23, 22, 20,
+ 19, 18, 17, 15, 14, 13, 12, 11, 9, 8, 7, 6, 4, 3, 2, 1 );
+
+type
+ pattern_src_brightness_to_alpha_rgba8 = object(pixel_source )
+ m_rb : rendering_buffer_ptr;
+ m_pf : pixel_formats;
+
+ constructor Construct(rb : rendering_buffer_ptr );
+
+ function _width : unsigned; virtual;
+ function _height : unsigned; virtual;
+
+ function pixel(x ,y : int ) : rgba8; virtual;
+
+ end;
+
+ the_application = object(platform_support )
+ m_ctrl_color : aggclr;
+
+ m_curve1 ,
+ m_curve2 ,
+ m_curve3 ,
+ m_curve4 ,
+ m_curve5 ,
+ m_curve6 ,
+ m_curve7 ,
+ m_curve8 ,
+ m_curve9 : bezier_ctrl;
+ m_scale_x ,
+ m_start_x : slider_ctrl;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure draw_curve(
+ patt : line_image_pattern_ptr;
+ ras : rasterizer_outline_aa_ptr;
+ ren : renderer_outline_image_ptr;
+ src : pixel_source_ptr;
+ vs : vertex_source_ptr );
+
+ procedure on_draw; virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+ procedure on_ctrl_change; virtual;
+
+ end;
+
+{ CONSTRUCT }
+constructor pattern_src_brightness_to_alpha_rgba8.Construct;
+begin
+ m_rb:=rb;
+
+ pixfmt_bgr24(m_pf ,m_rb );
+
+end;
+
+{ _WIDTH }
+function pattern_src_brightness_to_alpha_rgba8._width;
+begin
+ result:=m_pf._width;
+
+end;
+
+{ _HEIGHT }
+function pattern_src_brightness_to_alpha_rgba8._height;
+begin
+ result:=m_pf._height;
+
+end;
+
+{ PIXEL }
+function pattern_src_brightness_to_alpha_rgba8.pixel;
+var
+ c : aggclr;
+
+begin
+ c :=m_pf.pixel(@m_pf ,x ,y );
+ c.a:=brightness_to_alpha[c.r + c.g + c.b ];
+
+ result.r:=c.r;
+ result.g:=c.g;
+ result.b:=c.b;
+ result.a:=c.a;
+
+end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_ctrl_color.ConstrDbl(0 ,0.3 ,0.5 ,0.3 );
+
+ m_scale_x.Construct(5.0 ,5.0 ,240.0 ,12.0 ,not flip_y_ );
+ m_start_x.Construct(250.0 ,5.0 ,495.0 ,12.0 ,not flip_y_ );
+
+ m_curve1.Construct;
+ m_curve2.Construct;
+ m_curve3.Construct;
+ m_curve4.Construct;
+ m_curve5.Construct;
+ m_curve6.Construct;
+ m_curve7.Construct;
+ m_curve8.Construct;
+ m_curve9.Construct;
+
+ m_curve1.line_color_(@m_ctrl_color );
+ m_curve2.line_color_(@m_ctrl_color );
+ m_curve3.line_color_(@m_ctrl_color );
+ m_curve4.line_color_(@m_ctrl_color );
+ m_curve5.line_color_(@m_ctrl_color );
+ m_curve6.line_color_(@m_ctrl_color );
+ m_curve7.line_color_(@m_ctrl_color );
+ m_curve8.line_color_(@m_ctrl_color );
+ m_curve9.line_color_(@m_ctrl_color );
+
+ m_curve1.curve_(64 ,19 ,14 ,126 ,118 ,266 ,19 ,265 );
+ m_curve2.curve_(112 ,113 ,178 ,32 ,200 ,132 ,125 ,438 );
+ m_curve3.curve_(401 ,24 ,326 ,149 ,285 ,11 ,177 ,77 );
+ m_curve4.curve_(188 ,427 ,129 ,295 ,19 ,283 ,25 ,410 );
+ m_curve5.curve_(451 ,346 ,302 ,218 ,265 ,441 ,459 ,400 );
+ m_curve6.curve_(454 ,198 ,14 ,13 ,220 ,291 ,483 ,283 );
+ m_curve7.curve_(301 ,398 ,355 ,231 ,209 ,211 ,170 ,353 );
+ m_curve8.curve_(484 ,101 ,222 ,33 ,486 ,435 ,487 ,138 );
+ m_curve9.curve_(143 ,147 ,11 ,45 ,83 ,427 ,132 ,197 );
+
+ add_ctrl(@m_curve1 );
+ add_ctrl(@m_curve2 );
+ add_ctrl(@m_curve3 );
+ add_ctrl(@m_curve4 );
+ add_ctrl(@m_curve5 );
+ add_ctrl(@m_curve6 );
+ add_ctrl(@m_curve7 );
+ add_ctrl(@m_curve8 );
+ add_ctrl(@m_curve9 );
+
+ m_curve1.no_transform;
+ m_curve2.no_transform;
+ m_curve3.no_transform;
+ m_curve4.no_transform;
+ m_curve5.no_transform;
+ m_curve6.no_transform;
+ m_curve7.no_transform;
+ m_curve8.no_transform;
+ m_curve9.no_transform;
+
+ m_scale_x.label_('Scale X=%.2f' );
+ m_scale_x.range_(0.2 ,3.0 );
+ m_scale_x.value_(1.0 );
+ m_scale_x.no_transform;
+
+ add_ctrl(@m_scale_x );
+
+ m_start_x.label_('Start X=%.2f' );
+ m_start_x.range_(0.0 ,10.0 );
+ m_start_x.value_(0.0 );
+ m_start_x.no_transform;
+
+ add_ctrl(@m_start_x );
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_scale_x.Destruct;
+ m_start_x.Destruct;
+
+ m_curve1.Destruct;
+ m_curve2.Destruct;
+ m_curve3.Destruct;
+ m_curve4.Destruct;
+ m_curve5.Destruct;
+ m_curve6.Destruct;
+ m_curve7.Destruct;
+ m_curve8.Destruct;
+ m_curve9.Destruct;
+
+end;
+
+{ DRAW_CURVE }
+procedure the_application.draw_curve;
+begin
+ patt.create (src );
+ ren.scale_x_(m_scale_x._value );
+ ren.start_x_(m_start_x._value );
+ ras.add_path(vs );
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ pf : pixel_formats;
+ ren : renderer_scanline_aa_solid;
+ ras : rasterizer_scanline_aa;
+ sl : scanline_p8;
+
+ rgba : aggclr;
+
+ ren_base : renderer_base;
+
+ p1 ,p2 ,p3 ,p4 ,p5 ,p6 ,p7 ,p8 ,p9 : pattern_src_brightness_to_alpha_rgba8;
+
+ fltr : pattern_filter_bilinear_rgba{};
+ patt : line_image_pattern;
+
+ ren_img : renderer_outline_image;
+ ras_img : rasterizer_outline_aa;
+
+begin
+// Initialize structures
+ pixfmt_bgr24(pf ,rbuf_window );
+
+ ren_base.Construct(@pf );
+ ren.Construct (@ren_base );
+
+ rgba.ConstrDbl(1.0 ,1.0 ,0.95 );
+ ren_base.clear(@rgba );
+
+ ras.Construct;
+ sl.Construct;
+
+// Pattern source. Must have an interface:
+// width() const
+// height() const
+// pixel(int x, int y) const
+// Any agg::renderer_base<> or derived
+// is good for the use as a source.
+ p1.Construct(rbuf_img(0 ) );
+ p2.Construct(rbuf_img(1 ) );
+ p3.Construct(rbuf_img(2 ) );
+ p4.Construct(rbuf_img(3 ) );
+ p5.Construct(rbuf_img(4 ) );
+ p6.Construct(rbuf_img(5 ) );
+ p7.Construct(rbuf_img(6 ) );
+ p8.Construct(rbuf_img(7 ) );
+ p9.Construct(rbuf_img(8 ) );
+
+ fltr.Construct; // Filtering functor
+
+// agg::line_image_pattern is the main container for the patterns. It creates
+// a copy of the patterns extended according to the needs of the filter.
+// agg::line_image_pattern can operate with arbitrary image width, but if the
+// width of the pattern is power of 2, it's better to use the modified
+// version agg::line_image_pattern_pow2 because it works about 15-25 percent
+// faster than agg::line_image_pattern (because of using simple masking instead
+// of expensive '%' operation).
+
+//-- Create with specifying the source
+// patt.Construct(@fltr ,@src );
+
+//-- Create uninitialized and set the source
+ patt.Construct (@fltr );
+ ren_img.Construct(@ren_base ,@patt );
+ ras_img.Construct(@ren_img );
+
+ draw_curve(@patt ,@ras_img ,@ren_img ,@p1 ,m_curve1._curve );
+ draw_curve(@patt ,@ras_img ,@ren_img ,@p2 ,m_curve2._curve );
+ draw_curve(@patt ,@ras_img ,@ren_img ,@p3 ,m_curve3._curve );
+ draw_curve(@patt ,@ras_img ,@ren_img ,@p4 ,m_curve4._curve );
+ draw_curve(@patt ,@ras_img ,@ren_img ,@p5 ,m_curve5._curve );
+ draw_curve(@patt ,@ras_img ,@ren_img ,@p6 ,m_curve6._curve );
+ draw_curve(@patt ,@ras_img ,@ren_img ,@p7 ,m_curve7._curve );
+ draw_curve(@patt ,@ras_img ,@ren_img ,@p8 ,m_curve8._curve );
+ draw_curve(@patt ,@ras_img ,@ren_img ,@p9 ,m_curve9._curve );
+
+// Render the controls
+ render_ctrl(@ras ,@sl ,@ren ,@m_curve1 );
+ render_ctrl(@ras ,@sl ,@ren ,@m_curve2 );
+ render_ctrl(@ras ,@sl ,@ren ,@m_curve3 );
+ render_ctrl(@ras ,@sl ,@ren ,@m_curve4 );
+ render_ctrl(@ras ,@sl ,@ren ,@m_curve5 );
+ render_ctrl(@ras ,@sl ,@ren ,@m_curve6 );
+ render_ctrl(@ras ,@sl ,@ren ,@m_curve7 );
+ render_ctrl(@ras ,@sl ,@ren ,@m_curve8 );
+ render_ctrl(@ras ,@sl ,@ren ,@m_curve9 );
+
+ render_ctrl(@ras ,@sl ,@ren ,@m_scale_x );
+ render_ctrl(@ras ,@sl ,@ren ,@m_start_x );
+
+// Free AGG resources
+ ras.Destruct;
+ sl.Destruct;
+
+ patt.Destruct;
+ ras_img.Destruct;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+var
+ fd : text;
+ buf : array[0..255 ] of char;
+
+begin
+ if key = byte(' ' ) then
+ begin
+ AssignFile(fd ,'coord' );
+ rewrite (fd );
+
+ sprintf(@buf[0 ] ,'%.0f, ' ,m_curve1._x1 );
+ sprintf(@buf[StrLen(@buf ) ] ,'%.0f, ' ,m_curve1._y1 );
+ sprintf(@buf[StrLen(@buf ) ] ,'%.0f, ' ,m_curve1._x2 );
+ sprintf(@buf[StrLen(@buf ) ] ,'%.0f, ' ,m_curve1._y2 );
+ sprintf(@buf[StrLen(@buf ) ] ,'%.0f, ' ,m_curve1._x3 );
+ sprintf(@buf[StrLen(@buf ) ] ,'%.0f, ' ,m_curve1._y3 );
+ sprintf(@buf[StrLen(@buf ) ] ,'%.0f, ' ,m_curve1._x4 );
+ sprintf(@buf[StrLen(@buf ) ] ,'%.0f' ,m_curve1._y4 );
+
+ write(fd ,PChar(@buf[0 ] ) );
+ close(fd );
+
+ end;
+
+ if key = key_f1 then
+ message_(
+ 'The demo shows a very powerful mechanism of using arbitrary images as line patterns. '#13 +
+ 'The main point of it is that the images are drawn along the path. It allows you to '#13 +
+ 'draw very fancy looking lines quite easily and very useful in GIS/cartography applications. '#13 +
+ 'There the bilinear filtering is used, but it''s also possible to add any other filtering '#13 +
+ 'methods, or just use the nearest neighbour one for the sake of speed. '#13 +
+ 'Actually, the algorithm uses 32bit images with alpha channel, but in this demo alpha is '#13 +
+ 'simulated in such a way that wite is transparent, black is opaque. The intermediate colors '#13 +
+ 'have intermediate opacity that is defined by the brightness_to_alpha array.'#13#13 +
+ 'How to play with:'#13#13 +
+ 'In the demo you can drag the control points of the curves and observe that the images '#13 +
+ 'are transformed quite consistently and smoothly. You can also try to replace the image '#13 +
+ 'files (1…9) with your own. The BMP files must have 24bit colors (TrueColor), the PPM '#13 +
+ 'ones must be of type "P6". Also, the heigh should not exceed 64 pixels, and the background '#13 +
+ 'should be white or very close to white.'#13 +
+ 'Press the spacebar to write down the "coord" file of the curve 1 (of 1.bmp).' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+{ ON_CTRL_CHANGE }
+procedure the_application.on_ctrl_change;
+begin
+end;
+
+VAR
+ app : the_application;
+ buf : array [0..255 ] of char;
+ ext : string[10 ];
+
+BEGIN
+ app.Construct(pix_format_bgr24 ,flip_y );
+ app.caption_ ('AGG Example. Drawing Lines with Image Patterns (F1-Help)' );
+
+ if not app.load_img(0 ,'1' ) or
+ not app.load_img(1 ,'2' ) or
+ not app.load_img(2 ,'3' ) or
+ not app.load_img(3 ,'4' ) or
+ not app.load_img(4 ,'5' ) or
+ not app.load_img(5 ,'6' ) or
+ not app.load_img(6 ,'7' ) or
+ not app.load_img(7 ,'8' ) or
+ not app.load_img(8 ,'9' ) then
+ begin
+ ext:=app._img_ext;
+
+ sprintf(@buf[0 ] ,'There must be files 1%s' ,ptrcomp(@ext[1 ] ) );
+ sprintf(
+ @buf[StrLen(@buf ) ] ,
+ '...9%s'#13 +
+ 'Download and unzip:'#13 +
+ 'http://www.antigrain.com/line_patterns.bmp.zip'#13 +
+ 'or'#13 +
+ 'http://www.antigrain.com/line_patterns.ppm.tar.gz'#13 ,
+ ptrcomp(@ext[1 ] ) );
+
+ app.message_(@buf[0 ] );
+
+ end
+ else
+ if app.init(500 ,450 ,window_resize ) then
+ app.run;
+
+ app.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/lion.dpr b/src/corelib/render/software/agg-demos/lion.dpr
new file mode 100644
index 00000000..1991509e
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/lion.dpr
@@ -0,0 +1,305 @@
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ lion ;
+
+{DEFINE AGG_GRAY8 }
+{$DEFINE AGG_BGR24 }
+{DEFINE AGG_RGB24 }
+{DEFINE AGG_BGRA32 }
+{DEFINE AGG_RGBA32 }
+{DEFINE AGG_ARGB32 }
+{DEFINE AGG_ABGR32 }
+{DEFINE AGG_RGB565 }
+{DEFINE AGG_RGB555 }
+
+uses
+ Math ,
+
+ agg_basics ,
+ agg_platform_support ,
+
+ agg_ctrl ,
+ agg_slider_ctrl ,
+
+ agg_rasterizer_scanline_aa ,
+ agg_scanline ,
+ agg_scanline_p ,
+
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_render_scanlines ,
+
+ agg_path_storage ,
+ agg_bounding_rect ,
+ agg_trans_affine ,
+ agg_conv_transform ,
+ parse_lion_
+
+{$I pixel_formats.inc }
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+var
+ g_rasterizer : rasterizer_scanline_aa;
+ g_scanline : scanline_p8;
+
+ g_path : path_storage;
+ g_colors : array[0..99 ] of aggclr;
+ g_path_idx : array[0..99 ] of unsigned;
+
+ g_npaths : unsigned;
+
+ g_x1 ,g_y1 ,g_x2 ,g_y2 ,
+ g_base_dx ,g_base_dy ,
+ g_angle ,g_scale ,
+ g_skew_x ,g_skew_y : double;
+
+ g_nclick : int;
+
+type
+ the_application = object(platform_support )
+ m_alpha_slider : slider_ctrl;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure on_resize(sx ,sy : int ); virtual;
+ procedure on_draw; virtual;
+
+ procedure transform(width_ ,height_ ,x ,y : double );
+
+ procedure on_mouse_move (x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ _PARSE_LION_ }
+procedure _parse_lion_;
+begin
+ g_npaths:=parse_lion(@g_path ,@g_colors ,@g_path_idx );
+
+ bounding_rect(@g_path ,@g_path_idx ,0 ,g_npaths ,@g_x1 ,@g_y1 ,@g_x2 ,@g_y2 );
+
+ g_base_dx:=(g_x2 - g_x1 ) / 2.0;
+ g_base_dy:=(g_y2 - g_y1 ) / 2.0;
+
+end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_alpha_slider.Construct(5 ,5 ,512 - 5 ,12 ,not flip_y_ );
+
+ _parse_lion_;
+
+ add_ctrl(@m_alpha_slider );
+
+ m_alpha_slider.no_transform;
+ m_alpha_slider.label_('Alpha%3.3f' );
+ m_alpha_slider.value_(0.1 );
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_alpha_slider.Destruct;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ i : unsigned;
+
+ width_ ,height_ : int;
+
+ pixf : pixel_formats;
+
+ rb : renderer_base;
+ r : renderer_scanline_aa_solid;
+
+ mtx : trans_affine;
+ tat : trans_affine_translation;
+ tas : trans_affine_scaling;
+ tar : trans_affine_rotation;
+ taw : trans_affine_skewing;
+
+ trans : conv_transform;
+
+begin
+ width_ :=rbuf_window._width;
+ height_:=rbuf_window._height;
+
+ for i:=0 to g_npaths - 1 do
+ aggclr_ptr(ptrcomp(@g_colors[0 ] ) + i * sizeof(aggclr ) ).a:=
+ int8u(trunc(m_alpha_slider._value * 255 ) );
+
+// Initialize structures
+ pixfmt(pixf ,rbuf_window );
+
+ rb.Construct(@pixf );
+ r.Construct (@rb );
+
+// Transform lion
+ mtx.Construct;
+
+ tat.Construct(-g_base_dx ,-g_base_dy );
+ mtx.multiply (@tat );
+
+ tas.Construct(g_scale ,g_scale );
+ mtx.multiply (@tas );
+
+ tar.Construct(g_angle + pi );
+ mtx.multiply (@tar );
+
+ taw.Construct(g_skew_x / 1000.0 ,g_skew_y / 1000.0 );
+ mtx.multiply (@taw );
+
+ tat.Construct(width_ / 2 ,height_ / 2 );
+ mtx.multiply (@tat );
+
+// This code renders the lion
+ trans.Construct(@g_path ,@mtx );
+
+ render_all_paths(@g_rasterizer ,@g_scanline ,@r ,@trans ,@g_colors ,@g_path_idx ,g_npaths );
+
+// Render the control
+ render_ctrl(@g_rasterizer ,@g_scanline ,@r ,@m_alpha_slider );
+
+end;
+
+{ ON_RESIZE }
+procedure the_application.on_resize;
+var
+ pf : pixel_formats;
+ r : renderer_base;
+
+ rgba : aggclr;
+
+begin
+ pixfmt(pf ,rbuf_window );
+
+ r.Construct (@pf );
+ rgba.ConstrDbl(1 ,1 ,1 );
+ r.clear (@rgba );
+
+end;
+
+{ TRANSFORM }
+procedure the_application.transform;
+begin
+ x:=x - (width_ / 2 );
+ y:=y - (height_ / 2 );
+
+ g_angle:=ArcTan2(y ,x );
+ g_scale:=Sqrt (y * y + x * x ) / 100.0;
+
+end;
+
+{ ON_MOUSE_MOVE }
+procedure the_application.on_mouse_move;
+begin
+ on_mouse_button_down(x ,y ,flags );
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure the_application.on_mouse_button_down;
+var
+ width_ ,height_ : int;
+
+begin
+ if flags and mouse_left <> 0 then
+ begin
+ width_ :=rbuf_window._width;
+ height_:=rbuf_window._height;
+
+ transform(_width ,_height ,x ,y );
+ force_redraw;
+
+ end;
+
+ if flags and mouse_right <> 0 then
+ begin
+ g_skew_x:=x;
+ g_skew_y:=y;
+
+ force_redraw;
+
+ end;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ 'This is the first example I used to implement and debug the scanline rasterizer, '#13 +
+ 'affine transformer, and basic renderers. The image is drawn over the old one '#13 +
+ 'with a cetrain opacity value.'#13#13 +
+ 'How to play with:'#13#13 +
+ 'You can rotate and scale the "Lion" with the left mouse button. '#13 +
+ 'Right mouse button adds "skewing" transformations, '#13 +
+ 'proportional to the "X" coordinate. '#13 +
+ 'Change "Alpha" to draw funny looking "lions". '#13 +
+ 'Change window size to clear the window.' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+VAR
+ app : the_application;
+
+BEGIN
+// Rendering
+ g_rasterizer.Construct;
+ g_scanline.Construct;
+ g_path.Construct;
+
+ g_npaths:=0;
+
+ g_x1:=0;
+ g_y1:=0;
+ g_x2:=0;
+ g_y2:=0;
+
+ g_base_dx:=0;
+ g_base_dy:=0;
+
+ g_angle:=0;
+ g_scale:=1.0;
+
+ g_skew_x:=0;
+ g_skew_y:=0;
+ g_nclick:=0;
+
+// App
+ app.Construct(pix_format ,flip_y );
+ app.caption_ ('AGG Example. Lion (F1-Help)' );
+
+ if app.init(512 ,400 ,window_resize ) then
+ app.run;
+
+ app.Destruct;
+
+// Free
+ g_rasterizer.Destruct;
+ g_scanline.Destruct;
+ g_path.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/lion_lens.dpr b/src/corelib/render/software/agg-demos/lion_lens.dpr
new file mode 100644
index 00000000..89c6ca52
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/lion_lens.dpr
@@ -0,0 +1,293 @@
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ lion_lens ;
+
+{DEFINE AGG_GRAY8 }
+{$DEFINE AGG_BGR24 }
+{DEFINE AGG_RGB24 }
+{DEFINE AGG_BGRA32 }
+{DEFINE AGG_RGBA32 }
+{DEFINE AGG_ARGB32 }
+{DEFINE AGG_ABGR32 }
+{DEFINE AGG_RGB565 }
+{DEFINE AGG_RGB555 }
+
+uses
+ agg_basics ,
+ agg_platform_support ,
+
+ agg_ctrl ,
+ agg_slider_ctrl ,
+
+ agg_rasterizer_scanline_aa ,
+ agg_scanline ,
+ agg_scanline_p ,
+
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_render_scanlines ,
+
+ agg_path_storage ,
+ agg_bounding_rect ,
+ agg_trans_affine ,
+ agg_trans_warp_magnifier ,
+ agg_conv_transform ,
+ agg_conv_segmentator ,
+ parse_lion_
+
+{$I pixel_formats.inc }
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+var
+ g_rasterizer : rasterizer_scanline_aa;
+ g_scanline : scanline_p8;
+
+ g_path : path_storage;
+ g_colors : array[0..99 ] of aggclr;
+ g_path_idx : array[0..99 ] of unsigned;
+
+ g_npaths : unsigned;
+
+ g_x1 ,g_y1 ,g_x2 ,g_y2 ,
+ g_base_dx ,g_base_dy ,
+ g_angle ,g_scale ,
+ g_skew_x ,g_skew_y : double;
+
+ g_nclick : int;
+
+type
+ the_application = object(platform_support )
+ m_magn_slider ,
+ m_radius_slider : slider_ctrl;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure on_init; virtual;
+ procedure on_draw; virtual;
+
+ procedure on_mouse_move (x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ _PARSE_LION_ }
+procedure _parse_lion_;
+begin
+ g_npaths:=parse_lion(@g_path ,@g_colors ,@g_path_idx );
+
+ bounding_rect(@g_path ,@g_path_idx ,0 ,g_npaths ,@g_x1 ,@g_y1 ,@g_x2 ,@g_y2 );
+
+ g_base_dx:=(g_x2 - g_x1 ) / 2.0;
+ g_base_dy:=(g_y2 - g_y1 ) / 2.0;
+
+end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_magn_slider.Construct (5 ,5 ,495 ,12 ,not flip_y_ );
+ m_radius_slider.Construct(5 ,20 ,495 ,27 ,not flip_y_ );
+
+ _parse_lion_;
+
+ add_ctrl(@m_magn_slider );
+
+ m_magn_slider.no_transform;
+ m_magn_slider.range_(0.01 ,4.0 );
+ m_magn_slider.value_(3.0 );
+ m_magn_slider.label_('Scale=%3.2f' );
+
+ add_ctrl(@m_radius_slider );
+
+ m_radius_slider.no_transform;
+ m_radius_slider.range_(0.0 ,100.0 );
+ m_radius_slider.value_(70.0 );
+ m_radius_slider.label_('Radius=%3.2f' );
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_magn_slider.Destruct;
+ m_radius_slider.Destruct;
+
+end;
+
+{ ON_INIT }
+procedure the_application.on_init;
+begin
+ g_x1:=200;
+ g_y1:=150;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ pixf : pixel_formats;
+
+ rb : renderer_base;
+ r : renderer_scanline_aa_solid;
+
+ rgba : aggclr;
+
+ lens : trans_warp_magnifier;
+ segm : conv_segmentator;
+
+ mtx : trans_affine;
+ tat : trans_affine_translation;
+ tar : trans_affine_rotation;
+
+ trans_mtx ,
+ trans_lens : conv_transform;
+
+begin
+// Initialize structures
+ pixfmt(pixf ,rbuf_window );
+
+ rb.Construct(@pixf );
+ r.Construct (@rb );
+
+ rgba.ConstrDbl(1 ,1 ,1 );
+ rb.clear (@rgba );
+
+// Transform lion
+ lens.Construct;
+ lens.center (g_x1 ,g_y1 );
+ lens.magnification(m_magn_slider._value );
+ lens.radius (m_radius_slider._value / m_magn_slider._value );
+
+ segm.Construct(@g_path );
+ mtx.Construct;
+
+ tat.Construct(-g_base_dx ,-g_base_dy );
+ mtx.multiply (@tat );
+
+ tar.Construct(g_angle + pi );
+ mtx.multiply (@tar );
+
+ tat.Construct(_width / 2 ,_height / 2);
+ mtx.multiply (@tat );
+
+ trans_mtx.Construct (@segm ,@mtx );
+ trans_lens.Construct(@trans_mtx ,@lens );
+
+ render_all_paths(@g_rasterizer ,@g_scanline ,@r ,@trans_lens ,@g_colors ,@g_path_idx ,g_npaths );
+
+// Render the controls
+ render_ctrl(@g_rasterizer ,@g_scanline ,@r ,@m_magn_slider );
+ render_ctrl(@g_rasterizer ,@g_scanline ,@r ,@m_radius_slider );
+
+// Free
+ segm.Destruct;
+
+end;
+
+{ ON_MOUSE_MOVE }
+procedure the_application.on_mouse_move;
+begin
+ on_mouse_button_down(x ,y ,flags );
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure the_application.on_mouse_button_down;
+begin
+ if flags and mouse_left <> 0 then
+ begin
+ g_x1:=x;
+ g_y1:=y;
+
+ force_redraw;
+
+ end;
+
+ if flags and mouse_right <> 0 then
+ begin
+ g_x2:=x;
+ g_y2:=y;
+
+ force_redraw;
+
+ end;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ 'This example exhibits a non-linear transformer that "magnifies" vertices that fall '#13 +
+ 'inside a circle and extends the rest (trans_warp_magnifier). Non-linear transformations '#13 +
+ 'are tricky because straight lines become curves. To achieve the correct result we need '#13 +
+ 'to divide long line segments into short ones. The example also demonstrates the use of '#13 +
+ 'conv_segmentator that does this division job. The transformer can also shrink away '#13 +
+ 'the image if the scaling value is less than 1.'#13#13 +
+ 'How to play with:'#13#13 +
+ 'Drag the center of the "lens" with the left mouse button and change the "Scale" and "Radius". '#13 +
+ 'To watch for an amazing effect, set the scale to the minimum (0.01), decrease the radius '#13 +
+ 'to about 1 and drag the "lens". You will see it behaves like a black hole consuming space '#13 +
+ 'around it. Move the lens somewhere to the side of the window and change the radius. It looks '#13 +
+ 'like changing the event horizon of the "black hole".' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+VAR
+ app : the_application;
+
+BEGIN
+// Rendering
+ g_rasterizer.Construct;
+ g_scanline.Construct;
+ g_path.Construct;
+
+ g_npaths:=0;
+
+ g_x1:=0;
+ g_y1:=0;
+ g_x2:=0;
+ g_y2:=0;
+
+ g_base_dx:=0;
+ g_base_dy:=0;
+
+ g_angle:=0;
+ g_scale:=1.0;
+
+ g_skew_x:=0;
+ g_skew_y:=0;
+ g_nclick:=0;
+
+// App
+ app.Construct(pix_format ,flip_y );
+ app.caption_ ('AGG Example. Lion (F1-Help)' );
+
+ if app.init(500 ,600 ,window_resize ) then
+ app.run;
+
+ app.Destruct;
+
+// Free
+ g_rasterizer.Destruct;
+ g_scanline.Destruct;
+ g_path.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/lion_outline.dpr b/src/corelib/render/software/agg-demos/lion_outline.dpr
new file mode 100644
index 00000000..533209db
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/lion_outline.dpr
@@ -0,0 +1,334 @@
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ lion_outline ;
+
+{DEFINE AGG_GRAY8 }
+{$DEFINE AGG_BGR24 }
+{DEFINE AGG_RGB24 }
+{DEFINE AGG_BGRA32 }
+{DEFINE AGG_RGBA32 }
+{DEFINE AGG_ARGB32 }
+{DEFINE AGG_ABGR32 }
+{DEFINE AGG_RGB565 }
+{DEFINE AGG_RGB555 }
+
+uses
+ Math ,
+
+ agg_basics ,
+ agg_platform_support ,
+
+ agg_ctrl ,
+ agg_slider_ctrl ,
+ agg_cbox_ctrl ,
+
+ agg_rasterizer_scanline_aa ,
+ agg_rasterizer_outline_aa ,
+ agg_scanline ,
+ agg_scanline_p ,
+
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_renderer_outline_aa ,
+ agg_render_scanlines ,
+
+ agg_path_storage ,
+ agg_bounding_rect ,
+ agg_trans_affine ,
+ agg_conv_stroke ,
+ agg_conv_transform ,
+ agg_vertex_source ,
+ parse_lion_
+
+{$I pixel_formats.inc }
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+var
+ g_rasterizer : rasterizer_scanline_aa;
+ g_scanline : scanline_p8;
+
+ g_path : path_storage;
+ g_colors : array[0..99 ] of aggclr;
+ g_path_idx : array[0..99 ] of unsigned;
+
+ g_npaths : unsigned;
+
+ g_x1 ,g_y1 ,g_x2 ,g_y2 ,
+ g_base_dx ,g_base_dy ,
+ g_angle ,g_scale ,
+ g_skew_x ,g_skew_y : double;
+
+ g_nclick : int;
+
+type
+ the_application = object(platform_support )
+ m_width_slider : slider_ctrl;
+ m_scanline : cbox_ctrl;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure on_draw; virtual;
+
+ procedure transform(width_ ,height_ ,x ,y : double );
+
+ procedure on_mouse_move (x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ _PARSE_LION_ }
+procedure _parse_lion_;
+begin
+ g_npaths:=parse_lion(@g_path ,@g_colors ,@g_path_idx );
+
+ bounding_rect(@g_path ,@g_path_idx ,0 ,g_npaths ,@g_x1 ,@g_y1 ,@g_x2 ,@g_y2 );
+
+ g_base_dx:=(g_x2 - g_x1 ) / 2.0;
+ g_base_dy:=(g_y2 - g_y1 ) / 2.0;
+
+end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_width_slider.Construct(5 ,5 ,150 ,12 ,not flip_y_ );
+ m_scanline.Construct (160 ,5 ,'Use Scanline Rasterizer' ,not flip_y_ );
+
+ _parse_lion_;
+
+ add_ctrl(@m_width_slider );
+
+ m_width_slider.no_transform;
+ m_width_slider.range_(0.0 ,4.0 );
+ m_width_slider.value_(1.0 );
+ m_width_slider.label_('Width %3.2f' );
+
+ add_ctrl(@m_scanline );
+
+ m_scanline.no_transform;
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_width_slider.Destruct;
+ m_scanline.Destruct;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ width_ ,height_ : int;
+
+ w : double;
+
+ pixf : pixel_formats;
+
+ rb : renderer_base;
+ r : renderer_scanline_aa_solid;
+
+ rgba : aggclr;
+
+ mtx : trans_affine;
+ tat : trans_affine_translation;
+ tas : trans_affine_scaling;
+ tar : trans_affine_rotation;
+ taw : trans_affine_skewing;
+
+ stroke : conv_stroke;
+ trans : conv_transform;
+
+ gm_no : vertex_source;
+ profile : line_profile_aa;
+
+ ren : renderer_outline_aa;
+ ras : rasterizer_outline_aa;
+
+begin
+ width_ :=rbuf_window._width;
+ height_:=rbuf_window._height;
+
+// Initialize structures
+ pixfmt(pixf ,rbuf_window );
+
+ rb.Construct(@pixf );
+ r.Construct (@rb );
+
+ rgba.ConstrDbl(1 ,1 ,1 );
+ rb.clear (@rgba );
+
+// Transform lion
+ mtx.Construct;
+
+ tat.Construct(-g_base_dx ,-g_base_dy );
+ mtx.multiply (@tat );
+
+ tas.Construct(g_scale ,g_scale );
+ mtx.multiply (@tas );
+
+ tar.Construct(g_angle + pi );
+ mtx.multiply (@tar );
+
+ taw.Construct(g_skew_x / 1000.0 ,g_skew_y / 1000.0 );
+ mtx.multiply (@taw );
+
+ tat.Construct(width_ / 2 ,height_ / 2 );
+ mtx.multiply (@tat );
+
+// Render lion
+ if m_scanline._status then
+ begin
+ stroke.Construct(@g_path );
+ stroke.width_ (m_width_slider._value );
+ trans.Construct (@stroke ,@mtx );
+
+ render_all_paths(@g_rasterizer ,@g_scanline ,@r ,@trans ,@g_colors ,@g_path_idx ,g_npaths );
+
+ stroke.Destruct;
+
+ end
+ else
+ begin
+ w:=m_width_slider._value * mtx.scale;
+
+ gm_no.Construct;
+ profile.Construct(w ,@gm_no );
+
+ ren.Construct (@rb ,@profile );
+ ras.Construct (@ren );
+ trans.Construct(@g_path ,@mtx );
+
+ ras.render_all_paths(@trans ,@g_colors ,@g_path_idx ,g_npaths );
+
+ profile.Destruct;
+ ras.Destruct;
+
+ end;
+
+// Render the control
+ render_ctrl(@g_rasterizer ,@g_scanline ,@r ,@m_width_slider );
+ render_ctrl(@g_rasterizer ,@g_scanline ,@r ,@m_scanline );
+
+end;
+
+{ TRANSFORM }
+procedure the_application.transform;
+begin
+ x:=x - (width_ / 2 );
+ y:=y - (height_ / 2 );
+
+ g_angle:=ArcTan2(y ,x );
+ g_scale:=Sqrt (y * y + x * x ) / 100.0;
+
+end;
+
+{ ON_MOUSE_MOVE }
+procedure the_application.on_mouse_move;
+begin
+ on_mouse_button_down(x ,y ,flags );
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure the_application.on_mouse_button_down;
+var
+ width_ ,height_ : int;
+
+begin
+ if flags and mouse_left <> 0 then
+ begin
+ width_ :=rbuf_window._width;
+ height_:=rbuf_window._height;
+
+ transform(width_ ,height_ ,x ,y );
+ force_redraw;
+
+ end;
+
+ if flags and mouse_right <> 0 then
+ begin
+ g_skew_x:=x;
+ g_skew_y:=y;
+
+ force_redraw;
+
+ end;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ 'The example demonstrates my new algorithm of drawing Anti-Aliased lines. '#13 +
+ 'The algorithm works about 2.5 times faster than the scanline rasterizer '#13 +
+ 'but has some restrictions, particularly, line joins can be only of the '#13 +
+ '"miter" type, and when so called miter limit is exceded, they are not as '#13 +
+ 'accurate as generated by the stroke converter (conv_stroke).'#13#13 +
+ 'How to play with:'#13#13 +
+ 'To see the difference, maximize the window and try to rotate and scale '#13 +
+ 'the "lion" with and without using the scanline rasterizer (a checkbox '#13 +
+ 'at the bottom). The difference in performance is obvious.' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+VAR
+ app : the_application;
+
+BEGIN
+// Rendering
+ g_rasterizer.Construct;
+ g_scanline.Construct;
+ g_path.Construct;
+
+ g_npaths:=0;
+
+ g_x1:=0;
+ g_y1:=0;
+ g_x2:=0;
+ g_y2:=0;
+
+ g_base_dx:=0;
+ g_base_dy:=0;
+
+ g_angle:=0;
+ g_scale:=1.0;
+
+ g_skew_x:=0;
+ g_skew_y:=0;
+ g_nclick:=0;
+
+// App
+ app.Construct(pix_format ,flip_y );
+ app.caption_ ('AGG Example. Lion (F1-Help)' );
+
+ if app.init(512 ,512 ,window_resize ) then
+ app.run;
+
+ app.Destruct;
+
+// Free
+ g_rasterizer.Destruct;
+ g_scanline.Destruct;
+ g_path.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/make_arrows_.pas b/src/corelib/render/software/agg-demos/make_arrows_.pas
new file mode 100644
index 00000000..c4065578
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/make_arrows_.pas
@@ -0,0 +1,61 @@
+unit
+ make_arrows_ ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_path_storage ;
+
+{ GLOBAL PROCEDURES }
+ procedure make_arrows(ps : path_storage_ptr );
+
+
+IMPLEMENTATION
+{ UNIT IMPLEMENTATION }
+{ MAKE_ARROWS {..}
+procedure make_arrows;
+begin
+ ps.remove_all;
+
+ ps.move_to(1330.599999999999909 ,1282.399999999999864 );
+ ps.line_to(1377.400000000000091 ,1282.399999999999864 );
+ ps.line_to(1361.799999999999955 ,1298.000000000000000 );
+ ps.line_to(1393.000000000000000 ,1313.599999999999909 );
+ ps.line_to(1361.799999999999955 ,1344.799999999999955 );
+ ps.line_to(1346.200000000000045 ,1313.599999999999909 );
+ ps.line_to(1330.599999999999909 ,1329.200000000000045 );
+ ps.close_polygon;
+
+ ps.move_to(1330.599999999999909 ,1266.799999999999955 );
+ ps.line_to(1377.400000000000091 ,1266.799999999999955 );
+ ps.line_to(1361.799999999999955 ,1251.200000000000045 );
+ ps.line_to(1393.000000000000000 ,1235.599999999999909 );
+ ps.line_to(1361.799999999999955 ,1204.399999999999864 );
+ ps.line_to(1346.200000000000045 ,1235.599999999999909 );
+ ps.line_to(1330.599999999999909 ,1220.000000000000000 );
+ ps.close_polygon;
+
+ ps.move_to(1315.000000000000000 ,1282.399999999999864 );
+ ps.line_to(1315.000000000000000 ,1329.200000000000045 );
+ ps.line_to(1299.400000000000091 ,1313.599999999999909 );
+ ps.line_to(1283.799999999999955 ,1344.799999999999955 );
+ ps.line_to(1252.599999999999909 ,1313.599999999999909 );
+ ps.line_to(1283.799999999999955 ,1298.000000000000000 );
+ ps.line_to(1268.200000000000045 ,1282.399999999999864 );
+ ps.close_polygon;
+
+ ps.move_to(1268.200000000000045 ,1266.799999999999955 );
+ ps.line_to(1315.000000000000000 ,1266.799999999999955 );
+ ps.line_to(1315.000000000000000 ,1220.000000000000000 );
+ ps.line_to(1299.400000000000091 ,1235.599999999999909 );
+ ps.line_to(1283.799999999999955 ,1204.399999999999864 );
+ ps.line_to(1252.599999999999909 ,1235.599999999999909 );
+ ps.line_to(1283.799999999999955 ,1251.200000000000045 );
+ ps.close_polygon;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg-demos/make_gb_poly_.pas b/src/corelib/render/software/agg-demos/make_gb_poly_.pas
new file mode 100644
index 00000000..177c164e
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/make_gb_poly_.pas
@@ -0,0 +1,1927 @@
+unit
+ make_gb_poly_ ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_path_storage ;
+
+{ GLOBAL PROCEDURES }
+ procedure make_gb_poly(ps : path_storage_ptr );
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+const
+ poly1 : array[0..1403 ] of double = (
+
+ 1250.8,1312.4,
+ 1252.8,1311.6,
+ 1254,1312,
+ 1254.8,1313.6,
+ 1254.8,1314.8,
+ 1256,1314,
+ 1257.6,1313.6,
+ 1258.4,1314.4,
+ 1260.4,1315.6,
+ 1261.6,1315.6,
+ 1262.4,1315.6,
+ 1263.2,1315.6,
+ 1264.8,1314.8,
+ 1266,1315.2,
+ 1266.8,1315.2,
+ 1267.2,1312.8,
+ 1266.8,1311.2,
+ 1267.6,1310.8,
+ 1268,1310.4,
+ 1268,1308.8,
+ 1268.8,1308.4,
+ 1270,1307.2,
+ 1270,1306.8,
+ 1270,1305.6,
+ 1270.8,1305.6,
+ 1271.2,1304,
+ 1271.2,1304,
+ 1270.4,1305.6,
+ 1270.8,1306.4,
+ 1271.2,1306,
+ 1271.6,1305.6,
+ 1272,1304.8,
+ 1271.6,1303.2,
+ 1271.2,1302.8,
+ 1269.2,1302,
+ 1268.4,1300.4,
+ 1268.4,1300,
+ 1269.2,1300.4,
+ 1270.8,1302.4,
+ 1272.4,1302,
+ 1273.2,1302,
+ 1273.6,1300.4,
+ 1274.8,1299.2,
+ 1274.4,1298,
+ 1275.2,1297.2,
+ 1274.4,1295.6,
+ 1274.4,1294.8,
+ 1274.4,1294.4,
+ 1274.4,1293.6,
+ 1273.6,1293.6,
+ 1273.6,1293.6,
+ 1273.2,1295.2,
+ 1273.6,1296.4,
+ 1273.6,1297.6,
+ 1273.2,1298,
+ 1272,1299.2,
+ 1271.6,1299.2,
+ 1271.2,1298,
+ 1272,1298,
+ 1271.6,1297.6,
+ 1272,1297.2,
+ 1272.4,1295.6,
+ 1270.8,1294,
+ 1272.8,1294.8,
+ 1273.2,1293.6,
+ 1273.6,1293.2,
+ 1272.8,1292.4,
+ 1271.6,1291.2,
+ 1271.2,1291.6,
+ 1270.4,1292,
+ 1268.8,1290.8,
+ 1268.8,1289.2,
+ 1268.4,1287.6,
+ 1266,1286.4,
+ 1265.2,1286.4,
+ 1265.6,1287.2,
+ 1264.4,1287.6,
+ 1264,1287.6,
+ 1263.2,1288,
+ 1264,1287.6,
+ 1264.4,1286.4,
+ 1264.8,1286.4,
+ 1265.2,1286,
+ 1264,1285.2,
+ 1262,1286.4,
+ 1261.6,1286.4,
+ 1261.6,1286.4,
+ 1261.6,1285.6,
+ 1261.2,1284,
+ 1261.6,1283.2,
+ 1262.8,1283.2,
+ 1262.8,1281.6,
+ 1263.2,1280.8,
+ 1263.2,1280,
+ 1263.2,1278.4,
+ 1263.2,1277.6,
+ 1265.2,1275.6,
+ 1264.8,1274.4,
+ 1264,1272.4,
+ 1264.4,1271.2,
+ 1265.2,1271.2,
+ 1265.6,1270.4,
+ 1264,1271.2,
+ 1263.6,1270.4,
+ 1263.2,1270.4,
+ 1263.6,1269.2,
+ 1264.4,1268.4,
+ 1264.4,1266.8,
+ 1265.2,1264.4,
+ 1264.8,1261.6,
+ 1266,1261.2,
+ 1264.8,1258.4,
+ 1264,1257.6,
+ 1263.2,1256,
+ 1262,1254,
+ 1262.4,1251.6,
+ 1260,1247.6,
+ 1259.6,1246.8,
+ 1258.8,1247.2,
+ 1258.8,1246.8,
+ 1258.8,1246,
+ 1259.2,1245.6,
+ 1259.2,1246,
+ 1259.2,1244.4,
+ 1260,1243.6,
+ 1259.2,1242.4,
+ 1258.8,1242.4,
+ 1259.2,1242.8,
+ 1258,1242.4,
+ 1258,1242.8,
+ 1257.6,1242.8,
+ 1256,1242.4,
+ 1254.4,1244,
+ 1253.2,1243.2,
+ 1253.6,1244,
+ 1253.2,1244,
+ 1252.8,1244,
+ 1252.4,1243.6,
+ 1252.8,1242.8,
+ 1252.4,1242.8,
+ 1251.6,1242,
+ 1250.8,1241.2,
+ 1250.8,1241.6,
+ 1251.6,1242,
+ 1251.6,1242.8,
+ 1251.2,1243.6,
+ 1250.8,1244,
+ 1250.4,1245.2,
+ 1250.8,1243.6,
+ 1250.4,1242.8,
+ 1250.8,1242.8,
+ 1250,1241.6,
+ 1248.4,1242,
+ 1249.2,1243.2,
+ 1248.4,1243.2,
+ 1248.4,1243.2,
+ 1248.4,1242.4,
+ 1247.6,1242.4,
+ 1247.2,1242,
+ 1243.6,1242,
+ 1242,1241.6,
+ 1242,1241.2,
+ 1241.2,1241.6,
+ 1240.8,1241.2,
+ 1241.2,1240.4,
+ 1242,1240,
+ 1241.6,1240,
+ 1241.6,1239.2,
+ 1239.6,1239.2,
+ 1239.2,1238,
+ 1238.4,1238,
+ 1237.6,1238,
+ 1237.2,1238.8,
+ 1236.8,1238,
+ 1236.4,1238,
+ 1236.8,1236.8,
+ 1235.2,1236.4,
+ 1234.4,1235.6,
+ 1234.8,1235.2,
+ 1232.4,1234.8,
+ 1231.2,1235.2,
+ 1231.2,1235.6,
+ 1232.4,1236,
+ 1232.8,1236.8,
+ 1230.8,1236.4,
+ 1229.6,1237.2,
+ 1229.2,1236.4,
+ 1230,1236.4,
+ 1230.8,1235.6,
+ 1230.4,1234.8,
+ 1230.4,1234.4,
+ 1229.6,1233.2,
+ 1228.4,1233.2,
+ 1228,1232.8,
+ 1226.8,1233.2,
+ 1227.2,1232.8,
+ 1226.4,1232,
+ 1226.4,1230.8,
+ 1226,1231.2,
+ 1224.4,1231.2,
+ 1224,1229.6,
+ 1223.2,1229.6,
+ 1223.2,1230.4,
+ 1221.6,1230.8,
+ 1221.2,1229.2,
+ 1220.4,1229.2,
+ 1220.4,1229.2,
+ 1219.6,1230.4,
+ 1218.4,1229.6,
+ 1217.6,1230.8,
+ 1218,1229.6,
+ 1216.8,1229.6,
+ 1216.8,1230,
+ 1216.8,1228.8,
+ 1216.4,1228.8,
+ 1216,1228.8,
+ 1216.4,1228.8,
+ 1215.6,1229.2,
+ 1215.6,1228.8,
+ 1214.8,1228.8,
+ 1214.4,1228.8,
+ 1214,1229.2,
+ 1214.4,1230.4,
+ 1213.6,1231.6,
+ 1213.6,1230.8,
+ 1212.8,1230.4,
+ 1212,1230.8,
+ 1212,1229.6,
+ 1211.6,1229.6,
+ 1211.2,1229.2,
+ 1210.8,1229.6,
+ 1210.8,1230.8,
+ 1209.6,1229.6,
+ 1210,1229.6,
+ 1208.8,1229.2,
+ 1208.8,1230,
+ 1208,1229.2,
+ 1208,1230,
+ 1208,1230,
+ 1209.6,1231.2,
+ 1210.8,1231.2,
+ 1212.4,1232.8,
+ 1212,1232.8,
+ 1208.4,1231.2,
+ 1208,1231.2,
+ 1208.8,1232,
+ 1209.6,1232.8,
+ 1214,1234,
+ 1214,1234,
+ 1214,1234.4,
+ 1213.6,1234.8,
+ 1213.2,1235.6,
+ 1212.8,1236,
+ 1212.8,1235.6,
+ 1212,1234,
+ 1207.2,1233.6,
+ 1206.8,1233.2,
+ 1205.2,1233.2,
+ 1204.8,1233.2,
+ 1204,1233.2,
+ 1203.6,1233.2,
+ 1203.6,1233.2,
+ 1203.6,1233.6,
+ 1204.8,1233.2,
+ 1204.8,1234,
+ 1204.4,1234.4,
+ 1204.8,1234.4,
+ 1206.4,1234.8,
+ 1206.8,1235.6,
+ 1206,1235.6,
+ 1206.4,1236.4,
+ 1207.6,1236.8,
+ 1208,1236.4,
+ 1208,1236.8,
+ 1209.6,1236.8,
+ 1208.8,1237.2,
+ 1210,1238.4,
+ 1211.2,1238.8,
+ 1212.4,1238.4,
+ 1210.4,1238.8,
+ 1209.2,1238,
+ 1208.4,1238,
+ 1208,1237.6,
+ 1207.6,1238,
+ 1204,1236.4,
+ 1204,1236.8,
+ 1202.8,1237.2,
+ 1203.2,1237.6,
+ 1203.6,1238.4,
+ 1203.2,1239.2,
+ 1202.4,1238.8,
+ 1201.2,1238,
+ 1201.6,1239.6,
+ 1200.8,1239.6,
+ 1200.4,1240.4,
+ 1202.4,1240.8,
+ 1202.8,1240.4,
+ 1202.4,1241.2,
+ 1202,1241.6,
+ 1202.8,1242,
+ 1202.8,1242.4,
+ 1206.8,1243.6,
+ 1207.6,1244.8,
+ 1207.6,1244,
+ 1208,1243.6,
+ 1208.8,1245.6,
+ 1209.2,1245.2,
+ 1210.4,1245.2,
+ 1208.8,1246,
+ 1207.6,1246,
+ 1207.6,1245.2,
+ 1207.2,1246,
+ 1204.4,1245.2,
+ 1203.6,1246,
+ 1202.8,1246,
+ 1202.4,1246,
+ 1203.2,1245.6,
+ 1202.8,1245.2,
+ 1201.2,1246,
+ 1202,1245.6,
+ 1200.8,1245.6,
+ 1200,1246,
+ 1200,1246.4,
+ 1200,1246.8,
+ 1200.4,1247.2,
+ 1200,1247.6,
+ 1200.8,1247.6,
+ 1200.8,1247.2,
+ 1201.6,1247.2,
+ 1201.6,1248.8,
+ 1202.4,1248.4,
+ 1203.2,1249.2,
+ 1204.8,1249.6,
+ 1204.8,1248.4,
+ 1206,1248,
+ 1206.8,1249.6,
+ 1206.4,1250,
+ 1207.2,1250.4,
+ 1206.8,1249.2,
+ 1208,1248,
+ 1209.2,1248,
+ 1209.6,1248,
+ 1209.6,1248,
+ 1210.8,1248,
+ 1210.8,1248.4,
+ 1208.8,1248.8,
+ 1208.8,1250,
+ 1209.6,1249.6,
+ 1209.6,1250,
+ 1210,1251.2,
+ 1208.4,1252,
+ 1208.4,1252.4,
+ 1211.2,1252.8,
+ 1212.4,1254,
+ 1213.2,1253.2,
+ 1212.8,1254,
+ 1212.4,1254,
+ 1212.4,1254,
+ 1212.8,1255.2,
+ 1213.6,1255.6,
+ 1215.6,1254.8,
+ 1215.6,1255.2,
+ 1217.6,1254.8,
+ 1221.2,1256,
+ 1221.2,1255.2,
+ 1222,1255.2,
+ 1222.8,1256.4,
+ 1224.4,1256,
+ 1224.8,1256.4,
+ 1226,1256.4,
+ 1224,1257.2,
+ 1222.8,1257.2,
+ 1222.8,1257.6,
+ 1222.4,1258.8,
+ 1221.2,1258.4,
+ 1221.2,1257.6,
+ 1219.6,1255.6,
+ 1218.4,1256,
+ 1217.6,1254.8,
+ 1217.2,1255.6,
+ 1218,1256.4,
+ 1216,1256,
+ 1214.8,1256.4,
+ 1214.4,1257.2,
+ 1214,1257.6,
+ 1214.4,1256.4,
+ 1212.4,1256.4,
+ 1212.4,1255.6,
+ 1209.6,1256,
+ 1208.8,1256,
+ 1210.4,1256.4,
+ 1212.8,1258.4,
+ 1214,1259.6,
+ 1215.2,1259.6,
+ 1215.2,1260.8,
+ 1216,1261.2,
+ 1216,1262.8,
+ 1217.6,1263.6,
+ 1217.2,1263.6,
+ 1215.6,1264,
+ 1215.6,1264,
+ 1216.4,1264.4,
+ 1218.8,1268,
+ 1220.4,1267.6,
+ 1221.6,1268,
+ 1221.2,1268,
+ 1222.8,1268,
+ 1221.6,1268,
+ 1223.2,1268,
+ 1223.2,1268,
+ 1223.6,1267.6,
+ 1223.6,1267.6,
+ 1223.6,1268.4,
+ 1224.4,1269.6,
+ 1223.6,1269.2,
+ 1222.8,1269.6,
+ 1223.2,1270,
+ 1223.6,1270.4,
+ 1224,1270.4,
+ 1224,1271.2,
+ 1222.4,1271.2,
+ 1220.4,1270.4,
+ 1216,1270.4,
+ 1215.2,1270.8,
+ 1215.2,1272.4,
+ 1215.2,1272,
+ 1214.8,1270.8,
+ 1214.8,1270.8,
+ 1214.8,1271.6,
+ 1214.8,1272.4,
+ 1214.8,1273.2,
+ 1214.8,1273.2,
+ 1215.2,1273.2,
+ 1214.8,1273.6,
+ 1214.8,1273.2,
+ 1214.8,1273.6,
+ 1214.4,1273.6,
+ 1214.8,1274,
+ 1214.4,1274,
+ 1213.6,1273.2,
+ 1213.2,1272.8,
+ 1212,1273.6,
+ 1211.2,1273.6,
+ 1211.6,1274.4,
+ 1211.2,1274.4,
+ 1213.2,1275.2,
+ 1213.2,1275.2,
+ 1212.8,1275.2,
+ 1212.8,1275.6,
+ 1211.6,1275.6,
+ 1211.6,1275.6,
+ 1211.6,1275.6,
+ 1211.2,1275.6,
+ 1210.8,1275.6,
+ 1210.4,1274.8,
+ 1209.2,1275.6,
+ 1208.8,1276,
+ 1208,1275.6,
+ 1207.6,1276.4,
+ 1207.2,1276,
+ 1208,1277.6,
+ 1209.2,1277.2,
+ 1208.4,1278,
+ 1208.4,1278.8,
+ 1208,1279.2,
+ 1207.2,1279.6,
+ 1208.8,1279.2,
+ 1208.8,1280,
+ 1210.4,1279.6,
+ 1209.6,1281.2,
+ 1212,1281.2,
+ 1212,1282.4,
+ 1212.4,1283.6,
+ 1214,1284.4,
+ 1215.6,1284,
+ 1216.4,1284.8,
+ 1215.6,1284.8,
+ 1216,1285.2,
+ 1215.6,1285.2,
+ 1216,1286.4,
+ 1216,1286.4,
+ 1216.4,1286.8,
+ 1214,1286.8,
+ 1213.2,1286.8,
+ 1212,1286.8,
+ 1212,1286.8,
+ 1212.4,1288.8,
+ 1213.6,1288,
+ 1214,1287.6,
+ 1214,1287.6,
+ 1214,1289.2,
+ 1213.6,1289.2,
+ 1213.6,1288.4,
+ 1213.6,1289.2,
+ 1213.6,1289.6,
+ 1212.8,1290.4,
+ 1212.8,1291.2,
+ 1213.6,1291.6,
+ 1213.2,1291.6,
+ 1214,1292.4,
+ 1213.2,1292.4,
+ 1213.2,1291.6,
+ 1212.4,1292,
+ 1212,1292,
+ 1212,1292,
+ 1212.8,1292.8,
+ 1212.4,1293.2,
+ 1212.8,1293.6,
+ 1212.4,1294,
+ 1212.8,1294.4,
+ 1212.8,1294.4,
+ 1211.6,1295.2,
+ 1211.6,1294.4,
+ 1211.2,1294.4,
+ 1211.6,1294,
+ 1210.8,1294,
+ 1210.8,1293.6,
+ 1210.4,1293.2,
+ 1210.8,1292,
+ 1210,1292.4,
+ 1210.4,1295.2,
+ 1210.8,1295.2,
+ 1210,1296,
+ 1210.8,1296,
+ 1210.8,1296.4,
+ 1212,1297.6,
+ 1212.4,1296.4,
+ 1213.2,1295.6,
+ 1212.8,1294.8,
+ 1212,1295.6,
+ 1212,1295.2,
+ 1213.6,1294.8,
+ 1213.6,1296,
+ 1214,1295.6,
+ 1214,1296.4,
+ 1214,1296.4,
+ 1213.6,1297.2,
+ 1214,1297.6,
+ 1215.6,1297.2,
+ 1218.4,1296.8,
+ 1219.6,1295.2,
+ 1220.4,1296.4,
+ 1221.2,1296,
+ 1221.6,1295.2,
+ 1222.4,1294.8,
+ 1222,1294.4,
+ 1222.4,1294,
+ 1222,1293.6,
+ 1222.8,1293.2,
+ 1223.2,1292.8,
+ 1224.4,1295.2,
+ 1226,1295.2,
+ 1227.6,1294,
+ 1228.4,1294.4,
+ 1228.8,1294.4,
+ 1229.6,1294,
+ 1230.8,1292.8,
+ 1231.6,1292.8,
+ 1230.8,1294,
+ 1230.4,1294,
+ 1231.2,1294.4,
+ 1232.4,1294.4,
+ 1231.2,1295.6,
+ 1231.2,1295.6,
+ 1232.4,1295.2,
+ 1232.4,1295.6,
+ 1231.6,1296,
+ 1230.4,1295.6,
+ 1230,1296,
+ 1231.2,1296.8,
+ 1231.2,1297.6,
+ 1231.6,1297.6,
+ 1232.8,1298,
+ 1232.4,1298.8,
+ 1232.8,1299.2,
+ 1233.2,1298.8,
+ 1235.2,1298.8,
+ 1236,1300,
+ 1236.4,1300.4,
+ 1237.6,1302.4,
+ 1238,1302.4,
+ 1238.4,1302,
+ 1238,1302.4,
+ 1236,1302.4,
+ 1235.6,1302.4,
+ 1235.6,1302.4,
+ 1235.6,1302.4,
+ 1234.8,1302.4,
+ 1233.2,1300.8,
+ 1233.2,1302,
+ 1234.4,1302.4,
+ 1234.4,1302.4,
+ 1233.2,1302.4,
+ 1232.8,1302.4,
+ 1231.6,1302.4,
+ 1230.4,1302.4,
+ 1228.8,1304,
+ 1229.2,1304.4,
+ 1228.8,1304.4,
+ 1229.6,1304.4,
+ 1229.2,1305.6,
+ 1230.4,1306.4,
+ 1234,1305.6,
+ 1233.2,1306.4,
+ 1232.4,1306.4,
+ 1233.2,1306.4,
+ 1234.4,1305.6,
+ 1232.4,1307.6,
+ 1233.2,1307.6,
+ 1235.6,1307.6,
+ 1234.8,1308.4,
+ 1234.8,1308.8,
+ 1235.6,1308.4,
+ 1236,1308.4,
+ 1235.6,1308.8,
+ 1234.8,1309.2,
+ 1234.8,1308.8,
+ 1234,1309.2,
+ 1234,1310.4,
+ 1235.2,1310.4,
+ 1234.8,1310.4,
+ 1234,1312,
+ 1234.8,1312,
+ 1234.8,1312.8,
+ 1235.6,1312.4,
+ 1235.6,1313.2,
+ 1236,1313.2,
+ 1236,1313.2,
+ 1236.4,1313.2,
+ 1236.4,1313.6,
+ 1236.8,1314.8,
+ 1238.4,1314.4,
+ 1238.8,1314.4,
+ 1238.8,1314.4,
+ 1238.4,1314,
+ 1239.6,1314.4,
+ 1240.4,1314.8,
+ 1240.4,1316.4,
+ 1240.8,1316.8,
+ 1241.6,1316.4,
+ 1241.6,1315.6,
+ 1242,1315.6,
+ 1242.4,1314.8,
+ 1242,1314.4,
+ 1242.8,1314.4,
+ 1242,1314.4,
+ 1242.8,1314.4,
+ 1242.8,1314.4,
+ 1243.2,1315.6,
+ 1242.4,1315.6,
+ 1242,1316.8,
+ 1242.8,1316.8,
+ 1243.2,1316.8,
+ 1243.2,1314.8,
+ 1244,1314.4,
+ 1244.8,1314,
+ 1244.8,1313.2,
+ 1245.2,1314,
+ 1244.8,1316.4,
+ 1244.4,1314.4,
+ 1244.4,1315.2,
+ 1244.4,1316,
+ 1243.6,1316.4,
+ 1244,1316.8,
+ 1244.4,1316.8,
+ 1245.2,1317.6,
+ 1246,1316.8,
+ 1246,1315.2,
+ 1246.8,1314,
+ 1246.8,1314,
+ 1246.8,1312.8,
+ 1245.2,1311.6,
+ 1246,1311.6,
+ 1246.4,1311.6,
+ 1245.2,1311.2,
+ 1244.8,1310,
+ 1246.4,1311.6,
+ 1247.6,1312,
+ 1247.6,1312.4,
+ 1247.6,1314,
+ 1246.8,1316,
+ 1247.6,1316.4,
+ 1246.8,1317.2,
+ 1247.6,1317.2,
+ 1247.6,1317.2,
+ 1248,1317.2,
+ 1249.2,1317.6,
+ 1249.6,1317.6,
+ 1249.6,1317.2,
+ 1250.8,1317.2,
+ 1249.6,1317.6,
+ 1249.2,1318.4,
+ 1249.6,1318.4,
+ 1249.2,1319.2,
+ 1248.8,1319.6,
+ 1248.8,1319.6,
+ 1250.8,1319.2,
+ 1251.6,1318.4,
+ 1252.4,1317.6,
+ 1255.2,1316,
+ 1255.2,1315.6,
+ 1252,1314 );
+
+ poly2 : array[0..2309 ] of double = (
+
+ 1284,1396.4,
+ 1284.4,1395.6,
+ 1285.2,1395.6,
+ 1286,1395.2,
+ 1286,1394.8,
+ 1286.8,1395.2,
+ 1286.4,1395.2,
+ 1286.4,1395.2,
+ 1286.8,1394.8,
+ 1288,1394,
+ 1288,1393.6,
+ 1286.8,1391.6,
+ 1288,1392.8,
+ 1288,1393.6,
+ 1288.8,1393.6,
+ 1288.8,1394.8,
+ 1290,1394.4,
+ 1290.8,1393.6,
+ 1291.2,1393.2,
+ 1290.4,1391.2,
+ 1291.6,1393.6,
+ 1292.8,1393.6,
+ 1293.6,1392.8,
+ 1293.6,1393.2,
+ 1293.6,1394,
+ 1294.4,1393.6,
+ 1294.8,1394.4,
+ 1295.6,1394,
+ 1296,1394.8,
+ 1296,1394.4,
+ 1297.6,1394.4,
+ 1298.8,1394.4,
+ 1300.4,1394.8,
+ 1302,1394.8,
+ 1302,1394.4,
+ 1302.4,1394.4,
+ 1303.2,1395.2,
+ 1304.4,1394.8,
+ 1304.4,1395.2,
+ 1303.6,1396.4,
+ 1304.4,1396.8,
+ 1304.4,1396.4,
+ 1306.8,1396,
+ 1306.8,1395.6,
+ 1308.4,1396,
+ 1308.8,1395.6,
+ 1307.6,1392.8,
+ 1307.6,1392,
+ 1308.8,1392,
+ 1307.6,1389.6,
+ 1307.2,1389.2,
+ 1306.4,1387.6,
+ 1304.4,1387.2,
+ 1302.8,1384,
+ 1299.6,1382,
+ 1298.8,1381.6,
+ 1298,1380.8,
+ 1296.4,1379.2,
+ 1296,1377.6,
+ 1295.2,1377.6,
+ 1294.4,1377.2,
+ 1293.6,1376.8,
+ 1293.6,1376.4,
+ 1295.2,1376.4,
+ 1296.4,1376.8,
+ 1296.8,1376.8,
+ 1296.8,1376.4,
+ 1298,1376.4,
+ 1298.8,1377.6,
+ 1299.2,1377.2,
+ 1298,1375.2,
+ 1296.4,1373.6,
+ 1296,1373.6,
+ 1296,1374,
+ 1295.2,1374,
+ 1294,1373.2,
+ 1292.4,1373.6,
+ 1292.4,1372.4,
+ 1290.8,1371.2,
+ 1290.4,1370.4,
+ 1293.2,1372.8,
+ 1295.2,1372.8,
+ 1295.6,1373.6,
+ 1296.4,1372.8,
+ 1294.8,1371.2,
+ 1294.8,1371.2,
+ 1294.8,1370.4,
+ 1294,1370,
+ 1293.6,1369.6,
+ 1292.8,1370,
+ 1293.2,1369.6,
+ 1292.8,1368.8,
+ 1293.6,1368.4,
+ 1294,1368.4,
+ 1294,1368.4,
+ 1295.6,1370,
+ 1295.6,1370.4,
+ 1295.2,1371.2,
+ 1298,1371.2,
+ 1300.4,1372,
+ 1302,1372.4,
+ 1302.8,1373.6,
+ 1304.8,1374.4,
+ 1308.8,1372.4,
+ 1310.8,1373.6,
+ 1311.2,1373.2,
+ 1312.4,1373.2,
+ 1316.8,1372.4,
+ 1317.6,1372.4,
+ 1318.4,1373.2,
+ 1319.6,1372.4,
+ 1320.4,1373.2,
+ 1322,1373.2,
+ 1322,1372.4,
+ 1322.8,1372.8,
+ 1323.6,1372.4,
+ 1324,1371.6,
+ 1324,1370.4,
+ 1324.8,1368.8,
+ 1324.4,1368.8,
+ 1324.8,1368,
+ 1325.2,1368,
+ 1321.6,1363.2,
+ 1320.8,1360.4,
+ 1321.2,1359.6,
+ 1319.6,1356,
+ 1319.6,1354.4,
+ 1318.4,1352.4,
+ 1317.2,1351.2,
+ 1316.8,1351.2,
+ 1316.8,1349.2,
+ 1316.8,1349.2,
+ 1315.6,1348.4,
+ 1316,1347.6,
+ 1315.2,1346,
+ 1312.8,1344.4,
+ 1312.4,1344,
+ 1311.6,1344,
+ 1310.8,1343.6,
+ 1310,1344,
+ 1309.2,1343.6,
+ 1308.4,1343.6,
+ 1305.6,1342,
+ 1304.8,1341.6,
+ 1305.2,1341.2,
+ 1306.4,1342,
+ 1310.4,1343.6,
+ 1311.6,1343.2,
+ 1311.2,1342,
+ 1311.2,1341.6,
+ 1311.2,1341.6,
+ 1312,1340.4,
+ 1313.6,1340.4,
+ 1314.8,1338.8,
+ 1313.2,1338,
+ 1311.6,1337.6,
+ 1310,1337.6,
+ 1309.6,1337.6,
+ 1307.2,1335.2,
+ 1306.8,1334.4,
+ 1305.2,1334,
+ 1303.6,1332.8,
+ 1301.2,1334,
+ 1299.6,1334,
+ 1299.6,1332.8,
+ 1300,1332.8,
+ 1302,1332.8,
+ 1304,1332.4,
+ 1304.4,1332.8,
+ 1305.2,1332.4,
+ 1307.2,1332.4,
+ 1307.6,1331.6,
+ 1308.8,1331.6,
+ 1309.6,1332.4,
+ 1310,1332.4,
+ 1310.8,1332.8,
+ 1310.8,1333.6,
+ 1311.6,1334.4,
+ 1313.6,1334.4,
+ 1314.8,1332.8,
+ 1314.8,1332.8,
+ 1316,1332.8,
+ 1318.4,1330.8,
+ 1320.8,1330.4,
+ 1320.8,1330.4,
+ 1321.6,1329.6,
+ 1322.8,1326.8,
+ 1324.8,1324.4,
+ 1325.2,1324.4,
+ 1325.6,1324,
+ 1325.6,1323.6,
+ 1325.6,1323.2,
+ 1326.8,1323.2,
+ 1327.2,1323.2,
+ 1327.6,1321.6,
+ 1328.4,1320.4,
+ 1328.4,1319.2,
+ 1328,1318,
+ 1328.8,1316.8,
+ 1328.4,1315.6,
+ 1329.6,1313.2,
+ 1329.6,1312.4,
+ 1330.8,1309.2,
+ 1331.6,1308,
+ 1331.6,1307.2,
+ 1332.8,1303.6,
+ 1333.2,1302,
+ 1334.4,1301.6,
+ 1334,1301.6,
+ 1334.4,1300.8,
+ 1334.4,1299.6,
+ 1334.4,1299.6,
+ 1334.8,1299.6,
+ 1334.8,1300,
+ 1337.2,1299.2,
+ 1339.6,1298.4,
+ 1341.6,1297.2,
+ 1342.8,1296.8,
+ 1343.6,1296.4,
+ 1343.6,1295.6,
+ 1344.8,1294,
+ 1346,1292,
+ 1347.2,1291.2,
+ 1347.6,1289.6,
+ 1350,1288.8,
+ 1348.8,1287.6,
+ 1348,1286.4,
+ 1349.6,1282.8,
+ 1351.2,1280,
+ 1352.8,1277.2,
+ 1353.2,1275.6,
+ 1353.2,1275.6,
+ 1353.2,1276.4,
+ 1352.8,1276.8,
+ 1351.6,1277.2,
+ 1351.2,1276.8,
+ 1350.4,1276.8,
+ 1349.6,1277.2,
+ 1348,1279.2,
+ 1347.2,1279.6,
+ 1345.6,1278.4,
+ 1343.6,1278,
+ 1342.4,1278.8,
+ 1341.2,1278,
+ 1341.6,1277.6,
+ 1342.8,1278,
+ 1344,1277.6,
+ 1344.8,1277.6,
+ 1347.2,1278.4,
+ 1348,1278,
+ 1348.4,1277.2,
+ 1350.4,1275.6,
+ 1351.2,1275.6,
+ 1351.6,1274.4,
+ 1352.4,1273.2,
+ 1353.6,1273.2,
+ 1354,1272.4,
+ 1354.8,1271.2,
+ 1356,1267.6,
+ 1356.8,1266,
+ 1356.4,1264.4,
+ 1354,1262,
+ 1352.8,1259.6,
+ 1352.4,1259.6,
+ 1352,1259.2,
+ 1352.8,1259.2,
+ 1353.6,1259.2,
+ 1354,1258.8,
+ 1355.6,1257.2,
+ 1357.2,1257.6,
+ 1357.6,1256.4,
+ 1357.6,1256.8,
+ 1358,1258,
+ 1358.8,1260.8,
+ 1359.6,1261.6,
+ 1360.4,1261.2,
+ 1361.2,1261.6,
+ 1364,1261.2,
+ 1364.4,1261.6,
+ 1364.8,1261.6,
+ 1365.6,1261.6,
+ 1366.4,1261.6,
+ 1365.6,1262,
+ 1366,1262,
+ 1366.8,1262,
+ 1367.6,1261.6,
+ 1370.4,1261.2,
+ 1372.4,1259.6,
+ 1376,1257.2,
+ 1376.4,1257.2,
+ 1377.6,1254.4,
+ 1377.6,1252.8,
+ 1378,1251.6,
+ 1377.6,1250,
+ 1378,1248.8,
+ 1376.4,1245.6,
+ 1376.4,1243.6,
+ 1376,1241.2,
+ 1374,1240,
+ 1372.8,1237.2,
+ 1371.6,1238.8,
+ 1371.6,1237.6,
+ 1370,1238,
+ 1369.6,1237.6,
+ 1372,1237.6,
+ 1370.8,1235.2,
+ 1371.6,1235.2,
+ 1371.6,1236,
+ 1372,1235.2,
+ 1372,1235.2,
+ 1370.8,1234,
+ 1369.6,1233.2,
+ 1368.4,1233.6,
+ 1367.6,1234,
+ 1366.8,1234,
+ 1366,1233.2,
+ 1365.6,1232.4,
+ 1363.6,1232,
+ 1364.4,1231.6,
+ 1364.8,1231.6,
+ 1366.4,1232.8,
+ 1367.2,1232.4,
+ 1367.2,1231.2,
+ 1366.8,1229.6,
+ 1366.4,1229.6,
+ 1365.2,1229.2,
+ 1366,1229.6,
+ 1366.4,1229.2,
+ 1366.4,1229.6,
+ 1367.2,1229.6,
+ 1367.6,1229.2,
+ 1365.2,1227.2,
+ 1363.2,1227.2,
+ 1362,1226,
+ 1360.4,1226,
+ 1360,1226,
+ 1359.2,1225.2,
+ 1360,1225.2,
+ 1360.4,1226,
+ 1361.6,1226,
+ 1364,1226,
+ 1364.4,1225.2,
+ 1364,1224.8,
+ 1363.2,1224.8,
+ 1362.4,1224.4,
+ 1361.6,1224.4,
+ 1362.4,1223.6,
+ 1363.2,1223.6,
+ 1363.6,1223.6,
+ 1364,1223.6,
+ 1364,1224.4,
+ 1364.4,1224,
+ 1364.4,1224.4,
+ 1364.4,1225.2,
+ 1366.8,1224.8,
+ 1367.6,1223.2,
+ 1366.8,1223.2,
+ 1365.2,1222.8,
+ 1367.2,1222.8,
+ 1371.6,1224,
+ 1375.2,1224.4,
+ 1374.8,1223.2,
+ 1374,1222,
+ 1374.8,1220.4,
+ 1374.4,1218.4,
+ 1374,1218,
+ 1372,1217.2,
+ 1371.6,1217.2,
+ 1370.4,1216.4,
+ 1369.2,1215.6,
+ 1368.4,1214.4,
+ 1368.8,1212.8,
+ 1366,1212.8,
+ 1364.8,1212.4,
+ 1364,1211.6,
+ 1359.2,1210,
+ 1358.4,1208.4,
+ 1357.6,1207.6,
+ 1354.4,1208.8,
+ 1351.2,1210,
+ 1344,1208.4,
+ 1343.6,1207.6,
+ 1343.2,1208.4,
+ 1343.2,1207.2,
+ 1342.4,1207.2,
+ 1340.8,1208.4,
+ 1341.2,1208.4,
+ 1340.8,1209.6,
+ 1340.4,1209.2,
+ 1340,1209.6,
+ 1339.6,1209.6,
+ 1340,1209.2,
+ 1340.4,1208.4,
+ 1338.8,1208.4,
+ 1339.2,1208.4,
+ 1339.2,1209.6,
+ 1338.4,1209.2,
+ 1338.4,1208,
+ 1338,1208,
+ 1337.6,1208,
+ 1338,1209.2,
+ 1338,1210,
+ 1336.4,1209.2,
+ 1337.2,1208.8,
+ 1336.8,1208,
+ 1334.4,1209.2,
+ 1333.6,1210.4,
+ 1332,1211.2,
+ 1332,1210.8,
+ 1333.2,1210.4,
+ 1334.4,1208.8,
+ 1333.6,1208,
+ 1332.4,1208,
+ 1331.2,1206.8,
+ 1329.2,1206.8,
+ 1328,1206.8,
+ 1328.4,1206.8,
+ 1328.4,1206.8,
+ 1327.2,1206.8,
+ 1326.4,1206.8,
+ 1325.2,1205.6,
+ 1325.2,1206.8,
+ 1323.6,1206.8,
+ 1323.2,1205.6,
+ 1323.6,1206,
+ 1323.6,1205.2,
+ 1325.2,1205.2,
+ 1325.2,1204.4,
+ 1325.6,1204.4,
+ 1325.2,1204,
+ 1324.8,1203.2,
+ 1323.6,1203.2,
+ 1323.2,1203.2,
+ 1321.2,1204,
+ 1318,1204,
+ 1317.6,1203.6,
+ 1317.2,1202.8,
+ 1318,1202,
+ 1317.2,1201.2,
+ 1317.2,1202.4,
+ 1314.8,1204.4,
+ 1312.4,1206,
+ 1310.8,1206.4,
+ 1309.6,1205.6,
+ 1307.6,1205.6,
+ 1306,1205.6,
+ 1303.6,1203.2,
+ 1302.8,1203.6,
+ 1302,1205.2,
+ 1302.4,1203.2,
+ 1301.2,1201.2,
+ 1301.6,1200,
+ 1300.4,1199.2,
+ 1300.8,1198.8,
+ 1301.6,1198,
+ 1301.2,1198,
+ 1300.8,1197.6,
+ 1300,1197.2,
+ 1300,1196.8,
+ 1299.2,1196.4,
+ 1299.2,1195.6,
+ 1299.2,1194.4,
+ 1298,1194,
+ 1297.2,1194.4,
+ 1297.2,1194.4,
+ 1296.4,1194.4,
+ 1295.6,1196,
+ 1294.4,1196.8,
+ 1292.8,1196.8,
+ 1291.6,1196.8,
+ 1291.6,1197.6,
+ 1290.4,1198,
+ 1290.4,1198,
+ 1291.2,1197.6,
+ 1290.8,1196.8,
+ 1290,1196.8,
+ 1289.6,1198,
+ 1288.8,1198,
+ 1287.2,1198,
+ 1286.4,1197.2,
+ 1283.6,1197.2,
+ 1283.2,1197.2,
+ 1283.2,1197.6,
+ 1282,1197.2,
+ 1281.2,1194.8,
+ 1280,1195.2,
+ 1279.6,1194.4,
+ 1278.8,1194.4,
+ 1278.8,1192.8,
+ 1278,1192.8,
+ 1278.4,1192.8,
+ 1278,1192.8,
+ 1278,1195.2,
+ 1277.6,1195.2,
+ 1277.2,1194.4,
+ 1277.6,1193.6,
+ 1277.2,1192.8,
+ 1277.6,1192.8,
+ 1277.2,1192.8,
+ 1277.2,1192,
+ 1276.4,1192,
+ 1277.2,1191.6,
+ 1277.2,1190.8,
+ 1276.8,1190,
+ 1275.6,1190,
+ 1275.2,1188.8,
+ 1274.4,1190,
+ 1274,1191.2,
+ 1273.2,1191.6,
+ 1270.8,1193.2,
+ 1270,1192.8,
+ 1270,1192,
+ 1269.6,1191.2,
+ 1268,1190.8,
+ 1267.2,1191.6,
+ 1267.6,1192,
+ 1267.2,1193.6,
+ 1268,1193.2,
+ 1270,1195.2,
+ 1271.6,1194.4,
+ 1272.4,1195.2,
+ 1273.2,1195.2,
+ 1274,1196.4,
+ 1274.8,1197.6,
+ 1276,1198.4,
+ 1276,1199.2,
+ 1277.6,1199.6,
+ 1278.4,1200.8,
+ 1278,1201.6,
+ 1278.4,1202.4,
+ 1278.8,1202.4,
+ 1279.6,1203.2,
+ 1279.6,1202.8,
+ 1280,1203.6,
+ 1282,1203.6,
+ 1282,1205.2,
+ 1283.2,1206.4,
+ 1283.6,1207.2,
+ 1285.6,1208,
+ 1285.6,1210.8,
+ 1286.4,1213.2,
+ 1286.8,1213.2,
+ 1288.8,1212.8,
+ 1289.2,1212.8,
+ 1290.4,1213.6,
+ 1291.2,1214.4,
+ 1290,1216.4,
+ 1290.4,1216.4,
+ 1290.4,1216.8,
+ 1290.8,1216.8,
+ 1297.2,1218.8,
+ 1300,1218.4,
+ 1300.4,1218.4,
+ 1302.4,1217.6,
+ 1302.8,1217.2,
+ 1304.4,1217.2,
+ 1306,1217.6,
+ 1308,1217.6,
+ 1308.8,1218.4,
+ 1308.8,1218.8,
+ 1308.8,1220,
+ 1309.2,1220,
+ 1309.6,1222,
+ 1310.4,1222.8,
+ 1312.4,1224.4,
+ 1313.2,1224.8,
+ 1316.8,1230,
+ 1318,1230.8,
+ 1318,1231.6,
+ 1318,1230.8,
+ 1316.8,1230.8,
+ 1313.2,1227.2,
+ 1310.8,1226,
+ 1309.6,1225.6,
+ 1309.6,1225.6,
+ 1309.6,1225.6,
+ 1308.8,1225.6,
+ 1307.2,1224.4,
+ 1307.2,1223.6,
+ 1306.4,1223.6,
+ 1306.4,1222.8,
+ 1305.2,1222.4,
+ 1302.8,1222.4,
+ 1300.8,1222.8,
+ 1299.2,1224.4,
+ 1298.4,1224.4,
+ 1297.2,1225.6,
+ 1296.4,1228,
+ 1294,1228,
+ 1294,1227.6,
+ 1294,1226,
+ 1291.6,1226,
+ 1291.6,1226,
+ 1290.8,1225.6,
+ 1289.6,1226,
+ 1289.6,1227.2,
+ 1290,1227.6,
+ 1290.4,1227.6,
+ 1290.8,1227.6,
+ 1292.4,1228,
+ 1292.8,1228.8,
+ 1293.2,1229.2,
+ 1292,1228.8,
+ 1291.2,1229.6,
+ 1289.6,1229.2,
+ 1289.6,1229.2,
+ 1288.4,1230,
+ 1288.4,1230.8,
+ 1289.6,1230,
+ 1288.8,1231.2,
+ 1288.8,1232,
+ 1288.4,1231.2,
+ 1287.6,1231.6,
+ 1287.6,1230.8,
+ 1284.4,1230.4,
+ 1283.6,1229.2,
+ 1282.8,1229.2,
+ 1282.4,1228.4,
+ 1281.2,1228,
+ 1280,1227.6,
+ 1278.4,1228.4,
+ 1278.4,1229.2,
+ 1277.6,1229.2,
+ 1277.6,1229.6,
+ 1278.4,1229.2,
+ 1278.8,1229.6,
+ 1278.8,1229.6,
+ 1279.6,1229.6,
+ 1281.2,1230,
+ 1279.6,1230.4,
+ 1276.8,1230.4,
+ 1276.8,1229.6,
+ 1276,1230.4,
+ 1275.6,1231.2,
+ 1276.4,1231.2,
+ 1276.8,1232,
+ 1278,1232,
+ 1277.6,1234,
+ 1276.4,1234,
+ 1274.4,1234.4,
+ 1274.8,1236,
+ 1276,1235.6,
+ 1276.4,1236,
+ 1278,1236.8,
+ 1278,1237.6,
+ 1279.6,1237.2,
+ 1280,1237.2,
+ 1280.8,1237.2,
+ 1280.8,1238,
+ 1281.2,1237.2,
+ 1282,1237.6,
+ 1282,1238.4,
+ 1282.8,1238.8,
+ 1283.6,1240,
+ 1284,1240,
+ 1284,1240.8,
+ 1286.8,1240.4,
+ 1288.8,1242.4,
+ 1289.6,1242.4,
+ 1290.8,1242.8,
+ 1292,1244.8,
+ 1292.8,1246.4,
+ 1293.6,1249.6,
+ 1294.4,1250,
+ 1295.2,1250.4,
+ 1293.6,1250.4,
+ 1292.4,1251.6,
+ 1293.6,1254,
+ 1294.4,1255.2,
+ 1293.6,1254.4,
+ 1293.2,1255.2,
+ 1292.4,1255.6,
+ 1292,1256.4,
+ 1292.8,1257.6,
+ 1292,1258.4,
+ 1288.8,1258.4,
+ 1288,1257.6,
+ 1287.6,1256.8,
+ 1287.6,1256.4,
+ 1286.8,1255.2,
+ 1285.6,1256.8,
+ 1285.2,1256.4,
+ 1284,1256.8,
+ 1283.6,1256,
+ 1283.6,1256.8,
+ 1284,1257.6,
+ 1285.6,1258.8,
+ 1286.8,1259.6,
+ 1289.2,1261.6,
+ 1289.2,1263.6,
+ 1290,1263.6,
+ 1290,1263.6,
+ 1292,1266.4,
+ 1292.8,1266.8,
+ 1293.6,1266.8,
+ 1296.4,1267.6,
+ 1296.8,1267.6,
+ 1296.4,1268.8,
+ 1297.6,1268.4,
+ 1298.4,1267.6,
+ 1300,1268,
+ 1303.6,1269.2,
+ 1304.8,1269.2,
+ 1304.8,1268.8,
+ 1307.6,1266.4,
+ 1308,1267.6,
+ 1306,1270,
+ 1306.4,1270,
+ 1308.4,1271.2,
+ 1308.8,1270.4,
+ 1310,1268.4,
+ 1311.2,1268,
+ 1312.4,1268,
+ 1312.8,1268.8,
+ 1312,1268.8,
+ 1310.4,1268.8,
+ 1309.6,1270.4,
+ 1307.6,1273.2,
+ 1309.2,1277.2,
+ 1311.2,1278.8,
+ 1308.4,1278.8,
+ 1308,1280.4,
+ 1308.4,1282.8,
+ 1310.4,1283.6,
+ 1310.8,1283.2,
+ 1311.2,1284.4,
+ 1310.8,1284.4,
+ 1310.8,1284.8,
+ 1310.4,1284.8,
+ 1310,1285.6,
+ 1310.8,1286.8,
+ 1311.6,1286.8,
+ 1311.6,1287.6,
+ 1311.2,1289.2,
+ 1311.6,1290,
+ 1310.8,1290,
+ 1310,1288.4,
+ 1309.6,1288.4,
+ 1308.4,1290,
+ 1307.6,1287.6,
+ 1306.8,1286.4,
+ 1307.2,1286.4,
+ 1305.6,1287.6,
+ 1305.6,1288.4,
+ 1305.6,1288.8,
+ 1306,1288.8,
+ 1306.4,1291.2,
+ 1305.6,1289.6,
+ 1304.4,1289.6,
+ 1303.2,1291.6,
+ 1303.2,1292.8,
+ 1300,1297.2,
+ 1300.8,1299.2,
+ 1301.2,1300.4,
+ 1302,1302,
+ 1302.8,1303.2,
+ 1302.8,1304,
+ 1303.6,1305.6,
+ 1304.4,1306,
+ 1304.4,1305.6,
+ 1305.2,1305.6,
+ 1305.6,1306,
+ 1305.2,1306,
+ 1305.2,1306.8,
+ 1306,1307.6,
+ 1307.6,1306.8,
+ 1308.4,1307.2,
+ 1308.4,1307.6,
+ 1308,1307.6,
+ 1308,1308,
+ 1308.8,1308,
+ 1308.8,1308.4,
+ 1307.2,1308.4,
+ 1305.6,1308,
+ 1303.2,1308,
+ 1302.8,1308,
+ 1302,1308,
+ 1301.6,1308,
+ 1301.2,1308,
+ 1301.2,1308,
+ 1301.2,1305.6,
+ 1300.8,1305.6,
+ 1299.2,1306,
+ 1298.4,1305.6,
+ 1298,1306,
+ 1297.6,1305.6,
+ 1297.6,1306,
+ 1298,1306,
+ 1297.2,1305.2,
+ 1297.6,1304.8,
+ 1295.6,1303.2,
+ 1294.4,1303.2,
+ 1294.4,1304.8,
+ 1294,1303.6,
+ 1293.2,1303.6,
+ 1292,1304.8,
+ 1292.4,1306,
+ 1291.6,1304.8,
+ 1290.4,1306,
+ 1290,1306.4,
+ 1289.6,1307.2,
+ 1289.6,1306,
+ 1289.2,1306.4,
+ 1289.2,1304.8,
+ 1290.4,1304.4,
+ 1290,1303.6,
+ 1290.4,1301.6,
+ 1290,1301.6,
+ 1288,1301.6,
+ 1286.8,1303.6,
+ 1284.4,1304.8,
+ 1284,1306,
+ 1283.6,1306.4,
+ 1282.4,1305.2,
+ 1281.6,1304.4,
+ 1282.4,1301.6,
+ 1282.8,1301.6,
+ 1283.2,1301.2,
+ 1283.6,1300.4,
+ 1283.2,1300.4,
+ 1282,1301.2,
+ 1282,1302.4,
+ 1279.6,1306,
+ 1278.8,1308,
+ 1279.2,1309.6,
+ 1280,1309.6,
+ 1280.4,1309.6,
+ 1280.8,1307.6,
+ 1281.6,1306.4,
+ 1281.6,1307.2,
+ 1280.8,1309.6,
+ 1280.8,1310,
+ 1281.2,1312.4,
+ 1283.6,1314.8,
+ 1284,1317.2,
+ 1284.8,1317.6,
+ 1285.2,1319.2,
+ 1286.8,1319.6,
+ 1286.8,1320.4,
+ 1286.4,1321.6,
+ 1286,1321.6,
+ 1286.4,1322,
+ 1286,1323.2,
+ 1284.4,1324,
+ 1284.4,1324.4,
+ 1283.2,1326,
+ 1284,1326.8,
+ 1283.6,1328.4,
+ 1283.2,1330.8,
+ 1283.6,1331.2,
+ 1284.8,1332.4,
+ 1285.6,1330.8,
+ 1288.8,1330.8,
+ 1286.8,1332,
+ 1285.2,1333.2,
+ 1284.4,1334.4,
+ 1284.8,1333.2,
+ 1285.2,1332.8,
+ 1284.8,1332.8,
+ 1284,1332.8,
+ 1283.6,1334.4,
+ 1284.8,1335.6,
+ 1284,1335.2,
+ 1284,1336,
+ 1283.6,1336.4,
+ 1283.2,1335.6,
+ 1284,1334.8,
+ 1283.6,1333.2,
+ 1282.8,1333.2,
+ 1283.2,1332.8,
+ 1282,1330,
+ 1281.2,1330,
+ 1281.2,1331.2,
+ 1280.8,1332.8,
+ 1280.8,1330.8,
+ 1279.6,1331.2,
+ 1279.6,1332.8,
+ 1279.6,1332.8,
+ 1279.2,1330.8,
+ 1278.8,1330.8,
+ 1279.2,1329.2,
+ 1277.6,1330,
+ 1277.2,1330.8,
+ 1277.6,1333.2,
+ 1278.4,1334.8,
+ 1279.6,1335.6,
+ 1279.6,1336,
+ 1281.2,1336.8,
+ 1281.6,1338,
+ 1283.2,1339.6,
+ 1282,1338.8,
+ 1281.2,1338.8,
+ 1280.8,1337.2,
+ 1278.8,1336,
+ 1277.2,1333.2,
+ 1276.4,1333.2,
+ 1276,1333.2,
+ 1276,1332,
+ 1276.4,1331.2,
+ 1276.4,1330,
+ 1278,1328.4,
+ 1277.6,1327.6,
+ 1276.8,1327.2,
+ 1276,1326,
+ 1275.6,1324.8,
+ 1275.2,1323.6,
+ 1275.6,1323.2,
+ 1275.2,1322.8,
+ 1275.2,1322,
+ 1274,1319.6,
+ 1273.6,1319.6,
+ 1274,1319.6,
+ 1274.8,1318.4,
+ 1274,1317.2,
+ 1272,1316.4,
+ 1270.8,1316.8,
+ 1270.8,1319.2,
+ 1272,1319.6,
+ 1272.4,1322,
+ 1272,1323.2,
+ 1272.8,1324.4,
+ 1272.8,1325.2,
+ 1275.6,1329.2,
+ 1274,1328,
+ 1272.8,1328.4,
+ 1272.8,1329.6,
+ 1274.4,1331.6,
+ 1272.8,1330.8,
+ 1272.8,1331.6,
+ 1274.8,1334.4,
+ 1274,1333.6,
+ 1272.8,1331.6,
+ 1272.4,1331.6,
+ 1272.8,1333.2,
+ 1273.6,1333.6,
+ 1273.6,1334.8,
+ 1274.4,1335.2,
+ 1275.2,1335.2,
+ 1274.8,1336,
+ 1275.2,1338,
+ 1274.4,1336,
+ 1274,1336.4,
+ 1274.8,1338,
+ 1274.4,1339.2,
+ 1274.4,1341.2,
+ 1275.2,1341.2,
+ 1276.4,1344,
+ 1279.2,1343.6,
+ 1278,1344.8,
+ 1277.2,1344.4,
+ 1276.8,1344.8,
+ 1276.8,1344.4,
+ 1276.4,1344.8,
+ 1276.8,1345.6,
+ 1277.6,1345.2,
+ 1278.4,1346,
+ 1279.2,1346.4,
+ 1277.6,1346,
+ 1277.2,1346.4,
+ 1278,1348.4,
+ 1278.4,1348.8,
+ 1278.4,1348.8,
+ 1279.6,1349.2,
+ 1280.8,1349.2,
+ 1281.6,1349.6,
+ 1280.8,1349.2,
+ 1279.2,1349.6,
+ 1281.2,1352.8,
+ 1280,1351.6,
+ 1279.6,1351.6,
+ 1278.8,1350,
+ 1278,1349.6,
+ 1277.6,1349.6,
+ 1276,1348,
+ 1275.2,1346,
+ 1273.2,1345.2,
+ 1273.2,1345.2,
+ 1272.4,1346,
+ 1272.4,1346,
+ 1270.4,1346.8,
+ 1269.6,1347.6,
+ 1269.2,1348.8,
+ 1270,1349.2,
+ 1270.8,1349.2,
+ 1272.8,1350,
+ 1274,1349.6,
+ 1275.2,1349.2,
+ 1273.6,1349.6,
+ 1272.4,1350,
+ 1271.6,1349.6,
+ 1270.8,1350,
+ 1266.8,1350,
+ 1266.4,1350.4,
+ 1267.6,1351.6,
+ 1269.2,1351.6,
+ 1270,1352,
+ 1270.8,1351.6,
+ 1271.2,1351.2,
+ 1271.2,1352,
+ 1271.2,1351.6,
+ 1272.4,1352,
+ 1272.4,1352,
+ 1271.6,1353.2,
+ 1271.6,1353.6,
+ 1272.8,1353.6,
+ 1273.2,1353.6,
+ 1274,1354,
+ 1273.6,1354,
+ 1273.2,1353.6,
+ 1272.8,1354,
+ 1273.2,1354.8,
+ 1270.8,1355.2,
+ 1271.2,1354.8,
+ 1272,1354.8,
+ 1271.6,1355.2,
+ 1272,1357.2,
+ 1273.2,1357.6,
+ 1273.2,1357.2,
+ 1274,1356.4,
+ 1276,1356.8,
+ 1274.8,1356.8,
+ 1274,1357.2,
+ 1274,1357.6,
+ 1274,1358.4,
+ 1272.8,1358.8,
+ 1272.8,1359.2,
+ 1273.6,1360,
+ 1274.4,1360,
+ 1276,1358.8,
+ 1277.2,1359.6,
+ 1275.6,1359.2,
+ 1275.6,1360,
+ 1274.4,1361.2,
+ 1274,1361.6,
+ 1274.8,1361.6,
+ 1274.8,1362.4,
+ 1274.8,1362.8,
+ 1274.8,1363.6,
+ 1276,1363.6,
+ 1276.4,1363.6,
+ 1277.6,1362.4,
+ 1278,1362.8,
+ 1277.2,1362.8,
+ 1276.4,1364,
+ 1274,1364,
+ 1273.6,1364,
+ 1274.4,1365.2,
+ 1276.4,1366.4,
+ 1277.2,1367.6,
+ 1276,1366.4,
+ 1275.2,1365.2,
+ 1274.8,1366.4,
+ 1275.2,1366.4,
+ 1275.2,1366.8,
+ 1273.2,1365.6,
+ 1272.4,1365.6,
+ 1272.4,1366.8,
+ 1272.8,1367.2,
+ 1272.4,1367.2,
+ 1272.8,1367.6,
+ 1272,1368,
+ 1272,1369.2,
+ 1272.8,1370.8,
+ 1273.2,1370.8,
+ 1273.6,1370,
+ 1274,1370.4,
+ 1274.8,1369.2,
+ 1274.8,1369.6,
+ 1275.2,1369.2,
+ 1276.4,1370,
+ 1275.6,1370,
+ 1274.8,1370.4,
+ 1274.4,1370.8,
+ 1274.4,1370.8,
+ 1274,1371.6,
+ 1274,1372.4,
+ 1272.8,1372.4,
+ 1273.2,1374.4,
+ 1274.4,1374.4,
+ 1274.4,1374.4,
+ 1273.6,1374.4,
+ 1272.8,1375.2,
+ 1273.2,1376,
+ 1272.8,1377.6,
+ 1274.4,1378,
+ 1274.8,1377.6,
+ 1274.8,1376,
+ 1275.2,1375.2,
+ 1275.6,1376,
+ 1276,1376,
+ 1276,1377.6,
+ 1275.2,1378,
+ 1275.6,1379.6,
+ 1276,1379.2,
+ 1276.4,1379.6,
+ 1276.4,1378,
+ 1277.6,1378,
+ 1278,1379.2,
+ 1280.8,1377.6,
+ 1280.4,1378,
+ 1278.8,1379.6,
+ 1278.4,1380,
+ 1278.8,1380,
+ 1279.6,1378.8,
+ 1280.4,1379.2,
+ 1281.6,1378,
+ 1282.4,1377.2,
+ 1282.4,1377.6,
+ 1280.8,1379.2,
+ 1281.2,1379.6,
+ 1281.2,1379.6,
+ 1280,1380.4,
+ 1279.2,1381.2,
+ 1278.4,1382.4,
+ 1278.4,1382.4,
+ 1278,1382.8,
+ 1278,1383.6,
+ 1279.2,1382.8,
+ 1279.2,1382.8,
+ 1280.4,1382.8,
+ 1280.8,1382.8,
+ 1280,1384,
+ 1280.4,1384,
+ 1280,1384.4,
+ 1280.4,1384.4,
+ 1280,1384.8,
+ 1280,1384.8,
+ 1279.2,1385.6,
+ 1279.6,1385.6,
+ 1278.8,1386.8,
+ 1278.8,1387.6,
+ 1280,1386,
+ 1281.2,1387.2,
+ 1281.6,1386.4,
+ 1282.4,1387.2,
+ 1284.4,1386.4,
+ 1284,1386.8,
+ 1284.4,1387.2,
+ 1283.2,1387.2,
+ 1282,1388,
+ 1282.4,1388.4,
+ 1282,1388.4,
+ 1281.6,1388.8,
+ 1282.4,1390.4,
+ 1283.6,1390,
+ 1283.2,1390.4,
+ 1282.8,1390.8,
+ 1283.2,1390.8,
+ 1282.8,1391.2,
+ 1283.6,1391.6,
+ 1284.4,1391.2,
+ 1284,1392,
+ 1282.4,1392.8,
+ 1282.4,1393.2,
+ 1283.6,1393.6 );
+
+{ UNIT IMPLEMENTATION }
+{ MAKE_GB_POLY }
+procedure make_gb_poly;
+var
+ i : unsigned;
+ p : double_2_ptr;
+
+begin
+ ps.remove_all;
+
+ p:=@poly1[0 ];
+
+ ps.move_to(p[0 ] ,p[1 ] );
+
+ inc(ptrcomp(p ) ,2 * sizeof(double ) );
+
+ for i:= 1 to (sizeof(poly1 ) div sizeof(double ) div 2 ) - 1 do
+ begin
+ ps.line_to(p[0 ] ,p[1 ] );
+
+ inc(ptrcomp(p ) ,2 * sizeof(double ) );
+
+ end;
+
+ ps.close_polygon;
+
+ p:=@poly2[0 ];
+
+ ps.move_to(p[0 ] ,p[1 ] );
+
+ inc(ptrcomp(p ) ,2 * sizeof(double ) );
+
+ for i:= 1 to (sizeof(poly2 ) div sizeof(double ) div 2 ) - 1 do
+ begin
+ ps.line_to(p[0 ] ,p[1 ] );
+
+ inc(ptrcomp(p ) ,2 * sizeof(double ) );
+
+ end;
+
+ ps.close_polygon;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg-demos/multi_clip.dpr b/src/corelib/render/software/agg-demos/multi_clip.dpr
new file mode 100644
index 00000000..59bd5a74
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/multi_clip.dpr
@@ -0,0 +1,542 @@
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ multi_clip ;
+
+{DEFINE AGG_GRAY8 }
+{$DEFINE AGG_BGR24 }
+{DEFINE AGG_RGB24 }
+{DEFINE AGG_BGRA32 }
+{DEFINE AGG_RGBA32 }
+{DEFINE AGG_ARGB32 }
+{DEFINE AGG_ABGR32 }
+{DEFINE AGG_RGB565 }
+{DEFINE AGG_RGB555 }
+
+uses
+ Math ,
+
+ agg_basics ,
+ agg_array ,
+ agg_platform_support ,
+
+ agg_ctrl ,
+ agg_slider_ctrl ,
+
+ agg_rasterizer_scanline_aa ,
+ agg_rasterizer_outline_aa ,
+ agg_scanline ,
+ agg_scanline_u ,
+
+ agg_rendering_buffer ,
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_renderer_outline_aa ,
+ agg_renderer_primitives ,
+ agg_renderer_markers ,
+ agg_renderer_mclip ,
+ agg_render_scanlines ,
+
+ agg_path_storage ,
+ agg_bounding_rect ,
+ agg_trans_affine ,
+ agg_conv_transform ,
+ agg_ellipse ,
+ agg_span_gradient ,
+ agg_span_allocator ,
+ agg_span_interpolator_linear ,
+ parse_lion_
+
+{$I pixel_formats.inc }
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+var
+ g_rasterizer : rasterizer_scanline_aa;
+ g_scanline : scanline_u8;
+
+ g_path : path_storage;
+ g_colors : array[0..99 ] of aggclr;
+ g_path_idx : array[0..99 ] of unsigned;
+
+ g_npaths : unsigned;
+
+ g_x1 ,g_y1 ,g_x2 ,g_y2 ,
+ g_base_dx ,g_base_dy ,
+ g_angle ,g_scale ,
+ g_skew_x ,g_skew_y : double;
+
+ g_nclick : int;
+
+type
+ gradient_linear_color = object(pod_auto_array )
+ m_c1 ,m_c2 ,c : aggclr;
+
+ constructor Construct(c1 ,c2 : aggclr_ptr );
+
+ function size : unsigned; virtual;
+ function array_operator(i : unsigned ) : pointer; virtual;
+
+ procedure colors(c1 ,c2 : aggclr_ptr );
+
+ end;
+
+ the_application = object(platform_support )
+ m_num_cb : slider_ctrl;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure on_draw; virtual;
+
+ procedure transform(width_ ,height_ ,x ,y : double );
+
+ procedure on_mouse_move (x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ CONSTRUCT }
+constructor gradient_linear_color.Construct;
+begin
+ m_c1:=c1^;
+ m_c2:=c2^;
+
+end;
+
+{ SIZE }
+function gradient_linear_color.size;
+begin
+ result:=256;
+
+end;
+
+{ ARRAY_OPERATOR }
+function gradient_linear_color.array_operator;
+begin
+ c.v:=int8u((((m_c2.v - m_c1.v ) * i ) + (m_c1.v shl 8 ) ) shr 8 );
+ c.r:=int8u((((m_c2.r - m_c1.r ) * i ) + (m_c1.r shl 8 ) ) shr 8 );
+ c.g:=int8u((((m_c2.g - m_c1.g ) * i ) + (m_c1.g shl 8 ) ) shr 8 );
+ c.b:=int8u((((m_c2.b - m_c1.b ) * i ) + (m_c1.b shl 8 ) ) shr 8 );
+ c.a:=int8u((((m_c2.a - m_c1.a ) * i ) + (m_c1.a shl 8 ) ) shr 8 );
+
+ result:=@c;
+
+end;
+
+{ COLORS }
+procedure gradient_linear_color.colors;
+begin
+ m_c1:=c1^;
+ m_c2:=c2^;
+
+end;
+
+{ _PARSE_LION_ }
+procedure _parse_lion_;
+begin
+ g_npaths:=parse_lion(@g_path ,@g_colors ,@g_path_idx );
+
+ bounding_rect(@g_path ,@g_path_idx ,0 ,g_npaths ,@g_x1 ,@g_y1 ,@g_x2 ,@g_y2 );
+
+ g_base_dx:=(g_x2 - g_x1 ) / 2.0;
+ g_base_dy:=(g_y2 - g_y1 ) / 2.0;
+
+end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_num_cb.Construct(5 ,5 ,150 ,12 ,not flip_y_ );
+
+ _parse_lion_;
+
+ add_ctrl(@m_num_cb );
+
+ m_num_cb.range_ (2 ,10 );
+ //m_num_cb.num_steps_(8 );
+ m_num_cb.label_ ('N=%.2f' );
+ m_num_cb.no_transform;
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_num_cb.Destruct;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ i : unsigned;
+
+ width_ ,height_ ,x ,y ,x1 ,y1 ,x2 ,y2 : int;
+
+ pf : pixel_formats;
+ r : renderer_mclip;
+ rs : renderer_scanline_aa_solid;
+
+ rgba ,
+ rgbb : aggclr;
+
+ mtx : trans_affine;
+ tat : trans_affine_translation;
+ tas : trans_affine_scaling;
+ tar : trans_affine_rotation;
+ taw : trans_affine_skewing;
+
+ trans : conv_transform;
+
+ m : renderer_markers;
+ w ,
+ n : double;
+
+ profile : line_profile_aa;
+
+ ren : renderer_outline_aa;
+ ras : rasterizer_outline_aa;
+ grm : trans_affine;
+ grf : gradient_circle;
+ grc : gradient_linear_color;
+ ell : ellipse;
+
+ sa : span_allocator;
+ sg : span_gradient;
+ rg : renderer_scanline_aa;
+
+ inter : span_interpolator_linear;
+
+begin
+ width_ :=rbuf_window._width;
+ height_:=rbuf_window._height;
+
+// Initialize structures
+ pixfmt(pf ,rbuf_window );
+
+ r.Construct (@pf );
+ rs.Construct(@r );
+
+// Transform lion
+ mtx.Construct;
+
+ tat.Construct(-g_base_dx ,-g_base_dy );
+ mtx.multiply (@tat );
+
+ tas.Construct(g_scale ,g_scale );
+ mtx.multiply (@tas );
+
+ tar.Construct(g_angle + pi );
+ mtx.multiply (@tar );
+
+ taw.Construct(g_skew_x / 1000.0 ,g_skew_y / 1000.0 );
+ mtx.multiply (@taw );
+
+ tat.Construct(_width / 2 ,_height / 2 );
+ mtx.multiply (@tat );
+
+ rgba.ConstrDbl(1 ,1 ,1 );
+ r.clear (@rgba );
+
+// Custom Clip Renderer Base
+ r.reset_clipping(false ); // Visibility: "false" means "no visible regions"
+
+ n:=m_num_cb._value;
+ x:=0;
+
+ while x < n do
+ begin
+ y:=0;
+
+ while y < n do
+ begin
+ x1:=trunc(width_ * x / n );
+ y1:=trunc(height_ * y / n );
+ x2:=trunc(width_ * (x + 1 ) / n );
+ y2:=trunc(height_ * (y + 1 ) / n );
+
+ r.add_clip_box(x1 + 5 ,y1 + 5 ,x2 - 5 ,y2 - 5 );
+
+ inc(y );
+
+ end;
+
+ inc(x );
+
+ end;{}
+
+// Render the lion
+ trans.Construct (@g_path ,@mtx );
+ render_all_paths(@g_rasterizer ,@g_scanline ,@rs ,@trans ,@g_colors ,@g_path_idx ,g_npaths );{}
+
+// The scanline rasterizer allows you to perform clipping to multiple
+// regions "manually", like in the following code, but the "embedded" method
+// shows much better performance.
+{ for i:=0 to g_npaths - 1 do
+ begin
+ g_rasterizer.reset;
+ g_rasterizer.add_path(@trans ,g_path_idx[i ] );
+
+ rs.color_(@g_colors[i ] );
+
+ n:=m_num_cb._value;
+ x:=0;
+
+ while x < n do
+ begin
+ y:=0;
+
+ while y < n do
+ begin
+ x1:=trunc(width_ * x / n );
+ y1:=trunc(height_ * y / n );
+ x2:=trunc(width_ * (x + 1 ) / n );
+ y2:=trunc(height_ * (y + 1 ) / n );
+
+ // r should be of type renderer_base
+ r.clip_box_(x1 + 5 ,y1 + 5 ,x2 - 5 ,y2 - 5 );
+
+ render_scanlines(@g_rasterizer ,@g_scanline ,@rs );
+
+ inc(y );
+
+ end;
+
+ inc(x );
+
+ end;
+
+ end;{}
+
+// Render random Bresenham lines and markers
+ m.Construct(@r );
+
+ for i:=0 to 49 do
+ begin
+ rgba.ConstrInt(
+ Random($7fff ) and $7F ,
+ Random($7fff ) and $7F ,
+ Random($7fff ) and $7F ,
+ (Random($7fff ) and $7F ) + $7F );
+
+ m.line_color_(@rgba );
+
+ rgba.ConstrInt(
+ Random($7fff ) and $7F ,
+ Random($7fff ) and $7F ,
+ Random($7fff ) and $7F ,
+ (Random($7fff ) and $7F ) + $7F );
+
+ m.fill_color_(@rgba );
+
+ m.line(
+ m.coord(Random($7fff ) mod width_ ) ,m.coord(Random($7fff ) mod height_ ) ,
+ m.coord(Random($7fff ) mod width_ ) ,m.coord(Random($7fff ) mod height_ ) );
+
+ m.marker(
+ Random($7fff ) mod width_ ,Random($7fff ) mod height_ ,Random($7fff ) mod 10 + 5 ,
+ marker_e(Random($7fff ) mod int(end_of_markers ) ) );
+
+ end;
+
+// Render random anti-aliased lines
+ w:=5.0;
+
+ profile.Construct;
+ profile.width_(w );
+
+ ren.Construct (@r ,@profile );
+ ras.Construct (@ren );
+ ras.round_cap_(true );
+
+ for i:=0 to 49 do
+ begin
+ rgba.ConstrInt(
+ Random($7fff ) and $7F ,
+ Random($7fff ) and $7F ,
+ Random($7fff ) and $7F ,
+ (Random($7fff ) and $7F ) + $7F );
+
+ ren.color_(@rgba );
+
+ ras.move_to_d(Random($7fff ) mod width_ ,Random($7fff ) mod height_ );
+ ras.line_to_d(Random($7fff ) mod width_ ,Random($7fff ) mod height_ );
+ ras.render (false );
+
+ end;
+
+// Render random circles with gradient
+ grm.Construct;
+ grf.Construct;
+ rgba.ConstrInt(0 ,0 ,0 );
+ rgbb.ConstrInt(0 ,0 ,0 );
+ grc.Construct (@rgba ,@rgbb );
+ ell.Construct;
+ sa.Construct;
+ inter.Construct(@grm );
+
+ sg.Construct(@sa ,@inter ,@grf ,@grc ,0 ,10 );
+ rg.Construct(@r ,@sg );
+
+ for i:=0 to 49 do
+ begin
+ x:=Random($7fff ) mod width_;
+ y:=Random($7fff ) mod height_;
+ w:=Random($7fff ) mod 10 + 5;
+
+ grm.reset;
+
+ tas.Construct(w / 10.0 );
+ grm.multiply (@tas );
+
+ tat.Construct(x ,y );
+ grm.multiply (@tat );
+
+ grm.invert;
+
+ rgba.ConstrInt(255 ,255 ,255 ,0 );
+ rgbb.ConstrInt(
+ Random($7fff ) and $7F ,
+ Random($7fff ) and $7F ,
+ Random($7fff ) and $7F ,255 );
+
+ grc.colors(@rgba ,@rgbb );
+ sg.color_function_(@grc );
+
+ ell.init(x ,y ,w ,w ,32 );
+
+ g_rasterizer.add_path(@ell );
+ render_scanlines (@g_rasterizer ,@g_scanline ,@rg );
+
+ end;
+
+// Render the controls
+ r.reset_clipping(true ); // "true" means "all rendering buffer is visible".
+
+ render_ctrl(@g_rasterizer ,@g_scanline ,@rs ,@m_num_cb );
+
+// Free AGG resources
+ profile.Destruct;
+ ras.Destruct;
+ sa.Destruct;
+ r.Destruct;
+
+end;
+
+{ TRANSFORM }
+procedure the_application.transform;
+begin
+ x:=x - width_ / 2;
+ y:=y - height_ / 2;
+
+ g_angle:=ArcTan2(y ,x );
+ g_scale:=Sqrt(y * y + x * x ) / 100.0;
+
+end;
+
+{ ON_MOUSE_MOVE }
+procedure the_application.on_mouse_move;
+begin
+ on_mouse_button_down(x ,y ,flags );
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure the_application.on_mouse_button_down;
+var
+ width_ ,height_ : int;
+
+begin
+ if flags and mouse_left <> 0 then
+ begin
+ width_ :=rbuf_window._width;
+ height_:=rbuf_window._height;
+
+ transform(width_ ,height_ ,x ,y );
+
+ force_redraw;
+
+ end;
+
+ if flags and mouse_right <> 0 then
+ begin
+ g_skew_x:=x;
+ g_skew_y:=y;
+
+ force_redraw;
+
+ end;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ 'A testing example that demonstrates clipping to multiple rectangular regions. '#13 +
+ 'It''s a low-level (pixel) clipping that can be useful to draw images clipped '#13 +
+ 'to a complex region with orthogonal boundaries. It can be useful in some window '#13 +
+ 'interfaces that use a custom mechanism to draw window content. The example '#13 +
+ 'uses all possible rendering mechanisms.'#13#13 +
+ 'How to play with:'#13#13 +
+ 'Use the left mouse button to rotate and resize the lion.'#13 +
+ 'Use the right mouse button to skew the lion.' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+VAR
+ app : the_application;
+
+BEGIN
+// Rendering
+ g_rasterizer.Construct;
+ g_scanline.Construct;
+ g_path.Construct;
+
+ g_npaths:=0;
+
+ g_x1:=0;
+ g_y1:=0;
+ g_x2:=0;
+ g_y2:=0;
+
+ g_base_dx:=0;
+ g_base_dy:=0;
+
+ g_angle:=0;
+ g_scale:=1.0;
+
+ g_skew_x:=0;
+ g_skew_y:=0;
+ g_nclick:=0;
+
+// App
+ app.Construct(pix_format ,flip_y );
+ app.caption_ ('AGG Example. Clipping to multiple rectangle regions (F1-Help)' );
+
+ if app.init(512 ,400 ,window_resize ) then
+ app.run;
+
+ app.Destruct;
+
+// Free
+ g_rasterizer.Destruct;
+ g_scanline.Destruct;
+ g_path.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/parse_lion_.pas b/src/corelib/render/software/agg-demos/parse_lion_.pas
new file mode 100644
index 00000000..1af63d23
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/parse_lion_.pas
@@ -0,0 +1,605 @@
+unit
+ parse_lion_ ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ Math ,
+ agg_basics ,
+ agg_color ,
+ agg_path_storage ;
+
+{ GLOBAL PROCEDURES }
+ function parse_lion(path : path_storage_ptr; colors : aggclr_ptr; path_idx : unsigned_ptr ) : unsigned;
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+const
+ g_lion : PChar =
+ 'f2cc99'#13 +
+ 'M 69,18 L 82,8 L 99,3 L 118,5 L 135,12 L 149,21 L 156,13 L 165,9 L 177,13 ' +
+ 'L 183,28 L 180,50 L 164,91 L 155,107 L 154,114 L 151,121 L 141,127 L 139,136 ' +
+ 'L 155,206 L 157,251 L 126,342 L 133,357 L 128,376 L 83,376 L 75,368 L 67,350 ' +
+ 'L 61,350 L 53,369 L 4,369 L 2,361 L 5,354 L 12,342 L 16,321 L 4,257 L 4,244 ' +
+ 'L 7,218 L 9,179 L 26,127 L 43,93 L 32,77 L 30,70 L 24,67 L 16,49 L 17,35 L 18,23 ' +
+ 'L 30,12 L 40,7 L 53,7 L 62,12 L 69,18 L 69,18 L 69,18'#13 +
+ 'e5b27f'#13 +
+ 'M 142,79 L 136,74 L 138,82 L 133,78 L 133,84 L 127,78 L 128,85 L 124,80 L 125,87 ' +
+ 'L 119,82 L 119,90 L 125,99 L 125,96 L 128,100 L 128,94 L 131,98 L 132,93 L 135,97 ' +
+ 'L 136,93 L 138,97 L 139,94 L 141,98 L 143,94 L 144,85 L 142,79 L 142,79 L 142,79'#13 +
+ 'eb8080'#13 +
+ 'M 127,101 L 132,100 L 137,99 L 144,101 L 143,105 L 135,110 L 127,101 L 127,101 ' +
+ 'L 127,101'#13 +
+ 'f2cc99'#13 +
+ 'M 178,229 L 157,248 L 139,296 L 126,349 L 137,356 L 158,357 L 183,342 L 212,332 ' +
+ 'L 235,288 L 235,261 L 228,252 L 212,250 L 188,251 L 178,229 L 178,229 L 178,229'#13 +
+ '9c826b'#13 +
+ 'M 56,229 L 48,241 L 48,250 L 57,281 L 63,325 L 71,338 L 81,315 L 76,321 L 79,311 ' +
+ 'L 83,301 L 75,308 L 80,298 L 73,303 L 76,296 L 71,298 L 74,292 L 69,293 L 74,284 ' +
+ 'L 78,278 L 71,278 L 74,274 L 68,273 L 70,268 L 66,267 L 68,261 L 60,266 L 62,259 ' +
+ 'L 65,253 L 57,258 L 59,251 L 55,254 L 55,248 L 60,237 L 54,240 L 58,234 L 54,236 ' +
+ 'L 56,229 L 56,229 L 56,229'#13 +
+ 'M 74,363 L 79,368 L 81,368 L 85,362 L 89,363 L 92,370 L 96,373 L 101,372 L 108,361 ' +
+ 'L 110,371 L 113,373 L 116,371 L 120,358 L 122,363 L 123,371 L 126,371 L 129,367 ' +
+ 'L 132,357 L 135,361 L 130,376 L 127,377 L 94,378 L 84,376 L 76,371 L 74,363 ' +
+ 'L 74,363 L 74,363'#13 +
+ 'M 212,250 L 219,251 L 228,258 L 236,270 L 235,287 L 225,304 L 205,332 L 177,343 ' +
+ 'L 171,352 L 158,357 L 166,352 L 168,346 L 168,339 L 165,333 L 155,327 L 155,323 ' +
+ 'L 161,320 L 165,316 L 169,316 L 167,312 L 171,313 L 168,308 L 173,309 L 170,306 ' +
+ 'L 177,306 L 175,308 L 177,311 L 174,311 L 176,316 L 171,315 L 174,319 L 168,320 ' +
+ 'L 168,323 L 175,327 L 179,332 L 183,326 L 184,332 L 189,323 L 190,328 L 194,320 ' +
+ 'L 194,325 L 199,316 L 201,320 L 204,313 L 206,316 L 208,310 L 211,305 L 219,298 ' +
+ 'L 226,288 L 229,279 L 228,266 L 224,259 L 217,253 L 212,250 L 212,250 L 212,250'#13 +
+ 'M 151,205 L 151,238 L 149,252 L 141,268 L 128,282 L 121,301 L 130,300 L 126,313 ' +
+ 'L 118,324 L 116,337 L 120,346 L 133,352 L 133,340 L 137,333 L 145,329 L 156,327 ' +
+ 'L 153,319 L 153,291 L 157,271 L 170,259 L 178,277 L 193,250 L 174,216 L 151,205 ' +
+ 'L 151,205 L 151,205'#13 +
+ 'M 78,127 L 90,142 L 95,155 L 108,164 L 125,167 L 139,175 L 150,206 L 152,191 ' +
+ 'L 141,140 L 121,148 L 100,136 L 78,127 L 78,127 L 78,127'#13 +
+ 'M 21,58 L 35,63 L 38,68 L 32,69 L 42,74 L 40,79 L 47,80 L 54,83 L 45,94 L 34,81 ' +
+ 'L 32,73 L 24,66 L 21,58 L 21,58 L 21,58'#13 +
+ 'M 71,34 L 67,34 L 66,27 L 59,24 L 54,17 L 48,17 L 39,22 L 30,26 L 28,31 L 31,39 ' +
+ 'L 38,46 L 29,45 L 36,54 L 41,61 L 41,70 L 50,69 L 54,71 L 55,58 L 67,52 L 76,43 ' +
+ 'L 76,39 L 68,44 L 71,34 L 71,34 L 71,34'#13 +
+ 'M 139,74 L 141,83 L 143,89 L 144,104 L 148,104 L 155,106 L 154,86 L 157,77 ' +
+ 'L 155,72 L 150,77 L 144,77 L 139,74 L 139,74 L 139,74'#13 +
+ 'M 105,44 L 102,53 L 108,58 L 111,62 L 112,55 L 105,44 L 105,44 L 105,44'#13 +
+ 'M 141,48 L 141,54 L 144,58 L 139,62 L 137,66 L 136,59 L 137,52 L 141,48 L 141,48 ' +
+ 'L 141,48'#13 +
+ 'M 98,135 L 104,130 L 105,134 L 108,132 L 108,135 L 112,134 L 113,137 L 116,136 ' +
+ 'L 116,139 L 119,139 L 124,141 L 128,140 L 133,138 L 140,133 L 139,140 L 126,146 ' +
+ 'L 104,144 L 98,135 L 98,135 L 98,135'#13 +
+ 'M 97,116 L 103,119 L 103,116 L 111,118 L 116,117 L 122,114 L 127,107 L 135,111 ' +
+ 'L 142,107 L 141,114 L 145,118 L 149,121 L 145,125 L 140,124 L 127,121 L 113,125 ' +
+ 'L 100,124 L 97,116 L 97,116 L 97,116'#13 +
+ 'M 147,33 L 152,35 L 157,34 L 153,31 L 160,31 L 156,28 L 161,28 L 159,24 L 163,25 ' +
+ 'L 163,21 L 165,22 L 170,23 L 167,17 L 172,21 L 174,18 L 175,23 L 176,22 L 177,28 ' +
+ 'L 177,33 L 174,37 L 176,39 L 174,44 L 171,49 L 168,53 L 164,57 L 159,68 L 156,70 ' +
+ 'L 154,60 L 150,51 L 146,43 L 144,35 L 147,33 L 147,33 L 147,33'#13 +
+ 'M 85,72 L 89,74 L 93,75 L 100,76 L 105,75 L 102,79 L 94,79 L 88,76 L 85,72 L 85,72 L 85,72'#13 +
+ 'M 86,214 L 79,221 L 76,232 L 82,225 L 78,239 L 82,234 L 78,245 L 81,243 L 79,255 ' +
+ 'L 84,250 L 84,267 L 87,254 L 90,271 L 90,257 L 95,271 L 93,256 L 95,249 L 92,252 ' +
+ 'L 93,243 L 89,253 L 89,241 L 86,250 L 87,236 L 83,245 L 87,231 L 82,231 L 90,219 ' +
+ 'L 84,221 L 86,214 L 86,214 L 86,214'#13 +
+ 'ffcc7f'#13 +
+ 'M 93,68 L 96,72 L 100,73 L 106,72 L 108,66 L 105,63 L 100,62 L 93,68 L 93,68 L 93,68'#13 +
+ 'M 144,64 L 142,68 L 142,73 L 146,74 L 150,73 L 154,64 L 149,62 L 144,64 L 144,64 L 144,64'#13 +
+ '9c826b'#13 +
+ 'M 57,91 L 42,111 L 52,105 L 41,117 L 53,112 L 46,120 L 53,116 L 50,124 L 57,119 ' +
+ 'L 55,127 L 61,122 L 60,130 L 67,126 L 66,134 L 71,129 L 72,136 L 77,130 L 76,137 ' +
+ 'L 80,133 L 82,138 L 86,135 L 96,135 L 94,129 L 86,124 L 83,117 L 77,123 L 79,117 ' +
+ 'L 73,120 L 75,112 L 68,116 L 71,111 L 65,114 L 69,107 L 63,110 L 68,102 L 61,107 ' +
+ 'L 66,98 L 61,103 L 63,97 L 57,99 L 57,91 L 57,91 L 57,91'#13 +
+ 'M 83,79 L 76,79 L 67,82 L 75,83 L 65,88 L 76,87 L 65,92 L 76,91 L 68,96 L 77,95 ' +
+ 'L 70,99 L 80,98 L 72,104 L 80,102 L 76,108 L 85,103 L 92,101 L 87,98 L 93,96 ' +
+ 'L 86,94 L 91,93 L 85,91 L 93,89 L 99,89 L 105,93 L 107,85 L 102,82 L 92,80 L 83,79 ' +
+ 'L 83,79 L 83,79'#13 +
+ 'M 109,77 L 111,83 L 109,89 L 113,94 L 117,90 L 117,81 L 114,78 L 109,77 L 109,77 L 109,77'#13 +
+ 'M 122,128 L 127,126 L 134,127 L 136,129 L 134,130 L 130,128 L 124,129 L 122,128 L 122,128 L 122,128'#13 +
+ 'M 78,27 L 82,32 L 80,33 L 82,36 L 78,37 L 82,40 L 78,42 L 81,46 L 76,47 L 78,49 ' +
+ 'L 74,50 L 82,52 L 87,50 L 83,48 L 91,46 L 86,45 L 91,42 L 88,40 L 92,37 L 86,34 ' +
+ 'L 90,31 L 86,29 L 89,26 L 78,27 L 78,27 L 78,27'#13 +
+ 'M 82,17 L 92,20 L 79,21 L 90,25 L 81,25 L 94,28 L 93,26 L 101,30 L 101,26 L 107,33 ' +
+ 'L 108,28 L 111,40 L 113,34 L 115,45 L 117,39 L 119,54 L 121,46 L 124,58 L 126,47 ' +
+ 'L 129,59 L 130,49 L 134,58 L 133,44 L 137,48 L 133,37 L 137,40 L 133,32 L 126,20 ' +
+ 'L 135,26 L 132,19 L 138,23 L 135,17 L 142,18 L 132,11 L 116,6 L 94,6 L 78,11 ' +
+ 'L 92,12 L 80,14 L 90,16 L 82,17 L 82,17 L 82,17'#13 +
+ 'M 142,234 L 132,227 L 124,223 L 115,220 L 110,225 L 118,224 L 127,229 L 135,236 ' +
+ 'L 122,234 L 115,237 L 113,242 L 121,238 L 139,243 L 121,245 L 111,254 L 95,254 ' +
+ 'L 102,244 L 104,235 L 110,229 L 100,231 L 104,224 L 113,216 L 122,215 L 132,217 ' +
+ 'L 141,224 L 145,230 L 149,240 L 142,234 L 142,234 L 142,234'#13 +
+ 'M 115,252 L 125,248 L 137,249 L 143,258 L 134,255 L 125,254 L 115,252 L 115,252 L 115,252'#13 +
+ 'M 114,212 L 130,213 L 140,219 L 147,225 L 144,214 L 137,209 L 128,207 L 114,212 L 114,212 L 114,212'#13 +
+ 'M 102,263 L 108,258 L 117,257 L 131,258 L 116,260 L 109,265 L 102,263 L 102,263 L 102,263'#13 +
+ 'M 51,241 L 35,224 L 40,238 L 23,224 L 31,242 L 19,239 L 28,247 L 17,246 L 25,250 ' +
+ 'L 37,254 L 39,263 L 44,271 L 47,294 L 48,317 L 51,328 L 60,351 L 60,323 L 53,262 ' +
+ 'L 47,246 L 51,241 L 51,241 L 51,241'#13 +
+ 'M 2,364 L 9,367 L 14,366 L 18,355 L 20,364 L 26,366 L 31,357 L 35,364 L 39,364 ' +
+ 'L 42,357 L 47,363 L 53,360 L 59,357 L 54,369 L 7,373 L 2,364 L 2,364 L 2,364'#13 +
+ 'M 7,349 L 19,345 L 25,339 L 18,341 L 23,333 L 28,326 L 23,326 L 27,320 L 23,316 ' +
+ 'L 25,311 L 20,298 L 15,277 L 12,264 L 9,249 L 10,223 L 3,248 L 5,261 L 15,307 ' +
+ 'L 17,326 L 11,343 L 7,349 L 7,349 L 7,349'#13 +
+ 'M 11,226 L 15,231 L 25,236 L 18,227 L 11,226 L 11,226 L 11,226'#13 +
+ 'M 13,214 L 19,217 L 32,227 L 23,214 L 16,208 L 15,190 L 24,148 L 31,121 L 24,137 ' +
+ 'L 14,170 L 8,189 L 13,214 L 13,214 L 13,214'#13 +
+ 'M 202,254 L 195,258 L 199,260 L 193,263 L 197,263 L 190,268 L 196,268 L 191,273 ' +
+ 'L 188,282 L 200,272 L 194,272 L 201,266 L 197,265 L 204,262 L 200,258 L 204,256 L 202,254 L 202,254 L 202,254'#13 +
+ '845433'#13 +
+ 'M 151,213 L 165,212 L 179,225 L 189,246 L 187,262 L 179,275 L 176,263 L 177,247 ' +
+ 'L 171,233 L 163,230 L 165,251 L 157,264 L 146,298 L 145,321 L 133,326 L 143,285 ' +
+ 'L 154,260 L 153,240 L 151,213 L 151,213 L 151,213'#13 +
+ 'M 91,132 L 95,145 L 97,154 L 104,148 L 107,155 L 109,150 L 111,158 L 115,152 ' +
+ 'L 118,159 L 120,153 L 125,161 L 126,155 L 133,164 L 132,154 L 137,163 L 137,152 ' +
+ 'L 142,163 L 147,186 L 152,192 L 148,167 L 141,143 L 124,145 L 105,143 L 91,132 ' +
+ 'L 91,132 L 91,132'#13 +
+ '9c826b'#13 +
+ 'M 31,57 L 23,52 L 26,51 L 20,44 L 23,42 L 21,36 L 22,29 L 25,23 L 24,32 L 30,43 L 26,41 L 30,50 L 26,48 L 31,57 L 31,57 L 31,57'#13 +
+ 'M 147,21 L 149,28 L 155,21 L 161,16 L 167,14 L 175,15 L 173,11 L 161,9 L 147,21 L 147,21 L 147,21'#13 +
+ 'M 181,39 L 175,51 L 169,57 L 171,65 L 165,68 L 165,75 L 160,76 L 162,91 L 171,71 L 180,51 L 181,39 L 181,39 L 181,39'#13 +
+ 'M 132,346 L 139,348 L 141,346 L 142,341 L 147,342 L 143,355 L 133,350 L 132,346 L 132,346 L 132,346'#13 +
+ 'M 146,355 L 151,352 L 155,348 L 157,343 L 160,349 L 151,356 L 147,357 L 146,355 L 146,355 L 146,355'#13 +
+ 'M 99,266 L 100,281 L 94,305 L 86,322 L 78,332 L 72,346 L 73,331 L 91,291 L 99,266 L 99,266 L 99,266'#13 +
+ 'M 20,347 L 32,342 L 45,340 L 54,345 L 45,350 L 42,353 L 38,350 L 31,353 L 29,356 L 23,350 L 19,353 L 15,349 L 20,347 L 20,347 L 20,347'#13 +
+ 'M 78,344 L 86,344 L 92,349 L 88,358 L 84,352 L 78,344 L 78,344 L 78,344'#13 +
+ 'M 93,347 L 104,344 L 117,345 L 124,354 L 121,357 L 116,351 L 112,351 L 108,355 L 102,351 L 93,347 L 93,347 L 93,347'#13 +
+ '000000'#13 +
+ 'M 105,12 L 111,18 L 113,24 L 113,29 L 119,34 L 116,23 L 112,16 L 105,12 L 105,12 L 105,12'#13 +
+ 'M 122,27 L 125,34 L 127,43 L 128,34 L 125,29 L 122,27 L 122,27 L 122,27'#13 +
+ 'M 115,13 L 122,19 L 122,15 L 113,10 L 115,13 L 115,13 L 115,13'#13 +
+ 'ffe5b2'#13 +
+ 'M 116,172 L 107,182 L 98,193 L 98,183 L 90,199 L 89,189 L 84,207 L 88,206 L 87,215 ' +
+ 'L 95,206 L 93,219 L 91,230 L 98,216 L 97,226 L 104,214 L 112,209 L 104,208 ' +
+ 'L 113,202 L 126,200 L 139,207 L 132,198 L 142,203 L 134,192 L 142,195 L 134,187 ' +
+ 'L 140,185 L 130,181 L 136,177 L 126,177 L 125,171 L 116,180 L 116,172 L 116,172 ' +
+ 'L 116,172'#13 +
+ 'M 74,220 L 67,230 L 67,221 L 59,235 L 63,233 L 60,248 L 70,232 L 65,249 L 71,243 ' +
+ 'L 67,256 L 73,250 L 69,262 L 73,259 L 71,267 L 76,262 L 72,271 L 78,270 L 76,275 ' +
+ 'L 82,274 L 78,290 L 86,279 L 86,289 L 92,274 L 88,275 L 87,264 L 82,270 L 82,258 ' +
+ 'L 77,257 L 78,247 L 73,246 L 77,233 L 72,236 L 74,220 L 74,220 L 74,220'#13 +
+ 'M 133,230 L 147,242 L 148,250 L 145,254 L 138,247 L 129,246 L 142,245 L 138,241 L 128,237 L 137,238 L 133,230 L 133,230 L 133,230'#13 +
+ 'M 133,261 L 125,261 L 116,263 L 111,267 L 125,265 L 133,261 L 133,261 L 133,261'#13 +
+ 'M 121,271 L 109,273 L 103,279 L 99,305 L 92,316 L 85,327 L 83,335 L 89,340 ' +
+ 'L 97,341 L 94,336 L 101,336 L 96,331 L 103,330 L 97,327 L 108,325 L 99,322 ' +
+ 'L 109,321 L 100,318 L 110,317 L 105,314 L 110,312 L 107,310 L 113,308 L 105,306 ' +
+ 'L 114,303 L 105,301 L 115,298 L 107,295 L 115,294 L 108,293 L 117,291 L 109,289 ' +
+ 'L 117,286 L 109,286 L 118,283 L 112,281 L 118,279 L 114,278 L 119,276 L 115,274 ' +
+ 'L 121,271 L 121,271 L 121,271'#13 +
+ 'M 79,364 L 74,359 L 74,353 L 76,347 L 80,351 L 83,356 L 82,360 L 79,364 L 79,364 L 79,364'#13 +
+ 'M 91,363 L 93,356 L 97,353 L 103,355 L 105,360 L 103,366 L 99,371 L 94,368 L 91,363 L 91,363 L 91,363'#13 +
+ 'M 110,355 L 114,353 L 118,357 L 117,363 L 113,369 L 111,362 L 110,355 L 110,355 L 110,355'#13 +
+ 'M 126,354 L 123,358 L 124,367 L 126,369 L 129,361 L 129,357 L 126,354 L 126,354 L 126,354'#13 +
+ 'M 30,154 L 24,166 L 20,182 L 23,194 L 29,208 L 37,218 L 41,210 L 41,223 L 46,214 ' +
+ 'L 46,227 L 52,216 L 52,227 L 61,216 L 59,225 L 68,213 L 73,219 L 70,207 L 77,212 ' +
+ 'L 69,200 L 77,202 L 70,194 L 78,197 L 68,187 L 76,182 L 64,182 L 58,175 L 58,185 ' +
+ 'L 53,177 L 50,186 L 46,171 L 44,182 L 39,167 L 36,172 L 36,162 L 30,166 L 30,154 L 30,154 L 30,154'#13 +
+ 'M 44,130 L 41,137 L 45,136 L 43,150 L 48,142 L 48,157 L 53,150 L 52,164 L 60,156 ' +
+ 'L 61,169 L 64,165 L 66,175 L 70,167 L 74,176 L 77,168 L 80,183 L 85,172 L 90,182 ' +
+ 'L 93,174 L 98,181 L 99,173 L 104,175 L 105,169 L 114,168 L 102,163 L 95,157 ' +
+ 'L 94,166 L 90,154 L 87,162 L 82,149 L 75,159 L 72,148 L 68,155 L 67,143 L 62,148 ' +
+ 'L 62,138 L 58,145 L 56,133 L 52,142 L 52,128 L 49,134 L 47,125 L 44,130 L 44,130 L 44,130'#13 +
+ 'M 13,216 L 19,219 L 36,231 L 22,223 L 16,222 L 22,227 L 12,224 L 13,220 L 16,220 L 13,216 L 13,216 L 13,216'#13 +
+ 'M 10,231 L 14,236 L 25,239 L 27,237 L 19,234 L 10,231 L 10,231 L 10,231'#13 +
+ 'M 9,245 L 14,242 L 25,245 L 13,245 L 9,245 L 9,245 L 9,245'#13 +
+ 'M 33,255 L 26,253 L 18,254 L 25,256 L 18,258 L 27,260 L 18,263 L 27,265 L 19,267 ' +
+ 'L 29,270 L 21,272 L 29,276 L 21,278 L 30,281 L 22,283 L 31,287 L 24,288 L 32,292 ' +
+ 'L 23,293 L 34,298 L 26,299 L 37,303 L 32,305 L 39,309 L 33,309 L 39,314 L 34,314 ' +
+ 'L 40,318 L 34,317 L 40,321 L 34,321 L 41,326 L 33,326 L 40,330 L 33,332 L 39,333 ' +
+ 'L 33,337 L 42,337 L 54,341 L 49,337 L 52,335 L 47,330 L 50,330 L 45,325 L 49,325 ' +
+ 'L 45,321 L 48,321 L 45,316 L 46,306 L 45,286 L 43,274 L 36,261 L 33,255 L 33,255 ' +
+ 'L 33,255'#13 +
+ 'M 7,358 L 9,351 L 14,351 L 17,359 L 11,364 L 7,358 L 7,358 L 7,358'#13 +
+ 'M 44,354 L 49,351 L 52,355 L 49,361 L 44,354 L 44,354 L 44,354'#13 +
+ 'M 32,357 L 37,353 L 40,358 L 36,361 L 32,357 L 32,357 L 32,357'#13 +
+ 'M 139,334 L 145,330 L 154,330 L 158,334 L 154,341 L 152,348 L 145,350 L 149,340 L 147,336 L 141,339 L 139,345 L 136,342 L 136,339 L 139,334 L 139,334 L 139,334'#13 +
+ 'M 208,259 L 215,259 L 212,255 L 220,259 L 224,263 L 225,274 L 224,283 L 220,292 ' +
+ 'L 208,300 L 206,308 L 203,304 L 199,315 L 197,309 L 195,318 L 193,313 L 190,322 ' +
+ 'L 190,316 L 185,325 L 182,318 L 180,325 L 172,321 L 178,320 L 176,313 L 186,312 ' +
+ 'L 180,307 L 188,307 L 184,303 L 191,302 L 186,299 L 195,294 L 187,290 L 197,288 ' +
+ 'L 192,286 L 201,283 L 194,280 L 203,277 L 198,275 L 207,271 L 200,269 L 209,265 ' +
+ 'L 204,265 L 212,262 L 208,259 L 208,259 L 208,259'#13 +
+ 'M 106,126 L 106,131 L 109,132 L 111,134 L 115,132 L 115,135 L 119,133 L 118,137 ' +
+ 'L 123,137 L 128,137 L 133,134 L 136,130 L 136,127 L 132,124 L 118,128 L 112,128 ' +
+ 'L 106,126 L 106,126 L 106,126'#13 +
+ 'M 107,114 L 101,110 L 98,102 L 105,97 L 111,98 L 119,102 L 121,108 L 118,112 L 113,115 L 107,114 L 107,114 L 107,114'#13 +
+ 'M 148,106 L 145,110 L 146,116 L 150,118 L 152,111 L 151,107 L 148,106 L 148,106 L 148,106'#13 +
+ 'M 80,55 L 70,52 L 75,58 L 63,57 L 72,61 L 57,61 L 67,66 L 57,67 L 62,69 L 54,71 ' +
+ 'L 61,73 L 54,77 L 63,78 L 53,85 L 60,84 L 56,90 L 69,84 L 63,82 L 75,76 L 70,75 ' +
+ 'L 77,72 L 72,71 L 78,69 L 72,66 L 81,67 L 78,64 L 82,63 L 80,60 L 86,62 L 80,55 ' +
+ 'L 80,55 L 80,55'#13 +
+ 'M 87,56 L 91,52 L 96,50 L 102,56 L 98,56 L 92,60 L 87,56 L 87,56 L 87,56'#13 +
+ 'M 85,68 L 89,73 L 98,76 L 106,74 L 96,73 L 91,70 L 85,68 L 85,68 L 85,68'#13 +
+ 'M 115,57 L 114,64 L 111,64 L 115,75 L 122,81 L 122,74 L 126,79 L 126,74 L 131,78 L 130,72 L 133,77 L 131,68 L 126,61 L 119,57 L 115,57 L 115,57 L 115,57'#13 +
+ 'M 145,48 L 143,53 L 147,59 L 151,59 L 150,55 L 145,48 L 145,48 L 145,48'#13 +
+ 'M 26,22 L 34,15 L 43,10 L 52,10 L 59,16 L 47,15 L 32,22 L 26,22 L 26,22 L 26,22'#13 +
+ 'M 160,19 L 152,26 L 149,34 L 154,33 L 152,30 L 157,30 L 155,26 L 158,27 L 157,23 L 161,23 L 160,19 L 160,19 L 160,19'#13 +
+ '000000'#13 +
+ 'M 98,117 L 105,122 L 109,122 L 105,117 L 113,120 L 121,120 L 130,112 L 128,108 ' +
+ 'L 123,103 L 123,99 L 128,101 L 132,106 L 135,109 L 142,105 L 142,101 L 145,101 ' +
+ 'L 145,91 L 148,101 L 145,105 L 136,112 L 135,116 L 143,124 L 148,120 L 150,122 ' +
+ 'L 142,128 L 133,122 L 121,125 L 112,126 L 103,125 L 100,129 L 96,124 L 98,117 ' +
+ 'L 98,117 L 98,117'#13 +
+ 'M 146,118 L 152,118 L 152,115 L 149,115 L 146,118 L 146,118 L 146,118'#13 +
+ 'M 148,112 L 154,111 L 154,109 L 149,109 L 148,112 L 148,112 L 148,112'#13 +
+ 'M 106,112 L 108,115 L 114,116 L 118,114 L 106,112 L 106,112 L 106,112'#13 +
+ 'M 108,108 L 111,110 L 116,110 L 119,108 L 108,108 L 108,108 L 108,108'#13 +
+ 'M 106,104 L 109,105 L 117,106 L 115,104 L 106,104 L 106,104 L 106,104'#13 +
+ 'M 50,25 L 41,26 L 34,33 L 39,43 L 49,58 L 36,51 L 47,68 L 55,69 L 54,59 L 61,57 ' +
+ 'L 74,46 L 60,52 L 67,42 L 57,48 L 61,40 L 54,45 L 60,36 L 59,29 L 48,38 L 52,30 ' +
+ 'L 47,32 L 50,25 L 50,25 L 50,25'#13 +
+ 'M 147,34 L 152,41 L 155,49 L 161,53 L 157,47 L 164,47 L 158,43 L 168,44 L 159,40 ' +
+ 'L 164,37 L 169,37 L 164,33 L 169,34 L 165,28 L 170,30 L 170,25 L 173,29 L 175,27 ' +
+ 'L 176,32 L 173,36 L 175,39 L 172,42 L 172,46 L 168,49 L 170,55 L 162,57 L 158,63 ' +
+ 'L 155,58 L 153,50 L 149,46 L 147,34 L 147,34 L 147,34'#13 +
+ 'M 155,71 L 159,80 L 157,93 L 157,102 L 155,108 L 150,101 L 149,93 L 154,101 L 152,91 L 151,83 L 155,79 L 155,71 L 155,71 L 155,71'#13 +
+ 'M 112,78 L 115,81 L 114,91 L 112,87 L 113,82 L 112,78 L 112,78 L 112,78'#13 +
+ 'M 78,28 L 64,17 L 58,11 L 47,9 L 36,10 L 28,16 L 21,26 L 18,41 L 20,51 L 23,61 ' +
+ 'L 33,65 L 28,68 L 37,74 L 36,81 L 43,87 L 48,90 L 43,100 L 40,98 L 39,90 L 31,80 ' +
+ 'L 30,72 L 22,71 L 17,61 L 14,46 L 16,28 L 23,17 L 33,9 L 45,6 L 54,6 L 65,12 ' +
+ 'L 78,28 L 78,28 L 78,28'#13 +
+ 'M 67,18 L 76,9 L 87,5 L 101,2 L 118,3 L 135,8 L 149,20 L 149,26 L 144,19 L 132,12 L 121,9 L 105,7 L 89,8 L 76,14 L 70,20 L 67,18 L 67,18 L 67,18'#13 +
+ 'M 56,98 L 48,106 L 56,103 L 47,112 L 56,110 L 52,115 L 57,113 L 52,121 L 62,115 ' +
+ 'L 58,123 L 65,119 L 63,125 L 69,121 L 68,127 L 74,125 L 74,129 L 79,128 L 83,132 ' +
+ 'L 94,135 L 93,129 L 85,127 L 81,122 L 76,126 L 75,121 L 71,124 L 71,117 L 66,121 ' +
+ 'L 66,117 L 62,117 L 64,112 L 60,113 L 60,110 L 57,111 L 61,105 L 57,107 L 60,101 ' +
+ 'L 55,102 L 56,98 L 56,98 L 56,98'#13 +
+ 'M 101,132 L 103,138 L 106,134 L 106,139 L 112,136 L 111,142 L 115,139 L 114,143 ' +
+ 'L 119,142 L 125,145 L 131,142 L 135,138 L 140,134 L 140,129 L 143,135 L 145,149 ' +
+ 'L 150,171 L 149,184 L 145,165 L 141,150 L 136,147 L 132,151 L 131,149 L 126,152 ' +
+ 'L 125,150 L 121,152 L 117,148 L 111,152 L 110,148 L 105,149 L 104,145 L 98,150 ' +
+ 'L 96,138 L 94,132 L 94,130 L 98,132 L 101,132 L 101,132 L 101,132'#13 +
+ 'M 41,94 L 32,110 L 23,132 L 12,163 L 6,190 L 7,217 L 5,236 L 3,247 L 9,230 ' +
+ 'L 12,211 L 12,185 L 18,160 L 26,134 L 35,110 L 43,99 L 41,94 L 41,94 L 41,94'#13 +
+ 'M 32,246 L 41,250 L 50,257 L 52,267 L 53,295 L 53,323 L 59,350 L 54,363 L 51,365 ' +
+ 'L 44,366 L 42,360 L 40,372 L 54,372 L 59,366 L 62,353 L 71,352 L 75,335 L 73,330 ' +
+ 'L 66,318 L 68,302 L 64,294 L 67,288 L 63,286 L 63,279 L 59,275 L 58,267 L 56,262 ' +
+ 'L 50,247 L 42,235 L 44,246 L 32,236 L 35,244 L 32,246 L 32,246 L 32,246'#13 +
+ 'M 134,324 L 146,320 L 159,322 L 173,327 L 179,337 L 179,349 L 172,355 L 158,357 ' +
+ 'L 170,350 L 174,343 L 170,333 L 163,328 L 152,326 L 134,329 L 134,324 L 134,324 ' +
+ 'L 134,324'#13 +
+ 'M 173,339 L 183,334 L 184,338 L 191,329 L 194,332 L 199,323 L 202,325 L 206,318 ' +
+ 'L 209,320 L 213,309 L 221,303 L 228,296 L 232,289 L 234,279 L 233,269 L 230,262 ' +
+ 'L 225,256 L 219,253 L 208,252 L 198,252 L 210,249 L 223,250 L 232,257 L 237,265 ' +
+ 'L 238,277 L 238,291 L 232,305 L 221,323 L 218,335 L 212,342 L 200,349 L 178,348 ' +
+ 'L 173,339 L 173,339 L 173,339'#13 +
+ 'M 165,296 L 158,301 L 156,310 L 156,323 L 162,324 L 159,318 L 162,308 L 162,304 ' +
+ 'L 165,296 L 165,296 L 165,296'#13 +
+ 'M 99,252 L 105,244 L 107,234 L 115,228 L 121,228 L 131,235 L 122,233 L 113,235 ' +
+ 'L 109,246 L 121,239 L 133,243 L 121,243 L 110,251 L 99,252 L 99,252 L 99,252'#13 +
+ 'M 117,252 L 124,247 L 134,249 L 136,253 L 126,252 L 117,252 L 117,252 L 117,252'#13 +
+ 'M 117,218 L 132,224 L 144,233 L 140,225 L 132,219 L 117,218 L 117,218 L 117,218'#13 +
+ 'M 122,212 L 134,214 L 143,221 L 141,213 L 132,210 L 122,212 L 122,212 L 122,212'#13 +
+ 'M 69,352 L 70,363 L 76,373 L 86,378 L 97,379 L 108,379 L 120,377 L 128,378 ' +
+ 'L 132,373 L 135,361 L 133,358 L 132,366 L 127,375 L 121,374 L 121,362 L 119,367 ' +
+ 'L 117,374 L 110,376 L 110,362 L 107,357 L 106,371 L 104,375 L 97,376 L 90,375 ' +
+ 'L 90,368 L 86,362 L 83,364 L 86,369 L 85,373 L 78,370 L 73,362 L 71,351 L 69,352 ' +
+ 'L 69,352 L 69,352'#13 +
+ 'M 100,360 L 96,363 L 99,369 L 102,364 L 100,360 L 100,360 L 100,360'#13 +
+ 'M 115,360 L 112,363 L 114,369 L 117,364 L 115,360 L 115,360 L 115,360'#13 +
+ 'M 127,362 L 125,364 L 126,369 L 128,365 L 127,362 L 127,362 L 127,362'#13 +
+ 'M 5,255 L 7,276 L 11,304 L 15,320 L 13,334 L 6,348 L 2,353 L 0,363 L 5,372 ' +
+ 'L 12,374 L 25,372 L 38,372 L 44,369 L 42,367 L 36,368 L 31,369 L 30,360 ' +
+ 'L 27,368 L 20,370 L 16,361 L 15,368 L 10,369 L 3,366 L 3,359 L 6,352 L 11,348 ' +
+ 'L 17,331 L 19,316 L 12,291 L 9,274 L 5,255 L 5,255 L 5,255'#13 +
+ 'M 10,358 L 7,362 L 10,366 L 11,362 L 10,358 L 10,358 L 10,358'#13 +
+ 'M 25,357 L 22,360 L 24,366 L 27,360 L 25,357 L 25,357 L 25,357'#13 +
+ 'M 37,357 L 34,361 L 36,365 L 38,361 L 37,357 L 37,357 L 37,357'#13 +
+ 'M 49,356 L 46,359 L 47,364 L 50,360 L 49,356 L 49,356 L 49,356'#13 +
+ 'M 130,101 L 132,102 L 135,101 L 139,102 L 143,103 L 142,101 L 137,100 L 133,100 L 130,101 L 130,101 L 130,101'#13 +
+ 'M 106,48 L 105,52 L 108,56 L 109,52 L 106,48 L 106,48 L 106,48'#13 +
+ 'M 139,52 L 139,56 L 140,60 L 142,58 L 141,56 L 139,52 L 139,52 L 139,52'#13 +
+ 'M 25,349 L 29,351 L 30,355 L 33,350 L 37,348 L 42,351 L 45,347 L 49,345 L 44,343 L 36,345 L 25,349 L 25,349 L 25,349'#13 +
+ 'M 98,347 L 105,351 L 107,354 L 109,349 L 115,349 L 120,353 L 118,349 L 113,346 L 104,346 L 98,347 L 98,347 L 98,347'#13 +
+ 'M 83,348 L 87,352 L 87,357 L 89,351 L 87,348 L 83,348 L 83,348 L 83,348'#13 +
+ 'M 155,107 L 163,107 L 170,107 L 186,108 L 175,109 L 155,109 L 155,107 L 155,107 L 155,107'#13 +
+ 'M 153,114 L 162,113 L 175,112 L 192,114 L 173,114 L 154,115 L 153,114 L 153,114 L 153,114'#13 +
+ 'M 152,118 L 164,120 L 180,123 L 197,129 L 169,123 L 151,120 L 152,118 L 152,118 L 152,118'#13 +
+ 'M 68,109 L 87,106 L 107,106 L 106,108 L 88,108 L 68,109 L 68,109 L 68,109'#13 +
+ 'M 105,111 L 95,112 L 79,114 L 71,116 L 85,115 L 102,113 L 105,111 L 105,111 L 105,111'#13 +
+ 'M 108,101 L 98,99 L 87,99 L 78,99 L 93,100 L 105,102 L 108,101 L 108,101 L 108,101'#13 +
+ 'M 85,63 L 91,63 L 97,60 L 104,60 L 108,62 L 111,69 L 112,75 L 110,74 L 108,71 ' +
+ 'L 103,73 L 106,69 L 105,65 L 103,64 L 103,67 L 102,70 L 99,70 L 97,66 L 94,67 ' +
+ 'L 97,72 L 88,67 L 84,66 L 85,63 L 85,63 L 85,63'#13 +
+ 'M 140,74 L 141,66 L 144,61 L 150,61 L 156,62 L 153,70 L 150,73 L 152,65 L 150,65 ' +
+ 'L 151,68 L 149,71 L 146,71 L 144,66 L 143,70 L 143,74 L 140,74 L 140,74 L 140,74'#13 +
+ 'M 146,20 L 156,11 L 163,9 L 172,9 L 178,14 L 182,18 L 184,32 L 182,42 L 182,52 ' +
+ 'L 177,58 L 176,67 L 171,76 L 165,90 L 157,105 L 160,92 L 164,85 L 168,78 L 167,73 ' +
+ 'L 173,66 L 172,62 L 175,59 L 174,55 L 177,53 L 180,46 L 181,29 L 179,21 L 173,13 ' +
+ 'L 166,11 L 159,13 L 153,18 L 148,23 L 146,20 L 146,20 L 146,20'#13 +
+ 'M 150,187 L 148,211 L 150,233 L 153,247 L 148,267 L 135,283 L 125,299 L 136,292 ' +
+ 'L 131,313 L 122,328 L 122,345 L 129,352 L 133,359 L 133,367 L 137,359 L 148,356 ' +
+ 'L 140,350 L 131,347 L 129,340 L 132,332 L 140,328 L 137,322 L 140,304 L 154,265 ' +
+ 'L 157,244 L 155,223 L 161,220 L 175,229 L 186,247 L 185,260 L 176,275 L 178,287 ' +
+ 'L 185,277 L 188,261 L 196,253 L 189,236 L 174,213 L 150,187 L 150,187 L 150,187'#13 +
+ 'M 147,338 L 142,341 L 143,345 L 141,354 L 147,343 L 147,338 L 147,338 L 147,338'#13 +
+ 'M 157,342 L 156,349 L 150,356 L 157,353 L 163,346 L 162,342 L 157,342 L 157,342 L 157,342'#13 +
+ 'M 99,265 L 96,284 L 92,299 L 73,339 L 73,333 L 87,300 L 99,265 L 99,265 L 99,265'#13#0;
+
+ pageEqHigh : shortstring =
+ #1#2#3#4#5#6#7#8#9#10#11#12#13#14#15#16 +
+ #17#18#19#20#21#22#23#24#25#26#27#28#29#30#31#32 +
+ #33#34#35#36#37#38#39#40#41#42#43#44#45#46#47#48 +
+ #49#50#51#52#53#54#55#56#57#58#59#60#61#62#63#64 +
+ #65#66#67#68#69#70#71#72#73#74#75#76#77#78#79#80 +
+ #81#82#83#84#85#86#87#88#89#90#91#92#93#94#95#96 +
+ #65#66#67#68#69#70#71#72#73#74#75#76#77#78#79#80 +
+ #81#82#83#84#85#86#87#88#89#90#123#124#125#126#127#128 +
+ #129#130#131#132#133#134#135#136#137#138#139#140#141#142#143#144 +
+ #145#146#147#148#149#150#151#152#153#154#155#156#157#158#159#160 +
+ #161#162#163#164#165#166#167#168#169#170#171#172#173#174#175#176 +
+ #177#178#179#180#181#182#183#184#185#186#187#188#189#190#191#192 +
+ #193#194#195#196#197#198#199#200#201#202#203#204#205#206#207#208 +
+ #209#210#211#212#213#214#215#216#217#218#219#220#221#222#223#224 +
+ #225#226#227#228#229#230#231#232#233#234#235#236#237#238#239#240 +
+ #241#242#243#244#245#246#247#248#249#250#251#252#253#254#255;
+
+{ UNIT IMPLEMENTATION }
+{ isalnum }
+function isalnum(c : char ) : boolean;
+begin
+ case c of
+ '0'..'9' ,'a'..'z' ,'A'..'Z' :
+ result:=true;
+
+ else
+ result:=false;
+
+ end;
+
+end;
+
+{ isdigit }
+function isdigit(c : char ) : boolean;
+begin
+ case c of
+ '0'..'9' :
+ result:=true;
+
+ else
+ result:=false;
+
+ end;
+
+end;
+
+{ isalpha }
+function isalpha(c : char ) : boolean;
+begin
+ case c of
+ 'a'..'z' ,'A'..'Z' :
+ result:=true;
+
+ else
+ result:=false;
+
+ end;
+
+end;
+
+{ UPSTR }
+function UpStr(s : shortstring ) : shortstring;
+var
+ fcb : byte;
+
+begin
+ if length(s ) > 0 then
+ for fcb:=1 to length(s ) do
+ if byte(s[fcb ] ) > 0 then
+ s[fcb ]:=pageEqHigh[byte(s[fcb ] ) ];
+
+ result:=s;
+
+end;
+
+{ HEXINT }
+function HexInt(h : shortstring ) : int;
+var
+ fcb : byte;
+ yps ,
+ mul ,
+ int : integer;
+
+label
+ Err ,Esc ;
+
+const
+ hex : string[16 ] = '0123456789ABCDEF';
+
+begin
+ if length(h ) > 0 then
+ begin
+ h:=UpStr(h );
+
+ case h[length(h ) ] of
+ '0'..'9' ,'A'..'F' :
+ else
+ goto Err;
+
+ end;
+
+ int:=pos(h[length(h ) ] ,hex ) - 1;
+ yps:=2;
+ mul:=trunc(Power(4 ,yps ) );
+
+ if length(h ) > 1 then
+ for fcb:=length(h ) - 1 downto 1 do
+ begin
+ case h[fcb ] of
+ '0'..'9' ,'A'..'F' :
+ else
+ goto Err;
+
+ end;
+
+ inc(int ,(pos(h[fcb ] ,hex ) - 1 ) * mul );
+ inc(yps ,2 );
+
+ mul:=trunc(Power(4 ,yps ) );
+
+ end;
+
+ goto Esc;
+
+ end;
+
+Err:
+ int:=0;
+
+Esc:
+ result:=int;
+
+end;
+
+{ sscanf }
+procedure sscanf(p : char_ptr; var c : unsigned );
+var
+ s : shortstring;
+
+begin
+ s:='';
+
+ while p^ <> #0 do
+ if isalnum(p^ ) then
+ begin
+ s:=s + p^;
+
+ inc(ptrcomp(p ) );
+
+ end
+ else
+ break;
+
+ c:=HexInt(s );
+
+end;
+
+{ atof }
+function atof(p : char_ptr ) : double;
+var
+ s : shortstring;
+ i ,
+ e : integer;
+
+begin
+ s:='';
+
+ while p^ <> #0 do
+ if isdigit(p^ ) then
+ begin
+ s:=s + p^;
+
+ inc(ptrcomp(p ) );
+
+ end
+ else
+ break;
+
+ val(s ,i ,e );
+
+ result:=i;
+
+end;
+
+{ PARSE_LION }
+function parse_lion;
+var
+ ptr : char_ptr;
+
+ npaths ,c : unsigned;
+
+ ch : char;
+
+ x ,y : double;
+
+begin
+ ptr :=@g_lion[0 ];
+ npaths:=0;
+
+ while ptr^ <> #0 do
+ if (ptr^ <> 'M' ) and
+ isalnum(ptr^ ) then
+ begin
+ c:=0;
+
+ sscanf(ptr ,c );
+
+ // New color. Every new color creates new path in the path object.
+ path.close_polygon;
+
+ colors^.Construct(rgb8_packed(c ) );
+
+ path_idx^:=path.start_new_path;
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(ptrcomp(path_idx ) ,sizeof(unsigned ) );
+ inc(npaths );
+
+ while (ptr^ <> #0 ) and
+ (ptr^ <> #13 ) do
+ inc(ptrcomp(ptr ) );
+
+ if ptr^ = #13 then
+ inc(ptrcomp(ptr ) );
+
+ end
+ else
+ begin
+ x:=0.0;
+ y:=0.0;
+
+ while (ptr^ <> #0 ) and
+ (ptr^ <> #13 ) do
+ begin
+ ch:=ptr^;
+
+ while (ptr^ <> #0 ) and
+ not isdigit(ptr^ ) do
+ inc(ptrcomp(ptr ) );
+
+ x:=atof(ptr );
+
+ while (ptr^ <> #0 ) and
+ isdigit(ptr^ ) do
+ inc(ptrcomp(ptr ) );
+
+ while (ptr^ <> #0 ) and
+ not isdigit(ptr^ ) do
+ inc(ptrcomp(ptr ) );
+
+ y:=atof(ptr );
+
+ if ch = 'M' then
+ begin
+ path.close_polygon;
+ path.move_to(x ,y );
+
+ end
+ else
+ path.line_to(x ,y );
+
+ while (ptr^ <> #0 ) and
+ isdigit(ptr^ ) do
+ inc(ptrcomp(ptr ) );
+
+ while (ptr^ <> #0 ) and
+ (ptr^ <> #13 ) and
+ not isalpha(ptr ^ ) do
+ inc(ptrcomp(ptr ) );
+
+ end;
+
+ if ptr^ = #13 then
+ inc(ptrcomp(ptr ) );
+
+ end;
+
+ path.arrange_orientations_all_paths(path_flags_cw );
+
+ result:=npaths;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg-demos/particle_demo.dpr b/src/corelib/render/software/agg-demos/particle_demo.dpr
new file mode 100644
index 00000000..c9c38403
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/particle_demo.dpr
@@ -0,0 +1,843 @@
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ particle_demo ;
+
+{DEFINE DISORDER }
+
+uses
+ Math ,
+ agg_basics ,
+ agg_platform_support ,
+ agg_ctrl ,
+ agg_slider_ctrl ,
+ agg_cbox_ctrl ,
+ agg_renderer_base ,
+ agg_rendering_buffer ,
+ agg_rasterizer_scanline_aa ,
+ agg_scanline_u ,
+ agg_color ,
+ agg_pixfmt ,
+ agg_pixfmt_rgb ,
+ agg_pixfmt_rgba ,
+ agg_renderer_scanline ,
+ agg_path_storage ,
+ agg_conv_transform ,
+ agg_bounding_rect ,
+ agg_span_allocator ,
+ agg_span_gradient ,
+ agg_span_interpolator_linear ,
+ agg_rasterizer_outline_aa ,
+ agg_rendering_buffer_dynarow ,
+ agg_ellipse ,
+ agg_array ,
+ agg_gsv_text ,
+ agg_conv_stroke ,
+ agg_render_scanlines ,
+ agg_trans_affine ,
+ agg_math ;
+
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+var
+ g_rasterizer : rasterizer_scanline_aa;
+
+ g_scanline : scanline_u8;
+
+ g_path : path_storage;
+
+ g_npaths : unsigned = 0;
+
+ g_x1 : double = 0;
+ g_y1 : double = 0;
+ g_x2 : double = 0;
+ g_y2 : double = 0;
+
+ g_base_dx : double = 0;
+ g_base_dy : double = 0;
+
+ g_scale : double = 1.0;
+
+ g_skew_x : double = 0;
+ g_skew_y : double = 0;
+
+ g_nclick : int = 0;
+
+ g_cx ,g_cy ,g_dx ,g_dy ,g_radius : array[0..999 ] of double;
+
+ g_color1 ,g_color2 ,g_color3 : array[0..999 ] of aggclr;
+
+ g_gradients : array[0..999 ] of pod_auto_array;
+
+ g_angle : double = 0;
+
+ g_center : double = 0;
+
+ g_dc : double = 0.5;
+
+ g_cache : array[0..999 ] of rendering_buffer_dynarow_ptr;
+
+type
+ gradient_tricolor = object(array_base )
+ private
+ m_c1 ,
+ m_c2 ,
+ m_c3 ,
+ m_rc : aggclr;
+
+ public
+ constructor Construct(c1 ,c2 ,c3 : aggclr );
+
+ function size : unsigned; virtual;
+ function array_operator(i : unsigned ) : pointer; virtual;
+
+ procedure colors(c1 ,c2 ,c3 : aggclr );
+
+ end;
+
+ the_application = object(platform_support )
+ private
+ m_particles ,
+ m_speed : slider_ctrl;
+ m_use_cache ,
+ m_run : cbox_ctrl;
+
+ m_run_flag ,
+ m_use_cache_flag ,
+ m_first_time : boolean;
+
+ m_particles_value ,
+ m_speed_value : double;
+
+ public
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure on_init; virtual;
+ procedure on_draw; virtual;
+
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_move (x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+ procedure on_idle; virtual;
+ procedure on_ctrl_change; virtual;
+
+ end;
+
+{ CONSTRUCT }
+constructor gradient_tricolor.Construct(c1 ,c2 ,c3 : aggclr );
+begin
+ m_c1:=c1;
+ m_c2:=c2;
+ m_c3:=c3;
+
+end;
+
+{ SIZE }
+function gradient_tricolor.size : unsigned;
+begin
+ result:=256;
+
+end;
+
+{ ARRAY_OPERATOR }
+function gradient_tricolor.array_operator(i : unsigned ) : pointer;
+begin
+ if i <= 127 then
+ begin
+ i:=i * 2;
+
+ m_rc.r:=int8u((((m_c2.r - m_c1.r ) * int(i ) ) + (m_c1.r shl 8 ) ) shr 8 );
+ m_rc.g:=int8u((((m_c2.g - m_c1.g ) * int(i ) ) + (m_c1.g shl 8 ) ) shr 8 );
+ m_rc.b:=int8u((((m_c2.b - m_c1.b ) * int(i ) ) + (m_c1.b shl 8 ) ) shr 8 );
+ m_rc.a:=int8u((((m_c2.a - m_c1.a ) * int(i ) ) + (m_c1.a shl 8 ) ) shr 8 );
+
+ end
+ else
+ begin
+ i:=(i - 127 ) * 2;
+
+ m_rc.r:=int8u((((m_c3.r - m_c2.r ) * int(i ) ) + (m_c2.r shl 8 ) ) shr 8 );
+ m_rc.g:=int8u((((m_c3.g - m_c2.g ) * int(i ) ) + (m_c2.g shl 8 ) ) shr 8 );
+ m_rc.b:=int8u((((m_c3.b - m_c2.b ) * int(i ) ) + (m_c2.b shl 8 ) ) shr 8 );
+ m_rc.a:=int8u((((m_c3.a - m_c2.a ) * int(i ) ) + (m_c2.a shl 8 ) ) shr 8 );
+
+ end;
+
+ result:=@m_rc;
+
+end;
+
+{ COLORS }
+procedure gradient_tricolor.colors(c1 ,c2 ,c3 : aggclr );
+begin
+ m_c1:=c1;
+ m_c2:=c2;
+ m_c3:=c3;
+
+end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+var
+ i : int;
+ c : aggclr;
+
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_particles.Construct(5 ,5 ,300 ,12 ,not flip_y_ );
+ m_speed.Construct (5 ,5 + 15 ,300 ,12 + 15 ,not flip_y_ );
+ m_use_cache.Construct(320 ,5 ,'Use Bitmap Cache' ,not flip_y_ );
+ m_run.Construct (320 ,5 + 15 ,'Start the Universe!' ,not flip_y_ );
+
+ m_run_flag :=true;
+ m_use_cache_flag:=false;
+
+ i:=0;
+
+ while i < 1000 do
+ begin
+ g_cache[i ]:=NIL;
+
+ g_gradients[i ].Construct(256 ,sizeof(aggclr ) );
+
+ inc(i );
+
+ end;
+
+ add_ctrl(@m_particles );
+
+ m_particles.range_(10 ,1000 );
+ m_particles.value_(200 );
+ m_particles.label_('Number of Particles=%.0f' );
+ m_particles.no_transform;
+
+ m_particles_value:=m_particles._value;
+
+ add_ctrl(@m_speed );
+
+ m_speed.range_(0.025 ,2.0 );
+ m_speed.value_(1.0 );
+ m_speed.label_('Dark Energy=%.3f' );
+ m_speed.no_transform;
+
+ m_speed_value:=m_speed._value;
+ m_first_time :=true;
+
+ add_ctrl(@m_use_cache );
+
+ c.ConstrDbl (1 ,1 ,1 );
+ m_use_cache.text_color_ (@c );
+ c.ConstrDbl (1 ,1 ,1 );
+ m_use_cache.inactive_color_(@c );
+ c.ConstrDbl (0.8 ,0 ,0 );
+ m_use_cache.active_color_ (@c );
+
+ m_use_cache.no_transform;
+
+ add_ctrl(@m_run );
+
+ c.ConstrDbl (1 ,1 ,1 );
+ m_run.text_color_ (@c );
+ c.ConstrDbl (1 ,1 ,1 );
+ m_run.inactive_color_(@c );
+ c.ConstrDbl (0.8 ,0 ,0 );
+ m_run.active_color_ (@c );
+
+ m_run.no_transform;
+ m_run.status_(true );
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+var
+ i : int;
+
+begin
+ inherited Destruct;
+
+ m_particles.Destruct;
+ m_speed.Destruct;
+ m_use_cache.Destruct;
+ m_run.Destruct;
+
+ i:=0;
+
+ while i < 1000 do
+ begin
+ if g_cache[i ] <> NIL then
+ dispose(g_cache[i ] ,Destruct );
+
+ g_gradients[i ].Destruct;
+
+ inc(i );
+
+ end;
+
+end;
+
+{ RENDER_PARTICLE }
+procedure render_particle(ren : renderer_base_ptr; i : unsigned; x ,y : double );
+var
+ grm : trans_affine;
+ grf : gradient_circle;
+ ell : ellipse;
+
+ sa : span_allocator;
+ sg : span_gradient;
+ rg : renderer_scanline_aa;
+
+ inter : span_interpolator_linear;
+
+ r : double;
+
+ tas : trans_affine_scaling;
+ tat : trans_affine_translation;
+
+begin
+ grm.Construct;
+ grf.Construct;
+ ell.Construct;
+ sa.Construct;
+ inter.Construct(@grm );
+ sg.Construct (@sa ,@inter ,@grf ,@g_gradients[i ] ,0 ,10 );
+ rg.Construct (ren ,@sg );
+
+ r:=g_radius[i ];
+
+ grm.reset;
+ tas.Construct(r / 10.0 );
+ grm.multiply (@tas );
+ tat.Construct(x ,y );
+ grm.multiply (@tat );
+ grm.invert;
+
+ ell.init(x ,y ,r ,r ,32 );
+
+ g_rasterizer.add_path(@ell );
+
+ render_scanlines(@g_rasterizer ,@g_scanline ,@rg );
+
+ sa.Destruct;
+ sg.Destruct;
+
+end;
+
+{ ON_INIT }
+procedure the_application.on_init;
+var
+ n ,i ,j ,d : unsigned;
+
+ component ,da : int;
+
+ divisor ,angle ,speed ,k : double;
+
+ grc : gradient_tricolor;
+
+ gr : pod_auto_array_ptr;
+
+ pixf : pixel_formats;
+ ren : renderer_base;
+
+begin
+ n:=Trunc(m_particles._value );
+
+ srand(123 );
+
+ if m_use_cache._status then
+ divisor:=250.0
+ else
+ divisor:=500.0;
+
+ if m_first_time then
+ begin
+ i:=0;
+
+ while i < n do
+ begin
+ g_cx[i ]:=_width / 2 {$IFDEF DISORDER } + rand mod 10 - 5 {$ENDIF };
+ g_cy[i ]:=_height / 2 {$IFDEF DISORDER } + rand mod 10 - 5 {$ENDIF };
+
+ {$IFDEF DISORDER }
+ if rand and 1 <> 0 then
+ g_dx[i ]:=(rand mod 5000 + 1000 ) / divisor
+ else
+ g_dx[i ]:=-(rand mod 5000 + 1000 ) / divisor;
+
+ g_dy[i ]:=g_dx[i ];
+
+ if rand and 1 <> 0 then
+ g_dy[i ]:=-g_dy[i ];
+
+ //---
+ angle:=(rand mod 10000 ) / 10000.0 * (2.0 / 8.0 ) * pi;
+ da :=rand and 3;
+ angle:=angle + 2.0 * pi * da / 4.0 + (pi / 10.0 );
+
+ {$ELSE }
+ angle:=(rand mod 10000 ) / 10000.0 * 2.0 * pi;
+
+ {$ENDIF }
+
+ speed:=((rand mod 10000 ) mod 5000 + 1000.0 ) / divisor;
+
+ g_dx[i ]:=Cos(angle ) * speed;
+ g_dy[i ]:=Sin(angle ) * speed;
+
+ k:=1.0 - n / 2000.0;
+
+ g_radius[i ]:=(rand mod 30 + 15 ) * k;
+
+ g_color1[i ].ConstrInt(rand and $FF ,rand and $FF ,rand and $FF ,0 );
+ g_color2[i ].ConstrInt(rand and $FF ,rand and $FF ,rand and $FF ,255 );
+
+ component:=rand mod 3;
+
+ if component = 0 then
+ g_color2[i ].r:=255;
+
+ if component = 1 then
+ g_color2[i ].g:=255;
+
+ if component = 2 then
+ g_color2[i ].b:=255;
+
+ {$IFDEF DISORDER }
+ g_color1[i ] :=g_color2[i ];
+ g_color1[i ].a:=0;
+
+ {$ENDIF }
+
+ g_color3[i ].ConstrInt(rand and $FF ,rand and $FF ,rand and $FF ,0 );
+
+ grc.Construct(g_color1[i ] ,g_color2[i ] ,g_color3[i ] );
+
+ gr:=@g_gradients[i ];
+ j :=0;
+
+ while j < gr.size do
+ begin
+ move(
+ grc.array_operator(j )^ ,
+ gr.array_operator(j )^ ,
+ sizeof(aggclr ) );
+
+ inc(j );
+
+ end;
+
+ inc(i );
+
+ end;
+
+ m_first_time:=false;
+
+ end;
+
+ if m_use_cache._status then
+ begin
+ i:=0;
+
+ while i < 1000 do
+ begin
+ if g_cache[i ] <> NIL then
+ dispose(g_cache[i ] ,Destruct );
+
+ g_cache[i ]:=NIL;
+
+ inc(i );
+
+ end;
+
+ i:=0;
+
+ while i < n do
+ begin
+ d:=Trunc(g_radius[i ] ) * 2;
+
+ new(g_cache[i ] ,Construct(d ,d ,d * 4 ) );
+
+ pixfmt_alpha_blend_rgba(pixf ,g_cache[i ] ,bgra_order );
+
+ ren.Construct(@pixf );
+
+ render_particle(@ren ,i ,d / 2 ,d / 2 );
+
+ inc(i );
+
+ end;
+
+ end;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ i : unsigned;
+
+ width ,height ,x ,y : int;
+
+ pf ,pf_pre ,pixf : pixel_formats;
+
+ r ,r_pre : renderer_base;
+
+ rs : renderer_scanline_aa_solid;
+
+ rgba : aggclr;
+
+ n : unsigned;
+ tm : double;
+
+ buf : array[0..63 ] of char;
+
+ t : gsv_text;
+ pt : conv_stroke;
+
+begin
+ width :=rbuf_window._width;
+ height:=rbuf_window._height;
+
+// Initialize structures
+ pixfmt_bgra32(pf ,rbuf_window );
+
+ r.Construct (@pf );
+ rs.Construct(@r );
+
+ g_rasterizer.clip_box(0 ,0 ,width ,height );
+
+ rgba.ConstrDbl(0 ,0 ,0 );
+ r.clear(@rgba );
+
+// Render
+ if m_run._status then
+ begin
+ start_timer;
+
+ n:=Trunc(m_particles._value );
+
+ if m_use_cache._status then
+ begin
+ pixfmt_bgra32_pre(pf_pre ,rbuf_window );
+ r_pre.Construct (@pf_pre );
+
+ i:=0;
+
+ while i < n do
+ begin
+ if g_cache[i ] <> NIL then
+ begin
+ pixfmt_alpha_blend_rgba(pixf ,g_cache[i ] ,bgra_order );
+
+ x:=Trunc(g_cx[i ] - g_radius[i ] ) + 1;
+ y:=Trunc(g_cy[i ] - g_radius[i ] ) + 1;
+
+ r_pre.blend_from(@pixf ,0 ,x ,y ,255 );
+
+ end;
+
+ inc(i );
+
+ end;
+
+ end
+ else
+ begin
+ i:=0;
+
+ while i < n do
+ begin
+ render_particle(@r ,i ,g_cx[i ] ,g_cy[i ] );
+
+ inc(i );
+
+ end;
+
+ end;
+
+ tm:=elapsed_time;
+
+ t.Construct;
+ t.size_(10.0 );
+
+ pt.Construct(@t );
+ pt.width_ (1.5 );
+
+ sprintf(@buf[0 ] ,'%6.1f fps' ,1000.0 / tm );
+
+ t.start_point_(10.0 ,35.0 );
+ t.text_ (@buf[0 ] );
+
+ g_rasterizer.add_path(@pt );
+
+ rgba.ConstrDbl(1 ,1 ,1 );
+ rs.color_ (@rgba );
+
+ render_scanlines(@g_rasterizer ,@g_scanline ,@rs );
+
+ t.Destruct;
+ pt.Destruct;
+
+ end;
+
+// Render the controls
+ render_ctrl(@g_rasterizer ,@g_scanline ,@rs ,@m_particles );
+ render_ctrl(@g_rasterizer ,@g_scanline ,@rs ,@m_speed );
+ render_ctrl(@g_rasterizer ,@g_scanline ,@rs ,@m_use_cache );
+ render_ctrl(@g_rasterizer ,@g_scanline ,@rs ,@m_run );
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure the_application.on_mouse_button_down;
+begin
+ if (flags and mouse_left <> 0 ) or
+ (flags and mouse_right <> 0 ) then
+ force_redraw;
+
+end;
+
+{ ON_MOUSE_MOVE }
+procedure the_application.on_mouse_move;
+begin
+ on_mouse_button_down(x ,y ,flags );
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ 'Demonstration of using the bitmap cache.'#13#13 +
+ 'Cached bitmaps are descended from AGG renderer_base '#13 +
+ 'and on_draw method just alpha blended to the scene.' );
+
+end;
+
+{ ON_IDLE }
+procedure the_application.on_idle;
+var
+ n ,i : unsigned;
+
+ x1 ,y1 ,x2 ,y2 ,dx ,dy ,cx ,cy ,max_dist ,d : double;
+
+begin
+ n:=Trunc(m_particles._value );
+
+ x1:=-100;
+ y1:=-100;
+ x2:=_width + 100;
+ y2:=_height + 100;
+ dx:=Cos(g_angle ) * g_center;
+ dy:=Sin(g_angle ) * g_center;
+ cx:=dx + _width / 2;
+ cy:=dy + _height / 2;
+
+ max_dist:=Sqrt(_width * _width / 2 + _height * _height / 2 );
+
+ g_angle :=g_angle + 5.0 * pi / 180.0;
+ g_center:=g_center + g_dc;
+
+ if g_center > max_dist / 2 then
+ begin
+ g_center:=max_dist / 2;
+ g_dc :=-g_dc;
+
+ end;
+
+ if g_center < 10.0 then
+ begin
+ g_center:=10.0;
+ g_dc :=-g_dc;
+
+ end;
+
+ i:=0;
+
+ while i < n do
+ begin
+ g_cx[i ]:=g_cx[i ] + g_dx[i ] * m_speed._value;
+ g_cy[i ]:=g_cy[i ] + g_dy[i ] * m_speed._value;
+
+ d:=calc_distance(g_cx[i ] ,g_cy[i ] ,cx ,cy );
+
+ if d > max_dist then
+ begin
+ g_cx[i ]:=cx;
+ g_cy[i ]:=cy;
+
+ end;
+
+ {$IFDEF DISORDER }
+ {
+ if g_cx[i ] < x1 then
+ begin
+ g_cx[i ]:=cx;
+ g_cy[i ]:=cy;
+
+ end;
+
+ if g_cx[i ] > x2 then
+ begin
+ g_cx[i ]:=cx;
+ g_cy[i ]:=cy;
+
+ end;
+
+ if g_cy[i ] < y1 then
+ begin
+ g_cx[i ]:=cx;
+ g_cy[i ]:=cy;
+
+ end;
+
+ if g_cy[i ] > y2 then
+ begin
+ g_cx[i ]:=cx;
+ g_cy[i ]:=cy;
+
+ end;
+
+ {}
+ if g_cx[i ] < x1 then
+ begin
+ g_cx[i ]:=x1;
+ g_dx[i ]:=-g_dx[i ];
+
+ end;
+
+ if g_cx[i ] > x2 then
+ begin
+ g_cx[i ]:=x2;
+ g_dx[i ]:=-g_dx[i];
+
+ end;
+
+ if g_cy[i ] < y1 then
+ begin
+ g_cy[i ]:=y1;
+ g_dy[i ]:=-g_dy[i ];
+
+ end;
+
+ if g_cy[i ] > y2 then
+ begin
+ g_cy[i ]:=y2;
+ g_dy[i ]:=-g_dy[i ];
+
+ end;
+
+ {}
+ {$ENDIF }
+
+ inc(i );
+
+ end;
+
+ force_redraw;
+
+end;
+
+{ ON_CTRL_CHANGE }
+procedure the_application.on_ctrl_change;
+var
+ stop ,over : boolean;
+
+begin
+ if m_run_flag <> m_run._status then
+ begin
+ wait_mode_(not m_run._status );
+
+ m_run_flag:=m_run._status;
+
+ if m_run_flag then
+ begin
+ m_first_time:=true;
+
+ on_init;
+
+ end;
+
+ end
+ else
+ begin
+ stop:=false;
+ over:=false;
+
+ if m_use_cache._status <> m_use_cache_flag then
+ begin
+ m_use_cache_flag:=m_use_cache._status;
+
+ stop:=false;
+ over:=true;
+
+ end;
+
+ if m_particles._value <> m_particles_value then
+ begin
+ m_particles_value:=m_particles._value;
+
+ stop:=true;
+ over:=false;
+
+ end;
+
+ if m_speed._value <> m_speed_value then
+ begin
+ m_speed_value:=m_speed._value;
+
+ stop:=false;
+ over:=false;
+
+ end;
+
+ if stop then
+ begin
+ wait_mode_ (true );
+ m_run.status_(false );
+
+ end
+ else
+ if over then
+ on_init;
+
+ end;
+
+end;
+
+VAR
+ app : the_application;
+
+BEGIN
+ app.Construct(pix_format_bgra32 ,flip_y );
+ app.caption_ ('Renesis project -- Particles demo. (F1-Help)' );
+
+ g_scanline.Construct;
+ g_rasterizer.Construct;
+ g_path.Construct;
+
+ if app.init(600 ,500 ,window_resize ) then
+ begin
+ app.wait_mode_(false );
+ app.run;
+
+ end;
+
+ g_rasterizer.Destruct;
+ g_scanline.Destruct;
+ g_path.Destruct;
+
+ app.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/pattern_fill.dpr b/src/corelib/render/software/agg-demos/pattern_fill.dpr
new file mode 100644
index 00000000..ad35bd68
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/pattern_fill.dpr
@@ -0,0 +1,522 @@
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ pattern_fill ;
+
+{$DEFINE AGG_BGR24 }
+
+uses
+ agg_basics ,
+ agg_platform_support ,
+ agg_pixfmt_rgba ,
+
+ agg_ctrl ,
+ agg_rbox_ctrl ,
+ agg_cbox_ctrl ,
+ agg_slider_ctrl ,
+
+ agg_rasterizer_scanline_aa ,
+ agg_scanline ,
+ agg_scanline_p ,
+
+ agg_rendering_buffer ,
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_render_scanlines ,
+
+ agg_path_storage ,
+ agg_trans_affine ,
+ agg_conv_stroke ,
+ agg_conv_transform ,
+ agg_conv_smooth_poly1 ,
+ agg_span_allocator ,
+ agg_span_pattern ,
+ agg_span_pattern_rgba
+
+{$I pixel_formats.inc }
+{$I agg_mode.inc }
+{$Q- }
+{$R- }
+const
+ flip_y = true;
+
+type
+ the_application = object(platform_support )
+ m_polygon_angle ,
+ m_polygon_scale ,
+ m_pattern_angle ,
+ m_pattern_size ,
+ m_pattern_alpha : slider_ctrl;
+
+ m_rotate_polygon ,
+ m_rotate_pattern ,
+ m_tie_pattern : cbox_ctrl;
+
+ m_polygon_cx ,
+ m_polygon_cy ,
+
+ m_dx ,
+ m_dy : double;
+
+ m_flag : int;
+
+ m_pattern : int8u_ptr;
+ m_pt_aloc : unsigned;
+
+ m_pattern_rbuf : rendering_buffer;
+
+ m_ras : rasterizer_scanline_aa;
+ m_sl : scanline_p8;
+ m_ps : path_storage;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure create_star(xc ,yc ,r1 ,r2 : double; n : unsigned; start_angle : double = 2.0 );
+ procedure generate_pattern;
+
+ procedure on_init; virtual;
+ procedure on_draw; virtual;
+
+ procedure on_mouse_move (x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_up (x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_ctrl_change; virtual;
+ procedure on_idle; virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_polygon_angle.Construct (5 ,5 ,145 ,12 ,not flip_y_ );
+ m_polygon_scale.Construct (5 ,5 + 14 ,145 ,12 + 14 ,not flip_y_ );
+ m_pattern_angle.Construct (155 ,5 ,300 ,12 ,not flip_y_ );
+ m_pattern_size.Construct (155 ,5 + 14 ,300 ,12 + 14 ,not flip_y_ );
+ m_pattern_alpha.Construct (310 ,5 ,460 ,12 ,not flip_y_ );
+ m_rotate_polygon.Construct(5 ,5 + 14 + 14 ,'Rotate Polygon' ,not flip_y_ );
+ m_rotate_pattern.Construct(5 ,5 + 14 + 14 + 14 ,'Rotate Pattern' ,not flip_y_ );
+ m_tie_pattern.Construct (155 ,5 + 14 + 14 ,'Tie pattern to polygon' ,not flip_y_ );
+
+ m_pattern_rbuf.Construct;
+
+ m_ras.Construct;
+ m_sl.Construct;
+ m_ps.Construct;
+
+ m_flag :=0;
+ m_pattern:=NIL;
+ m_pt_aloc:=0;
+
+ add_ctrl(@m_polygon_angle );
+ add_ctrl(@m_polygon_scale );
+ add_ctrl(@m_pattern_angle );
+ add_ctrl(@m_pattern_size );
+ add_ctrl(@m_pattern_alpha );
+ add_ctrl(@m_rotate_polygon );
+ add_ctrl(@m_rotate_pattern );
+ add_ctrl(@m_tie_pattern );
+
+ m_polygon_angle.label_('Polygon Angle=%3.2f' );
+ m_polygon_angle.range_(-180.0 ,180.0 );
+
+ m_polygon_scale.label_('Polygon Scale=%3.2f' );
+ m_polygon_scale.range_(0.1 ,5.0 );
+ m_polygon_scale.value_(1.0 );
+
+ m_pattern_angle.label_('Pattern Angle=%3.2f' );
+ m_pattern_angle.range_(-180.0 ,180.0 );
+
+ m_pattern_size.label_('Pattern Size=%3.2f' );
+ m_pattern_size.range_(10 ,40 );
+ m_pattern_size.value_(30 );
+
+ m_pattern_alpha.label_('Background Alpha=%.2f' );
+ m_pattern_alpha.value_(0.1 );
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_polygon_angle.Destruct;
+ m_polygon_scale.Destruct;
+ m_pattern_angle.Destruct;
+ m_pattern_size.Destruct;
+ m_pattern_alpha.Destruct;
+ m_rotate_polygon.Destruct;
+ m_rotate_pattern.Destruct;
+ m_tie_pattern.Destruct;
+
+ m_pattern_rbuf.Destruct;
+
+ m_ras.Destruct;
+ m_sl.Destruct;
+ m_ps.Destruct;
+
+ agg_freemem(pointer(m_pattern ) ,m_pt_aloc );
+
+end;
+
+{ CREATE_STAR }
+procedure the_application.create_star;
+var
+ i : unsigned;
+
+ a ,dx ,dy : double;
+
+begin
+ m_ps.remove_all;
+
+ start_angle:=start_angle * pi / 180.0;
+
+ i:=0;
+
+ while i < n do
+ begin
+ a :=pi * 2.0 * i / n - pi / 2.0;
+ dx:=Cos(a + start_angle );
+ dy:=Sin(a + start_angle );
+
+ if i and 1 <> 0 then
+ m_ps.line_to(xc + dx * r1 ,yc + dy * r1 )
+ else
+ if i <> 0 then
+ m_ps.line_to(xc + dx * r2 ,yc + dy * r2 )
+ else
+ m_ps.move_to(xc + dx * r2 ,yc + dy * r2 );
+
+ inc(i );
+
+ end;
+
+ m_ps.close_polygon;
+
+end;
+
+{ GENERATE_PATTERN }
+procedure the_application.generate_pattern;
+var
+ size : unsigned;
+ pixf : pixel_formats;
+ rgba : aggclr;
+
+ smooth : conv_smooth_poly1_curve;
+ stroke : conv_stroke;
+
+ rb : renderer_base;
+ rs : renderer_scanline_aa_solid;
+
+begin
+ size:=trunc(m_pattern_size._value );
+
+ create_star(
+ m_pattern_size._value / 2.0 ,
+ m_pattern_size._value / 2.0 ,
+ m_pattern_size._value / 2.5 ,
+ m_pattern_size._value / 6.0 ,
+ 6 ,
+ m_pattern_angle._value );
+
+ smooth.Construct(@m_ps );
+ stroke.Construct(@smooth );
+
+ smooth.smooth_value_ (0.0 );
+ smooth.approximation_scale_(4.0 );
+
+ stroke.width_(m_pattern_size._value / 15.0);
+
+ agg_freemem(pointer(m_pattern ) ,m_pt_aloc );
+
+ m_pt_aloc:=size * size * 4 * sizeof(int8u );
+
+ agg_getmem(pointer(m_pattern ) ,m_pt_aloc );
+
+ m_pattern_rbuf.attach(m_pattern ,size ,size ,size * 4 );
+
+ pixfmt_rgba32(pixf ,@m_pattern_rbuf );
+ rb.Construct (@pixf );
+ rs.Construct (@rb );
+
+ rgba.ConstrDbl(0.4 ,0.0 ,0.1 ,m_pattern_alpha._value ); // Pattern background color
+ rb.clear (@rgba );
+
+ m_ras.add_path (@smooth );
+ rgba.ConstrInt (110 ,130 ,50 );
+ rs.color_ (@rgba );
+ render_scanlines(@m_ras ,@m_sl ,@rs );
+
+ m_ras.add_path (@stroke );
+ rgba.ConstrInt (0 ,50 ,80 );
+ rs.color_ (@rgba );
+ render_scanlines(@m_ras ,@m_sl ,@rs );
+
+ smooth.Destruct;
+ stroke.Destruct;
+
+end;
+
+{ ON_INIT }
+procedure the_application.on_init;
+begin
+ m_polygon_cx:=_initial_width / 2.0;
+ m_polygon_cy:=_initial_height / 2.0;
+
+ generate_pattern;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ width_ ,height_ : double;
+
+ pixf : pixel_formats;
+ rgba : aggclr;
+
+ rb : renderer_base;
+ rs : renderer_scanline_aa_solid;
+
+ polygon_mtx : trans_affine;
+
+ tat : trans_affine_translation;
+ tar : trans_affine_rotation;
+ tas : trans_affine_scaling;
+
+ r : double;
+
+ offset_x ,offset_y : unsigned;
+
+ tr : conv_transform;
+ wx ,
+ wy : wrap_mode_reflect_auto_pow2;
+ sa : span_allocator;
+ sg : span_pattern_rgba;
+ rp : renderer_scanline_aa;
+
+begin
+// Initialize structures
+ width_ :=rbuf_window._width;
+ height_:=rbuf_window._height;
+
+ pixfmt(pixf ,rbuf_window );
+
+ rb.Construct(@pixf );
+ rs.Construct(@rb );
+
+ rgba.ConstrDbl(1.0 ,1.0 ,1.0 );
+ rb.clear (@rgba );
+
+// Render
+ polygon_mtx.Construct;
+
+ tat.Construct(-m_polygon_cx ,-m_polygon_cy ); polygon_mtx.multiply(@tat );
+ tar.Construct(m_polygon_angle._value * pi / 180.0 ); polygon_mtx.multiply(@tar );
+ tas.Construct(m_polygon_scale._value ); polygon_mtx.multiply(@tas );
+ tat.Construct(m_polygon_cx ,m_polygon_cy ); polygon_mtx.multiply(@tat );
+
+ r:=_initial_width / 3.0 - 8.0;
+
+ create_star(m_polygon_cx ,m_polygon_cy ,r ,r / 1.45 ,14 );
+
+ tr.Construct(@m_ps ,@polygon_mtx );
+
+ offset_x:=0;
+ offset_y:=0;
+
+ if m_tie_pattern._status then
+ begin
+ offset_x:=trunc(width_ - m_polygon_cx );
+ offset_y:=trunc(height_ - m_polygon_cy );
+
+ end;
+
+ sa.Construct;
+ wx.Construct;
+ wy.Construct;
+ sg.Construct(@sa ,@m_pattern_rbuf ,offset_x ,offset_y ,@wx ,@wy ,rgba_order );
+ rp.Construct(@rb ,@sg );
+
+{ m_ras.clip_box (-1 ,0 ,width_ ,height_ );
+ m_ras.move_to_d(-1 ,100 );
+ m_ras.line_to_d(100 ,100 );
+ m_ras.line_to_d(100 ,200 );
+ m_ras.line_to_d(-1 ,200 );
+ m_ras.close_polygon;{}
+
+ m_ras.add_path (@tr );
+ rgba.ConstrDbl (0 ,0 ,0 );
+ rs.color_ (@rgba );
+ render_scanlines(@m_ras ,@m_sl ,@rp );
+
+// Render the controls
+ render_ctrl(@m_ras ,@m_sl ,@rs ,@m_polygon_angle );
+ render_ctrl(@m_ras ,@m_sl ,@rs ,@m_polygon_scale );
+ render_ctrl(@m_ras ,@m_sl ,@rs ,@m_pattern_angle );
+ render_ctrl(@m_ras ,@m_sl ,@rs ,@m_pattern_size );
+ render_ctrl(@m_ras ,@m_sl ,@rs ,@m_pattern_alpha );
+ render_ctrl(@m_ras ,@m_sl ,@rs ,@m_rotate_polygon );
+ render_ctrl(@m_ras ,@m_sl ,@rs ,@m_rotate_pattern );
+ render_ctrl(@m_ras ,@m_sl ,@rs ,@m_tie_pattern );
+
+// Free AGG resources
+ sa.Destruct;
+
+end;
+
+{ ON_MOUSE_MOVE }
+procedure the_application.on_mouse_move;
+begin
+ if flags and mouse_left <> 0 then
+ if m_flag <> 0 then
+ begin
+ m_polygon_cx:=x - m_dx;
+ m_polygon_cy:=y - m_dy;
+
+ force_redraw;
+
+ end
+ else
+ else
+ on_mouse_button_up(x ,y ,flags );
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure the_application.on_mouse_button_down;
+var
+ polygon_mtx : trans_affine;
+
+ tat : trans_affine_translation;
+ tar : trans_affine_rotation;
+ tas : trans_affine_scaling;
+
+ r : double;
+ tr : conv_transform;
+
+begin
+ if flags and mouse_left <> 0 then
+ begin
+ polygon_mtx.Construct;
+
+ tat.Construct(-m_polygon_cx ,-m_polygon_cy ); polygon_mtx.multiply(@tat );
+ tar.Construct(m_polygon_angle._value * pi / 180.0 ); polygon_mtx.multiply(@tar );
+ tas.Construct(m_polygon_scale._value ,m_polygon_scale._value ); polygon_mtx.multiply(@tas );
+ tat.Construct(m_polygon_cx ,m_polygon_cy ); polygon_mtx.multiply(@tat );
+
+ r:=_initial_width / 3.0 - 8.0;
+
+ create_star(m_polygon_cx ,m_polygon_cy ,r ,r / 1.45 ,14 );
+
+ tr.Construct (@m_ps ,@polygon_mtx );
+ m_ras.add_path(@tr );
+
+ if m_ras.hit_test(x ,y ) then
+ begin
+ m_dx:=x - m_polygon_cx;
+ m_dy:=y - m_polygon_cy;
+
+ m_flag:=1;
+
+ end;
+
+ end;
+
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+procedure the_application.on_mouse_button_up;
+begin
+ m_flag:=0;
+
+end;
+
+{ ON_CTRL_CHANGE }
+procedure the_application.on_ctrl_change;
+begin
+ if m_rotate_polygon._status or
+ m_rotate_pattern._status then
+ wait_mode_(false )
+ else
+ wait_mode_(true);
+
+ generate_pattern;
+ force_redraw;
+
+end;
+
+{ ON_IDLE }
+procedure the_application.on_idle;
+var
+ redraw : boolean;
+
+begin
+ redraw:=false;
+ if m_rotate_polygon._status then
+ begin
+ m_polygon_angle.value_(m_polygon_angle._value + 0.5 );
+
+ if m_polygon_angle._value >= 180.0 then
+ m_polygon_angle.value_(m_polygon_angle._value - 360.0 );
+
+ redraw:=true;
+
+ end;
+
+ if m_rotate_pattern._status then
+ begin
+ m_pattern_angle.value_(m_pattern_angle._value - 0.5 );
+
+ if m_pattern_angle._value <= -180.0 then
+ m_pattern_angle.value_(m_pattern_angle._value + 360.0 );
+
+ generate_pattern;
+
+ redraw:=true;
+
+ end;
+
+ if redraw then
+ force_redraw;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ 'The example demonstrates how to use arbitrary images as fill patterns. '#13 +
+ 'This span generator is very simple, so, it doesn''t allow you to apply '#13 +
+ 'arbitrary transformations to the pattern, i.e., it cannot be used as '#13 +
+ 'a texturing tool. But it works pretty fast and can be useful in some applications. '#13#13 +
+ 'How to play with:'#13#13 +
+ 'Use the left mouse button to move the polygon around.' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+VAR
+ app : the_application;
+
+BEGIN
+ app.Construct(pix_format_bgr24 ,flip_y );
+ app.caption_ ('AGG Example. Pattern Filling (F1-Help)' );
+
+ if app.init(640 ,480 ,0 ) then
+ app.run;
+
+ app.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/pattern_perspective.dpr b/src/corelib/render/software/agg-demos/pattern_perspective.dpr
new file mode 100644
index 00000000..98d3d324
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/pattern_perspective.dpr
@@ -0,0 +1,438 @@
+{mac_copy:agg.bmp}
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ pattern_perspective ;
+
+uses
+ Math ,SysUtils ,
+
+ agg_basics ,
+ agg_platform_support ,
+
+ agg_color ,
+ agg_pixfmt ,
+ agg_pixfmt_rgb ,
+
+ agg_ctrl ,
+ agg_rbox_ctrl ,
+
+ agg_rendering_buffer ,
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_rasterizer_scanline_aa ,
+ agg_scanline ,
+ agg_scanline_u ,
+ agg_render_scanlines ,
+
+ agg_path_storage ,
+ agg_conv_transform ,
+ agg_trans_affine ,
+ agg_trans_bilinear ,
+ agg_trans_perspective ,
+ agg_span_pattern ,
+ agg_span_allocator ,
+ agg_image_filters ,
+ agg_span_interpolator_linear ,
+ agg_span_interpolator_trans ,
+ agg_span_image_filter ,
+ agg_span_pattern_filter_rgb ,
+ interactive_polygon_ ,
+ file_utils_ ;
+
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+var
+ g_x1 ,
+ g_y1 ,
+ g_x2 ,
+ g_y2 : double;
+
+ g_rasterizer : rasterizer_scanline_aa;
+ g_scanline : scanline_u8;
+
+type
+ the_application = object(platform_support )
+ m_quad : interactive_polygon;
+ m_trans_type : rbox_ctrl;
+ m_test_flag : boolean;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure on_init; virtual;
+ procedure on_draw; virtual;
+
+ procedure on_mouse_move (x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_up (x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_quad.Construct (4 ,5.0 );
+ m_trans_type.Construct(460 ,5.0 ,420 + 170.0 ,60.0 ,not flip_y_ );
+
+ m_test_flag:=false;
+
+ m_trans_type.text_size_ (8 );
+ m_trans_type.text_thickness_(1 );
+
+ m_trans_type.add_item ('Affine' );
+ m_trans_type.add_item ('Bilinear' );
+ m_trans_type.add_item ('Perspective' );
+ m_trans_type.cur_item_(2 );
+
+ add_ctrl(@m_trans_type );
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_quad.Destruct;
+ m_trans_type.Destruct;
+
+end;
+
+{ ON_INIT }
+procedure the_application.on_init;
+var
+ trans_x1 ,trans_y1 ,trans_x2 ,trans_y2 ,dx ,dy : double;
+
+begin
+ g_x1:=-150;
+ g_y1:=-150;
+ g_x2:=150;
+ g_y2:=150;
+
+ trans_x1:=-200;
+ trans_y1:=-200;
+ trans_x2:=200;
+ trans_y2:=200;
+
+ dx:=_width / 2.0 - (trans_x2 + trans_x1 ) / 2.0;
+ dy:=_height / 2.0 - (trans_y2 + trans_y1 ) / 2.0;
+
+ m_quad.xn_ptr(0 )^:=Floor(trans_x1 + dx );
+ m_quad.yn_ptr(0 )^:=Floor(trans_y1 + dy );
+ m_quad.xn_ptr(1 )^:=Floor(trans_x2 + dx );// - 150;
+ m_quad.yn_ptr(1 )^:=Floor(trans_y1 + dy );// + 150;
+ m_quad.xn_ptr(2 )^:=Floor(trans_x2 + dx );
+ m_quad.yn_ptr(2 )^:=Floor(trans_y2 + dy );
+ m_quad.xn_ptr(3 )^:=Floor(trans_x1 + dx );
+ m_quad.yn_ptr(3 )^:=Floor(trans_y2 + dy );
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+const
+ subdiv_shift = 2;
+
+var
+ pixf ,pixf_pre : pixel_formats;
+
+ rb ,rb_pre : renderer_base;
+
+ rgba : aggclr;
+
+ r : renderer_scanline_aa_solid;
+ sa : span_allocator;
+ fi : image_filter_hanning;
+ sg : span_image_filter_ptr;
+ ri : renderer_scanline_aa;
+ wx ,
+ wy : wrap_mode_reflect_auto_pow2;
+
+ interpolator : span_interpolator_linear;
+ interpsubdiv : span_interpolator_linear_subdiv;
+
+ filter : image_filter;
+
+ tr : trans_affine;
+ trb : trans_bilinear;
+ trp : trans_perspective23;
+
+begin
+ sg:=NIL;
+
+// Initialize structures
+ pixfmt_bgr24 (pixf ,rbuf_window );
+ pixfmt_bgr24_pre(pixf_pre ,rbuf_window );
+
+ rb.Construct (@pixf );
+ rb_pre.Construct(@pixf_pre );
+
+ r.Construct(@rb );
+
+ if not m_test_flag then
+ begin
+ rgba.ConstrDbl(1 ,1 ,1 );
+ rb.clear (@rgba );
+
+ end;
+
+ if m_trans_type._cur_item = 0 then
+ begin
+ // For the affine parallelogram transformations we
+ // calculate the 4-th (implicit) point of the parallelogram
+ m_quad.xn_ptr(3 )^:=m_quad.xn(0 ) + (m_quad.xn(2 ) - m_quad.xn(1 ) );
+ m_quad.yn_ptr(3 )^:=m_quad.yn(0 ) + (m_quad.yn(2 ) - m_quad.yn(1 ) );
+
+ end;
+
+ if not m_test_flag then
+ begin
+ // Render the "quad" tool
+ g_rasterizer.add_path(@m_quad );
+
+ rgba.ConstrDbl (0 ,0.3 ,0.5 ,0.6 );
+ r.color_ (@rgba );
+ render_scanlines(@g_rasterizer ,@g_scanline ,@r );
+
+ // Render the controls
+ render_ctrl(@g_rasterizer ,@g_scanline ,@r ,@m_trans_type );
+
+ end;
+
+// Prepare the polygon to rasterize. Here we need to fill
+// the destination (transformed) polygon.
+ g_rasterizer.clip_box(0 ,0 ,_width ,_height );
+ g_rasterizer.reset;
+ g_rasterizer.move_to_d(m_quad.xn(0 ) ,m_quad.yn(0 ) );
+ g_rasterizer.line_to_d(m_quad.xn(1 ) ,m_quad.yn(1 ) );
+ g_rasterizer.line_to_d(m_quad.xn(2 ) ,m_quad.yn(2 ) );
+ g_rasterizer.line_to_d(m_quad.xn(3 ) ,m_quad.yn(3 ) );
+
+ sa.Construct;
+ fi.Construct;
+ filter.Construct(@fi );
+
+// Render
+ wx.Construct;
+ wy.Construct;
+
+ case m_trans_type._cur_item of
+ 0 :
+ begin
+ // Note that we consruct an affine matrix that transforms
+ // a parallelogram to a rectangle, i.e., it's inverted.
+ // It's actually the same as:
+ // tr(g_x1, g_y1, g_x2, g_y2, m_triangle.polygon());
+ // tr.invert();
+ tr.Construct(parallelo_ptr(m_quad.polygon ) ,g_x1 ,g_y1 ,g_x2 ,g_y2 );
+
+ // Also note that we can use the linear interpolator instead of
+ // arbitrary span_interpolator_trans. It works much faster,
+ // but the transformations must be linear and parellel.
+ interpolator.Construct(@tr );
+
+ sg:=new(
+ span_pattern_filter_rgb_2x2_ptr ,
+ Construct(
+ @sa ,rbuf_img(0 ) ,@interpolator ,@filter ,@wx ,@wy ,bgr_order ) );
+
+ ri.Construct (@rb_pre ,sg );
+ render_scanlines(@g_rasterizer ,@g_scanline ,@ri );
+
+ end;
+
+ 1 :
+ begin
+ trb.Construct(m_quad.polygon ,g_x1 ,g_y1 ,g_x2 ,g_y2 );
+
+ if trb.is_valid then
+ begin
+ interpolator.Construct(@trb );
+
+ sg:=new(
+ span_pattern_filter_rgb_2x2_ptr ,
+ Construct(
+ @sa ,rbuf_img(0 ) ,@interpolator ,@filter ,@wx ,@wy ,bgr_order ) );
+
+ ri.Construct (@rb_pre ,sg );
+ render_scanlines(@g_rasterizer ,@g_scanline ,@ri );
+
+ end;
+
+ end;
+
+ 2 :
+ begin
+ trp.Construct(m_quad.polygon ,g_x1 ,g_y1 ,g_x2 ,g_y2 );
+
+ if trp.is_valid then
+ begin
+ interpsubdiv.Construct(@trp );
+
+ sg:=new(
+ span_pattern_filter_rgb_2x2_ptr ,
+ Construct(
+ @sa ,rbuf_img(0 ) ,@interpsubdiv ,@filter ,@wx ,@wy ,bgr_order ) );
+
+ ri.Construct (@rb_pre ,sg );
+ render_scanlines(@g_rasterizer ,@g_scanline ,@ri );
+
+ end;
+
+ end;
+
+ end;
+
+// Free AGG resources
+ sa.Destruct;
+ filter.Destruct;
+
+ if sg <> NIL then
+ dispose(sg ,Destruct );
+
+end;
+
+{ ON_MOUSE_MOVE }
+procedure the_application.on_mouse_move;
+begin
+ if flags and mouse_left <> 0 then
+ if m_quad.on_mouse_move(x ,y ) then
+ force_redraw();
+
+ if flags and mouse_left = 0 then
+ on_mouse_button_up(x ,y ,flags );
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure the_application.on_mouse_button_down;
+var
+ buf : array[0..99 ] of char;
+
+begin
+ if flags and mouse_left <> 0 then
+ if m_quad.on_mouse_button_down(x ,y ) then
+ force_redraw
+ else
+ begin
+ start_timer;
+
+ m_test_flag:=true;
+
+ on_draw;
+ on_draw;
+ on_draw;
+ on_draw;
+
+ sprintf(@buf[0 ] ,'time=%.3f' ,elapsed_time );
+
+ m_test_flag:=false;
+
+ force_redraw;
+
+ message_(@buf[0 ] );
+
+ end;
+
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+procedure the_application.on_mouse_button_up;
+begin
+ if m_quad.on_mouse_button_up(x ,y ) then
+ force_redraw;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ 'Pattern perspective transformations. Essentially it''s the same as Demo '#13 +
+ '"image_perspective", but working with a repeating pattern. Can be used '#13 +
+ 'for texturing.'#13#13 +
+ 'How to play with:'#13#13 +
+ 'Use the left mouse button to move and distort the pattern.'#13 +
+ 'Click the left mouse outside the pattern to run the performance test.' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+VAR
+ app : the_application;
+ buf : array [0..255 ] of char;
+ ext : string[10 ];
+
+ img_name ,p ,n ,x : shortstring;
+
+BEGIN
+ g_x1:=0;
+ g_y1:=0;
+ g_x2:=0;
+ g_y2:=0;
+
+ g_rasterizer.Construct;
+ g_scanline.Construct;
+
+ app.Construct(pix_format_bgr24 ,flip_y );
+ app.caption_ ('AGG Example. Pattern Perspective Transformations (F1-Help)' );
+
+ img_name:='agg';
+
+{$IFDEF WIN32 }
+ if ParamCount > 0 then
+ begin
+ spread_name(ParamStr(1 ) ,p ,n ,x );
+
+ img_name:=fold_name(p ,n ,'' );
+
+ end;
+
+{$ENDIF }
+
+ if not app.load_img(0 ,img_name ) then
+ begin
+ img_name:=img_name + #0;
+ ext :=app._img_ext + #0;
+
+ if img_name = 'spheres' then
+ begin
+ sprintf(@buf[0 ] ,'File not found: %s' ,ptrcomp(@img_name[1 ] ) );
+ sprintf(@buf[StrLen(@buf ) ] ,'%s. Download http://www.antigrain.com/' ,ptrcomp(@ext[1 ] ) );
+ sprintf(@buf[StrLen(@buf ) ] ,'%s' ,ptrcomp(@img_name[1 ] ) );
+ sprintf(@buf[StrLen(@buf ) ] ,'%s'#13'or copy it from another directory if available.' ,ptrcomp(@ext[1 ] ) );
+
+ end
+ else
+ begin
+ sprintf(@buf[0 ] ,'File not found: %s' ,ptrcomp(@img_name[1 ] ) );
+ sprintf(@buf[StrLen(@buf ) ] ,'%s' ,ptrcomp(@ext[1 ] ) );
+
+ end;
+
+ app.message_(@buf[0 ] );
+
+ end
+ else
+ if app.init(600 ,600 ,window_resize ) then
+ app.run;
+
+ app.Destruct;
+
+ g_rasterizer.Destruct;
+ g_scanline.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/perspective.dpr b/src/corelib/render/software/agg-demos/perspective.dpr
new file mode 100644
index 00000000..33b326f7
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/perspective.dpr
@@ -0,0 +1,416 @@
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ perspective ;
+
+{DEFINE AGG_GRAY8 }
+{$DEFINE AGG_BGR24 }
+{DEFINE AGG_RGB24 }
+{DEFINE AGG_BGRA32 }
+{DEFINE AGG_RGBA32 }
+{DEFINE AGG_ARGB32 }
+{DEFINE AGG_ABGR32 }
+{DEFINE AGG_RGB565 }
+{DEFINE AGG_RGB555 }
+
+uses
+ agg_basics ,
+ agg_platform_support ,
+
+ agg_ctrl ,
+ agg_rbox_ctrl ,
+
+ agg_rasterizer_scanline_aa ,
+ agg_scanline ,
+ agg_scanline_p ,
+
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_render_scanlines ,
+
+ agg_path_storage ,
+ agg_bounding_rect ,
+ agg_trans_affine ,
+ agg_trans_bilinear ,
+ agg_trans_perspective ,
+ agg_conv_transform ,
+ agg_conv_stroke ,
+ agg_conv_clip_polygon ,
+ agg_ellipse ,
+ interactive_polygon_ ,
+ parse_lion_
+
+{$I pixel_formats.inc }
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+var
+ g_rasterizer : rasterizer_scanline_aa;
+ g_scanline : scanline_p8;
+
+ g_path : path_storage;
+ g_colors : array[0..99 ] of aggclr;
+ g_path_idx : array[0..99 ] of unsigned;
+
+ g_npaths : unsigned;
+
+ g_x1 ,g_y1 ,g_x2 ,g_y2 ,
+ g_base_dx ,g_base_dy ,
+ g_angle ,g_scale ,
+ g_skew_x ,g_skew_y : double;
+
+ g_nclick : int;
+
+type
+ the_application = object(platform_support )
+ m_quad : interactive_polygon;
+ m_trans_type : rbox_ctrl;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure on_init; virtual;
+ procedure on_draw; virtual;
+
+ procedure on_mouse_move (x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_up (x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ _PARSE_LION_ }
+procedure _parse_lion_;
+begin
+ g_npaths:=parse_lion(@g_path ,@g_colors ,@g_path_idx );
+
+ bounding_rect(@g_path ,@g_path_idx ,0 ,g_npaths ,@g_x1 ,@g_y1 ,@g_x2 ,@g_y2 );
+
+ g_base_dx:=(g_x2 - g_x1 ) / 2.0;
+ g_base_dy:=(g_y2 - g_y1 ) / 2.0;
+
+ g_path.flip_x(g_x1 ,g_x2 );
+ g_path.flip_y(g_y1 ,g_y2 );
+
+end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_quad.Construct (4 ,5.0 );
+ m_trans_type.Construct(420 ,5.0 ,420 + 130.0 ,55.0 ,not flip_y_ );
+
+ _parse_lion_;
+
+ m_quad.xn_ptr(0 )^:=g_x1;
+ m_quad.yn_ptr(0 )^:=g_y1;
+ m_quad.xn_ptr(1 )^:=g_x2;
+ m_quad.yn_ptr(1 )^:=g_y1;
+ m_quad.xn_ptr(2 )^:=g_x2;
+ m_quad.yn_ptr(2 )^:=g_y2;
+ m_quad.xn_ptr(3 )^:=g_x1;
+ m_quad.yn_ptr(3 )^:=g_y2;
+
+ m_trans_type.add_item ('Bilinear' );
+ m_trans_type.add_item ('Perspective' );
+ m_trans_type.cur_item_(0 );
+
+ add_ctrl(@m_trans_type );
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_quad.Destruct;
+ m_trans_type.Destruct;
+
+end;
+
+{ ON_INIT }
+procedure the_application.on_init;
+var
+ dx ,dy : double;
+
+begin
+ dx:=_width / 2.0 - (m_quad.xn_ptr(1 )^ - m_quad.xn_ptr(0 )^ ) / 2.0;
+ dy:=_height / 2.0 - (m_quad.yn_ptr(2 )^ - m_quad.yn_ptr(0 )^ ) / 2.0;
+
+ m_quad.xn_ptr(0 )^:=m_quad.xn_ptr(0 )^ + dx;
+ m_quad.yn_ptr(0 )^:=m_quad.yn_ptr(0 )^ + dy;
+ m_quad.xn_ptr(1 )^:=m_quad.xn_ptr(1 )^ + dx;
+ m_quad.yn_ptr(1 )^:=m_quad.yn_ptr(1 )^ + dy;
+ m_quad.xn_ptr(2 )^:=m_quad.xn_ptr(2 )^ + dx;
+ m_quad.yn_ptr(2 )^:=m_quad.yn_ptr(2 )^ + dy;
+ m_quad.xn_ptr(3 )^:=m_quad.xn_ptr(3 )^ + dx;
+ m_quad.yn_ptr(3 )^:=m_quad.yn_ptr(3 )^ + dy;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ pixf : pixel_formats;
+
+ rb : renderer_base;
+ r : renderer_scanline_aa_solid;
+
+ rgba : aggclr;
+
+ tr_bi : trans_bilinear;
+ tr_pe ,
+ tr2 : trans_perspective23;
+
+ trans : conv_transform;
+
+ ell : ellipse;
+ ell_stroke : conv_stroke;
+ trans_ell ,
+ trans_ell_stroke : conv_transform;
+
+ x ,y : double;
+
+begin
+// Initialize structures
+ pixfmt(pixf ,rbuf_window );
+
+ rb.Construct(@pixf );
+ r.Construct (@rb );
+
+ rgba.ConstrDbl(1 ,1 ,1 );
+ rb.clear (@rgba );
+
+ g_rasterizer.clip_box(0 ,0 ,_width ,_height );
+
+// Perspective rendering
+ if m_trans_type._cur_item = 0 then
+ begin
+ tr_bi.Construct(g_x1 ,g_y1 ,g_x2 ,g_y2 ,m_quad.polygon );
+
+ if tr_bi.is_valid then
+ begin
+ // Render transformed lion
+ trans.Construct (@g_path ,@tr_bi );
+ render_all_paths(@g_rasterizer ,@g_scanline ,@r ,@trans ,@g_colors ,@g_path_idx ,g_npaths );
+
+ // Render transformed ellipse
+ ell.Construct(
+ (g_x1 + g_x2 ) * 0.5 ,(g_y1 + g_y2 ) * 0.5 ,
+ (g_x2 - g_x1 ) * 0.5 ,(g_y2 - g_y1 ) * 0.5 ,200 );
+
+ ell_stroke.Construct(@ell );
+ ell_stroke.width_ (3.0 );
+ trans_ell.Construct (@ell ,@tr_bi );
+
+ trans_ell_stroke.Construct(@ell_stroke ,@tr_bi );
+
+ g_rasterizer.add_path(@trans_ell );
+
+ rgba.ConstrDbl(0.5 ,0.3 ,0.0 ,0.3 );
+ r.color_ (@rgba );
+
+ render_scanlines(@g_rasterizer ,@g_scanline ,@r );
+
+ g_rasterizer.add_path(@trans_ell_stroke );
+
+ rgba.ConstrDbl(0.0 ,0.3 ,0.2 ,1.0 );
+ r.color_ (@rgba );
+
+ render_scanlines(@g_rasterizer ,@g_scanline ,@r );
+
+ // Free
+ ell_stroke.Destruct;
+
+ end;
+
+ end
+ else
+ begin
+ tr_pe.Construct(g_x1 ,g_y1 ,g_x2 ,g_y2 ,m_quad.polygon );
+
+ if tr_pe.is_valid then
+ begin
+ // Render transformed lion
+ trans.Construct(@g_path ,@tr_pe );
+
+ render_all_paths(@g_rasterizer ,@g_scanline ,@r ,@trans ,@g_colors ,@g_path_idx ,g_npaths );
+
+ // Render transformed ellipse
+ ell.Construct(
+ (g_x1 + g_x2 ) * 0.5 ,(g_y1 + g_y2 ) * 0.5 ,
+ (g_x2 - g_x1 ) * 0.5 ,(g_y2 - g_y1 ) * 0.5 ,200 );
+
+ ell_stroke.Construct(@ell );
+ ell_stroke.width_ (3.0 );
+
+ trans_ell.Construct (@ell ,@tr_pe );
+ trans_ell_stroke.Construct(@ell_stroke ,@tr_pe );
+
+ g_rasterizer.add_path(@trans_ell );
+
+ rgba.ConstrDbl(0.5 ,0.3 ,0.0 ,0.3 );
+ r.color_ (@rgba );
+
+ render_scanlines(@g_rasterizer ,@g_scanline ,@r );
+
+ g_rasterizer.add_path(@trans_ell_stroke );
+
+ rgba.ConstrDbl(0.0 ,0.3 ,0.2 ,1.0 );
+ r.color_ (@rgba );
+
+ render_scanlines(@g_rasterizer ,@g_scanline ,@r );
+
+ // Free
+ ell_stroke.Destruct;
+
+ // Testing the reverse transformations
+ { tr2.Construct(m_quad.polygon ,g_x1 ,g_y1 ,g_x2 ,g_y2 );
+
+ if tr2.is_valid then
+ begin
+ x:=m_quad.xn_ptr(0 )^;
+ y:=m_quad.yn_ptr(0 )^;
+
+ tr2.transform (@tr2 ,@x ,@y );
+ g_rasterizer.move_to_d(x ,y );
+
+ x:=m_quad.xn_ptr(1 )^;
+ y:=m_quad.yn_ptr(1 )^;
+
+ tr2.transform (@tr2 ,@x ,@y );
+ g_rasterizer.line_to_d(x ,y );
+
+ x:=m_quad.xn_ptr(2 )^;
+ y:=m_quad.yn_ptr(2 )^;
+
+ tr2.transform (@tr2 ,@x ,@y );
+ g_rasterizer.line_to_d(x ,y );
+
+ x:=m_quad.xn_ptr(3 )^;
+ y:=m_quad.yn_ptr(3 )^;
+
+ tr2.transform (@tr2 ,@x ,@y );
+ g_rasterizer.line_to_d(x ,y );
+
+ rgba.ConstrDbl(0.5 ,0.0 ,0.0 ,0.5 );
+ r.color_ (@rgba );
+
+ render_scanlines(@g_rasterizer ,@g_scanline ,@r );
+
+ end
+ else
+ message_('Singularity...' );{}
+
+ end;
+
+ end;
+
+// Render the "quad" tool and controls
+ g_rasterizer.add_path(@m_quad );
+
+ rgba.ConstrDbl(0 ,0.3 ,0.5 ,0.6 );
+ r.color_ (@rgba );
+
+ render_scanlines(@g_rasterizer ,@g_scanline ,@r );
+ render_ctrl (@g_rasterizer ,@g_scanline ,@r ,@m_trans_type );
+
+end;
+
+{ ON_MOUSE_MOVE }
+procedure the_application.on_mouse_move;
+begin
+ if flags and mouse_left <> 0 then
+ if m_quad.on_mouse_move(x ,y ) then
+ force_redraw;
+
+ if flags and mouse_left = 0 then
+ on_mouse_button_up(x ,y ,flags );
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure the_application.on_mouse_button_down;
+begin
+ if flags and mouse_left <> 0 then
+ if m_quad.on_mouse_button_down(x ,y ) then
+ force_redraw;
+
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+procedure the_application.on_mouse_button_up;
+begin
+ if m_quad.on_mouse_button_up(x ,y ) then
+ force_redraw;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ 'Perspective and bilinear transformations. In general, these classes can transform '#13 +
+ 'an arbitrary quadrangle to another arbitrary quadrangle (with some restrictions). '#13 +
+ 'The example demonstrates how to transform a rectangle to a quadrangle defined by '#13 +
+ '4 vertices. Note, that the perspective transformations don''t work correctly if '#13 +
+ 'the destination quadrangle is concave. Bilinear thansformations give a different '#13 +
+ 'result, but remain valid with any shape of the destination quadrangle.'#13#13 +
+ 'How to play with:'#13#13 +
+ 'You can drag the 4 corners of the quadrangle, as well as its boundaries.' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+VAR
+ app : the_application;
+
+BEGIN
+// Rendering
+ g_rasterizer.Construct;
+ g_scanline.Construct;
+ g_path.Construct;
+
+ g_npaths:=0;
+
+ g_x1:=0;
+ g_y1:=0;
+ g_x2:=0;
+ g_y2:=0;
+
+ g_base_dx:=0;
+ g_base_dy:=0;
+
+ g_angle:=0;
+ g_scale:=1.0;
+
+ g_skew_x:=0;
+ g_skew_y:=0;
+ g_nclick:=0;
+
+// App
+ app.Construct(pix_format ,flip_y );
+ app.caption_ ('AGG Example. Perspective Transformations (F1-Help)' );
+
+ if app.init(600 ,600 ,window_resize ) then
+ app.run;
+
+ app.Destruct;
+
+// Free
+ g_rasterizer.Destruct;
+ g_scanline.Destruct;
+ g_path.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/polymorphic_renderer.dpr b/src/corelib/render/software/agg-demos/polymorphic_renderer.dpr
new file mode 100644
index 00000000..1443f1ef
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/polymorphic_renderer.dpr
@@ -0,0 +1,249 @@
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ polymorphic_renderer ;
+
+uses
+ agg_basics ,
+ agg_platform_support ,
+ agg_color ,
+ agg_pixfmt ,
+ agg_pixfmt_rgb ,
+ agg_pixfmt_rgb_packed ,
+ agg_pixfmt_rgba ,
+ agg_rendering_buffer ,
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_rasterizer_scanline_aa ,
+ agg_scanline_p ,
+ agg_render_scanlines ,
+ agg_path_storage ;
+
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+ //pix_fmt = pix_format_rgb555;
+ //pix_fmt = pix_format_rgb565;
+ //pix_fmt = pix_format_rgb24;
+ pix_fmt = pix_format_bgr24;
+ //pix_fmt = pix_format_rgba32;
+ //pix_fmt = pix_format_argb32;
+ //pix_fmt = pix_format_abgr32;
+ //pix_fmt = pix_format_bgra32;
+
+type
+ polymorphic_renderer_solid_rgba8_base = object
+ destructor Destruct; virtual;
+
+ procedure clear(c : aggclr_ptr ); virtual; abstract;
+ procedure color(c : aggclr_ptr ); virtual; abstract;
+
+ end;
+
+ polymorphic_renderer_solid_rgba8_adaptor_ptr = ^polymorphic_renderer_solid_rgba8_adaptor;
+ polymorphic_renderer_solid_rgba8_adaptor = object(polymorphic_renderer_solid_rgba8_base )
+ m_pixfmt : pixel_formats;
+ m_ren_base : renderer_base;
+ m_ren : renderer_scanline_aa_solid;
+
+ constructor Construct(PixFmt : pix_format_e; rbuf : rendering_buffer_ptr );
+
+ procedure clear(c : aggclr_ptr ); virtual;
+ procedure color(c : aggclr_ptr ); virtual;
+
+ function RendererBase : renderer_scanline_aa_solid_ptr;
+
+ end;
+
+ the_application = object(platform_support )
+ m_x ,
+ m_y : array[0..2 ] of double;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure on_draw; virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ DESTRUCT }
+destructor polymorphic_renderer_solid_rgba8_base.Destruct;
+begin
+end;
+
+{ CONSTRUCT }
+constructor polymorphic_renderer_solid_rgba8_adaptor.Construct;
+begin
+ pixfmt_undefined(m_pixfmt );
+
+ case PixFmt of
+ pix_format_rgb555 :
+ pixfmt_rgb555(m_pixfmt ,rbuf );
+
+ pix_format_rgb565 :
+ pixfmt_rgb565(m_pixfmt ,rbuf );
+
+ pix_format_rgb24 :
+ pixfmt_rgb24(m_pixfmt ,rbuf );
+
+ pix_format_bgr24 :
+ pixfmt_bgr24(m_pixfmt ,rbuf );
+
+ pix_format_rgba32 :
+ pixfmt_rgba32(m_pixfmt ,rbuf );
+
+ pix_format_argb32 :
+ pixfmt_argb32(m_pixfmt ,rbuf );
+
+ pix_format_abgr32 :
+ pixfmt_abgr32(m_pixfmt ,rbuf );
+
+ pix_format_bgra32 :
+ pixfmt_bgra32(m_pixfmt ,rbuf );
+
+ end;
+
+ if m_pixfmt.m_rbuf <> NIL then
+ begin
+ m_ren_base.Construct(@m_pixfmt );
+ m_ren.Construct (@m_ren_base );
+
+ end;
+
+end;
+
+{ CLEAR }
+procedure polymorphic_renderer_solid_rgba8_adaptor.clear;
+begin
+ if m_pixfmt.m_rbuf <> NIL then
+ m_ren_base.clear(c );
+
+end;
+
+{ COLOR }
+procedure polymorphic_renderer_solid_rgba8_adaptor.color;
+begin
+ if m_pixfmt.m_rbuf <> NIL then
+ m_ren.color_(c );
+
+end;
+
+{ RENDERERBASE }
+function polymorphic_renderer_solid_rgba8_adaptor.RendererBase;
+begin
+ if m_pixfmt.m_rbuf <> NIL then
+ result:=@m_ren
+ else
+ result:=NIL;
+
+end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_x[0 ]:=100; m_y[0 ]:=60;
+ m_x[1 ]:=369; m_y[1 ]:=170;
+ m_x[2 ]:=143; m_y[2 ]:=310;
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ ren : polymorphic_renderer_solid_rgba8_adaptor_ptr;
+ ras : rasterizer_scanline_aa;
+ sl : scanline_p8;
+
+ rgba : aggclr;
+ path : path_storage;
+
+begin
+// Create Path
+ path.Construct;
+
+ path.move_to(m_x[0 ] ,m_y[0 ] );
+ path.line_to(m_x[1 ] ,m_y[1 ] );
+ path.line_to(m_x[2 ] ,m_y[2 ] );
+
+ path.close_polygon;
+
+// Rasterizer, scanlines & Polymorphic renderer class factory
+ new(ren ,Construct(pix_fmt ,rbuf_window ) );
+
+ ras.Construct;
+ sl.Construct;
+
+// Render
+ if (ren <> NIL ) and
+ (ren.RendererBase <> NIL ) then
+ begin
+ rgba.ConstrInt(255 ,255 ,255 );
+ ren.clear (@rgba );
+
+ rgba.ConstrInt(80 ,30 ,20 );
+ ren.color (@rgba );
+
+ ras.add_path(@path );
+
+ render_scanlines(@ras ,@sl ,ren.RendererBase );
+
+ end;
+
+// Free AGG resources
+ ras.Destruct;
+ sl.Destruct;
+
+ dispose(ren ,Destruct );
+
+ path.Destruct;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ 'There''s nothing looking effective. AGG has renderers for different pixel formats '#13 +
+ 'in memory, particularly, for different byte order (RGB or BGR). But the renderers '#13 +
+ 'are class templates (only C++), where byte order is defined at the compile time. '#13 +
+ 'It''s done for the sake of performance and in most cases it fits all your needs. '#13 +
+ 'Still, if you need to switch between different pixel formats dynamically, you can '#13 +
+ 'write a simple polymorphic class wrapper, like the one in this example.'#13#13 +
+ 'How to play with:'#13#13 +
+ 'To use another pixel format for rendering, comment/uncomment the pix_fmt '#13 +
+ 'constant in the demo source code and recompile it.' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+VAR
+ app : the_application;
+
+BEGIN
+ app.Construct(pix_fmt ,flip_y );
+ app.caption_ ('AGG Example. Polymorphic Renderers (F1-Help)' );
+
+ if app.init(400 ,330 ,window_resize ) then
+ app.run;
+
+ app.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/ppm/1.ppm b/src/corelib/render/software/agg-demos/ppm/1.ppm
new file mode 100755
index 00000000..79947657
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/ppm/1.ppm
Binary files differ
diff --git a/src/corelib/render/software/agg-demos/ppm/2.ppm b/src/corelib/render/software/agg-demos/ppm/2.ppm
new file mode 100755
index 00000000..3bfd2ce2
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/ppm/2.ppm
Binary files differ
diff --git a/src/corelib/render/software/agg-demos/ppm/3.ppm b/src/corelib/render/software/agg-demos/ppm/3.ppm
new file mode 100755
index 00000000..acff54f8
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/ppm/3.ppm
Binary files differ
diff --git a/src/corelib/render/software/agg-demos/ppm/4.ppm b/src/corelib/render/software/agg-demos/ppm/4.ppm
new file mode 100755
index 00000000..0c643fb2
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/ppm/4.ppm
@@ -0,0 +1,5 @@
+P6
+# Created by IrfanView
+21 15
+255
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøøÿÛÛÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøùÿÐÓÿýýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÙÙÿ©ªÿééÿÿÿÿÿÿÿýýÿûûÿÿÿÿ×Úÿ•œÿÝßÿÿÿÿññÿ®«ÿïïÿúüÿÄÖÿª¾ÿÿÿÿÿÿÿÿÿÿááÿ°±ÿÚÜÿòòÿÁÁÿÆÈÿãåÿÿÿÿáãÿ•œÿîïÿóôÿœ¡ÿbbÿÄÂÿËÜÿ}ŒÿptÿññÿÿÿÿÿÿÿúúÿÎÏÿÜßÿßßÿ²²ÿ½¾ÿââÿÿÿÿùùÿƒ€ÿœ‘ÿÔÖÿ…ÿciÿÍËÿïôÿª©ÿ®«ÿ÷öÿÿÿÿÿÿÿûûÿÿÿÿêëÿùùÿòðÿ·¯ÿ –ÿòòÿôõÿÆÂÿËÌÿö÷ÿ²ÆÿÊÍÿçåÿÿÿÿøúÿØäÿøúÿÿÿÿììÿ¹¹ÿüüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿØÚÿ”œÿÖÙÿÜßÿùùÿ¾·ÿ–‹ÿŸ•ÿççÿèíÿ¯ÈÿÀÔÿÀ¾ÿˆ„ÿ©©ÿææÿíîÿõöÿÿÿÿßÞÿ˜“ÿššÿpxÿÈÌÿâéÿÝèÿø÷ÿlgÿkjÿ”šÿ›¢ÿÚæÿèîÿ˜”ÿˆ„ÿÿÿÿÿÿÿíîÿÜßÿëéÿª¢ÿ¤¡ÿ¬¬ÿØØÿûüÿ¸ÎÿÅÊÿåãÿ««ÿtuÿ•œÿÄÈÿø÷ÿø÷ÿÿÿÿÿÿÿÿÿÿòòÿóóÿóôÿÅÄÿýýÿýýÿ·±ÿÖÕÿÛßÿßâÿœ‘ÿ†ŒÿàèÿöùÿÁÒÿëðÿúúÿ©§ÿËÉÿÿÿÿÿÿÿÕÕÿÍÍÿÿÿÿßßÿÆÈÿÆÂÿœ‘ÿÏÊÿÒÕÿº¿ÿÓÎÿ¦²ÿ²»ÿóöÿŸµÿoyÿïôÿüüÿÛÚÿïïÿÿÿÿïïÿÕÕÿÿÿÿÿÿÿïïÿ¥žÿœ‘ÿÐËÿñòÿÄÈÿÿÿÿäìÿòóÿøùÿ½Ðÿq}ÿÇÕÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüÿÿÿÿÿÿÿÿÿÿðîÿ´¬ÿïíÿÿÿÿýýÿÿÿÿÿÿÿÿÿÿÿÿÿúüÿêîÿ÷øÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/ppm/5.ppm b/src/corelib/render/software/agg-demos/ppm/5.ppm
new file mode 100755
index 00000000..59658c71
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/ppm/5.ppm
Binary files differ
diff --git a/src/corelib/render/software/agg-demos/ppm/6.ppm b/src/corelib/render/software/agg-demos/ppm/6.ppm
new file mode 100755
index 00000000..73c0b9b6
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/ppm/6.ppm
Binary files differ
diff --git a/src/corelib/render/software/agg-demos/ppm/7.ppm b/src/corelib/render/software/agg-demos/ppm/7.ppm
new file mode 100755
index 00000000..f1b97c94
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/ppm/7.ppm
Binary files differ
diff --git a/src/corelib/render/software/agg-demos/ppm/8.ppm b/src/corelib/render/software/agg-demos/ppm/8.ppm
new file mode 100755
index 00000000..23183e38
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/ppm/8.ppm
@@ -0,0 +1,5 @@
+P6
+# Created by IrfanView
+26 15
+255
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛ¸¦õìèÒ¥Ž¹rO¥Jš5š5š5£HµkFÓ§‘ÿÿÿÿÿÿ×®šõìçÍ›‚¶mI¢Eš5š5š5¦M ·pLÚµ£ÿÿÿÿÿÿ«V,Û¸¦< š5š5š5š5š5š5š5½|[ÿÿÿúõó Aß¿¯š5š5š5š5š5š5š5š5É”yÿÿÿóçáš5ÈjÅŠmš5š5š5š5š5š5š5Û¸¦ÿÿÿÒ¥Žš5Ï ˆ·pLš5š5š5š5š5š5š5çÏÃÿÿÿÅŠmš5¦M òåÞ›7š5š5š5š5š5›7øñíýúù¦M š5²e>æÍÀš5š5š5š5š5š5¡Cþýü÷îêŸ>š5š5íÛÒ¼yXš5š5š5š5š5²e>ÿÿÿÚµ£š5š5›7øñí±b;š5š5š5š5š5½|[ÿÿÿÍ›‚š5š5š5Ï ˆìÙÏš5š5š5š5š5Ï ˆÿÿÿ«V,š5š5š5Û¸¦ß¿¯š5š5š5š5š5Û¸¦ûøö¢Eš5š5š5²e>ÿÿÿµkFš5š5š5š5íÛÒáĵš5š5š5š5½|[þýü©T)š5š5š5›7øñíÔ©”š5š5š5š5›7øñíäÉ»š5š5š5¥Jÿÿÿ³gAš5š5š5š5¡Cþýü×®šš5š5š5²e>þýü§O#š5š5š5š5š5Û¸¦ÿÿÿ­[2š5š5½|[èÑÆš5š5š5š5š5š5çÏÃýúù£Hš5š5Ï ˆÝº©š5š5š5š5š5š5½|[ÿÿÿݺ©š5š5Û¸¦ºuRš5š5š5š5š5š5É”yÿÿÿÏ ˆš5š5íÛÒ­[2š5š5š5š5š5š5¡Cþýüþýü§O#›7éÔÉ›7š5š5š5š5š5š5¬Y/ÿÿÿùóðŸ>¢EäÉ»š5š5š5š5š5š5š5š5çÏÃÿÿÿÔ©”²e>Â…gš5š5š5š5š5š5š5š5÷îêÿÿÿÈ‘v½|[µkFš5š5š5š5š5š5¬Y/½|[ìÙÏÿÿÿûøöرäɻ…g­[2š5š5š5š5®]5Â…gôéäÿÿÿôéäÞ½¬Þ½¬¿~^«V,š5š5ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/ppm/9.ppm b/src/corelib/render/software/agg-demos/ppm/9.ppm
new file mode 100755
index 00000000..dfd9ddca
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/ppm/9.ppm
@@ -0,0 +1,5 @@
+P6
+# Created by IrfanView
+41 25
+255
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþýÿýúÿÿÿÿýûÿþýÿÿÿÿÿÿÿþýÿýûÿÿÿÿÿÿÿýüÿýúÿÿÿÿÿÿÿþüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìÚÿüúÿÿÿÿùôÿñâÿõêÿéÓÿôéÿÿÿÿÿÿÿõêÿäÈÿÿÿÿÿÿÿïáÿàÆÿôéÿÿÿÿðáÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿß¿ÿçÐÿÿÿÿÿÿÿسÿåËÿÌœÿêÓÿøðÿÿÿÿúóÿÇŠÿúõÿÿÿÿÞÁÿÌ¢ÿÛ¹ÿþýÿÞÀÿþýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿáÄÿΞÿûøÿÿÿÿÉ•ÿѤÿÈ“ÿÜ»ÿݸÿû÷ÿòçÿ·jÿãÅÿøñÿßÂÿ¸|ÿËÿæÏÿßÁÿìÚÿýûÿû÷ÿÿÿÿÿÿÿÿÿÿ÷ïÿýûÿÿÿÿþýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿíÚÿÀƒÿáÅÿÿÿÿÒ¦ÿ²gÿÖ¯ÿ¼|ÿÊÿÖ¬ÿðâÿ´cÿ¿{ÿçÒÿÙµÿ«bÿ¥SÿÌÿæÏÿÌ›ÿâÂÿþýÿÿÿÿüùÿàÆÿâÆÿÿÿÿê×ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿû÷ÿîÜÿþüÿÿÿÿÿÿÿøòÿºwÿ¼|ÿõëÿݼÿœ>ÿÚ¶ÿ¦Pÿ³cÿ½zÿÿÿÿ·iÿ¨MÿÖ©ÿ²iÿ¡Oÿ¡Nÿ¸vÿÛ·ÿ¤JÿáÂÿÿÿÿöîÿÃÿ‰ÿöíÿÛºÿóçÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿùóÿТÿÑ¥ÿðâÿÿÿÿÆŒÿ±eÿÆÿÎœÿ›;ÿ²jÿ‘,ÿ›7ÿ¼uÿðãÿ¨Mÿ¢>ÿ¬Vÿ­`ÿš@ÿ¢Sÿ«]ÿ¨Pÿ¡DÿÞ¾ÿîÞÿ°lÿ¬bÿÖ¯ÿݾÿسÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿîÞÿåËÿ÷îÿû÷ÿê×ÿèÒÿʘÿ¯dÿ³kÿºxÿ¬[ÿ·mÿºpÿ—,ÿ›8ÿ(ÿ†ÿ’.ÿDÿ“(ÿ—,ÿš3ÿ­[ÿ¥TÿžKÿ“/ÿœ;ÿ®bÿµpÿ¦Zÿ¡NÿºzÿÖ¯ÿÁ‡ÿøòÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿíÛÿÄŠÿ´kÿÉÿÈ“ÿ¼|ÿ¬Zÿ™5ÿ“(ÿ“%ÿš6ÿ³hÿ™/ÿ–&ÿ–)ÿ—,ÿŒ ÿˆÿ‰ÿˆÿŠÿ”,ÿEÿŠ!ÿŒ!ÿŸEÿ¢Jÿ‘-ÿ–8ÿ©ZÿÁ†ÿ¾ÿàÃÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìÚÿ¾ÿªYÿ©Wÿ£Kÿš9ÿŒÿŠÿŒÿÿÿÿ–'ÿ—(ÿ—'ÿ ÿ‡ÿˆÿŠÿˆÿ†ÿ…ÿ‡ÿŽ%ÿ$ÿŠ ÿ”1ÿ¯eÿ¶rÿÅÿüùÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿëÖÿ¾~ÿ«Zÿ¨VÿžAÿŠÿ‰ÿŠÿŒÿŽÿÿ“#ÿ–&ÿ—(ÿ”%ÿ‰ÿ†ÿ‰ÿ‰ÿ‡ÿ‡ÿˆÿ‰ÿ"ÿ–4ÿ¨Vÿ¾ÿèÓÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþüÿΛÿ«[ÿ™6ÿ’(ÿ‰ÿŠÿŠÿ‹ÿÿÿ•%ÿ–'ÿÿŠÿˆÿ„ÿˆÿŠÿˆÿˆÿ‹ÿ’+ÿŸEÿ¶pÿË™ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøòÿÇÿ£Hÿ•,ÿ‘&ÿŠÿ‹ ÿŠÿŒÿÿ‘ÿ”#ÿÿ‰ÿ‡ÿ„ÿ‚ÿ†ÿ‡ÿ†ÿ†ÿ‡ÿŠÿ&ÿ˜5ÿ£KÿµpÿÅŽÿ×±ÿçÐÿéÔÿéÔÿìÚÿùóÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿåÊÿ­[ÿš6ÿ”+ÿ‘'ÿ#ÿ‹ ÿŒÿÿÿ’!ÿÿŠÿˆÿ†ÿ…ÿ‚ÿ†ÿ†ÿ…ÿ…ÿ…ÿ†ÿ†ÿ‡ÿˆÿ‰ÿ"ÿ&ÿ’,ÿ™:ÿ¤OÿºyÿÑ¥ÿæÎÿõìÿÿÿÿÿÿÿÿÿÿòåÿÇÿ©Tÿ¦Nÿ©WÿœAÿ’.ÿ&ÿÿÿÿÿŠÿŠÿ‰ÿ‰ÿ‡ÿˆÿ‡ÿ†ÿ†ÿ…ÿ‰ÿ†ÿ†ÿ†ÿˆÿ‰ÿŒ"ÿ•4ÿ¥Sÿº}ÿÔ®ÿæÑÿþüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷îÿСÿĉÿÁ…ÿ·tÿ©Yÿ°gÿªYÿ–.ÿÿ‘ÿÿ$ÿ ÿŽ"ÿŒÿ‹ÿ"ÿŒÿ‹ÿŠ!ÿ‰ ÿ†ÿ*ÿŠÿŽ$ÿ•2ÿ¡Gÿ³iÿëØÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿöìÿ×®ÿâÅÿÓ¨ÿÍžÿΠÿíÜÿÛ·ÿ¦Lÿ™2ÿž8ÿ¡Bÿ’)ÿ(ÿ#ÿ!ÿ"ÿ–.ÿ˜/ÿ’&ÿŽ ÿ“2ÿ’/ÿ%ÿ‘+ÿ'ÿ‘-ÿªZÿ¡Jÿ¥QÿÄÿþüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿóçÿöíÿæÎÿõìÿöíÿÿÿÿñäÿÓ¨ÿ¼xÿ¦Nÿ¨QÿÊ•ÿš=ÿ›>ÿ“&ÿ•(ÿ—.ÿŸ@ÿ«Qÿ—1ÿ‹ÿ”3ÿ¤Mÿ—5ÿ–2ÿ#ÿ¤Sÿ±lÿ°hÿ©Yÿ©YÿÜ»ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿéÔÿÀÿ¦NÿÂ…ÿײÿ§WÿÊÿš5ÿ”'ÿ¤Iÿ®\ÿ¢Dÿ¡Gÿ›?ÿ‘-ÿ¦Rÿ¨Tÿ¢Hÿ%ÿª_ÿ¼…ÿÃŽÿ¾„ÿ±hÿ°fÿòæÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿéÔÿ¾}ÿ­[ÿßÀÿÓªÿ°iÿ÷ðÿ¸pÿ—,ÿ¯]ÿÀ~ÿ³gÿ’,ÿÒªÿ¢Oÿ?ÿ»zÿ«Xÿ Fÿ§UÿÈ™ÿÕ²ÿÊœÿÖ³ÿ¸vÿÁ†ÿþüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿéÔÿÅŠÿÉÿíÜÿÌÿÃÿÿÿÿÈÿ¯]ÿ®\ÿÉŽÿÕ«ÿ?ÿ¾†ÿÝÁÿ«]ÿ»yÿ´lÿ¹qÿΠÿÆŽÿͤÿñäÿÒªÿîÝÿÆÿÚ¸ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿéÔÿË—ÿײÿùóÿÈ•ÿãÊÿÿÿÿĉÿÌ—ÿéÓÿÀzÿàÃÿÌ™ÿ¼ƒÿìÛÿЦÿТÿ½}ÿãÇÿéÏÿÖ°ÿêÕÿÝÁÿþýÿãËÿýüÿÛ¹ÿõìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿæÌÿæÌÿáÅÿÿÿÿФÿýûÿÿÿÿÓ¦ÿäÈÿÿÿÿÚ³ÿݽÿëÖÿåÐÿôëÿàÅÿøðÿÈ”ÿû÷ÿýûÿúöÿîßÿüúÿ÷ðÿÿÿÿüùÿÿÿÿúôÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿïàÿýúÿñãÿÿÿÿéÔÿÿÿÿÿÿÿîÝÿòãÿÿÿÿõêÿðàÿû÷ÿøñÿÿÿÿñäÿÿÿÿåÍÿÿÿÿÿÿÿÿÿÿþýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþýÿÿÿÿýûÿÿÿÿþýÿÿÿÿÿÿÿýúÿþýÿÿÿÿÿÿÿþýÿÿÿÿÿÿÿÿÿÿþýÿÿÿÿüùÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/ppm/agg.ppm b/src/corelib/render/software/agg-demos/ppm/agg.ppm
new file mode 100755
index 00000000..90f1c8f5
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/ppm/agg.ppm
Binary files differ
diff --git a/src/corelib/render/software/agg-demos/ppm/compositing.ppm b/src/corelib/render/software/agg-demos/ppm/compositing.ppm
new file mode 100755
index 00000000..c1b89589
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/ppm/compositing.ppm
@@ -0,0 +1,101 @@
+P6
+# Created by IrfanView
+149 143
+255
+kifTRPDCB431
+=;9zwu³°­ÜÙÕàÜؼ¸³smi.("VPH¨¡™ÕÍĬ¥›WPF1*pi^¾·¬º³¨icXTNCª¥šæáÖ«¦c_U‡‚z˜“ŒPKCD=3ƒznuhXYH6“€iœ†ozdJ¡‰n¥Œqy\¬—x¡ŽmŸŽm©–w£qàÙͨ•tª—v«˜w¬™x®›z±ž}´¡€¶¢¶¢µ¢‚´¡³ €±Ÿ²Ÿ³ €´ €³ ´ ´ €´ €´ ŸŽtš‰oœŒp£’w¥”z¤•{¢’y¡‘yŸwŽvžwŸ‘y¡“|¡”}¤˜¥šƒ¤›ƒ¢š‚¡™‚¤…¤ ‰¡£ ¥‘Ÿ§” ª—¬˜—©˜’¥•Œ¡‘‡„™Œ—Š€–‡€–‡˜‰ƒš‹˜Š}“…r‰{w‹vŠ}fxlxŠ~w‡}[ias‚xƒˆZe\^i`‹•‹t|sHNDlqfœ –x|rBK?XaT—¢•ž©ere7F8VfXœ¬ž¿ÏÀŸ° aqc7G:HTJƒŽ…ÁËÂçîçàæàÀž•\b\8>8&,&UROMKI=;9%$#MKI‚|»·´ãßÛßÛ×®ª¥fa\("%]WO°©¡ÖÏƤ“QJ@71&|ukÊĺÁ¼²zukpmcÅÁ¸ÑÌÅtpi@;4ysj‰}PH:SH9šŒzŠxdnYC¦‘x¢r‚mSª•{¥v“d¬›|Ÿp¡p«™yª—vâÛЯœ{°|°{¯œ{°|±ž}³Ÿ~µ¡µ¡´¡€´¡µ¢‚´¡´¡€´¡€´¡€µ¡€µ¡€µ¡€µ¡µ¡ŸŽt›ŠožŽs¦–{§—}§—}¨˜~¨™¥–}¡’y¡’y£”|¤–~§™ª†ªŸ‡ªŸˆ© ˆ¨ ‰§ ‰§¢‹¥¤£¤¢¥’Ÿ¥’¥“š¥••¢“‘ ’Œ†™Œ‚—Š—‡}–†€™‰€š‹™‹|–ˆtŽv‚x’ƒd~ptŒ€xŽ‚Yndp‚y‚’‰Yi_\j`ˆ”‹yƒxHPFfmb˜“€…{BJ?T]PšŽ£¯£ivi8F9P_Q“¤•¾Î¿¨¸ªevh<L>CPDw„y³¾µÞçÞâêâÈÏÈ“™“`ga=D>%,&NKH752(&#  /-+\ZW–“ÎËÇèäàØÔÏ¡œ˜TNI#,& pjcÁ»³ÒÌ×KF<GB8”…áÝÔÏËÄ€xkg_ œ•§¢›ZTM:2*„{n—Ž|\O=rbN±ŸŠ’gzfM®›¤‘wŒz`µ¥‹¦–|”„j®ŸŸr¤“s®|®›xãÜаœ{¯œz­šy¬™x­šx®›z¯œ{²ž{³Ÿ}µ¡€µ¢·¤ƒ¹¦…»§†º¦…¸¥„¹¥„¹¤ƒ¸¤‚¸¤ƒ·£‚¡sœŒp¢’w©™~«›€¬œ‚¯Ÿ„°¡…­žƒ©š¨˜~¨™€«œ„«†­Ÿˆ¬ ˆ¯¤Œ°¦®¥Ž¬£©¢Œ¥¡Œ£¡¡ ŸŸŒœžšŸ˜Ÿ•Ÿ‘’Ÿ‘‰˜‹ƒ•ˆ•…|”ƒ}•„~—‡~™Š}š‹v’…v”†x–ˆeƒur‚z”Š\sim‚yƒ—]oeXh^†“‰}ˆKTJag^•›‘…ŒHPEISFŒ–Š£®¢s€s?M?HWI†–ˆ½Í¾«¼­rƒuAQC=K?gth§³©ÖàÖäíäÊÒÊ¡ª¢wwHPI*2+2/+*'$!
+ !GDBzwt«¨¥ÛØÔæâÞÊÅÁˆ‚}HB=;5.„~wÏÊÁÏÊÁ‹†}HC:[WNº¶®óðè±­¦OJENIB˜“‹›”‹LC7I>/¦–ƒlZE…r\½©’’g€mT·¦‹¤’x“ƒi¸©Ž¤–yœ‹o²¡„¢‘s§–v¬šz«™wâÜЮ›z®›z­šy¬™x¬™x­šy¯œ{²ž{´ }·£º¦…½©ˆ¿«ŠÁ­‹¾ªˆº§…º¦„»¥ƒ¾§…¾¨†½¨…¤’t r¨—{®‚± …± …± …° …¯Ÿƒ¯žƒ®ž„±¡‡³¤‹³¤Œ²¤±¤Œ±¥Ž°¦°¦®¥«£Ž¥ŸŒ£žŠ¡›‰žšˆœ™ˆ™˜ˆ˜™Š•™‹‘™‹‹–‰…’…“ƒ~’|“‚}”„€˜‰™‹z–ˆv“†z™‹h‡yo‚|™Žbzpkƒx…›’fyoTe[Ž„…‡PZQV_U‘˜•‹NWKFOB~ˆ|¦±¥}‰}AOB>M?xˆz²Ã´¶È¸~IZL6F8Zh\œ‘ÇÓÈàêá×áׯ¹°‰€XbZ4>7%!
+
+963]YV–’Æ¿àÜØßÚÕ¶±¬ojd83,#PKC¤Ÿ—ØÓËÈû†‚yRNFxtm¼º²ÌÈÂ{vq50*PJB–Œ•ŒSH7eVD´¢§’€mXD™„nÀ¬”|dŽ|cÁ¯”¥•z–‡l»«Ž¤”v¢rµ£…¢pª—wª™x¨˜wâÛÏ­šy®›z­šy­šy­šy®›z°{³Ÿ|¶¢~¹¥‚¼¨‡¾ª‰À¬‹À¬Š¾ª‡¼¨†»¦ƒ½§„¬‡Æ°ŒÅ°‹©˜x¥“w¬›€³¢…¶¥‰µ¥ˆ³£†²¡…²¢†²¢†´£‡´£‰µ¥‹¶¦Ž¶§¶¨‘´¨‘³¨‘±¦®¤© Œ¥Š£›ˆ ˜†Ÿ˜†—†›—†—•…•–‡”—‰–ˆ‹“…„€Ž~‘‚•†–ˆz”†v‘„|™Œj‰|mŒœ‘eue}s‡”mwTf\zŠ‰—Ze[PYOˆ‡‘™[dX=G:qzn¥°¤Œ—‹MYM5B6jyk¦·¨·Éº“¥–UfX4D6CRE|‹~­»¯Õâ××äÙÂÎÄ™¤›gsiFQH
+
+ 3/,VROˆ„°¬©ÓÎÊåáÜÑÌÇ•‘‹WSL#3.'kh_¿»³åáÙÁ½¶xtmGC<he_²¯©«§¡a[T/(i`S´©š’…tWH5|jW¯›œ‡sq]G¦’{¿«“‰w]šˆoijšžŽtŸs¼¬žŽq§–w´¢„¢q¬™z¬™y«˜wâÛÏ®›z®›{®›z®›z¯œ{²ž|µ¡~·£~¸¤€º¦ƒ¼¨…½©†½©ˆÀ¬Š¿¬Š¾«‡¼¨…½©…¿«ˆÄ°ŒÇ³¬›|¨—z°Ÿ‚¶¥ˆ¹©¹¨·¦Šµ¥‰²¢‡±¡„± …°¡…°¡ˆ³¥Œµ¨µ¨‘´¨’²¨’²¨’®¥ª¡¦‹£š‰¢˜† —…Ÿ—…ž—…™‡›™‰—˜‰”–ˆ‚…‹|€‰y€‹{Ž~‚‘‚“†}“…vŽ}—Šmˆ|k‡{€šk„zczpƒ™xŒ‚Ug]s‚zž”andJTLy‚x– –eod=H;bma§›™£—[g[4B5TcU“¤•¸Ê»¢µ¦fwi<L>8G9`ob”£–ÆÕÈ×æÚÎÜѬ¹¯ƒ†\i_ &";73WSOyuq©¥ ÒÍÉåàÜ×ÓÍ·³­xtm=91)$MHA›—áÝ×êçàš”C?962,qmf´®§œ•ŒMD:A7*”‰y¿² ‹}j]L8•ƒmŲœ}gwdM¶¤Œ·¥Œ…sZ¨—}³˜˜ˆn§—|¼¬›‹n¬›~²¡‚£‘r°ž~®›{¯œ{âÜЮ›z¯œ{¯œ|¯œ{±ž|µ¡~¹¤¼¨ƒ¾©…Á­‰Â­ŠÀ¬‰¾«ˆÀ¬‹Á­‹Á®ŠÁ­Š¿«ˆÀ¬‰Ã¯ŒÈ´‘®ž­œ´£†¸§Š¹©¹§·¦‹²¢‡¯Ÿ„­¬‚­ž„¯ ‡²¤Œ³¦Žµ¨‘´¨’³§‘²¦‘¯¤Žª¡Œ¥œŠ¥›Š¢˜‡¢˜† ˜„ž—„—„™•„—”„‘‹Š|…†xƒ†w†wˆz‹}Œ|Ž€t‰|{’†q‰~g€u~–s‰€^ul”Š}‘‰Xj`hxo›’mzqFQHjsk•Ÿ–vu@K?NYMŽ™¡« q|p7E8>N@{Œ~°Ã³­À°‘‚IZK0A3DTFv†y¦¶©ÍÝÐÔã×ÄÓÈ¡°¥}‹‚$*% 72.D?;fa]|x©¤ŸÊÅÀÞÚÔÞÚÔÅÀ»‰‚WSL1-&A=6{wqÇľçãÞ»¸³fd_&#?:3‘Š½µª’‡zMA2bTD±£‘ĵ¢~nYiXA¬šƒÃ°™ƒqX„sYò™­œ‚ˆw^¸©À°–™‰n²£‡»ªŸŽq´£„°Ÿ€¨—w´£‚² ~µ¢äÝÒ²Ÿ~²Ÿ~±ž}±ž|³ }·£º¦ƒ¿«†Æ±Ê¶“dz¯‹¿­‰¿¬‰À­‹Ä°Å°ŒÃ¯ŠÃ¯ŠÄ°‹Æ²Ž®°Ÿ‚·¦‰·§‹¸§·¦‹´¤‰²¡ˆ­Ÿ…¬ƒ¬œƒ­…°¡‰³¤´¦µ¨’´¨’²¦°£Ž­¡ŒªžŠ§œŠ¤š‰£š‰¢˜†¡˜…Ÿ—ƒ›”™“–‘€’Ž‰|‰†w…„vƒƒu„v…x|…xz†yq‚uyŒ€v‰~h}r{‘†xƒ^riuˆ„–\lc[kaˆ•Œy…}HTJZd[™‡‘‡MXLCMBz„y¤®£†‘†GTG6D7aqc˜©›µÈ¹œ®Ÿ]o`2D52C5UfXƒ”†²Ä·ÊÚÎËÚϺɾ¬¢GA;TNH`ZUzupŽ‰„¶±¬ÊÅÀåàÚåáÛÌÈ¢ž—gc\<92<82c`[ž›–ÇÄ¿Æÿ†ƒ~<83*%`XO¶­¡½±£}o_PA/r_ͽ©·¥‘n\FxeN°™¶¥{jR˜ˆo˼£¢’y‘‚hƶµ¦Œ™‰nÀ¯”¸¨Š£“tºª‰¯ž}¬›yµ¤±Ÿ|³¡}äÝÑ´¡¶£¶£µ£µ£º¦ƒÀ¬ˆÃ¯ŒÉµ‘Ë·“Ʋ°ŒÀ®Š¿­‰Â¯‹Æ²ÊµÍ·‘θ“˵ɴ¯ž²¡„¸§‹¸¨Ž¹©·§µ¥‹´¤‹±¡ˆ¯Ÿ‡­†®žˆ°¡‹²¤Žµ¦‘¶¨’¶¨’³§‘±¥®¢¬ Œ¨‰¨Š¥›‰¤›ˆ¤š‡¡˜†Ÿ—…•…œ”„—”ŽŠ{†„uƒs€r~rz~qzst{nwt|†{jujv„x~‚`pdkzo‡”ŠhtjUaX|†~‡’ˆU_WLUM‰“š’`h`?F>fnf˜¢™š¤š]h^2>3DRF‚‘…®¾²©»­~‚HYK+=/8J<`qdŠ›ŽµÆºËÜÐÇ×̽ÌÂztn‚{u”Žˆ¨¢œÃ½·ÑËÅäßÙàÛÕÎÊĨ¤~zsURL?<7GE@tqm¨¥¡ÈÄÀ©¥ _[T,&C;1’ˆ|δ® eVD]M:¤“€ÓÁ­ž‹viVA–ƒmμ¥£’{}mU³¤‹Ë½¤–‡n¡’yË»¡«œ¡‘vÄ´˜­œ¦–v¼«‹¬›y°ž|² ~®œy¯yãÜбž}³¡}´¢~µ¢~·¥¼¨…®‹Ç³Éµ’Ì·”̸•É¶’ƴñŲɴ͸’Ò¼•Ô½—к•Ì·‘°ž² ƒ¹§‹º©Ž»«‘¹¨·§Žµ¥Œ´¤Œ²£‹°¡Š° Š±¡‹³¤Ž´¦¶¨’¶©”µ¨“²¦¯¤­¢©žŠ¨‹¦œ‰¥›Š¤›‰¢šˆ ˜‡ž–‡•†™‘‚•~Ž‰{‡„v€~p}p||pz{nz|pwzovzo~vmshpym€‹grfdodƒŽƒt~tR\RnvnŒ•gogFMFlsl—œ–w}vELEKTL††ž¨Ÿ}‡~BNC5B7aod˜¦›²Ã¶š­žfwi7I;(:,;L?dthŽ’²Â·ÉØÎÄÓÉ«¥ž¹³¬ÆÀºÏÉÂâÝÖäßØàÜÕËÈÀ¨¥žˆ…~`^X:83750\YT™–‘Á½¸¹´­€zr?8.5+qfYÀ³¥ÎÁ±€oXH7ueRÅ´ É·£„r]p^H¶¤ŽÌº¤’‚j‹{cɹ¡¾¯–g°¢‰Ë¼¢ v«›󗤔w¯ž€»ª‹ª˜x³¡±ž~°|°{ãÝѳ ¶¤€¸¦‚¸¦‚º¨„¾ª‡Â®‹Æ²È´‘͹–Ó¿›Ð¼—̸“ɵɴͷѻ”Ó½–Ó½–Ñ»•Ï¹”´ µ£…¼ªŽ¾¬‘»«‘¸§Ž¶¥Œ³£Š²¢‰²¢Š²¢‹±¡‹²£Œ³¥µ§‘·ª”¸«–¶©”±¥®¢Ž©ŸŠ¨Š¨žŒ§žŒ¥œŠ¤›Š¡™‰ ˜ˆž˜ˆ›”„–Ž‰z‰„w‚€q}p}{o{znyymyynyyostj|}spsiinc~†{oxm[dYyw}†}V^U]e\‡†y€yHOIW^W“Œ‹ŠSYR?G?jskœ¦ž“ž•Zf\0>3BPEw†z¦·©­¿°ˆ™‹VgZ0A4&6)>MA`qe‰™Ž©¸­¿ÎÃÏÈÁ×ÑÉßÙÒâÜÕßÙÒ×ÓËÀ¼µ¥£œƒ|RPK.+&*'#ROJ†ƒ}»·±Á»´š“‰^UJ9.!WK=¦™ŠÔÇ·²£’l]L]M: |ÔÁ­°Ÿ‰sbLŠyb˺¢¾­—‡w^žuѧ«‚g¿°—À±—œŒqºªŽÁ±”§–xº©Œ¸¦ˆ«™z·¥…³ ´¡€´¡€æßÓº§†À®‹Á¯‹¾¬ˆÀ­‰Å±Å±ŽÄ±Ä²ŽÈµ’Ï»—м—κ•Î¹”к“Ô¾—ÚÄœÛÅÙÃœ×ÁšÕ¿™¹¥…º¨ŠÁ¯’Á¯”¼«‘·§´¤Š²¢‰° ‡°¡‰±¡Š±¢‹³¤µ¦·©”¹«—¹¬˜¶©”±¥¬ ¨ž‹¦œ‰¦œ‹¦œŒ¥œ‹¤Œ¡šŠŸ˜ˆ–‡›•…–€‰|‰„w‚q~|o{ym|ynywlxvlxvmtrh{xowvmgg^vyox|r\_Wjne†}`f]QWNx~uƒ‰‚V^VGNFv{t”š“mrl@H?MUM†‡œ¦}ˆ~BNC.:0P^R†•‰©º­¤µ¨ƒ“†L\O.>1#3'5E:RaVu„y”£™ÜÖÍÚÔËÒÌÄÐËÂÇú²¯¨—”igc962%"+(#PLG†{·²«Êû¯§rh]E:-J>0†xiȺªÌ¾­n\L;yhUÁ¯›Ñ¿ª‘€io^FªšÓ©¡‘xƒsYº«Ì½£—‰ožu˼¢­ž‚žsŵ˜¶¦‡©˜zÀ¯‘±Ÿ¯~¸¦†·¤ƒ¹¦…º§†çáÕ½ª‰½ª‰½ª‡½«ˆÀ­ŠÅ±ŽÇ´Ä±Ã±Æ´Ë·’ѽ—ÖÀšÕ¿™ÖÀ˜Ø™ÜÆàÊ áÊ¢ßÉ¢ÞÈ¢À¬Á¯‘Æ´—IJ–¿­“¹¨Ž´¤Š±¡‰¯ ‡¯¡‰°£‹²¥Žµ¦¸ª”¹¬—»®šº¬˜µ©–°¥’« Ž¨ž‹¥œŠ¦œ‹¤›Š¤œ‹¤Œ¡šŠŸ˜‡œ•†š’„—‚’‹}ˆ„v‚€r~{nzxlyvkxtjwsivqiupgwrj|wpjg_one||tcd\__X{~uqtlMPIdia†‹ƒjohCHA^c]Ž“ˆŽ‡RYQ;C;ene– ˜”ž•fpf5@50;1^ma “¬¼¯¢±¥{Š~HXL,:/!0%,;1DSIapf¹³ª¹³«·²©¯¬¤•“trmGDA+(%&#.+%TPJ‡‚z»´«ÈÀ··®£„ymMA4B6(tgXº­ÕÇ·¦˜†gXE`O<¡|Öů´¡ŒucL…t\É·ŸÆµœŠz`’ƒhξ£ºª‘‚h¶§ÉºŸ ‘u¬ȸš«œ}± ¾­­›|³¡¶£ƒ¶£‚·¤ƒº§†æàÔ¸¥„¸¥„¸¥„º§†½ªˆÀ®ŠÃ±Â°ŒÃ±ŒÆ´Ë·’ѽ•Ø›ÛÅžÜÆžÝÇàÊ¡ãͤåÎ¥ãÍ¥â̦İı”È·šÅ´˜¿¯“º©´¤Œ±¢Š® ‰¯ Š¯¡Œ±£Ž²¥¶©“·«–¹­š¸¬™µ©–°¥“«¡¨žŒ¥›Š¦Œ¦Œ¦œ¤œ¡™Š–†š’ƒ—€•~“‹|Š…x‚s}zmzvkxtixsixrivpguphtle}unqkcid\{xppnfYWOrqi}~uWYQQTLz~v~ƒ{PVOGMFtzt”š”ounBIAENFxy¦††S]S1:05B7drf“¢–§µª ®£~ŒQ_T/<3,#!.%.;3‘Œƒ‘…„zhe`LIE/+'# %!>:5e`Z˜’‹Ã»²ÑȽº°¤†{nTG:E7)m_P©›ŒÕÇ·¼­œ{lZZK8†ta˹¥Ìº£Œycr_H¬š‚ÖÆ­©™€‚sY° †Ò¨£“y™‰oǹœ½¯‘Žq½­’ò–©™|¾­½«Œ°ž~¹§‡¶£ƒ·¤ƒ·¤ƒ¸¥„æßÓ·¤ƒ·¤ƒ·¤ƒ¸¥„º§…¼ª†¾«ˆÀ­‹Ã±Èµ‘κ”ÕÁ™ÛÅÝÇŸÞÈ àÊ¢âÌ£äÎ¥äÎ¥äÎ¥ãͦűIJ”É·›Æ´˜À°”ºª·¦²£‹¯¡Š® Š®ŸŠ¯¡Œ²¤µ¨“¶ª•¸«˜¶ª˜´©—¯¥“¬¢¨ž£šˆ¡˜† —†¢™‰¡˜‰ž—‡š“‚—€“‹}“Š|‰{ˆƒv~q}ymzvkxtixriwpgvofungqibwohvohg`Xtneyum]YRa_W~|uijaJLCdf_„‡€imeDICW]W‰‰‹’ŠX_W9@8T[S‡‡¤œzƒzGPF*5+8D9huj’Ÿ•¦²¨¤°¦„]h`:F=!,$&jg_XUO@=8-)%&"'#;61[VO}wo©¢™È¿¶Í·²¦šˆ{nVI;G9*fWG¢“ƒÒijʻª~k_O<rbN¶¥ØÆ°¨•ubKŽ|eν¥È¸ŸŽ~e“…k̼¢¾®•’‚h«œÌ¼ ¨š|¤•xƶšµ¤ˆ®Ƶ—»©‰¶¤…½ªŠº§…»¨‡»¨‡¼©ˆçàÔ·¤ƒ¶£‚·¤ƒ¹¦…º§…º¨„»©…¾«‰Ä²Í»—ØÄžÞÊ¢àÊ¡àÊ àÊ¢áË£âÌ£âÌ£âÌ£ãÍ£ãͥŲIJ“É·›Ç¶™Ã²–½¬¸¨Ž´¤‹±¢‰¯¡‰¯¡‹±£Ž³¦‘¶ª•¸«—¹¬™·«™µ«˜¯¦“«¢¦‹¡™‡”‚š’€š’š’‚š’‚—€•~“‹}’‰|…x‡u}p}xmzukxsiwriupgupguogrlesleyskjd\jd\|wohd\WUMrqizzqSTLSTLyzs‚{SXQAGAini•Žx~wHNG;A:^e]‘—™ —w~vAJA)3*7B8bme˜¤®¦¦°¨‘›“q{sJUN1<5FB<63.2/+840EA<[UO~wo¡™Ã»¯Ðƺɾ²©€seSF7I;,hYI£•„ÔÅ´ÏÀ°›‹yiYFgWD¤“ÙDz½«•…r\zgO´¢‰Ô룓z„u\´¦ŒÑ餕|”…k²–½®‘˜Šl´¤‡Ã³—©˜z¶¥ˆÂ°’² º¨ˆº¨‡º§†º§†¹¦…º§…æßÔ¶£‚·¤ƒ¹¦…»¨‡¼ªˆ»¨„»¨…½ª‰Ã°ŽÍº–×ÃÚÆžÜÆÝÇÞÈŸàÊ£áË£áË¢áË¢áË¢â̤űIJ’ɸšÈ·™Å³˜¿¯”»«¶¦³£‹±£‹±¢Œ³¤µ¨“¹¬—º­™»®œ¹®›¶¬™²©–®¥’¨ ¢™‡œ”‚—~–Ž}•|“Œ|’‹{“‹|‘‰{†xˆtƒ}rzn}xl{vkwshtpfsofsoerofrmemibvsiokab]TqnetpgYVMb`W{zrih_KJCdc\ƒ„}lpjCHBINHyxŠ‰iog=C=>D<gld“˜•š’qxp?I@'1)2;3U_Vˆ€ž¨ ¨±ªœ¥ž…Ž‡islRNJVRMd_Xsnf‰€¨ –½³¨ÏŸÍô¼°¡”†xobSPC4J<-pbS¢”„ÓÄ´ÎÀ°ž~m\KeS@•ƒoѾªÊ¸¢”‚ktaJžŒsÑ¿§ºª‡w]šŠpÏÀ¦¼®””ƒj«›Êºž¨™|Ÿq²”´¤‡§–y¿®¹¨‰±Ÿ€»¨ˆ¸¥…¹¦…¹¥„¸¥„·¤ƒæßÓ·¤ƒº§…¼©ˆ½©ˆ¼©ˆ¼ª†¼©†¾«ŠÂ°ŽÊ·“н—ÔÀ˜ÚÛÚÄœÛÅÞÇ ßÉ¢àÊ¢áÊ£ßÊ£Þɣ®ŽÃ°’É·™Ç¶™Å´˜À°”½®’¸¨µ¥Œ³¤Œ´£Œµ¥¸ª•»®š¼°œ½°ž¼°ž¸®›²©–®¥’¨ ¡™‡›“–Ž}”Œ{‘‰xˆx‡xˆzŽ‡y‹ƒv†sƒ|qyn}wlzukvqgsofqndomcllbmmbjjamlbrqfa`UcaWvtkdaYTRJnldyvoVSLNKDsrl~|Z_Y<@;TXSƒ‡ˆ†]a[8<4?D<hle•˜‘’—nvmENE&.',5,GPHnvo‹”Œ¡©¢¦®§¦ Š†›”Ž¥ž•¹±¦Å»¯ÍöËÀ²»¯ œ€}p`_QAJ<,TG7zl\¬Òijο®¢’‚qaOaP>{gȶ¡ÔÀ¬¡yvcK‹x`ȵœÌ¹¡–„k‰x^»ªÌ¼¡ŸŽt˜‡kÅ´˜»«›‹n²¢„Á±”©˜{± ƒÀ®³¡‚¸¦†¼©ˆº§†»¨‡»¨‡»¨‡º§†çàÔ»¨‡¾«ŠÀ­ŒÁ¯ŽÁ¯ŽÀ®‹À®ŠÁ®Ä²‘É·“о˜ÖÁ›ØÂœØÂœÙÂœÙÃÛÅŸÜÆ ÜÇ¡ÛÇ¢ÛÇ£¾¬Ž¿­’ŵ™Å³˜Á²–¾¯“¼­’¹©¶¦µ¥Žµ¥¸¨“»­˜¾±¿²ŸÀ³¡¾²¡»±žµ«š®¤’§ŒŸ–…š‘€–|”Œ{ˆxŽ‡w…w…wŒ„w‹„wˆt„}r{p~wmztjuqgtqfpndlkchj`gi_gh_eh\mncgg]\\RkkbppgWUMZYQvulnkdKHBUTNw{uu{uJOJ<A:_c]‡‹†…TXR37/AD<gjbŽ“Œ’˜’szrJQJ+2+")"7>7SZTszu‡Ž‰œ¤ž¶°§¾¶¬Ç½±Äº­¿³¥°£•—‰{tebUGQD5NA2fXIŽ€p½¯ŸÖȷ˼«|r`NdSA‹zhÅ´¡ÔÁ®­š†ygR‚pY¹§Ð¾¦¨—~…sZ§–|ÑÀ¦´¤Š‘f²¡…ɹ§—}¢“xô˜¶¦Š§—z¾­¼«´£†À¯‘¿®Ž¾¬À®Ã°Ä²‘ðéãØIJ’ǵ•È¶–ȶ–É·–È·”ʸ–˸˜Ë¸™Ì»™Ò¿œÖßÚÄ ÙÄ ØÞÙÄžÚÅ ÛÈ¢ÛɤÛȤÛȦ½­¾¯“ô˜Â´˜À²–½¯”º«“¸ª‘·§·§·§‘º¬–¾°›Áµ Á¶¢Ã¸¥Á¶¤¿´¢º¯±§•¨žŸ–…š‘€–}•Œ|’‹zˆy…w‹„u‰‚tˆ‚tˆ‚t†sƒ|p~wl{ujwshushrpfmmbijagi`fi_de[hi^mme^_V``Xsrjfe\RPGecZzxp_\TFE=\_XyxjoiAG@<A:dic…Š„|{RVP/4-:?9ae_ˆŽˆ“™’…[a[6<6")#$+&295NUPfmi•‰¢™Œ¡–ˆ’†w…whvhYfXIUG8YK<fXI„vg¯¡‘̾­×ɸÀ±¡”ƒro_Nl[I’nȶ¤ÙÇ´±ž‹~lX}lV±Ÿ‰ÔÁ«¶£‹†t\™†nË»¡Å´š™ˆn£’wÌ»Ÿ»ªŸŽt¸§Äµ™«œ€µ¥‡Ä´•·§ˆ¾®Å´—ij•Â°’ò“Å´•È·˜É·˜ìæÛ̺œÌºœË¹™É¸˜Ë¹™Ëº™Í¼›Î½žÏ¿ŸÑÀŸÓ ÖÄ¡ØÄ¢×áØÄ¡ÙÅ¢ÙÆ£ÙÇ£ÚÈ¥ÚȦÚȧ½­“½®“´™Â´™¿±˜¼¯—¹¬”·ª”µ¨’´§‘³¦·ª•»¯šÀ´ŸÁ¶¢Å»§Äº§À¶¤º°ž³¨—¬¢¢šˆ›”ƒ˜‘™‘—€”‹}ˆz‹„u‰‚s†q…~p„}o{m|wj{ujxtivsisqhomdkkbhiahiagh_dd\lkdgf_[ZShg_sqiZWOSQHpmdurjRQIDH@chaz€ybha;A;=C=eke†Œ†yyNTN/5/695VYT||’–‘‰ˆpupKPL061%!% '/*rfWnaRi\LbTD_P@[M=_QBo`R‡xj¨™ŠÈº«ÕÆ·Òô°¡‘ˆxgl\KraPœ‹yͼ©ÛÉ·³¡…s`~nY¯ž‰Ô¬À­—}e}eÁ¯—ν¥¦–|˜ˆoij™Ç¶œ¦”z¬œƒÈ¸ž¸ª¯¡„Ä·™¿±”»¬ŽÇ·™Æµ˜Ä³–²•Ã³–Ƶ˜É¹œËºìçÜʻ̻žË»œË»œÌ»œÌ¼Î¾žÐÁ¡ÐÁ¡ÐÁ Ñ Ò¡Ó¢ÖĤÙȧÜÉ©ÜʪÛÉ©ÚɨÙȧØǧ»¬’½®•Â´›Ãµœ¿²š¼°™¹­—¶«—³§”²§“²¦“´©–¹®š¼²ž¿µ¢Â¸¦Ä¸§Àµ¤º°Ÿ´©™­¤“¤›‹œ•„™’˜‘‚—‚–Ž€‘Š|Œ…x‰‚u†rƒ}p{m~yk|wjyujxsiuqirphomekkeiidhichhadd^gf_llecbY][TpmfjhaSPIYWPtqkkkcGKDFLFjnhy~x[`[;?:?D?dhc‚†€{ySWR361/2-FIEjmhˆŒ‡ŒŒ‚‡‚elgKRM/72"*&_P>dTCcTCj[KvhX†xhž€¶¦—;¯ØÊ»ÕƸ»¬›Œ{xhXk[Ko^ªš‰ÔñÓñ°žŒ‚p^p\¬›‡ÔïǶ¡™‡rŒ{d·§Òª°¡‰–‡n¶§ÐÀ¦³£‰¥–{´™Ãµš® †½°”ǹœ¼®‘ó•Ç·šÅµ™Åµ™Åµ™Ç¶šÊºžË»ŸÌ¼ íèÞ̾¡Ë¼ Ì¼ Î¾¡Í¾ Î¿¡ÑÁ¢Ñ¤Ñ£ÑÁ¢ÒäÒäÔÅ¥ÖƦÚɪÜ̬ÝÌ­Ü̬ÛÊ«ÚɪÙȪ¼¬”»­”Á³œÃµ¿²œ¼±›¸­™µ©–²§”±§’²§“´©–·¬š»±Ÿ¿´¢Â¸§Ã¸§À·§»²¡µ¬›¬¤“£›‹œ•„—€•Ž”“Œ‘‹}†zŒ…x‰ƒv„rƒ}p~ym{wjytjvrisphpogmmejjdhicfhcef`ee_bb]jjdkkd\\U`_Xqoib_YNLE_]Vuuncf_DGBLPKormy}x\`[9<7?B=ad`~|€ƒ~^b]:=:),)473SVSsxt…Š†Œ’}…€lsoU]Zm“„rž®Ÿ¹ª›È¹ªÔŶØʺο°¼­žŸ‘„uem]MufV“„s½­œØÈ·ÒÁ°¨—†€o^‚q^«›ˆÑÁ®Ç·£›ŠuŠyd° ‹Ò«ºª”™‰r«ž…ÐÁ©¾¯–¥–}¼­“̽¤µ¨µ©ŽÈº À²˜½¯•Ç¸Ç¸Ç¸žÇ¹ŸÆ¸žÈºŸÉ»¡É»¡Ê¼¢ìçÞʽ¢Ë¾¢Ì¾£Î¿¤ÏÀ¥ÐÁ¦ÒçÒħÒħÔŨÕǪÖȪÖȪÖȪØÈ«ÛÊ­ÜÌ®Ü̯Ü̯ÜÌ®Û̯¼¯—º­–¿³œÂµ ¿´ž¼±œ¹®›´«˜³©–±§–²¨–³©˜·®œ»²¡¾µ¥Â¹©Ã¹ªÂ¹©¾µ¥·¯Ÿ­¦–¤›•†—‘‚•€•”Ž‘Š~‡{‹…z‰ƒy†v†€t‚}q{wmyukusisqhnmfkkdiicghcfhcefadf`bc]bb^kkfdd_XWSdc]omhZXRNKFdb]tup]_ZBC?NPLqroy{w\^[;=::<8Y[W{|xƒ…‚knkHJG+/+*-*7;8SYUnsp‚ˆ…‰„‰Æ¸¥Ê½ªÏÁ°ÓƵÕÇ·ÏÁ°Â´£®ŸšŒ{p`rdTqbRŠ|j­žÒóÝͽǷ¦›‹z‚q_‹ziµ¥“Óñŵ¢œ‹xŠzg¯ŸŠÐÀ«À°›žy§˜ÍÀ©É¼¤«ž…´¦ÎÀ§½°—³¥ŒÅ¸ŸÆ¹ ¼¯—Ä·ŸÇº¡Ç» Ç»¡Ç»¡Ç»¡È»¢È»¢È¼£É½¤ìèßʾ¤Ì¿¥ÍÀ¦ÏÁ§ÒêÒĪÒĪÓŪÔƪ×É®ÙÌ°ÙÌ°ÙË®ÖÈ­ØÉ®ÚʯÜ̱ßϳÞϳÝϳÜϲ¿²œº®™¿´ŸÂ¶¡À¶ ½² ¹¯œµ¬›³ªš±©˜°¨–³«š¸¯¼³¤¿·¨Ä»­Ä»­Ã»«¾¶§¸°¡°©š¦ž‘–‰—‘ƒ•‚’€‹~Ž‰}‹…z‰„y‡‚w…u‚~s{pyvmxulusjqpgnngklejkehjegidfhddfbcea_a\deaije^^ZXWRgfakkeUSNNNIffbqrn[\XBB?MNKnolxyvbcaAA>785LLIopm„wzw]a^<?=)-)',)385HMJ]darxuÀ²Ÿ¾°¸ª˜¬ž¡’‚•†v‚tdwhXrcSwhXŒ}m¯ Í¾­ÝͽÔÄ´²£’o‚ra–†uÀ° ×ȷ󢜌{~l¯ŸŒÑÁ®Äµ¡Ÿ{£”É»¤ÎÀª¯¡‹°¢‹Ì½¦Ç¹¡´§Á´›ÍÀ¨Â¶žÅ¹¢Ê¾¦È½¥É½¥É½¥È½¥È½¥Ê¾¥Ê¾¦ÌÀ¨ÍªíéáͩΪÏêÐÄ«ÓÅ­ÔÆ®ÔÆ­ÓÇ­ÕÈ®×É°Ø˱Ù̲Ù̲ÚͲÛͳÛÍ´ÝϵÝеÞѶßÒ·ÝзÁµŸ»°œ¾´ Á¸¤Á·¥¾´£¹°ž¶­³ªš±¨˜°¨˜²ªšµ­»²¤À¸ªÅ¼®Å½°Â»­¾¶¨·¯¢°©›¨¡”ž™Œ—’†’‘Œ‹Ž‰~Š…{ˆƒz†‚xƒ€v|s|xnxulusksrjpoinnhlmgklgikfgiefhefhecfbbeb_a]egcfifYZWXZUjjfiieRRNPPKiifrroZYVCC?JJHjjg|{yjigHGD553??>[\\xzy€‚svtVZX;?=+0."(&&,*286sa{m[vhWufVn_OqbQvgV„uf™‹{´¥•Î¿¯ØɹÖǶ¿°Ÿœ|†wgŠ{k©š‰Î¿¯Øɹº¬›—ˆw’ƒq´¤“ÓIJô¡¡’~¢’~Ŷ¡Î¿ª²¤Ž¬ŸˆÇº£Í¿©º¬•½±šÐĬȽ¦Çº¤Ì«ËÀªÌÀªÌÁªÌÁ©Ê¿¨ËÀ¨ÌÁ©ÌÁªÏĬÑƯïëãÓÇ°ÒÇ°ÒÇ°ÒǯÒÅ®ÓƯÓƯÓÇ°Õȱ×ʳ×ʳØ˳Ù̳Ü϶ÞÒ¹ÞѸÞѸÞѸÞѸÞÒ¸ÞйÁµ¡»±ž¾´¢Â¸§Á·§¿¶¥º±¡·®Ÿ´«œ±©š²©š²©š´«¸°£¾¶©Ã»®Ä½°Ãº®¾¶ª¹±¥°©¨£–ž™˜“‡”ƒ“‚’ƒŽŠ€‹ˆ~‰…|†ƒz„€w{s{xpwtlurlqpjoohnnilmhknijmiilhgjgeigcgdadc`c`_b^ehedgdUWT[\XlmifgcRQMPPLihfsrp]]ZCB?HHFca_zzwsspTTR999445GGHeffz|{‚‚txw]aaEIH166&,,i]NocTtgX|o`Œ~mš{¯¡Ãµ¤Óŵ×ʹвº¬›¢”ƒ‹|l‡xgžÀ²¢×ɹÒ³²£”•†v˜Šz»¬œÓųÁ³¢¢“‚¤•ƒÆ·£Ñï·©•¬ŸŠÅ¶ ÑîÁ²¾±›ÏíÎÀ¬Ç»¥Î­Í­Í®ÎïÎîÎíÍìÎíÏÄ®ÐůÑÇ°ÒȲðìåÔÉ´ÔÉ´ÔÊ´ÓɳÓɲÔȲÔȲÔɳÖ˵×̶Ø̶Ø̶ÚζÜиÞÒºÞÒºÞÒºÞÒºÞÒºÞÒ»ÞÒ¼À¶£º±ž¼³£Á¸¨Á¸¨½¶¦»³¤¸°¡¶® ²«›²ªš±©›³«·°£¼µ©Ã»®Å½²Ä¼°À¹­º³¨±«Ÿ¨¢—žšŽ˜“ˆ“„’ƒ‹Œˆ‰†}ˆ…|…‚zƒw€|t{xqxvourmrqkqojnojmnjknijnjjmigkiejibgfbfebfc_ba^b_figbdbVWT\^ZklieebOOMOOLffcttq``^EECBA@WWTrsqxxvbccFFG446557HII`bbuxx~‚x||lppY__¢˜Œ¥š®£–¹­ŸÂµ¦ÏÁ°Ñòɻª¿±¡ª–‰y‰{k†xi˜Šz¶¨˜Óŵ×ɺĵ¦¤•†“…u£–†Å·§ÕÇ·½¯Ÿ¡“ƒ§˜‡È¹¨ÓIJº¬š­ŸŒÃ¶¢ÓDZķ¢¾²ÏîÑŰɽ§Í¬ÏįÏįÏÄ°ÐűÑƲÑƱÑDzÑDzÓȳÔɵÕʵÕʵðíåÕ˵Õ˶ÕË·ÕÌ·ÖÌ·ÕÌ·ÖÌ·×͸×͸ØκÙϺÙϺÚϺÚϺÚÑ»ÜÑ»ÞÒ¼ÞÓ½ßÔ¾àÕ¿ÞÔ¿À¸¦º±¡»³£Á¹ªÁ¹ª¿¶©»´¦¹°£µ® ²«°©›°©²«ž·¯£»µ©Â»°ÆÀ´Å¿³Á»°¼¶«²­¢¨£™žš˜”Š’Ž„‘Œƒ‹‚Š‡~ˆ…|…‚zƒ€yƒy€~w}ztxwpvtossmqqlpqmnollokknkhlifkjejiciibgf`ee`dd]a_^a_egf_b`SUT[\ZjlidecPQOLMK_a^qqoefcKLJ<><JKIdecwwwpnqZZ[?@B345124ACEUXYhlmuzzz€È¿¶Ç¾³À¶ª½³§·¬Ÿ¬¡“¡•…“†w…xi€sd‰|l™Œ|·©šÎÁ±Ù̼˾®²¥–˜‹|š}³¥–ÒŶÔÆ·¹«¢”„¬žŽË½­Ñ²»¬›¯¡Å¶¥Öǵȼ¨À´ŸÍ®ÓdzÌÀ«Î­ÒƱÒƱÑƲÒdzÔɶÕʶÕʶÕÊ·ÕÊ·Ö˸Ö˸×Ì·Ø͸ñíæ×͸Ö͹×ͺØÏ»ØÏ»ØÏ»ØÏ»ØϼÙмÙмÛѾÛÒ¾ÚѽÚѽÛÒ¾ÝÓ¿ßÔÁâ×ÃãØÄâØÅà×ùª½µ¦¼´¦Ã»­Ã¼¯Âº­¾·ªº³¦·°¤³¬ ²«Ÿ±ªž²« ·°¥»µªÂ¼±ÇÁ¶ÆÁ¶Ã½³½·¬³®¤©¤šŸ›‘™•Œ”‘‡”‘ˆ’‡Ž‹‚‰†~…ƒ{ƒyx€~w}{tzxrwvqttossorsppronqnknmjmkglkejkdijbhhbfgbfe_dc[_^^a`dge]`_RUS[^[ikheieRTQILHX[XknjjmiSUS?A?=@=RRRkjlvuxnnpXY[CDF468.12367?DEMRSŸ—ž–š‘‰Ž…{‚zp}sh{reugŽƒu£–‡»®ÐòÖȸ̿¯µ¨˜Ÿ’‚˜‹|§š‹Æ¹ªØ˽㳦˜¥˜‰¶©šÒĵÐô¹«œ°¢”Ƹ¨ÕÇ·É»ªÀ´¡Ïð×̸ÑűÒƱÖʵ×˶ÖʶÕÊ·Ö˸×̹×̹×͹×͹ØͺØλØμÙϼÙмòîçÙнÙѾÙÑ¿ÚÑ¿ÚÑ¿ÙÑ¿ÙÑ¿ÙѾÚÑ¿ÛÒÀÜÓÁÝÔÁÜÓÁÜÓÁÝÔÂÞÖÄáØÅäÚÇåÛÈãÚÈâÙÇž¯¿¸ª¾·ªÄ¾±ÇÀ³Å¾²Á»®¾¶«º²§·°¥´­¢³¬¡³¬¢·±§»µ«À»±ÇÀ·ÆÁ¸Ä¾µ½·¯´®¦ª¥¡œ”›—Ž–’Š•‘Š“‰‹„‹ˆ‡„~„|‚y|w|{v{yuxwswvstuqturrsqoromomknmimlfllejldiichhbgg`dd^cb[__\a`cge]a`SWTX\YfkhiliUXUFJFNROdgdmqo^b_HLJ:<<@ABTTWjkmtvwmprbdgNQR;?A.13)-/€ysƒ{u…~wŽ†–ˆŸ—¦Ÿ•³«ŸÃ¹¬ÍÁ´ÏÁ´Á´¥®¡’‘‚™Œ|¦™‰¿³£ÔȸÔǸ¿³¤ªŽ«ŸÁµ¦ÖɺÎÀ³¸«´§™Ê½¯Õȹɻ­Â´¤Ï±ÙÌ»ÔÉ·ÕÉ·ÚλÚκÙͺØ͹ØͺÙλÙμÙϼÙϼÙнÚпÚÑÀÛÒÁÛÓÁÛÓÂòïéÜÓÂÜÔÂÛÓÂÜÔÃÛÔÃÛÔÂÛÓÂÛÓÂÛÓÂÜÔÃÝÕÄÝÕÄÞÕÄÞÖÅß×ÆàØÆàØÇáÙÈáÙÈáÙÈàØÈÅ¿±Â»®¿¹¬Å¾±ÇÁ´Æ¿´Á»°½·¬º´©·±§µ¯¥³¬£´­¥¸±¨º´«À¹±Ä½¶Ä¿¸Ã½¶¾·±µ°©¬¦Ÿ¤ž—›––‘‹“Ž‰‹‡Ž‰…‹†‚ˆƒ†~„€|€~z}}y{zwzyvyxvvvtuusstrrrqpqononknminmgllfkjeiibggaef_dd]ccZ__\bcchhaedTWVUYXcffhllZ]\GJJGJIX\[imleiiW[[AEF7:<=ABOSTademqrqwwkpq]cdOUV¯¨¢²«¥¹²¬¿¸²Å¿¸ÍÇ¿ÑÊÃËż¼³ª­¤™Ÿ”ˆ•Š}–Š|¥™‹½°¢ÓÆ·Öɺǻ¬³¦˜¦šŒ³¨šÌÀ²Ø̾ɽ°¸¬Ÿ»¯¢ÏöÖɼȼ¯Â¶¨Ï´×Ë»ÔȸÖʺÜпÜоÛϾÚϽÛоÜÑ¿ÜÒÀÝÒÁÝÓÁÜÓÂÝÓÃÝÔÅÞÖÆÞ×Çß×Èß×Èôñëß×Æß×Çß×Çß×Çß×Èß×Èß×Èß×Èß×Èß×Çß×ÈßØÈàØÉàÙÉáÚÊáÚÊáÚÊâÚËâÚËâÚÌâÚÌÇÀ´Ã½²Á»°Ä¾´ÇÀ¶Å¿µÂ¼²¾¹¯»¶¬¹³ª¶¯§µ®§¶¯¨¸³«¼µ¯¿¹³Ã½·Ã¾¸Ã¾¸¾¹´·±¬®©£¥ šž™“˜“Ž“Ž‹‘‹ˆŠ†Œ‡„Š…‚‡‚€…€~}~~{}}{|{yzyxxxvwvuuusssrrrqppomookooimmgllfkkdiibhg`ef_ee^dd[bb]bbeiiaeeVYYRVV^bagkk_ccNQPCGFKOO\__imnejkTYYBFG6;<8=>BGHQVX`egjppmstȼÆÀ»Å¾¹Â»µº³®´­¦©£œ£– ™’š’Šœ”‹¨Ÿ”½³¨ÎÄ·Ôɻȼ¯µª›¨œ­¡“Áµ¨ÓÈ»ÓȺÁµ©¶«žÂ¶©ÓÈ»ÕɽǼ¯Æº­Òƹ×˾ÓǹÔȹÚοÛÐÀÛÐÀÜÐÁÝÒÂÞÔÃàÕÅàÖÅàÖÆà×Çß×Èà×ÉáØÊáÚËâÚÍâÛÍâÛÍõòíâÚÊâÚÊâÚËâÚÌâÛÍáÛÍáÛÍâÛÍáÚÌáÚÌáÚÌâÛÌâÛÍäÜÎäÝÏäÝÏäÜÏäÝÐäÝÐäÝÑäÞÑÊĹſ´Á¼²Ä¾´ÇÁ¸È¸Ŀ¶À¼²¾¹¯»µ­¸²ª¶°©¶°©º³­¼¶°¿º³Â½¶Ã¾¸Â½¸¿ºµ¸³®°«§©¤Ÿ¢œ˜š•’•’ŠŠˆ‰‡‹†…ˆ„‚†‚ƒ~}}}||{zzzxxwvvuttusssrqqqnqplpojnnhlmgklejjdiibgg`fg`ef_de\ab]aacggcffX\\OSSVZZcggehhVZYFJIBFELPP]abgllfkkY^`GLM:?@49;3899?@DIK¦ š¤ž˜Ÿ™“›”š”Ž™“Œ›•¤˜±«¥Ä½·ÓÌÅÖÐÇÎƽÀ¸¯¯¦œ¦œ« “¼±¥ÑƹÕ˽ËÀ³»°£¹¯£ÊÀ³×ÍÀÓȽǼ°É¾²ÖʾØÍÂÔɽÖʾÙÎÂÚÐÃÛÑÄÝÓÅßÔÆá×ÈãÙÊäÚËãÚËãÚËâÚÌâÛÍãÛÍãÜÏäÝÏäÝÐåÝÐåÝÐöóîæÞÏåÞÐäÝÏäÝÏäÝÐãÝÐäÝÑäÝÐäÝÐäÞÑäÞÑåßÑæßÓæàÔæàÔæàÔæáÔçáÕèáÖèáÖçáÖËǼÆÁ¸Ä¿µÄ¿¶ÉÄ»ÊżÇúĿ·¿»³½¸°ºµ®¸²¬¸´­ºµ¯»·±¾º´Á½·Â½¸Â½¸À»¶ºµ±³®«¬§¤¤Ÿœ˜–—’“ŽŒ‘ŒŠŠˆ‹‡…‰…„‡„‚„‚ƒ€€€~}|}|z{yyyxwwvvttsssrprqmqqlpojnnhmlfkkdjidiibhhbggaffaff_cc\`aaeecgg\`aQTTPTT[__dgg`ddQTTCGI@EFJOPW]^dijgln`fgTZ[FLM7=>.45£¢­¤£¯§¦±­¬·²²º½¼ÄÄÄÌÌËÔÐÏØÎÎÕÇÅÌ¿½Á±¯²¨¦©¬ª­»¸ºÌÉÌÓÐÓÌÈ˾»½¸µ¶Â¿¿ÒÎÎÖÔÒÎÊÊÆÀÁÌÈÈÕÑÒÕÑÒÒÍÎÔÏÏÖÒÏÖÒÐ×ÓÐØÓÑÙÕÒÙÖÒÚ×ÔÛØÖÛØÕÛØÖÜÙ×ÜÙ×ÜÙÖÝØÕÞÚÔÞÚÕÞÚÕÞÚÕÞÚÕóòðßÚÕßÚÕÞÚÔÞÚÔÝÙÕÝÙÕÞÙÔÞÚÓÞÚÓÞÚÔÞÚÔÞÚÔßÛÕáÛÕàÚÔàÚÔßÚÓßÙÔßÙÔßÙÓàØÔÆ¿¼Â¼¹À¹¶À¹µÄ¾ºÅÁ¼Ã¿ºÀ¼·¼¸´¹´±·²®´¯­³­®´®¯¶¯¯¹²²¼µµ¾¶¶¿·µ½¶²¶±­¯ª¨§£¢žœœ—••’ŒŽˆ‰Œ…‡‰‚„†ƒ}€|}€|}||~zz}yx}ww{vu{vuzuswsruqptqoqpnoolmmjlkijjhgigefededbddbddacc_aa_``]__YZZ[^]`ca]`_TVULONQTR\^]bfd]baNTTBFF?DDCHHNSS\abdiibgg^ccSYYÅÉÝÉÌàÉÌàÊÍáËÎàÈËÜÅÈÚ½ÁÑ´·È¬°Á§«»¨«·³µÁÁÄÐÌÏÜÏÓßÈÊ×¾¿Ì··Ä½½ÈÊËÕÔÕÞÑÓÙÈÉÏÈÇÏÐÏ×ÖÕÝÔÓÛÒÑÙÔÓÛÖÕÛÖÕØÖÕØÖÖÙ×ÖÚ×ÖÚ×ÖÚ×ÖÚ×ÖÚ×ÖÚØ×ÛØØÜØØÜØØÛÚØÙÚØØÚØØÚØØÚØØÚØØòññÚØØÚØØÚØØÚ×ØÚ×ØÚ×ØÚ×ÖÚ×ÕÚ×ÕÚ×ÕÚ×ÕÚ×ÕÚ×ÕÛÖÓÛÖÓÛÖÓÚÕÑÚÕÑÚÕÑÚÕÑÛÔÑýº¿¹¶½·´»µ³¿¹·Â½»À¼¹½º·¹¶³¶²¯³®¬¯«©®ªª®©ª°ª«´¬­¸®°º°²»²²¹²±³®¯«©¬ ¡§–™¡‘š…ˆ”€Žz|‰uvƒrspp~mo{lpympympxopxqqwrrxusuurqtqpsonsnmqmkominiemidkhdifcgebdcacc`ba_``^__]^_]]]\Z[ZWXVVXU\][_`_Y[YNPNKMKORP[]\aed]a`SWVFJJ>BB<@@@EEGLLMRRSYY¸»Ð´¹Ì²µÊ¯³Æ«¯Á¦ª½£¦¹¢¦¹¥¨¼ª­Áµ¹ËÀÄÔÈÍÜÇÌÜ¿ÃÔ´¸É°µÅ´¶ÆÁÂÏÌÌÙÍÎÙÅÇÑÁÂËÆÇÎÍÍÕÑÏØÎÍÖÏÎ×ÑÐÙÓÑÚÓÒÙÓÓÖÔÓ×ÕÕØÕÕØÕÕØÕÕØÕÕ×ÕÕ×ÕÕ×ÕÕ×ÕÕ×ÕÕ×ÖÕ××ÕÖ×ÕÕ×ÕÕ×ÕÕ×ÕÕ×ÕÕñðð×ÕÕ×ÕÕ×ÕÕÖÓÔÖÓÔÖÓÔ×ÔÓ×ÕÓ×ÕÓ×ÔÒÖÓÑÖÓÑ×ÓÑÙÕÐÚÕÐÚÕÐÙÔÐØÓÏØÓÏÙÓÎÚÓͼ¶¿¹³¼¶±º³®»µ±¾¹¶½¹¶º¶³·³°µ°­°«©­¨¥«¨Ÿ«§ ©¦¢¬©§¯¬®±¯²¯®¶¨©µž ¯”¤€ˆšt}‘hs‰]l†Ud€P`{M]yKZuIXsHVqFVnGWnHVmIVkKWkLXkRZhY]g^`iabjggnjjnijlihgigehecgdafc`ea^b`\a_\_]Z]]Z\\Z[[ZYZYYZWUWTTURVWV[\Z[\ZTVTJMJHJHJNMTXV\__]a`X\[OSSEII;?>5:9499¢¨»£©½£¨¼¥ª¾§¬Á¬±Æ³·Ì¸»Ñ¼¿Õ¿ÃÙ½ÂÖ¸¾Ñ®µÈ©¯Â¥«¾«±Åµ¼Ï¿ÂÔÁÁѼ½Ë¸¹Å»¼ÆÂÃÌÈÉÐÉÈÒÉÇÑÌÊÔÌÊÔÌÊÓÌËÕÎÌÔÏÏÒÑÐÓÒÑÕÒÑÕÒÑÕÒÑÕÒÒÒÒÒÑÒÒÑÒÒÑÒÒÑÒÒÑÒÒÑÔÑÒÔÑÒÔÑÒÔÑÒÔÑÒÔÑÒðïïÔÑÒÔÑÒÔÑÒÓÏÐÒÏÐÒÏÐÓÐÏÓÐÎÓÐÎÒÏÍÒÏÌÒÏÌÒÏÌÕÐÌÕÐÌÕÐÌÖÑÌÖÑÌÖÑÌ×ÐÊØÐÈÁº³½¶¯º³­¸²«·±ª»¶±¼·³¹µ±¶²®²®ª¯ª§¬¦¢©¤¨¥¡¤¤§ «”š¬‰‘¨}‰¥t‚¥p} jy›es•_nYiŠPc†K_‚G[~DWzAUw?Qt>Qr=Qs<Pp=No>Ml=Lj=Jg=Kf=Ke?LcALaEM`IPaOVcV[b]`ccdeddceb_e`\c^Z`]Z_\Y\ZW[ZXYYWXXWVWTUVSUVSRSPQROTURXYWXZVQSQILJEGEEIHMPOTXW]`_\a`W[[PTSGLK¸¼Ñ¹¾Ò»¾Ó¼ÀÔ¿ÃØ¿ÃÙ½ÂØ»¿Ó´¸Í¯´È©­Â¦«¿¨­Á­²Æ´¹Î¹½Óº½Ò´µÊ®°Ã¯°Âµ¶Ç¹»Ì¹¼Ë·ºÈ¼¼Ê¿½ËÀ¿ÍÀ¿ÍÀ¾ÌÁ¿ÎÃÂÎÈÈÏËËÐÍÍÒÍÎÑÍÎÑÎÏÑÎÎÎÍÍËÌÌËÌÌËÎÎÌÎÎÌÎÍÌÐÍÏÐÍÐÐÍÐÐÌÏÐÌÏÐÌÏîíîÐÍÎÐÌÍÐÌÍÏËÌÏËÌÎËËÌÉÈËÈÆËÈÆÊÆÅÉÆÄÉÆÄÊÆÅËÆÆËÆÆËÆÆËÇÇÌÇÇÌÇÇÎÆÅÐƹ±¯´¯­²®¬¯«©®ª¨´®ª¸°¬µ¯ª±­©®©¨«¦¨¤¢©™©Š‘¡u~–fs’_n•^o›`v¢bx¦bw¥]ržXl—SfN`‰GY€DV{BSx?Pt=Mr;Ko:In9Io8Im9Hl:Gj:Fh9Ef7Fh4Fh4De4Cb5A^5B\6CZ9EV=GUGMXQU[[[]_]\`\Z^ZW]YV[XUZXVYWUXVTVURUTQTTQTURRSOOPKNOJRSOUWUWYXSVSJMKCFD@CBCFDHLKLOOOTSRVU¶¹Ï¶¹Îµ¸Í²µÉ¯³Å­±Áª­¾©­¾©­¾¬°Á°³Å¸¹Ì¼½Ð½½Ñ¹ºÍµµÉ°±Å¯²Ç°´Ì´¸Ð´¸Ñ²·Ï°¶Î°´Ë²´È´µÈ¶¶É¶·Ê¶·Ê¶·Ê··È¸ºÆ½¿ÈÀÃÊÄÇËÆÉËÇÊËÈÈÈÇÇÅÆÆÄÆÆÄÈÈÆÈÈÆÈÈÈËÈËÌÈÍÌÈÍËÇÌÊÆËÊÆËìëìÉÆÈÈÅÆÈÄÅÈÄÅÇÃÄÆÂÃÅÁÂÄÀÁ¿ÀÁ½¿À¼¾À¼¾À¼ÀÀ¼ÂÀ¼ÂÀ¼ÂÀ¼ÂÀ¼ÂÀ¼Â»Àĺ¾®¨¬©¦ª§¥©¦£§¦¢¥­£¦²¨§²«¦¬©¨¦§¯—š¬y‚ŸZr–KeŒHbŒMf’Ng–Pi˜SkšUmšTl˜Qh•NeI`‹EZ…AU=Pz;Mw7Ir4Fn2Dl2Cj2Bi1Ah1Ag0@f0?e0?c1?b2?a2>`2>_/;]-;Y+:X,;Y.=X1=T5?P;COCJRORVZWX[WVZWUYVTXVSWUQWUOVSNTRPSRPRRORRLPQIMNHLMJNPMQTQSVSRURNPNILIDGD=@>;=<;?<§«Â¨«Â§ªÁ¨¬Áª¯Â¬±Ã®³Å³·É·»Í¸½Ï¹½Ï¹ºÌ¶·É³´Ç²³Æµ¶Ç¸¹Ë·ºÍµ¹Î´¸Î´¸Î³¸Í±¶Ì±´Ê±²Ç±±Å°±Ä±±Å±±Å±±Å±²Ä²´Ãµ·Ã·ºÃº½Ä¼¿Ä½ÁÄ¿ÀÁÀÀÀÁÁÂÂÂÂÃÂÃÃÂÃÃÂÄÄÀÅÅÀÆÅÀÆÅÀÆÆÁÇÆÁÇëéêÿÁ¾¿Á½¾Á½¾À¼½¿»¼¾¹¾½·¿»¶¾»µ½»¶½»¶¾»¶½»¶º¼¶º¼¶º¼¶º¼¶º¼¶º¼¶º½¶º«£¦©Ÿ¡¨¦››¤™š¤¢¦¢«£¦¯™§q€šSfŠH_ŠC_B_B]ŽB^ŽB]B]E`‘Ic“Jc“Ib‘F_ŽC\‰?V„;Q~7Ly5Iu1Eq.Al,>j+>h+=g+=f+<d*:c):a)9a*9_+9]+9]+9\+8[)7Y'7V$6T"4Q&6P(5N-8N09N4;L=?MJJTUTYXWWXURXUNWTLUSKTRLTRNSQNQOKPOIPOJNOJJKGHJFGIFJMIMOLSTQRTPMOLGJGBDB«¯È¬°È­°É®²É±¶Ê²·Ë²·Ê²·Ê²¶Ê°µÈ°´Æ²´Äµ·Æ¸¹Ê¹»Ì¹ºË¹ºË¸ºË¸¹Ê¸¹Ê¸ºË¸ºË·¸Éµ·È´µÆ²³Ä¯°Á­¯À­®¿­¯À®¯Á®°Â¯±Á°²¿²µ¿´·¾¶¹¿¸¹¾º¹¾¼¼Á¾½Â¾½Â¾½Â¾½Â¿»Á¿ºÀ¿ºÀÀ»ÁÀ»ÁÀ»Áéç龿¾¿Â¾¿Á½¾À¼½¿»¼¾¹¿½¸Á¼·À¼¶À½·Á½·Á½·¿¿·¸À·¶À·¶À·¶À·¶À·¶½¸¹»¸º®¥¢®Ÿ›«›˜§™š¤š š›¬‰“«jz—MdŠCa>a—=`™<Z‘;X8UŠ6Sˆ7Sˆ:VŠ>ZC^E`‘E_D]ŽAZŠ<U…8O~4Ix0Et-Bp+@m)>k(<i(<g(;f':e&8c%8a%7`&6^&6\&4Z&4Y&4Y%5X%5W!5T2P0O0P"0Q%2R*5S-5Q06K8<JFJPSSRWUNVTLVTKTRKSPKSOKRMJQLIPLHMMFLLGKKFHIDEGCEF@FGAIJCJKEJLFJMG¬°Ê®²Ë®²Ë­²Ê¯´Ê¯´È¯´È¯´È¯´Ç¯´È±¶È·¹Ç¹»É¼¾Ì½¿Ì½¿Ì½¿Í¾¾Ê¿½É¿½É¿¾É¿¾É¾¼È¼»Ç¸¹Çµ·Ä±³Á°²¿¯±¿¯±¾®°À®¯Ä®¯Ã®°Á±³Á³µÀ´·À··À¹¸À»ºÁ½»Ã½¼Ä½¼Ä¾¼Ã¿ºÁ¿ºÀ¿ºÀ¿ºÀ¿ºÀ¿ºÀéçèÁ½¾Ã¿ÀÄÀÁÄÀÁÄÀÁÄÀÁþÁ½À½À½À½À½Àý¾Æ½·Ç¼¶Ç¼¶Ç¼¶Ç¼¶Ç¼¶Ã¾º¿¾»²¨£²£­Ÿ¡£ž«•¬h{œJb‹D_Ec›Ce¡<aŸ8^š:W”9V’9U7SŠ7Tˆ9Vˆ>YŒB]E_‘E_E_C\Œ>W‡:P5Kz1Fu-Bp,An+?l)=j';g';f':e&8c&8a%7`%5^&5\&4[&4Y&4Y%4X$4W"4T!3R 1R/Q-Q-R"/T'4T+7Q-7K.6C8=DINPVWVWUQVTNURJVPIVNITMIQMHNLGLLEKJEKKELLGMMFNMELKCHH@DE?CD=°´Î²¶Ï²¶Ï²¶Ï³¸Í³¸Ì³¸Ì´¹Í´¹Í´¹ÍµºË¹»Ç¹»Çº¼Ç¼¾Ê¾ÁÌÁÃÏÅÄÍÆÃÊÆÃÊÆÃÊÄÂÉÃÀÇÁ¿Ç¾¿Ê»½È·ºÅ¶¸Ä´·Â²´¿°²Á°°Ç°±Ç°±Å±³Ã³µÂ´·Â··Â¹¸Â»¹Ä¼ºÅ»ºÄ»ºÄ¼ºÃ¿ºÁ¿ºÀ¿ºÀ¿ºÀ¿ºÀ¿ºÀèçè¿»¼Á½¾Â¾¿Â¾¿ÄÀÁÇÃÃÈÅÀȞȞȞȞȞɎÎùϹϹϹϹϹÊļÆŽ¸®¦¸«¦ª¥®‰¤Lf4Xˆ6\‘@c¡Dd¨Bb¥?_›<[–:W˜:V–9U’9UŽ:V‹;WŠ>ZŒA]C^D_‘D^C\?Yˆ;R‚7M}2Hw.Cr-Bo,@n)=k(;g';f':e&9d&8b%7a%6^&5\&5[&5Z&4Y%5Y%4Y&4V&3U&3U#1T"1S!.R,M-J$1K)6M*7J(5F,7F?CLTSUXVSXTKXSHYQGWOHSNHQMHOLGNKFOLGOLGOLFOKCOMDNLDLJCIG@µ¹ÑµºÑµºÑµºÑµ¹Î¶¹Í¶¹Í·ºÎ¸»Ï¸»Ï¹»Í¼½È¼¼Ç»¼ÇººÅ½½ÈÁÁÌÆÅÌÉÈÌÊÉÌÊÉÌÈÇÊÇÆÉÆÅÈÂÃÈ¿Àǽ¾Å»»Ä¸¹Ã¶¶Á´´Ã³²Æ³²Ä²±Ã´³ÃµµÄ··Ä¸·Á¹¸¿º¸Àº¹À¹¸À¹¸Àº¸À½¹À¾¹À¾¹À¿ºÀ¿ºÁ¿ºÁèæ轸½¿º¿À»¾¾º»À¼¼Ã¿¾ÈþËŽÌƽÍƼÍÇ»ÍÇ»ÎǹÒǶÒǶÐǹÏÇ»ÏÇ»ÐǺÒƸÒŹº´³£§¶j{œA\Œ8Z’6[”9]—?`ŸCb¢C`žB_˜B]•>Z—<X•;V‘<W<W=XŒ?YA[ŽB\C\C\ŽC[@X‰>U…9O€5Jy1Ft.Cq,Ao*>l(<i';f&:e&9d%8b$6a$5_%5]%5]%4\$4[$4Z$4Y&4W&4W&4W%2U$1T"0R.M,I,G-G#2J'5M&4K+2E7:DLMMWUMYSH\QH[OHWNIUMITLHSKGRKFQKDPJCPIBOIBLF@ID>GC=¶»Ð·¼Ñ·¼Ñ·¼Ð¹»Í¹»Ì¹»Ì»¼Î¼¾Ï¼¾Ï¾¾ÍÁÀÉÁÀÉÁ¿È½¼Å¾½ÆÁÀÈÆÆÉËËÉÌÌËÍÍÌÌÍËÌÍËÌÌËÉÉÇÇÇÆÅÅÆÂÁÅ¿¾Å½¼Å»¹Å¸¶Ä¶´Âµ³Á·µÃ¹·Å»¸Æ»¹Âº¹¾º¹¾º¹¾º¹¾º¹¾º¹¾¼¸¾¼·¾¼·¾½¸¿½¸¿½¸¿èæ轸À¿¹ÀÀ»¿À¼¼Á½»Ã¿»ÉÀ¾ÍÁ¿ÎþÏŽÏÅ»ÏƹÐƶÑȱÐȳÏȶÏȸÏȹÑǸÕŸÔƘŸ¯Tn–7]•8]š=]š?]—=[•A^˜EcœFb›EašD_—C^•A\“@Z‘?Z@Y?Y@YŽAZŽBZŽBZD[ŽD[CZ‹@V‡;Q‚6L{2Gv/Ds-Ap*?m)=j';g&9e&9d$7b#6`$6`%7`%7_$6^$5]"4["4Z#3X$3W$3V$3V$2U"1S 0Q.N,J)F*E"/I'4M(3J)2C06>DEDWRM]RM\OJ[OIXMGXLGWKFVLEUKCSJCQHCPGCLD@JB>IB=¸¾Ð¹¾Ñ¹¾Ñ¹¿Ï¼ÀɽÀǽÀÇÀÃÊÂÆÌÂÆÌÄÆËÇÇÉÇÇÈÇÇÈÉÈÊÉÉÊÉÉÊËËÇÌÎÆÎÏÈÏÐÉÎÏÈÎÏÈÎÏÈÎÏÆÍÎÅËÌÅÉÊÆÆÆÆÂÁþ½Ã»ºÅº¸Å¹·Ã¹·Ä»¹Æ¼ºÇ¾½Ä¾½Â¾½Â¾½Â¾½Â¾½Â¾½ÂÀ¼ÁÀ»ÁÀ»ÁÀ»À¿ºÀ¿ºÀèç鿺ÀÁ¼À¾¿ÄÀ¾Å¾ÇþËþÏÄ¿ÐƾÑǽÑÇ»ÑȹÑÉ·ÏÉ´ÐɳÒdzÔÆ´ÔƶÔƹÉÅÇ”¡¹Ng‹;`’6_š;`œ?^˜@]˜?]—@^˜FcIfŸIežHcœE`˜C^•A\“B\’A[‘AZAZB[BZŽC[ŽD\ŽE\ŽD[Œ@Vˆ;Rƒ7M}3Hw0Et-Bp+?n)=k(<h&:f&9d%7c#7a%8b&8a&7`%7_$5]"4[!3Y#3X#3W#2V$3V#2U"0S 0Q/O-L+H)D)D$0J'5I(5E*2C/2A?>FTPPXSL[RHZQF[OEZNEYMFYLFWKFTJDSHCOE@LC>KB<¼ÂѼÂѼÂѼÂÐÀÄÈÁÅÅÁÅÅÃÇÇÅÊÊÅÉÊÇÊÉËÌÈËÌÈËÌÈÌÍÉÌÍÈËÌÈÍÎÇÎÏÇÏÐÈÏÐÈÎÏÇÎÏÇÎÏÆÍÏÂÍÏÁÌÎÂËÍÅÉÊÆÆÆÄÃÃÅÁÀÈ¿¾Ç¾¼Æ¼»Ä¼»Ä¿½ÆÁÀÆÂÁÆÃÂÇÃÂÇÂÁÆÂÁÇÃÂÆÆÂÃÆÂÃÆÂÃÆÁÂÅÁÂÅÁÂêééþÁ¾¾Â¾¼Å½ÇĽÉƼÎƾÒÇ¿ÓÉ¿Ô˽Ô˺Ô˸ÓÌ·ÐÌ·ÓË´×ɳ×Ç·ÖÉÂÉÂņ“­Gkž:b˜7bž8aŸ=`?^—@^™A_š@_™FdKh¡Lh¢JgŸGc›Fa˜D^–D^”B\’@Z@YŽ@X@YBZŽD\E\ŽCZŒ@W‰<Rƒ8N~4Jz0Fu-Bq-Ao+?m*=k(;h(;g':f'9d&9c&8b&7a%7`$5]"4\!3Z"3Y#3X#2V#2V#2U#2U 0R/P.N-K,H+F -F$3F(7H)4K+2K-0C9=COQNZWM[SH\RF]RF\OG\NIZLHXKEVKDRGAOD>MC<ÀÆÒÁÈÔÁÈÔÂÈÓÄÉÍÅÉÊÅÉÊÆÊËÆÊËÆÊËÈÊÌÌÌÍÌÌÍÌÌÍÌÌÍÌÌÍÌÌÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÌÌÍÆÌÍÅÌÍÇÍÍÊÌÌÌËÊÌÈÈÌÆÅÊÄÃÉÃÂÇÁÀŽ¼Â½¼ÂÀ¿ÄÂÁÆÄÃÈÅÄÉÄÃÈÄÃÈÅÄÇÇÄÂÇÃÁÇÃÁÇÃÁÇÄÁÇÄÁëêéÇÃÁÅÁ¿Å½ÈżÉǼËɼÑʾÕËÀÖÍ¿ØϾÙѽÙÑ»ØѺÖÒ»ÚѹÝϺÙÎÆÃÅÑ}Ž¬Gh›>i¬:c¡;b <bŸ>aœ@a›B`œB`œCa›FdžKh¢Nj£Mi¢IežHc›Gb™E_–B]“@Z?XŽ?X@XŒAYŽBZŽCZAX‹@Wˆ=S…:P€6L}3Ix0Et.Dr-Ao+?l)=j)=i(<h(;f&9c%8b%8a%6`$6^#5]!4[#3Y#3X"2V"2U"1U"1T 0R/P/O.L!0M!/J".H$1G(5I+6M,6L+3F*2?6<CQOO^XR]TJ^TH^RH]OJ[NIYNFXMETJBRH@OF>»Â̽ÄͽÄͽÄÍÀÄÊÁÄÊÀÄÊÁÄËÂÅËÂÅËÃÅÌÅÄÍÅÄÍÅÄÍÅÄÍÅÄÍÅÄÎÅÃÍÄÃÍÄÃÍÄÃÍÄÃÍÄÃÍÄÃËÅÅÆÅÆÅÅÅÇÅÄÉÃÂÊÂÀÊÂÀÉÃÂÇÁÁÅÀÀÄÀ¿Ã½½Á¾½Á¿¾ÃÀ¿ÄÂÁÆÃÂÇÄÃÈÄÃÈÅÄÇÇÄÁÇÄ¿ÇÄ¿ÇÄ¿ÇÄ¿ÇÄ¿ëêéÈÅÁÊÇÂËÈÁÌÉ¿Í˾Ï;ÔÍ¿×Í¿ØÏ¿ÚÒ¾ÚÒ¼ÚÓºÚÓ¹ÙÔ¸ÜÒ¹ÞÑÁËÉÌzŽ­>i¢=k±Ci°Ac¢BcŸAcžAdŸ@d BcŸDcŸEcFdKh¢Ok¥Nk¤Lg KfžIdœGb™D_•B\’@Z@YŽ@YŽAYAZAYŒ@X‹@W‰=T†;Q‚8N6L{2Gw0Et.Cq,An*?l*>k)<i(;g&9d&8c&8b%7a$6_#6^"5\"3Z#3X"2W"2V"1U!0T 0S0Q/O.M!/L$0M$0L&/L)1J-5H.8E-6C*3C*0B;8CTNP]VP^UI^TH^PJ]OI[QFZPFVMBSJAQH?¹ÁϺÁиÀÏ·¿Í¶½Ì¶¼Ë¶¼Ë·½Ì·½Ì·½Ì¸½Ìº½Ìº½Ë»½Ë»½Ì»½Ì»½Ì¾½Ê¿½É¿¼È¿¼È¿¼È¿¼È¿¼È¾¿Ä½¿Ã½¿Ä¾¿Å¾¿Ç½¾Æ¾¾ÅÀ¿Ã¿¾Â½½Á¾½Á¾¾Á¿¿ÃÁÀÅÁÀÆÂÁÆÃÂÈÅÄÉÆÅÊÆÅÊÅÅÃÅÅÁÅÅÁÅÅÁÅÅÁÅÅÁëëéÉÆÂÌÉÃÎËÁÏÍ¿ÏμÐλØκÜμÜοÚÏÀØÎÀØÐÀÙÓ¹ÝÖ°ÖÖÀ¾ËÐsŽ®Ek ?k«Ak¯Fj¯Dc£Ed¡Ee¢Ef¢Ce¡DdŸDcDcœEcœIgŸNk£Pm¤Oj¡NhŸMfœKcšHa–E^’C\BZAYAXŒAXŠAWŠ@Wˆ@V‡?U…=Rƒ<Q€8M|5Iw2Ft0Dq.Ao,?k*=j+<h*<g);g(9f)9f(9d'8c&7a%7`%6]$4[#4Z$4Y#3W"2V 0S 0R /P-M!-K#/L&1M(1L+3L,5G.7E08E.4D)/A+/>8:CQQQ\WP^UK_SH_SI]SI[RHWOFTLCPI@¶¾Ñ¶¾Ñµ½Ð´¼Ï´¼Ï´¼Ï´¼Ï´¼Ï³»Ï³»Ï´¼Î·½Î·¾Î·½Î¸¾ÎºÀнÃÓÄÅÏÈÅÌÉÆÍÈÆÍÆÄËÆÄËÆÄÊÃÆÈÂÆÇÂÆÇÂÆÇÂÆÇÂÆÇÅÇÉÉÈÍÇÆËÆÅÊÄÃÈÄÃÈÄÃÈÄÃÈÄÃÉÄÃÈÄÃÉÅÄÊÇÆÌÈÇÌÆÈÅÆÈÃÆÈÃÆÈÃÆÈÃÆÈÃëëéÇÄÁÈÅÀÊÇ¿ÎÌÀÏξÐνØϽÜξÛÎÁÙÍÁØÍÁÙÏÂÛÒ¾ÝظÉÔÌy™¶?k¤>j®Ek¬Hk¬Hk¯Df¥Ef¥Hh¦Hg¦Gf£Fe FdœEc›Ec›GeœLi Ql£Sl¢Qj¡PhžNf›Lc˜H_“F]‘E[ŽDZBX‹BXŠAV‡AV†?T„?Sƒ>S‚=Q:N|7Jx5Hu3Fs1Dp/Am,?j,>h,=h,=i,<j+<i,;h*:f):e)9d(9a'8^&6]&6\%6[$4Y"1U"0T#1S"0P".M".J".J%1J)4K+5J,5H07G17F.4B(0?)1=;?DSRP]WO_UI_TH]TJ\SJXPGTMDQJB²ºÍ²ºÍ³»Î´¼Ï´¼Ï´¼Ï´¼Ïµ½Ðµ½Ñµ½Ð·¾Ð¹¿Ð¹¿Ï¹¿ÐºÀлÁѾÃÓÃÆÍÇÈÉËËÌÌÌÎÊËÌÊËÌÊËËÈÌÈÇÌÈÇÌÈÇÌÈÇÌÈÇÌÈÉÌÊËÊÏÉÈÍÈÇÌÇÆËÇÆËÇÆËÆÅÊÅÅÉÅÅÉÅÄÈÅÄÈÇÆÊÈÈÊËËÇÌËÆÌËÆÌËÆÌËÆÌËÆíìëÊÆÅÈÄÃÈÄÁÌÈÃÏÌÅÒÏÇÔÐÉÕÐÈ×ÐÄ×ÏÀØξÛοÜÑÅÑÕÓŒž²Jjš@h­?i´Dj±Hk°Jm±Fh¨Gi¨Jj©Jj§Ih¥Hg¢GfŸGeFdœFd›IfOk£Un¥Tm£Rk PhžNfšJb–H_“F]‘E\BYŒBXŠAWˆ@V‡>T…>S‚>R=Q€;O}8Kz6Iw4Hu2Fr0Co.Am-@k-@k-@l,?l,?k,?j+=i+=h*>g+=d)<b(:`'8^&6\%5[#2W$1W%3W%3U%3Q#1N!/K#/I'2K*4J+4H.5G28F28E.5D*1?-3=?@DXTQ`XP`WM_VM_VM[SJWPGTLD¯·Ê¯·Ê°¸Ë±¹Ì³»Î´¼Ïµ½Ðµ½Ñµ½Ðµ½Ð¶¾Ð¹¿Ï¹¿Ï¹¿Ï»ÁѼÂÒ»ÁѾÃÊÁÅÆÂÆÇÃÇÈÃÈÈÅÊËÈÌÌÆËÈÆËÇÆËÇÅÊÆÅÊÆÅÊÆÅÈÇÆÅÉÆÅÊÇÆËÇÆËÆÅÊÆÆÊÇÇÈÇÇÇÇÇÇÇÇÇÇÇÆÇÇÆÉÈÆÏÌÅÑÎÅÒÏÆÒÎÆÑÎÅÒÎÅïîëÑÍÈÎÊÅËÇÂÊÇÂÍÉÅÏËÈÑÍÌÒÎÊÓÏÁÔмÖϾÚÐÅÓÏÑ—©ÆQmœEg¨Bh¶Bj·Ek´Im²Lo³IjªIj©Jj©Jj¨Jj§Jj¥Ji¢Ih¡HgŸGeHeNj¢Sn¥Tn¤Rl¢QiŸNgœLd™Jb—H`”G^‘D[ŽBY‹BW‰AVˆ@V†?T…=Sƒ=Q<P9M|7Ky6Jv4Ht1Fr/Cn.Bm-Bm-Cn-Cn-Cm-Cl,Bm,Ak+@h+@g*?e)=c':`'9^&7\%5[%3Z%3X%3V&5U%4R#2N#0K$1K'3K)3H-4F17F17E16F,3E*2B05AHGL`ZXcZTbXPaXO\TLXPHTME±¹Ì±¹Ì±¹Ì±¹Ì²ºÍ´¼Ïµ½Ð·¿Ò¸ÀÓ·ÀÓ¸¿Ò¸¾Ï¸¾Î¸¾ÎºÀлÁÑ»ÁѺÁ̹ÁȹÀȹÀȺÁȼÄË¿ÆÌÂÆËÃÆÊÂÆÊÂÅÉÁÄÈÁÄÈÂÄÈÅÄÉÆÅËÈÇÌÉÈÍÉÈÍÉÈÍËËÊÌÍÈÌÍÈÌÍÈÍÍÈÍÎÉÏÏÉÔÏÆ×ÐÆØÒÇØÑÇ×ÐÆ×ÐÆñïëÕÔÂÓÒÀÑÏÁÒÐÄÑÏÅÐÌÅÓÉÇÔÉÂÒ̹ÏζÏÐÀÍÏΫ´ÈTuªAh«Ci´Ek¸El´Go¯Jp°NqµLm­Ll¬Jj©Jj©Lk©Ll¦Lk¥Kj£Ji¢Jh¡IgŸLi¡Sm¥Tm¥Tm¤Rk¡PiŸNfœLd™Jb—H`“F]DZBX‹AWˆAV‡@U†>S„=R‚<P€:N}8M{7Ky5Jw4Iu1Fr/Ep0Ep/Eo.En,Dm,Dm-En,Dl,Bj+Ch,Cg,Bf*@d)=a';^&8^&6_&5\%5Y$4T%4T%4Q%3P%1M'3L*4J-4H/6G05E.2E*0G'2H*3E58BPMOc[WcYQbXN]TKYQIWNFµ½Ðµ½Ðµ½Ðµ½Ð³»Î´¼Ïµ¾Ð¶¿Ñ¶¿Ñ¶¿Ñ·¿Ñ¸¾Ï¸¾Î¸¾Ï¹¿Ï¹¿Ï¹¿Ï¸¿Ï¸¿Ð¸¿Ð¸¿Ð¸ÀиÀѹÀнÁοÁξÁÎÀÂÏÁÃÐÁÃÐÂÃÍÅÄÉÆÆÊÈÈÍÌËÐÍÌÑÍÌÑÏÐÍÐÑËÐÑËÐÑËÑÒÌÔÕÏ××ÐÚÓÉÜÔÉÝÕÊÝÕÊÜÔÉÜÔÉòñêÚÚ»ÙÚ¼ÙÙÀÙØÃÙ×ÆÚÖÉáÑÉãÐÄßÔ¼ÖÕ»ÍÖÉ»ÉÓm„¨;h«;i´Bk·FmµGo¯IrªLs®Ps·No°Mo®Lm¬Lm«Nn¬Nn©Nm§Ml¦Lk¤Lj£Ki¡Li Rl¤Vo§Vp§Un¥Sl¢QižOg›Ld™Jb–H_’F\CZŒBXŠAWˆAV‡?T…>Sƒ=Q‚<P:N}9M{7Lz6Kx4Jv3Iu3Iu3Jt2Js0Jq/Iq/Ip.Gn-Gm-Gk.Gj/Hj/Gi,Cf)@b'=a(;b':`'9]&6X'7W&5T'4S(4R*6Q,5O-5K/5H05G.1F'.F$/H'2H/4B>;@^URg\SfZPaVM\SIWPFµÀÕµÁÖ¶ÁÖµÁÕ³ÀгÀÏ´Àг¿Ï²¾Î²¾Î´¾Ï·¾Ñ·¾Ñ·¾Ð¶½Ð·¾Ð¸¿Ñ¹ÂкÃκÃκÄÏ»ÅлÅмÅϾÅͽÃʺÀǺÀǼÂɽÃÊ¿ÃÊÁÃÉÂÃÉÂÄÊÆÈÎÈÉÐÉÊÑËÌÎÍÍÌÎÏÌÎÏÊÎÏÉÑÒÊÓÔÊ×ÔÈÙÕÉÚÖËÛ×ËÛ×ËÛ×ËóñëÞؾßؾßØÀßØÁàØÃáÙÅâ×ËåÖÇçؽàØÀÐÙÖ„£¿Am£>j­Al²Dl²Gn²Jq³Ks²Ls¶Nr»Nn´Nm±Pm¯Rm®Sn­No«MnªQm«Sl©Ql¦Oo£Mm Sk¥Vm¦Vo¦Vp¦Sp£PmžNi›Mf™Jc•I`’F^DZŒBX‰AWˆ@U‡>S„>Sƒ=R‚=Q€;P~8N{7My6Lx6Lw6Lw5Lw5Mv5Ov4Nu4Nu2Ms1Mr1Ms0Lq1Lq2Lp2Kp/Hl*Cg(@d'>a'=_&<^(:[(:Z(8X'6V*9X-;X.:T.8N08K08J-5F$/C"-D&1G)2D.5BDFJa[UbZS_VN[SKWPIµÁ×µÁ×µÁ×µÁ×´ÀÔ³ÀÓ³ÀÓ³ÀÓ³ÀÓ³ÀÓ´ÀÓ¸ÀÓ¸ÀÓ¸ÀÓ¶¾Ò·¿Ò¹ÁÔºÃÒºÄкÄкÄлÅлÅлÅнÄλÂ˹ÀÉ·¾Ç¸¿Ç¹ÀɼÂÊ¿ÂÉ¿ÂÉ¿ÂÊÂÅÌÃÆÍÅÈÏÈÉÍËÊÌÌÌËÍÎÉÎÏÈÏÑÇÑÒÇÔÒÆÖÔÇ×ÕÉØÖÊØÖÊØÖÊòðëÞÓÃÞÓÃßÓÃàÕÅàÕÅàÕÅÞÖÆßÖÁâÖ½ÞÙȱ¾ÈPu¢8j¬Bk¯El¯Fm±Ho³JqµLs¶MsºNr¾No·Qo³Sp°Vo¯Wp­Sq¯Ur°Zp®^q®_u­Yv©Ut¤Xp¨Vn§Wp¦Vr¦Sq£OnžOkœNhšMe—Jb”G`E\ŒBY‰AW‰?U‡=R„=R‚=R‚<Q;P9O|7Ny7Mx6Lw4Lw4Mw5Ow5Pw5Pw4Qw3Qv3Qw3Rw5Rx4Qw2Nt/Kp+Gm)Dj(Cg&Ac&@a&?`(<_*<^);](:[,?^0A]2@Y1<S1<O0;L+8I$1D".D$0G'3G*7H3<EPOP`\Z^XS[TOVQM¶ÂصÁ×µÁ×µÁØ´¿Ù³¿Ú³¿Ú´¿ÚµÀÛ´ÀÛ¶ÁÙºÂÕºÂÕºÂÕ¸ÀÔ¹ÁÔ»ÃÖ»ÃÖºÂÕºÃÕºÂÕ¹ÁÔ¹ÁÔ¹ÁÔ¹¿Ð¹¾Ï¹¿Ï¹¾Ï¹¿Ï»ÁѽÂÏ¿ÂÊ¿ÂÉ¿ÂÉÀÃÊÂÅÌÃÆÍÅÆÊÇÇÈÈÈÇÊÊÆÌÍÆÍÏÅÏÐÅÒÐÄÔÒÆÕÓÇÖÔÈÖÔÈÖÔÈñïìÚÑÊÚÑÊÛÑÊÜÒÌÜÓÌÜÓËÝÔÂÝÖ½Ú×ÅÈÏÎuŠ§Bg¥=j¸Bj°El¯Fm±Ho³JqµLs¶NtºPu½Pr·Sq³Vr²Xr¯Zr®Zt¯aw±l|³tƒ¶v†¸n…µf€°_w«Yq¤Xr¥Xt§Sr¤Pp¢QmŸQjOh™Ld•H`‘E]BYŠAW‰?U‡=S„=Rƒ=R‚<P:P~9O|8Nz7Ny6Ny6Oz6Oz6Pz6Ry5Sy4Sy3Rw1Rw0Qw1Qw2Qv2Qu0Ns,Jo+Hm*Gj(Eh(Df(Ce*@c*>a*=`(<^-@`/B`2B]3BY2?T1=P,;M&3H#/H#/H%1H(5H-6F>BKYX]]XZYUSVRP¶ÂصÁ×µÁ×µÁײ¾Ù±¼Ù¯º×®º×¯º×®º×°»Õ´¼Ð´¼Ï´¼Ï³»Ï´¼Ï´¼Ï´¼Ï³»Ð³»Ð³»Ï³»Ï´¼Ñ¶¾Ò¶¼Î·¼Î¸¾Ðº¿Ñ»ÀÒ»ÀÒ½ÂÐÁÄËÁÄËÁÄËÂÅÌÄÇÎÆÉÐÈÉÍÉÉËÊÊÉËËÇÍÎÇÏÐÆÑÒÇÓÒÆÔÒÆÔÒÆÔÒÆÔÒÆÒÐÄïîëÓËÉÓËÉÓÌÉÔÍÊÔÍÊÕÍÉÚÏ¿ÖнÎÔЙ¯ÂOpŸAi²@i½Bi°El¯Gn²Ip³JqµLs¶Nt¹Qv»QtµSt²Vt±Yu¯_x±j~´zŠ¹’œÂž¦Æž¨ÉŸÃ}’¹j‚­\v£Vq Wt¤Vt¦Sr¥Rn¢PkOi›Mf—Jb”H_D\ŒBY‹AW‰?Uˆ?T‡>T…=Rƒ<Q;R€9Q~8P|8P}8Q|6P{5Pz3Qy3Rx3Ry2Rx1Ry0Sx/Qu/Ps/Pt0Pt/Os.Nq-Kn*Im*Hl+Gk,Dh*Be'?a'=`*@b-C`2Ea4F^5EZ1AU+;Q&6M$1K"0K#1K'5J+7J2:JMQ]_^d]Z\XWU¶ÂصÁ×µÁ×µÁײ¿Õ²¾Ô±½Ô²¾Õ³¿Ö³¿Õ´¿Ô¶¾Ò¶¾Ò¶¾Ò¶¾Ò¶¾Ò¶¾Ò¶¿Ð¶¿Î¶¿Î·ÀϸÁиÁйÂкÁμÂξÄнÄнÃϽÃÏ¿ÄÎÂÅÌÂÅÌÃÆÍÇÊÑÉÌÓÉÌÓËÌÐÌÌÎÌÌËÍÎÊÑÒËÒÔÊÔÖÊ×ÕÉ×ÕÉ×ÕÉØÖÊ×ÕÉÖÔÈðïìÔÑÊÔÑÊÔÐÊÒÏÉÒÏÉÓÎÈÛÍÄÓÌȼËÚf‰¯=j¥Bm¸Bi¹Cj¯Fm°Ip´KrµLs¶Mt¸Pv¹RxºRv³Vv²Zw±^y±jƒ¸„•¿ª´ÏÇÍÜÓØßÐ×à¹ÄÖ•¦Áu²`{¢Uq›Ur Vu§Ts¨Qn¢RkžPjœNg™Me–Jb“G^DZŽBYŒBXŠ@W‰?U‡>T„=R‚;R€:Q8O}7P}6P|4Oz3Oy2Px2Qy1Sz1Ry/Ry.Rx/Ru0Rs1Su2Su1Rt1Rt1Pr0Os.Mq.Lp-Gk*Dh&Ad%?b(Bc+Db1Gc5Ia4H^0DX,@W):U&5S$3Q$3O&6O(9P-;P>HV\ag_aa\^ZãèñãèñäéñäéñäéïäéðåêðåêñåêðåêðåêñçêñçêñçêñçêñçêñçêñæêïåéíåéíæêíçëîæêîæêíçêìèëíèëíéëíéëíéëíéëîêëîêëîêëîëíïëìïêëîëëíëëìëëëëìêììéìíéííéîíéîíéîíéïîêïîêïíéïîêÖÕÉÖÕÊÖÕÊÖÕÊÖÕÊ×ÔÊßÏÌÙÒÜœ°ÏGs¦:n®Bp·FlµEl°Ho²KrµLt·Nu¸OvºRxºUzºUy¶Xy³^{´hƒ¹ƒšÌ±¿ÝÛâêçêçæçÞâåßÔÜß©¸É—·c£WsœSpžTs¦Ss¨So¥Sm QkPiœPhšLe—Jb“G]D[ŽCYŒBX‹AW‰@U‡?T„?V„>Uƒ;S9R€8R6Q}5R}5T|4U}4V}4V~1T|.Rz0Sw2Tv5Wy6Xz6Xy4Uv1Pt/Ot-Mr,Jo*Hl(Ei$Ae"@c%Bc(Dc/Id4Ld5K`1H[.E\,@\);Z'8Y%7U&8S';T+?U4DSR\bbih_d_ÀÌàÁÌáÁÍáÁÌàÂÌÝÃÌÝÄÍÝÄÍÝÃÌÝÃÌÝÄÍÜÇÐÙÇÐÙÇÐÙÈÑÚÈÒÚÈÒÚÉÑÙÈÏ×ÆÍÕÆÍÕÈÎ×ÈÎÖÇÎÖÉÏÖÊÏÖÊÏÖÊÐ×ÊÐ×ÊÐ×ÊÏÖËÍÓËÍÒËÍÓÌÎÓËÍÒÉËÐÊËÏËÌÎÊÌÍËÍÍÌÎÍÌÎÍÍÎÍÐÏÎÑÏÏÑÏÏÑÏÏÑÏÏÑÏÏÐÎÍÏÎÊÏÎÉÏÎÉÏÎÊÏÏÊÐÏÊÖÏÉÈÌÝl‹¾:n¯;s±Fq³MlµIn³Ho²KrµNu¸PwºQy¼Vz»YyºVx·Y{¹d¸{ŽÀ©µÝÛäïéííêëçéèäåååÜáå°½Ñ~–¾d«Ws PnŸQp£Rq¦Ur¦Wo£TlŸSiœQgšNd—K`“G^D\CZ‹CZŠBWˆ@V†?U…@W†>V„<Tƒ:T9S7T€7U5U€4U€4W4X1V1U€3U5V7X€8Y~6X{4Ux2Qu0Nt,Kq+Jp)Ip$Gm!Ek DiBg%Fg,Jf4Nf6Na4J\1J]0G]-B[,?[';X&9W(=X-C[7I[FS]cjmdhf¼ÊÞ½Ëß½Ëß½ËÞ¿ÊÜÀÊÛÀÊÛÁËÜÂËÝÂËÝÂÌÛÄÏ×ÄÏ×ÄÏ×ÄÐ×ÄÐ×ÄÐ×ÆÏØÇÎØÇÎØÆÎØÇÎØÇÎØÇÎÙÊÑÜËÒÜËÒÜÈÏÚÆÍØÆÍØÆÌÖÆÊÑÇÉÑÆÉÑÅÈÐÄÇÏÃÅÍÃÆËÄÇËÄÇËÄÈËÆÉÍÆÉÍÇÉÍËÉÎËÊÏËÊÏËÊÏËÊÏËÊÏËÊÍËËÊËËÊÌËÊÍÌËÍÌËÍÌÊÎÎ̪µÍSu°9o³<t²Ir³On¶KpµIp´Ls·Ov¹Pw»Ry¼Wy½Zx»Xw¸Z{·k‡·Ž¡ÆÄÏæéîðîîììêçêçåèæçÙÝ䨴Ìwºa{«Vr¢Qo Nn¢Op¥Vr¦Xp¥Vm¢SižRgœOd˜Lb•H_‘E]ŽC[‹BZ‰AX‡?V…=Tƒ>V…=U„;Tƒ:S7S6S5S4S€1S2U€2U1U€2U‚4V‚5V€5V5V}4Uz3Tw0Qv+Mt'Jr%Hr!FoDmDnDmEk#Gi(Hf2Oh7Qf6Ob3Nc2Kb/G`+A\(?\'=\)A]-F^:Pc=MYZdiflk¹Éà¸ÇÞ·ÇÞ¸ÇÞºÇÛºÇÚºÇÚ¼ÉܾÊݾÊݾËÜÀÍÚÀÍÚÀÍÚ¾ÌؾËؾËØ¿ÊÖÁËÖÃÍÙÄÎÙÃÌØÃÌØÃÌØÄÍÙÄÎÙÄÍÙÃÍÙÃÍØÃÍÙÃÌ×ÄÉÓÄÉÓÄÉÓÄÉÓÃÈÒÁÇÑÂÇÎÂÈÍÂÈÍÃÉÎÄÊÏÄÊÏÅÊÏÉÊÑÊÊÑÊÊÑÊËÑÊËÑÊËÑËÌÑÌÍÐÌÍÏÌÎÐÏÐÓÐÑÓÏÑÔÍÔÝŠœÀIl®>q·?u³Jt´Op¹Lr·KrµNu¸Ov¹PwºRy¼Wy¾Zx½Xy¹[}³pŽµ™°ÆÒÞçðòñðîêîëçëèçæäéÉÎÜ–£¾n†²\v¦Uq¡Qo Mm¡Mm¢Up¥Yp¥Wm£UkŸRhPfšMb–I`’F^E\CZ‹@Wˆ>U„;R‚;T‚;Uƒ:U‚7R€6R5R3Q~2Q~1P}1Q}2R1S€3U4V€3T~2T{2Tz1Tx1Tw.Sw(Nw$Lv"JvHsEqEqEoFl#Gk(Jj/Ol3Pk1Ng0Mi/Mh/Lg'D`(Ea(Eb+Jf/Nf7Sg8N[M]ders³ÅÞµÆàµÇàµÆà·ÇݸÇݸÇݹÈÞºÉߺÉß»Êß½Ìß½Ìß½Ìß¼ËÞ¼ËÞ¼ËÞ»ÈÙ¼ÈÖ¿ÊÙÁÍÛÄÐÞÄÐÞÄÐÞÄÐÞÁÍܾÊؾÊØ¿ËÙ¿ËÙÂÌÙÆÎÙÆÎÙÆÎÙÅÍØÅÍØÄÍØÃÌÕÃÌÔÅÎÕÆÏÖÆÏÖÆÏÖÆÏÖÉÎ×ÉÎ×ÉÎ×ËÏØÌÐÙËÐÙÌÑØÍÒ×ÍÒ×ÍÒ×ÏÔØÐÕÙÒØݼËáh‚¶Ekµ?p¸?r®Gs²Nr»Ms¸Mt·Mt·Mt¸Nv¹PwºVx½[x¾[|¼^·r‘·š°ÅÐÝæïñòñïîïìíëéíÔØ婶Ï“¶f¬Zu¥Ws£Rq£Nn¢Ll¡Qn¢Wo¤Wo¤Vl¢TjŸQgœMc—Ja“Ha’G_E]BZŠ>U†;Sƒ:T‚:Uƒ:U‚8T6S€4Q~3P}2P~1P}0O}0P~2S3U1S}/Oz.Ox0Sy1Ty0Tw/Sw*Px&Nw#Lu!KtIsGqGp"Io$Kn&Km*Mm.Pn-Ol,Ll+Ll(Jh$Ec)Lh*Lh.Pk.Qj4Ti7SbAXb\pt­ÂÞ­ÁÝ­ÁÝ­ÁݱÂܲÃÛ²ÃÛ³ÄÝ´ÅÞ´ÅÞµÆ߸Éá¸Éá¸ÉáºËãºËãºËã¼Ëß½ËÛ¼ËÛ¾ÌÜÀÏßÀÏßÁÏßÀÎÞ¿ÍݽÌܼÊÚ»ÉÙ»ÉÚ½ÊÙ¿ÊØ¿Ê×ÀËØÁÌÙÁÌÙÁÌÙÃÎØÄÐÙÆÒÛÇÓÛÇÒÛÇÒÛÇÒÛÉÑÛÊÑÛÉÑÛÈÐÚÈÏÚÈÏÚÇÏØÆÎÕÆÎÔÇÏÕÊÒØÌÔÚÎ×ß¡¸ÙOo±Cj¼Bp»Aq­Gs±Lr¼Mt¹Mt·Mt·Mt·Nu¹PwºVx¼[y¼[|½`‚½s¿’§É¼ÈßÝâíéêðâäìÌÑ⧴рšÁi‡´_z©Yt¤Vr¢Sp£No£Kl¡NjŸSj Ul¢Uk¡RhžOe›Ne™Jb•G_‘D\ŽC[ŒAY‰>V†<Tƒ9S‚9T‚9Tƒ8S‚7S4Q3Q~3Q1P~1P~1Q2S2T€0R|.Ny-Nw/Rx3V{6Z~9\€8Y~5V{0Sy+Pv)Ou&Mt'Nu)Ou)Ot(Nr'Np(No'Km%Hl$Hk#Hi#Ig+Pm-Sn.To-Sl3Vl7Vg;VaSlq¯Åá±Çã±Çã±Çâ±ÅÞ±ÄݱÄݲÅÞ²Æß²Æß²Æß²Åß²Åß²Åß²Åß²Åß²Åß³ÄÛµÅÙ·ÈÛºËÞ½Íà½Íà¼Íà¼Ìß¼Íà½Íà¼Ìß»ËÞ»ËÞ½ËÝ¿ÌÛ¿ÌÛ¿ËÛ¿ËÛ¿ËÛ¿ËÛÀÌÙÁÍØÃÏÙÄÐÚÄÐÛÄÐÛÅÐÛÆÏÛÆÎÚÆÎÚÆÎÚÆÍÚÆÎÚÃÌÖÀÊÑÀÉÒÁÊÑÂÌÑÃÍÓÂÎÙ€ÆBi±@i¼BoºBq­Fs²Ks¼Mt¸Mt·Mt·Mt·Nu¸PwºVyº[yº[|¾`€Ám‰Äƒ—ÉžªÔ²½Ù¸ÂØ®¸Ðš¨Ç€—¾g‰ºZ~³Yu¦Xs¤Ur£Rq£Oo£Mm¢LiŸOhQhžSk¡Um¡PhD\Ha”G`“C\ŽAY‹@Wˆ?V‡=T„9R‚7R€8R;V„;V…9Vƒ8Uƒ7Vƒ6Uƒ6Uƒ5Uƒ4V‚4V3U€1R}0R{0Sz3V|7[<^€@]>]~=]<]€7Y}2Uy.Sx,Rx*Qv)Pt'Os&Or'Os(Nu%Kq#Jm$Kl)Qo-Vr-Ur+Sp/Uo2Uj9WfNjs²Æß´Èá³Èá³Èà³Çà²Æß²Æß²Æß³Çà³Çà´Çà·Èà¸Èà¸ÈàºËâºÊâ¸Éá³Æß±Åß³Èâ´Éâ´Èâ´ÉãµÉâ´Éà´Éß´Éà¶Ëâ¸Íã·ÍãºÌà¿ÌÜ¿ÌÜÀÌÜÁÍÞÁÎÞÁÎÞÅÏàÇÏáÇÏáÇÏáÇÏáÇÏáÇÏáÆÎàÅÌÞÃÊÝÅÌÞÆÎàÆÎàÅÏÛÄÐØÆÍÞÈÎÙÅÐÍÂÓÒ³ÊÝcŽ¿;o¯<o±Ar³Cr²Fs´It¶MuµOvµPx·Pw·Px·Rz¹U{¹Y|¹Z~»\€½b…ÁmÉy˜Ð„žÓ…œÐ}•ÈtŒÀi‚¸_z±Yv¬Xu©Vs¦Tp£So¢Pm¡NlLjJgœJc™Ja—D_“9ZŒ#Fw2N‚>V‹>VŠ?W‹D\E\AYŠAY†?X…?Y†A[ˆ@[‡=X…<Xƒ:X‚:Yƒ:Yƒ8Yƒ7Y‚6X4X3W2W€1V/U}.U}0U|5X{7[}:^<_ƒ;_ƒ<`ƒ7\€/V{,Rw)Pu)Os)Pt)Qu&Qy&Qz"Mt Ko)Qu-Uw)RvLr Lq)Ts1VnEdv¨¼Ü©½Üª¾Þ¬Àß°Äà²Æá³Èâ¶Êå·Ìæ·Ìæ¸Ëå¹ËãºËâºËâ¹Êâ¸Éá¶Èß³Æà±Æá³Èã³Èä²Çã²Çã²Èâ³Éá³Éà³ÉàµËâ¶Ìã¶Ìã¸Ìá½ÌܽËܽÌÜÀÎÞÀÏßÀÏßÃÏàÅÎáÅÎáÅÎáÅÎáÅÎáÅÎáÅÏáÅÏáÅÏáÆÐãÇÑãÇÑãÅÓÞÄÔÜÈÐäÊÐßÅÑÐÁÔקÁÛSµ:q°=r°Bs³Es´Ht¶Ju¶Mu´OwµPx·Qy·Rz¹T|ºU|¹W{·X|¸Z~º]‚¾`…ÀdˆÃj‰Ãl‰Áh„¼b~¶]y°Yt«Wt©WtªUr¦Rp¤So£Rn¡OlžKkžJiLeœMe›Je™<_DsA^’PiLe™Kd–Jc–Ja”E^B\‰@Z‡@[ˆ@\ˆ?[ˆ<Y…;Yƒ:Yƒ9[ƒ8Zƒ6Y‚6Y4X€2X€1W€0W€.U+R|'Py(Qy*Sy*Tz,U{.X~.W},U{)Sz$Ov!Ls!Ls!Ms!Ms!Ls Nw!Ox MuIp&Pu.W{(SyIqIq#Or/Vq=^q¤¹â£¹â¦¼å©¿ç©¿à«Âß®Åã±Èæ³Êè´ËéµÊçµÉãµÉãµÉã¶ÉãµÈâ³Çá²Çá²Çâ´ÉäµÊå¶Ëæ¶Ëæ¶Ìæ¶Ìä·Íä·Íä·Íä·Íä·Íä¸Ìá¹ÊܹÊÛ¹ÊÛ¹ÉÛ¸ÉÛ¸ÉÛ¼ÊܾËܾËܾËܽÊܽÊÛ¼ÉÛ¾ËÜÀÍÞÁÎßÂÏàÂÏáÂÏáÁÑÜÀÒÛÃÎäÆÎàÂÐÕ¿Óßœ·ÚHv®<s±@u³Ct´Fu¶Jv·Kw·Mu´OwµPx·Rz¹T|ºU}¼U|¹Uy¶V{·X|¸Y}¹[»]€¼^~·_~¶]{²Zy¯Wv¬WuªXv«Vt¨Tr¦Sp¤Sp£Qo¢PlŸLkžJjžLgNfœNiž?a”>n?]ŽOhšLe–Jc”Ha‘D^C\‹A]Š?\ˆ=Z‡>[ˆ=[ˆ<[†<]‡>`‰=`‰;_‡9]†8]…6\ƒ5]…3\„2[ƒ0Z‚.X€*T}(U}&U~%T}#S|$T}#RzOwPyOyOxPyPyOxOwQy Pz"Qz#Px*U|1[,W~ MvLu#Ps0Yu;^s ¸ã¡¹ä¡ºå¡ºä¡»Ý¢½Ü¤¿Þ¨Ãâ­Çç²Ìì¶Ïî¸Ïì¸Ïì¸Ïì¸Ïì¸Ïì¸Îë¹ÏëºÏêºÏê¹Îé¸Íè¹ÎéºÏéºÐçºÐç»Ñè»Ñè»Ñè»Ñè¼Ñç½Ðå½Ïå¼Ïå½ÐåÀÓèÃÖëÅÖèÅÕåÅÕåÆÖæÇ×çÅÕåÃÓäÆÖæÆÖçÆ×çÉÙéÈØèÂÓã¾ÒܽÒÜÀÎæÁÍã½ÍÙ·Î㉦ÓGv±Ax¶Dy¸Fx¸Gv¶Jw¸Lw¸NvµOwµQy·S{¹S|ºS|ºU{¹Vz·Vz·W{·X|¸X|¸X|·X|´X|²Y|²Y{±Wz®Vy®Wx¬Xw¬XvªVt©Tq¥Ro£Qn¡Nm¡Lj MgžMd›Kgœ=`“BrDc‘Sl›RlšQk˜Pj–Mf“Id‘Fd‘C`?]Š>^Š?_‹?aŒ=_‰<_ˆ:`ˆ8^‡6]…5\„3[‚1\ƒ2]„4_‡3^†1]†0\„-[ƒ)Zƒ(Zƒ(Z‚(Y‚$V~!S{R{R{S|!V~"W€$Y‚%[ƒ#X"W€&X‚)Z‚/^„2`†1_…/]„+[‚,[€1^|7_w£Á墿䢿䢿㡾᡾ߠ¾ß¡¿à£Áâ¦ÄåªÆç®Çæ®Çæ®Çæ®Çæ®Çæ®Çæ²ÉæµÊåµÊå´Éä´Éä·Ìç»Ðê½Ôë½ÓêºÐç¹Ïæ¸Îå¸Îå·Íä¶Ìã¸Îå¹Ïæ¹Îæ»Ðè¾ÓêÄØêÇÙéÇÙéÈÚêÊÝìÍßîÎáðÎàðÎàðÎàðËÞíÇÚéÃÕä½ÓݺÑܹÉä¸ÆáµÇÚ¯Çäz˜ÎEs³By·Ez¸Gy¸Iw¸LyºNyºOx·Qy·R{¹T|»U}»U}»V}ºX|¹X|¸X|¸X|¸X|¸X|¸V|µW|³X}³X}²W|±W{¯Wz®Xw¬Xv«XuªVs§Ur¦Tq¤Qq¥Oo¥Pk¢PhŸLh>b•!IyIh–VqUpœRl˜Oi•Lf‘HdCbŽ@`Œ=]‰<]ˆ=^Š>a‹=b‹;a‰8`ˆ8`ˆ7`ˆ4^…1\‚.Z.Z‚.[ƒ,Z‚,Z‚-[„.]„.]‚.]‚.^‚+Z€)X})Y}&X~$W}&Z€(\‚'\'\€&\$\„%^ˆ'^ˆ(]†,aˆ.a‡-^„/`†2eŒ0dˆ/`~5bz¥Ãã¤Ãâ¤Ãâ¥Ãã¥Ãã¤Âã¢Áá¢Àà¢Áá£Ââ¥Ââ¦Âà§Âà§Âá§Âá§Âà¦ÁߧÁÞ©ÀÝ©ÀÝ©ÀݪÁݪÁÞ«ÂÝ®ÅÞ¯Çß°Èà²Éá³Êâ³Êã³Êâ³Ëâ¶Îå¹Ñé¼Ôë»ÓêºÒé¼Óæ¿Ôä¿Ôä¿Ôä¿ÕåÀÕåÀÕå½Òâ¼Òá»ÑáºÐà¹ÏÞ¸ÎÞ¶ÏÚ¶ÐܹËè»ÊèµÉ߬Éèp’ËCs´Bw·Ex¹IyºKyºNz»P{»P{¸R|¹S}ºU¼W€½W½W¼X~ºY~ºY}¹X|¸X{·X{·X}¶W~µY~´YµY´X~³Y|°Yy®Yw¬WvªWu©Vt§Us¦Ss¦Rr¦Rp¤Rm¢Om Cg˜+QLj–Vp›TošUn™Tm—Pj”Mh“Gg”Ee’Bc=_Œ;^‹=a@f?g<fŒ9dŠ8c‰8d‰8cˆ6eŠ5dŠ3cˆ1a‡/`†.`…0`ƒ4b‚5b‚5c‚6c„4a‚4a‚2bƒ+^+_0e†0d†0e†/e‡.gŒ)e)dŒ-f.gŒ1i6m‘6m3k0hŠ2g„7g£Àâ£Àâ¥Âä¦Ãä¥Âà¥Ãà§Åá§Åâ§Åá§Åá§Åâ¨Åã¨Åã¨Åã¦Äâ¥Âà£ÀÞ£Àà¤Àâ¤Àâ¤Áâ¦Ãä§Äå¨Åå¨ÅâªÇã«Éä¬Éå­Êæ¯Ìè²Îç·Ðå¹ÒæºÔè½Öê½Öë½Öë½Ôé¾Óç¾Óç¾Óè¿Ôé¿Ôé¾Ôè¼ÔçºÓæ¸Ñä¹Òå¹Ñå·Ðã´Ïß³Îâ·ÌïºÏï·Ôç®Öïf“ÅDu¸Fw¾Jy¾N{¾Ny»RzºR}ºPƒ»P„»Qƒ»Tƒ»V‚¼W¼V»U‚¹W¹X€¹Y¸[~¸\~¸^¸^·]¶\³Z}±Z|°Y{®Xz­Xz«WyªVy©Wx¨Uw¦Uw¥Tw£Tv¢Uu£Uu¢PpœHi”Ro—WqšYs›[uœZtœYs™Vq™Rp›PošNm˜Ji”Fh’EgGlIpHpEmDmDnCnŒAo@n>m‹>mŒ=m‹;kŠ;i‡=hƒ>hƒ=iƒ>i…>h…=i„:i‡5hˆ3g†2g†4iˆ6k‰7m‹4lŒ0j/kŽ/l0l2n‘3p“3q”3p’6p:oŠ9l„­Êë«Èé«ÈèªÇç¨Æã©Çã«ÉåªÉåªÈäªÈäªÈäªÈäªÈåªÈå©Çã©Æã©Çã¨Æå¨Åæ¨Åæ¨Åæ¨Åæ«Èé®Ìì°Îë±Ïì³Ñí³Ñí³ÒîµÓð·Ôí¹ÓèºÕé»Öë»Õê»Õê»Õê½Ôê½Óé»ÑçºÐæ»Ñç»ÑçºÑç¹Òç·ÒæµÐåµÏä´ÏäµÏä´Ðã´ÐçµÌòµÌî±Ðä¥Ïé\Œ¾Cv¸K|ÂN}ÂP}¿R}¼V~¼V€½S…½R…¼T„¼V„½Yƒ½Z‚½X„¼V‡¼W‡»Y†»[…»]ƒ»^ƒ»^„¹]„·]ƒ¶]ƒ·^„¶]ƒµ]‚´]ƒ´]‚²\±[¯Z~¯Y}­Z}¬[}«Z|ªXz§Yy§Wx¦Ww¤Vx¡Uw Xy¢[}¥]~¥\}¤\{ ^z›^y˜[w–Yt“Wr’TpUrYvZx‘VwUvTuŽTuŽTs’Ts“Ss”Qr’Qr’Qr’Ps‘NuMt‹Kr‹Jr‹JrŒJsIsŽGsŽGsErŽErEsŽEtBt=r<s’=u“?w–?x–<v–;xš9v–9s:rŒ9o‡¯Ìê­Ëé«Éç©Çä¥Ãà¦Äà¨ÆâªÈä«ÉåªÈäªÈã«Éã¯Íæ²Ðé±Ïè¯Íæ¬Ëä«Èä©Çå©Æä¨Æä©Æä¨Æä¨Æã©ÇãªÈä«Éå­Ëç®Ìè¯Íé±ÎèµÒé¸Õëº×î½Úð½Úñ½ÚñÀÚòÀØñ¾Öï¼Ôí»Óì»ÓìºÓì¸Ôë¶Óê´Ñè³Ðæ²Ðæ´Ñè´Óç±Ðê­Çî©Ãæ¤ÇÝ”ÁÝXŠ¾ExºL}ÀO~¿Q~¼V¾Z‚¾Z„¾W†¿W‡¿Z‡À^ˆÂaˆÄc‡Ã_ŠÀ[½\Œ½^‹½a‹¾bŠ¾d‰¾fŠ¼f‹»fŠ»eŠºb‡¶b†µa…µ`ƒµ^€³]±\~°[|­Z{«WyªVx©Tv§St¤Uv¦Qq¡NpŸFnšDošEošFp™IrœJsIr™Hp‘Iq’Ho‘GlŽFkEkFiŒHj‹IlJp‘Ip‘FmŽHoLoLoŽLpJoŽJoŽKqLrŽMsŒNuŒNuMuŽNvPx’QxRxRy‘S{“T{“S{“R{”Q|–N}—L}—L}—J|–I|•G}™E~B}›?y•=u;qˆ«Éä¬Êå«ÉãªÈã°ÎêµÓï¸Öò¹×óºØô»Ùõ»Úó¼Ûð¼Ûð¼ÛðºÙî¹Øí¹Øí·Õí³Òì±Ïé±Ïé³ÑëµÔî¸Öñ¸Öò·ÕñµÓï´Òî²Ðì¯Íé­Ëç¬Íç­Îç®Ïè°Ñë°Ñë°Ñë²Ïê³ÏëµÑìµÑìµÐìµÐì´Ðë®Îè¬ÍçªËå¨Èâ§Çá§Çá¦Éà¦Èã¦Ãì¥Ãè£Èá”ÃáYŽÃG{»OÀSƒÀW…À\ˆÁ_‰Á`ŠÂ^ŒÄ`ÆdÈfŒÈg‹ÈiŠÈgŒÃd½e½gŒ½h‹½h‡ºk‰¼o‰»oˆ¹m†·n†·l…¶i‚²h€±i€µ_v¬Zq¦Xo¤Uj Zp¥Rn£GhEgœFgœ@a•@a•Bc˜9b”8d•3^Ž/YŠ1\Œ6`5c‘+aŽ-c&[ˆ+^,_.a*\Œ'XŠ'XŠ,`‘-b“(\+`Ž2g‹0f…/f….f…-e„,e„2g„9fƒ;g„<h…=jˆ=kˆ>lŠDo‹Ep‰GrŒKvMx’Q{–S~šR}—Q˜R‚šR‚šS„R„N‚œMœLœHšE|”;s‰¶Õë²Ñç°Ïå¯Íä®Ìç®Ìé¯Íê±Ïë±Ïì°Îë¯Îç¯Îá±Ðã³Òå¶Õç¶Õè¶Õè¸Øì¸×íµÔê²Ðæ®Íã¯Íã¯Íä¯Íè­Ëè¬Êæ«Éæ«ÉåªÈä¨Çä¥Èä¦Èä¦Éå§Êæ¨Ëæ¨Êæ©Éæ«Éæ¬Ëè­Ìé¬Ëè¬Ëè¬Ëè©Ëè©Ìè©Ìè©Ìç¨Ëç§Êæ¦Ëä¤Èæ¤Äï¢ÃêžÆà’Ää[“ÉKÀT‡ÃYŠÄ]‹ÄbŽÄcŒÁbŒÀa‹Äa‰ÄaˆÄa…ÁbƒÀc‚Àd‚ºe‚³iƒµm„·o…¸o‚¶sƒ¸w‚¶x€µxµu~²py­py­hp¥mt°kq­ah£_f¡\cž_f M`š7W:[”:\•8Y‘0Pˆ-N†.S‹3Z’0W,S‰)O…,R‡2ZŒ2_Ž%R€:g Jy,W†&P M~MOƒ"T†$W‰!Vˆ$YŠ$\ˆY‚![„[ƒ"]… \„ Y€)^*^‚+_‚,`„,a„*_‚1eˆ1e‡2fˆ4i‹6k9o’=r”Et‘Hw“J|—MšPƒžR…¡T‡ V‡žS†žN‚›H~–>vŽ»Ùî»ÚîºÙí¹Øí·Õí·Ôî·Õî¶ÓíµÓì¶Ôí·Ôë¸Öç»Øé½Ûì¿Üí¿Üí¿Üí¿ÜðÀÝòÂßôÂßôÀÝò¾Ûï»Øî¹×ï¸Öï¶ÔíµÒì´ÒëµÒì³Òì®Ðê«Îè©ÌæªÍçªÍçªÌæ¬Íç¯Îé°Ðë²Ñí³Óî´Óî´Ôî²Óí³Õî´Öï´Öï±Óì­Ïè©Íä¦Ìä§Éê§Èé¤Ëæ™Éìa–ÌT…¿^‹Ã^ŽÆ]Æ[ŒÃZˆÀW…½TºT|·Wy¶\z¸a}½a{¼fz³ky«o~µn}·pz´zµ||­|x­~w­„¹‚y­wp¦ro§vx²ek¥[`œeg¦ca¡_[›d^KX”0h.L„C_˜7S‹/M„1P‡3QŠ-K…9Y’;]”-Q‡*O„(M~Ai0X.W5^?i"Bl Cp Fv,Tƒ,Tƒ(Q*U„ M| P€QOSR€RS€S|W€ ZƒVZ‚"]…#]‡ [†]ˆ ^ˆ#_‡-d‹7i?j…Akƒ5bz,Zr7i‚H}˜M›SƒT†ŸP„›L—C|ÀÜîÀÝîÁÝîÀÜîÀÜîÀÜîÂÞðÅáóÈäöÉå÷ÊåöÊãñÊâñÊãñÊãòÊãòÊãòÉâóÈàóÈàóÈàóÇßòÄÜïÀÙì¿Úì½Ùë¼Øê»×é¼Øê¼Øê¹×êµÖê¶×ë·Øì¸Ùî·Øì¶Öë¶×ì¸ÙíºÚïºÛïºÛï¼Üñ½Ýñ¼Úì¼Ùë¼Ùë¾Úì¿Ûí¾Ûí»Üê·ÞçºÜç¼Ûê¹Ùñ±×úv¢Ða‡ºhŽÂ^ÃQ‹ÁF‚½E~¾Bw¸Bu±Nx¶Vs´Yn±Re©Ma¤nz²rs¥oq«vx¸ŠˆÄ„{«‰zž›‰³…p›t›™~¤Šv¢rhrn¤qi›oi ^]˜SX”CO†<Lz$=k
+*\2g8L‚GYF^‘5O‚AVŒEZC]6T‡>n
+1_9d>e.T4] Fs>m@q'M(O‚!I|DvAsI{L|$TƒQ~P|P{O{JvLxP{TR}R{!\…"\†U‚S‚]Š\ˆ Z/X}Fd‚JexC^l7T`"BO:K&VlAt‘Dy›K€ŸN‚›N„–HÆáðÆâðÆâðÆáðÅàïÆáðÇãñÉäóÊåôÌçöÎçõÏåóÏåòÏåòÏåòÏåòÏåòÏåôÏäöÏåöÎäõËáòÉÞïÇÝîÇáðÆáðÄßîÃÞíÃÞíÃÞíÁÞî¾Ýð½Üï½Ûï¿Þñ¾Ýñ½Üï¼Ûï¾Üð¿ÞñÁàóÄãöÅäøÇåøÉåôÉäóÉäóÊåôËæõËæõÊçòÊèîÎçíÐæïÎåöÆãýŠ¯Ôa‹¾\ÆM†¾?¸?~¹9s±9n°;m²?i¯Ml³Neª<T• ;xXp©s~³|v§‡sž¤³£’·‡} œŽ­™…Ÿ§§µžµ›‰£oc„ˆ{žŸ†ª|iTN|6?k!7[6Q-O)X&X$Y)].a5f"=o+F{'Dw'Cv7U†4Rƒ%Gv<e-V4_ Ft%I{(L~)N€&M~Ex Gy?qEw J| O}KxMyO{RQ~IvP}U‚IuFpMwItErLxZ„\„!Wz4^|Gf€Gdw7Ud+HT"?L;J=Q%Uo:s“@z˜G~—N–OÎåóÎåóÎæóÏæôÍåóÎåóÏæôÎåóÍåòÎæôÐæóÓæñÓæñÓæñÑåðÑäïÑäïÒåòÓæõÓæõÒåôÐãòÑäóÒæõÐçõÎæôÍåòÌäòÌäñÌäñËäóÊåõÉäõÈãôÇâóÆáòÅàñÃÞïÃÞïÄßðÅàñÆáòÇãóÉãóËãñÌãñÌãñÍäòÍåòÍäòÎæðÑçëÔæéÖäéÒãíÎå÷›»×^ÀJ…Â;|µ3v¬/n¤9o¦5d¡3_¦9^§Faª<S—#<y.e)Kƒ_u«~wŸ¨ˆ¢»–¬š„ž{v–‰{›“}›†o–€ž—Ÿ‚mŒ]QmNYmALh?BlXS…€u©‚s¦.=k
+>j =iDnFqDmNt%Yy&Tl4^q>fz7[m.M[ ;F7E4E7M+d6s?x“J|“U’ÐåðÑæòÓèôÔéõÓèôÓèôÓèôÒçóÒçòÒçòÓæñÕæðÕæïÕæïÕçïÕçðÕçðÕæñÕæóÕæóÕæóÖæôÖæôÕçôÓçóÒçóÒçóÓèôÔéõÔéõÓéöÐè÷ÏçöÎæõÍåóÌåóÌåóËãòÊãñÊãñËãòÌåóÌåóÍåóÐåòÑæñÑæñÑæñÑæñÑæñÑåñÑåîÔäê×äéÖæîÐè÷«Ëâ\Ž¿B»5u«0oŸ6l˜3]‡6d.h.H…?R‘=M‹DW“5Oˆ ,c4gOT|•ƒ ¡ˆƒq†jby|j†©‘²€kŽzf‰´œ½½¡½¢‚œŸ€¤ˆ®h™[JULƒTQ„)>k(R,YBSƒHR„4=o.;m5j6l3i 6l)Av&=r6i8d .Z*X8i/Oƒ3T‰1S„$HwCq Dr%Hv&Iw'Ky)P-V„.X† Lz<j 9g>nBqEsJyJxCpAnEqErBnFoWw(aw7n€;o„)Ti AP!:F#7C,?M.A!Rl3lŠ6pBvW„–ÕèòÕèò×éôØëõ×êô×êô×êô×éóÖéóÖéóØéòÜëòÝìòÞíôßîôÝìóÜëòÛéòÙçóÙçóÚèóÛéõÛéõÛêõÙëõÙëõÙëõ×êôÖèóÖèóÔèóÑçôÑçôÑçôÒèöÒéöÒéöÓé÷Ôê÷Ôê÷ÓéöÑçõÑçõÑçôÓæñÓæðÓæðÓæðÓæðÓæðÑæôÎç÷ÒæòÔåîÐæðÌè÷°Õë^‘¿=x¯0lš<r˜Bl‹,Gc-I%HGLS„^b™LUEU’-c&Bp=Sƒ>Hv[[~tj¨™¡¼§«ÚÆÌ­ž¨s~¶¡§°’£xtˆĎž”i„}an`€b_|4Gh'Q%TMPƒytªqj ie›\dO]—0@y0g6k5h/` .[
++X
+*Y$Dv>]’2Q‡&Gx#Er Cn#Eq Bn<h$Gs,P~,R*R$M|GvFu@p=n>n<l =k?mCqGvGxIzJwUy&kƒ,s…+h"Ri@R3?&4=#-8"4%Jf4f‡3kŒ=s\‹žÜëôÝëôÞìõÞíöÝìöÝì÷ÞìöÞìöáî÷áíöáíöâïø×æô¹ÌÝ©¾ÏÅÜçÞôúàï÷âí÷âí÷áìößêôßêôßêôÝêóÜëóÜëóÜëóÜëóÜëóÜëõÛìöÙêô×èó×çò×çò×çòØèóØéôØéôØéôÙéôÙéôØéóÖéñÕèïÕèïÕèïÖèðÖèïÔèôÑèùÓè÷ÔçôÓèöÒìûÃãöiŸÈ0s£#e‹=y•8d{"<Q,@+< ,7<bab•SUŽLRŽ$:m3^5UˆE[SYƒƒyØÄÊÑ»º›Š‡À´­ÏùèØÍàȾʯ§Ì·­Ñ¶°É¤£Ëž¥É–¨·…UHh.V+6b'&Wka•gVS@zME€BC~JQŠHT‹BU‹;S‰3N‚ =m-^,^0d"Av.N‚.O~0S1T€+NzAp=l@pBr=m@o)O,Q‚)O€ Hv$My(Q~Gt@l =jBqEx @x Cy Ev"]‚9vŒ0lz,^r*Vh)JW(8E).<+&:+Pr.`ˆ4k?q‹h”¢èñøèñøèñøèñøèñùèñùèñøéñ÷êñ÷ìñöèð÷ËÝëtŽª1Qv6Y2Tk§ÅÎãõúêóúêóúéòùçï÷æï÷æï÷æï÷æï÷æï÷æï÷æï÷æï÷æï÷æïöæð÷æïöåîõäíôäíôåïöæïöæïöæïöæïöæïöåðöÞðôÛîòÚíñÚíñÛîòÛîòÜíôÝìøÝìøÝìøÝìøßîùÚìú³×+v /}œ:‚™Th3I+?"/'/6\ty¬lm¦WW3I{2`<lJW†SOu}”¸£°…q‰~nƒË¾ÂóèãÎÃÉy‰tc}n\q†jt’ij½ŒŒÕ¡­Â«|g‰07\NSy20[pg–Šx¬wa˜l_—jeœji¡`e›[dœP^•;N…#<r5P†)Ez3g8j1c
+.Y4]=gBoBr@t<q#Dv"Cu6f7e=k9e3]?e:`†<dŒ Lt 9cDoJ}JH}M{ Qr"K^<G;FLS(PX.DO,3C&6 <S+Z„%_,b‰Jr†Ÿ§ð÷ýïöüïöüï÷ûðø÷ðøõïøõñúøïø÷òúúÀÓØ]†š4aCl9c
+(GI^pÜèîñøýïöüïöüîõûîõûîõûîõûîõûîõûîõûîõûîõûîõûîõûîõûîõûìóùìóùìóùêñ÷éðöéðöéðöéðöéðöéñöæô÷äóöãòôãòõäóöäóöæò÷èñ÷èñøèð÷çïöçïöëõý¦ÊäC|¥6v— `z#Tk!;R#+C";#F:=nae _d¢ELˆ:L8e*ZOYˆ|y¡†y”“€“k\~^St“‹›ôîòžÃh`oj_v~l„²˜©ÀŸ¦ª‚Šrƒ­‚Ÿ¤Œ°TMswŸcY„I?m`W‡QIzA>o;;nJN‚Zc—ZiSešI_“.E{;TŠ3N)Gy*J|4e(T)S)T*V*Y6g:l/^ -X
+-W
+/V-Q1Q
+2S:\'Mo+Pp<\7V!Cb+Kn+Mu!HoAf<Z 0H.?JR:w{4ot+R[#8D*3!FY'\‰$c–']…W|Ž§­ó÷ûô÷ûô÷ûô÷úôøñôúðòùñòûöïû÷ðüú¢¾Ã>zSv:f7c(ILWlàäìôøüóöúóöúòõùòõùòõùòõùòõùòõùòõùòõùòõùòöúó÷ûó÷ûó÷ûó÷ûó÷ûó÷úòöúòõùòõùòöúóöúóöúò÷úñùûðøûï÷úðøúï÷ùîöùïöøñõøñõøòöùóøúðô÷áæê½ÒåPu›
+6YDc1c}2Kb%=7')UDF}pt²af¥EMˆIO‚X\ˆ-4bDKy  É€w˜o^zocˆXRu’Ž¤øöýäâê{y†aZnjWt{f~†˜uˆ\?WxWx„l‘L<bxeŽxd6(U<9e>Am57f+-^/6h.:n,<q)?s3K€.F}:SŠ+G}2O„)K~!Cw<n6i /a)Z*\,],]-Y/X,Q,K/H2G 6N6V9W!?Z8QhSh|[m€IWm.=W#9S:U:VHeRn=m|E‚Š:x‚/Sd+4C/@V†"e/f…¡±»ÇÆùùúùùúùùúùùùùùñøùðõúôôüùñýýáðò‚¢«,h€$`ƒ >i1Z2Db¦«¸úùýúûüúúûúúûùùúùùúùùúùùúùùúùùúùùúùùúùùúùúûúúüúúüúûüûûýûüýûüýûûýûûýûûýúûüùúûùúûùúûúüüúüýúüýúüýûýýùûüöúüôûýéñôÛâæÔÛ߯·¼hpwGSi=[y%[z+nŒC|—4Ui&92(1[>DyadžFFNMƒaV…m˜g`Œ"$QIKv[U|^Psynˆ›”¨ÉÂÓòëößØ㦞°bWohUvaPqL@]cWs_On\FisaƒM>adMu¥ˆµ‡qžRLulq™qpžVRƒ<<m27j/:n(8lHZ1F{6k2L€MjNlŸHhš>a•9]“/S‡>p9g8e 2\/S2R3N9O:XhSmyWmzXl~^q‚gx‡jy†gs~]grFNXDKT_isFYf<\pEtŽV‹¨]‰œD|Œ/k4Sl*)?1&. '0Gi!W‚Fr’³ÅÎÏÓÏþýüþýüþýüþýúþû÷ýüøùûûãëÇk}Šjˆ™u¨À?r“?f0Rš¨ºùûýÿýüþýûþýûþýûþýûþýüþýüþýûþýûþýûþýûþýüþýüþþüÿþüÿþüÿþüþþüþýüþýüÿÿýÿÿþÿÿþþþüüûúüûúýüúþýûþýüþýüýüûÿþýþüûó÷ùÌÚ⌚¥rŒo~‰YhsFT`S_qFbz@z–7„ /tŒ(Td$=J '<.OR^Š|~±`XŒ`Tƒ“x£”pš†u BAn25cZW‚aT{±¤¯ýóóûñ÷µ¨¶scxo^x`MjkV{ZMsD@dMLpLEjTFjg^}XQojTz¨‡²¥‡´dV€\[ƒ‹€¯‰{­|r¥to¢ghfk¡eo¥):o%XF]Mh™?\ŒBa‘Gg›Ab™Bc˜@a’;]‰;^‡9_„+_{+^w5\qYq‚s}‰}{„zv{tvwvz|pwzW`eHRZLX`EOT[`cmrr_jlNdn6\pEv:r‚,x†,}+`w0AS<>?4:5"5B'Jdb“¿ÇÊ¿¿¹þýúúüúöþýõÿÿöÿþô÷úÈÌÔz‰“Xr~Rj{Gi€>~™4m&Os8Zzˆ¡ÌÓáÞÙåôñøõûü÷þûýüøÿûõûýôóÿõøÿ÷üþùùþûøþþýüþÿûÿþÿÿþÿÿþÿÿýþþýþþýþþþþþþÿþþÿþüÿþúþýùþüøÿýöÿÿúÿþüÿû÷üù×åè§À̃£´h†—av‡WgvDTdNevHgx9Zj/Zl2o‡.sB~•6]m5LU;MYCSdUcyck‡XWuLCczpŒŽ€†±ˆ~¯'7d1Dp]\…²¥¢ùíÙúòêÄ»ÀuhyhSmˆoŠjQjdRnWNo[UzUJq^MsaXzQJk[BltX‡WJy:>k>GsZZ‡rnz«|v¨wq¤wp¥in 'Bm*U1O{7TƒGc“OkœFo•IlYfŽXq•T‰¢\‘ªe‹¨U SŠ™Tx†Zkwcfnrmqhdc\^XYa^FTT1BFFW[m|~rur{}xEUU>[c&IW&H[?_r7hq/w€1‡—!j}1[e0A;FF9ZTPGOXVcogmq^aZþýùõúøØèé¿ÙÞ¾Þæ ·È]q‰Io†Dz8f‚7iŠ5€¡'f‰%OtF`„cv˜]pP^z{“¦¥ÌÒÈåèñùûüúúúýøøýöýùöÿøùüþþ÷ÿÿýýÿÿüÿþþÿýÿÿýÿÿþÿÿþÿÿþÿÿþþÿþþÿýÿÿúþþõüýàéé¸ÇÊœ½É¤ÁÊ»ÏÑœ³¶iœE{˜7lˆ?`nFYe9DQCQ`Ol8ez.dt Yi)cz5k…8cz,IZ2BNDJUakthxbt}YfrQWg?LZQm|\z“Ws™"8f3Bs:Bl²šœûÜÌþèÞûíèż¹µ¯©æÜÖ¶¢¡yhpZQfPKjLFiOEiUOpH;^T5a[Dt:>k/[/_1Bm/@i=Isjpuv¥sp ir›?d€-Qm4VvKjŽMgUl—YpŽgr‰hp‰U™=¢¢@‡”\iŠOt‡Do{AWePVcZW`^[^VUULMMDLQ6CM*9DGQYty}vunS^V4]a(gv\pPb'JXFajGp}%^r*cw-P\+00K>6RD<KFJ]bmW`iQ[Xüþûõûú¿ÎÒ\w‚2_t>eƒKn‘1hb‡%f’@y¨-i‘!V|"KpFfˆbXwBl‰/pŠ7ƒ–5pƒ€¡¶ÃÝèÓîõöøÿÿöÿÿòþþüþúÿüýÿúÿýúÿþýÿþýÿÿýÿÿýÿÿýÿÿþÿýÿÿýÿÿþÿûýÿùýÿÓÚÛr‰%Jf;U/M^MhvWvŠ>gƒ?auixz€‡ˆrw{es}<Yl+Wp!Wk%^p9p…>m…Flƒ4Ob?Qb7EX<O`rŒ™oŠ•NfoHYbO[iEm{2Ž”4 *Tz6Ap>RwNfnŒ˜˜®«²Â¯³ïÓÌÿâÊúÜ¿ëÒÅžŒc]kCD_@CeTUyQMlgTqŠhŽ`Hq==c.8`$)V+T1V/U=T{Tj‘EZD[|Edt?\l(DV>WnRhƒVj‡RdSYwMVt6gz#zƒ"j{0Ll#?W1D'5H9;M>:I6/<.(4#!/"5#:"*@NPbyu‚fhkAWX8gqbt^qYiVcMl|Om€<`vKm8IWEBIVNO)))7<FEO_@MZS_c÷üûñúûåôø§³[|Š¥½ËÈßí=j† Hg+fŽ.^ŒLwEm;_Cb?Z8P(KkOs[x!fƒOo2€›D¡²p¬·º×Þçõüïÿÿðÿüûù÷þö÷úúûúüýùûüùúüùûüúûýúúþùùÿøúÿöúÿôúýñùû©¸À:Vl":NsƒÕàæßéíØäëãìðõ÷ôûýùùÿý¨¸¾+I\<W7O%\p<l€7^r5Ti.F\$7N$6N!:P6Vh!BP2?+AOFUh?Tn$Zqbuqƒ\rD_o'Š4v“;TqíÅÀûÉ»¹‘ŒtV]`NcVKmPFoJ?kJ?`mXsÓÇÔ¿¶Å±±¿³µÄµ²Å§¬½ ª¹ «¹Ÿ«º¡®¼¡°¾©·Á§¬š£§›¤©Ÿ¨¯£­´¢«´Ÿ¬µ¡¬·¦¨·£¨·­ºµÀœ³½Ÿ¯¹Ÿ­·ž«µ£®·§±¹¢ª²¥­µ¡ª³ž©´Ÿ«· ¬·©²»¼ÁÇ·¹¾²µ¼­¶¿¤³½¤¸Â ·À§¿ÆºÏÖ·ËѲÂÇ­º½®¸»·¾À°·¹¦­¯­³¸¨®´­²¸ºÀÃëóôçñõâñúÛïùßñôï÷ûËÔß3Sf"Xn%Xw 6_3_2Z-O*G&A*H_•¥¹|©LwDt‹/a{iˆ”ˆ’+v…a“£šÄÎÊìðåîöíëöìõüéôúçòúèóûèóûçòúçñúæðùåñùãòùäõúßóöÌàä´ÈÏ´ÅÌØæéëôôëñîíñíìððêðõæòóæ÷÷–­´"AT ,HEa7l„&Oc9K+>+B+C 4-1
+:Z=U?[m8DV9;P8;T(/J%@+D-Xn7~0o{5^b:UT4PO*OR;@28"2;$/19D<GOáìîßêñÛé÷ÖéúÖìòßëô•£¶(Nf+h…YEs4_
+š°™«iw;anGaw2Ol*Il <c/Bi6@cADdNFhÄ¿Í;=e#4]'._RA|~i¡iZŽB<l27d&7_/U.R0Q(J $G%J(O'N )P (L
+4d<l4_$>bK\w2GX&<H/:H(.> ((<M9`r_x%Vi8IP:;<)03&0 /9-0$)$ÎëøÍæôËãòÎè÷ÎìöÐíù~œ²&Qm$_Sw<c
+
+  BRR±Úì°×ì°Öê´Ûî§×ç£Ðäy¸>]#Ci>f 1Z *Q%K8\z¥Å Ñì˜ËåšÈà§Ñè³Ýò¼æú±Üò±Ûó³Þõ£ÓêžÑçŸÒè¥×í¥ØîŸÑè›Ìâ–ÈܘËàšÏåœÔëœÖï—Ñì“Ìë’Èé—Êé¦Õð²Üô¸ÞòÀä÷ºÞñ´Øë­ÓçªÒç¦Ðæ¥Ðè¡Ïå¨Øë®ÛÉ1Of%=V@Wp*TjEZ8N
+#;1+*/
+!G@o5\“;u7pDZ’dj£jh¢WOˆNF{sp¡or¡vm¡zb”}VzEh›]}¶u—¹u–¾x”Ë€£Íƒ­¿}ª–d]>`F6\,5\©³¾.J>@aj]€SIk;:`8;d;Al1=i0\#8e3]!6[,R1X*En1My+Jw=g7_ /W2Z /W .V1Y5_;l%B}4P‘5Q’4QŒ)K
+4b0]
+5_5VG`uL\f*;G'>L";H">JTs~jŠ•7bnUi H^)0B6:D-4')!$')&(*.k„‹©Ôì°Üô°Üõ©Øð Øí¢Öîl”³:Y'Dl=g%Ck6\$IIm Íë˜ÍëÈä—Ìè¦ÖñªÚòªÚñ¦ÖñœÌè”Åá‘Çå”Ìê˜ÐìšÑížÕòšÒðÈå‘Éã–Ïê“ÎéÌéŽËéŒÊé“Ñò“Îò’Ëí”Èè”ÅáÊã¤Ðè ÏéÌæšÈãžÌå¡Îç§Õí¬Ýô¬àöªÙï™ÀÖ?\s+@WGYo)I^'Lb:Q1((* C:hAu&V(Y“<t$D{UgŸ_f RRŒ_\“qq¥mr£enŸww¦‘~¦\~€Mn¶{ŸÀ„§Ã‚£Ë|¡Ñv Ðx£½}£¤~Ÿt`Š==n®¶Ã1T<:_YSu59V!*L-6]1=f(7b/Z0]+U'9]-@c5JpH`‡Hb‹4P{4^)R&N(P ,T 0X1X9a5c7o.Kˆ1M‹3Qˆ*L~ 3a0\9b2S7OdFV`':E6C2>8CCcn]€‰,R]#La;]p%8F3<F!)1).*. #'. #5KXzš§œÊã”Åà‘ÄሽۃÀÝ‚»ÚV„§2Y~ FkBfFi4U )JiŽ¬¨Õð“ÆæÅæ•Ìì”ÊêŽÄ函ބºÛ„ºÛˆ¾ß‰ÄæˆÄé}¹Þr¯Ót°Õ}¹ß½ä¾ç…ÂêÇê’Èé•Çç—Çå’Æå‘Èê”ÌîšÓó˜Òð†Âåy¶Ûz¹á}¼ã„Áç‰ÄçŠÂä’ÈéÄ↾؇¹Ñ‰±ÈKg}3FZ?M`,DY">T.F 6 (#/Hq—Bv¦C|"Y–6h¥(R;t0LƒYi£X^˜_`šdfbkžGb–Je•\eŽ^UxfRstY}™xŸ®€¨¶€¥¶{œ³{›¬‚¡˜~Ÿr\‡OBs¶·ÇAClZM{G>i#*O06\8=f:Eo!4]3\5^-S$5V0@a,?b)?c&=d1Y 'P'O(P 0X2Z 0Y8_>d8c:o(E1O‡7Uˆ>m1_3`2\2S;Sh<LV"2>+>M8O],FSA]iGdo%BO-GY%IW4=&1!  &1GXŠ­½™¿ÎªÚîÐìŒÃä»Ýy¹Û|·ÛM€¥-\€QrQoMi=X ,INr£Îé™Çê”ÄêÃ䆽܂¹Ûˆ¿á†¾à‚¹Û}¶Ùr°×uµÞ}½â€Àã~¾âw·Ýk­Ûf©às²äÄëËï¥Êë²Óï¯×òšÊ抿Þ{·Ûm®×b©×Y£ÕW£×]©Ûb«Ûh¬Úr³ÝzºáˆÆéÌé›Ðë¢ÌäUq†3DV:FW1E,B,C '=%7$-?T‘¸YžÏ#dOŽ1a Af¤6X’:p3Jƒ[f gk¥gj¢dm£C^š3o&5h@Bm[T}XNx`Kz‹`”™qœ—y˜‹smUty`†“u¢~g•ÇÄÔl_Ž…m£q`˜NOJHu><h(1[0X/U1W2V1Bb6Ee"2T%9\.Ei0W
+(P*R2Z3[4\3[ /V4X<e*I{6S‹:W0M€3b-[3_CmAb8Pe@PZ,6D/:L5BS/?MFZgVky/CR'<L LT6:"+&%%)+7ERt”ªuž·d§m©Ñh¨Ôe¨Øh¬Ýl­Ût­×Tz¢=X-[yey)Gm7Z +L .OT~ž€¯Ï²ÏŠ·Î’¹Ë™ÀЩÐÞ­Õã­Õâ§Ñâ–ÉäŠÀ⇿áŽÇ烿ái¥Ìc¢Ëf¥Ñq¯Ú|ºãƒ¿ç€»ã}¶Þ†¼äŽÃë“ÉðÆïŒÃíŒÄí‹Âë‰Áì„½å€ºá‚¼à‚¾ãz·Ýq±Ûc¬Ú_ªÐn©ÉAa~0BX;R`>J7G*:Q06P'@,#I^k«Íj«×cŸÐ+b™P/^Ÿ2]™Dx7l@XŒ[m [i›[i›Qg£1K‰-c-\0:eVW‚G?jI6eUFqWOuFDg66Z88^FIwU]¾ÁÑKHw{l €i¤{f¥re¢\^“/Cq0X -R5[5Ek<Hn6Dj#7[4W4V ,M7]4^-T2W1W2Z<f8a&Iu6W‰5S‹5O‹)@~8p#@n3T=_‹@^‚I^wIUe37F58F3:A7ACYbg\bm$1? @L bg?@)),'),') "#(-jŽ~¡¸f­Vƒžw¸æb¥Ö]£Ög­âm°ão«ÙJo›3Is#Qtg}#<k2\)O(L8c…Åã’Ìç‚Àät´ßv¶ßx¸ßw·ßq±Úx¶ß…¸Ýƒ³Úv©ÑuªÔz±Ýu®Üv±Úy´×t²×n¯×fªÔYŸÊL”ÁJ‘ÄIÄS—Ë]ŸÑ^Í_œÉ_›ÇdÊ`šÇY•ÃY—Ç\žÏS–ÉC‰¿CÆHœÇ] Ã6Ww->W<Vc?K:J)=T*3O:
+6[5]%Cn;g!Fs$Ew(F}4NŠ;P‘BW‘H`‹GcŽHg’Ro”I_{ANb?DT?AMIMQQVUX\]KNV)7"Sb2bm%8?%"&"  ;N[‡¥¹ˆ°Ç‚­Âx£ºx·ãjª×r²ák­Ýa§ÚWšÉ7d“(HwV~|˜@t 0].W
+0W.U
+2Y2Z2\1^ 1`?o1Pƒ=WŽBX’H^‘Lc‹Jg8X€3Sw#=Z%8N8AQ?CN@BF@@AMMPCFN4>J4M\ 5C"%3<Eq‘¨ŒµÑ«Èu ¹l’¨Y—ÀX•¾Y•¾R·A…´9}©(W…#Hw\…  Aw1]6_
+0\~–•ÃãÅìz¶ãm§×Xº%X‡BwJ;n8k8XŠ9Wˆ%Bt Br
+2^/Y 1Y;e":e2Z'@h6Jt7Fq0;g?EsWQzdUwÇÄÏTVt-9\)V+`"2b):f(Ak+Ir=f!<g#<h&Bm(Fp=g>g!Dl 3Z /V 2Y .V1Y6^4[7_4b;l3T„8X‡<Wˆ>V‡JaŒF^,Im#El=b *I6L1BP28B65;IDGgcgRU]"/8 !'$*,24;@@HH7@:EY^…®Ä®Æb’«R”RxŠ†Àà‹Ãâ‹ÁáÂã†Ååe£Å!Lr3]X~ ‚žL1X/S
+0] .[1^3a.W-T5_4`4_7_9a;j Du)Jw-Mv7T{JdˆG_Mb~If…Aeˆ!Jl7S$G^-DRBLR[X_UKQG@FGKR=IOGTPWZ\88@%$., ot}Ãݾ߀²Ôy¨Èržº2~·?ŠÁK—Ë[£Õ{³àV…°7b*U1X"bƒ1d‡"Gh ,J *H,NS~¤´Ü„´Ø¹Ø‰·ÖƒµÔx®În§Él¨Ë[ŸÊI¿M”ÄN•ÅFŽ¿FŽÀPÁc•Æx«Ø€´Ý‚¶Ý}²Ø…»ÞŠÁ惺åeŸÑT’ÈH‹Æ6~¼$n­ j¨&p®+u²2}¹-zµ.{¶7¼H‹Ã[”ÃMvš)B_%6N3F\=Xe}i„9X); .0;Ko•a˜Ç?¸'n¥*p£*pŸ'oœ#jœ&f›$YŽ*Q„3Q:j1a2^0Y1V0T;^<b?f!Cj Ah:b<d;` 7X©¹Ä 5T
+0P /Q0T1V.?e 2Y2Y#;b8_/W-X-X-X-Y /[4` /Z.Y2^ /[2]5`<g=j6a6Z(BaMf…ToŽToŽTmŒJhˆ%Ff6PBZmO_jAIK<?A6:@>BKYZcgchKQP!B<3+6,#.(;<;=ANDJ€Ž™’»Öp£ÃY‡¤Lr‡@ev[“¾\“¼_—¼b›¿n¤ËM{¥6` -V +PAb=g†,Pq0N/M .Q0[ƒT‹·S»U»Y’½^˜ÁcÄg¡Çf¡Ä[™¿V•¾Z˜Á[šÄY˜ÂX–Âc›Çz§ÒˆµÝ½à”Âã¥Óò¥Ôð“Àà~¬Óo¡Ëb™ÈPÂ9{³%l¨f¨i«gªl®sµ"v¸%r±2r¨J|©Jn)B\'=S6Ka$Faqˆ!‡¢6W&9,:9 .aw’¢Èìy«×s¬×t®×`ÊO“ÅJÆKÈRÆK}±;d“1Z‰?n 4`:c
+6\.Q1S 7[Fk#Ho;b -U0Y /T-O¨µÁ4X:^">d7]&<d9Nv'>f9_!?d9] .T+U-X.Y 4`<g 4_.Y 2]0[
+3]7b<g<h?l7a;VzVk‹WmRlLhŒ5Ps=`2S9TnSfwS^eSTRBA==@A\_etsxkbd%$!81UQY^X_M_]RTUI?B<HU=`‡)W†"Mt4TpGe|¸ÙºÖ“½ÕŒ¹ÔtªÇ=o6Y,O+M+J6Tr3Vv4S.L*LFp6nž5q©5q«B|²a—ǃ¶ß¿áŠ¹ÖŠ¹Õˆ·Õ¿Ü‘Áà‘ÀàŠ¹Ûƒ°ÓªÎw Är›¾m—¸m—¶o™·j•¸e‘¸b¶XŠ³M‚°G¯<y­+v°)w³$r¯h¦i§i§dž*c–<j“Bcƒ(@X(>S0F](NiwŒ›:[&: *: <,$>\OwŸH|ªU¾V’¿J„¶D}·>~»8}º:¹D…·?y¥3b1\‡Hr9b4[ 8^ 4[1W 8_>f=f8b9c=e -SªµÃ;c+En*Ak5_6^:a0V-R
+2V/S/T
+1[ 0[ 0\8c>i 3^
+3^1[2\ 6`:d>h;e 1^"@kRiWkŽPeŠ:T~=g0W8^.RtVtgzŠDNT9:8MJF^\ZVSSZSTSHH1-*G\Yy…dgjGMK520"*Xr’s›Ã¦Ë‘±ÌºÒI´J‚²SŒºl¥ÐºÜP‚¢4V/R3U3RRpŽ1Tu7U
+)G)L0]†p§Óu°Ýy²â}´ã€³ß†¶Ý€­ÒsžÀu¡Å}¨Ì~©Î«Ï†±Õƒ®Ò‚®Ñ†³Ô–Ãâ”À܉µÐ¹Ô½Ù‘¾Ü„³×t¥Ïp¢În¡Ëe™Äc˜ÄižÄo£Çr¦Îf›Å]’½R‡±K¬Hz¦Hp•@]y3J(>5MJd{x’Ce)>$5;9 %O%Z"dœbœd'cœ.`š'`œ^š]”)jšB§]ŽµY…«Iu›7c‹Bl 6a 5`6_4\0Z
+2]8e6c2\ .V©¶Ä5^2]0\4`;e5^ 1Y.U3Y4Y5[ 3]6a 4_8c8c=h<f3\1Z3\5^4]5^@l<[…A\‚5Ns<d,Y
+2`GrQ{¥‚©Ìz˜´Yl|DMSFJLQSSSQPC<;KBC^WX`\`[hoEac*==**,1,+B:7WRSƒ”¡—»Ó†­Åv—§e‚Ž0s³*n«-r¬Eˆ¿b›ÆR©;d +S%J$Ii‡°ÐNr“ @_
+*H)K&R{UŒ¹Q…·P~³V„·Yˆ·V†±U†­^µYŒ¸Cv¥6i˜<ožS†µ^’Às§Îu¬Îµ×r¨Í[‘»R‡µEzª=u¦6o &^$\C{¬W½^”¾mœ¿nœ¼p¾w¥Æ†´ÕŽ¼ß’À匷ÞgŠ«:Tm)?
+;cBj;a .R+O/W =k3g–_¼‰·â¸ßkŠ¦Qds[diGQW2<C68<HFHjgjppwMMZ.8JHL9;?=Fcbdwusjaaclrv”§]‚™Nm|GakTX‘[’(f›Cw¨DqŸ=j)T
+6g 4e.`2^8_¦·Å/X/X2\ 1\3a8g:h7e9g@m7c 2] 6a 5` 4_
+3^.Y-V1X3[
+,1?[/r—#No<Oc .?, %,7W.\„1c'[ˆ']+dš0i (a˜!Z!Y%]“!`—a™+k¢8t©;t§:p¢<p¡Ar¦8hž&U‹E{ :p7m5d 6]©¸Æ 5\
+6]
+6^
+5] 6_;e=g 8b 7` 5_3]3^3^2]/Z
+:e9d :f
+:f8d6a2]
+8Z 5U8j‘XŽ»dšÇn¤Ñ]’¿T‰¶Oƒ¯P|¨U¬S‚°As§'\•RŒO‰RŠS‹S‹VŽTŒVŽV!]—<s©N¯aŒ¶q•ºzœ¿~¡Å¤Ã‰­Î•ºÞ›Àç”¹àƒ¯Õƒ´Ô\™&8M"69< 78YR}@c0DW0>O"6'+#?\z¦Í±Þz¬Ún ÏW‰ºEw©>p¡8jœ>p¡?q£BxªF°D|­K‚²Nƒ³U‰¹]‘¾g™Âo¡Ét¥Îp¢Êe–¿\¶Tˆ´H¯·ÊÛT„SƒT„U… U„SM|JyHvFtCp?j
+;f5`6a :eHs.Z…Sz¥j’½m•À`ˆ³T|§Pz¥Bv£,e”JzCtL}L~Am
+Io\‡$[~CarZgnYgqTal?JT",6'1;[enr{…Zhp.Wcd\n0GINVdlr‚yx~gjpGTc5Qg@X/DbÁj–Çw¢Ò}§×|¢Ôi»Dj*M*P0TdÀ>o¦*[‘'V‰An:^.M@d5h’;m˜Lª]ºb•Àa’¾[ˆµY†´X‰¸K€¶/h¡TMˆO…Q‡Q‡SŠ#Y)_•(`—*b˜5gšGs¡\ƒ«hŠ®y˜ºƒ¢Ãˆ§Èƒ¢Ãx—¸p²s’µp–¸i—µUy”$;T%>6467[#Q~'Ko4G[5DU':!&-H0X}9g‘ApšQ~©Y…²T€­Bm›2^‹2]‹Gs bº^·T„®T…±[º`“Á]½X‰³S„®O€©Hy¢:l•=n˜<pœ1g–²ÅÖQ€OM}L{O|(Xƒ1aŒ*Z…&W‚)Y„-^‰1b7h“8i”8i•5f’>ošKy£b¸t¡Ës ÉZ‡°DqšEsF}©7t  ]ŠX†Xˆ K{FrY€W€DaJ_kt}cpz7ER(2-8BT^guˆcmv/>F 9FqD‰›s‰Œv}‹djzHIM&,/ , &:4H7c•<d—Bg›Il¡Dfš?c=d
+.R*Q!BqV~­W‡±Y‰·Wƒ¸.WŒ6d)O 8b*X‰.]Ž3b“+Z‹NNMM~J{K{W‡.e•S…³sžÊtžÉj”Àl–Âu Ë}¦ÒvŸÈo•¾všÂ†©Ï–¸Ü™¹ÝŸ¾á½á˜¸Ýœ½á Áå½á˜¸Ü‰­Ów ÆRv™7U&?+ 8C\ƒJr¡@`†@Re4DU(: ( 'A)Ps3_†=i’Al”Cj”LsT{¥Qw¡Rx£a‡±k´i²`ˆ®[‡¯Ix¢-_‹$V„ P P!Q‚ P P&V‡*Y‡.^ˆ¹ÊÙJz¤V†±ZŠ´c’¼q›ÁxŸÃ„«Ï{¢Æb‰®Mt˜LvœT…¯]Žºa’½U‡²Fw£>p›7k“1h-eŠ/f‹4j7m“ByžF~£7o–+eŒ%^‡ Fo@jQz"W€Ai C_oyƒ‡‡ŒLS`(4+5?U_hfpyV_h4=F*1,]hV©Äl«½t…ˆOT^!)2  &=NZdy‰~“¤§Õ„¨Ø‚£Ô‚¡Ó„¤Ôs”Á?h +R ,V8[Šl•¿a“·W‡´Al¢)Pˆ8i
+-V9gK€-\‘Hw¬N~³Ix®Bs¨&b•PM|HuMx+^‡R§wœÄ}¡É}¢Ê£Ë{ŸÇ{ Ç…¦ËŒ«Î¯Ó’³Ø–¸Þ–¹ß™½äžÃé Äê Äê Åë–»ás˜½_†®X€ªPt›%Bb 6(&'0"8MgŽk“ÃušÃSj…-?S'9((0Jv™½Š³ÜŽ¹ä¹äµßŽ³Ý‘·áµÞµß“¹â”¹Ý‚¨ËgµS§;i“)Z…%W†OƒN„N„O…!Rˆ$TŠ-Y†0W|¹ÇÓPt˜dˆ«p“µ|žÀ‹©È•±Ï•²ÐŠ§Å‚Ÿ½x•²fˆ©Drš3b‹$S}Al9d:f;c
+Dj9^ @fRwGl6YFcSoƒm|‰JQ\5:FOU\NSW).0 '18Yivn‰šd¤¹;™¨M\#$0223PXZjkp~€ƒ‰Œ‰’š–¥±{‹˜¡Â瘹ްհԗ²Õx’µ8].V1Qz\~©;b,Z‚/Z‡FkšLl—4Pr8Q=_!Lw&Q}'R~0[‡:e‘Al—>i”;f’Cn™7b.Y…'R}&Q}2]ˆ8c.Y…$P{$O{"Mx Hs"Hq(Ox0V4Zƒ3Y‚)Ox-U|.V}-U|)Qx*Ry)Qx#Lr$Mr/Tu'D`
+5&
+#)D-Qx&S#U†#Nz5St1D[+:&3:[JsL| O€$O|"M{#N{'RIvIvMy Pz Oz Pz$T~)Xƒ'W‚IwGv$S‚,[‹.]Œ)Yˆ([Œ&[Ž²ÄÖ"Rƒ0]Œ8cDm–Oo”Hf‰A_‚Db„>\~2Ps*LnEf =_7[9_
+BOZj^|‘:~’ hw L\?LZkmr“™ž‡Š‘uyyX]`8?EEQ[8HS‰­Ó´Ú•¹ß–¹ßž¸Üs‹®!9\-Ph‚¦©Î‰¦Ê³Ô€£ÉnŒ·rŽ¶`zš8P-KiiŒ±jŒ²mµr•ºmµhŠ°eˆ­g‰¯gŠ¯d†¬c†«iŒ±t–¼} Åƒ¦Ë…§Í…¨Í…¨Í‡©Î‹¬ÏŒ«Î¬Ï‘°Ó“²Õ‘°Ò‚£Æv›ÁxžÆvœÃfŒ³Tz¡Pu[€§iŽ´kŒ¯1Mj1&4LeŠ¬Ñˆ±Ü®ÛrœÆVxœ)Fc2E
+8\:g >nCp!LyHuFsHuHuKuJsEnDmGpKt%R{ JuBm=g>h@jIs"O}Iz®¿ÐL}M|DsDsJu IsEp8c 5`
+3^2[
+;`2W@cHk5W1T#Np4Vp6L]O\ggpwaip@EM :BKp€Žkƒ˜5TlK^cs@‚’qŒ˜’•“–žipv388 &.2?I=dŒBi‘LršW}¥mµSp— (N1Lp˜²Ô§¿á¥Ààž¿Þ–¸ÝŠªÔˆ§Ðy—º#A^/Nnm³a‚§Jk9[6X|8Y}?a…Pr–\}¡h‰­p’¶{œÁ’´Ø™ºßš¼à™ºß’´Ø“´Ù–¸Ü›»Ýž¼Ýž¼Ýž¼Ý—µÖŒªË‰§Êƒ¤Ë¡ÊŠ¬Õ“µÝ–¸á™»ã˜¹â—¶ß”²ÖId4'"%?X`€¥`„«Qx¡9`Š)Ow%Lp=W
+5b 8e7dCl"Nt&Qx!Ms Kr#Ou+Tz9]ƒDhŽLp–X|¢a…«kµt”·q®ËÕápŽ°o³Qq–3V|,V‚,X‡+W…$P&R€Cr=k >g:a:`:_7[ >a@eBiKq)U|,XEk 6]:`2W;^/Wz6]-RtIp’gŒ­]y“N`pkvy‚†NV[!$)==B`dm†“¢u‹¡Hh€CsƒY‘¤z³Ã…¨²ˆc`i,49
+  ?EJ`lt2[…:dŽ=f‘9cU~¬Ah–*W;\…mŒ³x”¹u“¶W}ž9^‡&K{%Jz Gq>b4Y>f!Fn*Ow.S{,Qy(MuDlAj&Kt0U}1V~6[ƒ>cŒEj’Y§b‡¯k¸l‘¹gŒ´iŒ²g‰­_¥TušDeŠ?a…Tušhˆ±~žÈ‚¢Ëy™Â†¦Ï­Öˆ¦Ð‘­Ö™´ÙOi†1
+5b:h!Mz,X…9c^‡®q™¾f³QzžR{ o—¼…«Ï“´×›ºÜ¼ß¡Àã¤Ãæ¢Á䡽ܤ¼ÚÖßêqŽ¯\|¡BeŒ/T}$Ny(T€&R~$O{%P}%P}"O|JyFsJu!Iq&KqEiSxœW~£b‰®n•»sšÀ`‡­]‚§^ƒ§Z¢i¯f‰ª@aƒFg‡kŒ­r‘²k„›pŽƒ”jsv)34" E;;e]_][ackw^p…\u‹‡ ®µÉ”¾ÎmŽ•KDL8/5'(!%&?@>hihˆ‹Ž ©²z¡ÌeŽ¸S}§Ku Fs¡Gu4`Uw¡jˆ°f€¦a|ŸUu˜Gh7\Š+U…(Uƒ"R}=f#LuIqšPv Z|¨e…±d„°Uz¤3Z„-T~*Q{'Nx8_ˆMtRw Uz£Rw¡Z©_…®W|¦Vz£SvPs›TwžZ}¥Twže‡¯ È‘¯×”²Ú’±Ù’°ØŒ«ÓŠ¦Î¨Ï‡¡ÅB[z3
+'I!HqCl=f=fEn*Px*Kn:[0P/N
+!?,J*KnFq@kAk&Mw,S|&Lu!IsDpEq%Ny%OzEp=h <e ;d:d:f;h9g7d9d°¾Î JuEp"Lx0Y„*N{ Cp<i Cp Cp;i>j?gCj&Py,R|3W6W‚3Y„3]ˆ.XƒGr?jCmFpBg7\€7Z>`'IjLmŽ;^|"CcCX{„¨zƒ†4><)1fae{pm@>> Q`k•¦¸ÀÒæÀÓ暨·DKS!%""%RSW„…‡¥¤¦¥¥©˜—š„‚‚x{q”¼Nt›*Qx 7]-R/S+NHo‘†©Ê‚ À}™¸mˆ§Ut”@eˆ$RxPy'a‹Ou3V/S6]>f"@j">i$Fo"EmAi;c8`9a7a 2_ 1^5bDq7]ŠRw¤g‰´o¸v–¿zšÃy™Âs“¼d„­YzžTv™WyœYzTu˜Vwšb€¢u®uŒªAUp30-*G>[|If‡If‡EbƒDa‚MiˆNc8Mi2N,I >/N9[€-Y„ LxJvDpIv%O|$Iq'Hm)Jp*Kp)Jp:[€/QvDh$Im)Lq)Jo-Kr*Fm AiBk¬ºÉDmEn Hq'Nw.S})Lv%Hr*Mx,Oz=`‹d…ª›µŽ¦¾²Ë§¹Ô«ºÕš©Åv‘´V}¦?g(OxFo Hp>f<a*Nr)Lo Bd4UwCd…,Nl(IhQh‹etS]b/76AGNtjlZLH"q~†°¾Í¼ÊÛš©¹gr~>DK?@Cbac’‘’°®¯°®±‹Œ‘a`cBAA(*->aŠBi7]:`4\
+4`:eDmBhEh"Gk*Ip-Mt.Sx)Qw Kr Ns&Rx%Pu Kq<b.U*Q4[AiAiAiBj&Iq Dl Bk#Dn%Fp)Jt&Gq#Dn!Bl$En @i6_ @i5U8X+Ks(Im!Be!Be Be.Or;\Klu°’£ºLRa $1,/Se}½Íä¿Ïæ¾Îå¼Ìã¹Éá¹Éà¼Í䥳ÉM[p&:"5.7I®´ÂÐÑÛÇÊ×´»Ë©»Žž´†™²}•²u®qŒªx’±u®D^}.HfF\|f}‘©ÉªÉ}™·cŸHiŠ2Sy±½Ê<b?e)Kq1Sy3W|5Y~4W|$Gl@e>c<aGnDlCl#Is&Jt7Xƒ;]…0Qw#Ej=c:`4Y8\#Fj%Il=`0Rt7Xy:Z6O;^uJhˆ)@\5EOcjjojpWJL PV[§ŽžP_p3@MAMXx‚Œ §¯³¶º¬«¬zxyFGL"
+
+&&(&Ir%Ks IpDl=n!?r#Br)Iw%Gq Ck&Fo2JwF^Šiƒ®u‘ºt’º{šÁl‹´FeLl•Xy¢Vx Y|¤Hl”/S{&Iq)Lt*Nv)Lu&Iq*Jp5Nq6Op5Np/Hj/Hj1Jl+Hn?h5^2[6`<e<d?c#Eh#Dh'Il1Ru+Lo"Dh$@`HUiDDN0.7- 4Vj„|Ž§|§€’ªƒ•®“¥¾™­Ç”«È•ªÄ`mƒ'-=*)21+0—ž¥¶—£¸ž¶j‚žCa‚4Tx'Gi'Fh"Ac!@b >`=_2Orh¤u±\wš?_€'KkDc=^=`±½É'Gk.Or1Qu)Jm"EhBd;]2T7Y<^=`FkIo#Jq/S{5V€2Pz2Qw+Kn!Ad&Fi,Ko&Fh,Lm,Os:]3V/Oq&Gh
+)I%F^Il€5Uu.LCTa„‡mci3&*
+ 58<ly‚}žI^q/C.=KZi†•¤¦³¿ ¨¯xz}HHJ 411__`@_†>^…<^„<^…3N{2a7dYu qŽ¸u“»‚ơΡΑªÔ‡¤Ì_€¥Jk*Ho)RNi’’­×ªÔ’ªÔŽ§Ñ„¡ÉžÆ ÈÅd‚ª:X€0Kq<PrMa‚bv—dw™[oXl^r™cx¡g}¤f{¡k¤v®h€¡PlMj‹c€¡w”µœ½b€ 6Wy%Ed7G^/1B+ .,G;Xv>Xw.Hg'Ba(Cb7Rq<Xx6V{2Op<Pk1;M44?)"(7>M*Fe%De?b Bg@h En>c4V9[>`%Fi*Ln#Cf(Dh3Os7Ux5Ux&IkAb=`3W¯¹Ç+Hm-Ko-Jn/Mq.Nq&Gj%Fi?b?b#Dg Bd8X;[;\"Ce-Ln2Ps2Ps5Ux,Ko)Il(Gk<^'Eh-Mo>`+Kl9Xy7W (H0Kf<Xo2P "?FYi†Ž•PMSSW^v‚Ž[m}'9N 47GZq‚“™©¹ ®ºpzƒCHM  $)EFHlii”””‘©Ï’«Ñ˜°×ž¶ÜŽ©Î6Rw,Qq²š¶Û—³ØœµÜ ³Ýž´Ýš¶ÝŒ±ÕT Ef
+0S5Rx†£Ê™±Ú›¯Ù­Ø­Ø™¯Ø—¯Ø˜¯Øš±Ú™°Ù•¬Õ¦Í£È”¨Íœ±Õž²×Ÿ´Ù¡µÚ¥³Ú©³Ù¬µÙ®¸×´¿Ú¹ÅÝ·ÅܴЀ™·m†¤[t’PjˆE^|3Ro/Pk7Id&+E43.K@c7\6Z5Y8]!Cg)Lr*Py'Ip+Gg/B[+6I$1&8M!Ef#Fh ?a*Fh2Jl0Gi$Aa=\9Y:Y"Cc"Dc1Qp7Uu'De(Ef'Dd=]6V9]6]¬·Ä4[8_!=d!=d">e*Fm">e5\7^">e&Dj>b5Y4Y9]>bCg Ch!Ag<b;a3X/T;_5X,N7Rt[v—7Rq3Ml^w“Sj† 8T'@Yaw‰w…+27@;=vx€{…’M[m!0B0?Pm|£³Ä®¼ËŒ˜£Zdm$.5-/0MQTuvx¡ŸŸ¿¿À›³Ùœ´Úœ´ÚœµÛœ·ÜQm’!FC_„˜´Ù™µÚ”®Ó•ªÑŽ¥Ì„¡Æy›¾y ÁR}%Hkh„©ˆ¢È~–¼}’¹uˆ°fy¡[r™Yq—d|¢y‘·”¬Òš²ØŸ¶Û¢¶Ù¢¶Ù ´×¡µØ£·Ú¥¹Ü«ºÝ¯¼Þ²¿àµÃá¶Äß¹Ç଼Ör‰¦1Jh&?]/Hg6Om;Tr1Lg6Mf?Ka*-@&*<0+C\3Rq(Hl'Gj%Ei<_6Y3W8^>b'Ba6Ic&3G."4I(If)Hf"?^%?`*Bd,Df!?_#Ed Aa;[!Cb"Cb1Rq*Gg4T2R1R.N
+'H
+'I 'Lª´Á,Q,Q5Z8]9^'Ch">c;`(Di.Ko-Jn/Lp0Lq*Fk*Fk)Fj+Gl/Mq&Gk@c"Cf @c @a7Vw-Kk<[6Rq4Pm#>\A\xZsŽ1Hc)C4Leavˆ[it$)!TPRrt|Wan'6F,=N]mœ®´ÃÔ¨¶ÄwƒŽGQ[+5=-25^__€„†§ª¬ºº»ÆÇɵ۞¶ÜŸ·Ýž·ÝŸºß^zŸ,Q9_A]‚B^ƒA[€<Sv,Dg:\9Z&Gg+Nm1No6Nq+Be'?b&>a2Jm7Nq%>a6Y9Qtl„§š²Õœ´×Ÿ¶Ø¢¶×¡µÕŸ´Ôž³Óž³Ó±Òœ®Ì•¥Âº„”°v†¢q‚žn€VnŒ6Pn,Ec)B`(A_)B`,C^0@W8BT'-:$2'9.?W,Ec&Cd%Bc+Gh$Ab;\<] ?b$Bc&?]&:T(7M 4 1F1Jb;UoAZw<Tt;Sv4Mq$Cc!Cb"Cb>]?^;[8X5U8X9Y;[;[ *J A$E©³¾ )J-O;\-Jk/Lm&Cd*Gh*Gh0Mn.Kl">_*Be2Km:Su<Tw1Jm+Df,Hj'Hh'Ih)Kk'Hg*Ki.Mk9V<X.Lg5P)C+F_7Oi %?99QiTi|AOY#212hfg`el.9F!&6Tdt„“¢ƒ’Ÿ^kw;FR+5?7@IZ_c„‡‡§­±¿ÅÈ»½¿³µ·Ÿ¸Þ—¯Õ‚šÀ\ušC^„(Dj!=b6[8]9_:].Gf0Ih-Ge/Ih1Lj3NlH_~G[|3Hh-Ee&@^&B`.Ki,Fe2JjUnd}œb{šaz™]t’Ti…OeUj†Qf‚F[w>To:Ng6Ia6Ib2E`*=['9Y&9Y 8V8V7U(A_(A_'@^CXuHWrBPe,:"18F[IXs4Ig+Dc$>\6U 9X 9X#=\,Gf6Pn7Ok;Pj.@X%<>Oc]p‚Ocy>Tn0Gf*Ce8];]"Dc-Nm(Ih"Dc@_%Ed'Ee5U7W<\0P &F-K1N¬¶Á8U%B`(Fc&Da*Ge*He&Da;X#A^'Db;X2O+H6S<Y/M/L2O -I)E(D&B/J.H8/H!<V#; #:0Ka+D[4-HG^vQfx3BL!'FFEnmnOU\%0
++:L\xŠ™ªw‡“HVb,8D*3?OWbx…ž¥¨¶ÁǼÅʪ­°µÜ€˜¾Wo•E^ƒ;V{+Gl7\5Z4Y4Z:\'B_6Pm7Pn0Ge'>\0O!3S):Z"6U5R">Z)Je%F`%@\+Eb#<Y7T";X%?\2Je6Ld5KdCYqJ`xBXp=Sk2I^0H[3J`9Oi4Jh-Ac%;]$<[+Db(A_5S/M1O0P!4T+AZ
+!5
+!54Ic5Hh,Aa%<[+Ca5Lj1Ig.Fd2Jh:SpPh†l‚ž•©Ãk˜*CQbu™§¶n8Kc5S4W$@e+Jl,Ml:[z"Cb=\:Y>]&Cc8X0P-M &F4T"@]#A]³¾È$B^=Y<W6R;W!?Z7R *F
+(D &B%@&@$=#<#<
+*C 88O;R"97LE_t2Lc+E6Ni_wTi{2@L-4:YZZjll:BH ',:Vkz‰œª ¬Zju"0; " )5U]iŒ•ª¶¼¼ËÔ³¿ÆŒ‘’iji–¯Ô–®Ó”¬Ñ¨ÍŽ¨ÊoŠ«!<]8Y#>^)De!=\8U6S7U!9X'=]'<\&?]:W8T:V$B^#C_5R0O4T4T.N.O":[":Y6R,D_6Ni4Lg2Jf-E`3Id,B\5KfCYvI^~Sh‰Pf‡HcNj‡Fa~,Ea!9S#:T+A\&=X*B[ #91I8Pl2Ih5Ml7Pn+Ca&>\";Y/Hf5Pm4Sl@YpQcyXhI_z%Dc0H<L\,>P%:P)@\&>_5W@^B](Kg(If'Ec#?] 9Y3Gi7Km(?`6V.M *I
+'C )C«µ¾-F +D'?$; 9 ";'B(D 'D
+%C (E
+(C
+)D ,F (C+F-H
+)E -K ,J&D%B-J-H4L:Sj=Vn&AY=YsUrŒ6Pi!7NI^tbuˆP_n6@J>DJaacaac&,1+<Jl£´{œAR_(5!-=GRow‚ž¥®¹Âdz½Ä–ž¤hloBCDAY}G_ƒMe‰Jb…AZy3Lj&?]'@^-Fd1Jh.He"@[">Z!;X"8V/Cb2Dd/Fe)Ec!=[ =[ =[$C`"@^9[4X$=`7[!9].Gk,Ef%>\8V!;Y6T6T*Ca5Ml)?_+Bb1Hh.Ee6V1P7V A_#A^">Y+D](@X(@W-G]9Q8 #=4N5P9V8W-L2Q7V'@_%B`A[,H_;Lb5F\3Pk5d„7Q 9K4Nb1Lb8Tn3Ol%A`C^=W8S6R0M&E"B#E'H'H(H 'E%B&A/H¬·À0I1K6P7P$:R';R#9R8R6R,K,K3R3R0P!6U0O.M %E )K$F 'I,M8X-K':P@Pf4G^%:S>VoGa|5N5JYljyˆOZf<DMJNUhinUTX"
+BLWzˆ–ž®kyˆ0=K)#-7airœ¢©ÆÊÏÈËϧ«¯|€…RUY"$&":[*Bd(@a%>^!:Y+Db/Hg.Ge2Ki5Nm3Lg4Kb<Rh8Kb8H`8E^=Hb>Ee?Fi8Ce*<\.L &B
+)E
+$D !B &G.O2S#;\(Aa3Lj,Ec&@^8V3Q1P*G,H4P <X-Ie)Ea =Z:[?`&Gf&Eb,Hb7Rk:Sm 8T7
+(D(E0N0N2P4R6S3P2O$A] ?Z6O5L¬µ¾'B*G#+J&D!2I/C &<
+%<&?%@ (E&E(H*I,K,K!6U.M &F (H+K/N2Q
+!>3AVhs†VbvANc\jWf|&8M1EK]oZixEP\FMVV[cgimLMP #)~ˆ¨¬²¥©¯qw}>CI049Y]a—šžÒÔ×ìíðÝÞá—š^bf:>A%>\2P0N0N4R4S+I,J#<Z7Pn>Vq=Rf>Qe>Nc?Kb@JaMVm\\z]Z}TWwBLj.B]6N0H &B 'E0N,Ec=Vt<Us4Mk0Ig)B`-Fd/Hf&?]#=Z%@Z<T2J0H2J1I3M9W6T%C`-Id4Mf-D[(A/.++*?OOds`s‚k{Œev‡YizXhyP`q7HZ(;P%8P4O0K!Mf0p‡Xo?X.G%?
+'C'E'E3Q'?^3Lj1Ki&?\,D^-F_":S'A%?&@ 71¦­µ#=8;XIEd4.M*?+< $7 5!8#; &A'E&E#B(G/O'F)H
+"A*I-L4S'>[+G$/FV_tV_sW`sx€“pvˆ>K^8MbK]oIWh@KXJQZbgodhl>@C
+,,3µ´¹çåæ×ÕÒ–”’a_^XVU|zy·¶µáßÞìëêÐÏБ“LOR),/  \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/ppm/spheres.ppm b/src/corelib/render/software/agg-demos/ppm/spheres.ppm
new file mode 100755
index 00000000..1c108613
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/ppm/spheres.ppm
Binary files differ
diff --git a/src/corelib/render/software/agg-demos/ppm/spheres2.ppm b/src/corelib/render/software/agg-demos/ppm/spheres2.ppm
new file mode 100755
index 00000000..5a2b6794
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/ppm/spheres2.ppm
Binary files differ
diff --git a/src/corelib/render/software/agg-demos/pure_api_win.dpr b/src/corelib/render/software/agg-demos/pure_api_win.dpr
new file mode 100644
index 00000000..69663136
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/pure_api_win.dpr
@@ -0,0 +1,254 @@
+{target:win}
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ pure_api_win;
+
+uses
+ Windows ,Messages ,
+
+ agg_basics ,
+ agg_rendering_buffer ,
+ agg_color ,
+ agg_pixfmt ,
+ agg_pixfmt_rgba ,
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_rasterizer_scanline_aa ,
+ agg_scanline_p ,
+ agg_render_scanlines ;
+
+{$I agg_mode.inc }
+
+const
+ szWindowClass = 'PURE_API';
+ szTitle = 'pure_api';
+
+{ WndProc }
+function WndProc(Wnd : HWND; Msg : UINT; WPar : WParam; LPar : LParam ) : LResult; stdcall;
+var
+// Win32
+ dc : HDC;
+ ps : TPaintStruct;
+ rt : TRect;
+
+ width ,
+ height : integer;
+
+ bmp_info : TBitmapInfo;
+ mem_dc : HDC;
+
+ buf : pointer;
+ bmp ,
+ temp : HBitmap;
+
+// AGG
+ rbuf : rendering_buffer;
+ pixf : pixel_formats;
+ renb : renderer_base;
+ rgba : aggclr;
+
+ ren : renderer_scanline_aa_solid;
+ ras : rasterizer_scanline_aa;
+ sl : scanline_p8;
+
+begin
+ result:=0;
+
+ case Msg of
+ WM_PAINT :
+ begin
+ dc:=BeginPaint(Wnd ,ps );
+
+ if dc <> 0 then
+ begin
+ GetClientRect(Wnd ,rt );
+
+ width :=rt.Right - rt.Left;
+ height:=rt.Bottom - rt.Top;
+
+ //Creating compatible DC and a bitmap to render the image
+ mem_dc:=CreateCompatibleDC(dc );
+
+ bmp_info.bmiHeader.biSize :=sizeof(TBITMAPINFOHEADER );
+ bmp_info.bmiHeader.biWidth :=width;
+ bmp_info.bmiHeader.biHeight:=height;
+ bmp_info.bmiHeader.biPlanes:=1;
+
+ bmp_info.bmiHeader.biBitCount :=32;
+ bmp_info.bmiHeader.biCompression :=BI_RGB;
+ bmp_info.bmiHeader.biSizeImage :=0;
+ bmp_info.bmiHeader.biXPelsPerMeter:=0;
+ bmp_info.bmiHeader.biYPelsPerMeter:=0;
+ bmp_info.bmiHeader.biClrUsed :=0;
+ bmp_info.bmiHeader.biClrImportant :=0;
+
+ buf:=NIL;
+ bmp:=CreateDIBSection(mem_dc ,bmp_info ,DIB_RGB_COLORS ,buf ,0 ,0 );
+
+ // Selecting the object before doing anything allows you
+ // to use AGG together with native Windows GDI.
+ temp:=SelectObject(mem_dc ,bmp );
+
+ //============================================================
+ // AGG lowest level code
+ rbuf.Construct;
+ rbuf.attach(buf ,width ,height ,-width * 4 ); // Use negative stride in order
+ // to keep Y-axis consistent with
+ // WinGDI, i.e., going down.
+
+ // Pixel format and basic primitives renderer
+ pixfmt_bgra32(pixf ,@rbuf );
+
+ renb.Construct(@pixf );
+ rgba.ConstrInt(255 ,255 ,255 ,127 );
+
+ renb.clear(@rgba );
+
+ // Scanline renderer for solid filling
+ ren.Construct(@renb );
+
+ // Rasterizer & scanline
+ ras.Construct;
+ sl.Construct;
+
+ // Polygon (triangle)
+ ras.move_to_d(20.7 ,34.15 );
+ ras.line_to_d(398.23 ,123.43 );
+ ras.line_to_d(165.45 ,401.87 );
+
+ // Setting the attrribute (color) & Rendering
+ rgba.ConstrInt(80 ,90 ,60 );
+ ren.color_ (@rgba );
+
+ render_scanlines(@ras ,@sl ,@ren );
+
+ //------------------------------------------------------------
+ // Display the image. If the image is B-G-R-A (32-bits per pixel)
+ // one can use AlphaBlend instead of BitBlt. In case of AlphaBlend
+ // one also should clear the image with zero alpha, i.e. rgba8(0,0,0,0)
+ BitBlt(
+ dc ,
+ rt.left ,rt.top ,width ,height ,
+ mem_dc ,0 ,0 ,
+ SRCCOPY );
+
+ // Free AGG resources
+ // Pascal doesn't call object destructors when leaving the local function range,
+ // thus we have to do it by hand
+ rbuf.Destruct;
+ ras.Destruct;
+ sl.Destruct;
+
+ // Free resources
+ SelectObject(mem_dc ,temp );
+ DeleteObject(bmp );
+ DeleteObject(mem_dc );
+
+ EndPaint(Wnd ,ps );
+
+ end;
+
+ end;
+
+ WM_SYSKEYDOWN ,WM_KEYDOWN :
+ case WPar of
+ VK_F1 :
+ MessageBox(
+ Wnd ,
+ 'The AGG library is able to draw to any surface. It is achieved by using an offline'#13 +
+ 'bitmap (buffer), to which AGG primarily renders. Then that bitmap is blited to the'#13 +
+ 'GDI device context of the destination device.'#13#13 +
+ 'This example demonstrates that simple setup for a Windows app that paints to a GDI '#13 +
+ 'device context. All it needs are the CreateCompatibleBitmap(), CreateDIBSection()'#13 +
+ 'and BitBlt() WinAPI calls.'#0 ,
+ 'AGG Message' ,MB_OK );
+
+ else
+ result:=DefWindowProc(Wnd ,Msg ,WPar ,LPar );
+
+ end;
+
+ WM_ERASEBKGND :
+ NoP;
+
+ WM_DESTROY :
+ PostQuitMessage(0 );
+
+ else
+ result:=DefWindowProc(Wnd ,Msg ,WPar ,LPar );
+
+ end;
+
+end;
+
+{ MyRegisterClass }
+procedure MyRegisterClass;
+var
+ wcex : TWndClassEx;
+
+begin
+ wcex.cbSize:=sizeof(TWndClassEx );
+
+ wcex.style :=CS_HREDRAW or CS_VREDRAW;
+ wcex.lpfnWndProc :=@WndProc;
+ wcex.cbClsExtra :=0;
+ wcex.cbWndExtra :=0;
+ wcex.hInstance :=HInstance;
+ wcex.hIcon :=LoadIcon(HInstance ,IDI_APPLICATION );
+ wcex.hCursor :=LoadCursor(0 ,IDC_ARROW );
+ wcex.hbrBackground:=COLOR_WINDOW + 1;
+ wcex.lpszMenuName :=NIL;
+ wcex.lpszClassName:=szWindowClass;
+ wcex.hIconSm :=0;
+
+ RegisterClassEx(wcex );
+
+end;
+
+{ InitInstance }
+function InitInstance : boolean;
+var
+ Wnd : HWND;
+
+begin
+ Wnd:=
+ CreateWindow(
+ szWindowClass ,
+ szTitle ,
+ WS_OVERLAPPEDWINDOW ,
+ integer(CW_USEDEFAULT ) ,0 ,integer(CW_USEDEFAULT ) ,0 ,
+ 0 ,0 ,HInstance ,NIL );
+
+ if Wnd <> 0 then
+ begin
+ ShowWindow (Wnd,SW_SHOW );
+ UpdateWindow(Wnd );
+
+ result:=true;
+
+ end
+ else
+ result:=false;
+
+end;
+
+var
+ Msg : TMsg;
+
+BEGIN
+ MyRegisterClass;
+
+ if InitInstance then
+ while GetMessage(Msg ,0 ,0 ,0 ) do
+ begin
+ TranslateMessage(Msg );
+ DispatchMessage (Msg );
+
+ end;
+
+END.
diff --git a/src/corelib/render/software/agg-demos/raster_text.dpr b/src/corelib/render/software/agg-demos/raster_text.dpr
new file mode 100644
index 00000000..63cfa510
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/raster_text.dpr
@@ -0,0 +1,257 @@
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ raster_text ;
+
+uses
+ agg_basics ,
+ agg_platform_support ,
+
+ agg_color ,
+ agg_pixfmt ,
+ agg_pixfmt_rgb ,
+
+ agg_rendering_buffer ,
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_rasterizer_scanline_aa ,
+ agg_scanline_u ,
+ agg_render_scanlines ,
+
+ agg_span_allocator ,
+ agg_span_gradient ,
+ agg_span_interpolator_linear ,
+ agg_embedded_raster_fonts ,
+ agg_glyph_raster_bin ,
+ agg_renderer_raster_text ,
+ agg_trans_affine ;
+
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+type
+ gradient_sine_repeat_adaptor = object(gradient )
+ m_gradient : gradient_ptr;
+ m_periods : double;
+
+ constructor Construct(GF : gradient_ptr );
+
+ procedure _periods(p : double );
+
+ function calculate(x ,y ,d : int ) : int; virtual;
+
+ end;
+
+ the_application = object(platform_support )
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure on_draw; virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ CONSTRUCT }
+constructor gradient_sine_repeat_adaptor.Construct;
+begin
+ m_gradient:=GF;
+ m_periods :=pi* 2.0;
+
+end;
+
+{ _PERIODS }
+procedure gradient_sine_repeat_adaptor._periods;
+begin
+ m_periods:=p * pi * 2.0;
+
+end;
+
+{ CALCULATE }
+function gradient_sine_repeat_adaptor.calculate;
+begin
+ result:=trunc((1.0 + Sin(m_gradient.calculate(x ,y ,d ) * m_periods / d ) ) * d / 2 );
+
+end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+type
+ font_type = record
+ font : int8u_ptr;
+ name : PChar;
+
+ end;
+
+const
+ fonts : array[0..34 ] of font_type = (
+ (font:@gse4x6; name:'gse4x6' ) ,
+ (font:@gse4x8; name:'gse4x8' ) ,
+ (font:@gse5x7; name:'gse5x7' ) ,
+ (font:@gse5x9; name:'gse5x9' ) ,
+ (font:@gse6x9; name:'gse6x9' ) ,
+ (font:@gse6x12; name:'gse6x12' ) ,
+ (font:@gse7x11; name:'gse7x11' ) ,
+ (font:@gse7x11_bold; name:'gse7x11_bold' ) ,
+ (font:@gse7x15; name:'gse7x15' ) ,
+ (font:@gse7x15_bold; name:'gse7x15_bold' ) ,
+ (font:@gse8x16; name:'gse8x16' ) ,
+ (font:@gse8x16_bold; name:'gse8x16_bold' ) ,
+ (font:@mcs11_prop; name:'mcs11_prop' ) ,
+ (font:@mcs11_prop_condensed; name:'mcs11_prop_condensed' ) ,
+ (font:@mcs12_prop; name:'mcs12_prop' ) ,
+ (font:@mcs13_prop; name:'mcs13_prop' ) ,
+ (font:@mcs5x10_mono; name:'mcs5x10_mono' ) ,
+ (font:@mcs5x11_mono; name:'mcs5x11_mono' ) ,
+ (font:@mcs6x10_mono; name:'mcs6x10_mono' ) ,
+ (font:@mcs6x11_mono; name:'mcs6x11_mono' ) ,
+ (font:@mcs7x12_mono_high; name:'mcs7x12_mono_high' ) ,
+ (font:@mcs7x12_mono_low; name:'mcs7x12_mono_low' ) ,
+ (font:@verdana12; name:'verdana12' ) ,
+ (font:@verdana12_bold; name:'verdana12_bold' ) ,
+ (font:@verdana13; name:'verdana13' ) ,
+ (font:@verdana13_bold; name:'verdana13_bold' ) ,
+ (font:@verdana14; name:'verdana14' ) ,
+ (font:@verdana14_bold; name:'verdana14_bold' ) ,
+ (font:@verdana16; name:'verdana16' ) ,
+ (font:@verdana16_bold; name:'verdana16_bold' ) ,
+ (font:@verdana17; name:'verdana17' ) ,
+ (font:@verdana17_bold; name:'verdana17_bold' ) ,
+ (font:@verdana18; name:'verdana18' ) ,
+ (font:@verdana18_bold; name:'verdana18_bold' ) ,
+ (font:NIL; name:NIL ) );
+
+var
+ pixf : pixel_formats;
+ rgba ,
+ rgbb : aggclr;
+
+ rb : renderer_base;
+ rt : renderer_raster_htext_solid;
+
+ glyph : glyph_raster_bin;
+
+ i : int;
+ y : double;
+
+ buf : string[100 ];
+ mtx : trans_affine;
+
+ grad_circ : gradient_circle;
+ grad_func : gradient_sine_repeat_adaptor;
+ color_func : gradient_linear_color;
+
+ inter : span_interpolator_linear;
+
+ sa : span_allocator;
+ sg : span_gradient;
+ ren : renderer_scanline_aa;
+ rt2 : renderer_raster_htext;
+
+begin
+// Initialize structures
+ glyph.Construct(NIL );
+
+ pixfmt_bgr24(pixf ,rbuf_window );
+ rb.Construct(@pixf );
+
+ rgba.ConstrDbl(1 ,1 ,1 );
+ rb.clear (@rgba );
+
+ rt.Construct(@rb ,@glyph );
+
+ y:=5;
+
+ rgba.ConstrDbl(0 ,0 ,0 );
+ rt.color_ (@rgba );
+
+// Render all raster fonts
+ i:=0;
+
+ while fonts[i ].font <> NIL do
+ begin
+ buf:='A quick brown fox jumps over the lazy dog 0123456789: ' + fonts[i ].name + #0;
+
+ glyph.font_ (fonts[i ].font );
+ rt.render_text(5 ,y ,@buf[1 ] ,not flip_y );
+
+ y:=y + glyph.height + 1;
+
+ inc(i );
+
+ end;
+
+// Render gradient font
+ grad_circ.Construct;
+ grad_func.Construct(@grad_circ );
+ grad_func._periods (5 );
+
+ rgba.ConstrDbl (1.0 ,0 ,0 );
+ rgbb.ConstrDbl (0 ,0.5 ,0 );
+ color_func.Construct(@rgba ,@rgbb );
+
+ mtx.Construct;
+ inter.Construct(@mtx );
+
+ sa.Construct;
+ sg.Construct (@sa ,@inter ,@grad_func ,@color_func ,0 ,150.0 );
+ ren.Construct(@rb ,@sg );
+ rt2.Construct(@ren ,@glyph );
+
+ rt2.render_text(5 ,465 ,'RADIAL REPEATING GRADIENT: A quick brown fox jumps over the lazy dog' ,not flip_y );
+
+// Free AGG resources
+ sa.Destruct;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ 'Classes that render raster text was added in AGG mostly to prove the concept of '#13 +
+ 'the design. They can be used to draw simple (aliased) raster text. The example '#13 +
+ 'demonstrates how to use text as a custom scanline generator together with any '#13 +
+ 'span generator (in this example it''s gradient filling). The font format is '#13 +
+ 'propriatory, but there are some predefined fonts that are shown in the example.'#13#13 +
+ 'How to play with:'#13#13 +
+ 'Change the renderer "rt" to "renderer_raster_vtext_solid" in the source code'#13 +
+ 'and recompile it, to get the vertical raster font orientation.' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+VAR
+ app : the_application;
+
+BEGIN
+ app.Construct(pix_format_bgr24 ,flip_y );
+ app.caption_ ('AGG Example. Raster Text (F1-Help)' );
+
+ if app.init(640 ,480 ,window_resize ) then
+ app.run;
+
+ app.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/rasterizer_compound.dpr b/src/corelib/render/software/agg-demos/rasterizer_compound.dpr
new file mode 100644
index 00000000..00399381
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/rasterizer_compound.dpr
@@ -0,0 +1,435 @@
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ rasterizer_compound ;
+
+uses
+ agg_basics ,
+ agg_color ,
+ agg_array ,
+ agg_platform_support ,
+ agg_ctrl ,
+ agg_slider_ctrl ,
+ agg_cbox_ctrl ,
+ agg_ellipse ,
+ agg_gamma_lut ,
+ agg_renderer_base ,
+ agg_rendering_buffer ,
+ agg_rasterizer_scanline_aa ,
+ agg_rasterizer_compound_aa ,
+ agg_conv_curve ,
+ agg_conv_stroke ,
+ agg_scanline_u ,
+ agg_renderer_scanline ,
+ agg_span_allocator ,
+ agg_pixfmt ,
+ agg_pixfmt_rgba ,
+ agg_path_storage ,
+ agg_trans_affine ,
+ agg_conv_transform ;
+
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+type
+ style_handler_ = object(style_handler )
+ private
+ m_transparent : aggclr;
+
+ m_styles : aggclr_ptr;
+ m_count : unsigned;
+
+ public
+ constructor Construct(styles : aggclr_ptr; count : unsigned );
+
+ function is_solid(style : unsigned ) : boolean; virtual;
+ function color (style : unsigned ) : aggclr_ptr; virtual;
+
+ procedure generate_span(span : aggclr_ptr; x ,y : int; len ,style : unsigned ); virtual;
+
+ end;
+
+ the_application = object(platform_support )
+ private
+ m_width ,
+ m_alpha1 ,
+ m_alpha2 ,
+ m_alpha3 ,
+ m_alpha4 : slider_ctrl;
+
+ m_invert_order : cbox_ctrl;
+
+ m_path : path_storage;
+
+ public
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure compose_path;
+
+ procedure on_draw; virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ CONSTRUCT }
+constructor style_handler_.Construct(styles : aggclr_ptr; count : unsigned );
+begin
+ m_transparent.ConstrInt(0 ,0 ,0 ,0 );
+
+ m_styles:=styles;
+ m_count :=count;
+
+end;
+
+{ IS_SOLID }
+function style_handler_.is_solid(style : unsigned ) : boolean;
+begin
+ result:=true;
+
+end;
+
+{ COLOR }
+function style_handler_.color(style : unsigned ) : aggclr_ptr;
+begin
+ if style < m_count then
+ result:=aggclr_ptr(ptrcomp(m_styles ) + style * sizeof(aggclr ) )
+ else
+ result:=@m_transparent;
+
+end;
+
+{ GENERATE_SPAN }
+procedure style_handler_.generate_span(span : aggclr_ptr; x ,y : int; len ,style : unsigned );
+begin
+end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_width.Construct (180 + 10.0 ,5.0 ,130 + 300.0 ,12 ,not flip_y_ );
+ m_alpha1.Construct(5 ,5 ,180 ,12 ,not flip_y_ );
+ m_alpha2.Construct(5 ,25 ,180 ,32 ,not flip_y_ );
+ m_alpha3.Construct(5 ,45 ,180 ,52 ,not flip_y_ );
+ m_alpha4.Construct(5 ,65 ,180 ,72 ,not flip_y_ );
+
+ m_invert_order.Construct(190 ,25 ,'Invert Z-Order' );
+ m_path.Construct;
+
+ add_ctrl(@m_width );
+
+ m_width.range_(-20.0 ,50.0 );
+ m_width.value_(10.0 );
+ m_width.label_('Width=%1.2f' );
+
+ add_ctrl(@m_alpha1 );
+
+ m_alpha1.range_(0 ,1 );
+ m_alpha1.value_(1 );
+ m_alpha1.label_('Alpha1=%1.3f' );
+
+ add_ctrl(@m_alpha2 );
+
+ m_alpha2.range_(0 ,1 );
+ m_alpha2.value_(1 );
+ m_alpha2.label_('Alpha2=%1.3f' );
+
+ add_ctrl(@m_alpha3 );
+
+ m_alpha3.range_(0 ,1 );
+ m_alpha3.value_(1 );
+ m_alpha3.label_('Alpha3=%1.3f' );
+
+ add_ctrl(@m_alpha4 );
+
+ m_alpha4.range_(0 ,1 );
+ m_alpha4.value_(1 );
+ m_alpha4.label_('Alpha4=%1.3f' );
+
+ add_ctrl(@m_invert_order );
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_width.Destruct;
+ m_alpha1.Destruct;
+ m_alpha2.Destruct;
+ m_alpha3.Destruct;
+ m_alpha4.Destruct;
+
+ m_invert_order.Destruct;
+ m_path.Destruct;
+
+end;
+
+{ COMPOSE_PATH }
+procedure the_application.compose_path;
+begin
+ m_path.remove_all;
+ m_path.move_to(28.47 ,6.45 );
+ m_path.curve3 (21.58 ,1.12 ,19.82 ,0.29 );
+ m_path.curve3 (17.19 ,-0.93 ,14.21 ,-0.93 );
+ m_path.curve3 (9.57 ,-0.93 ,6.57 ,2.25 );
+ m_path.curve3 (3.56 ,5.42 ,3.56 ,10.60 );
+ m_path.curve3 (3.56 ,13.87 ,5.03 ,16.26 );
+ m_path.curve3 (7.03 ,19.58 ,11.99 ,22.51 );
+ m_path.curve3 (16.94 ,25.44 ,28.47 ,29.64 );
+ m_path.line_to(28.47 ,31.40 );
+ m_path.curve3 (28.47 ,38.09 ,26.34 ,40.58 );
+ m_path.curve3 (24.22 ,43.07 ,20.17 ,43.07 );
+ m_path.curve3 (17.09 ,43.07 ,15.28 ,41.41 );
+ m_path.curve3 (13.43 ,39.75 ,13.43 ,37.60 );
+ m_path.line_to(13.53 ,34.77 );
+ m_path.curve3 (13.53 ,32.52 ,12.38 ,31.30 );
+ m_path.curve3 (11.23 ,30.08 ,9.38 ,30.08 );
+ m_path.curve3 (7.57 ,30.08 ,6.42 ,31.35 );
+ m_path.curve3 (5.27 ,32.62 ,5.27 ,34.81 );
+ m_path.curve3 (5.27 ,39.01 ,9.57 ,42.53 );
+ m_path.curve3 (13.87 ,46.04 ,21.63 ,46.04 );
+ m_path.curve3 (27.59 ,46.04 ,31.40 ,44.04 );
+ m_path.curve3 (34.28 ,42.53 ,35.64 ,39.31 );
+ m_path.curve3 (36.52 ,37.21 ,36.52 ,30.71 );
+ m_path.line_to(36.52 ,15.53 );
+ m_path.curve3 (36.52 ,9.13 ,36.77 ,7.69 );
+ m_path.curve3 (37.01 ,6.25 ,37.57 ,5.76 );
+ m_path.curve3 (38.13 ,5.27 ,38.87 ,5.27 );
+ m_path.curve3 (39.65 ,5.27 ,40.23 ,5.62 );
+ m_path.curve3 (41.26 ,6.25 ,44.19 ,9.18 );
+ m_path.line_to(44.19 ,6.45 );
+ m_path.curve3 (38.72 ,-0.88 ,33.74 ,-0.88 );
+ m_path.curve3 (31.35 ,-0.88 ,29.93 ,0.78 );
+ m_path.curve3 (28.52 ,2.44 ,28.47 ,6.45 );
+ m_path.close_polygon;
+
+ m_path.move_to(28.47 ,9.62 );
+ m_path.line_to(28.47 ,26.66 );
+ m_path.curve3 (21.09 ,23.73 ,18.95 ,22.51 );
+ m_path.curve3 (15.09 ,20.36 ,13.43 ,18.02 );
+ m_path.curve3 (11.77 ,15.67 ,11.77 ,12.89 );
+ m_path.curve3 (11.77 ,9.38 ,13.87 ,7.06 );
+ m_path.curve3 (15.97 ,4.74 ,18.70 ,4.74 );
+ m_path.curve3 (22.41 ,4.74 ,28.47 ,9.62 );
+ m_path.close_polygon;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ pixf ,pixf_pre : pixel_formats;
+
+ rgba ,c1 ,c2 : aggclr;
+
+ renb ,renb_pre : renderer_base;
+
+ rs : renderer_scanline_aa_solid;
+ gr : pod_vector;
+ i : unsigned;
+
+ lut : gamma_lut;
+ ras : rasterizer_scanline_aa;
+ rasc : rasterizer_compound_aa_dbl;
+
+ sl : scanline_u8;
+ sh : style_handler_;
+
+ alloc : span_allocator;
+
+ mtx : trans_affine;
+ tas : trans_affine_scaling;
+ tat : trans_affine_translation;
+
+ trans : conv_transform;
+ curve : conv_curve;
+
+ stroke ,str_ell : conv_stroke_math;
+
+ styles : array[0..3 ] of aggclr;
+
+ ell : ellipse;
+
+begin
+// Initialize structures
+ lut.Construct(2.0 );
+
+ pixfmt_bgra32 (pixf ,rbuf_window );
+ renb.Construct(@pixf );
+ rs.Construct (@renb );
+
+ pixfmt_bgra32_pre (pixf_pre ,rbuf_window );
+ renb_pre.Construct(@pixf_pre );
+
+// Clear the window with a gradient
+ gr.Create(sizeof(aggclr ) ,pixf._width );
+
+ i:=0;
+
+ while i < pixf._width do
+ begin
+ c1.ConstrInt(255 ,255 ,0 );
+ c2.ConstrInt(0 ,255 ,255 );
+
+ rgba:=c1.gradient(@c2 ,i / pixf._width );
+
+ gr.add(@rgba );
+ inc (i );
+
+ end;
+
+ i:=0;
+
+ while i < pixf._height do
+ begin
+ renb.copy_color_hspan(0 ,i ,pixf._width ,gr.array_operator(0 ) );
+
+ inc(i );
+
+ end;
+
+ pixf.apply_gamma_dir(@lut ,bgra_order );
+
+ ras.Construct;
+ rasc.Construct;
+ sl.Construct;
+ alloc.Construct;
+
+// Draw two triangles
+ ras.move_to_d(0 ,0 );
+ ras.line_to_d(_width ,0 );
+ ras.line_to_d(_width ,_height );
+
+ rgba.ConstrInt(lut.dir(0 ) ,lut.dir(100 ) ,lut.dir(0 ) );
+
+ render_scanlines_aa_solid(@ras ,@sl ,@renb ,@rgba );
+
+ ras.move_to_d(0 ,0 );
+ ras.line_to_d(0 ,_height );
+ ras.line_to_d(_width ,0 );
+
+ rgba.ConstrInt(lut.dir(0 ) ,lut.dir(100 ) ,lut.dir(100 ) );
+
+ render_scanlines_aa_solid(@ras ,@sl ,@renb ,@rgba );
+
+ mtx.Construct;
+ tas.Construct(4.0 );
+ mtx.multiply (@tas );
+ tat.Construct(150 ,100 );
+ mtx.multiply (@tat );
+
+ trans.Construct (@m_path ,@mtx );
+ curve.Construct (@trans );
+ stroke.Construct(@curve );
+
+ compose_path;
+
+ if m_invert_order._status then
+ rasc.layer_order(layer_inverse )
+ else
+ rasc.layer_order(layer_direct );
+
+ styles[3 ].ConstrInt(lut.dir(255 ) ,lut.dir(0 ) ,lut.dir(108 ) ,200 );
+ styles[3 ].premultiply;
+ styles[2 ].ConstrInt(lut.dir(51 ) ,lut.dir(0 ) ,lut.dir(151 ) ,180 );
+ styles[2 ].premultiply;
+ styles[1 ].ConstrInt(lut.dir(143 ) ,lut.dir(90 ) ,lut.dir(6 ) ,200 );
+ styles[1 ].premultiply;
+ styles[0 ].ConstrInt(lut.dir(0 ) ,lut.dir(0 ) ,lut.dir(255 ) ,220 );
+ styles[0 ].premultiply;
+
+ sh.Construct (@styles[0 ] ,4 );
+ stroke.width_(m_width._value );
+
+ rasc.reset;
+ rasc.master_alpha(3 ,m_alpha1._value );
+ rasc.master_alpha(2 ,m_alpha2._value );
+ rasc.master_alpha(1 ,m_alpha3._value );
+ rasc.master_alpha(0 ,m_alpha4._value );
+
+ ell.Construct (220.0 ,180.0 ,120.0 ,10.0 ,128 ,false );
+ str_ell.Construct(@ell );
+ str_ell.width_ (m_width._value / 2 );
+
+ rasc.styles (3 ,-1 );
+ rasc.add_path(@str_ell );
+
+ rasc.styles (2 ,-1 );
+ rasc.add_path(@ell );
+
+ rasc.styles (1 ,-1 );
+ rasc.add_path(@stroke );
+
+ rasc.styles (0 ,-1 );
+ rasc.add_path(@curve );
+
+ render_scanlines_compound_layered(@rasc ,@sl ,@renb_pre ,@alloc ,@sh );
+
+// Render the controls
+ render_ctrl(@ras ,@sl ,@rs ,@m_width );
+ render_ctrl(@ras ,@sl ,@rs ,@m_alpha1 );
+ render_ctrl(@ras ,@sl ,@rs ,@m_alpha2 );
+ render_ctrl(@ras ,@sl ,@rs ,@m_alpha3 );
+ render_ctrl(@ras ,@sl ,@rs ,@m_alpha4 );
+ render_ctrl(@ras ,@sl ,@rs ,@m_invert_order );
+
+ pixf.apply_gamma_inv(@lut ,bgra_order );
+
+// Free AGG resources
+ lut.Destruct;
+ gr.Destruct;
+
+ ras.Destruct;
+ rasc.Destruct;
+ sl.Destruct;
+ alloc.Destruct;
+
+ curve.Destruct;
+ stroke.Destruct;
+ str_ell.Destruct;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ 'This simple example demonstrates a rather advanced technique of using '#13 +
+ 'the compound rasterizer. The idea is you assign styles to the polygons '#13 +
+ '(left=style, right=-1) and rasterize this "multi-styled" compound shape '#13 +
+ 'as a whole. If the polygons in the shape overlap, the greater styles '#13 +
+ 'have higher priority. That is, the result is as if greater styles were '#13 +
+ 'painted last, but the geometry is flattened before rendering. It means '#13 +
+ 'there are no pixels will be painted twice. Then the style are associated '#13 +
+ 'with colors, gradients, images, etc. in a special style handler. '#13 +
+ 'It simulates Constructive Solid Geometry so that, you can, for example '#13 +
+ 'draw a translucent fill plus translucent stroke without the overlapped '#13 +
+ 'part of the fill being visible through the stroke.' );
+
+end;
+
+VAR
+ app : the_application;
+
+BEGIN
+ app.Construct(pix_format_bgra32 ,flip_y );
+ app.caption_ ('AGG Example. Compound Rasterizer -- Geometry Flattening (F1-Help)' );
+
+ if app.init(440 ,330 ,0 ) then
+ app.run;
+
+ app.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/rasterizers.dpr b/src/corelib/render/software/agg-demos/rasterizers.dpr
new file mode 100644
index 00000000..d67093b9
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/rasterizers.dpr
@@ -0,0 +1,449 @@
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ rasterizers ;
+
+{$DEFINE AGG_BGR24 }
+
+uses
+ SysUtils ,
+
+ agg_basics ,
+ agg_platform_support ,
+ agg_math ,
+
+ agg_ctrl ,
+ agg_slider_ctrl ,
+ agg_cbox_ctrl ,
+
+ agg_rasterizer_scanline_aa ,
+ agg_rasterizer_outline ,
+ agg_scanline ,
+ agg_scanline_p ,
+ agg_scanline_bin ,
+
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_renderer_primitives ,
+ agg_render_scanlines ,
+
+ agg_path_storage ,
+ agg_gamma_functions
+
+{$I pixel_formats.inc }
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+type
+ the_application = object(platform_support )
+ m_x ,
+ m_y : array[0..2 ] of double;
+
+ m_dx ,
+ m_dy : double;
+
+ m_idx : int;
+
+ m_gamma ,
+ m_alpha : slider_ctrl;
+ m_test : cbox_ctrl;
+
+ m_ras : rasterizer_scanline_aa;
+ m_sl_p8 : scanline_p8;
+ m_sl_bin : scanline_bin;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure draw_anti_aliased;
+ procedure draw_aliased;
+
+ procedure on_draw; virtual;
+
+ procedure on_mouse_move(x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_up (x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+ procedure on_ctrl_change; virtual;
+
+ end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_ras.Construct;
+ m_sl_p8.Construct;
+ m_sl_bin.Construct;
+
+ m_idx:=-1;
+
+ m_x[0 ]:=100 + 120; m_y[0 ]:=60;
+ m_x[1 ]:=369 + 120; m_y[1 ]:=170;
+ m_x[2 ]:=143 + 120; m_y[2 ]:=310;
+
+ m_gamma.Construct(130 + 10 ,10 + 4 ,130 + 150 ,10 + 8 + 4 ,not flip_y );
+
+ add_ctrl(@m_gamma );
+
+ m_gamma.range_(0 ,1 );
+ m_gamma.value_(0.5 );
+ m_gamma.label_('Gamma=%1.2f' );
+ m_gamma.no_transform;
+
+ m_alpha.Construct(130 + 150 + 10 ,10 + 4 ,500 - 10 ,10 + 8 + 4 ,not flip_y );
+
+ add_ctrl(@m_alpha );
+
+ m_alpha.range_(0 ,1 );
+ m_alpha.value_(1 );
+ m_alpha.label_('Alpha=%1.2f' );
+ m_alpha.no_transform;
+
+ m_test.Construct(130 + 10.0 ,10.0 + 4.0 + 16.0 ,'Test Performance' ,not flip_y );
+
+ add_ctrl(@m_test );
+
+ m_test.no_transform;
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_alpha.Destruct;
+ m_gamma.Destruct;
+ m_test.Destruct;
+
+ m_ras.Destruct;
+ m_sl_p8.Destruct;
+ m_sl_bin.Destruct;
+
+end;
+
+{ DRAW_ANTI_ALIASED }
+procedure the_application.draw_anti_aliased;
+var
+ pixf : pixel_formats;
+ rb : renderer_base;
+ ren_aa : renderer_scanline_aa_solid;
+
+ path : path_storage;
+ rgba : aggclr;
+
+ gamma : gamma_power;
+
+begin
+ pixfmt(pixf ,rbuf_window );
+
+ rb.Construct (@pixf );
+ ren_aa.Construct(@rb );
+
+// Path & Color
+ path.Construct;
+
+ path.move_to(m_x[0 ] ,m_y[0 ] );
+ path.line_to(m_x[1 ] ,m_y[1 ] );
+ path.line_to(m_x[2 ] ,m_y[2 ] );
+ path.close_polygon;
+
+ rgba.ConstrDbl(0.7 ,0.5 ,0.1 ,m_alpha._value );
+ ren_aa.color_ (@rgba );
+
+// Draw
+ gamma.Construct(m_gamma._value * 2.0 );
+
+ m_ras.gamma (@gamma );
+ m_ras.add_path(@path );
+
+ render_scanlines(@m_ras ,@m_sl_p8 ,@ren_aa );
+
+// Free
+ path.Destruct;
+
+end;
+
+{ DRAW_ALIASED }
+procedure the_application.draw_aliased;
+var
+ pixf : pixel_formats;
+ rb : renderer_base;
+ ren_bin : renderer_scanline_bin_solid;
+
+ path : path_storage;
+ rgba : aggclr;
+
+ gamma : gamma_threshold;
+
+ ren_pr : renderer_primitives;
+ ras_line : rasterizer_outline;
+
+begin
+ pixfmt(pixf ,rbuf_window );
+
+ rb.Construct (@pixf );
+ ren_bin.Construct(@rb );
+
+// Path & Color
+ path.Construct;
+
+ path.move_to(m_x[0 ] - 200 ,m_y[0 ] );
+ path.line_to(m_x[1 ] - 200 ,m_y[1 ] );
+ path.line_to(m_x[2 ] - 200 ,m_y[2 ] );
+ path.close_polygon;
+
+ rgba.ConstrDbl(0.1 ,0.5 ,0.7 ,m_alpha._value );
+ ren_bin.color_(@rgba );
+
+// Draw
+ gamma.Construct(m_gamma._value );
+
+ m_ras.gamma (@gamma );
+ m_ras.add_path(@path );
+
+ render_scanlines(@m_ras ,@m_sl_bin ,@ren_bin );
+
+//-- Drawing an outline with subpixel accuracy (aliased)
+(* ren_pr.Construct (@rb );
+ ras_line.Construct(@ren_pr );
+
+ rgba.ConstrDbl(0.0 ,0.0 ,0.0 );
+
+ ren_pr._line_color(@rgba );
+ ras_line.add_path (@path );(**)
+
+// Free
+ path.Destruct;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ pixf : pixel_formats;
+ rb : renderer_base;
+ ren_aa : renderer_scanline_aa_solid;
+
+ ras_aa : rasterizer_scanline_aa;
+
+ rgba : aggclr;
+
+begin
+// Initialize structures
+ pixfmt(pixf ,rbuf_window );
+
+ rb.Construct (@pixf );
+ ren_aa.Construct(@rb );
+
+ ras_aa.Construct;
+
+// Setup colors & background
+ rgba.ConstrDbl(1 ,1 ,1 );
+
+ rb.clear(@rgba );
+
+// Draw
+ draw_anti_aliased;
+ draw_aliased;
+
+// Render controls
+ render_ctrl(@ras_aa ,@m_sl_p8 ,@ren_aa ,@m_gamma );
+ render_ctrl(@ras_aa ,@m_sl_p8 ,@ren_aa ,@m_alpha );
+ render_ctrl(@ras_aa ,@m_sl_p8 ,@ren_aa ,@m_test );
+
+// Free AGG resources
+ ras_aa.Destruct;
+
+end;
+
+{ ON_MOUSE_MOVE }
+procedure the_application.on_mouse_move;
+var
+ dx ,dy : double;
+
+begin
+ if flags and mouse_left <> 0 then
+ begin
+ if m_idx = 3 then
+ begin
+ dx:=x - m_dx;
+ dy:=y - m_dy;
+
+ m_x[1 ]:=m_x[1 ] - (m_x[0 ] - dx );
+ m_y[1 ]:=m_y[1 ] - (m_y[0 ] - dy );
+ m_x[2 ]:=m_x[2 ] - (m_x[0 ] - dx );
+ m_y[2 ]:=m_y[2 ] - (m_y[0 ] - dy );
+ m_x[0 ]:= dx;
+ m_y[0 ]:= dy;
+
+ force_redraw;
+ exit;
+
+ end;
+
+ if m_idx >= 0 then
+ begin
+ m_x[m_idx ]:=x - m_dx;
+ m_y[m_idx ]:=y - m_dy;
+
+ force_redraw;
+
+ end;
+
+ end;
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure the_application.on_mouse_button_down;
+var
+ i : unsigned;
+
+begin
+ if flags and mouse_left <> 0 then
+ begin
+ i:=0;
+
+ while i < 3 do
+ begin
+ if (Sqrt((x - m_x[i ] ) * (x - m_x[i ] ) + (y - m_y[i ] ) * (y - m_y[i ] ) ) < 20 ) or
+ (Sqrt((x - m_x[i ] + 200 ) * (x - m_x[i ] + 200 ) + (y - m_y[i ] ) * (y - m_y[i ] ) ) < 20 ) then
+ begin
+ m_dx :=x - m_x[i ];
+ m_dy :=y - m_y[i ];
+ m_idx:=i;
+
+ break;
+
+ end;
+
+ inc(i );
+
+ end;
+
+ if i = 3 then
+ if point_in_triangle(m_x[0 ] ,m_y[0 ] ,m_x[1 ] ,m_y[1 ] ,m_x[2 ] ,m_y[2 ] ,x ,y ) or
+ point_in_triangle(m_x[0 ] - 200 ,m_y[0 ] ,m_x[1 ] - 200 ,m_y[1 ] ,m_x[2 ] - 200 ,m_y[2 ] ,x ,y ) then
+ begin
+ m_dx :=x - m_x[0 ];
+ m_dy :=y - m_y[0 ];
+ m_idx:= 3;
+
+ end;
+
+ end;
+
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+procedure the_application.on_mouse_button_up;
+begin
+ m_idx:=-1;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+var
+ dx ,dy : double;
+
+begin
+ dx:=0;
+ dy:=0;
+
+ case key of
+ key_left : dx:=-0.1;
+ key_right : dx:= 0.1;
+ key_up : dy:= 0.1;
+ key_down : dy:=-0.1;
+
+ end;
+
+ m_x[0 ]:=m_x[0 ] + dx;
+ m_y[0 ]:=m_y[0 ] + dy;
+ m_x[1 ]:=m_x[1 ] + dx;
+ m_y[1 ]:=m_y[1 ] + dy;
+
+ force_redraw;
+
+ if key = key_f1 then
+ message_(
+ 'It''s a very simple example that was written to compare the performance between '#13 +
+ 'Anti-Aliased and regular polygon filling. It appears that the most expensive '#13 +
+ 'operation is rendering of horizontal scanlines. So that, we can use the very '#13 +
+ 'same rasterization algorithm to draw regular, aliased polygons. Of course, it''s '#13 +
+ 'possible to write a special version of the rasterizer that will work faster, but '#13 +
+ 'won''t calculate the pixel coverage values. But on the other hand, the existing '#13 +
+ 'version of the rasterizer_scanline_aa allows you to change gamma, and to "dilate" '#13 +
+ 'or "shrink" the polygons in range of ± 1 pixel.'#13#13 +
+ 'How to play with:'#13#13 +
+ 'As usual, you can drag the triangles as well as the vertices of them. '#13 +
+ 'Compare the performance with different shapes and opacity.' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+{ ON_CTRL_CHANGE }
+procedure the_application.on_ctrl_change;
+var
+ i : int;
+
+ t1 ,t2 : double;
+
+ buf : array[0..99 ] of char;
+
+begin
+ if m_test._status then
+ begin
+ on_draw;
+ update_window;
+ m_test.status_(false );
+
+ start_timer;
+
+ for i:=0 to 999 do
+ draw_aliased;
+
+ t1:=elapsed_time;
+
+ start_timer;
+
+ for i:=0 to 999 do
+ draw_anti_aliased;
+
+ t2:=elapsed_time;
+
+ update_window;
+
+ sprintf (@buf[0 ] ,'Time Aliased=%.2fms '#0 ,t1 );
+ sprintf (@buf[StrLen(@buf[0 ] ) ] ,'Time Anti-Aliased=%.2fms'#0 ,t2 );
+ message_(@buf[0 ] );
+
+ end;
+
+end;
+
+VAR
+ app : the_application;
+
+BEGIN
+ app.Construct(pix_format ,flip_y );
+ app.caption_ ('AGG Example. Line Join (F1-Help)' );
+
+ if app.init(500 ,330 ,window_resize ) then
+ app.run;
+
+ app.Destruct;
+
+END.
diff --git a/src/corelib/render/software/agg-demos/rasterizers2.dpr b/src/corelib/render/software/agg-demos/rasterizers2.dpr
new file mode 100644
index 00000000..473616ee
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/rasterizers2.dpr
@@ -0,0 +1,805 @@
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ rasterizers2 ;
+
+{DEFINE AGG_GRAY8 }
+{$DEFINE AGG_BGR24 }
+{DEFINE AGG_RGB24 }
+{DEFINE AGG_BGRA32 }
+{DEFINE AGG_RGBA32 }
+{DEFINE AGG_ARGB32 }
+{DEFINE AGG_ABGR32 }
+{DEFINE AGG_RGB565 }
+{DEFINE AGG_RGB555 }
+
+uses
+ Math ,SysUtils ,
+
+ agg_basics ,
+ agg_platform_support ,
+
+ agg_ctrl ,
+ agg_slider_ctrl ,
+ agg_cbox_ctrl ,
+
+ agg_rasterizer_scanline_aa ,
+ agg_rasterizer_outline ,
+ agg_rasterizer_outline_aa ,
+ agg_scanline ,
+ agg_scanline_p ,
+
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_renderer_primitives ,
+ agg_renderer_outline_aa ,
+ agg_renderer_outline_image ,
+ agg_render_scanlines ,
+
+ agg_gsv_text ,
+ agg_conv_stroke ,
+ agg_conv_transform ,
+ agg_vertex_source ,
+ agg_math_stroke ,
+ agg_trans_affine ,
+ agg_pattern_filters_rgba ,
+ agg_gamma_functions
+
+{$I pixel_formats.inc }
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+ pixmap_chain : array[0..113 ] of int32u = (
+ 16 ,7 ,
+ $00ffffff ,$00ffffff ,$00ffffff ,$00ffffff ,$b4c29999 ,$ff9a5757 ,$ff9a5757 ,
+ $ff9a5757 ,$ff9a5757 ,$ff9a5757 ,$ff9a5757 ,$b4c29999 ,$00ffffff ,$00ffffff ,
+ $00ffffff ,$00ffffff ,$00ffffff ,$00ffffff ,$0cfbf9f9 ,$ff9a5757 ,$ff660000 ,
+ $ff660000 ,$ff660000 ,$ff660000 ,$ff660000 ,$ff660000 ,$ff660000 ,$ff660000 ,
+ $b4c29999 ,$00ffffff ,$00ffffff ,$00ffffff ,$00ffffff ,$5ae0cccc ,$ffa46767 ,
+ $ff660000 ,$ff975252 ,$7ed4b8b8 ,$5ae0cccc ,$5ae0cccc ,$5ae0cccc ,$5ae0cccc ,
+ $a8c6a0a0 ,$ff7f2929 ,$ff670202 ,$9ecaa6a6 ,$5ae0cccc ,$00ffffff ,$ff660000 ,
+ $ff660000 ,$ff660000 ,$ff660000 ,$ff660000 ,$ff660000 ,$a4c7a2a2 ,$3affff00 ,
+ $3affff00 ,$ff975151 ,$ff660000 ,$ff660000 ,$ff660000 ,$ff660000 ,$ff660000 ,
+ $ff660000 ,$00ffffff ,$5ae0cccc ,$ffa46767 ,$ff660000 ,$ff954f4f ,$7ed4b8b8 ,
+ $5ae0cccc ,$5ae0cccc ,$5ae0cccc ,$5ae0cccc ,$a8c6a0a0 ,$ff7f2929 ,$ff670202 ,
+ $9ecaa6a6 ,$5ae0cccc ,$00ffffff ,$00ffffff ,$00ffffff ,$0cfbf9f9 ,$ff9a5757 ,
+ $ff660000 ,$ff660000 ,$ff660000 ,$ff660000 ,$ff660000 ,$ff660000 ,$ff660000 ,
+ $ff660000 ,$b4c29999 ,$00ffffff ,$00ffffff ,$00ffffff ,$00ffffff ,$00ffffff ,
+ $00ffffff ,$00ffffff ,$b4c29999 ,$ff9a5757 ,$ff9a5757 ,$ff9a5757 ,$ff9a5757 ,
+ $ff9a5757 ,$ff9a5757 ,$b4c29999 ,$00ffffff ,$00ffffff ,$00ffffff ,$00ffffff );
+
+type
+ pattern_pixmap_argb32 = object(pixel_source )
+ m_pixmap : int32u_ptr;
+
+ constructor Construct(pixmap : int32u_ptr );
+
+ function _width : unsigned; virtual;
+ function _height : unsigned; virtual;
+
+ function pixel(x ,y : int ) : rgba8; virtual;
+
+ end;
+
+ spiral = object(vertex_source )
+ m_x ,m_y ,m_r1 ,m_r2 ,
+ m_step ,m_start_angle ,
+ m_angle ,m_curr_r ,m_da ,m_dr : double;
+
+ m_start : boolean;
+
+ constructor Construct(x ,y ,r1 ,r2 ,step : double; start_angle : double = 0 );
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ end;
+
+ the_application = object(platform_support )
+ m_step ,
+ m_width : slider_ctrl;
+ m_test ,
+ m_rotate ,
+
+ m_accurate_joins ,
+ m_scale_pattern : cbox_ctrl;
+
+ m_start_angle : double;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure draw_aliased_pix_accuracy (ras : rasterizer_outline_ptr; prim : renderer_primitives_ptr );
+ procedure draw_aliased_subpix_accuracy(ras : rasterizer_outline_ptr; prim : renderer_primitives_ptr );
+
+ procedure draw_anti_aliased_outline(
+ ras : rasterizer_outline_aa_ptr;
+ ren : renderer_outline_aa_ptr );
+
+ procedure draw_anti_aliased_scanline(
+ ras : rasterizer_scanline_aa_ptr;
+ sl : scanline_ptr;
+ ren : renderer_scanline_aa_solid_ptr );
+
+ procedure draw_anti_aliased_outline_img(
+ ras : rasterizer_outline_aa_ptr;
+ ren : renderer_outline_ptr );
+
+ procedure text(
+ ras : rasterizer_scanline_aa_ptr;
+ sl : scanline_ptr;
+ ren : renderer_scanline_aa_solid_ptr;
+ x ,y : double; txt : PChar );
+
+ procedure on_draw; virtual;
+ procedure on_idle; virtual;
+
+ procedure on_ctrl_change; virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ CONSTRUCT }
+constructor pattern_pixmap_argb32.Construct;
+begin
+ m_pixmap:=pixmap;
+
+end;
+
+{ _WIDTH }
+function pattern_pixmap_argb32._width;
+begin
+ result:=m_pixmap^;
+
+end;
+
+{ _HEIGHT }
+function pattern_pixmap_argb32._height;
+begin
+ result:=int32u_ptr(ptrcomp(m_pixmap ) + sizeof(int32u ) )^;
+
+end;
+
+{ PIXEL }
+function pattern_pixmap_argb32.pixel;
+var
+ p : int32u;
+
+begin
+ p:=int32u_ptr(ptrcomp(m_pixmap ) + (y * _width + x + 2 ) * sizeof(int32u ) )^;
+
+ result.r:=(p shr 16 ) and $FF;
+ result.g:=(p shr 8 ) and $FF;
+ result.b:=p and $FF;
+ result.a:=p shr 24;
+
+end;
+
+{ ROUNDOFF }
+procedure roundoff(this : trans_affine_ptr; x ,y : double_ptr );
+begin
+ x^:=Floor(x^ );
+ y^:=Floor(y^ );
+
+end;
+
+{ CONSTRUCT }
+constructor spiral.Construct;
+begin
+ m_x :=x;
+ m_y :=y;
+ m_r1:=r1;
+ m_r2:=r2;
+
+ m_step :=step;
+ m_start_angle:=start_angle;
+ m_angle :=start_angle;
+
+ m_da:=deg2rad(8.0 );
+ m_dr:=m_step / 45.0;
+
+end;
+
+{ REWIND }
+procedure spiral.rewind;
+begin
+ m_angle :=m_start_angle;
+ m_curr_r:=m_r1;
+ m_start :=true;
+
+end;
+
+{ VERTEX }
+function spiral.vertex;
+begin
+ if m_curr_r > m_r2 then
+ result:=path_cmd_stop
+
+ else
+ begin
+ x^:=m_x + Cos(m_angle ) * m_curr_r;
+ y^:=m_y + Sin(m_angle ) * m_curr_r;
+
+ m_curr_r:=m_curr_r + m_dr;
+ m_angle :=m_angle + m_da;
+
+ if m_start then
+ begin
+ m_start:=false;
+
+ result:=path_cmd_move_to;
+
+ end
+ else
+ result:=path_cmd_line_to;
+
+ end;
+
+end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_step.Construct (10.0 ,10.0 + 4.0 ,150.0 ,10.0 + 8.0 + 4.0 ,not flip_y_ );
+ m_width.Construct (150.0 + 10.0 ,10.0 + 4.0 ,400 - 10.0 ,10.0 + 8.0 + 4.0 ,not flip_y_ );
+ m_test.Construct (10.0 ,10.0 + 4.0 + 16.0 ,'Test Performance' ,not flip_y_ );
+ m_rotate.Construct(130 + 10.0 ,10.0 + 4.0 + 16.0 ,'Rotate' ,not flip_y_ );
+
+ m_accurate_joins.Construct(200 + 10.0 ,10.0 + 4.0 + 16.0 ,'Accurate Joins' ,not flip_y_ );
+ m_scale_pattern.Construct (310 + 10.0 ,10.0 + 4.0 + 16.0 ,'Scale Pattern' ,not flip_y_ );
+
+ m_start_angle:=0.0;
+
+ add_ctrl(@m_step );
+
+ m_step.range_(0.0 ,2.0 );
+ m_step.value_(0.1 );
+ m_step.label_('Step=%1.2f' );
+ m_step.no_transform;
+
+ add_ctrl(@m_width );
+
+ m_width.range_(0.0 ,7.0 );
+ m_width.value_(3.0 );
+ m_width.label_('Width=%1.2f' );
+ m_width.no_transform;
+
+ add_ctrl(@m_test );
+
+ m_test.text_size_(9.0 ,7.0 );
+ m_test.no_transform;
+
+ add_ctrl(@m_rotate );
+
+ m_rotate.text_size_(9.0 ,7.0 );
+ m_rotate.no_transform;
+
+ add_ctrl(@m_accurate_joins);
+
+ m_accurate_joins.text_size_(9.0 ,7.0 );
+ m_accurate_joins.no_transform;
+
+ add_ctrl(@m_scale_pattern );
+
+ m_scale_pattern.text_size_(9.0 ,7.0 );
+ m_scale_pattern.status_ (true );
+ m_scale_pattern.no_transform;
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_step.Destruct;
+ m_width.Destruct;
+ m_test.Destruct;
+ m_rotate.Destruct;
+
+ m_accurate_joins.Destruct;
+ m_scale_pattern.Destruct;
+
+end;
+
+{ DRAW_ANTI_ALIASED_OUTLINE }
+procedure the_application.draw_anti_aliased_outline;
+var
+ s3 : spiral;
+
+ rgba : aggclr;
+
+begin
+ s3.Construct(_width / 5 ,_height - _height / 4 + 20 ,5 ,70 ,8 ,m_start_angle );
+
+ rgba.ConstrDbl(0.4 ,0.3 ,0.1 );
+ ren.color_ (@rgba );
+ ras.add_path (@s3 );
+
+end;
+
+{ DRAW_ANTI_ALIASED_SCANLINE }
+procedure the_application.draw_anti_aliased_scanline;
+var
+ s4 : spiral;
+
+ rgba : aggclr;
+
+ stroke : conv_stroke;
+
+begin
+ s4.Construct(_width / 2 ,_height - _height / 4 + 20 ,5 ,70 ,8 ,m_start_angle );
+
+ stroke.Construct(@s4 );
+ stroke.width_ (m_width._value );
+ stroke.line_cap_(round_cap );
+
+ rgba.ConstrDbl(0.4 ,0.3 ,0.1 );
+ ren.color_ (@rgba );
+
+ ras.add_path (@stroke );
+ render_scanlines(ras ,sl ,ren );
+
+ stroke.Destruct;
+
+end;
+
+{ DRAW_ALIASED_PIX_ACCURACY }
+procedure the_application.draw_aliased_pix_accuracy;
+var
+ s1 : spiral;
+ rn : trans_affine;
+
+ rgba : aggclr;
+ trans : conv_transform;
+
+begin
+ s1.Construct(_width / 5 ,_height / 4 + 50 ,5 ,70 ,8 ,m_start_angle );
+ rn.Construct(@roundoff );
+
+ trans.Construct(@s1 ,@rn );
+
+ rgba.ConstrDbl (0.4 ,0.3 ,0.1 );
+ prim.line_color_(@rgba );
+ ras.add_path (@trans );
+
+end;
+
+{ DRAW_ALIASED_SUBPIX_ACCURACY }
+procedure the_application.draw_aliased_subpix_accuracy;
+var
+ s2 : spiral;
+
+ rgba : aggclr;
+
+begin
+ s2.Construct(_width / 2 ,_height / 4 + 50 ,5 ,70 ,8 ,m_start_angle );
+
+ rgba.ConstrDbl (0.4 ,0.3 ,0.1 );
+ prim.line_color_(@rgba );
+ ras.add_path (@s2 );
+
+end;
+
+{ DRAW_ANTI_ALIASED_OUTLINE_IMG }
+procedure the_application.draw_anti_aliased_outline_img;
+var
+ s5 : spiral;
+
+begin
+ s5.Construct(_width - _width / 5 ,_height - _height / 4 + 20 ,5 ,70 ,8 ,m_start_angle );
+ ras.add_path(@s5 );
+
+end;
+
+{ TEXT }
+procedure the_application.text;
+var
+ t : gsv_text;
+
+ stroke : conv_stroke;
+ rgba : aggclr;
+
+begin
+ t.Construct;
+ t.size_(8 );
+ t.text_(txt );
+
+ t.start_point_ (x ,y );
+ stroke.Construct(@t );
+ stroke.width_ (0.7 );
+
+ ras.add_path (@stroke );
+ rgba.ConstrDbl(0 ,0 ,0 );
+ ren.color_ (@rgba );
+
+ render_scanlines(ras ,sl ,ren );
+
+ t.Destruct;
+ stroke.Destruct;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ pf : pixel_formats;
+
+ ren_base : renderer_base;
+ ren_aa : renderer_scanline_aa_solid;
+ ren_prim : renderer_primitives;
+ ras_aa : rasterizer_scanline_aa;
+ ras_al : rasterizer_outline;
+ sl : scanline_p8;
+
+ rgba : aggclr;
+
+ prof : line_profile_aa;
+ ren_oaa : renderer_outline_aa;
+ ras_oaa : rasterizer_outline_aa;
+
+ filter : pattern_filter_bilinear_rgba;
+ src : pattern_pixmap_argb32;
+ src_scaled : line_image_scale;
+ pattern : line_image_pattern_pow2;
+
+ ren_img : renderer_outline_image;
+ ras_img : rasterizer_outline_aa;
+
+ width_ : double;
+ profile : line_profile_aa;
+ gm_pw : gamma_power;
+
+ pixf : pixel_formats;
+ base_ren : renderer_base;
+ ren : renderer_outline_aa;
+ ras : rasterizer_outline_aa;
+
+ fltr : pattern_filter_bilinear_rgba;
+ patt_src : pattern_pixmap_argb32;
+ patt : line_image_pattern_pow2;
+ renimg : renderer_outline_image;
+ rasimg : rasterizer_outline_aa;
+
+begin
+// Initialize structures
+ pixfmt(pf ,rbuf_window );
+
+ ren_base.Construct(@pf );
+ ren_aa.Construct (@ren_base );
+ ren_prim.Construct(@ren_base );
+
+ ras_aa.Construct;
+ sl.Construct;
+ ras_al.Construct(@ren_prim );
+
+ prof.Construct;
+ prof.width_(m_width._value );
+
+ ren_oaa.Construct(@ren_base ,@prof );
+ ras_oaa.Construct(@ren_oaa );
+
+ ras_oaa.accurate_join_(m_accurate_joins._status );
+ ras_oaa.round_cap_ (true );
+
+// Image pattern
+ filter.Construct;
+ src.Construct(@pixmap_chain );
+
+ src_scaled.Construct(@src ,m_width._value );
+ pattern.Construct (@filter );
+
+ if m_scale_pattern._status then
+ pattern.create(@src_scaled )
+ else
+ pattern.create(@src );
+
+ ren_img.Construct(@ren_base ,@pattern );
+
+ if m_scale_pattern._status then
+ ren_img.scale_x_(m_width._value / src._height );
+
+ ras_img.Construct(@ren_img );
+
+// Circles
+ rgba.ConstrDbl(1.0 ,1.0 ,0.95 );
+ ren_base.clear(@rgba );
+
+ draw_aliased_pix_accuracy (@ras_al ,@ren_prim );
+ draw_aliased_subpix_accuracy (@ras_al ,@ren_prim );
+ draw_anti_aliased_outline (@ras_oaa ,@ren_oaa );
+ draw_anti_aliased_scanline (@ras_aa ,@sl ,@ren_aa );
+ draw_anti_aliased_outline_img(@ras_img ,@ren_img );
+
+// Text
+ text(@ras_aa ,@sl ,@ren_aa ,50 ,80 ,'Bresenham lines,'#13#13'regular accuracy' );
+ text(@ras_aa ,@sl ,@ren_aa ,_width / 2 - 50 ,80 ,'Bresenham lines,'#13#13'subpixel accuracy' );
+ text(@ras_aa ,@sl ,@ren_aa ,50 ,_height / 2 + 50 ,'Anti-aliased lines' );
+ text(@ras_aa ,@sl ,@ren_aa ,_width / 2 - 50 ,_height / 2 + 50 ,'Scanline rasterizer' );
+ text(@ras_aa ,@sl ,@ren_aa ,_width - _width / 5 - 50 ,_height / 2 + 50 ,'Arbitrary Image Pattern' );
+
+// Render the controls
+ render_ctrl(@ras_aa ,@sl ,@ren_aa ,@m_step );
+ render_ctrl(@ras_aa ,@sl ,@ren_aa ,@m_width );
+ render_ctrl(@ras_aa ,@sl ,@ren_aa ,@m_test );
+ render_ctrl(@ras_aa ,@sl ,@ren_aa ,@m_rotate );
+ render_ctrl(@ras_aa ,@sl ,@ren_aa ,@m_accurate_joins );
+ render_ctrl(@ras_aa ,@sl ,@ren_aa ,@m_scale_pattern );
+
+// An example of using anti-aliased outline rasterizer.
+// Uncomment it to see the result
+{ width_:=5.0 + m_width.value - 3.0;
+
+ profile.Construct;
+ gm_pw.Construct(1.2 );
+
+ profile.gamma (@gm_pw ); //optional
+ profile._min_width (0.75 ); //optional
+ profile._smoother_width(3.0); //optional
+ profile.width (width_ ); //mandatory!
+
+ pixfmt(pixf ,rbuf_window );
+
+ base_ren.Construct(@pixf );
+ ren.Construct (@base_ren ,@profile );
+
+ rgba.ConstrInt(0 ,0 ,0 );
+ ren._color (@rgba ); //mandatory!
+
+ ras.Construct (@ren );
+ ras._round_cap (true ); //optional
+ ras._accurate_join(true ); //optional
+
+ ras.move_to_d(100 ,100 );
+ ras.line_to_d(150 ,200 );
+ ras.render (false ); // false means "don't close the polygon", i.e. polyline
+
+ ras.Destruct;
+ profile.Destruct;{}
+
+// An example of using image pattern outline rasterizer
+// Uncomment it to see the result
+{ fltr.Construct; // Filtering functor
+
+ patt_src.Construct(@pixmap_chain ); // Source. Must have an interface:
+ // width() const
+ // height() const
+ // pixel(int x, int y) const
+ // Any agg::renderer_base<> or derived
+ // is good for the use as a source.
+
+// agg::line_image_pattern is the main container for the patterns. It creates
+// a copy of the patterns extended according to the needs of the filter.
+// agg::line_image_pattern can operate with arbitrary image width, but if the
+// width of the pattern is power of 2, it's better to use the modified
+// version agg::line_image_pattern_pow2 because it works about 15-25 percent
+// faster than agg::line_image_pattern (because of using simple masking instead
+// of expensive '%' operation).
+ patt.Construct(@fltr ,@src );
+
+ pixfmt(pixf ,rbuf_window );
+
+ base_ren.Construct(@pixf );
+ renimg.Construct (@base_ren ,@patt );
+ //renimg._scale_x (1.3 ); // Optional
+
+ rasimg.Construct(@renimg );
+ rasimg.move_to_d(100 ,150 );
+ rasimg.line_to_d(0 ,0 );
+ rasimg.line_to_d(300 ,200 );
+ rasimg.render (false );
+
+ patt.Destruct;
+ rasimg.Destruct;{}
+
+// Free AGG resources
+ ras_aa.Destruct;
+ sl.Destruct;
+
+ prof.Destruct;
+ ras_oaa.Destruct;
+
+ pattern.Destruct;
+ ras_img.Destruct;
+
+end;
+
+{ ON_IDLE }
+procedure the_application.on_idle;
+begin
+ m_start_angle:=m_start_angle + deg2rad(m_step._value );
+
+ if m_start_angle > deg2rad(360.0 ) then
+ m_start_angle:=m_start_angle - deg2rad(360.0 );
+
+ force_redraw;
+
+end;
+
+{ ON_CTRL_CHANGE }
+procedure the_application.on_ctrl_change;
+var
+ i : unsigned;
+
+ t2 ,t3 ,t4 ,t5 : double;
+
+ buf : array[0..255 ] of char;
+
+ pf : pixel_formats;
+
+ ren_base : renderer_base;
+ ren_aa : renderer_scanline_aa_solid;
+ ren_prim : renderer_primitives;
+ ras_aa : rasterizer_scanline_aa;
+ ras_al : rasterizer_outline;
+ sl : scanline_p8;
+
+ rgba : aggclr;
+
+ prof : line_profile_aa;
+ ren_oaa : renderer_outline_aa;
+ ras_oaa : rasterizer_outline_aa;
+
+ filter : pattern_filter_bilinear_rgba;
+ src : pattern_pixmap_argb32;
+ src_scaled : line_image_scale;
+ pattern : line_image_pattern_pow2;
+
+ ren_img : renderer_outline_image;
+ ras_img : rasterizer_outline_aa;
+
+begin
+ wait_mode_(not m_rotate._status );
+
+ if m_test._status then
+ begin
+ on_draw;
+ update_window;
+
+ // Initialize structures
+ pixfmt(pf ,rbuf_window );
+
+ ren_base.Construct(@pf );
+ ren_aa.Construct (@ren_base );
+ ren_prim.Construct(@ren_base );
+
+ ras_aa.Construct;
+ sl.Construct;
+ ras_al.Construct(@ren_prim );
+
+ prof.Construct;
+ prof.width_(m_width._value );
+
+ ren_oaa.Construct(@ren_base ,@prof );
+ ras_oaa.Construct(@ren_oaa );
+
+ ras_oaa.accurate_join_(m_accurate_joins._status );
+ ras_oaa.round_cap_ (true );
+
+ // Image pattern
+ filter.Construct;
+ src.Construct(@pixmap_chain );
+
+ src_scaled.Construct(@src ,m_width._value );
+ pattern.Construct (@filter );
+
+ if m_scale_pattern._status then
+ pattern.create(@src_scaled )
+ else
+ pattern.create(@src );
+
+ ren_img.Construct(@ren_base ,@pattern );
+
+ if m_scale_pattern._status then
+ ren_img.scale_x_(src._height / m_width._value );
+
+ ras_img.Construct(@ren_img );
+
+ // Do Test
+ start_timer;
+
+ for i:=1 to 200 do
+ begin
+ draw_aliased_subpix_accuracy(@ras_al ,@ren_prim );
+
+ m_start_angle:=m_start_angle + deg2rad(m_step._value );
+
+ end;
+
+ t2:=elapsed_time;
+
+ start_timer;
+
+ for i:=1 to 200 do
+ begin
+ draw_anti_aliased_outline(@ras_oaa ,@ren_oaa );
+
+ m_start_angle:=m_start_angle + deg2rad(m_step._value );
+
+ end;
+
+ t3:=elapsed_time;
+
+ start_timer;
+
+ for i:=1 to 200 do
+ begin
+ draw_anti_aliased_scanline(@ras_aa ,@sl ,@ren_aa );
+
+ m_start_angle:=m_start_angle + deg2rad(m_step._value );
+
+ end;
+
+ t4:=elapsed_time;
+
+ start_timer;
+
+ for i:=1 to 200 do
+ begin
+ draw_anti_aliased_outline_img(@ras_img ,@ren_img );
+
+ m_start_angle:=m_start_angle + deg2rad(m_step._value );
+
+ end;
+
+ t5:=elapsed_time;
+
+ // Display results
+ m_test.status_(false );
+ force_redraw;
+
+ sprintf(@buf[0 ] ,'Aliased=%1.2fms, '#0 ,t2 );
+ sprintf(@buf[StrLen(@buf[0 ] ) ] ,'Anti-Aliased=%1.2fms, '#0 ,t3 );
+ sprintf(@buf[StrLen(@buf[0 ] ) ] ,'Scanline=%1.2fms, '#0 ,t4 );
+ sprintf(@buf[StrLen(@buf[0 ] ) ] ,'Image-Pattern=%1.2fms'#0 ,t5 );
+
+ message_(@buf[0 ] );
+
+ // Free AGG resources
+ ras_aa.Destruct;
+ sl.Destruct;
+
+ prof.Destruct;
+ ras_oaa.Destruct;
+
+ pattern.Destruct;
+ ras_img.Destruct;
+
+ end;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ 'More complex example demostrating different rasterizers. Here you can see how '#13 +
+ 'the outline rasterizer works, and how to use an image as the line pattern. '#13 +
+ 'This capability can be very useful to draw geographical maps.' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+VAR
+ app : the_application;
+
+BEGIN
+ app.Construct(pix_format ,flip_y );
+ app.caption_ ('AGG Example. Line Join (F1-Help)' );
+
+ if app.init(500 ,450 ,0 ) then
+ app.run;
+
+ app.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/readme.txt b/src/corelib/render/software/agg-demos/readme.txt
new file mode 100644
index 00000000..f284ecaf
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/readme.txt
@@ -0,0 +1,385 @@
+================================================================================
+
+ Anti-Grain Geometry - Version 2.4
+ Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+
+ Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+ Pascal Port By: Milan Marusinec alias Milano
+ milan@marusinec.sk
+ http://www.aggpas.org
+ Copyright (c) 2005-2008
+
+================================================================================
+ News
+================================================================================
+
+ 22.01.2008 - AggPas - version 2.4 Release Milano 3
+ ----------
+
+ - Library source code is updated all over to keep up with new possibilities
+ of AGG C/C++ 2.4 version. Some code is slightly changed and there are also
+ a newly ported units. However this update is not rewrite, for example image
+ and pattern stuff and path storage is kept from 2.3 (same functionality).
+ See examples for 14 new demos.
+
+ - Flash compound rasterizer - fully ported, full functional
+ - Gaussian and stack blurs
+ - Two more composition modes - invert & invert rgb
+ - Focal gradient with extended center point
+ - New gradients: Contour, Assymetric conic, Bitmap
+ - Bitmap caching - see the Particles demo
+ - SVG demo now works also with expat.dll
+ - FreeType2 bindings - freetype demos are now fully ported
+ - Agg2D API and also TAgg2D for Delphi VCL (over 100 API commands)
+
+ - Documentation for TAgg2D API is available at:
+
+ http://www.aggpas.org/documentation
+
+ This documentation is not a part of software distribution package, because
+ it is planned to be an independent live document evolving over time.
+
+
+ 26.06.2006 - AggPas - version 2.3 Release Milano 2
+ ----------
+
+ - SVG demo is ported for now. See svg_test.dpr & svg directory in src.
+ As a part of the SVG demo, I had also ported partialy the Expat library.
+ See Expat directory & read the readme.txt if you are interested more.
+
+ - Whole source code of AggPas library was adjusted to be compilable under
+ the emerging 64bit FreePascal compiler. The adjustment includes changing
+ the "integer(pointer(x ) )" constructs to the "ptrcomp(pointer(x ) )".
+ Ptrcomp is defined in the agg_basics.pas and depending on the CPU64
+ conditional it is either integer or int64.
+
+================================================================================
+ Remarks
+================================================================================
+
+ I'm glad to hear that AGG and my work on AggPas inspired Mr. Lars Brubaker
+ to make a native port in C#.
+
+ Try it at: http://agg-sharp.sourceforge.net/
+
+ From the .9 demo seen so far, it looks very promising. Maybe over a year,
+ I will try to help with the C# version to get finished (not promise).
+
+ Keep on the good work Lars !
+
+================================================================================
+ Introduction
+================================================================================
+
+ AggPas is an Object Pascal port of the Anti-Grain Geometry library - AGG,
+ originally written by Maxim Shemanarev in industrially standard C++.
+ AGG as well as AggPas is Open Source and free of charge 2D vector graphic
+ library.
+
+ AGG (and AggPas too) doesn't depend on any graphic API or technology.
+ Basically, you can think of AGG as of a rendering engine that produces pixel
+ images in memory from some vectorial data. But of course, AGG can do much
+ more than that. The ideas and the philosophy of AGG are ...
+
+ Read more at: http://www.antigrain.com/about
+
+ This version of AGG library is the Object Pascal one and this Readme Note
+ is dealing with issues mainly around the Pascal version.
+
+================================================================================
+ Installation notes & compiling
+================================================================================
+
+ AggPas can be currently compiled on the platforms with compilers
+ according to the following matrix:
+
+ +----------------------+---------------------+---------------------+
+ | Platform / Compiler | Free Pascal (FPC) | Delphi (Borland) |
+ +======================+=====================+=====================+
+ | Windows Win32 API | versions 2.0 and up | versions 2.0 and up |
+ +----------------------+---------------------+---------------------+
+ | Linux X11 | versions 2.0 and up | * no support * |
+ +----------------------+---------------------+---------------------+
+ | Mac OS X Carbon | versions 2.0 and up | * no support * |
+ +----------------------+---------------------+---------------------+
+
+ After downloading and unpacking the library distribution archive I recommend
+ to run the find_compilers_xxx utility, where xxx is the name of the platform.
+ It will scan the current working directory for the Agg demo projects and
+ create appropriate up to-date compile scripts. On the permission-based
+ file systems (linux & mac) it will also assign the "execute" file attributes
+ to the script files. Then, to compile all of the demos, you just run
+ appropriate compile script from the command line (terminal). The utility also
+ excludes from compile scripts those demos, which are primarily targeted
+ to different platforms (for ex. TT & gpc demos compiles only on windows).
+
+ AggPas was tested on the following systems:
+
+ * Windows XP, Windows 2000
+ * Mac OS X 10.4.5
+ * Fedora Core 4
+
+================================================================================
+ Port comments
+================================================================================
+
+ The Object Pascal version (AggPas) was created mainly during the first three
+ months of the year 2006. This port is based on the C++ version 2.3, which was
+ officialy released on 25 September 2005.
+
+ AggPas port is the pure manual work. There were used no c_to_pascal conversion
+ utilities and the port is the native-one, which means it uses no external dll
+ bindings - it's all just the native pascal code.
+
+ This Pascal library has nearly all of the original C++ version functionality.
+ I will mention the differences more around on later. All of the demos were
+ ported (except 3 of them), and they do exactly all that the C++ version demos
+ do.
+
+ AggPas supports the following rendering buffer pixel formats:
+
+ - gray8 ,gray8_pre
+ - gray8_bgr24r ,gray8_pre_bgr24r
+ - gray8_bgr24g ,gray8_pre_bgr24g
+ - gray8_bgr24b ,gray8_pre_bgr24b
+
+ - rgb555 ,rgb555_pre ,rgb555_gamma
+ - rgb565 ,rgb565_pre ,rgb565_gamma
+
+ - bgr24 ,bgr24_pre ,bgr24_gamma
+ - rgb24 ,rgb24_pre ,rgb24_gamma
+
+ - bgra32 ,bgra32_pre
+ - rgba32 ,rgba32_pre
+ - argb32 ,argb32_pre
+ - abgr32 ,abgr32_pre
+
+ - custom_blend_rgba
+
+ The high precision pixel formats support is not implemented for now, mainly
+ for the reason, I haven't any real-world examples to try and test with.
+ There are also some other issues related to the color data structure and
+ it's data members, which are of byte size per color component now. In C++
+ version it was solved using the templates, but in Pascal i would have to find
+ another solution.
+
+ C++ TEMPLATES
+ =============
+
+ Well, well, well. I was forced to remove the Maxim's template based
+ architecture and to replace it with the conventional one - object oriented,
+ because in Object Pascal there are no templates. Due to that there is a
+ speed penalty consequence. AggPas is in fact slower by 20 - 50%.
+
+ Despite the speed decrease, the AggPas is still a very usable super-trooper 2d
+ vector graphic library. Unless you are willing to make a real-time (30 fps >)
+ rendering, there is still a great benefit of incorporating it into your Pascal
+ based projects. Try to compile the demos and see for yourself ...
+
+ On the other hand, I believe I had opened the doors for someone to try to
+ port the Agg into some other language(s). Is there anybody out capable
+ of making the template-less Java or C# native-port version ? Trust me, it's
+ worth doing so.
+
+ For those agg-fanatics with spare 3 or so months (like me), willing to create
+ some cool agg-native-port, I am giving here some hints:
+
+ AggPas was ported demo by demo in the following order:
+
+ Simple: pure_api, component_rendering ,polymorphic_renderers ,rasterizers ,
+ rounded_rect ,aa_demo ,bspline ,scanline_boolean ,idea ,trans_polar ,
+ aa_test ,circles ,gamma_correction ,gamma_ctrl ,gouraud ,rasterizers2
+
+ Lion: lion ,lion_lens ,lion_outline ,perspective ,simple_blur ,alpha_mask ,
+ alpha_mask2, multi_clip
+
+ Fonts: conv_contour ,raster_text ,trans_curve1 ,trans_curve2 ,truetype_test
+
+ England: alpha_mask3 ,gpc_test ,scanline_boolean2
+
+ Complex: alpha_gradient ,bezier_div ,conv_dash_marker ,conv_stroke ,gradients ,
+ graph_test ,pattern_fill
+
+ Images: line_patterns ,image1 ,image_alpha ,image_filters ,image_filters2 ,
+ image_fltr_graph ,image_perspective ,image_resample ,image_transforms ,
+ pattern_perspective ,distortions ,compositing
+
+ After finishing all of the demos above, the whole library consisting of 120+
+ files folded up. I must appreciate Maxim's work for completness at this point,
+ because only four source files left unused in the library:
+
+ - agg_conv_close_polygon.h
+ - agg_conv_unclose_polygon.h
+ - agg_rendering_buffer_dynarow.h
+ - agg_trans_lens.h
+
+ But as I said, 3 demos were ported not and I believe those source files are
+ used just there (see the What's next on the end of this readme).
+
+ Start porting with pure_api and all units it uses. Other unit's ports comes
+ automatically, as you will go through more and more demos.
+
+ Create appropriate basic data types (agg_basics) and then use them. The most
+ used types throughout agg are "int" and "unsigned" which are "longint" and
+ "longword" in pascal.
+
+ Be cautious of arithmetic shift right operation (>>) on signed integers.
+ In pascal, there was an incompatibility with the C++ implementation.
+ On the assembler level, pascal compilers were always generating "shr" (i386)
+ "srw" (powerpc) instructions instead of "sar" (i386) "sraw" (powerpc) ops.
+ I hacked this situation with shr_intXX function calls whenever arithmeticaly
+ shifting right signed integers (see the end of agg_basics.pas file).
+ That leads of cource to speed penalty, because of additional function call,
+ but not doing so is very crucial - lots of agg algos depends on ">>".
+
+
+ Back to the Pascal port Issues
+ ==============================
+
+ Accessors:
+
+ The names of getters and setters methods of class objects are a little bit
+ modified against the c version mostly due to the fact, that pascal doesn't
+ distinguish between same methods names, if they are differentiating only by
+ the return value. I used one rule: If the method is setter, then it has
+ the underscore after the name (eg: width_, like width=something). If the
+ method is getter, then it has the underscore before the name (eg: _width,
+ like something=width). [See agg_vcgen_stroke for example].
+
+ Source code comment marks:
+
+ Here and there around the AggPas source code, following comment marks
+ can be found:
+
+ {untested} - unit or procedure/function, which was ported but not tested
+ (there was no reference to it's use from demos)
+
+ {not_implemented} - procedure/function, which was not ported, because
+ related features were not implemented in port
+
+ {hack} - marks some nonstandard solution
+
+ {..} - part of the code, which is unfinished. There is just
+ one unit with this marks - agg_color_conv.pas, with lots
+ of pixel format conversion functions. Sorry, I was too
+ lazy to finish this one. I did all conversion functions,
+ which are used by the demos. If you'll need some more,
+ finish it yourself. It's not that hard (but many of them).
+
+ Compiling mode:
+
+ The "agg_mode.inc" is the main compiler mode configuration file.
+ The only one item, you would wish to change is the AGG_DEBUG conditional,
+ which turns on/off the debug mode compilation settings. With the
+ AGG_DEBUG not defined the range checking for example is turned off,
+ which should lead to building the faster and smallest code.
+
+
+ Bugs
+ ====
+
+ All bugs i know of in AggPas are related to the compiler issues.
+ These are:
+
+ In Delphi on Windows:
+
+ - The SetDIBitsToDevice WinAPI call sometimes fails, but only in Delphi.
+ In FPC it always works OK. Due to Delphi, I hacked this with solution,
+ which puts on fail the image to the screen anyway, but with some speed
+ penalty of course. (See agg_win32_bmp.pas::pixel_map::draw fn).
+
+ In FPC on Windows:
+
+ - GetGlyphOutline(X) WinAPI call is working not. The consequence of this
+ is that the True-type demos compiled with FPC work not.
+ I have reported this problem to the FPC people (bug report 4827).
+ They have fixed it and in upcoming version 2.0.3 of FreePascal compiler
+ it should be OK.
+
+ In FPC on Windows and Linux:
+
+ - Demos gouraud.dpr & aa_test.dpr generate some broken gouraud shading
+ patterns. I think, this is an compiler error issue, because in FPC
+ on Mac (which is powerpc) - it is OK, from the same source code, as
+ well as in Delphi.
+
+ If anybody knows how to fix those (or other) bugs, don't hesitate to
+ send me a mail or fix it yourself and let me know.
+
+
+ MacPort comments
+ ================
+
+ The speed of the library on the PowerPC Mac target is rather slow.
+ I suspect, this is due to the FPC compiler, which itself is not much
+ optimized for PowerPC targets. Maybe I'm wrong, but the size of the
+ compiled executables is about 1.4 Megs, compared to the 200 KB C++
+ versions of the same demos.
+
+ The agg demo framework has on Mac in Pascal following improvements
+ over the C++ version:
+
+ - resizing of windows
+ - right click
+ - app.message displays the "long" C strings
+ - keyboard support is better (sort of hack) with Alt+F4 for quit
+
+ When compiling on Mac, there is a need of additional libraries,
+ which are not a part of the Free Pascal installation. They are
+ the Universal Pascal Interfaces (UPI), which are a part of the
+ Apple Universal Interfaces, which can be downloaded at:
+
+ ftp://ftp.apple.com/developer/Development_Kits/UniversalInterfaces3.4.2.dmg
+
+ To compile AggPas on Mac succesfully you will need the following
+ files in the upi directory of AggPas:
+
+ - Carbon.o
+ - Carbon.ppu
+ - ImageCompression.o
+ - ImageCompression.ppu
+ - QuickTimeComponents.o
+ - QuickTimeComponents.ppu
+
+ If you had downloaded the Mac .dmg AggPas archive, it already
+ contains above mentioned files, so you don't have to download
+ anything else - just compile. In the case, you want to recompile
+ the UPI for yourself, do following:
+
+ 1. Click on the UniversalInterfaces3.4.2.dmg archive
+ 2. Change directory to Universal/Interfaces/PInterfaces
+ 3. Copy all files to AggPas/UPInterfaces
+ 4. Execute ./build_upi script
+
+
+ LinuxPort comments
+ ==================
+
+ The linux port of agg demo framework has one small improvement
+ over the C++ version -> It displays the app.message(s) in window
+ instead of sending the text to the stderr output.
+
+
+================================================================================
+ What's next
+================================================================================
+
+ I mentioned above, that 3 demos (out of 50+) were ported not.
+ These are:
+
+ - mol_view:
+
+ I'm sorry, but this one was the last one, I was lazy to port.
+ Besides, there were no new units used.
+
+ - freetype_test (& related trans_curve1/2_ft):
+
+ [Update] Fully working in AggPas 2.4 RM3.
+
+
+ All for now
+ Yours Milano
+
+================================================================================
+ End of file
+================================================================================
diff --git a/src/corelib/render/software/agg-demos/rounded_rect.dpr b/src/corelib/render/software/agg-demos/rounded_rect.dpr
new file mode 100644
index 00000000..f6425f53
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/rounded_rect.dpr
@@ -0,0 +1,293 @@
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ rounded_rect ;
+
+uses
+ agg_basics ,
+ agg_platform_support ,
+ agg_color ,
+ agg_pixfmt ,
+ agg_pixfmt_rgb ,
+
+ agg_ctrl ,
+ agg_slider_ctrl ,
+ agg_cbox_ctrl ,
+
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_rasterizer_scanline_aa ,
+ agg_scanline_p ,
+ agg_render_scanlines ,
+
+ agg_gamma_functions ,
+ agg_gamma_lut ,
+ agg_ellipse ,
+ agg_rounded_rect ,
+ agg_conv_stroke ,
+ agg_vertex_source ;
+
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+type
+ the_application = object(platform_support )
+ m_x ,
+ m_y : array[0..1 ] of double;
+
+ m_dx ,
+ m_dy : double;
+
+ m_idx : int;
+
+ m_radius ,
+ m_gamma ,
+ m_offset : slider_ctrl;
+
+ m_white_on_black : cbox_ctrl;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure on_draw; virtual;
+
+ procedure on_mouse_move (x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_up (x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+var
+ rgba8 : aggclr;
+
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_radius.Construct(10 ,10 ,600 - 10 ,19 ,not flip_y_ );
+ m_gamma.Construct (10 ,10 + 20 ,600 - 10 ,19 + 20 ,not flip_y_ );
+ m_offset.Construct(10 ,10 + 40 ,600 - 10 ,19 + 40 ,not flip_y_ );
+
+ m_white_on_black.Construct(10 ,10 + 60 ,'White on black' );
+
+ m_idx:=-1;
+
+ m_x[0 ]:=100; m_y[0 ]:=100;
+ m_x[1 ]:=500; m_y[1 ]:=350;
+
+ add_ctrl(@m_radius );
+ add_ctrl(@m_gamma );
+ add_ctrl(@m_offset );
+ add_ctrl(@m_white_on_black );
+
+ m_gamma.label_('gamma=%4.3f' );
+ m_gamma.range_(0.0 ,3.0 );
+ m_gamma.value_(1.8 );
+
+ m_radius.label_('radius=%4.3f' );
+ m_radius.range_(0.0 ,50.0 );
+ m_radius.value_(25.0 );
+
+ m_offset.label_('subpixel offset=%4.3f' );
+ m_offset.range_(-2.0 ,3.0 );
+
+ rgba8.ConstrInt(127 ,127 ,127 );
+
+ m_white_on_black.text_color_ (@rgba8 );
+ m_white_on_black.inactive_color_(@rgba8 );
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_radius.Destruct;
+ m_gamma.Destruct;
+ m_offset.Destruct;
+
+ m_white_on_black.Destruct;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ pixf : pixel_formats;
+
+ rb : renderer_base;
+ ren : renderer_scanline_aa_solid;
+ ras : rasterizer_scanline_aa;
+ sl : scanline_p8;
+
+ rgba : aggclr;
+ gamma : gamma_lut;
+ gm_no : vertex_source;
+
+ e : ellipse;
+ r : agg_rounded_rect.rounded_rect;
+ p : conv_stroke;
+ d : double;
+
+begin
+// Initialize structures
+ gamma.Construct(m_gamma._value ,8 ,8 );
+
+ pixfmt_bgr24_gamma(pixf ,rbuf_window ,@gamma );
+
+ rb.Construct (@pixf );
+ ren.Construct(@rb );
+
+ if m_white_on_black._status then
+ rgba.ConstrDbl(0 ,0 ,0 )
+ else
+ rgba.ConstrDbl(1 ,1 ,1 );
+
+ rb.clear(@rgba );
+
+ ras.Construct;
+ sl.Construct;
+
+// Render two "control" circles
+ e.Construct;
+ rgba.ConstrInt(127 ,127 ,127 );
+ ren.color_ (@rgba );
+
+ e.init (m_x[0 ] ,m_y[0 ] ,3 ,3 ,16 );
+ ras.add_path(@e );
+
+ render_scanlines(@ras ,@sl ,@ren );
+
+ e.init (m_x[1 ] ,m_y[1 ] ,3 ,3 ,16 );
+ ras.add_path(@e );
+
+ render_scanlines(@ras ,@sl ,@ren );
+
+// Creating a rounded rectangle
+ d:=m_offset._value;
+
+ r.Construct(m_x[0 ] + d ,m_y[0 ] + d ,m_x[1 ] + d ,m_y[1 ] + d ,m_radius._value );
+ r.normalize_radius;
+
+// Drawing as an outline
+ p.Construct(@r );
+ p.width_ (1.0 );
+
+ ras.add_path(@p );
+
+ if m_white_on_black._status then
+ rgba.ConstrDbl(1 ,1 ,1 )
+ else
+ rgba.ConstrDbl(0 ,0 ,0 );
+
+ ren.color_(@rgba );
+
+ render_scanlines(@ras ,@sl ,@ren );
+
+ gm_no.Construct;
+ ras.gamma(@gm_no );
+
+// Render the controls
+ render_ctrl(@ras ,@sl ,@ren ,@m_radius );
+ render_ctrl(@ras ,@sl ,@ren ,@m_gamma );
+ render_ctrl(@ras ,@sl ,@ren ,@m_offset );
+ render_ctrl(@ras ,@sl ,@ren ,@m_white_on_black );
+
+// Free AGG resources
+ ras.Destruct;
+ sl.Destruct;
+
+ gamma.Destruct;
+ p.Destruct;
+
+end;
+
+{ ON_MOUSE_MOVE }
+procedure the_application.on_mouse_move;
+begin
+ if flags and mouse_left <> 0 then
+ if m_idx >= 0 then
+ begin
+ m_x[m_idx ]:=x - m_dx;
+ m_y[m_idx ]:=y - m_dy;
+
+ force_redraw;
+
+ end
+ else
+ else
+ on_mouse_button_up(x ,y ,flags );
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure the_application.on_mouse_button_down;
+var
+ i : unsigned;
+
+begin
+ if flags and mouse_left <> 0 then
+ for i:=0 to 1 do
+ if Sqrt((x - m_x[i ] ) * (x - m_x[i ] ) + (y - m_y[i ] ) * (y - m_y[i ] ) ) < 5.0 then
+ begin
+ m_dx :=x - m_x[i ];
+ m_dy :=y - m_y[i ];
+ m_idx:=i;
+
+ break;
+
+ end;
+
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+procedure the_application.on_mouse_button_up;
+begin
+ m_idx:=-1;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ 'Yet another example dedicated to Gamma Correction. If you have a CRT monitor: '#13 +
+ 'The rectangle looks bad - the rounded corners are thicker than its side lines. '#13 +
+ 'First try to drag the "subpixel offset" control — it simply adds some fractional '#13 +
+ 'value to the coordinates. When dragging you will see that the rectangle is'#13 +
+ '"blinking". Then increase "Gamma" to about 1.5. The result will look almost '#13 +
+ 'perfect — the visual thickness of the rectangle remains the same. That''s good, '#13 +
+ 'but turn the checkbox "White on black" on — what do we see ? Our rounded '#13 +
+ 'rectangle looks terrible. Drag the "subpixel offset" slider — it''s blinking as hell. '#13 +
+ 'Now decrease "Gamma" to about 0.6. What do we see now ? Perfect result ! '#13 +
+ 'If you use an LCD monitor, the good value of gamma will be closer to 1.0 in both '#13 +
+ 'cases — black on white or white on black. There''s no perfection in this world, but '#13 +
+ 'at least you can control Gamma in Anti-Grain Geometry :-)' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+VAR
+ app : the_application;
+
+BEGIN
+ app.Construct(pix_format_bgr24 ,flip_y );
+ app.caption_ ('AGG Example. Rounded rectangle with gamma-correction & stuff (F1-Help)' );
+
+ if app.init(600 ,400 ,window_resize ) then
+ app.run;
+
+ app.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/scanline_boolean.dpr b/src/corelib/render/software/agg-demos/scanline_boolean.dpr
new file mode 100644
index 00000000..4fccc7ad
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/scanline_boolean.dpr
@@ -0,0 +1,385 @@
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ scanline_boolean ;
+
+{DEFINE AGG_GRAY8 }
+{$DEFINE AGG_BGR24 }
+{DEFINE AGG_RGB24 }
+{DEFINE AGG_BGRA32 }
+{DEFINE AGG_RGBA32 }
+{DEFINE AGG_ARGB32 }
+{DEFINE AGG_ABGR32 }
+{DEFINE AGG_RGB565 }
+{DEFINE AGG_RGB555 }
+
+uses
+ agg_basics ,
+ agg_platform_support ,
+
+ agg_ctrl ,
+ agg_slider_ctrl ,
+ agg_cbox_ctrl ,
+ agg_rbox_ctrl ,
+
+ agg_rasterizer_scanline_aa ,
+ agg_scanline ,
+ agg_scanline_p ,
+ agg_scanline_u ,
+ agg_scanline_bin ,
+ agg_scanline_boolean_algebra ,
+
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_render_scanlines ,
+
+ agg_path_storage ,
+ agg_ellipse ,
+ agg_gamma_functions ,
+ interactive_polygon_
+
+{$I pixel_formats.inc }
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+type
+ the_application = object(platform_support )
+ m_quad1 ,
+ m_quad2 : interactive_polygon;
+
+ m_trans_type : rbox_ctrl;
+
+ m_reset : cbox_ctrl;
+ m_mul1 ,
+ m_mul2 : slider_ctrl;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure on_init; virtual;
+ procedure on_draw; virtual;
+
+ procedure on_mouse_move (x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_up (x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_ctrl_change; virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ GENERATE_CIRCLES }
+procedure generate_circles(ps : path_storage_ptr; quad : double_ptr; num_circles : unsigned; radius : double );
+var
+ ell : ellipse;
+
+ i ,j ,n1 ,n2 : unsigned;
+
+begin
+ ps.remove_all;
+ ell.Construct;
+
+ for i:=0 to 3 do
+ begin
+ n1:=i * 2;
+
+ if i < 3 then
+ n2:=i * 2 + 2
+ else
+ n2:=0;
+
+ for j:=0 to num_circles - 1 do
+ begin
+ ell.init(
+ double_ptr(ptrcomp(quad ) + n1 * sizeof(double ) )^ +
+ (double_ptr(ptrcomp(quad ) + n2 * sizeof(double ) )^ -
+ double_ptr(ptrcomp(quad ) + n1 * sizeof(double ) )^ ) *
+ j / num_circles ,
+ double_ptr(ptrcomp(quad ) + (n1 + 1 ) * sizeof(double ) )^ +
+ (double_ptr(ptrcomp(quad ) + (n2 + 1 ) * sizeof(double ) )^ -
+ double_ptr(ptrcomp(quad ) + (n1 + 1 ) * sizeof(double ) )^ ) *
+ j / num_circles ,
+ radius ,radius ,100 );
+
+ ps.add_path(@ell ,0 ,false );
+
+ end;
+
+ end;
+
+end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_quad1.Construct(4 ,5.0 );
+ m_quad2.Construct(4 ,5.0 );
+
+ m_trans_type.Construct(420 ,5.0 ,420 + 130.0 ,145.0 ,not flip_y_ );
+
+ m_reset.Construct(350 ,5.0 ,'Reset' ,not flip_y_ );
+
+ m_mul1.Construct(5.0 ,5.0 ,340.0 ,12.0 ,not flip_y_ );
+ m_mul2.Construct(5.0 ,20.0 ,340.0 ,27.0 ,not flip_y_ );
+
+ m_trans_type.add_item ('Union' );
+ m_trans_type.add_item ('Intersection' );
+ m_trans_type.add_item ('Linear XOR' );
+ m_trans_type.add_item ('Saddle XOR' );
+ m_trans_type.add_item ('Abs Diff XOR' );
+ m_trans_type.add_item ('A-B' );
+ m_trans_type.add_item ('B-A' );
+ m_trans_type.cur_item_(0 );
+
+ add_ctrl(@m_trans_type );
+ add_ctrl(@m_reset );
+ add_ctrl(@m_mul1 );
+ add_ctrl(@m_mul2 );
+
+ m_mul1.value_(1.0 );
+ m_mul2.value_(1.0 );
+ m_mul1.label_('Opacity1=%.3f' );
+ m_mul2.label_('Opacity2=%.3f' );
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_quad1.Destruct;
+ m_quad2.Destruct;
+
+ m_trans_type.Destruct;
+ m_reset.Destruct;
+ m_mul1.Destruct;
+ m_mul2.Destruct;
+
+end;
+
+{ ON_INIT }
+procedure the_application.on_init;
+begin
+ m_quad1.xn_ptr(0 )^:=50;
+ m_quad1.yn_ptr(0 )^:=200 - 20;
+ m_quad1.xn_ptr(1 )^:=_width / 2 - 25;
+ m_quad1.yn_ptr(1 )^:=200;
+ m_quad1.xn_ptr(2 )^:=_width / 2 - 25;
+ m_quad1.yn_ptr(2 )^:=_height - 50 - 20;
+ m_quad1.xn_ptr(3 )^:=50;
+ m_quad1.yn_ptr(3 )^:=_height - 50;
+
+ m_quad2.xn_ptr(0 )^:=_width / 2 + 25;
+ m_quad2.yn_ptr(0 )^:=200 - 20;
+ m_quad2.xn_ptr(1 )^:=_width - 50;
+ m_quad2.yn_ptr(1 )^:=200;
+ m_quad2.xn_ptr(2 )^:=_width - 50;
+ m_quad2.yn_ptr(2 )^:=_height - 50 - 20;
+ m_quad2.xn_ptr(3 )^:=_width / 2 + 25;
+ m_quad2.yn_ptr(3 )^:=_height - 50;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ pixf : pixel_formats;
+
+ rb : renderer_base;
+ r : renderer_scanline_aa_solid;
+ sl : scanline_p8;
+
+ ras ,
+ ras1 ,
+ ras2 : rasterizer_scanline_aa;
+ rgba : aggclr;
+
+ op : sbool_op_e;
+ gm : gamma_multiply;
+
+ ps1 ,
+ ps2 : path_storage;
+
+ sl_result ,sl1 ,sl2 : scanline_p8;
+
+ sren : renderer_scanline_aa_solid;
+
+begin
+// Initialize structures
+ pixfmt(pixf ,rbuf_window );
+
+ rb.Construct(@pixf );
+ r.Construct (@rb );
+
+ rgba.ConstrDbl(1 ,1 ,1 );
+ rb.clear (@rgba );
+
+ sl.Construct;
+ ras.Construct;
+ ras1.Construct;
+ ras2.Construct;
+
+// Draw
+ op:=sbool_op_e(m_trans_type._cur_item );
+
+ gm.Construct(m_mul1._value );
+ ras1.gamma (@gm );
+
+ gm.Construct(m_mul2._value );
+ ras2.gamma (@gm );
+
+ ras.clip_box(0 ,0 ,_width ,_height );
+
+ ps1.Construct;
+ generate_circles(@ps1 ,m_quad1.polygon ,5 ,20 );
+
+ ps2.Construct;
+ generate_circles(@ps2 ,m_quad2.polygon ,5 ,20 );
+
+ ras1.filling_rule(fill_even_odd );
+
+// Bottom Layer of Polygon1
+ rgba.ConstrInt(240, 255, 200, 100 );
+ r.color_ (@rgba );
+
+ ras1.add_path (@ps1 );
+ render_scanlines(@ras1 ,@sl ,@r );
+
+// Bottom Layer of Polygon2
+ rgba.ConstrInt(255 ,240 ,240 ,100 );
+ r.color_ (@rgba );
+
+ ras2.add_path (@ps2 );
+ render_scanlines(@ras2 ,@sl ,@r );
+
+// Combine shapes
+ sl_result.Construct;
+ sl1.Construct;
+ sl2.Construct;
+ sren.Construct(@rb );
+
+ rgba.ConstrInt(0 ,0 ,0 );
+ sren.color_ (@rgba );
+
+ sbool_combine_shapes_aa(op ,@ras1 ,@ras2 ,@sl1 ,@sl2 ,@sl_result ,@sren );
+
+// Render the "quad" tools
+ rgba.ConstrDbl(0 ,0.3 ,0.5 ,0.6 );
+ r.color_ (@rgba );
+
+ ras.add_path (@m_quad1 );
+ render_scanlines(@ras ,@sl ,@r );
+
+ ras.add_path (@m_quad2 );
+ render_scanlines(@ras ,@sl ,@r );
+
+// Render the controls
+ render_ctrl(@ras ,@sl ,@r ,@m_trans_type);
+ render_ctrl(@ras ,@sl ,@r ,@m_reset);
+ render_ctrl(@ras ,@sl ,@r ,@m_mul1);
+ render_ctrl(@ras ,@sl ,@r ,@m_mul2);
+
+// Free AGG resources
+ ps1.Destruct;
+ ps2.Destruct;
+
+ ras2.Destruct;
+ ras1.Destruct;
+
+ sl_result.Destruct;
+ sl1.Destruct;
+ sl2.Destruct;
+
+ ras.Destruct;
+ sl.Destruct;
+
+end;
+
+{ ON_MOUSE_MOVE }
+procedure the_application.on_mouse_move;
+begin
+ if flags and mouse_left <> 0 then
+ if m_quad1.on_mouse_move(x ,y ) or
+ m_quad2.on_mouse_move(x ,y ) then
+ force_redraw;
+
+ if flags and mouse_left = 0 then
+ on_mouse_button_up(x ,y ,flags );
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure the_application.on_mouse_button_down;
+begin
+ if flags and mouse_left <> 0 then
+ if m_quad1.on_mouse_button_down(x ,y ) or
+ m_quad2.on_mouse_button_down(x ,y ) then
+ force_redraw;
+
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+procedure the_application.on_mouse_button_up;
+begin
+ if m_quad1.on_mouse_button_up(x ,y ) or
+ m_quad2.on_mouse_button_up(x ,y ) then
+ force_redraw;
+
+end;
+
+{ ON_CTRL_CHANGE }
+procedure the_application.on_ctrl_change;
+begin
+ if m_reset._status then
+ begin
+ on_init;
+ m_reset.status_(false );
+ force_redraw;
+
+ end;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ 'A new method to perform boolean operations on polygons (Union, Intersection, XOR, '#13 +
+ 'and Difference). It uses the scanline approach and in typical screen resolutions '#13 +
+ 'works much faster (about 10 times) than vectorial algorithms like General Polygon '#13 +
+ 'Clipper. It preserves perfect Anti-Aliasing and besides, can work with translucency. '#13 +
+ 'There are two XOR operations, Linear XOR and Saddle XOR. The only difference is in '#13 +
+ 'the formula of XORing of the two cells with Anti-Aliasing. The first one is:'#13#13 +
+ 'cover = a+b; if(cover > 1) cover = 2.0 - cover;'#13#13 +
+ 'The second uses the classical "Saddle" formula:'#13#13 +
+ 'cover = 1.0 - (1.0 - a + a*b) * (1.0 - b + a*b);'#13#13 +
+ 'The Linear XOR produces more correct intersections and works constistently with the'#13 +
+ 'scanline rasterizer algorithm. The Saddle XOR works better with semi-transparent polygons. ' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+VAR
+ app : the_application;
+
+BEGIN
+ app.Construct(pix_format ,flip_y );
+ app.caption_ ('AGG Example. Scanline Boolean (F1-Help)' );
+
+ if app.init(800 ,600 ,window_resize ) then
+ app.run;
+
+ app.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/scanline_boolean2.dpr b/src/corelib/render/software/agg-demos/scanline_boolean2.dpr
new file mode 100644
index 00000000..2ffda897
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/scanline_boolean2.dpr
@@ -0,0 +1,947 @@
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ scanline_boolean2 ;
+
+uses
+ SysUtils ,
+
+ agg_basics ,
+ agg_platform_support ,
+
+ agg_color ,
+ agg_pixfmt ,
+ agg_pixfmt_rgb ,
+
+ agg_ctrl ,
+ agg_slider_ctrl ,
+ agg_cbox_ctrl ,
+ agg_rbox_ctrl ,
+
+ agg_rendering_buffer ,
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_renderer_primitives ,
+ agg_rasterizer_scanline_aa ,
+ agg_scanline ,
+ agg_scanline_u ,
+ agg_scanline_p ,
+ agg_scanline_bin ,
+ agg_scanline_storage_aa ,
+ agg_scanline_storage_bin ,
+ agg_scanline_boolean_algebra ,
+ agg_render_scanlines ,
+
+ agg_math_stroke ,
+ agg_path_storage ,
+ agg_span_solid ,
+ agg_conv_curve ,
+ agg_conv_stroke ,
+ agg_conv_transform ,
+ agg_gsv_text ,
+ agg_trans_affine ,
+ agg_vertex_source ,
+
+ make_gb_poly_ ,
+ make_arrows_ ;
+
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+type
+ spiral = object(vertex_source )
+ m_x ,
+ m_y ,
+ m_r1 ,
+ m_r2 ,
+ m_step ,
+
+ m_start_angle ,
+
+ m_angle ,
+ m_curr_r ,
+ m_da ,
+ m_dr : double;
+ m_start : boolean;
+
+ constructor Construct(x ,y ,r1 ,r2 ,step : double; start_angle : double = 0 );
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ end;
+
+ the_application = object(platform_support )
+ m_polygons ,
+ m_fill_rule ,
+ m_scanline_type ,
+ m_operation : rbox_ctrl;
+
+ m_x ,
+ m_y : double;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure render_scanline_boolean(ras1 ,ras2 : rasterizer_scanline_ptr );
+ function render_sbool (ras1 ,ras2 : rasterizer_scanline_ptr ) : unsigned;
+
+ procedure on_init; virtual;
+ procedure on_draw; virtual;
+
+ procedure on_mouse_move (x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ CONSTRUCT }
+constructor spiral.Construct;
+begin
+ m_x :=x;
+ m_y :=y;
+ m_r1:=r1;
+ m_r2:=r2;
+
+ m_step :=step;
+ m_start_angle:=start_angle;
+ m_angle :=start_angle;
+
+ m_da:=deg2rad(4.0 );
+ m_dr:=m_step / 90.0;
+
+end;
+
+{ REWIND }
+procedure spiral.rewind;
+begin
+ m_angle :=m_start_angle;
+ m_curr_r:=m_r1;
+ m_start :=true;
+
+end;
+
+{ VERTEX }
+function spiral.vertex;
+begin
+ if m_curr_r > m_r2 then
+ begin
+ result:=path_cmd_stop;
+
+ exit;
+
+ end;
+
+ x^:=m_x + Cos(m_angle ) * m_curr_r;
+ y^:=m_y + Sin(m_angle ) * m_curr_r;
+
+ m_curr_r:=m_curr_r + m_dr;
+ m_angle :=m_angle + m_da;
+
+ if m_start then
+ begin
+ m_start:=false;
+
+ result:=path_cmd_move_to;
+
+ end
+ else
+ result:=path_cmd_line_to;
+
+end;
+
+{ COUNT_SPANS }
+function count_spans(ras : rasterizer_scanline_ptr; sl : scanline_ptr ) : unsigned;
+var
+ n : unsigned;
+
+begin
+ n:=0;
+
+ if ras.rewind_scanlines then
+ begin
+ sl.reset(ras._min_x ,ras._max_x );
+
+ if sl.is_embedded then
+ while ras.sweep_scanline_em(sl ) do
+ inc(n ,sl.num_spans )
+ else
+ while ras.sweep_scanline(sl ) do
+ inc(n ,sl.num_spans );
+
+ end;
+
+ result:=n;
+
+end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_polygons.Construct (5.0 ,5.0 ,5.0 + 205.0 ,110.0 ,not flip_y_ );
+ m_fill_rule.Construct (200 ,5.0 ,200 + 105.0 ,50.0 ,not flip_y_ );
+ m_scanline_type.Construct(300 ,5.0 ,300 + 115.0 ,70.0 ,not flip_y_ );
+ m_operation.Construct (535.0 ,5.0 ,535.0 + 115.0 ,145.0 ,not flip_y_ );
+
+ m_operation.add_item ('None' );
+ m_operation.add_item ('OR' );
+ m_operation.add_item ('AND' );
+ m_operation.add_item ('XOR Linear' );
+ m_operation.add_item ('XOR Saddle' );
+ m_operation.add_item ('A-B' );
+ m_operation.add_item ('B-A' );
+ m_operation.cur_item_(2 );
+
+ add_ctrl(@m_operation );
+
+ m_operation.no_transform;
+
+ m_fill_rule.add_item ('Even-Odd' );
+ m_fill_rule.add_item ('Non Zero' );
+ m_fill_rule.cur_item_(1 );
+
+ add_ctrl(@m_fill_rule );
+
+ m_fill_rule.no_transform;
+
+ m_scanline_type.add_item ('scanline_p' );
+ m_scanline_type.add_item ('scanline_u' );
+ m_scanline_type.add_item ('scanline_bin' );
+ m_scanline_type.cur_item_(1 );
+
+ add_ctrl(@m_scanline_type );
+
+ m_scanline_type.no_transform;
+
+ m_polygons.add_item ('Two Simple Paths' );
+ m_polygons.add_item ('Closed Stroke' );
+ m_polygons.add_item ('Great Britain and Arrows' );
+ m_polygons.add_item ('Great Britain and Spiral' );
+ m_polygons.add_item ('Spiral and Glyph' );
+ m_polygons.cur_item_(3 );
+
+ add_ctrl(@m_polygons );
+
+ m_polygons.no_transform;
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_polygons.Destruct;
+ m_fill_rule.Destruct;
+ m_scanline_type.Destruct;
+ m_operation.Destruct;
+
+end;
+
+{ RENDER_SCANLINE_BOOLEAN }
+procedure the_application.render_scanline_boolean;
+var
+ op : sbool_op_e;
+ rb : renderer_base;
+
+ buf : array[0..99 ] of char;
+
+ pixf : pixel_formats;
+ rgba : aggclr;
+
+ t1 ,t2 : double;
+
+ i : int;
+
+ num_spans : unsigned;
+
+ renp ,
+ renu ,
+ rent : renderer_scanline_aa_solid;
+ renb : renderer_scanline_bin_solid;
+
+ slt ,
+ slp ,
+ slp1 ,
+ slp2 : scanline_p8;
+ slu ,
+ slu1 ,
+ slu2 : scanline_u8;
+ slb ,
+ slb1 ,
+ slb2 : scanline_bin;
+ txt : gsv_text;
+
+ txt_stroke : conv_stroke;
+
+ storage ,
+ storage1 ,
+ storage2 : scanline_storage_aa8;
+
+ storageb ,
+ storageb1 ,
+ storageb2 : scanline_storage_bin;
+
+begin
+ if m_operation._cur_item > 0 then
+ begin
+ case m_operation._cur_item of
+ 1 : op:=sbool_or;
+ 2 : op:=sbool_and;
+ 3 : op:=sbool_xor;
+ 4 : op:=sbool_xor_saddle;
+ 5 : op:=sbool_a_minus_b;
+ 6 : op:=sbool_b_minus_a;
+
+ end;
+
+ pixfmt_bgr24(pixf ,rbuf_window );
+ rb.Construct(@pixf );
+
+ t1:=0.0;
+ t2:=0.0;
+
+ num_spans:=0;
+
+ // Render Clipping
+ case m_scanline_type._cur_item of
+ 0 :
+ begin
+ renp.Construct(@rb );
+ slp.Construct;
+ slp1.Construct;
+ slp2.Construct;
+
+ // The intermediate storage is used only to test the perfoprmance,
+ // the short variant can be as follows:
+ // ------------------------
+ // rgba.ConstrDbl (0.5 ,0.0 ,0 ,0.5 );
+ // renp.color (@rgba );
+ // sbool_combine_shapes_aa(op ,ras1 ,ras2 ,@slp1 ,@slp2 ,@slp ,@renp );
+
+ storage.Construct;
+ storage1.Construct;
+ storage2.Construct;
+
+ render_scanlines(ras1 ,@slp ,@storage1 );
+ render_scanlines(ras2 ,@slp ,@storage2 );
+
+ start_timer;
+
+ for i:=0 to 9 do
+ sbool_combine_shapes_aa(op ,@storage1 ,@storage2 ,@slp1 ,@slp2 ,@slp ,@storage );
+
+ t1:=elapsed_time / 10.0;
+
+ start_timer;
+
+ rgba.ConstrDbl (0.5 ,0.0 ,0 ,0.5 );
+ renp.color_ (@rgba );
+ render_scanlines(@storage ,@slp ,@renp );
+
+ t2:=elapsed_time;
+
+ num_spans:=count_spans(@storage ,@slp );
+
+ slp.Destruct;
+ slp1.Destruct;
+ slp2.Destruct;
+
+ storage.Destruct;
+ storage1.Destruct;
+ storage2.Destruct;
+
+ end;
+
+ 1 :
+ begin
+ renu.Construct(@rb );
+
+ slu.Construct;
+ slu1.Construct;
+ slu2.Construct;
+
+ {rgba.ConstrDbl (0.5 ,0.0 ,0 ,0.5 );
+ renu.color (@rgba );
+ sbool_combine_shapes_aa(op ,ras1 ,ras2 ,@slu1 ,@slu2 ,@slu ,@renu );}
+
+ storage.Construct;
+ storage1.Construct;
+ storage2.Construct;
+
+ render_scanlines(ras1 ,@slu ,@storage1 );
+ render_scanlines(ras2 ,@slu ,@storage2 );
+
+ start_timer;
+
+ for i:=0 to 9 do
+ sbool_combine_shapes_aa(op ,@storage1 ,@storage2 ,@slu1 ,@slu2 ,@slu ,@storage );
+
+ t1:=elapsed_time / 10.0;
+
+ start_timer;
+
+ rgba.ConstrDbl (0.5 ,0.0 ,0 ,0.5 );
+ renu.color_ (@rgba );
+ render_scanlines(@storage ,@slu ,@renu );
+
+ t2:=elapsed_time;
+
+ num_spans:=count_spans(@storage ,@slu );{}
+
+ slu.Destruct;
+ slu1.Destruct;
+ slu2.Destruct;
+
+ storage.Destruct;
+ storage1.Destruct;
+ storage2.Destruct;{}
+
+ end;
+
+ 2 :
+ begin
+ renb.Construct(@rb );
+
+ slb.Construct;
+ slb1.Construct;
+ slb2.Construct;
+
+ storageb.Construct;
+ storageb1.Construct;
+ storageb2.Construct;
+
+ render_scanlines(ras1 ,@slb ,@storageb1 );
+ render_scanlines(ras2 ,@slb ,@storageb2 );
+
+ start_timer;
+
+ for i:=0 to 9 do
+ sbool_combine_shapes_bin(op ,@storageb1 ,@storageb2 ,@slb1 ,@slb2 ,@slb ,@storageb );
+
+ t1:=elapsed_time / 10.0;
+
+ start_timer;
+
+ rgba.ConstrDbl ({0.5}1 ,0.0 ,0 {,0.5} );
+ renb.color_ (@rgba );
+ render_scanlines(@storageb ,@slb ,@renb );
+
+ t2:=elapsed_time;
+
+ num_spans:=count_spans(@storageb ,@slb );
+
+ slb.Destruct;
+ slb1.Destruct;
+ slb2.Destruct;
+
+ storageb.Destruct;
+ storageb1.Destruct;
+ storageb2.Destruct;
+
+ end;
+
+ end;
+
+ // Render text
+ sprintf(@buf[0 ] ,'Combine=%.3fms'#13#13 ,t1 );
+ sprintf(@buf[StrLen(@buf ) ] ,'Render=%.3fms'#13#13 ,t2 );
+ sprintf(@buf[StrLen(@buf ) ] ,'num_spans=%d' ,num_spans );
+
+ rent.Construct(@rb );
+ slt.Construct;
+ txt.Construct;
+ txt_stroke.Construct(@txt );
+ txt_stroke.width_ (1.0 );
+ txt_stroke.line_cap_(round_cap );
+ txt.size_ (8.0 );
+ txt.start_point_ (420 ,40 );
+ txt.text_ (@buf[0 ] );
+
+ ras1.reset;
+ ras1.add_path (@txt_stroke );
+ rgba.ConstrDbl (0.0 ,0.0 ,0.0 );
+ rent.color_ (@rgba );
+ render_scanlines(ras1 ,@slt ,@rent );
+
+ slt.Destruct;
+ txt.Destruct;
+ txt_stroke.Destruct;
+
+ end;
+
+end;
+
+{ RENDER_SBOOL }
+function the_application.render_sbool;
+var
+ pf : pixel_formats;
+ rb : renderer_base;
+ ren : renderer_scanline_aa_solid;
+ sl : scanline_p8;
+
+ ps1 ,
+ ps2 ,
+
+ gb_poly ,
+ arrows ,
+ glyph : path_storage;
+
+ rgba : aggclr;
+ x ,y : double;
+
+ mtx1 ,
+ mtx2 ,
+ mtx : trans_affine;
+ tat : trans_affine_translation;
+ tas : trans_affine_scaling;
+
+ stroke ,
+ stroke_gb_poly : conv_stroke;
+
+ trans ,
+ trans_gb_poly ,
+ trans_arrows : conv_transform;
+
+ curve : conv_curve;
+
+ sp : spiral;
+
+begin
+ pixfmt_bgr24(pf ,rbuf_window );
+
+ rb.Construct (@pf );
+ ren.Construct(@rb );
+
+ sl.Construct;
+
+ if m_fill_rule._cur_item <> 0 then
+ ras1.filling_rule(fill_non_zero )
+ else
+ ras1.filling_rule(fill_even_odd );
+
+ if m_fill_rule._cur_item <> 0 then
+ ras2.filling_rule(fill_non_zero )
+ else
+ ras2.filling_rule(fill_even_odd );
+
+ case m_polygons._cur_item of
+ 0 : // Two simple paths
+ begin
+ ps1.Construct;
+ ps2.Construct;
+
+ x:=m_x - _initial_width / 2 + 100;
+ y:=m_y - _initial_height / 2 + 100;
+
+ ps1.move_to(x + 140 ,y + 145 );
+ ps1.line_to(x + 225 ,y + 44 );
+ ps1.line_to(x + 296 ,y + 219 );
+ ps1.close_polygon;
+
+ ps1.line_to(x + 226 ,y + 289 );
+ ps1.line_to(x + 82 ,y + 292 );
+
+ ps1.move_to(x + 220 ,y + 222 );
+ ps1.line_to(x + 363 ,y + 249 );
+ ps1.line_to(x + 265 ,y + 331 );
+
+ ps1.move_to(x + 242 ,y + 243 );
+ ps1.line_to(x + 268 ,y + 309 );
+ ps1.line_to(x + 325 ,y + 261 );
+
+ ps1.move_to(x + 259 ,y + 259 );
+ ps1.line_to(x + 273 ,y + 288 );
+ ps1.line_to(x + 298 ,y + 266 );
+
+ ps2.move_to(100 + 32 ,100 + 77 );
+ ps2.line_to(100 + 473 ,100 + 263 );
+ ps2.line_to(100 + 351 ,100 + 290 );
+ ps2.line_to(100 + 354 ,100 + 374 );
+
+ ras1.reset;
+ ras1.add_path (@ps1 );
+ rgba.ConstrDbl (0 ,0 ,0 ,{0.1}0.0 );
+ ren.color_ (@rgba );
+ { render_scanlines(ras1 ,@sl ,@ren ); }
+
+ ras2.reset;
+ ras2.add_path (@ps2 );
+ rgba.ConstrDbl (0 ,0.6 ,0 ,{0.1}0.0 );
+ ren.color_ (@rgba );
+ { render_scanlines(ras2 ,@sl ,@ren ); }
+
+ render_scanline_boolean(ras1 ,ras2 );
+
+ ps1.Destruct;
+ ps2.Destruct;
+
+ end;
+
+ 1 : // Closed stroke
+ begin
+ ps1.Construct;
+ ps2.Construct;
+ stroke.Construct(@ps2 );
+ stroke.width_ (15.0 );
+
+ x:=m_x - _initial_width / 2 + 100;
+ y:=m_y - _initial_height / 2 + 100;
+
+ ps1.move_to(x + 140 ,y + 145 );
+ ps1.line_to(x + 225 ,y + 44 );
+ ps1.line_to(x + 296 ,y + 219 );
+ ps1.close_polygon;
+
+ ps1.line_to(x + 226 ,y + 289 );
+ ps1.line_to(x + 82 ,y + 292 );
+
+ ps1.move_to(x + 220 - 50 ,y + 222 );
+ ps1.line_to(x + 265 - 50 ,y + 331 );
+ ps1.line_to(x + 363 - 50 ,y + 249 );
+ ps1.close_polygon(path_flags_ccw );
+
+ ps2.move_to(100 + 32 ,100 + 77 );
+ ps2.line_to(100 + 473 ,100 + 263 );
+ ps2.line_to(100 + 351 ,100 + 290 );
+ ps2.line_to(100 + 354 ,100 + 374 );
+ ps2.close_polygon;
+
+ ras1.reset;
+ ras1.add_path (@ps1 );
+ rgba.ConstrDbl (0 ,0 ,0 ,0.1 );
+ ren.color_ (@rgba );
+ render_scanlines(ras1 ,@sl ,@ren );
+
+ ras2.reset;
+ ras2.add_path (@stroke );
+ rgba.ConstrDbl (0 ,0.6 ,0 ,0.1 );
+ ren.color_ (@rgba );
+ render_scanlines(ras2 ,@sl ,@ren );
+
+ render_scanline_boolean(ras1 ,ras2 );
+
+ ps1.Destruct;
+ ps2.Destruct;
+ stroke.Destruct;
+
+ end;
+
+ 2 : // Great Britain and Arrows
+ begin
+ gb_poly.Construct;
+ arrows.Construct;
+
+ make_gb_poly(@gb_poly );
+ make_arrows (@arrows );
+
+ mtx1.Construct;
+ mtx2.Construct;
+ tat.Construct(-1150 ,-1150 );
+ tas.Construct(2.0 );
+ mtx1.multiply(@tat );
+ mtx1.multiply(@tas );
+
+ mtx2:=mtx1;
+
+ tat.Construct(m_x - _initial_width / 2 ,m_y - _initial_height / 2 );
+
+ mtx2.multiply(@tat );
+
+ trans_gb_poly.Construct(@gb_poly ,@mtx1 );
+ trans_arrows.Construct (@arrows ,@mtx2 );
+
+ ras2.add_path (@trans_gb_poly );
+ rgba.ConstrDbl (0.5 ,0.5 ,0 ,0.1 );
+ ren.color_ (@rgba );
+ render_scanlines(ras2 ,@sl ,@ren );
+
+ stroke_gb_poly.Construct(@trans_gb_poly );
+ stroke_gb_poly.width_ (0.1);
+ ras1.add_path (@stroke_gb_poly );
+ rgba.ConstrDbl (0 ,0 ,0 );
+ ren.color_ (@rgba );
+ render_scanlines (ras1 ,@sl ,@ren );
+
+ ras2.add_path (@trans_arrows );
+ rgba.ConstrDbl (0.0 ,0.5 ,0.5 ,0.1 );
+ ren.color_ (@rgba );
+ render_scanlines(ras2 ,@sl ,@ren );
+
+ ras1.reset;
+ ras1.add_path(@trans_gb_poly );
+
+ render_scanline_boolean(ras1 ,ras2 );
+
+ gb_poly.Destruct;
+ arrows.Destruct;
+ stroke_gb_poly.Destruct;
+
+ end;
+
+ 3 : // Great Britain and a Spiral
+ begin
+ sp.Construct (m_x ,m_y ,10 ,150 ,30 ,0.0 );
+ stroke.Construct(@sp );
+ stroke.width_ (15.0 );
+
+ gb_poly.Construct;
+ make_gb_poly(@gb_poly );
+
+ mtx.Construct;
+ tat.Construct(-1150 ,-1150 );
+ tas.Construct(2.0 );
+ mtx.multiply(@tat );
+ mtx.multiply(@tas );
+ mtx.multiply(_trans_affine_resizing );
+
+ trans_gb_poly.Construct(@gb_poly ,@mtx );
+
+ ras1.add_path (@trans_gb_poly );
+ rgba.ConstrDbl (0.5 ,0.5 ,0 ,0.1 );
+ ren.color_ (@rgba );
+ render_scanlines(ras1 ,@sl ,@ren );
+
+ stroke_gb_poly.Construct(@trans_gb_poly );
+ stroke_gb_poly.width_ (0.1 );
+ ras1.add_path (@stroke_gb_poly );
+ rgba.ConstrDbl (0 ,0 ,0 );
+ ren.color_ (@rgba );
+ render_scanlines (ras1 ,@sl ,@ren );
+
+ ras2.reset;
+ ras2.add_path (@stroke );
+ rgba.ConstrDbl (0.0 ,0.5 ,0.5 ,0.1 );
+ ren.color_ (@rgba );
+ render_scanlines(ras2 ,@sl ,@ren );
+
+ ras1.reset;
+ ras1.add_path(@trans_gb_poly );
+
+ render_scanline_boolean(ras1 ,ras2 );
+
+ stroke.Destruct;
+ gb_poly.Destruct;
+ stroke_gb_poly.Destruct;
+
+ end;
+
+ 4 : // Spiral and glyph
+ begin
+ sp.Construct (m_x ,m_y ,10 ,150 ,30 ,0.0 );
+ stroke.Construct(@sp );
+ stroke.width_ (15.0 );
+
+ glyph.Construct;
+ glyph.move_to(28.47 ,6.45 );
+ glyph.curve3 (21.58 ,1.12 ,19.82 ,0.29 );
+ glyph.curve3 (17.19 ,-0.93 ,14.21 ,-0.93 );
+ glyph.curve3 (9.57 ,-0.93 ,6.57 ,2.25 );
+ glyph.curve3 (3.56 ,5.42 ,3.56 ,10.60 );
+ glyph.curve3 (3.56 ,13.87 ,5.03 ,16.26 );
+ glyph.curve3 (7.03 ,19.58 ,11.99 ,22.51 );
+ glyph.curve3 (16.94 ,25.44 ,28.47 ,29.64 );
+ glyph.line_to(28.47 ,31.40 );
+ glyph.curve3 (28.47 ,38.09 ,26.34 ,40.58 );
+ glyph.curve3 (24.22 ,43.07 ,20.17 ,43.07 );
+ glyph.curve3 (17.09 ,43.07 ,15.28 ,41.41 );
+ glyph.curve3 (13.43 ,39.75 ,13.43 ,37.60 );
+ glyph.line_to(13.53 ,34.77 );
+ glyph.curve3 (13.53 ,32.52 ,12.38 ,31.30 );
+ glyph.curve3 (11.23 ,30.08 ,9.38 ,30.08 );
+ glyph.curve3 (7.57 ,30.08 ,6.42 ,31.35 );
+ glyph.curve3 (5.27 ,32.62 ,5.27 ,34.81 );
+ glyph.curve3 (5.27 ,39.01 ,9.57 ,42.53 );
+ glyph.curve3 (13.87 ,46.04 ,21.63 ,46.04 );
+ glyph.curve3 (27.59 ,46.04 ,31.40 ,44.04 );
+ glyph.curve3 (34.28 ,42.53 ,35.64 ,39.31 );
+ glyph.curve3 (36.52 ,37.21 ,36.52 ,30.71 );
+ glyph.line_to(36.52 ,15.53 );
+ glyph.curve3 (36.52 ,9.13 ,36.77 ,7.69 );
+ glyph.curve3 (37.01 ,6.25 ,37.57 ,5.76 );
+ glyph.curve3 (38.13 ,5.27 ,38.87 ,5.27 );
+ glyph.curve3 (39.65 ,5.27 ,40.23 ,5.62 );
+ glyph.curve3 (41.26 ,6.25 ,44.19 ,9.18 );
+ glyph.line_to(44.19 ,6.45 );
+ glyph.curve3 (38.72 ,-0.88 ,33.74 ,-0.88 );
+ glyph.curve3 (31.35 ,-0.88 ,29.93 ,0.78 );
+ glyph.curve3 (28.52 ,2.44 ,28.47 ,6.45 );
+ glyph.close_polygon;
+
+ glyph.move_to(28.47 ,9.62 );
+ glyph.line_to(28.47 ,26.66 );
+ glyph.curve3 (21.09 ,23.73 ,18.95 ,22.51 );
+ glyph.curve3 (15.09 ,20.36 ,13.43 ,18.02 );
+ glyph.curve3 (11.77 ,15.67 ,11.77 ,12.89 );
+ glyph.curve3 (11.77 ,9.38 ,13.87 ,7.06 );
+ glyph.curve3 (15.97 ,4.74 ,18.70 ,4.74 );
+ glyph.curve3 (22.41 ,4.74 ,28.47 ,9.62 );
+ glyph.close_polygon;
+
+ mtx.Construct;
+ tas.Construct(4.0 );
+ tat.Construct(220 ,200 );
+ mtx.multiply(@tas );
+ mtx.multiply(@tat );
+
+ trans.Construct(@glyph ,@mtx );
+ curve.Construct(@trans );
+
+ ras1.reset;
+ ras1.add_path (@stroke );
+ rgba.ConstrDbl (0 ,0 ,0 ,0.1 );
+ ren.color_ (@rgba );
+ render_scanlines(ras1 ,@sl ,@ren );
+
+ ras2.reset;
+ ras2.add_path (@curve );
+ rgba.ConstrDbl (0 ,0.6 ,0 ,0.1 );
+ ren.color_ (@rgba );
+ render_scanlines(ras2 ,@sl ,@ren );
+
+ render_scanline_boolean(ras1 ,ras2 );
+
+ stroke.Destruct;
+ glyph.Destruct;
+ curve.Destruct;
+
+ end;
+
+ end;
+
+ sl.Destruct;
+
+ result:=0;
+
+end;
+
+{ ON_INIT }
+procedure the_application.on_init;
+begin
+ m_x:=_width / 2.0;
+ m_y:=_height / 2.0;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ pf : pixel_formats;
+
+ rgba : aggclr;
+
+ ren_base : renderer_base;
+ ren_solid : renderer_scanline_aa_solid;
+
+ sl : scanline_u8;
+ ras ,
+ ras2 : rasterizer_scanline_aa;
+
+begin
+// Initialize structures
+ pixfmt_bgr24(pf ,rbuf_window );
+
+ ren_base.Construct (@pf );
+ ren_solid.Construct(@ren_base );
+
+ rgba.ConstrDbl(1 ,1 ,1 );
+ ren_base.clear(@rgba );
+
+ sl.Construct;
+ ras.Construct;
+ ras2.Construct;
+
+// Render the controls
+ render_ctrl(@ras ,@sl ,@ren_solid ,@m_polygons );
+ render_ctrl(@ras ,@sl ,@ren_solid ,@m_fill_rule );
+ render_ctrl(@ras ,@sl ,@ren_solid ,@m_scanline_type );
+ render_ctrl(@ras ,@sl ,@ren_solid ,@m_operation );
+
+// Render
+ render_sbool(@ras ,@ras2 );
+
+// Free AGG resources
+ sl.Destruct;
+ ras.Destruct;
+ ras2.Destruct;
+
+end;
+
+{ ON_MOUSE_MOVE }
+procedure the_application.on_mouse_move;
+begin
+ if flags and mouse_left <> 0 then
+ begin
+ m_x:=x;
+ m_y:=y;
+
+ force_redraw;
+
+ end;
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure the_application.on_mouse_button_down;
+var
+ buf : array[0..99 ] of char;
+
+begin
+ if flags and mouse_left <> 0 then
+ begin
+ m_x:=x;
+ m_y:=y;
+
+ force_redraw;
+
+ end;
+
+ if flags and mouse_right <> 0 then
+ begin
+ sprintf (@buf[0 ] ,'%d ' ,x );
+ sprintf (@buf[StrLen(@buf ) ] ,'%d' ,y );
+ message_(@buf[0 ] );
+
+ end;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ 'This is another example of using of the scanline boolean algebra. The example is '#13 +
+ 'similar to Demo gpc_test. Note that the cost of the boolean operation with Anti-Aliasing '#13 +
+ 'is comparable with rendering (the rasterization time is not included). Also note that '#13 +
+ 'there is a difference in timings between using of scanline_u and scanline_p. Most often '#13 +
+ 'scanline_u works faster, but it''s because of much less number of produced spans.'#13 +
+ 'Actually, when using the scanline_u the complexity of the algorithm becomes proportional '#13 +
+ 'to the area of the polygons, while in scanline_p it''s proportional to the perimeter. '#13 +
+ 'Of course, the binary variant works much faster than the Anti-Aliased one.' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+VAR
+ app : the_application;
+
+BEGIN
+ app.Construct(pix_format_bgr24 ,flip_y );
+ app.caption_ ('AGG Example. Scanline Boolean (F1-Help)' );
+
+ if app.init(655 ,520 ,window_resize ) then
+ app.run;
+
+ app.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/settings.dat b/src/corelib/render/software/agg-demos/settings.dat
new file mode 100644
index 00000000..370515d9
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/settings.dat
@@ -0,0 +1,56 @@
+350.000000
+280.000000
+1.000000
+0.000000
+0.000000
+1.000000
+0.200000
+0.800000
+0.400000
+0.600000
+0.600000
+0.400000
+0.800000
+0.200000
+1.000000
+0.000000
+0.000000
+1.000000
+0.195968
+0.012121
+0.400000
+0.600000
+0.600000
+0.400000
+0.795968
+0.927273
+1.000000
+0.000000
+0.000000
+1.000000
+0.200000
+0.800000
+0.400000
+0.600000
+0.600000
+0.703030
+0.800000
+0.200000
+1.000000
+0.000000
+0.000000
+1.000000
+0.200000
+1.000000
+0.400000
+1.000000
+0.600000
+1.000000
+0.800000
+1.000000
+1.000000
+1.000000
+1.000000
+1.000000
+1.666667
+1.000000
diff --git a/src/corelib/render/software/agg-demos/shapes.txt b/src/corelib/render/software/agg-demos/shapes.txt
new file mode 100644
index 00000000..5bdba8a4
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/shapes.txt
@@ -0,0 +1,10740 @@
+=======BeginShape
+Path -1 -1 0 607 -1043
+Curve 704 -1101 804 -1117
+Curve 896 -1122 988 -1126
+Curve 1073 -1120 1157 -1094
+Curve 1240 -1069 1316 -1001
+<-------EndPath
+Path -1 -1 0 550 -1069
+Curve 554 -1074 557 -1078
+Curve 606 -1135 684 -1187
+Curve 761 -1240 877 -1255
+Curve 962 -1265 1046 -1275
+Curve 1099 -1279 1195 -1256
+Curve 1291 -1234 1396 -1135
+<-------EndPath
+Path -1 -1 0 463 -1101
+Curve 512 -1225 577 -1297
+Curve 642 -1369 725 -1416
+Curve 807 -1464 911 -1475
+Curve 1000 -1481 1088 -1486
+Curve 1161 -1487 1219 -1454
+<-------EndPath
+Path 1 -1 0 510 -1085
+Curve 487 -1093 463 -1101
+Curve 396 -1119 328 -1136
+Curve 202 -1161 62 -1165
+Curve -73 -1169 -215 -1136
+Curve -246 -1129 -277 -1121
+Curve -311 -1112 -345 -1102
+Curve -372 -1094 -399 -1085
+Curve -439 -1072 -479 -1058
+Curve -546 -1032 -592 -995
+<-------EndPath
+Path 1 0 0 -592 -995
+Curve -633 -963 -656 -923
+<-------EndPath
+Path 1 -1 0 -656 -923
+Curve -659 -918 -661 -912
+Curve -709 -819 -660 -751
+Curve -612 -684 -466 -628
+Curve -320 -572 -222 -538
+Curve -125 -505 -101 -476
+Curve -93 -465 -92 -457
+<-------EndPath
+Path 1 1 0 -92 -457
+Curve -72 -411 -73 -367
+<-------EndPath
+Path 1 -1 -1 -73 -367
+Curve -73 -366 -73 -364
+Curve -73 -365 -72 -365
+<-------EndPath
+Path 1 -1 0 -72 -365
+Curve -88 -319 -131 -281
+Curve -132 -281 -132 -280
+<-------EndPath
+Path 1 2 0 -132 -280
+Curve -126 -263 -120 -246
+Curve -90 -163 -5 -162
+Curve 34 -162 60 -174
+Curve 96 -192 107 -236
+<-------EndPath
+Path 1 0 -1 107 -236
+Curve 90 -259 72 -281
+Curve 54 -303 36 -325
+Curve 15 -347 -6 -369
+Curve -40 -400 13 -434
+Curve 71 -471 132 -482
+Curve 136 -483 140 -483
+Curve 166 -488 192 -493
+Curve 192 -492 192 -491
+<-------EndPath
+Path 1 -1 0 192 -491
+Curve 242 -501 291 -510
+<-------EndPath
+Path 1 0 -1 291 -510
+Curve 290 -514 288 -518
+Curve 358 -538 428 -558
+Curve 499 -577 594 -610
+Curve 689 -644 748 -710
+Curve 807 -777 771 -861
+Curve 734 -945 649 -993
+Curve 564 -1041 510 -1085
+<-------EndPath
+Path -1 0 0 510 -1085
+Curve 530 -1077 550 -1069
+Curve 551 -1068 552 -1067
+Curve 568 -1061 583 -1054
+Curve 595 -1049 607 -1043
+Curve 717 -991 774 -932
+Curve 792 -914 809 -895
+Curve 817 -886 824 -877
+Curve 848 -898 886 -885
+Curve 914 -853 866 -808
+Curve 899 -708 769 -632
+Curve 662 -571 530 -549
+Curve 411 -530 291 -510
+<-------EndPath
+Path -1 0 0 192 -491
+Curve 163 -484 133 -476
+Curve 55 -450 41 -368
+Curve 46 -355 57 -343
+Curve 67 -334 77 -325
+<-------EndPath
+Path -1 1 -1 77 -325
+Curve 88 -318 99 -311
+Curve 106 -301 112 -291
+<-------EndPath
+Path -1 2 0 112 -291
+Curve 113 -291 113 -291
+Curve 148 -254 182 -216
+Curve 186 -211 190 -206
+<-------EndPath
+Path -1 0 0 190 -206
+Curve 211 -172 232 -138
+Curve 237 -128 242 -117
+Curve 243 -116 243 -115
+<-------EndPath
+Path -1 -1 0 243 -115
+Curve 290 -106 337 -96
+Curve 391 -81 439 -52
+Curve 489 -22 521 28
+Curve 554 83 519 135
+Curve 498 162 466 179
+Curve 416 204 363 221
+Curve 309 239 260 260
+<-------EndPath
+Path -1 0 0 260 260
+Curve 258 272 255 283
+<-------EndPath
+Path -1 -1 0 255 283
+Curve 301 307 357 282
+Curve 371 275 384 268
+<-------EndPath
+Path 1 0 0 77 -325
+Curve 95 -308 112 -291
+<-------EndPath
+Path 2 0 0 112 -291
+Curve 113 -260 107 -236
+<-------EndPath
+Path 1 2 0 161 -167
+Curve 132 -116 147 -63
+Curve 152 -42 165 -20
+Curve 185 13 232 8
+<-------EndPath
+Path 1 0 -1 232 8
+Curve 224 -28 216 -63
+Curve 215 -66 214 -69
+Curve 206 -89 198 -108
+Curve 180 -138 161 -167
+<-------EndPath
+Path 2 0 0 161 -167
+Curve 172 -187 190 -206
+<-------EndPath
+Path 0 0 0 243 -115
+Curve 241 -116 238 -116
+Curve 235 -115 231 -114
+Curve 215 -111 198 -108
+<-------EndPath
+Path 0 0 0 238 -116
+Curve 240 -117 242 -117
+<-------EndPath
+Path -1 2 -1 278 -6
+Curve 278 -6 278 -5
+<-------EndPath
+Path -1 2 0 278 -5
+Curve 280 73 282 151
+<-------EndPath
+Path -1 2 -1 282 151
+Curve 282 151 281 151
+<-------EndPath
+Path -1 0 0 281 151
+Curve 266 209 263 255
+<-------EndPath
+Path -1 0 -1 263 255
+Curve 262 254 261 253
+<-------EndPath
+Path -1 0 0 261 253
+Curve 261 257 260 260
+<-------EndPath
+Path 0 0 0 260 260
+Curve 258 261 256 261
+Curve 224 273 251 295
+<-------EndPath
+Path 0 -1 0 251 295
+Curve 253 289 255 283
+<-------EndPath
+Path 0 -1 0 278 -6
+Curve 271 -35 263 -63
+Curve 253 -89 243 -115
+<-------EndPath
+Path 0 0 0 866 -808
+Curve 860 -822 854 -835
+Curve 839 -856 824 -877
+<-------EndPath
+Path 0 1 -1 228 172
+Curve 222 195 215 217
+Curve 190 288 134 321
+Curve 80 353 2 363
+Curve 2 366 2 369
+<-------EndPath
+Path 0 3 0 2 369
+Curve 33 370 63 370
+Curve 177 374 243 312
+<-------EndPath
+Path 0 -1 0 243 312
+Curve 246 307 248 301
+Curve 250 298 251 295
+<-------EndPath
+Path -1 -1 0 251 295
+Curve 253 296 254 297
+Curve 255 298 256 299
+Curve 300 330 357 328
+Curve 369 324 381 320
+<-------EndPath
+Path 0 2 0 281 151
+Curve 270 156 259 160
+Curve 244 166 228 172
+<-------EndPath
+Path 1 2 0 228 172
+Curve 169 192 110 212
+Curve 13 238 -89 244
+Curve -90 244 -90 244
+Curve -186 229 -245 193
+Curve -260 183 -274 172
+<-------EndPath
+Path 1 -1 0 -274 172
+Curve -275 172 -275 171
+<-------EndPath
+Path 1 2 0 -275 171
+Curve -361 157 -409 117
+<-------EndPath
+Path 1 0 -1 -409 117
+Curve -412 117 -414 116
+<-------EndPath
+Path 1 -1 0 -414 116
+Curve -432 196 -421 293
+Curve -421 295 -421 297
+<-------EndPath
+Path 1 3 0 -421 297
+Curve -421 303 -420 309
+<-------EndPath
+Path 1 3 -1 -420 309
+Curve -417 309 -413 309
+<-------EndPath
+Path 1 3 0 -413 309
+Curve -399 335 -362 351
+Curve -267 390 -153 377
+Curve -133 375 -112 373
+Curve -94 372 -76 371
+Curve -37 370 2 369
+<-------EndPath
+Path 2 2 0 65 118
+Curve 131 107 164 66
+<-------EndPath
+Path 3 1 -1 170 282
+Curve 173 280 176 278
+Curve 175 279 173 280
+Curve 172 281 170 282
+<-------EndPath
+Path 3 0 0 33 483
+Curve 70 475 106 466
+Curve 116 458 127 453
+<-------EndPath
+Path 3 -1 0 127 453
+Curve 129 452 131 451
+<-------EndPath
+Path 3 4 0 131 451
+Curve 134 450 137 448
+Curve 139 448 140 447
+Curve 176 435 210 456
+Curve 224 469 237 481
+<-------EndPath
+Path 3 3 0 237 481
+Curve 238 481 238 481
+<-------EndPath
+Path 3 -1 0 238 481
+Curve 222 366 243 312
+<-------EndPath
+Path 0 3 0 33 483
+Curve 28 484 22 485
+<-------EndPath
+Path 0 4 0 22 485
+Curve 24 508 26 530
+Curve 26 536 26 542
+<-------EndPath
+Path 0 -1 0 26 542
+Curve 29 608 14 748
+Curve -1 889 -29 943
+Curve -58 992 -87 1040
+Curve -117 1083 -148 1250
+Curve -153 1278 -158 1305
+<-------EndPath
+Path 0 -1 -1 -158 1305
+Curve -155 1306 -152 1306
+<-------EndPath
+Path 0 -1 0 -152 1306
+Curve -103 1232 -61 1154
+Curve -20 1076 14 992
+Curve 48 908 72 814
+Curve 95 722 108 628
+Curve 121 547 134 466
+<-------EndPath
+Path 0 -1 -1 134 466
+Curve 131 460 127 453
+<-------EndPath
+Path 4 -1 0 131 451
+Curve 132 453 133 455
+Curve 134 458 135 460
+<-------EndPath
+Path 4 4 0 135 460
+Curve 136 454 137 448
+<-------EndPath
+Path -1 4 0 134 466
+Curve 135 463 135 460
+<-------EndPath
+Path 4 4 0 135 460
+Curve 140 471 144 482
+Curve 173 468 210 456
+<-------EndPath
+Path -1 -1 0 133 455
+Curve 134 461 134 466
+<-------EndPath
+Path 4 -1 0 134 466
+Curve 136 486 138 505
+Curve 186 483 237 481
+<-------EndPath
+Path 3 -1 0 237 481
+Curve 238 482 238 483
+Curve 238 482 238 481
+<-------EndPath
+Path -1 -1 0 330 358
+Curve 261 360 256 299
+<-------EndPath
+Path 4 -1 0 -172 1377
+Curve -171 1377 -170 1377
+Curve -127 1378 -83 1379
+Curve 4 1375 90 1371
+Curve 124 1365 196 1371
+Curve 30 1288 -67 1335
+Curve -114 1358 -165 1368
+Curve -167 1369 -169 1369
+Curve -170 1369 -170 1369
+<-------EndPath
+Path 4 4 0 -170 1369
+Curve -171 1373 -172 1377
+<-------EndPath
+Path -1 4 0 -172 1377
+Curve -173 1377 -174 1376
+Curve -175 1376 -176 1375
+<-------EndPath
+Path -1 4 -1 -176 1375
+Curve -177 1375 -178 1374
+Curve -179 1374 -179 1374
+Curve -178 1373 -176 1372
+Curve -174 1371 -172 1370
+<-------EndPath
+Path -1 -1 0 -172 1370
+Curve -171 1365 -169 1359
+Curve -168 1352 -166 1345
+Curve -162 1325 -158 1305
+<-------EndPath
+Path 0 2 0 232 8
+Curve 255 1 278 -6
+<-------EndPath
+Path -1 -1 0 -345 -1102
+Curve -382 -1205 -478 -1264
+Curve -574 -1324 -699 -1305
+Curve -825 -1287 -869 -1257
+Curve -905 -1235 -941 -1213
+Curve -969 -1200 -1030 -1139
+<-------EndPath
+Path -1 -1 0 -399 -1085
+Curve -439 -1186 -567 -1186
+Curve -695 -1186 -765 -1167
+Curve -836 -1148 -860 -1130
+Curve -889 -1114 -918 -1098
+Curve -952 -1085 -1029 -1002
+<-------EndPath
+Path -1 -1 0 -277 -1121
+Curve -298 -1204 -319 -1286
+Curve -347 -1396 -428 -1464
+Curve -510 -1533 -640 -1525
+Curve -771 -1518 -834 -1495
+Curve -897 -1472 -977 -1419
+<-------EndPath
+Path -1 -1 0 -319 -120
+Curve -379 -125 -438 -129
+Curve -516 -127 -589 -104
+Curve -666 -81 -712 -17
+Curve -764 55 -701 120
+Curve -650 174 -581 200
+Curve -513 225 -444 233
+Curve -442 264 -471 274
+Curve -506 289 -540 304
+<-------EndPath
+Path 1 -1 -1 -92 -455
+Curve -75 -409 -73 -367
+<-------EndPath
+Path 1 -1 0 -92 -457
+Curve -92 -456 -92 -455
+<-------EndPath
+Path 2 1 0 -239 -202
+Curve -222 -190 -204 -177
+Curve -165 -137 -187 -63
+Curve -192 -48 -197 -33
+Curve -232 47 -304 47
+Curve -326 44 -348 40
+Curve -380 31 -382 -8
+<-------EndPath
+Path 2 2 0 -382 -8
+Curve -383 -7 -383 -6
+<-------EndPath
+Path 2 -1 0 -383 -6
+Curve -404 44 -409 98
+Curve -410 107 -411 115
+Curve -410 116 -409 117
+<-------EndPath
+Path 0 -1 -1 -409 117
+Curve -412 117 -414 116
+<-------EndPath
+Path -1 1 0 -319 -120
+Curve -296 -146 -273 -171
+Curve -256 -187 -239 -202
+<-------EndPath
+Path -1 2 0 -239 -202
+Curve -184 -250 -132 -280
+<-------EndPath
+Path -1 1 0 -382 -10
+Curve -381 -12 -380 -13
+Curve -368 -38 -356 -63
+Curve -341 -88 -325 -112
+Curve -322 -116 -319 -120
+<-------EndPath
+Path 1 1 0 -319 -120
+Curve -302 -117 -285 -113
+<-------EndPath
+Path 2 1 0 -382 -8
+Curve -382 -9 -382 -10
+<-------EndPath
+Path 2 -1 0 -382 -10
+Curve -383 -8 -383 -6
+<-------EndPath
+Path 0 -1 0 -592 -995
+Curve -757 -1026 -656 -923
+<-------EndPath
+Path 2 -1 -1 -275 171
+Curve -275 172 -274 172
+<-------EndPath
+Path 4 4 0 -288 493
+Curve -288 483 -288 472
+<-------EndPath
+Path 4 3 0 -288 472
+Curve -289 472 -290 471
+Curve -325 467 -360 463
+Curve -417 465 -455 505
+<-------EndPath
+Path 4 -1 0 -455 505
+Curve -458 519 -461 533
+Curve -376 496 -297 520
+Curve -293 507 -288 493
+<-------EndPath
+Path 4 0 0 -288 493
+Curve -284 484 -280 474
+<-------EndPath
+Path 4 3 0 -280 474
+Curve -284 473 -288 472
+<-------EndPath
+Path 0 3 0 -192 519
+Curve -220 511 -239 489
+Curve -254 483 -269 477
+Curve -275 476 -280 474
+<-------EndPath
+Path 3 4 0 -189 520
+Curve -148 530 -89 511
+Curve -56 503 -22 494
+Curve -12 492 -1 490
+Curve 11 488 22 485
+<-------EndPath
+Path 1 1 0 -58 306
+Curve -75 336 -41 312
+<-------EndPath
+Path 2 2 0 -212 77
+Curve -182 142 -124 143
+<-------EndPath
+Path -1 -1 0 -409 98
+Curve -411 107 -413 115
+Curve -414 116 -414 116
+<-------EndPath
+Path -1 -1 0 -472 345
+Curve -439 307 -440 254
+Curve -474 285 -505 334
+<-------EndPath
+Path 3 -1 0 -192 519
+Curve -191 520 -189 520
+<-------EndPath
+Path 4 -1 0 -189 520
+Curve -191 524 -192 528
+<-------EndPath
+Path 4 0 0 -192 528
+Curve -193 541 -194 553
+<-------EndPath
+Path 4 4 0 -194 553
+Curve -92 537 -89 511
+<-------EndPath
+Path 4 4 0 -195 556
+Curve -195 555 -194 553
+<-------EndPath
+Path 4 0 -1 -194 553
+Curve -199 554 -204 554
+Curve -204 555 -204 556
+Curve -200 556 -195 556
+<-------EndPath
+Path 4 -1 0 -195 556
+Curve -85 549 26 542
+<-------EndPath
+Path 0 -1 0 -192 528
+Curve -192 524 -192 519
+<-------EndPath
+Path 0 -1 0 -288 493
+Curve -287 575 -278 657
+Curve -267 750 -268 843
+Curve -268 937 -283 1029
+Curve -299 1125 -314 1221
+Curve -326 1303 -354 1351
+<-------EndPath
+Path 0 4 0 -354 1351
+Curve -353 1352 -352 1352
+Curve -351 1353 -349 1353
+<-------EndPath
+Path 0 -1 0 -349 1353
+Curve -321 1311 -288 1240
+Curve -256 1169 -236 1075
+Curve -217 981 -224 897
+Curve -231 812 -214 725
+Curve -197 637 -195 556
+<-------EndPath
+Path 3 -1 0 -421 297
+Curve -424 373 -455 505
+<-------EndPath
+Path -1 4 0 -342 1354
+Curve -334 1367 -344 1372
+Curve -375 1379 -406 1385
+Curve -459 1392 -698 1350
+Curve -602 1334 -505 1318
+Curve -457 1306 -366 1346
+Curve -366 1346 -365 1346
+Curve -360 1349 -354 1351
+<-------EndPath
+Path 4 4 0 -354 1351
+Curve -359 1358 -363 1365
+<-------EndPath
+Path -1 4 0 -349 1353
+Curve -348 1354 -346 1354
+<-------EndPath
+Path -1 4 -1 -346 1354
+Curve -346 1357 -345 1360
+Curve -344 1357 -342 1354
+<-------EndPath
+Path -1 -1 0 -166 1345
+Curve -161 1323 -152 1306
+<-------EndPath
+Path -1 -1 0 -169 1359
+Curve -170 1364 -170 1368
+Curve -170 1368 -170 1367
+Curve -169 1363 -168 1358
+Curve -168 1356 -167 1354
+Curve -167 1350 -166 1345
+<-------EndPath
+Path 4 4 0 -176 1372
+Curve -176 1374 -176 1375
+<-------EndPath
+Path 4 -1 0 -170 1369
+Curve -171 1369 -171 1369
+<-------EndPath
+Path 4 -1 -1 -171 1369
+Curve -172 1370 -172 1370
+<-------EndPath
+Path 4 4 0 -172 1370
+Curve -173 1373 -174 1376
+<-------EndPath
+Path -1 -1 0 -171 1369
+Curve -171 1369 -170 1368
+Curve -171 1369 -171 1369
+<-------EndPath
+Path -1 -1 0 -170 1369
+Curve -170 1368 -170 1367
+<-------EndPath
+Path -1 -1 0 -165 1368
+Curve -166 1361 -167 1354
+<-------EndPath
+Path 4 4 0 26 530
+Curve -23 517 -22 494
+<-------EndPath
+!======EndShape
+=======BeginShape
+Path 0 19 0 1581 -1974
+Curve 1502 -2209 1742 -2358
+Curve 1886 -2447 1957 -2288
+Curve 1998 -2197 1999 -2124
+Curve 2011 -2548 2405 -2476
+Curve 2848 -2395 2498 -2129
+Curve 2777 -2211 2665 -1888
+Curve 2664 -1883 2662 -1878
+Curve 2661 -1876 2660 -1873
+Curve 2658 -1868 2656 -1862
+Curve 2655 -1860 2654 -1857
+Curve 2650 -1848 2645 -1839
+Curve 2645 -1838 2644 -1836
+Curve 2643 -1834 2642 -1832
+Curve 2641 -1830 2640 -1828
+Curve 2636 -1821 2632 -1813
+Curve 2632 -1812 2631 -1811
+Curve 2539 -1738 2447 -1665
+<-------EndPath
+Path 0 0 0 2447 -1665
+Curve 2443 -1664 2439 -1662
+<-------EndPath
+Path 0 2 -1 2439 -1662
+Curve 2752 -1649 3065 -1636
+<-------EndPath
+Path 0 19 0 3065 -1636
+Curve 3131 -1670 3228 -1671
+Curve 3306 -1887 3449 -1712
+<-------EndPath
+Path 0 3 0 3449 -1712
+Curve 3468 -1686 3487 -1660
+Curve 3475 -1782 3512 -1898
+<-------EndPath
+Path 0 19 0 3512 -1898
+Curve 3533 -1965 3571 -2030
+Curve 3579 -2042 3586 -2054
+Curve 3589 -2058 3591 -2062
+Curve 3665 -2175 3758 -2049
+Curve 3720 -2328 3880 -2277
+Curve 3963 -2250 4098 -2135
+<-------EndPath
+Path 0 -1 1 4098 -2135
+Curve 4098 -2470 4098 -2804
+<-------EndPath
+Path 0 2 -1 4098 -2804
+Curve 4019 -2812 3939 -2820
+Curve 3519 -2864 3098 -2907
+Curve 3101 -2908 3103 -2909
+Curve 3151 -2911 3198 -2912
+Curve 3657 -2921 4098 -2990
+<-------EndPath
+Path 0 -1 1 4098 -2990
+Curve 4098 -3040 4098 -3089
+Curve 147 -3089 -3805 -3089
+<-------EndPath
+Path 0 2 -1 -3805 -3089
+Curve -3986 -3039 -4161 -2972
+<-------EndPath
+Path 0 -1 1 -4161 -2972
+Curve -4161 -2567 -4161 -2161
+<-------EndPath
+Path 0 2 -1 -4161 -2161
+Curve -3659 -2058 -3147 -2006
+Curve -2519 -1950 -1890 -1893
+Curve -1890 -1894 -1890 -1895
+<-------EndPath
+Path 0 19 0 -1890 -1895
+Curve -1900 -1977 -1826 -2126
+Curve -1825 -2128 -1824 -2129
+Curve -1820 -2137 -1816 -2145
+Curve -1667 -2429 -1470 -2270
+Curve -1465 -2310 -1453 -2343
+<-------EndPath
+Path 0 2 -1 -1453 -2343
+Curve -1745 -2346 -2036 -2348
+Curve -2571 -2351 -3101 -2424
+Curve -2581 -2437 -2062 -2400
+Curve -1755 -2379 -1448 -2357
+<-------EndPath
+Path 0 19 0 -1448 -2357
+Curve -1363 -2558 -1000 -2471
+Curve -861 -2438 -755 -2399
+Curve -737 -2494 -681 -2512
+Curve -675 -2514 -668 -2515
+Curve -652 -2515 -635 -2514
+Curve -633 -2514 -631 -2514
+Curve -550 -2500 -419 -2383
+Curve -300 -2277 -444 -2174
+Curve -444 -2173 -443 -2171
+Curve -443 -2170 -442 -2169
+Curve -438 -2147 -433 -2125
+<-------EndPath
+Path 0 19 -1 -433 -2125
+Curve -433 -2122 -433 -2118
+<-------EndPath
+Path 0 19 0 -433 -2118
+Curve -432 -2049 -486 -1970
+Curve -222 -2104 -56 -2015
+Curve 7 -2282 213 -1989
+Curve 215 -1987 217 -1984
+Curve 245 -1943 254 -1899
+Curve 266 -1841 245 -1778
+<-------EndPath
+Path 0 2 -1 245 -1778
+Curve 242 -1769 238 -1760
+Curve 356 -1754 474 -1748
+<-------EndPath
+Path 0 19 0 474 -1748
+Curve 522 -2045 729 -2014
+<-------EndPath
+Path 0 3 0 729 -2014
+Curve 735 -2013 740 -2012
+<-------EndPath
+Path 0 19 0 740 -2012
+Curve 777 -2006 818 -1989
+Curve 790 -2016 762 -2043
+Curve 644 -2178 947 -2151
+<-------EndPath
+Path 0 19 -1 947 -2151
+Curve 995 -2146 1043 -2140
+<-------EndPath
+Path 0 19 0 1043 -2140
+Curve 1046 -2140 1049 -2139
+Curve 1063 -2137 1076 -2134
+<-------EndPath
+Path 0 3 -1 1076 -2134
+Curve 1089 -2132 1101 -2130
+Curve 1101 -2130 1101 -2129
+<-------EndPath
+Path 0 19 0 1101 -2129
+Curve 1121 -2125 1141 -2120
+Curve 1251 -2089 1311 -2026
+<-------EndPath
+Path 0 19 -1 1311 -2026
+Curve 1313 -2024 1315 -2021
+<-------EndPath
+Path 0 19 0 1315 -2021
+Curve 1331 -1999 1347 -1976
+Curve 1384 -1908 1377 -1812
+Curve 1487 -1853 1640 -1852
+Curve 1638 -1856 1636 -1859
+Curve 1635 -1861 1634 -1862
+Curve 1608 -1906 1591 -1947
+<-------EndPath
+Path 0 3 -1 1591 -1947
+Curve 1586 -1961 1581 -1974
+<-------EndPath
+Path 19 3 0 1581 -1974
+Curve 1586 -1961 1591 -1947
+<-------EndPath
+Path 2 0 -1 1708 -2594
+Curve 1093 -2637 478 -2679
+Curve 156 -2694 -167 -2709
+Curve -207 -2707 -247 -2704
+Curve -290 -2702 -332 -2699
+Curve 236 -2659 803 -2618
+Curve 1383 -2575 1962 -2531
+Curve 2563 -2494 3163 -2456
+Curve 3371 -2448 3578 -2439
+Curve 3176 -2478 2773 -2516
+Curve 2241 -2555 1708 -2594
+<-------EndPath
+Path 19 3 -1 740 -2012
+Curve 734 -2006 728 -1999
+Curve 729 -2007 729 -2014
+<-------EndPath
+Path 19 3 0 1101 -2129
+Curve 1089 -2132 1076 -2134
+<-------EndPath
+Path 19 2 0 474 -1748
+Curve 473 -1743 472 -1738
+Curve 415 -1365 738 -1429
+Curve 534 -1333 718 -1139
+Curve 719 -1139 719 -1138
+Curve 718 -1137 717 -1135
+Curve 711 -1126 705 -1117
+Curve 689 -1090 672 -1062
+Curve 545 -840 543 -590
+Curve 541 -383 624 -158
+Curve 524 -295 399 -355
+<-------EndPath
+Path 19 1 0 399 -355
+Curve 399 -355 398 -355
+<-------EndPath
+Path 19 3 -1 398 -355
+Curve 393 -354 387 -352
+Curve 387 -357 386 -361
+<-------EndPath
+Path 19 2 0 386 -361
+Curve 355 -372 324 -383
+Curve 266 -400 204 -402
+Curve 214 -411 224 -419
+Curve 262 -456 273 -490
+Curve 287 -539 246 -583
+Curve 211 -625 176 -666
+Curve -58 -969 126 -1182
+Curve 140 -1200 154 -1217
+Curve 155 -1219 156 -1220
+Curve 220 -1312 212 -1398
+Curve 198 -1540 171 -1650
+Curve 224 -1716 245 -1778
+<-------EndPath
+Path 3 2 0 399 -356
+Curve 393 -359 386 -361
+<-------EndPath
+Path 3 3 0 386 -361
+Curve 392 -358 398 -355
+<-------EndPath
+Path 3 1 -1 398 -355
+Curve 399 -356 399 -356
+<-------EndPath
+Path 2 1 -1 399 -356
+Curve 399 -356 399 -355
+<-------EndPath
+Path 2 2 0 224 -419
+Curve 274 -401 324 -383
+<-------EndPath
+Path 19 0 -1 2439 -1662
+Curve 2443 -1664 2447 -1665
+<-------EndPath
+Path 2 19 0 2439 -1662
+Curve 2409 -1656 2378 -1649
+Curve 2637 -1608 2442 -1372
+Curve 2507 -1167 2298 -1009
+Curve 2743 -710 2498 -209
+Curve 3135 -462 2987 -974
+Curve 2831 -1515 3065 -1636
+<-------EndPath
+Path -1 2 1 4098 -2990
+Curve 4098 -2897 4098 -2804
+<-------EndPath
+Path -1 19 1 4098 -1949
+Curve 4098 -1651 4098 -1352
+<-------EndPath
+Path -1 -1 0 4098 -1352
+Curve 4223 -1294 4098 -1249
+<-------EndPath
+Path -1 19 1 4098 -1249
+Curve 4098 -119 4098 1011
+<-------EndPath
+Path -1 11 1 4098 1011
+Curve 4098 1081 4098 1151
+<-------EndPath
+Path -1 8 1 4098 1151
+Curve 4098 1789 4098 2427
+<-------EndPath
+Path -1 -1 1 4098 2427
+Curve 4106 2427 4113 2427
+<-------EndPath
+Path -1 19 1 4098 -1352
+Curve 4098 -1301 4098 -1249
+<-------EndPath
+Path 2 3 0 3487 -1660
+Curve 3489 -1645 3491 -1629
+Curve 3501 -1626 3511 -1623
+Curve 3499 -1642 3487 -1660
+<-------EndPath
+Path 19 3 -1 3512 -1898
+Curve 3600 -1628 3566 -1406
+Curve 3561 -1375 3528 -1374
+Curve 3374 -1369 3406 -1535
+Curve 3424 -1625 3449 -1712
+<-------EndPath
+Path -1 19 0 4098 -2135
+Curve 4098 -2042 4098 -1949
+<-------EndPath
+Path 8 11 -1 3811 1475
+Curve 3814 1478 3817 1480
+Curve 3651 1490 3485 1499
+Curve 3457 1503 3429 1507
+Curve 3462 1510 3495 1513
+Curve 3694 1501 3879 1567
+Curve 3922 1582 3960 1603
+Curve 3971 1609 3977 1625
+Curve 3341 1710 2710 1662
+Curve 3286 1630 3861 1598
+Curve 3429 1501 2976 1518
+Curve 2976 1516 2976 1513
+Curve 3065 1507 3153 1501
+Curve 3347 1483 3540 1464
+Curve 3676 1470 3811 1475
+<-------EndPath
+Path 14 8 -1 4098 2450
+Curve 4096 2450 4094 2450
+Curve 3473 2429 2848 2413
+<-------EndPath
+Path 14 14 1 2848 2413
+Curve 2899 2466 2944 2532
+<-------EndPath
+Path 14 5 1 2944 2532
+Curve 2948 2538 2952 2544
+<-------EndPath
+Path 14 12 1 2952 2544
+Curve 3525 2559 4098 2574
+<-------EndPath
+Path 14 -1 1 4098 2574
+Curve 4098 2512 4098 2450
+<-------EndPath
+Path 8 -1 1 4098 2450
+Curve 4098 2439 4098 2427
+<-------EndPath
+Path 8 8 1 4098 2427
+Curve 1010 2339 -2078 2251
+Curve -2100 2262 -2122 2272
+<-------EndPath
+Path 8 15 -1 -2122 2272
+Curve -2087 2274 -2051 2275
+<-------EndPath
+Path 8 14 1 -2051 2275
+Curve -2028 2276 -2004 2277
+<-------EndPath
+Path 8 14 -1 -2004 2277
+Curve -1223 2303 -442 2328
+Curve -80 2338 283 2348
+<-------EndPath
+Path 8 14 1 283 2348
+Curve 287 2348 291 2348
+<-------EndPath
+Path 8 14 -1 291 2348
+Curve 715 2360 1138 2371
+Curve 1626 2383 2113 2395
+Curve 2481 2404 2848 2413
+<-------EndPath
+Path -1 -1 1 4098 2833
+Curve 4106 2833 4113 2833
+<-------EndPath
+Path -1 16 1 4098 2833
+Curve 4098 2840 4098 2846
+<-------EndPath
+Path -1 17 1 4098 2846
+Curve 4098 3683 4098 4519
+Curve -32 4519 -4161 4519
+Curve -4161 3607 -4161 2695
+<-------EndPath
+Path -1 16 1 -4161 2695
+Curve -4161 2635 -4161 2574
+<-------EndPath
+Path -1 12 1 -4161 2574
+Curve -4161 2468 -4161 2361
+<-------EndPath
+Path -1 13 1 -4161 2361
+Curve -4161 2277 -4161 2193
+<-------EndPath
+Path -1 8 1 -4161 2193
+Curve -4161 2193 -4161 2192
+Curve -4161 1994 -4161 1795
+<-------EndPath
+Path -1 9 1 -4161 1795
+Curve -4161 1745 -4161 1694
+<-------EndPath
+Path -1 8 1 -4161 1694
+Curve -4161 1403 -4161 1111
+<-------EndPath
+Path -1 11 1 -4161 1111
+Curve -4161 991 -4161 871
+<-------EndPath
+Path -1 19 1 -4161 871
+Curve -4161 171 -4161 -529
+<-------EndPath
+Path -1 0 1 -4161 -529
+Curve -4161 -609 -4161 -689
+<-------EndPath
+Path -1 2 1 -4161 -689
+Curve -4161 -1006 -4161 -1322
+<-------EndPath
+Path -1 0 1 -4161 -1322
+Curve -4161 -1515 -4161 -1708
+<-------EndPath
+Path -1 2 1 -4161 -1708
+Curve -4161 -1935 -4161 -2161
+<-------EndPath
+Path -1 12 1 4098 2574
+Curve 4098 2618 4098 2662
+<-------EndPath
+Path -1 -1 1 4098 2662
+Curve 4106 2662 4113 2662
+<-------EndPath
+Path -1 12 1 4098 2662
+Curve 4098 2704 4098 2745
+<-------EndPath
+Path -1 16 1 4098 2745
+Curve 4098 2789 4098 2833
+<-------EndPath
+Path 16 17 -1 -1748 2624
+Curve -1748 2637 -1748 2650
+Curve -2089 2950 -2154 2993
+Curve -2220 3036 -1836 3056
+Curve -1387 3085 -937 3113
+Curve -422 3150 136 3135
+Curve 693 3119 1028 3145
+Curve 1363 3170 1454 3139
+Curve 1545 3108 1693 2941
+Curve 1840 2773 2055 2789
+Curve 2269 2804 1898 2769
+Curve 2454 2780 2621 2776
+Curve 2765 2772 2908 2768
+Curve 2910 2768 2912 2768
+Curve 2942 2767 2972 2766
+Curve 2980 2766 2988 2766
+Curve 3077 2762 3166 2758
+Curve 3299 2752 3431 2761
+Curve 3563 2769 3695 2792
+Curve 3897 2819 4098 2846
+<-------EndPath
+Path 8 11 -1 2179 1609
+Curve 2117 1617 2054 1625
+Curve 1711 1696 1383 1609
+Curve 1376 1600 1368 1591
+Curve 1365 1584 1361 1577
+Curve 1362 1573 1362 1568
+Curve 1445 1554 1527 1539
+Curve 1070 1456 603 1470
+Curve 418 1475 232 1480
+Curve 239 1474 245 1467
+Curve 260 1456 277 1450
+Curve 282 1448 286 1446
+Curve 287 1445 288 1443
+Curve 877 1436 1460 1505
+Curve 1543 1517 1626 1529
+Curve 1623 1534 1619 1538
+Curve 1506 1572 1388 1582
+Curve 1438 1588 1488 1594
+Curve 1798 1601 2106 1580
+Curve 2152 1576 2179 1609
+<-------EndPath
+Path 10 8 -1 2389 1389
+Curve 2466 1390 2543 1391
+Curve 2466 1388 2388 1384
+Curve 1761 1373 1133 1371
+Curve 1686 1392 2238 1389
+Curve 2314 1389 2389 1389
+<-------EndPath
+Path 11 4 -1 685 954
+Curve 685 957 685 959
+<-------EndPath
+Path 11 7 0 685 959
+Curve 682 959 679 959
+<-------EndPath
+Path 11 19 0 679 959
+Curve -310 940 -1298 920
+<-------EndPath
+Path 11 7 0 -1298 920
+Curve -1308 920 -1318 919
+<-------EndPath
+Path 11 4 -1 -1318 919
+Curve -1318 919 -1318 918
+<-------EndPath
+Path 11 19 0 -1318 918
+Curve -2740 895 -4161 871
+<-------EndPath
+Path 7 4 -1 685 959
+Curve 682 959 679 959
+<-------EndPath
+Path 19 4 -1 679 959
+Curve 680 957 680 954
+<-------EndPath
+Path 19 4 0 680 954
+Curve 683 954 685 954
+<-------EndPath
+Path 19 11 0 685 954
+Curve 2392 983 4098 1011
+<-------EndPath
+Path 8 4 -1 649 1140
+Curve 653 1140 656 1140
+Curve 653 1140 649 1140
+<-------EndPath
+Path 8 11 -1 649 1140
+Curve -145 1134 -938 1128
+<-------EndPath
+Path 8 6 -1 -938 1128
+Curve -943 1128 -947 1128
+<-------EndPath
+Path 8 11 -1 -947 1128
+Curve -1155 1127 -1363 1125
+<-------EndPath
+Path 8 4 -1 -1363 1125
+Curve -1374 1125 -1384 1125
+Curve -1384 1125 -1384 1124
+<-------EndPath
+Path 8 11 -1 -1384 1124
+Curve -2773 1118 -4161 1111
+<-------EndPath
+Path 8 11 -1 642 1208
+Curve 757 1186 851 1246
+Curve 863 1254 874 1261
+Curve 863 1264 852 1267
+Curve 479 1212 92 1278
+Curve 63 1278 33 1277
+Curve 246 1252 459 1226
+Curve 551 1217 642 1208
+<-------EndPath
+Path 11 8 -1 649 1140
+Curve 649 1138 649 1135
+Curve 2374 1143 4098 1151
+<-------EndPath
+Path 9 8 -1 -4161 1795
+Curve -3724 1814 -3286 1832
+Curve -2756 1853 -2226 1873
+Curve -1943 1883 -1660 1892
+Curve -1374 1902 -1087 1911
+Curve -960 1916 -833 1920
+Curve -475 1929 -117 1937
+Curve 24 1940 164 1942
+Curve 716 1954 1268 1966
+Curve 1273 1966 1277 1966
+Curve 1760 1988 2243 2010
+Curve 2590 2032 2948 2031
+Curve 2113 1950 1278 1940
+Curve 1273 1940 1268 1940
+Curve 716 1914 164 1888
+Curve -334 1860 -832 1831
+Curve -1245 1810 -1657 1788
+Curve -2049 1766 -2441 1744
+Curve -3131 1717 -3821 1706
+Curve -3989 1700 -4157 1694
+Curve -4159 1694 -4161 1694
+<-------EndPath
+Path 14 14 1 283 2348
+Curve 247 2390 258 2468
+Curve 257 2472 255 2475
+<-------EndPath
+Path 14 12 1 255 2475
+Curve 1599 2510 2942 2544
+<-------EndPath
+Path 14 5 1 2942 2544
+Curve 2943 2538 2944 2532
+<-------EndPath
+Path 16 16 1 223 2665
+Curve 223 2673 223 2681
+<-------EndPath
+Path 12 12 1 223 2665
+Curve 219 2554 255 2475
+<-------EndPath
+Path 12 14 1 255 2475
+Curve -997 2443 -2249 2410
+<-------EndPath
+Path 12 5 1 -2249 2410
+Curve -2253 2416 -2256 2422
+<-------EndPath
+Path 12 15 1 -2256 2422
+Curve -2250 2503 -2244 2584
+<-------EndPath
+Path 12 16 1 -2244 2584
+Curve -2244 2599 -2243 2614
+Curve -2054 2618 -1864 2622
+<-------EndPath
+Path 12 17 1 -1864 2622
+Curve -1806 2623 -1748 2624
+<-------EndPath
+Path 12 16 1 -1748 2624
+Curve -1712 2625 -1676 2626
+<-------EndPath
+Path 12 5 1 -1676 2626
+Curve -1664 2626 -1651 2626
+<-------EndPath
+Path 12 16 1 -1651 2626
+Curve -714 2646 223 2665
+Curve 1287 2687 2350 2709
+<-------EndPath
+Path 12 12 1 2350 2709
+Curve 2370 2690 2390 2671
+<-------EndPath
+Path 5 8 -1 2963 2038
+Curve 3003 2040 3043 2041
+Curve 3018 2039 2993 2036
+Curve 2978 2036 2963 2036
+Curve 2963 2037 2963 2038
+<-------EndPath
+Path 12 12 1 2942 2544
+Curve 2941 2552 2940 2560
+<-------EndPath
+Path 12 15 1 2940 2560
+Curve 2972 2620 2983 2706
+<-------EndPath
+Path 12 5 1 2983 2706
+Curve 2984 2714 2984 2722
+<-------EndPath
+Path 12 16 1 2984 2722
+Curve 3541 2734 4098 2745
+<-------EndPath
+Path 5 12 1 2942 2544
+Curve 2947 2544 2952 2544
+<-------EndPath
+Path 16 15 -1 2925 2698
+Curve 2920 2697 2915 2696
+<-------EndPath
+Path 16 12 1 2915 2696
+Curve 2914 2701 2912 2705
+Curve 2910 2713 2908 2720
+<-------EndPath
+Path 16 16 1 2908 2720
+Curve 2908 2728 2908 2736
+<-------EndPath
+Path 16 15 1 2938 2711
+Curve 2933 2706 2927 2701
+Curve 2926 2700 2925 2698
+<-------EndPath
+Path 5 15 -1 2983 2706
+Curve 2965 2710 2947 2713
+Curve 2943 2712 2938 2711
+<-------EndPath
+Path 5 16 1 2938 2711
+Curve 2940 2713 2941 2714
+Curve 2946 2718 2950 2721
+Curve 2961 2728 2971 2735
+<-------EndPath
+Path 5 16 -1 2971 2735
+Curve 2978 2729 2984 2722
+<-------EndPath
+Path 16 16 1 2984 2722
+Curve 2985 2729 2985 2735
+<-------EndPath
+Path 15 12 1 2940 2560
+Curve 2931 2634 2915 2696
+<-------EndPath
+Path 12 16 1 2350 2709
+Curve 2629 2715 2908 2720
+<-------EndPath
+Path -1 2 1 -4161 -2972
+Curve -4161 -3031 -4161 -3089
+Curve -3983 -3089 -3805 -3089
+<-------EndPath
+Path 2 19 0 -3530 -1596
+Curve -3478 -1603 -3429 -1577
+<-------EndPath
+Path 2 0 -1 -3429 -1577
+Curve -3416 -1574 -3403 -1571
+<-------EndPath
+Path 2 19 0 -3403 -1571
+Curve -3473 -1743 -3153 -1823
+Curve -2750 -1924 -2803 -1637
+Curve -2812 -1573 -2821 -1509
+Curve -2666 -1432 -2613 -1335
+<-------EndPath
+Path 2 0 -1 -2613 -1335
+Curve -2391 -1239 -2254 -1045
+Curve -2089 -812 -2297 -616
+Curve -2365 -551 -2444 -507
+<-------EndPath
+Path 2 19 0 -2444 -507
+Curve -2454 -389 -2534 -240
+Curve -1946 -188 -2238 48
+Curve -2331 123 -2378 174
+Curve -2470 272 -2392 279
+Curve -2418 243 -2261 241
+Curve -2099 239 -1921 -78
+Curve -1862 -183 -1784 -212
+Curve -1628 -272 -1394 -24
+<-------EndPath
+Path 2 2 0 -1394 -24
+Curve -1394 -24 -1393 -24
+<-------EndPath
+Path 2 19 0 -1393 -24
+Curve -1504 -211 -1521 -331
+Curve -1544 -493 -1400 -533
+Curve -1400 -534 -1399 -534
+Curve -1349 -541 -1299 -547
+Curve -1343 -566 -1386 -585
+Curve -1396 -589 -1405 -593
+Curve -2072 -899 -1557 -1459
+Curve -1495 -1521 -1433 -1582
+Curve -1385 -1626 -1322 -1629
+Curve -1372 -1752 -1406 -1857
+<-------EndPath
+Path 2 0 -1 -1406 -1857
+Curve -1408 -1858 -1410 -1858
+<-------EndPath
+Path 2 19 0 -1410 -1858
+Curve -1489 -1838 -1568 -1817
+Curve -1873 -1743 -1890 -1895
+<-------EndPath
+Path 0 2 -1 -3530 -1596
+Curve -3526 -1597 -3521 -1597
+Curve -3599 -1612 -3676 -1627
+Curve -3919 -1668 -4161 -1708
+<-------EndPath
+Path 0 19 0 -3429 -1577
+Curve -3414 -1568 -3399 -1558
+Curve -3398 -1557 -3396 -1556
+Curve -3400 -1564 -3403 -1571
+<-------EndPath
+Path 19 0 0 -3530 -1596
+Curve -3671 -1478 -3811 -1360
+Curve -3813 -1358 -3814 -1355
+Curve -3819 -1349 -3823 -1342
+Curve -3840 -1316 -3857 -1290
+<-------EndPath
+Path 19 0 -1 -3857 -1290
+Curve -3862 -1282 -3867 -1273
+Curve -3868 -1273 -3868 -1273
+<-------EndPath
+Path 19 2 0 -3868 -1273
+Curve -3881 -1252 -3894 -1230
+<-------EndPath
+Path 19 3 -1 -3894 -1230
+Curve -3891 -1236 -3887 -1241
+Curve -3754 -1209 -3622 -1166
+Curve -3609 -1162 -3596 -1154
+Curve -3592 -1147 -3588 -1139
+Curve -3582 -1117 -3575 -1094
+Curve -3571 -1071 -3581 -1049
+Curve -3584 -1042 -3586 -1034
+Curve -3729 -957 -3899 -998
+Curve -3948 -1006 -3996 -1013
+Curve -4003 -1014 -4009 -1014
+<-------EndPath
+Path 19 2 0 -4009 -1014
+Curve -4084 -854 -4125 -697
+<-------EndPath
+Path 19 0 0 -4125 -697
+Curve -4148 -613 -4161 -529
+<-------EndPath
+Path 0 0 0 -3868 -1273
+Curve -3863 -1282 -3857 -1290
+<-------EndPath
+Path 2 3 0 -4009 -1014
+Curve -3952 -1122 -3894 -1230
+<-------EndPath
+Path 2 0 -1 -3868 -1273
+Curve -3963 -1290 -4057 -1306
+Curve -4109 -1314 -4161 -1322
+<-------EndPath
+Path 2 0 -1 -4161 -689
+Curve -4159 -690 -4157 -691
+Curve -4147 -694 -4136 -697
+Curve -4131 -697 -4125 -697
+<-------EndPath
+Path 2 19 0 -1453 -2343
+Curve -1451 -2350 -1448 -2357
+<-------EndPath
+Path 19 3 -1 -622 -1984
+Curve -620 -1989 -618 -1993
+Curve -616 -1993 -614 -1992
+Curve -617 -1989 -619 -1986
+Curve -621 -1985 -622 -1984
+<-------EndPath
+Path 2 0 -1 -2656 -841
+Curve -2631 -853 -2606 -864
+Curve -2610 -870 -2614 -875
+Curve -2672 -908 -2730 -941
+<-------EndPath
+Path 2 19 0 -2730 -941
+Curve -2756 -915 -2781 -889
+Curve -2711 -868 -2656 -841
+<-------EndPath
+Path 0 19 0 -2656 -841
+Curve -2426 -730 -2444 -507
+<-------EndPath
+Path 0 19 0 -2613 -1335
+Curve -2521 -1168 -2730 -941
+<-------EndPath
+Path 19 2 0 -486 -1970
+Curve -484 -1960 -482 -1949
+Curve -542 -1929 -562 -1929
+Curve -536 -1944 -510 -1958
+Curve -504 -1962 -497 -1965
+Curve -492 -1968 -486 -1970
+<-------EndPath
+Path 19 0 0 -1410 -1858
+Curve -1408 -1859 -1406 -1859
+Curve -1406 -1858 -1406 -1857
+<-------EndPath
+Path -1 19 -1 -1241 -1614
+Curve -1243 -1613 -1244 -1612
+Curve -1244 -1610 -1243 -1608
+Curve -1224 -1527 -1204 -1445
+<-------EndPath
+Path -1 19 0 -1204 -1445
+Curve -1222 -1525 -1239 -1605
+Curve -1240 -1607 -1240 -1608
+Curve -1241 -1611 -1241 -1614
+<-------EndPath
+Path 19 3 -1 -1399 -531
+Curve -1400 -532 -1400 -533
+Curve -1400 -533 -1399 -533
+Curve -1399 -532 -1399 -531
+<-------EndPath
+Path 2 19 0 -1394 -24
+Curve -1390 -17 -1385 -10
+Curve -1389 -17 -1393 -24
+<-------EndPath
+Path 19 18 0 -559 926
+Curve -642 159 -679 32
+Curve -731 -154 -694 -336
+Curve -656 -521 -676 -711
+Curve -694 -878 -732 -1041
+Curve -706 -975 -674 -917
+Curve -592 -771 -604 -570
+Curve -614 -384 -601 -199
+Curve -488 -197 -417 -253
+Curve -480 -184 -543 -114
+Curve -671 37 -555 204
+Curve -513 264 -422 929
+<-------EndPath
+Path 19 18 -1 -422 929
+Curve -491 928 -559 926
+<-------EndPath
+Path 7 19 0 -1298 918
+Curve -1308 918 -1318 918
+<-------EndPath
+Path 7 4 -1 -1318 918
+Curve -1318 919 -1318 919
+<-------EndPath
+Path 7 19 -1 -1298 920
+Curve -1298 919 -1298 918
+<-------EndPath
+Path 11 6 -1 -947 1128
+Curve -947 1128 -946 1127
+Curve -942 1128 -938 1128
+<-------EndPath
+Path 4 11 -1 -1363 1125
+Curve -1374 1125 -1384 1124
+<-------EndPath
+Path 8 11 -1 -2987 1315
+Curve -2383 1326 -1787 1411
+Curve -1784 1414 -1781 1416
+Curve -1787 1418 -1792 1420
+Curve -1958 1434 -2124 1448
+Curve -1281 1432 -454 1438
+Curve -1393 1537 -2290 1443
+Curve -2290 1439 -2289 1435
+Curve -2190 1423 -2091 1411
+Curve -2705 1293 -3328 1384
+Curve -3404 1398 -3479 1411
+Curve -3488 1418 -3497 1425
+Curve -3508 1432 -3518 1438
+Curve -3521 1434 -3523 1430
+Curve -3513 1411 -3496 1395
+Curve -3491 1390 -3485 1384
+Curve -3398 1371 -3311 1358
+Curve -3177 1342 -3042 1325
+Curve -3015 1320 -2987 1315
+<-------EndPath
+Path 5 15 1 -2249 2410
+Curve -2253 2410 -2257 2410
+Curve -2257 2416 -2256 2422
+<-------EndPath
+Path 5 12 1 -2325 2409
+Curve -2325 2410 -2324 2410
+<-------EndPath
+Path 5 15 1 -2324 2410
+Curve -2324 2410 -2323 2409
+<-------EndPath
+Path 5 13 1 -2323 2409
+Curve -2324 2409 -2325 2409
+<-------EndPath
+Path 12 13 1 -2325 2409
+Curve -3243 2385 -4161 2361
+<-------EndPath
+Path 12 12 1 -2341 2424
+Curve -2333 2417 -2324 2410
+<-------EndPath
+Path 15 12 1 -2324 2410
+Curve -2302 2501 -2299 2613
+<-------EndPath
+Path 15 5 1 -2299 2613
+Curve -2299 2617 -2299 2621
+<-------EndPath
+Path 15 16 1 -2299 2621
+Curve -2277 2607 -2254 2593
+Curve -2249 2589 -2244 2584
+<-------EndPath
+Path 14 15 1 -2051 2275
+Curve -2179 2298 -2249 2410
+<-------EndPath
+Path 13 8 -1 -2122 2272
+Curve -2239 2267 -2356 2262
+Curve -3254 2228 -4151 2193
+Curve -4156 2193 -4161 2193
+<-------EndPath
+Path 15 13 1 -2122 2272
+Curve -2226 2323 -2323 2409
+<-------EndPath
+Path 5 16 1 -2301 2622
+Curve -2300 2622 -2299 2621
+<-------EndPath
+Path 16 5 -1 -2301 2622
+Curve -2301 2618 -2301 2613
+<-------EndPath
+Path 16 12 1 -2301 2613
+Curve -3231 2594 -4161 2574
+<-------EndPath
+Path 16 16 1 -2313 2627
+Curve -2307 2625 -2301 2622
+<-------EndPath
+Path 16 17 -1 -4161 2695
+Curve -4155 2695 -4149 2695
+Curve -3901 2646 -3630 2650
+Curve -3371 2660 -3111 2669
+Curve -2841 2686 -2565 2684
+Curve -2438 2679 -2310 2673
+Curve -2303 2673 -2296 2672
+Curve -2161 2656 -2026 2639
+Curve -1945 2631 -1864 2622
+<-------EndPath
+Path 5 12 1 -2299 2613
+Curve -2300 2613 -2301 2613
+<-------EndPath
+Path 16 5 -1 -1651 2626
+Curve -1651 2627 -1651 2628
+<-------EndPath
+Path 16 5 1 -1651 2628
+Curve -1664 2627 -1676 2626
+<-------EndPath
+Path 8 8 1 -2078 2251
+Curve -3120 2222 -4161 2192
+<-------EndPath
+!======EndShape
+=======BeginShape
+Path 2 0 -1 169 -1261
+Curve 341 -1240 513 -1218
+Curve 497 -944 352 -711
+Curve 403 -692 453 -673
+Curve 516 -719 578 -765
+Curve 904 -584 962 -215
+Curve 1013 -322 1064 -428
+Curve 1059 -804 685 -827
+Curve 659 -827 633 -827
+Curve 835 -1201 499 -1314
+Curve 353 -1363 202 -1319
+Curve 186 -1290 169 -1261
+<-------EndPath
+Path 0 0 0 37 -1420
+Curve 16 -1345 4 -1268
+<-------EndPath
+Path 0 -1 0 1122 -438
+Curve 1441 -514 1294 -999
+Curve 1150 -1470 784 -1308
+Curve 1009 -1495 741 -1765
+Curve 378 -2131 134 -1663
+Curve 72 -1544 37 -1420
+Curve 75 -1720 -121 -1957
+Curve -484 -2397 -636 -1928
+Curve -598 -2186 -919 -2298
+Curve -1502 -2501 -1375 -2063
+Curve -1352 -1982 -1236 -2008
+Curve -1504 -1922 -1439 -1587
+Curve -1386 -1318 -1055 -1274
+Curve -1009 -1271 -962 -1268
+Curve -1252 -1264 -1341 -918
+Curve -1457 -471 -916 -464
+Curve -911 -464 -906 -464
+Curve -821 -476 -736 -488
+Curve -816 -464 -906 -464
+Curve -1229 -389 -1064 -125
+Curve -987 -2 -796 6
+Curve -656 9 -516 12
+Curve -721 106 -902 364
+Curve -1208 800 -677 768
+Curve -588 762 -496 732
+Curve -462 676 -482 614
+Curve -402 604 -386 569
+<-------EndPath
+Path 0 1 0 -386 569
+Curve -386 551 -386 533
+Curve -383 228 -379 -77
+Curve -372 -518 -610 -1384
+<-------EndPath
+Path 0 0 0 -610 -1384
+Curve -631 -1438 -652 -1491
+<-------EndPath
+Path 0 -1 0 -112 476
+Curve -246 948 237 891
+Curve 384 874 415 798
+Curve 394 752 404 672
+Curve 435 748 415 798
+Curve 472 928 773 788
+Curve 1268 558 864 292
+Curve 1317 342 1430 -88
+Curve 1538 -498 1122 -438
+<-------EndPath
+Path 0 0 0 1122 -438
+Curve 1093 -433 1064 -428
+<-------EndPath
+Path 1 0 0 -112 476
+Curve -66 416 -9 366
+Curve 229 158 404 -68
+Curve 165 67 -132 200
+Curve -224 -29 -1 -347
+Curve -132 -191 -176 -189
+Curve -309 -298 -314 -455
+Curve -319 -612 -610 -1384
+<-------EndPath
+Path -1 1 0 -112 476
+Curve -264 672 -294 970
+Curve -296 990 -298 1010
+Curve -298 1013 -297 1015
+Curve -260 1332 -237 1732
+Curve -213 2143 -43 2262
+<-------EndPath
+Path -1 1 -1 -43 2262
+Curve -72 2290 -101 2317
+<-------EndPath
+Path -1 1 0 -101 2317
+Curve -334 2016 -385 2362
+Curve -459 2097 -732 2350
+Curve -734 2352 -736 2354
+<-------EndPath
+Path -1 1 -1 -736 2354
+Curve -808 2333 -880 2312
+<-------EndPath
+Path -1 1 0 -880 2312
+Curve -487 2266 -437 1890
+Curve -428 1820 -412 1756
+Curve -408 1724 -403 1692
+Curve -362 1354 -542 1137
+Curve -385 1139 -386 751
+Curve -386 660 -386 569
+<-------EndPath
+Path 0 0 0 123 -504
+Curve 61 -426 -1 -347
+<-------EndPath
+!======EndShape
+=======BeginShape
+Path 1 0 -1 -2346 -172
+Curve -2562 -273 -2770 -361
+Curve -2463 -421 -2134 -470
+Curve -2091 -477 -2048 -483
+Curve -1930 -500 -1827 -542
+Curve -1798 -554 -1769 -566
+Curve -1767 -567 -1764 -568
+Curve -1615 -636 -1488 -731
+Curve -1353 -833 -1139 -880
+Curve -1110 -886 -1080 -892
+Curve -850 -941 -608 -965
+Curve -520 -973 -432 -980
+Curve -466 -1266 -306 -1278
+Curve -282 -1277 -257 -1276
+Curve -224 -1268 -191 -1260
+Curve -5 -1226 181 -1192
+Curve 192 -1190 202 -1188
+Curve 357 -1162 511 -1135
+Curve 624 -1116 737 -1096
+Curve 953 -1058 1169 -1020
+Curve 982 -910 1234 -866
+Curve 1244 -865 1253 -863
+Curve 1260 -862 1266 -861
+Curve 1927 -759 2569 -560
+Curve 2337 -484 1974 -484
+Curve 1814 -491 1653 -498
+Curve 1694 -393 1756 -308
+<-------EndPath
+Path 1 -1 -1 1756 -308
+Curve 1702 -421 1973 -406
+Curve 2268 -393 2562 -380
+Curve 2689 -376 2816 -371
+Curve 3308 -356 2831 -630
+Curve 2711 -653 2591 -675
+Curve 1765 -829 1270 -889
+Curve 1258 -891 1246 -893
+Curve 1244 -894 1241 -894
+Curve 1239 -895 1236 -896
+Curve 1196 -907 1166 -933
+Curve 1181 -933 1195 -932
+Curve 1206 -932 1216 -932
+Curve 1219 -932 1222 -932
+Curve 1247 -932 1272 -932
+Curve 2042 -934 1480 -1038
+Curve 1338 -1066 1195 -1094
+Curve 1195 -1095 1194 -1095
+Curve 1194 -1095 1193 -1095
+Curve 970 -1126 747 -1156
+Curve 633 -1173 519 -1190
+Curve 408 -1211 303 -1241
+Curve 260 -1255 217 -1268
+Curve 35 -1328 -209 -1326
+Curve -232 -1329 -254 -1331
+Curve -279 -1332 -304 -1333
+Curve -306 -1333 -307 -1333
+Curve -309 -1333 -310 -1333
+Curve -554 -1329 -554 -1103
+Curve -554 -1062 -588 -1049
+Curve -602 -1047 -615 -1044
+Curve -858 -1020 -1100 -996
+Curve -1346 -966 -1590 -900
+Curve -1978 -795 -1689 -636
+Curve -1727 -608 -1774 -587
+Curve -1776 -586 -1777 -585
+Curve -1887 -539 -2047 -534
+Curve -2096 -535 -2144 -535
+Curve -2405 -547 -2788 -477
+Curve -2790 -477 -2792 -476
+Curve -2855 -464 -2918 -451
+Curve -3263 -381 -2796 -264
+Curve -2795 -264 -2793 -263
+Curve -2623 -221 -2346 -172
+<-------EndPath
+Path 0 -1 -1 -2346 -172
+Curve -2345 -172 -2343 -172
+Curve -2033 -107 -2095 -52
+<-------EndPath
+Path 0 1 -1 -2095 -52
+Curve -2003 -6 -1910 40
+Curve -1932 50 -1953 60
+Curve -2279 203 -2692 237
+Curve -2788 245 -2830 300
+Curve -2424 429 -2012 571
+Curve -2013 575 -2014 578
+<-------EndPath
+Path 0 -1 -1 -2014 578
+Curve -1868 624 -1725 678
+Curve -1582 731 -1442 792
+<-------EndPath
+Path 0 1 -1 -1442 792
+Curve -1439 784 -1436 775
+Curve -1436 775 -1435 775
+Curve -1277 833 -1150 920
+Curve -1320 959 -1490 998
+Curve -1331 1027 -1171 1056
+Curve -750 1124 -305 1162
+Curve -97 1176 111 1190
+Curve 802 1231 1492 1271
+Curve 1522 1272 1552 1272
+Curve 1745 1262 1737 1081
+Curve 1728 896 1863 797
+Curve 1866 795 1869 793
+Curve 1964 726 2129 700
+Curve 1693 627 1309 386
+Curve 1307 384 1304 382
+Curve 1189 310 1079 222
+Curve 919 96 1073 -4
+Curve 1129 -40 1209 -40
+Curve 1347 -41 1484 -41
+Curve 1514 -41 1543 -41
+Curve 1816 -41 2089 -40
+Curve 1931 -111 1820 -229
+<-------EndPath
+Path 0 -1 -1 1820 -229
+Curve 1818 -230 1815 -231
+Curve 1771 -275 1756 -308
+<-------EndPath
+Path 2 0 -1 -221 -1046
+Curve -188 -987 -196 -959
+Curve -303 -930 -410 -901
+Curve -545 -872 -680 -843
+Curve -886 -802 -1204 -752
+Curve -1523 -703 -1285 -643
+Curve -1047 -584 -1061 -566
+Curve -1075 -549 -1126 -544
+Curve -1137 -543 -1148 -541
+Curve -1444 -508 -1716 -408
+Curve -1742 -399 -1768 -389
+Curve -1835 -363 -2400 -353
+Curve -1678 -237 -1465 -83
+Curve -1380 -21 -1777 49
+Curve -1513 71 -1677 167
+Curve -1810 200 -1877 235
+Curve -2172 383 -1252 558
+Curve -416 717 420 875
+Curve 960 977 1356 950
+Curve 1371 949 1386 947
+Curve 1466 940 1352 832
+Curve 1164 652 948 508
+Curve 945 506 941 504
+Curve 939 503 937 501
+Curve 778 394 618 286
+Curve 508 209 663 101
+Curve 818 -8 576 -109
+Curve 334 -211 1566 -206
+Curve 768 -367 698 -456
+Curve 628 -545 698 -588
+Curve 768 -631 1737 -608
+Curve 792 -845 459 -915
+Curve 451 -917 443 -918
+Curve 423 -922 407 -929
+Curve 347 -954 339 -1022
+Curve 293 -1044 248 -1056
+Curve 215 -1062 181 -1068
+Curve 81 -1078 -13 -1038
+Curve -117 -1042 -221 -1046
+<-------EndPath
+Path 3 2 -1 327 -831
+Curve 326 -832 325 -832
+Curve 3 -847 -320 -861
+Curve 174 -629 494 -672
+Curve 465 -783 374 -825
+Curve 351 -828 327 -831
+<-------EndPath
+Path 3 2 -1 72 -651
+Curve -134 -664 -339 -676
+Curve -360 -677 -380 -678
+Curve -570 -688 -764 -653
+Curve -937 -621 -1045 -545
+Curve -1101 -506 -1139 -455
+Curve -1052 -340 -1256 -311
+Curve -1563 -266 -1410 -159
+Curve -1322 -98 -1178 -28
+Curve -1035 41 -1084 285
+Curve -1133 528 -704 444
+Curve -275 360 -222 364
+Curve 617 398 117 132
+Curve -383 -134 -148 -197
+Curve 87 -260 207 -308
+Curve 326 -356 -240 -516
+Curve -181 -545 -177 -565
+Curve -193 -641 72 -651
+<-------EndPath
+Path 1 -1 -1 -1442 792
+Curve -1369 825 -1296 858
+Curve -3128 1002 -597 1231
+Curve -455 1244 -313 1256
+Curve -313 1256 -312 1256
+Curve 930 1360 1495 1326
+Curve 1497 1326 1498 1326
+Curve 1506 1326 1513 1325
+Curve 1535 1324 1556 1322
+Curve 1952 1291 1965 1182
+Curve 1750 1034 1857 876
+Curve 1873 853 1897 839
+Curve 1921 824 1954 819
+Curve 2067 799 2152 760
+Curve 2154 759 2155 758
+Curve 2156 758 2156 758
+Curve 2159 757 2161 756
+Curve 2194 737 2227 717
+Curve 2750 595 2170 492
+Curve 1590 388 1384 261
+Curve 1177 133 1351 85
+Curve 1400 71 1484 69
+Curve 1514 70 1543 70
+Curve 1733 74 2061 126
+Curve 2098 132 2135 138
+Curve 2744 240 2450 23
+Curve 2286 -47 2121 -117
+Curve 2121 -117 2120 -117
+Curve 1938 -191 1820 -229
+<-------EndPath
+Path 1 -1 -1 -2095 -52
+Curve -2145 -10 -2427 27
+Curve -2627 52 -2744 92
+Curve -3005 179 -2865 336
+Curve -2820 362 -2774 387
+Curve -2383 460 -2014 578
+<-------EndPath
+Path 3 2 -1 904 665
+Curve 882 647 860 628
+Curve 785 579 655 573
+Curve -140 417 -98 600
+Curve 425 659 725 757
+Curve 1024 854 899 787
+Curve 773 719 821 701
+Curve 863 683 904 665
+<-------EndPath
+!======EndShape
+=======BeginShape
+Path 8 -1 0 1430 206
+Curve 1424 200 1417 193
+Curve 1287 69 1071 90
+Curve 1112 65 1093 -21
+Curve 980 -90 909 -81
+Curve 943 -133 904 -183
+Curve 861 -238 822 -211
+Curve 901 -289 825 -368
+Curve 730 -466 589 -455
+Curve 638 -488 629 -546
+Curve 601 -725 411 -722
+Curve 208 -719 141 -602
+Curve 148 -787 -35 -732
+Curve -188 -687 -250 -556
+Curve -306 -552 -337 -511
+Curve -358 -482 -364 -447
+<-------EndPath
+Path 8 7 0 -364 -447
+Curve -365 -440 -366 -432
+<-------EndPath
+Path 8 7 -1 -366 -432
+Curve -359 -431 -351 -430
+Curve -350 -433 -348 -435
+Curve -312 -494 -235 -513
+Curve -153 -533 -86 -484
+Curve -67 -467 -48 -450
+Curve -46 -486 -44 -522
+Curve -35 -581 24 -582
+Curve 79 -583 110 -553
+Curve 140 -523 146 -462
+Curve 187 -506 254 -530
+Curve 340 -561 428 -529
+Curve 492 -505 489 -450
+Curve 485 -431 480 -411
+Curve 462 -371 443 -330
+Curve 445 -332 447 -333
+Curve 458 -319 469 -304
+<-------EndPath
+Path 8 7 0 469 -304
+Curve 549 -326 588 -246
+Curve 616 -186 560 -147
+Curve 650 -142 725 -86
+Curve 744 -69 762 -51
+<-------EndPath
+Path 8 7 -1 762 -51
+Curve 766 -55 770 -59
+Curve 809 -58 847 -56
+Curve 864 -50 877 -40
+Curve 896 -25 904 1
+Curve 920 50 905 88
+Curve 899 101 892 113
+Curve 915 109 937 104
+Curve 997 101 1040 141
+Curve 1110 208 1077 304
+Curve 1117 268 1184 233
+Curve 1249 198 1319 190
+Curve 1364 184 1380 220
+Curve 1392 214 1403 207
+Curve 1411 205 1418 203
+Curve 1424 205 1430 206
+<-------EndPath
+Path -1 7 -1 1430 206
+Curve 1431 206 1431 206
+<-------EndPath
+Path -1 7 0 1431 206
+Curve 1436 212 1441 217
+Curve 1478 258 1507 312
+<-------EndPath
+Path -1 3 0 1507 312
+Curve 1541 375 1475 407
+Curve 1475 408 1474 408
+<-------EndPath
+Path -1 7 0 1474 408
+Curve 1507 425 1522 465
+Curve 1526 481 1529 497
+Curve 1541 583 1483 602
+Curve 1398 629 1363 573
+Curve 1350 591 1337 608
+Curve 1252 690 1144 656
+Curve 1109 645 1086 624
+<-------EndPath
+Path -1 2 0 1086 624
+Curve 1081 627 1069 640
+Curve 1042 669 1007 688
+Curve 977 704 946 719
+Curve 910 737 872 740
+Curve 836 743 800 745
+Curve 760 750 725 736
+Curve 722 752 719 767
+Curve 712 773 705 778
+Curve 690 776 674 774
+Curve 647 771 619 774
+Curve 604 775 588 775
+Curve 575 773 562 770
+Curve 556 767 557 761
+Curve 503 704 450 626
+<-------EndPath
+Path -1 5 0 450 626
+Curve 381 682 264 684
+Curve 67 688 -4 537
+Curve -26 599 -121 625
+Curve -145 631 -169 636
+<-------EndPath
+Path -1 2 0 -169 636
+Curve -189 652 -208 668
+Curve -234 691 -226 709
+Curve -243 707 -259 705
+Curve -333 708 -406 710
+<-------EndPath
+Path -1 1 0 -406 710
+Curve -442 670 -471 618
+<-------EndPath
+Path -1 5 0 -471 618
+Curve -643 628 -836 591
+Curve -902 578 -908 517
+Curve -918 418 -865 364
+<-------EndPath
+Path -1 -1 0 -865 364
+Curve -886 369 -906 406
+<-------EndPath
+Path 7 8 -1 -319 -278
+Curve -319 -282 -319 -286
+Curve -317 -321 -303 -348
+Curve -286 -378 -254 -398
+Curve -224 -397 -193 -395
+Curve -155 -362 -163 -306
+Curve -137 -355 -60 -352
+Curve 59 -347 76 -238
+Curve 81 -210 94 -198
+Curve 212 -191 184 -92
+Curve 167 -33 122 8
+Curve 113 17 100 17
+Curve 88 -26 76 -68
+Curve 61 -115 21 -131
+Curve -1 -132 -23 -132
+Curve -42 -125 -56 -145
+Curve -69 -161 -92 -160
+Curve -124 -160 -148 -139
+Curve -121 -168 -153 -212
+Curve -166 -229 -183 -235
+Curve -203 -237 -223 -238
+Curve -202 -256 -243 -299
+Curve -268 -326 -316 -280
+Curve -317 -280 -317 -279
+<-------EndPath
+Path 7 0 -1 -317 -279
+Curve -318 -279 -318 -278
+Curve -319 -278 -319 -278
+<-------EndPath
+Path 7 7 0 -319 -278
+Curve -384 -233 -330 -154
+Curve -293 -101 -230 -103
+Curve -271 -53 -289 17
+Curve -327 162 -198 202
+Curve -151 200 -104 198
+Curve -98 196 -92 194
+Curve -27 164 3 105
+<-------EndPath
+Path 7 7 0 762 -51
+Curve 762 -51 762 -50
+Curve 794 -12 804 38
+Curve 817 102 756 135
+Curve 684 175 602 158
+Curve 585 156 568 153
+<-------EndPath
+Path 7 3 -1 1474 408
+Curve 1491 360 1507 312
+<-------EndPath
+Path 7 7 0 1474 408
+Curve 1347 460 1291 404
+<-------EndPath
+Path 7 2 0 829 448
+Curve 850 435 870 422
+Curve 849 453 845 485
+<-------EndPath
+Path 7 6 0 845 485
+Curve 838 535 873 588
+Curve 1013 558 1050 488
+Curve 1042 548 1061 589
+<-------EndPath
+Path 7 2 0 1061 589
+Curve 1070 609 1086 624
+<-------EndPath
+Path 6 2 0 845 485
+Curve 821 518 797 551
+Curve 776 577 755 602
+Curve 733 628 710 654
+Curve 699 670 687 685
+Curve 700 686 712 687
+Curve 734 691 756 695
+Curve 789 698 822 701
+Curve 846 700 870 699
+Curve 951 689 1018 639
+Curve 1036 620 1053 600
+Curve 1057 595 1061 589
+<-------EndPath
+Path 7 7 0 1363 573
+Curve 1349 552 1343 519
+<-------EndPath
+Path 5 7 -1 544 449
+Curve 541 451 537 453
+Curve 512 464 487 475
+Curve 455 481 423 486
+Curve 396 487 376 470
+Curve 361 457 353 438
+Curve 342 414 350 390
+Curve 359 364 345 344
+Curve 322 359 296 370
+Curve 259 384 222 397
+Curve 179 405 136 412
+Curve 95 414 56 400
+Curve 14 384 -20 355
+Curve -54 327 -40 284
+Curve -74 317 -107 349
+Curve -161 394 -223 426
+Curve -236 433 -248 439
+Curve -294 460 -342 473
+Curve -411 493 -483 493
+Curve -553 493 -622 492
+Curve -694 491 -756 459
+Curve -834 417 -802 344
+Curve -806 336 -809 327
+<-------EndPath
+Path 5 -1 0 -809 327
+Curve -843 341 -865 364
+<-------EndPath
+Path 6 7 0 586 436
+Curve 582 427 577 417
+Curve 574 403 570 388
+<-------EndPath
+Path 6 -1 0 570 388
+Curve 567 388 563 388
+<-------EndPath
+Path 6 7 0 563 388
+Curve 552 417 544 449
+<-------EndPath
+Path 6 5 0 544 449
+Curve 544 451 543 452
+<-------EndPath
+Path 6 2 0 543 452
+Curve 560 488 564 529
+Curve 566 561 588 582
+Curve 597 559 597 529
+Curve 594 493 590 456
+Curve 588 446 586 436
+<-------EndPath
+Path 7 2 0 586 436
+Curve 594 445 601 454
+Curve 627 479 674 482
+<-------EndPath
+Path 7 6 0 674 482
+Curve 689 482 703 481
+Curve 773 475 829 448
+<-------EndPath
+Path 2 6 0 829 448
+Curve 749 521 672 622
+Curve 663 634 654 646
+Curve 687 570 674 482
+<-------EndPath
+Path -1 7 0 570 388
+Curve 569 381 568 373
+Curve 566 381 563 388
+<-------EndPath
+Path 5 2 0 527 513
+Curve 533 493 538 473
+Curve 541 463 543 452
+<-------EndPath
+Path 6 2 0 500 569
+Curve 518 624 547 656
+Curve 555 565 527 513
+<-------EndPath
+Path 6 5 0 527 513
+Curve 514 541 500 569
+<-------EndPath
+Path 2 5 0 500 569
+Curve 479 602 450 626
+<-------EndPath
+Path 2 2 0 601 454
+Curve 634 536 605 622
+<-------EndPath
+Path 8 7 0 -630 39
+Curve -642 -18 -653 -74
+Curve -654 -82 -655 -90
+<-------EndPath
+Path 8 -1 0 -655 -90
+Curve -960 -158 -909 16
+Curve -846 37 -815 37
+Curve -942 69 -949 206
+Curve -952 255 -899 269
+Curve -837 287 -774 304
+<-------EndPath
+Path 8 7 -1 -774 304
+Curve -788 294 -801 284
+Curve -847 247 -813 189
+Curve -791 151 -746 144
+Curve -759 139 -772 133
+Curve -813 104 -784 75
+Curve -771 65 -757 54
+Curve -693 16 -630 39
+<-------EndPath
+Path 7 7 0 -630 39
+Curve -594 179 -533 268
+<-------EndPath
+Path -1 7 0 -655 -90
+Curve -685 -300 -552 -433
+Curve -510 -475 -449 -475
+Curve -383 -476 -364 -447
+<-------EndPath
+Path 7 7 0 -365 -382
+Curve -366 -407 -366 -431
+Curve -366 -432 -366 -432
+<-------EndPath
+Path 0 8 0 -317 -279
+Curve -318 -279 -319 -278
+<-------EndPath
+Path 7 -1 0 -774 304
+Curve -764 307 -753 310
+Curve -781 319 -809 327
+<-------EndPath
+Path 2 1 -1 -412 676
+Curve -409 693 -406 710
+<-------EndPath
+Path 1 1 0 -438 629
+Curve -425 653 -412 676
+<-------EndPath
+Path 1 2 0 -412 676
+Curve -401 651 -398 611
+<-------EndPath
+Path 1 5 0 -398 611
+Curve -435 615 -471 618
+<-------EndPath
+Path 5 5 0 -19 498
+Curve -12 518 -4 537
+<-------EndPath
+Path 5 2 0 -219 557
+Curve -229 577 -238 596
+<-------EndPath
+Path 5 1 0 -238 596
+Curve -247 626 -225 635
+<-------EndPath
+Path 5 2 0 -225 635
+Curve -197 636 -169 636
+<-------EndPath
+Path 5 5 0 -219 557
+Curve -210 548 -208 540
+<-------EndPath
+Path 5 2 0 -296 594
+Curve -280 590 -264 586
+Curve -242 572 -219 557
+<-------EndPath
+Path 5 2 0 -398 611
+Curve -382 609 -365 607
+<-------EndPath
+Path 5 4 0 -365 607
+Curve -331 601 -296 594
+<-------EndPath
+Path 2 4 0 -296 594
+Curve -301 605 -305 615
+Curve -376 697 -365 607
+<-------EndPath
+Path 1 2 0 -238 596
+Curve -284 643 -306 674
+Curve -266 655 -225 635
+<-------EndPath
+!======EndShape
+=======BeginShape
+Path -1 0 0 -885 -3357
+Curve -885 -3358 -885 -3358
+Curve -814 -3706 -502 -3880
+Curve -305 -3990 -110 -3972
+Curve -47 -4346 312 -4434
+Curve 720 -4535 968 -4267
+Curve 1180 -4040 1153 -3624
+<-------EndPath
+Path -1 -1 0 1153 -3624
+Curve 1148 -3539 1128 -3458
+<-------EndPath
+Path -1 0 0 1128 -3458
+Curve 1514 -3377 1614 -2966
+Curve 1710 -2573 1589 -2299
+Curve 1582 -2284 1574 -2268
+Curve 1521 -2164 1451 -2062
+Curve 1451 -2062 1450 -2061
+Curve 1446 -2056 1442 -2050
+<-------EndPath
+Path -1 1 0 1442 -2050
+Curve 1524 -1893 1543 -1683
+<-------EndPath
+Path -1 1 -1 1543 -1683
+Curve 1546 -1679 1549 -1675
+<-------EndPath
+Path -1 0 0 1549 -1675
+Curve 1635 -1744 1737 -1800
+Curve 1745 -1805 1753 -1809
+Curve 1755 -1810 1757 -1811
+Curve 1766 -1816 1775 -1821
+Curve 2096 -1988 2434 -1872
+Curve 3039 -1665 2846 -1036
+Curve 2712 -597 2344 -463
+Curve 2455 -471 2507 -409
+Curve 2693 -185 2571 60
+Curve 2571 61 2570 61
+<-------EndPath
+Path -1 1 0 2570 61
+Curve 2570 62 2570 62
+Curve 2526 148 2444 237
+<-------EndPath
+Path -1 1 -1 2444 237
+Curve 2443 241 2442 244
+<-------EndPath
+Path -1 1 0 2442 244
+Curve 2562 294 2620 401
+Curve 2819 769 2406 1019
+Curve 2134 1184 1884 1157
+Curve 1897 1361 1754 1476
+<-------EndPath
+Path -1 6 0 1754 1476
+Curve 1649 1559 1460 1594
+Curve 1233 1637 1029 1601
+Curve 869 1573 724 1497
+<-------EndPath
+Path -1 6 -1 724 1497
+Curve 714 1497 704 1497
+<-------EndPath
+Path -1 6 0 704 1497
+Curve 341 1441 544 1195
+Curve 80 1166 249 710
+<-------EndPath
+Path -1 3 0 249 710
+Curve 176 731 103 752
+Curve 75 762 46 772
+Curve -1 789 -42 814
+Curve -44 816 -46 817
+Curve -241 935 -322 1203
+Curve -406 1486 -391 1777
+Curve -387 1826 -383 1874
+Curve -377 1923 -370 1971
+Curve -338 2174 -306 2376
+<-------EndPath
+Path -1 8 0 -306 2376
+Curve -305 2382 -304 2387
+<-------EndPath
+Path -1 3 0 -304 2387
+Curve -291 2475 -278 2562
+Curve -276 2582 -273 2602
+Curve -265 2662 -256 2722
+Curve -204 3098 -222 3539
+Curve -232 3785 -163 3960
+Curve -108 4099 -4 4194
+Curve 160 4342 226 4375
+<-------EndPath
+Path -1 -1 0 226 4375
+Curve 281 4368 264 4382
+Curve 254 4389 226 4375
+<-------EndPath
+Path -1 3 0 226 4375
+Curve 194 4380 161 4385
+<-------EndPath
+Path -1 -1 0 161 4385
+Curve 173 4391 184 4397
+<-------EndPath
+Path 0 0 0 -115 -3943
+Curve -113 -3958 -110 -3972
+Curve -12 -3964 85 -3923
+<-------EndPath
+Path -1 1 0 -895 -3303
+Curve -890 -3330 -885 -3357
+<-------EndPath
+Path 0 1 -1 -885 -3357
+Curve -662 -3766 -150 -3797
+Curve -48 -3791 54 -3785
+Curve 142 -3766 205 -3723
+Curve 221 -3795 242 -3854
+Curve 385 -4251 729 -4024
+Curve 1035 -3822 1024 -3464
+Curve 1021 -3388 1005 -3306
+Curve 967 -3114 903 -2980
+Curve 916 -2968 928 -2955
+Curve 1305 -3343 1440 -2907
+Curve 1450 -2872 1459 -2837
+Curve 1516 -2595 1473 -2350
+Curve 1445 -2191 1416 -2085
+<-------EndPath
+Path 0 4 0 1416 -2085
+Curve 1429 -2068 1442 -2050
+<-------EndPath
+Path 1 4 0 1442 -2050
+Curve 1403 -1998 1363 -1946
+Curve 1363 -1945 1362 -1944
+<-------EndPath
+Path 1 1 0 1362 -1944
+Curve 1353 -1934 1344 -1923
+<-------EndPath
+Path 1 -1 -1 -895 -3303
+Curve -912 -3282 -928 -3260
+<-------EndPath
+Path 1 0 0 -928 -3260
+Curve -920 -3253 -912 -3246
+Curve -638 -3010 -708 -2589
+Curve -764 -2254 -913 -1976
+<-------EndPath
+Path 1 1 0 -913 -1976
+Curve -926 -1936 -938 -1896
+<-------EndPath
+Path 1 1 0 201 -3707
+Curve 203 -3715 205 -3723
+<-------EndPath
+Path 1 1 0 -123 -3372
+Curve -126 -3379 -128 -3385
+Curve -132 -3394 -135 -3403
+<-------EndPath
+Path 1 2 0 165 -1863
+Curve 192 -1952 211 -2042
+Curve 248 -2220 253 -2405
+Curve 252 -2503 250 -2601
+Curve 242 -2735 198 -2851
+Curve 146 -2989 44 -3102
+Curve 41 -3106 37 -3109
+Curve -64 -3224 -123 -3372
+Curve -12 -3264 99 -3155
+Curve 100 -3155 100 -3154
+Curve 216 -3032 331 -2893
+Curve 365 -3013 399 -3133
+Curve 490 -3465 507 -3597
+Curve 529 -3774 539 -3733
+Curve 572 -3406 527 -3097
+Curve 473 -2731 401 -2395
+Curve 362 -2210 328 -2022
+Curve 299 -1842 269 -1662
+Curve 268 -1653 266 -1643
+<-------EndPath
+Path 1 2 -1 266 -1643
+Curve 255 -1638 244 -1632
+<-------EndPath
+Path 1 0 0 244 -1632
+Curve 245 -1631 245 -1630
+Curve 255 -1612 265 -1593
+<-------EndPath
+Path 1 0 -1 265 -1593
+Curve 269 -1594 272 -1594
+<-------EndPath
+Path 1 1 0 272 -1594
+Curve 272 -1595 272 -1595
+Curve 268 -1609 264 -1623
+<-------EndPath
+Path -1 0 0 -2118 -782
+Curve -2525 -742 -2752 -1085
+Curve -2969 -1415 -2851 -1816
+Curve -2741 -2190 -2462 -2362
+Curve -2404 -2398 -2340 -2416
+Curve -2394 -2775 -2181 -3052
+Curve -1943 -3362 -1591 -3416
+Curve -1195 -3478 -928 -3260
+<-------EndPath
+Path 2 1 0 -1771 -1919
+Curve -1791 -2124 -1783 -2341
+Curve -1781 -2422 -1770 -2500
+<-------EndPath
+Path 2 1 -1 -1770 -2500
+Curve -1776 -2501 -1782 -2502
+<-------EndPath
+Path 2 1 0 -1782 -2502
+Curve -1814 -2415 -1827 -2322
+Curve -1841 -2229 -1836 -2129
+Curve -1833 -2024 -1830 -1919
+<-------EndPath
+Path 2 3 -1 -1830 -1919
+Curve -1801 -1919 -1771 -1919
+<-------EndPath
+Path 1 3 0 -1771 -1919
+Curve -1771 -1918 -1771 -1916
+Curve -1750 -1707 -1709 -1503
+Curve -1698 -1458 -1687 -1412
+Curve -1649 -1270 -1582 -1136
+Curve -1537 -1046 -1484 -966
+Curve -1484 -966 -1483 -965
+Curve -1431 -885 -1370 -815
+<-------EndPath
+Path 1 3 -1 -1370 -815
+Curve -1363 -815 -1356 -815
+<-------EndPath
+Path 1 3 0 -1356 -815
+Curve -1061 -598 -836 -315
+Curve -796 -261 -756 -206
+Curve -755 -205 -754 -204
+Curve -754 -204 -754 -203
+Curve -671 -80 -610 51
+Curve -610 52 -610 52
+Curve -549 184 -511 324
+Curve -457 526 -388 615
+<-------EndPath
+Path 1 6 -1 -388 615
+Curve -103 209 -419 27
+Curve -420 27 -420 26
+Curve -448 12 -476 -3
+Curve -482 -8 -487 -12
+Curve -453 -51 -419 -90
+Curve -393 -123 -367 -156
+Curve -146 -445 -376 -783
+Curve -369 -795 -361 -807
+<-------EndPath
+Path 1 1 0 -361 -807
+Curve -362 -808 -363 -808
+Curve -370 -812 -376 -815
+<-------EndPath
+Path 3 1 0 -1830 -1919
+Curve -1830 -1918 -1830 -1916
+Curve -1830 -1826 -1830 -1735
+Curve -1833 -1547 -1786 -1388
+<-------EndPath
+Path 3 1 -1 -1786 -1388
+Curve -1790 -1388 -1793 -1387
+<-------EndPath
+Path 3 1 0 -1793 -1387
+Curve -1805 -1393 -1817 -1399
+Curve -1992 -1493 -2074 -1660
+Curve -2123 -1758 -2148 -1839
+<-------EndPath
+Path 3 1 -1 -2148 -1839
+Curve -2155 -1837 -2161 -1835
+<-------EndPath
+Path 3 1 0 -2161 -1835
+Curve -2142 -1613 -2019 -1460
+Curve -1964 -1393 -1908 -1325
+Curve -1908 -1325 -1907 -1324
+Curve -1894 -1308 -1880 -1291
+Curve -1832 -1235 -1784 -1179
+Curve -1732 -1117 -1680 -1054
+Curve -1625 -979 -1570 -903
+Curve -1569 -902 -1568 -900
+Curve -1542 -862 -1524 -821
+Curve -1524 -821 -1523 -820
+Curve -1522 -818 -1521 -815
+<-------EndPath
+Path 3 5 0 -1521 -815
+Curve -1516 -803 -1511 -791
+<-------EndPath
+Path 3 1 0 -1511 -791
+Curve -1506 -786 -1501 -781
+Curve -1481 -759 -1461 -736
+Curve -1459 -733 -1457 -730
+Curve -1457 -729 -1456 -728
+Curve -1454 -725 -1451 -722
+Curve -1269 -493 -1086 -263
+Curve -1062 -234 -1038 -204
+Curve -874 -2 -815 282
+Curve -796 376 -788 480
+Curve -769 716 -750 952
+Curve -738 1089 -726 1226
+Curve -725 1241 -723 1256
+<-------EndPath
+Path 3 6 0 -723 1256
+Curve -716 1339 -708 1422
+<-------EndPath
+Path 3 -1 0 -708 1422
+Curve -699 1523 -689 1624
+Curve -681 1714 -673 1803
+Curve -664 1903 -654 2003
+Curve -654 2006 -653 2008
+Curve -639 2161 -635 2315
+Curve -632 2465 -639 2615
+Curve -645 2702 -651 2789
+Curve -684 3169 -717 3446
+Curve -724 3482 -731 3517
+Curve -801 3771 -1156 4108
+Curve -1561 4492 -1116 4205
+<-------EndPath
+Path 3 3 0 -1116 4205
+Curve -1166 4225 -1176 4225
+<-------EndPath
+Path 0 0 0 -2340 -2416
+Curve -2328 -2420 -2315 -2423
+<-------EndPath
+Path 0 0 0 -2335 -2383
+Curve -2338 -2400 -2340 -2416
+<-------EndPath
+Path 1 0 0 -2017 -2352
+Curve -2017 -2352 -2017 -2351
+<-------EndPath
+Path 1 0 -1 -2017 -2351
+Curve -2025 -2352 -2032 -2353
+Curve -2161 -2325 -2261 -2265
+Curve -2500 -2122 -2570 -1798
+Curve -2676 -1304 -2367 -1037
+Curve -2238 -918 -2108 -798
+<-------EndPath
+Path 1 1 0 -2108 -798
+Curve -2102 -807 -2096 -815
+<-------EndPath
+Path 0 1 -1 -191 -2108
+Curve -195 -2110 -199 -2111
+<-------EndPath
+Path 0 1 0 -199 -2111
+Curve -512 -2137 -556 -1863
+<-------EndPath
+Path 0 1 -1 -556 -1863
+Curve -221 -2050 14 -1759
+Curve 96 -1658 164 -1533
+Curve 240 -1392 298 -1221
+<-------EndPath
+Path 0 1 0 298 -1221
+Curve 317 -1422 272 -1594
+<-------EndPath
+Path 2 0 0 143 -1855
+Curve 144 -1854 144 -1853
+Curve 145 -1852 145 -1850
+Curve 152 -1834 158 -1817
+Curve 176 -1776 194 -1734
+Curve 218 -1684 242 -1634
+Curve 243 -1633 244 -1632
+<-------EndPath
+Path 1 1 0 144 -1883
+Curve 135 -1893 126 -1903
+<-------EndPath
+Path 1 0 0 126 -1903
+Curve 135 -1879 143 -1855
+<-------EndPath
+Path 1 2 -1 143 -1855
+Curve 154 -1859 165 -1863
+<-------EndPath
+Path 0 1 0 126 -1903
+Curve -6 -2047 -191 -2108
+<-------EndPath
+Path 1 0 -1 -913 -1976
+Curve -811 -2333 -867 -2550
+Curve -960 -2912 -1493 -2884
+Curve -1964 -2859 -2017 -2352
+<-------EndPath
+Path 1 1 0 -913 -1976
+Curve -934 -1940 -955 -1903
+<-------EndPath
+Path 1 1 0 298 -1221
+Curve 298 -1213 297 -1204
+Curve 296 -1194 294 -1184
+<-------EndPath
+Path 0 1 0 1174 -1454
+Curve 1114 -1636 840 -1658
+Curve 651 -1673 563 -1524
+Curve 554 -1508 545 -1492
+Curve 534 -1473 523 -1453
+Curve 480 -1375 445 -1293
+Curve 424 -1238 402 -1182
+Curve 400 -1176 397 -1169
+Curve 349 -1033 320 -888
+Curve 312 -848 312 -812
+Curve 312 -811 312 -810
+<-------EndPath
+Path 0 1 -1 312 -810
+Curve 315 -788 317 -766
+<-------EndPath
+Path 0 0 0 317 -766
+Curve 318 -759 319 -752
+<-------EndPath
+Path 0 -1 -1 319 -752
+Curve 331 -721 342 -689
+<-------EndPath
+Path 0 1 -1 342 -689
+Curve 342 -689 342 -688
+Curve 343 -693 344 -698
+Curve 402 -1009 556 -1246
+Curve 850 -1699 1174 -1454
+<-------EndPath
+Path 1 1 0 1174 -1454
+Curve 1175 -1452 1175 -1449
+Curve 1202 -1362 1181 -1238
+Curve 1181 -1238 1181 -1237
+Curve 1176 -1214 1171 -1191
+Curve 1170 -1187 1169 -1183
+Curve 1167 -1173 1164 -1163
+<-------EndPath
+Path 0 -1 -1 1121 -3460
+Curve 1137 -3542 1153 -3624
+<-------EndPath
+Path 0 0 0 1128 -3458
+Curve 1117 -3421 1105 -3383
+<-------EndPath
+Path -1 0 0 1121 -3460
+Curve 1125 -3459 1128 -3458
+<-------EndPath
+Path 0 0 0 1105 -3463
+Curve 1113 -3462 1121 -3460
+<-------EndPath
+Path 4 1 0 1363 -1946
+Curve 1363 -1946 1362 -1945
+Curve 1362 -1945 1362 -1944
+<-------EndPath
+Path 4 1 0 1416 -2085
+Curve 1390 -1997 1363 -1946
+<-------EndPath
+Path 0 1 0 1549 -1675
+Curve 1549 -1675 1549 -1674
+Curve 1405 -1559 1305 -1409
+Curve 1237 -1308 1217 -1230
+Curve 1210 -1205 1209 -1181
+<-------EndPath
+Path 0 1 -1 1209 -1181
+Curve 1415 -1539 1808 -1681
+Curve 1816 -1684 1824 -1687
+Curve 1841 -1693 1857 -1698
+Curve 2336 -1851 2547 -1443
+Curve 2651 -1243 2573 -1063
+Curve 2445 -764 2249 -556
+Curve 2199 -467 2148 -378
+Curve 2600 -320 2559 55
+Curve 2565 58 2570 61
+<-------EndPath
+Path 1 1 0 2442 244
+Curve 2433 241 2424 237
+<-------EndPath
+Path 1 3 -1 1838 -15
+Curve 1840 -12 1842 -9
+<-------EndPath
+Path 1 3 0 1842 -9
+Curve 1748 130 1576 225
+Curve 1535 248 1493 271
+Curve 1493 271 1492 271
+Curve 1366 337 1240 402
+<-------EndPath
+Path 1 2 -1 1240 402
+Curve 1241 405 1242 407
+<-------EndPath
+Path 1 3 0 1242 407
+Curve 1276 459 1337 477
+Curve 1517 531 1690 648
+Curve 1620 644 1501 608
+Curve 1340 560 1196 474
+Curve 1196 474 1195 473
+Curve 1161 452 1127 430
+Curve 1093 439 1059 447
+Curve 1010 459 960 471
+Curve 934 479 907 487
+Curve 803 519 704 567
+Curve 704 569 704 571
+Curve 564 615 424 658
+<-------EndPath
+Path 1 6 -1 424 658
+Curve 270 1130 723 1127
+<-------EndPath
+Path 1 1 0 723 1127
+Curve 724 1122 724 1117
+<-------EndPath
+Path 1 1 0 1696 -496
+Curve 1701 -497 1705 -498
+Curve 1715 -501 1724 -503
+<-------EndPath
+Path 1 3 0 704 -426
+Curve 705 -427 706 -427
+Curve 751 -436 795 -444
+Curve 960 -481 1106 -542
+Curve 1231 -594 1343 -665
+Curve 1441 -725 1539 -784
+Curve 1338 -606 1124 -502
+Curve 1125 -502 1125 -501
+Curve 1139 -457 1165 -429
+Curve 1203 -388 1266 -383
+Curve 1329 -378 1416 -411
+Curve 1561 -464 1696 -496
+Curve 1498 -338 1268 -335
+Curve 1176 -335 1078 -359
+Curve 967 -386 820 -344
+Curve 815 -343 810 -342
+Curve 757 -325 704 -308
+<-------EndPath
+Path 1 4 0 704 -308
+Curve 683 -300 661 -292
+<-------EndPath
+Path 1 3 0 661 -292
+Curve 611 -265 572 -227
+Curve 490 -150 449 -34
+Curve 449 -33 448 -31
+Curve 437 8 426 47
+Curve 422 72 417 96
+<-------EndPath
+Path 1 6 -1 417 96
+Curve 461 458 877 428
+<-------EndPath
+Path 1 3 0 877 428
+Curve 883 426 888 424
+Curve 889 424 890 424
+Curve 978 395 1062 358
+Curve 1129 329 1195 300
+Curve 1322 244 1449 188
+Curve 1553 143 1656 97
+Curve 1758 43 1838 -15
+<-------EndPath
+Path 1 1 0 1838 -15
+Curve 1846 -21 1853 -27
+<-------EndPath
+Path 5 1 0 704 -426
+Curve 704 -431 704 -436
+Curve 693 -433 682 -429
+<-------EndPath
+Path 5 3 0 682 -429
+Curve 693 -428 704 -426
+<-------EndPath
+Path 3 1 0 682 -429
+Curve 579 -396 496 -338
+Curve 368 -250 287 -106
+<-------EndPath
+Path 3 6 0 287 -106
+Curve 261 -61 241 -11
+Curve 240 -9 239 -6
+Curve 237 -2 235 2
+Curve 226 25 217 48
+Curve 187 115 156 181
+<-------EndPath
+Path 3 -1 0 156 181
+Curve 71 351 -35 493
+<-------EndPath
+Path 3 7 0 -35 493
+Curve -68 534 -101 575
+Curve -134 614 -165 639
+Curve -182 651 -199 663
+Curve -251 692 -297 681
+Curve -308 678 -318 674
+Curve -327 670 -335 665
+<-------EndPath
+Path 3 6 0 -335 665
+Curve -362 648 -387 616
+Curve -388 616 -388 615
+<-------EndPath
+Path 3 3 0 661 -292
+Curve 623 -279 584 -252
+<-------EndPath
+Path 4 3 0 704 -308
+Curve 704 -312 704 -315
+Curve 681 -305 661 -292
+<-------EndPath
+Path 3 2 0 1242 407
+Curve 1235 405 1240 402
+<-------EndPath
+Path 6 3 0 417 96
+Curve 406 162 405 238
+Curve 405 242 405 245
+Curve 402 631 723 472
+Curve 714 473 704 473
+<-------EndPath
+Path 6 6 0 704 473
+Curve 697 475 690 476
+<-------EndPath
+Path 6 3 0 704 473
+Curve 707 473 709 472
+Curve 793 450 877 428
+<-------EndPath
+Path 6 1 -1 1754 1476
+Curve 1487 1560 1144 1553
+Curve 1092 1549 1039 1545
+Curve 696 1492 723 1127
+<-------EndPath
+Path -1 1 0 316 -774
+Curve 316 -775 316 -775
+<-------EndPath
+Path -1 1 -1 316 -775
+Curve 315 -779 314 -782
+Curve 315 -774 316 -766
+Curve 318 -753 316 -774
+<-------EndPath
+Path 1 1 0 316 -774
+Curve 317 -770 317 -766
+<-------EndPath
+Path 0 1 -1 317 -766
+Curve 317 -762 317 -757
+<-------EndPath
+Path 0 -1 -1 317 -757
+Curve 318 -755 319 -752
+<-------EndPath
+Path -1 -1 0 319 -752
+Curve 319 -752 319 -751
+<-------EndPath
+Path -1 1 -1 319 -751
+Curve 324 -735 329 -718
+Curve 332 -711 335 -703
+Curve 337 -699 339 -695
+Curve 339 -695 339 -694
+Curve 341 -692 342 -689
+<-------EndPath
+Path 1 1 0 316 -775
+Curve 316 -779 315 -783
+Curve 314 -793 313 -803
+Curve 313 -807 312 -810
+Curve 313 -796 314 -782
+<-------EndPath
+Path 1 -1 -1 319 -751
+Curve 318 -754 317 -757
+<-------EndPath
+Path 1 1 0 364 -535
+Curve 342 -584 324 -715
+Curve 324 -716 324 -717
+Curve 322 -734 319 -751
+<-------EndPath
+Path 1 6 -1 364 -535
+Curve 372 -518 379 -501
+Curve 118 -406 287 -106
+<-------EndPath
+Path 1 6 0 23 -363
+Curve 45 -428 85 -492
+Curve 208 -688 364 -535
+<-------EndPath
+Path 4 6 0 -127 -410
+Curve -132 -397 -137 -384
+<-------EndPath
+Path 4 -1 0 -137 -384
+Curve -138 -292 -94 -256
+<-------EndPath
+Path 4 4 0 -94 -256
+Curve -92 -261 -89 -265
+<-------EndPath
+Path 1 4 -1 -127 -410
+Curve -52 -387 23 -363
+<-------EndPath
+Path 6 4 0 23 -363
+Curve 1 -299 -2 -233
+Curve -2 -233 -2 -232
+<-------EndPath
+Path 6 7 0 -2 -232
+Curve -7 -148 20 -62
+Curve 31 -34 41 -5
+<-------EndPath
+Path 6 -1 0 41 -5
+Curve 81 87 156 181
+<-------EndPath
+Path 1 6 0 -361 -807
+Curve -332 -791 -303 -775
+Curve -60 -625 -127 -410
+<-------EndPath
+Path 4 7 0 -94 -256
+Curve -61 -228 -2 -232
+<-------EndPath
+Path -1 6 0 -137 -384
+Curve -164 -316 -220 -243
+Curve -300 -139 -376 -55
+Curve -285 -119 -224 -109
+Curve -197 -105 -176 -86
+<-------EndPath
+Path -1 7 0 -176 -86
+Curve -131 -190 -94 -256
+<-------EndPath
+Path 7 6 0 -176 -86
+Curve -148 -62 -129 -11
+Curve -108 43 -100 129
+Curve -92 210 -97 282
+Curve -115 495 -261 615
+Curve -265 618 -269 621
+Curve -302 643 -335 665
+<-------EndPath
+Path 7 -1 0 -35 493
+Curve -44 386 -33 287
+Curve -27 217 -11 152
+Curve 8 70 41 -5
+<-------EndPath
+Path 3 2 -1 -608 1617
+Curve -599 1217 -648 908
+Curve -698 598 -725 454
+Curve -752 310 -751 286
+Curve -752 271 -752 256
+Curve -754 247 -755 237
+Curve -822 -98 -1015 -321
+Curve -1036 -346 -1057 -370
+Curve -1126 -429 -1168 -490
+Curve -1113 -430 -1057 -370
+Curve -1032 -350 -1006 -329
+Curve -953 -290 -910 -243
+Curve -870 -199 -838 -148
+Curve -743 5 -708 107
+Curve -673 208 -686 242
+Curve -699 275 -671 366
+Curve -643 457 -597 545
+Curve -523 661 -409 710
+Curve -235 787 -93 665
+Curve 31 559 113 436
+Curve 199 309 273 143
+Curve 288 113 302 83
+Curve 279 157 276 209
+Curve 266 401 225 583
+Curve 162 631 75 663
+Curve 43 673 11 682
+Curve -77 705 -150 747
+Curve -343 858 -424 1101
+Curve -500 1328 -492 1617
+Curve -492 1623 -491 1628
+Curve -491 1630 -491 1632
+Curve -486 1708 -481 1783
+Curve -478 1810 -475 1837
+Curve -472 1860 -469 1883
+Curve -441 2135 -439 2380
+Curve -438 2480 -442 2578
+Curve -444 2651 -446 2723
+Curve -447 2749 -447 2775
+Curve -452 3064 -435 3320
+Curve -426 3456 -401 3579
+Curve -355 3812 -252 3995
+Curve -247 4004 -242 4013
+Curve -100 4252 161 4385
+<-------EndPath
+Path -1 2 0 161 4385
+Curve 122 4393 83 4401
+<-------EndPath
+Path -1 -1 0 83 4401
+Curve 68 4427 50 4428
+Curve 34 4428 17 4412
+<-------EndPath
+Path -1 2 0 17 4412
+Curve -213 4299 -286 4355
+Curve -387 4433 -377 4462
+Curve -666 4147 -838 4363
+Curve -967 4290 -1095 4217
+<-------EndPath
+Path -1 3 0 -1095 4217
+Curve -1106 4211 -1116 4205
+<-------EndPath
+Path 6 1 -1 -723 1256
+Curve -730 1257 -736 1257
+Curve -1007 1278 -983 1148
+Curve -976 1126 -968 1104
+Curve -968 1104 -968 1103
+Curve -941 1044 -870 962
+Curve -1305 1043 -1410 735
+Curve -1505 454 -1376 177
+Curve -1387 170 -1397 163
+<-------EndPath
+Path 6 -1 0 -1397 163
+Curve -1397 164 -1397 164
+Curve -1559 383 -1585 688
+Curve -1622 1120 -1176 1145
+Curve -1098 1149 -1054 1125
+<-------EndPath
+Path 6 6 0 -1054 1125
+Curve -1043 1117 -1032 1108
+Curve -1024 1097 -1016 1085
+<-------EndPath
+Path 3 6 0 249 710
+Curve 337 684 424 658
+<-------EndPath
+Path 1 5 -1 -1536 -815
+Curve -1529 -815 -1521 -815
+<-------EndPath
+Path 5 1 0 -1536 -815
+Curve -1524 -803 -1511 -791
+<-------EndPath
+Path -1 1 0 -1397 163
+Curve -1397 163 -1396 162
+Curve -1807 106 -2053 -175
+Curve -2319 -480 -2118 -782
+<-------EndPath
+Path 0 1 0 -2118 -782
+Curve -2113 -790 -2108 -798
+<-------EndPath
+Path 1 1 0 -2108 -798
+Curve -2107 -797 -2106 -796
+Curve -2094 -785 -2082 -773
+<-------EndPath
+Path 3 2 -1 -1095 4217
+Curve -819 4078 -712 3779
+Curve -671 3665 -640 3541
+Curve -640 3540 -640 3538
+Curve -587 3316 -568 3060
+Curve -558 2923 -557 2789
+Curve -557 2782 -557 2775
+Curve -557 2564 -579 2360
+Curve -598 2186 -605 2005
+Curve -613 1822 -608 1632
+Curve -608 1625 -608 1617
+<-------EndPath
+Path -1 6 0 -708 1422
+Curve -930 1509 -1056 1353
+Curve -1149 1237 -1054 1125
+<-------EndPath
+Path 3 8 -1 -304 2387
+Curve -315 2383 -325 2379
+Curve -316 2378 -306 2376
+<-------EndPath
+Path -1 2 0 83 4401
+Curve 50 4407 17 4412
+<-------EndPath
+!======EndShape
+=======BeginShape
+Path 1 0 -1 -409 -2925
+Curve -421 -2925 -433 -2924
+Curve -767 -2951 -859 -2729
+Curve -862 -2723 -864 -2716
+Curve -913 -2585 -883 -2372
+Curve -860 -2204 -799 -2086
+<-------EndPath
+Path 1 1 0 -799 -2086
+Curve -790 -2089 -781 -2092
+Curve -738 -2111 -684 -2121
+<-------EndPath
+Path 0 0 0 -572 -3173
+Curve -577 -3175 -582 -3177
+Curve -588 -3177 -594 -3176
+Curve -582 -3135 -563 -3101
+<-------EndPath
+Path -1 0 0 -811 -2097
+Curve -1079 -2369 -1002 -2758
+Curve -999 -2774 -996 -2789
+Curve -908 -3165 -594 -3176
+Curve -600 -3197 -606 -3218
+Curve -611 -3237 -616 -3256
+Curve -655 -3642 -375 -3902
+Curve -72 -4184 324 -4136
+Curve 505 -4115 633 -3963
+Curve 857 -3699 866 -3337
+Curve 1270 -3263 1480 -2924
+Curve 1597 -2734 1592 -2557
+Curve 1592 -2554 1592 -2551
+Curve 1593 -2552 1594 -2553
+Curve 1599 -2556 1603 -2558
+Curve 1737 -2628 2030 -2535
+Curve 2322 -2443 2351 -2229
+Curve 2371 -2063 2391 -1897
+Curve 2401 -1778 2182 -1569
+Curve 2318 -1272 2098 -1030
+<-------EndPath
+Path -1 5 0 2098 -1030
+Curve 1961 -879 1816 -809
+Curve 1815 -809 1814 -808
+<-------EndPath
+Path -1 1 0 1814 -808
+Curve 1796 -800 1777 -792
+Curve 1769 -789 1760 -785
+Curve 1618 -734 1469 -757
+Curve 1469 -733 1469 -708
+<-------EndPath
+Path -1 1 -1 1469 -708
+Curve 1472 -720 1474 -732
+<-------EndPath
+Path -1 1 0 1474 -732
+Curve 1438 -426 1290 -393
+<-------EndPath
+Path -1 4 0 1290 -393
+Curve 1742 -433 1511 -43
+Curve 1480 5 1448 53
+Curve 1187 411 749 431
+Curve 783 458 826 478
+Curve 1320 705 969 1011
+Curve 632 1304 262 1210
+<-------EndPath
+Path -1 3 0 262 1210
+Curve 304 1567 293 1951
+Curve 290 2075 294 2197
+Curve 295 2227 296 2256
+Curve 301 2327 306 2397
+Curve 315 2501 330 2603
+Curve 339 2657 347 2711
+Curve 356 2756 364 2801
+Curve 377 2858 389 2915
+Curve 447 3173 535 3416
+Curve 560 3477 584 3538
+Curve 673 3741 934 3972
+Curve 1021 4050 1129 4131
+Curve 1070 4120 1011 4109
+<-------EndPath
+Path -1 -1 0 1011 4109
+Curve 1050 4126 1089 4143
+<-------EndPath
+Path 1 1 0 -409 -2925
+Curve -409 -2912 -408 -2899
+<-------EndPath
+Path 1 0 -1 1473 -2366
+Curve 1472 -2432 1462 -2489
+Curve 1459 -2506 1455 -2522
+Curve 1421 -2674 1321 -2770
+Curve 1221 -2867 1056 -2908
+Curve 747 -2986 696 -2849
+Curve 687 -2981 660 -3094
+Curve 584 -3416 366 -3589
+Curve -42 -3911 -309 -3425
+Curve -369 -3315 -394 -3183
+Curve -397 -3164 -400 -3145
+Curve -404 -3115 -407 -3084
+Curve -414 -3008 -409 -2925
+<-------EndPath
+Path 1 0 -1 -781 -2092
+Curve -628 -2134 -511 -2037
+Curve -825 -1996 -881 -1760
+Curve -897 -1696 -893 -1617
+Curve -898 -1616 -902 -1615
+Curve -902 -1613 -901 -1610
+Curve -937 -1684 -973 -1758
+Curve -1003 -1786 -1033 -1813
+Curve -1163 -1919 -1284 -1905
+Curve -1438 -1887 -1577 -1672
+Curve -1695 -1488 -1707 -1296
+Curve -1712 -1229 -1703 -1160
+Curve -1703 -1159 -1703 -1158
+Curve -1703 -1158 -1702 -1157
+Curve -1701 -1149 -1700 -1141
+Curve -1699 -1136 -1698 -1131
+Curve -1687 -1062 -1662 -991
+Curve -1671 -990 -1679 -989
+Curve -1687 -988 -1695 -987
+Curve -1735 -980 -1775 -973
+Curve -2068 -900 -1896 -585
+Curve -1861 -530 -1826 -474
+Curve -1823 -455 -1819 -435
+<-------EndPath
+Path 1 1 0 -1819 -435
+Curve -1803 -438 -1787 -441
+<-------EndPath
+Path -1 0 0 -2051 -497
+Curve -2381 -691 -2098 -1029
+Curve -2010 -1134 -1831 -1137
+Curve -1987 -1484 -1722 -1813
+Curve -1559 -2015 -1306 -2035
+Curve -1302 -2036 -1297 -2036
+Curve -1193 -2043 -1074 -2020
+Curve -995 -2004 -927 -1982
+<-------EndPath
+Path -1 1 -1 -927 -1982
+Curve -914 -2036 -863 -2061
+Curve -835 -2073 -807 -2084
+Curve -809 -2091 -811 -2097
+<-------EndPath
+Path 0 1 -1 -811 -2097
+Curve -805 -2092 -799 -2086
+<-------EndPath
+Path 1 1 0 -799 -2086
+Curve -799 -2085 -798 -2084
+<-------EndPath
+Path 1 0 0 -798 -2084
+Curve -790 -2088 -781 -2092
+<-------EndPath
+Path -1 1 0 117 -1928
+Curve 116 -1937 115 -1946
+Curve 108 -1976 101 -2006
+<-------EndPath
+Path -1 2 0 101 -2006
+Curve 109 -1969 117 -1931
+Curve 117 -1930 117 -1928
+<-------EndPath
+Path 1 3 0 117 -1928
+Curve 166 -1700 214 -1472
+Curve 248 -1575 291 -1676
+Curve 365 -1855 438 -2033
+<-------EndPath
+Path 1 2 0 438 -2033
+Curve 546 -2305 654 -2577
+Curve 518 -2143 464 -2023
+<-------EndPath
+Path 1 3 0 464 -2023
+Curve 409 -1903 266 -1246
+Curve 294 -1131 322 -1015
+Curve 339 -950 356 -884
+<-------EndPath
+Path 1 4 -1 356 -884
+Curve 437 -669 711 -767
+<-------EndPath
+Path 1 3 0 711 -767
+Curve 740 -792 768 -817
+Curve 847 -893 925 -969
+Curve 932 -975 938 -981
+Curve 1051 -1164 1064 -1284
+Curve 1075 -1407 1086 -1529
+Curve 1096 -1653 1116 -1747
+Curve 1132 -1594 1117 -1472
+Curve 1101 -1350 1130 -1310
+Curve 1145 -1290 1160 -1270
+Curve 1186 -1266 1227 -1309
+Curve 1245 -1331 1262 -1353
+Curve 1425 -1558 1709 -1797
+Curve 1534 -1544 1344 -1292
+Curve 1344 -1292 1343 -1291
+Curve 1319 -1260 1294 -1228
+Curve 1170 -1064 1046 -900
+Curve 976 -806 905 -712
+<-------EndPath
+Path 1 -1 -1 905 -712
+Curve 907 -711 909 -709
+<-------EndPath
+Path 1 3 0 909 -709
+Curve 702 -467 607 -329
+Curve 577 -280 546 -231
+Curve 444 -29 377 161
+Curve 331 293 301 418
+Curve 261 587 248 759
+Curve 236 923 249 1091
+<-------EndPath
+Path 1 4 -1 249 1091
+Curve 634 1232 766 855
+Curve 867 563 552 450
+Curve 631 405 711 362
+Curve 920 246 1135 135
+Curve 1277 62 1339 -20
+Curve 1442 -156 1322 -317
+Curve 1291 -354 1260 -390
+<-------EndPath
+Path 1 1 0 1260 -390
+Curve 1258 -393 1255 -395
+Curve 1232 -416 1209 -437
+<-------EndPath
+Path 2 3 -1 72 -1922
+Curve 95 -1925 117 -1928
+<-------EndPath
+Path 2 1 0 101 -2006
+Curve 72 -2140 43 -2274
+Curve 58 -2098 72 -1922
+<-------EndPath
+Path 3 1 0 72 -1922
+Curve 114 -1422 148 -1225
+Curve 154 -1194 160 -1162
+Curve 199 -990 257 -797
+Curve 258 -796 258 -795
+Curve 271 -754 283 -712
+<-------EndPath
+Path 3 -1 0 283 -712
+Curve 284 -711 284 -709
+<-------EndPath
+Path 3 2 0 284 -709
+Curve 299 -683 283 -684
+<-------EndPath
+Path 3 1 0 283 -684
+Curve 403 -341 152 -190
+Curve -158 -4 -465 -246
+Curve -548 -312 -617 -382
+Curve -764 -531 -846 -699
+<-------EndPath
+Path 3 2 0 -846 -699
+Curve -849 -704 -852 -709
+<-------EndPath
+Path 3 1 0 -852 -709
+Curve -894 -1023 -881 -1357
+<-------EndPath
+Path 3 1 -1 -881 -1357
+Curve -884 -1358 -886 -1358
+<-------EndPath
+Path 3 1 0 -886 -1358
+Curve -887 -1358 -887 -1358
+Curve -927 -1249 -931 -1125
+Curve -936 -986 -930 -858
+Curve -926 -792 -948 -745
+Curve -957 -727 -969 -712
+<-------EndPath
+Path 3 -1 -1 -969 -712
+Curve -969 -711 -969 -709
+Curve -970 -709 -971 -709
+<-------EndPath
+Path 3 2 0 -971 -709
+Curve -1003 -673 -1064 -664
+Curve -1088 -661 -1111 -658
+<-------EndPath
+Path 3 1 0 -1111 -658
+Curve -1204 -655 -1297 -651
+<-------EndPath
+Path 3 -1 -1 -1297 -651
+Curve -1404 -647 -1510 -643
+<-------EndPath
+Path 3 2 0 -1510 -643
+Curve -1525 -641 -1539 -639
+<-------EndPath
+Path 3 1 0 -1539 -639
+Curve -904 -505 -709 -290
+Curve -686 -259 -663 -227
+Curve -520 18 -920 -67
+Curve -1012 -77 -1104 -86
+<-------EndPath
+Path 3 2 0 -1104 -86
+Curve -1104 -76 -1111 -77
+<-------EndPath
+Path 3 1 0 -1111 -77
+Curve -1238 -88 -1366 -81
+Curve -1433 -74 -1499 -67
+Curve -1502 -67 -1504 -66
+Curve -1566 -53 -1628 -39
+Curve -1755 -4 -1847 43
+<-------EndPath
+Path 3 1 -1 -1847 43
+Curve -1850 40 -1852 36
+<-------EndPath
+Path 3 1 0 -1852 36
+Curve -1852 36 -1852 35
+Curve -1929 71 -1977 132
+Curve -1863 94 -1749 55
+Curve -1725 54 -1700 52
+<-------EndPath
+Path 3 1 -1 -1700 52
+Curve -1698 54 -1695 56
+<-------EndPath
+Path 3 3 0 -1695 56
+Curve -1674 34 -1653 12
+<-------EndPath
+Path 1 1 0 -799 -2086
+Curve -803 -2085 -807 -2084
+<-------EndPath
+Path 0 1 0 -798 -2084
+Curve -802 -2082 -805 -2080
+Curve -890 -2036 -928 -1956
+Curve -928 -1969 -927 -1982
+<-------EndPath
+Path 3 3 0 214 -1472
+Curve 212 -1465 209 -1457
+<-------EndPath
+Path 0 0 0 866 -3337
+Curve 866 -3307 866 -3277
+Curve 864 -3182 829 -3137
+<-------EndPath
+Path 0 0 0 1589 -2517
+Curve 1591 -2534 1592 -2551
+Curve 1568 -2536 1546 -2507
+Curve 1507 -2457 1473 -2366
+Curve 1473 -2344 1473 -2322
+<-------EndPath
+Path 0 1 0 1473 -2366
+Curve 1453 -2312 1435 -2243
+Curve 1435 -2242 1435 -2241
+<-------EndPath
+Path 0 1 -1 1435 -2241
+Curve 1448 -2238 1461 -2235
+Curve 1563 -2321 1659 -2354
+Curve 1873 -2428 2058 -2232
+Curve 2295 -1981 2061 -1685
+Curve 2115 -1641 2168 -1597
+<-------EndPath
+Path 0 1 0 2168 -1597
+Curve 2175 -1583 2182 -1569
+<-------EndPath
+Path 0 1 -1 2182 -1569
+Curve 2122 -1627 2061 -1685
+Curve 2006 -1616 1925 -1544
+Curve 1924 -1531 1922 -1517
+Curve 2096 -1266 2010 -1055
+<-------EndPath
+Path 0 5 -1 2010 -1055
+Curve 2054 -1043 2098 -1030
+<-------EndPath
+Path 1 1 0 1435 -2241
+Curve 1421 -2190 1410 -2132
+<-------EndPath
+Path 2 3 -1 438 -2033
+Curve 451 -2028 464 -2023
+<-------EndPath
+Path 3 4 0 409 -717
+Curve 390 -773 371 -829
+Curve 364 -857 356 -884
+<-------EndPath
+Path 1 1 0 1777 -792
+Curve 1794 -804 1810 -815
+<-------EndPath
+Path 1 5 -1 1810 -815
+Curve 1957 -928 2010 -1055
+<-------EndPath
+Path 1 1 0 1469 -777
+Curve 1469 -767 1469 -757
+<-------EndPath
+Path 5 1 -1 1810 -815
+Curve 1812 -812 1814 -808
+<-------EndPath
+Path 0 0 0 2168 -1557
+Curve 2175 -1563 2182 -1569
+<-------EndPath
+Path 4 1 0 1290 -393
+Curve 1275 -392 1260 -390
+<-------EndPath
+Path 3 -1 0 892 -696
+Curve 899 -704 905 -712
+<-------EndPath
+Path -1 3 -1 892 -696
+Curve 901 -703 909 -709
+<-------EndPath
+Path 4 3 -1 644 -709
+Curve 647 -709 649 -708
+Curve 649 -713 649 -717
+<-------EndPath
+Path 4 3 0 649 -717
+Curve 680 -742 711 -767
+<-------EndPath
+Path 4 3 -1 409 -717
+Curve 409 -713 409 -709
+Curve 419 -709 429 -709
+<-------EndPath
+Path 4 3 0 429 -709
+Curve 466 -387 644 -709
+<-------EndPath
+Path 1 -1 -1 274 -709
+Curve 279 -711 283 -712
+<-------EndPath
+Path 1 2 0 283 -684
+Curve 279 -697 274 -709
+<-------EndPath
+Path -1 2 -1 274 -709
+Curve 279 -709 284 -709
+<-------EndPath
+Path 3 2 -1 258 113
+Curve 295 73 332 32
+Curve 312 77 291 122
+Curve 290 126 288 129
+Curve 278 156 267 182
+Curve 164 447 139 755
+<-------EndPath
+Path 3 2 0 139 755
+Curve 139 756 139 756
+<-------EndPath
+Path 3 2 -1 139 756
+Curve 134 818 132 883
+Curve 132 983 131 1083
+Curve 131 1086 131 1088
+Curve 132 1109 132 1129
+Curve 136 1203 140 1276
+Curve 153 1469 186 1657
+Curve 211 1798 224 1956
+Curve 231 2078 238 2200
+Curve 239 2230 239 2259
+Curve 240 2331 240 2403
+Curve 240 2405 240 2407
+Curve 240 2426 240 2445
+Curve 241 2478 241 2511
+Curve 243 2564 244 2616
+Curve 244 2620 244 2623
+Curve 244 2624 244 2625
+Curve 247 2671 249 2717
+Curve 253 2770 257 2823
+Curve 262 2874 267 2925
+Curve 268 2934 269 2943
+Curve 316 3266 450 3594
+Curve 574 3898 869 4042
+Curve 940 4076 1011 4109
+<-------EndPath
+Path -1 2 0 1011 4109
+Curve 846 4069 675 3980
+Curve 442 3859 308 3946
+Curve 174 4032 129 4071
+Curve 102 4038 -128 4114
+Curve -26 3993 76 3872
+Curve 119 3781 -306 3899
+<-------EndPath
+Path -1 7 0 -306 3899
+Curve -458 3942 -671 4011
+Curve -505 3903 -385 3801
+<-------EndPath
+Path -1 3 0 -385 3801
+Curve -188 3632 -112 3478
+Curve -67 3385 -32 3284
+Curve 29 3109 57 2928
+<-------EndPath
+Path -1 6 0 57 2928
+Curve 56 2928 54 2928
+Curve 56 2928 57 2928
+<-------EndPath
+Path -1 3 0 57 2928
+Curve 64 2877 70 2825
+Curve 79 2727 80 2628
+Curve 79 2570 77 2512
+Curve 75 2463 72 2413
+Curve 53 2112 15 1813
+Curve 0 1678 -15 1542
+Curve -15 1541 -15 1540
+Curve -26 1415 -36 1290
+Curve -36 1289 -36 1288
+Curve -37 1270 -38 1251
+<-------EndPath
+Path -1 4 0 -38 1251
+Curve -129 1446 -304 1264
+Curve -401 1164 -431 1011
+Curve -368 1381 -671 1380
+Curve -912 1379 -1111 1258
+<-------EndPath
+Path -1 4 -1 -1111 1258
+Curve -1111 1246 -1111 1233
+<-------EndPath
+Path -1 4 0 -1111 1233
+Curve -1259 1153 -1272 958
+<-------EndPath
+Path -1 1 0 -1272 958
+Curve -1273 931 -1273 903
+Curve -1273 893 -1272 883
+<-------EndPath
+Path -1 1 -1 -1272 883
+Curve -1282 883 -1291 883
+<-------EndPath
+Path -1 1 0 -1291 883
+Curve -1615 1099 -1965 958
+Curve -2265 836 -2356 439
+Curve -2358 432 -2359 424
+<-------EndPath
+Path -1 0 0 -2359 424
+Curve -2442 41 -2303 -302
+Curve -2219 -509 -2053 -477
+<-------EndPath
+Path -1 0 -1 -2053 -477
+Curve -2052 -487 -2051 -497
+<-------EndPath
+Path 3 2 0 258 114
+Curve 258 114 258 113
+<-------EndPath
+Path 3 2 -1 59 1281
+Curve 59 1222 58 1163
+Curve 59 1025 72 887
+Curve 73 883 73 878
+Curve 78 820 86 763
+Curve 87 758 88 753
+Curve 88 749 87 744
+Curve 83 698 79 652
+Curve 79 620 79 587
+Curve 88 339 235 158
+Curve 242 141 249 123
+Curve 254 119 258 114
+<-------EndPath
+Path 4 3 0 249 1091
+Curve 254 1141 259 1190
+Curve 261 1200 262 1210
+<-------EndPath
+Path 1 2 0 -851 -709
+Curve -849 -704 -846 -699
+<-------EndPath
+Path 1 2 -1 -852 -709
+Curve -852 -709 -851 -709
+<-------EndPath
+Path -1 1 0 -969 -712
+Curve -970 -711 -971 -709
+<-------EndPath
+Path 2 1 -1 -971 -709
+Curve -1041 -709 -1111 -709
+Curve -1111 -684 -1111 -658
+<-------EndPath
+Path -1 1 0 -1297 -651
+Curve -1311 -652 -1325 -652
+Curve -1418 -648 -1510 -643
+<-------EndPath
+Path 2 1 -1 -1510 -643
+Curve -1531 -643 -1552 -642
+<-------EndPath
+Path 2 1 0 -1552 -642
+Curve -1546 -641 -1539 -639
+<-------EndPath
+Path 1 1 0 -1539 -639
+Curve -1544 -639 -1548 -638
+Curve -1554 -637 -1560 -636
+<-------EndPath
+Path 2 1 0 -1104 -86
+Curve -1105 -86 -1105 -86
+Curve -1108 -86 -1111 -86
+<-------EndPath
+Path 2 -1 0 -1111 -86
+Curve -1111 -82 -1111 -77
+<-------EndPath
+Path 1 -1 -1 -1111 -77
+Curve -1111 -82 -1111 -86
+<-------EndPath
+Path 2 3 0 -1091 51
+Curve -1101 48 -1111 45
+<-------EndPath
+Path 2 1 0 -1111 45
+Curve -1111 48 -1111 50
+Curve -1101 51 -1091 51
+<-------EndPath
+Path 3 1 0 -1091 51
+Curve -757 58 -458 188
+Curve -203 300 -77 588
+<-------EndPath
+Path 3 3 0 -77 588
+Curve -84 520 -91 451
+<-------EndPath
+Path 1 3 0 -1111 45
+Curve -1232 35 -1352 24
+Curve -1419 27 -1486 29
+Curve -1548 41 -1599 72
+Curve -1658 109 -1700 159
+Curve -1785 264 -1838 345
+<-------EndPath
+Path 1 3 -1 -1838 345
+Curve -1845 344 -1852 342
+<-------EndPath
+Path 1 3 0 -1852 342
+Curve -1853 342 -1853 342
+Curve -1832 215 -1749 117
+Curve -1722 87 -1695 56
+<-------EndPath
+Path 1 4 -1 -1272 958
+Curve -1251 1113 -1013 1191
+Curve -903 1227 -766 1180
+Curve -500 1090 -378 781
+<-------EndPath
+Path 1 1 0 -378 781
+Curve -383 771 -387 761
+<-------EndPath
+Path 4 4 0 -1111 1233
+Curve -1101 1238 -1091 1243
+<-------EndPath
+Path 1 3 0 -48 1042
+Curve -49 1037 -49 1031
+Curve -52 963 -55 894
+Curve -63 779 -71 663
+Curve -74 626 -77 588
+<-------EndPath
+Path 4 3 0 -38 1251
+Curve -41 1210 -43 1169
+Curve -43 1169 -43 1168
+Curve -46 1105 -48 1042
+<-------EndPath
+Path 4 1 -1 -48 1042
+Curve -60 1043 -71 1043
+Curve -256 1036 -378 781
+<-------EndPath
+Path 1 0 -1 -1819 -435
+Curve -1927 -416 -2013 -379
+Curve -2014 -379 -2015 -378
+Curve -2316 -250 -2354 87
+Curve -2374 266 -2359 424
+<-------EndPath
+Path 3 2 -1 -311 3883
+Curve 11 3769 74 3370
+Curve 112 3123 142 2834
+Curve 152 2731 162 2628
+Curve 166 2570 170 2512
+Curve 171 2479 172 2445
+Curve 172 2426 172 2407
+Curve 172 2405 172 2403
+Curve 171 2333 169 2262
+Curve 159 2079 124 1896
+Curve 90 1716 73 1533
+Curve 62 1408 59 1282
+<-------EndPath
+Path 3 2 0 59 1282
+Curve 59 1282 59 1281
+<-------EndPath
+Path 7 2 -1 -306 3899
+Curve -309 3891 -311 3883
+<-------EndPath
+Path 7 3 -1 -311 3883
+Curve -348 3842 -385 3801
+<-------EndPath
+Path 3 3 0 229 1083
+Curve 239 1087 249 1091
+<-------EndPath
+!======EndShape
+=======BeginShape
+Path 0 1 -1 733 -731
+Curve 762 -712 790 -692
+Curve 800 -683 809 -674
+Curve 851 -634 883 -579
+Curve 950 -465 965 -337
+Curve 983 -189 1067 -100
+Curve 1147 -14 1233 65
+Curve 1248 77 1262 88
+<-------EndPath
+Path 0 6 -1 1262 88
+Curve 1290 102 1318 115
+Curve 1369 131 1387 169
+<-------EndPath
+Path 0 -1 0 1387 169
+Curve 1379 133 1344 98
+Curve 1317 71 1281 52
+Curve 1267 46 1252 39
+Curve 1145 -2 1090 -95
+Curve 1036 -185 1019 -301
+Curve 1004 -413 966 -517
+Curve 928 -623 833 -691
+Curve 786 -724 733 -731
+<-------EndPath
+Path 1 -1 0 733 -731
+Curve 690 -730 647 -728
+Curve 641 -727 634 -725
+<-------EndPath
+Path 1 3 0 634 -725
+Curve 654 -721 674 -717
+Curve 675 -717 676 -717
+Curve 733 -703 769 -668
+<-------EndPath
+Path 1 2 0 769 -668
+Curve 778 -659 787 -649
+Curve 813 -617 827 -575
+<-------EndPath
+Path 1 3 0 827 -575
+Curve 828 -572 829 -568
+Curve 830 -567 830 -565
+Curve 841 -526 851 -486
+<-------EndPath
+Path 1 4 0 851 -486
+Curve 854 -473 857 -459
+<-------EndPath
+Path 1 -1 0 857 -459
+Curve 866 -402 875 -344
+Curve 877 -332 878 -320
+<-------EndPath
+Path 1 5 0 878 -320
+Curve 882 -287 886 -253
+<-------EndPath
+Path 1 2 0 886 -253
+Curve 891 -209 896 -165
+<-------EndPath
+Path 1 5 0 896 -165
+Curve 899 -143 901 -120
+Curve 904 -87 916 -61
+Curve 916 -61 916 -60
+Curve 947 9 1033 23
+<-------EndPath
+Path 1 -1 0 1033 23
+Curve 1034 23 1034 23
+Curve 1040 24 1045 25
+<-------EndPath
+Path 1 3 0 1045 25
+Curve 1152 44 1246 83
+Curve 1254 87 1261 90
+<-------EndPath
+Path 1 6 -1 1261 90
+Curve 1262 89 1262 88
+<-------EndPath
+Path 3 2 1 -1199 -608
+Curve -1194 -608 -1189 -607
+Curve -1090 -603 -991 -599
+Curve -876 -594 -760 -589
+Curve -645 -579 -529 -585
+Curve -417 -595 -304 -605
+Curve -194 -612 -84 -619
+Curve 33 -626 149 -632
+Curve 264 -640 379 -647
+Curve 496 -652 612 -657
+Curve 691 -663 769 -668
+<-------EndPath
+Path 3 2 1 827 -575
+Curve 781 -573 735 -570
+Curve 623 -561 510 -551
+Curve 397 -547 284 -542
+Curve 204 -538 124 -534
+Curve 120 -534 116 -533
+Curve 113 -533 110 -533
+Curve 88 -531 65 -529
+Curve 25 -526 -15 -522
+<-------EndPath
+Path 3 4 1 -15 -522
+Curve -91 -517 -167 -512
+Curve -280 -504 -392 -495
+Curve -508 -484 -623 -472
+Curve -718 -465 -813 -458
+Curve -936 -445 -1058 -431
+<-------EndPath
+Path 3 0 1 -1058 -431
+Curve -1058 -430 -1057 -428
+Curve -1043 -384 -1029 -340
+<-------EndPath
+Path 3 -1 1 -1029 -340
+Curve -1019 -341 -1009 -342
+<-------EndPath
+Path 3 4 1 -1009 -342
+Curve -914 -352 -818 -362
+Curve -700 -370 -582 -378
+Curve -472 -382 -362 -386
+Curve -244 -397 -125 -408
+Curve -10 -418 106 -428
+Curve 216 -439 325 -450
+<-------EndPath
+Path 3 -1 1 325 -450
+Curve 332 -451 339 -452
+<-------EndPath
+Path 3 4 1 339 -452
+Curve 454 -467 569 -482
+Curve 682 -486 794 -489
+Curve 823 -488 851 -486
+<-------EndPath
+Path -1 3 0 563 -725
+Curve 611 -720 634 -725
+<-------EndPath
+Path -1 -1 1 647 -728
+Curve 605 -727 563 -725
+<-------EndPath
+Path 3 -1 1 563 -725
+Curve 354 -707 145 -689
+Curve 29 -681 -88 -673
+Curve -424 -660 -760 -646
+Curve -982 -641 -1200 -643
+<-------EndPath
+Path 3 -1 -1 -1200 -643
+Curve -1207 -630 -1213 -616
+<-------EndPath
+Path 3 0 1 -1213 -616
+Curve -1206 -612 -1199 -608
+<-------EndPath
+Path 2 0 1 -1199 -608
+Curve -1195 -605 -1190 -602
+Curve -1125 -556 -1087 -492
+<-------EndPath
+Path 2 4 -1 -1087 -492
+Curve -1079 -498 -1070 -503
+<-------EndPath
+Path 2 4 1 -1070 -503
+Curve -995 -505 -919 -507
+Curve -843 -504 -767 -510
+Curve -695 -516 -623 -522
+Curve -549 -526 -475 -529
+Curve -434 -530 -392 -530
+Curve -360 -531 -327 -532
+Curve -251 -536 -175 -539
+Curve -171 -539 -167 -539
+Curve -92 -537 -16 -535
+<-------EndPath
+Path 2 2 1 -16 -535
+Curve -15 -535 -14 -535
+Curve 26 -533 66 -531
+Curve 88 -532 110 -533
+<-------EndPath
+Path -1 -1 1 328 -428
+Curve 335 -429 341 -429
+<-------EndPath
+Path -1 4 -1 341 -429
+Curve 340 -441 339 -452
+<-------EndPath
+Path 4 -1 -1 328 -428
+Curve 327 -439 325 -450
+<-------EndPath
+Path 4 -1 1 -1007 -311
+Curve -935 -313 -863 -314
+Curve -791 -316 -719 -318
+Curve -642 -320 -564 -321
+Curve -485 -324 -405 -327
+Curve -330 -338 -254 -348
+Curve -184 -355 -113 -362
+Curve -39 -372 35 -382
+Curve 74 -390 112 -398
+Curve 146 -404 180 -410
+Curve 254 -419 327 -428
+Curve 328 -428 328 -428
+<-------EndPath
+Path 2 5 1 886 -253
+Curve 856 -267 765 -270
+Curve 765 -270 764 -270
+Curve 661 -267 558 -263
+Curve 549 -263 539 -262
+Curve 431 -255 322 -247
+Curve 322 -247 321 -247
+Curve 315 -247 308 -247
+Curve 204 -243 100 -238
+Curve 99 -238 98 -238
+Curve -16 -226 -130 -214
+Curve -249 -204 -368 -194
+Curve -463 -190 -558 -185
+Curve -668 -176 -777 -167
+Curve -889 -157 -999 -181
+<-------EndPath
+Path 2 0 1 -999 -181
+Curve -985 -109 -955 -48
+<-------EndPath
+Path 2 5 1 -955 -48
+Curve -849 -58 -742 -68
+Curve -627 -74 -511 -79
+Curve -407 -76 -303 -83
+Curve -196 -96 -88 -109
+Curve 21 -117 130 -125
+Curve 190 -125 250 -125
+Curve 309 -129 368 -133
+Curve 486 -144 604 -154
+Curve 720 -159 836 -164
+Curve 866 -165 896 -165
+<-------EndPath
+Path 5 5 1 916 -60
+Curve 784 -65 652 -70
+Curve 537 -71 421 -71
+Curve 337 -69 253 -67
+Curve 221 -65 189 -63
+Curve 74 -52 -42 -40
+Curve -149 -30 -256 -20
+Curve -360 -14 -463 -8
+Curve -576 2 -689 11
+Curve -793 15 -896 19
+<-------EndPath
+Path -1 5 1 -997 -260
+Curve -881 -263 -766 -259
+Curve -671 -259 -576 -258
+Curve -469 -262 -362 -265
+Curve -244 -268 -125 -270
+Curve -16 -271 94 -272
+Curve 207 -276 320 -280
+Curve 438 -291 556 -301
+Curve 660 -310 763 -318
+Curve 776 -319 789 -319
+Curve 832 -320 875 -320
+Curve 877 -320 878 -320
+<-------EndPath
+Path -1 4 1 857 -459
+Curve 826 -458 795 -457
+Curve 795 -457 794 -457
+Curve 790 -457 786 -457
+Curve 709 -453 631 -449
+Curve 552 -444 472 -439
+Curve 407 -434 341 -429
+<-------EndPath
+Path 6 2 0 1323 191
+Curve 1321 216 1319 241
+Curve 1312 277 1292 299
+<-------EndPath
+Path 6 -1 1 1292 299
+Curve 1309 299 1326 298
+<-------EndPath
+Path 6 8 0 1326 298
+Curve 1335 292 1344 285
+<-------EndPath
+Path 6 -1 0 1344 285
+Curve 1348 281 1352 276
+Curve 1398 221 1387 169
+<-------EndPath
+Path 3 6 0 1323 191
+Curve 1320 121 1261 90
+<-------EndPath
+Path 3 3 1 1261 90
+Curve 1141 100 1020 110
+Curve 913 109 806 108
+Curve 697 108 587 107
+Curve 564 107 541 107
+<-------EndPath
+Path 3 4 1 541 107
+Curve 451 114 361 120
+<-------EndPath
+Path 3 -1 1 361 120
+Curve 361 121 361 122
+<-------EndPath
+Path 3 4 1 361 122
+Curve 424 136 478 190
+<-------EndPath
+Path 3 2 1 478 190
+Curve 482 190 486 189
+Curve 602 184 717 179
+Curve 833 175 949 170
+Curve 985 169 1020 168
+Curve 1100 171 1180 173
+Curve 1252 182 1323 191
+<-------EndPath
+Path -1 -1 0 1279 314
+Curve 1279 313 1278 311
+<-------EndPath
+Path -1 1 0 1278 311
+Curve 1276 313 1273 315
+Curve 1276 315 1279 314
+<-------EndPath
+Path -1 8 0 1279 314
+Curve 1306 310 1326 298
+<-------EndPath
+Path 1 -1 0 1278 311
+Curve 1285 305 1292 299
+<-------EndPath
+Path 1 2 1 1292 299
+Curve 1051 307 809 314
+<-------EndPath
+Path 1 -1 0 809 314
+Curve 884 344 966 346
+Curve 1094 349 1058 462
+Curve 1044 506 1044 553
+Curve 1044 583 1032 588
+Curve 1067 591 1102 593
+Curve 1145 602 1188 610
+Curve 1249 622 1310 640
+Curve 1325 643 1340 645
+Curve 1343 645 1346 644
+Curve 1354 642 1359 636
+<-------EndPath
+Path 1 8 0 1359 636
+Curve 1361 625 1363 613
+Curve 1354 531 1321 446
+Curve 1293 374 1279 314
+<-------EndPath
+Path -1 8 0 1344 285
+Curve 1402 371 1467 455
+Curve 1516 518 1548 582
+Curve 1499 606 1442 612
+Curve 1393 617 1359 636
+<-------EndPath
+Path 5 3 1 -724 137
+Curve -614 120 -504 102
+Curve -395 86 -285 69
+Curve -179 64 -72 58
+Curve 38 55 148 52
+Curve 150 52 151 52
+Curve 187 50 223 48
+Curve 280 46 336 43
+Curve 358 42 379 41
+Curve 498 35 617 29
+Curve 729 21 842 23
+Curve 938 24 1033 25
+<-------EndPath
+Path 5 -1 -1 1033 25
+Curve 1033 24 1033 23
+<-------EndPath
+Path -1 3 1 1033 25
+Curve 1039 25 1045 25
+<-------EndPath
+Path 4 3 1 541 107
+Curve 499 103 456 98
+Curve 418 97 379 96
+Curve 359 96 338 96
+Curve 282 100 225 103
+Curve 190 107 154 110
+Curve 74 117 -7 124
+Curve -117 136 -226 148
+Curve -345 161 -463 174
+Curve -572 180 -681 185
+<-------EndPath
+Path 4 0 1 -681 185
+Curve -680 186 -679 187
+Curve -666 203 -653 218
+<-------EndPath
+Path 4 3 1 -653 218
+Curve -564 216 -474 213
+Curve -438 215 -402 217
+<-------EndPath
+Path 4 -1 1 -402 217
+Curve -320 215 -238 212
+<-------EndPath
+Path 4 3 1 -238 212
+Curve -131 197 -23 182
+Curve 87 160 183 131
+Curve 224 146 259 163
+<-------EndPath
+Path 4 -1 1 259 163
+Curve 308 157 356 151
+<-------EndPath
+Path 4 4 1 356 151
+Curve 357 136 361 122
+<-------EndPath
+Path 4 -1 1 361 122
+Curve 358 122 355 121
+Curve 358 121 361 120
+<-------EndPath
+Path 6 -1 0 515 322
+Curve 509 339 502 355
+Curve 633 412 723 464
+Curve 733 435 731 392
+Curve 729 352 742 316
+<-------EndPath
+Path 6 2 1 742 316
+Curve 629 319 515 322
+<-------EndPath
+Path -1 2 1 515 322
+Curve -65 340 -644 357
+<-------EndPath
+Path -1 -1 1 -644 357
+Curve -654 357 -664 357
+<-------EndPath
+Path -1 0 1 -664 357
+Curve -666 359 -667 360
+Curve -669 363 -671 365
+Curve -675 370 -679 374
+<-------EndPath
+Path -1 8 1 -679 374
+Curve -618 459 -556 544
+Curve -507 607 -475 671
+Curve -524 695 -581 701
+Curve -630 706 -664 725
+<-------EndPath
+Path -1 6 1 -664 725
+Curve -669 731 -677 733
+Curve -680 734 -683 734
+Curve -693 733 -702 732
+<-------EndPath
+Path -1 6 -1 -702 732
+Curve -704 732 -705 731
+<-------EndPath
+Path -1 1 1 -705 731
+Curve -709 730 -713 729
+Curve -774 714 -835 699
+Curve -878 691 -921 682
+Curve -956 680 -991 677
+Curve -979 672 -979 642
+Curve -979 595 -965 551
+Curve -929 438 -1057 435
+Curve -1155 433 -1244 389
+Curve -1271 375 -1281 404
+Curve -1294 441 -1292 481
+Curve -1290 524 -1300 553
+Curve -1390 501 -1521 444
+Curve -1478 337 -1446 223
+Curve -1420 131 -1401 36
+Curve -1398 16 -1394 -5
+Curve -1376 -108 -1384 -213
+Curve -1390 -303 -1402 -391
+Curve -1443 -378 -1501 -418
+Curve -1580 -471 -1527 -550
+Curve -1517 -563 -1507 -576
+Curve -1507 -576 -1506 -576
+<-------EndPath
+Path -1 6 1 -1506 -576
+Curve -1506 -577 -1506 -577
+Curve -1474 -614 -1438 -628
+Curve -1414 -632 -1389 -636
+<-------EndPath
+Path -1 0 1 -1389 -636
+Curve -1351 -640 -1312 -644
+<-------EndPath
+Path -1 -1 1 -1312 -644
+Curve -1256 -644 -1200 -643
+<-------EndPath
+Path 2 -1 1 742 316
+Curve 776 315 809 314
+<-------EndPath
+Path 4 -1 1 356 151
+Curve 354 174 358 198
+<-------EndPath
+Path 4 2 1 358 198
+Curve 418 194 478 190
+<-------EndPath
+Path 2 -1 1 358 198
+Curve 356 198 354 198
+<-------EndPath
+Path 2 3 1 354 198
+Curve 308 200 261 202
+Curve 151 206 41 210
+Curve -70 217 -180 224
+Curve -208 227 -236 230
+<-------EndPath
+Path 2 -1 1 -236 230
+Curve -320 243 -404 255
+<-------EndPath
+Path 2 3 1 -404 255
+Curve -519 265 -634 274
+<-------EndPath
+Path 2 0 1 -634 274
+Curve -633 299 -644 324
+<-------EndPath
+Path 2 -1 -1 -644 324
+Curve -644 341 -644 357
+<-------EndPath
+Path -1 3 1 259 163
+Curve 306 184 354 198
+<-------EndPath
+Path 1 6 -1 -904 239
+Curve -1014 237 -1129 242
+Curve -1258 247 -1210 198
+Curve -1166 152 -1220 152
+Curve -1352 153 -1339 48
+Curve -1335 13 -1315 -34
+Curve -1261 -155 -1229 -284
+Curve -1212 -354 -1224 -416
+Curve -1237 -478 -1280 -533
+Curve -1282 -535 -1283 -537
+Curve -1285 -539 -1286 -540
+Curve -1296 -551 -1305 -561
+Curve -1324 -575 -1342 -588
+Curve -1361 -599 -1381 -602
+Curve -1436 -612 -1500 -570
+Curve -1503 -573 -1506 -576
+<-------EndPath
+Path 0 6 1 -1344 -633
+Curve -1334 -629 -1324 -625
+Curve -1273 -603 -1239 -564
+Curve -1238 -563 -1237 -562
+Curve -1208 -527 -1194 -479
+Curve -1187 -454 -1180 -428
+Curve -1180 -427 -1179 -426
+Curve -1158 -342 -1148 -255
+Curve -1135 -143 -1122 -31
+Curve -1109 92 -990 112
+Curve -876 131 -777 172
+Curve -695 205 -700 298
+Curve -700 301 -700 304
+<-------EndPath
+Path 0 7 1 -700 304
+Curve -700 305 -700 306
+<-------EndPath
+Path 0 6 1 -700 306
+Curve -702 318 -704 330
+Curve -713 377 -745 400
+<-------EndPath
+Path 0 -1 1 -745 400
+Curve -745 402 -744 403
+<-------EndPath
+Path 0 8 1 -744 403
+Curve -704 397 -679 374
+<-------EndPath
+Path 0 6 1 -1389 -636
+Curve -1383 -636 -1376 -635
+Curve -1362 -632 -1347 -628
+<-------EndPath
+Path 0 6 -1 -1347 -628
+Curve -1346 -631 -1344 -633
+<-------EndPath
+Path 1 1 1 -1402 -391
+Curve -1361 -405 -1337 -473
+Curve -1333 -485 -1337 -494
+Curve -1345 -502 -1353 -510
+Curve -1463 -566 -1434 -458
+<-------EndPath
+Path 4 -1 -1 -1009 -342
+Curve -1008 -327 -1007 -311
+<-------EndPath
+Path -1 5 -1 -1011 -257
+Curve -1004 -259 -997 -260
+<-------EndPath
+Path 0 -1 1 -1011 -257
+Curve -1016 -283 -1021 -308
+Curve -1025 -324 -1029 -340
+<-------EndPath
+Path 4 0 1 -1087 -492
+Curve -1073 -462 -1058 -431
+<-------EndPath
+Path 0 5 1 -999 -181
+Curve -1002 -197 -1004 -212
+Curve -1008 -235 -1011 -257
+<-------EndPath
+Path 0 5 1 -729 148
+Curve -743 141 -757 134
+Curve -758 134 -759 133
+Curve -760 133 -760 133
+Curve -766 131 -771 128
+Curve -857 95 -909 29
+Curve -921 12 -933 -6
+Curve -944 -27 -955 -48
+<-------EndPath
+Path 0 -1 1 -1213 -616
+Curve -1259 -642 -1312 -644
+<-------EndPath
+Path 2 4 -1 -16 -535
+Curve -16 -529 -15 -522
+<-------EndPath
+Path -1 3 -1 -402 217
+Curve -403 236 -404 255
+<-------EndPath
+Path -1 3 -1 -236 230
+Curve -237 221 -238 212
+<-------EndPath
+Path 5 3 -1 -729 148
+Curve -727 143 -724 137
+<-------EndPath
+Path 0 3 1 -681 185
+Curve -703 164 -729 148
+<-------EndPath
+Path 0 -1 1 -664 357
+Curve -654 341 -644 324
+<-------EndPath
+Path -1 6 1 -745 400
+Curve -748 402 -750 404
+Curve -747 404 -744 403
+<-------EndPath
+Path 8 6 1 -744 403
+Curve -730 463 -702 535
+Curve -669 620 -660 702
+Curve -659 717 -664 725
+<-------EndPath
+Path 7 6 -1 -700 304
+Curve -733 301 -766 298
+Curve -733 302 -700 306
+<-------EndPath
+Path 0 3 1 -634 274
+Curve -635 245 -653 218
+<-------EndPath
+Path 1 6 -1 -705 731
+Curve -720 724 -719 651
+Curve -717 577 -774 530
+Curve -831 483 -832 422
+<-------EndPath
+Path 1 6 1 -832 422
+Curve -944 419 -933 319
+Curve -933 319 -933 318
+Curve -933 316 -933 314
+Curve -933 313 -933 312
+Curve -932 306 -931 300
+Curve -923 257 -904 239
+<-------EndPath
+Path 6 6 1 -904 239
+Curve -864 240 -824 241
+Curve -764 273 -766 298
+Curve -769 318 -814 334
+Curve -824 337 -834 340
+Curve -859 346 -867 321
+<-------EndPath
+Path 6 6 1 -750 404
+Curve -775 419 -813 421
+Curve -823 422 -832 422
+<-------EndPath
+!======EndShape
+=======BeginShape
+Path -1 2 -1 2391 3220
+Curve 2390 3220 2389 3220
+Curve 2390 3215 2391 3210
+Curve 2411 3207 2430 3204
+Curve 2439 3203 2447 3202
+Curve 2551 3191 2666 3204
+Curve 2701 3209 2735 3214
+Curve 2744 3216 2753 3217
+<-------EndPath
+Path -1 9 -1 2753 3217
+Curve 2815 3220 2876 3222
+Curve 2875 3226 2874 3229
+<-------EndPath
+Path -1 2 -1 2874 3229
+Curve 2881 3230 2888 3231
+<-------EndPath
+Path -1 2 0 2888 3231
+Curve 2890 3233 2892 3235
+Curve 2902 3250 2911 3265
+Curve 2923 3289 2935 3313
+Curve 2939 3321 2942 3329
+<-------EndPath
+Path -1 3 0 2942 3329
+Curve 2957 3320 2972 3310
+<-------EndPath
+Path -1 -1 0 2972 3310
+Curve 2980 3305 2987 3300
+Curve 2988 3305 2988 3309
+<-------EndPath
+Path -1 3 0 2988 3309
+Curve 2991 3315 2993 3320
+Curve 3019 3357 3055 3384
+Curve 3043 3383 3030 3382
+Curve 3022 3384 3014 3385
+<-------EndPath
+Path -1 9 0 3014 3385
+Curve 3052 3483 3021 3574
+Curve 3012 3597 2999 3610
+<-------EndPath
+Path -1 -1 0 2999 3610
+Curve 3003 3633 3006 3655
+<-------EndPath
+Path -1 11 0 3006 3655
+Curve 3022 3649 3037 3643
+<-------EndPath
+Path -1 12 0 3037 3643
+Curve 3045 3640 3052 3636
+Curve 3080 3694 3085 3739
+Curve 3065 3744 3052 3755
+Curve 3035 3768 3018 3781
+Curve 2998 3723 2977 3664
+Curve 2985 3662 2993 3659
+<-------EndPath
+Path -1 11 0 2993 3659
+Curve 3000 3657 3006 3655
+<-------EndPath
+Path -1 -1 0 2213 3208
+Curve 2219 3205 2225 3201
+<-------EndPath
+Path 0 2 0 2228 3212
+Curve 2227 3215 2226 3217
+Curve 2226 3218 2225 3219
+Curve 2223 3231 2220 3243
+Curve 2217 3249 2214 3254
+Curve 2203 3273 2192 3291
+<-------EndPath
+Path 0 5 0 2192 3291
+Curve 2205 3311 2217 3330
+<-------EndPath
+Path 0 1 -1 2217 3330
+Curve 2219 3329 2220 3328
+Curve 2233 3316 2246 3303
+Curve 2271 3272 2278 3235
+Curve 2281 3236 2284 3237
+Curve 2285 3232 2286 3227
+<-------EndPath
+Path 0 -1 -1 2286 3227
+Curve 2257 3220 2228 3212
+<-------EndPath
+Path 2 -1 -1 2228 3212
+Curve 2221 3210 2213 3208
+<-------EndPath
+Path 2 -1 0 2213 3208
+Curve 2156 3245 2137 3307
+<-------EndPath
+Path 2 -1 -1 2137 3307
+Curve 2138 3308 2138 3308
+<-------EndPath
+Path 2 3 0 2138 3308
+Curve 2164 3295 2184 3302
+<-------EndPath
+Path 2 5 0 2184 3302
+Curve 2188 3297 2192 3291
+<-------EndPath
+Path 3 -1 0 2129 3358
+Curve 2124 3356 2119 3353
+Curve 2117 3347 2114 3340
+Curve 2114 3333 2119 3328
+Curve 2125 3322 2132 3322
+Curve 2138 3322 2144 3328
+Curve 2147 3334 2149 3340
+<-------EndPath
+Path 3 4 0 2149 3340
+Curve 2159 3330 2169 3320
+<-------EndPath
+Path 3 5 0 2169 3320
+Curve 2177 3311 2184 3302
+<-------EndPath
+Path -1 -1 0 2137 3308
+Curve 2137 3308 2137 3307
+<-------EndPath
+Path 3 -1 0 2138 3308
+Curve 2138 3308 2137 3308
+Curve 2052 3340 2073 3441
+<-------EndPath
+Path 3 5 0 2073 3441
+Curve 2075 3435 2077 3429
+Curve 2079 3423 2081 3416
+<-------EndPath
+Path 3 4 0 2081 3416
+Curve 2095 3383 2120 3365
+Curve 2125 3362 2129 3358
+<-------EndPath
+Path -1 4 0 2129 3358
+Curve 2139 3349 2149 3340
+<-------EndPath
+Path 5 1 0 2457 3346
+Curve 2443 3376 2412 3385
+Curve 2411 3386 2409 3386
+Curve 2384 3390 2358 3394
+Curve 2275 3399 2222 3336
+Curve 2220 3333 2217 3330
+<-------EndPath
+Path 5 4 0 2040 3610
+Curve 2061 3594 2081 3578
+Curve 2094 3564 2106 3549
+Curve 2159 3474 2085 3419
+Curve 2083 3418 2081 3416
+<-------EndPath
+Path 5 4 0 2169 3320
+Curve 2168 3355 2176 3383
+Curve 2185 3411 2203 3431
+Curve 2220 3449 2246 3459
+Curve 2283 3475 2341 3475
+Curve 2357 3474 2373 3473
+Curve 2396 3467 2418 3461
+Curve 2491 3428 2500 3322
+<-------EndPath
+Path 5 2 0 2500 3322
+Curve 2500 3322 2499 3321
+Curve 2485 3312 2470 3303
+Curve 2469 3303 2468 3302
+<-------EndPath
+Path 5 0 0 2468 3302
+Curve 2463 3324 2457 3346
+<-------EndPath
+Path 1 0 -1 2457 3346
+Curve 2426 3342 2402 3330
+Curve 2352 3307 2331 3250
+Curve 2327 3249 2323 3248
+Curve 2324 3242 2324 3236
+<-------EndPath
+Path 1 -1 -1 2324 3236
+Curve 2305 3232 2286 3227
+<-------EndPath
+Path -1 2 0 2416 3260
+Curve 2400 3241 2391 3220
+<-------EndPath
+Path -1 0 -1 2324 3236
+Curve 2370 3248 2416 3260
+<-------EndPath
+Path 2 0 0 2416 3260
+Curve 2437 3283 2468 3302
+<-------EndPath
+Path -1 6 0 2021 3952
+Curve 2023 3955 2024 3958
+<-------EndPath
+Path -1 7 0 2024 3958
+Curve 2025 3954 2025 3950
+<-------EndPath
+Path -1 -1 0 2025 3950
+Curve 2023 3951 2021 3952
+<-------EndPath
+Path 6 -1 0 2021 3952
+Curve 1974 3974 1953 4025
+Curve 1941 4056 1928 4087
+<-------EndPath
+Path 6 6 0 1928 4087
+Curve 1941 4117 1954 4147
+Curve 1955 4149 1956 4151
+Curve 1957 4152 1957 4152
+Curve 2012 4155 2055 4191
+Curve 2061 4198 2067 4204
+<-------EndPath
+Path -1 -1 0 1928 4087
+Curve 1921 4068 1914 4048
+Curve 1896 3998 1889 3948
+Curve 1882 3893 1891 3839
+Curve 1900 3790 1909 3741
+Curve 1920 3691 1945 3646
+Curve 1971 3597 2004 3554
+Curve 2034 3517 2063 3479
+<-------EndPath
+Path -1 5 0 2063 3479
+Curve 2063 3479 2063 3478
+Curve 2064 3476 2064 3474
+Curve 2069 3458 2073 3441
+<-------EndPath
+Path 4 4 0 2391 3908
+Curve 2393 3891 2384 3881
+Curve 2358 3848 2375 3802
+Curve 2376 3801 2376 3799
+Curve 2381 3781 2385 3762
+Curve 2385 3758 2385 3754
+Curve 2385 3754 2385 3753
+Curve 2385 3752 2385 3750
+Curve 2385 3735 2384 3719
+Curve 2384 3719 2384 3718
+Curve 2378 3684 2357 3649
+Curve 2346 3629 2342 3608
+Curve 2338 3589 2340 3570
+Curve 2343 3527 2345 3484
+<-------EndPath
+Path 4 -1 0 2040 3610
+Curve 2038 3652 2036 3694
+Curve 2034 3761 2032 3828
+<-------EndPath
+Path 4 1 0 2032 3828
+Curve 2042 3832 2052 3835
+<-------EndPath
+Path 4 7 0 2052 3835
+Curve 2071 3842 2090 3848
+Curve 2190 3880 2300 3898
+<-------EndPath
+Path 4 0 -1 2300 3898
+Curve 2302 3899 2304 3899
+<-------EndPath
+Path 4 7 0 2304 3899
+Curve 2311 3900 2317 3900
+Curve 2354 3904 2391 3908
+Curve 2485 3915 2574 3908
+<-------EndPath
+Path 4 4 0 2574 3908
+Curve 2587 3872 2599 3835
+Curve 2611 3788 2622 3741
+Curve 2631 3693 2640 3644
+Curve 2647 3599 2653 3553
+Curve 2659 3520 2664 3486
+<-------EndPath
+Path 4 5 0 2664 3486
+Curve 2621 3445 2593 3370
+<-------EndPath
+Path 4 2 0 2593 3370
+Curve 2560 3353 2526 3336
+Curve 2513 3329 2500 3322
+<-------EndPath
+Path 5 5 0 2064 3474
+Curve 2064 3477 2063 3479
+<-------EndPath
+Path 5 -1 0 2063 3479
+Curve 2046 3544 2040 3610
+<-------EndPath
+Path 1 -1 0 2032 3828
+Curve 2032 3840 2031 3851
+<-------EndPath
+Path 1 7 -1 2031 3851
+Curve 2042 3843 2052 3835
+<-------EndPath
+Path 7 -1 0 2031 3851
+Curve 2031 3886 2031 3921
+Curve 2028 3935 2025 3948
+Curve 2025 3949 2025 3950
+<-------EndPath
+Path 0 7 -1 2300 3898
+Curve 2300 3899 2300 3899
+Curve 2302 3899 2304 3899
+<-------EndPath
+Path -1 3 -1 2972 3310
+Curve 2980 3310 2988 3309
+<-------EndPath
+Path 10 3 0 2900 3426
+Curve 2887 3435 2874 3443
+Curve 2873 3408 2852 3379
+<-------EndPath
+Path 10 2 0 2852 3379
+Curve 2847 3382 2841 3385
+Curve 2875 3478 2878 3571
+Curve 2879 3579 2879 3586
+Curve 2888 3579 2907 3593
+<-------EndPath
+Path 10 9 0 2907 3593
+Curve 2924 3546 2918 3488
+Curve 2913 3451 2900 3426
+<-------EndPath
+Path 3 9 0 2900 3426
+Curve 2930 3409 2965 3398
+Curve 2990 3392 3014 3385
+<-------EndPath
+Path 3 2 0 2942 3329
+Curve 2909 3349 2876 3368
+Curve 2864 3374 2852 3379
+<-------EndPath
+Path 9 -1 0 2996 3464
+Curve 2993 3472 2989 3480
+Curve 2981 3483 2973 3486
+Curve 2965 3483 2957 3480
+Curve 2950 3473 2950 3464
+Curve 2950 3454 2957 3447
+Curve 2963 3441 2973 3441
+Curve 2983 3441 2989 3447
+Curve 2996 3454 2996 3464
+<-------EndPath
+Path 9 2 0 2753 3217
+Curve 2740 3234 2727 3251
+Curve 2715 3267 2711 3310
+Curve 2706 3359 2712 3444
+Curve 2712 3445 2712 3446
+<-------EndPath
+Path 9 9 0 2712 3446
+Curve 2738 3456 2761 3470
+<-------EndPath
+Path 9 2 0 2761 3470
+Curve 2751 3362 2762 3313
+Curve 2765 3306 2767 3298
+Curve 2795 3219 2874 3229
+<-------EndPath
+Path 9 2 0 2712 3446
+Curve 2713 3455 2713 3463
+<-------EndPath
+Path 9 5 0 2713 3463
+Curve 2736 3488 2759 3512
+Curve 2763 3517 2767 3521
+<-------EndPath
+Path 9 2 0 2767 3521
+Curve 2764 3496 2761 3470
+<-------EndPath
+Path 5 2 0 2713 3463
+Curve 2657 3409 2593 3370
+<-------EndPath
+Path 5 4 0 2664 3486
+Curve 2688 3510 2718 3522
+Curve 2744 3529 2769 3535
+Curve 2774 3536 2779 3536
+<-------EndPath
+Path 5 2 0 2779 3536
+Curve 2773 3529 2767 3521
+<-------EndPath
+Path 7 4 0 2884 3747
+Curve 2865 3772 2845 3796
+Curve 2793 3849 2721 3878
+Curve 2666 3899 2600 3906
+Curve 2587 3907 2574 3908
+<-------EndPath
+Path 7 7 0 2574 3908
+Curve 2568 3923 2561 3938
+Curve 2538 3985 2507 4028
+Curve 2476 4069 2438 4103
+Curve 2426 4116 2414 4128
+<-------EndPath
+Path 7 6 0 2414 4128
+Curve 2461 4133 2508 4137
+Curve 2561 4143 2614 4148
+Curve 2669 4156 2724 4148
+Curve 2770 4141 2815 4134
+<-------EndPath
+Path 7 -1 0 2815 4134
+Curve 2822 4131 2828 4127
+Curve 2854 4110 2879 4092
+<-------EndPath
+Path 7 6 0 2879 4092
+Curve 2887 4083 2895 4074
+Curve 2895 4076 2894 4077
+<-------EndPath
+Path 7 -1 0 2894 4077
+Curve 2896 4076 2897 4074
+Curve 2900 3989 2902 3903
+Curve 2902 3828 2888 3763
+Curve 2886 3755 2884 3747
+<-------EndPath
+Path 4 -1 0 2884 3747
+Curve 2883 3742 2882 3737
+<-------EndPath
+Path 4 8 0 2882 3737
+Curve 2865 3677 2836 3623
+<-------EndPath
+Path 4 2 0 2836 3623
+Curve 2812 3577 2779 3536
+<-------EndPath
+Path 9 -1 0 2907 3593
+Curve 2908 3594 2908 3594
+Curve 2908 3607 2899 3615
+<-------EndPath
+Path 9 2 0 2899 3615
+Curve 2929 3627 2953 3627
+<-------EndPath
+Path 9 -1 0 2953 3627
+Curve 2981 3627 2999 3610
+<-------EndPath
+Path 9 9 0 2999 3610
+Curve 2993 3593 2987 3576
+<-------EndPath
+Path 2 -1 0 2899 3615
+Curve 2903 3604 2907 3593
+<-------EndPath
+Path 2 8 0 2836 3623
+Curve 2849 3629 2862 3635
+Curve 2880 3643 2893 3654
+Curve 2910 3670 2916 3694
+<-------EndPath
+Path 2 -1 0 2916 3694
+Curve 2935 3661 2953 3627
+<-------EndPath
+Path 11 11 0 3029 3659
+Curve 3031 3666 3033 3672
+<-------EndPath
+Path 12 11 0 3037 3643
+Curve 3045 3661 3053 3678
+Curve 3031 3684 3008 3690
+Curve 3001 3675 2993 3659
+<-------EndPath
+Path 12 11 0 3028 3722
+Curve 3030 3718 3031 3713
+Curve 3036 3712 3040 3710
+Curve 3045 3710 3048 3713
+Curve 3050 3718 3052 3722
+Curve 3050 3726 3048 3730
+Curve 3044 3732 3040 3734
+Curve 3035 3734 3031 3730
+Curve 3028 3727 3028 3722
+<-------EndPath
+Path 8 -1 0 2882 3737
+Curve 2889 3730 2895 3722
+Curve 2906 3708 2916 3694
+<-------EndPath
+Path 2 2 0 2841 3385
+Curve 2836 3387 2830 3389
+<-------EndPath
+Path 5 5 0 2664 3486
+Curve 2668 3468 2671 3449
+<-------EndPath
+Path 6 6 0 2879 4092
+Curve 2887 4085 2894 4077
+<-------EndPath
+Path -1 6 0 2894 4077
+Curve 2876 4125 2826 4154
+Curve 2773 4183 2731 4215
+Curve 2688 4247 2653 4287
+Curve 2634 4307 2624 4328
+Curve 2623 4330 2622 4331
+<-------EndPath
+Path -1 6 -1 2622 4331
+Curve 2628 4330 2625 4343
+Curve 2619 4353 2613 4363
+Curve 2613 4364 2613 4364
+<-------EndPath
+Path -1 6 0 2613 4364
+Curve 2612 4369 2611 4374
+Curve 2602 4419 2566 4428
+Curve 2511 4441 2461 4416
+Curve 2414 4393 2357 4390
+Curve 2327 4387 2296 4383
+<-------EndPath
+Path -1 -1 0 2296 4383
+Curve 2279 4424 2278 4486
+Curve 2279 4507 2279 4527
+<-------EndPath
+Path -1 13 0 2279 4527
+Curve 2279 4528 2279 4528
+Curve 2288 4568 2263 4603
+Curve 2228 4644 2192 4685
+Curve 2172 4704 2151 4722
+Curve 2157 4772 2162 4822
+Curve 2169 4862 2176 4902
+<-------EndPath
+Path -1 13 -1 2176 4902
+Curve 2177 4906 2177 4909
+<-------EndPath
+Path -1 13 0 2177 4909
+Curve 2170 4907 2162 4905
+Curve 2131 4878 2106 4844
+Curve 2083 4812 2069 4776
+Curve 2033 4785 1997 4793
+Curve 1998 4745 2041 4711
+Curve 2046 4708 2050 4704
+Curve 2048 4671 2045 4637
+Curve 2045 4584 2076 4543
+<-------EndPath
+Path -1 -1 0 2076 4543
+Curve 2072 4540 2068 4536
+Curve 2067 4536 2065 4535
+Curve 2059 4484 2062 4430
+Curve 2067 4382 2072 4334
+<-------EndPath
+Path -1 6 0 2072 4334
+Curve 2072 4334 2071 4334
+Curve 2030 4321 1993 4299
+Curve 1971 4286 1948 4280
+Curve 1882 4259 1902 4211
+Curve 1902 4206 1901 4201
+Curve 1903 4183 1905 4164
+Curve 1911 4142 1917 4119
+Curve 1923 4103 1928 4087
+<-------EndPath
+Path -1 6 0 2815 4134
+Curve 2822 4133 2828 4131
+Curve 2846 4128 2879 4092
+<-------EndPath
+Path 6 6 0 2613 4364
+Curve 2612 4364 2610 4363
+Curve 2611 4369 2611 4374
+<-------EndPath
+Path 6 6 0 2622 4331
+Curve 2616 4347 2610 4363
+<-------EndPath
+Path 7 7 0 2359 4057
+Curve 2376 4040 2408 4046
+Curve 2407 4071 2381 4073
+<-------EndPath
+Path 6 6 0 2214 4361
+Curve 2220 4359 2225 4357
+Curve 2223 4352 2220 4346
+Curve 2207 4302 2227 4258
+Curve 2231 4251 2235 4243
+Curve 2254 4210 2279 4183
+Curve 2285 4177 2290 4171
+Curve 2294 4168 2298 4164
+<-------EndPath
+Path 6 6 0 2389 4247
+Curve 2372 4210 2383 4171
+Curve 2384 4168 2385 4165
+Curve 2378 4176 2371 4187
+Curve 2357 4210 2351 4236
+<-------EndPath
+Path 6 6 0 2414 4128
+Curve 2399 4143 2387 4161
+Curve 2386 4163 2385 4165
+<-------EndPath
+Path 7 6 0 2024 3958
+Curve 2052 4000 2095 4027
+Curve 2143 4056 2195 4075
+Curve 2244 4091 2292 4106
+Curve 2345 4116 2398 4126
+Curve 2406 4127 2414 4128
+<-------EndPath
+Path -1 6 0 2168 4360
+Curve 2162 4358 2156 4355
+Curve 2123 4348 2090 4340
+Curve 2081 4337 2072 4334
+<-------EndPath
+Path -1 -1 0 2214 4361
+Curve 2211 4362 2207 4362
+<-------EndPath
+Path -1 6 -1 2207 4362
+Curve 2207 4374 2194 4362
+Curve 2194 4362 2193 4361
+<-------EndPath
+Path -1 6 0 2193 4361
+Curve 2185 4360 2177 4359
+<-------EndPath
+Path -1 6 -1 2177 4359
+Curve 2173 4360 2168 4360
+<-------EndPath
+Path -1 -1 0 2168 4360
+Curve 2185 4365 2201 4369
+Curve 2214 4370 2227 4371
+Curve 2237 4372 2246 4372
+<-------EndPath
+Path -1 6 0 2246 4372
+Curve 2239 4368 2231 4364
+<-------EndPath
+Path -1 6 -1 2231 4364
+Curve 2223 4363 2214 4361
+Curve 2211 4361 2207 4360
+Curve 2207 4361 2207 4362
+<-------EndPath
+Path 6 6 0 2207 4362
+Curve 2201 4362 2195 4361
+Curve 2194 4361 2193 4361
+<-------EndPath
+Path 13 -1 -1 2206 4377
+Curve 2220 4382 2231 4390
+Curve 2232 4388 2233 4385
+Curve 2217 4377 2201 4369
+Curve 2204 4373 2206 4377
+<-------EndPath
+Path 6 6 0 2156 4355
+Curve 2167 4357 2177 4359
+<-------EndPath
+Path -1 6 0 2296 4383
+Curve 2275 4379 2253 4375
+Curve 2250 4374 2246 4372
+<-------EndPath
+Path 6 6 0 2231 4364
+Curve 2228 4361 2225 4357
+<-------EndPath
+Path 6 6 0 2383 4171
+Curve 2390 4213 2417 4248
+<-------EndPath
+Path 6 6 0 1956 4151
+Curve 1967 4172 1978 4192
+Curve 1992 4218 1995 4217
+<-------EndPath
+Path -1 13 0 2076 4543
+Curve 2110 4569 2127 4612
+Curve 2128 4615 2129 4618
+Curve 2155 4588 2189 4566
+Curve 2231 4537 2279 4527
+<-------EndPath
+Path 13 13 0 2050 4704
+Curve 2083 4676 2109 4642
+Curve 2119 4630 2129 4618
+Curve 2145 4664 2150 4715
+Curve 2151 4719 2151 4722
+Curve 2129 4739 2107 4756
+Curve 2090 4768 2069 4776
+Curve 2064 4761 2059 4745
+Curve 2055 4725 2050 4704
+<-------EndPath
+Path 6 6 0 2031 4215
+Curve 1999 4181 1957 4152
+<-------EndPath
+!======EndShape
+=======BeginShape
+Path -1 -1 0 1248 -825
+Curve 1227 -864 1206 -902
+Curve 1164 -963 1103 -1001
+Curve 1054 -1033 999 -1050
+Curve 944 -1067 888 -1067
+Curve 829 -1066 770 -1064
+Curve 698 -1061 630 -1038
+Curve 563 -1016 504 -977
+Curve 444 -937 399 -881
+<-------EndPath
+Path -1 2 0 399 -881
+Curve 443 -844 486 -806
+<-------EndPath
+Path -1 -1 0 486 -806
+Curve 490 -809 493 -811
+Curve 498 -814 503 -817
+Curve 507 -820 510 -822
+Curve 555 -849 609 -866
+Curve 674 -889 741 -895
+Curve 803 -894 865 -892
+Curve 932 -881 994 -856
+Curve 1046 -834 1097 -804
+Curve 1144 -776 1186 -739
+Curve 1189 -737 1192 -734
+Curve 1241 -690 1280 -633
+Curve 1305 -597 1305 -564
+<-------EndPath
+Path -1 1 0 -487 -1037
+Curve -418 -1048 -348 -1058
+Curve -317 -1061 -286 -1063
+Curve -237 -1064 -187 -1065
+Curve -139 -1058 -91 -1050
+Curve -24 -1039 44 -1028
+Curve 93 -1016 142 -1003
+Curve 181 -989 219 -975
+<-------EndPath
+Path -1 2 0 219 -975
+Curve 244 -965 269 -954
+Curve 348 -920 383 -893
+Curve 391 -887 399 -881
+<-------EndPath
+Path -1 2 0 486 -806
+Curve 487 -806 487 -805
+Curve 498 -795 509 -784
+Curve 529 -762 548 -739
+<-------EndPath
+Path -1 -1 0 548 -739
+Curve 575 -741 602 -743
+Curve 636 -743 670 -742
+Curve 741 -730 811 -717
+Curve 878 -701 933 -655
+Curve 986 -606 1039 -556
+Curve 1084 -506 1094 -437
+Curve 1104 -368 1097 -311
+<-------EndPath
+Path -1 2 0 548 -739
+Curve 556 -729 564 -718
+Curve 585 -685 606 -652
+Curve 622 -625 623 -598
+Curve 623 -593 623 -588
+Curve 622 -557 601 -527
+Curve 579 -494 550 -466
+Curve 445 -374 310 -362
+Curve 187 -358 63 -354
+Curve 57 -354 51 -354
+Curve -12 -358 -74 -362
+<-------EndPath
+Path -1 2 1 -74 -362
+Curve -94 -364 -113 -366
+<-------EndPath
+Path -1 1 1 -113 -366
+Curve -128 -368 -142 -369
+Curve -156 -368 -170 -366
+Curve -184 -365 -194 -354
+Curve -203 -347 -205 -335
+Curve -205 -321 -205 -306
+Curve -202 -295 -198 -283
+Curve -191 -268 -183 -252
+<-------EndPath
+Path -1 0 1 -183 -252
+Curve -180 -247 -177 -242
+Curve -159 -218 -141 -193
+<-------EndPath
+Path -1 2 1 -141 -193
+Curve -131 -170 -120 -147
+Curve -96 -80 -99 8
+<-------EndPath
+Path -1 0 1 -99 8
+Curve -99 15 -99 21
+Curve -104 60 -109 98
+Curve -111 110 -113 122
+Curve -114 125 -115 128
+Curve -118 144 -121 159
+Curve -128 197 -135 234
+Curve -135 235 -135 235
+<-------EndPath
+Path -1 2 1 -135 235
+Curve -136 237 -136 239
+Curve -142 270 -155 296
+<-------EndPath
+Path -1 4 1 -155 296
+Curve -161 311 -166 326
+<-------EndPath
+Path -1 4 0 -166 326
+Curve -182 378 -177 436
+Curve -172 483 -167 530
+Curve -210 534 -249 517
+Curve -299 495 -349 472
+Curve -351 471 -352 470
+Curve -364 465 -376 459
+Curve -378 459 -379 458
+Curve -384 456 -388 453
+<-------EndPath
+Path -1 2 0 -388 453
+Curve -428 472 -468 491
+Curve -490 500 -512 508
+Curve -566 527 -621 542
+Curve -639 546 -656 550
+Curve -672 554 -687 557
+Curve -726 565 -765 572
+Curve -757 615 -754 660
+Curve -750 719 -755 777
+<-------EndPath
+Path -1 -1 0 -755 777
+Curve -757 793 -758 809
+Curve -759 816 -759 822
+Curve -761 821 -762 819
+<-------EndPath
+Path -1 3 0 -762 819
+Curve -765 839 -767 859
+Curve -774 907 -826 970
+Curve -878 1033 -928 1061
+<-------EndPath
+Path -1 -1 0 -928 1061
+Curve -961 1083 -993 1105
+Curve -970 1075 -947 1044
+<-------EndPath
+Path -1 3 0 -947 1044
+Curve -913 996 -878 948
+Curve -836 894 -793 840
+Curve -779 824 -765 807
+<-------EndPath
+Path -1 -1 0 -765 807
+Curve -768 792 -770 776
+<-------EndPath
+Path -1 2 0 -770 776
+Curve -781 703 -796 654
+Curve -809 618 -821 582
+Curve -843 586 -864 589
+<-------EndPath
+Path -1 2 -1 -864 589
+Curve -870 587 -875 585
+<-------EndPath
+Path -1 2 0 -875 585
+Curve -913 646 -943 714
+Curve -974 782 -1016 848
+Curve -1036 876 -1056 904
+Curve -1084 938 -1112 972
+Curve -1119 979 -1125 986
+<-------EndPath
+Path -1 -1 0 -1125 986
+Curve -1128 998 -1130 1009
+<-------EndPath
+Path -1 3 0 -1130 1009
+Curve -1145 1061 -1166 1109
+Curve -1177 1130 -1187 1150
+Curve -1208 1185 -1257 1193
+Curve -1353 1209 -1449 1190
+Curve -1493 1184 -1537 1177
+Curve -1470 1148 -1391 1126
+Curve -1314 1104 -1238 1108
+Curve -1187 1056 -1136 1004
+<-------EndPath
+Path -1 -1 0 -1136 1004
+Curve -1137 1004 -1137 1004
+Curve -1133 997 -1129 990
+<-------EndPath
+Path -1 2 0 -1129 990
+Curve -1128 988 -1126 986
+Curve -1099 938 -1079 887
+Curve -1055 828 -1030 768
+Curve -1006 716 -982 664
+Curve -955 609 -917 563
+Curve -915 561 -912 559
+Curve -888 539 -848 515
+Curve -858 489 -907 398
+Curve -956 307 -890 318
+Curve -874 322 -858 326
+<-------EndPath
+Path -1 4 0 -858 326
+Curve -807 318 -782 272
+Curve -775 259 -768 246
+Curve -761 233 -753 220
+<-------EndPath
+Path -1 -1 1 -753 220
+Curve -753 218 -753 216
+Curve -753 215 -752 214
+Curve -752 212 -751 210
+Curve -751 210 -750 210
+<-------EndPath
+Path -1 1 1 -750 210
+Curve -755 177 -751 139
+Curve -748 121 -745 103
+<-------EndPath
+Path -1 0 1 -745 103
+Curve -744 100 -743 96
+Curve -743 95 -743 94
+Curve -742 90 -741 85
+Curve -740 79 -739 73
+Curve -735 55 -730 36
+Curve -729 31 -728 26
+Curve -726 18 -723 10
+Curve -706 -45 -674 -91
+Curve -657 -111 -640 -131
+<-------EndPath
+Path -1 1 1 -640 -131
+Curve -610 -157 -580 -182
+Curve -594 -174 -607 -166
+Curve -576 -190 -544 -213
+Curve -513 -236 -481 -258
+<-------EndPath
+Path -1 0 1 -481 -258
+Curve -450 -278 -415 -294
+<-------EndPath
+Path -1 1 1 -415 -294
+Curve -409 -298 -402 -301
+Curve -395 -305 -387 -308
+Curve -351 -323 -333 -352
+Curve -328 -363 -323 -373
+Curve -324 -381 -325 -389
+Curve -345 -420 -377 -436
+Curve -385 -441 -393 -445
+<-------EndPath
+Path -1 1 0 -393 -445
+Curve -439 -465 -485 -485
+Curve -514 -497 -544 -512
+Curve -578 -531 -612 -549
+Curve -641 -567 -670 -585
+Curve -697 -605 -723 -624
+Curve -748 -647 -773 -670
+Curve -795 -694 -816 -718
+Curve -845 -758 -832 -803
+<-------EndPath
+Path -1 -1 0 -832 -803
+Curve -905 -859 -807 -861
+<-------EndPath
+Path -1 1 0 -807 -861
+Curve -805 -864 -803 -866
+Curve -743 -939 -664 -981
+<-------EndPath
+Path -1 -1 0 -664 -981
+Curve -717 -1018 -788 -1032
+Curve -855 -1046 -923 -1030
+Curve -992 -1015 -1055 -983
+Curve -1112 -953 -1162 -912
+Curve -1211 -873 -1243 -818
+Curve -1273 -768 -1282 -717
+<-------EndPath
+Path 2 2 0 548 -739
+Curve 542 -738 536 -737
+<-------EndPath
+Path 2 2 0 544 -632
+Curve 582 -610 583 -593
+Curve 583 -577 548 -566
+<-------EndPath
+Path 2 1 -1 219 -975
+Curve 217 -970 215 -965
+Curve 271 -902 327 -838
+Curve 382 -769 399 -688
+Curve 419 -591 371 -527
+Curve 328 -470 252 -428
+Curve 204 -402 135 -401
+Curve 42 -395 -51 -389
+Curve -81 -385 -111 -381
+Curve -112 -374 -113 -366
+<-------EndPath
+Path -1 -1 1 17 23
+Curve 13 29 9 34
+<-------EndPath
+Path -1 -1 0 -487 -1037
+Curve -489 -1042 -490 -1047
+Curve -510 -1112 -544 -1167
+Curve -577 -1218 -625 -1259
+Curve -679 -1307 -741 -1346
+Curve -797 -1381 -862 -1396
+Curve -930 -1399 -998 -1401
+Curve -1065 -1391 -1126 -1364
+Curve -1157 -1348 -1187 -1332
+<-------EndPath
+Path -1 -1 0 -1305 -1074
+Curve -1300 -1094 -1284 -1109
+Curve -1233 -1160 -1166 -1184
+Curve -1157 -1188 -1147 -1191
+Curve -1091 -1206 -1035 -1221
+Curve -968 -1235 -901 -1220
+Curve -831 -1205 -767 -1173
+Curve -711 -1146 -662 -1108
+Curve -625 -1078 -596 -1040
+Curve -595 -1039 -593 -1037
+Curve -586 -1026 -578 -1015
+<-------EndPath
+Path -1 1 0 -578 -1015
+Curve -571 -1017 -563 -1018
+Curve -525 -1028 -487 -1037
+<-------EndPath
+Path -1 1 0 -832 -803
+Curve -830 -813 -827 -822
+Curve -817 -842 -807 -861
+<-------EndPath
+Path 0 0 1 -587 -69
+Curve -555 -49 -515 -48
+<-------EndPath
+Path 0 1 1 -481 -258
+Curve -465 -211 -510 -168
+Curve -550 -132 -596 -128
+Curve -618 -130 -640 -131
+<-------EndPath
+Path 1 2 -1 -231 -232
+Curve -232 -233 -232 -234
+Curve -241 -253 -242 -277
+Curve -240 -294 -238 -311
+Curve -233 -330 -219 -339
+Curve -217 -337 -215 -335
+Curve -214 -333 -213 -331
+Curve -209 -317 -211 -301
+Curve -211 -300 -211 -298
+Curve -207 -292 -203 -286
+Curve -197 -266 -203 -245
+Curve -204 -243 -204 -241
+Curve -209 -239 -213 -236
+Curve -215 -234 -216 -232
+Curve -217 -231 -218 -229
+Curve -219 -227 -220 -225
+Curve -222 -223 -224 -221
+Curve -227 -226 -230 -230
+<-------EndPath
+Path 1 2 2 -230 -230
+Curve -231 -231 -231 -232
+<-------EndPath
+Path 0 1 1 -183 -252
+Curve -216 -238 -241 -195
+Curve -267 -153 -321 -148
+Curve -376 -144 -400 -168
+Curve -452 -222 -415 -294
+<-------EndPath
+Path 0 0 1 -383 -28
+Curve -346 -11 -304 -12
+<-------EndPath
+Path 0 1 1 -162 7
+Curve -203 -10 -216 -45
+Curve -225 -68 -223 -97
+Curve -220 -132 -204 -154
+Curve -203 -156 -202 -157
+<-------EndPath
+Path 0 2 1 -202 -157
+Curve -182 -184 -141 -193
+<-------EndPath
+Path 2 1 -1 -202 -157
+Curve -199 -154 -196 -150
+Curve -188 -139 -180 -127
+Curve -152 -77 -155 -5
+Curve -159 1 -162 7
+<-------EndPath
+Path 2 0 1 -162 7
+Curve -160 8 -157 9
+Curve -128 9 -99 8
+<-------EndPath
+Path 2 2 1 -168 -135
+Curve -144 -141 -120 -147
+<-------EndPath
+Path -1 1 0 -664 -981
+Curve -624 -1003 -578 -1015
+<-------EndPath
+Path 0 2 1 -222 160
+Curve -194 181 -166 201
+Curve -149 215 -135 235
+<-------EndPath
+Path 2 1 -1 -222 160
+Curve -226 165 -230 170
+Curve -247 223 -304 235
+<-------EndPath
+Path 2 4 1 -304 235
+Curve -291 240 -278 244
+Curve -211 267 -165 303
+<-------EndPath
+Path 2 4 -1 -165 303
+Curve -163 305 -161 306
+<-------EndPath
+Path 2 4 1 -161 306
+Curve -158 301 -155 296
+<-------EndPath
+Path 4 1 2 -304 235
+Curve -309 234 -313 232
+<-------EndPath
+Path 4 1 1 -313 232
+Curve -364 218 -415 210
+Curve -475 203 -534 195
+Curve -541 195 -548 194
+Curve -613 197 -678 200
+Curve -714 205 -750 210
+<-------EndPath
+Path 4 -1 1 -750 210
+Curve -751 213 -751 215
+<-------EndPath
+Path 4 -1 -1 -751 215
+Curve -752 217 -752 218
+Curve -754 223 -755 227
+<-------EndPath
+Path 4 -1 1 -755 227
+Curve -754 224 -753 220
+<-------EndPath
+Path -1 -1 0 -753 220
+Curve -753 219 -752 218
+<-------EndPath
+Path 4 4 0 -206 364
+Curve -249 405 -292 432
+<-------EndPath
+Path 1 1 1 -549 139
+Curve -539 143 -528 147
+<-------EndPath
+Path 0 1 1 -745 103
+Curve -739 101 -733 98
+Curve -582 30 -416 74
+Curve -310 102 -222 160
+<-------EndPath
+Path -1 -1 1 -753 216
+Curve -752 216 -751 215
+<-------EndPath
+Path 4 5 0 -690 359
+Curve -671 360 -651 361
+<-------EndPath
+Path 4 2 0 -651 361
+Curve -645 362 -638 363
+Curve -604 371 -569 379
+Curve -546 385 -524 394
+Curve -514 398 -504 402
+Curve -483 412 -461 421
+Curve -425 437 -388 453
+<-------EndPath
+Path 2 5 0 -651 361
+Curve -652 363 -637 370
+Curve -632 372 -626 374
+Curve -658 367 -690 359
+<-------EndPath
+Path 2 4 0 -690 359
+Curve -736 350 -781 341
+Curve -788 340 -795 339
+Curve -827 333 -858 326
+<-------EndPath
+Path 2 -1 0 -810 432
+Curve -770 446 -723 449
+Curve -699 450 -674 451
+<-------EndPath
+Path 2 5 0 -674 451
+Curve -674 451 -673 450
+<-------EndPath
+Path 2 2 0 -673 450
+Curve -666 447 -659 444
+Curve -648 440 -636 435
+Curve -609 425 -582 414
+Curve -555 405 -527 395
+Curve -526 395 -524 394
+<-------EndPath
+Path 2 5 0 -673 450
+Curve -673 451 -673 451
+Curve -674 451 -674 451
+<-------EndPath
+Path 2 -1 0 -674 451
+Curve -729 474 -784 497
+<-------EndPath
+Path 2 2 0 -784 497
+Curve -782 504 -780 511
+Curve -771 541 -765 572
+<-------EndPath
+Path -1 3 0 -765 807
+Curve -764 811 -763 814
+<-------EndPath
+Path -1 -1 0 -763 814
+Curve -761 807 -759 800
+Curve -762 804 -765 807
+<-------EndPath
+Path -1 3 0 -763 814
+Curve -763 817 -762 819
+<-------EndPath
+Path -1 -1 0 -758 809
+Curve -759 814 -759 819
+Curve -759 821 -759 822
+<-------EndPath
+Path 2 -1 -1 -770 776
+Curve -763 777 -755 777
+<-------EndPath
+Path -1 2 0 -810 432
+Curve -794 463 -784 497
+<-------EndPath
+Path -1 -1 0 -815 107
+Curve -819 114 -823 121
+<-------EndPath
+Path 2 2 0 -849 370
+Curve -843 380 -836 389
+Curve -834 393 -831 396
+Curve -827 403 -823 409
+Curve -817 421 -810 432
+<-------EndPath
+Path 2 2 0 -848 515
+Curve -835 549 -821 582
+<-------EndPath
+Path 3 -1 -1 -947 1044
+Curve -938 1053 -928 1061
+<-------EndPath
+Path 3 -1 0 -1130 1009
+Curve -1133 1007 -1136 1004
+<-------EndPath
+Path -1 2 0 -1125 986
+Curve -1127 988 -1129 990
+<-------EndPath
+!======EndShape
+=======BeginShape
+Path -1 -1 0 -2883 -474
+Curve -2871 -520 -2858 -565
+Curve -2831 -639 -2777 -696
+Curve -2734 -742 -2681 -774
+Curve -2628 -806 -2569 -821
+Curve -2507 -835 -2445 -848
+Curve -2369 -853 -2292 -858
+Curve -2217 -853 -2144 -827
+Curve -2072 -801 -2010 -754
+<-------EndPath
+Path -1 1 0 -2010 -754
+Curve -2003 -763 -1996 -771
+Curve -1966 -808 -1893 -864
+Curve -1869 -882 -1845 -899
+Curve -1809 -924 -1773 -948
+Curve -1725 -974 -1676 -1000
+Curve -1609 -1030 -1541 -1059
+Curve -1527 -1066 -1513 -1073
+Curve -1479 -1086 -1445 -1099
+Curve -1393 -1111 -1341 -1123
+Curve -1308 -1129 -1274 -1134
+<-------EndPath
+Path -1 0 0 -1274 -1134
+Curve -1199 -1142 -1124 -1149
+<-------EndPath
+Path -1 -1 0 -1124 -1149
+Curve -1124 -1154 -1123 -1159
+Curve -1120 -1232 -1098 -1299
+Curve -1078 -1361 -1038 -1417
+Curve -994 -1481 -939 -1538
+Curve -890 -1589 -825 -1622
+Curve -760 -1658 -685 -1663
+Curve -614 -1660 -542 -1657
+Curve -506 -1648 -469 -1639
+<-------EndPath
+Path -1 -1 0 -2081 -653
+Curve -2085 -655 -2089 -656
+Curve -2095 -658 -2101 -660
+Curve -2106 -662 -2110 -663
+Curve -2168 -674 -2225 -684
+Curve -2298 -682 -2371 -679
+Curve -2439 -669 -2500 -643
+Curve -2567 -615 -2625 -573
+Curve -2674 -536 -2718 -491
+Curve -2762 -449 -2795 -400
+Curve -2798 -397 -2800 -393
+Curve -2841 -334 -2866 -265
+Curve -2883 -221 -2874 -186
+<-------EndPath
+Path -1 -1 0 -2128 -567
+Curve -2157 -562 -2186 -556
+Curve -2221 -547 -2256 -538
+Curve -2330 -512 -2397 -475
+Curve -2463 -440 -2509 -378
+Curve -2556 -317 -2593 -247
+Curve -2628 -183 -2620 -108
+Curve -2612 -34 -2590 24
+<-------EndPath
+Path 1 -1 0 -2010 -754
+Curve -2046 -704 -2081 -653
+Curve -2082 -652 -2082 -651
+Curve -2091 -638 -2099 -624
+Curve -2114 -596 -2128 -567
+<-------EndPath
+Path 1 1 0 -2128 -567
+Curve -2122 -568 -2115 -568
+<-------EndPath
+Path -1 1 0 -1273 -269
+Curve -1261 -288 -1248 -306
+Curve -1236 -333 -1248 -356
+Curve -1250 -357 -1252 -358
+Curve -1267 -361 -1281 -364
+Curve -1296 -362 -1310 -360
+Curve -1325 -355 -1340 -349
+Curve -1360 -342 -1379 -335
+Curve -1446 -318 -1508 -294
+Curve -1513 -293 -1517 -292
+Curve -1519 -292 -1520 -291
+Curve -1621 -262 -1724 -244
+Curve -1753 -240 -1781 -235
+Curve -1926 -212 -2059 -281
+Curve -2094 -306 -2129 -331
+Curve -2159 -357 -2167 -390
+Curve -2168 -392 -2168 -394
+Curve -2169 -397 -2170 -399
+Curve -2176 -428 -2166 -460
+Curve -2153 -500 -2140 -540
+Curve -2134 -554 -2128 -567
+<-------EndPath
+Path 1 1 0 -2096 -456
+Curve -2130 -423 -2126 -405
+Curve -2123 -388 -2083 -386
+<-------EndPath
+Path -1 -1 0 -278 -1401
+Curve -294 -1417 -310 -1432
+Curve -377 -1472 -453 -1480
+Curve -464 -1481 -474 -1481
+Curve -537 -1483 -599 -1484
+Curve -674 -1482 -739 -1448
+Curve -809 -1414 -867 -1364
+Curve -919 -1321 -960 -1268
+Curve -990 -1227 -1011 -1180
+Curve -1012 -1178 -1013 -1176
+Curve -1018 -1163 -1023 -1149
+<-------EndPath
+Path -1 0 0 -1023 -1149
+Curve -974 -1143 -924 -1137
+<-------EndPath
+Path -1 -1 0 -924 -1137
+Curve -879 -1189 -808 -1222
+Curve -742 -1254 -666 -1255
+Curve -591 -1248 -516 -1240
+Curve -449 -1224 -386 -1194
+Curve -325 -1167 -276 -1118
+Curve -233 -1073 -210 -1021
+<-------EndPath
+Path 0 -1 0 -743 -1048
+Curve -746 -1050 -749 -1052
+Curve -831 -1113 -924 -1137
+<-------EndPath
+Path 0 0 0 -702 -994
+Curve -708 -1003 -713 -1012
+Curve -725 -1032 -743 -1048
+<-------EndPath
+Path -1 0 0 -743 -1048
+Curve -640 -1071 -702 -994
+Curve -677 -950 -697 -901
+Curve -710 -869 -729 -839
+Curve -749 -809 -769 -778
+Curve -792 -751 -815 -723
+Curve -841 -697 -866 -671
+Curve -897 -643 -927 -615
+Curve -955 -593 -982 -571
+Curve -1025 -538 -1068 -505
+Curve -1075 -498 -1082 -491
+Curve -1111 -466 -1124 -429
+Curve -1124 -423 -1123 -416
+Curve -1115 -397 -1100 -383
+Curve -1098 -381 -1096 -379
+<-------EndPath
+Path -1 -1 0 -1096 -379
+Curve -1075 -369 -1054 -359
+<-------EndPath
+Path -1 0 0 -1054 -359
+Curve -999 -330 -949 -291
+<-------EndPath
+Path -1 4 0 -949 -291
+Curve -929 -275 -909 -258
+Curve -840 -198 -789 -122
+Curve -780 -108 -771 -94
+Curve -744 -50 -724 7
+<-------EndPath
+Path -1 0 0 -724 7
+Curve -709 52 -697 127
+<-------EndPath
+Path -1 -1 0 -697 127
+Curve -621 185 -545 243
+<-------EndPath
+Path 0 1 -1 -1274 -1134
+Curve -1273 -1115 -1271 -1096
+Curve -1240 -1098 -1209 -1099
+Curve -1050 -1105 -905 -1051
+Curve -740 -990 -850 -832
+Curve -938 -705 -1054 -619
+Curve -1162 -539 -1159 -387
+Curve -1159 -386 -1159 -385
+Curve -1157 -323 -1103 -295
+Curve -1041 -263 -985 -218
+<-------EndPath
+Path 0 -1 -1 -985 -218
+Curve -977 -212 -968 -205
+<-------EndPath
+Path 0 4 0 -968 -205
+Curve -943 -230 -949 -291
+<-------EndPath
+Path 0 -1 0 -1023 -1149
+Curve -1031 -1149 -1039 -1149
+Curve -1082 -1149 -1124 -1149
+<-------EndPath
+Path 4 1 -1 -1264 -263
+Curve -1269 -266 -1273 -269
+<-------EndPath
+Path 4 -1 0 -1273 -269
+Curve -1283 -257 -1292 -244
+Curve -1316 -213 -1330 -178
+Curve -1341 -144 -1352 -110
+Curve -1354 -101 -1355 -91
+<-------EndPath
+Path 4 1 0 -1355 -91
+Curve -1348 -94 -1341 -96
+Curve -1339 -97 -1337 -97
+Curve -1256 -211 -1209 -204
+Curve -1182 -200 -1166 -153
+Curve -1126 -27 -1218 21
+Curve -1310 69 -1364 -53
+<-------EndPath
+Path 4 -1 0 -1364 -53
+Curve -1370 -19 -1375 15
+Curve -1380 98 -1385 181
+Curve -1385 182 -1385 182
+<-------EndPath
+Path 4 1 -1 -1385 182
+Curve -1380 182 -1375 182
+<-------EndPath
+Path 4 1 0 -1375 182
+Curve -1274 214 -1174 203
+Curve -1075 191 -966 161
+Curve -884 139 -787 62
+<-------EndPath
+Path 4 0 0 -787 62
+Curve -756 35 -724 7
+<-------EndPath
+Path -1 1 0 -1364 -53
+Curve -1363 -57 -1361 -61
+Curve -1360 -64 -1359 -67
+Curve -1357 -79 -1355 -91
+<-------EndPath
+Path -1 -1 0 -1355 -91
+Curve -1427 -65 -1495 -25
+Curve -1604 41 -1708 114
+Curve -1878 232 -1674 253
+Curve -1539 266 -1409 301
+Curve -1396 305 -1382 308
+<-------EndPath
+Path -1 1 0 -1382 308
+Curve -1388 255 -1386 201
+Curve -1386 192 -1385 182
+<-------EndPath
+Path 1 1 0 -1337 -97
+Curve -1296 -109 -1254 -120
+<-------EndPath
+Path 0 -1 0 -1054 -359
+Curve -1062 -362 -1069 -364
+Curve -1083 -372 -1096 -379
+<-------EndPath
+Path 4 1 0 -1008 -187
+Curve -1076 -181 -1133 -218
+Curve -1160 -236 -1192 -247
+Curve -1193 -247 -1193 -247
+Curve -1195 -248 -1196 -248
+Curve -1230 -256 -1264 -263
+<-------EndPath
+Path -1 1 -1 -985 -218
+Curve -997 -203 -1008 -187
+<-------EndPath
+Path -1 4 0 -1008 -187
+Curve -983 -190 -968 -205
+<-------EndPath
+Path -1 -1 0 -904 -267
+Curve -769 -270 -637 -242
+Curve -438 -199 -538 -83
+Curve -613 4 -687 90
+Curve -627 96 -566 101
+<-------EndPath
+Path -1 2 0 -686 199
+Curve -685 212 -683 225
+Curve -667 371 -595 383
+Curve -642 489 -717 530
+<-------EndPath
+Path -1 0 0 -717 530
+Curve -717 587 -725 645
+Curve -735 708 -745 771
+Curve -754 820 -754 870
+Curve -752 877 -750 883
+Curve -740 928 -729 972
+Curve -712 1043 -717 1116
+Curve -720 1162 -723 1207
+Curve -726 1239 -728 1270
+Curve -730 1337 -731 1404
+<-------EndPath
+Path -1 -1 0 -731 1404
+Curve -729 1405 -727 1406
+Curve -726 1411 -725 1415
+Curve -728 1416 -731 1416
+<-------EndPath
+Path -1 3 0 -731 1416
+Curve -734 1417 -736 1417
+Curve -799 1421 -861 1424
+Curve -940 1411 -1019 1398
+Curve -1087 1383 -1154 1368
+Curve -1192 1357 -1229 1346
+Curve -1182 1328 -1131 1327
+Curve -1071 1331 -1011 1334
+Curve -994 1337 -977 1339
+Curve -908 1352 -838 1365
+Curve -807 1374 -776 1383
+Curve -755 1391 -735 1402
+<-------EndPath
+Path -1 0 0 -735 1402
+Curve -757 1303 -779 1203
+Curve -798 1113 -804 1014
+Curve -810 915 -816 816
+Curve -818 798 -819 779
+Curve -826 715 -842 651
+Curve -850 619 -858 587
+<-------EndPath
+Path -1 2 0 -858 587
+Curve -887 586 -915 584
+<-------EndPath
+Path -1 3 0 -915 584
+Curve -998 610 -1081 635
+Curve -1094 639 -1107 642
+Curve -1127 646 -1146 650
+<-------EndPath
+Path -1 -1 0 -1146 650
+Curve -1150 658 -1153 665
+<-------EndPath
+Path -1 0 0 -1153 665
+Curve -1219 862 -1252 924
+Curve -1267 954 -1281 983
+Curve -1271 1127 -1364 1261
+Curve -1424 1347 -1484 1432
+Curve -1436 1326 -1407 1245
+Curve -1398 1215 -1389 1185
+Curve -1351 1046 -1329 904
+Curve -1306 782 -1283 660
+<-------EndPath
+Path -1 -1 0 -1283 660
+Curve -1286 660 -1288 659
+<-------EndPath
+Path -1 3 0 -1288 659
+Curve -1368 655 -1438 625
+Curve -1434 621 -1430 616
+<-------EndPath
+Path -1 2 0 -1430 616
+Curve -1355 518 -1344 474
+<-------EndPath
+Path -1 -1 0 -1344 474
+Curve -1351 445 -1358 415
+<-------EndPath
+Path -1 2 0 -1358 415
+Curve -1363 398 -1368 380
+<-------EndPath
+Path -1 -1 0 -1368 380
+Curve -1371 384 -1374 388
+Curve -1392 413 -1410 437
+<-------EndPath
+Path 0 -1 0 -686 199
+Curve -692 163 -697 127
+<-------EndPath
+Path 0 1 -1 -787 62
+Curve -783 97 -779 131
+Curve -773 271 -876 351
+<-------EndPath
+Path 0 2 0 -876 351
+Curve -778 317 -686 199
+<-------EndPath
+Path -1 -1 0 -687 104
+Curve -632 144 -560 160
+<-------EndPath
+Path 0 2 0 -717 530
+Curve -741 541 -764 551
+Curve -812 568 -859 584
+Curve -859 585 -858 586
+<-------EndPath
+Path 0 -1 0 -858 586
+Curve -857 587 -856 587
+Curve -857 587 -858 587
+<-------EndPath
+Path 2 -1 0 -858 587
+Curve -858 587 -858 586
+<-------EndPath
+Path 2 1 0 -876 351
+Curve -888 354 -899 357
+Curve -1009 383 -1121 378
+Curve -1236 366 -1351 353
+<-------EndPath
+Path 2 -1 0 -1351 353
+Curve -1360 367 -1368 380
+<-------EndPath
+Path -1 -1 0 -1368 380
+Curve -1372 367 -1376 353
+Curve -1410 380 -1443 407
+<-------EndPath
+Path -1 -1 0 -1376 353
+Curve -1374 351 -1372 349
+Curve -1375 349 -1377 348
+Curve -1377 351 -1376 353
+<-------EndPath
+Path -1 -1 0 -1372 349
+Curve -1357 334 -1341 319
+Curve -1360 325 -1379 331
+Curve -1378 340 -1377 348
+<-------EndPath
+Path -1 1 0 -1351 353
+Curve -1345 336 -1339 318
+<-------EndPath
+Path -1 -1 0 -1339 318
+Curve -1340 319 -1341 319
+<-------EndPath
+Path 1 -1 0 -1382 308
+Curve -1361 313 -1339 318
+<-------EndPath
+Path -1 -1 0 -1382 308
+Curve -1381 320 -1379 331
+Curve -1462 358 -1541 394
+<-------EndPath
+Path -1 -1 0 -1372 349
+Curve -1362 351 -1351 353
+<-------EndPath
+Path 2 -1 0 -1358 415
+Curve -1351 443 -1343 470
+Curve -1344 472 -1344 474
+<-------EndPath
+Path 0 -1 0 -1279 628
+Curve -1281 644 -1283 660
+<-------EndPath
+Path 3 -1 0 -1288 659
+Curve -1284 644 -1279 628
+<-------EndPath
+Path 3 0 0 -1279 628
+Curve -1269 598 -1259 568
+<-------EndPath
+Path 3 0 -1 -1259 568
+Curve -1256 562 -1252 556
+<-------EndPath
+Path 3 2 0 -1252 556
+Curve -1349 561 -1430 616
+<-------EndPath
+Path 0 0 0 -1281 983
+Curve -1283 972 -1284 961
+<-------EndPath
+Path 3 2 0 -915 584
+Curve -955 580 -994 576
+Curve -1057 569 -1120 562
+<-------EndPath
+Path 3 0 0 -1120 562
+Curve -1130 593 -1139 624
+<-------EndPath
+Path 3 -1 0 -1139 624
+Curve -1143 637 -1146 650
+<-------EndPath
+Path -1 -1 0 -1146 650
+Curve -1147 650 -1148 650
+<-------EndPath
+Path -1 0 0 -1148 650
+Curve -1151 658 -1153 665
+<-------EndPath
+Path 2 0 0 -1252 556
+Curve -1231 556 -1210 556
+Curve -1165 559 -1120 562
+<-------EndPath
+Path -1 0 0 -1139 624
+Curve -1144 637 -1148 650
+<-------EndPath
+Path -1 0 0 -731 1404
+Curve -733 1403 -735 1402
+<-------EndPath
+Path -1 3 0 -735 1402
+Curve -733 1409 -731 1416
+<-------EndPath
+Path -1 -1 0 -731 1416
+Curve -731 1410 -731 1404
+<-------EndPath
+Path 3 -1 0 -1796 1387
+Curve -1949 1375 -2096 1407
+Curve -2131 1415 -2160 1432
+Curve -2055 1472 -1930 1478
+Curve -1793 1474 -1655 1470
+Curve -1569 1457 -1482 1444
+Curve -1565 1420 -1647 1406
+Curve -1722 1397 -1796 1387
+<-------EndPath
+!======EndShape
+=======BeginShape
+Path -1 -1 0 423 -1034
+Curve 424 -1039 424 -1044
+Curve 427 -1116 449 -1182
+Curve 469 -1242 509 -1297
+Curve 553 -1360 608 -1416
+Curve 657 -1466 722 -1498
+Curve 787 -1533 862 -1538
+Curve 934 -1535 1005 -1532
+Curve 1042 -1524 1078 -1515
+<-------EndPath
+Path -1 -1 0 623 -1022
+Curve 668 -1074 739 -1106
+Curve 805 -1137 881 -1138
+Curve 956 -1131 1031 -1124
+Curve 1098 -1108 1161 -1079
+Curve 1222 -1052 1271 -1004
+Curve 1314 -960 1337 -909
+<-------EndPath
+Path -1 -1 0 1269 -1281
+Curve 1257 -1300 1237 -1312
+Curve 1170 -1351 1094 -1359
+Curve 1084 -1360 1073 -1360
+Curve 1011 -1362 948 -1363
+Curve 873 -1360 808 -1327
+Curve 738 -1294 680 -1245
+Curve 628 -1203 587 -1151
+Curve 557 -1111 536 -1064
+Curve 535 -1063 534 -1061
+Curve 529 -1048 524 -1034
+<-------EndPath
+Path -1 0 0 524 -1034
+Curve 574 -1028 623 -1022
+Curve 716 -999 798 -939
+Curve 801 -937 804 -935
+Curve 907 -958 845 -882
+Curve 870 -839 850 -791
+Curve 834 -761 818 -730
+Curve 798 -700 778 -670
+Curve 755 -643 732 -616
+Curve 707 -591 681 -565
+Curve 651 -538 620 -510
+Curve 593 -489 565 -467
+Curve 522 -435 479 -402
+Curve 472 -396 465 -389
+Curve 436 -364 423 -328
+Curve 424 -322 424 -315
+Curve 432 -296 447 -283
+Curve 449 -281 451 -279
+<-------EndPath
+Path -1 -1 0 451 -279
+Curve 472 -269 493 -259
+<-------EndPath
+Path -1 0 0 493 -259
+Curve 546 -226 598 -192
+<-------EndPath
+Path -1 2 0 598 -192
+Curve 618 -176 638 -160
+Curve 707 -101 758 -26
+Curve 767 -13 776 1
+Curve 796 41 816 81
+Curve 820 91 823 100
+<-------EndPath
+Path -1 0 0 823 100
+Curve 838 145 850 220
+<-------EndPath
+Path -1 -1 0 850 220
+Curve 926 278 1002 336
+<-------EndPath
+Path 1 -1 0 273 -1019
+Curve 240 -1014 206 -1009
+Curve 154 -997 102 -985
+Curve 68 -973 34 -960
+Curve 20 -953 6 -946
+Curve -62 -917 -129 -888
+Curve -178 -863 -226 -837
+Curve -262 -813 -298 -789
+Curve -322 -772 -346 -754
+Curve -419 -700 -449 -663
+Curve -456 -655 -463 -646
+Curve -499 -597 -534 -548
+Curve -535 -547 -535 -546
+Curve -544 -533 -552 -519
+Curve -567 -491 -581 -463
+<-------EndPath
+Path 1 1 0 -581 -463
+Curve -575 -464 -568 -464
+<-------EndPath
+Path 0 -1 0 524 -1034
+Curve 516 -1034 508 -1034
+Curve 466 -1034 423 -1034
+Curve 348 -1027 273 -1019
+<-------EndPath
+Path 0 1 -1 273 -1019
+Curve 275 -1001 276 -982
+Curve 307 -984 338 -985
+Curve 497 -991 642 -938
+Curve 807 -878 697 -723
+Curve 609 -598 493 -514
+Curve 385 -435 388 -286
+Curve 388 -285 388 -284
+Curve 390 -224 444 -196
+Curve 506 -165 562 -121
+<-------EndPath
+Path 0 -1 -1 562 -121
+Curve 571 -115 579 -108
+<-------EndPath
+Path 0 2 0 579 -108
+Curve 604 -133 598 -192
+<-------EndPath
+Path -1 1 0 274 -171
+Curve 287 -189 299 -207
+Curve 311 -233 299 -256
+Curve 297 -257 295 -258
+Curve 281 -261 266 -264
+Curve 252 -262 237 -260
+Curve 222 -255 207 -249
+Curve 188 -243 168 -236
+Curve 104 -216 39 -195
+Curve 35 -195 30 -194
+Curve 29 -193 27 -192
+Curve -74 -164 -177 -146
+Curve -206 -142 -234 -137
+Curve -379 -115 -512 -183
+Curve -547 -207 -582 -231
+Curve -612 -257 -620 -289
+Curve -621 -291 -621 -293
+Curve -622 -296 -623 -299
+Curve -629 -326 -619 -358
+Curve -606 -397 -593 -436
+Curve -587 -450 -581 -463
+<-------EndPath
+Path -1 -1 0 -581 -463
+Curve -610 -458 -639 -453
+Curve -674 -444 -709 -434
+Curve -783 -409 -850 -373
+Curve -916 -339 -962 -278
+Curve -1009 -217 -1046 -149
+Curve -1081 -87 -1073 -13
+Curve -1068 38 -1055 82
+Curve -1049 100 -1043 117
+<-------EndPath
+Path 2 1 0 539 -90
+Curve 471 -84 414 -120
+Curve 387 -138 355 -149
+Curve 355 -149 354 -149
+Curve 353 -150 351 -150
+Curve 317 -158 283 -165
+<-------EndPath
+Path 2 1 -1 283 -165
+Curve 279 -168 274 -171
+<-------EndPath
+Path 2 -1 0 274 -171
+Curve 265 -159 255 -146
+Curve 231 -116 217 -81
+Curve 206 -48 195 -14
+Curve 194 -5 192 4
+<-------EndPath
+Path 2 1 0 192 4
+Curve 199 2 206 -1
+Curve 208 -2 210 -2
+Curve 291 -114 338 -107
+Curve 365 -103 381 -57
+Curve 410 32 371 81
+Curve 371 82 370 82
+Curve 354 101 329 114
+Curve 255 152 206 82
+Curve 206 82 205 81
+Curve 194 61 183 41
+<-------EndPath
+Path 2 -1 0 183 41
+Curve 179 61 175 81
+Curve 175 82 175 82
+Curve 174 95 172 108
+Curve 167 191 162 274
+Curve 162 275 162 275
+<-------EndPath
+Path 2 1 -1 162 275
+Curve 167 275 172 275
+<-------EndPath
+Path 2 1 0 172 275
+Curve 273 307 373 296
+Curve 472 284 581 254
+Curve 663 232 760 155
+<-------EndPath
+Path 2 0 0 760 155
+Curve 792 128 823 100
+<-------EndPath
+Path 1 1 0 210 -2
+Curve 252 -13 293 -24
+<-------EndPath
+Path 0 -1 0 493 -259
+Curve 486 -262 478 -264
+Curve 463 -270 451 -279
+<-------EndPath
+Path -1 1 -1 562 -121
+Curve 551 -106 539 -90
+<-------EndPath
+Path -1 2 0 539 -90
+Curve 564 -93 579 -108
+<-------EndPath
+Path 0 0 0 845 -882
+Curve 840 -891 834 -900
+Curve 819 -918 804 -935
+<-------EndPath
+Path -1 -1 0 643 -168
+Curve 778 -171 910 -144
+Curve 1109 -102 1009 12
+Curve 979 47 949 82
+Curve 905 133 860 183
+Curve 921 178 981 194
+<-------EndPath
+Path -1 4 0 861 292
+Curve 863 305 864 318
+Curve 880 464 952 476
+Curve 905 582 830 623
+<-------EndPath
+Path -1 0 0 830 623
+Curve 830 680 822 738
+Curve 812 801 802 864
+Curve 793 913 793 963
+Curve 795 970 797 976
+Curve 808 1021 818 1065
+Curve 835 1136 830 1209
+Curve 827 1255 824 1300
+Curve 822 1332 819 1363
+Curve 815 1414 816 1497
+<-------EndPath
+Path -1 -1 0 816 1497
+Curve 818 1498 820 1499
+Curve 821 1504 822 1508
+Curve 819 1509 816 1509
+<-------EndPath
+Path -1 3 0 816 1509
+Curve 814 1510 811 1510
+Curve 749 1514 686 1517
+Curve 607 1504 528 1491
+Curve 461 1476 393 1461
+Curve 356 1450 318 1439
+Curve 365 1421 416 1420
+Curve 476 1424 536 1427
+Curve 553 1430 570 1432
+Curve 640 1445 709 1458
+Curve 740 1467 771 1476
+Curve 792 1484 812 1495
+<-------EndPath
+Path -1 0 0 812 1495
+Curve 790 1396 768 1296
+Curve 749 1206 743 1107
+Curve 737 1008 731 909
+Curve 730 891 728 872
+Curve 721 808 705 744
+Curve 697 712 689 680
+<-------EndPath
+Path -1 4 0 689 680
+Curve 661 679 632 677
+<-------EndPath
+Path -1 3 0 632 677
+Curve 549 703 466 728
+Curve 453 732 440 735
+Curve 421 739 401 743
+<-------EndPath
+Path -1 -1 0 401 743
+Curve 398 751 394 758
+<-------EndPath
+Path -1 0 0 394 758
+Curve 328 955 295 1017
+Curve 281 1047 266 1076
+Curve 276 1220 183 1354
+Curve 123 1440 63 1525
+Curve 102 1432 140 1338
+Curve 149 1308 158 1278
+Curve 196 1139 218 997
+Curve 241 875 264 753
+<-------EndPath
+Path -1 -1 0 264 753
+Curve 262 753 259 752
+<-------EndPath
+Path -1 3 0 259 752
+Curve 179 748 109 718
+Curve 113 714 117 709
+<-------EndPath
+Path -1 4 0 117 709
+Curve 192 611 203 567
+<-------EndPath
+Path -1 -1 0 203 567
+Curve 196 538 189 508
+<-------EndPath
+Path -1 4 0 189 508
+Curve 184 491 179 473
+<-------EndPath
+Path -1 -1 0 179 473
+Curve 176 477 173 481
+Curve 155 506 137 530
+<-------EndPath
+Path -1 -1 0 860 197
+Curve 915 237 987 253
+<-------EndPath
+Path -1 0 0 850 220
+Curve 856 256 861 292
+<-------EndPath
+Path 4 0 0 861 292
+Curve 769 410 671 444
+<-------EndPath
+Path 4 1 0 671 444
+Curve 660 447 648 450
+Curve 538 476 426 471
+Curve 311 459 196 446
+<-------EndPath
+Path 4 -1 0 196 446
+Curve 188 460 179 473
+<-------EndPath
+Path -1 -1 0 179 473
+Curve 175 460 171 446
+Curve 138 473 104 500
+<-------EndPath
+Path 0 1 -1 760 155
+Curve 764 190 768 224
+Curve 774 364 671 444
+<-------EndPath
+Path 1 -1 0 192 4
+Curve 190 16 188 28
+Curve 187 31 186 33
+Curve 185 37 183 41
+<-------EndPath
+Path -1 -1 0 6 487
+Curve 85 451 168 424
+Curve 167 413 165 401
+Curve 152 398 138 394
+Curve 8 359 -127 346
+Curve -331 325 -161 207
+Curve -67 141 31 81
+Curve 42 75 52 69
+Curve 120 29 192 4
+<-------EndPath
+Path 1 -1 0 162 275
+Curve 162 285 161 294
+Curve 159 348 165 401
+Curve 187 406 208 411
+Curve 202 429 196 446
+<-------EndPath
+Path -1 -1 0 196 446
+Curve 186 444 175 442
+Curve 173 444 171 446
+Curve 171 444 170 441
+Curve 169 433 168 424
+Curve 187 418 206 412
+Curve 207 412 208 411
+<-------EndPath
+Path -1 -1 0 170 441
+Curve 173 442 175 442
+Curve 191 427 206 412
+<-------EndPath
+Path 0 3 0 288 661
+Curve 278 691 268 721
+<-------EndPath
+Path 0 -1 0 268 721
+Curve 266 737 264 753
+<-------EndPath
+Path 4 -1 0 189 508
+Curve 197 536 204 563
+Curve 204 565 203 567
+<-------EndPath
+Path 3 0 -1 288 661
+Curve 292 655 295 649
+<-------EndPath
+Path 3 4 0 295 649
+Curve 198 654 117 709
+<-------EndPath
+Path 4 0 0 295 649
+Curve 316 649 337 649
+Curve 382 652 427 655
+<-------EndPath
+Path 4 3 0 427 655
+Curve 490 662 553 669
+Curve 593 673 632 677
+<-------EndPath
+Path 0 -1 0 394 758
+Curve 397 751 399 743
+Curve 404 730 408 717
+<-------EndPath
+Path 0 3 0 408 717
+Curve 418 686 427 655
+<-------EndPath
+Path -1 -1 0 399 743
+Curve 400 743 401 743
+<-------EndPath
+Path -1 3 0 401 743
+Curve 405 730 408 717
+<-------EndPath
+Path -1 3 0 268 721
+Curve 264 737 259 752
+<-------EndPath
+Path 4 -1 0 689 680
+Curve 689 680 689 679
+<-------EndPath
+Path 4 0 0 689 679
+Curve 689 678 688 677
+Curve 736 661 783 644
+Curve 807 634 830 623
+<-------EndPath
+Path 0 -1 0 689 679
+Curve 690 680 691 680
+Curve 690 680 689 680
+<-------EndPath
+Path 0 0 0 263 1054
+Curve 265 1065 266 1076
+<-------EndPath
+Path 0 -1 0 812 1495
+Curve 814 1496 816 1497
+<-------EndPath
+Path -1 -1 0 816 1497
+Curve 816 1503 816 1509
+<-------EndPath
+Path 3 -1 0 816 1509
+Curve 814 1502 812 1495
+<-------EndPath
+Path -1 -1 0 -1336 -372
+Curve -1324 -417 -1311 -461
+Curve -1284 -534 -1230 -589
+Curve -1187 -635 -1134 -666
+Curve -1081 -698 -1022 -713
+Curve -960 -726 -898 -739
+Curve -822 -744 -745 -749
+Curve -670 -743 -597 -718
+Curve -525 -692 -463 -646
+<-------EndPath
+Path -1 -1 0 -534 -548
+Curve -538 -549 -542 -550
+Curve -548 -553 -554 -555
+Curve -559 -557 -563 -558
+Curve -618 -574 -678 -578
+Curve -751 -576 -824 -573
+Curve -892 -563 -953 -538
+Curve -1020 -510 -1078 -469
+Curve -1125 -429 -1171 -388
+Curve -1215 -348 -1248 -299
+Curve -1251 -296 -1253 -293
+Curve -1294 -235 -1319 -167
+Curve -1336 -124 -1327 -89
+<-------EndPath
+Path 1 1 0 -549 -354
+Curve -583 -322 -579 -304
+Curve -576 -287 -536 -285
+<-------EndPath
+Path 3 -1 0 -549 1500
+Curve -584 1508 -613 1525
+Curve -508 1565 -383 1571
+Curve -246 1567 -108 1563
+Curve -22 1550 65 1537
+Curve -18 1513 -100 1499
+Curve -175 1490 -249 1480
+Curve -402 1468 -549 1500
+<-------EndPath
+!======EndShape
+=======BeginShape
+Path -1 -1 0 1168 -1806
+Curve 1045 -1810 922 -1814
+Curve 799 -1796 704 -1719
+Curve 686 -1703 667 -1686
+Curve 601 -1622 573 -1545
+Curve 520 -1667 576 -1774
+Curve 582 -1785 588 -1796
+Curve 638 -1891 708 -1973
+Curve 782 -2059 884 -2106
+Curve 908 -2115 932 -2124
+Curve 975 -2132 1018 -2140
+<-------EndPath
+Path 1 -1 0 1121 -1437
+Curve 1090 -1445 1059 -1453
+Curve 999 -1465 939 -1477
+<-------EndPath
+Path 1 0 -1 939 -1477
+Curve 946 -1474 953 -1470
+Curve 956 -1469 959 -1467
+Curve 1071 -1436 1165 -1370
+Curve 1194 -1349 1222 -1328
+<-------EndPath
+Path 1 1 0 1222 -1328
+Curve 1196 -1411 1121 -1437
+<-------EndPath
+Path -1 1 0 1121 -1437
+Curve 1262 -1393 1373 -1311
+Curve 1484 -1230 1506 -1179
+Curve 1528 -1128 1491 -1038
+Curve 1454 -948 1074 -821
+<-------EndPath
+Path -1 1 1 1074 -821
+Curve 1049 -817 1024 -813
+<-------EndPath
+Path -1 -1 1 1024 -813
+Curve 1004 -810 984 -806
+<-------EndPath
+Path -1 1 1 984 -806
+Curve 925 -798 866 -789
+<-------EndPath
+Path -1 0 1 866 -789
+Curve 835 -787 804 -785
+Curve 724 -788 643 -791
+<-------EndPath
+Path -1 -1 1 643 -791
+Curve 611 -790 579 -788
+Curve 562 -788 542 -770
+Curve 522 -749 502 -728
+<-------EndPath
+Path -1 -1 0 502 -728
+Curve 495 -718 488 -707
+Curve 486 -701 484 -695
+Curve 482 -682 480 -669
+<-------EndPath
+Path -1 1 0 480 -669
+Curve 478 -651 484 -636
+Curve 500 -612 515 -587
+<-------EndPath
+Path -1 4 0 515 -587
+Curve 524 -573 533 -558
+Curve 540 -549 546 -539
+Curve 553 -528 559 -516
+Curve 562 -509 564 -502
+<-------EndPath
+Path -1 1 0 564 -502
+Curve 595 -417 569 -254
+Curve 563 -219 556 -183
+<-------EndPath
+Path -1 0 0 556 -183
+Curve 531 -63 492 36
+<-------EndPath
+Path -1 4 0 492 36
+Curve 479 67 466 97
+Curve 400 237 328 455
+<-------EndPath
+Path -1 -1 0 328 455
+Curve 323 476 318 496
+<-------EndPath
+Path -1 4 0 318 496
+Curve 319 521 319 546
+Curve 321 567 323 588
+Curve 339 732 412 874
+Curve 465 979 499 1089
+Curve 531 1193 546 1302
+Curve 566 1441 558 1575
+Curve 555 1611 511 1632
+<-------EndPath
+Path -1 3 0 511 1632
+Curve 552 1669 751 1503
+Curve 974 1539 813 1696
+Curve 652 1852 449 1910
+Curve 246 1967 224 1686
+<-------EndPath
+Path -1 3 -1 224 1686
+Curve 224 1683 223 1680
+<-------EndPath
+Path -1 4 0 223 1680
+Curve 153 1694 83 1707
+Curve -33 1730 -49 1586
+Curve -61 1482 -90 1440
+Curve -106 1473 -121 1505
+Curve -198 1658 -291 1789
+Curve -308 1808 -324 1826
+Curve -350 1843 -375 1859
+Curve -419 1845 -462 1830
+Curve -485 1822 -507 1813
+<-------EndPath
+Path -1 3 0 -507 1813
+Curve -442 1848 -383 1875
+Curve -319 1901 -255 1927
+Curve -234 1933 -225 1947
+Curve -222 1961 -243 2025
+Curve -285 2039 -340 2042
+Curve -366 2042 -392 2042
+Curve -459 2034 -526 2025
+Curve -705 1988 -859 1907
+Curve -1051 1806 -910 1657
+<-------EndPath
+Path -1 4 0 -910 1657
+Curve -931 1636 -952 1614
+Curve -938 1591 -923 1568
+Curve -826 1434 -749 1288
+Curve -699 1191 -659 1089
+Curve -642 1041 -624 992
+Curve -575 844 -522 705
+Curve -522 695 -521 684
+Curve -515 620 -499 559
+Curve -499 558 -499 556
+Curve -499 555 -498 554
+Curve -498 553 -498 552
+Curve -498 551 -497 550
+Curve -497 549 -496 547
+Curve -496 544 -495 541
+Curve -493 534 -490 527
+Curve -489 520 -487 512
+Curve -468 422 -443 349
+Curve -396 213 -349 76
+Curve -347 69 -344 61
+<-------EndPath
+Path -1 0 0 -344 61
+Curve -310 -31 -275 -122
+Curve -184 -357 -66 -468
+Curve 50 -578 148 -621
+<-------EndPath
+Path -1 4 0 148 -621
+Curve 150 -622 152 -622
+Curve 191 -636 230 -649
+<-------EndPath
+Path -1 0 0 230 -649
+Curve 253 -661 276 -673
+Curve 308 -695 326 -726
+<-------EndPath
+Path -1 0 1 326 -726
+Curve 330 -734 334 -742
+Curve 337 -749 339 -756
+Curve 341 -766 342 -775
+Curve 345 -796 334 -818
+Curve 323 -840 304 -856
+<-------EndPath
+Path -1 0 0 304 -856
+Curve 189 -888 -11 -986
+Curve -295 -1125 -279 -1231
+Curve -276 -1253 -272 -1275
+Curve -269 -1285 -266 -1295
+Curve -246 -1350 -194 -1385
+Curve -114 -1439 -38 -1461
+Curve 27 -1478 92 -1494
+Curve 122 -1500 152 -1505
+Curve 155 -1506 157 -1506
+Curve 274 -1520 390 -1533
+Curve 414 -1534 437 -1535
+Curve 465 -1536 492 -1537
+Curve 520 -1537 548 -1536
+Curve 560 -1536 572 -1535
+Curve 625 -1531 678 -1527
+Curve 720 -1519 762 -1511
+Curve 851 -1494 939 -1477
+<-------EndPath
+Path 0 0 0 959 -1467
+Curve 1002 -1443 1023 -1395
+<-------EndPath
+Path 1 0 -1 1222 -1328
+Curve 1328 -1309 1414 -1192
+Curve 1500 -1075 1358 -987
+Curve 1215 -899 1068 -863
+Curve 930 -829 866 -789
+<-------EndPath
+Path -1 -1 0 1043 -1933
+Curve 919 -1974 808 -1912
+Curve 708 -1856 630 -1771
+Curve 621 -1759 612 -1747
+Curve 546 -1659 573 -1545
+<-------EndPath
+Path 0 0 0 157 -1506
+Curve 185 -1485 191 -1453
+Curve 194 -1432 189 -1407
+<-------EndPath
+Path 0 0 0 390 -1533
+Curve 405 -1518 420 -1503
+Curve 434 -1482 438 -1453
+<-------EndPath
+Path -1 0 -1 643 -791
+Curve 619 -793 594 -795
+Curve 527 -777 489 -726
+Curve 484 -719 479 -711
+Curve 476 -706 473 -701
+Curve 468 -690 462 -678
+<-------EndPath
+Path -1 1 -1 462 -678
+Curve 471 -674 480 -669
+<-------EndPath
+Path 1 0 -1 462 -678
+Curve 461 -675 460 -671
+Curve 430 -590 466 -503
+Curve 481 -468 495 -432
+<-------EndPath
+Path 1 4 0 495 -432
+Curve 504 -487 512 -542
+Curve 513 -551 514 -559
+Curve 515 -573 515 -587
+<-------EndPath
+Path 4 0 -1 148 -621
+Curve 151 -615 153 -609
+<-------EndPath
+Path 4 0 0 153 -609
+Curve 170 -489 140 -376
+Curve 108 -260 62 -151
+Curve 58 -142 53 -132
+Curve 5 -27 -75 54
+Curve -174 154 -299 95
+Curve -335 78 -335 65
+<-------EndPath
+Path 4 0 -1 -335 65
+Curve -340 63 -344 61
+<-------EndPath
+Path 4 0 0 495 -432
+Curve 492 -421 489 -409
+Curve 475 -355 461 -300
+Curve 461 -300 460 -299
+Curve 443 -227 426 -155
+Curve 416 -111 393 -103
+Curve 354 -92 314 -81
+Curve 225 -59 134 -54
+Curve 142 -70 149 -86
+Curve 177 -138 204 -190
+Curve 265 -297 274 -421
+Curve 282 -551 230 -649
+<-------EndPath
+Path 1 4 0 564 -502
+Curve 557 -462 550 -422
+Curve 550 -421 550 -420
+Curve 548 -409 546 -397
+Curve 538 -361 530 -324
+<-------EndPath
+Path 1 0 -1 530 -324
+Curve 536 -303 542 -282
+Curve 555 -232 556 -183
+<-------EndPath
+Path 0 4 0 530 -324
+Curve 526 -305 522 -286
+Curve 522 -286 521 -285
+Curve 492 -161 479 -35
+Curve 472 30 492 36
+<-------EndPath
+Path 1 -1 0 984 -806
+Curve 988 -807 992 -808
+Curve 1008 -811 1024 -813
+<-------EndPath
+Path 0 0 0 762 -1511
+Curve 801 -1471 812 -1414
+<-------EndPath
+Path -1 4 0 328 455
+Curve 323 471 318 486
+Curve 318 487 318 487
+Curve 318 492 318 496
+<-------EndPath
+Path 4 4 0 -90 1440
+Curve -49 1346 -18 1248
+Curve -12 1226 -5 1204
+Curve 11 1147 27 1089
+Curve 55 994 83 899
+Curve 98 845 112 790
+Curve 124 738 136 685
+Curve 143 659 149 633
+Curve 149 590 148 547
+<-------EndPath
+Path 4 4 0 88 1212
+Curve 69 1241 63 1274
+Curve 56 1306 61 1342
+<-------EndPath
+Path 2 3 -1 375 1656
+Curve 375 1660 375 1664
+<-------EndPath
+Path 2 3 0 375 1664
+Curve 393 1661 411 1658
+<-------EndPath
+Path 2 4 0 411 1658
+Curve 393 1657 375 1656
+<-------EndPath
+Path 3 4 0 375 1656
+Curve 299 1668 223 1680
+<-------EndPath
+Path 3 4 0 511 1632
+Curve 494 1638 476 1644
+Curve 451 1650 426 1655
+Curve 419 1657 411 1658
+<-------EndPath
+Path 0 0 0 -184 -1301
+Curve -225 -1296 -238 -1282
+Curve -241 -1275 -243 -1267
+Curve -240 -1260 -237 -1252
+Curve -236 -1250 -234 -1247
+Curve -221 -1231 -199 -1221
+<-------EndPath
+Path 4 4 0 -235 347
+Curve -223 497 -362 620
+<-------EndPath
+Path 4 3 0 -910 1657
+Curve -910 1658 -910 1658
+Curve -854 1703 -771 1727
+Curve -647 1763 -524 1807
+Curve -516 1810 -507 1813
+<-------EndPath
+Path 4 4 0 -157 980
+Curve -158 1036 -175 1089
+<-------EndPath
+!======EndShape
+=======BeginShape
+Path -1 -1 0 1168 -1832
+Curve 1045 -1836 922 -1840
+Curve 799 -1822 704 -1745
+Curve 686 -1729 667 -1712
+Curve 601 -1647 573 -1570
+Curve 520 -1693 576 -1800
+Curve 582 -1811 588 -1822
+Curve 638 -1917 708 -1999
+Curve 782 -2085 884 -2132
+Curve 908 -2141 932 -2150
+Curve 975 -2158 1018 -2166
+<-------EndPath
+Path 1 0 -1 939 -1503
+Curve 946 -1500 953 -1496
+Curve 956 -1495 959 -1493
+Curve 1071 -1462 1165 -1396
+Curve 1194 -1375 1222 -1354
+<-------EndPath
+Path 1 1 0 1222 -1354
+Curve 1196 -1437 1121 -1463
+<-------EndPath
+Path 1 -1 0 1121 -1463
+Curve 1090 -1471 1059 -1479
+Curve 999 -1491 939 -1503
+<-------EndPath
+Path 0 -1 0 939 -1503
+Curve 851 -1520 762 -1537
+<-------EndPath
+Path 0 0 0 762 -1537
+Curve 801 -1497 812 -1440
+<-------EndPath
+Path 1 -1 0 866 -815
+Curve 925 -824 984 -832
+Curve 988 -833 992 -834
+Curve 1008 -837 1024 -839
+Curve 1049 -843 1074 -847
+Curve 1454 -974 1491 -1064
+Curve 1528 -1154 1506 -1205
+Curve 1484 -1256 1373 -1337
+Curve 1262 -1419 1121 -1463
+<-------EndPath
+Path 1 0 -1 1222 -1354
+Curve 1328 -1335 1414 -1218
+Curve 1500 -1101 1358 -1013
+Curve 1215 -925 1068 -889
+Curve 930 -855 866 -815
+<-------EndPath
+Path -1 0 0 866 -815
+Curve 835 -813 804 -811
+Curve 724 -814 643 -817
+<-------EndPath
+Path -1 -1 0 643 -817
+Curve 611 -816 579 -814
+Curve 562 -814 542 -796
+Curve 522 -775 502 -754
+Curve 488 -738 484 -721
+Curve 482 -708 480 -695
+<-------EndPath
+Path -1 1 0 480 -695
+Curve 478 -677 484 -662
+Curve 500 -638 515 -613
+<-------EndPath
+Path -1 3 0 515 -613
+Curve 524 -599 533 -584
+Curve 540 -575 546 -565
+Curve 555 -547 564 -528
+<-------EndPath
+Path -1 -1 0 564 -528
+Curve 566 -537 567 -545
+<-------EndPath
+Path 0 0 0 959 -1493
+Curve 1002 -1469 1023 -1421
+<-------EndPath
+Path -1 -1 0 1043 -1959
+Curve 919 -2000 808 -1938
+Curve 708 -1882 630 -1797
+Curve 621 -1785 612 -1773
+Curve 546 -1685 573 -1570
+<-------EndPath
+Path -1 0 0 230 -675
+Curve 253 -687 276 -699
+Curve 316 -727 334 -768
+Curve 338 -785 342 -801
+Curve 345 -821 334 -843
+Curve 323 -866 304 -882
+Curve 189 -914 -11 -1012
+Curve -295 -1151 -279 -1257
+Curve -276 -1279 -272 -1301
+Curve -269 -1311 -266 -1321
+Curve -246 -1376 -194 -1411
+Curve -114 -1465 -38 -1486
+Curve 27 -1503 92 -1520
+Curve 122 -1526 152 -1531
+Curve 155 -1532 157 -1532
+Curve 274 -1546 390 -1559
+Curve 414 -1560 437 -1561
+Curve 465 -1562 492 -1563
+Curve 520 -1563 548 -1562
+Curve 560 -1562 572 -1561
+Curve 625 -1557 678 -1553
+Curve 720 -1545 762 -1537
+<-------EndPath
+Path 0 0 0 157 -1532
+Curve 185 -1511 191 -1479
+Curve 194 -1458 189 -1433
+<-------EndPath
+Path 0 0 0 390 -1559
+Curve 405 -1544 420 -1529
+Curve 434 -1508 438 -1479
+<-------EndPath
+Path -1 1 -1 462 -704
+Curve 471 -700 480 -695
+<-------EndPath
+Path -1 0 -1 643 -817
+Curve 619 -819 594 -821
+Curve 511 -799 473 -727
+Curve 468 -716 462 -704
+<-------EndPath
+Path 1 0 -1 462 -704
+Curve 461 -701 460 -697
+Curve 430 -616 466 -529
+Curve 481 -494 495 -458
+<-------EndPath
+Path 1 3 0 495 -458
+Curve 504 -513 512 -568
+Curve 513 -577 514 -585
+Curve 515 -599 515 -613
+<-------EndPath
+Path 3 -1 0 230 -675
+Curve 191 -662 152 -648
+Curve 150 -648 148 -647
+<-------EndPath
+Path 3 0 -1 148 -647
+Curve 151 -641 153 -635
+<-------EndPath
+Path 3 0 0 153 -635
+Curve 170 -515 140 -402
+Curve 108 -286 62 -177
+Curve 58 -168 53 -158
+Curve 5 -53 -75 28
+Curve -174 128 -299 69
+Curve -335 52 -335 39
+<-------EndPath
+Path 3 0 -1 -335 39
+Curve -340 37 -344 35
+<-------EndPath
+Path 3 -1 0 -344 35
+Curve -347 43 -349 51
+Curve -396 187 -443 323
+Curve -468 396 -487 486
+Curve -489 494 -490 501
+Curve -493 508 -495 515
+Curve -496 519 -496 522
+Curve -497 523 -497 524
+Curve -498 525 -498 526
+Curve -498 527 -498 528
+Curve -499 530 -499 531
+Curve -499 532 -499 533
+Curve -515 593 -520 656
+<-------EndPath
+Path 3 -1 -1 -520 656
+Curve -519 656 -518 656
+<-------EndPath
+Path 3 3 1 -518 656
+Curve -514 640 -509 624
+<-------EndPath
+Path 3 0 0 495 -458
+Curve 492 -447 489 -435
+Curve 475 -381 461 -326
+Curve 444 -254 426 -181
+Curve 416 -137 393 -129
+Curve 354 -118 314 -107
+Curve 225 -85 134 -80
+Curve 142 -96 149 -112
+Curve 177 -164 204 -216
+Curve 265 -323 274 -447
+Curve 282 -577 230 -675
+<-------EndPath
+Path 0 1 -1 556 -209
+Curve 555 -258 542 -308
+Curve 536 -329 530 -350
+<-------EndPath
+Path 0 3 0 530 -350
+Curve 526 -331 521 -311
+Curve 492 -187 479 -61
+Curve 472 4 492 10
+<-------EndPath
+Path 0 -1 0 492 10
+Curve 531 -89 556 -209
+<-------EndPath
+Path 1 -1 0 556 -209
+Curve 563 -245 569 -280
+Curve 595 -443 564 -528
+<-------EndPath
+Path 1 3 0 564 -528
+Curve 557 -488 550 -448
+Curve 550 -447 550 -446
+Curve 548 -435 546 -423
+Curve 538 -387 530 -350
+<-------EndPath
+Path -1 -1 0 984 -832
+Curve 1004 -836 1024 -839
+<-------EndPath
+Path -1 3 0 492 10
+Curve 479 41 466 71
+Curve 400 211 328 429
+<-------EndPath
+Path -1 -1 0 328 429
+Curve 323 450 318 470
+<-------EndPath
+Path -1 3 0 318 470
+Curve 317 495 319 507
+Curve 313 529 307 550
+<-------EndPath
+Path -1 3 1 307 550
+Curve 294 581 295 656
+Curve 297 676 298 695
+Curve 311 801 323 907
+Curve 334 1017 357 1126
+Curve 377 1227 412 1323
+Curve 442 1404 462 1484
+Curve 466 1520 469 1555
+Curve 457 1576 445 1597
+Curve 396 1662 325 1692
+<-------EndPath
+Path -1 2 1 325 1692
+Curve 341 1694 356 1696
+Curve 455 1679 559 1644
+Curve 587 1644 614 1643
+Curve 727 1682 623 1798
+Curve 550 1879 455 1901
+Curve 359 1922 272 1950
+Curve 184 1977 96 1981
+Curve 7 1985 -10 1906
+Curve -22 1836 -34 1766
+<-------EndPath
+Path -1 3 1 -34 1766
+Curve -99 1774 -163 1782
+Curve -150 1702 -129 1625
+Curve -123 1599 -116 1573
+Curve -183 1627 -258 1670
+Curve -342 1716 -433 1739
+Curve -445 1731 -456 1722
+<-------EndPath
+Path -1 2 1 -456 1722
+Curve -457 1800 -410 1864
+Curve -339 1864 -269 1892
+Curve -227 1908 -246 1953
+Curve -292 2057 -421 2038
+Curve -532 2022 -617 1948
+Curve -696 1879 -747 1783
+Curve -799 1687 -838 1595
+Curve -886 1480 -780 1421
+<-------EndPath
+Path -1 3 1 -780 1421
+Curve -801 1386 -813 1348
+Curve -695 1316 -620 1257
+Curve -532 1187 -526 1073
+Curve -521 963 -534 856
+Curve -546 756 -518 656
+<-------EndPath
+Path 3 -1 0 318 470
+Curve 318 466 318 461
+Curve 318 461 318 460
+Curve 323 445 328 429
+<-------EndPath
+Path 3 3 1 -116 1573
+Curve -96 1555 -75 1537
+Curve 4 1465 75 1382
+Curve 146 1300 180 1195
+Curve 213 1092 226 985
+Curve 240 874 211 767
+Curve 194 712 176 656
+Curve 163 632 149 607
+Curve 143 593 136 578
+Curve 119 538 94 512
+<-------EndPath
+Path 3 2 1 -34 1766
+Curve 7 1760 47 1753
+Curve 158 1731 269 1709
+Curve 297 1701 325 1692
+<-------EndPath
+Path 0 0 0 -184 -1327
+Curve -225 -1322 -238 -1308
+Curve -241 -1301 -243 -1293
+Curve -240 -1286 -237 -1278
+Curve -236 -1276 -234 -1273
+Curve -221 -1257 -199 -1247
+<-------EndPath
+Path 0 -1 0 148 -647
+Curve 50 -604 -66 -494
+Curve -184 -383 -275 -148
+Curve -310 -57 -344 35
+<-------EndPath
+Path 0 0 0 -335 39
+Curve -333 35 -331 30
+<-------EndPath
+Path 3 3 0 -193 309
+Curve -181 459 -320 582
+<-------EndPath
+Path 3 2 1 -780 1421
+Curve -749 1473 -698 1518
+Curve -618 1587 -537 1656
+Curve -498 1689 -459 1721
+Curve -458 1722 -456 1722
+<-------EndPath
+Path 2 2 1 -410 1864
+Curve -438 1866 -466 1868
+Curve -497 1870 -527 1871
+<-------EndPath
+!======EndShape
+=======BeginShape
+Path -1 -1 0 1168 -1867
+Curve 1045 -1871 922 -1875
+Curve 799 -1857 704 -1780
+Curve 686 -1764 667 -1747
+Curve 601 -1683 573 -1606
+Curve 520 -1729 576 -1836
+Curve 582 -1847 588 -1858
+Curve 638 -1952 708 -2034
+Curve 782 -2120 884 -2167
+Curve 908 -2176 932 -2185
+Curve 975 -2193 1018 -2201
+<-------EndPath
+Path -1 1 0 939 -1538
+Curve 999 -1526 1059 -1514
+Curve 1090 -1506 1121 -1498
+Curve 1262 -1454 1373 -1373
+Curve 1484 -1291 1506 -1240
+Curve 1528 -1190 1491 -1099
+Curve 1454 -1009 1074 -882
+Curve 1054 -879 1034 -876
+<-------EndPath
+Path -1 -1 0 1034 -876
+Curve 1009 -872 984 -868
+<-------EndPath
+Path -1 1 0 984 -868
+Curve 925 -859 866 -850
+<-------EndPath
+Path -1 0 0 866 -850
+Curve 835 -849 804 -847
+Curve 724 -850 643 -852
+<-------EndPath
+Path -1 -1 0 643 -852
+Curve 611 -851 579 -849
+Curve 562 -849 542 -832
+Curve 522 -811 502 -790
+Curve 488 -773 484 -756
+Curve 482 -743 480 -730
+<-------EndPath
+Path -1 1 0 480 -730
+Curve 478 -712 484 -698
+Curve 500 -673 515 -648
+<-------EndPath
+Path -1 4 0 515 -648
+Curve 524 -634 533 -620
+Curve 540 -610 546 -600
+Curve 555 -582 564 -564
+<-------EndPath
+Path -1 -1 0 564 -564
+Curve 566 -573 567 -581
+<-------EndPath
+Path 0 1 -1 959 -1528
+Curve 956 -1530 953 -1532
+Curve 946 -1535 939 -1538
+<-------EndPath
+Path 0 -1 0 939 -1538
+Curve 851 -1555 762 -1572
+<-------EndPath
+Path 0 0 0 762 -1572
+Curve 801 -1532 812 -1475
+<-------EndPath
+Path 1 0 -1 1222 -1389
+Curve 1328 -1370 1414 -1253
+Curve 1500 -1137 1358 -1048
+Curve 1215 -960 1068 -924
+Curve 930 -890 866 -850
+<-------EndPath
+Path 0 1 -1 1222 -1389
+Curve 1194 -1410 1165 -1431
+Curve 1071 -1497 959 -1528
+<-------EndPath
+Path 0 0 0 959 -1528
+Curve 1002 -1504 1023 -1456
+<-------EndPath
+Path 1 1 0 1121 -1498
+Curve 1196 -1472 1222 -1389
+<-------EndPath
+Path -1 -1 0 1043 -1994
+Curve 919 -2035 808 -1973
+Curve 708 -1917 630 -1832
+Curve 621 -1820 612 -1808
+Curve 546 -1720 573 -1606
+<-------EndPath
+Path 0 0 0 390 -1595
+Curve 405 -1580 420 -1565
+Curve 434 -1543 438 -1514
+<-------EndPath
+Path -1 0 0 230 -710
+Curve 258 -722 276 -735
+Curve 316 -762 334 -804
+Curve 338 -820 342 -836
+Curve 345 -857 334 -879
+Curve 323 -901 304 -917
+Curve 189 -949 -11 -1047
+Curve -295 -1186 -279 -1292
+Curve -276 -1315 -272 -1337
+Curve -269 -1347 -266 -1356
+Curve -246 -1412 -194 -1447
+Curve -114 -1501 -38 -1522
+Curve 27 -1539 92 -1555
+Curve 122 -1561 152 -1567
+Curve 155 -1567 157 -1567
+Curve 274 -1581 390 -1595
+Curve 414 -1596 437 -1596
+Curve 465 -1598 492 -1599
+Curve 520 -1598 548 -1597
+Curve 560 -1597 572 -1596
+Curve 625 -1592 678 -1588
+Curve 720 -1580 762 -1572
+<-------EndPath
+Path 0 0 0 157 -1567
+Curve 185 -1546 191 -1514
+Curve 194 -1494 189 -1469
+<-------EndPath
+Path -1 0 -1 643 -852
+Curve 619 -854 594 -856
+Curve 511 -834 473 -762
+Curve 468 -751 462 -739
+<-------EndPath
+Path -1 1 -1 462 -739
+Curve 471 -735 480 -730
+<-------EndPath
+Path 4 1 0 515 -648
+Curve 515 -635 514 -621
+Curve 513 -612 512 -603
+Curve 504 -548 495 -493
+<-------EndPath
+Path 4 0 0 495 -493
+Curve 492 -482 489 -470
+Curve 475 -416 461 -361
+Curve 444 -289 426 -216
+Curve 416 -172 393 -164
+Curve 354 -153 314 -142
+Curve 225 -121 134 -115
+Curve 142 -131 149 -147
+Curve 177 -200 204 -252
+Curve 265 -359 274 -482
+Curve 282 -612 230 -710
+<-------EndPath
+Path 4 -1 0 230 -710
+Curve 191 -697 152 -684
+Curve 150 -683 148 -682
+<-------EndPath
+Path 4 0 -1 148 -682
+Curve 151 -677 153 -671
+<-------EndPath
+Path 4 0 0 153 -671
+Curve 170 -551 140 -437
+Curve 108 -321 62 -212
+Curve 58 -203 53 -193
+Curve 5 -88 -75 -7
+Curve -174 92 -299 33
+Curve -335 16 -335 3
+<-------EndPath
+Path 4 0 -1 -335 3
+Curve -340 2 -344 0
+<-------EndPath
+Path 4 -1 0 -344 0
+Curve -347 8 -349 15
+Curve -396 152 -443 288
+Curve -468 361 -487 450
+Curve -489 458 -490 466
+Curve -493 473 -495 480
+Curve -496 483 -496 486
+Curve -497 488 -497 489
+Curve -498 490 -498 491
+Curve -498 492 -498 493
+Curve -499 494 -499 495
+Curve -499 497 -499 498
+Curve -514 553 -520 611
+<-------EndPath
+Path 4 2 1 -520 611
+Curve -519 638 -518 665
+<-------EndPath
+Path 4 -1 1 -518 665
+Curve -516 715 -499 765
+Curve -459 881 -377 976
+Curve -369 987 -360 997
+<-------EndPath
+Path 4 4 1 -360 997
+Curve -268 1112 -326 1159
+<-------EndPath
+Path 1 0 -1 462 -739
+Curve 461 -736 460 -732
+Curve 430 -652 466 -565
+Curve 481 -529 495 -493
+<-------EndPath
+Path 1 0 -1 530 -385
+Curve 536 -364 542 -343
+Curve 555 -294 556 -244
+<-------EndPath
+Path 1 -1 0 556 -244
+Curve 563 -280 569 -316
+Curve 595 -478 564 -564
+<-------EndPath
+Path 1 4 0 564 -564
+Curve 557 -524 550 -483
+Curve 550 -483 550 -482
+Curve 548 -471 546 -459
+Curve 538 -422 530 -385
+<-------EndPath
+Path 0 4 0 530 -385
+Curve 526 -366 521 -346
+Curve 492 -222 479 -96
+Curve 472 -31 492 -25
+<-------EndPath
+Path 0 -1 0 492 -25
+Curve 531 -125 556 -244
+<-------EndPath
+Path -1 1 0 1034 -876
+Curve 1013 -873 992 -870
+Curve 988 -869 984 -868
+<-------EndPath
+Path -1 4 0 328 394
+Curve 323 410 318 425
+Curve 318 426 318 426
+Curve 318 431 318 435
+<-------EndPath
+Path -1 -1 0 318 435
+Curve 323 415 328 394
+<-------EndPath
+Path 4 -1 0 328 394
+Curve 400 176 466 36
+Curve 479 6 492 -25
+<-------EndPath
+Path -1 4 0 318 435
+Curve 316 453 313 471
+Curve 305 498 296 525
+<-------EndPath
+Path -1 4 1 296 525
+Curve 282 567 281 615
+Curve 281 640 280 665
+Curve 258 777 256 893
+<-------EndPath
+Path -1 -1 1 256 893
+Curve 256 899 256 904
+Curve 257 959 257 1013
+Curve 258 1073 262 1133
+Curve 263 1143 263 1153
+<-------EndPath
+Path -1 4 1 263 1153
+Curve 271 1274 311 1389
+Curve 354 1509 356 1629
+Curve 239 1668 138 1688
+<-------EndPath
+Path -1 3 1 138 1688
+Curve 151 1714 204 1726
+Curve 325 1754 450 1769
+Curve 562 1782 507 1876
+Curve 440 1988 304 1992
+Curve 184 1994 63 1996
+Curve -60 1997 -176 1972
+Curve -314 1942 -267 1844
+Curve -336 1836 -401 1799
+Curve -511 1735 -601 1650
+Curve -691 1566 -776 1439
+Curve -733 1343 -643 1269
+<-------EndPath
+Path -1 4 1 -643 1269
+Curve -706 1186 -587 1125
+Curve -472 1067 -360 997
+<-------EndPath
+Path -1 4 -1 256 893
+Curve 253 893 249 892
+<-------EndPath
+Path -1 4 1 249 892
+Curve 250 898 250 904
+Curve 252 959 254 1013
+Curve 252 1074 250 1134
+Curve 250 1143 249 1151
+<-------EndPath
+Path -1 4 -1 249 1151
+Curve 256 1152 263 1153
+<-------EndPath
+Path 4 4 1 249 892
+Curve 241 779 223 665
+Curve 223 660 222 655
+Curve 202 528 189 402
+<-------EndPath
+Path 4 4 1 249 1151
+Curve 235 1266 154 1353
+Curve 106 1406 37 1430
+Curve -72 1468 -164 1554
+Curve -168 1558 -172 1561
+Curve -185 1566 -210 1553
+Curve -263 1525 -315 1496
+<-------EndPath
+Path 4 3 1 -315 1496
+Curve -386 1510 -336 1588
+Curve -273 1686 -141 1704
+Curve -111 1707 -93 1723
+Curve -5 1710 83 1697
+Curve 111 1693 138 1688
+<-------EndPath
+Path 0 0 0 -184 -1362
+Curve -225 -1357 -238 -1344
+Curve -241 -1336 -243 -1328
+Curve -240 -1321 -237 -1314
+Curve -236 -1312 -234 -1309
+Curve -221 -1292 -199 -1282
+<-------EndPath
+Path 0 -1 0 148 -682
+Curve 50 -639 -66 -529
+Curve -184 -418 -275 -183
+Curve -310 -92 -344 0
+<-------EndPath
+Path 2 -1 -1 -520 611
+Curve -521 617 -521 623
+Curve -522 633 -522 643
+Curve -523 654 -523 665
+Curve -521 665 -518 665
+<-------EndPath
+Path 4 4 0 -163 298
+Curve -151 448 -290 571
+<-------EndPath
+Path 3 4 1 -315 1496
+Curve -368 1467 -420 1438
+Curve -525 1380 -613 1300
+Curve -628 1285 -643 1269
+<-------EndPath
+Path 3 3 1 -93 1723
+Curve -86 1732 -78 1740
+Curve -35 1810 -160 1838
+Curve -214 1841 -267 1844
+<-------EndPath
+Path 0 0 0 -335 3
+Curve -333 -1 -331 -5
+<-------EndPath
+!======EndShape
+=======BeginShape
+Path -1 -1 0 1168 -1806
+Curve 1045 -1810 922 -1814
+Curve 799 -1796 704 -1719
+Curve 686 -1703 667 -1686
+Curve 601 -1622 573 -1545
+Curve 520 -1667 576 -1774
+Curve 582 -1785 588 -1796
+Curve 638 -1891 708 -1973
+Curve 782 -2059 884 -2106
+Curve 908 -2115 932 -2124
+Curve 975 -2132 1018 -2140
+<-------EndPath
+Path 1 -1 0 1121 -1437
+Curve 1090 -1445 1059 -1453
+Curve 999 -1465 939 -1477
+<-------EndPath
+Path 1 0 -1 939 -1477
+Curve 946 -1474 953 -1470
+Curve 956 -1469 959 -1467
+Curve 1071 -1436 1165 -1370
+Curve 1194 -1349 1222 -1328
+<-------EndPath
+Path 1 1 0 1222 -1328
+Curve 1196 -1411 1121 -1437
+<-------EndPath
+Path -1 1 0 1121 -1437
+Curve 1262 -1393 1373 -1311
+Curve 1484 -1230 1506 -1179
+Curve 1528 -1128 1491 -1038
+Curve 1454 -948 1074 -821
+Curve 1049 -817 1024 -813
+<-------EndPath
+Path -1 -1 0 1024 -813
+Curve 1004 -810 984 -806
+<-------EndPath
+Path -1 1 0 984 -806
+Curve 925 -798 866 -789
+<-------EndPath
+Path -1 0 0 866 -789
+Curve 835 -787 804 -785
+Curve 724 -788 643 -791
+<-------EndPath
+Path -1 -1 0 643 -791
+Curve 611 -790 579 -788
+Curve 562 -788 542 -770
+Curve 522 -749 502 -728
+Curve 488 -712 484 -695
+Curve 482 -682 480 -669
+<-------EndPath
+Path -1 1 0 480 -669
+Curve 478 -651 484 -636
+Curve 500 -612 515 -587
+<-------EndPath
+Path -1 3 0 515 -587
+Curve 524 -573 533 -558
+Curve 540 -549 546 -539
+Curve 555 -521 564 -502
+<-------EndPath
+Path -1 -1 0 564 -502
+Curve 566 -511 567 -519
+<-------EndPath
+Path 0 0 0 959 -1467
+Curve 1002 -1443 1023 -1395
+<-------EndPath
+Path 1 0 -1 1222 -1328
+Curve 1328 -1309 1414 -1192
+Curve 1500 -1075 1358 -987
+Curve 1215 -899 1068 -863
+Curve 930 -829 866 -789
+<-------EndPath
+Path -1 -1 0 1043 -1933
+Curve 919 -1974 808 -1912
+Curve 708 -1856 630 -1771
+Curve 621 -1759 612 -1747
+Curve 546 -1659 573 -1545
+<-------EndPath
+Path -1 0 0 230 -649
+Curve 253 -661 276 -673
+Curve 316 -701 334 -742
+Curve 338 -759 342 -775
+Curve 345 -796 334 -818
+Curve 323 -840 304 -856
+Curve 189 -888 -11 -986
+Curve -295 -1125 -279 -1231
+Curve -276 -1253 -272 -1275
+Curve -269 -1285 -266 -1295
+Curve -246 -1350 -194 -1385
+Curve -114 -1439 -38 -1461
+Curve 27 -1478 92 -1494
+Curve 122 -1500 152 -1505
+Curve 155 -1506 157 -1506
+Curve 274 -1520 390 -1533
+Curve 414 -1534 437 -1535
+Curve 465 -1536 492 -1537
+Curve 520 -1537 548 -1536
+Curve 560 -1536 572 -1535
+Curve 625 -1531 678 -1527
+Curve 720 -1519 762 -1511
+Curve 851 -1494 939 -1477
+<-------EndPath
+Path 0 0 0 157 -1506
+Curve 185 -1485 191 -1453
+Curve 194 -1432 189 -1407
+<-------EndPath
+Path 0 0 0 390 -1533
+Curve 405 -1518 420 -1503
+Curve 434 -1482 438 -1453
+<-------EndPath
+Path -1 1 -1 462 -678
+Curve 471 -674 480 -669
+<-------EndPath
+Path -1 0 -1 643 -791
+Curve 619 -793 594 -795
+Curve 511 -773 473 -701
+Curve 468 -690 462 -678
+<-------EndPath
+Path 1 0 -1 462 -678
+Curve 461 -675 460 -671
+Curve 430 -590 466 -503
+Curve 481 -468 495 -432
+<-------EndPath
+Path 1 3 0 495 -432
+Curve 504 -487 512 -542
+Curve 513 -551 514 -559
+Curve 515 -573 515 -587
+<-------EndPath
+Path 3 -1 0 230 -649
+Curve 191 -636 152 -622
+Curve 150 -622 148 -621
+<-------EndPath
+Path 3 0 -1 148 -621
+Curve 151 -615 153 -609
+<-------EndPath
+Path 3 0 0 153 -609
+Curve 170 -489 140 -376
+Curve 108 -260 62 -151
+Curve 58 -142 53 -132
+Curve 5 -27 -75 54
+Curve -174 154 -299 95
+Curve -335 78 -335 65
+<-------EndPath
+Path 3 0 -1 -335 65
+Curve -340 63 -344 61
+<-------EndPath
+Path 3 -1 0 -344 61
+Curve -347 69 -349 76
+Curve -396 213 -443 349
+Curve -468 422 -487 512
+Curve -489 520 -490 527
+Curve -493 534 -495 541
+Curve -496 544 -496 547
+Curve -497 549 -497 550
+Curve -498 551 -498 552
+Curve -498 553 -498 554
+Curve -499 555 -499 556
+Curve -499 558 -499 559
+Curve -515 620 -521 684
+Curve -522 695 -522 705
+Curve -563 817 -603 929
+Curve -614 961 -624 992
+Curve -676 1145 -749 1288
+Curve -799 1385 -859 1476
+<-------EndPath
+Path 3 -1 1 -859 1476
+Curve -820 1509 -781 1542
+<-------EndPath
+Path 3 2 1 -781 1542
+Curve -731 1578 -667 1610
+Curve -555 1664 -442 1717
+<-------EndPath
+Path 3 -1 1 -442 1717
+Curve -392 1741 -341 1765
+Curve -316 1777 -290 1788
+<-------EndPath
+Path 3 -1 0 -290 1788
+Curve -198 1657 -121 1505
+Curve -108 1477 -94 1448
+<-------EndPath
+Path 3 3 1 -94 1448
+Curve -148 1355 -201 1261
+Curve -321 1050 -388 829
+Curve -457 597 -436 362
+<-------EndPath
+Path 3 0 0 495 -432
+Curve 492 -421 489 -409
+Curve 475 -355 461 -300
+Curve 444 -228 426 -155
+Curve 416 -111 393 -103
+Curve 354 -92 314 -81
+Curve 225 -59 134 -54
+Curve 142 -70 149 -86
+Curve 177 -138 204 -190
+Curve 265 -297 274 -421
+Curve 282 -551 230 -649
+<-------EndPath
+Path 3 1 0 530 -324
+Curve 538 -361 546 -397
+Curve 548 -409 550 -420
+Curve 550 -421 550 -422
+Curve 557 -462 564 -502
+<-------EndPath
+Path -1 1 0 564 -502
+Curve 595 -417 569 -254
+Curve 563 -219 556 -183
+<-------EndPath
+Path -1 0 0 556 -183
+Curve 531 -63 492 36
+<-------EndPath
+Path -1 3 0 492 36
+Curve 479 67 466 97
+Curve 400 237 328 455
+<-------EndPath
+Path -1 -1 0 328 455
+Curve 323 476 318 496
+<-------EndPath
+Path -1 3 0 318 496
+Curve 319 521 319 546
+Curve 321 567 323 588
+Curve 329 647 346 707
+<-------EndPath
+Path -1 3 1 346 707
+Curve 414 859 486 1000
+Curve 487 1001 487 1002
+Curve 589 1203 693 1371
+Curve 826 1586 665 1685
+Curve 661 1688 656 1690
+<-------EndPath
+Path -1 2 -1 656 1690
+Curve 662 1690 668 1690
+<-------EndPath
+Path -1 2 1 668 1690
+Curve 682 1692 695 1694
+Curve 750 1688 800 1663
+Curve 850 1637 905 1620
+Curve 961 1602 1010 1629
+Curve 1066 1660 1040 1719
+Curve 1016 1770 979 1814
+Curve 944 1855 895 1876
+Curve 844 1896 793 1916
+Curve 744 1930 695 1944
+Curve 641 1957 587 1970
+Curve 531 1980 474 1989
+Curve 420 1990 386 1949
+Curve 353 1907 341 1857
+<-------EndPath
+Path -1 2 -1 341 1857
+Curve 338 1850 335 1842
+<-------EndPath
+Path -1 3 1 335 1842
+Curve 274 1866 212 1889
+Curve 128 1816 59 1710
+Curve 47 1690 35 1670
+Curve -15 1584 -65 1498
+<-------EndPath
+Path -1 -1 1 -65 1498
+Curve -80 1473 -94 1448
+<-------EndPath
+Path 3 -1 0 -94 1448
+Curve -92 1444 -90 1440
+Curve -76 1461 -65 1498
+<-------EndPath
+Path 3 0 0 492 36
+Curve 472 30 479 -35
+Curve 492 -161 521 -285
+Curve 526 -305 530 -324
+<-------EndPath
+Path 1 0 -1 530 -324
+Curve 536 -303 542 -282
+Curve 555 -232 556 -183
+<-------EndPath
+Path 1 -1 0 984 -806
+Curve 988 -807 992 -808
+Curve 1008 -811 1024 -813
+<-------EndPath
+Path 0 0 0 762 -1511
+Curve 801 -1471 812 -1414
+<-------EndPath
+Path -1 3 0 328 455
+Curve 323 471 318 486
+Curve 318 487 318 487
+Curve 318 492 318 496
+<-------EndPath
+Path 3 3 1 346 707
+Curve 328 666 310 625
+<-------EndPath
+Path 3 3 0 210 1201
+Curve 172 1259 182 1330
+<-------EndPath
+Path 2 3 1 656 1690
+Curve 612 1714 567 1737
+Curve 461 1791 335 1842
+<-------EndPath
+Path 0 0 0 -184 -1301
+Curve -225 -1296 -238 -1282
+Curve -241 -1275 -243 -1267
+Curve -240 -1260 -237 -1252
+Curve -236 -1250 -234 -1247
+Curve -221 -1231 -199 -1221
+<-------EndPath
+Path 0 -1 0 148 -621
+Curve 50 -578 -66 -468
+Curve -184 -357 -275 -122
+Curve -310 -31 -344 61
+<-------EndPath
+Path 0 0 0 -335 65
+Curve -333 61 -331 56
+<-------EndPath
+Path 3 3 0 -113 335
+Curve -102 485 -241 608
+<-------EndPath
+Path 2 -1 1 -781 1542
+Curve -811 1584 -827 1637
+Curve -836 1668 -824 1701
+Curve -803 1750 -781 1798
+Curve -758 1844 -722 1882
+Curve -683 1915 -644 1947
+Curve -602 1976 -559 2004
+Curve -513 2034 -460 2045
+Curve -409 2052 -357 2059
+Curve -299 2062 -245 2040
+Curve -196 2019 -167 1973
+Curve -139 1926 -160 1907
+Curve -181 1888 -206 1891
+Curve -246 1888 -285 1884
+Curve -339 1873 -380 1840
+Curve -426 1803 -440 1748
+Curve -441 1733 -442 1717
+<-------EndPath
+Path 3 3 0 -36 969
+Curve -37 1029 -57 1086
+<-------EndPath
+!======EndShape
+=======BeginShape
+Path -1 -1 0 1168 -1832
+Curve 1045 -1836 922 -1840
+Curve 799 -1822 704 -1745
+Curve 686 -1729 667 -1712
+Curve 601 -1647 573 -1570
+Curve 520 -1693 576 -1800
+Curve 582 -1811 588 -1822
+Curve 638 -1917 708 -1999
+Curve 782 -2085 884 -2132
+Curve 908 -2141 932 -2150
+Curve 975 -2158 1018 -2166
+<-------EndPath
+Path 1 0 -1 939 -1503
+Curve 946 -1500 953 -1496
+Curve 956 -1495 959 -1493
+Curve 1071 -1462 1165 -1396
+Curve 1194 -1375 1222 -1354
+<-------EndPath
+Path 1 1 0 1222 -1354
+Curve 1196 -1437 1121 -1463
+<-------EndPath
+Path 1 -1 0 1121 -1463
+Curve 1090 -1471 1059 -1479
+Curve 999 -1491 939 -1503
+<-------EndPath
+Path 0 -1 0 939 -1503
+Curve 851 -1520 762 -1537
+<-------EndPath
+Path 0 0 0 762 -1537
+Curve 801 -1497 812 -1440
+<-------EndPath
+Path 1 -1 0 866 -815
+Curve 925 -824 984 -832
+Curve 988 -833 992 -834
+Curve 1008 -837 1024 -839
+Curve 1049 -843 1074 -847
+Curve 1454 -974 1491 -1064
+Curve 1528 -1154 1506 -1205
+Curve 1484 -1256 1373 -1337
+Curve 1262 -1419 1121 -1463
+<-------EndPath
+Path 1 0 -1 1222 -1354
+Curve 1328 -1335 1414 -1218
+Curve 1500 -1101 1358 -1013
+Curve 1215 -925 1068 -889
+Curve 930 -855 866 -815
+<-------EndPath
+Path -1 0 0 866 -815
+Curve 835 -813 804 -811
+Curve 724 -814 643 -817
+<-------EndPath
+Path -1 -1 0 643 -817
+Curve 611 -816 579 -814
+Curve 562 -814 542 -796
+Curve 522 -775 502 -754
+Curve 488 -738 484 -721
+Curve 482 -708 480 -695
+<-------EndPath
+Path -1 1 0 480 -695
+Curve 478 -677 484 -662
+Curve 500 -638 515 -613
+<-------EndPath
+Path -1 4 0 515 -613
+Curve 524 -599 533 -584
+Curve 540 -575 546 -565
+Curve 555 -547 564 -528
+<-------EndPath
+Path -1 -1 0 564 -528
+Curve 566 -537 567 -545
+<-------EndPath
+Path 0 0 0 959 -1493
+Curve 1002 -1469 1023 -1421
+<-------EndPath
+Path -1 -1 0 1043 -1959
+Curve 919 -2000 808 -1938
+Curve 708 -1882 630 -1797
+Curve 621 -1785 612 -1773
+Curve 546 -1685 573 -1570
+<-------EndPath
+Path -1 0 0 230 -675
+Curve 253 -687 276 -699
+Curve 316 -727 334 -768
+Curve 338 -785 342 -801
+Curve 345 -821 334 -843
+Curve 323 -866 304 -882
+Curve 189 -914 -11 -1012
+Curve -295 -1151 -279 -1257
+Curve -276 -1279 -272 -1301
+Curve -269 -1311 -266 -1321
+Curve -246 -1376 -194 -1411
+Curve -114 -1465 -38 -1486
+Curve 27 -1503 92 -1520
+Curve 122 -1526 152 -1531
+Curve 155 -1532 157 -1532
+Curve 274 -1546 390 -1559
+Curve 414 -1560 437 -1561
+Curve 465 -1562 492 -1563
+Curve 520 -1563 548 -1562
+Curve 560 -1562 572 -1561
+Curve 625 -1557 678 -1553
+Curve 720 -1545 762 -1537
+<-------EndPath
+Path 0 0 0 157 -1532
+Curve 185 -1511 191 -1479
+Curve 194 -1458 189 -1433
+<-------EndPath
+Path 0 0 0 390 -1559
+Curve 405 -1544 420 -1529
+Curve 434 -1508 438 -1479
+<-------EndPath
+Path -1 1 -1 462 -704
+Curve 471 -700 480 -695
+<-------EndPath
+Path -1 0 -1 643 -817
+Curve 619 -819 594 -821
+Curve 511 -799 473 -727
+Curve 468 -716 462 -704
+<-------EndPath
+Path 1 0 -1 462 -704
+Curve 461 -701 460 -697
+Curve 430 -616 466 -529
+Curve 481 -494 495 -458
+<-------EndPath
+Path 1 4 0 495 -458
+Curve 504 -513 512 -568
+Curve 513 -577 514 -585
+Curve 515 -599 515 -613
+<-------EndPath
+Path 4 -1 0 230 -675
+Curve 191 -662 152 -648
+Curve 150 -648 148 -647
+<-------EndPath
+Path 4 0 -1 148 -647
+Curve 151 -641 153 -635
+<-------EndPath
+Path 4 0 0 153 -635
+Curve 170 -515 140 -402
+Curve 108 -286 62 -177
+Curve 58 -168 53 -158
+Curve 5 -53 -75 28
+Curve -174 128 -299 69
+Curve -335 52 -335 39
+<-------EndPath
+Path 4 0 -1 -335 39
+Curve -340 37 -344 35
+<-------EndPath
+Path 4 -1 0 -344 35
+Curve -347 43 -349 51
+Curve -396 187 -443 323
+Curve -468 396 -487 486
+Curve -489 494 -490 501
+Curve -493 508 -495 515
+Curve -496 519 -496 522
+Curve -497 523 -497 524
+Curve -498 525 -498 526
+Curve -498 527 -498 528
+Curve -499 530 -499 531
+Curve -499 532 -499 533
+Curve -505 558 -511 583
+<-------EndPath
+Path 4 2 1 -511 583
+Curve -513 604 -514 624
+Curve -514 631 -513 638
+<-------EndPath
+Path 4 -1 1 -513 638
+Curve -512 679 -495 721
+Curve -490 733 -485 744
+Curve -473 765 -460 786
+<-------EndPath
+Path 4 4 1 -460 786
+Curve -396 880 -358 987
+Curve -321 1084 -284 1180
+Curve -241 1281 -204 1385
+Curve -167 1488 -162 1599
+Curve -160 1644 -163 1687
+<-------EndPath
+Path 4 -1 1 -163 1687
+Curve -169 1752 -188 1814
+Curve -196 1835 -196 1859
+Curve -127 1860 -57 1861
+<-------EndPath
+Path 4 3 1 -57 1861
+Curve -14 1862 29 1863
+Curve 150 1866 265 1825
+Curve 313 1807 357 1783
+<-------EndPath
+Path 4 -1 1 357 1783
+Curve 392 1761 427 1738
+Curve 430 1723 433 1707
+Curve 466 1470 412 1233
+Curve 397 1174 381 1115
+Curve 312 878 291 638
+<-------EndPath
+Path 4 2 1 291 638
+Curve 294 627 296 615
+<-------EndPath
+Path 4 -1 1 296 615
+Curve 297 608 297 600
+Curve 300 568 307 550
+<-------EndPath
+Path 4 -1 0 307 550
+Curve 313 529 319 507
+Curve 317 495 318 470
+Curve 318 466 318 461
+Curve 318 461 318 460
+Curve 323 445 328 429
+Curve 400 211 466 71
+Curve 479 41 492 10
+<-------EndPath
+Path 4 0 0 492 10
+Curve 472 4 479 -61
+Curve 492 -187 521 -311
+Curve 526 -331 530 -350
+<-------EndPath
+Path 4 1 0 530 -350
+Curve 538 -387 546 -423
+Curve 548 -435 550 -446
+Curve 550 -447 550 -448
+Curve 557 -488 564 -528
+<-------EndPath
+Path -1 1 0 564 -528
+Curve 595 -443 569 -280
+Curve 563 -245 556 -209
+<-------EndPath
+Path -1 0 0 556 -209
+Curve 531 -89 492 10
+<-------EndPath
+Path 4 0 0 495 -458
+Curve 492 -447 489 -435
+Curve 475 -381 461 -326
+Curve 444 -254 426 -181
+Curve 416 -137 393 -129
+Curve 354 -118 314 -107
+Curve 225 -85 134 -80
+Curve 142 -96 149 -112
+Curve 177 -164 204 -216
+Curve 265 -323 274 -447
+Curve 282 -577 230 -675
+<-------EndPath
+Path 0 1 -1 556 -209
+Curve 555 -258 542 -308
+Curve 536 -329 530 -350
+<-------EndPath
+Path -1 -1 0 984 -832
+Curve 1004 -836 1024 -839
+<-------EndPath
+Path -1 -1 0 328 429
+Curve 323 450 318 470
+<-------EndPath
+Path -1 2 1 296 615
+Curve 296 627 295 638
+<-------EndPath
+Path -1 2 -1 295 638
+Curve 293 638 291 638
+<-------EndPath
+Path -1 3 1 357 1783
+Curve 373 1802 388 1820
+Curve 504 1777 597 1767
+Curve 661 1760 674 1826
+Curve 696 1940 590 1996
+Curve 492 2047 385 2067
+Curve 372 2068 359 2069
+Curve 306 2090 247 2092
+Curve 138 2083 29 2074
+Curve -2 2066 -18 2048
+Curve -91 1973 -57 1861
+<-------EndPath
+Path 3 3 1 388 1820
+Curve 399 1829 409 1837
+<-------EndPath
+Path 0 0 0 -184 -1327
+Curve -225 -1322 -238 -1308
+Curve -241 -1301 -243 -1293
+Curve -240 -1286 -237 -1278
+Curve -236 -1276 -234 -1273
+Curve -221 -1257 -199 -1247
+<-------EndPath
+Path 0 -1 0 148 -647
+Curve 50 -604 -66 -494
+Curve -184 -383 -275 -148
+Curve -310 -57 -344 35
+<-------EndPath
+Path 0 0 0 -335 39
+Curve -333 35 -331 30
+<-------EndPath
+Path 2 -1 -1 -518 638
+Curve -516 638 -513 638
+<-------EndPath
+Path 2 -1 0 -511 583
+Curve -515 611 -518 638
+<-------EndPath
+Path -1 4 -1 -471 788
+Curve -466 787 -460 786
+<-------EndPath
+Path -1 -1 1 -471 788
+Curve -478 766 -485 744
+<-------EndPath
+Path -1 4 1 -567 1458
+Curve -612 1412 -666 1388
+Curve -625 1359 -584 1330
+Curve -496 1258 -428 1184
+Curve -361 1109 -406 978
+Curve -439 883 -471 788
+<-------EndPath
+Path 4 4 0 -193 309
+Curve -181 459 -320 582
+<-------EndPath
+Path 3 4 1 -326 1706
+Curve -383 1653 -440 1600
+Curve -490 1558 -526 1507
+Curve -547 1483 -567 1458
+<-------EndPath
+Path 3 -1 1 -567 1458
+Curve -625 1484 -639 1537
+Curve -659 1615 -637 1691
+Curve -607 1799 -569 1907
+Curve -549 1964 -515 2000
+Curve -504 2020 -479 2029
+Curve -446 2040 -413 2051
+Curve -321 2079 -210 2041
+Curve -166 2025 -150 1989
+Curve -138 1960 -159 1942
+Curve -230 1880 -328 1881
+Curve -363 1835 -362 1774
+Curve -360 1771 -357 1767
+Curve -342 1737 -326 1706
+<-------EndPath
+Path 4 -1 1 -326 1706
+Curve -300 1733 -274 1759
+Curve -203 1726 -163 1687
+<-------EndPath
+!======EndShape
+=======BeginShape
+Path -1 -1 0 1168 -1867
+Curve 1045 -1871 922 -1875
+Curve 799 -1857 704 -1780
+Curve 686 -1764 667 -1747
+Curve 601 -1683 573 -1606
+Curve 520 -1729 576 -1836
+Curve 582 -1847 588 -1858
+Curve 638 -1952 708 -2034
+Curve 782 -2120 884 -2167
+Curve 908 -2176 932 -2185
+Curve 975 -2193 1018 -2201
+<-------EndPath
+Path -1 1 0 939 -1538
+Curve 999 -1526 1059 -1514
+Curve 1090 -1506 1121 -1498
+Curve 1262 -1454 1373 -1373
+Curve 1484 -1291 1506 -1240
+Curve 1528 -1190 1491 -1099
+Curve 1454 -1009 1074 -882
+Curve 1054 -879 1034 -876
+<-------EndPath
+Path -1 -1 0 1034 -876
+Curve 1009 -872 984 -868
+<-------EndPath
+Path -1 1 0 984 -868
+Curve 925 -859 866 -850
+<-------EndPath
+Path -1 0 0 866 -850
+Curve 835 -849 804 -847
+Curve 724 -850 643 -852
+<-------EndPath
+Path -1 -1 0 643 -852
+Curve 611 -851 579 -849
+Curve 562 -849 542 -832
+Curve 522 -811 502 -790
+Curve 488 -773 484 -756
+Curve 482 -743 480 -730
+<-------EndPath
+Path -1 1 0 480 -730
+Curve 478 -712 484 -698
+Curve 500 -673 515 -648
+<-------EndPath
+Path -1 4 0 515 -648
+Curve 524 -634 533 -620
+Curve 540 -610 546 -600
+Curve 555 -582 564 -564
+<-------EndPath
+Path -1 -1 0 564 -564
+Curve 566 -573 567 -581
+<-------EndPath
+Path 0 1 -1 959 -1528
+Curve 956 -1530 953 -1532
+Curve 946 -1535 939 -1538
+<-------EndPath
+Path 0 -1 0 939 -1538
+Curve 851 -1555 762 -1572
+<-------EndPath
+Path 0 0 0 762 -1572
+Curve 801 -1532 812 -1475
+<-------EndPath
+Path 1 0 -1 1222 -1389
+Curve 1328 -1370 1414 -1253
+Curve 1500 -1137 1358 -1048
+Curve 1215 -960 1068 -924
+Curve 930 -890 866 -850
+<-------EndPath
+Path 0 1 -1 1222 -1389
+Curve 1194 -1410 1165 -1431
+Curve 1071 -1497 959 -1528
+<-------EndPath
+Path 0 0 0 959 -1528
+Curve 1002 -1504 1023 -1456
+<-------EndPath
+Path 1 1 0 1121 -1498
+Curve 1196 -1472 1222 -1389
+<-------EndPath
+Path -1 -1 0 1043 -1994
+Curve 919 -2035 808 -1973
+Curve 708 -1917 630 -1832
+Curve 621 -1820 612 -1808
+Curve 546 -1720 573 -1606
+<-------EndPath
+Path -1 0 0 230 -710
+Curve 258 -722 276 -735
+Curve 316 -762 334 -804
+Curve 338 -820 342 -836
+Curve 345 -857 334 -879
+Curve 323 -901 304 -917
+Curve 189 -949 -11 -1047
+Curve -295 -1186 -279 -1292
+Curve -276 -1315 -272 -1337
+Curve -269 -1347 -266 -1356
+Curve -246 -1412 -194 -1447
+Curve -114 -1501 -38 -1522
+Curve 27 -1539 92 -1555
+Curve 122 -1561 152 -1567
+Curve 155 -1567 157 -1567
+Curve 274 -1581 390 -1595
+Curve 414 -1596 437 -1596
+Curve 465 -1598 492 -1599
+Curve 520 -1598 548 -1597
+Curve 560 -1597 572 -1596
+Curve 625 -1592 678 -1588
+Curve 720 -1580 762 -1572
+<-------EndPath
+Path 0 0 0 390 -1595
+Curve 405 -1580 420 -1565
+Curve 434 -1543 438 -1514
+<-------EndPath
+Path 0 0 0 157 -1567
+Curve 185 -1546 191 -1514
+Curve 194 -1494 189 -1469
+<-------EndPath
+Path -1 0 -1 643 -852
+Curve 619 -854 594 -856
+Curve 511 -834 473 -762
+Curve 468 -751 462 -739
+<-------EndPath
+Path -1 1 -1 462 -739
+Curve 471 -735 480 -730
+<-------EndPath
+Path 4 1 0 515 -648
+Curve 515 -635 514 -621
+Curve 513 -612 512 -603
+Curve 504 -548 495 -493
+<-------EndPath
+Path 4 0 0 495 -493
+Curve 492 -482 489 -470
+Curve 475 -416 461 -361
+Curve 444 -289 426 -216
+Curve 416 -172 393 -164
+Curve 354 -153 314 -142
+Curve 225 -121 134 -115
+Curve 142 -131 149 -147
+Curve 177 -200 204 -252
+Curve 265 -359 274 -482
+Curve 282 -612 230 -710
+<-------EndPath
+Path 4 -1 0 230 -710
+Curve 191 -697 152 -684
+Curve 150 -683 148 -682
+<-------EndPath
+Path 4 0 -1 148 -682
+Curve 151 -677 153 -671
+<-------EndPath
+Path 4 0 0 153 -671
+Curve 170 -551 140 -437
+Curve 108 -321 62 -212
+Curve 58 -203 53 -193
+Curve 5 -88 -75 -7
+Curve -174 92 -299 33
+Curve -335 16 -335 3
+<-------EndPath
+Path 4 0 -1 -335 3
+Curve -340 2 -344 0
+<-------EndPath
+Path 4 -1 0 -344 0
+Curve -347 8 -349 15
+Curve -396 152 -443 288
+Curve -460 346 -476 404
+Curve -482 427 -487 450
+Curve -488 452 -488 454
+Curve -489 460 -490 466
+Curve -493 473 -495 480
+Curve -496 483 -496 486
+Curve -497 488 -497 489
+Curve -498 490 -498 491
+Curve -498 492 -498 493
+Curve -499 494 -499 495
+Curve -499 497 -499 498
+Curve -503 515 -507 531
+Curve -513 569 -519 607
+<-------EndPath
+Path 4 -1 1 -519 607
+Curve -519 607 -518 607
+Curve -515 610 -512 613
+Curve -508 740 -459 841
+Curve -408 947 -388 1064
+Curve -385 1083 -381 1102
+<-------EndPath
+Path 4 4 1 -381 1102
+Curve -368 1202 -377 1305
+Curve -385 1382 -392 1459
+<-------EndPath
+Path 4 3 1 -392 1459
+Curve -397 1507 -402 1554
+Curve -405 1613 -407 1672
+<-------EndPath
+Path 4 -1 1 -407 1672
+Curve -407 1673 -407 1674
+Curve -404 1727 -393 1772
+Curve -352 1785 -311 1797
+<-------EndPath
+Path 4 3 1 -311 1797
+Curve -218 1821 -134 1826
+Curve -12 1830 136 1820
+<-------EndPath
+Path 4 -1 1 136 1820
+Curve 138 1820 139 1819
+Curve 288 1808 261 1685
+Curve 236 1574 234 1464
+Curve 234 1463 234 1462
+<-------EndPath
+Path 4 4 1 234 1462
+Curve 234 1452 234 1442
+Curve 234 1321 245 1198
+Curve 255 1077 273 958
+Curve 292 835 286 714
+Curve 284 670 281 626
+Curve 281 621 281 615
+Curve 283 571 294 531
+Curve 295 528 296 525
+<-------EndPath
+Path 4 4 0 296 525
+Curve 303 502 310 479
+<-------EndPath
+Path 4 2 1 310 479
+Curve 311 477 311 474
+Curve 313 471 315 467
+<-------EndPath
+Path 4 -1 0 315 467
+Curve 316 461 317 454
+Curve 318 445 318 435
+Curve 318 431 318 426
+Curve 318 426 318 425
+Curve 322 415 325 404
+Curve 327 399 328 394
+Curve 400 176 466 36
+Curve 479 6 492 -25
+<-------EndPath
+Path 4 0 0 492 -25
+Curve 472 -31 479 -96
+Curve 492 -222 521 -346
+Curve 526 -366 530 -385
+<-------EndPath
+Path 4 1 0 530 -385
+Curve 538 -422 546 -459
+Curve 548 -471 550 -482
+Curve 550 -483 550 -483
+Curve 557 -524 564 -564
+<-------EndPath
+Path -1 1 0 564 -564
+Curve 595 -478 569 -316
+Curve 563 -280 556 -244
+<-------EndPath
+Path -1 0 0 556 -244
+Curve 531 -125 492 -25
+<-------EndPath
+Path 1 0 -1 462 -739
+Curve 461 -736 460 -732
+Curve 430 -652 466 -565
+Curve 481 -529 495 -493
+<-------EndPath
+Path 1 0 -1 530 -385
+Curve 536 -364 542 -343
+Curve 555 -294 556 -244
+<-------EndPath
+Path -1 1 0 1034 -876
+Curve 1013 -873 992 -870
+Curve 988 -869 984 -868
+<-------EndPath
+Path 4 4 1 218 626
+Curve 214 595 209 564
+Curve 207 548 204 531
+Curve 200 493 195 454
+Curve 192 429 189 404
+<-------EndPath
+Path -1 -1 0 318 435
+Curve 322 420 326 404
+Curve 327 399 328 394
+<-------EndPath
+Path 2 -1 0 310 479
+Curve 312 475 313 471
+Curve 314 469 315 467
+<-------EndPath
+Path 4 -1 1 234 1462
+Curve 288 1443 360 1367
+Curve 447 1275 475 1151
+Curve 502 1030 471 912
+Curve 439 795 375 692
+Curve 310 590 310 479
+<-------EndPath
+Path 3 -1 -1 137 1829
+Curve 137 1825 136 1820
+<-------EndPath
+Path 3 -1 1 -311 1797
+Curve -386 1907 -308 2009
+Curve -291 2022 -273 2035
+Curve -163 2087 -39 2082
+Curve 87 2075 215 2079
+Curve 361 2085 410 1967
+Curve 440 1897 368 1899
+Curve 228 1901 137 1829
+<-------EndPath
+Path 0 0 0 -184 -1362
+Curve -225 -1357 -238 -1344
+Curve -241 -1336 -243 -1328
+Curve -240 -1321 -237 -1314
+Curve -236 -1312 -234 -1309
+Curve -221 -1292 -199 -1282
+<-------EndPath
+Path 0 -1 0 148 -682
+Curve 50 -639 -66 -529
+Curve -184 -418 -275 -183
+Curve -310 -92 -344 0
+<-------EndPath
+Path 4 4 0 -163 298
+Curve -159 352 -174 404
+Curve -185 429 -195 454
+Curve -216 493 -250 531
+Curve -270 551 -290 571
+<-------EndPath
+Path -1 -1 1 -519 607
+Curve -519 607 -518 607
+<-------EndPath
+Path -1 -1 0 -519 607
+Curve -520 609 -520 611
+<-------EndPath
+Path -1 2 1 -520 611
+Curve -520 619 -520 626
+<-------EndPath
+Path -1 2 -1 -520 626
+Curve -521 626 -521 626
+Curve -521 625 -521 623
+Curve -521 623 -521 622
+Curve -521 617 -520 611
+<-------EndPath
+Path 4 -1 1 -381 1102
+Curve -519 1126 -483 1262
+Curve -464 1316 -445 1369
+<-------EndPath
+Path 4 3 1 -445 1369
+Curve -422 1419 -392 1459
+<-------EndPath
+Path 3 -1 1 -445 1369
+Curve -594 1379 -558 1505
+Curve -543 1561 -502 1603
+Curve -458 1649 -407 1672
+<-------EndPath
+Path 0 0 0 -335 3
+Curve -333 -1 -331 -5
+<-------EndPath
+!======EndShape
+=======BeginShape
+Path -1 -1 0 1168 -1806
+Curve 1045 -1810 922 -1814
+Curve 799 -1796 704 -1719
+Curve 686 -1703 667 -1686
+Curve 601 -1622 573 -1545
+Curve 520 -1667 576 -1774
+Curve 582 -1785 588 -1796
+Curve 638 -1891 708 -1973
+Curve 782 -2059 884 -2106
+Curve 908 -2115 932 -2124
+Curve 975 -2132 1018 -2140
+<-------EndPath
+Path 1 -1 0 1121 -1437
+Curve 1090 -1445 1059 -1453
+Curve 999 -1465 939 -1477
+<-------EndPath
+Path 1 0 -1 939 -1477
+Curve 946 -1474 953 -1470
+Curve 956 -1469 959 -1467
+Curve 1071 -1436 1165 -1370
+Curve 1194 -1349 1222 -1328
+<-------EndPath
+Path 1 1 0 1222 -1328
+Curve 1196 -1411 1121 -1437
+<-------EndPath
+Path -1 1 0 1121 -1437
+Curve 1262 -1393 1373 -1311
+Curve 1484 -1230 1506 -1179
+Curve 1528 -1128 1491 -1038
+Curve 1454 -948 1074 -821
+Curve 1049 -817 1024 -813
+<-------EndPath
+Path -1 -1 0 1024 -813
+Curve 1004 -810 984 -806
+<-------EndPath
+Path -1 1 0 984 -806
+Curve 925 -798 866 -789
+<-------EndPath
+Path -1 0 0 866 -789
+Curve 835 -787 804 -785
+Curve 724 -788 643 -791
+<-------EndPath
+Path -1 -1 0 643 -791
+Curve 611 -790 579 -788
+Curve 562 -788 542 -770
+Curve 522 -749 502 -728
+Curve 488 -712 484 -695
+Curve 482 -682 480 -669
+<-------EndPath
+Path -1 1 0 480 -669
+Curve 478 -651 484 -636
+Curve 500 -612 515 -587
+<-------EndPath
+Path -1 3 0 515 -587
+Curve 524 -573 533 -558
+Curve 540 -549 546 -539
+Curve 555 -521 564 -502
+<-------EndPath
+Path -1 -1 0 564 -502
+Curve 566 -511 567 -519
+<-------EndPath
+Path 0 0 0 959 -1467
+Curve 1002 -1443 1023 -1395
+<-------EndPath
+Path 1 0 -1 1222 -1328
+Curve 1328 -1309 1414 -1192
+Curve 1500 -1075 1358 -987
+Curve 1215 -899 1068 -863
+Curve 930 -829 866 -789
+<-------EndPath
+Path -1 -1 0 1043 -1933
+Curve 919 -1974 808 -1912
+Curve 708 -1856 630 -1771
+Curve 621 -1759 612 -1747
+Curve 546 -1659 573 -1545
+<-------EndPath
+Path -1 0 0 230 -649
+Curve 253 -661 276 -673
+Curve 316 -701 334 -742
+Curve 338 -759 342 -775
+Curve 345 -796 334 -818
+Curve 323 -840 304 -856
+Curve 189 -888 -11 -986
+Curve -295 -1125 -279 -1231
+Curve -276 -1253 -272 -1275
+Curve -269 -1285 -266 -1295
+Curve -246 -1350 -194 -1385
+Curve -114 -1439 -38 -1461
+Curve 27 -1478 92 -1494
+Curve 122 -1500 152 -1505
+Curve 155 -1506 157 -1506
+Curve 274 -1520 390 -1533
+Curve 414 -1534 437 -1535
+Curve 465 -1536 492 -1537
+Curve 520 -1537 548 -1536
+Curve 560 -1536 572 -1535
+Curve 625 -1531 678 -1527
+Curve 720 -1519 762 -1511
+Curve 851 -1494 939 -1477
+<-------EndPath
+Path 0 0 0 157 -1506
+Curve 185 -1485 191 -1453
+Curve 194 -1432 189 -1407
+<-------EndPath
+Path 0 0 0 390 -1533
+Curve 405 -1518 420 -1503
+Curve 434 -1482 438 -1453
+<-------EndPath
+Path 0 1 -1 495 -432
+Curve 481 -468 466 -503
+Curve 430 -590 460 -671
+Curve 461 -675 462 -678
+<-------EndPath
+Path 0 -1 -1 462 -678
+Curve 468 -690 473 -701
+Curve 511 -773 594 -795
+Curve 619 -793 643 -791
+<-------EndPath
+Path -1 1 -1 462 -678
+Curve 471 -674 480 -669
+<-------EndPath
+Path 3 1 0 515 -587
+Curve 515 -573 514 -559
+Curve 513 -551 512 -542
+Curve 504 -487 495 -432
+<-------EndPath
+Path 3 0 0 495 -432
+Curve 492 -421 489 -409
+Curve 475 -355 461 -300
+Curve 444 -228 426 -155
+Curve 416 -111 393 -103
+Curve 354 -92 314 -81
+Curve 225 -59 134 -54
+Curve 142 -70 149 -86
+Curve 177 -138 204 -190
+Curve 265 -297 274 -421
+Curve 282 -551 230 -649
+<-------EndPath
+Path 3 -1 0 230 -649
+Curve 191 -636 152 -622
+Curve 150 -622 148 -621
+<-------EndPath
+Path 3 0 -1 148 -621
+Curve 151 -615 153 -609
+<-------EndPath
+Path 3 0 0 153 -609
+Curve 170 -489 140 -376
+Curve 108 -260 62 -151
+Curve 58 -142 53 -132
+Curve 5 -27 -75 54
+Curve -174 154 -299 95
+Curve -335 78 -335 65
+<-------EndPath
+Path 3 0 -1 -335 65
+Curve -340 63 -344 61
+<-------EndPath
+Path 3 -1 0 -344 61
+Curve -347 69 -349 76
+Curve -396 213 -443 349
+Curve -468 422 -487 512
+Curve -489 520 -490 527
+Curve -493 534 -495 541
+Curve -496 544 -496 547
+Curve -497 549 -497 550
+Curve -498 551 -498 552
+Curve -498 553 -498 554
+Curve -499 555 -499 556
+Curve -499 558 -499 559
+Curve -515 620 -521 684
+Curve -522 695 -522 705
+Curve -563 817 -603 929
+Curve -614 961 -624 992
+Curve -676 1145 -749 1288
+Curve -799 1385 -859 1476
+<-------EndPath
+Path 3 -1 1 -859 1476
+Curve -820 1509 -781 1542
+<-------EndPath
+Path 3 2 1 -781 1542
+Curve -731 1578 -667 1610
+Curve -555 1664 -442 1717
+<-------EndPath
+Path 3 -1 1 -442 1717
+Curve -392 1741 -341 1765
+Curve -316 1777 -290 1788
+<-------EndPath
+Path 3 -1 0 -290 1788
+Curve -198 1657 -121 1505
+Curve -108 1477 -94 1448
+<-------EndPath
+Path 3 3 1 -94 1448
+Curve -148 1355 -201 1261
+Curve -321 1050 -388 829
+Curve -457 597 -436 362
+<-------EndPath
+Path 3 1 0 530 -324
+Curve 538 -361 546 -397
+Curve 548 -409 550 -420
+Curve 550 -421 550 -422
+Curve 557 -462 564 -502
+<-------EndPath
+Path -1 1 0 564 -502
+Curve 595 -417 569 -254
+Curve 563 -219 556 -183
+<-------EndPath
+Path -1 0 0 556 -183
+Curve 531 -63 492 36
+<-------EndPath
+Path -1 3 0 492 36
+Curve 479 67 466 97
+Curve 400 237 328 455
+<-------EndPath
+Path -1 -1 0 328 455
+Curve 323 476 318 496
+<-------EndPath
+Path -1 3 0 318 496
+Curve 319 521 319 546
+Curve 321 567 323 588
+Curve 329 647 346 707
+<-------EndPath
+Path -1 3 1 346 707
+Curve 414 859 486 1000
+Curve 487 1001 487 1002
+Curve 589 1203 693 1371
+Curve 826 1586 665 1685
+Curve 661 1688 656 1690
+<-------EndPath
+Path -1 2 -1 656 1690
+Curve 662 1690 668 1690
+<-------EndPath
+Path -1 2 1 668 1690
+Curve 682 1692 695 1694
+Curve 750 1688 800 1663
+Curve 850 1637 905 1620
+Curve 961 1602 1010 1629
+Curve 1066 1660 1040 1719
+Curve 1016 1770 979 1814
+Curve 944 1855 895 1876
+Curve 844 1896 793 1916
+Curve 744 1930 695 1944
+Curve 641 1957 587 1970
+Curve 531 1980 474 1989
+Curve 420 1990 386 1949
+Curve 353 1907 341 1857
+<-------EndPath
+Path -1 2 -1 341 1857
+Curve 338 1850 335 1842
+<-------EndPath
+Path -1 3 1 335 1842
+Curve 274 1866 212 1889
+Curve 128 1816 59 1710
+Curve 47 1690 35 1670
+Curve -15 1584 -65 1498
+<-------EndPath
+Path -1 -1 1 -65 1498
+Curve -80 1473 -94 1448
+<-------EndPath
+Path 3 -1 0 -94 1448
+Curve -92 1444 -90 1440
+Curve -76 1461 -65 1498
+<-------EndPath
+Path 3 0 0 492 36
+Curve 472 30 479 -35
+Curve 492 -161 521 -285
+Curve 526 -305 530 -324
+<-------EndPath
+Path 1 0 -1 530 -324
+Curve 536 -303 542 -282
+Curve 555 -232 556 -183
+<-------EndPath
+Path 1 -1 0 984 -806
+Curve 988 -807 992 -808
+Curve 1008 -811 1024 -813
+<-------EndPath
+Path 0 0 0 762 -1511
+Curve 801 -1471 812 -1414
+<-------EndPath
+Path -1 3 0 328 455
+Curve 323 471 318 486
+Curve 318 487 318 487
+Curve 318 492 318 496
+<-------EndPath
+Path 3 3 1 346 707
+Curve 328 666 310 625
+<-------EndPath
+Path 3 3 0 210 1201
+Curve 172 1259 182 1330
+<-------EndPath
+Path 2 3 1 656 1690
+Curve 612 1714 567 1737
+Curve 461 1791 335 1842
+<-------EndPath
+Path 0 0 0 -184 -1301
+Curve -225 -1296 -238 -1282
+Curve -241 -1275 -243 -1267
+Curve -240 -1260 -237 -1252
+Curve -236 -1250 -234 -1247
+Curve -221 -1231 -199 -1221
+<-------EndPath
+Path 0 -1 0 148 -621
+Curve 50 -578 -66 -468
+Curve -184 -357 -275 -122
+Curve -310 -31 -344 61
+<-------EndPath
+Path 0 0 0 -335 65
+Curve -333 61 -331 56
+<-------EndPath
+Path 3 3 0 -113 335
+Curve -102 485 -241 608
+<-------EndPath
+Path 2 -1 1 -781 1542
+Curve -811 1584 -827 1637
+Curve -836 1668 -824 1701
+Curve -803 1750 -781 1798
+Curve -758 1844 -722 1882
+Curve -683 1915 -644 1947
+Curve -602 1976 -559 2004
+Curve -513 2034 -460 2045
+Curve -409 2052 -357 2059
+Curve -299 2062 -245 2040
+Curve -196 2019 -167 1973
+Curve -139 1926 -160 1907
+Curve -181 1888 -206 1891
+Curve -246 1888 -285 1884
+Curve -339 1873 -380 1840
+Curve -426 1803 -440 1748
+Curve -441 1733 -442 1717
+<-------EndPath
+Path 3 3 0 -36 969
+Curve -37 1029 -57 1086
+<-------EndPath
+!======EndShape
+=======BeginShape
+Path -1 -1 0 1168 -1867
+Curve 1045 -1871 922 -1875
+Curve 799 -1857 704 -1780
+Curve 686 -1764 667 -1747
+Curve 601 -1683 573 -1606
+Curve 520 -1729 576 -1836
+Curve 582 -1847 588 -1858
+Curve 638 -1952 708 -2034
+Curve 782 -2120 884 -2167
+Curve 908 -2176 932 -2185
+Curve 975 -2193 1018 -2201
+<-------EndPath
+Path -1 1 0 939 -1538
+Curve 999 -1526 1059 -1514
+Curve 1090 -1506 1121 -1498
+Curve 1262 -1454 1373 -1373
+Curve 1484 -1291 1506 -1240
+Curve 1528 -1190 1491 -1099
+Curve 1454 -1009 1074 -882
+Curve 1054 -879 1034 -876
+<-------EndPath
+Path -1 -1 0 1034 -876
+Curve 1009 -872 984 -868
+<-------EndPath
+Path -1 1 0 984 -868
+Curve 925 -859 866 -850
+<-------EndPath
+Path -1 0 0 866 -850
+Curve 835 -849 804 -847
+Curve 724 -850 643 -852
+<-------EndPath
+Path -1 -1 0 643 -852
+Curve 611 -851 579 -849
+Curve 562 -849 542 -832
+Curve 522 -811 502 -790
+Curve 488 -773 484 -756
+Curve 482 -743 480 -730
+<-------EndPath
+Path -1 1 0 480 -730
+Curve 478 -712 484 -698
+Curve 500 -673 515 -648
+<-------EndPath
+Path -1 4 0 515 -648
+Curve 524 -634 533 -620
+Curve 540 -610 546 -600
+Curve 555 -582 564 -564
+<-------EndPath
+Path -1 -1 0 564 -564
+Curve 566 -573 567 -581
+<-------EndPath
+Path 0 1 -1 959 -1528
+Curve 956 -1530 953 -1532
+Curve 946 -1535 939 -1538
+<-------EndPath
+Path 0 -1 0 939 -1538
+Curve 851 -1555 762 -1572
+<-------EndPath
+Path 0 0 0 762 -1572
+Curve 801 -1532 812 -1475
+<-------EndPath
+Path 1 0 -1 1222 -1389
+Curve 1328 -1370 1414 -1253
+Curve 1500 -1137 1358 -1048
+Curve 1215 -960 1068 -924
+Curve 930 -890 866 -850
+<-------EndPath
+Path 0 1 -1 1222 -1389
+Curve 1194 -1410 1165 -1431
+Curve 1071 -1497 959 -1528
+<-------EndPath
+Path 0 0 0 959 -1528
+Curve 1002 -1504 1023 -1456
+<-------EndPath
+Path 1 1 0 1121 -1498
+Curve 1196 -1472 1222 -1389
+<-------EndPath
+Path -1 -1 0 1043 -1994
+Curve 919 -2035 808 -1973
+Curve 708 -1917 630 -1832
+Curve 621 -1820 612 -1808
+Curve 546 -1720 573 -1606
+<-------EndPath
+Path 0 0 0 390 -1595
+Curve 405 -1580 420 -1565
+Curve 434 -1543 438 -1514
+<-------EndPath
+Path -1 0 0 230 -710
+Curve 258 -722 276 -735
+Curve 316 -762 334 -804
+Curve 338 -820 342 -836
+Curve 345 -857 334 -879
+Curve 323 -901 304 -917
+Curve 189 -949 -11 -1047
+Curve -295 -1186 -279 -1292
+Curve -276 -1315 -272 -1337
+Curve -269 -1347 -266 -1356
+Curve -246 -1412 -194 -1447
+Curve -114 -1501 -38 -1522
+Curve 27 -1539 92 -1555
+Curve 122 -1561 152 -1567
+Curve 155 -1567 157 -1567
+Curve 274 -1581 390 -1595
+Curve 414 -1596 437 -1596
+Curve 465 -1598 492 -1599
+Curve 520 -1598 548 -1597
+Curve 560 -1597 572 -1596
+Curve 625 -1592 678 -1588
+Curve 720 -1580 762 -1572
+<-------EndPath
+Path 0 0 0 157 -1567
+Curve 185 -1546 191 -1514
+Curve 194 -1494 189 -1469
+<-------EndPath
+Path -1 0 -1 643 -852
+Curve 619 -854 594 -856
+Curve 511 -834 473 -762
+Curve 468 -751 462 -739
+<-------EndPath
+Path -1 1 -1 462 -739
+Curve 471 -735 480 -730
+<-------EndPath
+Path 4 1 0 515 -648
+Curve 515 -635 514 -621
+Curve 513 -612 512 -603
+Curve 504 -548 495 -493
+<-------EndPath
+Path 4 0 0 495 -493
+Curve 492 -482 489 -470
+Curve 475 -416 461 -361
+Curve 444 -289 426 -216
+Curve 416 -172 393 -164
+Curve 354 -153 314 -142
+Curve 225 -121 134 -115
+Curve 142 -131 149 -147
+Curve 177 -200 204 -252
+Curve 265 -359 274 -482
+Curve 282 -612 230 -710
+<-------EndPath
+Path 4 -1 0 230 -710
+Curve 191 -697 152 -684
+Curve 150 -683 148 -682
+<-------EndPath
+Path 4 0 -1 148 -682
+Curve 151 -677 153 -671
+<-------EndPath
+Path 4 0 0 153 -671
+Curve 170 -551 140 -437
+Curve 108 -321 62 -212
+Curve 58 -203 53 -193
+Curve 5 -88 -75 -7
+Curve -174 92 -299 33
+Curve -335 16 -335 3
+<-------EndPath
+Path 4 0 -1 -335 3
+Curve -340 2 -344 0
+<-------EndPath
+Path 4 -1 0 -344 0
+Curve -347 8 -349 15
+Curve -396 152 -443 288
+Curve -460 346 -476 404
+Curve -482 427 -487 450
+Curve -488 452 -488 454
+Curve -489 460 -490 466
+Curve -493 473 -495 480
+Curve -496 483 -496 486
+Curve -497 488 -497 489
+Curve -498 490 -498 491
+Curve -498 492 -498 493
+Curve -499 494 -499 495
+Curve -499 497 -499 498
+Curve -503 515 -507 531
+Curve -513 569 -519 607
+<-------EndPath
+Path 4 -1 1 -519 607
+Curve -519 607 -518 607
+Curve -515 610 -512 613
+Curve -508 740 -459 841
+Curve -408 947 -388 1064
+Curve -385 1083 -381 1102
+<-------EndPath
+Path 4 4 1 -381 1102
+Curve -368 1202 -377 1305
+Curve -385 1382 -392 1459
+<-------EndPath
+Path 4 3 1 -392 1459
+Curve -397 1507 -402 1554
+Curve -405 1613 -407 1672
+<-------EndPath
+Path 4 -1 1 -407 1672
+Curve -407 1673 -407 1674
+Curve -404 1727 -393 1772
+Curve -352 1785 -311 1797
+<-------EndPath
+Path 4 3 1 -311 1797
+Curve -218 1821 -134 1826
+Curve -12 1830 136 1820
+<-------EndPath
+Path 4 -1 1 136 1820
+Curve 138 1820 139 1819
+Curve 288 1808 261 1685
+Curve 236 1574 234 1464
+Curve 234 1463 234 1462
+<-------EndPath
+Path 4 4 1 234 1462
+Curve 234 1452 234 1442
+Curve 234 1321 245 1198
+Curve 255 1077 273 958
+Curve 292 835 286 714
+Curve 284 670 281 626
+Curve 281 621 281 615
+Curve 283 571 294 531
+Curve 295 528 296 525
+<-------EndPath
+Path 4 4 0 296 525
+Curve 303 502 310 479
+<-------EndPath
+Path 4 2 1 310 479
+Curve 311 477 311 474
+Curve 313 471 315 467
+<-------EndPath
+Path 4 -1 0 315 467
+Curve 316 461 317 454
+Curve 318 445 318 435
+Curve 318 431 318 426
+Curve 318 426 318 425
+Curve 322 415 325 404
+Curve 327 399 328 394
+Curve 400 176 466 36
+Curve 479 6 492 -25
+<-------EndPath
+Path 4 0 0 492 -25
+Curve 472 -31 479 -96
+Curve 492 -222 521 -346
+Curve 526 -366 530 -385
+<-------EndPath
+Path 4 1 0 530 -385
+Curve 538 -422 546 -459
+Curve 548 -471 550 -482
+Curve 550 -483 550 -483
+Curve 557 -524 564 -564
+<-------EndPath
+Path -1 1 0 564 -564
+Curve 595 -478 569 -316
+Curve 563 -280 556 -244
+<-------EndPath
+Path -1 0 0 556 -244
+Curve 531 -125 492 -25
+<-------EndPath
+Path 1 0 -1 462 -739
+Curve 461 -736 460 -732
+Curve 430 -652 466 -565
+Curve 481 -529 495 -493
+<-------EndPath
+Path 1 0 -1 530 -385
+Curve 536 -364 542 -343
+Curve 555 -294 556 -244
+<-------EndPath
+Path -1 1 0 1034 -876
+Curve 1013 -873 992 -870
+Curve 988 -869 984 -868
+<-------EndPath
+Path 4 4 1 218 626
+Curve 214 595 209 564
+Curve 207 548 204 531
+Curve 200 493 195 454
+Curve 192 429 189 404
+<-------EndPath
+Path -1 -1 0 328 394
+Curve 327 399 326 404
+Curve 322 420 318 435
+<-------EndPath
+Path -1 2 0 315 467
+Curve 314 469 313 471
+Curve 312 475 310 479
+<-------EndPath
+Path -1 4 1 310 479
+Curve 310 590 375 692
+Curve 439 795 471 912
+Curve 502 1030 475 1151
+Curve 447 1275 360 1367
+Curve 288 1443 234 1462
+<-------EndPath
+Path 3 -1 1 -311 1797
+Curve -386 1907 -308 2009
+Curve -291 2022 -273 2035
+Curve -163 2087 -39 2082
+Curve 87 2075 215 2079
+Curve 361 2085 410 1967
+Curve 440 1897 368 1899
+Curve 228 1901 137 1829
+<-------EndPath
+Path 3 -1 -1 137 1829
+Curve 137 1825 136 1820
+<-------EndPath
+Path 0 0 0 -184 -1362
+Curve -225 -1357 -238 -1344
+Curve -241 -1336 -243 -1328
+Curve -240 -1321 -237 -1314
+Curve -236 -1312 -234 -1309
+Curve -221 -1292 -199 -1282
+<-------EndPath
+Path 0 -1 0 148 -682
+Curve 50 -639 -66 -529
+Curve -184 -418 -275 -183
+Curve -310 -92 -344 0
+<-------EndPath
+Path 4 4 0 -163 298
+Curve -159 352 -174 404
+Curve -185 429 -195 454
+Curve -216 493 -250 531
+Curve -270 551 -290 571
+<-------EndPath
+Path -1 -1 0 -519 607
+Curve -520 609 -520 611
+<-------EndPath
+Path -1 2 1 -520 611
+Curve -520 619 -520 626
+<-------EndPath
+Path -1 2 -1 -520 626
+Curve -521 626 -521 626
+Curve -521 625 -521 623
+Curve -521 623 -521 622
+Curve -521 617 -520 611
+<-------EndPath
+Path -1 -1 1 -518 607
+Curve -519 607 -519 607
+<-------EndPath
+Path 4 -1 1 -381 1102
+Curve -519 1126 -483 1262
+Curve -464 1316 -445 1369
+<-------EndPath
+Path 4 3 1 -445 1369
+Curve -422 1419 -392 1459
+<-------EndPath
+Path 3 -1 1 -445 1369
+Curve -594 1379 -558 1505
+Curve -543 1561 -502 1603
+Curve -458 1649 -407 1672
+<-------EndPath
+Path 0 0 0 -335 3
+Curve -333 -1 -331 -5
+<-------EndPath
+!======EndShape
+=======BeginShape
+Path -1 -1 0 1168 -1867
+Curve 1045 -1871 922 -1875
+Curve 799 -1857 704 -1780
+Curve 686 -1764 667 -1747
+Curve 601 -1683 573 -1606
+Curve 520 -1729 576 -1836
+Curve 582 -1847 588 -1858
+Curve 638 -1952 708 -2034
+Curve 782 -2120 884 -2167
+Curve 908 -2176 932 -2185
+Curve 975 -2193 1018 -2201
+<-------EndPath
+Path -1 1 0 939 -1538
+Curve 999 -1526 1059 -1514
+Curve 1090 -1506 1121 -1498
+Curve 1262 -1454 1373 -1373
+Curve 1484 -1291 1506 -1240
+Curve 1528 -1190 1491 -1099
+Curve 1454 -1009 1074 -882
+Curve 1054 -879 1034 -876
+<-------EndPath
+Path -1 -1 0 1034 -876
+Curve 1009 -872 984 -868
+<-------EndPath
+Path -1 1 0 984 -868
+Curve 925 -859 866 -850
+<-------EndPath
+Path -1 0 0 866 -850
+Curve 835 -849 804 -847
+Curve 724 -850 643 -852
+<-------EndPath
+Path -1 -1 0 643 -852
+Curve 611 -851 579 -849
+Curve 562 -849 542 -832
+Curve 522 -811 502 -790
+Curve 488 -773 484 -756
+Curve 482 -743 480 -730
+<-------EndPath
+Path -1 1 0 480 -730
+Curve 478 -712 484 -698
+Curve 500 -673 515 -648
+<-------EndPath
+Path -1 4 0 515 -648
+Curve 524 -634 533 -620
+Curve 540 -610 546 -600
+Curve 555 -582 564 -564
+<-------EndPath
+Path -1 -1 0 564 -564
+Curve 566 -573 567 -581
+<-------EndPath
+Path 0 1 -1 959 -1528
+Curve 956 -1530 953 -1532
+Curve 946 -1535 939 -1538
+<-------EndPath
+Path 0 -1 0 939 -1538
+Curve 851 -1555 762 -1572
+<-------EndPath
+Path 0 0 0 762 -1572
+Curve 801 -1532 812 -1475
+<-------EndPath
+Path 1 0 -1 1222 -1389
+Curve 1328 -1370 1414 -1253
+Curve 1500 -1137 1358 -1048
+Curve 1215 -960 1068 -924
+Curve 930 -890 866 -850
+<-------EndPath
+Path 0 1 -1 1222 -1389
+Curve 1194 -1410 1165 -1431
+Curve 1071 -1497 959 -1528
+<-------EndPath
+Path 0 0 0 959 -1528
+Curve 1002 -1504 1023 -1456
+<-------EndPath
+Path 1 1 0 1121 -1498
+Curve 1196 -1472 1222 -1389
+<-------EndPath
+Path -1 -1 0 1043 -1994
+Curve 919 -2035 808 -1973
+Curve 708 -1917 630 -1832
+Curve 621 -1820 612 -1808
+Curve 546 -1720 573 -1606
+<-------EndPath
+Path 0 0 0 390 -1595
+Curve 405 -1580 420 -1565
+Curve 434 -1543 438 -1514
+<-------EndPath
+Path -1 0 0 230 -710
+Curve 258 -722 276 -735
+Curve 316 -762 334 -804
+Curve 338 -820 342 -836
+Curve 345 -857 334 -879
+Curve 323 -901 304 -917
+Curve 189 -949 -11 -1047
+Curve -295 -1186 -279 -1292
+Curve -276 -1315 -272 -1337
+Curve -269 -1347 -266 -1356
+Curve -246 -1412 -194 -1447
+Curve -114 -1501 -38 -1522
+Curve 27 -1539 92 -1555
+Curve 122 -1561 152 -1567
+Curve 155 -1567 157 -1567
+Curve 274 -1581 390 -1595
+Curve 414 -1596 437 -1596
+Curve 465 -1598 492 -1599
+Curve 520 -1598 548 -1597
+Curve 560 -1597 572 -1596
+Curve 625 -1592 678 -1588
+Curve 720 -1580 762 -1572
+<-------EndPath
+Path 0 0 0 157 -1567
+Curve 185 -1546 191 -1514
+Curve 194 -1494 189 -1469
+<-------EndPath
+Path -1 0 -1 643 -852
+Curve 619 -854 594 -856
+Curve 511 -834 473 -762
+Curve 468 -751 462 -739
+<-------EndPath
+Path -1 1 -1 462 -739
+Curve 471 -735 480 -730
+<-------EndPath
+Path 4 1 0 515 -648
+Curve 515 -635 514 -621
+Curve 513 -612 512 -603
+Curve 504 -548 495 -493
+<-------EndPath
+Path 4 0 0 495 -493
+Curve 492 -482 489 -470
+Curve 475 -416 461 -361
+Curve 444 -289 426 -216
+Curve 416 -172 393 -164
+Curve 354 -153 314 -142
+Curve 225 -121 134 -115
+Curve 142 -131 149 -147
+Curve 177 -200 204 -252
+Curve 265 -359 274 -482
+Curve 282 -612 230 -710
+<-------EndPath
+Path 4 -1 0 230 -710
+Curve 191 -697 152 -684
+Curve 150 -683 148 -682
+<-------EndPath
+Path 4 0 -1 148 -682
+Curve 151 -677 153 -671
+<-------EndPath
+Path 4 0 0 153 -671
+Curve 170 -551 140 -437
+Curve 108 -321 62 -212
+Curve 58 -203 53 -193
+Curve 5 -88 -75 -7
+Curve -174 92 -299 33
+Curve -335 16 -335 3
+<-------EndPath
+Path 4 0 -1 -335 3
+Curve -340 2 -344 0
+<-------EndPath
+Path 4 -1 0 -344 0
+Curve -347 8 -349 15
+Curve -396 152 -443 288
+Curve -460 346 -476 404
+Curve -482 427 -487 450
+Curve -488 452 -488 454
+Curve -489 460 -490 466
+Curve -493 473 -495 480
+Curve -496 483 -496 486
+Curve -497 488 -497 489
+Curve -498 490 -498 491
+Curve -498 492 -498 493
+Curve -499 494 -499 495
+Curve -499 497 -499 498
+Curve -503 515 -507 531
+Curve -512 558 -516 584
+<-------EndPath
+Path 4 -1 -1 -516 584
+Curve -513 584 -509 584
+<-------EndPath
+Path 4 4 1 -509 584
+Curve -504 570 -499 556
+<-------EndPath
+Path 1 0 -1 462 -739
+Curve 461 -736 460 -732
+Curve 430 -652 466 -565
+Curve 481 -529 495 -493
+<-------EndPath
+Path 1 0 -1 530 -385
+Curve 536 -364 542 -343
+Curve 555 -294 556 -244
+<-------EndPath
+Path 1 -1 0 556 -244
+Curve 563 -280 569 -316
+Curve 595 -478 564 -564
+<-------EndPath
+Path 1 4 0 564 -564
+Curve 557 -524 550 -483
+Curve 550 -483 550 -482
+Curve 548 -471 546 -459
+Curve 538 -422 530 -385
+<-------EndPath
+Path 0 4 0 530 -385
+Curve 526 -366 521 -346
+Curve 492 -222 479 -96
+Curve 472 -31 492 -25
+<-------EndPath
+Path 0 -1 0 492 -25
+Curve 531 -125 556 -244
+<-------EndPath
+Path -1 1 0 1034 -876
+Curve 1013 -873 992 -870
+Curve 988 -869 984 -868
+<-------EndPath
+Path 4 -1 0 315 467
+Curve 316 461 317 454
+Curve 318 445 318 435
+Curve 318 431 318 426
+Curve 318 426 318 425
+Curve 322 415 325 404
+Curve 327 399 328 394
+Curve 400 176 466 36
+Curve 479 6 492 -25
+<-------EndPath
+Path -1 -1 0 328 394
+Curve 327 399 326 404
+Curve 322 420 318 435
+<-------EndPath
+Path 2 4 0 315 467
+Curve 313 471 311 474
+Curve 311 477 310 479
+<-------EndPath
+Path 2 -1 0 310 479
+Curve 312 475 313 471
+Curve 314 469 315 467
+<-------EndPath
+Path 4 4 0 310 479
+Curve 303 502 296 525
+Curve 295 528 294 531
+Curve 291 547 287 562
+<-------EndPath
+Path 4 4 1 287 562
+Curve 278 573 269 584
+Curve 231 651 206 729
+Curve 178 817 166 916
+Curve 154 1015 141 1113
+Curve 140 1127 138 1141
+<-------EndPath
+Path 4 -1 1 138 1141
+Curve 202 1159 197 1275
+Curve 188 1372 179 1468
+Curve 174 1499 220 1499
+Curve 241 1499 262 1498
+<-------EndPath
+Path 4 3 1 262 1498
+Curve 336 1495 410 1492
+Curve 508 1489 606 1486
+Curve 637 1486 651 1474
+Curve 652 1457 653 1440
+<-------EndPath
+Path 4 -1 1 653 1440
+Curve 659 1292 665 1143
+Curve 661 1046 657 948
+Curve 649 851 593 770
+Curve 536 689 448 651
+Curve 358 611 314 534
+<-------EndPath
+Path 4 -1 0 314 534
+Curve 312 507 310 479
+<-------EndPath
+Path -1 4 1 138 1141
+Curve 130 1221 130 1302
+Curve 133 1403 135 1503
+Curve 139 1597 127 1690
+Curve 115 1768 87 1828
+Curve 32 1833 -23 1837
+<-------EndPath
+Path -1 3 1 -23 1837
+Curve 4 1882 86 1891
+Curve 194 1902 193 2011
+Curve 193 2024 179 2039
+Curve 175 2043 170 2046
+Curve 162 2052 154 2057
+Curve 126 2074 93 2079
+Curve 0 2083 -93 2086
+Curve -189 2076 -284 2065
+Curve -380 2049 -460 2012
+Curve -525 1982 -561 1929
+Curve -612 1855 -543 1770
+<-------EndPath
+Path -1 4 1 -543 1770
+Curve -599 1752 -637 1726
+Curve -610 1665 -582 1604
+Curve -555 1530 -528 1456
+Curve -505 1383 -496 1306
+Curve -484 1212 -493 1117
+Curve -504 1025 -515 933
+Curve -527 839 -531 747
+Curve -535 663 -509 584
+<-------EndPath
+Path -1 3 1 653 1440
+Curve 726 1338 835 1376
+Curve 943 1413 914 1456
+Curve 884 1497 803 1575
+Curve 776 1611 691 1647
+Curve 683 1651 674 1655
+Curve 628 1678 581 1701
+Curve 492 1744 394 1755
+Curve 273 1768 259 1651
+Curve 248 1568 262 1498
+<-------EndPath
+Path 0 0 0 -184 -1362
+Curve -225 -1357 -238 -1344
+Curve -241 -1336 -243 -1328
+Curve -240 -1321 -237 -1314
+Curve -236 -1312 -234 -1309
+Curve -221 -1292 -199 -1282
+<-------EndPath
+Path 0 -1 0 148 -682
+Curve 50 -639 -66 -529
+Curve -184 -418 -275 -183
+Curve -310 -92 -344 0
+<-------EndPath
+Path 4 4 0 -204 324
+Curve -200 378 -216 430
+Curve -227 455 -237 480
+Curve -258 519 -292 557
+Curve -306 571 -319 584
+Curve -326 591 -332 597
+<-------EndPath
+Path 3 4 1 -23 1837
+Curve -38 1839 -53 1841
+Curve -159 1835 -265 1829
+Curve -368 1808 -471 1787
+Curve -507 1779 -543 1770
+<-------EndPath
+Path 4 4 1 -543 1770
+Curve -540 1766 -537 1762
+<-------EndPath
+Path 0 0 0 -335 3
+Curve -333 -1 -331 -5
+<-------EndPath
+!======EndShape
+=======BeginShape
+Path 0 -1 -1 22 -320
+Curve 15 -320 8 -320
+<-------EndPath
+Path 0 -1 0 8 -320
+Curve 8 -275 8 -230
+<-------EndPath
+Path 0 2 1 8 -230
+Curve 15 -275 22 -320
+<-------EndPath
+Path -1 2 -1 22 -320
+Curve 1609 -320 3195 -320
+<-------EndPath
+Path -1 0 -1 3195 -320
+Curve 3285 -320 3375 -320
+<-------EndPath
+Path -1 1 -1 3375 -320
+Curve 4296 -320 5216 -320
+<-------EndPath
+Path -1 2 -1 5216 -320
+Curve 5854 -320 6491 -320
+<-------EndPath
+Path -1 4 -1 6491 -320
+Curve 6552 -320 6612 -320
+<-------EndPath
+Path -1 2 -1 6612 -320
+Curve 7167 -320 7721 -320
+Curve 7721 1266 7721 2851
+<-------EndPath
+Path -1 6 -1 7721 2851
+Curve 7721 3049 7721 3247
+<-------EndPath
+Path -1 5 -1 7721 3247
+Curve 7721 4020 7721 4793
+<-------EndPath
+Path -1 10 -1 7721 4793
+Curve 7721 4860 7721 4927
+<-------EndPath
+Path -1 5 -1 7721 4927
+Curve 7721 5315 7721 5702
+Curve 7721 5733 7721 5764
+<-------EndPath
+Path -1 9 -1 7721 5764
+Curve 7721 5898 7721 6032
+<-------EndPath
+Path -1 11 -1 7721 6032
+Curve 7721 6197 7721 6362
+Curve 6171 6362 4621 6362
+<-------EndPath
+Path -1 12 -1 4621 6362
+Curve 4624 6362 4626 6362
+Curve 4557 6362 4488 6362
+<-------EndPath
+Path -1 13 -1 4488 6362
+Curve 4324 6362 4159 6362
+<-------EndPath
+Path -1 12 -1 4159 6362
+Curve 3802 6362 3444 6362
+Curve 1726 6362 8 6362
+<-------EndPath
+Path -1 12 0 8 6362
+Curve 8 6308 8 6254
+<-------EndPath
+Path -1 11 0 8 6254
+Curve 8 6032 8 5809
+<-------EndPath
+Path -1 15 0 8 5809
+Curve 8 5633 8 5457
+<-------EndPath
+Path -1 5 0 8 5457
+Curve 8 5457 8 5456
+Curve 8 5041 8 4626
+<-------EndPath
+Path -1 10 0 8 4626
+Curve 8 4520 8 4414
+<-------EndPath
+Path -1 5 0 8 4414
+Curve 8 3806 8 3197
+<-------EndPath
+Path -1 6 0 8 3197
+Curve 8 2946 8 2695
+<-------EndPath
+Path -1 2 0 8 2695
+Curve 8 1233 8 -230
+<-------EndPath
+Path 0 2 1 3195 -320
+Curve 3200 -255 3195 -184
+<-------EndPath
+Path 0 1 -1 3195 -184
+Curve 3289 -244 3375 -320
+<-------EndPath
+Path 2 3 -1 5136 -240
+Curve 5136 -237 5136 -234
+Curve 5135 -237 5134 -239
+Curve 5135 -240 5136 -240
+<-------EndPath
+Path 1 2 1 5146 824
+Curve 4942 433 4910 183
+Curve 4866 -154 5133 -240
+Curve 5135 -241 5136 -241
+Curve 5215 -265 5322 -268
+Curve 5269 -294 5216 -320
+<-------EndPath
+Path 4 2 1 6950 2817
+Curve 6780 1427 6703 1302
+Curve 6487 953 6725 637
+Curve 6852 468 6959 347
+Curve 6827 464 6617 459
+Curve 6593 73 6612 -316
+Curve 6612 -318 6612 -320
+<-------EndPath
+Path 4 2 -1 6695 2810
+Curve 6823 2814 6950 2817
+<-------EndPath
+Path 5 10 -1 7721 4927
+Curve 7619 4925 7516 4923
+Curve 6847 4910 6186 4887
+Curve 5951 4878 5715 4869
+Curve 5183 4849 4651 4828
+Curve 4126 4809 3601 4789
+Curve 2617 4746 1633 4703
+Curve 821 4665 8 4626
+<-------EndPath
+Path 5 9 -1 4012 5632
+Curve 5463 5686 6913 5740
+Curve 7317 5752 7721 5764
+<-------EndPath
+Path 4 2 1 6491 -320
+Curve 6489 -71 6445 173
+Curve 6376 553 6473 942
+Curve 6540 1207 6695 2810
+<-------EndPath
+Path 1 1 1 5146 824
+Curve 5146 825 5145 825
+<-------EndPath
+Path 1 2 1 5145 825
+Curve 5153 839 5161 853
+Curve 5154 839 5146 824
+<-------EndPath
+Path 1 2 1 3195 -184
+Curve 3176 62 3029 374
+Curve 4121 483 3578 976
+Curve 3406 1132 3318 1238
+Curve 3147 1443 3292 1458
+Curve 3245 1383 3535 1379
+Curve 3836 1374 4167 712
+Curve 4276 493 4420 431
+Curve 4711 307 5145 825
+<-------EndPath
+Path 5 6 -1 3484 3874
+Curve 3665 3840 3851 3824
+Curve 2711 3577 1555 3767
+Curve 1415 3790 1274 3824
+Curve 1258 3839 1241 3853
+Curve 1222 3867 1202 3880
+Curve 1198 3872 1193 3863
+Curve 1211 3823 1243 3790
+Curve 1253 3779 1263 3767
+Curve 1425 3740 1586 3713
+Curve 1833 3669 2086 3644
+Curve 2149 3637 2188 3623
+Curve 3309 3646 4416 3824
+Curve 4422 3829 4427 3834
+Curve 4417 3839 4406 3843
+Curve 4098 3872 3790 3901
+Curve 5355 3868 6890 3880
+Curve 5147 4087 3482 3891
+Curve 3482 3874 3484 3874
+<-------EndPath
+Path 8 2 -1 5324 2797
+Curve 5324 2796 5324 2794
+<-------EndPath
+Path 8 2 1 5324 2794
+Curve 5305 2793 5286 2792
+<-------EndPath
+Path 8 7 -1 5286 2792
+Curve 5286 2794 5285 2796
+<-------EndPath
+Path 8 6 1 5285 2796
+Curve 5305 2797 5324 2797
+<-------EndPath
+Path 2 6 1 5324 2797
+Curve 6523 2824 7721 2851
+<-------EndPath
+Path 2 7 1 5285 2792
+Curve 5286 2792 5286 2792
+<-------EndPath
+Path 6 7 -1 5285 2796
+Curve 5285 2794 5285 2792
+<-------EndPath
+Path 6 2 1 5285 2792
+Curve 2647 2744 8 2695
+<-------EndPath
+Path 5 7 -1 5203 3225
+Curve 5184 3225 5164 3225
+Curve 5164 3225 5164 3224
+<-------EndPath
+Path 5 6 -1 5164 3224
+Curve 2586 3211 8 3197
+<-------EndPath
+Path 6 7 -1 5164 3224
+Curve 5184 3225 5203 3225
+<-------EndPath
+Path 6 5 -1 5203 3225
+Curve 5589 3229 5975 3232
+<-------EndPath
+Path 6 14 -1 5975 3232
+Curve 5976 3231 5976 3229
+Curve 5977 3229 5977 3229
+Curve 5984 3231 5991 3232
+<-------EndPath
+Path 6 5 -1 5991 3232
+Curve 6856 3240 7721 3247
+<-------EndPath
+Path 5 14 -1 5991 3232
+Curve 5983 3232 5975 3232
+<-------EndPath
+Path 10 5 -1 7721 4793
+Curve 6961 4730 6189 4701
+Curve 5423 4656 4657 4611
+Curve 3930 4566 3202 4520
+Curve 1921 4480 640 4440
+Curve 328 4427 15 4414
+Curve 12 4414 8 4414
+<-------EndPath
+Path 5 15 -1 8 5457
+Curve 18 5458 27 5458
+Curve 1693 5530 3359 5602
+Curve 3576 5612 3793 5622
+<-------EndPath
+Path 5 5 0 3793 5622
+Curve 3833 5599 3875 5579
+Curve 1942 5518 8 5456
+<-------EndPath
+Path 16 17 0 3418 5910
+Curve 3419 5909 3420 5908
+<-------EndPath
+Path 16 15 0 3420 5908
+Curve 3419 5908 3417 5908
+<-------EndPath
+Path 16 11 0 3417 5908
+Curve 3418 5909 3418 5910
+<-------EndPath
+Path 17 11 0 3418 5910
+Curve 3458 6101 3464 6334
+<-------EndPath
+Path 17 16 0 3464 6334
+Curve 3465 6343 3465 6351
+<-------EndPath
+Path 17 12 0 3465 6351
+Curve 3507 6323 3548 6294
+Curve 3557 6285 3566 6275
+<-------EndPath
+Path 17 11 0 3566 6275
+Curve 3556 6106 3545 5936
+<-------EndPath
+Path 17 16 0 3545 5936
+Curve 3544 5924 3543 5911
+Curve 3551 5911 3558 5911
+<-------EndPath
+Path 17 9 0 3558 5911
+Curve 3687 5676 3926 5628
+<-------EndPath
+Path 17 5 -1 3926 5628
+Curve 3860 5625 3793 5622
+<-------EndPath
+Path 17 15 0 3793 5622
+Curve 3601 5730 3420 5908
+<-------EndPath
+Path 11 16 0 3558 5911
+Curve 3552 5924 3545 5936
+<-------EndPath
+Path 5 9 0 3926 5628
+Curve 3969 5630 4012 5632
+<-------EndPath
+Path 13 12 -1 4273 6353
+Curve 4216 6358 4159 6362
+<-------EndPath
+Path 13 12 -1 4488 6362
+Curve 4488 6360 4488 6358
+<-------EndPath
+Path 13 11 0 4488 6358
+Curve 4381 6356 4273 6353
+<-------EndPath
+Path 12 11 0 4273 6353
+Curve 3921 6345 3569 6336
+Curve 3568 6306 3566 6275
+<-------EndPath
+Path 11 12 0 4488 6358
+Curve 4555 6360 4621 6362
+<-------EndPath
+Path 16 12 0 3461 6353
+Curve 3463 6352 3465 6351
+<-------EndPath
+Path 12 12 0 3461 6353
+Curve 3453 6358 3444 6362
+<-------EndPath
+Path 16 12 -1 3461 6334
+Curve 3461 6344 3461 6353
+<-------EndPath
+Path 16 11 0 3464 6334
+Curve 3463 6334 3461 6334
+<-------EndPath
+Path 12 11 0 3461 6334
+Curve 1735 6294 8 6254
+<-------EndPath
+Path 11 11 0 3418 5910
+Curve 3403 5925 3387 5940
+<-------EndPath
+Path 11 15 0 3417 5908
+Curve 1713 5859 8 5809
+<-------EndPath
+Path 11 9 0 7721 6032
+Curve 5640 5972 3558 5911
+<-------EndPath
+Path 5 5 0 3875 5579
+Curve 5798 5641 7721 5702
+<-------EndPath
+!======EndShape
+=======BeginShape
+Path -1 -1 1 46 -2079
+Curve 79 -2083 112 -2087
+Curve 228 -2098 330 -2028
+Curve 433 -1961 484 -1849
+Curve 489 -1838 493 -1827
+Curve 519 -1763 527 -1697
+Curve 534 -1673 541 -1649
+Curve 542 -1649 542 -1648
+Curve 546 -1671 549 -1693
+Curve 549 -1694 549 -1695
+Curve 559 -1789 530 -1883
+Curve 492 -1998 453 -2112
+Curve 410 -2233 291 -2302
+Curve 212 -2350 127 -2385
+Curve 24 -2429 -85 -2432
+<-------EndPath
+Path 0 -1 1 873 -1534
+Curve 870 -1535 866 -1536
+Curve 772 -1574 675 -1595
+Curve 607 -1608 538 -1620
+Curve 533 -1621 528 -1622
+Curve 438 -1633 348 -1644
+Curve 266 -1654 174 -1646
+<-------EndPath
+Path 0 0 1 174 -1646
+Curve 240 -1626 258 -1565
+<-------EndPath
+Path 1 -1 1 1338 -1166
+Curve 1313 -1230 1244 -1299
+Curve 1231 -1312 1217 -1325
+Curve 1211 -1331 1205 -1336
+Curve 1089 -1440 947 -1501
+Curve 910 -1518 873 -1534
+<-------EndPath
+Path 1 0 1 873 -1534
+Curve 880 -1513 887 -1492
+<-------EndPath
+Path 1 0 -1 887 -1492
+Curve 987 -1428 1064 -1339
+Curve 1102 -1294 1139 -1248
+Curve 1170 -1211 1220 -1085
+Curve 1269 -959 1027 -882
+Curve 784 -805 606 -793
+Curve 563 -791 527 -777
+Curve 523 -775 518 -773
+Curve 508 -774 497 -775
+Curve 495 -765 492 -754
+Curve 492 -754 491 -754
+Curve 465 -740 454 -716
+Curve 453 -719 452 -722
+Curve 447 -735 445 -713
+Curve 444 -690 443 -667
+Curve 443 -666 443 -664
+Curve 443 -659 443 -654
+Curve 442 -562 466 -503
+Curve 481 -468 495 -432
+<-------EndPath
+Path 1 4 0 495 -432
+Curve 504 -487 512 -542
+Curve 513 -551 514 -559
+Curve 515 -573 515 -587
+<-------EndPath
+Path 1 -1 0 515 -587
+Curve 500 -612 484 -636
+Curve 478 -651 480 -669
+<-------EndPath
+Path 1 -1 -1 480 -669
+Curve 479 -670 478 -670
+<-------EndPath
+Path 1 -1 1 478 -670
+Curve 480 -675 481 -679
+Curve 484 -688 486 -696
+Curve 489 -703 491 -709
+Curve 492 -711 493 -713
+Curve 503 -739 514 -750
+Curve 525 -761 536 -772
+Curve 555 -776 574 -780
+Curve 579 -779 583 -778
+Curve 588 -778 592 -777
+Curve 635 -774 678 -771
+Curve 965 -758 1196 -892
+Curve 1347 -981 1353 -1088
+<-------EndPath
+Path 1 1 1 1353 -1088
+Curve 1355 -1126 1338 -1166
+<-------EndPath
+Path -1 1 1 1338 -1166
+Curve 1437 -1148 1353 -1088
+<-------EndPath
+Path 0 0 1 887 -1492
+Curve 890 -1473 893 -1453
+<-------EndPath
+Path -1 -1 1 528 -1622
+Curve 529 -1635 529 -1647
+Curve 528 -1672 527 -1697
+Curve 501 -1763 448 -1814
+Curve 429 -1830 409 -1845
+Curve 306 -1916 183 -1938
+Curve 132 -1947 84 -1939
+<-------EndPath
+Path 0 -1 1 174 -1646
+Curve 94 -1634 13 -1621
+<-------EndPath
+Path 0 0 1 13 -1621
+Curve 76 -1591 116 -1531
+<-------EndPath
+Path -1 0 -1 430 -722
+Curve 437 -722 444 -722
+Curve 436 -724 428 -726
+<-------EndPath
+Path -1 1 -1 428 -726
+Curve 429 -724 430 -722
+<-------EndPath
+Path 0 1 -1 430 -722
+Curve 377 -722 323 -722
+<-------EndPath
+Path 0 -1 0 323 -722
+Curve 320 -718 317 -713
+Curve 301 -690 276 -673
+Curve 253 -661 230 -649
+<-------EndPath
+Path 0 4 0 230 -649
+Curve 282 -551 274 -421
+Curve 265 -297 204 -190
+Curve 177 -138 149 -86
+Curve 142 -70 134 -54
+Curve 225 -59 314 -81
+Curve 354 -92 393 -103
+Curve 416 -111 426 -155
+Curve 443 -227 460 -299
+Curve 461 -300 461 -300
+Curve 475 -355 489 -409
+Curve 492 -421 495 -432
+<-------EndPath
+Path -1 -1 1 491 -709
+Curve 486 -694 481 -679
+<-------EndPath
+Path -1 4 0 515 -587
+Curve 524 -573 533 -558
+Curve 540 -549 546 -539
+Curve 553 -528 559 -516
+Curve 562 -509 564 -502
+<-------EndPath
+Path -1 1 0 564 -502
+Curve 595 -417 569 -254
+Curve 563 -219 556 -183
+<-------EndPath
+Path -1 0 0 556 -183
+Curve 531 -63 492 36
+<-------EndPath
+Path -1 4 0 492 36
+Curve 479 67 466 97
+Curve 400 237 328 455
+<-------EndPath
+Path -1 -1 0 328 455
+Curve 323 476 318 496
+<-------EndPath
+Path -1 4 0 318 496
+Curve 319 521 319 546
+Curve 321 567 323 588
+Curve 339 732 412 874
+Curve 465 979 499 1089
+Curve 531 1193 546 1302
+Curve 566 1441 558 1575
+Curve 555 1611 511 1632
+<-------EndPath
+Path -1 3 0 511 1632
+Curve 552 1669 751 1503
+Curve 974 1539 813 1696
+Curve 652 1852 449 1910
+Curve 246 1967 224 1686
+<-------EndPath
+Path -1 3 -1 224 1686
+Curve 224 1683 223 1680
+<-------EndPath
+Path -1 4 0 223 1680
+Curve 153 1694 83 1707
+Curve -33 1730 -49 1586
+Curve -61 1482 -90 1440
+Curve -106 1473 -121 1505
+Curve -198 1658 -291 1789
+Curve -308 1808 -324 1826
+Curve -350 1843 -375 1859
+Curve -419 1845 -462 1830
+Curve -485 1822 -507 1813
+<-------EndPath
+Path -1 3 0 -507 1813
+Curve -442 1848 -383 1875
+Curve -319 1901 -255 1927
+Curve -234 1933 -225 1947
+Curve -222 1961 -243 2025
+Curve -285 2039 -340 2042
+Curve -366 2042 -392 2042
+Curve -459 2034 -526 2025
+Curve -705 1988 -859 1907
+Curve -1051 1806 -910 1657
+<-------EndPath
+Path -1 4 0 -910 1657
+Curve -931 1636 -952 1614
+Curve -938 1591 -923 1568
+Curve -826 1434 -749 1288
+Curve -699 1191 -659 1089
+Curve -642 1041 -624 992
+Curve -575 844 -522 705
+Curve -522 695 -521 684
+Curve -515 620 -499 559
+Curve -499 558 -499 556
+Curve -499 555 -498 554
+Curve -498 553 -498 552
+Curve -498 551 -497 550
+Curve -497 549 -496 547
+Curve -496 544 -495 541
+Curve -493 534 -490 527
+Curve -489 520 -487 512
+Curve -468 422 -443 349
+Curve -396 213 -349 76
+Curve -347 69 -344 61
+<-------EndPath
+Path -1 0 0 -344 61
+Curve -310 -31 -275 -122
+Curve -184 -357 -66 -468
+Curve 50 -578 148 -621
+<-------EndPath
+Path -1 4 0 148 -621
+Curve 150 -622 152 -622
+Curve 191 -636 230 -649
+<-------EndPath
+Path -1 0 1 323 -722
+Curve 342 -779 299 -808
+Curve 256 -838 230 -846
+Curve 165 -864 81 -896
+Curve -81 -958 -266 -1062
+Curve -447 -1164 -443 -1319
+Curve -443 -1324 -443 -1328
+Curve -435 -1471 -209 -1557
+Curve -179 -1568 -148 -1579
+Curve -68 -1600 13 -1621
+<-------EndPath
+Path 4 0 -1 148 -621
+Curve 151 -615 153 -609
+<-------EndPath
+Path 4 0 0 153 -609
+Curve 170 -489 140 -376
+Curve 108 -260 62 -151
+Curve 58 -142 53 -132
+Curve 5 -27 -75 54
+Curve -174 154 -299 95
+Curve -335 78 -335 65
+<-------EndPath
+Path 4 0 -1 -335 65
+Curve -340 63 -344 61
+<-------EndPath
+Path 1 4 0 564 -502
+Curve 557 -462 550 -422
+Curve 550 -421 550 -420
+Curve 548 -409 546 -397
+Curve 538 -361 530 -324
+<-------EndPath
+Path 1 0 -1 530 -324
+Curve 536 -303 542 -282
+Curve 555 -232 556 -183
+<-------EndPath
+Path 0 4 0 530 -324
+Curve 526 -305 522 -286
+Curve 522 -286 521 -285
+Curve 492 -161 479 -35
+Curve 472 30 492 36
+<-------EndPath
+Path 1 0 -1 428 -726
+Curve 376 -724 323 -722
+<-------EndPath
+Path -1 4 0 328 455
+Curve 323 471 318 486
+Curve 318 487 318 487
+Curve 318 492 318 496
+<-------EndPath
+Path 4 4 0 -90 1440
+Curve -49 1346 -18 1248
+Curve -12 1226 -5 1204
+Curve 11 1147 27 1089
+Curve 55 994 83 899
+Curve 98 845 112 790
+Curve 124 738 136 685
+Curve 143 659 149 633
+Curve 149 590 148 547
+<-------EndPath
+Path 4 4 0 88 1212
+Curve 69 1241 63 1274
+Curve 56 1306 61 1342
+<-------EndPath
+Path 2 3 -1 375 1656
+Curve 375 1660 375 1664
+<-------EndPath
+Path 2 3 0 375 1664
+Curve 393 1661 411 1658
+<-------EndPath
+Path 2 4 0 411 1658
+Curve 393 1657 375 1656
+<-------EndPath
+Path 3 4 0 375 1656
+Curve 299 1668 223 1680
+<-------EndPath
+Path 3 4 0 511 1632
+Curve 494 1638 476 1644
+Curve 451 1650 426 1655
+Curve 419 1657 411 1658
+<-------EndPath
+Path 0 0 1 -209 -1557
+Curve -141 -1528 -100 -1466
+<-------EndPath
+Path 0 0 1 -355 -1352
+Curve -397 -1340 -402 -1319
+Curve -408 -1298 -376 -1267
+<-------EndPath
+Path 4 4 0 -235 347
+Curve -223 497 -362 620
+<-------EndPath
+Path 4 3 0 -910 1657
+Curve -910 1658 -910 1658
+Curve -854 1703 -771 1727
+Curve -647 1763 -524 1807
+Curve -516 1810 -507 1813
+<-------EndPath
+Path 4 4 0 -157 980
+Curve -158 1036 -175 1089
+<-------EndPath
+!======EndShape
+=======BeginShape
+Path -1 0 0 -234 -1074
+Curve -187 -1080 -139 -1085
+Curve -53 -1093 37 -1081
+Curve 129 -1062 220 -1043
+Curve 262 -1035 304 -1026
+<-------EndPath
+Path -1 -1 0 304 -1026
+Curve 396 -1045 409 -989
+<-------EndPath
+Path -1 0 0 409 -989
+Curve 411 -989 413 -988
+Curve 430 -981 447 -973
+<-------EndPath
+Path -1 -1 0 447 -973
+Curve 514 -961 534 -929
+<-------EndPath
+Path -1 0 0 534 -929
+Curve 570 -908 606 -886
+<-------EndPath
+Path -1 -1 0 606 -886
+Curve 647 -868 662 -848
+<-------EndPath
+Path -1 0 0 662 -848
+Curve 775 -761 758 -609
+Curve 737 -440 596 -372
+Curve 514 -333 435 -326
+Curve 384 -328 333 -330
+<-------EndPath
+Path -1 0 -1 333 -330
+Curve 330 -331 327 -331
+<-------EndPath
+Path -1 0 0 327 -331
+Curve 327 -331 326 -331
+Curve 324 -332 322 -332
+Curve 248 -336 174 -340
+Curve 108 -333 79 -290
+<-------EndPath
+Path -1 2 0 79 -290
+Curve 111 -296 143 -301
+Curve 248 -321 314 -300
+Curve 356 -290 397 -279
+Curve 400 -279 403 -278
+Curve 416 -277 429 -275
+Curve 460 -273 490 -270
+<-------EndPath
+Path -1 6 0 490 -270
+Curve 556 -315 590 -226
+<-------EndPath
+Path -1 5 0 590 -226
+Curve 597 -219 603 -212
+<-------EndPath
+Path -1 2 0 603 -212
+Curve 605 -210 607 -207
+Curve 618 -191 628 -175
+Curve 645 -140 662 -104
+<-------EndPath
+Path -1 7 0 662 -104
+Curve 687 -120 712 -136
+Curve 711 -125 718 -115
+Curve 748 -74 787 -44
+Curve 773 -45 759 -46
+Curve 750 -45 741 -43
+<-------EndPath
+Path -1 6 0 741 -43
+Curve 783 64 749 165
+Curve 740 190 725 205
+<-------EndPath
+Path -1 -1 0 725 205
+Curve 728 227 731 248
+<-------EndPath
+Path -1 0 0 606 -886
+Curve 626 -873 645 -860
+Curve 649 -857 653 -854
+Curve 658 -851 662 -848
+<-------EndPath
+Path 0 0 0 662 -848
+Curve 691 -806 607 -752
+<-------EndPath
+Path 0 1 -1 607 -752
+Curve 650 -716 692 -679
+Curve 673 -646 654 -613
+Curve 618 -575 582 -537
+Curve 522 -495 462 -453
+Curve 331 -399 75 -389
+Curve 63 -377 50 -365
+Curve 20 -331 4 -293
+Curve -11 -260 -15 -224
+Curve -16 -218 -17 -211
+Curve -18 -202 -18 -193
+Curve -14 -192 -10 -191
+Curve 14 -129 68 -103
+Curve 95 -90 129 -86
+<-------EndPath
+Path 0 3 0 129 -86
+Curve 135 -110 141 -134
+<-------EndPath
+Path 0 2 0 141 -134
+Curve 80 -170 56 -224
+<-------EndPath
+Path 0 2 -1 56 -224
+Curve 56 -224 55 -224
+<-------EndPath
+Path 0 0 0 55 -224
+Curve 55 -209 54 -193
+Curve 55 -184 56 -174
+<-------EndPath
+Path -1 0 0 447 -973
+Curve 490 -952 533 -930
+Curve 534 -930 534 -929
+<-------EndPath
+Path 0 0 0 534 -929
+Curve 559 -890 510 -821
+<-------EndPath
+Path 0 1 -1 510 -821
+Curve 560 -790 607 -752
+<-------EndPath
+Path 1 1 0 607 -752
+Curve 594 -745 580 -737
+<-------EndPath
+Path 1 0 -1 510 -821
+Curve 452 -855 393 -888
+Curve 323 -923 249 -948
+Curve 77 -1005 -99 -1019
+Curve -237 -1013 -375 -1007
+Curve -390 -1005 -404 -1002
+<-------EndPath
+Path 1 1 0 -404 -1002
+Curve -407 -977 -410 -952
+<-------EndPath
+Path 1 0 -1 14 -709
+Curve -8 -679 -42 -689
+Curve -104 -706 -101 -767
+Curve -101 -773 -100 -778
+Curve -133 -722 -197 -705
+Curve -216 -710 -234 -715
+Curve -293 -769 -250 -846
+Curve -237 -868 -224 -889
+Curve -224 -912 -216 -933
+Curve -212 -941 -208 -949
+Curve -206 -951 -204 -953
+Curve -199 -956 -194 -958
+Curve -186 -955 -178 -952
+Curve -163 -890 -178 -827
+Curve -180 -820 -182 -812
+Curve -164 -844 -133 -871
+Curve -105 -889 -77 -906
+Curve -54 -905 -31 -904
+Curve -13 -859 -40 -826
+Curve -39 -806 -38 -785
+Curve -39 -776 -40 -766
+Curve -39 -764 -38 -761
+Curve -35 -760 -32 -758
+Curve -3 -820 56 -857
+Curve 63 -860 69 -863
+Curve 83 -861 96 -859
+Curve 140 -827 92 -789
+Curve 46 -756 14 -709
+<-------EndPath
+Path 0 0 0 333 -330
+Curve 330 -331 327 -331
+<-------EndPath
+Path 2 2 0 397 -279
+Curve 385 -279 375 -263
+Curve 354 -230 340 -230
+Curve 326 -232 311 -233
+Curve 266 -239 220 -245
+Curve 143 -255 101 -222
+Curve 101 -251 82 -283
+<-------EndPath
+Path 2 3 0 141 -134
+Curve 143 -134 144 -133
+Curve 160 -123 175 -113
+Curve 176 -113 176 -112
+<-------EndPath
+Path 2 4 0 176 -112
+Curve 191 -105 205 -97
+Curve 242 -78 278 -59
+<-------EndPath
+Path 2 3 0 278 -59
+Curve 349 -16 410 43
+<-------EndPath
+Path 2 6 0 410 43
+Curve 410 34 409 25
+<-------EndPath
+Path 2 2 0 409 25
+Curve 406 24 403 23
+<-------EndPath
+Path 2 0 0 79 -290
+Curve 63 -268 57 -237
+Curve 56 -231 55 -224
+<-------EndPath
+Path 3 1 0 129 -86
+Curve 114 -53 79 -43
+Curve 78 -43 76 -42
+Curve 48 -38 20 -33
+Curve -72 -28 -129 -96
+Curve -132 -100 -135 -103
+<-------EndPath
+Path 3 0 0 -135 -103
+Curve -149 -125 -162 -146
+<-------EndPath
+Path 3 2 0 -162 -146
+Curve -167 -141 -171 -135
+<-------EndPath
+Path 3 7 0 -171 -135
+Curve -179 -125 -187 -114
+<-------EndPath
+Path 3 4 0 -187 -114
+Curve -189 -75 -180 -45
+Curve -170 -14 -150 8
+Curve -127 24 -103 39
+Curve -61 56 2 56
+Curve 20 55 37 54
+Curve 62 48 86 41
+Curve 167 5 176 -112
+<-------EndPath
+Path 2 5 0 603 -212
+Curve 596 -213 588 -214
+<-------EndPath
+Path 2 6 0 588 -214
+Curve 501 -225 469 -138
+Curve 450 -87 463 51
+<-------EndPath
+Path 2 2 0 463 51
+Curve 528 90 571 163
+Curve 598 207 608 253
+<-------EndPath
+Path 2 5 0 608 253
+Curve 627 271 633 297
+<-------EndPath
+Path 2 -1 0 633 297
+Curve 654 260 674 223
+<-------EndPath
+Path 2 6 0 674 223
+Curve 648 223 614 210
+<-------EndPath
+Path 2 -1 0 614 210
+Curve 619 198 624 186
+<-------EndPath
+Path 2 12 0 624 186
+Curve 603 170 593 178
+Curve 593 170 592 161
+Curve 589 59 551 -43
+<-------EndPath
+Path 2 2 0 551 -43
+Curve 545 -41 539 -39
+<-------EndPath
+Path 2 12 0 551 -43
+Curve 557 -46 563 -49
+<-------EndPath
+Path 2 7 0 563 -49
+Curve 575 -54 589 -62
+Curve 627 -82 662 -104
+<-------EndPath
+Path 6 5 -1 588 -214
+Curve 589 -220 590 -226
+<-------EndPath
+Path 7 6 0 616 3
+Curve 649 -16 688 -29
+Curve 715 -36 741 -43
+<-------EndPath
+Path 6 2 0 490 -270
+Curve 458 -230 426 -190
+Curve 397 -152 409 25
+<-------EndPath
+Path 6 6 0 409 25
+Curve 438 35 463 51
+<-------EndPath
+Path 2 6 0 463 51
+Curve 467 79 470 107
+<-------EndPath
+Path 2 3 0 470 107
+Curve 477 115 483 123
+<-------EndPath
+Path 2 4 0 483 123
+Curve 515 171 546 219
+<-------EndPath
+Path 2 5 0 546 219
+Curve 560 226 574 232
+Curve 591 243 608 253
+<-------EndPath
+Path 5 5 0 608 253
+Curve 615 290 611 327
+<-------EndPath
+Path 5 -1 0 611 327
+Curve 622 312 633 297
+<-------EndPath
+Path 0 0 0 409 -989
+Curve 417 -953 393 -888
+<-------EndPath
+Path -1 0 0 304 -1026
+Curve 357 -1012 409 -989
+<-------EndPath
+Path 0 -1 0 -394 -1046
+Curve -416 -1042 -437 -1038
+Curve -456 -1034 -475 -1030
+Curve -530 -1015 -585 -1000
+Curve -601 -994 -616 -988
+<-------EndPath
+Path 0 0 0 -616 -988
+Curve -621 -957 -625 -925
+Curve -637 -897 -635 -908
+<-------EndPath
+Path -1 -1 0 -234 -1074
+Curve -355 -1181 -394 -1046
+<-------EndPath
+Path -1 0 0 -394 -1046
+Curve -357 -1053 -320 -1060
+Curve -277 -1067 -234 -1074
+<-------EndPath
+Path 0 0 0 -394 -1046
+Curve -399 -1024 -404 -1002
+<-------EndPath
+Path 1 0 -1 -404 -1002
+Curve -582 -969 -694 -841
+Curve -718 -814 -729 -781
+Curve -732 -767 -735 -752
+Curve -735 -738 -734 -723
+Curve -731 -708 -728 -692
+Curve -720 -668 -706 -649
+Curve -685 -624 -656 -606
+Curve -496 -520 -319 -464
+Curve -214 -432 -106 -411
+Curve -78 -339 -49 -266
+<-------EndPath
+Path 1 1 0 -49 -266
+Curve -48 -265 -47 -263
+Curve -45 -255 -42 -247
+<-------EndPath
+Path -1 0 0 -80 -300
+Curve -107 -322 -154 -347
+Curve -287 -417 -454 -453
+Curve -617 -489 -733 -589
+Curve -875 -712 -781 -858
+Curve -873 -974 -747 -901
+Curve -689 -957 -616 -988
+<-------EndPath
+Path -1 -1 0 -616 -988
+Curve -581 -1156 -475 -1030
+<-------EndPath
+Path 0 0 0 -781 -858
+Curve -764 -880 -747 -901
+<-------EndPath
+Path 0 8 0 -80 -282
+Curve -82 -277 -84 -272
+Curve -86 -268 -88 -263
+<-------EndPath
+Path 0 2 0 -88 -263
+Curve -101 -244 -113 -224
+Curve -115 -224 -116 -224
+<-------EndPath
+Path 0 2 -1 -116 -224
+Curve -119 -224 -121 -224
+<-------EndPath
+Path 0 2 0 -121 -224
+Curve -137 -183 -162 -146
+<-------EndPath
+Path 6 8 0 -98 -293
+Curve -89 -288 -80 -282
+<-------EndPath
+Path 6 0 0 -80 -282
+Curve -77 -289 -74 -295
+Curve -77 -298 -80 -300
+<-------EndPath
+Path 6 -1 0 -80 -300
+Curve -89 -297 -98 -293
+<-------EndPath
+Path 8 -1 0 -98 -293
+Curve -107 -294 -113 -286
+Curve -122 -275 -126 -245
+<-------EndPath
+Path 8 2 0 -126 -245
+Curve -107 -254 -88 -263
+<-------EndPath
+Path 0 1 -1 -135 -103
+Curve -133 -104 -131 -105
+Curve -117 -119 -103 -133
+Curve -76 -166 -68 -207
+Curve -65 -206 -62 -205
+Curve -60 -215 -57 -224
+Curve -57 -226 -56 -227
+Curve -55 -233 -54 -238
+Curve -52 -251 -50 -263
+Curve -50 -265 -49 -266
+<-------EndPath
+Path 0 0 0 -49 -266
+Curve -62 -281 -74 -295
+<-------EndPath
+Path -1 -1 0 -223 -128
+Curve -223 -128 -223 -127
+<-------EndPath
+Path -1 7 0 -223 -127
+Curve -223 -128 -222 -128
+<-------EndPath
+Path -1 2 -1 -222 -128
+Curve -223 -128 -223 -128
+<-------EndPath
+Path -1 2 0 -223 -128
+Curve -200 -203 -126 -245
+<-------EndPath
+Path 7 -1 0 -231 -72
+Curve -237 -75 -242 -78
+Curve -245 -85 -248 -92
+Curve -245 -99 -242 -105
+Curve -236 -108 -229 -111
+Curve -221 -111 -215 -105
+Curve -212 -99 -209 -92
+<-------EndPath
+Path 7 4 0 -209 -92
+Curve -198 -103 -187 -114
+<-------EndPath
+Path 4 7 0 -231 -72
+Curve -237 -68 -242 -64
+Curve -269 -44 -284 -8
+<-------EndPath
+Path 4 3 0 -284 -8
+Curve -282 -7 -280 -5
+Curve -199 55 -257 137
+Curve -271 153 -284 169
+Curve -306 193 -329 205
+<-------EndPath
+Path 4 -1 0 -329 205
+Curve -332 251 -334 297
+Curve -336 371 -338 444
+<-------EndPath
+Path 4 1 0 -338 444
+Curve -327 448 -316 452
+<-------EndPath
+Path 4 9 0 -316 452
+Curve -296 460 -275 467
+Curve -165 502 -43 521
+<-------EndPath
+Path 4 0 -1 -43 521
+Curve -42 522 -40 522
+<-------EndPath
+Path 4 9 0 -40 522
+Curve -33 523 -25 524
+Curve 16 529 56 533
+<-------EndPath
+Path 4 4 0 56 533
+Curve 58 513 48 502
+Curve 21 466 39 415
+Curve 40 414 40 412
+Curve 45 392 49 372
+Curve 50 368 50 363
+Curve 50 363 50 362
+Curve 50 361 50 359
+Curve 49 342 48 325
+Curve 48 325 48 324
+Curve 42 286 19 247
+Curve 7 226 2 203
+Curve 1 182 0 161
+Curve 3 114 6 66
+<-------EndPath
+Path 4 -1 0 -209 -92
+Curve -220 -82 -231 -72
+<-------EndPath
+Path 2 7 0 -222 -128
+Curve -194 -142 -171 -135
+<-------EndPath
+Path 3 7 0 -284 -8
+Curve -287 -1 -289 6
+Curve -291 13 -293 19
+<-------EndPath
+Path 3 -1 0 -293 19
+Curve -299 39 -304 59
+<-------EndPath
+Path 3 3 0 -304 59
+Curve -295 54 -285 49
+<-------EndPath
+Path 3 -1 0 -304 59
+Curve -322 131 -329 205
+<-------EndPath
+Path 1 -1 0 -338 444
+Curve -339 457 -340 470
+<-------EndPath
+Path 1 9 -1 -340 470
+Curve -328 461 -316 452
+<-------EndPath
+Path -1 -1 0 -340 547
+Curve -386 511 -410 444
+Curve -447 341 -420 221
+Curve -397 115 -304 59
+<-------EndPath
+Path 0 9 -1 -43 521
+Curve -43 522 -43 522
+Curve -42 522 -40 522
+<-------EndPath
+Path 9 9 0 -2 595
+Curve -32 629 -78 626
+Curve -42 651 -14 658
+<-------EndPath
+Path 9 9 0 -26 583
+Curve -53 605 -79 626
+Curve -79 626 -78 626
+<-------EndPath
+Path 9 9 0 -340 547
+Curve -306 573 -259 582
+Curve -177 597 -124 616
+Curve -102 621 -79 626
+<-------EndPath
+Path 9 -1 0 -340 547
+Curve -343 562 -345 576
+Curve -347 600 -349 624
+Curve -350 654 -351 683
+<-------EndPath
+Path 9 10 0 -351 683
+Curve -283 731 -208 766
+Curve -142 797 -71 817
+Curve -69 818 -67 818
+Curve -47 823 -26 828
+Curve 47 836 119 844
+Curve 153 847 186 850
+Curve 217 849 247 847
+Curve 413 836 537 773
+Curve 583 749 612 715
+<-------EndPath
+Path 9 -1 0 612 715
+Curve 616 621 619 527
+Curve 619 445 603 372
+<-------EndPath
+Path 9 9 0 603 372
+Curve 602 376 601 379
+Curve 546 471 464 546
+Curve 428 584 392 621
+Curve 392 622 392 622
+Curve 388 663 365 689
+<-------EndPath
+Path -1 10 0 -189 1029
+Curve -229 1014 -251 981
+Curve -272 951 -292 921
+Curve -351 829 -351 683
+<-------EndPath
+Path 10 10 0 -67 818
+Curve -62 893 -88 934
+Curve -97 922 -119 918
+Curve -246 891 -208 766
+<-------EndPath
+Path 9 -1 0 -340 470
+Curve -340 509 -340 547
+<-------EndPath
+Path -1 10 -1 -63 1044
+Curve -65 1042 -67 1040
+Curve -107 1035 -146 1029
+Curve -145 1045 -160 1031
+Curve -175 1030 -189 1029
+<-------EndPath
+Path -1 -1 0 -189 1029
+Curve -171 1034 -152 1039
+Curve -138 1041 -124 1042
+Curve -94 1043 -63 1044
+<-------EndPath
+Path 10 -1 0 -63 1044
+Curve -60 1044 -57 1044
+Curve -22 1044 14 1044
+Curve 84 1041 154 1038
+Curve 189 1036 197 999
+Curve 209 948 238 921
+Curve 258 1056 401 1066
+Curve 402 1066 402 1066
+Curve 445 1065 487 1064
+Curve 507 1059 527 1053
+Curve 568 1035 578 979
+Curve 602 844 612 715
+<-------EndPath
+Path 11 -1 -1 -117 1057
+Curve -135 1048 -152 1039
+<-------EndPath
+Path 11 -1 0 -152 1039
+Curve -134 1063 -139 1098
+Curve -128 1078 -117 1057
+<-------EndPath
+Path 11 -1 -1 -149 1205
+Curve -144 1202 -138 1199
+<-------EndPath
+Path 11 -1 0 -138 1199
+Curve -148 1175 -171 1166
+Curve -177 1165 -182 1163
+Curve -257 1148 -328 1174
+Curve -328 1174 -328 1173
+Curve -355 1116 -418 1078
+Curve -481 1041 -554 1027
+Curve -512 1114 -469 1174
+Curve -457 1191 -430 1200
+Curve -357 1225 -279 1227
+Curve -204 1228 -149 1205
+<-------EndPath
+Path -1 -1 0 -139 1098
+Curve -155 1132 -171 1166
+<-------EndPath
+Path 6 -1 0 721 44
+Curve 718 53 714 61
+Curve 707 68 696 69
+Curve 685 68 678 61
+Curve 671 54 671 44
+Curve 671 33 678 26
+Curve 685 18 696 19
+Curve 707 18 714 26
+Curve 721 33 721 44
+<-------EndPath
+Path 6 12 0 616 3
+Curve 631 29 636 70
+Curve 643 134 624 186
+<-------EndPath
+Path 6 -1 0 624 186
+Curve 625 187 625 187
+Curve 625 202 614 210
+<-------EndPath
+Path 13 -1 0 718 259
+Curve 710 262 701 264
+Curve 724 329 746 393
+Curve 765 379 783 364
+Curve 797 352 820 346
+Curve 814 297 783 233
+Curve 775 237 767 241
+<-------EndPath
+Path 13 14 0 767 241
+Curve 776 261 784 280
+Curve 759 287 734 293
+Curve 726 276 718 259
+<-------EndPath
+Path -1 14 0 718 259
+Curve 743 250 767 241
+<-------EndPath
+Path 6 6 0 725 205
+Curve 719 186 712 167
+<-------EndPath
+Path -1 6 0 725 205
+Curve 705 223 674 223
+<-------EndPath
+Path 3 6 0 470 107
+Curve 466 102 461 97
+Curve 436 70 410 43
+<-------EndPath
+Path 3 4 0 278 -59
+Curve 328 71 416 108
+Curve 442 119 472 122
+Curve 478 123 483 123
+<-------EndPath
+Path 1 4 0 599 355
+Curve 599 355 598 355
+<-------EndPath
+Path 1 9 -1 598 355
+Curve 599 355 599 355
+<-------EndPath
+Path -1 9 0 599 355
+Curve 601 364 603 372
+<-------EndPath
+Path -1 -1 0 603 372
+Curve 607 350 611 327
+<-------EndPath
+Path -1 5 0 611 327
+Curve 604 336 596 345
+<-------EndPath
+Path -1 4 0 596 345
+Curve 598 350 599 355
+<-------EndPath
+Path 9 4 0 598 355
+Curve 581 385 556 409
+Curve 499 467 419 499
+Curve 359 522 287 530
+Curve 175 541 56 533
+<-------EndPath
+Path 13 14 0 783 328
+Curve 781 333 779 337
+Curve 775 341 770 341
+Curve 765 339 760 337
+Curve 759 333 757 328
+Curve 756 322 760 318
+Curve 764 314 770 315
+Curve 775 317 779 318
+Curve 781 323 783 328
+<-------EndPath
+Path 14 14 0 758 259
+Curve 761 266 763 272
+<-------EndPath
+Path 4 5 0 596 345
+Curve 577 279 546 219
+<-------EndPath
+Path 7 12 0 563 -49
+Curve 586 -17 587 21
+Curve 602 12 616 3
+<-------EndPath
+Path 9 9 0 331 666
+Curve 357 652 391 622
+Curve 355 638 310 631
+<-------EndPath
+Path 9 9 0 392 621
+Curve 392 622 391 622
+Curve 392 622 392 622
+<-------EndPath
+Path 9 9 0 129 696
+Curve 147 677 182 684
+Curve 181 712 153 714
+<-------EndPath
+Path 10 0 0 155 849
+Curve 164 850 172 850
+<-------EndPath
+Path 10 10 0 172 850
+Curve 179 850 186 850
+<-------EndPath
+Path 10 0 -1 144 850
+Curve 131 850 117 849
+Curve 99 847 107 847
+Curve 131 848 155 849
+<-------EndPath
+Path 10 0 0 172 850
+Curve 158 850 144 850
+<-------EndPath
+Path -1 11 0 99 1231
+Curve 163 1190 242 1177
+Curve 317 1181 391 1184
+Curve 406 1188 416 1194
+Curve 417 1194 417 1194
+Curve 449 1156 493 1137
+Curve 500 1134 506 1131
+<-------EndPath
+Path -1 -1 0 506 1131
+Curve 507 1131 507 1131
+Curve 502 1096 487 1064
+<-------EndPath
+Path -1 -1 0 507 1131
+Curve 508 1134 508 1136
+<-------EndPath
+Path -1 11 0 508 1136
+Curve 509 1152 510 1168
+Curve 510 1176 509 1183
+Curve 497 1236 416 1246
+Curve 339 1255 259 1249
+Curve 182 1246 104 1242
+<-------EndPath
+Path -1 11 -1 104 1242
+Curve 102 1237 99 1231
+<-------EndPath
+Path -1 11 -1 506 1131
+Curve 507 1134 508 1136
+<-------EndPath
+Path 7 -1 0 -223 -127
+Curve -317 -93 -293 19
+<-------EndPath
+!======EndShape
diff --git a/src/corelib/render/software/agg-demos/simple_blur.dpr b/src/corelib/render/software/agg-demos/simple_blur.dpr
new file mode 100644
index 00000000..305c43b5
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/simple_blur.dpr
@@ -0,0 +1,450 @@
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ simple_blur ;
+
+uses
+ agg_basics ,
+ agg_platform_support ,
+
+ agg_color ,
+ agg_pixfmt ,
+ agg_pixfmt_rgb ,
+
+ agg_rendering_buffer ,
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_renderer_outline_aa ,
+ agg_rasterizer_scanline_aa ,
+ agg_rasterizer_outline_aa ,
+ agg_scanline ,
+ agg_scanline_u ,
+ agg_scanline_p ,
+ agg_render_scanlines ,
+
+ agg_ellipse ,
+ agg_path_storage ,
+ agg_conv_stroke ,
+ agg_conv_transform ,
+ agg_bounding_rect ,
+ agg_span_generator ,
+ agg_trans_affine ,
+ agg_span_allocator ,
+ parse_lion_ ;
+
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+var
+ g_path : path_storage;
+ g_colors : array[0..99 ] of aggclr;
+ g_path_idx : array[0..99 ] of unsigned;
+
+ g_npaths : unsigned;
+
+ g_x1 ,g_y1 ,g_x2 ,g_y2 ,
+ g_base_dx ,g_base_dy ,
+ g_angle ,g_scale ,
+ g_skew_x ,g_skew_y : double;
+
+ g_nclick : int;
+
+type
+ span_simple_blur_rgb24 = object(span_generator )
+ m_source_image : rendering_buffer_ptr;
+
+ constructor Construct(alloc : span_allocator_ptr ); overload;
+ constructor Construct(alloc : span_allocator_ptr; src : rendering_buffer_ptr ); overload;
+
+ procedure _source_image(src : rendering_buffer_ptr );
+ function source_image : rendering_buffer_ptr;
+
+ function generate(x ,y : int; len : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+ the_application = object(platform_support )
+ m_cx ,
+ m_cy : double;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure on_draw; virtual;
+
+ procedure on_mouse_move (x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ CONSTRUCT }
+constructor span_simple_blur_rgb24.Construct(alloc : span_allocator_ptr );
+begin
+ inherited Construct(alloc );
+
+ m_source_image:=NIL;
+
+end;
+
+{ CONSTRUCT }
+constructor span_simple_blur_rgb24.Construct(alloc : span_allocator_ptr; src : rendering_buffer_ptr );
+begin
+ inherited Construct(alloc );
+
+ m_source_image:=src;
+
+end;
+
+{ _SOURCE_IMAGE }
+procedure span_simple_blur_rgb24._source_image;
+begin
+ m_source_image:=src;
+
+end;
+
+{ SOURCE_IMAGE }
+function span_simple_blur_rgb24.source_image;
+begin
+ result:=m_source_image;
+
+end;
+
+{ GENERATE }
+function span_simple_blur_rgb24.generate;
+var
+ span : aggclr_ptr;
+ color : array[0..3 ] of int;
+
+ i : int;
+ ptr : int8u_ptr;
+
+begin
+ span:=_allocator.span;
+
+ if (y < 1 ) or
+ (y >= m_source_image._height - 1 ) then
+ begin
+ repeat
+ span.ConstrInt(0 ,0 ,0 ,0 );
+
+ inc(integer(span ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+ result:=_allocator.span;
+
+ exit;
+
+ end;
+
+ repeat
+ color[0 ]:=0;
+ color[1 ]:=0;
+ color[2 ]:=0;
+ color[3 ]:=0;
+
+ if (x > 0 ) and
+ (x < m_source_image._width - 1 ) then
+ begin
+ i:=3;
+
+ repeat
+ ptr:=int8u_ptr(integer(m_source_image.row(y - i + 2 ) ) + ((x - 1 ) * 3 ) * sizeof(int8u ) );
+
+ inc(color[0 ] ,ptr^ ); inc(integer(ptr ) ,sizeof(int8u ) );
+ inc(color[1 ] ,ptr^ ); inc(integer(ptr ) ,sizeof(int8u ) );
+ inc(color[2 ] ,ptr^ ); inc(integer(ptr ) ,sizeof(int8u ) );
+ inc(color[3 ] ,255 );
+
+ inc(color[0 ] ,ptr^ ); inc(integer(ptr ) ,sizeof(int8u ) );
+ inc(color[1 ] ,ptr^ ); inc(integer(ptr ) ,sizeof(int8u ) );
+ inc(color[2 ] ,ptr^ ); inc(integer(ptr ) ,sizeof(int8u ) );
+ inc(color[3 ] ,255 );
+
+ inc(color[0 ] ,ptr^ ); inc(integer(ptr ) ,sizeof(int8u ) );
+ inc(color[1 ] ,ptr^ ); inc(integer(ptr ) ,sizeof(int8u ) );
+ inc(color[2 ] ,ptr^ ); inc(integer(ptr ) ,sizeof(int8u ) );
+ inc(color[3 ] ,255 );
+
+ dec(i );
+
+ until i = 0;
+
+ color[0 ]:=color[0 ] div 9;
+ color[1 ]:=color[1 ] div 9;
+ color[2 ]:=color[2 ] div 9;
+ color[3 ]:=color[3 ] div 9;
+
+ end;
+
+ span.ConstrInt(color[2 ] ,color[1 ] ,color[0 ] ,color[3 ] );
+
+ inc(integer(span ) ,sizeof(aggclr ) );
+ inc(x );
+ dec(len );
+
+ until len = 0;
+
+ result:=_allocator.span;
+
+end;
+
+{ _PARSE_LION_ }
+procedure _parse_lion_;
+begin
+ g_npaths:=parse_lion(@g_path ,@g_colors ,@g_path_idx );
+
+ bounding_rect(@g_path ,@g_path_idx ,0 ,g_npaths ,@g_x1 ,@g_y1 ,@g_x2 ,@g_y2 );
+
+ g_base_dx:=(g_x2 - g_x1 ) / 2.0;
+ g_base_dy:=(g_y2 - g_y1 ) / 2.0;
+
+end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_cx:=100;
+ m_cy:=102;
+
+ _parse_lion_;
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ pixf : pixel_formats;
+
+ rb : renderer_base;
+ rs : renderer_scanline_aa_solid;
+
+ rgba : aggclr;
+ trans : conv_transform;
+
+ mtx ,
+ inv : trans_affine;
+ tat : trans_affine_translation;
+ tas : trans_affine_scaling;
+ tar : trans_affine_rotation;
+ taw : trans_affine_skewing;
+
+ ras2 : rasterizer_scanline_aa;
+ sl : scanline_p8;
+ sl2 : scanline_u8;
+
+ profile : line_profile_aa;
+
+ rp : renderer_outline_aa;
+ ras : rasterizer_outline_aa;
+
+ ell : ellipse;
+
+ ell_stroke1 ,
+ ell_stroke2 : conv_stroke;
+
+ sa : span_allocator;
+ sg : span_simple_blur_rgb24;
+
+ rblur : renderer_scanline_aa;
+
+begin
+// Initialize structures
+ pixfmt_bgr24(pixf ,rbuf_window );
+
+ rb.Construct(@pixf );
+ rs.Construct(@rb );
+
+ rgba.ConstrDbl(1 ,1 ,1 );
+ rb.clear (@rgba );
+
+ mtx.Construct;
+ trans.Construct(@g_path ,@mtx );
+
+ tat.Construct(-g_base_dx ,-g_base_dy );
+ mtx.multiply (@tat );
+
+ tas.Construct(g_scale ,g_scale );
+ mtx.multiply (@tas );
+
+ tar.Construct(g_angle + pi );
+ mtx.multiply (@tar );
+
+ taw.Construct(g_skew_x / 1000.0 ,g_skew_y / 1000.0 );
+ mtx.multiply (@taw );
+
+ tat.Construct(_initial_width / 4 ,_initial_height / 2 );
+ mtx.multiply (@tat );
+
+ mtx.multiply(_trans_affine_resizing );
+
+ ras2.Construct;
+ sl.Construct;
+ sl2.Construct;
+
+// Full lion
+ render_all_paths(@ras2 ,@sl ,@rs ,@trans ,@g_colors ,@g_path_idx ,g_npaths );
+
+// Outline Lion
+ inv.Construct;
+ inv.assign(_trans_affine_resizing );
+
+ inv.invert;
+ mtx.multiply(@inv );
+
+ tat.Construct(_initial_width / 2 ,0 );
+ mtx.multiply(@tat );
+
+ mtx.multiply(_trans_affine_resizing );
+
+ profile.Construct;
+ profile.width_(1.0 );
+
+ rp.Construct (@rb ,@profile );
+ ras.Construct(@rp );
+
+ ras.round_cap_ (true );
+ ras.accurate_join_(true );
+
+ ras.render_all_paths(@trans ,@g_colors ,@g_path_idx ,g_npaths );
+
+// Ellipses
+ ell.Construct(m_cx ,m_cy ,100.0 ,100.0 ,100 );
+
+ ell_stroke1.Construct(@ell );
+ ell_stroke1.width_ (6.0 );
+ ell_stroke2.Construct(@ell_stroke1 );
+ ell_stroke2.width_ (2.0 );
+
+ rgba.ConstrDbl(0,0.2,0);
+ rs.color_ (@rgba );
+
+ ras2.add_path (@ell_stroke2 );
+ render_scanlines(@ras2 ,@sl ,@rs );
+
+// Blur
+ sa.Construct;
+ sg.Construct(@sa );
+
+ rblur.Construct (@rb ,@sg );
+ sg._source_image(rbuf_img(0 ) );
+
+ ras2.add_path(@ell );
+
+ copy_window_to_img(0 );
+ render_scanlines (@ras2 ,@sl2 ,@rblur );
+
+// More blur if desired :-)
+{ copy_window_to_img(0 );
+ render_scanlines (@ras2 ,@sl2 ,@rblur );
+
+ copy_window_to_img(0 );
+ render_scanlines (@ras2 ,@sl2 ,@rblur );
+
+ copy_window_to_img(0 );
+ render_scanlines (@ras2 ,@sl2 ,@rblur );{}
+
+// Free AGG resources
+ ras2.Destruct;
+ sl.Destruct;
+ sl2.Destruct;
+
+ ras.Destruct;
+ profile.Destruct;
+ ell_stroke1.Destruct;
+ ell_stroke2.Destruct;
+ sa.Destruct;
+
+end;
+
+{ ON_MOUSE_MOVE }
+procedure the_application.on_mouse_move;
+begin
+ on_mouse_button_down(x ,y ,flags );
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure the_application.on_mouse_button_down;
+begin
+ if flags and mouse_left <> 0 then
+ begin
+ m_cx:=x;
+ m_cy:=y;
+
+ force_redraw;
+
+ end;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ 'The example demonstrates how to write custom span generators. This one just applies '#13 +
+ 'the simplest "blur" filter 3x3 to a prerendered image. It calculates the average value '#13 +
+ 'of 9 neighbor pixels.'#13#13 +
+ 'How to play with:'#13#13 +
+ 'Just press the left mouse button and drag.'#13 +
+ 'Uncomment and recompile the part of the demo source code to get more blur.' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+VAR
+ app : the_application;
+
+BEGIN
+// Rendering
+ g_path.Construct;
+
+ g_npaths:=0;
+
+ g_x1:=0;
+ g_y1:=0;
+ g_x2:=0;
+ g_y2:=0;
+
+ g_base_dx:=0;
+ g_base_dy:=0;
+
+ g_angle:=0;
+ g_scale:=1.0;
+
+ g_skew_x:=0;
+ g_skew_y:=0;
+ g_nclick:=0;
+
+// App
+ app.Construct(pix_format_bgr24 ,flip_y );
+ app.caption_ ('AGG Example. Lion with Alpha-Masking (F1-Help)' );
+
+ if app.init(512 ,400 ,window_resize ) then
+ app.run;
+
+ app.Destruct;
+
+// Free
+ g_path.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/svg/agg@pas.svg b/src/corelib/render/software/agg-demos/svg/agg@pas.svg
new file mode 100755
index 00000000..8da6f4f0
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/svg/agg@pas.svg
@@ -0,0 +1,279 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="215.89999mm"
+ height="279.39999mm"
+ viewBox="0 0 215.9 279.4"
+ id="svg22046"
+ xml:space="preserve">
+ <defs
+ id="defs22048">
+ <style
+ type="text/css"
+ id="style22050" />
+ </defs>
+ <g
+ transform="matrix(2.5,0,0,2.5,0,0)"
+ id="Layer_x0020_1">
+
+ <path
+ d="M 68.8728,29.2879 L 68.8728,26.5297 L 78.8472,26.5133 L 78.8472,35.2485 C 77.3173,36.4713 75.7381,37.387 74.1095,38.0067 C 72.4809,38.6208 70.8084,38.9279 69.0976,38.9279 C 66.7835,38.9279 64.6779,38.4344 62.7916,37.4419 C 60.8998,36.4548 59.4741,35.0182 58.509,33.1483 C 57.5439,31.273 57.0613,29.1783 57.0613,26.8642 C 57.0613,24.5721 57.5439,22.4336 58.5035,20.4486 C 59.4576,18.4581 60.8395,16.983 62.638,16.0179 C 64.4366,15.0583 66.5094,14.5757 68.8563,14.5757 C 70.5562,14.5757 72.097,14.8499 73.4734,15.4038 C 74.8498,15.9521 75.93,16.7198 76.7087,17.7068 C 77.4928,18.6938 78.085,19.977 78.4963,21.5617 L 75.6832,22.3349 C 75.3268,21.134 74.8881,20.1908 74.3672,19.5054 C 73.8408,18.82 73.0896,18.2716 72.1135,17.8604 C 71.1429,17.4491 70.0572,17.2407 68.8728,17.2407 C 67.447,17.2407 66.2133,17.4601 65.1769,17.8933 C 64.135,18.3264 63.3015,18.8967 62.66,19.6041 C 62.0239,20.3115 61.5304,21.0846 61.1739,21.9346 C 60.5762,23.3877 60.2747,24.9669 60.2747,26.6723 C 60.2747,28.7725 60.6366,30.5272 61.3604,31.9419 C 62.0842,33.3567 63.137,34.404 64.5189,35.0895 C 65.9007,35.7749 67.3648,36.1204 68.9166,36.1204 C 70.271,36.1204 71.5871,35.8571 72.8702,35.3362 C 74.1588,34.8208 75.1294,34.2669 75.7929,33.6747 L 75.7929,29.2879 L 68.8728,29.2879 L 68.8728,29.2879 z "
+ style="fill:#135288;fill-rule:nonzero;stroke:#135288"
+ id="path22054" />
+ <path
+ d="M 44.0534,29.2879 L 44.0534,26.5297 L 54.0278,26.5133 L 54.0278,35.2485 C 52.4979,36.4713 50.9187,37.387 49.2901,38.0067 C 47.6615,38.6208 45.989,38.9279 44.2782,38.9279 C 41.9641,38.9279 39.8585,38.4344 37.9722,37.4419 C 36.0804,36.4548 34.6547,35.0182 33.6896,33.1483 C 32.7245,31.273 32.2419,29.1783 32.2419,26.8642 C 32.2419,24.5721 32.7245,22.4336 33.6841,20.4486 C 34.6382,18.4581 36.0201,16.983 37.8186,16.0179 C 39.6172,15.0583 41.69,14.5757 44.0369,14.5757 C 45.7368,14.5757 47.2776,14.8499 48.654,15.4038 C 50.0304,15.9521 51.1106,16.7198 51.8893,17.7068 C 52.6734,18.6938 53.2656,19.977 53.6769,21.5617 L 50.8638,22.3349 C 50.5074,21.134 50.0687,20.1908 49.5478,19.5054 C 49.0214,18.82 48.2702,18.2716 47.2941,17.8604 C 46.3235,17.4491 45.2378,17.2407 44.0534,17.2407 C 42.6276,17.2407 41.3939,17.4601 40.3575,17.8933 C 39.3156,18.3264 38.4821,18.8967 37.8406,19.6041 C 37.2045,20.3115 36.711,21.0846 36.3545,21.9346 C 35.7568,23.3877 35.4553,24.9669 35.4553,26.6723 C 35.4553,28.7725 35.8172,30.5272 36.541,31.9419 C 37.2648,33.3567 38.3176,34.404 39.6995,35.0895 C 41.0813,35.7749 42.5454,36.1204 44.0972,36.1204 C 45.4516,36.1204 46.7677,35.8571 48.0508,35.3362 C 49.3394,34.8208 50.31,34.2669 50.9735,33.6747 L 50.9735,29.2879 L 44.0534,29.2879 L 44.0534,29.2879 z "
+ style="fill:#135288;fill-rule:nonzero;stroke:#135288"
+ id="path22056" />
+ <polygon
+ points="9.2704,38.5276 18.3182,14.976 21.6741,14.976 31.3141,38.5276 27.7608,38.5276 25.0135,31.3936 15.1652,31.3936 12.5825,38.5276 9.2704,38.5276 "
+ style="fill:#135288;fill-rule:nonzero;stroke:#135288"
+ id="polygon22058" />
+ <path
+ d="M 16.0645,28.8547 L 24.0539,28.8547 L 21.5918,22.3349 C 20.8461,20.3553 20.2868,18.7267 19.9249,17.4491 C 19.6233,18.9625 19.201,20.4595 18.6527,21.951 L 16.0645,28.8547 z "
+ style="fill:#ffffff;fill-rule:nonzero;stroke:#135288"
+ id="path22060" />
+ <path
+ d="M 158.082,30.9604 L 161.0212,30.7027 C 161.1583,31.8816 161.4818,32.8467 161.9918,33.6034 C 162.5017,34.3602 163.2913,34.9688 164.3606,35.4349 C 165.4299,35.901 166.6363,36.1313 167.9742,36.1313 C 169.1642,36.1313 170.2115,35.9558 171.1218,35.6049 C 172.032,35.2485 172.712,34.7659 173.1561,34.1518 C 173.6003,33.5321 173.8251,32.8632 173.8251,32.1339 C 173.8251,31.3936 173.6113,30.752 173.1781,30.1982 C 172.7504,29.6444 172.043,29.1837 171.0614,28.8109 C 170.4254,28.5641 169.0326,28.1803 166.8666,27.6593 C 164.7061,27.1384 163.1872,26.6504 162.3208,26.1898 C 161.1967,25.603 160.3577,24.8682 159.8039,23.9964 C 159.2555,23.1245 158.9813,22.1484 158.9813,21.0627 C 158.9813,19.8783 159.3158,18.7651 159.9903,17.7342 C 160.6648,16.6979 161.6518,15.9137 162.9459,15.3763 C 164.2455,14.8444 165.6821,14.5757 167.2669,14.5757 C 169.0161,14.5757 170.5515,14.8554 171.8895,15.4202 C 173.2219,15.9795 174.2473,16.8075 174.9657,17.8987 C 175.6785,18.9899 176.0679,20.2292 176.1227,21.6111 L 173.1342,21.8359 C 172.9697,20.3499 172.4268,19.2203 171.5001,18.4635 C 170.5734,17.7013 169.208,17.323 167.3985,17.323 C 165.5122,17.323 164.1413,17.6684 163.2749,18.3593 C 162.414,19.0503 161.9808,19.8838 161.9808,20.8543 C 161.9808,21.7043 162.2879,22.4007 162.8965,22.9435 C 163.4997,23.4919 165.0625,24.0512 167.5959,24.6215 C 170.1293,25.1973 171.8675,25.6962 172.8107,26.124 C 174.1815,26.76 175.196,27.5606 175.8485,28.5257 C 176.5011,29.4963 176.8246,30.6149 176.8246,31.8761 C 176.8246,33.1319 176.4682,34.3108 175.7498,35.4185 C 175.0315,36.5261 174.0006,37.387 172.6571,38.0067 C 171.3137,38.6208 169.8002,38.9279 168.1223,38.9279 C 165.9892,38.9279 164.2016,38.6208 162.7649,37.9957 C 161.3228,37.3761 160.1932,36.4439 159.3707,35.1936 C 158.5536,33.9489 158.1204,32.5342 158.082,30.9604 L 158.082,30.9604 z "
+ style="fill:#135288;fill-rule:nonzero;stroke:#135288"
+ id="path22062" />
+ <polygon
+ points="135.379,38.5276 144.427,14.976 147.783,14.976 157.423,38.5276 153.869,38.5276 151.122,31.3936 141.274,31.3936 138.691,38.5276 135.379,38.5276 "
+ style="fill:#135288;fill-rule:nonzero;stroke:#135288"
+ id="polygon22064" />
+ <path
+ d="M 142.173,28.8547 L 150.1624,28.8547 L 147.7003,22.3349 C 146.9546,20.3553 146.3953,18.7267 146.0334,17.4491 C 145.7318,18.9625 145.3095,20.4595 144.7612,21.951 L 142.173,28.8547 z "
+ style="fill:#ffffff;fill-rule:nonzero;stroke:#135288"
+ id="path22066" />
+ <path
+ d="M 119.234,38.5276 L 119.234,14.976 L 128.1172,14.976 C 129.68,14.976 130.8754,15.0528 131.6979,15.2009 C 132.8549,15.3928 133.8255,15.7602 134.6096,16.303 C 135.3883,16.8404 136.0189,17.6026 136.496,18.5732 C 136.973,19.5493 137.2088,20.6185 137.2088,21.7865 C 137.2088,23.788 136.5727,25.4879 135.3006,26.8752 C 134.0229,28.257 131.7198,28.9534 128.3914,28.9534 L 122.3486,28.9534 L 122.3486,38.5276 L 119.234,38.5276 L 119.234,38.5276 z "
+ style="fill:#135288;fill-rule:nonzero;stroke:#135288"
+ id="path22068" />
+ <path
+ d="M 122.349,26.1733 L 128.4411,26.1733 C 130.4536,26.1733 131.8847,25.8004 132.7292,25.0492 C 133.5737,24.298 133.9959,23.2451 133.9959,21.8852 C 133.9959,20.8982 133.7491,20.0537 133.2501,19.3519 C 132.7511,18.65 132.0986,18.1894 131.2816,17.9645 C 130.7552,17.8275 129.7901,17.7562 128.3753,17.7562 L 122.349,17.7562 L 122.349,26.1733 L 122.349,26.1733 z "
+ style="fill:#ffffff;fill-rule:nonzero;stroke:#135288"
+ id="path22070" />
+ <polygon
+ points="175.039,50.0567 175.039,43.4912 176.297,43.4912 176.297,50.0567 175.039,50.0567 "
+ style="fill:#af756f;fill-rule:nonzero"
+ id="polygon22072" />
+ <path
+ d="M 170.879,46.7518 L 169.7371,46.5454 C 169.8655,46.0853 170.0856,45.746 170.399,45.5243 C 170.7139,45.3042 171.1786,45.1926 171.7961,45.1926 C 172.3587,45.1926 172.776,45.2598 173.0511,45.3928 C 173.3248,45.5258 173.5189,45.694 173.6305,45.8988 C 173.7421,46.1037 173.7986,46.4782 173.7986,47.0254 L 173.7849,48.4944 C 173.7849,48.9118 173.8048,49.2205 173.846,49.4193 C 173.8858,49.6165 173.9622,49.8305 174.0723,50.0567 L 172.8264,50.0567 C 172.7943,49.9726 172.7531,49.8488 172.7057,49.6852 C 172.6858,49.6103 172.6705,49.5614 172.6613,49.537 C 172.4458,49.7464 172.2165,49.9023 171.9719,50.0078 C 171.7273,50.1117 171.4659,50.1637 171.1877,50.1637 C 170.6986,50.1637 170.3118,50.0307 170.0306,49.7663 C 169.7478,49.5003 169.6071,49.164 169.6071,48.7574 C 169.6071,48.4899 169.6713,48.2499 169.7997,48.0389 C 169.9281,47.828 170.1085,47.6674 170.3393,47.5559 C 170.5702,47.4443 170.9049,47.3464 171.3406,47.2624 C 171.9276,47.1523 172.3357,47.0483 172.562,46.9536 L 172.562,46.8282 C 172.562,46.5852 172.5024,46.414 172.3831,46.31 C 172.2639,46.2076 172.0392,46.1556 171.7075,46.1556 C 171.4828,46.1556 171.3085,46.2 171.1831,46.2886 C 171.0578,46.3758 170.9569,46.5301 170.879,46.7518 L 170.879,46.7518 z "
+ style="fill:#af756f;fill-rule:nonzero"
+ id="path22074" />
+ <path
+ d="M 172.562,47.7729 C 172.4015,47.8264 172.1462,47.8906 171.7961,47.9655 C 171.4476,48.0404 171.2198,48.1138 171.1113,48.1841 C 170.9477,48.3018 170.8652,48.4486 170.8652,48.6274 C 170.8652,48.8047 170.9309,48.9561 171.0624,49.0845 C 171.1938,49.2129 171.3605,49.2771 171.5638,49.2771 C 171.7915,49.2771 172.0071,49.2022 172.2134,49.0539 C 172.3663,48.9408 172.4657,48.8017 172.5131,48.6366 C 172.5467,48.5296 172.562,48.3248 172.562,48.0236 L 172.562,47.7729 z "
+ style="fill:#ffffff;fill-rule:nonzero"
+ id="path22076" />
+ <path
+ d="M 168.985,46.7075 L 167.7438,46.9306 C 167.7025,46.683 167.6077,46.4965 167.4594,46.3712 C 167.3112,46.2458 167.1201,46.1831 166.8847,46.1831 C 166.5698,46.1831 166.3206,46.2917 166.1341,46.5072 C 165.9476,46.7243 165.8544,47.0866 165.8544,47.5941 C 165.8544,48.1581 165.9492,48.5571 166.1387,48.7895 C 166.3283,49.0218 166.582,49.138 166.9015,49.138 C 167.1415,49.138 167.3356,49.0707 167.4885,48.9347 C 167.6414,48.7986 167.7484,48.5648 167.811,48.2346 L 169.0477,48.444 C 168.9193,49.0111 168.6717,49.4407 168.3078,49.7296 C 167.944,50.02 167.4564,50.1637 166.8434,50.1637 C 166.1479,50.1637 165.593,49.9451 165.1803,49.5064 C 164.7659,49.0677 164.5595,48.4593 164.5595,47.6827 C 164.5595,46.8985 164.7674,46.2871 165.1818,45.8499 C 165.5976,45.4112 166.1586,45.1926 166.8663,45.1926 C 167.4457,45.1926 167.9058,45.3179 168.2482,45.5671 C 168.5891,45.8163 168.8352,46.1969 168.985,46.7075 L 168.985,46.7075 z "
+ style="fill:#af756f;fill-rule:nonzero"
+ id="path22078" />
+ <path
+ d="M 159.293,48.6993 L 160.5557,48.5067 C 160.6092,48.7512 160.7177,48.9377 160.8828,49.0646 C 161.0464,49.1915 161.2757,49.2557 161.5722,49.2557 C 161.8978,49.2557 162.1424,49.1961 162.306,49.0753 C 162.4176,48.9928 162.4726,48.8797 162.4726,48.7405 C 162.4726,48.6442 162.442,48.5648 162.3824,48.5021 C 162.3197,48.4425 162.1791,48.3874 161.962,48.337 C 160.947,48.1138 160.3035,47.909 160.0314,47.724 C 159.6553,47.4672 159.4673,47.1095 159.4673,46.6524 C 159.4673,46.2412 159.6293,45.8942 159.9549,45.6145 C 160.2805,45.3332 160.785,45.1926 161.4683,45.1926 C 162.1195,45.1926 162.6041,45.2996 162.9205,45.5105 C 163.2369,45.723 163.454,46.0364 163.5732,46.4522 L 162.387,46.6708 C 162.3365,46.4858 162.2402,46.3436 162.0981,46.2458 C 161.9559,46.1465 161.7541,46.0975 161.4912,46.0975 C 161.1595,46.0975 160.9226,46.1434 160.7789,46.2366 C 160.6841,46.3024 160.6367,46.388 160.6367,46.4919 C 160.6367,46.5821 160.678,46.657 160.7621,46.7197 C 160.8752,46.8038 161.2665,46.9215 161.9376,47.0743 C 162.6071,47.2257 163.0749,47.4122 163.3409,47.6338 C 163.6038,47.8585 163.7352,48.1704 163.7352,48.5693 C 163.7352,49.005 163.5533,49.381 163.188,49.6944 C 162.8242,50.0078 162.2861,50.1637 161.5722,50.1637 C 160.9241,50.1637 160.412,50.0322 160.0329,49.7693 C 159.6553,49.5079 159.4092,49.1502 159.293,48.6993 L 159.293,48.6993 z "
+ style="fill:#af756f;fill-rule:nonzero"
+ id="path22080" />
+ <path
+ d="M 155.575,46.7518 L 154.4331,46.5454 C 154.5615,46.0853 154.7816,45.746 155.095,45.5243 C 155.4099,45.3042 155.8746,45.1926 156.4921,45.1926 C 157.0547,45.1926 157.472,45.2598 157.7471,45.3928 C 158.0208,45.5258 158.2149,45.694 158.3265,45.8988 C 158.4381,46.1037 158.4946,46.4782 158.4946,47.0254 L 158.4809,48.4944 C 158.4809,48.9118 158.5008,49.2205 158.542,49.4193 C 158.5818,49.6165 158.6582,49.8305 158.7683,50.0567 L 157.5224,50.0567 C 157.4903,49.9726 157.4491,49.8488 157.4017,49.6852 C 157.3818,49.6103 157.3665,49.5614 157.3573,49.537 C 157.1418,49.7464 156.9125,49.9023 156.6679,50.0078 C 156.4233,50.1117 156.1619,50.1637 155.8837,50.1637 C 155.3946,50.1637 155.0078,50.0307 154.7266,49.7663 C 154.4438,49.5003 154.3031,49.164 154.3031,48.7574 C 154.3031,48.4899 154.3673,48.2499 154.4957,48.0389 C 154.6241,47.828 154.8045,47.6674 155.0353,47.5559 C 155.2662,47.4443 155.6009,47.3464 156.0366,47.2624 C 156.6236,47.1523 157.0317,47.0483 157.258,46.9536 L 157.258,46.8282 C 157.258,46.5852 157.1984,46.414 157.0791,46.31 C 156.9599,46.2076 156.7352,46.1556 156.4035,46.1556 C 156.1788,46.1556 156.0045,46.2 155.8791,46.2886 C 155.7538,46.3758 155.6529,46.5301 155.575,46.7518 L 155.575,46.7518 z "
+ style="fill:#af756f;fill-rule:nonzero"
+ id="path22082" />
+ <path
+ d="M 157.258,47.7729 C 157.0975,47.8264 156.8422,47.8906 156.4921,47.9655 C 156.1436,48.0404 155.9158,48.1138 155.8073,48.1841 C 155.6437,48.3018 155.5612,48.4486 155.5612,48.6274 C 155.5612,48.8047 155.6269,48.9561 155.7584,49.0845 C 155.8898,49.2129 156.0565,49.2771 156.2598,49.2771 C 156.4875,49.2771 156.7031,49.2022 156.9094,49.0539 C 157.0623,48.9408 157.1617,48.8017 157.2091,48.6366 C 157.2427,48.5296 157.258,48.3248 157.258,48.0236 L 157.258,47.7729 z "
+ style="fill:#ffffff;fill-rule:nonzero"
+ id="path22084" />
+ <path
+ d="M 148.527,50.0567 L 148.527,43.4912 L 150.6533,43.4912 C 151.4589,43.4912 151.9848,43.5248 152.2294,43.5906 C 152.6054,43.6884 152.9218,43.9024 153.1756,44.2326 C 153.4293,44.5628 153.5562,44.9893 153.5562,45.5105 C 153.5562,45.9141 153.4828,46.2535 153.3361,46.5271 C 153.1893,46.8022 153.0044,47.0178 152.7781,47.1752 C 152.5534,47.3311 152.3241,47.4351 152.0918,47.4855 C 151.7754,47.5482 151.3168,47.5803 150.716,47.5803 L 149.8523,47.5803 L 149.8523,50.0567 L 148.527,50.0567 z "
+ style="fill:#af756f;fill-rule:nonzero"
+ id="path22086" />
+ <path
+ d="M 149.852,44.6025 L 149.852,46.4644 L 150.5766,46.4644 C 151.0994,46.4644 151.4495,46.4308 151.6253,46.362 C 151.801,46.2932 151.9386,46.1862 152.0395,46.0395 C 152.1389,45.8927 152.1893,45.723 152.1893,45.5289 C 152.1893,45.2904 152.119,45.0932 151.9784,44.9373 C 151.8393,44.7829 151.6604,44.6851 151.4464,44.6469 C 151.2874,44.6163 150.9695,44.6025 150.4925,44.6025 L 149.852,44.6025 L 149.852,44.6025 z "
+ style="fill:#ffffff;fill-rule:nonzero"
+ id="path22088" />
+ <path
+ d="M 145.095,45.3011 L 145.095,46.3039 L 144.2359,46.3039 L 144.2359,48.2208 C 144.2359,48.6091 144.2435,48.8353 144.2603,48.8995 C 144.2772,48.9637 144.3138,49.0157 144.3719,49.0585 C 144.43,49.0998 144.5019,49.1212 144.5844,49.1212 C 144.7021,49.1212 144.8703,49.0799 145.0919,49.0004 L 145.1989,49.9757 C 144.9054,50.101 144.5752,50.1637 144.2038,50.1637 C 143.9775,50.1637 143.7727,50.1255 143.5908,50.0506 C 143.4089,49.9742 143.2759,49.8748 143.1903,49.754 C 143.1047,49.6333 143.0466,49.4697 143.013,49.2633 C 142.987,49.1181 142.9732,48.8216 142.9732,48.3767 L 142.9732,46.3039 L 142.3954,46.3039 L 142.3954,45.3011 L 142.9732,45.3011 L 142.9732,44.3549 L 144.2359,43.6212 L 144.2359,45.3011 L 145.095,45.3011 L 145.095,45.3011 z "
+ style="fill:#af756f;fill-rule:nonzero"
+ id="path22090" />
+ <path
+ d="M 141.961,46.7075 L 140.7198,46.9306 C 140.6785,46.683 140.5837,46.4965 140.4354,46.3712 C 140.2872,46.2458 140.0961,46.1831 139.8607,46.1831 C 139.5458,46.1831 139.2966,46.2917 139.1101,46.5072 C 138.9236,46.7243 138.8304,47.0866 138.8304,47.5941 C 138.8304,48.1581 138.9252,48.5571 139.1147,48.7895 C 139.3043,49.0218 139.558,49.138 139.8775,49.138 C 140.1175,49.138 140.3116,49.0707 140.4645,48.9347 C 140.6174,48.7986 140.7244,48.5648 140.787,48.2346 L 142.0237,48.444 C 141.8953,49.0111 141.6477,49.4407 141.2838,49.7296 C 140.92,50.02 140.4324,50.1637 139.8194,50.1637 C 139.1239,50.1637 138.569,49.9451 138.1563,49.5064 C 137.742,49.0677 137.5356,48.4593 137.5356,47.6827 C 137.5356,46.8985 137.7435,46.2871 138.1578,45.8499 C 138.5736,45.4112 139.1346,45.1926 139.8423,45.1926 C 140.4217,45.1926 140.8818,45.3179 141.2242,45.5671 C 141.5651,45.8163 141.8112,46.1969 141.961,46.7075 L 141.961,46.7075 z "
+ style="fill:#af756f;fill-rule:nonzero"
+ id="path22092" />
+ <path
+ d="M 135.466,48.5434 L 136.721,48.7528 C 136.559,49.2129 136.3052,49.563 135.9567,49.8029 C 135.6097,50.0445 135.174,50.1637 134.6512,50.1637 C 133.8243,50.1637 133.2128,49.8947 132.8154,49.3535 C 132.502,48.9209 132.3445,48.3737 132.3445,47.7148 C 132.3445,46.9261 132.5509,46.3085 132.9636,45.8621 C 133.3748,45.4158 133.8961,45.1926 134.5259,45.1926 C 135.2337,45.1926 135.7916,45.4265 136.2013,45.8942 C 136.6094,46.362 136.8051,47.0774 136.7883,48.042 L 133.6347,48.042 C 133.6439,48.4149 133.7448,48.7054 133.9389,48.9118 C 134.133,49.1196 134.3761,49.2236 134.665,49.2236 C 134.8622,49.2236 135.0273,49.1701 135.1618,49.0631 C 135.2963,48.9546 135.3987,48.7818 135.466,48.5434 z "
+ style="fill:#af756f;fill-rule:nonzero"
+ id="path22094" />
+ <path
+ d="M 135.538,47.2715 C 135.5288,46.9062 135.4355,46.6295 135.2567,46.44 C 135.0778,46.2504 134.8592,46.1556 134.6024,46.1556 C 134.3273,46.1556 134.101,46.2565 133.9222,46.4568 C 133.7433,46.6555 133.6547,46.9276 133.6577,47.2715 L 135.538,47.2715 L 135.538,47.2715 z "
+ style="fill:#ffffff;fill-rule:nonzero"
+ id="path22096" />
+ <path
+ d="M 131.396,45.3011 L 131.396,49.9084 C 131.396,50.5153 131.3562,50.9433 131.2783,51.1925 C 131.1988,51.4416 131.0459,51.6358 130.8212,51.7764 C 130.595,51.917 130.3076,51.9874 129.9591,51.9874 C 129.8337,51.9874 129.6977,51.9751 129.554,51.9537 C 129.4088,51.9308 129.2528,51.8972 129.0862,51.8528 L 129.3048,50.7782 C 129.3644,50.7889 129.421,50.7996 129.473,50.8073 C 129.5249,50.8149 129.5739,50.818 129.6182,50.818 C 129.7466,50.818 129.8521,50.7904 129.9346,50.7354 C 130.0172,50.6804 130.0707,50.6131 130.0982,50.5352 C 130.1242,50.4587 130.1379,50.2248 130.1379,49.8366 L 130.1379,45.3011 L 131.396,45.3011 z "
+ style="fill:#af756f;fill-rule:nonzero"
+ id="path22098" />
+ <polygon
+ points="130.137,44.656 130.137,43.4912 131.396,43.4912 131.396,44.656 130.137,44.656 "
+ style="fill:#af756f;fill-rule:nonzero"
+ id="polygon22100" />
+ <path
+ d="M 124.509,50.0567 L 124.509,43.4912 L 125.7671,43.4912 L 125.7671,45.856 C 126.1554,45.4142 126.614,45.1926 127.1459,45.1926 C 127.7253,45.1926 128.2037,45.4035 128.5844,45.8224 C 128.9635,46.2412 129.153,46.8435 129.153,47.6292 C 129.153,48.4409 128.9589,49.0677 128.5721,49.5064 C 128.1854,49.9451 127.7161,50.1637 127.1643,50.1637 C 126.8922,50.1637 126.6247,50.0964 126.3602,49.9604 C 126.0958,49.8243 125.868,49.6241 125.6769,49.3581 L 125.6769,50.0567 L 124.509,50.0567 L 124.509,50.0567 z "
+ style="fill:#af756f;fill-rule:nonzero"
+ id="path22102" />
+ <path
+ d="M 125.758,47.5757 C 125.758,48.0679 125.836,48.4318 125.9904,48.6687 C 126.209,49.0035 126.4979,49.1701 126.8602,49.1701 C 127.1369,49.1701 127.3738,49.0509 127.5695,48.8139 C 127.7651,48.577 127.863,48.2025 127.863,47.6919 C 127.863,47.1492 127.7636,46.7564 127.5664,46.5164 C 127.3707,46.2764 127.1185,46.1556 126.8097,46.1556 C 126.5086,46.1556 126.2579,46.2733 126.0576,46.5072 C 125.8574,46.7426 125.758,47.0973 125.758,47.5757 z "
+ style="fill:#ffffff;fill-rule:nonzero"
+ id="path22104" />
+ <path
+ d="M 117.169,46.8145 C 117.169,46.1449 117.2683,45.5839 117.4686,45.1299 C 117.6184,44.7967 117.8217,44.4955 118.08,44.2295 C 118.3384,43.9651 118.6212,43.7679 118.9284,43.6395 C 119.3381,43.4652 119.8089,43.3796 120.3439,43.3796 C 121.3116,43.3796 122.0851,43.6792 122.6659,44.28 C 123.2468,44.8792 123.5373,45.7139 123.5373,46.7824 C 123.5373,47.8432 123.2483,48.6718 122.6721,49.271 C 122.0958,49.8687 121.3253,50.1683 120.3623,50.1683 C 119.3855,50.1683 118.6089,49.8702 118.0327,49.2756 C 117.4564,48.6794 117.169,47.8585 117.169,46.8145 L 117.169,46.8145 z "
+ style="fill:#af756f;fill-rule:nonzero"
+ id="path22106" />
+ <path
+ d="M 118.534,46.7701 C 118.534,47.5131 118.7068,48.0771 119.0492,48.4608 C 119.3931,48.8445 119.8288,49.0356 120.3577,49.0356 C 120.8851,49.0356 121.3192,48.846 121.6586,48.4639 C 121.9964,48.0832 122.1661,47.5131 122.1661,46.7518 C 122.1661,45.9997 122.001,45.4387 121.6723,45.0672 C 121.3421,44.6973 120.9034,44.5123 120.3577,44.5123 C 119.8105,44.5123 119.3702,44.7004 119.0354,45.0749 C 118.7022,45.4494 118.534,46.0135 118.534,46.7701 L 118.534,46.7701 z "
+ style="fill:#ffffff;fill-rule:nonzero"
+ id="path22108" />
+ <path
+ d="M 112.516,50.0567 L 111.2579,50.0567 L 111.2579,45.3011 L 112.4258,45.3011 L 112.4258,45.9768 C 112.6261,45.6573 112.8064,45.4463 112.9654,45.3455 C 113.1259,45.2446 113.3063,45.1926 113.5096,45.1926 C 113.797,45.1926 114.0722,45.2721 114.3381,45.4311 L 113.9483,46.5271 C 113.7374,46.391 113.5402,46.3222 113.3583,46.3222 C 113.181,46.3222 113.0327,46.3696 112.9104,46.4675 C 112.7866,46.5638 112.6918,46.7396 112.6215,46.9933 C 112.5512,47.2471 112.516,47.779 112.516,48.5877 L 112.516,50.0567 L 112.516,50.0567 z "
+ style="fill:#af756f;fill-rule:nonzero"
+ id="path22110" />
+ <path
+ d="M 105.417,47.6109 C 105.417,47.1936 105.5209,46.7885 105.7258,46.3972 C 105.9321,46.0074 106.2241,45.7077 106.6017,45.5029 C 106.9792,45.2965 107.4011,45.1926 107.8674,45.1926 C 108.5858,45.1926 109.1759,45.4265 109.636,45.8942 C 110.0961,46.362 110.3254,46.952 110.3254,47.6659 C 110.3254,48.3844 110.0931,48.9805 109.6299,49.4544 C 109.1652,49.9283 108.5812,50.1637 107.8765,50.1637 C 107.4394,50.1637 107.0251,50.0659 106.6292,49.8687 C 106.2333,49.6715 105.9321,49.3826 105.7258,49.0019 C 105.5209,48.6213 105.417,48.1581 105.417,47.6109 L 105.417,47.6109 z "
+ style="fill:#af756f;fill-rule:nonzero"
+ id="path22112" />
+ <path
+ d="M 106.707,47.6781 C 106.707,48.1505 106.8186,48.5113 107.0433,48.7619 C 107.2665,49.0126 107.5432,49.138 107.8719,49.138 C 108.2005,49.138 108.4757,49.0126 108.6973,48.7619 C 108.9205,48.5113 109.0321,48.1474 109.0321,47.669 C 109.0321,47.2043 108.9205,46.845 108.6973,46.5943 C 108.4757,46.3436 108.2005,46.2183 107.8719,46.2183 C 107.5432,46.2183 107.2665,46.3436 107.0433,46.5943 C 106.8186,46.845 106.707,47.2073 106.707,47.6781 z "
+ style="fill:#ffffff;fill-rule:nonzero"
+ id="path22114" />
+ <path
+ d="M 102.102,45.3011 L 102.8007,45.3011 L 102.8007,44.9419 C 102.8007,44.5429 102.8435,44.2433 102.9291,44.0461 C 103.0147,43.8489 103.1706,43.6884 103.3984,43.5646 C 103.6277,43.4408 103.9166,43.3796 104.2651,43.3796 C 104.6243,43.3796 104.9744,43.4331 105.3183,43.5401 L 105.1487,44.4191 C 104.9484,44.3702 104.7558,44.3473 104.5708,44.3473 C 104.3874,44.3473 104.2575,44.3885 104.178,44.4741 C 104.0985,44.5597 104.0603,44.7233 104.0603,44.9648 L 104.0603,45.3011 L 105.0004,45.3011 L 105.0004,46.2901 L 104.0603,46.2901 L 104.0603,50.0567 L 102.8007,50.0567 L 102.8007,46.2901 L 102.102,46.2901 L 102.102,45.3011 L 102.102,45.3011 z "
+ style="fill:#af756f;fill-rule:nonzero"
+ id="path22116" />
+ <path
+ d="M 94.4089,45.3011 L 95.748,45.3011 L 96.8853,48.6779 L 97.9966,45.3011 L 99.299,45.3011 L 97.6205,49.8778 L 97.3194,50.7064 C 97.2093,50.9831 97.1039,51.1955 97.0045,51.3423 C 96.9036,51.489 96.789,51.6067 96.659,51.6985 C 96.5291,51.7886 96.3701,51.8605 96.1806,51.9109 C 95.991,51.9614 95.777,51.9874 95.537,51.9874 C 95.2955,51.9874 95.0585,51.9614 94.8247,51.9109 L 94.7131,50.925 C 94.9103,50.9647 95.0876,50.9831 95.2466,50.9831 C 95.5385,50.9831 95.7556,50.8974 95.8962,50.7262 C 96.0353,50.555 96.1439,50.3364 96.2188,50.0705 L 94.4089,45.3011 L 94.4089,45.3011 z "
+ style="fill:#af756f;fill-rule:nonzero"
+ id="path22118" />
+ <path
+ d="M 92.6402,50.0567 L 91.3821,50.0567 L 91.3821,45.3011 L 92.55,45.3011 L 92.55,45.9768 C 92.7503,45.6573 92.9306,45.4463 93.0896,45.3455 C 93.2501,45.2446 93.4305,45.1926 93.6338,45.1926 C 93.9212,45.1926 94.1964,45.2721 94.4623,45.4311 L 94.0725,46.5271 C 93.8616,46.391 93.6644,46.3222 93.4825,46.3222 C 93.3052,46.3222 93.1569,46.3696 93.0346,46.4675 C 92.9108,46.5638 92.816,46.7396 92.7457,46.9933 C 92.6754,47.2471 92.6402,47.779 92.6402,48.5877 L 92.6402,50.0567 L 92.6402,50.0567 z "
+ style="fill:#af756f;fill-rule:nonzero"
+ id="path22120" />
+ <path
+ d="M 90.5613,45.3011 L 90.5613,46.3039 L 89.7022,46.3039 L 89.7022,48.2208 C 89.7022,48.6091 89.7098,48.8353 89.7266,48.8995 C 89.7435,48.9637 89.7801,49.0157 89.8382,49.0585 C 89.8963,49.0998 89.9682,49.1212 90.0507,49.1212 C 90.1684,49.1212 90.3366,49.0799 90.5582,49.0004 L 90.6652,49.9757 C 90.3717,50.101 90.0415,50.1637 89.6701,50.1637 C 89.4438,50.1637 89.239,50.1255 89.0571,50.0506 C 88.8752,49.9742 88.7422,49.8748 88.6566,49.754 C 88.571,49.6333 88.5129,49.4697 88.4793,49.2633 C 88.4533,49.1181 88.4395,48.8216 88.4395,48.3767 L 88.4395,46.3039 L 87.8617,46.3039 L 87.8617,45.3011 L 88.4395,45.3011 L 88.4395,44.3549 L 89.7022,43.6212 L 89.7022,45.3011 L 90.5613,45.3011 L 90.5613,45.3011 z "
+ style="fill:#af756f;fill-rule:nonzero"
+ id="path22122" />
+ <path
+ d="M 86.0335,48.5434 L 87.2885,48.7528 C 87.1265,49.2129 86.8727,49.563 86.5242,49.8029 C 86.1772,50.0445 85.7415,50.1637 85.2187,50.1637 C 84.3918,50.1637 83.7803,49.8947 83.3829,49.3535 C 83.0695,48.9209 82.912,48.3737 82.912,47.7148 C 82.912,46.9261 83.1184,46.3085 83.5311,45.8621 C 83.9423,45.4158 84.4636,45.1926 85.0934,45.1926 C 85.8012,45.1926 86.3591,45.4265 86.7688,45.8942 C 87.1769,46.362 87.3726,47.0774 87.3558,48.042 L 84.2022,48.042 C 84.2114,48.4149 84.3123,48.7054 84.5064,48.9118 C 84.7005,49.1196 84.9436,49.2236 85.2325,49.2236 C 85.4297,49.2236 85.5948,49.1701 85.7293,49.0631 C 85.8638,48.9546 85.9662,48.7818 86.0335,48.5434 L 86.0335,48.5434 z "
+ style="fill:#af756f;fill-rule:nonzero"
+ id="path22124" />
+ <path
+ d="M 86.1054,47.2715 C 86.0962,46.9062 86.0029,46.6295 85.8241,46.44 C 85.6452,46.2504 85.4266,46.1556 85.1698,46.1556 C 84.8947,46.1556 84.6684,46.2565 84.4896,46.4568 C 84.3107,46.6555 84.2221,46.9276 84.2251,47.2715 L 86.1054,47.2715 L 86.1054,47.2715 z "
+ style="fill:#ffffff;fill-rule:nonzero"
+ id="path22126" />
+ <path
+ d="M 75.0304,45.3011 L 76.1906,45.3011 L 76.1906,45.9493 C 76.6049,45.4448 77.1001,45.1926 77.6734,45.1926 C 77.9776,45.1926 78.242,45.2553 78.4652,45.3806 C 78.6899,45.506 78.8734,45.6955 79.017,45.9493 C 79.2249,45.6955 79.4512,45.506 79.6927,45.3806 C 79.9342,45.2553 80.1926,45.1926 80.4677,45.1926 C 80.8162,45.1926 81.1128,45.2644 81.3543,45.4066 C 81.5958,45.5472 81.7762,45.7567 81.8955,46.0303 C 81.9826,46.2336 82.0254,46.5622 82.0254,47.0162 L 82.0254,50.0567 L 80.7673,50.0567 L 80.7673,47.3388 C 80.7673,46.8664 80.7245,46.5622 80.6374,46.4247 C 80.5212,46.2458 80.3424,46.1556 80.1008,46.1556 C 79.9235,46.1556 79.7584,46.2091 79.6025,46.3177 C 79.4481,46.4247 79.3365,46.5821 79.2677,46.79 C 79.1989,46.9979 79.1638,47.325 79.1638,47.7729 L 79.1638,50.0567 L 77.9057,50.0567 L 77.9057,47.4504 C 77.9057,46.9872 77.8828,46.6891 77.8385,46.5546 C 77.7941,46.4201 77.7238,46.3207 77.6306,46.255 C 77.5358,46.1893 77.4089,46.1556 77.2469,46.1556 C 77.0527,46.1556 76.8785,46.2076 76.7241,46.3131 C 76.5682,46.417 76.4566,46.5684 76.3893,46.7656 C 76.3221,46.9627 76.2884,47.2883 76.2884,47.7454 L 76.2884,50.0567 L 75.0304,50.0567 L 75.0304,45.3011 L 75.0304,45.3011 z "
+ style="fill:#af756f;fill-rule:nonzero"
+ id="path22128" />
+ <path
+ d="M 69.2308,47.6109 C 69.2308,47.1936 69.3347,46.7885 69.5396,46.3972 C 69.7459,46.0074 70.0379,45.7077 70.4155,45.5029 C 70.793,45.2965 71.2149,45.1926 71.6812,45.1926 C 72.3996,45.1926 72.9897,45.4265 73.4498,45.8942 C 73.9099,46.362 74.1392,46.952 74.1392,47.6659 C 74.1392,48.3844 73.9069,48.9805 73.4437,49.4544 C 72.979,49.9283 72.395,50.1637 71.6903,50.1637 C 71.2532,50.1637 70.8389,50.0659 70.443,49.8687 C 70.0471,49.6715 69.7459,49.3826 69.5396,49.0019 C 69.3347,48.6213 69.2308,48.1581 69.2308,47.6109 L 69.2308,47.6109 z "
+ style="fill:#af756f;fill-rule:nonzero"
+ id="path22130" />
+ <path
+ d="M 70.5209,47.6781 C 70.5209,48.1505 70.6325,48.5113 70.8572,48.7619 C 71.0804,49.0126 71.3571,49.138 71.6858,49.138 C 72.0144,49.138 72.2896,49.0126 72.5112,48.7619 C 72.7344,48.5113 72.846,48.1474 72.846,47.669 C 72.846,47.2043 72.7344,46.845 72.5112,46.5943 C 72.2896,46.3436 72.0144,46.2183 71.6858,46.2183 C 71.3571,46.2183 71.0804,46.3436 70.8572,46.5943 C 70.6325,46.845 70.5209,47.2073 70.5209,47.6781 z "
+ style="fill:#ffffff;fill-rule:nonzero"
+ id="path22132" />
+ <path
+ d="M 67.1748,48.5434 L 68.4298,48.7528 C 68.2678,49.2129 68.014,49.563 67.6655,49.8029 C 67.3185,50.0445 66.8828,50.1637 66.36,50.1637 C 65.5331,50.1637 64.9216,49.8947 64.5242,49.3535 C 64.2108,48.9209 64.0533,48.3737 64.0533,47.7148 C 64.0533,46.9261 64.2597,46.3085 64.6724,45.8621 C 65.0836,45.4158 65.6049,45.1926 66.2347,45.1926 C 66.9425,45.1926 67.5004,45.4265 67.9101,45.8942 C 68.3182,46.362 68.5139,47.0774 68.4971,48.042 L 65.3435,48.042 C 65.3527,48.4149 65.4536,48.7054 65.6477,48.9118 C 65.8418,49.1196 66.0849,49.2236 66.3738,49.2236 C 66.571,49.2236 66.7361,49.1701 66.8706,49.0631 C 67.0051,48.9546 67.1075,48.7818 67.1748,48.5434 L 67.1748,48.5434 z "
+ style="fill:#af756f;fill-rule:nonzero"
+ id="path22134" />
+ <path
+ d="M 67.2467,47.2715 C 67.2375,46.9062 67.1442,46.6295 66.9654,46.44 C 66.7865,46.2504 66.5679,46.1556 66.3111,46.1556 C 66.036,46.1556 65.8097,46.2565 65.6309,46.4568 C 65.452,46.6555 65.3634,46.9276 65.3664,47.2715 L 67.2467,47.2715 L 67.2467,47.2715 z "
+ style="fill:#ffffff;fill-rule:nonzero"
+ id="path22136" />
+ <path
+ d="M 60.351,47.643 L 60.351,46.5363 L 63.208,46.5363 L 63.208,49.1517 C 62.9298,49.4208 62.5278,49.6577 62.0004,49.8626 C 61.473,50.0659 60.9395,50.1683 60.3999,50.1683 C 59.7136,50.1683 59.1144,50.0246 58.6038,49.7372 C 58.0932,49.4483 57.7095,49.0371 57.4527,48.5006 C 57.1959,47.964 57.0675,47.3816 57.0675,46.7518 C 57.0675,46.0685 57.2112,45.4601 57.4971,44.9281 C 57.7844,44.3977 58.2033,43.9896 58.7567,43.7068 C 59.177,43.4882 59.7014,43.3796 60.3281,43.3796 C 61.1429,43.3796 61.7803,43.5508 62.2374,43.8917 C 62.6959,44.2341 62.991,44.7065 63.1224,45.3103 L 61.8063,45.5564 C 61.713,45.2339 61.5388,44.9786 61.2835,44.7921 C 61.0282,44.6056 60.7103,44.5123 60.3281,44.5123 C 59.7487,44.5123 59.2886,44.6958 58.9462,45.0627 C 58.6038,45.4311 58.4341,45.9752 58.4341,46.6983 C 58.4341,47.4764 58.6069,48.0618 58.9539,48.4516 C 59.2993,48.8414 59.7533,49.0356 60.3143,49.0356 C 60.5925,49.0356 60.8708,48.9805 61.1505,48.872 C 61.4287,48.7635 61.6687,48.6305 61.869,48.4761 L 61.869,47.643 L 60.351,47.643 L 60.351,47.643 z "
+ style="fill:#af756f;fill-rule:nonzero"
+ id="path22138" />
+ <path
+ d="M 53.4631,50.0567 L 52.205,50.0567 L 52.205,47.6292 C 52.205,47.1156 52.1775,46.7839 52.124,46.6326 C 52.0705,46.4828 51.9818,46.3651 51.8611,46.281 C 51.7403,46.1984 51.5951,46.1556 51.4254,46.1556 C 51.2068,46.1556 51.0111,46.2152 50.8384,46.3345 C 50.6657,46.4552 50.5464,46.6127 50.4822,46.8099 C 50.418,47.0071 50.3859,47.3709 50.3859,47.9029 L 50.3859,50.0567 L 49.1279,50.0567 L 49.1279,45.3011 L 50.2957,45.3011 L 50.2957,45.9997 C 50.7115,45.4616 51.2343,45.1926 51.8641,45.1926 C 52.1408,45.1926 52.3961,45.243 52.6254,45.3424 C 52.8547,45.4433 53.0289,45.5702 53.1466,45.7261 C 53.2644,45.882 53.3469,46.0578 53.3928,46.255 C 53.4401,46.4522 53.4631,46.7335 53.4631,47.1003 L 53.4631,50.0567 L 53.4631,50.0567 z "
+ style="fill:#af756f;fill-rule:nonzero"
+ id="path22140" />
+ <polygon
+ points="46.5888,50.0567 46.5888,45.3011 47.8469,45.3011 47.8469,50.0567 46.5888,50.0567 "
+ style="fill:#af756f;fill-rule:nonzero"
+ id="polygon22142" />
+ <polygon
+ points="46.5888,44.656 46.5888,43.4912 47.8469,43.4912 47.8469,44.656 46.5888,44.656 "
+ style="fill:#af756f;fill-rule:nonzero"
+ id="polygon22144" />
+ <path
+ d="M 42.428,46.7518 L 41.2861,46.5454 C 41.4145,46.0853 41.6346,45.746 41.948,45.5243 C 42.2629,45.3042 42.7276,45.1926 43.3451,45.1926 C 43.9077,45.1926 44.325,45.2598 44.6001,45.3928 C 44.8738,45.5258 45.0679,45.694 45.1795,45.8988 C 45.2911,46.1037 45.3476,46.4782 45.3476,47.0254 L 45.3339,48.4944 C 45.3339,48.9118 45.3538,49.2205 45.395,49.4193 C 45.4348,49.6165 45.5112,49.8305 45.6213,50.0567 L 44.3754,50.0567 C 44.3433,49.9726 44.3021,49.8488 44.2547,49.6852 C 44.2348,49.6103 44.2195,49.5614 44.2103,49.537 C 43.9948,49.7464 43.7655,49.9023 43.5209,50.0078 C 43.2763,50.1117 43.0149,50.1637 42.7367,50.1637 C 42.2476,50.1637 41.8608,50.0307 41.5796,49.7663 C 41.2968,49.5003 41.1561,49.164 41.1561,48.7574 C 41.1561,48.4899 41.2203,48.2499 41.3487,48.0389 C 41.4771,47.828 41.6575,47.6674 41.8883,47.5559 C 42.1192,47.4443 42.4539,47.3464 42.8896,47.2624 C 43.4766,47.1523 43.8847,47.0483 44.111,46.9536 L 44.111,46.8282 C 44.111,46.5852 44.0514,46.414 43.9321,46.31 C 43.8129,46.2076 43.5882,46.1556 43.2565,46.1556 C 43.0318,46.1556 42.8575,46.2 42.7321,46.2886 C 42.6068,46.3758 42.5059,46.5301 42.428,46.7518 L 42.428,46.7518 z "
+ style="fill:#af756f;fill-rule:nonzero"
+ id="path22146" />
+ <path
+ d="M 44.111,47.7729 C 43.9505,47.8264 43.6952,47.8906 43.3451,47.9655 C 42.9966,48.0404 42.7688,48.1138 42.6603,48.1841 C 42.4967,48.3018 42.4142,48.4486 42.4142,48.6274 C 42.4142,48.8047 42.4799,48.9561 42.6114,49.0845 C 42.7428,49.2129 42.9095,49.2771 43.1128,49.2771 C 43.3405,49.2771 43.5561,49.2022 43.7624,49.0539 C 43.9153,48.9408 44.0147,48.8017 44.0621,48.6366 C 44.0957,48.5296 44.111,48.3248 44.111,48.0236 L 44.111,47.7729 z "
+ style="fill:#ffffff;fill-rule:nonzero"
+ id="path22148" />
+ <path
+ d="M 39.1229,50.0567 L 37.8648,50.0567 L 37.8648,45.3011 L 39.0327,45.3011 L 39.0327,45.9768 C 39.233,45.6573 39.4133,45.4463 39.5723,45.3455 C 39.7328,45.2446 39.9132,45.1926 40.1165,45.1926 C 40.404,45.1926 40.6792,45.2721 40.9451,45.4311 L 40.5553,46.5271 C 40.3443,46.391 40.1471,46.3222 39.9652,46.3222 C 39.7879,46.3222 39.6396,46.3696 39.5173,46.4675 C 39.3935,46.5638 39.2987,46.7396 39.2284,46.9933 C 39.1581,47.2471 39.1229,47.779 39.1229,48.5877 L 39.1229,50.0567 L 39.1229,50.0567 z "
+ style="fill:#af756f;fill-rule:nonzero"
+ id="path22150" />
+ <path
+ d="M 33.8476,47.643 L 33.8476,46.5363 L 36.7046,46.5363 L 36.7046,49.1517 C 36.4264,49.4208 36.0244,49.6577 35.497,49.8626 C 34.9696,50.0659 34.4361,50.1683 33.8965,50.1683 C 33.2102,50.1683 32.611,50.0246 32.1004,49.7372 C 31.5898,49.4483 31.2061,49.0371 30.9493,48.5006 C 30.6925,47.964 30.5641,47.3816 30.5641,46.7518 C 30.5641,46.0685 30.7078,45.4601 30.9937,44.9281 C 31.281,44.3977 31.6999,43.9896 32.2533,43.7068 C 32.6736,43.4882 33.198,43.3796 33.8247,43.3796 C 34.6395,43.3796 35.2769,43.5508 35.734,43.8917 C 36.1925,44.2341 36.4876,44.7065 36.619,45.3103 L 35.3029,45.5564 C 35.2096,45.2339 35.0354,44.9786 34.7801,44.7921 C 34.5248,44.6056 34.2069,44.5123 33.8247,44.5123 C 33.2453,44.5123 32.7852,44.6958 32.4428,45.0627 C 32.1004,45.4311 31.9307,45.9752 31.9307,46.6983 C 31.9307,47.4764 32.1035,48.0618 32.4505,48.4516 C 32.7959,48.8414 33.2499,49.0356 33.8109,49.0356 C 34.0891,49.0356 34.3674,48.9805 34.6471,48.872 C 34.9253,48.7635 35.1653,48.6305 35.3656,48.4761 L 35.3656,47.643 L 33.8476,47.643 L 33.8476,47.643 z "
+ style="fill:#af756f;fill-rule:nonzero"
+ id="path22152" />
+ <polygon
+ points="27.5863,48.3049 27.5863,47.0468 30.0581,47.0468 30.0581,48.3049 27.5863,48.3049 "
+ style="fill:#af756f;fill-rule:nonzero"
+ id="polygon22154" />
+ <polygon
+ points="25.1818,50.0567 25.1818,45.3011 26.4399,45.3011 26.4399,50.0567 25.1818,50.0567 "
+ style="fill:#af756f;fill-rule:nonzero"
+ id="polygon22156" />
+ <polygon
+ points="25.1818,44.656 25.1818,43.4912 26.4399,43.4912 26.4399,44.656 25.1818,44.656 "
+ style="fill:#af756f;fill-rule:nonzero"
+ id="polygon22158" />
+ <path
+ d="M 24.3075,45.3011 L 24.3075,46.3039 L 23.4484,46.3039 L 23.4484,48.2208 C 23.4484,48.6091 23.456,48.8353 23.4728,48.8995 C 23.4897,48.9637 23.5263,49.0157 23.5844,49.0585 C 23.6425,49.0998 23.7144,49.1212 23.7969,49.1212 C 23.9146,49.1212 24.0828,49.0799 24.3044,49.0004 L 24.4114,49.9757 C 24.1179,50.101 23.7877,50.1637 23.4163,50.1637 C 23.19,50.1637 22.9852,50.1255 22.8033,50.0506 C 22.6214,49.9742 22.4884,49.8748 22.4028,49.754 C 22.3172,49.6333 22.2591,49.4697 22.2255,49.2633 C 22.1995,49.1181 22.1857,48.8216 22.1857,48.3767 L 22.1857,46.3039 L 21.6079,46.3039 L 21.6079,45.3011 L 22.1857,45.3011 L 22.1857,44.3549 L 23.4484,43.6212 L 23.4484,45.3011 L 24.3075,45.3011 L 24.3075,45.3011 z "
+ style="fill:#af756f;fill-rule:nonzero"
+ id="path22160" />
+ <path
+ d="M 20.8513,50.0567 L 19.5932,50.0567 L 19.5932,47.6292 C 19.5932,47.1156 19.5657,46.7839 19.5122,46.6326 C 19.4587,46.4828 19.37,46.3651 19.2493,46.281 C 19.1285,46.1984 18.9833,46.1556 18.8136,46.1556 C 18.595,46.1556 18.3993,46.2152 18.2266,46.3345 C 18.0539,46.4552 17.9346,46.6127 17.8704,46.8099 C 17.8062,47.0071 17.7741,47.3709 17.7741,47.9029 L 17.7741,50.0567 L 16.5161,50.0567 L 16.5161,45.3011 L 17.6839,45.3011 L 17.6839,45.9997 C 18.0997,45.4616 18.6225,45.1926 19.2523,45.1926 C 19.529,45.1926 19.7843,45.243 20.0136,45.3424 C 20.2429,45.4433 20.4171,45.5702 20.5348,45.7261 C 20.6526,45.882 20.7351,46.0578 20.781,46.255 C 20.8283,46.4522 20.8513,46.7335 20.8513,47.1003 L 20.8513,50.0567 L 20.8513,50.0567 z "
+ style="fill:#af756f;fill-rule:nonzero"
+ id="path22162" />
+ <polygon
+ points="15.8312,50.0567 14.3882,50.0567 13.8149,48.5648 11.1903,48.5648 10.6491,50.0567 9.2428,50.0567 11.8002,43.4912 13.202,43.4912 15.8312,50.0567 "
+ style="fill:#af756f;fill-rule:nonzero"
+ id="polygon22164" />
+ <polygon
+ points="13.39,47.4596 12.485,45.0229 11.5984,47.4596 13.39,47.4596 "
+ style="fill:#ffffff;fill-rule:nonzero"
+ id="polygon22166" />
+ <path
+ d="M 81.2128,16.1804 C 84.9324,15.608 89.1767,14.9567 94.0752,14.1917 C 99.7892,13.2992 106.5495,12.2281 114.6748,10.9319 C 114.1506,17.3686 113.6906,23.1078 113.2835,28.2537 C 112.9162,32.8964 112.5897,37.109 112.2915,40.9467 C 106.3386,39.8648 101.152,38.9183 96.5959,38.0797 C 92.5583,37.3365 88.954,36.6672 85.7134,36.0658 C 85.0808,33.2807 84.4034,30.3126 83.6852,27.145 C 82.9157,23.7514 82.0942,20.103 81.2128,16.1804 L 81.2128,16.1804 z "
+ style="fill:none;stroke:#6296b6;stroke-width:0.33000001"
+ id="path22168" />
+ <path
+ d="M 95.5026,29.3022 C 96.0534,30.4142 97.4365,31.0368 98.7177,30.6728 C 99.9989,30.3089 100.6765,29.0131 100.1058,27.7927 C 98.9461,25.3123 95.7656,24.198 93.4685,25.1644 C 91.1715,26.1308 90.518,28.4934 91.5904,30.5715 C 92.3812,32.1039 93.7167,33.3099 95.2769,34.0477 C 96.8839,34.8077 98.7392,35.1215 100.6917,34.7245 C 102.6443,34.3274 104.3251,33.1895 105.2695,31.6605 C 106.2764,30.0304 106.4996,27.9758 105.6196,25.9654 C 104.4178,23.2198 101.9974,21.2321 99.2032,20.3147 C 96.5537,19.4446 93.6132,19.646 91.3639,20.8365 C 89.1146,22.027 87.8964,23.8059 87.4056,25.798 C 86.9472,27.6587 87.1979,29.7335 88.2277,31.6599 C 89.485,34.0121 91.5306,35.8956 93.9225,37.11 C 96.4327,38.3843 99.3076,39.045 102.6064,38.6113 C 105.9052,38.1776 109.0748,36.4665 110.9887,33.9502 C 113.1233,31.144 113.8303,27.4319 112.3269,23.7186 C 110.4501,19.083 106.3322,15.8441 101.5921,14.5621 C 97.237,13.3843 92.4956,14.1422 89.1909,16.3064 C 85.8862,18.4706 84.3733,21.2289 83.8342,24.2287 C 83.3455,26.9491 83.821,29.8933 85.3004,32.601"
+ style="fill:none"
+ id="path22170" />
+ <path
+ d="M 85.5723,35.4365 C 85.9318,35.5011 86.2956,35.8382 86.3728,36.1856 C 86.45,36.5331 86.2117,36.7532 85.855,36.6838 C 85.4983,36.6144 85.1547,36.2879 85.0748,35.9464 C 84.9949,35.6049 85.2129,35.3719 85.5723,35.4365 L 85.5723,35.4365 z "
+ style="fill:#6296b6;stroke:#6296b6;stroke-width:0.0834"
+ id="path22172" />
+ <path
+ d="M 96.5058,28.8224 C 96.5132,28.8365 96.5242,28.8592 96.5424,28.8874 C 96.6704,29.1257 96.8799,29.3086 97.1139,29.412 C 97.3608,29.5192 97.6459,29.5493 97.9169,29.4797 C 97.946,29.4751 97.9718,29.4674 97.9878,29.4594 C 97.9943,29.4597 98.004,29.4572 98.0136,29.4519 C 98.0136,29.4519 98.0136,29.4519 98.0136,29.4519 C 98.0136,29.4519 98.0136,29.4519 98.0136,29.4519 C 98.0877,29.4259 98.1549,29.3941 98.2187,29.3533 C 98.289,29.3128 98.3493,29.2604 98.4029,29.2077 C 98.6878,28.9202 98.7816,28.4845 98.5958,28.0752 C 98.5637,28.0145 98.5282,27.9449 98.4889,27.8669 C 98.0632,27.0841 97.3874,26.4932 96.6068,26.1726 C 95.8281,25.85 94.9645,25.7968 94.186,26.0614 C 94.186,26.0614 94.186,26.0614 94.1858,26.0587 C 94.1397,26.0727 94.0743,26.1007 93.9795,26.1395 C 93.9731,26.1424 93.9631,26.1451 93.9567,26.148 C 93.9535,26.148 93.9535,26.148 93.9535,26.148 C 93.9535,26.148 93.9535,26.148 93.9535,26.148 C 93.7353,26.2417 93.5365,26.359 93.3599,26.4914 C 93.1743,26.6311 93.0113,26.7887 92.8767,26.9586 C 92.1817,27.814 92.0488,29.0546 92.6026,30.186 C 92.6512,30.2825 92.707,30.3874 92.7729,30.4982 C 93.4221,31.6445 94.4268,32.5416 95.5846,33.1018 C 96.7762,33.673 98.1702,33.9049 99.5347,33.6616 C 99.6656,33.6364 99.7935,33.614 99.9118,33.5817 C 99.9181,33.5794 99.9305,33.5774 99.9398,33.5755 C 99.9398,33.5755 99.9398,33.5755 99.9398,33.5755 C 99.9398,33.5755 99.9398,33.5755 99.9398,33.5755 C 100.3646,33.4691 100.7615,33.3199 101.131,33.1364 C 101.5181,32.9457 101.8622,32.7132 102.1825,32.4548 C 103.8876,31.0306 104.5836,28.6379 103.5823,26.3108 C 103.5068,26.1362 103.4209,25.953 103.3214,25.761 C 102.271,23.7144 100.467,22.2248 98.4162,21.4766 C 96.4315,20.753 94.2891,20.7635 92.4246,21.5842 C 92.4246,21.5844 92.4243,21.5817 92.4241,21.5791 C 92.2912,21.6371 92.1353,21.7156 91.9528,21.8087 C 91.9463,21.8147 91.936,21.818 91.9328,21.8211 C 91.9295,21.8239 91.9295,21.8239 91.9295,21.8239 C 91.9295,21.8239 91.9295,21.8239 91.9295,21.8239 C 91.412,22.0963 90.9561,22.4242 90.5501,22.7866 C 90.1515,23.1493 89.8029,23.5488 89.5169,23.9744 C 88.7943,25.0408 88.4079,26.2945 88.3672,27.5787 C 88.3279,28.8174 88.6102,30.1127 89.2426,31.3483 C 89.3311,31.5192 89.4261,31.6961 89.531,31.8767 C 90.6502,33.7889 92.3276,35.3152 94.2571,36.3176 C 96.2739,37.3556 98.6631,37.8765 101.0853,37.6179 C 101.3233,37.5932 101.5523,37.564 101.7757,37.5208 C 101.7817,37.5219 101.7908,37.5203 101.7999,37.5189 C 101.7999,37.5189 101.7999,37.5189 101.8028,37.5164 C 101.8028,37.5164 101.8028,37.5164 101.8028,37.5164 C 102.5874,37.383 103.3367,37.1738 104.04,36.8886 C 104.7764,36.5987 105.4587,36.2301 106.0927,35.7945 C 107.7968,34.6138 109.1027,32.9422 109.7809,30.9732 C 110.501,28.8824 110.5137,26.504 109.5838,24.1656 C 109.458,23.8568 109.3187,23.5299 109.1578,23.205 C 107.4024,19.5933 104.1985,17.0499 100.5637,15.9356 C 98.8267,15.4001 97.0351,15.2135 95.293,15.3828 C 93.6311,15.5442 92.035,16.0266 90.5885,16.825 C 90.3332,16.9667 90.0834,17.115 89.8458,17.2656 C 89.8391,17.2746 89.8284,17.2785 89.825,17.2818 C 89.8214,17.2822 89.8214,17.2822 89.8214,17.2822 C 89.8214,17.2822 89.8214,17.2822 89.8214,17.2822 C 89.0277,17.8055 88.3333,18.3949 87.7406,19.0441 C 87.1555,19.6735 86.6609,20.3531 86.2575,21.0658 C 85.2752,22.8064 84.8024,24.7749 84.8379,26.7444 C 84.8718,28.6144 85.358,30.5381 86.3154,32.362 C 85.8421,32.5235 85.3773,32.6771 84.9246,32.8301 C 83.8018,30.7265 83.2075,28.4979 83.1185,26.323 C 83.0236,24.0056 83.5006,21.6644 84.5821,19.5529 C 85.0309,18.6756 85.5888,17.8296 86.2497,17.0439 C 86.9429,16.2255 87.7532,15.4577 88.6881,14.7806 C 88.6952,14.777 88.7025,14.7728 88.7093,14.7636 C 88.7093,14.7636 88.7093,14.7636 88.713,14.7631 C 88.713,14.7631 88.713,14.7631 88.713,14.7631 C 88.9979,14.56 89.2811,14.3689 89.567,14.1924 C 91.2877,13.1263 93.2205,12.4351 95.2505,12.1496 C 97.3959,11.8479 99.6234,12.0067 101.8107,12.6025 C 104.0826,13.2296 106.2473,14.3403 108.1351,15.8714 C 110.051,17.4252 111.645,19.3736 112.7211,21.6529 C 112.9058,22.0335 113.0805,22.4405 113.2454,22.8668 C 114.3999,25.9245 114.2775,29.0014 113.2091,31.6768 C 112.2191,34.1553 110.4414,36.2075 108.2021,37.6095 C 107.3792,38.124 106.499,38.5457 105.573,38.8716 C 104.6711,39.1844 103.7303,39.4112 102.7468,39.5396 C 102.7378,39.5408 102.7289,39.5425 102.723,39.5444 C 102.72,39.5438 102.72,39.5438 102.72,39.5438 C 102.72,39.5438 102.72,39.5438 102.72,39.5438 C 102.438,39.5785 102.1596,39.6076 101.8933,39.626 C 100.3775,39.7327 98.8906,39.6032 97.4912,39.2869 C 96.1404,38.9815 94.8434,38.4921 93.6595,37.8581 C 91.3533,36.6282 89.3549,34.7913 88.0077,32.5109 C 87.8911,32.3165 87.7745,32.1063 87.6621,31.8871 C 86.8524,30.3298 86.4619,28.6953 86.4686,27.1164 C 86.4755,25.4669 86.9195,23.8379 87.7897,22.4238 C 88.1461,21.8445 88.5672,21.301 89.0694,20.8075 C 89.5833,20.2951 90.1677,19.8386 90.8373,19.4408 C 90.8442,19.4375 90.8512,19.434 90.8614,19.4278 C 90.8614,19.4278 90.8614,19.4278 90.8614,19.4275 C 90.8614,19.4275 90.8614,19.4275 90.8614,19.4275 C 91.0296,19.3275 91.2304,19.2213 91.4568,19.1115 C 91.4568,19.1115 91.4565,19.1087 91.4598,19.1058 C 93.8886,17.8963 96.7533,17.7703 99.4519,18.6766 C 102.3067,19.6309 104.8201,21.6696 106.2399,24.5008 C 106.3549,24.7357 106.4651,24.9907 106.5779,25.2592 C 107.3054,27.0171 107.3532,28.8104 106.8766,30.4075 C 106.422,31.9311 105.4874,33.2534 104.2224,34.2138 C 103.7466,34.5716 103.2248,34.8787 102.6665,35.1274 C 102.121,35.3718 101.5353,35.5586 100.9177,35.6832 C 100.9085,35.6848 100.9024,35.6869 100.8932,35.689 C 100.8901,35.6916 100.8901,35.6916 100.8901,35.6916 C 100.8901,35.6916 100.8901,35.6916 100.8901,35.6916 C 100.7156,35.725 100.5441,35.7561 100.3789,35.7787 C 98.4606,36.045 96.5378,35.6713 94.9,34.8538 C 93.303,34.0531 91.9193,32.8076 91.0092,31.2363 C 90.9356,31.1019 90.8603,30.9603 90.7833,30.8038 C 89.8383,28.9342 89.9958,26.8549 91.0887,25.3647 C 91.3176,25.0648 91.5779,24.7826 91.8744,24.5338 C 92.1829,24.2822 92.5238,24.0615 92.9012,23.8799 C 92.9078,23.8771 92.9179,23.874 92.9246,23.871 C 92.9246,23.871 92.9246,23.871 92.9278,23.8681 C 92.928,23.8707 92.928,23.8707 92.928,23.8707 C 93.0144,23.8295 93.1245,23.7816 93.2553,23.73 C 93.2553,23.73 93.2553,23.73 93.255,23.7273 C 94.5868,23.2107 96.0958,23.2533 97.4799,23.7892 C 98.9085,24.3462 100.1667,25.4021 100.9137,26.8265 C 100.9753,26.9395 101.0337,27.0675 101.0987,27.2075 C 101.7079,28.5867 101.3572,30.0252 100.3742,30.9187 C 100.1907,31.0876 99.9817,31.2365 99.7567,31.3631 C 99.526,31.4855 99.2856,31.5858 99.0289,31.6581 C 99.0258,31.6609 99.0258,31.6609 99.0258,31.6609 C 99.0227,31.6635 99.0227,31.6635 99.0227,31.6635 C 99.0195,31.6633 99.0195,31.6633 99.0195,31.6633 C 99.0163,31.6631 99.0163,31.6631 99.0163,31.6631 C 99.0131,31.6657 99.01,31.6655 99.01,31.6655 C 99.01,31.6655 99.01,31.6655 99.01,31.6655 C 99.0069,31.6653 99.0004,31.665 99.0004,31.665 C 99.0037,31.668 99.0037,31.668 99.0037,31.668 C 99.0037,31.668 99.0037,31.668 99.0004,31.665 C 98.9277,31.6888 98.8581,31.7042 98.7915,31.7199 C 97.9543,31.9003 97.083,31.7764 96.3171,31.4244 C 95.5594,31.0736 94.9043,30.4973 94.487,29.7536 C 94.4565,29.6957 94.422,29.6323 94.3831,29.5526 C 95.0703,29.3194 95.7778,29.0752 96.5058,28.8224 L 96.5058,28.8224 z "
+ style="fill:#af756f;fill-rule:nonzero"
+ id="path22174" />
+ <path
+ d="M 112.357,40.0897 C 113.1134,40.2176 113.7063,40.7193 113.6611,41.1947 C 113.6158,41.6701 112.9646,41.928 112.2275,41.7865 C 111.4904,41.6449 110.9361,41.1677 110.9636,40.706 C 110.9911,40.2443 111.6006,39.9618 112.357,40.0897 L 112.357,40.0897 z "
+ style="fill:#6296b6;stroke:#6296b6;stroke-width:0.0834"
+ id="path22176" />
+ <path
+ d="M 80.9994,15.2306 C 81.4068,15.1603 81.8489,15.5387 81.9627,16.0656 C 82.0765,16.5925 81.8253,17.0573 81.4225,17.1118 C 81.0196,17.1663 80.6113,16.8032 80.493,16.292 C 80.3746,15.7809 80.592,15.3009 80.9994,15.2306 L 80.9994,15.2306 z "
+ style="fill:#6296b6;stroke:#6296b6;stroke-width:0.0834"
+ id="path22178" />
+ <path
+ d="M 114.784,9.5681 C 115.841,9.3845 116.6635,9.9651 116.5776,10.8523 C 116.4918,11.7395 115.555,12.5601 114.5288,12.705 C 113.5026,12.8498 112.7574,12.2943 112.8145,11.4458 C 112.8715,10.5974 113.7271,9.7518 114.784,9.5681 z "
+ style="fill:#6296b6;stroke:#6296b6;stroke-width:0.0834"
+ id="path22180" />
+ </g>
+</svg> \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/svg/tiger.svg b/src/corelib/render/software/agg-demos/svg/tiger.svg
new file mode 100755
index 00000000..234c1673
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/svg/tiger.svg
@@ -0,0 +1,728 @@
+<?xml version = "1.0" standalone = "no"?>
+<!DOCTYPE svg SYSTEM "svg-19990812.dtd">
+<svg width = "600px" height="600px">
+<title>A less cute tiger
+</title>
+<g transform="translate(190,150)">
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.172">
+ <path d="M-122.304 84.285C-122.304 84.285 -122.203 86.179 -123.027 86.16C-123.851 86.141 -140.305 38.066 -160.833 40.309C-160.833 40.309 -143.05 32.956 -122.304 84.285z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.172">
+ <path d="M-118.774 81.262C-118.774 81.262 -119.323 83.078 -120.092 82.779C-120.86 82.481 -119.977 31.675 -140.043 26.801C-140.043 26.801 -120.82 25.937 -118.774 81.262z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.172">
+ <path d="M-91.284 123.59C-91.284 123.59 -89.648 124.55 -90.118 125.227C-90.589 125.904 -139.763 113.102 -149.218 131.459C-149.218 131.459 -145.539 112.572 -91.284 123.59z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.172">
+ <path d="M-94.093 133.801C-94.093 133.801 -92.237 134.197 -92.471 134.988C-92.704 135.779 -143.407 139.121 -146.597 159.522C-146.597 159.522 -149.055 140.437 -94.093 133.801z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.172">
+ <path d="M-98.304 128.276C-98.304 128.276 -96.526 128.939 -96.872 129.687C-97.218 130.435 -147.866 126.346 -153.998 146.064C-153.998 146.064 -153.646 126.825 -98.304 128.276z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.172">
+ <path d="M-109.009 110.072C-109.009 110.072 -107.701 111.446 -108.34 111.967C-108.979 112.488 -152.722 86.634 -166.869 101.676C-166.869 101.676 -158.128 84.533 -109.009 110.072z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.172">
+ <path d="M-116.554 114.263C-116.554 114.263 -115.098 115.48 -115.674 116.071C-116.25 116.661 -162.638 95.922 -174.992 112.469C-174.992 112.469 -168.247 94.447 -116.554 114.263z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.172">
+ <path d="M-119.154 118.335C-119.154 118.335 -117.546 119.343 -118.036 120.006C-118.526 120.669 -167.308 106.446 -177.291 124.522C-177.291 124.522 -173.066 105.749 -119.154 118.335z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.172">
+ <path d="M-108.42 118.949C-108.42 118.949 -107.298 120.48 -107.999 120.915C-108.7 121.35 -148.769 90.102 -164.727 103.207C-164.727 103.207 -153.862 87.326 -108.42 118.949z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.172">
+ <path d="M-128.2 90C-128.2 90 -127.6 91.8 -128.4 92C-129.2 92.2 -157.8 50.2 -177.001 57.8C-177.001 57.8 -161.8 46 -128.2 90z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.172">
+ <path d="M-127.505 96.979C-127.505 96.979 -126.53 98.608 -127.269 98.975C-128.007 99.343 -164.992 64.499 -182.101 76.061C-182.101 76.061 -169.804 61.261 -127.505 96.979z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.172">
+ <path d="M-127.62 101.349C-127.62 101.349 -126.498 102.88 -127.199 103.315C-127.9 103.749 -167.969 72.502 -183.927 85.607C-183.927 85.607 -173.062 69.726 -127.62 101.349z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000">
+ <path d="M-129.83 103.065C-129.327 109.113 -128.339 115.682 -126.6 118.801C-126.6 118.801 -130.2 131.201 -121.4 144.401C-121.4 144.401 -121.8 151.601 -120.2 154.801C-120.2 154.801 -116.2 163.201 -111.4 164.001C-107.516 164.648 -98.793 167.717 -88.932 169.121C-88.932 169.121 -71.8 183.201 -75 196.001C-75 196.001 -75.4 212.401 -79 214.001C-79 214.001 -67.4 202.801 -77 219.601L-81.4 238.401C-81.4 238.401 -55.8 216.801 -71.4 235.201L-81.4 261.201C-81.4 261.201 -61.8 242.801 -69 251.201L-72.2 260.001C-72.2 260.001 -29 232.801 -59.8 262.401C-59.8 262.401 -51.8 258.801 -47.4 261.601C-47.4 261.601 -40.6 260.401 -41.4 262.001C-41.4 262.001 -62.2 272.401 -65.8 290.801C-65.8 290.801 -57.4 280.801 -60.6 291.601L-60.2 303.201C-60.2 303.201 -56.2 281.601 -56.6 319.201C-56.6 319.201 -37.4 301.201 -49 322.001L-49 338.801C-49 338.801 -33.8 322.401 -40.2 335.201C-40.2 335.201 -30.2 326.401 -34.2 341.601C-34.2 341.601 -35 352.001 -30.6 340.801C-30.6 340.801 -14.6 310.201 -20.6 336.401C-20.6 336.401 -21.4 355.601 -16.6 340.801C-16.6 340.801 -16.2 351.201 -7 358.401C-7 358.401 -8.2 307.601 4.6 343.601L8.6 360.001C8.6 360.001 11.4 350.801 11 345.601C11 345.601 25.8 329.201 19 353.601C19 353.601 34.2 330.801 31 344.001C31 344.001 23.4 360.001 25 364.801C25 364.801 41.8 330.001 43 328.401C43 328.401 41 370.802 51.8 334.801C51.8 334.801 57.4 346.801 54.6 351.201C54.6 351.201 62.6 343.201 61.8 340.001C61.8 340.001 66.4 331.801 69.2 345.401C69.2 345.401 71 354.801 72.6 351.601C72.6 351.601 76.6 375.602 77.8 352.801C77.8 352.801 79.4 339.201 72.2 327.601C72.2 327.601 73 324.401 70.2 320.401C70.2 320.401 83.8 342.001 76.6 313.201C76.6 313.201 87.801 321.201 89.001 321.201C89.001 321.201 75.4 298.001 84.2 302.801C84.2 302.801 79 292.401 97.001 304.401C97.001 304.401 81 288.401 98.601 298.001C98.601 298.001 106.601 304.401 99.001 294.401C99.001 294.401 84.6 278.401 106.601 296.401C106.601 296.401 118.201 312.801 119.001 315.601C119.001 315.601 109.001 286.401 104.601 283.601C104.601 283.601 113.001 247.201 154.201 262.801C154.201 262.801 161.001 280.001 165.401 261.601C165.401 261.601 178.201 255.201 189.401 282.801C189.401 282.801 193.401 269.201 192.601 266.401C192.601 266.401 199.401 267.601 198.601 266.401C198.601 266.401 211.801 270.801 213.001 270.001C213.001 270.001 219.801 276.801 220.201 273.201C220.201 273.201 229.401 276.001 227.401 272.401C227.401 272.401 236.201 288.001 236.601 291.601L239.001 277.601L241.001 280.401C241.001 280.401 242.601 272.801 241.801 271.601C241.001 270.401 261.801 278.401 266.601 299.201L268.601 307.601C268.601 307.601 274.601 292.801 273.001 288.801C273.001 288.801 278.201 289.601 278.601 294.001C278.601 294.001 282.601 270.801 277.801 264.801C277.801 264.801 282.201 264.001 283.401 267.601L283.401 260.401C283.401 260.401 290.601 261.201 290.601 258.801C290.601 258.801 295.001 254.801 297.001 259.601C297.001 259.601 284.601 224.401 303.001 243.601C303.001 243.601 310.201 254.401 306.601 235.601C303.001 216.801 299.001 215.201 303.801 214.801C303.801 214.801 304.601 211.201 302.601 209.601C300.601 208.001 303.801 209.601 303.801 209.601C303.801 209.601 308.601 213.601 303.401 191.601C303.401 191.601 309.801 193.201 297.801 164.001C297.801 164.001 300.601 161.601 296.601 153.201C296.601 153.201 304.601 157.601 307.401 156.001C307.401 156.001 307.001 154.401 303.801 150.401C303.801 150.401 282.201 95.6 302.601 117.601C302.601 117.601 314.451 131.151 308.051 108.351C308.051 108.351 298.94 84.341 299.717 80.045L-129.83 103.065z"/>
+ </g>
+ <g style="fill: #cc7226; stroke:#000000">
+ <path d="M299.717 80.245C300.345 80.426 302.551 81.55 303.801 83.2C303.801 83.2 310.601 94 305.401 75.6C305.401 75.6 296.201 46.8 305.001 58C305.001 58 311.001 65.2 307.801 51.6C303.936 35.173 301.401 28.8 301.401 28.8C301.401 28.8 313.001 33.6 286.201 -6L295.001 -2.4C295.001 -2.4 275.401 -42 253.801 -47.2L245.801 -53.2C245.801 -53.2 284.201 -91.2 271.401 -128C271.401 -128 264.601 -133.2 255.001 -124C255.001 -124 248.601 -119.2 242.601 -120.8C242.601 -120.8 211.801 -119.6 209.801 -119.6C207.801 -119.6 173.001 -156.8 107.401 -139.2C107.401 -139.2 102.201 -137.2 97.801 -138.4C97.801 -138.4 79.4 -154.4 30.6 -131.6C30.6 -131.6 20.6 -129.6 19 -129.6C17.4 -129.6 14.6 -129.6 6.6 -123.2C-1.4 -116.8 -1.8 -116 -3.8 -114.4C-3.8 -114.4 -20.2 -103.2 -25 -102.4C-25 -102.4 -36.6 -96 -41 -86L-44.6 -84.8C-44.6 -84.8 -46.2 -77.6 -46.6 -76.4C-46.6 -76.4 -51.4 -72.8 -52.2 -67.2C-52.2 -67.2 -61 -61.2 -60.6 -56.8C-60.6 -56.8 -62.2 -51.6 -63 -46.8C-63 -46.8 -70.2 -42 -69.4 -39.2C-69.4 -39.2 -77 -25.2 -75.8 -18.4C-75.8 -18.4 -82.2 -18.8 -85 -16.4C-85 -16.4 -85.8 -11.6 -87.4 -11.2C-87.4 -11.2 -90.2 -10 -87.8 -6C-87.8 -6 -89.4 -3.2 -89.8 -1.6C-89.8 -1.6 -89 1.2 -93.4 6.8C-93.4 6.8 -99.8 25.6 -97.8 30.8C-97.8 30.8 -97.4 35.6 -100.2 37.2C-100.2 37.2 -103.8 36.8 -95.4 48.8C-95.4 48.8 -94.6 50 -97.8 52.4C-97.8 52.4 -115 56 -117.4 72.4C-117.4 72.4 -131 87.2 -131 92.4C-131 94.705 -130.729 97.852 -130.03 102.465C-130.03 102.465 -130.6 110.801 -103 111.601C-75.4 112.401 299.717 80.245 299.717 80.245z"/>
+ </g>
+ <g style="fill: #cc7226">
+ <path d="M-115.6 102.6C-140.6 63.2 -126.2 119.601 -126.2 119.601C-117.4 154.001 12.2 116.401 12.2 116.401C12.2 116.401 181.001 86 192.201 82C203.401 78 298.601 84.4 298.601 84.4L293.001 67.6C228.201 21.2 209.001 44.4 195.401 40.4C181.801 36.4 184.201 46 181.001 46.8C177.801 47.6 138.601 22.8 132.201 23.6C125.801 24.4 100.459 0.649 115.401 32.4C131.401 66.4 57 71.6 40.2 60.4C23.4 49.2 47.4 78.8 47.4 78.8C65.8 98.8 31.4 82 31.4 82C-3 69.2 -27 94.8 -30.2 95.6C-33.4 96.4 -38.2 99.6 -39 93.2C-39.8 86.8 -47.31 70.099 -79 96.4C-99 113.001 -112.8 91 -112.8 91L-115.6 102.6z"/>
+ </g>
+ <g style="fill: #e87f3a">
+ <path d="M133.51 25.346C127.11 26.146 101.743 2.407 116.71 34.146C133.31 69.346 58.31 73.346 41.51 62.146C24.709 50.946 48.71 80.546 48.71 80.546C67.11 100.546 32.709 83.746 32.709 83.746C-1.691 70.946 -25.691 96.546 -28.891 97.346C-32.091 98.146 -36.891 101.346 -37.691 94.946C-38.491 88.546 -45.87 72.012 -77.691 98.146C-98.927 115.492 -112.418 94.037 -112.418 94.037L-115.618 104.146C-140.618 64.346 -125.546 122.655 -125.546 122.655C-116.745 157.056 13.509 118.146 13.509 118.146C13.509 118.146 182.31 87.746 193.51 83.746C204.71 79.746 299.038 86.073 299.038 86.073L293.51 68.764C228.71 22.364 210.31 46.146 196.71 42.146C183.11 38.146 185.51 47.746 182.31 48.546C179.11 49.346 139.91 24.546 133.51 25.346z"/>
+ </g>
+ <g style="fill: #ea8c4d">
+ <path d="M134.819 27.091C128.419 27.891 103.685 3.862 118.019 35.891C134.219 72.092 59.619 75.092 42.819 63.892C26.019 52.692 50.019 82.292 50.019 82.292C68.419 102.292 34.019 85.492 34.019 85.492C-0.381 72.692 -24.382 98.292 -27.582 99.092C-30.782 99.892 -35.582 103.092 -36.382 96.692C-37.182 90.292 -44.43 73.925 -76.382 99.892C-98.855 117.983 -112.036 97.074 -112.036 97.074L-115.636 105.692C-139.436 66.692 -124.891 125.71 -124.891 125.71C-116.091 160.11 14.819 119.892 14.819 119.892C14.819 119.892 183.619 89.492 194.819 85.492C206.019 81.492 299.474 87.746 299.474 87.746L294.02 69.928C229.219 23.528 211.619 47.891 198.019 43.891C184.419 39.891 186.819 49.491 183.619 50.292C180.419 51.092 141.219 26.291 134.819 27.091z"/>
+ </g>
+ <g style="fill: #ec9961">
+ <path d="M136.128 28.837C129.728 29.637 104.999 5.605 119.328 37.637C136.128 75.193 60.394 76.482 44.128 65.637C27.328 54.437 51.328 84.037 51.328 84.037C69.728 104.037 35.328 87.237 35.328 87.237C0.928 74.437 -23.072 100.037 -26.272 100.837C-29.472 101.637 -34.272 104.837 -35.072 98.437C-35.872 92.037 -42.989 75.839 -75.073 101.637C-98.782 120.474 -111.655 100.11 -111.655 100.11L-115.655 107.237C-137.455 70.437 -124.236 128.765 -124.236 128.765C-115.436 163.165 16.128 121.637 16.128 121.637C16.128 121.637 184.928 91.237 196.129 87.237C207.329 83.237 299.911 89.419 299.911 89.419L294.529 71.092C229.729 24.691 212.929 49.637 199.329 45.637C185.728 41.637 188.128 51.237 184.928 52.037C181.728 52.837 142.528 28.037 136.128 28.837z"/>
+ </g>
+ <g style="fill: #eea575">
+ <path d="M137.438 30.583C131.037 31.383 106.814 7.129 120.637 39.383C137.438 78.583 62.237 78.583 45.437 67.383C28.637 56.183 52.637 85.783 52.637 85.783C71.037 105.783 36.637 88.983 36.637 88.983C2.237 76.183 -21.763 101.783 -24.963 102.583C-28.163 103.383 -32.963 106.583 -33.763 100.183C-34.563 93.783 -41.548 77.752 -73.763 103.383C-98.709 122.965 -111.273 103.146 -111.273 103.146L-115.673 108.783C-135.473 73.982 -123.582 131.819 -123.582 131.819C-114.782 166.22 17.437 123.383 17.437 123.383C17.437 123.383 186.238 92.983 197.438 88.983C208.638 84.983 300.347 91.092 300.347 91.092L295.038 72.255C230.238 25.855 214.238 51.383 200.638 47.383C187.038 43.383 189.438 52.983 186.238 53.783C183.038 54.583 143.838 29.783 137.438 30.583z"/>
+ </g>
+ <g style="fill: #f1b288">
+ <path d="M138.747 32.328C132.347 33.128 106.383 9.677 121.947 41.128C141.147 79.928 63.546 80.328 46.746 69.128C29.946 57.928 53.946 87.528 53.946 87.528C72.346 107.528 37.946 90.728 37.946 90.728C3.546 77.928 -20.454 103.528 -23.654 104.328C-26.854 105.128 -31.654 108.328 -32.454 101.928C-33.254 95.528 -40.108 79.665 -72.454 105.128C-98.636 125.456 -110.891 106.183 -110.891 106.183L-115.691 110.328C-133.691 77.128 -122.927 134.874 -122.927 134.874C-114.127 169.274 18.746 125.128 18.746 125.128C18.746 125.128 187.547 94.728 198.747 90.728C209.947 86.728 300.783 92.764 300.783 92.764L295.547 73.419C230.747 27.019 215.547 53.128 201.947 49.128C188.347 45.128 190.747 54.728 187.547 55.528C184.347 56.328 145.147 31.528 138.747 32.328z"/>
+ </g>
+ <g style="fill: #f3bf9c">
+ <path d="M140.056 34.073C133.655 34.873 107.313 11.613 123.255 42.873C143.656 82.874 64.855 82.074 48.055 70.874C31.255 59.674 55.255 89.274 55.255 89.274C73.655 109.274 39.255 92.474 39.255 92.474C4.855 79.674 -19.145 105.274 -22.345 106.074C-25.545 106.874 -30.345 110.074 -31.145 103.674C-31.945 97.274 -38.668 81.578 -71.145 106.874C-98.564 127.947 -110.509 109.219 -110.509 109.219L-115.709 111.874C-131.709 81.674 -122.273 137.929 -122.273 137.929C-113.473 172.329 20.055 126.874 20.055 126.874C20.055 126.874 188.856 96.474 200.056 92.474C211.256 88.474 301.22 94.437 301.22 94.437L296.056 74.583C231.256 28.183 216.856 54.874 203.256 50.874C189.656 46.873 192.056 56.474 188.856 57.274C185.656 58.074 146.456 33.273 140.056 34.073z"/>
+ </g>
+ <g style="fill: #f5ccb0">
+ <path d="M141.365 35.819C134.965 36.619 107.523 13.944 124.565 44.619C146.565 84.219 66.164 83.819 49.364 72.619C32.564 61.419 56.564 91.019 56.564 91.019C74.964 111.019 40.564 94.219 40.564 94.219C6.164 81.419 -17.836 107.019 -21.036 107.819C-24.236 108.619 -29.036 111.819 -29.836 105.419C-30.636 99.019 -37.227 83.492 -69.836 108.619C-98.491 130.438 -110.127 112.256 -110.127 112.256L-115.727 113.419C-130.128 85.019 -121.618 140.983 -121.618 140.983C-112.818 175.384 21.364 128.619 21.364 128.619C21.364 128.619 190.165 98.219 201.365 94.219C212.565 90.219 301.656 96.11 301.656 96.11L296.565 75.746C231.765 29.346 218.165 56.619 204.565 52.619C190.965 48.619 193.365 58.219 190.165 59.019C186.965 59.819 147.765 35.019 141.365 35.819z"/>
+ </g>
+ <g style="fill: #f8d8c4">
+ <path d="M142.674 37.565C136.274 38.365 108.832 15.689 125.874 46.365C147.874 85.965 67.474 85.565 50.674 74.365C33.874 63.165 57.874 92.765 57.874 92.765C76.274 112.765 41.874 95.965 41.874 95.965C7.473 83.165 -16.527 108.765 -19.727 109.565C-22.927 110.365 -27.727 113.565 -28.527 107.165C-29.327 100.765 -35.786 85.405 -68.527 110.365C-98.418 132.929 -109.745 115.293 -109.745 115.293L-115.745 114.965C-129.346 88.564 -120.963 144.038 -120.963 144.038C-112.163 178.438 22.673 130.365 22.673 130.365C22.673 130.365 191.474 99.965 202.674 95.965C213.874 91.965 302.093 97.783 302.093 97.783L297.075 76.91C232.274 30.51 219.474 58.365 205.874 54.365C192.274 50.365 194.674 59.965 191.474 60.765C188.274 61.565 149.074 36.765 142.674 37.565z"/>
+ </g>
+ <g style="fill: #fae5d7">
+ <path d="M143.983 39.31C137.583 40.11 110.529 17.223 127.183 48.11C149.183 88.91 68.783 87.31 51.983 76.11C35.183 64.91 59.183 94.51 59.183 94.51C77.583 114.51 43.183 97.71 43.183 97.71C8.783 84.91 -15.217 110.51 -18.417 111.31C-21.618 112.11 -26.418 115.31 -27.218 108.91C-28.018 102.51 -34.346 87.318 -67.218 112.11C-98.345 135.42 -109.363 118.329 -109.363 118.329L-115.764 116.51C-128.764 92.51 -120.309 147.093 -120.309 147.093C-111.509 181.493 23.983 132.11 23.983 132.11C23.983 132.11 192.783 101.71 203.983 97.71C215.183 93.71 302.529 99.456 302.529 99.456L297.583 78.074C232.783 31.673 220.783 60.11 207.183 56.11C193.583 52.11 195.983 61.71 192.783 62.51C189.583 63.31 150.383 38.51 143.983 39.31z"/>
+ </g>
+ <g style="fill: #fcf2eb">
+ <path d="M145.292 41.055C138.892 41.855 112.917 18.411 128.492 49.855C149.692 92.656 70.092 89.056 53.292 77.856C36.492 66.656 60.492 96.256 60.492 96.256C78.892 116.256 44.492 99.456 44.492 99.456C10.092 86.656 -13.908 112.256 -17.108 113.056C-20.308 113.856 -25.108 117.056 -25.908 110.656C-26.708 104.256 -32.905 89.232 -65.908 113.856C-98.273 137.911 -108.982 121.365 -108.982 121.365L-115.782 118.056C-128.582 94.856 -119.654 150.147 -119.654 150.147C-110.854 184.547 25.292 133.856 25.292 133.856C25.292 133.856 194.093 103.456 205.293 99.456C216.493 95.456 302.965 101.128 302.965 101.128L298.093 79.237C233.292 32.837 222.093 61.856 208.493 57.856C194.893 53.855 197.293 63.456 194.093 64.256C190.892 65.056 151.692 40.255 145.292 41.055z"/>
+ </g>
+ <g style="fill: #ffffff">
+ <path d="M-115.8 119.601C-128.6 97.6 -119 153.201 -119 153.201C-110.2 187.601 26.6 135.601 26.6 135.601C26.6 135.601 195.401 105.2 206.601 101.2C217.801 97.2 303.401 102.8 303.401 102.8L298.601 80.4C233.801 34 223.401 63.6 209.801 59.6C196.201 55.6 198.601 65.2 195.401 66C192.201 66.8 153.001 42 146.601 42.8C140.201 43.6 114.981 19.793 129.801 51.6C152.028 99.307 69.041 89.227 54.6 79.6C37.8 68.4 61.8 98 61.8 98C80.2 118.001 45.8 101.2 45.8 101.2C11.4 88.4 -12.6 114.001 -15.8 114.801C-19 115.601 -23.8 118.801 -24.6 112.401C-25.4 106 -31.465 91.144 -64.6 115.601C-98.2 140.401 -108.6 124.401 -108.6 124.401L-115.8 119.601z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-74.2 149.601C-74.2 149.601 -81.4 161.201 -60.6 174.401C-60.6 174.401 -59.2 175.801 -77.2 171.601C-77.2 171.601 -83.4 169.601 -85 159.201C-85 159.201 -89.8 154.801 -94.6 149.201C-99.4 143.601 -74.2 149.601 -74.2 149.601z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M65.8 102C65.8 102 83.498 128.821 82.9 133.601C81.6 144.001 81.4 153.601 84.6 157.601C87.801 161.601 96.601 194.801 96.601 194.801C96.601 194.801 96.201 196.001 108.601 158.001C108.601 158.001 120.201 142.001 100.201 123.601C100.201 123.601 65 94.8 65.8 102z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-54.2 176.401C-54.2 176.401 -43 183.601 -57.4 214.801L-51 212.401C-51 212.401 -51.8 223.601 -55 226.001L-47.8 222.801C-47.8 222.801 -43 230.801 -47 235.601C-47 235.601 -30.2 243.601 -31 250.001C-31 250.001 -24.6 242.001 -28.6 235.601C-32.6 229.201 -39.8 233.201 -39 214.801L-47.8 218.001C-47.8 218.001 -42.2 209.201 -42.2 202.801L-50.2 205.201C-50.2 205.201 -34.731 178.623 -45.4 177.201C-51.4 176.401 -54.2 176.401 -54.2 176.401z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M-21.8 193.201C-21.8 193.201 -19 188.801 -21.8 189.601C-24.6 190.401 -55.8 205.201 -61.8 214.801C-61.8 214.801 -27.4 190.401 -21.8 193.201z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M-11.4 201.201C-11.4 201.201 -8.6 196.801 -11.4 197.601C-14.2 198.401 -45.4 213.201 -51.4 222.801C-51.4 222.801 -17 198.401 -11.4 201.201z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M1.8 186.001C1.8 186.001 4.6 181.601 1.8 182.401C-1 183.201 -32.2 198.001 -38.2 207.601C-38.2 207.601 -3.8 183.201 1.8 186.001z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M-21.4 229.601C-21.4 229.601 -21.4 223.601 -24.2 224.401C-27 225.201 -63 242.801 -69 252.401C-69 252.401 -27 226.801 -21.4 229.601z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M-20.2 218.801C-20.2 218.801 -19 214.001 -21.8 214.801C-23.8 214.801 -50.2 226.401 -56.2 236.001C-56.2 236.001 -26.6 214.401 -20.2 218.801z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M-34.6 266.401L-44.6 274.001C-44.6 274.001 -34.2 266.401 -30.6 267.601C-30.6 267.601 -37.4 278.801 -38.2 284.001C-38.2 284.001 -27.8 271.201 -22.2 271.601C-22.2 271.601 -14.6 272.001 -14.6 282.801C-14.6 282.801 -9 272.401 -5.8 272.801C-5.8 272.801 -4.6 279.201 -5.8 286.001C-5.8 286.001 -1.8 278.401 2.2 280.001C2.2 280.001 8.6 278.001 7.8 289.601C7.8 289.601 7.8 300.001 7 302.801C7 302.801 12.6 276.401 15 276.001C15 276.001 23 274.801 27.8 283.601C27.8 283.601 23.8 276.001 28.6 278.001C28.6 278.001 39.4 279.601 42.6 286.401C42.6 286.401 35.8 274.401 41.4 277.601C41.4 277.601 48.2 277.601 49.4 284.001C49.4 284.001 57.8 305.201 59.8 306.801C59.8 306.801 52.2 285.201 53.8 285.201C53.8 285.201 51.8 273.201 57 288.001C57 288.001 53.8 274.001 59.4 274.801C65 275.601 69.4 285.601 77.8 283.201C77.8 283.201 87.401 288.801 89.401 219.601L-34.6 266.401z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-29.8 173.601C-29.8 173.601 -15 167.601 25 173.601C25 173.601 32.2 174.001 39 165.201C45.8 156.401 72.6 149.201 79 151.201L88.601 157.601L89.401 158.801C89.401 158.801 101.801 169.201 102.201 176.801C102.601 184.401 87.801 232.401 78.2 248.401C68.6 264.401 59 276.801 39.8 274.401C39.8 274.401 19 270.401 -6.6 274.401C-6.6 274.401 -35.8 272.801 -38.6 264.801C-41.4 256.801 -27.4 241.601 -27.4 241.601C-27.4 241.601 -23 233.201 -24.2 218.801C-25.4 204.401 -25 176.401 -29.8 173.601z"/>
+ </g>
+ <g style="fill: #e5668c">
+ <path d="M-7.8 175.601C0.6 194.001 -29 259.201 -29 259.201C-31 260.801 -16.34 266.846 -6.2 264.401C4.746 261.763 45 266.001 45 266.001C68.6 250.401 81.4 206.001 81.4 206.001C81.4 206.001 91.801 182.001 74.2 178.801C56.6 175.601 -7.8 175.601 -7.8 175.601z"/>
+ </g>
+ <g style="fill: #b23259">
+ <path d="M-9.831 206.497C-6.505 193.707 -4.921 181.906 -7.8 175.601C-7.8 175.601 54.6 182.001 65.8 161.201C70.041 153.326 84.801 184.001 84.4 193.601C84.4 193.601 21.4 208.001 6.6 196.801L-9.831 206.497z"/>
+ </g>
+ <g style="fill: #a5264c">
+ <path d="M-5.4 222.801C-5.4 222.801 -3.4 230.001 -5.8 234.001C-5.8 234.001 -7.4 234.801 -8.6 235.201C-8.6 235.201 -7.4 238.801 -1.4 240.401C-1.4 240.401 0.6 244.801 3 245.201C5.4 245.601 10.2 251.201 14.2 250.001C18.2 248.801 29.4 244.801 29.4 244.801C29.4 244.801 35 241.601 43.8 245.201C43.8 245.201 46.175 244.399 46.6 240.401C47.1 235.701 50.2 232.001 52.2 230.001C54.2 228.001 63.8 215.201 62.6 214.801C61.4 214.401 -5.4 222.801 -5.4 222.801z"/>
+ </g>
+ <g style="fill: #ff727f; stroke:#000000">
+ <path d="M-9.8 174.401C-9.8 174.401 -12.6 196.801 -9.4 205.201C-6.2 213.601 -7 215.601 -7.8 219.601C-8.6 223.601 -4.2 233.601 1.4 239.601L13.4 241.201C13.4 241.201 28.6 237.601 37.8 240.401C37.8 240.401 46.794 241.744 50.2 226.801C50.2 226.801 55 220.401 62.2 217.601C69.4 214.801 76.6 173.201 72.6 165.201C68.6 157.201 54.2 152.801 38.2 168.401C22.2 184.001 20.2 167.201 -9.8 174.401z"/>
+ </g>
+ <g style="fill: #ffffcc; stroke:#000000; stroke-width:0.5">
+ <path d="M-8.2 249.201C-8.2 249.201 -9 247.201 -13.4 246.801C-13.4 246.801 -35.8 243.201 -44.2 230.801C-44.2 230.801 -51 225.201 -46.6 236.801C-46.6 236.801 -36.2 257.201 -29.4 260.001C-29.4 260.001 -13 264.001 -8.2 249.201z"/>
+ </g>
+ <g style="fill: #cc3f4c">
+ <path d="M71.742 185.229C72.401 177.323 74.354 168.709 72.6 165.201C66.154 152.307 49.181 157.695 38.2 168.401C22.2 184.001 20.2 167.201 -9.8 174.401C-9.8 174.401 -11.545 188.364 -10.705 198.376C-10.705 198.376 26.6 186.801 27.4 192.401C27.4 192.401 29 189.201 38.2 189.201C47.4 189.201 70.142 188.029 71.742 185.229z"/>
+ </g>
+ <g style="stroke:#a51926; stroke-width:2">
+ <path d="M28.6 175.201C28.6 175.201 33.4 180.001 29.8 189.601C29.8 189.601 15.4 205.601 17.4 219.601"/>
+ </g>
+ <g style="fill: #ffffcc; stroke:#000000; stroke-width:0.5">
+ <path d="M-19.4 260.001C-19.4 260.001 -23.8 247.201 -15 254.001C-15 254.001 -10.2 256.001 -11.4 257.601C-12.6 259.201 -18.2 263.201 -19.4 260.001z"/>
+ </g>
+ <g style="fill: #ffffcc; stroke:#000000; stroke-width:0.5">
+ <path d="M-14.36 261.201C-14.36 261.201 -17.88 250.961 -10.84 256.401C-10.84 256.401 -6.419 258.849 -7.96 259.281C-12.52 260.561 -7.96 263.121 -14.36 261.201z"/>
+ </g>
+ <g style="fill: #ffffcc; stroke:#000000; stroke-width:0.5">
+ <path d="M-9.56 261.201C-9.56 261.201 -13.08 250.961 -6.04 256.401C-6.04 256.401 -1.665 258.711 -3.16 259.281C-6.52 260.561 -3.16 263.121 -9.56 261.201z"/>
+ </g>
+ <g style="fill: #ffffcc; stroke:#000000; stroke-width:0.5">
+ <path d="M-2.96 261.401C-2.96 261.401 -6.48 251.161 0.56 256.601C0.56 256.601 4.943 258.933 3.441 259.481C0.48 260.561 3.441 263.321 -2.96 261.401z"/>
+ </g>
+ <g style="fill: #ffffcc; stroke:#000000; stroke-width:0.5">
+ <path d="M3.52 261.321C3.52 261.321 0 251.081 7.041 256.521C7.041 256.521 10.881 258.121 9.921 259.401C8.961 260.681 9.921 263.241 3.52 261.321z"/>
+ </g>
+ <g style="fill: #ffffcc; stroke:#000000; stroke-width:0.5">
+ <path d="M10.2 262.001C10.2 262.001 5.4 249.601 14.6 256.001C14.6 256.001 19.4 258.001 18.2 259.601C17 261.201 18.2 264.401 10.2 262.001z"/>
+ </g>
+ <g style="stroke:#a5264c; stroke-width:2">
+ <path d="M-18.2 244.801C-18.2 244.801 -5 242.001 1 245.201C1 245.201 7 246.401 8.2 246.001C9.4 245.601 12.6 245.201 12.6 245.201"/>
+ </g>
+ <g style="stroke:#a5264c; stroke-width:2">
+ <path d="M15.8 253.601C15.8 253.601 27.8 240.001 39.8 244.401C46.816 246.974 45.8 243.601 46.6 240.801C47.4 238.001 47.6 233.801 52.6 230.801"/>
+ </g>
+ <g style="fill: #ffffcc; stroke:#000000; stroke-width:0.5">
+ <path d="M33 237.601C33 237.601 29 226.801 26.2 239.601C23.4 252.401 20.2 256.001 18.6 258.801C18.6 258.801 18.6 264.001 27 263.601C27 263.601 37.8 263.201 38.2 260.401C38.6 257.601 37 246.001 33 237.601z"/>
+ </g>
+ <g style="stroke:#a5264c; stroke-width:2">
+ <path d="M47 244.801C47 244.801 50.6 242.401 53 243.601"/>
+ </g>
+ <g style="stroke:#a5264c; stroke-width:2">
+ <path d="M53.5 228.401C53.5 228.401 56.4 223.501 61.2 222.701"/>
+ </g>
+ <g style="fill: #b2b2b2">
+ <path d="M-25.8 265.201C-25.8 265.201 -7.8 268.401 -3.4 266.801C-3.4 266.801 5.4 266.801 -3 268.801C-3 268.801 -15.8 268.801 -23.8 267.601C-23.8 267.601 -35.4 262.001 -25.8 265.201z"/>
+ </g>
+ <g style="fill: #ffffcc; stroke:#000000; stroke-width:0.5">
+ <path d="M-11.8 172.001C-11.8 172.001 5.8 172.001 7.8 172.801C7.8 172.801 15 203.601 11.4 211.201C11.4 211.201 10.2 214.001 7.4 208.401C7.4 208.401 -11 175.601 -14.2 173.601C-17.4 171.601 -13 172.001 -11.8 172.001z"/>
+ </g>
+ <g style="fill: #ffffcc; stroke:#000000; stroke-width:0.5">
+ <path d="M-88.9 169.301C-88.9 169.301 -80 171.001 -67.4 173.601C-67.4 173.601 -62.6 196.001 -59.4 200.801C-56.2 205.601 -59.8 205.601 -63.4 202.801C-67 200.001 -81.8 186.001 -83.8 181.601C-85.8 177.201 -88.9 169.301 -88.9 169.301z"/>
+ </g>
+ <g style="fill: #ffffcc; stroke:#000000; stroke-width:0.5">
+ <path d="M-67.039 173.818C-67.039 173.818 -61.239 175.366 -60.23 177.581C-59.222 179.795 -61.432 183.092 -61.432 183.092C-61.432 183.092 -62.432 186.397 -63.634 184.235C-64.836 182.072 -67.708 174.412 -67.039 173.818z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-67 173.601C-67 173.601 -63.4 178.801 -59.8 178.801C-56.2 178.801 -55.818 178.388 -53 179.001C-48.4 180.001 -48.8 178.001 -42.2 179.201C-39.56 179.681 -37 178.801 -34.2 180.001C-31.4 181.201 -28.2 180.401 -27 178.401C-25.8 176.401 -21 172.201 -21 172.201C-21 172.201 -33.8 174.001 -36.6 174.801C-36.6 174.801 -59 176.001 -67 173.601z"/>
+ </g>
+ <g style="fill: #ffffcc; stroke:#000000; stroke-width:0.5">
+ <path d="M-22.4 173.801C-22.4 173.801 -28.85 177.301 -29.25 179.701C-29.65 182.101 -24 185.801 -24 185.801C-24 185.801 -21.25 190.401 -20.65 188.001C-20.05 185.601 -21.6 174.201 -22.4 173.801z"/>
+ </g>
+ <g style="fill: #ffffcc; stroke:#000000; stroke-width:0.5">
+ <path d="M-59.885 179.265C-59.885 179.265 -52.878 190.453 -52.661 179.242C-52.661 179.242 -52.104 177.984 -53.864 177.962C-59.939 177.886 -58.418 173.784 -59.885 179.265z"/>
+ </g>
+ <g style="fill: #ffffcc; stroke:#000000; stroke-width:0.5">
+ <path d="M-52.707 179.514C-52.707 179.514 -44.786 190.701 -45.422 179.421C-45.422 179.421 -45.415 179.089 -47.168 178.936C-51.915 178.522 -51.57 174.004 -52.707 179.514z"/>
+ </g>
+ <g style="fill: #ffffcc; stroke:#000000; stroke-width:0.5">
+ <path d="M-45.494 179.522C-45.494 179.522 -37.534 190.15 -38.203 180.484C-38.203 180.484 -38.084 179.251 -39.738 178.95C-43.63 178.244 -43.841 174.995 -45.494 179.522z"/>
+ </g>
+ <g style="fill: #ffffcc; stroke:#000000; stroke-width:0.5">
+ <path d="M-38.618 179.602C-38.618 179.602 -30.718 191.163 -30.37 181.382C-30.37 181.382 -28.726 180.004 -30.472 179.782C-36.29 179.042 -35.492 174.588 -38.618 179.602z"/>
+ </g>
+ <g style="fill: #e5e5b2">
+ <path d="M-74.792 183.132L-82.45 181.601C-85.05 176.601 -87.15 170.451 -87.15 170.451C-87.15 170.451 -80.8 171.451 -68.3 174.251C-68.3 174.251 -67.424 177.569 -65.952 183.364L-74.792 183.132z"/>
+ </g>
+ <g style="fill: #e5e5b2">
+ <path d="M-9.724 178.47C-11.39 175.964 -12.707 174.206 -13.357 173.8C-16.37 171.917 -12.227 172.294 -11.098 172.294C-11.098 172.294 5.473 172.294 7.356 173.047C7.356 173.047 7.88 175.289 8.564 178.68C8.564 178.68 -1.524 176.67 -9.724 178.47z"/>
+ </g>
+ <g style="fill: #cc7226">
+ <path d="M43.88 40.321C71.601 44.281 97.121 8.641 98.881 -1.04C100.641 -10.72 90.521 -22.6 90.521 -22.6C91.841 -25.68 87.001 -39.76 81.721 -49C76.441 -58.24 60.54 -57.266 43 -58.24C27.16 -59.12 8.68 -35.8 7.36 -34.04C6.04 -32.28 12.2 6.001 13.52 11.721C14.84 17.441 12.2 43.841 12.2 43.841C46.44 34.741 16.16 36.361 43.88 40.321z"/>
+ </g>
+ <g style="fill: #ea8e51">
+ <path d="M8.088 -33.392C6.792 -31.664 12.84 5.921 14.136 11.537C15.432 17.153 12.84 43.073 12.84 43.073C45.512 34.193 16.728 35.729 43.944 39.617C71.161 43.505 96.217 8.513 97.945 -0.992C99.673 -10.496 89.737 -22.16 89.737 -22.16C91.033 -25.184 86.281 -39.008 81.097 -48.08C75.913 -57.152 60.302 -56.195 43.08 -57.152C27.528 -58.016 9.384 -35.12 8.088 -33.392z"/>
+ </g>
+ <g style="fill: #efaa7c">
+ <path d="M8.816 -32.744C7.544 -31.048 13.48 5.841 14.752 11.353C16.024 16.865 13.48 42.305 13.48 42.305C44.884 33.145 17.296 35.097 44.008 38.913C70.721 42.729 95.313 8.385 97.009 -0.944C98.705 -10.272 88.953 -21.72 88.953 -21.72C90.225 -24.688 85.561 -38.256 80.473 -47.16C75.385 -56.064 60.063 -55.125 43.16 -56.064C27.896 -56.912 10.088 -34.44 8.816 -32.744z"/>
+ </g>
+ <g style="fill: #f4c6a8">
+ <path d="M9.544 -32.096C8.296 -30.432 14.12 5.761 15.368 11.169C16.616 16.577 14.12 41.537 14.12 41.537C43.556 32.497 17.864 34.465 44.072 38.209C70.281 41.953 94.409 8.257 96.073 -0.895C97.737 -10.048 88.169 -21.28 88.169 -21.28C89.417 -24.192 84.841 -37.504 79.849 -46.24C74.857 -54.976 59.824 -54.055 43.24 -54.976C28.264 -55.808 10.792 -33.76 9.544 -32.096z"/>
+ </g>
+ <g style="fill: #f9e2d3">
+ <path d="M10.272 -31.448C9.048 -29.816 14.76 5.681 15.984 10.985C17.208 16.289 14.76 40.769 14.76 40.769C42.628 31.849 18.432 33.833 44.136 37.505C69.841 41.177 93.505 8.129 95.137 -0.848C96.769 -9.824 87.385 -20.84 87.385 -20.84C88.609 -23.696 84.121 -36.752 79.225 -45.32C74.329 -53.888 59.585 -52.985 43.32 -53.888C28.632 -54.704 11.496 -33.08 10.272 -31.448z"/>
+ </g>
+ <g style="fill: #ffffff">
+ <path d="M44.2 36.8C69.4 40.4 92.601 8 94.201 -0.8C95.801 -9.6 86.601 -20.4 86.601 -20.4C87.801 -23.2 83.4 -36 78.6 -44.4C73.8 -52.8 59.346 -51.914 43.4 -52.8C29 -53.6 12.2 -32.4 11 -30.8C9.8 -29.2 15.4 5.6 16.6 10.8C17.8 16 15.4 40 15.4 40C40.9 31.4 19 33.2 44.2 36.8z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M90.601 2.8C90.601 2.8 62.8 10.4 51.2 8.8C51.2 8.8 35.4 2.2 26.6 24C26.6 24 23 31.2 21 33.2C19 35.2 90.601 2.8 90.601 2.8z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M94.401 0.6C94.401 0.6 65.4 12.8 55.4 12.4C55.4 12.4 39 7.8 30.6 22.4C30.6 22.4 22.2 31.6 19 33.2C19 33.2 18.6 34.8 25 30.8L35.4 36C35.4 36 50.2 45.6 59.8 29.6C59.8 29.6 63.8 18.4 63.8 16.4C63.8 14.4 85 8.8 86.601 8.4C88.201 8 94.801 3.8 94.401 0.6z"/>
+ </g>
+ <g style="fill: #99cc32">
+ <path d="M47 36.514C40.128 36.514 31.755 32.649 31.755 26.4C31.755 20.152 40.128 13.887 47 13.887C53.874 13.887 59.446 18.952 59.446 25.2C59.446 31.449 53.874 36.514 47 36.514z"/>
+ </g>
+ <g style="fill: #659900">
+ <path d="M43.377 19.83C38.531 20.552 33.442 22.055 33.514 21.839C35.054 17.22 41.415 13.887 47 13.887C51.296 13.887 55.084 15.865 57.32 18.875C57.32 18.875 52.004 18.545 43.377 19.83z"/>
+ </g>
+ <g style="fill: #ffffff">
+ <path d="M55.4 19.6C55.4 19.6 51 16.4 51 18.6C51 18.6 54.6 23 55.4 19.6z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M45.4 27.726C42.901 27.726 40.875 25.7 40.875 23.2C40.875 20.701 42.901 18.675 45.4 18.675C47.9 18.675 49.926 20.701 49.926 23.2C49.926 25.7 47.9 27.726 45.4 27.726z"/>
+ </g>
+ <g style="fill: #cc7226">
+ <path d="M-58.6 14.4C-58.6 14.4 -61.8 -6.8 -59.4 -11.2C-59.4 -11.2 -48.6 -21.2 -49 -24.8C-49 -24.8 -49.4 -42.8 -50.6 -43.6C-51.8 -44.4 -59.4 -50.4 -65.4 -44C-65.4 -44 -75.8 -26 -75 -19.6L-75 -17.6C-75 -17.6 -82.6 -18 -84.2 -16C-84.2 -16 -85.4 -10.8 -86.6 -10.4C-86.6 -10.4 -89.4 -8 -87.4 -5.2C-87.4 -5.2 -89.4 -2.8 -89 1.2L-81.4 5.2C-81.4 5.2 -79.4 19.6 -68.6 24.8C-63.764 27.129 -60.6 20.4 -58.6 14.4z"/>
+ </g>
+ <g style="fill: #ffffff">
+ <path d="M-59.6 12.56C-59.6 12.56 -62.48 -6.52 -60.32 -10.48C-60.32 -10.48 -50.6 -19.48 -50.96 -22.72C-50.96 -22.72 -51.32 -38.92 -52.4 -39.64C-53.48 -40.36 -60.32 -45.76 -65.72 -40C-65.72 -40 -75.08 -23.8 -74.36 -18.04L-74.36 -16.24C-74.36 -16.24 -81.2 -16.6 -82.64 -14.8C-82.64 -14.8 -83.72 -10.12 -84.8 -9.76C-84.8 -9.76 -87.32 -7.6 -85.52 -5.08C-85.52 -5.08 -87.32 -2.92 -86.96 0.68L-80.12 4.28C-80.12 4.28 -78.32 17.24 -68.6 21.92C-64.248 24.015 -61.4 17.96 -59.6 12.56z"/>
+ </g>
+ <g style="fill: #eb955c">
+ <path d="M-51.05 -42.61C-52.14 -43.47 -59.63 -49.24 -65.48 -43C-65.48 -43 -75.62 -25.45 -74.84 -19.21L-74.84 -17.26C-74.84 -17.26 -82.25 -17.65 -83.81 -15.7C-83.81 -15.7 -84.98 -10.63 -86.15 -10.24C-86.15 -10.24 -88.88 -7.9 -86.93 -5.17C-86.93 -5.17 -88.88 -2.83 -88.49 1.07L-81.08 4.97C-81.08 4.97 -79.13 19.01 -68.6 24.08C-63.886 26.35 -60.8 19.79 -58.85 13.94C-58.85 13.94 -61.97 -6.73 -59.63 -11.02C-59.63 -11.02 -49.1 -20.77 -49.49 -24.28C-49.49 -24.28 -49.88 -41.83 -51.05 -42.61z"/>
+ </g>
+ <g style="fill: #f2b892">
+ <path d="M-51.5 -41.62C-52.48 -42.54 -59.86 -48.08 -65.56 -42C-65.56 -42 -75.44 -24.9 -74.68 -18.82L-74.68 -16.92C-74.68 -16.92 -81.9 -17.3 -83.42 -15.4C-83.42 -15.4 -84.56 -10.46 -85.7 -10.08C-85.7 -10.08 -88.36 -7.8 -86.46 -5.14C-86.46 -5.14 -88.36 -2.86 -87.98 0.94L-80.76 4.74C-80.76 4.74 -78.86 18.42 -68.6 23.36C-64.006 25.572 -61 19.18 -59.1 13.48C-59.1 13.48 -62.14 -6.66 -59.86 -10.84C-59.86 -10.84 -49.6 -20.34 -49.98 -23.76C-49.98 -23.76 -50.36 -40.86 -51.5 -41.62z"/>
+ </g>
+ <g style="fill: #f8dcc8">
+ <path d="M-51.95 -40.63C-52.82 -41.61 -60.09 -46.92 -65.64 -41C-65.64 -41 -75.26 -24.35 -74.52 -18.43L-74.52 -16.58C-74.52 -16.58 -81.55 -16.95 -83.03 -15.1C-83.03 -15.1 -84.14 -10.29 -85.25 -9.92C-85.25 -9.92 -87.84 -7.7 -85.99 -5.11C-85.99 -5.11 -87.84 -2.89 -87.47 0.81L-80.44 4.51C-80.44 4.51 -78.59 17.83 -68.6 22.64C-64.127 24.794 -61.2 18.57 -59.35 13.02C-59.35 13.02 -62.31 -6.59 -60.09 -10.66C-60.09 -10.66 -50.1 -19.91 -50.47 -23.24C-50.47 -23.24 -50.84 -39.89 -51.95 -40.63z"/>
+ </g>
+ <g style="fill: #ffffff">
+ <path d="M-59.6 12.46C-59.6 12.46 -62.48 -6.52 -60.32 -10.48C-60.32 -10.48 -50.6 -19.48 -50.96 -22.72C-50.96 -22.72 -51.32 -38.92 -52.4 -39.64C-53.16 -40.68 -60.32 -45.76 -65.72 -40C-65.72 -40 -75.08 -23.8 -74.36 -18.04L-74.36 -16.24C-74.36 -16.24 -81.2 -16.6 -82.64 -14.8C-82.64 -14.8 -83.72 -10.12 -84.8 -9.76C-84.8 -9.76 -87.32 -7.6 -85.52 -5.08C-85.52 -5.08 -87.32 -2.92 -86.96 0.68L-80.12 4.28C-80.12 4.28 -78.32 17.24 -68.6 21.92C-64.248 24.015 -61.4 17.86 -59.6 12.46z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M-62.7 6.2C-62.7 6.2 -84.3 -4 -85.2 -4.8C-85.2 -4.8 -76.1 3.4 -75.3 3.4C-74.5 3.4 -62.7 6.2 -62.7 6.2z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-79.8 0C-79.8 0 -61.4 3.6 -61.4 8C-61.4 10.912 -61.643 24.331 -67 22.8C-75.4 20.4 -71.8 6 -79.8 0z"/>
+ </g>
+ <g style="fill: #99cc32">
+ <path d="M-71.4 3.8C-71.4 3.8 -62.422 5.274 -61.4 8C-60.8 9.6 -60.137 17.908 -65.6 19C-70.152 19.911 -72.382 9.69 -71.4 3.8z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M14.595 46.349C14.098 44.607 15.409 44.738 17.2 44.2C19.2 43.6 31.4 39.8 32.2 37.2C33 34.6 46.2 39 46.2 39C48 39.8 52.4 42.4 52.4 42.4C57.2 43.6 63.8 44 63.8 44C66.2 45 69.6 47.8 69.6 47.8C84.2 58 96.601 50.8 96.601 50.8C116.601 44.2 110.601 27 110.601 27C107.601 18 110.801 14.6 110.801 14.6C111.001 10.8 118.201 17.2 118.201 17.2C120.801 21.4 121.601 26.4 121.601 26.4C129.601 37.6 126.201 19.8 126.201 19.8C126.401 18.8 123.601 15.2 123.601 14C123.601 12.8 121.801 9.4 121.801 9.4C118.801 6 121.201 -1 121.201 -1C123.001 -14.8 120.801 -13 120.801 -13C119.601 -14.8 110.401 -4.8 110.401 -4.8C108.201 -1.4 102.201 0.2 102.201 0.2C99.401 2 96.001 0.6 96.001 0.6C93.401 0.2 87.801 7.2 87.801 7.2C90.601 7 93.001 11.4 95.401 11.6C97.801 11.8 99.601 9.2 101.201 8.6C102.801 8 105.601 13.8 105.601 13.8C106.001 16.4 100.401 21.2 100.401 21.2C100.001 25.8 98.401 24.2 98.401 24.2C95.401 23.6 94.201 27.4 93.201 32C92.201 36.6 88.001 37 88.001 37C86.401 44.4 85.2 41.4 85.2 41.4C85 35.8 79 41.6 79 41.6C77.8 43.6 73.2 41.4 73.2 41.4C66.4 39.4 68.8 37.4 68.8 37.4C70.6 35.2 81.8 37.4 81.8 37.4C84 35.8 76 31.8 76 31.8C75.4 30 76.4 25.6 76.4 25.6C77.6 22.4 84.4 16.8 84.4 16.8C93.801 15.6 91.001 14 91.001 14C84.801 8.8 79 16.4 79 16.4C76.8 22.6 59.4 37.6 59.4 37.6C54.6 41 57.2 34.2 53.2 37.6C49.2 41 28.6 32 28.6 32C17.038 30.807 14.306 46.549 10.777 43.429C10.777 43.429 16.195 51.949 14.595 46.349z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M209.401 -120C209.401 -120 183.801 -112 181.001 -93.2C181.001 -93.2 178.601 -70.4 199.001 -52.8C199.001 -52.8 199.401 -46.4 201.401 -43.2C201.401 -43.2 199.801 -38.4 218.601 -46L245.801 -54.4C245.801 -54.4 252.201 -56.8 257.401 -65.6C262.601 -74.4 277.801 -93.2 274.201 -118.4C274.201 -118.4 275.401 -129.6 269.401 -130C269.401 -130 261.001 -131.6 253.801 -124C253.801 -124 247.001 -120.8 244.601 -121.2L209.401 -120z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M264.022 -120.99C264.022 -120.99 266.122 -129.92 261.282 -125.08C261.282 -125.08 254.242 -119.36 246.761 -119.36C246.761 -119.36 232.241 -117.16 227.841 -103.96C227.841 -103.96 223.881 -77.12 231.801 -71.4C231.801 -71.4 236.641 -63.92 243.681 -70.52C250.722 -77.12 266.222 -107.35 264.022 -120.99z"/>
+ </g>
+ <g style="fill: #323232">
+ <path d="M263.648 -120.632C263.648 -120.632 265.738 -129.376 260.986 -124.624C260.986 -124.624 254.074 -119.008 246.729 -119.008C246.729 -119.008 232.473 -116.848 228.153 -103.888C228.153 -103.888 224.265 -77.536 232.041 -71.92C232.041 -71.92 236.793 -64.576 243.705 -71.056C250.618 -77.536 265.808 -107.24 263.648 -120.632z"/>
+ </g>
+ <g style="fill: #666666">
+ <path d="M263.274 -120.274C263.274 -120.274 265.354 -128.832 260.69 -124.168C260.69 -124.168 253.906 -118.656 246.697 -118.656C246.697 -118.656 232.705 -116.536 228.465 -103.816C228.465 -103.816 224.649 -77.952 232.281 -72.44C232.281 -72.44 236.945 -65.232 243.729 -71.592C250.514 -77.952 265.394 -107.13 263.274 -120.274z"/>
+ </g>
+ <g style="fill: #999999">
+ <path d="M262.9 -119.916C262.9 -119.916 264.97 -128.288 260.394 -123.712C260.394 -123.712 253.738 -118.304 246.665 -118.304C246.665 -118.304 232.937 -116.224 228.777 -103.744C228.777 -103.744 225.033 -78.368 232.521 -72.96C232.521 -72.96 237.097 -65.888 243.753 -72.128C250.41 -78.368 264.98 -107.02 262.9 -119.916z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M262.526 -119.558C262.526 -119.558 264.586 -127.744 260.098 -123.256C260.098 -123.256 253.569 -117.952 246.633 -117.952C246.633 -117.952 233.169 -115.912 229.089 -103.672C229.089 -103.672 225.417 -78.784 232.761 -73.48C232.761 -73.48 237.249 -66.544 243.777 -72.664C250.305 -78.784 264.566 -106.91 262.526 -119.558z"/>
+ </g>
+ <g style="fill: #ffffff">
+ <path d="M262.151 -119.2C262.151 -119.2 264.201 -127.2 259.801 -122.8C259.801 -122.8 253.401 -117.6 246.601 -117.6C246.601 -117.6 233.401 -115.6 229.401 -103.6C229.401 -103.6 225.801 -79.2 233.001 -74C233.001 -74 237.401 -67.2 243.801 -73.2C250.201 -79.2 264.151 -106.8 262.151 -119.2z"/>
+ </g>
+ <g style="fill: #992600">
+ <path d="M50.6 84C50.6 84 30.2 64.8 22.2 64C22.2 64 -12.2 60 -27 78C-27 78 -9.4 57.6 18.2 63.2C18.2 63.2 -3.4 58.8 -15.8 62C-15.8 62 -32.6 62 -42.2 76L-45 80.8C-45 80.8 -41 66 -22.6 60C-22.6 60 0.2 55.2 11 60C11 60 -10.6 53.2 -20.6 55.2C-20.6 55.2 -51 52.8 -63.8 79.2C-63.8 79.2 -59.8 64.8 -45 57.6C-45 57.6 -31.4 48.8 -11 51.6C-11 51.6 3.4 54.8 8.6 57.2C13.8 59.6 12.6 56.8 4.2 52C4.2 52 -1.4 42 -15.4 42.4C-15.4 42.4 -58.2 46 -68.6 58C-68.6 58 -55 46.8 -44.6 44C-44.6 44 -22.2 36 -13.8 36.8C-13.8 36.8 11 37.8 18.6 33.8C18.6 33.8 7.4 38.8 10.6 42C13.8 45.2 20.6 52.8 20.6 54C20.6 55.2 44.8 77.3 48.4 81.7L50.6 84z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M189 278C189 278 173.5 241.5 161 232C161 232 187 248 190.5 266C190.5 266 190.5 276 189 278z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M236 285.5C236 285.5 209.5 230.5 191 206.5C191 206.5 234.5 244 239.5 270.5L240 276L237 273.5C237 273.5 236.5 282.5 236 285.5z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M292.5 237C292.5 237 230 177.5 228.5 175C228.5 175 289 241 292 248.5C292 248.5 290 239.5 292.5 237z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M104 280.5C104 280.5 123.5 228.5 142.5 251C142.5 251 157.5 261 157 264C157 264 153 257.5 135 258C135 258 116 255 104 280.5z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M294.5 153C294.5 153 249.5 124.5 242 123C230.193 120.639 291.5 152 296.5 162.5C296.5 162.5 298.5 160 294.5 153z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M143.801 259.601C143.801 259.601 164.201 257.601 171.001 250.801L175.401 254.401L193.001 216.001L196.601 221.201C196.601 221.201 211.001 206.401 210.201 198.401C209.401 190.401 223.001 204.401 223.001 204.401C223.001 204.401 222.201 192.801 229.401 199.601C229.401 199.601 227.001 184.001 235.401 192.001C235.401 192.001 224.864 161.844 247.401 187.601C253.001 194.001 248.601 187.201 248.601 187.201C248.601 187.201 222.601 139.201 244.201 153.601C244.201 153.601 246.201 130.801 245.001 126.401C243.801 122.001 241.801 99.6 237.001 94.4C232.201 89.2 237.401 87.6 243.001 92.8C243.001 92.8 231.801 68.8 245.001 80.8C245.001 80.8 241.401 65.6 237.001 62.8C237.001 62.8 231.401 45.6 246.601 56.4C246.601 56.4 242.201 44 239.001 40.8C239.001 40.8 227.401 13.2 234.601 18L239.001 21.6C239.001 21.6 232.201 7.6 238.601 12C245.001 16.4 245.001 16 245.001 16C245.001 16 223.801 -17.2 244.201 0.4C244.201 0.4 236.042 -13.518 232.601 -20.4C232.601 -20.4 213.801 -40.8 228.201 -34.4L233.001 -32.8C233.001 -32.8 224.201 -42.8 216.201 -44.4C208.201 -46 218.601 -52.4 225.001 -50.4C231.401 -48.4 247.001 -40.8 247.001 -40.8C247.001 -40.8 259.801 -22 263.801 -21.6C263.801 -21.6 243.801 -29.2 249.801 -21.2C249.801 -21.2 264.201 -7.2 257.001 -7.6C257.001 -7.6 251.001 -0.4 255.801 8.4C255.801 8.4 237.342 -9.991 252.201 15.6L259.001 32C259.001 32 234.601 7.2 245.801 29.2C245.801 29.2 263.001 52.8 265.001 53.2C267.001 53.6 271.401 62.4 271.401 62.4L267.001 60.4L272.201 69.2C272.201 69.2 261.001 57.2 267.001 70.4L272.601 84.8C272.601 84.8 252.201 62.8 265.801 92.4C265.801 92.4 249.401 87.2 258.201 104.4C258.201 104.4 256.601 120.401 257.001 125.601C257.401 130.801 258.601 159.201 254.201 167.201C249.801 175.201 260.201 194.401 262.201 198.401C264.201 202.401 267.801 213.201 259.001 204.001C250.201 194.801 254.601 200.401 256.601 209.201C258.601 218.001 264.601 233.601 263.801 239.201C263.801 239.201 262.601 240.401 259.401 236.801C259.401 236.801 244.601 214.001 246.201 228.401C246.201 228.401 245.001 236.401 241.801 245.201C241.801 245.201 238.601 256.001 238.601 247.201C238.601 247.201 235.401 230.401 232.601 238.001C229.801 245.601 226.201 251.601 223.401 254.001C220.601 256.401 215.401 233.601 214.201 244.001C214.201 244.001 202.201 231.601 197.401 248.001L185.801 264.401C185.801 264.401 185.401 252.001 184.201 258.001C184.201 258.001 154.201 264.001 143.801 259.601z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M109.401 -97.2C109.401 -97.2 97.801 -105.2 93.801 -104.8C89.801 -104.4 121.401 -113.6 162.601 -86C162.601 -86 167.401 -83.2 171.001 -83.6C171.001 -83.6 174.201 -81.2 171.401 -77.6C171.401 -77.6 162.601 -68 173.801 -56.8C173.801 -56.8 192.201 -50 186.601 -58.8C186.601 -58.8 197.401 -54.8 199.801 -50.8C202.201 -46.8 201.001 -50.8 201.001 -50.8C201.001 -50.8 194.601 -58 188.601 -63.2C188.601 -63.2 183.401 -65.2 180.601 -73.6C177.801 -82 175.401 -92 179.801 -95.2C179.801 -95.2 175.801 -90.8 176.601 -94.8C177.401 -98.8 181.001 -102.4 182.601 -102.8C184.201 -103.2 200.601 -119 207.401 -119.4C207.401 -119.4 198.201 -118 195.201 -119C192.201 -120 165.601 -131.4 159.601 -132.6C159.601 -132.6 142.801 -139.2 154.801 -137.2C154.801 -137.2 190.601 -133.4 208.801 -120.2C208.801 -120.2 201.601 -128.6 183.201 -135.6C183.201 -135.6 161.001 -148.2 125.801 -143.2C125.801 -143.2 108.001 -140 100.201 -138.2C100.201 -138.2 97.601 -138.8 97.001 -139.2C96.401 -139.6 84.6 -148.6 57 -141.6C57 -141.6 40 -137 31.4 -132.2C31.4 -132.2 16.2 -131 12.6 -127.8C12.6 -127.8 -6 -113.2 -8 -112.4C-10 -111.6 -21.4 -104 -22.2 -103.6C-22.2 -103.6 2.4 -110.2 4.8 -112.6C7.2 -115 24.6 -117.6 27 -116.2C29.4 -114.8 37.8 -115.4 28.2 -114.8C28.2 -114.8 103.801 -100 104.601 -98C105.401 -96 109.401 -97.2 109.401 -97.2z"/>
+ </g>
+ <g style="fill: #cc7226">
+ <path d="M180.801 -106.4C180.801 -106.4 170.601 -113.8 168.601 -113.8C166.601 -113.8 154.201 -124 150.001 -123.6C145.801 -123.2 133.601 -133.2 106.201 -125C106.201 -125 105.601 -127 109.201 -127.8C109.201 -127.8 115.601 -130 116.001 -130.6C116.001 -130.6 136.201 -134.8 143.401 -131.2C143.401 -131.2 152.601 -128.6 158.801 -122.4C158.801 -122.4 170.001 -119.2 173.201 -120.2C173.201 -120.2 182.001 -118 182.401 -116.2C182.401 -116.2 188.201 -113.2 186.401 -110.6C186.401 -110.6 186.801 -109 180.801 -106.4z"/>
+ </g>
+ <g style="fill: #cc7226">
+ <path d="M168.33 -108.509C169.137 -107.877 170.156 -107.779 170.761 -106.97C170.995 -106.656 170.706 -106.33 170.391 -106.233C169.348 -105.916 168.292 -106.486 167.15 -105.898C166.748 -105.691 166.106 -105.873 165.553 -106.022C163.921 -106.463 162.092 -106.488 160.401 -105.8C158.416 -106.929 156.056 -106.345 153.975 -107.346C153.917 -107.373 153.695 -107.027 153.621 -107.054C150.575 -108.199 146.832 -107.916 144.401 -110.2C141.973 -110.612 139.616 -111.074 137.188 -111.754C135.37 -112.263 133.961 -113.252 132.341 -114.084C130.964 -114.792 129.507 -115.314 127.973 -115.686C126.11 -116.138 124.279 -116.026 122.386 -116.546C122.293 -116.571 122.101 -116.227 122.019 -116.254C121.695 -116.362 121.405 -116.945 121.234 -116.892C119.553 -116.37 118.065 -117.342 116.401 -117C115.223 -118.224 113.495 -117.979 111.949 -118.421C108.985 -119.269 105.831 -117.999 102.801 -119C106.914 -120.842 111.601 -119.61 115.663 -121.679C117.991 -122.865 120.653 -121.763 123.223 -122.523C123.71 -122.667 124.401 -122.869 124.801 -122.2C124.935 -122.335 125.117 -122.574 125.175 -122.546C127.625 -121.389 129.94 -120.115 132.422 -119.049C132.763 -118.903 133.295 -119.135 133.547 -118.933C135.067 -117.717 137.01 -117.82 138.401 -116.6C140.099 -117.102 141.892 -116.722 143.621 -117.346C143.698 -117.373 143.932 -117.032 143.965 -117.054C145.095 -117.802 146.25 -117.531 147.142 -117.227C147.48 -117.112 148.143 -116.865 148.448 -116.791C149.574 -116.515 150.43 -116.035 151.609 -115.852C151.723 -115.834 151.908 -116.174 151.98 -116.146C153.103 -115.708 154.145 -115.764 154.801 -114.6C154.936 -114.735 155.101 -114.973 155.183 -114.946C156.21 -114.608 156.859 -113.853 157.96 -113.612C158.445 -113.506 159.057 -112.88 159.633 -112.704C162.025 -111.973 163.868 -110.444 166.062 -109.549C166.821 -109.239 167.697 -109.005 168.33 -108.509z"/>
+ </g>
+ <g style="fill: #cc7226">
+ <path d="M91.696 -122.739C89.178 -124.464 86.81 -125.57 84.368 -127.356C84.187 -127.489 83.827 -127.319 83.625 -127.441C82.618 -128.05 81.73 -128.631 80.748 -129.327C80.209 -129.709 79.388 -129.698 78.88 -129.956C76.336 -131.248 73.707 -131.806 71.2 -133C71.882 -133.638 73.004 -133.394 73.6 -134.2C73.795 -133.92 74.033 -133.636 74.386 -133.827C76.064 -134.731 77.914 -134.884 79.59 -134.794C81.294 -134.702 83.014 -134.397 84.789 -134.125C85.096 -134.078 85.295 -133.555 85.618 -133.458C87.846 -132.795 90.235 -133.32 92.354 -132.482C93.945 -131.853 95.515 -131.03 96.754 -129.755C97.006 -129.495 96.681 -129.194 96.401 -129C96.789 -129.109 97.062 -128.903 97.173 -128.59C97.257 -128.351 97.257 -128.049 97.173 -127.81C97.061 -127.498 96.782 -127.397 96.408 -127.346C95.001 -127.156 96.773 -128.536 96.073 -128.088C94.8 -127.274 95.546 -125.868 94.801 -124.6C94.521 -124.794 94.291 -125.012 94.401 -125.4C94.635 -124.878 94.033 -124.588 93.865 -124.272C93.48 -123.547 92.581 -122.132 91.696 -122.739z"/>
+ </g>
+ <g style="fill: #cc7226">
+ <path d="M59.198 -115.391C56.044 -116.185 52.994 -116.07 49.978 -117.346C49.911 -117.374 49.688 -117.027 49.624 -117.054C48.258 -117.648 47.34 -118.614 46.264 -119.66C45.351 -120.548 43.693 -120.161 42.419 -120.648C42.095 -120.772 41.892 -121.284 41.591 -121.323C40.372 -121.48 39.445 -122.429 38.4 -123C40.736 -123.795 43.147 -123.764 45.609 -124.148C45.722 -124.166 45.867 -123.845 46 -123.845C46.136 -123.845 46.266 -124.066 46.4 -124.2C46.595 -123.92 46.897 -123.594 47.154 -123.848C47.702 -124.388 48.258 -124.198 48.798 -124.158C48.942 -124.148 49.067 -123.845 49.2 -123.845C49.336 -123.845 49.467 -124.156 49.6 -124.156C49.736 -124.155 49.867 -123.845 50 -123.845C50.136 -123.845 50.266 -124.066 50.4 -124.2C51.092 -123.418 51.977 -123.972 52.799 -123.793C53.837 -123.566 54.104 -122.418 55.178 -122.12C59.893 -120.816 64.03 -118.671 68.393 -116.584C68.7 -116.437 68.91 -116.189 68.8 -115.8C69.067 -115.8 69.38 -115.888 69.57 -115.756C70.628 -115.024 71.669 -114.476 72.366 -113.378C72.582 -113.039 72.253 -112.632 72.02 -112.684C67.591 -113.679 63.585 -114.287 59.198 -115.391z"/>
+ </g>
+ <g style="fill: #cc7226">
+ <path d="M45.338 -71.179C43.746 -72.398 43.162 -74.429 42.034 -76.221C41.82 -76.561 42.094 -76.875 42.411 -76.964C42.971 -77.123 43.514 -76.645 43.923 -76.443C45.668 -75.581 47.203 -74.339 49.2 -74.2C51.19 -71.966 55.45 -71.581 55.457 -68.2C55.458 -67.341 54.03 -68.259 53.6 -67.4C51.149 -68.403 48.76 -68.3 46.38 -69.767C45.763 -70.148 46.093 -70.601 45.338 -71.179z"/>
+ </g>
+ <g style="fill: #cc7226">
+ <path d="M17.8 -123.756C17.935 -123.755 24.966 -123.522 24.949 -123.408C24.904 -123.099 17.174 -122.05 16.81 -122.22C16.646 -122.296 9.134 -119.866 9 -120C9.268 -120.135 17.534 -123.756 17.8 -123.756z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M33.2 -114C33.2 -114 18.4 -112.2 14 -111C9.6 -109.8 -9 -102.2 -12 -100.2C-12 -100.2 -25.4 -94.8 -42.4 -74.8C-42.4 -74.8 -34.8 -78.2 -32.6 -81C-32.6 -81 -19 -93.6 -19.2 -91C-19.2 -91 -7 -99.6 -7.6 -97.4C-7.6 -97.4 16.8 -108.6 14.8 -105.4C14.8 -105.4 36.4 -110 35.4 -108C35.4 -108 54.2 -103.6 51.4 -103.4C51.4 -103.4 45.6 -102.2 52 -98.6C52 -98.6 48.6 -94.2 43.2 -98.2C37.8 -102.2 40.8 -100 35.8 -99C35.8 -99 33.2 -98.2 28.6 -102.2C28.6 -102.2 23 -106.8 14.2 -103.2C14.2 -103.2 -16.4 -90.6 -18.4 -90C-18.4 -90 -22 -87.2 -24.4 -83.6C-24.4 -83.6 -30.2 -79.2 -33.2 -77.8C-33.2 -77.8 -46 -66.2 -47.2 -64.8C-47.2 -64.8 -50.6 -59.6 -51.4 -59.2C-51.4 -59.2 -45 -63 -43 -65C-43 -65 -29 -75 -23.6 -75.8C-23.6 -75.8 -19.2 -78.8 -18.4 -80.2C-18.4 -80.2 -4 -89.4 0.2 -89.4C0.2 -89.4 9.4 -84.2 11.8 -91.2C11.8 -91.2 17.6 -93 23.2 -91.8C23.2 -91.8 26.4 -94.4 25.6 -96.6C25.6 -96.6 27.2 -98.4 28.2 -94.6C28.2 -94.6 31.6 -91 36.4 -93C36.4 -93 40.4 -93.2 38.4 -90.8C38.4 -90.8 34 -87 22.2 -86.8C22.2 -86.8 9.8 -86.2 -6.6 -78.6C-6.6 -78.6 -36.4 -68.2 -45.6 -57.8C-45.6 -57.8 -52 -49 -57.4 -47.8C-57.4 -47.8 -63.2 -47 -69.2 -39.6C-69.2 -39.6 -59.4 -45.4 -50.4 -45.4C-50.4 -45.4 -46.4 -47.8 -50.2 -44.2C-50.2 -44.2 -53.8 -36.6 -52.2 -31.2C-52.2 -31.2 -52.8 -26 -53.6 -24.4C-53.6 -24.4 -61.4 -11.6 -61.4 -9.2C-61.4 -6.8 -60.2 3 -59.8 3.6C-59.4 4.2 -60.8 2 -57 4.4C-53.2 6.8 -50.4 8.4 -49.6 11.2C-48.8 14 -51.6 5.8 -51.8 4C-52 2.2 -56.2 -5 -55.4 -7.4C-55.4 -7.4 -54.4 -6.4 -53.6 -5C-53.6 -5 -54.2 -5.6 -53.6 -9.2C-53.6 -9.2 -52.8 -14.4 -51.4 -17.6C-50 -20.8 -48 -24.6 -47.6 -25.4C-47.2 -26.2 -47.2 -32 -45.8 -29.4L-42.4 -26.8C-42.4 -26.8 -45.2 -29.4 -43 -31.6C-43 -31.6 -44 -37.2 -42.2 -39.8C-42.2 -39.8 -35.2 -48.2 -33.6 -49.2C-32 -50.2 -33.4 -49.8 -33.4 -49.8C-33.4 -49.8 -27.4 -54 -33.2 -52.4C-33.2 -52.4 -37.2 -50.8 -40.2 -50.8C-40.2 -50.8 -47.8 -48.8 -43.8 -53C-39.8 -57.2 -29.8 -62.6 -26 -62.4L-25.2 -60.8L-14 -63.2L-15.2 -62.4C-15.2 -62.4 -15.4 -62.6 -11.2 -63C-7 -63.4 -1.2 -62 0.2 -63.8C1.6 -65.6 5 -66.6 4.6 -65.2C4.2 -63.8 4 -61.8 4 -61.8C4 -61.8 9 -67.6 8.4 -65.4C7.8 -63.2 -0.4 -58 -1.8 -51.8L8.6 -60L12.2 -63C12.2 -63 15.8 -60.8 16 -62.4C16.2 -64 20.8 -69.8 22 -69.6C23.2 -69.4 25.2 -72.2 25 -69.6C24.8 -67 32.4 -61.6 32.4 -61.6C32.4 -61.6 35.6 -63.4 37 -62C38.4 -60.6 42.6 -81.8 42.6 -81.8L67.6 -92.4L111.201 -95.8L94.201 -102.6L33.2 -114z"/>
+ </g>
+ <g style="stroke:#4c0000; stroke-width:2">
+ <path d="M51.4 85C51.4 85 36.4 68.2 28 65.6C28 65.6 14.6 58.8 -10 66.6"/>
+ </g>
+ <g style="stroke:#4c0000; stroke-width:2">
+ <path d="M24.8 64.2C24.8 64.2 -0.4 56.2 -15.8 60.4C-15.8 60.4 -34.2 62.4 -42.6 76.2"/>
+ </g>
+ <g style="stroke:#4c0000; stroke-width:2">
+ <path d="M21.2 63C21.2 63 4.2 55.8 -10.6 53.6C-10.6 53.6 -27.2 51 -43.8 58.2C-43.8 58.2 -56 64.2 -61.4 74.4"/>
+ </g>
+ <g style="stroke:#4c0000; stroke-width:2">
+ <path d="M22.2 63.4C22.2 63.4 6.8 52.4 5.8 51C5.8 51 -1.2 40 -14.2 39.6C-14.2 39.6 -35.6 40.4 -52.8 48.4"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M20.895 54.407C22.437 55.87 49.4 84.8 49.4 84.8C84.6 121.401 56.6 87.2 56.6 87.2C49 82.4 39.8 63.6 39.8 63.6C38.6 60.8 53.8 70.8 53.8 70.8C57.8 71.6 71.4 90.8 71.4 90.8C64.6 88.4 69.4 95.6 69.4 95.6C72.2 97.6 92.601 113.201 92.601 113.201C96.201 117.201 100.201 118.801 100.201 118.801C114.201 113.601 107.801 126.801 107.801 126.801C110.201 133.601 115.801 122.001 115.801 122.001C127.001 105.2 110.601 107.601 110.601 107.601C80.6 110.401 73.8 94.4 73.8 94.4C71.4 92 80.2 94.4 80.2 94.4C88.601 96.4 73 82 73 82C75.4 82 84.6 88.8 84.6 88.8C95.001 98 97.001 96 97.001 96C115.001 87.2 125.401 94.8 125.401 94.8C127.401 96.4 121.801 103.2 123.401 108.401C125.001 113.601 129.801 126.001 129.801 126.001C127.401 127.601 127.801 138.401 127.801 138.401C144.601 161.601 135.001 159.601 135.001 159.601C119.401 159.201 134.201 166.801 134.201 166.801C137.401 168.801 146.201 176.001 146.201 176.001C143.401 174.801 141.801 180.001 141.801 180.001C146.601 184.001 143.801 188.801 143.801 188.801C137.801 190.001 136.601 194.001 136.601 194.001C143.401 202.001 133.401 202.401 133.401 202.401C137.001 206.801 132.201 218.801 132.201 218.801C127.401 218.801 121.001 224.401 121.001 224.401C123.401 229.201 113.001 234.801 113.001 234.801C104.601 236.401 107.401 243.201 107.401 243.201C99.401 249.201 97.001 265.201 97.001 265.201C96.201 275.601 93.801 278.801 99.001 276.801C104.201 274.801 103.401 262.401 103.401 262.401C98.601 246.801 141.401 230.801 141.401 230.801C145.401 229.201 146.201 224.001 146.201 224.001C148.201 224.401 157.001 232.001 157.001 232.001C164.601 243.201 165.001 234.001 165.001 234.001C166.201 230.401 164.601 224.401 164.601 224.401C170.601 202.801 156.601 196.401 156.601 196.401C146.601 162.801 160.601 171.201 160.601 171.201C163.401 176.801 174.201 182.001 174.201 182.001L177.801 179.601C176.201 174.801 184.601 168.801 184.601 168.801C187.401 175.201 193.401 167.201 193.401 167.201C197.001 142.801 209.401 157.201 209.401 157.201C213.401 158.401 214.601 151.601 214.601 151.601C218.201 141.201 214.601 127.601 214.601 127.601C218.201 127.201 227.801 133.201 227.801 133.201C230.601 129.601 221.401 112.801 225.401 115.201C229.401 117.601 233.801 119.201 233.801 119.201C234.601 117.201 224.601 104.801 224.601 104.801C220.201 102 215.001 81.6 215.001 81.6C222.201 85.2 212.201 70 212.201 70C212.201 66.8 218.201 55.6 218.201 55.6C217.401 48.8 218.201 49.2 218.201 49.2C221.001 50.4 229.001 52 222.201 45.6C215.401 39.2 223.001 34.4 223.001 34.4C227.401 31.6 213.801 32 213.801 32C208.601 27.6 209.001 23.6 209.001 23.6C217.001 25.6 202.601 11.2 200.201 7.6C197.801 4 207.401 -1.2 207.401 -1.2C220.601 -4.8 209.001 -8 209.001 -8C189.401 -7.6 200.201 -18.4 200.201 -18.4C206.201 -18 204.601 -20.4 204.601 -20.4C199.401 -21.6 189.801 -28 189.801 -28C185.801 -31.6 189.401 -30.8 189.401 -30.8C206.201 -29.6 177.401 -40.8 177.401 -40.8C185.401 -40.8 167.401 -51.2 167.401 -51.2C165.401 -52.8 162.201 -60.4 162.201 -60.4C156.201 -65.6 151.401 -72.4 151.401 -72.4C151.001 -76.8 146.201 -81.6 146.201 -81.6C134.601 -95.2 129.001 -94.8 129.001 -94.8C114.201 -98.4 109.001 -97.6 109.001 -97.6L56.2 -93.2C29.8 -80.4 37.6 -59.4 37.6 -59.4C44 -51 53.2 -54.8 53.2 -54.8C57.8 -61 69.4 -58.8 69.4 -58.8C89.801 -55.6 87.201 -59.2 87.201 -59.2C84.801 -63.8 68.6 -70 68.4 -70.6C68.2 -71.2 59.4 -74.6 59.4 -74.6C56.4 -75.8 52 -85 52 -85C48.8 -88.4 64.6 -82.6 64.6 -82.6C63.4 -81.6 70.8 -77.6 70.8 -77.6C88.201 -78.6 98.801 -67.8 98.801 -67.8C109.601 -51.2 109.801 -59.4 109.801 -59.4C112.601 -68.8 100.801 -90 100.801 -90C101.201 -92 109.401 -85.4 109.401 -85.4C110.801 -87.4 111.601 -81.6 111.601 -81.6C111.801 -79.2 115.601 -71.2 115.601 -71.2C118.401 -58.2 122.001 -65.6 122.001 -65.6L126.601 -56.2C128.001 -53.6 122.001 -46 122.001 -46C121.801 -43.2 122.601 -43.4 117.001 -35.8C111.401 -28.2 114.801 -23.8 114.801 -23.8C113.401 -17.2 122.201 -17.6 122.201 -17.6C124.801 -15.4 128.201 -15.4 128.201 -15.4C130.001 -13.4 132.401 -14 132.401 -14C134.001 -17.8 140.201 -15.8 140.201 -15.8C141.601 -18.2 149.801 -18.6 149.801 -18.6C150.801 -21.2 151.201 -22.8 154.601 -23.4C158.001 -24 133.401 -67 133.401 -67C139.801 -67.8 131.601 -80.2 131.601 -80.2C129.401 -86.8 140.801 -72.2 143.001 -70.8C145.201 -69.4 146.201 -67.2 144.601 -67.4C143.001 -67.6 141.201 -65.4 142.601 -65.2C144.001 -65 157.001 -50 160.401 -39.8C163.801 -29.6 169.801 -25.6 176.001 -19.6C182.201 -13.6 181.401 10.6 181.401 10.6C181.001 19.4 187.001 30 187.001 30C189.001 33.8 184.801 52 184.801 52C182.801 54.2 184.201 55 184.201 55C185.201 56.2 192.001 69.4 192.001 69.4C190.201 69.2 193.801 72.8 193.801 72.8C199.001 78.8 192.601 75.8 192.601 75.8C186.601 74.2 193.601 84 193.601 84C194.801 85.8 185.801 81.2 185.801 81.2C176.601 80.6 188.201 87.8 188.201 87.8C196.801 95 185.401 90.6 185.401 90.6C180.801 88.8 184.001 95.6 184.001 95.6C187.201 97.2 204.401 104.2 204.401 104.2C204.801 108.001 201.801 113.001 201.801 113.001C202.201 117.001 200.001 120.401 200.001 120.401C198.801 128.601 198.201 129.401 198.201 129.401C194.001 129.601 186.601 143.401 186.601 143.401C184.801 146.001 174.601 158.001 174.601 158.001C172.601 165.001 154.601 157.801 154.601 157.801C148.001 161.201 150.001 157.801 150.001 157.801C149.601 155.601 154.401 149.601 154.401 149.601C161.401 147.001 158.801 136.201 158.801 136.201C162.801 134.801 151.601 132.001 151.801 130.801C152.001 129.601 157.801 128.201 157.801 128.201C165.801 126.201 161.401 123.801 161.401 123.801C160.801 119.801 163.801 114.201 163.801 114.201C175.401 113.401 163.801 97.2 163.801 97.2C153.001 89.6 152.001 83.8 152.001 83.8C164.601 75.6 156.401 63.2 156.601 59.6C156.801 56 158.001 34.4 158.001 34.4C156.001 28.2 153.001 14.6 153.001 14.6C155.201 9.4 162.601 -3.2 162.601 -3.2C165.401 -7.4 174.201 -12.2 172.001 -15.2C169.801 -18.2 162.001 -16.4 162.001 -16.4C154.201 -17.8 154.801 -12.6 154.801 -12.6C153.201 -11.6 152.401 -6.6 152.401 -6.6C151.68 1.333 142.801 7.6 142.801 7.6C131.601 13.8 140.801 17.8 140.801 17.8C146.801 24.4 137.001 24.6 137.001 24.6C126.001 22.8 134.201 33 134.201 33C145.001 45.8 142.001 48.6 142.001 48.6C131.801 49.6 144.401 58.8 144.401 58.8C144.401 58.8 143.601 56.8 143.801 58.6C144.001 60.4 147.001 64.6 147.801 66.6C148.601 68.6 144.601 68.8 144.601 68.8C145.201 78.4 129.801 74.2 129.801 74.2C129.801 74.2 129.801 74.2 128.201 74.4C126.601 74.6 115.401 73.8 109.601 71.6C103.801 69.4 97.001 69.4 97.001 69.4C97.001 69.4 93.001 71.2 85.4 71C77.8 70.8 69.8 73.6 69.8 73.6C65.4 73.2 74 68.8 74.2 69C74.4 69.2 80 63.6 72 64.2C50.203 65.835 39.4 55.6 39.4 55.6C37.4 54.2 34.8 51.4 34.8 51.4C24.8 49.4 36.2 63.8 36.2 63.8C37.4 65.2 36 66.2 36 66.2C35.2 64.6 27.4 59.2 27.4 59.2C24.589 58.227 23.226 56.893 20.895 54.407z"/>
+ </g>
+ <g style="fill: #4c0000">
+ <path d="M-3 42.8C-3 42.8 8.6 48.4 11.2 51.2C13.8 54 27.8 65.4 27.8 65.4C27.8 65.4 22.4 63.4 19.8 61.6C17.2 59.8 6.4 51.6 6.4 51.6C6.4 51.6 2.6 45.6 -3 42.8z"/>
+ </g>
+ <g style="fill: #99cc32">
+ <path d="M-61.009 11.603C-60.672 11.455 -61.196 8.743 -61.4 8.2C-62.422 5.474 -71.4 4 -71.4 4C-71.627 5.365 -71.682 6.961 -71.576 8.599C-71.576 8.599 -66.708 14.118 -61.009 11.603z"/>
+ </g>
+ <g style="fill: #659900">
+ <path d="M-61.009 11.403C-61.458 11.561 -61.024 8.669 -61.2 8.2C-62.222 5.474 -71.4 3.9 -71.4 3.9C-71.627 5.265 -71.682 6.861 -71.576 8.499C-71.576 8.499 -67.308 13.618 -61.009 11.403z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-65.4 11.546C-66.025 11.546 -66.531 10.406 -66.531 9C-66.531 7.595 -66.025 6.455 -65.4 6.455C-64.775 6.455 -64.268 7.595 -64.268 9C-64.268 10.406 -64.775 11.546 -65.4 11.546z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-65.4 9z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-111 109.601C-111 109.601 -116.6 119.601 -91.8 113.601C-91.8 113.601 -77.8 112.401 -75.4 110.001C-74.2 110.801 -65.834 113.734 -63 114.401C-56.2 116.001 -47.8 106 -47.8 106C-47.8 106 -43.2 95.5 -40.4 95.5C-37.6 95.5 -40.8 97.1 -40.8 97.1C-40.8 97.1 -47.4 107.201 -47 108.801C-47 108.801 -52.2 128.801 -68.2 129.601C-68.2 129.601 -84.35 130.551 -83 136.401C-83 136.401 -74.2 134.001 -71.8 136.401C-71.8 136.401 -61 136.001 -69 142.401L-75.8 154.001C-75.8 154.001 -75.66 157.919 -85.8 154.401C-95.6 151.001 -105.9 138.101 -105.9 138.101C-105.9 138.101 -121.85 123.551 -111 109.601z"/>
+ </g>
+ <g style="fill: #e59999">
+ <path d="M-112.2 113.601C-112.2 113.601 -114.2 123.201 -77.4 112.801C-77.4 112.801 -73 112.801 -70.6 113.601C-68.2 114.401 -56.2 117.201 -54.2 116.001C-54.2 116.001 -61.4 129.601 -73 128.001C-73 128.001 -86.2 129.601 -85.8 134.401C-85.8 134.401 -81.8 141.601 -77 144.001C-77 144.001 -74.2 146.401 -74.6 149.601C-75 152.801 -77.8 154.401 -79.8 155.201C-81.8 156.001 -85 152.801 -86.6 152.801C-88.2 152.801 -96.6 146.401 -101 141.601C-105.4 136.801 -113.8 124.801 -113.4 122.001C-113 119.201 -112.2 113.601 -112.2 113.601z"/>
+ </g>
+ <g style="fill: #b26565">
+ <path d="M-109 131.051C-106.4 135.001 -103.2 139.201 -101 141.601C-96.6 146.401 -88.2 152.801 -86.6 152.801C-85 152.801 -81.8 156.001 -79.8 155.201C-77.8 154.401 -75 152.801 -74.6 149.601C-74.2 146.401 -77 144.001 -77 144.001C-80.066 142.468 -82.806 138.976 -84.385 136.653C-84.385 136.653 -84.2 139.201 -89.4 138.401C-94.6 137.601 -99.8 134.801 -101.4 131.601C-103 128.401 -105.4 126.001 -103.8 129.601C-102.2 133.201 -99.8 136.801 -98.2 137.201C-96.6 137.601 -97 138.801 -99.4 138.401C-101.8 138.001 -104.6 137.601 -109 132.401z"/>
+ </g>
+ <g style="fill: #992600">
+ <path d="M-111.6 110.001C-111.6 110.001 -109.8 96.4 -108.6 92.4C-108.6 92.4 -109.4 85.6 -107 81.4C-104.6 77.2 -102.6 71 -99.6 65.6C-96.6 60.2 -96.4 56.2 -92.4 54.6C-88.4 53 -82.4 44.4 -79.6 43.4C-76.8 42.4 -77 43.2 -77 43.2C-77 43.2 -70.2 28.4 -56.6 32.4C-56.6 32.4 -72.8 29.6 -57 20.2C-57 20.2 -61.8 21.3 -58.5 14.3C-56.299 9.632 -56.8 16.4 -67.8 28.2C-67.8 28.2 -72.8 36.8 -78 39.8C-83.2 42.8 -95.2 49.8 -96.4 53.6C-97.6 57.4 -100.8 63.2 -102.8 64.8C-104.8 66.4 -107.6 70.6 -108 74C-108 74 -109.2 78 -110.6 79.2C-112 80.4 -112.2 83.6 -112.2 85.6C-112.2 87.6 -114.2 90.4 -114 92.8C-114 92.8 -113.2 111.801 -113.6 113.801L-111.6 110.001z"/>
+ </g>
+ <g style="fill: #ffffff">
+ <path d="M-120.2 114.601C-120.2 114.601 -122.2 113.201 -126.6 119.201C-126.6 119.201 -119.3 152.201 -119.3 153.601C-119.3 153.601 -118.2 151.501 -119.5 144.301C-120.8 137.101 -121.7 124.401 -121.7 124.401L-120.2 114.601z"/>
+ </g>
+ <g style="fill: #992600">
+ <path d="M-98.6 54C-98.6 54 -116.2 57.2 -115.8 86.4L-116.6 111.201C-116.6 111.201 -117.8 85.6 -119 84C-120.2 82.4 -116.2 71.2 -119.4 77.2C-119.4 77.2 -133.4 91.2 -125.4 112.401C-125.4 112.401 -123.9 115.701 -126.9 111.101C-126.9 111.101 -131.5 98.5 -130.4 92.1C-130.4 92.1 -130.2 89.9 -128.3 87.1C-128.3 87.1 -119.7 75.4 -117 73.1C-117 73.1 -115.2 58.7 -99.8 53.5C-99.8 53.5 -94.1 51.2 -98.6 54z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M40.8 -12.2C41.46 -12.554 41.451 -13.524 42.031 -13.697C43.18 -14.041 43.344 -15.108 43.862 -15.892C44.735 -17.211 44.928 -18.744 45.51 -20.235C45.782 -20.935 45.809 -21.89 45.496 -22.55C44.322 -25.031 43.62 -27.48 42.178 -29.906C41.91 -30.356 41.648 -31.15 41.447 -31.748C40.984 -33.132 39.727 -34.123 38.867 -35.443C38.579 -35.884 39.104 -36.809 38.388 -36.893C37.491 -36.998 36.042 -37.578 35.809 -36.552C35.221 -33.965 36.232 -31.442 37.2 -29C36.418 -28.308 36.752 -27.387 36.904 -26.62C37.614 -23.014 36.416 -19.662 35.655 -16.188C35.632 -16.084 35.974 -15.886 35.946 -15.824C34.724 -13.138 33.272 -10.693 31.453 -8.312C30.695 -7.32 29.823 -6.404 29.326 -5.341C28.958 -4.554 28.55 -3.588 28.8 -2.6C25.365 0.18 23.115 4.025 20.504 7.871C20.042 8.551 20.333 9.76 20.884 10.029C21.697 10.427 22.653 9.403 23.123 8.557C23.512 7.859 23.865 7.209 24.356 6.566C24.489 6.391 24.31 5.972 24.445 5.851C27.078 3.504 28.747 0.568 31.2 -1.8C33.15 -2.129 34.687 -3.127 36.435 -4.14C36.743 -4.319 37.267 -4.07 37.557 -4.265C39.31 -5.442 39.308 -7.478 39.414 -9.388C39.464 -10.272 39.66 -11.589 40.8 -12.2z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M31.959 -16.666C32.083 -16.743 31.928 -17.166 32.037 -17.382C32.199 -17.706 32.602 -17.894 32.764 -18.218C32.873 -18.434 32.71 -18.814 32.846 -18.956C35.179 -21.403 35.436 -24.427 34.4 -27.4C35.424 -28.02 35.485 -29.282 35.06 -30.129C34.207 -31.829 34.014 -33.755 33.039 -35.298C32.237 -36.567 30.659 -37.811 29.288 -36.508C28.867 -36.108 28.546 -35.321 28.824 -34.609C28.888 -34.446 29.173 -34.3 29.146 -34.218C29.039 -33.894 28.493 -33.67 28.487 -33.398C28.457 -31.902 27.503 -30.391 28.133 -29.062C28.905 -27.433 29.724 -25.576 30.4 -23.8C29.166 -21.684 30.199 -19.235 28.446 -17.358C28.31 -17.212 28.319 -16.826 28.441 -16.624C28.733 -16.138 29.139 -15.732 29.625 -15.44C29.827 -15.319 30.175 -15.317 30.375 -15.441C30.953 -15.803 31.351 -16.29 31.959 -16.666z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M94.771 -26.977C96.16 -25.185 96.45 -22.39 94.401 -21C94.951 -17.691 98.302 -19.67 100.401 -20.2C100.292 -20.588 100.519 -20.932 100.802 -20.937C101.859 -20.952 102.539 -21.984 103.601 -21.8C104.035 -23.357 105.673 -24.059 106.317 -25.439C108.043 -29.134 107.452 -33.407 104.868 -36.653C104.666 -36.907 104.883 -37.424 104.759 -37.786C104.003 -39.997 101.935 -40.312 100.001 -41C98.824 -44.875 98.163 -48.906 96.401 -52.6C94.787 -52.85 94.089 -54.589 92.752 -55.309C91.419 -56.028 90.851 -54.449 90.892 -53.403C90.899 -53.198 91.351 -52.974 91.181 -52.609C91.105 -52.445 90.845 -52.334 90.845 -52.2C90.846 -52.065 91.067 -51.934 91.201 -51.8C90.283 -50.98 88.86 -50.503 88.565 -49.358C87.611 -45.648 90.184 -42.523 91.852 -39.322C92.443 -38.187 91.707 -36.916 90.947 -35.708C90.509 -35.013 90.617 -33.886 90.893 -33.03C91.645 -30.699 93.236 -28.96 94.771 -26.977z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M57.611 -8.591C56.124 -6.74 52.712 -4.171 55.629 -2.243C55.823 -2.114 56.193 -2.11 56.366 -2.244C58.387 -3.809 60.39 -4.712 62.826 -5.294C62.95 -5.323 63.224 -4.856 63.593 -5.017C65.206 -5.72 67.216 -5.662 68.4 -7C72.167 -6.776 75.732 -7.892 79.123 -9.2C80.284 -9.648 81.554 -10.207 82.755 -10.709C84.131 -11.285 85.335 -12.213 86.447 -13.354C86.58 -13.49 86.934 -13.4 87.201 -13.4C87.161 -14.263 88.123 -14.39 88.37 -15.012C88.462 -15.244 88.312 -15.64 88.445 -15.742C90.583 -17.372 91.503 -19.39 90.334 -21.767C90.049 -22.345 89.8 -22.963 89.234 -23.439C88.149 -24.35 87.047 -23.496 86 -23.8C85.841 -23.172 85.112 -23.344 84.726 -23.146C83.867 -22.707 82.534 -23.292 81.675 -22.854C80.313 -22.159 79.072 -21.99 77.65 -21.613C77.338 -21.531 76.56 -21.627 76.4 -21C76.266 -21.134 76.118 -21.368 76.012 -21.346C74.104 -20.95 72.844 -20.736 71.543 -19.044C71.44 -18.911 70.998 -19.09 70.839 -18.955C69.882 -18.147 69.477 -16.913 68.376 -16.241C68.175 -16.118 67.823 -16.286 67.629 -16.157C66.983 -15.726 66.616 -15.085 65.974 -14.638C65.645 -14.409 65.245 -14.734 65.277 -14.99C65.522 -16.937 66.175 -18.724 65.6 -20.6C67.677 -23.12 70.194 -25.069 72 -27.8C72.015 -29.966 72.707 -32.112 72.594 -34.189C72.584 -34.382 72.296 -35.115 72.17 -35.462C71.858 -36.316 72.764 -37.382 71.92 -38.106C70.516 -39.309 69.224 -38.433 68.4 -37C66.562 -36.61 64.496 -35.917 62.918 -37.151C61.911 -37.938 61.333 -38.844 60.534 -39.9C59.549 -41.202 59.884 -42.638 59.954 -44.202C59.96 -44.33 59.645 -44.466 59.645 -44.6C59.646 -44.735 59.866 -44.866 60 -45C59.294 -45.626 59.019 -46.684 58 -47C58.305 -48.092 57.629 -48.976 56.758 -49.278C54.763 -49.969 53.086 -48.057 51.194 -47.984C50.68 -47.965 50.213 -49.003 49.564 -49.328C49.132 -49.544 48.428 -49.577 48.066 -49.311C47.378 -48.807 46.789 -48.693 46.031 -48.488C44.414 -48.052 43.136 -46.958 41.656 -46.103C40.171 -45.246 39.216 -43.809 38.136 -42.489C37.195 -41.337 37.059 -38.923 38.479 -38.423C40.322 -37.773 41.626 -40.476 43.592 -40.15C43.904 -40.099 44.11 -39.788 44 -39.4C44.389 -39.291 44.607 -39.52 44.8 -39.8C45.658 -38.781 46.822 -38.444 47.76 -37.571C48.73 -36.667 50.476 -37.085 51.491 -36.088C53.02 -34.586 52.461 -31.905 54.4 -30.6C53.814 -29.287 53.207 -28.01 52.872 -26.583C52.59 -25.377 53.584 -24.18 54.795 -24.271C56.053 -24.365 56.315 -25.124 56.8 -26.2C57.067 -25.933 57.536 -25.636 57.495 -25.42C57.038 -23.033 56.011 -21.04 55.553 -18.609C55.494 -18.292 55.189 -18.09 54.8 -18.2C54.332 -14.051 50.28 -11.657 47.735 -8.492C47.332 -7.99 47.328 -6.741 47.737 -6.338C49.14 -4.951 51.1 -6.497 52.8 -7C53.013 -8.206 53.872 -9.148 55.204 -9.092C55.46 -9.082 55.695 -9.624 56.019 -9.754C56.367 -9.892 56.869 -9.668 57.155 -9.866C58.884 -11.061 60.292 -12.167 62.03 -13.356C62.222 -13.487 62.566 -13.328 62.782 -13.436C63.107 -13.598 63.294 -13.985 63.617 -14.17C63.965 -14.37 64.207 -14.08 64.4 -13.8C63.754 -13.451 63.75 -12.494 63.168 -12.292C62.393 -12.024 61.832 -11.511 61.158 -11.064C60.866 -10.871 60.207 -11.119 60.103 -10.94C59.505 -9.912 58.321 -9.474 57.611 -8.591z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M2.2 -58C2.2 -58 -7.038 -60.872 -18.2 -35.2C-18.2 -35.2 -20.6 -30 -23 -28C-25.4 -26 -36.6 -22.4 -38.6 -18.4L-49 -2.4C-49 -2.4 -34.2 -18.4 -31 -20.8C-31 -20.8 -23 -29.2 -26.2 -22.4C-26.2 -22.4 -40.2 -11.6 -39 -2.4C-39 -2.4 -44.6 12 -45.4 14C-45.4 14 -29.4 -18 -27 -19.2C-24.6 -20.4 -23.4 -20.4 -24.6 -16.8C-25.8 -13.2 -26.2 3.2 -29 5.2C-29 5.2 -21 -15.2 -21.8 -18.4C-21.8 -18.4 -18.6 -22 -16.2 -16.8L-17.4 -0.8L-13 11.2C-13 11.2 -15.4 0 -13.8 -15.6C-13.8 -15.6 -15.8 -26 -11.8 -20.4C-7.8 -14.8 1.8 -8.8 1.8 -4C1.8 -4 -3.4 -21.6 -12.6 -26.4L-16.6 -20.4L-17.8 -22.4C-17.8 -22.4 -21.4 -23.2 -17 -30C-12.6 -36.8 -13 -37.6 -13 -37.6C-13 -37.6 -6.6 -30.4 -5 -30.4C-5 -30.4 8.2 -38 9.4 -13.6C9.4 -13.6 16.2 -28 7 -34.8C7 -34.8 -7.8 -36.8 -6.6 -42L0.6 -54.4C4.2 -59.6 2.6 -56.8 2.6 -56.8z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-17.8 -41.6C-17.8 -41.6 -30.6 -41.6 -33.8 -36.4L-41 -26.8C-41 -26.8 -23.8 -36.8 -19.8 -38C-15.8 -39.2 -17.8 -41.6 -17.8 -41.6z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-57.8 -35.2C-57.8 -35.2 -59.8 -34 -60.2 -31.2C-60.6 -28.4 -63 -28 -62.2 -25.2C-61.4 -22.4 -59.4 -20 -59.4 -24C-59.4 -28 -57.8 -30 -57 -31.2C-56.2 -32.4 -54.6 -36.8 -57.8 -35.2z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-66.6 26C-66.6 26 -75 22 -78.2 18.4C-81.4 14.8 -80.948 19.966 -85.8 19.6C-91.647 19.159 -90.6 3.2 -90.6 3.2L-94.6 10.8C-94.6 10.8 -95.8 25.2 -87.8 22.8C-83.893 21.628 -82.6 23.2 -84.2 24C-85.8 24.8 -78.6 25.2 -81.4 26.8C-84.2 28.4 -69.8 23.2 -72.2 33.6L-66.6 26z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-79.2 40.4C-79.2 40.4 -94.6 44.8 -98.2 35.2C-98.2 35.2 -103 37.6 -100.8 40.6C-98.6 43.6 -97.4 44 -97.4 44C-97.4 44 -92 45.2 -92.6 46C-93.2 46.8 -95.6 50.2 -95.6 50.2C-95.6 50.2 -85.4 44.2 -79.2 40.4z"/>
+ </g>
+ <g style="fill: #ffffff">
+ <path d="M149.201 118.601C148.774 120.735 147.103 121.536 145.201 122.201C143.284 121.243 140.686 118.137 138.801 120.201C138.327 119.721 137.548 119.661 137.204 118.999C136.739 118.101 137.011 117.055 136.669 116.257C136.124 114.985 135.415 113.619 135.601 112.201C137.407 111.489 138.002 109.583 137.528 107.82C137.459 107.563 137.03 107.366 137.23 107.017C137.416 106.694 137.734 106.467 138.001 106.2C137.866 106.335 137.721 106.568 137.61 106.548C137 106.442 137.124 105.805 137.254 105.418C137.839 103.672 139.853 103.408 141.201 104.6C141.457 104.035 141.966 104.229 142.401 104.2C142.351 103.621 142.759 103.094 142.957 102.674C143.475 101.576 145.104 102.682 145.901 102.07C146.977 101.245 148.04 100.546 149.118 101.149C150.927 102.162 152.636 103.374 153.835 105.115C154.41 105.949 154.65 107.23 154.592 108.188C154.554 108.835 153.173 108.483 152.83 109.412C152.185 111.16 154.016 111.679 154.772 113.017C154.97 113.366 154.706 113.67 154.391 113.768C153.98 113.896 153.196 113.707 153.334 114.16C154.306 117.353 151.55 118.031 149.201 118.601z"/>
+ </g>
+ <g style="fill: #ffffff">
+ <path d="M139.6 138.201C139.593 136.463 137.992 134.707 139.201 133.001C139.336 133.135 139.467 133.356 139.601 133.356C139.736 133.356 139.867 133.135 140.001 133.001C141.496 135.217 145.148 136.145 145.006 138.991C144.984 139.438 143.897 140.356 144.801 141.001C142.988 142.349 142.933 144.719 142.001 146.601C140.763 146.315 139.551 145.952 138.401 145.401C138.753 143.915 138.636 142.231 139.456 140.911C139.89 140.213 139.603 139.134 139.6 138.201z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M-26.6 129.201C-26.6 129.201 -43.458 139.337 -29.4 124.001C-20.6 114.401 -10.6 108.801 -10.6 108.801C-10.6 108.801 -0.2 104.4 3.4 103.2C7 102 22.2 96.8 25.4 96.4C28.6 96 38.2 92 45 96C51.8 100 59.8 104.4 59.8 104.4C59.8 104.4 43.4 96 39.8 98.4C36.2 100.8 29 100.4 23 103.6C23 103.6 8.2 108.001 5 110.001C1.8 112.001 -8.6 123.601 -10.2 122.801C-11.8 122.001 -9.8 121.601 -8.6 118.801C-7.4 116.001 -9.4 114.401 -17.4 120.801C-25.4 127.201 -26.6 129.201 -26.6 129.201z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-19.195 123.234C-19.195 123.234 -17.785 110.194 -9.307 111.859C-9.307 111.859 -1.081 107.689 1.641 105.721C1.641 105.721 9.78 104.019 11.09 103.402C29.569 94.702 44.288 99.221 44.835 98.101C45.381 96.982 65.006 104.099 68.615 108.185C69.006 108.628 58.384 102.588 48.686 100.697C40.413 99.083 18.811 100.944 7.905 106.48C4.932 107.989 -4.013 113.773 -6.544 113.662C-9.075 113.55 -19.195 123.234 -19.195 123.234z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M-23 148.801C-23 148.801 -38.2 146.401 -21.4 144.801C-21.4 144.801 -3.4 142.801 0.6 137.601C0.6 137.601 14.2 128.401 17 128.001C19.8 127.601 49.8 120.401 50.2 118.001C50.6 115.601 56.2 115.601 57.8 116.401C59.4 117.201 58.6 118.401 55.8 119.201C53 120.001 21.8 136.401 15.4 137.601C9 138.801 -2.6 146.401 -7.4 147.601C-12.2 148.801 -23 148.801 -23 148.801z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-3.48 141.403C-3.48 141.403 -12.062 140.574 -3.461 139.755C-3.461 139.755 5.355 136.331 7.403 133.668C7.403 133.668 14.367 128.957 15.8 128.753C17.234 128.548 31.194 124.861 31.399 123.633C31.604 122.404 65.67 109.823 70.09 113.013C73.001 115.114 63.1 113.437 53.466 117.847C52.111 118.467 18.258 133.054 14.981 133.668C11.704 134.283 5.765 138.174 3.307 138.788C0.85 139.403 -3.48 141.403 -3.48 141.403z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-11.4 143.601C-11.4 143.601 -6.2 143.201 -7.4 144.801C-8.6 146.401 -11 145.601 -11 145.601L-11.4 143.601z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-18.6 145.201C-18.6 145.201 -13.4 144.801 -14.6 146.401C-15.8 148.001 -18.2 147.201 -18.2 147.201L-18.6 145.201z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-29 146.801C-29 146.801 -23.8 146.401 -25 148.001C-26.2 149.601 -28.6 148.801 -28.6 148.801L-29 146.801z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-36.6 147.601C-36.6 147.601 -31.4 147.201 -32.6 148.801C-33.8 150.401 -36.2 149.601 -36.2 149.601L-36.6 147.601z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M1.8 108.001C1.8 108.001 6.2 108.001 5 109.601C3.8 111.201 0.6 110.801 0.6 110.801L1.8 108.001z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-8.2 113.601C-8.2 113.601 -1.694 111.46 -4.2 114.801C-5.4 116.401 -7.8 115.601 -7.8 115.601L-8.2 113.601z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-19.4 118.401C-19.4 118.401 -14.2 118.001 -15.4 119.601C-16.6 121.201 -19 120.401 -19 120.401L-19.4 118.401z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-27 124.401C-27 124.401 -21.8 124.001 -23 125.601C-24.2 127.201 -26.6 126.401 -26.6 126.401L-27 124.401z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-33.8 129.201C-33.8 129.201 -28.6 128.801 -29.8 130.401C-31 132.001 -33.4 131.201 -33.4 131.201L-33.8 129.201z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M5.282 135.598C5.282 135.598 12.203 135.066 10.606 137.195C9.009 139.325 5.814 138.26 5.814 138.26L5.282 135.598z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M15.682 130.798C15.682 130.798 22.603 130.266 21.006 132.395C19.409 134.525 16.214 133.46 16.214 133.46L15.682 130.798z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M26.482 126.398C26.482 126.398 33.403 125.866 31.806 127.995C30.209 130.125 27.014 129.06 27.014 129.06L26.482 126.398z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M36.882 121.598C36.882 121.598 43.803 121.066 42.206 123.195C40.609 125.325 37.414 124.26 37.414 124.26L36.882 121.598z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M9.282 103.598C9.282 103.598 16.203 103.066 14.606 105.195C13.009 107.325 9.014 107.06 9.014 107.06L9.282 103.598z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M19.282 100.398C19.282 100.398 26.203 99.866 24.606 101.995C23.009 104.125 18.614 103.86 18.614 103.86L19.282 100.398z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-3.4 140.401C-3.4 140.401 1.8 140.001 0.6 141.601C-0.6 143.201 -3 142.401 -3 142.401L-3.4 140.401z"/>
+ </g>
+ <g style="fill: #992600">
+ <path d="M-76.6 41.2C-76.6 41.2 -81 50 -81.4 53.2C-81.4 53.2 -80.6 44.4 -79.4 42.4C-78.2 40.4 -76.6 41.2 -76.6 41.2z"/>
+ </g>
+ <g style="fill: #992600">
+ <path d="M-95 55.2C-95 55.2 -98.2 69.6 -97.8 72.4C-97.8 72.4 -99 60.8 -98.6 59.6C-98.2 58.4 -95 55.2 -95 55.2z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M-74.2 -19.4L-74.4 -16.2L-76.6 -16C-76.6 -16 -62.4 -3.4 -61.8 4.2C-61.8 4.2 -61 -4 -74.2 -19.4z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-70.216 -18.135C-70.647 -18.551 -70.428 -19.296 -70.836 -19.556C-71.645 -20.072 -69.538 -20.129 -69.766 -20.845C-70.149 -22.051 -69.962 -22.072 -70.084 -23.348C-70.141 -23.946 -69.553 -25.486 -69.168 -25.926C-67.722 -27.578 -69.046 -30.51 -67.406 -32.061C-67.102 -32.35 -66.726 -32.902 -66.441 -33.32C-65.782 -34.283 -64.598 -34.771 -63.648 -35.599C-63.33 -35.875 -63.531 -36.702 -62.962 -36.61C-62.248 -36.495 -61.007 -36.625 -61.052 -35.784C-61.165 -33.664 -62.494 -31.944 -63.774 -30.276C-63.323 -29.572 -63.781 -28.937 -64.065 -28.38C-65.4 -25.76 -65.211 -22.919 -65.385 -20.079C-65.39 -19.994 -65.697 -19.916 -65.689 -19.863C-65.336 -17.528 -64.752 -15.329 -63.873 -13.1C-63.507 -12.17 -63.036 -11.275 -62.886 -10.348C-62.775 -9.662 -62.672 -8.829 -63.08 -8.124C-61.045 -5.234 -62.354 -2.583 -61.185 0.948C-60.978 1.573 -59.286 3.487 -59.749 3.326C-62.262 2.455 -62.374 2.057 -62.551 1.304C-62.697 0.681 -63.027 -0.696 -63.264 -1.298C-63.328 -1.462 -63.499 -3.346 -63.577 -3.468C-65.09 -5.85 -63.732 -5.674 -65.102 -8.032C-66.53 -8.712 -67.496 -9.816 -68.619 -10.978C-68.817 -11.182 -67.674 -11.906 -67.855 -12.119C-68.947 -13.408 -70.1 -14.175 -69.764 -15.668C-69.609 -16.358 -69.472 -17.415 -70.216 -18.135z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-73.8 -16.4C-73.8 -16.4 -73.4 -9.6 -71 -8C-68.6 -6.4 -69.8 -7.2 -73 -8.4C-76.2 -9.6 -75 -10.4 -75 -10.4C-75 -10.4 -77.8 -10 -75.4 -8C-73 -6 -69.4 -3.6 -71 -3.6C-72.6 -3.6 -80.2 -7.6 -80.2 -10.4C-80.2 -13.2 -81.2 -17.3 -81.2 -17.3C-81.2 -17.3 -80.1 -18.1 -75.3 -18C-75.3 -18 -73.9 -17.3 -73.8 -16.4z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M-74.6 2.2C-74.6 2.2 -83.12 -0.591 -101.6 2.8C-101.6 2.8 -92.569 0.722 -73.8 3C-63.5 4.25 -74.6 2.2 -74.6 2.2z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M-72.502 2.129C-72.502 2.129 -80.748 -1.389 -99.453 0.392C-99.453 0.392 -90.275 -0.897 -71.774 2.995C-61.62 5.131 -72.502 2.129 -72.502 2.129z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M-70.714 2.222C-70.714 2.222 -78.676 -1.899 -97.461 -1.514C-97.461 -1.514 -88.213 -2.118 -70.052 3.14C-60.086 6.025 -70.714 2.222 -70.714 2.222z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M-69.444 2.445C-69.444 2.445 -76.268 -1.862 -93.142 -2.96C-93.142 -2.96 -84.803 -2.79 -68.922 3.319C-60.206 6.672 -69.444 2.445 -69.444 2.445z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M45.84 12.961C45.84 12.961 44.91 13.605 45.124 12.424C45.339 11.243 73.547 -1.927 77.161 -1.677C77.161 -1.677 46.913 11.529 45.84 12.961z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M42.446 13.6C42.446 13.6 41.57 14.315 41.691 13.121C41.812 11.927 68.899 -3.418 72.521 -3.452C72.521 -3.452 43.404 12.089 42.446 13.6z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M39.16 14.975C39.16 14.975 38.332 15.747 38.374 14.547C38.416 13.348 58.233 -2.149 68.045 -4.023C68.045 -4.023 50.015 4.104 39.16 14.975z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M36.284 16.838C36.284 16.838 35.539 17.532 35.577 16.453C35.615 15.373 53.449 1.426 62.28 -0.26C62.28 -0.26 46.054 7.054 36.284 16.838z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M4.6 164.801C4.6 164.801 -10.6 162.401 6.2 160.801C6.2 160.801 24.2 158.801 28.2 153.601C28.2 153.601 41.8 144.401 44.6 144.001C47.4 143.601 63.8 140.001 64.2 137.601C64.6 135.201 70.6 132.801 72.2 133.601C73.8 134.401 73.8 143.601 71 144.401C68.2 145.201 49.4 152.401 43 153.601C36.6 154.801 25 162.401 20.2 163.601C15.4 164.801 4.6 164.801 4.6 164.801z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M77.6 127.401C77.6 127.401 74.6 129.001 73.4 131.601C73.4 131.601 67 142.201 52.8 145.401C52.8 145.401 29.8 154.401 22 156.401C22 156.401 8.6 161.401 1.2 160.601C1.2 160.601 -5.8 160.801 0.4 162.401C0.4 162.401 20.6 160.401 24 158.601C24 158.601 39.6 153.401 42.6 150.801C45.6 148.201 63.8 143.201 66 141.201C68.2 139.201 78 130.801 77.6 127.401z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M18.882 158.911C18.882 158.911 24.111 158.685 22.958 160.234C21.805 161.784 19.357 160.91 19.357 160.91L18.882 158.911z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M11.68 160.263C11.68 160.263 16.908 160.037 15.756 161.586C14.603 163.136 12.155 162.263 12.155 162.263L11.68 160.263z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M1.251 161.511C1.251 161.511 6.48 161.284 5.327 162.834C4.174 164.383 1.726 163.51 1.726 163.51L1.251 161.511z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-6.383 162.055C-6.383 162.055 -1.154 161.829 -2.307 163.378C-3.46 164.928 -5.908 164.054 -5.908 164.054L-6.383 162.055z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M35.415 151.513C35.415 151.513 42.375 151.212 40.84 153.274C39.306 155.336 36.047 154.174 36.047 154.174L35.415 151.513z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M45.73 147.088C45.73 147.088 51.689 143.787 51.155 148.849C50.885 151.405 46.362 149.749 46.362 149.749L45.73 147.088z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M54.862 144.274C54.862 144.274 62.021 140.573 60.287 146.035C59.509 148.485 55.493 146.935 55.493 146.935L54.862 144.274z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M64.376 139.449C64.376 139.449 68.735 134.548 69.801 141.21C70.207 143.748 65.008 142.11 65.008 142.11L64.376 139.449z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M26.834 155.997C26.834 155.997 32.062 155.77 30.91 157.32C29.757 158.869 27.308 157.996 27.308 157.996L26.834 155.997z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M62.434 34.603C62.434 34.603 61.708 35.268 61.707 34.197C61.707 33.127 79.191 19.863 88.034 18.479C88.034 18.479 71.935 25.208 62.434 34.603z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M65.4 98.4C65.4 98.4 87.401 120.801 96.601 124.401C96.601 124.401 105.801 135.601 101.801 161.601C101.801 161.601 98.601 169.201 95.401 148.401C95.401 148.401 98.601 123.201 87.401 139.201C87.401 139.201 79 129.301 85.4 129.601C85.4 129.601 88.601 131.601 89.001 130.001C89.401 128.401 81.4 114.801 64.2 100.4C47 86 65.4 98.4 65.4 98.4z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M7 137.201C7 137.201 6.8 135.401 8.6 136.201C10.4 137.001 104.601 143.201 136.201 167.201C136.201 167.201 91.001 144.001 7 137.201z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M17.4 132.801C17.4 132.801 17.2 131.001 19 131.801C20.8 132.601 157.401 131.601 181.001 164.001C181.001 164.001 159.001 138.801 17.4 132.801z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M29 128.801C29 128.801 28.8 127.001 30.6 127.801C32.4 128.601 205.801 115.601 229.401 148.001C229.401 148.001 219.801 122.401 29 128.801z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M39 124.001C39 124.001 38.8 122.201 40.6 123.001C42.4 123.801 164.601 85.2 188.201 117.601C188.201 117.601 174.801 93 39 124.001z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M-19 146.801C-19 146.801 -19.2 145.001 -17.4 145.801C-15.6 146.601 2.2 148.801 4.2 187.601C4.2 187.601 -3 145.601 -19 146.801z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M-27.8 148.401C-27.8 148.401 -28 146.601 -26.2 147.401C-24.4 148.201 -10.2 143.601 -13 182.401C-13 182.401 -11.8 147.201 -27.8 148.401z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M-35.8 148.801C-35.8 148.801 -36 147.001 -34.2 147.801C-32.4 148.601 -17 149.201 -29.4 171.601C-29.4 171.601 -19.8 147.601 -35.8 148.801z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M11.526 104.465C11.526 104.465 11.082 106.464 12.631 105.247C28.699 92.622 61.141 33.72 116.826 28.086C116.826 28.086 78.518 15.976 11.526 104.465z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M22.726 102.665C22.726 102.665 21.363 101.472 23.231 100.847C25.099 100.222 137.541 27.72 176.826 35.686C176.826 35.686 149.719 28.176 22.726 102.665z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M1.885 108.767C1.885 108.767 1.376 110.366 3.087 109.39C12.062 104.27 15.677 47.059 59.254 45.804C59.254 45.804 26.843 31.09 1.885 108.767z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M-18.038 119.793C-18.038 119.793 -19.115 121.079 -17.162 120.825C-6.916 119.493 14.489 78.222 58.928 83.301C58.928 83.301 26.962 68.955 -18.038 119.793z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M-6.8 113.667C-6.8 113.667 -7.611 115.136 -5.742 114.511C4.057 111.237 17.141 66.625 61.729 63.078C61.729 63.078 27.603 55.135 -6.8 113.667z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M-25.078 124.912C-25.078 124.912 -25.951 125.954 -24.369 125.748C-16.07 124.669 1.268 91.24 37.264 95.354C37.264 95.354 11.371 83.734 -25.078 124.912z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M-32.677 130.821C-32.677 130.821 -33.682 131.866 -32.091 131.748C-27.923 131.439 2.715 98.36 21.183 113.862C21.183 113.862 9.168 95.139 -32.677 130.821z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M36.855 98.898C36.855 98.898 35.654 97.543 37.586 97.158C39.518 96.774 160.221 39.061 198.184 51.927C198.184 51.927 172.243 41.053 36.855 98.898z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M3.4 163.201C3.4 163.201 3.2 161.401 5 162.201C6.8 163.001 22.2 163.601 9.8 186.001C9.8 186.001 19.4 162.001 3.4 163.201z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M13.8 161.601C13.8 161.601 13.6 159.801 15.4 160.601C17.2 161.401 35 163.601 37 202.401C37 202.401 29.8 160.401 13.8 161.601z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M20.6 160.001C20.6 160.001 20.4 158.201 22.2 159.001C24 159.801 48.6 163.201 72.2 195.601C72.2 195.601 36.6 158.801 20.6 160.001z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M28.225 157.972C28.225 157.972 27.788 156.214 29.678 156.768C31.568 157.322 52.002 155.423 90.099 189.599C90.099 189.599 43.924 154.656 28.225 157.972z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M38.625 153.572C38.625 153.572 38.188 151.814 40.078 152.368C41.968 152.922 76.802 157.423 128.499 192.399C128.499 192.399 54.324 150.256 38.625 153.572z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M-1.8 142.001C-1.8 142.001 -2 140.201 -0.2 141.001C1.6 141.801 55 144.401 85.4 171.201C85.4 171.201 50.499 146.426 -1.8 142.001z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M-11.8 146.001C-11.8 146.001 -12 144.201 -10.2 145.001C-8.4 145.801 16.2 149.201 39.8 181.601C39.8 181.601 4.2 144.801 -11.8 146.001z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M49.503 148.962C49.503 148.962 48.938 147.241 50.864 147.655C52.79 148.068 87.86 150.004 141.981 181.098C141.981 181.098 64.317 146.704 49.503 148.962z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M57.903 146.562C57.903 146.562 57.338 144.841 59.264 145.255C61.19 145.668 96.26 147.604 150.381 178.698C150.381 178.698 73.317 143.904 57.903 146.562z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M67.503 141.562C67.503 141.562 66.938 139.841 68.864 140.255C70.79 140.668 113.86 145.004 203.582 179.298C203.582 179.298 82.917 138.904 67.503 141.562z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-43.8 148.401C-43.8 148.401 -38.6 148.001 -39.8 149.601C-41 151.201 -43.4 150.401 -43.4 150.401L-43.8 148.401z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-13 162.401C-13 162.401 -7.8 162.001 -9 163.601C-10.2 165.201 -12.6 164.401 -12.6 164.401L-13 162.401z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-21.8 162.001C-21.8 162.001 -16.6 161.601 -17.8 163.201C-19 164.801 -21.4 164.001 -21.4 164.001L-21.8 162.001z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-117.169 150.182C-117.169 150.182 -112.124 151.505 -113.782 152.624C-115.439 153.744 -117.446 152.202 -117.446 152.202L-117.169 150.182z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-115.169 140.582C-115.169 140.582 -110.124 141.905 -111.782 143.024C-113.439 144.144 -115.446 142.602 -115.446 142.602L-115.169 140.582z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-122.369 136.182C-122.369 136.182 -117.324 137.505 -118.982 138.624C-120.639 139.744 -122.646 138.202 -122.646 138.202L-122.369 136.182z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M-42.6 211.201C-42.6 211.201 -44.2 211.201 -48.2 213.201C-50.2 213.201 -61.4 216.801 -67 226.801C-67 226.801 -54.6 217.201 -42.6 211.201z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M45.116 303.847C45.257 304.105 45.312 304.525 45.604 304.542C46.262 304.582 47.495 304.883 47.37 304.247C46.522 299.941 45.648 295.004 41.515 293.197C40.876 292.918 39.434 293.331 39.36 294.215C39.233 295.739 39.116 297.088 39.425 298.554C39.725 299.975 41.883 299.985 42.8 298.601C43.736 300.273 44.168 302.116 45.116 303.847z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M34.038 308.581C34.786 309.994 34.659 311.853 36.074 312.416C36.814 312.71 38.664 311.735 38.246 310.661C37.444 308.6 37.056 306.361 35.667 304.55C35.467 304.288 35.707 303.755 35.547 303.427C34.953 302.207 33.808 301.472 32.4 301.801C31.285 304.004 32.433 306.133 33.955 307.842C34.091 307.994 33.925 308.37 34.038 308.581z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M-5.564 303.391C-5.672 303.014 -5.71 302.551 -5.545 302.23C-5.014 301.197 -4.221 300.075 -4.558 299.053C-4.906 297.997 -6.022 298.179 -6.672 298.748C-7.807 299.742 -7.856 301.568 -8.547 302.927C-8.743 303.313 -8.692 303.886 -9.133 304.277C-9.607 304.698 -10.047 306.222 -9.951 306.793C-9.898 307.106 -10.081 317.014 -9.859 316.751C-9.24 316.018 -6.19 306.284 -6.121 305.392C-6.064 304.661 -5.332 304.196 -5.564 303.391z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M-31.202 296.599C-28.568 294.1 -25.778 291.139 -26.22 287.427C-26.336 286.451 -28.111 286.978 -28.298 287.824C-29.1 291.449 -31.139 294.11 -33.707 296.502C-35.903 298.549 -37.765 304.893 -38 305.401C-34.303 300.145 -32.046 297.399 -31.202 296.599z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M-44.776 290.635C-44.253 290.265 -44.555 289.774 -44.338 289.442C-43.385 287.984 -42.084 286.738 -42.066 285C-42.063 284.723 -42.441 284.414 -42.776 284.638C-43.053 284.822 -43.395 284.952 -43.503 285.082C-45.533 287.531 -46.933 290.202 -48.376 293.014C-48.559 293.371 -49.703 297.862 -49.39 297.973C-49.151 298.058 -47.431 293.877 -47.221 293.763C-45.958 293.077 -45.946 291.462 -44.776 290.635z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M-28.043 310.179C-27.599 309.31 -26.023 308.108 -26.136 307.219C-26.254 306.291 -25.786 304.848 -26.698 305.536C-27.955 306.484 -31.404 307.833 -31.674 313.641C-31.7 314.212 -28.726 311.519 -28.043 310.179z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M-13.6 293.001C-13.2 292.333 -12.492 292.806 -12.033 292.543C-11.385 292.171 -10.774 291.613 -10.482 290.964C-9.512 288.815 -7.743 286.995 -7.6 284.601C-9.091 283.196 -9.77 285.236 -10.4 286.201C-11.723 284.554 -12.722 286.428 -14.022 286.947C-14.092 286.975 -14.305 286.628 -14.38 286.655C-15.557 287.095 -16.237 288.176 -17.235 288.957C-17.406 289.091 -17.811 288.911 -17.958 289.047C-18.61 289.65 -19.583 289.975 -19.863 290.657C-20.973 293.364 -24.113 295.459 -26 303.001C-25.619 303.91 -21.488 296.359 -21.001 295.661C-20.165 294.465 -20.047 297.322 -18.771 296.656C-18.72 296.629 -18.534 296.867 -18.4 297.001C-18.206 296.721 -17.988 296.492 -17.6 296.601C-17.6 296.201 -17.734 295.645 -17.533 295.486C-16.296 294.509 -16.38 293.441 -15.6 292.201C-15.142 292.99 -14.081 292.271 -13.6 293.001z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M46.2 347.401C46.2 347.401 53.6 327.001 49.2 315.801C49.2 315.801 60.6 337.401 56 348.601C56 348.601 55.6 338.201 51.6 333.201C51.6 333.201 47.6 346.001 46.2 347.401z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M31.4 344.801C31.4 344.801 36.8 336.001 28.8 317.601C28.8 317.601 28 338.001 21.2 349.001C21.2 349.001 35.4 328.801 31.4 344.801z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M21.4 342.801C21.4 342.801 21.2 322.801 21.6 319.801C21.6 319.801 17.8 336.401 7.6 346.001C7.6 346.001 22 334.001 21.4 342.801z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M11.8 310.801C11.8 310.801 17.8 324.401 7.8 342.801C7.8 342.801 14.2 330.601 9.4 323.601C9.4 323.601 12 320.201 11.8 310.801z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M-7.4 342.401C-7.4 342.401 -8.4 326.801 -6.6 324.601C-6.6 324.601 -6.4 318.201 -6.8 317.201C-6.8 317.201 -2.8 311.001 -2.6 318.401C-2.6 318.401 -1.2 326.201 1.6 330.801C1.6 330.801 5.2 336.201 5 342.601C5 342.601 -5 312.401 -7.4 342.401z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M-11 314.801C-11 314.801 -17.6 325.601 -19.4 344.601C-19.4 344.601 -20.8 338.401 -17 324.001C-17 324.001 -12.8 308.601 -11 314.801z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M-32.8 334.601C-32.8 334.601 -27.8 329.201 -26.4 324.201C-26.4 324.201 -22.8 308.401 -29.2 317.001C-29.2 317.001 -29 325.001 -37.2 332.401C-37.2 332.401 -32.4 330.001 -32.8 334.601z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M-38.6 329.601C-38.6 329.601 -35.2 312.201 -34.4 311.401C-34.4 311.401 -32.6 308.001 -35.4 311.201C-35.4 311.201 -44.2 330.401 -48.2 337.001C-48.2 337.001 -40.2 327.801 -38.6 329.601z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M-44.4 313.001C-44.4 313.001 -32.8 290.601 -54.6 316.401C-54.6 316.401 -43.6 306.601 -44.4 313.001z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M-59.8 298.401C-59.8 298.401 -55 279.601 -52.4 279.801C-52.4 279.801 -44.2 270.801 -50.8 281.401C-50.8 281.401 -56.8 291.001 -56.2 300.801C-56.2 300.801 -56.8 291.201 -59.8 298.401z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M270.5 287C270.5 287 258.5 277 256 273.5C256 273.5 269.5 292 269.5 299C269.5 299 272 291.5 270.5 287z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M276 265C276 265 255 250 251.5 242.5C251.5 242.5 278 272 278 276.5C278 276.5 278.5 267.5 276 265z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M293 111C293 111 281 103 279.5 105C279.5 105 290 111.5 292.5 120C292.5 120 291 111 293 111z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M301.5 191.5L284 179.5C284 179.5 303 196.5 303.5 200.5L301.5 191.5z"/>
+ </g>
+ <g style="stroke:#000000">
+ <path d="M-89.25 169L-67.25 173.75"/>
+ </g>
+ <g style="stroke:#000000">
+ <path d="M-39 331C-39 331 -39.5 327.5 -48.5 338"/>
+ </g>
+ <g style="stroke:#000000">
+ <path d="M-33.5 336C-33.5 336 -31.5 329.5 -38 334"/>
+ </g>
+ <g style="stroke:#000000">
+ <path d="M20.5 344.5C20.5 344.5 22 333.5 10.5 346.5"/>
+ </g>
+</g>
+</svg>
diff --git a/src/corelib/render/software/agg-demos/svg_test.dpr b/src/corelib/render/software/agg-demos/svg_test.dpr
new file mode 100644
index 00000000..8d148127
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/svg_test.dpr
@@ -0,0 +1,439 @@
+{mac_copy:tiger.svg}
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ svg_test ;
+
+uses
+ SysUtils ,
+
+ agg_basics ,
+ agg_platform_support ,
+
+ agg_color ,
+ agg_pixfmt ,
+ agg_pixfmt_rgba ,
+
+ agg_ctrl ,
+ agg_slider_ctrl ,
+
+ agg_rendering_buffer ,
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_rasterizer_scanline_aa ,
+ agg_scanline ,
+ agg_scanline_p ,
+ agg_render_scanlines ,
+
+ agg_trans_affine ,
+ agg_gamma_functions ,
+ agg_gsv_text ,
+ agg_conv_stroke ,
+
+ agg_svg_parser ,
+ agg_svg_path_renderer ,
+ agg_svg_exception ,
+ file_utils_ ;
+
+{$I agg_mode.inc }
+
+const
+ flip_y = false;
+
+type
+ the_application = object(platform_support )
+ m_path : path_renderer;
+
+ m_expand ,
+ m_gamma ,
+ m_scale ,
+ m_rotate : slider_ctrl;
+
+ m_min_x ,
+ m_min_y ,
+ m_max_x ,
+ m_max_y ,
+
+ m_x ,
+ m_y ,
+ m_dx ,
+ m_dy : double;
+
+ m_drag_flag : boolean;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure parse_svg(fname : shortstring );
+
+ procedure on_resize(sx ,sy : int ); virtual;
+ procedure on_draw; virtual;
+
+ procedure on_mouse_move(x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_up (x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_path.Construct;
+
+ m_expand.Construct(5 ,5 ,256 - 5 ,11 ,not flip_y_ );
+ m_gamma.Construct (5 ,5 + 15 ,256 - 5 ,11 + 15 ,not flip_y_ );
+ m_scale.Construct (256 + 5 ,5 ,512 - 5 ,11 ,not flip_y_ );
+ m_rotate.Construct(256 + 5 ,5 + 15 ,512 - 5 ,11 + 15 ,not flip_y_ );
+
+ m_min_x:=0.0;
+ m_min_y:=0.0;
+ m_max_x:=0.0;
+ m_max_y:=0.0;
+
+ m_x :=0.0;
+ m_y :=0.0;
+ m_dx:=0.0;
+ m_dy:=0.0;
+
+ m_drag_flag:=false;
+
+ add_ctrl(@m_expand );
+ add_ctrl(@m_gamma );
+ add_ctrl(@m_scale );
+ add_ctrl(@m_rotate );
+
+ m_expand.label_('Expand=%3.2f' );
+ m_expand.range_(-1 ,1.2 );
+ m_expand.value_(0.0 );
+
+ m_gamma.label_('Gamma=%3.2f' );
+ m_gamma.range_(0.0 ,3.0 );
+ m_gamma.value_(1.0 );
+
+ m_scale.label_('Scale=%3.2f' );
+ m_scale.range_(0.2 ,10.0 );
+ m_scale.value_(1.0 );
+
+ m_rotate.label_('Rotate=%3.2f' );
+ m_rotate.range_(-180.0 ,180.0 );
+ m_rotate.value_(0.0 );
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_path.Destruct;
+
+ m_expand.Destruct;
+ m_gamma.Destruct;
+ m_scale.Destruct;
+ m_rotate.Destruct;
+
+end;
+
+{ PARSE_SVG }
+procedure the_application.parse_svg;
+var
+ p : parser;
+
+begin
+ p.Construct(@m_path );
+
+ try
+ p.parse(fname );
+
+ except
+ p.Destruct;
+ raise;
+
+ end;
+
+ m_path.arrange_orientations;
+ m_path.bounding_rect(@m_min_x ,@m_min_y ,@m_max_x ,@m_max_y );
+
+ caption_(StrPas(PChar(p.title ) ) + ' (F1-Help)' );
+
+ p.Destruct;
+
+end;
+
+{ ON_RESIZE }
+procedure the_application.on_resize;
+begin
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ pixf : pixel_formats;
+
+ rb : renderer_base;
+ ren : renderer_scanline_aa_solid;
+ ras : rasterizer_scanline_aa;
+ sl : scanline_p8;
+ mtx : trans_affine;
+
+ rgba : aggclr;
+ gmpw : gamma_power;
+ gmno : gamma_none;
+
+ tat : trans_affine_translation;
+ tas : trans_affine_scaling;
+ tar : trans_affine_rotation;
+
+ tm : double;
+
+ vertex_count : unsigned;
+
+ buf : array[0..127 ] of char;
+ t : gsv_text;
+ pt : conv_stroke;
+
+begin
+// Initialize structures
+ pixfmt_bgra32(pixf ,rbuf_window );
+
+ rb.Construct (@pixf );
+ ren.Construct(@rb );
+
+ rgba.ConstrDbl(1 ,1 ,1 );
+ rb.clear (@rgba );
+
+ ras.Construct;
+ sl.Construct;
+ mtx.Construct;
+
+// Render
+ gmpw.Construct(m_gamma._value );
+ ras.gamma (@gmpw );
+
+ tat.Construct((m_min_x + m_max_x ) * -0.5 ,(m_min_y + m_max_y ) * -0.5 );
+ mtx.multiply (@tat );
+
+ tas.Construct(m_scale._value );
+ mtx.multiply (@tas );
+
+ tar.Construct(deg2rad(m_rotate._value ) );
+ mtx.multiply (@tar );
+
+ tat.Construct((m_min_x + m_max_x ) * 0.5 + m_x ,(m_min_y + m_max_y ) * 0.5 + m_y + 30 );
+ mtx.multiply (@tat );
+
+ m_path.expand(m_expand._value );
+
+ start_timer;
+
+ m_path.render(@ras ,@sl ,@ren ,@mtx ,rb._clip_box ,1.0 );
+
+ tm:=elapsed_time;
+
+ vertex_count:=m_path.vertex_count;
+
+// Render the controls
+ gmno.Construct;
+ ras.gamma(@gmno );
+
+ render_ctrl(@ras ,@sl ,@ren ,@m_expand );
+ render_ctrl(@ras ,@sl ,@ren ,@m_gamma );
+ render_ctrl(@ras ,@sl ,@ren ,@m_scale );
+ render_ctrl(@ras ,@sl ,@ren ,@m_rotate );
+
+// Display text
+ t.Construct;
+ t.size_(10.0 );
+ t.flip_(true );
+
+ pt.Construct(@t );
+ pt.width_ (1.5 );
+
+ sprintf(@buf[0 ] ,'Vertices=%d ' ,vertex_count );
+ sprintf(@buf[StrLen(@buf[0 ] ) ] ,'Time=%.3f ms' ,tm );
+
+ t.start_point_(10.0 ,40.0 );
+ t.text_ (@buf[0 ] );
+
+ ras.add_path (@pt );
+ rgba.ConstrDbl (0 ,0 ,0 );
+ ren.color_ (@rgba );
+ render_scanlines(@ras ,@sl ,@ren );
+
+// Free AGG resources
+ ras.Destruct;
+ sl.Destruct;
+
+ t.Destruct;
+ pt.Destruct;
+
+end;
+
+{ ON_MOUSE_MOVE }
+procedure the_application.on_mouse_move;
+begin
+ if flags = 0 then
+ m_drag_flag:=false;
+
+ if m_drag_flag then
+ begin
+ m_x:=x - m_dx;
+ m_y:=y - m_dy;
+
+ force_redraw;
+
+ end;
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure the_application.on_mouse_button_down;
+begin
+ m_dx:=x - m_x;
+ m_dy:=y - m_y;
+
+ m_drag_flag:=true;
+
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+procedure the_application.on_mouse_button_up;
+begin
+ m_drag_flag:=false;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+var
+ mtx : trans_affine;
+ tat : trans_affine_translation;
+ tas : trans_affine_scaling;
+ tar : trans_affine_rotation;
+
+ m : array[0..5 ] of double;
+ buf : array[0..127 ] of char;
+ fd : text;
+
+begin
+ if key = byte(' ' ) then
+ begin
+ mtx.Construct;
+
+ tat.Construct((m_min_x + m_max_x ) * -0.5 ,(m_min_y + m_max_y ) * -0.5 );
+ mtx.multiply (@tat );
+
+ tas.Construct(m_scale._value );
+ mtx.multiply (@tas );
+
+ tar.Construct(deg2rad(m_rotate._value ) );
+ mtx.multiply (@tar );
+
+ tat.Construct((m_min_x + m_max_x ) * 0.5 ,(m_min_y + m_max_y ) * 0.5 );
+ mtx.multiply (@tat );
+
+ tat.Construct(m_x ,m_y );
+ mtx.multiply (@tat );
+
+ mtx.store_to(@m );
+
+ sprintf(@buf[0 ] ,'%3.3f, ' ,m[0 ] );
+ sprintf(@buf[StrLen(@buf[0 ] ) ] ,'%3.3f, ' ,m[1 ] );
+ sprintf(@buf[StrLen(@buf[0 ] ) ] ,'%3.3f, ' ,m[2 ] );
+ sprintf(@buf[StrLen(@buf[0 ] ) ] ,'%3.3f, ' ,m[3 ] );
+ sprintf(@buf[StrLen(@buf[0 ] ) ] ,'%3.3f, ' ,m[4 ] );
+ sprintf(@buf[StrLen(@buf[0 ] ) ] ,'%3.3f' ,m[5 ] );
+
+ message_(@buf[0 ] );
+
+ {$I- }
+ AssignFile(fd ,'transform.txt' );
+ rewrite (fd );
+ writeln (fd ,PChar(@buf[0 ] ) );
+ close (fd );
+
+ end;
+
+ if key = key_f1 then
+ message_(
+ 'The SVG viewer is just another example of using Anti-Grain Geometry. The viewer '#13 +
+ 'supports absolute minimum of the SVG specification, it basically can be used as '#13 +
+ 'a simple example of AGG plus SVG. But of course, its functionality can be extended. '#13 +
+ 'The main point of the viewer is high quality and high performance. The Anti-Aliasing '#13 +
+ 'algorithm produces 256 levels of transparency. Actually, AGG computes the exact '#13 +
+ 'coverage of the outline on each pixel cell.'#13#13 +
+
+ 'Besides, the viewer has a very nice feature that I haven''t seen in any other ones. '#13 +
+ 'It''s eliminating of the "problem of adjacent edges". It appears when rendering '#13 +
+ 'adjacent polygons with anti-aliasing and looks like thin "web" upon the image. '#13 +
+ 'Strictly speaking, it''s possible to get rid of it completely only when the polygons '#13 +
+ 'are fully opaque. When they are translucent, the effect will appear anyway. However, '#13 +
+ 'it''s possible to reduce the effect so that it becomes almost invisible.'#13#13 +
+ 'How to play with:'#13#13 +
+ 'Use mouse to move the drawing around. Change size & rotation with top controls.'#13 +
+ 'Press the spacebar key to display and save the current transformation matrix.' );
+
+end;
+
+VAR
+ app : the_application;
+ fname : shortstring;
+ af : api_file;
+
+label
+ Esc ;
+
+BEGIN
+ app.Construct(pix_format_bgra32 ,flip_y );
+
+ fname:=app.file_source('svg' ,'tiger.svg' );
+
+ if param_count > 0 then
+ fname:=param_str(1 )
+
+ else
+ begin
+ if api_open_file(af ,fname ) then
+ api_close_file(af )
+ else
+ begin
+ app.message_('Usage: svg_test <svg_file>' );
+
+ goto Esc;
+
+ end;
+
+ end;
+
+ try
+ app.parse_svg(fname );
+
+ if app.init(512 ,600 ,window_resize ) then
+ app.run;
+
+ except
+ on e:svg_exception do
+ begin
+ app.message_(PChar(e._msg ) );
+ e.Free;
+
+ end;
+
+ else
+ app.message_('Unknown exception' );
+
+ end;
+
+Esc:
+ app.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/times.ttf b/src/corelib/render/software/agg-demos/times.ttf
new file mode 100644
index 00000000..a998feec
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/times.ttf
Binary files differ
diff --git a/src/corelib/render/software/agg-demos/timesi.ttf b/src/corelib/render/software/agg-demos/timesi.ttf
new file mode 100644
index 00000000..28798d3c
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/timesi.ttf
Binary files differ
diff --git a/src/corelib/render/software/agg-demos/trans_curve1.dpr b/src/corelib/render/software/agg-demos/trans_curve1.dpr
new file mode 100644
index 00000000..46dcdd0a
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/trans_curve1.dpr
@@ -0,0 +1,454 @@
+{target:win}
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ trans_curve1 ;
+
+{DEFINE AGG_GRAY8 }
+{$DEFINE AGG_BGR24 }
+{DEFINE AGG_RGB24 }
+{DEFINE AGG_BGRA32 }
+{DEFINE AGG_RGBA32 }
+{DEFINE AGG_ARGB32 }
+{DEFINE AGG_ABGR32 }
+{DEFINE AGG_RGB565 }
+{DEFINE AGG_RGB555 }
+
+uses
+ Windows ,
+
+ agg_basics ,
+ agg_platform_support ,
+
+ agg_ctrl ,
+ agg_cbox_ctrl ,
+ agg_slider_ctrl ,
+
+ agg_rasterizer_scanline_aa ,
+ agg_scanline ,
+ agg_scanline_p ,
+
+ agg_rendering_buffer ,
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_render_scanlines ,
+
+ agg_conv_curve ,
+ agg_conv_transform ,
+ agg_conv_bspline ,
+ agg_conv_segmentator ,
+ agg_conv_stroke ,
+ agg_font_win32_tt ,
+ agg_font_cache_manager ,
+ agg_trans_single_path ,
+ interactive_polygon_
+
+{$I pixel_formats.inc }
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+ text_ : PChar =
+ 'Anti-Grain Geometry is designed as a set of loosely coupled ' +
+ 'algorithms and class templates united with a common idea, ' +
+ 'so that all the components can be easily combined. Also, ' +
+ 'the template based design allows you to replace any part of ' +
+ 'the library without the necessity to modify a single byte in ' +
+ 'the existing code. ';
+
+type
+ the_application = object(platform_support )
+ m_feng : font_engine_win32_tt_int16;
+ m_fman : font_cache_manager;
+ m_poly : interactive_polygon;
+
+ m_num_points : slider_ctrl;
+ m_close ,
+ m_preserve_x_scale ,
+ m_fixed_len ,
+ m_animate : cbox_ctrl;
+
+ m_dx ,
+ m_dy : array[0..5 ] of double;
+
+ m_prev_animate : boolean;
+
+ constructor Construct(dc : HDC; format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure on_init; virtual;
+ procedure on_draw; virtual;
+
+ procedure on_mouse_move (x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_up (x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+ procedure on_ctrl_change; virtual;
+
+ procedure move_point(x ,y ,dx ,dy : double_ptr );
+
+ procedure on_idle; virtual;
+
+ end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_feng.Construct(dc );
+ m_fman.Construct(@m_feng );
+ m_poly.Construct(6 ,5.0 );
+
+ m_num_points.Construct (5.0 ,5.0 ,340.0 ,12.0 ,not flip_y_ );
+ m_close.Construct (350 ,5.0 ,'Close' ,not flip_y_ );
+ m_preserve_x_scale.Construct(460 ,5.0 ,'Preserve X scale' ,not flip_y_ );
+ m_fixed_len.Construct (350 ,25.0 ,'Fixed Length' ,not flip_y_ );
+ m_animate.Construct (460 ,25.0 ,'Animate' ,not flip_y_ );
+
+ m_prev_animate:=false;
+
+ add_ctrl(@m_close );
+ add_ctrl(@m_preserve_x_scale );
+ add_ctrl(@m_fixed_len );
+ add_ctrl(@m_animate );
+
+ m_preserve_x_scale.status_(true );
+ m_fixed_len.status_ (true );
+
+ m_num_points.range_(10.0 ,400.0 );
+ m_num_points.value_(200.0 );
+ m_num_points.label_('Number of intermediate Points = %.3f' );
+
+ add_ctrl(@m_num_points );
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_poly.Destruct;
+
+ m_num_points.Destruct;
+ m_close.Destruct;
+ m_preserve_x_scale.Destruct;
+ m_fixed_len.Destruct;
+ m_animate.Destruct;
+
+ m_feng.Destruct;
+ m_fman.Destruct;
+
+end;
+
+{ ON_INIT }
+procedure the_application.on_init;
+begin
+ m_poly.xn_ptr(0 )^:=50;
+ m_poly.yn_ptr(0 )^:=50;
+ m_poly.xn_ptr(1 )^:=150 + 20;
+ m_poly.yn_ptr(1 )^:=150 - 20;
+ m_poly.xn_ptr(2 )^:=250 - 20;
+ m_poly.yn_ptr(2 )^:=250 + 20;
+ m_poly.xn_ptr(3 )^:=350 + 20;
+ m_poly.yn_ptr(3 )^:=350 - 20;
+ m_poly.xn_ptr(4 )^:=450 - 20;
+ m_poly.yn_ptr(4 )^:=450 + 20;
+ m_poly.xn_ptr(5 )^:=550;
+ m_poly.yn_ptr(5 )^:=550;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ pixf : pixel_formats;
+ rgba : aggclr;
+
+ rb : renderer_base;
+ r : renderer_scanline_aa_solid;
+ sl : scanline_p8;
+
+ ras : rasterizer_scanline_aa;
+
+ path : simple_polygon_vertex_source;
+ bspline : conv_bspline;
+ tcurve : trans_single_path;
+ fcurves : conv_curve;
+ fsegm : conv_segmentator;
+ ftrans : conv_transform;
+
+ x ,y : double;
+
+ p : int8u_ptr;
+
+ glyph : glyph_cache_ptr;
+
+ stroke : conv_stroke;
+
+begin
+// Initialize structures
+ pixfmt(pixf ,rbuf_window );
+
+ rb.Construct(@pixf );
+ r.Construct (@rb );
+
+ rgba.ConstrDbl(1 ,1 ,1 );
+ rb.clear (@rgba );
+
+ sl.Construct;
+ ras.Construct;
+
+ m_poly.close_(m_close._status );
+
+// Render the text
+ path.Construct (m_poly.polygon ,m_poly.num_points ,false ,m_close._status );
+ bspline.Construct(@path );
+
+ bspline.interpolation_step_(1.0 / m_num_points._value );
+
+ tcurve.Construct;
+ tcurve.add_path (@bspline );
+ tcurve.preserve_x_scale_(m_preserve_x_scale._status );
+
+ if m_fixed_len._status then
+ tcurve.base_length_(1120 );
+
+ fcurves.Construct(m_fman.path_adaptor );
+ fsegm.Construct (@fcurves );
+ ftrans.Construct (@fsegm ,@tcurve );
+
+ fsegm.approximation_scale_ (3.0 );
+ fcurves.approximation_scale_(2.0 );
+
+ m_feng.height_(40.0 );
+ //m_feng.italic_(true );
+
+ if m_feng.create_font('Times New Roman' ,glyph_ren_outline ) then
+ begin
+ x:=0.0;
+ y:=3.0;
+ p:=@text_[0 ];
+
+ while p^ <> 0 do
+ begin
+ glyph:=m_fman.glyph(p^ );
+
+ if glyph <> NIL then
+ begin
+ if x > tcurve.total_length then
+ break;
+
+ m_fman.add_kerning (@x ,@y );
+ m_fman.init_embedded_adaptors(glyph ,x ,y );
+
+ if glyph.data_type = glyph_data_outline then
+ begin
+ ras.reset;
+ ras.add_path(@ftrans );
+
+ rgba.ConstrInt(0 ,0 ,0 );
+ r.color_ (@rgba );
+
+ render_scanlines(@ras ,@sl ,@r );
+
+ end;
+
+ // increment pen position
+ x:=x + glyph.advance_x;
+ y:=y + glyph.advance_y;
+
+ end;
+
+ inc(ptrcomp(p ) ,sizeof(int8u ) );
+
+ end;
+
+ end;
+
+// Render the path curve
+ stroke.Construct(@bspline );
+ stroke.width_ (2.0 );
+
+ rgba.ConstrInt(170 ,50 ,20 ,100 );
+ r.color_ (@rgba );
+
+ ras.add_path (@stroke );
+ render_scanlines(@ras ,@sl ,@r );
+
+// Render the "poly" tool
+ rgba.ConstrDbl(0 ,0.3 ,0.5 ,0.3 );
+ r.color_ (@rgba );
+
+ ras.add_path (@m_poly );
+ render_scanlines(@ras ,@sl ,@r );
+
+// Render the controls
+ render_ctrl(@ras ,@sl ,@r ,@m_close );
+ render_ctrl(@ras ,@sl ,@r ,@m_preserve_x_scale );
+ render_ctrl(@ras ,@sl ,@r ,@m_fixed_len );
+ render_ctrl(@ras ,@sl ,@r ,@m_animate );
+ render_ctrl(@ras ,@sl ,@r ,@m_num_points );
+
+// Free AGG resources
+ sl.Destruct;
+ ras.Destruct;
+
+ bspline.Destruct;
+ tcurve.Destruct;
+ fcurves.Destruct;
+ fsegm.Destruct;
+
+ stroke.Destruct;
+
+end;
+
+{ ON_MOUSE_MOVE }
+procedure the_application.on_mouse_move;
+begin
+ if flags and mouse_left <> 0 then
+ if m_poly.on_mouse_move(x ,y ) then
+ force_redraw;
+
+ if flags and mouse_left = 0 then
+ on_mouse_button_up(x ,y ,flags );
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure the_application.on_mouse_button_down;
+begin
+ if flags and mouse_left <> 0 then
+ if m_poly.on_mouse_button_down(x ,y ) then
+ force_redraw;
+
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+procedure the_application.on_mouse_button_up;
+begin
+ if m_poly.on_mouse_button_up(x ,y ) then
+ force_redraw;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ 'This is a "kinda-cool-stuff" demo that performs non-linear transformations and '#13 +
+ 'draws vector text along a curve. Note that it''s not just calculating of the glyph '#13 +
+ 'angles and positions, they are transformed as if they were elastic. The curve is '#13 +
+ 'calculated as a bicubic spline. The option "Preserve X scale" makes the converter '#13 +
+ 'distribute all the points uniformly along the curve. If it''s unchechked, the scale '#13 +
+ 'will be proportional to the distance between the control points.' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+{ ON_CTRL_CHANGE }
+procedure the_application.on_ctrl_change;
+var
+ i : int;
+
+begin
+ if m_animate._status <> m_prev_animate then
+ begin
+ if m_animate._status then
+ begin
+ on_init;
+
+ for i:=0 to 5 do
+ begin
+ m_dx[i ]:=((Random($7fff ) mod 1000 ) - 500 ) * 0.01;
+ m_dy[i ]:=((Random($7fff ) mod 1000 ) - 500 ) * 0.01;
+
+ end;
+
+ wait_mode_(false );
+
+ end
+ else
+ wait_mode_(true );
+
+ m_prev_animate:=m_animate._status;
+
+ end;
+
+end;
+
+{ MOVE_POINT }
+procedure the_application.move_point;
+begin
+ if x^ < 0.0 then
+ begin
+ x^ :=0.0;
+ dx^:=-dx^;
+
+ end;
+
+ if x^ > _width then
+ begin
+ x^ :=_width;
+ dx^:=-dx^;
+
+ end;
+
+ if y^ < 0.0 then
+ begin
+ y^ :=0.0;
+ dy^:=-dy^;
+
+ end;
+
+ if y^ > _height then
+ begin
+ y^ :=_height;
+ dy^:=-dy^;
+
+ end;
+
+ x^:=x^ + dx^;
+ y^:=y^ + dy^;
+
+end;
+
+{ ON_IDLE }
+procedure the_application.on_idle;
+var
+ i : int;
+
+begin
+ for i:=0 to 5 do
+ move_point(m_poly.xn_ptr(i ) ,m_poly.yn_ptr(i ) ,@m_dx[i ] ,@m_dy[i ] );
+
+ force_redraw;
+
+end;
+
+VAR
+ app : the_application;
+ dc : HDC;
+
+BEGIN
+ dc:=GetDC(0 );
+
+ app.Construct(dc ,pix_format ,flip_y );
+ app.caption_ ('AGG Example. Non-linear "Along-A-Curve" Transformer - Win32 (F1-Help)' );
+
+ if app.init(600 ,600 ,window_resize ) then
+ app.run;
+
+ app.Destruct;
+
+ ReleaseDC(0 ,dc );
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/trans_curve1_ft.dpr b/src/corelib/render/software/agg-demos/trans_curve1_ft.dpr
new file mode 100644
index 00000000..a0e883e9
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/trans_curve1_ft.dpr
@@ -0,0 +1,450 @@
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ trans_curve1_ft ;
+
+{DEFINE AGG_GRAY8 }
+{$DEFINE AGG_BGR24 }
+{DEFINE AGG_RGB24 }
+{DEFINE AGG_BGRA32 }
+{DEFINE AGG_RGBA32 }
+{DEFINE AGG_ARGB32 }
+{DEFINE AGG_ABGR32 }
+{DEFINE AGG_RGB565 }
+{DEFINE AGG_RGB555 }
+
+uses
+ agg_basics ,
+ agg_platform_support ,
+
+ agg_ctrl ,
+ agg_cbox_ctrl ,
+ agg_slider_ctrl ,
+
+ agg_rasterizer_scanline_aa ,
+ agg_scanline ,
+ agg_scanline_p ,
+
+ agg_rendering_buffer ,
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_render_scanlines ,
+
+ agg_conv_curve ,
+ agg_conv_transform ,
+ agg_conv_bspline ,
+ agg_conv_segmentator ,
+ agg_conv_stroke ,
+ agg_font_freetype ,
+ agg_font_cache_manager ,
+ agg_trans_single_path ,
+ interactive_polygon_
+
+{$I pixel_formats.inc }
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+ text_ : PChar =
+ 'Anti-Grain Geometry is designed as a set of loosely coupled ' +
+ 'algorithms and class templates united with a common idea, ' +
+ 'so that all the components can be easily combined. Also, ' +
+ 'the template based design allows you to replace any part of ' +
+ 'the library without the necessity to modify a single byte in ' +
+ 'the existing code. ';
+
+type
+ the_application = object(platform_support )
+ m_feng : font_engine_freetype_int16;
+ m_fman : font_cache_manager;
+ m_poly : interactive_polygon;
+
+ m_num_points : slider_ctrl;
+ m_close ,
+ m_preserve_x_scale ,
+ m_fixed_len ,
+ m_animate : cbox_ctrl;
+
+ m_dx ,
+ m_dy : array[0..5 ] of double;
+
+ m_prev_animate : boolean;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure on_init; virtual;
+ procedure on_draw; virtual;
+
+ procedure on_mouse_move (x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_up (x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+ procedure on_ctrl_change; virtual;
+
+ procedure move_point(x ,y ,dx ,dy : double_ptr );
+
+ procedure on_idle; virtual;
+
+ end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_feng.Construct;
+ m_fman.Construct(@m_feng );
+ m_poly.Construct(6 ,5.0 );
+
+ m_num_points.Construct (5.0 ,5.0 ,340.0 ,12.0 ,not flip_y_ );
+ m_close.Construct (350 ,5.0 ,'Close' ,not flip_y_ );
+ m_preserve_x_scale.Construct(460 ,5.0 ,'Preserve X scale' ,not flip_y_ );
+ m_fixed_len.Construct (350 ,25.0 ,'Fixed Length' ,not flip_y_ );
+ m_animate.Construct (460 ,25.0 ,'Animate' ,not flip_y_ );
+
+ m_prev_animate:=false;
+
+ add_ctrl(@m_close );
+ add_ctrl(@m_preserve_x_scale );
+ add_ctrl(@m_fixed_len );
+ add_ctrl(@m_animate );
+
+ m_preserve_x_scale.status_(true );
+ m_fixed_len.status_ (true );
+
+ m_num_points.range_(10.0 ,400.0 );
+ m_num_points.value_(200.0 );
+ m_num_points.label_('Number of intermediate Points = %.3f' );
+
+ add_ctrl(@m_num_points );
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_poly.Destruct;
+
+ m_num_points.Destruct;
+ m_close.Destruct;
+ m_preserve_x_scale.Destruct;
+ m_fixed_len.Destruct;
+ m_animate.Destruct;
+
+ m_feng.Destruct;
+ m_fman.Destruct;
+
+end;
+
+{ ON_INIT }
+procedure the_application.on_init;
+begin
+ m_poly.xn_ptr(0 )^:=50;
+ m_poly.yn_ptr(0 )^:=50;
+ m_poly.xn_ptr(1 )^:=150 + 20;
+ m_poly.yn_ptr(1 )^:=150 - 20;
+ m_poly.xn_ptr(2 )^:=250 - 20;
+ m_poly.yn_ptr(2 )^:=250 + 20;
+ m_poly.xn_ptr(3 )^:=350 + 20;
+ m_poly.yn_ptr(3 )^:=350 - 20;
+ m_poly.xn_ptr(4 )^:=450 - 20;
+ m_poly.yn_ptr(4 )^:=450 + 20;
+ m_poly.xn_ptr(5 )^:=550;
+ m_poly.yn_ptr(5 )^:=550;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ pixf : pixel_formats;
+ rgba : aggclr;
+
+ rb : renderer_base;
+ r : renderer_scanline_aa_solid;
+ sl : scanline_p8;
+
+ ras : rasterizer_scanline_aa;
+
+ path : simple_polygon_vertex_source;
+ bspline : conv_bspline;
+ tcurve : trans_single_path;
+ fcurves : conv_curve;
+ fsegm : conv_segmentator;
+ ftrans : conv_transform;
+
+ x ,y : double;
+
+ p : int8u_ptr;
+
+ glyph : glyph_cache_ptr;
+
+ stroke : conv_stroke;
+
+begin
+// Initialize structures
+ pixfmt(pixf ,rbuf_window );
+
+ rb.Construct(@pixf );
+ r.Construct (@rb );
+
+ rgba.ConstrDbl(1 ,1 ,1 );
+ rb.clear (@rgba );
+
+ sl.Construct;
+ ras.Construct;
+
+ m_poly.close_(m_close._status );
+
+// Render the text
+ path.Construct (m_poly.polygon ,m_poly.num_points ,false ,m_close._status );
+ bspline.Construct(@path );
+
+ bspline.interpolation_step_(1.0 / m_num_points._value );
+
+ tcurve.Construct;
+ tcurve.add_path (@bspline );
+ tcurve.preserve_x_scale_(m_preserve_x_scale._status );
+
+ if m_fixed_len._status then
+ tcurve.base_length_(1120 );
+
+ fcurves.Construct(m_fman.path_adaptor );
+ fsegm.Construct (@fcurves );
+ ftrans.Construct (@fsegm ,@tcurve );
+
+ fsegm.approximation_scale_ (3.0 );
+ fcurves.approximation_scale_(2.0 );
+
+ if m_feng.load_font('timesi.ttf' ,0 ,glyph_ren_outline ) then
+ begin
+ x:=0.0;
+ y:=3.0;
+ p:=@text_[0 ];
+
+ m_feng.hinting_(false );
+ m_feng.height_ (40.0 );
+
+ while p^ <> 0 do
+ begin
+ glyph:=m_fman.glyph(p^ );
+
+ if glyph <> NIL then
+ begin
+ if x > tcurve.total_length then
+ break;
+
+ m_fman.add_kerning (@x ,@y );
+ m_fman.init_embedded_adaptors(glyph ,x ,y );
+
+ if glyph.data_type = glyph_data_outline then
+ begin
+ ras.reset;
+ ras.add_path(@ftrans );
+
+ rgba.ConstrInt(0 ,0 ,0 );
+ r.color_ (@rgba );
+
+ render_scanlines(@ras ,@sl ,@r );
+
+ end;
+
+ // increment pen position
+ x:=x + glyph.advance_x;
+ y:=y + glyph.advance_y;
+
+ end;
+
+ inc(ptrcomp(p ) ,sizeof(int8u ) );
+
+ end;
+
+ end
+ else
+ message_(
+ 'Please copy file timesi.ttf to the current directory'#13 +
+ 'or download it from http://www.antigrain.com/timesi.zip' );
+
+// Render the path curve
+ stroke.Construct(@bspline );
+ stroke.width_ (2.0 );
+
+ rgba.ConstrInt(170 ,50 ,20 ,100 );
+ r.color_ (@rgba );
+
+ ras.add_path (@stroke );
+ render_scanlines(@ras ,@sl ,@r );
+
+// Render the "poly" tool
+ rgba.ConstrDbl(0 ,0.3 ,0.5 ,0.3 );
+ r.color_ (@rgba );
+
+ ras.add_path (@m_poly );
+ render_scanlines(@ras ,@sl ,@r );
+
+// Render the controls
+ render_ctrl(@ras ,@sl ,@r ,@m_close );
+ render_ctrl(@ras ,@sl ,@r ,@m_preserve_x_scale );
+ render_ctrl(@ras ,@sl ,@r ,@m_fixed_len );
+ render_ctrl(@ras ,@sl ,@r ,@m_animate );
+ render_ctrl(@ras ,@sl ,@r ,@m_num_points );
+
+// Free AGG resources
+ sl.Destruct;
+ ras.Destruct;
+
+ bspline.Destruct;
+ tcurve.Destruct;
+ fcurves.Destruct;
+ fsegm.Destruct;
+
+ stroke.Destruct;
+
+end;
+
+{ ON_MOUSE_MOVE }
+procedure the_application.on_mouse_move;
+begin
+ if flags and mouse_left <> 0 then
+ if m_poly.on_mouse_move(x ,y ) then
+ force_redraw;
+
+ if flags and mouse_left = 0 then
+ on_mouse_button_up(x ,y ,flags );
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure the_application.on_mouse_button_down;
+begin
+ if flags and mouse_left <> 0 then
+ if m_poly.on_mouse_button_down(x ,y ) then
+ force_redraw;
+
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+procedure the_application.on_mouse_button_up;
+begin
+ if m_poly.on_mouse_button_up(x ,y ) then
+ force_redraw;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ 'This is a "kinda-cool-stuff" demo that performs non-linear transformations and '#13 +
+ 'draws vector text along a curve. Note that it''s not just calculating of the glyph '#13 +
+ 'angles and positions, they are transformed as if they were elastic. The curve is '#13 +
+ 'calculated as a bicubic spline. The option "Preserve X scale" makes the converter '#13 +
+ 'distribute all the points uniformly along the curve. If it''s unchechked, the scale '#13 +
+ 'will be proportional to the distance between the control points.' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+{ ON_CTRL_CHANGE }
+procedure the_application.on_ctrl_change;
+var
+ i : int;
+
+begin
+ if m_animate._status <> m_prev_animate then
+ begin
+ if m_animate._status then
+ begin
+ on_init;
+
+ for i:=0 to 5 do
+ begin
+ m_dx[i ]:=((Random($7fff ) mod 1000 ) - 500 ) * 0.01;
+ m_dy[i ]:=((Random($7fff ) mod 1000 ) - 500 ) * 0.01;
+
+ end;
+
+ wait_mode_(false );
+
+ end
+ else
+ wait_mode_(true );
+
+ m_prev_animate:=m_animate._status;
+
+ end;
+
+end;
+
+{ MOVE_POINT }
+procedure the_application.move_point;
+begin
+ if x^ < 0.0 then
+ begin
+ x^ :=0.0;
+ dx^:=-dx^;
+
+ end;
+
+ if x^ > _width then
+ begin
+ x^ :=_width;
+ dx^:=-dx^;
+
+ end;
+
+ if y^ < 0.0 then
+ begin
+ y^ :=0.0;
+ dy^:=-dy^;
+
+ end;
+
+ if y^ > _height then
+ begin
+ y^ :=_height;
+ dy^:=-dy^;
+
+ end;
+
+ x^:=x^ + dx^;
+ y^:=y^ + dy^;
+
+end;
+
+{ ON_IDLE }
+procedure the_application.on_idle;
+var
+ i : int;
+
+begin
+ for i:=0 to 5 do
+ move_point(m_poly.xn_ptr(i ) ,m_poly.yn_ptr(i ) ,@m_dx[i ] ,@m_dy[i ] );
+
+ force_redraw;
+
+end;
+
+VAR
+ app : the_application;
+
+BEGIN
+ app.Construct(pix_format ,flip_y );
+ app.caption_ ('AGG Example. Non-linear "Along-A-Curve" Transformer - FreeType (F1-Help)' );
+
+ if app.init(600 ,600 ,window_resize ) then
+ app.run;
+
+ app.Destruct;
+
+END.
diff --git a/src/corelib/render/software/agg-demos/trans_curve2.dpr b/src/corelib/render/software/agg-demos/trans_curve2.dpr
new file mode 100644
index 00000000..7969e069
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/trans_curve2.dpr
@@ -0,0 +1,541 @@
+{target:win}
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ trans_curve2 ;
+
+{DEFINE AGG_GRAY8 }
+{$DEFINE AGG_BGR24 }
+{DEFINE AGG_RGB24 }
+{DEFINE AGG_BGRA32 }
+{DEFINE AGG_RGBA32 }
+{DEFINE AGG_ARGB32 }
+{DEFINE AGG_ABGR32 }
+{DEFINE AGG_RGB565 }
+{DEFINE AGG_RGB555 }
+
+uses
+ Windows ,
+
+ agg_basics ,
+ agg_platform_support ,
+
+ agg_ctrl ,
+ agg_cbox_ctrl ,
+ agg_slider_ctrl ,
+
+ agg_rasterizer_scanline_aa ,
+ agg_scanline ,
+ agg_scanline_p ,
+
+ agg_rendering_buffer ,
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_render_scanlines ,
+
+ agg_math ,
+ agg_conv_curve ,
+ agg_conv_transform ,
+ agg_trans_double_path ,
+ agg_conv_bspline ,
+ agg_conv_segmentator ,
+ agg_conv_stroke ,
+ agg_font_win32_tt ,
+ agg_font_cache_manager ,
+ interactive_polygon_
+
+{$I pixel_formats.inc }
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+ text_ : PChar =
+ 'Anti-Grain Geometry is designed as a set of loosely coupled ' +
+ 'algorithms and class templates united with a common idea, ' +
+ 'so that all the components can be easily combined. Also, ' +
+ 'the template based design allows you to replace any part of ' +
+ 'the library without the necessity to modify a single byte in ' +
+ 'the existing code. ';
+
+type
+ the_application = object(platform_support )
+ m_feng : font_engine_win32_tt_int16;
+ m_fman : font_cache_manager;
+ m_poly1 ,
+ m_poly2 : interactive_polygon;
+
+ m_num_points : slider_ctrl;
+ m_fixed_len ,
+ m_preserve_x_scale ,
+ m_animate : cbox_ctrl;
+
+ m_dx1 ,
+ m_dy1 ,
+ m_dx2 ,
+ m_dy2 : array[0..5 ] of double;
+
+ m_prev_animate : boolean;
+
+ constructor Construct(dc : HDC; format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure on_init; virtual;
+ procedure on_draw; virtual;
+
+ procedure on_mouse_move (x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_up (x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+ procedure on_ctrl_change; virtual;
+
+ procedure move_point (x ,y ,dx ,dy : double_ptr );
+ procedure normalize_point(i : unsigned );
+
+ procedure on_idle; virtual;
+
+ end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_feng.Construct (dc );
+ m_fman.Construct (@m_feng );
+ m_poly1.Construct(6 ,5.0 );
+ m_poly2.Construct(6 ,5.0 );
+
+ m_num_points.Construct (5.0 ,5.0 ,340.0 ,12.0 ,not flip_y_ );
+ m_fixed_len.Construct (350 ,5.0 ,'Fixed Length' ,not flip_y_ );
+ m_preserve_x_scale.Construct(465 ,5.0 ,'Preserve X scale' ,not flip_y_ );
+ m_animate.Construct (350 ,25.0 ,'Animate' ,not flip_y_ );
+
+ m_prev_animate:=false;
+
+ add_ctrl(@m_fixed_len );
+ add_ctrl(@m_preserve_x_scale );
+ add_ctrl(@m_animate );
+
+ m_fixed_len.status_ (true );
+ m_preserve_x_scale.status_(true );
+
+ m_num_points.range_(10.0 ,400.0 );
+ m_num_points.value_(200.0 );
+ m_num_points.label_('Number of intermediate Points = %.3f' );
+
+ add_ctrl(@m_num_points );
+
+ m_poly1.close_(false );
+ m_poly2.close_(false );
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_num_points.Destruct;
+ m_fixed_len.Destruct;
+ m_preserve_x_scale.Destruct;
+ m_animate.Destruct;
+
+ m_poly1.Destruct;
+ m_poly2.Destruct;
+
+ m_feng.Destruct;
+ m_fman.Destruct;
+
+end;
+
+{ ON_INIT }
+procedure the_application.on_init;
+begin
+ m_poly1.xn_ptr(0 )^:= 10 + 50;
+ m_poly1.yn_ptr(0 )^:=-10 + 50;
+ m_poly1.xn_ptr(1 )^:= 10 + 150 + 20;
+ m_poly1.yn_ptr(1 )^:=-10 + 150 - 20;
+ m_poly1.xn_ptr(2 )^:= 10 + 250 - 20;
+ m_poly1.yn_ptr(2 )^:=-10 + 250 + 20;
+ m_poly1.xn_ptr(3 )^:= 10 + 350 + 20;
+ m_poly1.yn_ptr(3 )^:=-10 + 350 - 20;
+ m_poly1.xn_ptr(4 )^:= 10 + 450 - 20;
+ m_poly1.yn_ptr(4 )^:=-10 + 450 + 20;
+ m_poly1.xn_ptr(5 )^:= 10 + 550;
+ m_poly1.yn_ptr(5 )^:=-10 + 550;
+
+ m_poly2.xn_ptr(0 )^:=-10 + 50;
+ m_poly2.yn_ptr(0 )^:= 10 + 50;
+ m_poly2.xn_ptr(1 )^:=-10 + 150 + 20;
+ m_poly2.yn_ptr(1 )^:= 10 + 150 - 20;
+ m_poly2.xn_ptr(2 )^:=-10 + 250 - 20;
+ m_poly2.yn_ptr(2 )^:= 10 + 250 + 20;
+ m_poly2.xn_ptr(3 )^:=-10 + 350 + 20;
+ m_poly2.yn_ptr(3 )^:= 10 + 350 - 20;
+ m_poly2.xn_ptr(4 )^:=-10 + 450 - 20;
+ m_poly2.yn_ptr(4 )^:= 10 + 450 + 20;
+ m_poly2.xn_ptr(5 )^:=-10 + 550;
+ m_poly2.yn_ptr(5 )^:= 10 + 550;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ pixf : pixel_formats;
+ rgba : aggclr;
+
+ rb : renderer_base;
+ r : renderer_scanline_aa_solid;
+ sl : scanline_p8;
+
+ ras : rasterizer_scanline_aa;
+
+ path1 ,
+ path2 : simple_polygon_vertex_source;
+
+ bspline1 ,
+ bspline2 : conv_bspline;
+
+ tcurve : trans_double_path;
+ fcurves : conv_curve;
+ fsegm : conv_segmentator;
+ ftrans : conv_transform;
+
+ x ,y : double;
+
+ p : int8u_ptr;
+
+ glyph : glyph_cache_ptr;
+
+ stroke1 ,
+ stroke2 : conv_stroke;
+
+begin
+// Initialize structures
+ pixfmt(pixf ,rbuf_window );
+
+ rb.Construct(@pixf );
+ r.Construct (@rb );
+
+ rgba.ConstrDbl(1 ,1 ,1 );
+ rb.clear (@rgba );
+
+ sl.Construct;
+ ras.Construct;
+
+// Render the text
+ path1.Construct(m_poly1.polygon ,m_poly1.num_points ,false ,false );
+ path2.Construct(m_poly2.polygon ,m_poly2.num_points ,false ,false );
+
+ bspline1.Construct(@path1 );
+ bspline2.Construct(@path2 );
+
+ bspline1.interpolation_step_(1.0 / m_num_points._value );
+ bspline2.interpolation_step_(1.0 / m_num_points._value );
+
+ tcurve.Construct;
+ fcurves.Construct(m_fman.path_adaptor );
+ fsegm.Construct (@fcurves);
+ ftrans.Construct (@fsegm ,@tcurve );
+
+ tcurve.preserve_x_scale_(m_preserve_x_scale._status );
+
+ if m_fixed_len._status then
+ tcurve.base_length_(1140.0 );
+
+ tcurve.base_height_(30.0 );
+ tcurve.add_paths (@bspline1 ,@bspline2 );
+
+ fsegm.approximation_scale_ (3.0 );
+ fcurves.approximation_scale_(5.0 );
+
+ m_feng.height_ (40.0 );
+ m_feng.hinting_(false );
+ m_feng.italic_ (true );
+
+ if m_feng.create_font('Times New Roman' ,glyph_ren_outline ) then
+ begin
+ x:=0.0;
+ y:=3.0;
+ p:=@text_[0 ];
+
+ while p^ <> 0 do
+ begin
+ glyph:=m_fman.glyph(p^ );
+
+ if glyph <> NIL then
+ begin
+ if x > tcurve.total_length1 then
+ break;
+
+ m_fman.add_kerning (@x ,@y );
+ m_fman.init_embedded_adaptors(glyph ,x ,y );
+
+ if glyph.data_type = glyph_data_outline then
+ begin
+ ras.reset;
+ ras.add_path(@ftrans );
+
+ rgba.ConstrInt(0 ,0 ,0 );
+ r.color_ (@rgba );
+
+ render_scanlines(@ras ,@sl ,@r );
+
+ end;
+
+ // increment pen position
+ x:=x + glyph.advance_x;
+ y:=y + glyph.advance_y;
+
+ end;
+
+ inc(ptrcomp(p ) ,sizeof(int8u ) );
+
+ end;
+
+ end;
+
+// Render the path curve
+ stroke1.Construct(@bspline1 );
+ stroke2.Construct(@bspline2 );
+
+ stroke1.width_(2.0 );
+ stroke2.width_(2.0 );
+
+ rgba.ConstrInt(170 ,50 ,20 ,100 );
+ r.color_ (@rgba );
+
+ ras.add_path (@stroke1 );
+ render_scanlines(@ras ,@sl ,@r );
+
+ ras.add_path (@stroke2);
+ render_scanlines(@ras ,@sl ,@r );
+
+// Render the "poly" tool
+ rgba.ConstrDbl(0 ,0.3 ,0.5 ,0.2 );
+ r.color_ (@rgba );
+
+ ras.add_path (@m_poly1 );
+ render_scanlines(@ras ,@sl ,@r );
+
+ ras.add_path (@m_poly2 );
+ render_scanlines(@ras ,@sl ,@r );
+
+// Render the controls
+ render_ctrl(@ras ,@sl ,@r ,@m_fixed_len );
+ render_ctrl(@ras ,@sl ,@r ,@m_preserve_x_scale );
+ render_ctrl(@ras ,@sl ,@r ,@m_animate );
+ render_ctrl(@ras ,@sl ,@r ,@m_num_points );
+
+// Free AGG resources
+ sl.Destruct;
+ ras.Destruct;
+
+ bspline1.Destruct;
+ bspline2.Destruct;
+ tcurve.Destruct;
+ fcurves.Destruct;
+ fsegm.Destruct;
+
+ stroke1.Destruct;
+ stroke2.Destruct;
+
+end;
+
+{ ON_MOUSE_MOVE }
+procedure the_application.on_mouse_move;
+begin
+ if flags and mouse_left <> 0 then
+ begin
+ if m_poly1.on_mouse_move(x ,y ) then
+ force_redraw;
+
+ if m_poly2.on_mouse_move(x ,y ) then
+ force_redraw;
+
+ end;
+
+ if flags and mouse_left = 0 then
+ on_mouse_button_up(x ,y ,flags );
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure the_application.on_mouse_button_down;
+begin
+ if flags and mouse_left <> 0 then
+ begin
+ if m_poly1.on_mouse_button_down(x ,y ) then
+ force_redraw;
+
+ if m_poly2.on_mouse_button_down(x ,y ) then
+ force_redraw;
+
+ end;
+
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+procedure the_application.on_mouse_button_up;
+begin
+ if m_poly1.on_mouse_button_up(x ,y ) then
+ force_redraw;
+
+ if m_poly2.on_mouse_button_up(x ,y ) then
+ force_redraw;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ 'Similar to the "trans_curve1" demo, but here the transformer operates with two '#13 +
+ 'arbitrary curves. It requires more calculations, but gives you more freedom. '#13 +
+ 'In other words you will see :-).' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+{ ON_CTRL_CHANGE }
+procedure the_application.on_ctrl_change;
+var
+ i : int;
+
+begin
+ if m_animate._status <> m_prev_animate then
+ begin
+ if m_animate._status then
+ begin
+ on_init;
+
+ for i:=0 to 5 do
+ begin
+ m_dx1[i ]:=((Random($7fff ) mod 1000 ) - 500 ) * 0.01;
+ m_dy1[i ]:=((Random($7fff ) mod 1000 ) - 500 ) * 0.01;
+ m_dx2[i ]:=((Random($7fff ) mod 1000 ) - 500 ) * 0.01;
+ m_dy2[i ]:=((Random($7fff ) mod 1000 ) - 500 ) * 0.01;
+
+ end;
+
+ wait_mode_(false );
+
+ end
+ else
+ wait_mode_(true );
+
+ m_prev_animate:=m_animate._status;
+
+ end;
+
+end;
+
+{ MOVE_POINT }
+procedure the_application.move_point;
+begin
+ if x^ < 0.0 then
+ begin
+ x^ :=0.0;
+ dx^:=-dx^;
+
+ end;
+
+ if x^ > _width then
+ begin
+ x^ :=_width;
+ dx^:=-dx^;
+
+ end;
+
+ if y^ < 0.0 then
+ begin
+ y^ :=0.0;
+ dy^:=-dy^;
+
+ end;
+
+ if y^ > _height then
+ begin
+ y^ :=_height;
+ dy^:=-dy^;
+
+ end;
+
+ x^:=x^ + dx^;
+ y^:=y^ + dy^;
+
+end;
+
+{ NORMALIZE_POINT }
+procedure the_application.normalize_point;
+var
+ d : double;
+
+begin
+ d:=
+ calc_distance(
+ m_poly1.xn_ptr(i )^ ,m_poly1.yn_ptr(i )^ ,
+ m_poly2.xn_ptr(i )^ ,m_poly2.yn_ptr(i )^ );
+
+// 28.8 is 20 * sqrt(2)
+ if d > 28.28 then
+ begin
+ m_poly2.xn_ptr(i )^:=
+ m_poly1.xn_ptr(i )^ +
+ (m_poly2.xn_ptr(i )^ -
+ m_poly1.xn_ptr(i )^ ) * 28.28 / d;
+
+ m_poly2.yn_ptr(i )^:=
+ m_poly1.yn_ptr(i )^ +
+ (m_poly2.yn_ptr(i )^ -
+ m_poly1.yn_ptr(i )^ ) * 28.28 / d;
+
+ end;
+
+end;
+
+{ ON_IDLE }
+procedure the_application.on_idle;
+var
+ i : int;
+
+begin
+ for i:=0 to 5 do
+ begin
+ move_point(m_poly1.xn_ptr(i ) ,m_poly1.yn_ptr(i ) ,@m_dx1[i ] ,@m_dy1[i ] );
+ move_point(m_poly2.xn_ptr(i ) ,m_poly2.yn_ptr(i ) ,@m_dx2[i ] ,@m_dy2[i ] );
+
+ normalize_point(i);
+
+ end;
+
+ force_redraw;
+
+end;
+
+VAR
+ app : the_application;
+ dc : HDC;
+
+BEGIN
+ dc:=GetDC(0 );
+
+ app.Construct(dc ,pix_format ,flip_y );
+ app.caption_ ('AGG Example. Non-linear "Along-A-Curve" Transformer - Win32 (F1-Help)' );
+
+ if app.init(600 ,600 ,window_resize ) then
+ app.run;
+
+ app.Destruct;
+
+ ReleaseDC(0 ,dc );
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/trans_curve2_ft.dpr b/src/corelib/render/software/agg-demos/trans_curve2_ft.dpr
new file mode 100644
index 00000000..1fbeec1b
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/trans_curve2_ft.dpr
@@ -0,0 +1,536 @@
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ trans_curve2_ft ;
+
+{DEFINE AGG_GRAY8 }
+{$DEFINE AGG_BGR24 }
+{DEFINE AGG_RGB24 }
+{DEFINE AGG_BGRA32 }
+{DEFINE AGG_RGBA32 }
+{DEFINE AGG_ARGB32 }
+{DEFINE AGG_ABGR32 }
+{DEFINE AGG_RGB565 }
+{DEFINE AGG_RGB555 }
+
+uses
+ agg_basics ,
+ agg_platform_support ,
+
+ agg_ctrl ,
+ agg_cbox_ctrl ,
+ agg_slider_ctrl ,
+
+ agg_rasterizer_scanline_aa ,
+ agg_scanline ,
+ agg_scanline_p ,
+
+ agg_rendering_buffer ,
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_render_scanlines ,
+
+ agg_math ,
+ agg_conv_curve ,
+ agg_conv_transform ,
+ agg_trans_double_path ,
+ agg_conv_bspline ,
+ agg_conv_segmentator ,
+ agg_conv_stroke ,
+ agg_font_freetype ,
+ agg_font_cache_manager ,
+ interactive_polygon_
+
+{$I pixel_formats.inc }
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+ text_ : PChar =
+ 'Anti-Grain Geometry is designed as a set of loosely coupled ' +
+ 'algorithms and class templates united with a common idea, ' +
+ 'so that all the components can be easily combined. Also, ' +
+ 'the template based design allows you to replace any part of ' +
+ 'the library without the necessity to modify a single byte in ' +
+ 'the existing code. ';
+
+type
+ the_application = object(platform_support )
+ m_feng : font_engine_freetype_int16;
+ m_fman : font_cache_manager;
+ m_poly1 ,
+ m_poly2 : interactive_polygon;
+
+ m_num_points : slider_ctrl;
+ m_fixed_len ,
+ m_preserve_x_scale ,
+ m_animate : cbox_ctrl;
+
+ m_dx1 ,
+ m_dy1 ,
+ m_dx2 ,
+ m_dy2 : array[0..5 ] of double;
+
+ m_prev_animate : boolean;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure on_init; virtual;
+ procedure on_draw; virtual;
+
+ procedure on_mouse_move (x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_up (x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+ procedure on_ctrl_change; virtual;
+
+ procedure move_point (x ,y ,dx ,dy : double_ptr );
+ procedure normalize_point(i : unsigned );
+
+ procedure on_idle; virtual;
+
+ end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_feng.Construct;
+ m_fman.Construct (@m_feng );
+ m_poly1.Construct(6 ,5.0 );
+ m_poly2.Construct(6 ,5.0 );
+
+ m_num_points.Construct (5.0 ,5.0 ,340.0 ,12.0 ,not flip_y_ );
+ m_fixed_len.Construct (350 ,5.0 ,'Fixed Length' ,not flip_y_ );
+ m_preserve_x_scale.Construct(465 ,5.0 ,'Preserve X scale' ,not flip_y_ );
+ m_animate.Construct (350 ,25.0 ,'Animate' ,not flip_y_ );
+
+ m_prev_animate:=false;
+
+ add_ctrl(@m_fixed_len );
+ add_ctrl(@m_preserve_x_scale );
+ add_ctrl(@m_animate );
+
+ m_fixed_len.status_ (true );
+ m_preserve_x_scale.status_(true );
+
+ m_num_points.range_(10.0 ,400.0 );
+ m_num_points.value_(200.0 );
+ m_num_points.label_('Number of intermediate Points = %.3f' );
+
+ add_ctrl(@m_num_points );
+
+ m_poly1.close_(false );
+ m_poly2.close_(false );
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_num_points.Destruct;
+ m_fixed_len.Destruct;
+ m_preserve_x_scale.Destruct;
+ m_animate.Destruct;
+
+ m_poly1.Destruct;
+ m_poly2.Destruct;
+
+ m_feng.Destruct;
+ m_fman.Destruct;
+
+end;
+
+{ ON_INIT }
+procedure the_application.on_init;
+begin
+ m_poly1.xn_ptr(0 )^:= 10 + 50;
+ m_poly1.yn_ptr(0 )^:=-10 + 50;
+ m_poly1.xn_ptr(1 )^:= 10 + 150 + 20;
+ m_poly1.yn_ptr(1 )^:=-10 + 150 - 20;
+ m_poly1.xn_ptr(2 )^:= 10 + 250 - 20;
+ m_poly1.yn_ptr(2 )^:=-10 + 250 + 20;
+ m_poly1.xn_ptr(3 )^:= 10 + 350 + 20;
+ m_poly1.yn_ptr(3 )^:=-10 + 350 - 20;
+ m_poly1.xn_ptr(4 )^:= 10 + 450 - 20;
+ m_poly1.yn_ptr(4 )^:=-10 + 450 + 20;
+ m_poly1.xn_ptr(5 )^:= 10 + 550;
+ m_poly1.yn_ptr(5 )^:=-10 + 550;
+
+ m_poly2.xn_ptr(0 )^:=-10 + 50;
+ m_poly2.yn_ptr(0 )^:= 10 + 50;
+ m_poly2.xn_ptr(1 )^:=-10 + 150 + 20;
+ m_poly2.yn_ptr(1 )^:= 10 + 150 - 20;
+ m_poly2.xn_ptr(2 )^:=-10 + 250 - 20;
+ m_poly2.yn_ptr(2 )^:= 10 + 250 + 20;
+ m_poly2.xn_ptr(3 )^:=-10 + 350 + 20;
+ m_poly2.yn_ptr(3 )^:= 10 + 350 - 20;
+ m_poly2.xn_ptr(4 )^:=-10 + 450 - 20;
+ m_poly2.yn_ptr(4 )^:= 10 + 450 + 20;
+ m_poly2.xn_ptr(5 )^:=-10 + 550;
+ m_poly2.yn_ptr(5 )^:= 10 + 550;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ pixf : pixel_formats;
+ rgba : aggclr;
+
+ rb : renderer_base;
+ r : renderer_scanline_aa_solid;
+ sl : scanline_p8;
+
+ ras : rasterizer_scanline_aa;
+
+ path1 ,
+ path2 : simple_polygon_vertex_source;
+
+ bspline1 ,
+ bspline2 : conv_bspline;
+
+ tcurve : trans_double_path;
+ fcurves : conv_curve;
+ fsegm : conv_segmentator;
+ ftrans : conv_transform;
+
+ x ,y : double;
+
+ p : int8u_ptr;
+
+ glyph : glyph_cache_ptr;
+
+ stroke1 ,
+ stroke2 : conv_stroke;
+
+begin
+// Initialize structures
+ pixfmt(pixf ,rbuf_window );
+
+ rb.Construct(@pixf );
+ r.Construct (@rb );
+
+ rgba.ConstrDbl(1 ,1 ,1 );
+ rb.clear (@rgba );
+
+ sl.Construct;
+ ras.Construct;
+
+// Render the text
+ path1.Construct(m_poly1.polygon ,m_poly1.num_points ,false ,false );
+ path2.Construct(m_poly2.polygon ,m_poly2.num_points ,false ,false );
+
+ bspline1.Construct(@path1 );
+ bspline2.Construct(@path2 );
+
+ bspline1.interpolation_step_(1.0 / m_num_points._value );
+ bspline2.interpolation_step_(1.0 / m_num_points._value );
+
+ tcurve.Construct;
+ fcurves.Construct(m_fman.path_adaptor );
+ fsegm.Construct (@fcurves);
+ ftrans.Construct (@fsegm ,@tcurve );
+
+ tcurve.preserve_x_scale_(m_preserve_x_scale._status );
+
+ if m_fixed_len._status then
+ tcurve.base_length_(1140.0 );
+
+ tcurve.base_height_(30.0 );
+ tcurve.add_paths (@bspline1 ,@bspline2 );
+
+ fsegm.approximation_scale_ (3.0 );
+ fcurves.approximation_scale_(5.0 );
+
+ if m_feng.load_font('timesi.ttf' ,0 ,glyph_ren_outline ) then
+ begin
+ x:=0.0;
+ y:=3.0;
+ p:=@text_[0 ];
+
+ m_feng.hinting_(false );
+ m_feng.height_ (40.0 );
+
+ while p^ <> 0 do
+ begin
+ glyph:=m_fman.glyph(p^ );
+
+ if glyph <> NIL then
+ begin
+ if x > tcurve.total_length1 then
+ break;
+
+ m_fman.add_kerning (@x ,@y );
+ m_fman.init_embedded_adaptors(glyph ,x ,y );
+
+ if glyph.data_type = glyph_data_outline then
+ begin
+ ras.reset;
+ ras.add_path(@ftrans );
+
+ rgba.ConstrInt(0 ,0 ,0 );
+ r.color_ (@rgba );
+
+ render_scanlines(@ras ,@sl ,@r );
+
+ end;
+
+ // increment pen position
+ x:=x + glyph.advance_x;
+ y:=y + glyph.advance_y;
+
+ end;
+
+ inc(ptrcomp(p ) ,sizeof(int8u ) );
+
+ end;
+
+ end
+ else
+ message_(
+ 'Please copy file timesi.ttf to the current directory'#13 +
+ 'or download it from http://www.antigrain.com/timesi.zip' );
+
+// Render the path curve
+ stroke1.Construct(@bspline1 );
+ stroke2.Construct(@bspline2 );
+
+ stroke1.width_(2.0 );
+ stroke2.width_(2.0 );
+
+ rgba.ConstrInt(170 ,50 ,20 ,100 );
+ r.color_ (@rgba );
+
+ ras.add_path (@stroke1 );
+ render_scanlines(@ras ,@sl ,@r );
+
+ ras.add_path (@stroke2);
+ render_scanlines(@ras ,@sl ,@r );
+
+// Render the "poly" tool
+ rgba.ConstrDbl(0 ,0.3 ,0.5 ,0.2 );
+ r.color_ (@rgba );
+
+ ras.add_path (@m_poly1 );
+ render_scanlines(@ras ,@sl ,@r );
+
+ ras.add_path (@m_poly2 );
+ render_scanlines(@ras ,@sl ,@r );
+
+// Render the controls
+ render_ctrl(@ras ,@sl ,@r ,@m_fixed_len );
+ render_ctrl(@ras ,@sl ,@r ,@m_preserve_x_scale );
+ render_ctrl(@ras ,@sl ,@r ,@m_animate );
+ render_ctrl(@ras ,@sl ,@r ,@m_num_points );
+
+// Free AGG resources
+ sl.Destruct;
+ ras.Destruct;
+
+ bspline1.Destruct;
+ bspline2.Destruct;
+ tcurve.Destruct;
+ fcurves.Destruct;
+ fsegm.Destruct;
+
+ stroke1.Destruct;
+ stroke2.Destruct;
+
+end;
+
+{ ON_MOUSE_MOVE }
+procedure the_application.on_mouse_move;
+begin
+ if flags and mouse_left <> 0 then
+ begin
+ if m_poly1.on_mouse_move(x ,y ) then
+ force_redraw;
+
+ if m_poly2.on_mouse_move(x ,y ) then
+ force_redraw;
+
+ end;
+
+ if flags and mouse_left = 0 then
+ on_mouse_button_up(x ,y ,flags );
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure the_application.on_mouse_button_down;
+begin
+ if flags and mouse_left <> 0 then
+ begin
+ if m_poly1.on_mouse_button_down(x ,y ) then
+ force_redraw;
+
+ if m_poly2.on_mouse_button_down(x ,y ) then
+ force_redraw;
+
+ end;
+
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+procedure the_application.on_mouse_button_up;
+begin
+ if m_poly1.on_mouse_button_up(x ,y ) then
+ force_redraw;
+
+ if m_poly2.on_mouse_button_up(x ,y ) then
+ force_redraw;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ 'Similar to the "trans_curve1" demo, but here the transformer operates with two '#13 +
+ 'arbitrary curves. It requires more calculations, but gives you more freedom. '#13 +
+ 'In other words you will see :-).' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+{ ON_CTRL_CHANGE }
+procedure the_application.on_ctrl_change;
+var
+ i : int;
+
+begin
+ if m_animate._status <> m_prev_animate then
+ begin
+ if m_animate._status then
+ begin
+ on_init;
+
+ for i:=0 to 5 do
+ begin
+ m_dx1[i ]:=((Random($7fff ) mod 1000 ) - 500 ) * 0.01;
+ m_dy1[i ]:=((Random($7fff ) mod 1000 ) - 500 ) * 0.01;
+ m_dx2[i ]:=((Random($7fff ) mod 1000 ) - 500 ) * 0.01;
+ m_dy2[i ]:=((Random($7fff ) mod 1000 ) - 500 ) * 0.01;
+
+ end;
+
+ wait_mode_(false );
+
+ end
+ else
+ wait_mode_(true );
+
+ m_prev_animate:=m_animate._status;
+
+ end;
+
+end;
+
+{ MOVE_POINT }
+procedure the_application.move_point;
+begin
+ if x^ < 0.0 then
+ begin
+ x^ :=0.0;
+ dx^:=-dx^;
+
+ end;
+
+ if x^ > _width then
+ begin
+ x^ :=_width;
+ dx^:=-dx^;
+
+ end;
+
+ if y^ < 0.0 then
+ begin
+ y^ :=0.0;
+ dy^:=-dy^;
+
+ end;
+
+ if y^ > _height then
+ begin
+ y^ :=_height;
+ dy^:=-dy^;
+
+ end;
+
+ x^:=x^ + dx^;
+ y^:=y^ + dy^;
+
+end;
+
+{ NORMALIZE_POINT }
+procedure the_application.normalize_point;
+var
+ d : double;
+
+begin
+ d:=
+ calc_distance(
+ m_poly1.xn_ptr(i )^ ,m_poly1.yn_ptr(i )^ ,
+ m_poly2.xn_ptr(i )^ ,m_poly2.yn_ptr(i )^ );
+
+// 28.8 is 20 * sqrt(2)
+ if d > 28.28 then
+ begin
+ m_poly2.xn_ptr(i )^:=
+ m_poly1.xn_ptr(i )^ +
+ (m_poly2.xn_ptr(i )^ -
+ m_poly1.xn_ptr(i )^ ) * 28.28 / d;
+
+ m_poly2.yn_ptr(i )^:=
+ m_poly1.yn_ptr(i )^ +
+ (m_poly2.yn_ptr(i )^ -
+ m_poly1.yn_ptr(i )^ ) * 28.28 / d;
+
+ end;
+
+end;
+
+{ ON_IDLE }
+procedure the_application.on_idle;
+var
+ i : int;
+
+begin
+ for i:=0 to 5 do
+ begin
+ move_point(m_poly1.xn_ptr(i ) ,m_poly1.yn_ptr(i ) ,@m_dx1[i ] ,@m_dy1[i ] );
+ move_point(m_poly2.xn_ptr(i ) ,m_poly2.yn_ptr(i ) ,@m_dx2[i ] ,@m_dy2[i ] );
+
+ normalize_point(i);
+
+ end;
+
+ force_redraw;
+
+end;
+
+VAR
+ app : the_application;
+
+BEGIN
+ app.Construct(pix_format ,flip_y );
+ app.caption_ ('AGG Example. Non-linear "Along-A-Curve" Transformer - FreeType (F1-Help)' );
+
+ if app.init(600 ,600 ,window_resize ) then
+ app.run;
+
+ app.Destruct;
+
+END.
diff --git a/src/corelib/render/software/agg-demos/trans_polar.dpr b/src/corelib/render/software/agg-demos/trans_polar.dpr
new file mode 100644
index 00000000..00e1fe9d
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/trans_polar.dpr
@@ -0,0 +1,324 @@
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ trans_polar_ ;
+
+uses
+ agg_basics ,
+ agg_platform_support ,
+ agg_color ,
+ agg_pixfmt ,
+ agg_pixfmt_rgb ,
+
+ agg_ctrl ,
+ agg_slider_ctrl ,
+ agg_cbox_ctrl ,
+
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_rasterizer_scanline_aa ,
+ agg_scanline_u ,
+ agg_render_scanlines ,
+
+ agg_conv_transform ,
+ agg_conv_segmentator ,
+ agg_vertex_source ,
+ agg_trans_affine ;
+
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+type
+ transformed_control = object(ctrl )
+ m_ctrl : ctrl_ptr;
+ m_pipeline : vertex_source_ptr;
+
+ constructor Construct(ctrl : ctrl_ptr; pl : vertex_source_ptr );
+
+ function num_paths : unsigned; virtual;
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+ function _color(i : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+ trans_polar_ptr = ^trans_polar;
+ trans_polar = object(trans_affine )
+ m_base_angle ,
+ m_base_scale ,
+
+ m_base_x ,
+ m_base_y ,
+
+ m_translation_x ,
+ m_translation_y ,
+
+ m_spiral : double;
+
+ constructor Construct;
+
+ procedure base_scale (v : double );
+ procedure full_circle(v : double );
+ procedure base_offset(dx ,dy : double );
+ procedure translation(dx ,dy : double );
+ procedure spiral (v : double );
+
+ end;
+
+ the_application = object(platform_support )
+ m_slider1 ,
+ m_slider_spiral ,
+ m_slider_base_y : slider_ctrl;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ procedure on_draw; virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+
+ end;
+
+{ CONSTRUCT }
+constructor transformed_control.Construct;
+begin
+ m_ctrl :=ctrl;
+ m_pipeline:=pl;
+
+end;
+
+{ NUM_PATHS }
+function transformed_control.num_paths;
+begin
+ result:=m_ctrl.num_paths;
+
+end;
+
+{ REWIND }
+procedure transformed_control.rewind;
+begin
+ m_pipeline.rewind(path_id );
+
+end;
+
+{ VERTEX }
+function transformed_control.vertex;
+begin
+ result:=m_pipeline.vertex(x ,y );
+
+end;
+
+{ _COLOR }
+function transformed_control._color;
+begin
+ result:=m_ctrl._color(i );
+
+end;
+
+{ trans_polar_transform }
+procedure trans_polar_transform(this : trans_polar_ptr; x ,y : double_ptr );
+var
+ x1 ,y1 : double;
+
+begin
+ x1:=(x^ + this.m_base_x ) * this.m_base_angle;
+ y1:=(y^ + this.m_base_y ) * this.m_base_scale + (x^ * this.m_spiral );
+
+ x^:=Cos(x1 ) * y1 + this.m_translation_x;
+ y^:=Sin(x1 ) * y1 + this.m_translation_y;
+
+end;
+
+{ CONSTRUCT }
+constructor trans_polar.Construct;
+begin
+ inherited Construct;
+
+ m_base_angle:=1.0;
+ m_base_scale:=1.0;
+
+ m_base_x:=0.0;
+ m_base_y:=0.0;
+
+ m_translation_x:=0.0;
+ m_translation_y:=0.0;
+
+ m_spiral:=0.0;
+
+ transform:=@trans_polar_transform;
+
+end;
+
+{ BASE_SCALE }
+procedure trans_polar.base_scale;
+begin
+ m_base_scale:=v;
+
+end;
+
+{ FULL_CIRCLE }
+procedure trans_polar.full_circle;
+begin
+ m_base_angle:=2.0 * pi / v;
+
+end;
+
+{ BASE_OFFSET }
+procedure trans_polar.base_offset;
+begin
+ m_base_x:=dx;
+ m_base_y:=dy;
+
+end;
+
+{ TRANSLATION }
+procedure trans_polar.translation;
+begin
+ m_translation_x:=dx;
+ m_translation_y:=dy;
+
+end;
+
+{ SPIRAL }
+procedure trans_polar.spiral;
+begin
+ m_spiral:=v;
+
+end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_slider1.Construct (10 ,10 ,600 - 10 ,17 ,not flip_y_ );
+ m_slider_spiral.Construct(10 ,10 + 20 ,600 - 10 ,17 + 20 ,not flip_y_ );
+ m_slider_base_y.Construct(10 ,10 + 40 ,600 - 10 ,17 + 40 ,not flip_y_ );
+
+ add_ctrl(@m_slider1 );
+
+ m_slider1.range_ (0.0 ,100.0 );
+ m_slider1.num_steps_(5 );
+ m_slider1.value_ (32.0);
+ m_slider1.label_ ('Some Value=%1.0f' );
+
+ add_ctrl(@m_slider_spiral );
+
+ m_slider_spiral.label_('Spiral=%.3f' );
+ m_slider_spiral.range_(-0.1 ,0.1 );
+ m_slider_spiral.value_(0.0 );
+
+ add_ctrl(@m_slider_base_y );
+
+ m_slider_base_y.label_('Base Y=%.3f' );
+ m_slider_base_y.range_(50.0 ,200.0 );
+ m_slider_base_y.value_(120.0 );
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_slider1.Destruct;
+ m_slider_spiral.Destruct;
+ m_slider_base_y.Destruct;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ pixf : pixel_formats;
+
+ rb : renderer_base;
+ ren : renderer_scanline_aa_solid;
+ ras : rasterizer_scanline_aa;
+ sl : scanline_u8;
+
+ rgba : aggclr;
+ trans : trans_polar;
+ segm : conv_segmentator;
+
+ pipeline : conv_transform;
+
+ ctrl : transformed_control;
+
+begin
+// Initialize structures
+ pixfmt_bgr24(pixf ,rbuf_window );
+
+ rb.Construct (@pixf );
+ ren.Construct(@rb );
+
+ rgba.ConstrDbl(1 ,1 ,1 );
+ rb.clear (@rgba );
+
+ ras.Construct;
+ sl.Construct;
+
+// Render the controls
+ render_ctrl(@ras ,@sl ,@ren ,@m_slider1 );
+ render_ctrl(@ras ,@sl ,@ren ,@m_slider_spiral );
+ render_ctrl(@ras ,@sl ,@ren ,@m_slider_base_y );
+
+// Render
+ trans.Construct;
+ trans.full_circle(-600 );
+ trans.base_scale (-1.0 );
+ trans.base_offset(0.0 ,m_slider_base_y._value );
+ trans.translation(_width / 2.0 ,_height / 2.0 + 30.0 );
+ trans.spiral (-m_slider_spiral._value );
+
+ segm.Construct (@m_slider1 );
+ pipeline.Construct(@segm ,@trans );
+ ctrl.Construct (@m_slider1 ,@pipeline );
+
+ render_ctrl(@ras ,@sl ,@ren ,@ctrl );
+
+// Free AGG resources
+ ras.Destruct;
+ sl.Destruct;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = key_f1 then
+ message_(
+ 'Another example of non-linear transformations requested by one of my friends. '#13 +
+ 'Here we render a standard AGG control in its original form (the slider in the '#13 +
+ 'bottom) and after the transformation. The transformer itself is not a part of '#13 +
+ 'AGG and just demonstrates how to write custom transformers (class trans_polar).'#13 +
+ 'Note that because the transformer is non-linear, we need to use conv_segmentator '#13 +
+ 'first. Don''t worry much about the transformed_control class, it''s just an adaptor '#13 +
+ 'used to render the controls with additional transformations.'#13#13 +
+ 'How to play with:'#13#13 +
+ 'Try to drag the value of the slider at the bottom and watch how it''s being '#13 +
+ 'synchronized in the polar coordinates. Also change two other parameters '#13 +
+ '(Spiral and Base Y) and the size of the window.' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+VAR
+ app : the_application;
+
+BEGIN
+ app.Construct(pix_format_bgr24 ,flip_y );
+ app.caption_ ('AGG Example. Polar Transformer (F1-Help)' );
+
+ if app.init(600 ,400 ,window_resize ) then
+ app.run;
+
+ app.Destruct;
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/truetype_test.dpr b/src/corelib/render/software/agg-demos/truetype_test.dpr
new file mode 100644
index 00000000..82dfd383
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/truetype_test.dpr
@@ -0,0 +1,706 @@
+{target:win}
+//
+// AggPas 2.4 RM3 Demo application
+// Note: Press F1 key on run to see more info about this demo
+//
+// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
+//
+program
+ truetype_test ;
+
+uses
+ Windows ,SysUtils ,
+
+ agg_basics ,
+ agg_platform_support ,
+
+ agg_color ,
+ agg_pixfmt ,
+ agg_pixfmt_rgb ,
+
+ agg_ctrl ,
+ agg_slider_ctrl ,
+ agg_cbox_ctrl ,
+ agg_rbox_ctrl ,
+
+ agg_rendering_buffer ,
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_renderer_primitives ,
+ agg_rasterizer_scanline_aa ,
+ agg_scanline ,
+ agg_scanline_u ,
+ agg_scanline_bin ,
+ agg_render_scanlines ,
+
+ agg_trans_affine ,
+ agg_curves ,
+ agg_conv_curve ,
+ agg_conv_contour ,
+ agg_gamma_lut ,
+ agg_gamma_functions ,
+ agg_font_win32_tt ,
+ agg_font_cache_manager ;
+
+{$I agg_mode.inc }
+
+const
+ flip_y = true;
+
+ angle_step = 0.5;
+
+ text_ : PChar =
+ //'0123456789ABCDEFGHIJKLMNOPRSTUVWXYZabcdefghijklmnoprstuvwxyz ' +
+ 'Anti-Grain Geometry is designed as a set of loosely coupled ' +
+ 'algorithms and class templates united with a common idea, ' +
+ 'so that all the components can be easily combined. Also, ' +
+ 'the template based design allows you to replace any part of ' +
+ 'the library without the necessity to modify a single byte in ' +
+ 'the existing code. ' +
+ 'AGG is designed keeping in mind extensibility and flexibility. ' +
+ 'Basically I just wanted to create a toolkit that would allow me ' +
+ '(and anyone else) to add new fancy algorithms very easily. ' +
+ 'AGG does not dictate you any style of its use, you are free to ' +
+ 'use any part of it. However, AGG is often associated with a tool ' +
+ 'for rendering images in memory. That is not quite true, but it can ' +
+ 'be a good starting point in studying. The tutorials describe the ' +
+ 'use of AGG starting from the low level functionality that deals with ' +
+ 'frame buffers and pixels. Then you will gradually understand how to ' +
+ 'abstract different parts of the library and how to use them separately. ' +
+ 'Remember, the raster picture is often not the only thing you want to ' +
+ 'obtain, you will probably want to print your graphics with highest ' +
+ 'possible quality and in this case you can easily combine the "vectorial" ' +
+ 'part of the library with some API like Windows GDI, having a common ' +
+ 'external interface. If that API can render multi-polygons with non-zero ' +
+ 'and even-odd filling rules it''s all you need to incorporate AGG into ' +
+ 'your application. For example, Windows API PolyPolygon perfectly fits ' +
+ 'these needs, except certain advanced things like gradient filling, ' +
+ 'Gouraud shading, image transformations, and so on. Or, as an alternative, ' +
+ 'you can use all AGG algorithms producing high resolution pixel images and ' +
+ 'then to send the result to the printer as a pixel map.' +
+ 'Below is a typical brief scheme of the AGG rendering pipeline. ' +
+ 'Please note that any component between the Vertex Source ' +
+ 'and Screen Output is not mandatory. It all depends on your ' +
+ 'particular needs. For example, you can use your own rasterizer, ' +
+ 'based on Windows API. In this case you won''t need the AGG rasterizer ' +
+ 'and renderers. Or, if you need to draw only lines, you can use the ' +
+ 'AGG outline rasterizer that has certain restrictions but works faster. ' +
+ 'The number of possibilities is endless. ' +
+ 'Vertex Source is some object that produces polygons or polylines as ' +
+ 'a set of consecutive 2D vertices with commands like MoveTo, LineTo. ' +
+ 'It can be a container or some other object that generates vertices ' +
+ 'on demand. ' +
+ 'Coordinate conversion pipeline consists of a number of coordinate ' +
+ 'converters. It always works with vectorial data (X,Y) represented ' +
+ 'as floating point numbers (double). For example, it can contain an ' +
+ 'affine transformer, outline (stroke) generator, some marker ' +
+ 'generator (like arrowheads/arrowtails), dashed lines generator, ' +
+ 'and so on. The pipeline can have branches and you also can have ' +
+ 'any number of different pipelines. You also can write your own ' +
+ 'converter and include it into the pipeline. ' +
+ 'Scanline Rasterizer converts vectorial data into a number of ' +
+ 'horizontal scanlines. The scanlines usually (but not obligatory) ' +
+ 'carry information about Anti-Aliasing as coverage values. ' +
+ 'Renderers render scanlines, sorry for the tautology. The simplest ' +
+ 'example is solid filling. The renderer just adds a color to the ' +
+ 'scanline and writes the result into the rendering buffer. ' +
+ 'More complex renderers can produce multi-color result, ' +
+ 'like gradients, Gouraud shading, image transformations, ' +
+ 'patterns, and so on. Rendering Buffer is a buffer in memory ' +
+ 'that will be displayed afterwards. Usually but not obligatory ' +
+ 'it contains pixels in format that fits your video system. ' +
+ 'For example, 24 bits B-G-R, 32 bits B-G-R-A, or 15 ' +
+ 'bits R-G-B-555 for Windows. But in general, there''re no ' +
+ 'restrictions on pixel formats or color space if you write ' +
+ 'your own low level class that supports that format. ' +
+ 'Colors in AGG appear only in renderers, that is, when you ' +
+ 'actually put some data to the rendering buffer. In general, ' +
+ 'there''s no general purpose structure or class like color, ' +
+ 'instead, AGG always operates with concrete color space. ' +
+ 'There are plenty of color spaces in the world, like RGB, ' +
+ 'HSV, CMYK, etc., and all of them have certain restrictions. ' +
+ 'For example, the RGB color space is just a poor subset of ' +
+ 'colors that a human eye can recognize. If you look at the full ' +
+ 'CIE Chromaticity Diagram, you will see that the RGB triangle ' +
+ 'is just a little part of it. ' +
+ 'In other words there are plenty of colors in the real world ' +
+ 'that cannot be reproduced with RGB, CMYK, HSV, etc. Any color ' +
+ 'space except the one existing in Nature is restrictive. Thus, ' +
+ 'it was decided not to introduce such an object like color in ' +
+ 'order not to restrict the possibilities in advance. Instead, ' +
+ 'there are objects that operate with concrete color spaces. ' +
+ 'Currently there are agg::rgba and agg::rgba8 that operate ' +
+ 'with the most popular RGB color space (strictly speaking there''s ' +
+ 'RGB plus Alpha). The RGB color space is used with different ' +
+ 'pixel formats, like 24-bit RGB or 32-bit RGBA with different ' +
+ 'order of color components. But the common property of all of ' +
+ 'them is that they are essentially RGB. Although, AGG doesn''t ' +
+ 'explicitly support any other color spaces, there is at least ' +
+ 'a potential possibility of adding them. It means that all ' +
+ 'class and function templates that depend on the color type ' +
+ 'are parameterized with the ColorT argument. ' +
+ 'Basically, AGG operates with coordinates of the output device. ' +
+ 'On your screen there are pixels. But unlike many other libraries ' +
+ 'and APIs AGG initially supports Subpixel Accuracy. It means ' +
+ 'that the coordinates are represented as doubles, where fractional ' +
+ 'values actually take effect. AGG doesn''t have an embedded ' +
+ 'conversion mechanism from world to screen coordinates in order ' +
+ 'not to restrict your freedom. It''s very important where and when ' +
+ 'you do that conversion, so, different applications can require ' +
+ 'different approaches. AGG just provides you a transformer of ' +
+ 'that kind, namely, that can convert your own view port to the ' +
+ 'device one. And it''s your responsibility to include it into ' +
+ 'the proper place of the pipeline. You can also write your ' +
+ 'own very simple class that will allow you to operate with ' +
+ 'millimeters, inches, or any other physical units. ' +
+ 'Internally, the rasterizers use integer coordinates of the ' +
+ 'format 24.8 bits, that is, 24 bits for the integer part and 8 ' +
+ 'bits for the fractional one. In other words, all the internal ' +
+ 'coordinates are multiplied by 256. If you intend to use AGG in ' +
+ 'some embedded system that has inefficient floating point ' +
+ 'processing, you still can use the rasterizers with their ' +
+ 'integer interfaces. Although, you won''t be able to use the ' +
+ 'floating point coordinate pipelines in this case. ';
+
+var
+ text_flip : boolean;
+ font_name : AnsiString;
+
+type
+ the_application = object(platform_support )
+ m_ren_type : rbox_ctrl;
+
+ m_height ,
+ m_width ,
+ m_weight ,
+ m_gamma : slider_ctrl;
+
+ m_hinting ,
+ m_kerning ,
+ m_performance : cbox_ctrl;
+
+ m_feng : font_engine_win32_tt_int32;
+ m_fman : font_cache_manager;
+
+ m_old_height : double;
+ m_gamma_lut : gamma_lut;
+
+ // Pipeline to process the vectors glyph paths (curves + contour)
+ m_curves : conv_curve;
+ m_contour : conv_contour;
+
+ m_angle : double;
+
+ constructor Construct(dc : HDC; format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ function draw_text(
+ ras : rasterizer_scanline_aa_ptr;
+ sl : scanline_ptr;
+ ren_solid : renderer_scanline_aa_solid_ptr;
+ ren_bin : renderer_scanline_bin_solid_ptr ) : unsigned;
+
+ procedure on_draw; virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+ procedure on_ctrl_change; virtual;
+
+ end;
+
+{ CONSTRUCT }
+constructor the_application.Construct;
+begin
+ inherited Construct(format_ ,flip_y_ );
+
+ m_ren_type.Construct (5.0 ,5.0 ,5.0 + 150.0 ,110.0 ,not flip_y_ );
+ m_height.Construct (160 ,10.0 ,640 - 5.0 ,18.0 ,not flip_y_ );
+ m_width.Construct (160 ,30.0 ,640 - 5.0 ,38.0 ,not flip_y_ );
+ m_weight.Construct (160 ,50.0 ,640 - 5.0 ,58.0 ,not flip_y_ );
+ m_gamma.Construct (260 ,70.0 ,640 - 5.0 ,78.0 ,not flip_y_ );
+ m_hinting.Construct (160 ,65.0 ,'Hinting' ,not flip_y_ );
+ m_kerning.Construct (160 ,80.0 ,'Kerning' ,not flip_y_ );
+ m_performance.Construct(160 ,95.0 ,'Test Performance' ,not flip_y_ );
+
+ m_feng.Construct(dc );
+ m_fman.Construct(@m_feng );
+
+ m_old_height:=0.0;
+
+ m_gamma_lut.Construct_(8 ,16 );
+ m_curves.Construct (m_fman.path_adaptor );
+ m_contour.Construct (@m_curves );
+
+ m_ren_type.add_item ('Native Mono' );
+ m_ren_type.add_item ('Native Gray 8' );
+ m_ren_type.add_item ('AGG Outline' );
+ m_ren_type.add_item ('AGG Mono' );
+ m_ren_type.add_item ('AGG Gray 8' );
+ m_ren_type.cur_item_(1 );
+
+ add_ctrl(@m_ren_type );
+
+ m_ren_type.no_transform;
+
+ m_height.label_('Font Height=%.2f' );
+ m_height.range_(8, 32);
+ m_height.value_(18 );
+
+ m_height.num_steps_ (32 - 8 );
+ m_height.text_thickness_(1.5 );
+
+ add_ctrl(@m_height );
+
+ m_height.no_transform;
+
+ m_width.label_('Font Width=%.2f' );
+ m_width.range_(8 ,32 );
+ m_width.value_(18 );
+
+ m_width.num_steps_ (32 - 8 );
+ m_width.text_thickness_(1.5 );
+
+ add_ctrl(@m_width );
+
+ m_width.no_transform;
+
+ m_weight.label_('Font Weight=%.2f' );
+ m_weight.range_(-1 ,1 );
+
+ m_weight.text_thickness_(1.5 );
+
+ add_ctrl(@m_weight );
+
+ m_weight.no_transform;
+
+ m_gamma.label_('Gamma=%.2f' );
+ m_gamma.range_(0.1 ,2.0 );
+ m_gamma.value_(1.0 );
+
+ m_gamma.text_thickness_(1.5 );
+
+ add_ctrl(@m_gamma );
+
+ m_gamma.no_transform;
+
+ add_ctrl(@m_hinting );
+
+ m_hinting.status_(true );
+ m_hinting.no_transform;
+
+ add_ctrl(@m_kerning );
+
+ m_kerning.status_(true );
+ m_kerning.no_transform;
+
+ add_ctrl(@m_performance );
+
+ m_performance.no_transform;
+
+ //m_curves.approximation_method_(curve_div );
+ //m_curves.approximation_scale_ (0.5 );
+ //m_curves.angle_tolerance_ (0.3 );
+
+ m_contour.auto_detect_orientation_(false );
+
+end;
+
+{ DESTRUCT }
+destructor the_application.Destruct;
+begin
+ inherited Destruct;
+
+ m_ren_type.Destruct;
+ m_height.Destruct;
+ m_width.Destruct;
+ m_weight.Destruct;
+ m_gamma.Destruct;
+ m_hinting.Destruct;
+ m_kerning.Destruct;
+ m_performance.Destruct;
+
+ m_feng.Destruct;
+ m_fman.Destruct;
+
+ m_gamma_lut.Destruct;
+ m_curves.Destruct;
+ m_contour.Destruct;
+
+end;
+
+{ DRAW_TEXT }
+function the_application.draw_text;
+var
+ gren : glyph_rendering;
+
+ num_glyphs : unsigned;
+
+ mtx : trans_affine;
+ taw : trans_affine_skewing;
+ tar : trans_affine_rotation;
+
+ x ,y0 ,y : double;
+
+ p : int8u_ptr;
+
+ rgba : aggclr;
+ glyph : glyph_cache_ptr;
+
+begin
+ gren:=glyph_ren_native_mono;
+
+ case m_ren_type._cur_item of
+ 0 : gren:=glyph_ren_native_mono;
+ 1 : gren:=glyph_ren_native_gray8;
+ 2 : gren:=glyph_ren_outline;
+ 3 : gren:=glyph_ren_agg_mono;
+ 4 : gren:=glyph_ren_agg_gray8;
+
+ end;
+
+ num_glyphs:=0;
+
+ m_contour.width_(-m_weight._value * m_height._value * 0.05 );
+
+ m_feng.hinting_(m_hinting._status );
+ m_feng.height_ (m_height._value );
+
+// Font width in Windows is strange. MSDN says,
+// "specifies the average width", but there's no clue what
+// this "average width" means. It'd be logical to specify
+// the width with regard to the font height, like it's done in
+// FreeType. That is, width == height should mean the "natural",
+// not distorted glyphs. In Windows you have to specify
+// the absolute width, which is very stupid and hard to use
+// in practice.
+ if m_width._value = m_height._value then
+ m_feng.width_(0.0 )
+ else
+ m_feng.width_(m_width._value / 2.4 );
+
+// m_feng.italic_(true );
+ m_feng.flip_y_(text_flip );
+
+ mtx.Construct;
+
+ if m_angle <> 0 then
+ begin
+ tar.Construct(deg2rad(m_angle ) );
+ mtx.multiply (@tar );
+
+ end;
+
+ //taw.Construct(-0.3 ,0 ); mtx.multiply(@taw );
+
+ m_feng.transform_(@mtx );
+
+ if m_feng.create_font(@font_name[1 ] ,gren ) then
+ begin
+ m_fman.precache(unsigned(' ' ) ,127 );
+
+ x :=10.0;
+ y0:=_height - m_height._value - 10.0;
+ y :=y0;
+ p :=@text_[0 ];
+
+ while p^ <> 0 do
+ begin
+ glyph:=m_fman.glyph(p^ );
+
+ if glyph <> NIL then
+ begin
+ if m_kerning._status then
+ m_fman.add_kerning(@x ,@y );
+
+ if x >= _width - m_height._value then
+ begin
+ x :=10.0;
+ y0:=y0 - m_height._value;
+
+ if y0 <= 120 then
+ break;
+
+ y:=y0;
+
+ end;
+
+ m_fman.init_embedded_adaptors(glyph ,x ,y );
+
+ case glyph.data_type of
+ glyph_data_mono :
+ begin
+ rgba.ConstrInt(0 ,0 ,0 );
+ ren_bin.color_(@rgba );
+
+ render_scanlines(
+ m_fman.mono_adaptor ,
+ m_fman.mono_scanline ,
+ ren_bin );
+
+ end;
+
+ glyph_data_gray8 :
+ begin
+ rgba.ConstrInt (0 ,0 ,0 );
+ ren_solid.color_(@rgba );
+
+ render_scanlines(
+ m_fman.gray8_adaptor ,
+ m_fman.gray8_scanline ,
+ ren_solid );
+
+ end;
+
+ glyph_data_outline :
+ begin
+ ras.reset;
+
+ if Abs(m_weight._value ) <= 0.01 then
+ // For the sake of efficiency skip the
+ // contour converter if the weight is about zero.
+ ras.add_path(@m_curves )
+ else
+ ras.add_path(@m_contour );
+
+ rgba.ConstrInt (0 ,0 ,0 );
+ ren_solid.color_(@rgba );
+
+ render_scanlines(ras ,sl ,ren_solid );
+
+ end;
+
+ end;
+
+ // increment pen position
+ x:=x + glyph.advance_x;
+ y:=y + glyph.advance_y;
+
+ inc(num_glyphs );
+
+ end;
+
+ inc(ptrcomp(p ) ,sizeof(int8u ) );
+
+ end;
+
+ end;
+
+ result:=num_glyphs;
+
+end;
+
+{ ON_DRAW }
+procedure the_application.on_draw;
+var
+ pf : pixel_formats;
+
+ rgba : aggclr;
+
+ ren_base : renderer_base;
+ ren_solid : renderer_scanline_aa_solid;
+ ren_bin : renderer_scanline_bin_solid;
+
+ sl : scanline_u8;
+ ras : rasterizer_scanline_aa;
+
+ gm_th : gamma_threshold;
+ gm_no : gamma_none;
+ gm_pw : gamma_power;
+
+begin
+// Initialize structures
+ pixfmt_bgr24_gamma(pf ,rbuf_window ,@m_gamma_lut );
+
+ ren_base.Construct (@pf );
+ ren_solid.Construct(@ren_base );
+ ren_bin.Construct (@ren_base );
+
+ rgba.ConstrDbl(1 ,1 ,1 );
+ ren_base.clear(@rgba );
+
+ sl.Construct;
+ ras.Construct;
+
+ if m_height._value <> m_old_height then
+ begin
+ m_old_height:=m_height._value;
+
+ m_width.value_(m_old_height );
+
+ end;
+
+// Setup Gamma
+ if m_ren_type._cur_item = 3 then
+ begin
+ // When rendering in mono format,
+ // Set threshold gamma = 0.5
+ gm_th.Construct(m_gamma._value / 2.0 );
+ m_feng.gamma_ (@gm_th );
+
+ end
+ else
+ begin
+ gm_no.Construct;
+ m_feng.gamma_(@gm_no );
+
+ m_gamma_lut.gamma_(m_gamma._value );
+
+ end;
+
+// Render the text
+ draw_text(@ras ,@sl ,@ren_solid ,@ren_bin );
+
+// Render the controls
+ gm_pw.Construct(1.0 );
+ ras.gamma (@gm_pw );
+
+ render_ctrl(@ras ,@sl ,@ren_solid ,@m_ren_type );
+ render_ctrl(@ras ,@sl ,@ren_solid ,@m_height );
+ render_ctrl(@ras ,@sl ,@ren_solid ,@m_width );
+ render_ctrl(@ras ,@sl ,@ren_solid ,@m_weight );
+ render_ctrl(@ras ,@sl ,@ren_solid ,@m_gamma );
+ render_ctrl(@ras ,@sl ,@ren_solid ,@m_hinting );
+ render_ctrl(@ras ,@sl ,@ren_solid ,@m_kerning );
+ render_ctrl(@ras ,@sl ,@ren_solid ,@m_performance );
+
+// Free AGG resources
+ sl.Destruct;
+ ras.Destruct;
+
+end;
+
+{ ON_KEY }
+procedure the_application.on_key;
+begin
+ if key = byte(' ' ) then
+ begin
+ text_flip:=not text_flip;
+
+ force_redraw;
+
+ end;
+
+ if key = key_kp_minus then
+ begin
+ m_angle:=m_angle + angle_step;
+
+ if m_angle > 360 then
+ m_angle:=0;
+
+ force_redraw;
+
+ end;
+
+ if key = key_kp_plus then
+ begin
+ m_angle:=m_angle - angle_step;
+
+ if m_angle < 0 then
+ m_angle:=360 - angle_step;
+
+ force_redraw;
+
+ end;
+
+ if key = key_f1 then
+ message_(
+ 'This example demonstrates the use of the Win32 TrueType font engine with cache. '#13 +
+ 'Cache can keep three types of data, vector path, Anti-Aliased scanline shape, '#13 +
+ 'and monochrome scanline shape. In case of caching scanline shapes the speed '#13 +
+ 'is pretty good and comparable with Windows hardware accelerated font rendering.'#13#13 +
+ 'How to play with:'#13#13 +
+ 'Press the spacebar to flip the text vertically.'#13#13 +
+ 'Key Plus - Increase font angle (not for Natives)'#13 +
+ 'Key Minus - Decrease font angle (not for Natives)' +
+ #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
+
+end;
+
+{ ON_CTRL_CHANGE }
+procedure the_application.on_ctrl_change;
+var
+ pf : pixel_formats;
+
+ rgba : aggclr;
+
+ ren_base : renderer_base;
+ ren_solid : renderer_scanline_aa_solid;
+ ren_bin : renderer_scanline_bin_solid;
+
+ sl : scanline_u8;
+ ras : rasterizer_scanline_aa;
+
+ num_glyphs ,i : unsigned;
+
+ t : double;
+
+ buf : array[0..99 ] of char;
+
+begin
+ if m_performance._status then
+ begin
+ pixfmt_bgr24_gamma(pf ,rbuf_window ,@m_gamma_lut );
+
+ ren_base.Construct (@pf );
+ ren_solid.Construct(@ren_base );
+ ren_bin.Construct (@ren_base );
+
+ rgba.ConstrDbl(1 ,1 ,1 );
+ ren_base.clear(@rgba );
+
+ sl.Construct;
+ ras.Construct;
+
+ num_glyphs:=0;
+
+ start_timer;
+
+ for i:=0 to 49 do
+ inc(num_glyphs ,draw_text(@ras ,@sl ,@ren_solid ,@ren_bin ) );
+
+ t:=elapsed_time;
+
+ sprintf(@buf[0 ] ,'Glyphs=%u, ' ,num_glyphs );
+ sprintf(@buf[StrLen(@buf ) ] ,'Time=%.3fms, ' ,t );
+ sprintf(@buf[StrLen(@buf ) ] ,'%.3f glyps/sec, ' ,(num_glyphs / t ) * 1000.0 );
+ sprintf(@buf[StrLen(@buf ) ] ,'%.3f microsecond/glyph' , (t / num_glyphs) * 1000.0);
+
+ message_(@buf[0 ] );
+
+ m_performance.status_(false );
+
+ force_redraw;
+
+ sl.Destruct;
+ ras.Destruct;
+
+ end;
+
+end;
+
+VAR
+ app : the_application;
+ dc : HDC;
+
+BEGIN
+ text_flip:=false;
+ font_name:='Arial';
+
+{$IFDEF WIN32 }
+ if ParamCount > 0 then
+ font_name:=ParamStr(1 );
+
+{$ENDIF }
+
+ dc:=GetDC(0 );
+
+ app.Construct(dc ,pix_format_bgr24 ,flip_y );
+ app.caption_ ('AGG Example. Rendering TrueType Fonts with WinAPI (F1-Help)' );
+
+ if app.init(640 ,520 ,window_resize ) then
+ app.run;
+
+ app.Destruct;
+
+ ReleaseDC(0 ,dc );
+
+END. \ No newline at end of file
diff --git a/src/corelib/render/software/agg-demos/verdana.ttf b/src/corelib/render/software/agg-demos/verdana.ttf
new file mode 100644
index 00000000..8f25a642
--- /dev/null
+++ b/src/corelib/render/software/agg-demos/verdana.ttf
Binary files differ
diff --git a/src/corelib/render/software/agg_2D.pas b/src/corelib/render/software/agg_2D.pas
new file mode 100644
index 00000000..3313ccc9
--- /dev/null
+++ b/src/corelib/render/software/agg_2D.pas
@@ -0,0 +1,3302 @@
+//----------------------------------------------------------------------------
+// Agg2D - Version 1.0
+// Based on Anti-Grain Geometry
+// Copyright (C) 2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Agg2D - Version 1.0 Release Milano 3 (AggPas 2.3 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2007
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 22.08.2007-Milano: Unit port establishment
+// 23.08.2007-Milano: Porting
+// 11.09.2007-Milano: -"-
+// 13.09.2007-Milano: -"-, Finished OK
+//
+{ agg_2D.pas }
+unit
+ agg_2D ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+// With this define uncommented you can use FreeType font engine
+{$DEFINE AGG2D_USE_FREETYPE }
+
+uses
+ agg_basics ,
+ agg_array ,
+ agg_trans_affine ,
+ agg_trans_viewport ,
+ agg_path_storage ,
+ agg_conv_stroke ,
+ agg_conv_transform ,
+ agg_conv_curve ,
+ agg_rendering_buffer ,
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_span_gradient ,
+ agg_span_image_filter_rgba ,
+ agg_span_image_resample_rgba ,
+ agg_span_converter ,
+ agg_span_interpolator_linear ,
+ agg_span_allocator ,
+ agg_rasterizer_scanline_aa ,
+ agg_gamma_functions ,
+ agg_scanline_u ,
+ agg_arc ,
+ agg_bezier_arc ,
+ agg_rounded_rect ,
+ agg_font_engine ,
+ agg_font_cache_manager ,
+ agg_pixfmt ,
+ agg_pixfmt_rgba ,
+ agg_color ,
+ agg_math_stroke ,
+ agg_image_filters ,
+ agg_vertex_source ,
+ agg_render_scanlines ,
+
+{$IFDEF AGG2D_USE_FREETYPE }
+ agg_font_freetype ,
+
+{$ELSE }
+ agg_font_win32_tt ,
+ Windows ,
+
+{$ENDIF }
+
+ Math ;
+
+{ GLOBAL VARIABLES & CONSTANTS }
+const
+// LineJoin
+ JoinMiter = miter_join;
+ JoinRound = round_join;
+ JoinBevel = bevel_join;
+
+// LineCap
+ CapButt = butt_cap;
+ CapSquare = square_cap;
+ CapRound = round_cap;
+
+// TextAlignment
+ AlignLeft = 0;
+ AlignRight = 1;
+ AlignCenter = 2;
+ AlignTop = AlignRight;
+ AlignBottom = AlignLeft;
+
+// BlendMode
+ BlendAlpha = end_of_comp_op_e;
+ BlendClear = comp_op_clear;
+ BlendSrc = comp_op_src;
+ BlendDst = comp_op_dst;
+ BlendSrcOver = comp_op_src_over;
+ BlendDstOver = comp_op_dst_over;
+ BlendSrcIn = comp_op_src_in;
+ BlendDstIn = comp_op_dst_in;
+ BlendSrcOut = comp_op_src_out;
+ BlendDstOut = comp_op_dst_out;
+ BlendSrcAtop = comp_op_src_atop;
+ BlendDstAtop = comp_op_dst_atop;
+ BlendXor = comp_op_xor;
+ BlendAdd = comp_op_plus;
+ BlendSub = comp_op_minus;
+ BlendMultiply = comp_op_multiply;
+ BlendScreen = comp_op_screen;
+ BlendOverlay = comp_op_overlay;
+ BlendDarken = comp_op_darken;
+ BlendLighten = comp_op_lighten;
+ BlendColorDodge = comp_op_color_dodge;
+ BlendColorBurn = comp_op_color_burn;
+ BlendHardLight = comp_op_hard_light;
+ BlendSoftLight = comp_op_soft_light;
+ BlendDifference = comp_op_difference;
+ BlendExclusion = comp_op_exclusion;
+ BlendContrast = comp_op_contrast;
+
+{ TYPES DEFINITION }
+type
+ Color_ptr = ^Color;
+ Color = rgba8;
+
+ Rect_ = agg_basics.rect;
+ RectD = agg_basics.rect_d;
+
+ Affine = trans_affine;
+ Affine_ptr = trans_affine_ptr;
+
+ FontRasterizer = gray8_adaptor_type;
+ FontRasterizer_ptr = gray8_adaptor_type_ptr;
+
+ FontScanline = gray8_scanline_type;
+ FontScanline_ptr = gray8_scanline_type_ptr;
+
+{$IFDEF AGG2D_USE_FREETYPE }
+ FontEngine = font_engine_freetype_int32;
+
+{$ELSE }
+ FontEngine = font_engine_win32_tt_int32;
+
+{$ENDIF }
+
+ Gradient = (Solid ,Linear ,Radial );
+ Direction = (CW, CCW );
+
+ LineJoin_ = int;
+ LineCap_ = int;
+ BlendMode_ = comp_op_e;
+
+ TextAlignment = int;
+
+ DrawPathFlag = (
+ FillOnly ,
+ StrokeOnly ,
+ FillAndStroke ,
+ FillWithLineColor );
+
+ ViewportOption = (
+ Anisotropic ,
+ XMinYMin ,
+ XMidYMin ,
+ XMaxYMin ,
+ XMinYMid ,
+ XMidYMid ,
+ XMaxYMid ,
+ XMinYMax ,
+ XMidYMax ,
+ XMaxYMax );
+
+ ImageFilter_ = (
+ NoFilter ,
+ Bilinear ,
+ Hanning ,
+ Hermite ,
+ Quadric ,
+ Bicubic ,
+ Catrom ,
+ Spline16 ,
+ Spline36 ,
+ Blackman144 );
+
+ ImageResample_ = (
+ NoResample ,
+ ResampleAlways ,
+ ResampleOnZoomOut );
+
+ FontCacheType = (
+ RasterFontCache ,
+ VectorFontCache );
+
+ Transformations_ptr = ^Transformations_;
+ Transformations_ = record
+ affineMatrix : array[0..5 ] of double;
+
+ end;
+
+ Image_ptr = ^Image;
+ Image = object
+ renBuf : rendering_buffer;
+
+ constructor Construct; overload;
+ constructor Construct(buf : int8u_ptr; width_ ,height_ : unsigned; stride : int ); overload;
+ destructor Destruct;
+
+ procedure attach(buf : int8u_ptr; width_ ,height_ : unsigned; stride : int );
+
+ function width : int;
+ function height : int;
+
+ procedure premultiply;
+ procedure demultiply;
+
+ end;
+
+ Agg2DRasterizerGamma = object(vertex_source )
+ m_alpha : gamma_multiply;
+ m_gamma : gamma_power;
+
+ constructor Construct(alpha ,gamma : double );
+
+ function func_operator_gamma(x : double ) : double; virtual;
+
+ end;
+
+ Agg2D_ptr = ^Agg2D;
+ Agg2D = object
+ private
+ m_rbuf : rendering_buffer;
+
+ m_pixFormat ,m_pixFormatComp ,m_pixFormatPre ,m_pixFormatCompPre : pixel_formats;
+ m_renBase ,m_renBaseComp ,m_renBasePre ,m_renBaseCompPre : renderer_base;
+
+ m_renSolid ,m_renSolidComp : renderer_scanline_aa_solid;
+
+ m_allocator : span_allocator;
+ m_clipBox : RectD;
+
+ m_blendMode ,m_imageBlendMode : BlendMode_;
+
+ m_imageBlendColor : Color;
+
+ m_scanline : scanline_u8;
+ m_rasterizer : rasterizer_scanline_aa;
+
+ m_masterAlpha ,m_antiAliasGamma : double;
+
+ m_fillColor ,m_lineColor : Color;
+
+ m_fillGradient ,m_lineGradient : pod_auto_array;
+
+ m_lineCap : LineCap_;
+ m_lineJoin : LineJoin_;
+
+ m_fillGradientFlag ,m_lineGradientFlag : Gradient;
+
+ m_fillGradientMatrix ,m_lineGradientMatrix : trans_affine;
+
+ m_fillGradientD1 ,
+ m_lineGradientD1 ,
+ m_fillGradientD2 ,
+ m_lineGradientD2 ,
+ m_textAngle : double;
+ m_textAlignX ,
+ m_textAlignY : TextAlignment;
+ m_textHints : boolean;
+ m_fontHeight ,
+ m_fontAscent ,
+ m_fontDescent : double;
+ m_fontCacheType : FontCacheType;
+
+ m_imageFilter : ImageFilter_;
+ m_imageResample : ImageResample_;
+ m_imageFilterLut : image_filter_lut;
+
+ m_fillGradientInterpolator ,
+ m_lineGradientInterpolator : span_interpolator_linear;
+
+ m_linearGradientFunction : gradient_x;
+ m_radialGradientFunction : gradient_circle;
+
+ m_lineWidth : double;
+ m_evenOddFlag : boolean;
+
+ m_path : path_storage;
+ m_transform : trans_affine;
+
+ m_convCurve : conv_curve;
+ m_convStroke : conv_stroke;
+
+ m_pathTransform ,m_strokeTransform : conv_transform;
+
+ {$IFNDEF AGG2D_USE_FREETYPE }
+ m_fontDC : HDC;
+
+ {$ENDIF }
+
+ m_fontEngine : FontEngine;
+ m_fontCacheManager : font_cache_manager;
+
+ // Other Pascal-specific members
+ m_gammaNone : gamma_none;
+ m_gammaAgg2D : Agg2DRasterizerGamma;
+
+ m_ifBilinear : image_filter_bilinear;
+ m_ifHanning : image_filter_hanning;
+ m_ifHermite : image_filter_hermite;
+ m_ifQuadric : image_filter_quadric;
+ m_ifBicubic : image_filter_bicubic;
+ m_ifCatrom : image_filter_catrom;
+ m_ifSpline16 : image_filter_spline16;
+ m_ifSpline36 : image_filter_spline36;
+ m_ifBlackman144 : image_filter_blackman144;
+
+ public
+ constructor Construct;
+ destructor Destruct;
+
+ // Setup
+ procedure attach(buf : int8u_ptr; width_ ,height_ : unsigned; stride : int ); overload;
+ procedure attach(img : Image_ptr ); overload;
+
+ procedure clipBox(x1 ,y1 ,x2 ,y2 : double ); overload;
+ function clipBox : RectD; overload;
+
+ procedure clearAll(c : Color ); overload;
+ procedure clearAll(r ,g ,b : unsigned; a : unsigned = 255 ); overload;
+
+ procedure clearClipBox(c : Color ); overload;
+ procedure clearClipBox(r ,g ,b : unsigned; a : unsigned = 255 ); overload;
+
+ // Conversions
+ procedure worldToScreen(x ,y : double_ptr ); overload;
+ procedure screenToWorld(x ,y : double_ptr ); overload;
+ function worldToScreen(scalar : double ) : double; overload;
+ function screenToWorld(scalar : double ) : double; overload;
+
+ procedure alignPoint(x ,y : double_ptr );
+
+ function inBox(worldX ,worldY : double ) : boolean;
+
+ // General Attributes
+ procedure blendMode(m : BlendMode_ ); overload;
+ function blendMode : BlendMode_; overload;
+
+ procedure imageBlendMode(m : BlendMode_ ); overload;
+ function imageBlendMode : BlendMode_; overload;
+
+ procedure imageBlendColor(c : Color ); overload;
+ procedure imageBlendColor(r ,g ,b : unsigned; a : unsigned = 255 ); overload;
+ function imageBlendColor : Color; overload;
+
+ procedure masterAlpha(a : double ); overload;
+ function masterAlpha : double; overload;
+
+ procedure antiAliasGamma(g : double ); overload;
+ function antiAliasGamma : double; overload;
+
+ procedure fillColor(c : Color ); overload;
+ procedure fillColor(r ,g ,b : unsigned; a : unsigned = 255 ); overload;
+ procedure noFill;
+
+ procedure lineColor(c : Color ); overload;
+ procedure lineColor(r ,g ,b : unsigned; a : unsigned = 255 ); overload;
+ procedure noLine;
+
+ function fillColor : Color; overload;
+ function lineColor : Color; overload;
+
+ procedure fillLinearGradient(x1 ,y1 ,x2 ,y2 : double; c1 ,c2 : Color; profile : double = 1.0 );
+ procedure lineLinearGradient(x1 ,y1 ,x2 ,y2 : double; c1 ,c2 : Color; profile : double = 1.0 );
+
+ procedure fillRadialGradient(x ,y ,r : double; c1 ,c2 : Color; profile : double = 1.0 ); overload;
+ procedure lineRadialGradient(x ,y ,r : double; c1 ,c2 : Color; profile : double = 1.0 ); overload;
+
+ procedure fillRadialGradient(x ,y ,r : double; c1 ,c2 ,c3 : Color ); overload;
+ procedure lineRadialGradient(x ,y ,r : double; c1 ,c2 ,c3 : Color ); overload;
+
+ procedure fillRadialGradient(x ,y ,r : double ); overload;
+ procedure lineRadialGradient(x ,y ,r : double ); overload;
+
+ procedure lineWidth (w : double );
+ function lineWidth_(w : double ) : double;
+
+ procedure lineCap(cap : LineCap_ ); overload;
+ function lineCap : LineCap_; overload;
+
+ procedure lineJoin(join : LineJoin_ ); overload;
+ function lineJoin : LineJoin_; overload;
+
+ procedure fillEvenOdd(evenOddFlag : boolean ); overload;
+ function fillEvenOdd : boolean; overload;
+
+ // Transformations
+ function transformations : Transformations_; overload;
+ procedure transformations(tr : Transformations_ptr ); overload;
+ procedure resetTransformations;
+
+ procedure affine(tr : Affine_ptr ); overload;
+ procedure affine(tr : Transformations_ptr ); overload;
+
+ procedure rotate (angle : double );
+ procedure scale (sx ,sy : double );
+ procedure skew (sx ,sy : double );
+ procedure translate(x ,y : double );
+
+ procedure parallelogram(x1 ,y1 ,x2 ,y2 : double; para : double_ptr );
+
+ procedure viewport(
+ worldX1 ,worldY1 ,worldX2 ,worldY2 ,
+ screenX1 ,screenY1 ,screenX2 ,screenY2 : double;
+ opt : ViewportOption = XMidYMid );
+
+ // Basic Shapes
+ procedure line (x1 ,y1 ,x2 ,y2 : double );
+ procedure triangle (x1 ,y1 ,x2 ,y2 ,x3 ,y3 : double );
+ procedure rectangle(x1 ,y1 ,x2 ,y2 : double );
+
+ procedure roundedRect(x1 ,y1 ,x2 ,y2 ,r : double ); overload;
+ procedure roundedRect(x1 ,y1 ,x2 ,y2 ,rx ,ry : double ); overload;
+ procedure roundedRect(
+ x1 ,y1 ,x2 ,y2 ,
+ rxBottom ,ryBottom ,
+ rxTop ,ryTop : double ); overload;
+
+ procedure ellipse(cx ,cy ,rx ,ry : double );
+
+ procedure arc (cx ,cy ,rx ,ry ,start ,sweep : double );
+ procedure star(cx ,cy ,r1 ,r2 ,startAngle : double; numRays : int );
+
+ procedure curve(x1 ,y1 ,x2 ,y2 ,x3 ,y3 : double ); overload;
+ procedure curve(x1 ,y1 ,x2 ,y2 ,x3 ,y3 ,x4 ,y4 : double ); overload;
+
+ procedure polygon (xy : double_ptr; numPoints : int );
+ procedure polyline(xy : double_ptr; numPoints : int );
+
+ // Text
+ procedure flipText(flip : boolean );
+
+ procedure font(
+ fileName : char_ptr; height : double;
+ bold : boolean = false;
+ italic : boolean = false;
+ ch : FontCacheType = RasterFontCache;
+ angle : double = 0.0 );
+
+ function fontHeight : double;
+
+ procedure textAlignment(alignX ,alignY : TextAlignment );
+
+ function textHints : boolean; overload;
+ procedure textHints(hints : boolean ); overload;
+ function textWidth(str : char_ptr ) : double;
+
+ procedure text(
+ x ,y : double; str : char_ptr;
+ roundOff : boolean = false;
+ ddx : double = 0.0;
+ ddy : double = 0.0 );
+
+ // Path commands
+ procedure resetPath;
+
+ procedure moveTo (x ,y : double );
+ procedure moveRel(dx ,dy : double );
+
+ procedure lineTo (x ,y : double );
+ procedure lineRel(dx ,dy : double );
+
+ procedure horLineTo (x : double );
+ procedure horLineRel(dx : double );
+
+ procedure verLineTo (y : double );
+ procedure verLineRel(dy : double );
+
+ procedure arcTo(
+ rx ,ry ,angle : double;
+ largeArcFlag ,sweepFlag : boolean;
+ x ,y : double );
+
+ procedure arcRel(
+ rx ,ry ,angle : double;
+ largeArcFlag ,sweepFlag : boolean;
+ dx ,dy : double );
+
+ procedure quadricCurveTo (xCtrl ,yCtrl ,xTo ,yTo : double ); overload;
+ procedure quadricCurveRel(dxCtrl ,dyCtrl ,dxTo ,dyTo : double ); overload;
+ procedure quadricCurveTo (xTo ,yTo : double ); overload;
+ procedure quadricCurveRel(dxTo ,dyTo : double ); overload;
+
+ procedure cubicCurveTo (xCtrl1 ,yCtrl1 ,xCtrl2 ,yCtrl2 ,xTo ,yTo : double ); overload;
+ procedure cubicCurveRel(dxCtrl1 ,dyCtrl1 ,dxCtrl2 ,dyCtrl2 ,dxTo ,dyTo : double ); overload;
+ procedure cubicCurveTo (xCtrl2 ,yCtrl2 ,xTo ,yTo : double ); overload;
+ procedure cubicCurveRel(xCtrl2 ,yCtrl2 ,xTo ,yTo : double ); overload;
+
+ procedure addEllipse(cx ,cy ,rx ,ry : double; dir : Direction );
+ procedure closePolygon;
+
+ procedure drawPath(flag : DrawPathFlag = FillAndStroke );
+
+ procedure drawPathNoTransform(flag : DrawPathFlag = FillAndStroke );
+
+ // Image Transformations
+ procedure imageFilter(f : ImageFilter_ ); overload;
+ function imageFilter : ImageFilter_; overload;
+
+ procedure imageResample(f : ImageResample_ ); overload;
+ function imageResample : ImageResample_; overload;
+
+ procedure transformImage(
+ img : Image_ptr;
+ imgX1 ,imgY1 ,imgX2 ,imgY2 : int;
+ dstX1 ,dstY1 ,dstX2 ,dstY2 : double ); overload;
+
+ procedure transformImage(
+ img : Image_ptr;
+ dstX1 ,dstY1 ,dstX2 ,dstY2 : double ); overload;
+
+ procedure transformImage(
+ img : Image_ptr;
+ imgX1 ,imgY1 ,imgX2 ,imgY2 : int;
+ parallelogram_ : double_ptr ); overload;
+
+ procedure transformImage(img : Image_ptr; parallelogram_ : double_ptr ); overload;
+
+ procedure transformImagePath(
+ img : Image_ptr;
+ imgX1 ,imgY1 ,imgX2 ,imgY2 : int;
+ dstX1 ,dstY1 ,dstX2 ,dstY2 : double ); overload;
+
+ procedure transformImagePath(
+ img : Image_ptr;
+ dstX1 ,dstY1 ,dstX2 ,dstY2 : double ); overload;
+
+ procedure transformImagePath(
+ img : Image_ptr;
+ imgX1 ,imgY1 ,imgX2 ,imgY2 : int;
+ parallelogram_ : double_ptr ); overload;
+
+ procedure transformImagePath(img : Image_ptr; parallelogram_ : double_ptr ); overload;
+
+ // Image Blending (no transformations available)
+ procedure blendImage(
+ img : Image_ptr;
+ imgX1 ,imgY1 ,imgX2 ,imgY2 : int;
+ dstX ,dstY : double; alpha : unsigned = 255 ); overload;
+
+ procedure blendImage(img : Image_ptr; dstX ,dstY : double; alpha : unsigned = 255 ); overload;
+
+ // Copy image directly, together with alpha-channel
+ procedure copyImage(
+ img : Image_ptr;
+ imgX1 ,imgY1 ,imgX2 ,imgY2 : int;
+ dstX ,dstY : double ); overload;
+
+ procedure copyImage(img : Image_ptr; dstX ,dstY : double ); overload;
+
+ private
+ procedure render(fillColor_ : boolean ); overload;
+ procedure render(ras : FontRasterizer_ptr; sl : FontScanline_ptr ); overload;
+
+ procedure addLine(x1 ,y1 ,x2 ,y2 : double );
+ procedure updateRasterizerGamma;
+ procedure renderImage(
+ img : Image_ptr;
+ x1 ,y1 ,x2 ,y2 : int;
+ parl : double_ptr );
+
+ end;
+
+ SpanConvImageBlend_ptr = ^SpanConvImageBlend;
+ SpanConvImageBlend = object(span_convertor )
+ private
+ m_mode : BlendMode_;
+ m_color : Color;
+ m_pixel : pixel_formats_ptr; // m_pixFormatCompPre
+
+ public
+ constructor Construct(m : BlendMode_; c : Color; p : pixel_formats_ptr );
+
+ procedure convert(span : aggclr_ptr; x ,y : int; len : unsigned ); virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+// Auxiliary
+ function pi : double;
+ function deg2Rad(v : double ) : double;
+ function rad2Deg(v : double ) : double;
+
+ function operator_is_equal (c1 ,c2 : Color_ptr ) : boolean;
+ function operator_is_not_equal(c1 ,c2 : Color_ptr ) : boolean;
+
+ procedure Agg2DRenderer_render(
+ gr : Agg2D_ptr;
+ renBase : renderer_base_ptr;
+ renSolid : renderer_scanline_aa_solid_ptr;
+ fillColor_ : boolean ); overload;
+
+ procedure Agg2DRenderer_render(
+ gr : Agg2D_ptr;
+ renBase : renderer_base_ptr;
+ renSolid : renderer_scanline_aa_solid_ptr;
+ ras : gray8_adaptor_type_ptr;
+ sl : gray8_scanline_type_ptr ); overload;
+
+ procedure Agg2DRenderer_renderImage(
+ gr : Agg2D_ptr;
+ img : Image_ptr;
+ renBase : renderer_base_ptr;
+ interpolator : span_interpolator_linear_ptr );
+
+ function Agg2DUsesFreeType : boolean;
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+var
+ g_approxScale : double = 2.0;
+
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor Image.Construct;
+begin
+end;
+
+{ CONSTRUCT }
+constructor Image.Construct(buf : int8u_ptr; width_ ,height_ : unsigned; stride : int );
+begin
+ renBuf.Construct(buf ,width_ ,height_ ,stride );
+
+end;
+
+{ DESTRUCT }
+destructor Image.Destruct;
+begin
+ renBuf.Destruct;
+
+end;
+
+{ ATTACH }
+procedure Image.attach(buf : int8u_ptr; width_ ,height_ : unsigned; stride : int );
+begin
+ renBuf.attach(buf ,width_ ,height_ ,stride );
+
+end;
+
+{ WIDTH }
+function Image.width : int;
+begin
+ result:=renBuf._width;
+
+end;
+
+{ HEIGHT }
+function Image.height : int;
+begin
+ result:=renBuf._height;
+
+end;
+
+{ PREMULTIPLY }
+procedure Image.premultiply;
+var
+ pixf : pixel_formats;
+
+begin
+{ pixfmt_rgba32(pixf ,@renBuf );
+
+ pixf.premultiply; {!}
+
+end;
+
+{ DEMULTIPLY }
+procedure Image.demultiply;
+var
+ pixf : pixel_formats;
+
+begin
+{ pixfmt_rgba32(pixf ,@renBuf );
+
+ pixf.demultiply; {!}
+
+end;
+
+{ CONSTRUCT }
+constructor Agg2DRasterizerGamma.Construct(alpha ,gamma : double );
+begin
+ m_alpha.Construct(alpha );
+ m_gamma.Construct(gamma );
+
+end;
+
+{ FUNC_OPERATOR_GAMMA }
+function Agg2DRasterizerGamma.func_operator_gamma(x : double ) : double;
+begin
+ result:=m_alpha.func_operator_gamma(m_gamma.func_operator_gamma(x ) );
+
+end;
+
+{ CONSTRUCT }
+constructor Agg2D.Construct;
+begin
+ m_rbuf.Construct;
+
+ pixfmt_rgba32 (m_pixFormat ,@m_rbuf );
+ pixfmt_custom_blend_rgba(m_pixFormatComp ,@m_rbuf ,@comp_op_adaptor_rgba ,rgba_order );
+ pixfmt_rgba32 (m_pixFormatPre ,@m_rbuf );
+ pixfmt_custom_blend_rgba(m_pixFormatCompPre ,@m_rbuf ,@comp_op_adaptor_rgba ,rgba_order );
+
+ m_renBase.Construct (@m_pixFormat );
+ m_renBaseComp.Construct (@m_pixFormatComp );
+ m_renBasePre.Construct (@m_pixFormatPre );
+ m_renBaseCompPre.Construct(@m_pixFormatCompPre );
+
+ m_renSolid.Construct (@m_renBase );
+ m_renSolidComp.Construct(@m_renBaseComp );
+
+ m_allocator.Construct;
+ m_clipBox.Construct(0 ,0 ,0 ,0 );
+
+ m_blendMode :=BlendAlpha;
+ m_imageBlendMode:=BlendDst;
+
+ m_imageBlendColor.Construct(0 ,0 ,0 );
+
+ m_scanline.Construct;
+ m_rasterizer.Construct;
+
+ m_masterAlpha :=1.0;
+ m_antiAliasGamma:=1.0;
+
+ m_fillColor.Construct(255 ,255 ,255 );
+ m_lineColor.Construct(0 ,0 ,0 );
+
+ m_fillGradient.Construct(256 ,sizeof(aggclr ) );
+ m_lineGradient.Construct(256 ,sizeof(aggclr ) );
+
+ m_lineCap :=CapRound;
+ m_lineJoin:=JoinRound;
+
+ m_fillGradientFlag:=Solid;
+ m_lineGradientFlag:=Solid;
+
+ m_fillGradientMatrix.Construct;
+ m_lineGradientMatrix.Construct;
+
+ m_fillGradientD1:=0.0;
+ m_lineGradientD1:=0.0;
+ m_fillGradientD2:=100.0;
+ m_lineGradientD2:=100.0;
+
+ m_textAngle :=0.0;
+ m_textAlignX :=AlignLeft;
+ m_textAlignY :=AlignBottom;
+ m_textHints :=true;
+ m_fontHeight :=0.0;
+ m_fontAscent :=0.0;
+ m_fontDescent:=0.0;
+
+ m_fontCacheType:=RasterFontCache;
+ m_imageFilter :=Bilinear;
+ m_imageResample:=NoResample;
+
+ m_gammaNone.Construct;
+
+ m_ifBilinear.Construct;
+ m_ifHanning.Construct;
+ m_ifHermite.Construct;
+ m_ifQuadric.Construct;
+ m_ifBicubic.Construct;
+ m_ifCatrom.Construct;
+ m_ifSpline16.Construct;
+ m_ifSpline36.Construct;
+ m_ifBlackman144.Construct;
+
+ m_imageFilterLut.Construct(@m_ifBilinear ,true );
+
+ m_linearGradientFunction.Construct;
+ m_radialGradientFunction.Construct;
+
+ m_fillGradientInterpolator.Construct(@m_fillGradientMatrix );
+ m_lineGradientInterpolator.Construct(@m_lineGradientMatrix );
+
+ m_lineWidth :=1;
+ m_evenOddFlag:=false;
+
+ m_path.Construct;
+ m_transform.Construct;
+
+ m_convCurve.Construct (@m_path );
+ m_convStroke.Construct(@m_convCurve );
+
+ m_pathTransform.Construct (@m_convCurve ,@m_transform );
+ m_strokeTransform.Construct(@m_convStroke ,@m_transform );
+
+{$IFDEF AGG2D_USE_FREETYPE }
+ m_fontEngine.Construct;
+
+{$ELSE }
+ m_fontDC:=GetDC(0 );
+
+ m_fontEngine.Construct(m_fontDC );
+
+{$ENDIF }
+
+ m_fontCacheManager.Construct(@m_fontEngine );
+
+ lineCap (m_lineCap );
+ lineJoin(m_lineJoin );
+
+end;
+
+{ DESTRUCT }
+destructor Agg2D.Destruct;
+begin
+ m_rbuf.Destruct;
+
+ m_allocator.Destruct;
+
+ m_scanline.Destruct;
+ m_rasterizer.Destruct;
+
+ m_fillGradient.Destruct;
+ m_lineGradient.Destruct;
+
+ m_imageFilterLut.Destruct;
+ m_path.Destruct;
+
+ m_convCurve.Destruct;
+ m_convStroke.Destruct;
+
+ m_fontEngine.Destruct;
+ m_fontCacheManager.Destruct;
+
+{$IFNDEF AGG2D_USE_FREETYPE }
+ ReleaseDC(0 ,m_fontDC );
+
+{$ENDIF }
+
+end;
+
+{ ATTACH }
+procedure Agg2D.attach(buf : int8u_ptr; width_ ,height_ : unsigned; stride : int );
+begin
+ m_rbuf.attach(buf ,width_ ,height_ ,stride );
+
+ m_renBase.reset_clipping (true );
+ m_renBaseComp.reset_clipping (true );
+ m_renBasePre.reset_clipping (true );
+ m_renBaseCompPre.reset_clipping(true );
+
+ resetTransformations;
+
+ lineWidth(1.0 );
+ lineColor(0 ,0 ,0 );
+ fillColor(255 ,255 ,255 );
+
+ textAlignment(AlignLeft ,AlignBottom );
+
+ clipBox (0 ,0 ,width_ ,height_ );
+ lineCap (CapRound );
+ lineJoin(JoinRound );
+ flipText(false );
+
+ imageFilter (Bilinear );
+ imageResample(NoResample );
+
+ m_masterAlpha :=1.0;
+ m_antiAliasGamma:=1.0;
+
+ m_rasterizer.gamma(@m_gammaNone );
+
+ m_blendMode:=BlendAlpha;
+
+end;
+
+{ ATTACH }
+procedure Agg2D.attach(img : Image_ptr );
+begin
+ attach(img.renBuf._buf ,img.renBuf._width ,img.renBuf._height ,img.renBuf._stride );
+
+end;
+
+{ CLIPBOX }
+procedure Agg2D.clipBox(x1 ,y1 ,x2 ,y2 : double );
+var
+ rx1 ,ry1 ,rx2 ,ry2 : int;
+
+begin
+ m_clipBox.Construct(x1 ,y1 ,x2 ,y2 );
+
+ rx1:=Trunc(x1 );
+ ry1:=Trunc(y1 );
+ rx2:=Trunc(x2 );
+ ry2:=Trunc(y2 );
+
+ m_renBase.clip_box_ (rx1 ,ry1 ,rx2 ,ry2 );
+ m_renBaseComp.clip_box_ (rx1 ,ry1 ,rx2 ,ry2 );
+ m_renBasePre.clip_box_ (rx1 ,ry1 ,rx2 ,ry2 );
+ m_renBaseCompPre.clip_box_(rx1 ,ry1 ,rx2 ,ry2 );
+
+ m_rasterizer.clip_box(x1 ,y1 ,x2 ,y2 );
+
+end;
+
+{ CLIPBOX }
+function Agg2D.clipBox : RectD;
+begin
+ result:=m_clipBox;
+
+end;
+
+{ CLEARALL }
+procedure Agg2D.clearAll(c : Color );
+var
+ clr : aggclr;
+
+begin
+ clr.Construct (c );
+ m_renBase.clear(@clr );
+
+end;
+
+{ CLEARALL }
+procedure Agg2D.clearAll(r ,g ,b : unsigned; a : unsigned = 255 );
+var
+ clr : Color;
+
+begin
+ clr.Construct(r ,g ,b ,a );
+ clearAll (clr );
+
+end;
+
+{ CLEARCLIPBOX }
+procedure Agg2D.clearClipBox(c : Color );
+var
+ clr : aggclr;
+
+begin
+ clr.Construct(c );
+
+ m_renBase.copy_bar(0 ,0 ,m_renBase.width ,m_renBase.height ,@clr );
+
+end;
+
+{ CLEARCLIPBOX }
+procedure Agg2D.clearClipBox(r ,g ,b : unsigned; a : unsigned = 255 );
+var
+ clr : Color;
+
+begin
+ clr.Construct(r ,g ,b ,a );
+ clearClipBox (clr );
+
+end;
+
+{ WORLDTOSCREEN }
+procedure Agg2D.worldToScreen(x ,y : double_ptr );
+begin
+ m_transform.transform(@m_transform ,x ,y );
+
+end;
+
+{ SCREENTOWORLD }
+procedure Agg2D.screenToWorld(x ,y : double_ptr );
+begin
+ m_transform.inverse_transform(@m_transform ,x ,y );
+
+end;
+
+{ WORLDTOSCREEN }
+function Agg2D.worldToScreen(scalar : double ) : double;
+var
+ x1 ,y1 ,x2 ,y2 : double;
+
+begin
+ x1:=0;
+ y1:=0;
+ x2:=scalar;
+ y2:=scalar;
+
+ worldToScreen(@x1 ,@y1 );
+ worldToScreen(@x2 ,@y2 );
+
+ result:=Sqrt((x2 - x1 ) * (x2 - x1 ) + (y2 - y1 ) * (y2 - y1 ) ) * 0.7071068;
+
+end;
+
+{ SCREENTOWORLD }
+function Agg2D.screenToWorld(scalar : double ) : double;
+var
+ x1 ,y1 ,x2 ,y2 : double;
+
+begin
+ x1:=0;
+ y1:=0;
+ x2:=scalar;
+ y2:=scalar;
+
+ screenToWorld(@x1 ,@y1 );
+ screenToWorld(@x2 ,@y2 );
+
+ result:=Sqrt((x2 - x1 ) * (x2 - x1 ) + (y2 - y1 ) * (y2 - y1 ) ) * 0.7071068;
+
+end;
+
+{ ALIGNPOINT }
+procedure Agg2D.alignPoint(x ,y : double_ptr );
+begin
+ worldToScreen(x ,y );
+
+ x^:=Floor(x^ ) + 0.5;
+ y^:=Floor(y^ ) + 0.5;
+
+ screenToWorld(x ,y );
+
+end;
+
+{ INBOX }
+function Agg2D.inBox(worldX ,worldY : double ) : boolean;
+begin
+ worldToScreen(@worldX ,@worldY );
+
+ result:=m_renBase.inbox(Trunc(worldX ) ,Trunc(worldY ) );
+
+end;
+
+{ BLENDMODE }
+procedure Agg2D.blendMode(m : BlendMode_ );
+begin
+ m_blendMode:=m;
+
+ m_pixFormatComp.comp_op_ (unsigned(m ) );
+ m_pixFormatCompPre.comp_op_(unsigned(m ) );
+
+end;
+
+{ BLENDMODE }
+function Agg2D.blendMode : BlendMode_;
+begin
+ result:=m_blendMode;
+
+end;
+
+{ IMAGEBLENDMODE }
+procedure Agg2D.imageBlendMode(m : BlendMode_ );
+begin
+ m_imageBlendMode:=m;
+
+end;
+
+{ IMAGEBLENDMODE }
+function Agg2D.imageBlendMode : BlendMode_;
+begin
+ result:=m_imageBlendMode;
+
+end;
+
+{ IMAGEBLENDCOLOR }
+procedure Agg2D.imageBlendColor(c : Color );
+begin
+ m_imageBlendColor:=c;
+
+end;
+
+{ IMAGEBLENDCOLOR }
+procedure Agg2D.imageBlendColor(r ,g ,b : unsigned; a : unsigned = 255 );
+var
+ clr : Color;
+
+begin
+ clr.Construct (r ,g ,b ,a );
+ imageBlendColor(clr );
+
+end;
+
+{ IMAGEBLENDCOLOR }
+function Agg2D.imageBlendColor : Color;
+begin
+ result:=m_imageBlendColor;
+
+end;
+
+{ MASTERALPHA }
+procedure Agg2D.masterAlpha(a : double );
+begin
+ m_masterAlpha:=a;
+
+ updateRasterizerGamma;
+
+end;
+
+{ MASTERALPHA }
+function Agg2D.masterAlpha : double;
+begin
+ result:=m_masterAlpha;
+
+end;
+
+{ ANTIALIASGAMMA }
+procedure Agg2D.antiAliasGamma(g : double );
+begin
+ m_antiAliasGamma:=g;
+
+ updateRasterizerGamma;
+
+end;
+
+{ ANTIALIASGAMMA }
+function Agg2D.antiAliasGamma : double;
+begin
+ result:=m_antiAliasGamma;
+
+end;
+
+{ FILLCOLOR }
+procedure Agg2D.fillColor(c : Color );
+begin
+ m_fillColor :=c;
+ m_fillGradientFlag:=Solid;
+
+end;
+
+{ FILLCOLOR }
+procedure Agg2D.fillColor(r ,g ,b : unsigned; a : unsigned = 255 );
+var
+ clr : Color;
+
+begin
+ clr.Construct(r ,g ,b ,a );
+ fillColor (clr );
+
+end;
+
+{ NOFILL }
+procedure Agg2D.noFill;
+var
+ clr : Color;
+
+begin
+ clr.Construct(0 ,0 ,0 ,0 );
+ fillColor (clr );
+
+end;
+
+{ LINECOLOR }
+procedure Agg2D.lineColor(c : Color );
+begin
+ m_lineColor :=c;
+ m_lineGradientFlag:=Solid;
+
+end;
+
+{ LINECOLOR }
+procedure Agg2D.lineColor(r ,g ,b : unsigned; a : unsigned = 255 );
+var
+ clr : Color;
+
+begin
+ clr.Construct(r ,g ,b ,a );
+ lineColor (clr );
+
+end;
+
+{ NOLINE }
+procedure Agg2D.noLine;
+var
+ clr : Color;
+
+begin
+ clr.Construct(0 ,0 ,0 ,0 );
+ lineColor (clr );
+
+end;
+
+{ FILLCOLOR }
+function Agg2D.fillColor : Color;
+begin
+ result:=m_fillColor;
+
+end;
+
+{ LINECOLOR }
+function Agg2D.lineColor : Color;
+begin
+ result:=m_lineColor;
+
+end;
+
+{ FILLLINEARGRADIENT }
+procedure Agg2D.fillLinearGradient(x1 ,y1 ,x2 ,y2 : double; c1 ,c2 : Color; profile : double = 1.0 );
+var
+ i ,startGradient ,endGradient : int;
+
+ k ,angle : double;
+
+ c : Color;
+
+ clr : aggclr;
+ tar : trans_affine_rotation;
+ tat : trans_affine_translation;
+
+begin
+ startGradient:=128 - Trunc(profile * 127.0 );
+ endGradient :=128 + Trunc(profile * 127.0 );
+
+ if endGradient <= startGradient then
+ endGradient:=startGradient + 1;
+
+ k:=1.0 / (endGradient - startGradient );
+ i:=0;
+
+ while i < startGradient do
+ begin
+ clr.Construct(c1 );
+
+ move(clr ,m_fillGradient.array_operator(i )^ ,sizeof(aggclr ) );
+ inc (i );
+
+ end;
+
+ while i < endGradient do
+ begin
+ c:=c1.gradient(c2 ,(i - startGradient ) * k );
+
+ clr.Construct(c );
+
+ move(clr ,m_fillGradient.array_operator(i )^ ,sizeof(aggclr ) );
+ inc (i );
+
+ end;
+
+ while i < 256 do
+ begin
+ clr.Construct(c2 );
+
+ move(clr ,m_fillGradient.array_operator(i )^ ,sizeof(aggclr ) );
+ inc (i );
+
+ end;
+
+ angle:=ArcTan2(y2 - y1 ,x2 - x1 );
+
+ m_fillGradientMatrix.reset;
+
+ tar.Construct(angle );
+
+ m_fillGradientMatrix.multiply(@tar );
+
+ tat.Construct(x1 ,y1 );
+
+ m_fillGradientMatrix.multiply(@tat );
+ m_fillGradientMatrix.multiply(@m_transform );
+ m_fillGradientMatrix.invert;
+
+ m_fillGradientD1 :=0.0;
+ m_fillGradientD2 :=Sqrt((x2 - x1 ) * (x2 - x1 ) + (y2 - y1 ) * (y2 - y1 ) );
+ m_fillGradientFlag:=Linear;
+
+ m_fillColor.Construct(0 ,0 ,0 ); // Set some real color
+
+end;
+
+{ LINELINEARGRADIENT }
+procedure Agg2D.lineLinearGradient(x1 ,y1 ,x2 ,y2 : double; c1 ,c2 : Color; profile : double = 1.0 );
+var
+ i ,startGradient ,endGradient : int;
+
+ k ,angle : double;
+
+ c : Color;
+
+ clr : aggclr;
+ tar : trans_affine_rotation;
+ tat : trans_affine_translation;
+
+begin
+ startGradient:=128 - Trunc(profile * 128.0 );
+ endGradient :=128 + Trunc(profile * 128.0 );
+
+ if endGradient <= startGradient then
+ endGradient:=startGradient + 1;
+
+ k:=1.0 / (endGradient - startGradient );
+ i:=0;
+
+ while i < startGradient do
+ begin
+ clr.Construct(c1 );
+
+ move(clr ,m_lineGradient.array_operator(i )^ ,sizeof(aggclr ) );
+ inc (i );
+
+ end;
+
+ while i < endGradient do
+ begin
+ c:=c1.gradient(c2 ,(i - startGradient) * k );
+
+ clr.Construct(c );
+
+ move(clr ,m_lineGradient.array_operator(i )^ ,sizeof(aggclr ) );
+ inc (i );
+
+ end;
+
+ while i < 256 do
+ begin
+ clr.Construct(c2 );
+
+ move(clr ,m_lineGradient.array_operator(i )^ ,sizeof(aggclr ) );
+ inc (i );
+
+ end;
+
+ angle:=ArcTan2(y2 - y1 ,x2 - x1 );
+
+ m_lineGradientMatrix.reset;
+
+ tar.Construct(angle );
+
+ m_lineGradientMatrix.multiply(@tar );
+
+ tat.Construct(x1 ,y1 );
+
+ m_lineGradientMatrix.multiply(@tat );
+ m_lineGradientMatrix.multiply(@m_transform ); {!}
+ m_lineGradientMatrix.invert;
+
+ m_lineGradientD1 :=0.0;
+ m_lineGradientD2 :=Sqrt((x2 - x1 ) * (x2 - x1 ) + (y2 - y1 ) * (y2 - y1 ) );
+ m_lineGradientFlag:=Linear;
+
+ m_lineColor.Construct(0 ,0 ,0 ); // Set some real color
+
+end;
+
+{ FILLRADIALGRADIENT }
+procedure Agg2D.fillRadialGradient(x ,y ,r : double; c1 ,c2 : Color; profile : double = 1.0 );
+var
+ i ,startGradient ,endGradient : int;
+
+ k : double;
+ c : Color;
+
+ clr : aggclr;
+ tat : trans_affine_translation;
+
+begin
+ startGradient:=128 - Trunc(profile * 127.0 );
+ endGradient :=128 + Trunc(profile * 127.0 );
+
+ if endGradient <= startGradient then
+ endGradient:=startGradient + 1;
+
+ k:=1.0 / (endGradient - startGradient );
+ i:=0;
+
+ while i < startGradient do
+ begin
+ clr.Construct(c1 );
+
+ move(clr ,m_fillGradient.array_operator(i )^ ,sizeof(aggclr ) );
+ inc (i );
+
+ end;
+
+ while i < endGradient do
+ begin
+ c:=c1.gradient(c2 ,(i - startGradient ) * k );
+
+ clr.Construct(c );
+
+ move(clr ,m_fillGradient.array_operator(i )^ ,sizeof(aggclr ) );
+ inc (i );
+
+ end;
+
+ while i < 256 do
+ begin
+ clr.Construct(c2 );
+
+ move(clr ,m_fillGradient.array_operator(i )^ ,sizeof(aggclr ) );
+ inc (i );
+
+ end;
+
+ m_fillGradientD2:=worldToScreen(r );
+
+ worldToScreen(@x ,@y );
+
+ m_fillGradientMatrix.reset;
+
+ tat.Construct(x ,y );
+
+ m_fillGradientMatrix.multiply(@tat );
+ m_fillGradientMatrix.invert;
+
+ m_fillGradientD1 :=0;
+ m_fillGradientFlag:=Radial;
+
+ m_fillColor.Construct(0 ,0 ,0 ); // Set some real color
+
+end;
+
+{ LINERADIALGRADIENT }
+procedure Agg2D.lineRadialGradient(x ,y ,r : double; c1 ,c2 : Color; profile : double = 1.0 );
+var
+ i ,startGradient ,endGradient : int;
+
+ k : double;
+ c : Color;
+
+ clr : aggclr;
+ tat : trans_affine_translation;
+
+begin
+ startGradient:=128 - Trunc(profile * 128.0 );
+ endGradient :=128 + Trunc(profile * 128.0 );
+
+ if endGradient <= startGradient then
+ endGradient:=startGradient + 1;
+
+ k:=1.0 / (endGradient - startGradient );
+ i:=0;
+
+ while i < startGradient do
+ begin
+ clr.Construct(c1 );
+
+ move(clr ,m_lineGradient.array_operator(i )^ ,sizeof(aggclr ) );
+ inc (i );
+
+ end;
+
+ while i < endGradient do
+ begin
+ c:=c1.gradient(c2 ,(i - startGradient ) * k );
+
+ clr.Construct(c );
+
+ move(clr ,m_lineGradient.array_operator(i )^ ,sizeof(aggclr ) );
+ inc (i );
+
+ end;
+
+ while i < 256 do
+ begin
+ clr.Construct(c2 );
+
+ move(clr ,m_lineGradient.array_operator(i )^ ,sizeof(aggclr ) );
+ inc (i );
+
+ end;
+
+ m_lineGradientD2:=worldToScreen(r );
+
+ worldToScreen(@x ,@y );
+
+ m_lineGradientMatrix.reset;
+
+ tat.Construct(x ,y );
+
+ m_lineGradientMatrix.multiply(@tat );
+ m_lineGradientMatrix.invert;
+
+ m_lineGradientD1 :=0;
+ m_lineGradientFlag:=Radial;
+
+ m_lineColor.Construct(0 ,0 ,0 ); // Set some real color
+
+end;
+
+{ FILLRADIALGRADIENT }
+procedure Agg2D.fillRadialGradient(x ,y ,r : double; c1 ,c2 ,c3 : Color );
+var
+ i : int;
+ c : Color;
+
+ clr : aggclr;
+ tat : trans_affine_translation;
+
+begin
+ i:=0;
+
+ while i < 128 do
+ begin
+ c:=c1.gradient(c2 ,i / 127.0 );
+
+ clr.Construct(c );
+
+ move(clr ,m_fillGradient.array_operator(i )^ ,sizeof(aggclr ) );
+ inc (i );
+
+ end;
+
+ while i < 256 do
+ begin
+ c:=c2.gradient(c3 ,(i - 128 ) / 127.0 );
+
+ clr.Construct(c );
+
+ move(clr ,m_fillGradient.array_operator(i )^ ,sizeof(aggclr ) );
+ inc (i );
+
+ end;
+
+ m_fillGradientD2:=worldToScreen(r );
+
+ worldToScreen(@x ,@y );
+
+ m_fillGradientMatrix.reset;
+
+ tat.Construct(x ,y );
+
+ m_fillGradientMatrix.multiply(@tat );
+ m_fillGradientMatrix.invert;
+
+ m_fillGradientD1 :=0;
+ m_fillGradientFlag:=Radial;
+
+ m_fillColor.Construct(0 ,0 ,0 ); // Set some real color
+
+end;
+
+{ LINERADIALGRADIENT }
+procedure Agg2D.lineRadialGradient(x ,y ,r : double; c1 ,c2 ,c3 : Color );
+var
+ i : int;
+ c : Color;
+
+ clr : aggclr;
+ tat : trans_affine_translation;
+
+begin
+ i:=0;
+
+ while i < 128 do
+ begin
+ c:=c1.gradient(c2 ,i / 127.0 );
+
+ clr.Construct(c );
+
+ move(clr ,m_lineGradient.array_operator(i )^ ,sizeof(aggclr ) );
+ inc (i );
+
+ end;
+
+ while i < 256 do
+ begin
+ c:=c2.gradient(c3 ,(i - 128 ) / 127.0 );
+
+ clr.Construct(c );
+
+ move(clr ,m_lineGradient.array_operator(i )^ ,sizeof(aggclr ) );
+ inc (i );
+
+ end;
+
+ m_lineGradientD2:=worldToScreen(r );
+
+ worldToScreen(@x ,@y );
+
+ m_lineGradientMatrix.reset;
+
+ tat.Construct(x ,y );
+
+ m_lineGradientMatrix.multiply(@tat );
+ m_lineGradientMatrix.invert;
+
+ m_lineGradientD1 :=0;
+ m_lineGradientFlag:=Radial;
+
+ m_lineColor.Construct(0 ,0 ,0 ); // Set some real color
+
+end;
+
+{ FILLRADIALGRADIENT }
+procedure Agg2D.fillRadialGradient(x ,y ,r : double );
+var
+ tat : trans_affine_translation;
+
+begin
+ m_fillGradientD2:=worldToScreen(r );
+
+ worldToScreen(@x ,@y );
+
+ m_fillGradientMatrix.reset;
+
+ tat.Construct(x ,y );
+
+ m_fillGradientMatrix.multiply(@tat );
+ m_fillGradientMatrix.invert;
+
+ m_fillGradientD1:=0;
+
+end;
+
+{ LINERADIALGRADIENT }
+procedure Agg2D.lineRadialGradient(x ,y ,r : double );
+var
+ tat : trans_affine_translation;
+
+begin
+ m_lineGradientD2:=worldToScreen(r );
+
+ worldToScreen(@x ,@y );
+
+ m_lineGradientMatrix.reset;
+
+ tat.Construct(x ,y );
+
+ m_lineGradientMatrix.multiply(@tat );
+ m_lineGradientMatrix.invert;
+
+ m_lineGradientD1:=0;
+
+end;
+
+{ LINEWIDTH }
+procedure Agg2D.lineWidth(w : double );
+begin
+ m_lineWidth:=w;
+
+ m_convStroke.width_(w );
+
+end;
+
+{ LINEWIDTH_ }
+function Agg2D.lineWidth_(w : double ) : double;
+begin
+ result:=m_lineWidth;
+
+end;
+
+{ LINECAP }
+procedure Agg2D.lineCap(cap : LineCap_ );
+begin
+ m_lineCap:=cap;
+
+ m_convStroke.line_cap_(cap );
+
+end;
+
+{ LINECAP }
+function Agg2D.lineCap : LineCap_;
+begin
+ result:=m_lineCap;
+
+end;
+
+{ LINEJOIN }
+procedure Agg2D.lineJoin(join : LineJoin_ );
+begin
+ m_lineJoin:=join;
+
+ m_convStroke.line_join_(join );
+
+end;
+
+{ LINEJOIN }
+function Agg2D.lineJoin : LineJoin_;
+begin
+ result:=m_lineJoin;
+
+end;
+
+{ FILLEVENODD }
+procedure Agg2D.fillEvenOdd(evenOddFlag : boolean );
+begin
+ m_evenOddFlag:=evenOddFlag;
+
+ if evenOddFlag then
+ m_rasterizer.filling_rule(fill_even_odd )
+ else
+ m_rasterizer.filling_rule(fill_non_zero );
+
+end;
+
+{ FILLEVENODD }
+function Agg2D.fillEvenOdd : boolean;
+begin
+ result:=m_evenOddFlag;
+
+end;
+
+{ TRANSFORMATIONS }
+function Agg2D.transformations : Transformations_;
+begin
+ m_transform.store_to(@result.affineMatrix[0 ] );
+
+end;
+
+{ TRANSFORMATIONS }
+procedure Agg2D.transformations(tr : Transformations_ptr );
+begin
+ m_transform.load_from(@tr.affineMatrix[0 ] );
+
+ m_convCurve.approximation_scale_ (worldToScreen(1.0 ) * g_approxScale );
+ m_convStroke.approximation_scale_(worldToScreen(1.0 ) * g_approxScale );
+
+end;
+
+{ RESETTRANSFORMATIONS }
+procedure Agg2D.resetTransformations;
+begin
+ m_transform.reset;
+
+end;
+
+{ AFFINE }
+procedure Agg2D.affine(tr : Affine_ptr );
+begin
+ m_transform.multiply(tr );
+
+ m_convCurve.approximation_scale_ (worldToScreen(1.0 ) * g_approxScale );
+ m_convStroke.approximation_scale_(worldToScreen(1.0 ) * g_approxScale );
+
+end;
+
+{ AFFINE }
+procedure Agg2D.affine(tr : Transformations_ptr );
+var
+ ta : trans_affine;
+
+begin
+ ta.Construct(
+ tr.affineMatrix[0 ] ,tr.affineMatrix[1 ] ,tr.affineMatrix[2 ] ,
+ tr.affineMatrix[3 ] ,tr.affineMatrix[4 ] ,tr.affineMatrix[5 ] );
+
+ affine(Affine_ptr(@ta ) );
+
+end;
+
+{ ROTATE }
+procedure Agg2D.rotate(angle : double );
+var
+ tar : trans_affine_rotation;
+
+begin
+ tar.Construct(angle );
+
+ m_transform.multiply(@tar );
+
+end;
+
+{ SCALE }
+procedure Agg2D.scale(sx ,sy : double );
+var
+ tas : trans_affine_scaling;
+
+begin
+ tas.Construct(sx ,sy );
+
+ m_transform.multiply(@tas );
+
+ m_convCurve.approximation_scale_ (worldToScreen(1.0 ) * g_approxScale );
+ m_convStroke.approximation_scale_(worldToScreen(1.0 ) * g_approxScale );
+
+end;
+
+{ SKEW }
+procedure Agg2D.skew(sx ,sy : double );
+var
+ tas : trans_affine_skewing;
+
+begin
+ tas.Construct(sx ,sy );
+
+ m_transform.multiply(@tas );
+
+end;
+
+{ TRANSLATE }
+procedure Agg2D.translate(x ,y : double );
+var
+ tat : trans_affine_translation;
+
+begin
+ tat.Construct(x ,y );
+
+ m_transform.multiply(@tat );
+
+end;
+
+{ PARALLELOGRAM }
+procedure Agg2D.parallelogram(x1 ,y1 ,x2 ,y2 : double; para : double_ptr );
+var
+ ta : trans_affine;
+
+begin
+ ta.Construct(x1 ,y1 ,x2 ,y2 ,parallelo_ptr(para ) );
+
+ m_transform.multiply(@ta );
+
+ m_convCurve.approximation_scale_ (worldToScreen(1.0 ) * g_approxScale );
+ m_convStroke.approximation_scale_(worldToScreen(1.0 ) * g_approxScale );
+
+end;
+
+{ VIEWPORT }
+procedure Agg2D.viewport(
+ worldX1 ,worldY1 ,worldX2 ,worldY2 ,
+ screenX1 ,screenY1 ,screenX2 ,screenY2 : double;
+ opt : ViewportOption = XMidYMid );
+var
+ vp : trans_viewport;
+ mx : trans_affine;
+
+begin
+ vp.Construct;
+
+ case opt of
+ Anisotropic :
+ vp.preserve_aspect_ratio(0.0 ,0.0 ,aspect_ratio_stretch );
+
+ XMinYMin :
+ vp.preserve_aspect_ratio(0.0 ,0.0 ,aspect_ratio_meet );
+
+ XMidYMin :
+ vp.preserve_aspect_ratio(0.5 ,0.0 ,aspect_ratio_meet );
+
+ XMaxYMin :
+ vp.preserve_aspect_ratio(1.0 ,0.0 ,aspect_ratio_meet );
+
+ XMinYMid :
+ vp.preserve_aspect_ratio(0.0 ,0.5 ,aspect_ratio_meet );
+
+ XMidYMid :
+ vp.preserve_aspect_ratio(0.5 ,0.5 ,aspect_ratio_meet );
+
+ XMaxYMid :
+ vp.preserve_aspect_ratio(1.0 ,0.5 ,aspect_ratio_meet );
+
+ XMinYMax :
+ vp.preserve_aspect_ratio(0.0 ,1.0 ,aspect_ratio_meet );
+
+ XMidYMax :
+ vp.preserve_aspect_ratio(0.5 ,1.0 ,aspect_ratio_meet );
+
+ XMaxYMax :
+ vp.preserve_aspect_ratio(1.0 ,1.0 ,aspect_ratio_meet );
+
+ end;
+
+ vp.world_viewport (worldX1 ,worldY1 ,worldX2 ,worldY2 );
+ vp.device_viewport(screenX1 ,screenY1 ,screenX2 ,screenY2 );
+
+ mx.Construct;
+
+ vp.to_affine (@mx );
+ m_transform.multiply(@mx );
+
+ m_convCurve.approximation_scale_ (worldToScreen(1.0 ) * g_approxScale );
+ m_convStroke.approximation_scale_(worldToScreen(1.0 ) * g_approxScale );
+
+end;
+
+{ LINE }
+procedure Agg2D.line(x1 ,y1 ,x2 ,y2 : double );
+begin
+ m_path.remove_all;
+
+ addLine (x1 ,y1 ,x2 ,y2 );
+ drawPath(StrokeOnly );
+
+end;
+
+{ TRIANGLE }
+procedure Agg2D.triangle(x1 ,y1 ,x2 ,y2 ,x3 ,y3 : double );
+begin
+ m_path.remove_all;
+ m_path.move_to(x1 ,y1 );
+ m_path.line_to(x2 ,y2 );
+ m_path.line_to(x3 ,y3 );
+ m_path.close_polygon;
+
+ drawPath(FillAndStroke );
+
+end;
+
+{ RECTANGLE }
+procedure Agg2D.rectangle(x1 ,y1 ,x2 ,y2 : double );
+begin
+ m_path.remove_all;
+ m_path.move_to(x1 ,y1 );
+ m_path.line_to(x2 ,y1 );
+ m_path.line_to(x2 ,y2 );
+ m_path.line_to(x1 ,y2 );
+ m_path.close_polygon;
+
+ drawPath(FillAndStroke );
+
+end;
+
+{ ROUNDEDRECT }
+procedure Agg2D.roundedRect(x1 ,y1 ,x2 ,y2 ,r : double );
+var
+ rc : rounded_rect;
+
+begin
+ m_path.remove_all;
+ rc.Construct(x1 ,y1 ,x2 ,y2 ,r );
+
+ rc.normalize_radius;
+ rc.approximation_scale_(worldToScreen(1.0 ) * g_approxScale );
+
+ m_path.add_path(@rc ,0 ,false );
+
+ drawPath(FillAndStroke );
+
+end;
+
+{ ROUNDEDRECT }
+procedure Agg2D.roundedRect(x1 ,y1 ,x2 ,y2 ,rx ,ry : double );
+var
+ rc : rounded_rect;
+
+begin
+ m_path.remove_all;
+ rc.Construct;
+
+ rc.rect (x1 ,y1 ,x2 ,y2 );
+ rc.radius(rx ,ry );
+ rc.normalize_radius;
+
+ m_path.add_path(@rc ,0 ,false );
+
+ drawPath(FillAndStroke );
+
+end;
+
+{ ROUNDEDRECT }
+procedure Agg2D.roundedRect(
+ x1 ,y1 ,x2 ,y2 ,
+ rxBottom ,ryBottom ,
+ rxTop ,ryTop : double );
+var
+ rc : rounded_rect;
+
+begin
+ m_path.remove_all;
+ rc.Construct;
+
+ rc.rect (x1 ,y1 ,x2 ,y2 );
+ rc.radius(rxBottom ,ryBottom ,rxTop ,ryTop );
+ rc.normalize_radius;
+
+ rc.approximation_scale_(worldToScreen(1.0 ) * g_approxScale );
+
+ m_path.add_path(@rc ,0 ,false );
+
+ drawPath(FillAndStroke );
+
+end;
+
+{ ELLIPSE }
+procedure Agg2D.ellipse(cx ,cy ,rx ,ry : double );
+var
+ el : bezier_arc;
+
+begin
+ m_path.remove_all;
+
+ el.Construct(cx ,cy ,rx ,ry ,0 ,2 * pi );
+
+ m_path.add_path(@el ,0 ,false );
+ m_path.close_polygon;
+
+ drawPath(FillAndStroke );
+
+end;
+
+{ ARC }
+procedure Agg2D.arc(cx ,cy ,rx ,ry ,start ,sweep : double );
+var
+ ar : {bezier_}agg_arc.arc;
+
+begin
+ m_path.remove_all;
+
+ ar.Construct(cx ,cy ,rx ,ry ,start ,sweep ,false );
+
+ m_path.add_path(@ar ,0 ,false );
+
+ drawPath(StrokeOnly );
+
+end;
+
+{ STAR }
+procedure Agg2D.star(cx ,cy ,r1 ,r2 ,startAngle : double; numRays : int );
+var
+ da ,a ,x ,y : double;
+
+ i : int;
+
+begin
+ m_path.remove_all;
+
+ da:=pi / numRays;
+ a :=startAngle;
+
+ i:=0;
+
+ while i < numRays do
+ begin
+ x:=Cos(a ) * r2 + cx;
+ y:=Sin(a ) * r2 + cy;
+
+ if i <> 0 then
+ m_path.line_to(x ,y )
+ else
+ m_path.move_to(x ,y );
+
+ a:=a + da;
+
+ m_path.line_to(Cos(a ) * r1 + cx ,Sin(a ) * r1 + cy );
+
+ a:=a + da;
+
+ inc(i );
+
+ end;
+
+ closePolygon;
+ drawPath(FillAndStroke );
+
+end;
+
+{ CURVE }
+procedure Agg2D.curve(x1 ,y1 ,x2 ,y2 ,x3 ,y3 : double );
+begin
+ m_path.remove_all;
+ m_path.move_to(x1 ,y1 );
+ m_path.curve3 (x2 ,y2 ,x3 ,y3 );
+
+ drawPath(StrokeOnly );
+
+end;
+
+{ CURVE }
+procedure Agg2D.curve(x1 ,y1 ,x2 ,y2 ,x3 ,y3 ,x4 ,y4 : double );
+begin
+ m_path.remove_all;
+ m_path.move_to(x1 ,y1 );
+ m_path.curve4 (x2 ,y2 ,x3 ,y3 ,x4 ,y4 );
+
+ drawPath(StrokeOnly );
+
+end;
+
+{ POLYGON }
+procedure Agg2D.polygon(xy : double_ptr; numPoints : int );
+begin
+ m_path.remove_all;
+ m_path.add_poly(double_2_ptr(xy ) ,numPoints );
+
+ closePolygon;
+ drawPath(FillAndStroke );
+
+end;
+
+{ POLYLINE }
+procedure Agg2D.polyline(xy : double_ptr; numPoints : int );
+begin
+ m_path.remove_all;
+ m_path.add_poly(double_2_ptr(xy ) ,numPoints );
+
+ drawPath(StrokeOnly );
+
+end;
+
+{ FLIPTEXT }
+procedure Agg2D.flipText(flip : boolean );
+begin
+ m_fontEngine.flip_y_(flip );
+
+end;
+
+{ FONT }
+procedure Agg2D.font(
+ fileName : char_ptr; height : double;
+ bold : boolean = false;
+ italic : boolean = false;
+ ch : FontCacheType = RasterFontCache;
+ angle : double = 0.0 );
+var
+ b : int;
+
+begin
+ m_textAngle :=angle;
+ m_fontHeight :=height;
+ m_fontCacheType:=ch;
+
+{$IFDEF AGG2D_USE_FREETYPE }
+ if ch = VectorFontCache then
+ m_fontEngine.load_font(PChar(fileName ) ,0 ,glyph_ren_outline )
+ else
+ m_fontEngine.load_font(PChar(fileName ) ,0 ,glyph_ren_agg_gray8 );
+
+ m_fontEngine.hinting_(m_textHints );
+
+ if ch = VectorFontCache then
+ m_fontEngine.height_(height )
+ else
+ m_fontEngine.height_(worldToScreen(height ) );
+
+{$ELSE }
+ m_fontEngine.hinting_(m_textHints );
+
+ if bold then
+ b:=700
+ else
+ b:=400;
+
+ if ch = VectorFontCache then
+ m_fontEngine.create_font_(PChar(fileName ) ,glyph_ren_outline ,height ,0.0 ,b ,italic )
+ else
+ m_fontEngine.create_font_(PChar(fileName ) ,glyph_ren_agg_gray8 ,worldToScreen(height) ,0.0 ,b ,italic );
+
+{$ENDIF }
+
+end;
+
+{ FONTHEIGHT }
+function Agg2D.fontHeight : double;
+begin
+ result:=m_fontHeight;
+
+end;
+
+{ TEXTALIGNMENT }
+procedure Agg2D.textAlignment(alignX ,alignY : TextAlignment );
+begin
+ m_textAlignX:=alignX;
+ m_textAlignY:=alignY;
+
+end;
+
+{ TEXTHINTS }
+function Agg2D.textHints : boolean;
+begin
+ result:=m_textHints;
+
+end;
+
+{ TEXTHINTS }
+procedure Agg2D.textHints(hints : boolean );
+begin
+ m_textHints:=hints;
+
+end;
+
+{ TEXTWIDTH }
+function Agg2D.textWidth(str : char_ptr ) : double;
+var
+ x ,y : double;
+ first : boolean;
+ glyph : glyph_cache_ptr;
+
+begin
+ x:=0;
+ y:=0;
+
+ first:=true;
+
+ while str^ <> #0 do
+ begin
+ glyph:=m_fontCacheManager.glyph(int32u(str^ ) );
+
+ if glyph <> NIL then
+ begin
+ if not first then
+ m_fontCacheManager.add_kerning(@x ,@y );
+
+ x:=x + glyph.advance_x;
+ y:=y + glyph.advance_y;
+
+ first:=false; {!}
+
+ end;
+
+ inc(ptrcomp(str ) );
+
+ end;
+
+ if m_fontCacheType = VectorFontCache then
+ result:=x
+ else
+ result:=screenToWorld(x );
+
+end;
+
+{ TEXT }
+procedure Agg2D.text(
+ x ,y : double; str : char_ptr;
+ roundOff : boolean = false;
+ ddx : double = 0.0;
+ ddy : double = 0.0 );
+var
+ dx ,dy ,asc ,start_x ,start_y : double;
+
+ glyph : glyph_cache_ptr;
+
+ mtx : trans_affine;
+
+ i : int;
+
+ tat : trans_affine_translation;
+ tar : trans_affine_rotation;
+
+ tr : conv_transform;
+
+begin
+ dx:=0.0;
+ dy:=0.0;
+
+ case m_textAlignX of
+ AlignCenter :
+ dx:=-textWidth(str ) * 0.5;
+
+ AlignRight :
+ dx:=-textWidth(str );
+
+ end;
+
+ asc :=fontHeight;
+ glyph:=m_fontCacheManager.glyph(int32u('H' ) );
+
+ if glyph <> NIL then
+ asc:=glyph.bounds.y2 - glyph.bounds.y1;
+
+ if m_fontCacheType = RasterFontCache then
+ asc:=screenToWorld(asc );
+
+ case m_textAlignY of
+ AlignCenter :
+ dy:=-asc * 0.5;
+
+ AlignTop :
+ dy:=-asc;
+
+ end;
+
+ if m_fontEngine._flip_y then
+ dy:=-dy;
+
+ mtx.Construct;
+
+ start_x:=x + dx;
+ start_y:=y + dy;
+
+ if roundOff then
+ begin
+ start_x:=Trunc(start_x );
+ start_y:=Trunc(start_y );
+
+ end;
+
+ start_x:=start_x + ddx;
+ start_y:=start_y + ddy;
+
+ tat.Construct(-x ,-y );
+ mtx.multiply (@tat );
+
+ tar.Construct(m_textAngle );
+ mtx.multiply (@tar );
+
+ tat.Construct(x ,y );
+ mtx.multiply (@tat );
+
+ tr.Construct(m_fontCacheManager.path_adaptor ,@mtx );
+
+ if m_fontCacheType = RasterFontCache then
+ worldToScreen(@start_x ,@start_y );
+
+ i:=0;
+
+ while char_ptr(ptrcomp(str ) + i * sizeof(char ) )^ <> #0 do
+ begin
+ glyph:=m_fontCacheManager.glyph(int32u(char_ptr(ptrcomp(str ) + i * sizeof(char ) )^ ) );
+
+ if glyph <> NIL then
+ begin
+ if i <> 0 then
+ m_fontCacheManager.add_kerning(@x ,@y );
+
+ m_fontCacheManager.init_embedded_adaptors(glyph ,start_x ,start_y );
+
+ if glyph.data_type = glyph_data_outline then
+ begin
+ m_path.remove_all;
+ m_path.add_path(@tr ,0 ,false );
+
+ drawPath;
+
+ end;
+
+ if glyph.data_type = glyph_data_gray8 then
+ begin
+ render(
+ m_fontCacheManager.gray8_adaptor ,
+ m_fontCacheManager.gray8_scanline );
+
+ end;
+
+ start_x:=start_x + glyph.advance_x;
+ start_y:=start_y + glyph.advance_y;
+
+ end;
+
+ inc(i );
+
+ end;
+
+end;
+
+{ RESETPATH }
+procedure Agg2D.resetPath;
+begin
+ m_path.remove_all;
+
+end;
+
+{ MOVETO }
+procedure Agg2D.moveTo(x ,y : double );
+begin
+ m_path.move_to(x ,y );
+
+end;
+
+{ MOVEREL }
+procedure Agg2D.moveRel(dx ,dy : double );
+begin
+ m_path.move_rel(dx ,dy );
+
+end;
+
+{ LINETO }
+procedure Agg2D.lineTo(x ,y : double );
+begin
+ m_path.line_to(x ,y );
+
+end;
+
+{ LINEREL }
+procedure Agg2D.lineRel(dx ,dy : double );
+begin
+ m_path.line_rel(dx ,dy );
+
+end;
+
+{ HORLINETO }
+procedure Agg2D.horLineTo(x : double );
+begin
+ m_path.hline_to(x );
+
+end;
+
+{ HORLINEREL }
+procedure Agg2D.horLineRel(dx : double );
+begin
+ m_path.hline_rel(dx );
+
+end;
+
+{ VERLINETO }
+procedure Agg2D.verLineTo(y : double );
+begin
+ m_path.vline_to(y );
+
+end;
+
+{ VERLINEREL }
+procedure Agg2D.verLineRel(dy : double );
+begin
+ m_path.vline_rel(dy );
+
+end;
+
+{ ARCTO }
+procedure Agg2D.arcTo(
+ rx ,ry ,angle : double;
+ largeArcFlag ,sweepFlag : boolean;
+ x ,y : double );
+begin
+ m_path.arc_to(rx ,ry ,angle ,largeArcFlag ,sweepFlag ,x ,y );
+
+end;
+
+{ ARCREL }
+procedure Agg2D.arcRel(
+ rx ,ry ,angle : double;
+ largeArcFlag ,sweepFlag : boolean;
+ dx ,dy : double );
+begin
+ m_path.arc_rel(rx ,ry ,angle ,largeArcFlag ,sweepFlag ,dx ,dy );
+
+end;
+
+{ QUADRICCURVETO }
+procedure Agg2D.quadricCurveTo (xCtrl ,yCtrl ,xTo ,yTo : double );
+begin
+ m_path.curve3(xCtrl ,yCtrl ,xTo ,yTo );
+
+end;
+
+{ QUADRICCURVEREL }
+procedure Agg2D.quadricCurveRel(dxCtrl ,dyCtrl ,dxTo ,dyTo : double );
+begin
+ m_path.curve3_rel(dxCtrl ,dyCtrl ,dxTo ,dyTo );
+
+end;
+
+{ QUADRICCURVETO }
+procedure Agg2D.quadricCurveTo (xTo ,yTo : double );
+begin
+ m_path.curve3(xTo ,yTo );
+
+end;
+
+{ QUADRICCURVEREL }
+procedure Agg2D.quadricCurveRel(dxTo ,dyTo : double );
+begin
+ m_path.curve3_rel(dxTo ,dyTo );
+
+end;
+
+{ CUBICCURVETO }
+procedure Agg2D.cubicCurveTo (xCtrl1 ,yCtrl1 ,xCtrl2 ,yCtrl2 ,xTo ,yTo : double );
+begin
+ m_path.curve4(xCtrl1 ,yCtrl1 ,xCtrl2 ,yCtrl2 ,xTo ,yTo );
+
+end;
+
+{ CUBICCURVEREL }
+procedure Agg2D.cubicCurveRel(dxCtrl1 ,dyCtrl1 ,dxCtrl2 ,dyCtrl2 ,dxTo ,dyTo : double );
+begin
+ m_path.curve4_rel(dxCtrl1 ,dyCtrl1 ,dxCtrl2 ,dyCtrl2 ,dxTo ,dyTo );
+
+end;
+
+{ CUBICCURVETO }
+procedure Agg2D.cubicCurveTo (xCtrl2 ,yCtrl2 ,xTo ,yTo : double );
+begin
+ m_path.curve4(xCtrl2 ,yCtrl2 ,xTo ,yTo );
+
+end;
+
+{ CUBICCURVEREL }
+procedure Agg2D.cubicCurveRel(xCtrl2 ,yCtrl2 ,xTo ,yTo : double );
+begin
+ m_path.curve4_rel(xCtrl2 ,yCtrl2 ,xTo ,yTo );
+
+end;
+
+{ ADDELLIPSE }
+procedure Agg2D.addEllipse(cx ,cy ,rx ,ry : double; dir : Direction );
+var
+ ar : bezier_arc;
+
+begin
+ if dir = CCW then
+ ar.Construct(cx ,cy ,rx ,ry ,0 ,2 * pi )
+ else
+ ar.Construct(cx ,cy ,rx ,ry ,0 ,-2 * pi );
+
+ m_path.add_path(@ar ,0 ,false );
+ m_path.close_polygon;
+
+end;
+
+{ CLOSEPOLYGON }
+procedure Agg2D.closePolygon;
+begin
+ m_path.close_polygon;
+
+end;
+
+{ DRAWPATH }
+procedure Agg2D.drawPath(flag : DrawPathFlag = FillAndStroke );
+begin
+ m_rasterizer.reset;
+
+ case flag of
+ FillOnly :
+ if m_fillColor.a <> 0 then
+ begin
+ m_rasterizer.add_path(@m_pathTransform );
+
+ render(true );
+
+ end;
+
+ StrokeOnly :
+ if (m_lineColor.a <> 0 ) and
+ (m_lineWidth > 0.0 ) then
+ begin
+ m_rasterizer.add_path(@m_strokeTransform );
+
+ render(false );
+
+ end;
+
+ FillAndStroke :
+ begin
+ if m_fillColor.a <> 0 then
+ begin
+ m_rasterizer.add_path(@m_pathTransform );
+
+ render(true );
+
+ end;
+
+ if (m_lineColor.a <> 0 ) and
+ (m_lineWidth > 0.0 ) then
+ begin
+ m_rasterizer.add_path(@m_strokeTransform );
+
+ render(false );
+
+ end;
+
+ end;
+
+ FillWithLineColor :
+ if m_lineColor.a <> 0 then
+ begin
+ m_rasterizer.add_path(@m_pathTransform );
+
+ render(false );
+
+ end;
+
+ end;
+
+end;
+
+{ DRAWPATHNOTRANSFORM }
+procedure Agg2D.drawPathNoTransform(flag : DrawPathFlag = FillAndStroke );
+begin
+end;
+
+{ IMAGEFILTER }
+procedure Agg2D.imageFilter(f : ImageFilter_ );
+begin
+ m_imageFilter:=f;
+
+ case f of
+ Bilinear :
+ m_imageFilterLut.calculate(@m_ifBilinear ,true );
+
+ Hanning :
+ m_imageFilterLut.calculate(@m_ifHanning ,true );
+
+ Hermite :
+ m_imageFilterLut.calculate(@m_ifHermite ,true );
+
+ Quadric :
+ m_imageFilterLut.calculate(@m_ifQuadric ,true );
+
+ Bicubic :
+ m_imageFilterLut.calculate(@m_ifBicubic ,true );
+
+ Catrom :
+ m_imageFilterLut.calculate(@m_ifCatrom ,true );
+
+ Spline16 :
+ m_imageFilterLut.calculate(@m_ifSpline16 ,true );
+
+ Spline36 :
+ m_imageFilterLut.calculate(@m_ifSpline36 ,true );
+
+ Blackman144 :
+ m_imageFilterLut.calculate(@m_ifBlackman144 ,true );
+
+ end;
+
+end;
+
+{ IMAGEFILTER }
+function Agg2D.imageFilter : ImageFilter_;
+begin
+ result:=m_imageFilter;
+
+end;
+
+{ IMAGERESAMPLE }
+procedure Agg2D.imageResample(f : ImageResample_ );
+begin
+ m_imageResample:=f;
+
+end;
+
+{ IMAGERESAMPLE }
+function Agg2D.imageResample : ImageResample_;
+begin
+ result:=m_imageResample;
+
+end;
+
+{ TRANSFORMIMAGE }
+procedure Agg2D.transformImage(
+ img : Image_ptr;
+ imgX1 ,imgY1 ,imgX2 ,imgY2 : int;
+ dstX1 ,dstY1 ,dstX2 ,dstY2 : double );
+var
+ parall : array[0..5 ] of double;
+
+begin
+ resetPath;
+ moveTo(dstX1 ,dstY1 );
+ lineTo(dstX2 ,dstY1 );
+ lineTo(dstX2 ,dstY2 );
+ lineTo(dstX1 ,dstY2 );
+ closePolygon;
+
+ parall[0 ]:=dstX1;
+ parall[1 ]:=dstY1;
+ parall[2 ]:=dstX2;
+ parall[3 ]:=dstY1;
+ parall[4 ]:=dstX2;
+ parall[5 ]:=dstY2;
+
+ renderImage(img ,imgX1 ,imgY1 ,imgX2 ,imgY2 ,@parall[0 ] );
+
+end;
+
+{ TRANSFORMIMAGE }
+procedure Agg2D.transformImage(
+ img : Image_ptr;
+ dstX1 ,dstY1 ,dstX2 ,dstY2 : double );
+var
+ parall : array[0..5 ] of double;
+
+begin
+ resetPath;
+ moveTo(dstX1 ,dstY1 );
+ lineTo(dstX2 ,dstY1 );
+ lineTo(dstX2 ,dstY2 );
+ lineTo(dstX1 ,dstY2 );
+ closePolygon;
+
+ parall[0 ]:=dstX1;
+ parall[1 ]:=dstY1;
+ parall[2 ]:=dstX2;
+ parall[3 ]:=dstY1;
+ parall[4 ]:=dstX2;
+ parall[5 ]:=dstY2;
+
+ renderImage(img ,0 ,0 ,img.renBuf._width ,img.renBuf._height ,@parall[0 ] );
+
+end;
+
+{ TRANSFORMIMAGE }
+procedure Agg2D.transformImage(
+ img : Image_ptr;
+ imgX1 ,imgY1 ,imgX2 ,imgY2 : int;
+ parallelogram_ : double_ptr );
+begin
+ resetPath;
+
+ moveTo(
+ double_ptr(ptrcomp(parallelogram_ ) + 0 * sizeof(double ) )^ ,
+ double_ptr(ptrcomp(parallelogram_ ) + 1 * sizeof(double ) )^ );
+
+ lineTo(
+ double_ptr(ptrcomp(parallelogram_ ) + 2 * sizeof(double ) )^ ,
+ double_ptr(ptrcomp(parallelogram_ ) + 3 * sizeof(double ) )^ );
+
+ lineTo(
+ double_ptr(ptrcomp(parallelogram_ ) + 4 * sizeof(double ) )^ ,
+ double_ptr(ptrcomp(parallelogram_ ) + 5 * sizeof(double ) )^ );
+
+ lineTo(
+ double_ptr(ptrcomp(parallelogram_ ) + 0 * sizeof(double ) )^ +
+ double_ptr(ptrcomp(parallelogram_ ) + 4 * sizeof(double ) )^ -
+ double_ptr(ptrcomp(parallelogram_ ) + 2 * sizeof(double ) )^ ,
+ double_ptr(ptrcomp(parallelogram_ ) + 1 * sizeof(double ) )^ +
+ double_ptr(ptrcomp(parallelogram_ ) + 5 * sizeof(double ) )^ -
+ double_ptr(ptrcomp(parallelogram_ ) + 3 * sizeof(double ) )^ );
+
+ closePolygon;
+
+ renderImage(img ,imgX1 ,imgY1 ,imgX2 ,imgY2 ,parallelogram_ );
+
+end;
+
+{ TRANSFORMIMAGE }
+procedure Agg2D.transformImage(img : Image_ptr; parallelogram_ : double_ptr );
+begin
+ resetPath;
+
+ moveTo(
+ double_ptr(ptrcomp(parallelogram_ ) + 0 * sizeof(double ) )^ ,
+ double_ptr(ptrcomp(parallelogram_ ) + 1 * sizeof(double ) )^ );
+
+ lineTo(
+ double_ptr(ptrcomp(parallelogram_ ) + 2 * sizeof(double ) )^ ,
+ double_ptr(ptrcomp(parallelogram_ ) + 3 * sizeof(double ) )^ );
+
+ lineTo(
+ double_ptr(ptrcomp(parallelogram_ ) + 4 * sizeof(double ) )^ ,
+ double_ptr(ptrcomp(parallelogram_ ) + 5 * sizeof(double ) )^ );
+
+ lineTo(
+ double_ptr(ptrcomp(parallelogram_ ) + 0 * sizeof(double ) )^ +
+ double_ptr(ptrcomp(parallelogram_ ) + 4 * sizeof(double ) )^ -
+ double_ptr(ptrcomp(parallelogram_ ) + 2 * sizeof(double ) )^ ,
+ double_ptr(ptrcomp(parallelogram_ ) + 1 * sizeof(double ) )^ +
+ double_ptr(ptrcomp(parallelogram_ ) + 5 * sizeof(double ) )^ -
+ double_ptr(ptrcomp(parallelogram_ ) + 3 * sizeof(double ) )^ );
+
+ closePolygon;
+
+ renderImage(img ,0 ,0 ,img.renBuf._width ,img.renBuf._height ,parallelogram_ );
+
+end;
+
+{ TRANSFORMIMAGEPATH }
+procedure Agg2D.transformImagePath(
+ img : Image_ptr;
+ imgX1 ,imgY1 ,imgX2 ,imgY2 : int;
+ dstX1 ,dstY1 ,dstX2 ,dstY2 : double );
+var
+ parall : array[0..5 ] of double;
+
+begin
+ parall[0 ]:=dstX1;
+ parall[1 ]:=dstY1;
+ parall[2 ]:=dstX2;
+ parall[3 ]:=dstY1;
+ parall[4 ]:=dstX2;
+ parall[5 ]:=dstY2;
+
+ renderImage(img ,imgX1 ,imgY1 ,imgX2 ,imgY2 ,@parall[0 ] );
+
+end;
+
+{ TRANSFORMIMAGEPATH }
+procedure Agg2D.transformImagePath(
+ img : Image_ptr;
+ dstX1 ,dstY1 ,dstX2 ,dstY2 : double );
+var
+ parall : array[0..5 ] of double;
+
+begin
+ parall[0 ]:=dstX1;
+ parall[1 ]:=dstY1;
+ parall[2 ]:=dstX2;
+ parall[3 ]:=dstY1;
+ parall[4 ]:=dstX2;
+ parall[5 ]:=dstY2;
+
+ renderImage(img ,0 ,0 ,img.renBuf._width ,img.renBuf._height ,@parall[0 ] );
+
+end;
+
+{ TRANSFORMIMAGEPATH }
+procedure Agg2D.transformImagePath(
+ img : Image_ptr;
+ imgX1 ,imgY1 ,imgX2 ,imgY2 : int;
+ parallelogram_ : double_ptr );
+begin
+ renderImage(img ,imgX1 ,imgY1 ,imgX2 ,imgY2 ,parallelogram_ );
+
+end;
+
+{ TRANSFORMIMAGEPATH }
+procedure Agg2D.transformImagePath(img : Image_ptr; parallelogram_ : double_ptr );
+begin
+ renderImage(img ,0 ,0 ,img.renBuf._width ,img.renBuf._height ,parallelogram_ );
+
+end;
+
+{ BLENDIMAGE }
+procedure Agg2D.blendImage(
+ img : Image_ptr;
+ imgX1 ,imgY1 ,imgX2 ,imgY2 : int;
+ dstX ,dstY : double; alpha : unsigned = 255 );
+var
+ pixF : pixel_formats;
+
+ r : agg_basics.rect;
+
+begin
+ worldToScreen(@dstX ,@dstY );
+ pixfmt_rgba32(pixF ,@img.renBuf );
+ r.Construct (imgX1 ,imgY1 ,imgX2 ,imgY2 );
+
+ if m_blendMode = BlendAlpha then
+ m_renBasePre.blend_from(@pixF ,@r ,Trunc(dstX ) - imgX1 ,Trunc(dstY ) - imgY1 ,alpha )
+ else
+ m_renBaseCompPre.blend_from(@pixF ,@r ,Trunc(dstX ) - imgX1 ,Trunc(dstY ) - imgY1 ,alpha );
+
+end;
+
+{ BLENDIMAGE }
+procedure Agg2D.blendImage(img : Image_ptr; dstX ,dstY : double; alpha : unsigned = 255 );
+var
+ pixF : pixel_formats;
+
+begin
+ worldToScreen(@dstX ,@dstY );
+ pixfmt_rgba32(pixF ,@img.renBuf );
+
+ m_renBasePre.blend_from(@pixF ,NIL ,Trunc(dstX ) ,Trunc(dstY ) ,alpha );
+
+ if m_blendMode = BlendAlpha then
+ m_renBasePre.blend_from(@pixF ,NIL ,Trunc(dstX ) ,Trunc(dstY ) ,alpha )
+ else
+ m_renBaseCompPre.blend_from(@pixF ,NIL ,Trunc(dstX ) ,Trunc(dstY ) ,alpha );
+
+end;
+
+{ COPYIMAGE }
+procedure Agg2D.copyImage(
+ img : Image_ptr;
+ imgX1 ,imgY1 ,imgX2 ,imgY2 : int;
+ dstX ,dstY : double );
+var
+ r : agg_basics.rect;
+
+begin
+ worldToScreen(@dstX ,@dstY );
+ r.Construct (imgX1 ,imgY1 ,imgX2 ,imgY2 );
+
+ m_renBase.copy_from(@img.renBuf ,@r ,Trunc(dstX ) - imgX1 ,Trunc(dstY ) - imgY1 );
+
+end;
+
+{ COPYIMAGE }
+procedure Agg2D.copyImage(img : Image_ptr; dstX ,dstY : double );
+begin
+ worldToScreen(@dstX ,@dstY );
+
+ m_renBase.copy_from(@img.renBuf ,NIL ,Trunc(dstX ) ,Trunc(dstY ) );
+
+end;
+
+{ RENDER }
+procedure Agg2D.render(fillColor_ : boolean );
+begin
+ if m_blendMode = BlendAlpha then
+ Agg2DRenderer_render(@self ,@m_renBase ,@m_renSolid ,fillColor_ )
+ else
+ Agg2DRenderer_render(@self ,@m_renBaseComp ,@m_renSolidComp ,fillColor_ );
+
+end;
+
+{ RENDER }
+procedure Agg2D.render(ras : FontRasterizer_ptr; sl : FontScanline_ptr );
+begin
+ if m_blendMode = BlendAlpha then
+ Agg2DRenderer_render(@self ,@m_renBase ,@m_renSolid ,ras ,sl )
+ else
+ Agg2DRenderer_render(@self ,@m_renBaseComp ,@m_renSolidComp ,ras ,sl );
+
+end;
+
+{ ADDLINE }
+procedure Agg2D.addLine(x1 ,y1 ,x2 ,y2 : double );
+begin
+ m_path.move_to(x1 ,y1 );
+ m_path.line_to(x2 ,y2 );
+
+end;
+
+{ UPDATERASTERIZERGAMMA }
+procedure Agg2D.updateRasterizerGamma;
+begin
+ m_gammaAgg2D.Construct(m_masterAlpha ,m_antiAliasGamma );
+ m_rasterizer.gamma (@m_gammaAgg2D );
+
+end;
+
+{ RENDERIMAGE }
+procedure Agg2D.renderImage(
+ img : Image_ptr;
+ x1 ,y1 ,x2 ,y2 : int;
+ parl : double_ptr );
+var
+ mtx : trans_affine;
+
+ interpolator : span_interpolator_linear;
+
+begin
+ mtx.Construct(x1 ,y1 ,x2 ,y2 ,parallelo_ptr(parl ) );
+ mtx.multiply (@m_transform );
+ mtx.invert;
+
+ m_rasterizer.reset;
+ m_rasterizer.add_path(@m_pathTransform );
+
+ interpolator.Construct(@mtx );
+
+ if m_blendMode = BlendAlpha then
+ Agg2DRenderer_renderImage(@self ,img ,@m_renBasePre ,@interpolator )
+ else
+ Agg2DRenderer_renderImage(@self ,img ,@m_renBaseCompPre ,@interpolator );
+
+end;
+
+{ CONSTRUCT }
+constructor SpanConvImageBlend.Construct(m : BlendMode_; c : Color; p : pixel_formats_ptr );
+begin
+ m_mode :=m;
+ m_color:=c;
+ m_pixel:=p;
+
+end;
+
+{ CONVERT }
+procedure SpanConvImageBlend.convert(span : aggclr_ptr; x ,y : int; len : unsigned );
+var
+ l2 ,a : unsigned;
+
+ s2 : Color_ptr;
+
+begin
+ if m_mode <> BlendDst then
+ begin
+ l2:=len;
+ s2:=Color_ptr(span );
+
+ repeat
+ comp_op_adaptor_clip_to_dst_rgba_pre(
+ m_pixel ,
+ unsigned(m_mode ) ,
+ int8u_ptr(s2 ) ,
+ m_color.r ,
+ m_color.g ,
+ m_color.b ,
+ base_mask ,
+ cover_full );
+
+ inc(ptrcomp(s2 ) ,sizeof(Color ) );
+ dec(l2 );
+
+ until l2 = 0;
+
+ end;
+
+ if m_color.a < base_mask then
+ begin
+ l2:=len;
+ s2:=Color_ptr(span );
+ a :=m_color.a;
+
+ repeat
+ s2.r:=(s2.r * a ) shr base_shift;
+ s2.g:=(s2.g * a ) shr base_shift;
+ s2.b:=(s2.b * a ) shr base_shift;
+ s2.a:=(s2.a * a ) shr base_shift;
+
+ inc(ptrcomp(s2 ) ,sizeof(Color ) );
+ dec(l2 );
+
+ until l2 = 0;
+
+ end;
+
+end;
+
+{ PI }
+function pi : double;
+begin
+ result:=agg_basics.pi;
+
+end;
+
+{ DEG2RAD }
+function deg2Rad(v : double ) : double;
+begin
+ result:=v * agg_basics.pi / 180.0;
+
+end;
+
+{ RAD2DEG }
+function rad2Deg(v : double ) : double;
+begin
+ result:=v * 180.0 / agg_basics.pi;
+
+end;
+
+{ OPERATOR_IS_EQUAL }
+function operator_is_equal(c1 ,c2 : Color_ptr ) : boolean;
+begin
+ result:=
+ (c1.r = c2.r ) and
+ (c1.g = c2.g ) and
+ (c1.b = c2.b ) and
+ (c1.a = c2.a );
+
+end;
+
+{ OPERATOR_IS_NOT_EQUAL }
+function operator_is_not_equal(c1 ,c2 : Color_ptr ) : boolean;
+begin
+ result:=not operator_is_equal(c1 ,c2 );
+
+end;
+
+{ AGG2DRENDERER_RENDER }
+procedure Agg2DRenderer_render(
+ gr : Agg2D_ptr;
+ renBase : renderer_base_ptr;
+ renSolid : renderer_scanline_aa_solid_ptr;
+ fillColor_ : boolean );
+var
+ span : span_gradient;
+ ren : renderer_scanline_aa;
+ clr : aggclr;
+
+begin
+ if (fillColor_ and
+ (gr.m_fillGradientFlag = Linear ) ) or
+ (not fillColor_ and
+ (gr.m_lineGradientFlag = Linear ) ) then
+ if fillColor_ then
+ begin
+ span.Construct(
+ @gr.m_allocator ,
+ @gr.m_fillGradientInterpolator ,
+ @gr.m_linearGradientFunction ,
+ @gr.m_fillGradient ,
+ gr.m_fillGradientD1 ,
+ gr.m_fillGradientD2 );
+
+ ren.Construct (renBase ,@span );
+ render_scanlines(@gr.m_rasterizer ,@gr.m_scanline ,@ren );
+
+ end
+ else
+ begin
+ span.Construct(
+ @gr.m_allocator ,
+ @gr.m_lineGradientInterpolator ,
+ @gr.m_linearGradientFunction ,
+ @gr.m_lineGradient ,
+ gr.m_lineGradientD1 ,
+ gr.m_lineGradientD2 );
+
+ ren.Construct (renBase ,@span );
+ render_scanlines(@gr.m_rasterizer ,@gr.m_scanline ,@ren );
+
+ end
+ else
+ if (fillColor_ and
+ (gr.m_fillGradientFlag = Radial ) ) or
+ (not fillColor_ and
+ (gr.m_lineGradientFlag = Radial ) ) then
+ if fillColor_ then
+ begin
+ span.Construct(
+ @gr.m_allocator ,
+ @gr.m_fillGradientInterpolator ,
+ @gr.m_radialGradientFunction ,
+ @gr.m_fillGradient ,
+ gr.m_fillGradientD1 ,
+ gr.m_fillGradientD2 );
+
+ ren.Construct (renBase ,@span );
+ render_scanlines(@gr.m_rasterizer ,@gr.m_scanline ,@ren );
+
+ end
+ else
+ begin
+ span.Construct(
+ @gr.m_allocator ,
+ @gr.m_lineGradientInterpolator ,
+ @gr.m_radialGradientFunction ,
+ @gr.m_lineGradient ,
+ gr.m_lineGradientD1 ,
+ gr.m_lineGradientD2 );
+
+ ren.Construct (renBase ,@span );
+ render_scanlines(@gr.m_rasterizer ,@gr.m_scanline ,@ren );
+
+ end
+ else
+ begin
+ if fillColor_ then
+ clr.Construct(gr.m_fillColor )
+ else
+ clr.Construct(gr.m_lineColor );
+
+ renSolid.color_ (@clr );
+ render_scanlines(@gr.m_rasterizer ,@gr.m_scanline ,renSolid );
+
+ end;
+
+end;
+
+{ AGG2DRENDERER_RENDER }
+procedure Agg2DRenderer_render(
+ gr : Agg2D_ptr;
+ renBase : renderer_base_ptr;
+ renSolid : renderer_scanline_aa_solid_ptr;
+ ras : gray8_adaptor_type_ptr;
+ sl : gray8_scanline_type_ptr );
+var
+ span : span_gradient;
+ ren : renderer_scanline_aa;
+ clr : aggclr;
+
+begin
+ if gr.m_fillGradientFlag = Linear then
+ begin
+ span.Construct(
+ @gr.m_allocator ,
+ @gr.m_fillGradientInterpolator ,
+ @gr.m_linearGradientFunction ,
+ @gr.m_fillGradient ,
+ gr.m_fillGradientD1 ,
+ gr.m_fillGradientD2 );
+
+ ren.Construct (renBase ,@span );
+ render_scanlines(ras ,sl ,@ren );
+
+ end
+ else
+ if gr.m_fillGradientFlag = Radial then
+ begin
+ span.Construct(
+ @gr.m_allocator ,
+ @gr.m_fillGradientInterpolator ,
+ @gr.m_radialGradientFunction ,
+ @gr.m_fillGradient ,
+ gr.m_fillGradientD1 ,
+ gr.m_fillGradientD2 );
+
+ ren.Construct (renBase ,@span );
+ render_scanlines(ras ,sl ,@ren );
+
+ end
+ else
+ begin
+ clr.Construct (gr.m_fillColor );
+ renSolid.color_ (@clr );
+ render_scanlines(ras ,sl ,renSolid );
+
+ end;
+
+end;
+
+{ AGG2DRENDERER_RENDERIMAGE }
+procedure Agg2DRenderer_renderImage(
+ gr : Agg2D_ptr;
+ img : Image_ptr;
+ renBase : renderer_base_ptr;
+ interpolator : span_interpolator_linear_ptr );
+var
+ blend : SpanConvImageBlend;
+
+ si : span_image_filter_rgba;
+ sg : span_image_filter_rgba_nn;
+ sb : span_image_filter_rgba_bilinear;
+ s2 : span_image_filter_rgba_2x2;
+ sa : span_image_resample_rgba_affine;
+ sc : span_converter;
+ ri : renderer_scanline_aa;
+
+ clr : aggclr;
+
+ resample : boolean;
+
+ sx ,sy : double;
+
+begin
+ blend.Construct(gr.m_imageBlendMode ,gr.m_imageBlendColor ,@gr.m_pixFormatCompPre );
+
+ if gr.m_imageFilter = NoFilter then
+ begin
+ clr.ConstrInt(0 ,0 ,0 ,0 );
+ sg.Construct (@gr.m_allocator ,@img.renBuf ,@clr ,interpolator ,rgba_order );
+ sc.Construct (@sg ,@blend );
+ ri.Construct (renBase ,@sc );
+
+ render_scanlines(@gr.m_rasterizer ,@gr.m_scanline ,@ri );
+
+ end
+ else
+ begin
+ resample:=gr.m_imageResample = ResampleAlways;
+
+ if gr.m_imageResample = ResampleOnZoomOut then
+ begin
+ interpolator._transformer.scaling_abs(@sx ,@sy );
+
+ if (sx > 1.125 ) or
+ (sy > 1.125 ) then
+ resample:=true;
+
+ end;
+
+ if resample then
+ begin
+ clr.ConstrInt(0 ,0 ,0 ,0 );
+ sa.Construct(
+ @gr.m_allocator ,
+ @img.renBuf ,
+ @clr ,
+ interpolator ,
+ @gr.m_imageFilterLut ,
+ rgba_order );
+
+ sc.Construct(@sa ,@blend );
+ ri.Construct(renBase ,@sc );
+
+ render_scanlines(@gr.m_rasterizer ,@gr.m_scanline ,@ri );
+
+ end
+ else
+ if gr.m_imageFilter = Bilinear then
+ begin
+ clr.ConstrInt(0 ,0 ,0 ,0 );
+ sb.Construct(
+ @gr.m_allocator ,
+ @img.renBuf ,
+ @clr ,
+ interpolator ,
+ rgba_order );
+
+ sc.Construct(@sb ,@blend );
+ ri.Construct(renBase ,@sc );
+
+ render_scanlines(@gr.m_rasterizer ,@gr.m_scanline ,@ri );
+
+ end
+ else
+ if gr.m_imageFilterLut.diameter = 2 then
+ begin
+ clr.ConstrInt(0 ,0 ,0 ,0 );
+ s2.Construct(
+ @gr.m_allocator ,
+ @img.renBuf ,
+ @clr ,
+ interpolator,
+ @gr.m_imageFilterLut ,
+ rgba_order );
+
+ sc.Construct(@s2 ,@blend );
+ ri.Construct(renBase ,@sc );
+
+ render_scanlines(@gr.m_rasterizer ,@gr.m_scanline ,@ri );
+
+ end
+ else
+ begin
+ clr.ConstrInt(0 ,0 ,0 ,0 );
+ si.Construct(
+ @gr.m_allocator ,
+ @img.renBuf ,
+ @clr ,
+ interpolator ,
+ @gr.m_imageFilterLut ,
+ rgba_order );
+
+ sc.Construct(@si ,@blend );
+ ri.Construct(renBase ,@sc );
+
+ render_scanlines(@gr.m_rasterizer ,@gr.m_scanline ,@ri );
+
+ end;
+
+ end;
+
+end;
+
+{ AGG2DUSESFREETYPE }
+function Agg2DUsesFreeType : boolean;
+begin
+{$IFDEF AGG2D_USE_FREETYPE }
+ result:=true;
+
+{$ELSE }
+ result:=false;
+
+{$ENDIF }
+
+end;
+
+END.
+
+{!}
+
diff --git a/src/corelib/render/software/agg_alpha_mask_u8.pas b/src/corelib/render/software/agg_alpha_mask_u8.pas
new file mode 100644
index 00000000..c50faf57
--- /dev/null
+++ b/src/corelib/render/software/agg_alpha_mask_u8.pas
@@ -0,0 +1,1350 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 10.02.2006-Milano: amask_no_clip_u8
+// 09.02.2006-Milano: Unit port establishment
+//
+{ agg_alpha_mask_u8.pas }
+unit
+ agg_alpha_mask_u8 ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_rendering_buffer ;
+
+{ TYPES DEFINITION }
+const
+ cover_shift = 8;
+ cover_none = 0;
+ cover_full = 255;
+
+type
+ func_mask_calculate = function(p : int8u_ptr ) : unsigned;
+
+//==========================================================alpha_mask_u8
+ alpha_mask_ptr = ^alpha_mask;
+ alpha_mask = object
+ procedure attach(rbuf : rendering_buffer_ptr ); virtual; abstract;
+
+ function mask_function : func_mask_calculate; virtual; abstract;
+
+ function pixel (x ,y : int ) : int8u; virtual; abstract;
+ function combine_pixel(x ,y : int; val : int8u ) : int8u; virtual; abstract;
+
+ procedure fill_hspan (x ,y : int; dst : int8u_ptr; num_pix : int ); virtual; abstract;
+ procedure combine_hspan(x ,y : int; dst : int8u_ptr; num_pix : int ); virtual; abstract;
+ procedure fill_vspan (x ,y : int; dst : int8u_ptr; num_pix : int ); virtual; abstract;
+ procedure combine_vspan(x ,y : int; dst : int8u_ptr; num_pix : int ); virtual; abstract;
+
+ end;
+
+ alpha_mask_u8 = object(alpha_mask )
+ Step ,
+ Offset : unsigned;
+
+ m_rbuf : rendering_buffer_ptr;
+ m_mask_function : func_mask_calculate;
+
+ constructor Construct(MaskF : func_mask_calculate; Step_ : unsigned = 1; Offset_ : unsigned = 0 ); overload;
+ constructor Construct(rbuf : rendering_buffer_ptr; MaskF : func_mask_calculate; Step_ : unsigned = 1; Offset_ : unsigned = 0 ); overload;
+
+ procedure attach(rbuf : rendering_buffer_ptr ); virtual;
+
+ function mask_function : func_mask_calculate; virtual;
+
+ function pixel (x ,y : int ) : int8u; virtual;
+ function combine_pixel(x ,y : int; val : int8u ) : int8u; virtual;
+
+ procedure fill_hspan (x ,y : int; dst : int8u_ptr; num_pix : int ); virtual;
+ procedure combine_hspan(x ,y : int; dst : int8u_ptr; num_pix : int ); virtual;
+ procedure fill_vspan (x ,y : int; dst : int8u_ptr; num_pix : int ); virtual;
+ procedure combine_vspan(x ,y : int; dst : int8u_ptr; num_pix : int ); virtual;
+
+ end;
+
+ alpha_mask_gray8 = object(alpha_mask_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ alpha_mask_rgb24r = object(alpha_mask_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ alpha_mask_rgb24g = object(alpha_mask_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ alpha_mask_rgb24b = object(alpha_mask_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ alpha_mask_bgr24r = object(alpha_mask_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ alpha_mask_bgr24g = object(alpha_mask_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ alpha_mask_bgr24b = object(alpha_mask_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ alpha_mask_rgba32r = object(alpha_mask_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ alpha_mask_rgba32g = object(alpha_mask_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ alpha_mask_rgba32b = object(alpha_mask_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ alpha_mask_rgba32a = object(alpha_mask_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ alpha_mask_argb32r = object(alpha_mask_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ alpha_mask_argb32g = object(alpha_mask_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ alpha_mask_argb32b = object(alpha_mask_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ alpha_mask_argb32a = object(alpha_mask_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ alpha_mask_bgra32r = object(alpha_mask_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ alpha_mask_bgra32g = object(alpha_mask_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ alpha_mask_bgra32b = object(alpha_mask_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ alpha_mask_bgra32a = object(alpha_mask_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ alpha_mask_abgr32r = object(alpha_mask_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ alpha_mask_abgr32g = object(alpha_mask_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ alpha_mask_abgr32b = object(alpha_mask_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ alpha_mask_abgr32a = object(alpha_mask_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ alpha_mask_rgb24gray = object(alpha_mask_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ alpha_mask_bgr24gray = object(alpha_mask_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ alpha_mask_rgba32gray = object(alpha_mask_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ alpha_mask_argb32gray = object(alpha_mask_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ alpha_mask_bgra32gray = object(alpha_mask_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ alpha_mask_abgr32gray = object(alpha_mask_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+//==========================================================amask_no_clip_u8
+ amask_no_clip_u8 = object(alpha_mask )
+ Step ,
+ Offset : unsigned;
+
+ m_rbuf : rendering_buffer_ptr;
+ m_mask_function : func_mask_calculate;
+
+ constructor Construct(MaskF : func_mask_calculate; Step_ : unsigned = 1; Offset_ : unsigned = 0 ); overload;
+ constructor Construct(rbuf : rendering_buffer_ptr; MaskF : func_mask_calculate; Step_ : unsigned = 1; Offset_ : unsigned = 0 ); overload;
+
+ procedure attach(rbuf : rendering_buffer_ptr ); virtual;
+
+ function mask_function : func_mask_calculate; virtual;
+
+ function pixel (x ,y : int ) : int8u; virtual;
+ function combine_pixel(x ,y : int; val : int8u ) : int8u; virtual;
+
+ procedure fill_hspan (x ,y : int; dst : int8u_ptr; num_pix : int ); virtual;
+ procedure combine_hspan(x ,y : int; dst : int8u_ptr; num_pix : int ); virtual;
+ procedure fill_vspan (x ,y : int; dst : int8u_ptr; num_pix : int ); virtual;
+ procedure combine_vspan(x ,y : int; dst : int8u_ptr; num_pix : int ); virtual;
+
+ end;
+
+ amask_no_clip_gray8 = object(amask_no_clip_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ amask_no_clip_rgb24r = object(amask_no_clip_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ amask_no_clip_rgb24g = object(amask_no_clip_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ amask_no_clip_rgb24b = object(amask_no_clip_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ amask_no_clip_bgr24r = object(amask_no_clip_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ amask_no_clip_bgr24g = object(amask_no_clip_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ amask_no_clip_bgr24b = object(amask_no_clip_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ amask_no_clip_rgba32r = object(amask_no_clip_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ amask_no_clip_rgba32g = object(amask_no_clip_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ amask_no_clip_rgba32b = object(amask_no_clip_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ amask_no_clip_rgba32a = object(amask_no_clip_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ amask_no_clip_argb32r = object(amask_no_clip_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ amask_no_clip_argb32g = object(amask_no_clip_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ amask_no_clip_argb32b = object(amask_no_clip_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ amask_no_clip_argb32a = object(amask_no_clip_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ amask_no_clip_bgra32r = object(amask_no_clip_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ amask_no_clip_bgra32g = object(amask_no_clip_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ amask_no_clip_bgra32b = object(amask_no_clip_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ amask_no_clip_bgra32a = object(amask_no_clip_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ amask_no_clip_abgr32r = object(amask_no_clip_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ amask_no_clip_abgr32g = object(amask_no_clip_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ amask_no_clip_abgr32b = object(amask_no_clip_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ amask_no_clip_abgr32a = object(amask_no_clip_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ amask_no_clip_rgb24gray = object(amask_no_clip_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ amask_no_clip_bgr24gray = object(amask_no_clip_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ amask_no_clip_rgba32gray = object(amask_no_clip_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ amask_no_clip_argb32gray = object(amask_no_clip_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ amask_no_clip_bgra32gray = object(amask_no_clip_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+ amask_no_clip_abgr32gray = object(amask_no_clip_u8 )
+ constructor Construct(rbuf : rendering_buffer_ptr );
+
+ end;
+
+{ GLOBAL PROCEDURES }
+ function one_component_mask_u8 (p : int8u_ptr ) : unsigned;
+ function rgb_to_gray_mask_u8_012(p : int8u_ptr ) : unsigned;
+ function rgb_to_gray_mask_u8_210(p : int8u_ptr ) : unsigned;
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ ONE_COMPONENT_MASK_U8 }
+function one_component_mask_u8;
+begin
+ result:=p^;
+
+end;
+
+{ RGB_TO_GRAY_MASK_U8_012 }
+function rgb_to_gray_mask_u8_012;
+begin
+ result:=
+ int8u((
+ int8u_ptr(ptrcomp(p ) + 0 * sizeof(int8u ) )^ * 77 +
+ int8u_ptr(ptrcomp(p ) + 1 * sizeof(int8u ) )^ * 150 +
+ int8u_ptr(ptrcomp(p ) + 2 * sizeof(int8u ) )^ * 29 shr 8 ) );
+
+end;
+
+{ RGB_TO_GRAY_MASK_U8_210 }
+function rgb_to_gray_mask_u8_210;
+begin
+ result:=
+ int8u((
+ int8u_ptr(ptrcomp(p ) + 2 * sizeof(int8u ) )^ * 77 +
+ int8u_ptr(ptrcomp(p ) + 1 * sizeof(int8u ) )^ * 150 +
+ int8u_ptr(ptrcomp(p ) + 0 * sizeof(int8u ) )^ * 29 shr 8 ) );
+
+end;
+
+{ CONSTRUCT }
+constructor alpha_mask_u8.Construct(MaskF : func_mask_calculate; Step_ : unsigned = 1; Offset_ : unsigned = 0 );
+begin
+ Step :=Step_;
+ Offset:=Offset_;
+
+ m_rbuf :=NIL;
+ m_mask_function:=MaskF;
+
+end;
+
+{ CONSTRUCT }
+constructor alpha_mask_u8.Construct(rbuf : rendering_buffer_ptr; MaskF : func_mask_calculate; Step_ : unsigned = 1; Offset_ : unsigned = 0 );
+begin
+ Step :=Step_;
+ Offset:=Offset_;
+
+ m_rbuf :=rbuf;
+ m_mask_function:=MaskF;
+
+end;
+
+{ ATTACH }
+procedure alpha_mask_u8.attach;
+begin
+ m_rbuf:=rbuf;
+
+end;
+
+{ MASK_FUNCTION }
+function alpha_mask_u8.mask_function;
+begin
+ result:=@m_mask_function;
+
+end;
+
+{ PIXEL }
+function alpha_mask_u8.pixel;
+begin
+ if(x >= 0 ) and
+ (y >= 0 ) and
+ (x < m_rbuf._width ) and
+ (y < m_rbuf._height ) then
+ result:=
+ int8u(m_mask_function(
+ int8u_ptr(ptrcomp(m_rbuf.row(y ) ) + (x * Step + Offset ) * sizeof(int8u ) ) ) )
+ else
+ result:=0;
+
+end;
+
+{ COMBINE_PIXEL }
+function alpha_mask_u8.combine_pixel;
+begin
+ if(x >= 0 ) and
+ (y >= 0 ) and
+ (x < m_rbuf._width ) and
+ (y < m_rbuf._height ) then
+ result:=int8u(
+ (cover_full + val *
+ m_mask_function(
+ int8u_ptr(ptrcomp(m_rbuf.row(y ) ) + (x * Step + Offset ) * sizeof(int8u ) ) )
+ ) shr cover_shift )
+ else
+ result:=0;
+
+end;
+
+{ FILL_HSPAN }
+procedure alpha_mask_u8.fill_hspan;
+var
+ xmax ,ymax ,count ,rest : int;
+
+ covers ,mask : int8u_ptr;
+
+begin
+ xmax:=m_rbuf._width - 1;
+ ymax:=m_rbuf._height - 1;
+
+ count :=num_pix;
+ covers:=dst;
+
+ if (y < 0 ) or
+ (y > ymax ) then
+ begin
+ fillchar(dst^ ,num_pix * sizeof(int8u ) ,0 );
+
+ exit;
+
+ end;
+
+ if x < 0 then
+ begin
+ inc(count ,x );
+
+ if count <= 0 then
+ begin
+ fillchar(dst^ ,num_pix * sizeof(int8u ) ,0 );
+
+ exit;
+
+ end;
+
+ fillchar(covers^ ,-x * sizeof(int8u ) ,0 );
+
+ dec(covers ,x );
+
+ x:=0;
+
+ end;
+
+ if x + count > xmax then
+ begin
+ rest:=x + count - xmax - 1;
+
+ dec(count ,rest );
+
+ if count <= 0 then
+ begin
+ fillchar(dst^ ,num_pix * sizeof(int8u ) ,0 );
+
+ exit;
+
+ end;
+
+ fillchar(int8u_ptr(ptrcomp(covers ) + count * sizeof(int8u ) )^ ,rest * sizeof(int8u ) ,0 );
+
+ end;
+
+ mask:=int8u_ptr(ptrcomp(m_rbuf.row(y ) ) + (x * Step + Offset ) * sizeof(int8u ) );
+
+ repeat
+ covers^:=int8u(m_mask_function(mask ) );
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+ inc(ptrcomp(mask ) ,Step * sizeof(int8u ) );
+ dec(count );
+
+ until count = 0;
+
+end;
+
+{ COMBINE_HSPAN }
+procedure alpha_mask_u8.combine_hspan;
+var
+ xmax ,ymax ,count ,rest : int;
+
+ covers ,mask : int8u_ptr;
+
+begin
+ xmax:=m_rbuf._width - 1;
+ ymax:=m_rbuf._height - 1;
+
+ count :=num_pix;
+ covers:=dst;
+
+ if (y < 0 ) or
+ (y > ymax ) then
+ begin
+ fillchar(dst^ ,num_pix * sizeof(int8u ) ,0 );
+
+ exit;
+
+ end;
+
+ if x < 0 then
+ begin
+ inc(count ,x );
+
+ if count <= 0 then
+ begin
+ fillchar(dst^ ,num_pix * sizeof(int8u ) ,0 );
+
+ exit;
+
+ end;
+
+ fillchar(covers^ ,-x * sizeof(int8u ) ,0 );
+
+ dec(ptrcomp(covers ) ,x * sizeof(int8u ) );
+
+ x:=0;
+
+ end;
+
+ if x + count > xmax then
+ begin
+ rest:=x + count - xmax - 1;
+
+ dec(count ,rest );
+
+ if count <= 0 then
+ begin
+ fillchar(dst^ ,num_pix * sizeof(int8u ) ,0 );
+
+ exit;
+
+ end;
+
+ fillchar(int8u_ptr(ptrcomp(covers ) + count * sizeof(int8u ) )^ ,rest * sizeof(int8u ) ,0 );
+
+ end;
+
+ mask:=int8u_ptr(ptrcomp(m_rbuf.row(y ) ) + (x * Step + Offset ) * sizeof(int8u ) );
+
+ repeat
+ covers^:=
+ int8u(
+ (cover_full + covers^ *
+ m_mask_function(mask ) ) shr cover_shift );
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+ inc(mask ,Step * sizeof(int8u ) );
+ dec(count );
+
+ until count = 0;
+
+
+end;
+
+{ FILL_VSPAN }
+procedure alpha_mask_u8.fill_vspan;
+var
+ xmax ,ymax ,count ,rest : int;
+
+ covers ,mask : int8u_ptr;
+
+begin
+ xmax:=m_rbuf._width - 1;
+ ymax:=m_rbuf._height - 1;
+
+ count :=num_pix;
+ covers:=dst;
+
+ if (x < 0 ) or
+ (x > xmax ) then
+ begin
+ fillchar(dst^ ,num_pix * sizeof(int8u ) ,0 );
+
+ exit;
+
+ end;
+
+ if y < 0 then
+ begin
+ inc(count ,y );
+
+ if count <= 0 then
+ begin
+ fillchar(dst^ ,num_pix * sizeof(int8u ) ,0 );
+
+ exit;
+
+ end;
+
+ fillchar(covers^ ,-y * sizeof(int8u ) ,0 );
+
+ dec(ptrcomp(covers ) ,y * sizeof(int8u ) );
+
+ y:=0;
+
+ end;
+
+ if y + count > ymax then
+ begin
+ rest:=y + count - ymax - 1;
+
+ dec(count ,rest );
+
+ if count <= 0 then
+ begin
+ fillchar(dst^ ,num_pix * sizeof(int8u ) ,0 );
+
+ exit;
+
+ end;
+
+ fillchar(int8u_ptr(ptrcomp(covers ) + count * sizeof(int8u ) )^ ,rest * sizeof(int8u ) ,0 );
+
+ end;
+
+ repeat
+ covers^:=int8u(m_mask_function(mask ) );
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+ inc(ptrcomp(mask ) ,m_rbuf._stride );
+ dec(count );
+
+ until count = 0;
+
+end;
+
+{ COMBINE_VSPAN }
+procedure alpha_mask_u8.combine_vspan;
+var
+ xmax ,ymax ,count ,rest : int;
+
+ covers ,mask : int8u_ptr;
+
+begin
+ xmax:=m_rbuf._width - 1;
+ ymax:=m_rbuf._height - 1;
+
+ count :=num_pix;
+ covers:=dst;
+
+ if (x < 0 ) or
+ (x > xmax ) then
+ begin
+ fillchar(dst^ ,num_pix * sizeof(int8u ) ,0 );
+
+ exit;
+
+ end;
+
+ if y < 0 then
+ begin
+ inc(count ,y );
+
+ if count <= 0 then
+ begin
+ fillchar(dst^ ,num_pix * sizeof(int8u ) ,0 );
+
+ exit;
+
+ end;
+
+ fillchar(covers^ ,-y * sizeof(int8u ) ,0 );
+
+ dec(ptrcomp(covers ) ,y * sizeof(int8u ) );
+
+ y:=0;
+
+ end;
+
+ if y + count > ymax then
+ begin
+ rest:=y + count - ymax - 1;
+
+ dec(count ,rest );
+
+ if count <= 0 then
+ begin
+ fillchar(dst^ ,num_pix * sizeof(int8u ) ,0 );
+
+ exit;
+
+ end;
+
+ fillchar(int8u_ptr(ptrcomp(covers ) + count * sizeof(int8u ) )^ ,rest * sizeof(int8u ) ,0 );
+
+ end;
+
+ mask:=int8u_ptr(ptrcomp(m_rbuf.row(y ) ) + (x * Step + Offset ) * sizeof(int8u ) );
+
+ repeat
+ covers^:=
+ int8u(
+ (cover_full + covers^ *
+ m_mask_function(mask ) ) shr cover_shift );
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+ inc(ptrcomp(mask ) ,m_rbuf._stride );
+ dec(count );
+
+ until count = 0;
+
+end;
+
+{ CONSTRUCT }
+constructor alpha_mask_gray8.Construct;
+begin
+ inherited Construct(rbuf ,@one_component_mask_u8 ,1 ,0 );
+
+end;
+
+{ CONSTRUCT }
+constructor alpha_mask_rgb24r.Construct;
+begin
+ inherited Construct(rbuf ,@one_component_mask_u8 ,3 ,0 );
+
+end;
+
+{ CONSTRUCT }
+constructor alpha_mask_rgb24g.Construct;
+begin
+ inherited Construct(rbuf ,@one_component_mask_u8 ,3 ,1 );
+
+end;
+
+{ CONSTRUCT }
+constructor alpha_mask_rgb24b.Construct;
+begin
+ inherited Construct(rbuf ,@one_component_mask_u8 ,3 ,2 );
+
+end;
+
+{ CONSTRUCT }
+constructor alpha_mask_bgr24r.Construct;
+begin
+ inherited Construct(rbuf ,@one_component_mask_u8 ,3 ,2 );
+
+end;
+
+{ CONSTRUCT }
+constructor alpha_mask_bgr24g.Construct;
+begin
+ inherited Construct(rbuf ,@one_component_mask_u8 ,3 ,1 );
+
+end;
+
+{ CONSTRUCT }
+constructor alpha_mask_bgr24b.Construct;
+begin
+ inherited Construct(rbuf ,@one_component_mask_u8 ,3 ,0 );
+
+end;
+
+{ CONSTRUCT }
+constructor alpha_mask_rgba32r.Construct;
+begin
+ inherited Construct(rbuf ,@one_component_mask_u8 ,4 ,0 );
+
+end;
+
+{ CONSTRUCT }
+constructor alpha_mask_rgba32g.Construct;
+begin
+ inherited Construct(rbuf ,@one_component_mask_u8 ,4 ,1 );
+
+end;
+
+{ CONSTRUCT }
+constructor alpha_mask_rgba32b.Construct;
+begin
+ inherited Construct(rbuf ,@one_component_mask_u8 ,4 ,2 );
+
+end;
+
+{ CONSTRUCT }
+constructor alpha_mask_rgba32a.Construct;
+begin
+ inherited Construct(rbuf ,@one_component_mask_u8 ,4 ,3 );
+
+end;
+
+{ CONSTRUCT }
+constructor alpha_mask_argb32r.Construct;
+begin
+ inherited Construct(rbuf ,@one_component_mask_u8 ,4 ,1 );
+
+end;
+
+{ CONSTRUCT }
+constructor alpha_mask_argb32g.Construct;
+begin
+ inherited Construct(rbuf ,@one_component_mask_u8 ,4 ,2 );
+
+end;
+
+{ CONSTRUCT }
+constructor alpha_mask_argb32b.Construct;
+begin
+ inherited Construct(rbuf ,@one_component_mask_u8 ,4 ,3 );
+
+end;
+
+{ CONSTRUCT }
+constructor alpha_mask_argb32a.Construct;
+begin
+ inherited Construct(rbuf ,@one_component_mask_u8 ,4 ,0 );
+
+end;
+
+{ CONSTRUCT }
+constructor alpha_mask_bgra32r.Construct;
+begin
+ inherited Construct(rbuf ,@one_component_mask_u8 ,4 ,2 );
+
+end;
+
+{ CONSTRUCT }
+constructor alpha_mask_bgra32g.Construct;
+begin
+ inherited Construct(rbuf ,@one_component_mask_u8 ,4 ,1 );
+
+end;
+
+{ CONSTRUCT }
+constructor alpha_mask_bgra32b.Construct;
+begin
+ inherited Construct(rbuf ,@one_component_mask_u8 ,4 ,0 );
+
+end;
+
+{ CONSTRUCT }
+constructor alpha_mask_bgra32a.Construct;
+begin
+ inherited Construct(rbuf ,@one_component_mask_u8 ,4 ,3 );
+
+end;
+
+{ CONSTRUCT }
+constructor alpha_mask_abgr32r.Construct;
+begin
+ inherited Construct(rbuf ,@one_component_mask_u8 ,4 ,3 );
+
+end;
+
+{ CONSTRUCT }
+constructor alpha_mask_abgr32g.Construct;
+begin
+ inherited Construct(rbuf ,@one_component_mask_u8 ,4 ,2 );
+
+end;
+
+{ CONSTRUCT }
+constructor alpha_mask_abgr32b.Construct;
+begin
+ inherited Construct(rbuf ,@one_component_mask_u8 ,4 ,1 );
+
+end;
+
+{ CONSTRUCT }
+constructor alpha_mask_abgr32a.Construct;
+begin
+ inherited Construct(rbuf ,@one_component_mask_u8 ,4 ,0 );
+
+end;
+
+{ CONSTRUCT }
+constructor alpha_mask_rgb24gray.Construct;
+begin
+ inherited Construct(rbuf ,@rgb_to_gray_mask_u8_012 ,3 ,0 );
+
+end;
+
+{ CONSTRUCT }
+constructor alpha_mask_bgr24gray.Construct;
+begin
+ inherited Construct(rbuf ,@rgb_to_gray_mask_u8_210 ,3 ,0 );
+
+end;
+
+{ CONSTRUCT }
+constructor alpha_mask_rgba32gray.Construct;
+begin
+ inherited Construct(rbuf ,@rgb_to_gray_mask_u8_012 ,4 ,0 );
+
+end;
+
+{ CONSTRUCT }
+constructor alpha_mask_argb32gray.Construct;
+begin
+ inherited Construct(rbuf ,@rgb_to_gray_mask_u8_012 ,4 ,1 );
+
+end;
+
+{ CONSTRUCT }
+constructor alpha_mask_bgra32gray.Construct;
+begin
+ inherited Construct(rbuf ,@rgb_to_gray_mask_u8_210 ,4 ,0 );
+
+end;
+
+{ CONSTRUCT }
+constructor alpha_mask_abgr32gray.Construct;
+begin
+ inherited Construct(rbuf ,@rgb_to_gray_mask_u8_210 ,4 ,1 );
+
+end;
+
+{ CONSTRUCT }
+constructor amask_no_clip_u8.Construct(MaskF : func_mask_calculate; Step_ : unsigned = 1; Offset_ : unsigned = 0 );
+begin
+ Step :=Step_;
+ Offset:=Offset_;
+
+ m_rbuf :=NIL;
+ m_mask_function:=MaskF;
+
+end;
+
+{ CONSTRUCT }
+constructor amask_no_clip_u8.Construct(rbuf : rendering_buffer_ptr; MaskF : func_mask_calculate; Step_ : unsigned = 1; Offset_ : unsigned = 0 );
+begin
+ Step :=Step_;
+ Offset:=Offset_;
+
+ m_rbuf :=rbuf;
+ m_mask_function:=MaskF;
+
+end;
+
+{ ATTACH }
+procedure amask_no_clip_u8.attach;
+begin
+ m_rbuf:=rbuf;
+
+end;
+
+{ MASK_FUNCTION }
+function amask_no_clip_u8.mask_function;
+begin
+ result:=@m_mask_function;
+
+end;
+
+{ PIXEL }
+function amask_no_clip_u8.pixel;
+begin
+ result:=
+ int8u(m_mask_function(
+ int8u_ptr(ptrcomp(m_rbuf.row(y ) ) + (x * Step + Offset ) * sizeof(int8u ) ) ) );
+
+end;
+
+{ COMBINE_PIXEL }
+function amask_no_clip_u8.combine_pixel;
+begin
+ result:=int8u(
+ (cover_full + val *
+ m_mask_function(
+ int8u_ptr(ptrcomp(m_rbuf.row(y ) ) + (x * Step + Offset ) * sizeof(int8u ) ) )
+ ) shr cover_shift );
+
+end;
+
+{ FILL_HSPAN }
+procedure amask_no_clip_u8.fill_hspan;
+var
+ mask : int8u_ptr;
+
+begin
+ mask:=int8u_ptr(ptrcomp(m_rbuf.row(y ) ) + (x * Step + Offset ) * sizeof(int8u ) );
+
+ repeat
+ dst^:=int8u(m_mask_function(mask ) );
+
+ inc(ptrcomp(dst ) ,sizeof(int8u ) );
+ inc(ptrcomp(mask ) ,Step * sizeof(int8u ) );
+ dec(num_pix );
+
+ until num_pix = 0;
+
+end;
+
+{ COMBINE_HSPAN }
+procedure amask_no_clip_u8.combine_hspan;
+var
+ mask : int8u_ptr;
+
+begin
+ mask:=int8u_ptr(ptrcomp(m_rbuf.row(y ) ) + (x * Step + Offset ) * sizeof(int8u ) );
+
+ repeat
+ dst^:=int8u((cover_full + dst^ * m_mask_function(mask ) ) shr cover_shift );
+
+ inc(ptrcomp(dst ) ,sizeof(int8u ) );
+ inc(ptrcomp(mask ) ,Step * sizeof(int8u ) );
+ dec(num_pix );
+
+ until num_pix = 0;
+
+end;
+
+{ FILL_VSPAN }
+procedure amask_no_clip_u8.fill_vspan;
+var
+ mask : int8u_ptr;
+
+begin
+ mask:=int8u_ptr(ptrcomp(m_rbuf.row(y ) ) + (x * Step + Offset ) * sizeof(int8u ) );
+
+ repeat
+ dst^:=int8u(m_mask_function(mask ) );
+
+ inc(ptrcomp(dst ) ,sizeof(int8u ) );
+ inc(ptrcomp(mask ) ,m_rbuf._stride );
+ dec(num_pix );
+
+ until num_pix = 0;
+
+end;
+
+{ COMBINE_VSPAN }
+procedure amask_no_clip_u8.combine_vspan;
+var
+ mask : int8u_ptr;
+
+begin
+ mask:=int8u_ptr(ptrcomp(m_rbuf.row(y ) ) + (x * Step + Offset ) * sizeof(int8u ) );
+
+ repeat
+ dst^:=int8u((cover_full + dst^ * m_mask_function(mask ) ) shr cover_shift );
+
+ inc(ptrcomp(dst ) ,sizeof(int8u ) );
+ inc(ptrcomp(mask ) ,m_rbuf._stride );
+ dec(num_pix );
+
+ until num_pix = 0;
+
+end;
+
+{ CONSTRUCT }
+constructor amask_no_clip_gray8.Construct;
+begin
+ inherited Construct(rbuf ,@one_component_mask_u8 ,1 ,0 );
+
+end;
+
+{ CONSTRUCT }
+constructor amask_no_clip_rgb24r.Construct;
+begin
+ inherited Construct(rbuf ,@one_component_mask_u8 ,3 ,0 );
+
+end;
+
+{ CONSTRUCT }
+constructor amask_no_clip_rgb24g.Construct;
+begin
+ inherited Construct(rbuf ,@one_component_mask_u8 ,3 ,1 );
+
+end;
+
+{ CONSTRUCT }
+constructor amask_no_clip_rgb24b.Construct;
+begin
+ inherited Construct(rbuf ,@one_component_mask_u8 ,3 ,2 );
+
+end;
+
+{ CONSTRUCT }
+constructor amask_no_clip_bgr24r.Construct;
+begin
+ inherited Construct(rbuf ,@one_component_mask_u8 ,3 ,2 );
+
+end;
+
+{ CONSTRUCT }
+constructor amask_no_clip_bgr24g.Construct;
+begin
+ inherited Construct(rbuf ,@one_component_mask_u8 ,3 ,1 );
+
+end;
+
+{ CONSTRUCT }
+constructor amask_no_clip_bgr24b.Construct;
+begin
+ inherited Construct(rbuf ,@one_component_mask_u8 ,3 ,0 );
+
+end;
+
+{ CONSTRUCT }
+constructor amask_no_clip_rgba32r.Construct;
+begin
+ inherited Construct(rbuf ,@one_component_mask_u8 ,4 ,0 );
+
+end;
+
+{ CONSTRUCT }
+constructor amask_no_clip_rgba32g.Construct;
+begin
+ inherited Construct(rbuf ,@one_component_mask_u8 ,4 ,1 );
+
+end;
+
+{ CONSTRUCT }
+constructor amask_no_clip_rgba32b.Construct;
+begin
+ inherited Construct(rbuf ,@one_component_mask_u8 ,4 ,2 );
+
+end;
+
+{ CONSTRUCT }
+constructor amask_no_clip_rgba32a.Construct;
+begin
+ inherited Construct(rbuf ,@one_component_mask_u8 ,4 ,3 );
+
+end;
+
+{ CONSTRUCT }
+constructor amask_no_clip_argb32r.Construct;
+begin
+ inherited Construct(rbuf ,@one_component_mask_u8 ,4 ,1 );
+
+end;
+
+{ CONSTRUCT }
+constructor amask_no_clip_argb32g.Construct;
+begin
+ inherited Construct(rbuf ,@one_component_mask_u8 ,4 ,2 );
+
+end;
+
+{ CONSTRUCT }
+constructor amask_no_clip_argb32b.Construct;
+begin
+ inherited Construct(rbuf ,@one_component_mask_u8 ,4 ,3 );
+
+end;
+
+{ CONSTRUCT }
+constructor amask_no_clip_argb32a.Construct;
+begin
+ inherited Construct(rbuf ,@one_component_mask_u8 ,4 ,0 );
+
+end;
+
+{ CONSTRUCT }
+constructor amask_no_clip_bgra32r.Construct;
+begin
+ inherited Construct(rbuf ,@one_component_mask_u8 ,4 ,2 );
+
+end;
+
+{ CONSTRUCT }
+constructor amask_no_clip_bgra32g.Construct;
+begin
+ inherited Construct(rbuf ,@one_component_mask_u8 ,4 ,1 );
+
+end;
+
+{ CONSTRUCT }
+constructor amask_no_clip_bgra32b.Construct;
+begin
+ inherited Construct(rbuf ,@one_component_mask_u8 ,4 ,0 );
+
+end;
+
+{ CONSTRUCT }
+constructor amask_no_clip_bgra32a.Construct;
+begin
+ inherited Construct(rbuf ,@one_component_mask_u8 ,4 ,3 );
+
+end;
+
+{ CONSTRUCT }
+constructor amask_no_clip_abgr32r.Construct;
+begin
+ inherited Construct(rbuf ,@one_component_mask_u8 ,4 ,3 );
+
+end;
+
+{ CONSTRUCT }
+constructor amask_no_clip_abgr32g.Construct;
+begin
+ inherited Construct(rbuf ,@one_component_mask_u8 ,4 ,2 );
+
+end;
+
+{ CONSTRUCT }
+constructor amask_no_clip_abgr32b.Construct;
+begin
+ inherited Construct(rbuf ,@one_component_mask_u8 ,4 ,1 );
+
+end;
+
+{ CONSTRUCT }
+constructor amask_no_clip_abgr32a.Construct;
+begin
+ inherited Construct(rbuf ,@one_component_mask_u8 ,4 ,0 );
+
+end;
+
+{ CONSTRUCT }
+constructor amask_no_clip_rgb24gray.Construct;
+begin
+ inherited Construct(rbuf ,@rgb_to_gray_mask_u8_012 ,3 ,0 );
+
+end;
+
+{ CONSTRUCT }
+constructor amask_no_clip_bgr24gray.Construct;
+begin
+ inherited Construct(rbuf ,@rgb_to_gray_mask_u8_210 ,3 ,0 );
+
+end;
+
+{ CONSTRUCT }
+constructor amask_no_clip_rgba32gray.Construct;
+begin
+ inherited Construct(rbuf ,@rgb_to_gray_mask_u8_012 ,4 ,0 );
+
+end;
+
+{ CONSTRUCT }
+constructor amask_no_clip_argb32gray.Construct;
+begin
+ inherited Construct(rbuf ,@rgb_to_gray_mask_u8_012 ,4 ,1 );
+
+end;
+
+{ CONSTRUCT }
+constructor amask_no_clip_bgra32gray.Construct;
+begin
+ inherited Construct(rbuf ,@rgb_to_gray_mask_u8_210 ,4 ,0 );
+
+end;
+
+{ CONSTRUCT }
+constructor amask_no_clip_abgr32gray.Construct;
+begin
+ inherited Construct(rbuf ,@rgb_to_gray_mask_u8_210 ,4 ,1 );
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_arc.pas b/src/corelib/render/software/agg_arc.pas
new file mode 100644
index 00000000..223a94c6
--- /dev/null
+++ b/src/corelib/render/software/agg_arc.pas
@@ -0,0 +1,221 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// Arc vertex generator
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 17.01.2006-Milano: Unit port establishment
+//
+{ agg_arc.pas }
+unit
+ agg_arc ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ Math ,
+ agg_basics ,
+ agg_vertex_source ;
+
+{ TYPES DEFINITION }
+type
+ arc = object(vertex_source )
+ m_x ,
+ m_y ,
+ m_rx ,
+ m_ry ,
+ m_angle ,
+ m_start ,
+ m_end ,
+ m_scale ,
+ m_da : double;
+
+ m_ccw ,
+ m_initialized : boolean;
+
+ m_path_cmd : unsigned;
+
+ constructor Construct; overload;
+ constructor Construct(x ,y ,rx ,ry ,a1 ,a2 : double; ccw : boolean = true ); overload;
+
+ procedure init(x ,y ,rx ,ry ,a1 ,a2 : double; ccw : boolean = true );
+
+ procedure approximation_scale_(s : double );
+ function _approximation_scale : double;
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ procedure normalize(a1 ,a2 : double; ccw : boolean );
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor arc.Construct;
+begin
+ m_x :=0;
+ m_y :=0;
+ m_rx :=0;
+ m_ry :=0;
+ m_angle:=0;
+ m_start:=0;
+ m_end :=0;
+ m_da :=0;
+
+ m_ccw :=false;
+ m_path_cmd:=0;
+
+ m_scale:=1;
+
+ m_initialized:=false;
+
+end;
+
+{ CONSTRUCT }
+constructor arc.Construct(x ,y ,rx ,ry ,a1 ,a2 : double; ccw : boolean = true );
+begin
+ Construct;
+
+ m_x :=x;
+ m_y :=y;
+ m_rx:=rx;
+ m_ry:=ry;
+
+ m_scale:=1;
+
+ normalize(a1 ,a2 ,ccw );
+
+end;
+
+{ INIT }
+procedure arc.init;
+begin
+ m_x :=x;
+ m_y :=y;
+ m_rx:=rx;
+ m_ry:=ry;
+
+ normalize(a1 ,a2 ,ccw );
+
+end;
+
+{ APPROXIMATION_SCALE_ }
+procedure arc.approximation_scale_;
+begin
+ m_scale:=s;
+
+ if m_initialized then
+ normalize(m_start ,m_end ,m_ccw );
+
+end;
+
+{ _APPROXIMATION_SCALE }
+function arc._approximation_scale;
+begin
+ result:=m_scale;
+
+end;
+
+{ REWIND }
+procedure arc.rewind;
+begin
+ m_path_cmd:=path_cmd_move_to;
+ m_angle :=m_start;
+
+end;
+
+{ VERTEX }
+function arc.vertex;
+var
+ pf : unsigned;
+
+begin
+ if is_stop(m_path_cmd ) then
+ result:=path_cmd_stop
+
+ else
+ if (m_angle < m_end - m_da / 4 ) <> m_ccw then
+ begin
+ x^:=m_x + Cos(m_end ) * m_rx;
+ y^:=m_y + Sin(m_end ) * m_ry;
+
+ m_path_cmd:=path_cmd_stop;
+
+ result:=path_cmd_line_to;
+
+ end
+ else
+ begin
+ x^:=m_x + Cos(m_angle ) * m_rx;
+ y^:=m_y + Sin(m_angle ) * m_ry;
+
+ m_angle:=m_angle + m_da;
+
+ pf :=m_path_cmd;
+ m_path_cmd:=path_cmd_line_to;
+
+ result:=pf;
+
+ end;
+
+end;
+
+{ NORMALIZE }
+procedure arc.normalize;
+var
+ ra : double;
+
+begin
+ ra :=(Abs(m_rx ) + Abs(m_ry ) ) / 2;
+ m_da:=ArcCos(ra / (ra + 0.125 / m_scale ) ) * 2;
+
+ if ccw then
+ while a2 < a1 do
+ a2:=a2 + (pi * 2.0 )
+ else
+ begin
+ while a1 < a2 do
+ a1:=a1 + (pi * 2.0 );
+
+ m_da:=-m_da;
+
+ end;
+
+ m_ccw :=ccw;
+ m_start:=a1;
+ m_end :=a2;
+
+ m_initialized:=true;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_array.pas b/src/corelib/render/software/agg_array.pas
new file mode 100644
index 00000000..ad013c9a
--- /dev/null
+++ b/src/corelib/render/software/agg_array.pas
@@ -0,0 +1,1194 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 18.02.2006-MIlano: pod_array_adaptor, quick_sort
+// 16.02.2006-Milano: pod_allocator
+// 19.12.2005-Milano: pod_deque
+// 15.11.2005-Milano: Unit port establishment
+//
+{ agg_array.pas }
+unit
+ agg_array ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ;
+
+{ TYPES DEFINITION }
+type
+ func_less = function(e1 ,e2 : pointer ) : boolean;
+ func_equal = function(e1 ,e2 : pointer ) : boolean;
+
+ array_base_ptr = ^array_base;
+ array_base = object
+ function size : unsigned; virtual; abstract;
+ function entry : unsigned; virtual; abstract;
+ function array_operator(i : unsigned ) : pointer; virtual; abstract;
+
+ function at(i : unsigned ) : pointer; virtual;
+
+ end;
+
+//----------------------------------------------------------range_adaptor
+ range_adaptor = object(array_base )
+ private
+ m_array : array_base_ptr;
+ m_start ,
+ m_size : unsigned;
+
+ public
+ constructor Construct(array_ : array_base_ptr; start ,size_ : unsigned );
+
+ function size : unsigned; virtual;
+ function entry : unsigned; virtual;
+ function array_operator(i : unsigned ) : pointer; virtual;
+
+ end;
+
+//-------------------------------------------------------pod_array_adaptor
+ pod_array_adaptor_ptr = ^pod_array_adaptor;
+ pod_array_adaptor = object(array_base )
+ m_array : pointer;
+ m_size ,
+ m_entry : unsigned;
+
+ constructor Construct(array_ : pointer; size_ ,entry_ : unsigned );
+
+ function size : unsigned; virtual;
+ function entry : unsigned; virtual;
+ function array_operator(i : unsigned ) : pointer; virtual;
+
+ function at(i : unsigned ) : pointer; virtual;
+
+ end;
+
+//---------------------------------------------------------pod_auto_array
+ pod_auto_array_ptr = ^pod_auto_array;
+ pod_auto_array = object(array_base )
+ m_size ,
+ m_entry_sz : unsigned;
+
+ m_array : pointer;
+
+ constructor Construct(size_ ,entry_sz : unsigned );
+ destructor Destruct;
+
+ function size : unsigned; virtual;
+ function entry : unsigned; virtual;
+ function array_operator(i : unsigned ) : pointer; virtual;
+
+ end;
+
+//---------------------------------------------------------------pod_array
+// A simple class template to store Plain Old Data, a vector
+// of a fixed size. The data is continous in memory
+//------------------------------------------------------------------------
+ pod_array = object(array_base )
+ m_entry_sz ,
+ m_size ,
+ m_capacity : unsigned;
+
+ m_array : pointer;
+
+ constructor Construct(entry_sz : unsigned ); overload;
+ constructor Construct(entry_sz ,size_ : unsigned ); overload;
+ constructor Create (entry_sz ,size_ : unsigned );
+ destructor Destruct;
+
+ procedure allocate(size_ : unsigned; extra_tail : unsigned = 0 );
+ procedure resize (new_size : unsigned );
+ procedure capacity(cap ,extra_tail : unsigned );
+
+ procedure zero;
+ procedure add(v : pointer );
+ function data : pointer;
+
+ function size : unsigned; virtual;
+ function entry : unsigned; virtual;
+ function array_operator(i : unsigned ) : pointer; virtual;
+
+ end;
+
+ pod_vector = pod_array;
+
+//---------------------------------------------------------------pod_deque
+// A simple class template to store Plain Old Data, similar to std::deque
+// It doesn't reallocate memory but instead, uses blocks of data of size
+// of (1 << S), that is, power of two. The data is NOT contiguous in memory,
+// so the only valid access method is operator [] or curr(), prev(), next()
+//
+// There reallocs occure only when the pool of pointers to blocks needs
+// to be extended (it happens very rarely). You can control the value
+// of increment to reallocate the pointer buffer. See the second constructor.
+// By default, the incremeent value equals (1 << S), i.e., the block size.
+//------------------------------------------------------------------------
+ pod_deque_ptr = ^pod_deque;
+ pod_deque = object(array_base )
+ block_shift ,
+ block_size ,
+ block_mask : unsigned;
+
+ m_size ,
+ m_num_blocks ,
+ m_max_blocks ,
+ m_block_ptr_inc : unsigned;
+
+ m_blocks : pointer;
+
+ m_entry_sz : unsigned;
+
+ constructor Construct(entry_sz : unsigned; s_ : unsigned = 6 ); overload;
+ constructor Construct(block_ptr_inc ,entry_sz : unsigned; s_ : unsigned ); overload;
+ destructor Destruct;
+
+ procedure remove_all;
+ procedure remove_last;
+
+ procedure add (val : pointer );
+ procedure modify_last(val : pointer );
+
+ procedure cut_at(size_ : unsigned );
+
+ function size : unsigned; virtual;
+ function entry : unsigned; virtual;
+
+ function array_operator (i : unsigned ) : pointer; virtual;
+ procedure assign_operator(v : pod_deque_ptr );
+
+ function curr(idx : unsigned ) : pointer;
+ function prev(idx : unsigned ) : pointer;
+ function next(idx : unsigned ) : pointer;
+ function last : pointer;
+
+ function allocate_continuous_block(num_elements : unsigned ) : int;
+ procedure allocate_block (nb : unsigned );
+
+ function data_ptr : pointer;
+
+ end;
+
+ pod_bvector_ptr = ^pod_bvector;
+ pod_bvector = pod_deque;
+
+//-----------------------------------------------------------pod_allocator
+// Allocator for arbitrary POD data. Most usable in different cache
+// systems for efficient memory allocations.
+// Memory is allocated with blocks of fixed size ("block_size" in
+// the constructor). If required size exceeds the block size the allocator
+// creates a new block of the required size. However, the most efficient
+// use is when the average reqired size is much less than the block size.
+//------------------------------------------------------------------------
+ pod_alloc_ptr = ^pod_alloc;
+ pod_alloc = record
+ ptr : int8u_ptr;
+ sz : unsigned;
+
+ end;
+
+ pod_allocator = object
+ m_block_size ,
+ m_block_ptr_inc ,
+ m_num_blocks ,
+ m_max_blocks : unsigned;
+
+ m_blocks : pod_alloc_ptr;
+ m_buf_ptr : int8u_ptr;
+
+ m_rest : unsigned;
+
+ constructor Construct(block_size : unsigned; block_ptr_inc : unsigned = 256 - 8 );
+ destructor Destruct;
+
+ procedure remove_all;
+
+ function allocate(size : unsigned; alignment : unsigned = 1 ) : int8u_ptr;
+
+ procedure allocate_block(size : unsigned );
+
+ end;
+
+{ GLOBAL VARIABLES & CONSTANTS }
+{ GLOBAL PROCEDURES }
+ procedure quick_sort (arr : array_base_ptr; less : func_less );
+ function remove_duplicates(arr : array_base_ptr; equal : func_equal ) : unsigned;
+
+ function int_less (a ,b : pointer ) : boolean;
+ function int_greater(a ,b : pointer ) : boolean;
+
+ function unsigned_less (a ,b : pointer ) : boolean;
+ function unsigned_greater(a ,b : pointer ) : boolean;
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ QUICK_SORT }
+procedure quick_sort;
+const
+ quick_sort_threshold = 9;
+
+type
+ int80_ptr = ^int80;
+ int80 = array[0..79 ] of int;
+
+var
+ temp ,e1 ,e2 : pointer;
+
+ swap : unsigned;
+
+ stack : int80;
+
+ top : int80_ptr;
+
+ limit ,base ,len ,i ,j ,pivot : int;
+
+begin
+ if arr.size < 2 then
+ exit;
+
+ agg_getmem(temp ,arr.entry );
+
+ swap :=arr.entry;
+ top :=@stack;
+ limit:=arr.size;
+ base :=0;
+
+ repeat
+ len:=limit - base;
+
+ if len > quick_sort_threshold then
+ begin
+ // we use base + len/2 as the pivot
+ pivot:=base + len div 2;
+
+ // swap_elements(arr[base], arr[pivot]);
+ move(arr.at(base )^ ,temp^ ,swap );
+ move(arr.at(pivot )^ ,arr.at(base )^ ,swap );
+ move(temp^ ,arr.at(pivot )^ ,swap );
+
+ i:=base + 1;
+ j:=limit - 1;
+
+ // now ensure that *i <= *base <= *j
+ e1:=arr.at(j );
+ e2:=arr.at(i );
+
+ if less(e1 ,e2 ) then
+ begin
+ // swap_elements(*e1, *e2);
+ move(e1^ ,temp^ ,swap );
+ move(e2^ ,e1^ ,swap );
+ move(temp^ ,e2^ ,swap );
+
+ end;
+
+ e1:=arr.at(base );
+ e2:=arr.at(i );
+
+ if less(e1 ,e2 ) then
+ begin
+ // swap_elements(*e1, *e2);
+ move(e1^ ,temp^ ,swap );
+ move(e2^ ,e1^ ,swap );
+ move(temp^ ,e2^ ,swap );
+
+ end;
+
+ e1:=arr.at(j );
+ e2:=arr.at(base );
+
+ if less(e1 ,e2 ) then
+ begin
+ // swap_elements(*e1, *e2);
+ move(e1^ ,temp^ ,swap );
+ move(e2^ ,e1^ ,swap );
+ move(temp^ ,e2^ ,swap );
+
+ end;
+
+ repeat
+ repeat
+ inc(i )
+
+ until not less(arr.at(i ) ,arr.at(base ) );
+
+ repeat
+ dec(j );
+
+ until not less(arr.at(base ) ,arr.at(j ) );
+
+ if i > j then
+ break;
+
+ // swap_elements(arr[i], arr[j]);
+ move(arr.at(i )^ ,temp^ ,swap );
+ move(arr.at(j )^ ,arr.at(i )^ ,swap );
+ move(temp^ ,arr.at(j )^ ,swap );
+
+ until false;
+
+ // swap_elements(arr[base], arr[j]);
+ move(arr.at(base )^ ,temp^ ,swap );
+ move(arr.at(j )^ ,arr.at(base )^ ,swap );
+ move(temp^ ,arr.at(j )^ ,swap );
+
+ // now, push the largest sub-array
+ if j - base > limit - i then
+ begin
+ top^[0 ]:=base;
+ top^[1 ]:=j;
+ base :=i;
+
+ end
+ else
+ begin
+ top^[0 ]:=i;
+ top^[1 ]:=limit;
+ limit :=j;
+
+ end;
+
+ inc(ptrcomp(top ) ,2 * sizeof(int ) );
+
+ end
+ else
+ begin
+ // the sub-array is small, perform insertion sort
+ j:=base;
+ i:=j + 1;
+
+ while i < limit do
+ begin
+ e1:=arr.at(j + 1 );
+ e2:=arr.at(j );
+
+ while less(e1 ,e2 ) do
+ begin
+ // swap_elements(*e1, *e2);
+ move(e1^ ,temp^ ,swap );
+ move(e2^ ,e1^ ,swap );
+ move(temp^ ,e2^ ,swap );
+
+ if j = base then
+ break;
+
+ dec(j );
+
+ e1:=arr.at(j + 1 );
+ e2:=arr.at(j );
+
+ end;
+
+ j:=i;
+
+ inc(i );
+
+ end;
+
+ if ptrcomp(top ) > ptrcomp(@stack ) then
+ begin
+ dec(ptrcomp(top ) ,2 * sizeof(int ) );
+
+ base :=top^[0 ];
+ limit:=top^[1 ];
+
+ end
+ else
+ break;
+
+ end;
+
+ until false;
+
+ agg_freemem(temp ,arr.entry );
+
+end;
+
+{ REMOVE_DUPLICATES }
+// Remove duplicates from a sorted array. It doesn't cut the
+// tail of the array, it just returns the number of remaining elements.
+function remove_duplicates(arr : array_base_ptr; equal : func_equal ) : unsigned;
+var
+ i ,j : unsigned;
+
+ e : pointer;
+
+begin
+ if arr.size < 2 then
+ begin
+ result:=arr.size;
+
+ exit;
+
+ end;
+
+ i:=1;
+ j:=1;
+
+ while i < arr.size do
+ begin
+ e:=arr.array_operator(i );
+
+ if not equal(e ,arr.array_operator(i - 1 ) ) then
+ begin
+ move(e^ ,arr.array_operator(j )^ ,arr.entry );
+ inc (j );
+
+ end;
+
+ inc(i );
+
+ end;
+
+ result:=j;
+
+end;
+
+{ INT_LESS }
+function int_less(a ,b : pointer ) : boolean;
+begin
+ result:=int_ptr(a )^ < int_ptr(b )^;
+
+end;
+
+{ INT_GREATER }
+function int_greater(a ,b : pointer ) : boolean;
+begin
+ result:=int_ptr(a )^ > int_ptr(b )^;
+
+end;
+
+{ UNSIGNED_LESS }
+function unsigned_less(a ,b : pointer ) : boolean;
+begin
+ result:=unsigned_ptr(a )^ < unsigned_ptr(b )^;
+
+end;
+
+{ UNSIGNED_GREATER }
+function unsigned_greater(a ,b : pointer ) : boolean;
+begin
+ result:=unsigned_ptr(a )^ > unsigned_ptr(b )^;
+
+end;
+
+{ UNIT IMPLEMENTATION }
+{ AT }
+function array_base.at;
+begin
+ at:=array_operator(i );
+
+end;
+
+{ CONSTRUCT }
+constructor range_adaptor.Construct(array_ : array_base_ptr; start ,size_ : unsigned );
+begin
+ m_array:=array_;
+ m_start:=start;
+ m_size :=size_;
+
+end;
+
+{ SIZE }
+function range_adaptor.size : unsigned;
+begin
+ result:=m_size;
+
+end;
+
+{ ENTRY }
+function range_adaptor.entry : unsigned;
+begin
+ result:=m_array.entry;
+
+end;
+
+{ ARRAY_OPERATOR }
+function range_adaptor.array_operator(i : unsigned ) : pointer;
+begin
+ result:=m_array.array_operator(m_start + i );
+
+end;
+
+{ CONSTRUCT }
+constructor pod_array_adaptor.Construct;
+begin
+ m_array:=array_;
+ m_size :=size_;
+ m_entry:=entry_;
+
+end;
+
+{ SIZE }
+function pod_array_adaptor.size;
+begin
+ result:=m_size;
+
+end;
+
+{ ENTRY }
+function pod_array_adaptor.entry;
+begin
+ result:=m_entry;
+
+end;
+
+{ ARRAY_OPERATOR }
+function pod_array_adaptor.array_operator;
+begin
+ result:=pointer(ptrcomp(m_array ) + i * sizeof(m_entry ) );
+
+end;
+
+{ AT }
+function pod_array_adaptor.at;
+begin
+ result:=pointer(ptrcomp(m_array ) + i * m_entry );
+
+end;
+
+{ CONSTRUCT }
+constructor pod_auto_array.Construct;
+begin
+ m_size :=size_;
+ m_entry_sz:=entry_sz;
+
+ agg_getmem(m_array ,m_size * m_entry_sz );
+
+end;
+
+{ DESTRUCT }
+destructor pod_auto_array.Destruct;
+begin
+ agg_freemem(m_array ,m_size * m_entry_sz );
+
+end;
+
+{ SIZE }
+function pod_auto_array.size;
+begin
+ result:=m_size;
+
+end;
+
+{ ENTRY }
+function pod_auto_array.entry;
+begin
+ result:=m_entry_sz;
+
+end;
+
+{ ARRAY_OPERATOR }
+function pod_auto_array.array_operator;
+begin
+ result:=pointer(ptrcomp(m_array ) + i * m_entry_sz );
+
+end;
+
+{ CONSTRUCT }
+constructor pod_array.Construct(entry_sz : unsigned );
+begin
+ m_entry_sz:=entry_sz;
+ m_size :=0;
+ m_capacity:=0;
+
+ m_array:=NIL;
+
+end;
+
+{ CONSTRUCT }
+constructor pod_array.Construct(entry_sz ,size_ : unsigned );
+begin
+ Construct(entry_sz );
+ allocate (size_ );
+
+end;
+
+{ CREATE }
+constructor pod_array.Create(entry_sz ,size_ : unsigned );
+begin
+ Construct(entry_sz );
+ capacity (size_ ,0 );
+
+end;
+
+{ DESTRUCT }
+destructor pod_array.Destruct;
+begin
+ if m_array <> NIL then
+ agg_freemem(m_array ,m_capacity * m_entry_sz );
+
+end;
+
+{ ALLOCATE }
+// Allocate n elements. All data is lost,
+// but elements can be accessed in range 0...size-1.
+procedure pod_array.allocate;
+begin
+ capacity(size_ ,extra_tail );
+
+ m_size:=size_;
+
+end;
+
+{ RESIZE }
+// Resize keeping the content.
+procedure pod_array.resize;
+var
+ buff : pointer;
+
+begin
+ if new_size > m_size then
+ if new_size > m_capacity then
+ begin
+ agg_getmem(buff ,new_size * m_entry_sz );
+
+ if m_array <> NIL then
+ begin
+ move(m_array^ ,buff^ ,m_size * m_entry_sz );
+
+ agg_freemem(m_array ,m_capacity * m_entry_sz );
+
+ end;
+
+ m_array :=buff;
+ m_capacity:=new_size;
+
+ end
+ else
+ else
+ m_size:=new_size;
+
+end;
+
+{ CAPACITY }
+procedure pod_array.capacity;
+begin
+ m_size:=0;
+
+ if cap > m_capacity then
+ begin
+ agg_freemem(m_array ,m_capacity * m_entry_sz );
+
+ m_capacity:=cap + extra_tail;
+
+ if m_capacity > 0 then
+ agg_getmem(m_array ,m_capacity * m_entry_sz )
+ else
+ m_array:=0;
+
+ end;
+
+end;
+
+{ ZERO }
+procedure pod_array.zero;
+begin
+ fillchar(m_array^ ,m_entry_sz * m_size ,0 );
+
+end;
+
+{ ADD }
+procedure pod_array.add(v : pointer );
+begin
+ move(v^ ,pointer(ptrcomp(m_array ) + m_size * m_entry_sz )^ ,m_entry_sz );
+ inc (m_size );
+
+end;
+
+{ DATA }
+function pod_array.data;
+begin
+ result:=m_array;
+
+end;
+
+{ SIZE }
+function pod_array.size;
+begin
+ result:=m_size;
+
+end;
+
+{ ENTRY }
+function pod_array.entry;
+begin
+ result:=m_entry_sz;
+
+end;
+
+{ ARRAY_OPERATOR }
+function pod_array.array_operator(i : unsigned ) : pointer;
+begin
+ result:=pointer(ptrcomp(m_array ) + i * m_entry_sz );
+
+end;
+
+{ CONSTRUCT }
+constructor pod_deque.Construct(entry_sz : unsigned; s_ : unsigned = 6 );
+begin
+ block_shift:=s_;
+ block_size :=1 shl block_shift;
+ block_mask :=block_size - 1;
+
+ m_size :=0;
+ m_num_blocks :=0;
+ m_max_blocks :=0;
+ m_blocks :=0;
+ m_block_ptr_inc:=block_size;
+
+ m_entry_sz:=entry_sz;
+
+end;
+
+{ CONSTRUCT }
+constructor pod_deque.Construct(block_ptr_inc ,entry_sz : unsigned; s_ : unsigned );
+begin
+ Construct(entry_sz ,s_ );
+
+ m_block_ptr_inc:=block_ptr_inc;
+
+end;
+
+{ DESTRUCT }
+destructor pod_deque.Destruct;
+var
+ blk : pointer;
+
+begin
+ if m_num_blocks <> 0 then
+ begin
+ blk:=pointer(ptrcomp(m_blocks ) + (m_num_blocks - 1 ) * sizeof(pointer ) );
+
+ while m_num_blocks <> 0 do
+ begin
+ agg_freemem(p32(blk^ ).ptr ,block_size * m_entry_sz );
+
+ dec(ptrcomp(blk ) ,sizeof(pointer ) );
+ dec(m_num_blocks );
+
+ end;
+
+ agg_freemem(m_blocks ,m_max_blocks * sizeof(pointer ) );
+
+ end;
+
+end;
+
+{ REMOVE_ALL }
+procedure pod_deque.remove_all;
+begin
+ m_size:=0;
+
+end;
+
+{ REMOVE_LAST }
+procedure pod_deque.remove_last;
+begin
+ if m_size <> 0 then
+ dec(m_size );
+
+end;
+
+{ ADD }
+procedure pod_deque.add;
+var
+ p : pointer;
+
+begin
+ p:=data_ptr;
+
+ move(val^ ,p^ ,m_entry_sz );
+ inc (m_size );
+
+end;
+
+{ MODIFY_LAST }
+procedure pod_deque.modify_last;
+begin
+ remove_last;
+ add(val );
+
+end;
+
+{ CUT_AT }
+procedure pod_deque.cut_at(size_ : unsigned );
+begin
+ if size_ < m_size then
+ m_size:=size_;
+
+end;
+
+{ SIZE }
+function pod_deque.size;
+begin
+ result:=m_size;
+
+end;
+
+{ ENTRY }
+function pod_deque.entry;
+begin
+ result:=m_entry_sz;
+
+end;
+
+{ ARRAY_OPERATOR }
+function pod_deque.array_operator;
+begin
+ result:=
+ pointer(
+ p32(pointer(ptrcomp(m_blocks ) + (i shr block_shift ) * sizeof(pointer ) )^ ).int
+ + (i and block_mask ) * m_entry_sz );
+
+end;
+
+{ ASSIGN_OPERATOR }
+procedure pod_deque.assign_operator;
+var
+ i : unsigned;
+ src ,
+ dst : pointer;
+
+begin
+ Destruct;
+
+ block_shift:=v.block_shift;
+ block_size :=v.block_size;
+ block_mask :=v.block_mask;
+
+ m_size :=v.m_size;
+ m_entry_sz:=v.m_entry_sz;
+
+ m_num_blocks:=v.m_num_blocks;
+ m_max_blocks:=v.m_max_blocks;
+
+ m_block_ptr_inc:=v.m_block_ptr_inc;
+
+ if m_max_blocks <> 0 then
+ agg_getmem(m_blocks ,m_max_blocks * sizeof(pointer ) )
+ else
+ m_blocks:=NIL;
+
+
+ src:=v.m_blocks;
+ dst:=m_blocks;
+ i :=0;
+
+ while i < m_num_blocks do
+ begin
+ agg_getmem(p32(dst^ ).ptr ,block_size * m_entry_sz );
+
+ move(
+ p32(src^ ).ptr^ ,
+ p32(dst^ ).ptr^ ,
+ block_size * m_entry_sz );
+
+ inc(ptrcomp(src ) ,sizeof(pointer ) );
+ inc(ptrcomp(dst ) ,sizeof(pointer ) );
+ inc(i );
+
+ end;
+
+end;
+
+{ CURR }
+function pod_deque.curr;
+begin
+ result:=array_operator(idx );
+
+end;
+
+{ PREV }
+function pod_deque.prev;
+begin
+ result:=array_operator((idx + m_size - 1 ) mod m_size );
+
+end;
+
+{ NEXT }
+function pod_deque.next;
+begin
+ result:=array_operator((idx + 1 ) mod m_size );
+
+end;
+
+{ LAST }
+function pod_deque.last : pointer;
+begin
+ result:=array_operator(m_size - 1 );
+
+end;
+
+{ ALLOCATE_CONTINUOUS_BLOCK }
+function pod_deque.allocate_continuous_block;
+var
+ rest ,index : unsigned;
+
+begin
+ if num_elements < block_size then
+ begin
+ data_ptr; // Allocate initial block if necessary
+
+ rest:=block_size - (m_size and block_mask );
+
+ if num_elements <= rest then
+ begin
+ // The rest of the block is good, we can use it
+ index:=m_size;
+
+ inc(m_size ,num_elements );
+
+ result:=index;
+
+ exit;
+
+ end;
+
+ // New block
+ inc(m_size ,rest );
+
+ data_ptr;
+
+ index:=m_size;
+
+ inc(m_size ,num_elements );
+
+ result:=index;
+
+ exit;
+
+ end;
+
+ result:=-1; // Impossible to allocate
+
+end;
+
+{ ALLOCATE_BLOCK }
+procedure pod_deque.allocate_block;
+var
+ new_blocks : pointer;
+
+begin
+ if nb >= m_max_blocks then
+ begin
+ agg_getmem(new_blocks ,(m_max_blocks + m_block_ptr_inc ) * sizeof(pointer ) );
+
+ if m_blocks <> NIL then
+ begin
+ move(
+ m_blocks^ ,
+ new_blocks^ ,
+ m_num_blocks * sizeof(pointer ) );
+
+ agg_freemem(m_blocks ,m_max_blocks * sizeof(pointer ) );
+
+ end;
+
+ m_blocks:=new_blocks;
+
+ inc(m_max_blocks ,m_block_ptr_inc );
+
+ end;
+
+ agg_getmem(
+ p32(pointer(ptrcomp(m_blocks ) + nb * sizeof(pointer ) )^ ).ptr ,
+ block_size * m_entry_sz );
+
+ inc(m_num_blocks );
+
+end;
+
+{ DATA_PTR }
+function pod_deque.data_ptr;
+var
+ nb : unsigned;
+
+begin
+ nb:=m_size shr block_shift;
+
+ if nb >= m_num_blocks then
+ allocate_block(nb );
+
+ result:=
+ pointer(
+ p32(pointer(ptrcomp(m_blocks ) + nb * sizeof(pointer ) )^ ).int
+ + (m_size and block_mask ) * m_entry_sz );
+
+end;
+
+{ CONSTRUCT }
+constructor pod_allocator.Construct;
+begin
+ m_block_size :=block_size;
+ m_block_ptr_inc:=block_ptr_inc;
+
+ m_num_blocks:=0;
+ m_max_blocks:=0;
+
+ m_blocks :=NIL;
+ m_buf_ptr:=NIL;
+ m_rest :=0;
+
+end;
+
+{ DESTRUCT }
+destructor pod_allocator.Destruct;
+begin
+ remove_all;
+
+end;
+
+{ REMOVE_ALL }
+procedure pod_allocator.remove_all;
+var
+ blk : pod_alloc_ptr;
+
+begin
+ if m_num_blocks <> 0 then
+ begin
+ blk:=pod_alloc_ptr(ptrcomp(m_blocks ) + (m_num_blocks - 1 ) * sizeof(pod_alloc ) );
+
+ while m_num_blocks <> 0 do
+ begin
+ agg_freemem(pointer(blk.ptr ) ,blk.sz );
+
+ dec(ptrcomp(blk ) ,sizeof(pod_alloc ) );
+ dec(m_num_blocks );
+
+ end;
+
+ agg_freemem(pointer(m_blocks ) ,m_max_blocks * sizeof(pod_alloc ) );
+
+ end;
+
+ m_num_blocks:=0;
+ m_max_blocks:=0;
+
+ m_blocks :=NIL;
+ m_buf_ptr:=NIL;
+ m_rest :=0;
+
+end;
+
+{ ALLOCATE }
+function pod_allocator.allocate;
+var
+ ptr : int8u_ptr;
+ align : unsigned;
+
+begin
+ if size = 0 then
+ begin
+ result:=0;
+
+ exit;
+
+ end;
+
+ if size <= m_rest then
+ begin
+ ptr:=m_buf_ptr;
+
+ if alignment > 1 then
+ begin
+ align:=(alignment - unsigned(int32u(ptr ) ) mod alignment ) mod alignment;
+
+ inc(size ,align );
+ inc(ptrcomp(ptr ) ,align );
+
+ if size <= m_rest then
+ begin
+ dec(m_rest ,size );
+ inc(ptrcomp(m_buf_ptr ) ,size );
+
+ result:=ptr;
+
+ exit;
+
+ end;
+
+ allocate_block(size );
+
+ result:=allocate(size - align ,alignment );
+
+ exit;
+
+ end;
+
+ dec(m_rest ,size );
+ inc(ptrcomp(m_buf_ptr ) ,size );
+
+ result:=ptr;
+
+ exit;
+
+ end;
+
+ allocate_block(size + alignment - 1 );
+
+ result:=allocate(size ,alignment );
+
+end;
+
+{ ALLOCATE_BLOCK }
+procedure pod_allocator.allocate_block;
+var
+ new_blocks : pod_alloc_ptr;
+
+begin
+ if size < m_block_size then
+ size:=m_block_size;
+
+ if m_num_blocks >= m_max_blocks then
+ begin
+ agg_getmem(pointer(new_blocks ) ,(m_max_blocks + m_block_ptr_inc ) * sizeof(pod_alloc ) );
+
+ if m_blocks <> NIL then
+ begin
+ move(m_blocks^ ,new_blocks^ ,m_num_blocks * sizeof(pod_alloc ) );
+
+ agg_freemem(pointer(m_blocks ) ,m_max_blocks * sizeof(pod_alloc ) );
+
+ end;
+
+ m_blocks:=new_blocks;
+
+ inc(m_max_blocks ,m_block_ptr_inc );
+
+ end;
+
+ agg_getmem(pointer(m_buf_ptr ) ,size * sizeof(int8u ) );
+
+ pod_alloc_ptr(ptrcomp(m_blocks ) + m_num_blocks * sizeof(pod_alloc ) ).ptr:=m_buf_ptr;
+ pod_alloc_ptr(ptrcomp(m_blocks ) + m_num_blocks * sizeof(pod_alloc ) ).sz :=size;
+
+ inc(m_num_blocks );
+
+ m_rest:=size;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_arrowhead.pas b/src/corelib/render/software/agg_arrowhead.pas
new file mode 100644
index 00000000..d12b325b
--- /dev/null
+++ b/src/corelib/render/software/agg_arrowhead.pas
@@ -0,0 +1,255 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// Simple arrowhead/arrowtail generator
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 24.02.2006-Milano: Unit port establishment
+//
+{ agg_arrowhead.pas }
+unit
+ agg_arrowhead ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_vertex_source ;
+
+{ TYPES DEFINITION }
+type
+ arrowhead = object(vertex_source )
+ m_head_d1 ,
+ m_head_d2 ,
+ m_head_d3 ,
+ m_head_d4 ,
+ m_tail_d1 ,
+ m_tail_d2 ,
+ m_tail_d3 ,
+ m_tail_d4 : double;
+
+ m_head_flag ,
+ m_tail_flag : boolean;
+
+ m_coord : array[0..15 ] of double;
+ m_cmd : array[0..7 ] of unsigned;
+
+ m_curr_id ,
+ m_curr_coord : unsigned;
+
+ constructor Construct;
+
+ procedure head_(d1 ,d2 ,d3 ,d4 : double );
+
+ procedure head;
+ procedure no_head;
+
+ procedure tail_(d1 ,d2 ,d3 ,d4 : double );
+
+ procedure tail;
+ procedure no_tail;
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor arrowhead.Construct;
+begin
+ m_head_d1:=1.0;
+ m_head_d2:=1.0;
+ m_head_d3:=1.0;
+ m_head_d4:=0.0;
+ m_tail_d1:=1.0;
+ m_tail_d2:=1.0;
+ m_tail_d3:=1.0;
+ m_tail_d4:=0.0;
+
+ m_head_flag:=false;
+ m_tail_flag:=false;
+
+ m_curr_id :=0;
+ m_curr_coord:=0;
+
+end;
+
+{ HEAD_ }
+procedure arrowhead.head_;
+begin
+ m_head_d1:=d1;
+ m_head_d2:=d2;
+ m_head_d3:=d3;
+ m_head_d4:=d4;
+
+ m_head_flag:=true;
+
+end;
+
+{ HEAD }
+procedure arrowhead.head;
+begin
+ m_head_flag:=true;
+
+end;
+
+{ NO_HEAD }
+procedure arrowhead.no_head;
+begin
+ m_head_flag:=false;
+
+end;
+
+{ TAIL_ }
+procedure arrowhead.tail_;
+begin
+ m_tail_d1:=d1;
+ m_tail_d2:=d2;
+ m_tail_d3:=d3;
+ m_tail_d4:=d4;
+
+ m_tail_flag:=true;
+
+end;
+
+{ TAIL }
+procedure arrowhead.tail;
+begin
+ m_tail_flag:=true;
+
+end;
+
+{ NO_TAIL }
+procedure arrowhead.no_tail;
+begin
+ m_tail_flag:=false;
+
+end;
+
+{ REWIND }
+procedure arrowhead.rewind;
+begin
+ m_curr_id :=path_id;
+ m_curr_coord:=0;
+
+ if path_id = 0 then
+ begin
+ if not m_tail_flag then
+ begin
+ m_cmd[0 ]:=path_cmd_stop;
+
+ exit;
+
+ end;
+
+ m_coord[0 ]:=m_tail_d1;
+ m_coord[1 ]:=0.0;
+ m_coord[2 ]:=m_tail_d1 - m_tail_d4;
+ m_coord[3 ]:=m_tail_d3;
+ m_coord[4 ]:=-m_tail_d2 - m_tail_d4;
+ m_coord[5 ]:=m_tail_d3;
+ m_coord[6 ]:=-m_tail_d2;
+ m_coord[7 ]:=0.0;
+ m_coord[8 ]:=-m_tail_d2 - m_tail_d4;
+ m_coord[9 ]:=-m_tail_d3;
+ m_coord[10 ]:= m_tail_d1 - m_tail_d4;
+ m_coord[11 ]:=-m_tail_d3;
+
+ m_cmd[0 ]:=path_cmd_move_to;
+ m_cmd[1 ]:=path_cmd_line_to;
+ m_cmd[2 ]:=path_cmd_line_to;
+ m_cmd[3 ]:=path_cmd_line_to;
+ m_cmd[4 ]:=path_cmd_line_to;
+ m_cmd[5 ]:=path_cmd_line_to;
+ m_cmd[7 ]:=path_cmd_end_poly or path_flags_close or path_flags_ccw;
+ m_cmd[6 ]:=path_cmd_stop;
+
+ exit;
+
+ end;
+
+ if path_id = 1 then
+ begin
+ if not m_head_flag then
+ begin
+ m_cmd[0 ]:=path_cmd_stop;
+
+ exit;
+
+ end;
+
+ m_coord[0 ]:=-m_head_d1;
+ m_coord[1 ]:=0.0;
+ m_coord[2 ]:=m_head_d2 + m_head_d4;
+ m_coord[3 ]:=-m_head_d3;
+ m_coord[4 ]:=m_head_d2;
+ m_coord[5 ]:=0.0;
+ m_coord[6 ]:=m_head_d2 + m_head_d4;
+ m_coord[7 ]:=m_head_d3;
+
+ m_cmd[0 ]:=path_cmd_move_to;
+ m_cmd[1 ]:=path_cmd_line_to;
+ m_cmd[2 ]:=path_cmd_line_to;
+ m_cmd[3 ]:=path_cmd_line_to;
+ m_cmd[4 ]:=path_cmd_end_poly or path_flags_close or path_flags_ccw;
+ m_cmd[5 ]:=path_cmd_stop;
+
+ exit;
+
+ end;
+
+end;
+
+{ VERTEX }
+function arrowhead.vertex;
+var
+ curr_idx : unsigned;
+
+begin
+ if m_curr_id < 2 then
+ begin
+ curr_idx:=m_curr_coord * 2;
+
+ x^:=m_coord[curr_idx ];
+ y^:=m_coord[curr_idx + 1 ];
+
+ result:=m_cmd[m_curr_coord ];
+
+ inc(m_curr_coord );
+
+ end
+ else
+ result:=path_cmd_stop;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_basics.pas b/src/corelib/render/software/agg_basics.pas
new file mode 100644
index 00000000..4d9cbe6d
--- /dev/null
+++ b/src/corelib/render/software/agg_basics.pas
@@ -0,0 +1,1679 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: added ptrcomp type + ptrcomp adjustments
+// 26.09.2005-Milano: Complete unit port
+//
+{ agg_basics.pas }
+unit
+ agg_basics ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+{$Q- }
+{$R- }
+
+uses
+ Math ;
+
+{ TYPES DEFINITION }
+type
+ agg_types = (
+
+ int8_type ,
+ int8u_type ,
+ int16_type ,
+ int16u_type ,
+ int32_type ,
+ int32u_type ,
+ int64_type ,
+ int64u_type
+
+ );
+
+ agg_type = (agg_int ,agg_unsigned ,agg_double );
+
+ AGG_INT8 = shortint;
+ AGG_INT8U = byte;
+
+ AGG_INT16 = smallint;
+ AGG_INT16U = word;
+
+ AGG_INT32 = longint;
+ AGG_INT32U = longword;
+
+ AGG_INT64 = int64;
+{$IFDEF FPC }
+ AGG_INT64U = qword;
+{$ELSE }
+ AGG_INT64U = int64;
+{$ENDIF }
+
+ int8 = AGG_INT8;
+ int8u = AGG_INT8U;
+ int16 = AGG_INT16;
+ int16u = AGG_INT16U;
+ int32 = AGG_INT32;
+ int32u = AGG_INT32U;
+ int64 = AGG_INT64;
+ int64u = AGG_INT64U;
+
+ int8_ptr = ^int8;
+ int8u_ptr = ^int8u;
+ int16_ptr = ^int16;
+ int16u_ptr = ^int16u;
+ int32_ptr = ^int32;
+ int32u_ptr = ^int32u;
+ int64_ptr = ^int64;
+ int64u_ptr = ^int64u;
+
+ int8u_ptr_ptr = ^int8u_ptr;
+
+ cover_type_ptr = ^cover_type;
+ cover_type = byte;
+
+ int_ptr = ^int;
+ int = int32;
+
+ unsigned_ptr = ^unsigned;
+ unsigned = int32u;
+
+ int8u_01_ptr = ^int8u_01;
+ int8u_01 = array[0..1 ] of int8u;
+
+ int16u_ = record
+ low ,
+ high : int8u;
+
+ end;
+
+ int32_ = record
+ low ,
+ high : int16;
+
+ end;
+
+ int32_int8u = record
+ _0 ,_1 ,_2 ,_3 : int8u;
+
+ end;
+
+ int32u_ = record
+ low ,
+ high : int16u;
+
+ end;
+
+{ To achive maximum compatiblity with older code, FPC doesn't change the size
+ of predefined data types like integer, longint or word when changing from
+ 32 to 64 Bit. However, the size of a pointer is 8 bytes on a 64 bit
+ architecture so constructs like longint(pointer(p)) are doomed to crash on
+ 64 bit architectures. However, to allow you to write portable code, the
+ FPC system unit introduces the types PtrInt and PtrUInt which are signed
+ and unsigned integer data types with the same size as a pointer.
+
+ Keep in mind that the size change of the "pointer" type also affects record
+ sizes. If you allocate records with fixed sizes, and not with new or with
+ getmem (<x>,sizeof(<x>)), this will have to be fixed. }
+// Pascal Pointer Computation Type
+{$IFDEF CPU64 }
+ ptrcomp = system.int64;
+
+{$ELSE }
+ ptrcomp = integer;
+
+{$ENDIF }
+
+// Pascal's pointer-in-an-array-access helper structures
+ p32_ptr = ^p32;
+ p32 = record
+ case integer of
+ 1 : (ptr : pointer );
+
+ {$IFDEF CPU64 }
+ 2 : (int : system.int64 );
+
+ {$ELSE }
+ 2 : (int : integer );
+
+ {$ENDIF }
+
+ end;
+
+ double_ptr_ptr = ^double_ptr;
+ double_ptr = ^double;
+
+ double_2_ptr = ^double_2;
+ double_2 = array[0..1 ] of double;
+
+ double_8_ptr = ^double_8;
+ double_8 = array[0..7 ] of double;
+
+ double_42_ptr = ^double_42;
+ double_42 = array[0..3 ,0..1 ] of double;
+
+ double_44_ptr = ^double_44;
+ double_44 = array[0..3 ,0..3 ] of double;
+
+ double_81_ptr = ^double_81;
+ double_81 = array[0..7 ,0..0 ] of double;
+
+ double_88_ptr = ^double_88;
+ double_88 = array[0..7 ,0..7 ] of double;
+
+ double_26_ptr = ^double_26;
+ double_26 = array[0..25 ] of double;
+
+ double_00_ptr = ^double_00;
+ double_00 = array of double;
+
+ char_ptr_ptr = ^char_ptr;
+ char_ptr = ^char;
+ pointer_ptr = ^pointer;
+
+ gamma_ptr = ^gamma;
+ gamma = object
+ function dir(v : unsigned ) : unsigned; virtual; abstract;
+ function inv(v : unsigned ) : unsigned; virtual; abstract;
+
+ end;
+
+ poly_subpixel_scale_e = int;
+
+ filling_rule_e = (fill_non_zero ,fill_even_odd );
+
+const
+// cover_scale_e
+ cover_shift = 8;
+ cover_size = 1 shl cover_shift;
+ cover_mask = cover_size - 1;
+ cover_none = 0;
+ cover_full = cover_mask;
+
+ pi : double = 3.14159265358979323846;
+
+// These constants determine the subpixel accuracy, to be more precise,
+// the number of bits of the fractional part of the coordinates.
+// The possible coordinate capacity in bits can be calculated by formula:
+// sizeof(int) * 8 - poly_subpixel_shift, i.e, for 32-bit integers and
+// 8-bits fractional part the capacity is 24 bits.
+ poly_subpixel_shift = 8; //----poly_subpixel_shift
+ poly_subpixel_scale = 1 shl poly_subpixel_shift; //----poly_subpixel_scale
+ poly_subpixel_mask = poly_subpixel_scale-1; //----poly_subpixel_mask
+
+// path_commands_e
+ path_cmd_stop = 0;
+ path_cmd_move_to = 1;
+ path_cmd_line_to = 2;
+ path_cmd_curve3 = 3;
+ path_cmd_curve4 = 4;
+ path_cmd_curveN = 5;
+ path_cmd_catrom = 6;
+ path_cmd_ubspline = 7;
+ path_cmd_end_poly = $0F;
+ path_cmd_mask = $0F;
+
+// path_flags_e
+ path_flags_none = 0;
+ path_flags_ccw = $10;
+ path_flags_cw = $20;
+ path_flags_close = $40;
+ path_flags_mask = $F0;
+
+type
+ rect_ptr = ^rect;
+ rect = object
+ x1 ,y1 ,x2 ,y2 : int;
+
+ constructor Construct; overload;
+ constructor Construct(x1_ ,y1_ ,x2_ ,y2_ : int ); overload;
+ constructor Construct(r : rect_ptr ); overload;
+
+ function normalize : rect_ptr;
+ function clip(r : rect_ptr ) : boolean;
+ function is_valid : boolean;
+
+ end;
+
+ rect_d_ptr = ^rect_d;
+ rect_d = object
+ x1 ,y1 ,x2 ,y2 : double;
+
+ constructor Construct; overload;
+ constructor Construct(x1_ ,y1_ ,x2_ ,y2_ : double ); overload;
+
+ function normalize : rect_d_ptr;
+ function clip(r : rect_d_ptr ) : boolean;
+ function is_valid : boolean;
+
+ end;
+
+ rect_i_ptr = ^rect_i;
+ rect_i = object
+ x1 ,y1 ,x2 ,y2 : int;
+
+ constructor Construct; overload;
+ constructor Construct(x1_ ,y1_ ,x2_ ,y2_ : int ); overload;
+
+ function clip(r : rect_i_ptr ) : boolean;
+
+ end;
+
+ point_type_ptr = ^point_type;
+ point_type = record
+ x ,y : double;
+
+ end;
+
+ vertex_type = object
+ x ,y : double;
+ cmd : byte;
+
+ constructor Construct; overload;
+ constructor Construct(x_ ,y_ : double; cmd_ : byte ); overload;
+
+ end;
+
+ unsigned_list_ptr = ^unsigned_list;
+ unsigned_list = object
+ function array_operator(idx : unsigned ) : unsigned; virtual; abstract;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+ function agg_getmem (var buf : pointer; sz : unsigned ) : boolean;
+ function agg_freemem(var buf : pointer; sz : unsigned ) : boolean;
+
+ function deg2rad(deg : double ) : double;
+ function rad2deg(rad : double ) : double;
+
+ procedure normalize_rect (var this : rect );
+ procedure normalize_rect_d(var this : rect_d );
+
+ function clip_rect (var this : rect; r : rect_ptr ) : boolean;
+ function clip_rect_d(var this : rect_d; r : rect_d_ptr ) : boolean;
+
+ function is_valid_rect (var this : rect ) : boolean;
+ function is_valid_rect_d(var this : rect_d ) : boolean;
+
+ function intersect_rectangles (r1 ,r2 : rect_ptr ) : rect;
+ function intersect_rectangles_d(r1 ,r2 : rect_d_ptr ) : rect_d;
+
+ function unite_rectangles (r1 ,r2 : rect_ptr ) : rect;
+ function unite_rectangles_d(r1 ,r2 : rect_d_ptr ) : rect_d;
+
+ function is_vertex (c : unsigned ) : boolean;
+ function is_drawing (c : unsigned ) : boolean;
+ function is_stop (c : unsigned ) : boolean;
+ function is_move (c : unsigned ) : boolean;
+ function is_line_to (c : unsigned ) : boolean;
+ function is_move_to (c : unsigned ) : boolean;
+ function is_curve (c : unsigned ) : boolean;
+ function is_curve3 (c : unsigned ) : boolean;
+ function is_curve4 (c : unsigned ) : boolean;
+ function is_end_poly (c : unsigned ) : boolean;
+ function is_close (c : unsigned ) : boolean;
+ function is_next_poly(c : unsigned ) : boolean;
+ function is_cw (c : unsigned ) : boolean;
+ function is_ccw (c : unsigned ) : boolean;
+ function is_oriented (c : unsigned ) : boolean;
+ function is_closed (c : unsigned ) : boolean;
+
+ function get_close_flag (c : unsigned ) : unsigned;
+ function clear_orientation(c : unsigned ) : unsigned;
+ function get_orientation (c : unsigned ) : unsigned;
+ function set_orientation (c ,o : unsigned ) : unsigned;
+
+ procedure swap_ptrs(a ,b : pointer );
+ procedure sprintf (dst : char_ptr; src : PChar; val : double );
+ function intdbl (i : int ) : double;
+
+ procedure srand_(seed : int );
+ function rand_ : int;
+
+ procedure srand(seed : int );
+ function rand : int;
+
+ function uround(v : double ) : int;
+ function iround(v : double ) : int;
+
+ function saturation_iround(Limit : int; v : double ) : int;
+
+// NoP = No Operation. It's the empty function, whose purpose is only for the
+// debugging, or for the piece of code where intentionaly nothing is planned
+// to be.
+ procedure NoP;
+
+// SHR for signed integers is differently implemented in pascal compilers
+// than in c++ compilers. On the assembler level, c++ is using the SAR and
+// pascal is using SHR. That gives completely different result, when the
+// number is negative. We have to be compatible with c++ implementation,
+// thus instead of directly using SHR we emulate c++ solution.
+ function shr_int8 (i ,shift : int8 ) : int8;
+ function shr_int16(i ,shift : int16 ) : int16;
+ function shr_int32(i ,shift : int ) : int;
+
+IMPLEMENTATION
+{ UNIT IMPLEMENTATION }
+{ agg_getmem }
+function agg_getmem;
+begin
+ result:=false;
+
+ try
+ getmem(buf ,sz );
+
+ result:=true;
+
+ except
+ buf:=NIL;
+
+ end;
+
+end;
+
+{ agg_freemem }
+function agg_freemem;
+begin
+ if buf = NIL then
+ result:=true
+
+ else
+ try
+ freemem(buf ,sz );
+
+ buf:=NIL;
+
+ result:=true;
+
+ except
+ result:=false;
+
+ end;
+
+end;
+
+{ deg2rad }
+function deg2rad;
+begin
+ result:=deg * pi / 180;
+
+end;
+
+{ rad2deg }
+function rad2deg;
+begin
+ result:=rad * 180 / pi;
+
+end;
+
+{ CONSTRUCT }
+constructor rect.Construct;
+begin
+ x1:=0;
+ y1:=0;
+ x2:=0;
+ y2:=0;
+
+end;
+
+{ CONSTRUCT }
+constructor rect.Construct(x1_ ,y1_ ,x2_ ,y2_ : int );
+begin
+ x1:=x1_;
+ y1:=y1_;
+ x2:=x2_;
+ y2:=y2_;
+
+end;
+
+{ CONSTRUCT }
+constructor rect.Construct(r : rect_ptr );
+begin
+ x1:=r.x1;
+ y1:=r.y1;
+ x2:=r.x2;
+ y2:=r.y2;
+
+end;
+
+{ NORMALIZE }
+function rect.normalize;
+var
+ t : int;
+
+begin
+ if x1 > x2 then
+ begin
+ t :=x1;
+ x1:=x2;
+ x2:=t;
+
+ end;
+
+ if y1 > y2 then
+ begin
+ t :=y1;
+ y1:=y2;
+ y2:=t;
+
+ end;
+
+ result:=@self;
+
+end;
+
+{ CLIP }
+function rect.clip;
+begin
+ if x2 > r.x2 then
+ x2:=r.x2;
+
+ if y2 > r.y2 then
+ y2:=r.y2;
+
+ if x1 < r.x1 then
+ x1:=r.x1;
+
+ if y1 < r.y1 then
+ y1:=r.y1;
+
+ result:=(x1 <= x2 ) and (y1 <= y2 );
+
+end;
+
+{ IS_VALID }
+function rect.is_valid;
+begin
+ result:=(x1 <= x2 ) and (y1 <= y2 );
+
+end;
+
+{ CONSTRUCT }
+constructor rect_d.Construct;
+begin
+ x1:=0;
+ y1:=0;
+ x2:=0;
+ y2:=0;
+
+end;
+
+{ CONSTRUCT }
+constructor rect_d.Construct(x1_ ,y1_ ,x2_ ,y2_ : double );
+begin
+ x1:=x1_;
+ y1:=y1_;
+ x2:=x2_;
+ y2:=y2_;
+
+end;
+
+{ NORMALIZE }
+function rect_d.normalize;
+var
+ t : double;
+
+begin
+ if x1 > x2 then
+ begin
+ t :=x1;
+ x1:=x2;
+ x2:=t;
+
+ end;
+
+ if y1 > y2 then
+ begin
+ t :=y1;
+ y1:=y2;
+ y2:=t;
+
+ end;
+
+ result:=@self;
+
+end;
+
+{ CLIP }
+function rect_d.clip;
+begin
+ if x2 > r.x2 then
+ x2:=r.x2;
+
+ if y2 > r.y2 then
+ y2:=r.y2;
+
+ if x1 < r.x1 then
+ x1:=r.x1;
+
+ if y1 < r.y1 then
+ y1:=r.y1;
+
+ result:=(x1 <= x2 ) and (y1 <= y2 );
+
+end;
+
+{ IS_VALID }
+function rect_d.is_valid;
+begin
+ result:=(x1 <= x2 ) and (y1 <= y2 );
+
+end;
+
+{ CONSTRUCT }
+constructor rect_i.Construct;
+begin
+ x1:=0;
+ y1:=0;
+ x2:=0;
+ y2:=0;
+
+end;
+
+{ CONSTRUCT }
+constructor rect_i.Construct(x1_ ,y1_ ,x2_ ,y2_ : int );
+begin
+ x1:=x1_;
+ y1:=y1_;
+ x2:=x2_;
+ y2:=y2_;
+
+end;
+
+{ CLIP }
+function rect_i.clip(r : rect_i_ptr ) : boolean;
+begin
+ if x2 > r.x2 then
+ x2:=r.x2;
+
+ if y2 > r.y2 then
+ y2:=r.y2;
+
+ if x1 < r.x1 then
+ x1:=r.x1;
+
+ if y1 < r.y1 then
+ y1:=r.y1;
+
+ result:=(x1 <= x2 ) and (y1 <= y2 );
+
+end;
+
+{ CONSTRUCT }
+constructor vertex_type.Construct;
+begin
+ x:=0;
+ y:=0;
+
+ cmd:=0;
+
+end;
+
+{ CONSTRUCT }
+constructor vertex_type.Construct(x_ ,y_ : double; cmd_ : byte );
+begin
+ x:=x_;
+ y:=y_;
+
+ cmd:=cmd_;
+
+end;
+
+{ normalize_rect }
+procedure normalize_rect(var this : rect );
+var
+ t : int;
+
+begin
+ if this.x1 > this.x2 then
+ begin
+ t :=this.x1;
+ this.x1:=this.x2;
+ this.x2:=t;
+
+ end;
+
+ if this.y1 > this.y2 then
+ begin
+ t :=this.y1;
+ this.y1:=this.y2;
+ this.y2:=t;
+
+ end;
+
+end;
+
+{ normalize_rect_d }
+procedure normalize_rect_d(var this : rect_d );
+var
+ t : double;
+
+begin
+ if this.x1 > this.x2 then
+ begin
+ t :=this.x1;
+ this.x1:=this.x2;
+ this.x2:=t;
+
+ end;
+
+ if this.y1 > this.y2 then
+ begin
+ t :=this.y1;
+ this.y1:=this.y2;
+ this.y2:=t;
+
+ end;
+
+end;
+
+{ clip_rect }
+function clip_rect(var this : rect; r : rect_ptr ) : boolean;
+begin
+ if this.x2 > r.x2 then
+ this.x2:=r.x2;
+
+ if this.y2 > r.y2 then
+ this.y2:=r.y2;
+
+ if this.x1 < r.x1 then
+ this.x1:=r.x1;
+
+ if this.y1 < r.y1 then
+ this.y1:=r.y1;
+
+ result:=(this.x1 <= this.x2 ) and (this.y1 <= this.y2 );
+
+end;
+
+{ clip_rect_d }
+function clip_rect_d(var this : rect_d; r : rect_d_ptr ) : boolean;
+begin
+ if this.x2 > r.x2 then
+ this.x2:=r.x2;
+
+ if this.y2 > r.y2 then
+ this.y2:=r.y2;
+
+ if this.x1 < r.x1 then
+ this.x1:=r.x1;
+
+ if this.y1 < r.y1 then
+ this.y1:=r.y1;
+
+ result:=(this.x1 <= this.x2 ) and (this.y1 <= this.y2 );
+
+end;
+
+{ is_valid_rect }
+function is_valid_rect(var this : rect ) : boolean;
+begin
+ result:=(this.x1 <= this.x2 ) and (this.y1 <= this.y2 );
+
+end;
+
+{ is_valid_rect_d }
+function is_valid_rect_d(var this : rect_d ) : boolean;
+begin
+ result:=(this.x1 <= this.x2 ) and (this.y1 <= this.y2 );
+
+end;
+
+{ intersect_rectangles }
+function intersect_rectangles(r1 ,r2 : rect_ptr ) : rect;
+begin
+ result:=r1^;
+
+ if result.x2 > r2.x2 then
+ result.x2:=r2.x2;
+
+ if result.y2 > r2.y2 then
+ result.y2:=r2.y2;
+
+ if result.x1 < r2.x1 then
+ result.x1:=r2.x1;
+
+ if result.y1 < r2.y1 then
+ result.y1:=r2.y1;
+
+end;
+
+{ intersect_rectangles_d }
+function intersect_rectangles_d(r1 ,r2 : rect_d_ptr ) : rect_d;
+begin
+ result:=r1^;
+
+ if result.x2 > r2.x2 then
+ result.x2:=r2.x2;
+
+ if result.y2 > r2.y2 then
+ result.y2:=r2.y2;
+
+ if result.x1 < r2.x1 then
+ result.x1:=r2.x1;
+
+ if result.y1 < r2.y1 then
+ result.y1:=r2.y1;
+
+end;
+
+{ unite_rectangles }
+function unite_rectangles(r1 ,r2 : rect_ptr ) : rect;
+begin
+ result:=r1^;
+
+ if result.x2 < r2.x2 then
+ result.x2:=r2.x2;
+
+ if result.y2 < r2.y2 then
+ result.y2:=r2.y2;
+
+ if result.x1 > r2.x1 then
+ result.x1:=r2.x1;
+
+ if result.y1 > r2.y1 then
+ result.y1:=r2.y1;
+
+end;
+
+{ unite_rectangles_d }
+function unite_rectangles_d(r1 ,r2 : rect_d_ptr ) : rect_d;
+begin
+ result:=r1^;
+
+ if result.x2 < r2.x2 then
+ result.x2:=r2.x2;
+
+ if result.y2 < r2.y2 then
+ result.y2:=r2.y2;
+
+ if result.x1 > r2.x1 then
+ result.x1:=r2.x1;
+
+ if result.y1 > r2.y1 then
+ result.y1:=r2.y1;
+
+end;
+
+{ is_vertex }
+function is_vertex;
+begin
+ result:=(c >= path_cmd_move_to ) and (c < path_cmd_end_poly );
+
+end;
+
+{ is_drawing }
+function is_drawing;
+begin
+ result:=(c >= path_cmd_line_to ) and (c < path_cmd_end_poly );
+
+end;
+
+{ is_stop }
+function is_stop;
+begin
+ result:=(c = path_cmd_stop );
+
+end;
+
+{ is_move }
+function is_move;
+begin
+ result:=(c = path_cmd_move_to );
+
+end;
+
+{ is_line_to }
+function is_line_to;
+begin
+ result:=(c = path_cmd_line_to );
+
+end;
+
+{ is_move_to }
+function is_move_to;
+begin
+ result:=(c = path_cmd_move_to );
+
+end;
+
+{ is_curve }
+function is_curve;
+begin
+ result:=(c = path_cmd_curve3 ) or (c = path_cmd_curve4 );
+
+end;
+
+{ is_curve3 }
+function is_curve3;
+begin
+ result:=(c = path_cmd_curve3 );
+
+end;
+
+{ is_curve4 }
+function is_curve4;
+begin
+ result:=(c = path_cmd_curve4 );
+
+end;
+
+{ is_end_poly }
+function is_end_poly;
+begin
+ result:=((c and path_cmd_mask ) = path_cmd_end_poly );
+
+end;
+
+{ is_close }
+function is_close;
+begin
+ result:=
+ (c and not(path_flags_cw or path_flags_ccw ) ) =
+ (path_cmd_end_poly or path_flags_close )
+
+end;
+
+{ is_next_poly }
+function is_next_poly;
+begin
+ result:=is_stop(c ) or is_move_to(c ) or is_end_poly(c );
+
+end;
+
+{ is_cw }
+function is_cw;
+begin
+ result:=not((c and path_flags_cw ) = 0 );
+
+end;
+
+{ is_ccw }
+function is_ccw;
+begin
+ result:=not((c and path_flags_ccw ) = 0 );
+
+end;
+
+{ is_oriented }
+function is_oriented;
+begin
+ result:=not((c and (path_flags_cw or path_flags_ccw ) ) = 0 );
+
+end;
+
+{ is_closed }
+function is_closed;
+begin
+ result:=not((c and path_flags_close ) = 0 );
+
+end;
+
+{ get_close_flag }
+function get_close_flag;
+begin
+ result:=c and path_flags_close;
+
+end;
+
+{ clear_orientation }
+function clear_orientation;
+begin
+ result:=c and not(path_flags_cw or path_flags_ccw );
+
+end;
+
+{ get_orientation }
+function get_orientation;
+begin
+ result:=c and (path_flags_cw or path_flags_ccw );
+
+end;
+
+{ set_orientation }
+function set_orientation;
+begin
+ result:=clear_orientation(c ) or o;
+
+end;
+
+{ swap_ptrs }
+procedure swap_ptrs;
+var
+ temp : pointer;
+
+begin
+ temp:=p32_ptr(a ).ptr;
+
+ p32_ptr(a ).ptr:=p32_ptr(b ).ptr;
+ p32_ptr(b ).ptr:=temp;
+
+end;
+
+{ MAKESTR }
+function MakeStr(ch : char; sz : byte ) : shortstring;
+begin
+ result[0 ]:=char(sz );
+
+ fillchar(result[1 ] ,sz ,ch );
+
+end;
+
+{ BACKLEN }
+function BackLen(s : shortstring; sz : byte ) : shortstring;
+type
+ tSCAN = (
+
+ SCAN_0 ,
+ SCAN_1 ,SCAN_2 ,SCAN_3 ,SCAN_4 ,SCAN_5 ,SCAN_6 ,SCAN_7 ,SCAN_8 ,SCAN_9 ,
+ SCAN_A ,SCAN_B ,SCAN_C ,SCAN_D ,SCAN_E ,SCAN_F ,SCAN_G ,SCAN_H ,SCAN_I ,
+ SCAN_J ,SCAN_K ,SCAN_L ,SCAN_M ,SCAN_N ,SCAN_O ,SCAN_P ,SCAN_Q ,SCAN_R ,
+ SCAN_S ,SCAN_T ,SCAN_U ,SCAN_V ,SCAN_W ,SCAN_X ,SCAN_Y ,SCAN_Z
+
+ );
+
+var
+ pos ,
+ wcb : byte;
+ scn : tSCAN;
+
+begin
+ result:='';
+
+ wcb:=sz;
+ pos:=length(s );
+ scn:=SCAN_1;
+
+ while wcb > 0 do
+ begin
+ case scn of
+ SCAN_1 :
+ if pos > 0 then
+ begin
+ result:=s[pos ] + result;
+
+ dec(pos );
+
+ end
+ else
+ begin
+ scn:=SCAN_2;
+
+ result:=' ' + result;
+
+ end;
+
+ SCAN_2 :
+ result:=' ' + result;
+
+ end;
+
+ dec(wcb );
+
+ end;
+
+end;
+
+{ INTHEX }
+function IntHex(i : int64; max : byte = 0; do_low : boolean = false ) : shortstring;
+type
+ tITEM = (
+
+ ITEM_0 ,
+ ITEM_1 ,ITEM_2 ,ITEM_3 ,ITEM_4 ,ITEM_5 ,ITEM_6 ,ITEM_7 ,ITEM_8 ,ITEM_9 ,
+ ITEM_A ,ITEM_B ,ITEM_C ,ITEM_D ,ITEM_E ,ITEM_F ,ITEM_G ,ITEM_H ,ITEM_I ,
+ ITEM_J ,ITEM_K ,ITEM_L ,ITEM_M ,ITEM_N ,ITEM_O ,ITEM_P ,ITEM_Q ,ITEM_R ,
+ ITEM_S ,ITEM_T ,ITEM_U ,ITEM_V ,ITEM_W ,ITEM_X ,ITEM_Y ,ITEM_Z
+
+ );
+
+var
+ str : shortstring;
+ itm : tITEM;
+ fcb : byte;
+
+const
+ low : array[0..$f ] of char = '0123456789abcdef';
+ hex : array[0..$f ] of char = '0123456789ABCDEF';
+
+begin
+ if do_low then
+ str:=
+ low[i shr 60 and 15 ] +
+ low[i shr 56 and 15 ] +
+ low[i shr 52 and 15 ] +
+ low[i shr 48 and 15 ] +
+ low[i shr 44 and 15 ] +
+ low[i shr 40 and 15 ] +
+ low[i shr 36 and 15 ] +
+ low[i shr 32 and 15 ] +
+
+ low[i shr 28 and 15 ] +
+ low[i shr 24 and 15 ] +
+ low[i shr 20 and 15 ] +
+ low[i shr 16 and 15 ] +
+ low[i shr 12 and 15 ] +
+ low[i shr 8 and 15 ] +
+ low[i shr 4 and 15 ] +
+ low[i and 15 ]
+ else
+ str:=
+ hex[i shr 60 and 15 ] +
+ hex[i shr 56 and 15 ] +
+ hex[i shr 52 and 15 ] +
+ hex[i shr 48 and 15 ] +
+ hex[i shr 44 and 15 ] +
+ hex[i shr 40 and 15 ] +
+ hex[i shr 36 and 15 ] +
+ hex[i shr 32 and 15 ] +
+
+ hex[i shr 28 and 15 ] +
+ hex[i shr 24 and 15 ] +
+ hex[i shr 20 and 15 ] +
+ hex[i shr 16 and 15 ] +
+ hex[i shr 12 and 15 ] +
+ hex[i shr 8 and 15 ] +
+ hex[i shr 4 and 15 ] +
+ hex[i and 15 ];
+
+ if max > 0 then
+ if length(str ) > max then
+ result:=BackLen(str ,max )
+ else
+ if length(str ) < max then
+ result:=MakeStr('0' ,max - length(str ) ) + str
+ else
+ result:=str
+
+ else
+ begin
+ result:='';
+
+ itm:=ITEM_1;
+
+ for fcb:=1 to length(str ) do
+ case itm of
+ ITEM_1 :
+ case str[fcb ] of
+ '0' :
+ else
+ begin
+ result:=str[fcb ];
+
+ itm:=ITEM_2;
+
+ end;
+
+ end;
+
+ ITEM_2 :
+ result:=result + str[fcb ];
+
+ end;
+
+ if result = '' then
+ result:='0';
+
+ end;
+
+end;
+
+{ SPRINTF }
+procedure sprintf;
+type
+ scan = (_string ,_flags ,_width ,_precision ,_prefix ,_type );
+
+var
+ sc : scan;
+ nt ,
+ fr : integer;
+
+ get : shortstring;
+ flg : char;
+ dth ,
+ prc ,
+ err : integer;
+ prf : array[0..3 ] of char;
+ typ : char;
+
+{ apply }
+procedure apply;
+var
+ i ,x : int;
+
+ add : shortstring;
+
+begin
+ add:='';
+
+ case typ of
+ 'X' :
+ begin
+ if dth = 1 then
+ dth:=0;
+
+ add:=IntHex(trunc(val ) ,dth ,false );
+
+ end;
+
+ 'x' :
+ begin
+ if dth = 1 then
+ dth:=0;
+
+ add:=IntHex(trunc(val ) ,dth ,true );
+
+ end;
+
+ 's' :
+ add:=PChar(trunc(val ) );
+
+ 'u' ,'d' :
+ begin
+ str(nt ,get );
+
+ while length(get ) < dth do
+ get:='0' + get;
+
+ add:=get;
+
+ end;
+
+ 'f' :
+ begin
+ str(nt ,get );
+
+ while length(get ) < dth do
+ get:=' ' + get;
+
+ add:=get;
+
+ if prc > 0 then
+ begin
+ x:=1;
+
+ for i:=1 to prc do
+ x:=x * 10;
+
+ fr:=Abs(trunc(system.frac(val ) * x ) );
+
+ str(fr ,get );
+
+ while length(get ) < prc do
+ get:='0' + get;
+
+ add:=add + '.' + get;
+
+ end;
+
+ if (val < 0 ) and
+ (add[1 ] <> '-' ) then
+ add:='-' + add;
+
+ end;
+
+ end;
+
+ err:=0;
+
+ while err < length(add ) do
+ begin
+ dst^:=add[err + 1 ];
+
+ inc(ptrcomp(dst ) );
+ inc(err );
+
+ end;
+
+ sc:=_string;
+
+end;
+
+begin
+ nt:=trunc(system.int (val ) );
+ fr:=trunc(system.frac(val ) );
+ sc:=_string;
+
+ flg:=#0;
+ dth:=1;
+ prc:=0;
+ prf:=#0;
+ typ:='s';
+
+ while src^ <> #0 do
+ begin
+ case sc of
+ { Copy Text or expect % }
+ _string :
+ case src^ of
+ '%' :
+ sc:=_flags;
+
+ else
+ begin
+ dst^:=src^;
+
+ inc(ptrcomp(dst ) );
+
+ end;
+
+ end;
+
+ { Flags }
+ _flags :
+ case src^ of
+ '-' ,'+' ,'0' ,' ' ,'#' :
+ flg:=src^;
+
+ '1'..'9' :
+ begin
+ get:=src^;
+ sc :=_width;
+
+ end;
+
+ '.' :
+ begin
+ get:='';
+ sc :=_precision;
+
+ end;
+
+ 'h' ,'l' :
+ begin
+ prf[0 ]:=src^;
+ prf[3 ]:=#1;
+
+ sc:=_type;
+
+ end;
+
+ 'I' :
+ begin
+ prf[0 ]:=src^;
+ prf[3 ]:=#1;
+
+ sc:=_prefix;
+
+ end;
+
+ 'c' ,'C' ,'d' ,'i' ,'o' ,'u' ,'x' ,'X' ,'e' ,'E' ,'f' ,'g' ,'G' ,'n' ,'p' ,'s' ,'S' :
+ begin
+ typ:=src^;
+
+ apply;
+
+ end;
+
+ else
+ begin
+ dst^:=src^;
+
+ inc(ptrcomp(dst ) );
+
+ sc:=_string;
+
+ end;
+
+ end;
+
+ { Width }
+ _width :
+ case src^ of
+ '0' ,'1'..'9' :
+ get:=get + src^;
+
+ else
+ begin
+ system.val(get ,dth ,err );
+
+ case src^ of
+ '.' :
+ begin
+ get:='';
+ sc :=_precision;
+
+ end;
+
+ 'h' ,'l' :
+ begin
+ prf[0 ]:=src^;
+ prf[3 ]:=#1;
+
+ sc:=_type;
+
+ end;
+
+ 'I' :
+ begin
+ prf[0 ]:=src^;
+ prf[3 ]:=#1;
+
+ sc:=_prefix;
+
+ end;
+
+ 'c' ,'C' ,'d' ,'i' ,'o' ,'u' ,'x' ,'X' ,'e' ,'E' ,'f' ,'g' ,'G' ,'n' ,'p' ,'s' ,'S' :
+ begin
+ typ:=src^;
+
+ apply;
+
+ end;
+
+ else
+ sc:=_string;
+
+ end;
+
+ end;
+
+ end;
+
+ { Precision }
+ _precision :
+ case src^ of
+ '0' ,'1'..'9' :
+ get:=get + src^;
+
+ else
+ begin
+ system.val(get ,prc ,err );
+
+ case src^ of
+ 'h' ,'l' :
+ begin
+ prf[0 ]:=src^;
+ prf[3 ]:=#1;
+
+ sc:=_type;
+
+ end;
+
+ 'I' :
+ begin
+ prf[0 ]:=src^;
+ prf[3 ]:=#1;
+
+ sc:=_prefix;
+
+ end;
+
+ 'c' ,'C' ,'d' ,'i' ,'o' ,'u' ,'x' ,'X' ,'e' ,'E' ,'f' ,'g' ,'G' ,'n' ,'p' ,'s' ,'S' :
+ begin
+ typ:=src^;
+
+ apply;
+
+ end;
+
+ else
+ sc:=_string;
+
+ end;
+
+ end;
+
+ end;
+
+ { Prefix }
+ _prefix :
+ if prf[3 ] = #1 then
+ case src^ of
+ '3' ,'6' :
+ begin
+ prf[1 ]:=src^;
+ prf[3 ]:=#2;
+
+ end;
+
+ 'c' ,'C' ,'d' ,'i' ,'o' ,'u' ,'x' ,'X' ,'e' ,'E' ,'f' ,'g' ,'G' ,'n' ,'p' ,'s' ,'S' :
+ begin
+ typ:=src^;
+
+ apply;
+
+ end;
+
+ else
+ sc:=_string;
+
+ end
+ else
+ if prf[3 ] = #2 then
+ case src^ of
+ '2' ,'4' :
+ begin
+ prf[2 ]:=src^;
+ prf[3 ]:=#3;
+
+ sc:=_type;
+
+ end;
+
+ 'c' ,'C' ,'d' ,'i' ,'o' ,'u' ,'x' ,'X' ,'e' ,'E' ,'f' ,'g' ,'G' ,'n' ,'p' ,'s' ,'S' :
+ begin
+ typ:=src^;
+
+ apply;
+
+ end;
+
+ else
+ sc:=_string;
+
+ end
+ else
+ sc:=_string;
+
+ { Type }
+ _type :
+ case src^ of
+ 'c' ,'C' ,'d' ,'i' ,'o' ,'u' ,'x' ,'X' ,'e' ,'E' ,'f' ,'g' ,'G' ,'n' ,'p' ,'s' ,'S' :
+ begin
+ typ:=src^;
+
+ apply;
+
+ end;
+
+ else
+ sc:=_string;
+
+ end;
+
+ end;
+
+ inc(ptrcomp(src ) );
+
+ end;
+
+ dst^:=#0;
+
+end;
+
+{ INTDBL }
+function intdbl;
+begin
+ result:=i;
+
+end;
+
+{ SRAND_ }
+procedure srand_(seed : int );
+begin
+ system.RandSeed:=seed;
+
+end;
+
+{ RAND_ }
+// Generates a pseudorandom number
+function rand_ : int;
+begin
+ result:=system.Random($7fff )
+
+end;
+
+var
+ g_holdrand : int = 1;
+
+{ SRAND }
+procedure srand(seed : int );
+begin
+ g_holdrand:=seed;
+
+end;
+
+{ RAND }
+function rand : int;
+begin
+ g_holdrand:=g_holdrand * 214013 + 2531011;
+
+ result:=(shr_int32(g_holdrand ,16 ) and $7fff );
+
+end;
+
+{ UROUND }
+function uround(v : double ) : int;
+begin
+ result:=unsigned(Trunc(v + 0.5 ) );
+
+end;
+
+{ IROUND }
+function iround(v : double ) : int;
+begin
+ if v < 0.0 then
+ result:=int(Trunc(v - 0.5 ) )
+ else
+ result:=int(Trunc(v + 0.5 ) );
+
+end;
+
+{ SATURATION_IROUND }
+function saturation_iround(Limit : int; v : double ) : int;
+begin
+ if v < -Limit then
+ result:=-Limit
+ else
+ if v > Limit then
+ result:=Limit
+ else
+ result:=iround(v );
+
+end;
+
+{ NoP }
+procedure NoP;
+begin
+end;
+
+{ SHR_INT8 }
+function shr_int8;
+begin
+{$IFDEF AGG_CPU_386 }
+ asm
+ mov al ,byte ptr [i ]
+ mov cl ,byte ptr [shift ]
+ sar al ,cl
+ mov byte ptr [result ] ,al
+
+ end;
+
+{$ENDIF }
+
+{$IFDEF AGG_CPU_PPC }
+ asm
+ lbz r2,i
+ extsb r2,r2
+ lbz r3,shift
+ extsb r3,r3
+ sraw r2,r2,r3
+ extsb r2,r2
+ stb r2,result
+
+ end;
+
+{$ENDIF }
+
+end;
+
+{ SHR_INT16 }
+function shr_int16;
+begin
+{$IFDEF AGG_CPU_386 }
+ asm
+ mov ax ,word ptr [i ]
+ mov cx ,word ptr [shift ]
+ sar ax ,cl
+ mov word ptr [result ] ,ax
+
+ end;
+
+{$ENDIF }
+
+{$IFDEF AGG_CPU_PPC }
+ asm
+ lha r2,i
+ lha r3,shift
+ sraw r2,r2,r3
+ extsh r2,r2
+ sth r2,result
+
+ end;
+
+{$ENDIF }
+
+end;
+
+{ SHR_INT32 }
+function shr_int32;
+begin
+{$IFDEF AGG_CPU_386 }
+ asm
+ mov eax ,dword ptr [i ]
+ mov ecx ,dword ptr [shift ]
+ sar eax ,cl
+ mov dword ptr [result ] ,eax
+
+ end;
+
+{$ENDIF }
+
+{$IFDEF AGG_CPU_PPC }
+ asm
+ lwz r3,i
+ lwz r2,shift
+ sraw r3,r3,r2
+ stw r3,result
+
+ end;
+
+{$ENDIF }
+
+end;
+
+END.
+
+
diff --git a/src/corelib/render/software/agg_bezier_arc.pas b/src/corelib/render/software/agg_bezier_arc.pas
new file mode 100644
index 00000000..e356ad04
--- /dev/null
+++ b/src/corelib/render/software/agg_bezier_arc.pas
@@ -0,0 +1,507 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// Arc generator. Produces at most 4 consecutive cubic bezier curves, i.e.,
+// 4, 7, 10, or 13 vertices.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 18.12.2005-Milano: Unit port establishment
+//
+{ agg_bezier_arc.pas }
+unit
+ agg_bezier_arc ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ Math ,
+ agg_basics ,
+ agg_vertex_source ,
+ agg_trans_affine ;
+
+{ TYPES DEFINITION }
+type
+ bezier_arc_ptr = ^bezier_arc;
+ bezier_arc = object(vertex_source )
+ m_vertex ,
+ m_num_vertices : unsigned;
+
+ m_vertices : double_26;
+
+ m_cmd : unsigned;
+
+ constructor Construct; overload;
+ constructor Construct(x ,y ,rx ,ry ,start_angle ,sweep_angle : double ); overload;
+
+ procedure init(x ,y ,rx ,ry ,start_angle ,sweep_angle : double );
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ // Supplemantary functions. num_vertices() actually returns doubled
+ // number of vertices. That is, for 1 vertex it returns 2.
+ function num_vertices : unsigned;
+ function vertices : double_26_ptr;
+
+ end;
+
+//==========================================================bezier_arc_svg
+// Compute an SVG-style bezier arc.
+//
+// Computes an elliptical arc from (x1, y1) to (x2, y2). The size and
+// orientation of the ellipse are defined by two radii (rx, ry)
+// and an x-axis-rotation, which indicates how the ellipse as a whole
+// is rotated relative to the current coordinate system. The center
+// (cx, cy) of the ellipse is calculated automatically to satisfy the
+// constraints imposed by the other parameters.
+// large-arc-flag and sweep-flag contribute to the automatic calculations
+// and help determine how the arc is drawn.
+ bezier_arc_svg_ptr = ^bezier_arc_svg;
+ bezier_arc_svg = object(bezier_arc )
+ m_radii_ok : boolean;
+
+ constructor Construct; overload;
+ constructor Construct(x1 ,y1 ,rx ,ry ,angle : double; large_arc_flag ,sweep_flag : boolean; x2 ,y2 : double ); overload;
+
+ procedure init(x0 ,y0 ,rx ,ry ,angle : double; large_arc_flag ,sweep_flag : boolean; x2 ,y2 : double );
+
+ function radii_ok : boolean;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+ procedure arc_to_bezier(cx ,cy ,rx ,ry ,start_angle ,sweep_angle : double; curve : double_8_ptr );
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+const
+ bezier_arc_angle_epsilon = 0.01;
+
+{ UNIT IMPLEMENTATION }
+{ ARC_TO_BEZIER }
+procedure arc_to_bezier;
+var
+ i : unsigned;
+
+ sn ,cs ,
+ x0 ,y0 ,
+ tx ,ty : double;
+ px ,py : array[0..3 ] of double;
+
+begin
+ x0:=Cos(sweep_angle / 2.0 );
+ y0:=Sin(sweep_angle / 2.0 );
+ tx:=(1.0 - x0 ) * 4.0 / 3.0;
+ ty:=y0 - tx * x0 / y0;
+
+ px[0 ]:=x0;
+ py[0 ]:=-y0;
+ px[1 ]:=x0 + tx;
+ py[1 ]:=-ty;
+ px[2 ]:=x0 + tx;
+ py[2 ]:=ty;
+ px[3 ]:=x0;
+ py[3 ]:=y0;
+
+ sn:=Sin(start_angle + sweep_angle / 2.0 );
+ cs:=Cos(start_angle + sweep_angle / 2.0 );
+
+ for i:=0 to 3 do
+ begin
+ curve[i * 2 ] :=cx + rx * (px[i ] * cs - py[i ] * sn );
+ curve[i * 2 + 1 ]:=cy + ry * (px[i ] * sn + py[i ] * cs );
+
+ end;
+
+end;
+
+{ CONSTRUCT }
+constructor bezier_arc.Construct;
+begin
+ m_vertex:=26;
+
+ m_num_vertices:=0;
+
+ m_cmd:=path_cmd_line_to;
+
+end;
+
+{ CONSTRUCT }
+constructor bezier_arc.Construct(x ,y ,rx ,ry ,start_angle ,sweep_angle : double );
+begin
+ init(x ,y ,rx ,ry ,start_angle ,sweep_angle );
+
+end;
+
+{ INIT }
+procedure bezier_arc.init;
+var
+ i : int;
+ f : double;
+
+ total_sweep ,
+ local_sweep ,
+ prev_sweep : double;
+
+ done : boolean;
+
+begin
+ i:=trunc(start_angle / (2.0 * pi ) );
+ f:=start_angle - (i * 2.0 * pi );
+
+ start_angle:=f;
+
+ if sweep_angle >= 2.0 * pi then
+ sweep_angle:=2.0 * pi;
+
+ if sweep_angle <= -2.0 * pi then
+ sweep_angle:=-2.0 * pi;
+
+ if Abs(sweep_angle ) < 1e-10 then
+ begin
+ m_num_vertices:=4;
+
+ m_cmd:=path_cmd_line_to;
+
+ m_vertices[0 ]:=x + rx * Cos(start_angle );
+ m_vertices[1 ]:=y + ry * Sin(start_angle );
+ m_vertices[2 ]:=x + rx * Cos(start_angle + sweep_angle );
+ m_vertices[3 ]:=y + ry * Sin(start_angle + sweep_angle );
+
+ exit;
+
+ end;
+
+ total_sweep:=0.0;
+ local_sweep:=0.0;
+
+ m_num_vertices:=2;
+
+ m_cmd:=path_cmd_curve4;
+ done :=false;
+
+ repeat
+ if sweep_angle < 0.0 then
+ begin
+ prev_sweep :=total_sweep;
+ local_sweep:=-pi * 0.5;
+ total_sweep:=total_sweep - (pi * 0.5 );
+
+ if total_sweep <= sweep_angle + bezier_arc_angle_epsilon then
+ begin
+ local_sweep:=sweep_angle - prev_sweep;
+
+ done:=true;
+
+ end;
+
+ end
+ else
+ begin
+ prev_sweep :=total_sweep;
+ local_sweep:=pi * 0.5;
+ total_sweep:=total_sweep + (pi * 0.5 );
+
+ if total_sweep >= sweep_angle - bezier_arc_angle_epsilon then
+ begin
+ local_sweep:=sweep_angle - prev_sweep;
+
+ done:=true;
+
+ end;
+
+ end;
+
+ arc_to_bezier(
+ x ,y ,rx ,ry ,
+ start_angle ,local_sweep ,
+ @m_vertices[m_num_vertices - 2 ] );
+
+ m_num_vertices:=m_num_vertices + 6;
+ start_angle :=start_angle + local_sweep;
+
+ until done or (m_num_vertices >= 26 );
+
+end;
+
+{ REWIND }
+procedure bezier_arc.rewind;
+begin
+ m_vertex:=0;
+
+end;
+
+{ VERTEX }
+function bezier_arc.vertex;
+begin
+ if m_vertex >= m_num_vertices then
+ begin
+ result:=path_cmd_stop;
+
+ exit;
+
+ end;
+
+ x^:=m_vertices[m_vertex ];
+ y^:=m_vertices[m_vertex + 1 ];
+
+ inc(m_vertex ,2 );
+
+ if m_vertex = 2 then
+ result:=path_cmd_move_to
+ else
+ result:=m_cmd;
+
+end;
+
+{ NUM_VERTICES }
+function bezier_arc.num_vertices;
+begin
+ result:=m_num_vertices;
+
+end;
+
+{ VERTICES }
+function bezier_arc.vertices;
+begin
+ result:=@m_vertices;
+
+end;
+
+{ CONSTRUCT }
+constructor bezier_arc_svg.Construct;
+begin
+ inherited Construct;
+
+ m_radii_ok:=false;
+
+end;
+
+{ CONSTRUCT }
+constructor bezier_arc_svg.Construct(x1 ,y1 ,rx ,ry ,angle : double; large_arc_flag ,sweep_flag : boolean; x2 ,y2 : double );
+begin
+ inherited Construct;
+
+ m_radii_ok:=false;
+
+ init(x1 ,y1 ,rx ,ry ,angle ,large_arc_flag ,sweep_flag ,x2 ,y2 );
+
+end;
+
+{ INIT }
+procedure bezier_arc_svg.init;
+var
+ i : unsigned;
+
+ v ,
+ p , n ,
+
+ sq ,
+ x1 ,y1 ,
+ cx ,cy ,
+ ux ,uy ,
+ vx ,vy ,
+
+ dx2 ,dy2 ,
+ prx ,pry ,
+ px1 ,py1 ,
+ cx1 ,cy1 ,
+ sx2 ,sy2 ,
+
+ sign ,coef ,
+
+ radii_check ,
+ start_angle ,
+ sweep_angle ,
+
+ cos_a ,sin_a : double;
+
+ mtx : trans_affine_rotation;
+ trn : trans_affine_translation;
+
+begin
+ m_radii_ok:=true;
+
+ if rx < 0.0 then
+ rx:=-rx;
+
+ if ry < 0.0 then
+ ry:=-rx;
+
+// Calculate the middle point between
+// the current and the final points
+ dx2:=(x0 - x2 ) / 2.0;
+ dy2:=(y0 - y2 ) / 2.0;
+
+// Convert angle from degrees to radians
+ cos_a:=Cos(angle );
+ sin_a:=Sin(angle );
+
+// Calculate (x1, y1)
+ x1:= cos_a * dx2 + sin_a * dy2;
+ y1:=-sin_a * dx2 + cos_a * dy2;
+
+// Ensure radii are large enough
+ prx:=rx * rx;
+ pry:=ry * ry;
+ px1:=x1 * x1;
+ py1:=y1 * y1;
+
+// Check that radii are large enough
+ radii_check:=px1 / prx + py1 / pry;
+
+ if radii_check > 1.0 then
+ begin
+ rx :=sqrt(radii_check ) * rx;
+ ry :=sqrt(radii_check ) * ry;
+ prx:=rx * rx;
+ pry:=ry * ry;
+
+ if radii_check > 10.0 then
+ m_radii_ok:=false;
+
+ end;
+
+// Calculate (cx1, cy1)
+ if large_arc_flag = sweep_flag then
+ sign:=-1.0
+ else
+ sign:=1.0;
+
+ sq:=(prx * pry - prx * py1 - pry * px1 ) / (prx * py1 + pry * px1 );
+
+ if sq < 0 then
+ coef:=sign * sqrt(0 )
+ else
+ coef:=sign * sqrt(sq );
+
+ cx1:=coef * ((rx * y1 ) / ry );
+ cy1:=coef * -((ry * x1 ) / rx );
+
+// Calculate (cx, cy) from (cx1, cy1)
+ sx2:=(x0 + x2 ) / 2.0;
+ sy2:=(y0 + y2 ) / 2.0;
+ cx :=sx2 + (cos_a * cx1 - sin_a * cy1 );
+ cy :=sy2 + (sin_a * cx1 + cos_a * cy1 );
+
+// Calculate the start_angle (angle1) and the sweep_angle (dangle)
+ ux:= (x1 - cx1 ) / rx;
+ uy:= (y1 - cy1 ) / ry;
+ vx:=(-x1 - cx1 ) / rx;
+ vy:=(-y1 - cy1 ) / ry;
+
+// Calculate the angle start
+ n:=sqrt(ux * ux + uy * uy );
+ p:=ux; // (1 * ux ) + (0 * uy )
+
+ if uy < 0 then
+ sign:=-1.0
+ else
+ sign:=1.0;
+
+ v:=p / n;
+
+ if v < -1.0 then
+ v:=-1.0;
+
+ if v > 1.0 then
+ v:=1.0;
+
+ start_angle:=sign * ArcCos(v );
+
+// Calculate the sweep angle
+ n:=sqrt((ux * ux + uy * uy ) * (vx * vx + vy * vy ) );
+ p:=ux * vx + uy * vy;
+
+ if ux * vy - uy * vx < 0 then
+ sign:=-1.0
+ else
+ sign:=1.0;
+
+ v:=p / n;
+
+ if v < -1.0 then
+ v:=-1.0;
+
+ if v > 1.0 then
+ v:=1.0;
+
+ sweep_angle:=sign * ArcCos(v );
+
+ if (not sweep_flag ) and
+ (sweep_angle > 0 ) then
+ sweep_angle:=sweep_angle - pi * 2.0
+ else
+ if sweep_flag and
+ (sweep_angle < 0 ) then
+ sweep_angle:=sweep_angle + pi * 2.0;
+
+// We can now build and transform the resulting arc
+ inherited init(0.0 ,0.0 ,rx ,ry ,start_angle ,sweep_angle );
+
+ mtx.Construct(angle );
+ trn.Construct(cx ,cy );
+
+ mtx.multiply(@trn );
+
+ i:=2;
+
+ while i < num_vertices - 2 do
+ begin
+ //mtx.transform(@m_arc.vertices[i ] ,@m_arc.vertices[i + 1 ] );
+ mtx.transform(
+ @mtx ,
+ double_ptr(ptrcomp(vertices ) + i * sizeof(double ) ) ,
+ double_ptr(ptrcomp(vertices ) + (i + 1 ) * sizeof(double ) ) );
+
+ inc(i ,2 );
+
+ end;
+
+// We must make sure that the starting and ending points
+// exactly coincide with the initial (x0,y0) and (x2,y2)
+ vertices[0 ]:=x0;
+ vertices[1 ]:=y0;
+
+ if num_vertices > 2 then
+ begin
+ vertices[num_vertices - 2 ]:=x2;
+ vertices[num_vertices - 1 ]:=y2;
+
+ end;
+
+end;
+
+{ RADII_OK }
+function bezier_arc_svg.radii_ok;
+begin
+ result:=m_radii_ok;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_bitset_iterator.pas b/src/corelib/render/software/agg_bitset_iterator.pas
new file mode 100644
index 00000000..d749ae38
--- /dev/null
+++ b/src/corelib/render/software/agg_bitset_iterator.pas
@@ -0,0 +1,88 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 17.02.2006-Milano: Unit port establishment
+//
+{ agg_bitset_iterator.pas }
+unit
+ agg_bitset_iterator ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ;
+
+{ TYPES DEFINITION }
+type
+ bitset_iterator = object
+ m_bits : int8u_ptr;
+ m_mask : int8u;
+
+ constructor Construct(bits : int8u_ptr; offset : unsigned = 0 );
+
+ procedure inc_operator;
+
+ function bit : unsigned;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor bitset_iterator.Construct;
+begin
+ m_bits:=int8u_ptr(ptrcomp(bits ) + (offset shr 3) * sizeof(int8u ) );
+ m_mask:=($80 shr (offset and 7 ) );
+
+end;
+
+{ INC_OPERATOR }
+procedure bitset_iterator.inc_operator;
+begin
+ m_mask:=m_mask shr 1;
+
+ if m_mask = 0 then
+ begin
+ inc(ptrcomp(m_bits ) ,sizeof(int8u ) );
+
+ m_mask:=$80;
+
+ end;
+
+end;
+
+{ BIT }
+function bitset_iterator.bit;
+begin
+ result:=m_bits^ and m_mask;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_blur.pas b/src/corelib/render/software/agg_blur.pas
new file mode 100644
index 00000000..ec0da0df
--- /dev/null
+++ b/src/corelib/render/software/agg_blur.pas
@@ -0,0 +1,1624 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// The Stack Blur Algorithm was invented by Mario Klingemann,
+// mario@quasimondo.com and described here:
+// http://incubator.quasimondo.com/processing/fast_blur_deluxe.php
+// (search phrase "Stackblur: Fast But Goodlooking").
+// The major improvement is that there's no more division table
+// that was very expensive to create for large blur radii. Insted,
+// for 8-bit per channel and radius not exceeding 254 the division is
+// replaced by multiplication and shift.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 11.10.2007-Milano: recursive_blur & finished OK
+// 10.10.2007-Milano: stack_blur
+// 09.10.2007-Milano: Unit port establishment
+//
+{ agg_blur.pas }
+unit
+ agg_blur ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+{$Q- }
+{$R- }
+uses
+ agg_basics ,
+ agg_array ,
+ agg_color ,
+ agg_pixfmt ,
+ agg_pixfmt_transposer ;
+
+{ GLOBAL VARIABLES & CONSTANTS }
+
+{ TYPES DEFINITION }
+type
+ stack_blur = object
+ private
+ m_buf ,
+ m_stack : pod_vector;
+
+ public
+ constructor Construct;
+ destructor Destruct;
+
+ procedure blur_x(img : pixel_formats_ptr; radius : unsigned );
+ procedure blur_y(img : pixel_formats_ptr; radius : unsigned );
+
+ procedure blur(img : pixel_formats_ptr; radius : unsigned );
+
+ end;
+
+ recursive_blur = object
+ private
+ m_sum1 ,
+ m_sum2 ,
+ m_buf : pod_vector;
+
+ public
+ constructor Construct;
+ destructor Destruct;
+
+ procedure blur_x(img : pixel_formats_ptr; radius : double );
+ procedure blur_y(img : pixel_formats_ptr; radius : double );
+
+ procedure blur(img : pixel_formats_ptr; radius : double );
+
+ end;
+
+{ GLOBAL PROCEDURES }
+ procedure stack_blur_gray8 (img : pixel_formats_ptr; rx ,ry : unsigned );
+ procedure stack_blur_rgb24 (img : pixel_formats_ptr; rx ,ry : unsigned );
+ procedure stack_blur_rgba32(img : pixel_formats_ptr; rx ,ry : unsigned );
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+const
+ g_stack_blur8_mul : array[0..254 ] of int16u = (
+ 512 ,512 ,456 ,512 ,328 ,456 ,335 ,512 ,405 ,328 ,271 ,456 ,388 ,335 ,292 ,512 ,
+ 454 ,405 ,364 ,328 ,298 ,271 ,496 ,456 ,420 ,388 ,360 ,335 ,312 ,292 ,273 ,512 ,
+ 482 ,454 ,428 ,405 ,383 ,364 ,345 ,328 ,312 ,298 ,284 ,271 ,259 ,496 ,475 ,456 ,
+ 437 ,420 ,404 ,388 ,374 ,360 ,347 ,335 ,323 ,312 ,302 ,292 ,282 ,273 ,265 ,512 ,
+ 497 ,482 ,468 ,454 ,441 ,428 ,417 ,405 ,394 ,383 ,373 ,364 ,354 ,345 ,337 ,328 ,
+ 320 ,312 ,305 ,298 ,291 ,284 ,278 ,271 ,265 ,259 ,507 ,496 ,485 ,475 ,465 ,456 ,
+ 446 ,437 ,428 ,420 ,412 ,404 ,396 ,388 ,381 ,374 ,367 ,360 ,354 ,347 ,341 ,335 ,
+ 329 ,323 ,318 ,312 ,307 ,302 ,297 ,292 ,287 ,282 ,278 ,273 ,269 ,265 ,261 ,512 ,
+ 505 ,497 ,489 ,482 ,475 ,468 ,461 ,454 ,447 ,441 ,435 ,428 ,422 ,417 ,411 ,405 ,
+ 399 ,394 ,389 ,383 ,378 ,373 ,368 ,364 ,359 ,354 ,350 ,345 ,341 ,337 ,332 ,328 ,
+ 324 ,320 ,316 ,312 ,309 ,305 ,301 ,298 ,294 ,291 ,287 ,284 ,281 ,278 ,274 ,271 ,
+ 268 ,265 ,262 ,259 ,257 ,507 ,501 ,496 ,491 ,485 ,480 ,475 ,470 ,465 ,460 ,456 ,
+ 451 ,446 ,442 ,437 ,433 ,428 ,424 ,420 ,416 ,412 ,408 ,404 ,400 ,396 ,392 ,388 ,
+ 385 ,381 ,377 ,374 ,370 ,367 ,363 ,360 ,357 ,354 ,350 ,347 ,344 ,341 ,338 ,335 ,
+ 332 ,329 ,326 ,323 ,320 ,318 ,315 ,312 ,310 ,307 ,304 ,302 ,299 ,297 ,294 ,292 ,
+ 289 ,287 ,285 ,282 ,280 ,278 ,275 ,273 ,271 ,269 ,267 ,265 ,263 ,261 ,259 );
+
+ g_stack_blur8_shr : array[0..254 ] of int8u = (
+ 9 ,11 ,12 ,13 ,13 ,14 ,14 ,15 ,15 ,15 ,15 ,16 ,16 ,16 ,16 ,17 ,
+ 17 ,17 ,17 ,17 ,17 ,17 ,18 ,18 ,18 ,18 ,18 ,18 ,18 ,18 ,18 ,19 ,
+ 19 ,19 ,19 ,19 ,19 ,19 ,19 ,19 ,19 ,19 ,19 ,19 ,19 ,20 ,20 ,20 ,
+ 20 ,20 ,20 ,20 ,20 ,20 ,20 ,20 ,20 ,20 ,20 ,20 ,20 ,20 ,20 ,21 ,
+ 21 ,21 ,21 ,21 ,21 ,21 ,21 ,21 ,21 ,21 ,21 ,21 ,21 ,21 ,21 ,21 ,
+ 21 ,21 ,21 ,21 ,21 ,21 ,21 ,21 ,21 ,21 ,22 ,22 ,22 ,22 ,22 ,22 ,
+ 22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,
+ 22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,23 ,
+ 23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,
+ 23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,
+ 23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,
+ 23 ,23 ,23 ,23 ,23 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,
+ 24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,
+ 24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,
+ 24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,
+ 24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 );
+
+type
+ stack_calculator_ptr = ^stack_calculator;
+ stack_calculator = object
+ v ,
+ r ,
+ g ,
+ b ,
+ a : unsigned;
+
+ procedure clear;
+
+ procedure add (c : aggclr );
+ procedure add_ (c : aggclr; k : unsigned );
+ procedure add__(c : stack_calculator );
+ procedure sub (c : aggclr );
+ procedure sub_ (c : stack_calculator );
+
+ procedure calc_pix (c : aggclr_ptr; div_ : unsigned );
+ procedure calc_pix_(c : aggclr_ptr; mul_ ,shr_ : unsigned );
+
+ end;
+
+ gauss_calculator_ptr = ^gauss_calculator;
+ gauss_calculator = object
+ v ,
+ r ,
+ g ,
+ b ,
+ a : double;
+
+ procedure from_pix(c : aggclr );
+
+ procedure calc(
+ b1 ,b2 ,b3 ,b4 : double;
+ c1 ,c2 ,c3 ,c4 : gauss_calculator_ptr );
+
+ procedure to_pix(c : aggclr_ptr );
+
+ end;
+
+{ UNIT IMPLEMENTATION }
+{ CLEAR }
+procedure stack_calculator.clear;
+begin
+ v:=0;
+ r:=0;
+ g:=0;
+ b:=0;
+ a:=0;
+
+end;
+
+{ ADD }
+procedure stack_calculator.add(c : aggclr );
+begin
+ inc(v ,c.v );
+ inc(r ,c.r );
+ inc(g ,c.g );
+ inc(b ,c.b );
+ inc(a ,c.a );
+
+end;
+
+{ ADD__ }
+procedure stack_calculator.add__(c : stack_calculator );
+begin
+ inc(v ,c.v );
+ inc(r ,c.r );
+ inc(g ,c.g );
+ inc(b ,c.b );
+ inc(a ,c.a );
+
+end;
+
+{ ADD_ }
+procedure stack_calculator.add_(c : aggclr; k : unsigned );
+begin
+ inc(v ,c.v * k );
+ inc(r ,c.r * k );
+ inc(g ,c.g * k );
+ inc(b ,c.b * k );
+ inc(a ,c.a * k );
+
+end;
+
+{ SUB }
+procedure stack_calculator.sub(c : aggclr );
+begin
+ dec(v ,c.v );
+ dec(r ,c.r );
+ dec(g ,c.g );
+ dec(b ,c.b );
+ dec(a ,c.a );
+
+end;
+
+{ SUB_ }
+procedure stack_calculator.sub_(c : stack_calculator );
+begin
+ dec(v ,c.v );
+ dec(r ,c.r );
+ dec(g ,c.g );
+ dec(b ,c.b );
+ dec(a ,c.a );
+
+end;
+
+{ CALC_PIX }
+procedure stack_calculator.calc_pix(c : aggclr_ptr; div_ : unsigned );
+begin
+ c.v:=int8u(v div div_ );
+ c.r:=int8u(r div div_ );
+ c.g:=int8u(g div div_ );
+ c.b:=int8u(b div div_ );
+ c.a:=int8u(a div div_ );
+
+end;
+
+{ CALC_PIX_ }
+procedure stack_calculator.calc_pix_(c : aggclr_ptr; mul_ ,shr_ : unsigned );
+begin
+ c.v:=int8u((v * mul_ ) shr shr_ );
+ c.r:=int8u((r * mul_ ) shr shr_ );
+ c.g:=int8u((g * mul_ ) shr shr_ );
+ c.b:=int8u((b * mul_ ) shr shr_ );
+ c.a:=int8u((a * mul_ ) shr shr_ );
+
+end;
+
+{ FROM_PIX }
+procedure gauss_calculator.from_pix(c : aggclr );
+begin
+ v:=c.v;
+ r:=c.r;
+ g:=c.g;
+ b:=c.b;
+ a:=c.a;
+
+end;
+
+{ CALC }
+procedure gauss_calculator.calc(
+ b1 ,b2 ,b3 ,b4 : double;
+ c1 ,c2 ,c3 ,c4 : gauss_calculator_ptr );
+begin
+ v:=b1 * c1.v + b2 * c2.v + b3 * c3.v + b4 * c4.v;
+ r:=b1 * c1.r + b2 * c2.r + b3 * c3.r + b4 * c4.r;
+ g:=b1 * c1.g + b2 * c2.g + b3 * c3.g + b4 * c4.g;
+ b:=b1 * c1.b + b2 * c2.b + b3 * c3.b + b4 * c4.b;
+ a:=b1 * c1.a + b2 * c2.a + b3 * c3.a + b4 * c4.a;
+
+end;
+
+{ TO_PIX }
+procedure gauss_calculator.to_pix(c : aggclr_ptr );
+begin
+ c.v:=int8u(uround(v ) );
+ c.r:=int8u(uround(r ) );
+ c.g:=int8u(uround(g ) );
+ c.b:=int8u(uround(b ) );
+ c.a:=int8u(uround(a ) );
+
+end;
+
+{ CONSTRUCT }
+constructor stack_blur.Construct;
+begin
+ m_buf.Construct (sizeof(aggclr ) );
+ m_stack.Construct(sizeof(aggclr ) );
+
+end;
+
+{ DESTRUCT }
+destructor stack_blur.Destruct;
+begin
+ m_buf.Destruct;
+ m_stack.Destruct;
+
+end;
+
+{ BLUR_X }
+procedure stack_blur.blur_x(img : pixel_formats_ptr; radius : unsigned );
+var
+ x ,y ,xp ,i ,stack_ptr ,stack_start ,
+
+ w ,h ,wm ,div_ ,div_sum ,mul_sum ,shr_sum ,max_val : unsigned;
+
+ pix : aggclr;
+
+ stack_pix ,_c : aggclr_ptr;
+
+ sum ,sum_in ,sum_out : stack_calculator;
+
+begin
+ if radius < 1 then
+ exit;
+
+ w :=img._width;
+ h :=img._height;
+ wm :=w - 1;
+ div_:=radius * 2 + 1;
+
+ div_sum:=(radius + 1 ) * (radius + 1 );
+ mul_sum:=0;
+ shr_sum:=0;
+ max_val:=base_mask;
+
+ if (max_val <= 255 ) and
+ (radius < 255 ) then
+ begin
+ mul_sum:=g_stack_blur8_mul[radius ];
+ shr_sum:=g_stack_blur8_shr[radius ];
+
+ end;
+
+ m_buf.allocate (w ,128 );
+ m_stack.allocate(div_ ,32 );
+
+ y:=0;
+
+ while y < h do
+ begin
+ sum.clear;
+ sum_in.clear;
+ sum_out.clear;
+
+ pix:=img.pixel(img ,0 ,y );
+
+ i:=0;
+
+ while i <= radius do
+ begin
+ move(pix ,m_stack.array_operator(i )^ ,sizeof(aggclr ) );
+
+ sum.add_ (pix ,i + 1 );
+ sum_out.add(pix );
+
+ inc(i );
+
+ end;
+
+ i:=1;
+
+ while i <= radius do
+ begin
+ if i > wm then
+ pix:=img.pixel(img ,wm ,y )
+ else
+ pix:=img.pixel(img ,i ,y );
+
+ move(pix ,m_stack.array_operator(i + radius )^ ,sizeof(aggclr ) );
+
+ sum.add_ (pix ,radius + 1 - i );
+ sum_in.add(pix );
+
+ inc(i );
+
+ end;
+
+ stack_ptr:=radius;
+
+ x:=0;
+
+ while x < w do
+ begin
+ if mul_sum <> 0 then
+ sum.calc_pix_(aggclr_ptr(m_buf.array_operator(x ) ) ,mul_sum ,shr_sum )
+ else
+ sum.calc_pix(aggclr_ptr(m_buf.array_operator(x ) ) ,div_sum );
+
+ sum.sub_(sum_out );
+
+ stack_start:=stack_ptr + div_ - radius;
+
+ if stack_start >= div_ then
+ dec(stack_start ,div_ );
+
+ stack_pix:=m_stack.array_operator(stack_start );
+
+ sum_out.sub(stack_pix^ );
+
+ xp:=x + radius + 1;
+
+ if xp > wm then
+ xp:=wm;
+
+ pix:=img.pixel(img ,xp ,y );
+
+ stack_pix^:=pix;
+
+ sum_in.add(pix );
+ sum.add__ (sum_in );
+
+ inc(stack_ptr );
+
+ if stack_ptr >= div_ then
+ stack_ptr:=0;
+
+ stack_pix:=m_stack.array_operator(stack_ptr );
+
+ sum_out.add(stack_pix^ );
+ sum_in.sub (stack_pix^ );
+
+ inc(x );
+
+ end;
+
+ _c:=m_buf.array_operator(0 );
+
+ img.copy_color_hspan(img ,0 ,y ,w ,_c );
+
+ inc(y );
+
+ end;
+
+end;
+
+{ BLUR_Y }
+procedure stack_blur.blur_y(img : pixel_formats_ptr; radius : unsigned );
+var
+ img2 : pixel_formats_transposer;
+
+begin
+ pixfmt_transposer(img2 ,img );
+ blur_x (@img2 ,radius );
+
+end;
+
+{ BLUR }
+procedure stack_blur.blur(img : pixel_formats_ptr; radius : unsigned );
+var
+ img2 : pixel_formats_transposer;
+
+begin
+ blur_x (img ,radius );
+ pixfmt_transposer(img2 ,img );
+ blur_x (@img2 ,radius );
+
+end;
+
+{ CONSTRUCT }
+constructor recursive_blur.Construct;
+begin
+ m_sum1.Construct(sizeof(gauss_calculator ) );
+ m_sum2.Construct(sizeof(gauss_calculator ) );
+ m_buf.Construct (sizeof(aggclr ) );
+
+end;
+
+{ DESTRUCT }
+destructor recursive_blur.Destruct;
+begin
+ m_sum1.Destruct;
+ m_sum2.Destruct;
+ m_buf.Destruct;
+
+end;
+
+{ BLUR_X }
+procedure recursive_blur.blur_x(img : pixel_formats_ptr; radius : double );
+var
+ s ,q ,q2 ,q3 ,b0 ,b1 ,b2 ,b3 ,b : double;
+
+ w ,h ,wm ,x ,y : int;
+
+ c : gauss_calculator;
+
+ g0 ,g1 : gauss_calculator_ptr;
+
+begin
+ if radius < 0.62 then
+ exit;
+
+ if img._width < 3 then
+ exit;
+
+ s:=radius * 0.5;
+
+ if s < 2.5 then
+ q:=3.97156 - 4.14554 * Sqrt(1 - 0.26891 * s )
+ else
+ q:=0.98711 * s - 0.96330;
+
+ q2:=q * q;
+ q3:=q2 * q;
+ b0:=1.0 / (1.578250 + 2.444130 * q + 1.428100 * q2 + 0.422205 * q3 );
+ b1:=2.44413 * q + 2.85619 * q2 + 1.26661 * q3;
+ b2:=-1.42810 * q2 + -1.26661 * q3;
+ b3:=0.422205 * q3;
+ b :=1 - (b1 + b2 + b3 ) * b0;
+ b1:=b1 * b0;
+ b2:=b2 * b0;
+ b3:=b3 * b0;
+ w :=img._width;
+ h :=img._height;
+ wm:=w - 1;
+
+ m_sum1.allocate(w );
+ m_sum2.allocate(w );
+ m_buf.allocate (w );
+
+ y:=0;
+
+ while y < h do
+ begin
+ g0:=gauss_calculator_ptr(m_sum1.array_operator(0 ) );
+
+ c.from_pix(img.pixel(img ,0 ,y ) );
+ g0.calc(
+ b ,b1 ,b2 ,b3 ,
+ @c ,@c ,@c ,@c );
+
+ g1:=gauss_calculator_ptr(m_sum1.array_operator(1 ) );
+
+ c.from_pix(img.pixel(img ,1 ,y ) );
+ g1.calc(
+ b ,b1 ,b2 ,b3 ,
+ @c ,g0 ,g0 ,g0 );
+
+ c.from_pix (img.pixel(img ,2 ,y ) );
+ gauss_calculator_ptr(m_sum1.array_operator(2 ) ).calc(
+ b ,b1 ,b2 ,b3 ,
+ @c ,g1 ,g0 ,g0 );
+
+ x:=3;
+
+ while x < w do
+ begin
+ c.from_pix(img.pixel(img ,x ,y ) );
+
+ gauss_calculator_ptr(m_sum1.array_operator(x ) ).calc(
+ b ,b1 ,b2 ,b3 ,
+ @c ,
+ gauss_calculator_ptr(m_sum1.array_operator(x - 1 ) ) ,
+ gauss_calculator_ptr(m_sum1.array_operator(x - 2 ) ) ,
+ gauss_calculator_ptr(m_sum1.array_operator(x - 3 ) ) );
+
+ inc(x );
+
+ end;
+
+ g0:=gauss_calculator_ptr(m_sum1.array_operator(wm ) );
+ g1:=gauss_calculator_ptr(m_sum2.array_operator(wm ) );
+
+ g1.calc(
+ b ,b1 ,b2 ,b3 ,
+ g0 ,g0 ,g0 ,g0 );
+
+ gauss_calculator_ptr(m_sum2.array_operator(wm - 1 ) ).calc(
+ b ,b1 ,b2 ,b3 ,
+ gauss_calculator_ptr(m_sum1.array_operator(wm - 1 ) ) ,
+ g1 ,g1 ,g1 );
+
+ gauss_calculator_ptr(m_sum2.array_operator(wm - 2 ) ).calc(
+ b ,b1 ,b2 ,b3 ,
+ gauss_calculator_ptr(m_sum1.array_operator(wm - 2 ) ) ,
+ gauss_calculator_ptr(m_sum2.array_operator(wm - 1 ) ) ,
+ g1 ,g1 );
+
+ g1.to_pix(
+ aggclr_ptr(m_buf.array_operator(wm ) ) );
+
+ gauss_calculator_ptr(m_sum2.array_operator(wm - 1 ) ).to_pix(
+ aggclr_ptr(m_buf.array_operator(wm - 1 ) ) );
+
+ gauss_calculator_ptr(m_sum2.array_operator(wm - 2 ) ).to_pix(
+ aggclr_ptr(m_buf.array_operator(wm - 2 ) ) );
+
+ x:=wm - 3;
+
+ while x >= 0 do
+ begin
+ gauss_calculator_ptr(m_sum2.array_operator(x ) ).calc(
+ b ,b1 ,b2 ,b3 ,
+ gauss_calculator_ptr(m_sum1.array_operator(x ) ) ,
+ gauss_calculator_ptr(m_sum2.array_operator(x + 1 ) ) ,
+ gauss_calculator_ptr(m_sum2.array_operator(x + 2 ) ) ,
+ gauss_calculator_ptr(m_sum2.array_operator(x + 3 ) ) );
+
+ gauss_calculator_ptr(m_sum2.array_operator(x ) ).to_pix(
+ aggclr_ptr(m_buf.array_operator(x ) ) );
+
+ dec(x );
+
+ end;
+
+ img.copy_color_hspan(img ,0 ,y ,w ,m_buf.array_operator(0 ) );
+
+ inc(y );
+
+ end;
+
+end;
+
+{ BLUR_Y }
+procedure recursive_blur.blur_y(img : pixel_formats_ptr; radius : double );
+var
+ img2 : pixel_formats_transposer;
+
+begin
+ pixfmt_transposer(img2 ,img );
+ blur_x (@img2 ,radius );
+
+end;
+
+{ BLUR }
+procedure recursive_blur.blur(img : pixel_formats_ptr; radius : double );
+var
+ img2 : pixel_formats_transposer;
+
+begin
+ blur_x (img ,radius );
+ pixfmt_transposer(img2 ,img );
+ blur_x (@img2 ,radius );
+
+end;
+
+{ STACK_BLUR_GRAY8 }
+procedure stack_blur_gray8(img : pixel_formats_ptr; rx ,ry : unsigned );
+var
+ stride : int;
+
+ x ,y ,xp ,yp ,i ,pix ,stack_pix ,sum ,sum_in ,sum_out ,
+
+ stack_ptr ,stack_start ,w ,h ,wm ,hm ,div_ ,mul_sum ,shr_sum : unsigned;
+
+ src_pix_ptr ,dst_pix_ptr : int8u_ptr;
+
+ stack : pod_vector;
+
+begin
+ w :=img._width;
+ h :=img._height;
+ wm:=w - 1;
+ hm:=h - 1;
+
+ stack.Construct(sizeof(int8u ) );
+
+ if rx > 0 then
+ begin
+ if rx > 254 then
+ rx:=254;
+
+ div_:=rx * 2 + 1;
+
+ mul_sum:=g_stack_blur8_mul[rx ];
+ shr_sum:=g_stack_blur8_shr[rx ];
+
+ stack.allocate(div_ );
+
+ y:=0;
+
+ while y < h do
+ begin
+ sum :=0;
+ sum_in :=0;
+ sum_out:=0;
+
+ src_pix_ptr:=img.pix_ptr(0 ,y );
+ pix :=src_pix_ptr^;
+
+ i:=0;
+
+ while i <= rx do
+ begin
+ int8u_ptr(stack.array_operator(i ) )^:=pix;
+
+ inc(sum ,pix * (i + 1 ) );
+ inc(sum_out ,pix );
+
+ inc(i );
+
+ end;
+
+ i:=1;
+
+ while i <= rx do
+ begin
+ if i <= wm then
+ inc(ptrcomp(src_pix_ptr ) ,img.m_step );
+
+ pix:=src_pix_ptr^;
+
+ int8u_ptr(stack.array_operator(i + rx ) )^:=pix;
+
+ inc(sum ,pix * (rx + 1 - i ) );
+ inc(sum_in ,pix );
+
+ inc(i );
+
+ end;
+
+ stack_ptr:=rx;
+ xp :=rx;
+
+ if xp > wm then
+ xp:=wm;
+
+ src_pix_ptr:=img.pix_ptr(xp ,y );
+ dst_pix_ptr:=img.pix_ptr(0 ,y );
+
+ x:=0;
+
+ while x < w do
+ begin
+ dst_pix_ptr^:=int8u((sum * mul_sum ) shr shr_sum );
+
+ inc(ptrcomp(dst_pix_ptr ) ,img.m_step );
+ dec(sum ,sum_out );
+
+ stack_start:=stack_ptr + div_ - rx;
+
+ if stack_start >= div_ then
+ dec(stack_start ,div_ );
+
+ dec(sum_out ,int8u_ptr(stack.array_operator(stack_start ) )^ );
+
+ if xp < wm then
+ begin
+ inc(ptrcomp(src_pix_ptr ) ,img.m_step );
+
+ pix:=src_pix_ptr^;
+
+ inc(xp );
+
+ end;
+
+ int8u_ptr(stack.array_operator(stack_start ) )^:=pix;
+
+ inc(sum_in ,pix );
+ inc(sum ,sum_in );
+
+ inc(stack_ptr );
+
+ if stack_ptr >= div_ then
+ stack_ptr:=0;
+
+ stack_pix:=int8u_ptr(stack.array_operator(stack_ptr ) )^;
+
+ inc(sum_out ,stack_pix );
+ dec(sum_in ,stack_pix );
+
+ inc(x );
+
+ end;
+
+ inc(y );
+
+ end;
+
+ end;
+
+ if ry > 0 then
+ begin
+ if ry > 254 then
+ ry:=254;
+
+ div_:=ry * 2 + 1;
+
+ mul_sum:=g_stack_blur8_mul[ry ];
+ shr_sum:=g_stack_blur8_shr[ry ];
+
+ stack.allocate(div_ );
+
+ stride:=img._stride;
+
+ x:=0;
+
+ while x < w do
+ begin
+ sum :=0;
+ sum_in :=0;
+ sum_out:=0;
+
+ src_pix_ptr:=img.pix_ptr(x ,0 );
+ pix :=src_pix_ptr^;
+
+ i:=0;
+
+ while i <= ry do
+ begin
+ int8u_ptr(stack.array_operator(i ) )^:=pix;
+
+ inc(sum ,pix * (i + 1 ) );
+ inc(sum_out ,pix );
+
+ inc(i );
+
+ end;
+
+ i:=1;
+
+ while i <= ry do
+ begin
+ if i <= hm then
+ inc(ptrcomp(src_pix_ptr ) ,stride );
+
+ pix:=src_pix_ptr^;
+
+ int8u_ptr(stack.array_operator(i + ry ) )^:=pix;
+
+ inc(sum ,pix * (ry + 1 - i ) );
+ inc(sum_in ,pix );
+
+ inc(i );
+
+ end;
+
+ stack_ptr:=ry;
+ yp :=ry;
+
+ if yp > hm then
+ yp:=hm;
+
+ src_pix_ptr:=img.pix_ptr(x ,yp );
+ dst_pix_ptr:=img.pix_ptr(x ,0 );
+
+ y:=0;
+
+ while y < h do
+ begin
+ dst_pix_ptr^:=int8u((sum * mul_sum ) shr shr_sum );
+
+ inc(ptrcomp(dst_pix_ptr ) ,stride );
+ dec(sum ,sum_out );
+
+ stack_start:=stack_ptr + div_ - ry;
+
+ if stack_start >= div_ then
+ dec(stack_start ,div_ );
+
+ dec(sum_out ,int8u_ptr(stack.array_operator(stack_start ) )^ );
+
+ if yp < hm then
+ begin
+ inc(ptrcomp(src_pix_ptr ) ,stride );
+
+ pix:=src_pix_ptr^;
+
+ inc(yp );
+
+ end;
+
+ int8u_ptr(stack.array_operator(stack_start ) )^:=pix;
+
+ inc(sum_in ,pix );
+ inc(sum ,sum_in );
+
+ inc(stack_ptr );
+
+ if stack_ptr >= div_ then
+ stack_ptr:=0;
+
+ stack_pix:=int8u_ptr(stack.array_operator(stack_ptr ) )^;
+
+ inc(sum_out ,stack_pix );
+ dec(sum_in ,stack_pix );
+
+ inc(y );
+
+ end;
+
+ inc(x );
+
+ end;
+
+ end;
+
+ stack.Destruct;
+
+end;
+
+{ STACK_BLUR_RGB24 }
+procedure stack_blur_rgb24(img : pixel_formats_ptr; rx ,ry : unsigned );
+var
+ R ,G ,B ,stride : int;
+
+ x ,y ,xp ,yp ,i ,stack_ptr ,stack_start ,
+
+ sum_r ,sum_g ,sum_b ,
+
+ sum_in_r ,sum_in_g ,sum_in_b ,
+
+ sum_out_r ,sum_out_g ,sum_out_b ,
+
+ w ,h ,wm ,hm ,div_ ,mul_sum ,shr_sum : unsigned;
+
+ src_pix_ptr ,dst_pix_ptr : int8u_ptr;
+
+ stack_pix_ptr : aggclr_ptr;
+
+ stack : pod_array;
+
+begin
+ R:=img.m_order.R;
+ G:=img.m_order.G;
+ B:=img.m_order.B;
+
+ w :=img._width;
+ h :=img._height;
+ wm:=w - 1;
+ hm:=h - 1;
+
+ stack.Construct(sizeof(aggclr ) );
+
+ if rx > 0 then
+ begin
+ if rx > 254 then
+ rx:=254;
+
+ div_ :=rx * 2 + 1;
+ mul_sum:=g_stack_blur8_mul[rx ];
+ shr_sum:=g_stack_blur8_shr[rx ];
+
+ stack.allocate(div_ );
+
+ y:=0;
+
+ while y < h do
+ begin
+ sum_r :=0;
+ sum_g :=0;
+ sum_b :=0;
+ sum_in_r :=0;
+ sum_in_g :=0;
+ sum_in_b :=0;
+ sum_out_r:=0;
+ sum_out_g:=0;
+ sum_out_b:=0;
+
+ src_pix_ptr:=img.pix_ptr(0 ,y );
+
+ i:=0;
+
+ while i <= rx do
+ begin
+ stack_pix_ptr:=stack.array_operator(i );
+
+ stack_pix_ptr.r:=int8u_ptr(ptrcomp(src_pix_ptr ) + R )^;
+ stack_pix_ptr.g:=int8u_ptr(ptrcomp(src_pix_ptr ) + G )^;
+ stack_pix_ptr.b:=int8u_ptr(ptrcomp(src_pix_ptr ) + B )^;
+
+ inc(sum_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ * (i + 1 ) );
+ inc(sum_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ * (i + 1 ) );
+ inc(sum_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ * (i + 1 ) );
+
+ inc(sum_out_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ );
+ inc(sum_out_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ );
+ inc(sum_out_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ );
+
+ inc(i );
+
+ end;
+
+ i:=1;
+
+ while i <= rx do
+ begin
+ if i <= wm then
+ inc(ptrcomp(src_pix_ptr ) ,img.m_pix_width );
+
+ stack_pix_ptr:=stack.array_operator(i + rx );
+
+ stack_pix_ptr.r:=int8u_ptr(ptrcomp(src_pix_ptr ) + R )^;
+ stack_pix_ptr.g:=int8u_ptr(ptrcomp(src_pix_ptr ) + G )^;
+ stack_pix_ptr.b:=int8u_ptr(ptrcomp(src_pix_ptr ) + B )^;
+
+ inc(sum_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ * (rx + 1 - i ) );
+ inc(sum_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ * (rx + 1 - i ) );
+ inc(sum_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ * (rx + 1 - i ) );
+
+ inc(sum_in_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ );
+ inc(sum_in_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ );
+ inc(sum_in_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ );
+
+ inc(i );
+
+ end;
+
+ stack_ptr:=rx;
+ xp :=rx;
+
+ if xp > wm then
+ xp:=wm;
+
+ src_pix_ptr:=img.pix_ptr(xp ,y );
+ dst_pix_ptr:=img.pix_ptr(0 ,y );
+
+ x:=0;
+
+ while x < w do
+ begin
+ int8u_ptr(ptrcomp(dst_pix_ptr ) + R )^:=int8u((sum_r * mul_sum ) shr shr_sum );
+ int8u_ptr(ptrcomp(dst_pix_ptr ) + G )^:=int8u((sum_g * mul_sum ) shr shr_sum );
+ int8u_ptr(ptrcomp(dst_pix_ptr ) + B )^:=int8u((sum_b * mul_sum ) shr shr_sum );
+
+ inc(ptrcomp(dst_pix_ptr ) ,img.m_pix_width );
+
+ dec(sum_r ,sum_out_r );
+ dec(sum_g ,sum_out_g );
+ dec(sum_b ,sum_out_b );
+
+ stack_start:=stack_ptr + div_ - rx;
+
+ if stack_start >= div_ then
+ dec(stack_start ,div_ );
+
+ stack_pix_ptr:=stack.array_operator(stack_start );
+
+ dec(sum_out_r ,stack_pix_ptr.r );
+ dec(sum_out_g ,stack_pix_ptr.g );
+ dec(sum_out_b ,stack_pix_ptr.b );
+
+ if xp < wm then
+ begin
+ inc(ptrcomp(src_pix_ptr ) ,img.m_pix_width );
+ inc(xp );
+
+ end;
+
+ stack_pix_ptr.r:=int8u_ptr(ptrcomp(src_pix_ptr ) + R )^;
+ stack_pix_ptr.g:=int8u_ptr(ptrcomp(src_pix_ptr ) + G )^;
+ stack_pix_ptr.b:=int8u_ptr(ptrcomp(src_pix_ptr ) + B )^;
+
+ inc(sum_in_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ );
+ inc(sum_in_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ );
+ inc(sum_in_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ );
+
+ inc(sum_r ,sum_in_r );
+ inc(sum_g ,sum_in_g );
+ inc(sum_b ,sum_in_b );
+
+ inc(stack_ptr );
+
+ if stack_ptr >= div_ then
+ stack_ptr:=0;
+
+ stack_pix_ptr:=stack.array_operator(stack_ptr );
+
+ inc(sum_out_r ,stack_pix_ptr.r );
+ inc(sum_out_g ,stack_pix_ptr.g );
+ inc(sum_out_b ,stack_pix_ptr.b );
+ dec(sum_in_r ,stack_pix_ptr.r );
+ dec(sum_in_g ,stack_pix_ptr.g );
+ dec(sum_in_b ,stack_pix_ptr.b );
+
+ inc(x );
+
+ end;
+
+ inc(y );
+
+ end;
+
+ end;
+
+ if ry > 0 then
+ begin
+ if ry > 254 then
+ ry:=254;
+
+ div_:=ry * 2 + 1;
+
+ mul_sum:=g_stack_blur8_mul[ry ];
+ shr_sum:=g_stack_blur8_shr[ry ];
+
+ stack.allocate(div_ );
+
+ stride:=img._stride;
+
+ x:=0;
+
+ while x < w do
+ begin
+ sum_r :=0;
+ sum_g :=0;
+ sum_b :=0;
+ sum_in_r :=0;
+ sum_in_g :=0;
+ sum_in_b :=0;
+ sum_out_r:=0;
+ sum_out_g:=0;
+ sum_out_b:=0;
+
+ src_pix_ptr:=img.pix_ptr(x ,0 );
+
+ i:=0;
+
+ while i <= ry do
+ begin
+ stack_pix_ptr:=stack.array_operator(i );
+
+ stack_pix_ptr.r:=int8u_ptr(ptrcomp(src_pix_ptr ) + R )^;
+ stack_pix_ptr.g:=int8u_ptr(ptrcomp(src_pix_ptr ) + G )^;
+ stack_pix_ptr.b:=int8u_ptr(ptrcomp(src_pix_ptr ) + B )^;
+
+ inc(sum_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ * (i + 1 ) );
+ inc(sum_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ * (i + 1 ) );
+ inc(sum_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ * (i + 1 ) );
+ inc(sum_out_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ );
+ inc(sum_out_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ );
+ inc(sum_out_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ );
+
+ inc(i );
+
+ end;
+
+ i:=1;
+
+ while i <= ry do
+ begin
+ if i <= hm then
+ inc(ptrcomp(src_pix_ptr ) ,stride );
+
+ stack_pix_ptr:=stack.array_operator(i + ry );
+
+ stack_pix_ptr.r:=int8u_ptr(ptrcomp(src_pix_ptr ) + R )^;
+ stack_pix_ptr.g:=int8u_ptr(ptrcomp(src_pix_ptr ) + G )^;
+ stack_pix_ptr.b:=int8u_ptr(ptrcomp(src_pix_ptr ) + B )^;
+
+ inc(sum_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ * (ry + 1 - i ) );
+ inc(sum_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ * (ry + 1 - i ) );
+ inc(sum_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ * (ry + 1 - i ) );
+ inc(sum_in_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ );
+ inc(sum_in_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ );
+ inc(sum_in_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ );
+
+ inc(i );
+
+ end;
+
+ stack_ptr:=ry;
+ yp :=ry;
+
+ if yp > hm then
+ yp:=hm;
+
+ src_pix_ptr:=img.pix_ptr(x ,yp );
+ dst_pix_ptr:=img.pix_ptr(x ,0 );
+
+ y:=0;
+
+ while y < h do
+ begin
+ int8u_ptr(ptrcomp(dst_pix_ptr ) + R )^:=int8u((sum_r * mul_sum ) shr shr_sum );
+ int8u_ptr(ptrcomp(dst_pix_ptr ) + G )^:=int8u((sum_g * mul_sum ) shr shr_sum );
+ int8u_ptr(ptrcomp(dst_pix_ptr ) + B )^:=int8u((sum_b * mul_sum ) shr shr_sum );
+
+ inc(ptrcomp(dst_pix_ptr ) ,stride );
+
+ dec(sum_r ,sum_out_r );
+ dec(sum_g ,sum_out_g );
+ dec(sum_b ,sum_out_b );
+
+ stack_start:=stack_ptr + div_ - ry;
+
+ if stack_start >= div_ then
+ dec(stack_start ,div_ );
+
+ stack_pix_ptr:=stack.array_operator(stack_start );
+
+ dec(sum_out_r ,stack_pix_ptr.r );
+ dec(sum_out_g ,stack_pix_ptr.g );
+ dec(sum_out_b ,stack_pix_ptr.b );
+
+ if yp < hm then
+ begin
+ inc(ptrcomp(src_pix_ptr ) ,stride );
+
+ inc(yp );
+
+ end;
+
+ stack_pix_ptr.r:=int8u_ptr(ptrcomp(src_pix_ptr ) + R )^;
+ stack_pix_ptr.g:=int8u_ptr(ptrcomp(src_pix_ptr ) + G )^;
+ stack_pix_ptr.b:=int8u_ptr(ptrcomp(src_pix_ptr ) + B )^;
+
+ inc(sum_in_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ );
+ inc(sum_in_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ );
+ inc(sum_in_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ );
+ inc(sum_r ,sum_in_r );
+ inc(sum_g ,sum_in_g );
+ inc(sum_b ,sum_in_b );
+
+ inc(stack_ptr );
+
+ if stack_ptr >= div_ then
+ stack_ptr:=0;
+
+ stack_pix_ptr:=stack.array_operator(stack_ptr );
+
+ inc(sum_out_r ,stack_pix_ptr.r );
+ inc(sum_out_g ,stack_pix_ptr.g );
+ inc(sum_out_b ,stack_pix_ptr.b );
+ dec(sum_in_r ,stack_pix_ptr.r );
+ dec(sum_in_g ,stack_pix_ptr.g );
+ dec(sum_in_b ,stack_pix_ptr.b );
+
+ inc(y );
+
+ end;
+
+ inc(x );
+
+ end;
+
+ end;
+
+ stack.Destruct;
+
+end;
+
+{ STACK_BLUR_RGBA32 }
+procedure stack_blur_rgba32(img : pixel_formats_ptr; rx ,ry : unsigned );
+var
+ R ,G ,B ,A ,stride : int;
+
+ x ,y ,xp ,yp ,i ,stack_ptr ,stack_start ,
+
+ sum_r ,sum_g ,sum_b ,sum_a ,
+
+ sum_in_r ,sum_in_g ,sum_in_b ,sum_in_a ,
+
+ sum_out_r ,sum_out_g ,sum_out_b ,sum_out_a ,
+
+ w ,h ,wm ,hm ,div_ ,mul_sum ,shr_sum : unsigned;
+
+ src_pix_ptr ,dst_pix_ptr : int8u_ptr;
+
+ stack_pix_ptr : aggclr_ptr;
+
+ stack : pod_array;
+
+begin
+ R:=img.m_order.R;
+ G:=img.m_order.G;
+ B:=img.m_order.B;
+ A:=img.m_order.A;
+
+ w :=img._width;
+ h :=img._height;
+ wm:=w - 1;
+ hm:=h - 1;
+
+ stack.Construct(sizeof(aggclr ) );
+
+ if rx > 0 then
+ begin
+ if rx > 254 then
+ rx:=254;
+
+ div_ :=rx * 2 + 1;
+ mul_sum:=g_stack_blur8_mul[rx ];
+ shr_sum:=g_stack_blur8_shr[rx ];
+
+ stack.allocate(div_ );
+
+ y:=0;
+
+ while y < h do
+ begin
+ sum_r :=0;
+ sum_g :=0;
+ sum_b :=0;
+ sum_a :=0;
+ sum_in_r :=0;
+ sum_in_g :=0;
+ sum_in_b :=0;
+ sum_in_a :=0;
+ sum_out_r:=0;
+ sum_out_g:=0;
+ sum_out_b:=0;
+ sum_out_a:=0;
+
+ src_pix_ptr:=img.pix_ptr(0 ,y );
+
+ i:=0;
+
+ while i <= rx do
+ begin
+ stack_pix_ptr:=stack.array_operator(i );
+
+ stack_pix_ptr.r:=int8u_ptr(ptrcomp(src_pix_ptr ) + R )^;
+ stack_pix_ptr.g:=int8u_ptr(ptrcomp(src_pix_ptr ) + G )^;
+ stack_pix_ptr.b:=int8u_ptr(ptrcomp(src_pix_ptr ) + B )^;
+ stack_pix_ptr.a:=int8u_ptr(ptrcomp(src_pix_ptr ) + A )^;
+
+ inc(sum_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ * (i + 1 ) );
+ inc(sum_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ * (i + 1 ) );
+ inc(sum_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ * (i + 1 ) );
+ inc(sum_a ,int8u_ptr(ptrcomp(src_pix_ptr ) + A )^ * (i + 1 ) );
+
+ inc(sum_out_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ );
+ inc(sum_out_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ );
+ inc(sum_out_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ );
+ inc(sum_out_a ,int8u_ptr(ptrcomp(src_pix_ptr ) + A )^ );
+
+ inc(i );
+
+ end;
+
+ i:=1;
+
+ while i <= rx do
+ begin
+ if i <= wm then
+ inc(ptrcomp(src_pix_ptr ) ,img.m_pix_width );
+
+ stack_pix_ptr:=stack.array_operator(i + rx );
+
+ stack_pix_ptr.r:=int8u_ptr(ptrcomp(src_pix_ptr ) + R )^;
+ stack_pix_ptr.g:=int8u_ptr(ptrcomp(src_pix_ptr ) + G )^;
+ stack_pix_ptr.b:=int8u_ptr(ptrcomp(src_pix_ptr ) + B )^;
+ stack_pix_ptr.a:=int8u_ptr(ptrcomp(src_pix_ptr ) + A )^;
+
+ inc(sum_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ * (rx + 1 - i ) );
+ inc(sum_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ * (rx + 1 - i ) );
+ inc(sum_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ * (rx + 1 - i ) );
+ inc(sum_a ,int8u_ptr(ptrcomp(src_pix_ptr ) + A )^ * (rx + 1 - i ) );
+
+ inc(sum_in_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ );
+ inc(sum_in_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ );
+ inc(sum_in_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ );
+ inc(sum_in_a ,int8u_ptr(ptrcomp(src_pix_ptr ) + A )^ );
+
+ inc(i );
+
+ end;
+
+ stack_ptr:=rx;
+ xp :=rx;
+
+ if xp > wm then
+ xp:=wm;
+
+ src_pix_ptr:=img.pix_ptr(xp ,y );
+ dst_pix_ptr:=img.pix_ptr(0 ,y );
+
+ x:=0;
+
+ while x < w do
+ begin
+ int8u_ptr(ptrcomp(dst_pix_ptr ) + R )^:=int8u((sum_r * mul_sum ) shr shr_sum );
+ int8u_ptr(ptrcomp(dst_pix_ptr ) + G )^:=int8u((sum_g * mul_sum ) shr shr_sum );
+ int8u_ptr(ptrcomp(dst_pix_ptr ) + B )^:=int8u((sum_b * mul_sum ) shr shr_sum );
+ int8u_ptr(ptrcomp(dst_pix_ptr ) + A )^:=int8u((sum_a * mul_sum ) shr shr_sum );
+
+ inc(ptrcomp(dst_pix_ptr ) ,img.m_pix_width );
+
+ dec(sum_r ,sum_out_r );
+ dec(sum_g ,sum_out_g );
+ dec(sum_b ,sum_out_b );
+ dec(sum_a ,sum_out_a );
+
+ stack_start:=stack_ptr + div_ - rx;
+
+ if stack_start >= div_ then
+ dec(stack_start ,div_ );
+
+ stack_pix_ptr:=stack.array_operator(stack_start );
+
+ dec(sum_out_r ,stack_pix_ptr.r );
+ dec(sum_out_g ,stack_pix_ptr.g );
+ dec(sum_out_b ,stack_pix_ptr.b );
+ dec(sum_out_a ,stack_pix_ptr.a );
+
+ if xp < wm then
+ begin
+ inc(ptrcomp(src_pix_ptr ) ,img.m_pix_width );
+ inc(xp );
+
+ end;
+
+ stack_pix_ptr.r:=int8u_ptr(ptrcomp(src_pix_ptr ) + R )^;
+ stack_pix_ptr.g:=int8u_ptr(ptrcomp(src_pix_ptr ) + G )^;
+ stack_pix_ptr.b:=int8u_ptr(ptrcomp(src_pix_ptr ) + B )^;
+ stack_pix_ptr.a:=int8u_ptr(ptrcomp(src_pix_ptr ) + A )^;
+
+ inc(sum_in_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ );
+ inc(sum_in_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ );
+ inc(sum_in_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ );
+ inc(sum_in_a ,int8u_ptr(ptrcomp(src_pix_ptr ) + A )^ );
+
+ inc(sum_r ,sum_in_r );
+ inc(sum_g ,sum_in_g );
+ inc(sum_b ,sum_in_b );
+ inc(sum_a ,sum_in_a );
+
+ inc(stack_ptr );
+
+ if stack_ptr >= div_ then
+ stack_ptr:=0;
+
+ stack_pix_ptr:=stack.array_operator(stack_ptr );
+
+ inc(sum_out_r ,stack_pix_ptr.r );
+ inc(sum_out_g ,stack_pix_ptr.g );
+ inc(sum_out_b ,stack_pix_ptr.b );
+ inc(sum_out_a ,stack_pix_ptr.a );
+ dec(sum_in_r ,stack_pix_ptr.r );
+ dec(sum_in_g ,stack_pix_ptr.g );
+ dec(sum_in_b ,stack_pix_ptr.b );
+ dec(sum_in_a ,stack_pix_ptr.a );
+
+ inc(x );
+
+ end;
+
+ inc(y );
+
+ end;
+
+ end;
+
+ if ry > 0 then
+ begin
+ if ry > 254 then
+ ry:=254;
+
+ div_:=ry * 2 + 1;
+
+ mul_sum:=g_stack_blur8_mul[ry ];
+ shr_sum:=g_stack_blur8_shr[ry ];
+
+ stack.allocate(div_ );
+
+ stride:=img._stride;
+
+ x:=0;
+
+ while x < w do
+ begin
+ sum_r :=0;
+ sum_g :=0;
+ sum_b :=0;
+ sum_a :=0;
+ sum_in_r :=0;
+ sum_in_g :=0;
+ sum_in_b :=0;
+ sum_in_a :=0;
+ sum_out_r:=0;
+ sum_out_g:=0;
+ sum_out_b:=0;
+ sum_out_a:=0;
+
+ src_pix_ptr:=img.pix_ptr(x ,0 );
+
+ i:=0;
+
+ while i <= ry do
+ begin
+ stack_pix_ptr:=stack.array_operator(i );
+
+ stack_pix_ptr.r:=int8u_ptr(ptrcomp(src_pix_ptr ) + R )^;
+ stack_pix_ptr.g:=int8u_ptr(ptrcomp(src_pix_ptr ) + G )^;
+ stack_pix_ptr.b:=int8u_ptr(ptrcomp(src_pix_ptr ) + B )^;
+ stack_pix_ptr.a:=int8u_ptr(ptrcomp(src_pix_ptr ) + A )^;
+
+ inc(sum_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ * (i + 1 ) );
+ inc(sum_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ * (i + 1 ) );
+ inc(sum_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ * (i + 1 ) );
+ inc(sum_a ,int8u_ptr(ptrcomp(src_pix_ptr ) + A )^ * (i + 1 ) );
+ inc(sum_out_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ );
+ inc(sum_out_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ );
+ inc(sum_out_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ );
+ inc(sum_out_a ,int8u_ptr(ptrcomp(src_pix_ptr ) + A )^ );
+
+ inc(i );
+
+ end;
+
+ i:=1;
+
+ while i <= ry do
+ begin
+ if i <= hm then
+ inc(ptrcomp(src_pix_ptr ) ,stride );
+
+ stack_pix_ptr:=stack.array_operator(i + ry );
+
+ stack_pix_ptr.r:=int8u_ptr(ptrcomp(src_pix_ptr ) + R )^;
+ stack_pix_ptr.g:=int8u_ptr(ptrcomp(src_pix_ptr ) + G )^;
+ stack_pix_ptr.b:=int8u_ptr(ptrcomp(src_pix_ptr ) + B )^;
+ stack_pix_ptr.a:=int8u_ptr(ptrcomp(src_pix_ptr ) + A )^;
+
+ inc(sum_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ * (ry + 1 - i ) );
+ inc(sum_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ * (ry + 1 - i ) );
+ inc(sum_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ * (ry + 1 - i ) );
+ inc(sum_a ,int8u_ptr(ptrcomp(src_pix_ptr ) + A )^ * (ry + 1 - i ) );
+ inc(sum_in_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ );
+ inc(sum_in_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ );
+ inc(sum_in_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ );
+ inc(sum_in_a ,int8u_ptr(ptrcomp(src_pix_ptr ) + A )^ );
+
+ inc(i );
+
+ end;
+
+ stack_ptr:=ry;
+ yp :=ry;
+
+ if yp > hm then
+ yp:=hm;
+
+ src_pix_ptr:=img.pix_ptr(x ,yp );
+ dst_pix_ptr:=img.pix_ptr(x ,0 );
+
+ y:=0;
+
+ while y < h do
+ begin
+ int8u_ptr(ptrcomp(dst_pix_ptr ) + R )^:=int8u((sum_r * mul_sum ) shr shr_sum );
+ int8u_ptr(ptrcomp(dst_pix_ptr ) + G )^:=int8u((sum_g * mul_sum ) shr shr_sum );
+ int8u_ptr(ptrcomp(dst_pix_ptr ) + B )^:=int8u((sum_b * mul_sum ) shr shr_sum );
+ int8u_ptr(ptrcomp(dst_pix_ptr ) + A )^:=int8u((sum_a * mul_sum ) shr shr_sum );
+
+ inc(ptrcomp(dst_pix_ptr ) ,stride );
+
+ dec(sum_r ,sum_out_r );
+ dec(sum_g ,sum_out_g );
+ dec(sum_b ,sum_out_b );
+ dec(sum_a ,sum_out_a );
+
+ stack_start:=stack_ptr + div_ - ry;
+
+ if stack_start >= div_ then
+ dec(stack_start ,div_ );
+
+ stack_pix_ptr:=stack.array_operator(stack_start );
+
+ dec(sum_out_r ,stack_pix_ptr.r );
+ dec(sum_out_g ,stack_pix_ptr.g );
+ dec(sum_out_b ,stack_pix_ptr.b );
+ dec(sum_out_a ,stack_pix_ptr.a );
+
+ if yp < hm then
+ begin
+ inc(ptrcomp(src_pix_ptr ) ,stride );
+
+ inc(yp );
+
+ end;
+
+ stack_pix_ptr.r:=int8u_ptr(ptrcomp(src_pix_ptr ) + R )^;
+ stack_pix_ptr.g:=int8u_ptr(ptrcomp(src_pix_ptr ) + G )^;
+ stack_pix_ptr.b:=int8u_ptr(ptrcomp(src_pix_ptr ) + B )^;
+ stack_pix_ptr.a:=int8u_ptr(ptrcomp(src_pix_ptr ) + A )^;
+
+ inc(sum_in_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ );
+ inc(sum_in_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ );
+ inc(sum_in_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ );
+ inc(sum_in_a ,int8u_ptr(ptrcomp(src_pix_ptr ) + A )^ );
+ inc(sum_r ,sum_in_r );
+ inc(sum_g ,sum_in_g );
+ inc(sum_b ,sum_in_b );
+ inc(sum_a ,sum_in_a );
+
+ inc(stack_ptr );
+
+ if stack_ptr >= div_ then
+ stack_ptr:=0;
+
+ stack_pix_ptr:=stack.array_operator(stack_ptr );
+
+ inc(sum_out_r ,stack_pix_ptr.r );
+ inc(sum_out_g ,stack_pix_ptr.g );
+ inc(sum_out_b ,stack_pix_ptr.b );
+ inc(sum_out_a ,stack_pix_ptr.a );
+ dec(sum_in_r ,stack_pix_ptr.r );
+ dec(sum_in_g ,stack_pix_ptr.g );
+ dec(sum_in_b ,stack_pix_ptr.b );
+ dec(sum_in_a ,stack_pix_ptr.a );
+
+ inc(y );
+
+ end;
+
+ inc(x );
+
+ end;
+
+ end;
+
+ stack.Destruct;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_bounding_rect.pas b/src/corelib/render/software/agg_bounding_rect.pas
new file mode 100644
index 00000000..9ad6e388
--- /dev/null
+++ b/src/corelib/render/software/agg_bounding_rect.pas
@@ -0,0 +1,390 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 05.02.2006-Milano: Unit port establishment
+//
+{ agg_bounding_rect.pas }
+unit
+ agg_bounding_rect ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_vertex_source ;
+
+{ GLOBAL PROCEDURES }
+ function bounding_rect(
+ vs : vertex_source_ptr;
+ gi : unsigned_ptr;
+ start ,num : unsigned;
+ x1 ,y1 ,x2 ,y2 : double_ptr ) : boolean;
+
+ function bounding_rect_vs(
+ vs ,
+ gi : vertex_source_ptr;
+ start ,num : unsigned;
+ x1 ,y1 ,x2 ,y2 : double_ptr ) : boolean;
+
+ function bounding_rect_ul(
+ vs : vertex_source_ptr;
+ ul : unsigned_list_ptr;
+ start ,num : unsigned;
+ x1 ,y1 ,x2 ,y2 : double_ptr ) : boolean;
+
+ function bounding_rect_single(
+ vs : vertex_source_ptr;
+ path_id : unsigned;
+ x1 ,y1 ,x2 ,y2 : double_ptr ) : boolean;
+
+ function bounding_rect_all_paths(
+ vs : vertex_source_ptr;
+ x1 ,y1 ,x2 ,y2 : double_ptr ) : boolean;
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ BOUNDING_RECT }
+function bounding_rect;
+var
+ i ,cmd : unsigned;
+
+ x ,y : double;
+
+ first : boolean;
+
+begin
+ first:=true;
+
+ x1^:=1;
+ y1^:=1;
+ x2^:=0;
+ y2^:=0;
+
+ i:=0;
+
+ while i < num do
+ begin
+ vs.rewind(unsigned_ptr(ptrcomp(gi ) + (start + i ) * sizeof(unsigned ) )^ );
+
+ cmd:=vs.vertex(@x ,@y );
+
+ while not is_stop(cmd ) do
+ begin
+ if is_vertex(cmd ) then
+ if first then
+ begin
+ x1^:=x;
+ y1^:=y;
+ x2^:=x;
+ y2^:=y;
+
+ first:=false;
+
+ end
+ else
+ begin
+ if x < x1^ then
+ x1^:=x;
+
+ if y < y1^ then
+ y1^:=y;
+
+ if x > x2^ then
+ x2^:=x;
+
+ if y > y2^ then
+ y2^:=y;
+
+ end;
+
+ cmd:=vs.vertex(@x ,@y );
+
+ end;
+
+ inc(i );
+
+ end;
+
+ result:=(x1^ <= x2^ ) and (y1^ <= y2^ );
+
+end;
+
+{ BOUNDING_RECT_VS }
+function bounding_rect_vs;
+var
+ i ,cmd : unsigned;
+
+ x ,y : double;
+
+ first : boolean;
+
+begin
+ first:=true;
+
+ x1^:=1;
+ y1^:=1;
+ x2^:=0;
+ y2^:=0;
+
+ i:=0;
+
+ while i < num do
+ begin
+ vs.rewind(gi.operator_array(start + i ) );
+
+ cmd:=vs.vertex(@x ,@y );
+
+ while not is_stop(cmd ) do
+ begin
+ if is_vertex(cmd ) then
+ if first then
+ begin
+ x1^:=x;
+ y1^:=y;
+ x2^:=x;
+ y2^:=y;
+
+ first:=false;
+
+ end
+ else
+ begin
+ if x < x1^ then
+ x1^:=x;
+
+ if y < y1^ then
+ y1^:=y;
+
+ if x > x2^ then
+ x2^:=x;
+
+ if y > y2^ then
+ y2^:=y;
+
+ end;
+
+ cmd:=vs.vertex(@x ,@y );
+
+ end;
+
+ inc(i );
+
+ end;
+
+ result:=(x1^ <= x2^ ) and (y1^ <= y2^ );
+
+end;
+
+{ BOUNDING_RECT_UL }
+function bounding_rect_ul;
+var
+ i ,cmd : unsigned;
+
+ x ,y : double;
+
+ first : boolean;
+
+begin
+ first:=true;
+
+ x1^:=1;
+ y1^:=1;
+ x2^:=0;
+ y2^:=0;
+
+ i:=0;
+
+ while i < num do
+ begin
+ vs.rewind(ul.array_operator(start + i ) );
+
+ cmd:=vs.vertex(@x ,@y );
+
+ while not is_stop(cmd ) do
+ begin
+ if is_vertex(cmd ) then
+ if first then
+ begin
+ x1^:=x;
+ y1^:=y;
+ x2^:=x;
+ y2^:=y;
+
+ first:=false;
+
+ end
+ else
+ begin
+ if x < x1^ then
+ x1^:=x;
+
+ if y < y1^ then
+ y1^:=y;
+
+ if x > x2^ then
+ x2^:=x;
+
+ if y > y2^ then
+ y2^:=y;
+
+ end;
+
+ cmd:=vs.vertex(@x ,@y );
+
+ end;
+
+ inc(i );
+
+ end;
+
+ result:=(x1^ <= x2^ ) and (y1^ <= y2^ );
+
+end;
+
+{ BOUNDING_RECT_SINGLE }
+function bounding_rect_single;
+var
+ cmd : unsigned;
+ x ,y : double;
+ first : boolean;
+
+begin
+ first:=true;
+
+ x1^:=1;
+ y1^:=1;
+ x2^:=0;
+ y2^:=0;
+
+ vs.rewind(path_id );
+
+ cmd:=vs.vertex(@x ,@y );
+
+ while not is_stop(cmd ) do
+ begin
+ if is_vertex(cmd ) then
+ if first then
+ begin
+ x1^:=x;
+ y1^:=y;
+ x2^:=x;
+ y2^:=y;
+
+ first:=false;
+
+ end
+ else
+ begin
+ if x < x1^ then
+ x1^:=x;
+
+ if y < y1^ then
+ y1^:=y;
+
+ if x > x2^ then
+ x2^:=x;
+
+ if y > y2^ then
+ y2^:=y;
+
+ end;
+
+ cmd:=vs.vertex(@x ,@y );
+
+ end;
+
+ result:=
+ (x1^ <= x2^ ) and
+ (y1^ <= y2^ );
+
+end;
+
+{ BOUNDING_RECT_ALL_PATHS }
+function bounding_rect_all_paths(
+ vs : vertex_source_ptr;
+ x1 ,y1 ,x2 ,y2 : double_ptr ) : boolean;
+var
+ i ,paths : unsigned;
+
+ sx1 ,sy1 ,sx2 ,sy2 : double;
+
+ first : boolean;
+
+begin
+ first:=true;
+ paths:=vs.num_paths;
+
+ x1^:=1;
+ y1^:=1;
+ x2^:=0;
+ y2^:=0;
+
+ i:=0;
+
+ while i < paths do
+ begin
+ if bounding_rect_single(vs ,i ,@sx1 ,@sy1 ,@sx2 ,@sy2 ) then
+ begin
+ if first then
+ begin
+ x1^:=sx1;
+ y1^:=sy1;
+ x2^:=sx2;
+ y2^:=sy2;
+
+ end
+ else
+ begin
+ if sx1 < x1^ then
+ x1^:=sx1;
+
+ if sy1 < y1^ then
+ y1^:=sy1;
+
+ if sx2 > x2^ then
+ x2^:=sx2;
+
+ if sy2 > y2^ then
+ y2^:=sy2;
+
+ end;
+
+ first:=false;
+
+ end;
+
+ inc(i );
+
+ end;
+
+ result:=
+ (x1^ <= x2^ ) and
+ (y1^ <= y2^ );
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_bspline.pas b/src/corelib/render/software/agg_bspline.pas
new file mode 100644
index 00000000..5ccdce1f
--- /dev/null
+++ b/src/corelib/render/software/agg_bspline.pas
@@ -0,0 +1,478 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// class bspline
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 19.01.2006-Milano: Complete Unit Port
+// 18.01.2006-Milano: Unit port establishment
+//
+{ agg_bspline.pas }
+unit
+ agg_bspline ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ;
+
+{ TYPES DEFINITION }
+type
+//----------------------------------------------------------------bspline
+// A very simple class of Bi-cubic Spline interpolation.
+// First call init(num, x[], y[]) where num - number of source points,
+// x, y - arrays of X and Y values respectively. Here Y must be a function
+// of X. It means that all the X-coordinates must be arranged in the ascending
+// order.
+// Then call get(x) that calculates a value Y for the respective X.
+// The class supports extrapolation, i.e. you can call get(x) where x is
+// outside the given with init() X-range. Extrapolation is a simple linear
+// function.
+ bspline = object
+ m_max ,
+ m_num : int;
+
+ m_x ,
+ m_y ,
+ m_am : double_ptr;
+
+ m_last_idx : int;
+
+ constructor Construct; overload;
+ constructor Construct(num : int ); overload;
+ constructor Construct(num : int; x ,y : double_ptr ); overload;
+ destructor Destruct;
+
+ procedure init(max : int ); overload;
+ procedure init(num : int; x ,y : double_ptr ); overload;
+
+ procedure add_point(x ,y : double );
+ procedure prepare;
+
+ function get (x : double ) : double;
+ function get_stateful(x : double ) : double;
+
+ procedure bsearch(n : int; x : double_ptr; x0 : double; i : int_ptr );
+
+ function extrapolation_left (x : double ) : double;
+ function extrapolation_right(x : double ) : double;
+
+ function interpolation(x : double; i : int ) : double;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor bspline.Construct;
+begin
+ m_max:=0;
+ m_num:=0;
+
+ m_x :=NIL;
+ m_y :=NIL;
+ m_am:=NIL;
+
+ m_last_idx:=-1;
+
+end;
+
+{ CONSTRUCT }
+constructor bspline.Construct(num : int );
+begin
+ Construct;
+
+ init(num );
+
+end;
+
+{ CONSTRUCT }
+constructor bspline.Construct(num : int; x ,y : double_ptr );
+begin
+ Construct;
+
+ init(num ,x ,y );
+
+end;
+
+{ DESTRUCT }
+destructor bspline.Destruct;
+begin
+ agg_freemem(pointer(m_am ) ,m_max * 3 * sizeof(double ) );
+
+end;
+
+{ INIT }
+procedure bspline.init(max : int );
+begin
+ if (max > 2 ) and
+ (max > m_max ) then
+ begin
+ agg_freemem(pointer(m_am ) ,m_max * 3 * sizeof(double ) );
+ agg_getmem (pointer(m_am ) ,max * 3 * sizeof(double ) );
+
+ m_max:=max;
+
+ m_x:=double_ptr(ptrcomp(m_am ) + m_max * sizeof(double ) );
+ m_y:=double_ptr(ptrcomp(m_am ) + m_max * 2 * sizeof(double ) );
+
+ end;
+
+ m_num :=0;
+ m_last_idx:=-1;
+
+end;
+
+{ INIT }
+procedure bspline.init(num : int; x ,y : double_ptr );
+var
+ i : int;
+
+begin
+ if num > 2 then
+ begin
+ init(num );
+
+ for i:=0 to num - 1 do
+ begin
+ add_point(x^ ,y^ );
+
+ inc(ptrcomp(x ) ,sizeof(double ) );
+ inc(ptrcomp(y ) ,sizeof(double ) );
+
+ end;
+
+ prepare;
+
+ end;
+
+ m_last_idx:=-1;
+
+end;
+
+{ ADD_POINT }
+procedure bspline.add_point;
+begin
+ if m_num < m_max then
+ begin
+ double_ptr(ptrcomp(m_x ) + m_num * sizeof(double ) )^:=x;
+ double_ptr(ptrcomp(m_y ) + m_num * sizeof(double ) )^:=y;
+
+ inc(m_num );
+
+ end;
+
+end;
+
+{ PREPARE }
+procedure bspline.prepare;
+var
+ i ,k ,n1 ,sz : int;
+ temp ,r ,s ,al : double_ptr;
+ h ,p ,d ,f ,e : double;
+
+begin
+ if m_num > 2 then
+ begin
+ for k:=0 to m_num - 1 do
+ double_ptr(ptrcomp(m_am ) + k * sizeof(double ) )^:=0;
+
+ n1:=3 * m_num;
+ sz:=n1;
+
+ agg_getmem(pointer(al ) ,n1 * sizeof(double ) );
+
+ temp:=al;
+
+ for k:=0 to n1 - 1 do
+ double_ptr(ptrcomp(temp ) + k * sizeof(double ) )^:=0;
+
+ r:=double_ptr(ptrcomp(temp ) + m_num * sizeof(double ) );
+ s:=double_ptr(ptrcomp(temp ) + m_num * 2 * sizeof(double ) );
+
+ n1:=m_num - 1;
+ d :=double_ptr(ptrcomp(m_x ) + sizeof(double ) )^ - m_x^;
+ e :=(double_ptr(ptrcomp(m_y ) + sizeof(double ) )^ - m_y^ ) / d;
+
+ k:=1;
+
+ while k < n1 do
+ begin
+ h:=d;
+ d:=double_ptr(ptrcomp(m_x ) + (k + 1 ) * sizeof(double ) )^ - double_ptr(ptrcomp(m_x ) + k * sizeof(double ) )^;
+ f:=e;
+ e:=(double_ptr(ptrcomp(m_y ) + (k + 1 ) * sizeof(double ) )^ - double_ptr(ptrcomp(m_y ) + k * sizeof(double ) )^ ) / d;
+
+ double_ptr(ptrcomp(al ) + k * sizeof(double ) )^:=d / (d + h );
+ double_ptr(ptrcomp(r ) + k * sizeof(double ) )^ :=1.0 - double_ptr(ptrcomp(al ) + k * sizeof(double ) )^;
+ double_ptr(ptrcomp(s ) + k * sizeof(double ) )^ :=6.0 * (e - f ) / (h + d );
+
+ inc(k );
+
+ end;
+
+ k:=1;
+
+ while k < n1 do
+ begin
+ p:=1.0 / (double_ptr(ptrcomp(r ) + k * sizeof(double ) )^ * double_ptr(ptrcomp(al ) + (k - 1 ) * sizeof(double ) )^ + 2.0 );
+
+ double_ptr(ptrcomp(al ) + k * sizeof(double ) )^:=
+ double_ptr(ptrcomp(al ) + k * sizeof(double ) )^ * -p;
+
+ double_ptr(ptrcomp(s ) + k * sizeof(double ) )^ :=
+ (double_ptr(ptrcomp(s ) + k * sizeof(double ) )^ -
+ double_ptr(ptrcomp(r ) + k * sizeof(double ) )^ *
+ double_ptr(ptrcomp(s ) + (k - 1 ) * sizeof(double ) )^ ) * p;
+
+ inc(k );
+
+ end;
+
+ double_ptr(ptrcomp(m_am ) + n1 * sizeof(double ) )^:=0.0;
+
+ double_ptr(ptrcomp(al ) + (n1 - 1 ) * sizeof(double ) )^:=
+ double_ptr(ptrcomp(s ) + (n1 - 1 ) * sizeof(double ) )^;
+
+ double_ptr(ptrcomp(m_am ) + (n1 - 1 ) * sizeof(double ) )^:=
+ double_ptr(ptrcomp(al ) + (n1 - 1 ) * sizeof(double ) )^;
+
+ k:=n1 - 2;
+ i:=0;
+
+ while i < m_num - 2 do
+ begin
+ double_ptr(ptrcomp(al ) + k * sizeof(double ) )^:=
+ double_ptr(ptrcomp(al ) + k * sizeof(double ) )^ *
+ double_ptr(ptrcomp(al ) + (k + 1 ) * sizeof(double ) )^ +
+ double_ptr(ptrcomp(s ) + k * sizeof(double ) )^;
+
+ double_ptr(ptrcomp(m_am ) + k * sizeof(double ) )^:=
+ double_ptr(ptrcomp(al ) + k * sizeof(double ) )^;
+
+ inc(i );
+ dec(k );
+
+ end;
+
+ agg_freemem(pointer(al ) ,sz * sizeof(double ) );
+
+ end;
+
+ m_last_idx:=-1;
+
+end;
+
+{ GET }
+function bspline.get;
+var
+ i : int;
+
+begin
+ if m_num > 2 then
+ begin
+ // Extrapolation on the left
+ if x < m_x^ then
+ begin
+ result:=extrapolation_left(x );
+
+ exit;
+
+ end;
+
+ // Extrapolation on the right
+ if x >= double_ptr(ptrcomp(m_x ) + (m_num - 1 ) * sizeof(double ) )^ then
+ begin
+ result:=extrapolation_right(x );
+
+ exit;
+
+ end;
+
+ // Interpolation
+ bsearch(m_num ,m_x ,x ,@i );
+
+ result:=interpolation(x ,i );
+
+ exit;
+
+ end;
+
+ result:=0.0;
+
+end;
+
+{ GET_STATEFUL }
+function bspline.get_stateful;
+begin
+ if m_num > 2 then
+ begin
+ // Extrapolation on the left
+ if x < m_x^ then
+ begin
+ result:=extrapolation_left(x );
+
+ exit;
+
+ end;
+
+ // Extrapolation on the right
+ if x >= double_ptr(ptrcomp(m_x ) + (m_num - 1 ) * sizeof(double ) )^ then
+ begin
+ result:=extrapolation_right(x );
+
+ exit;
+
+ end;
+
+ if m_last_idx >= 0 then
+ begin
+ // Check if x is not in current range
+ if (x < double_ptr(ptrcomp(m_x ) + m_last_idx * sizeof(double ) )^ ) or
+ (x > double_ptr(ptrcomp(m_x ) + (m_last_idx + 1 ) * sizeof(double ) )^ ) then
+ // Check if x between next points (most probably)
+ if (m_last_idx < m_num - 2 ) and
+ (x >= double_ptr(ptrcomp(m_x ) + (m_last_idx + 1 ) * sizeof(double ) )^ ) and
+ (x <= double_ptr(ptrcomp(m_x ) + (m_last_idx + 2 ) * sizeof(double ) )^ ) then
+ inc(m_last_idx )
+ else
+ if (m_last_idx > 0 ) and
+ (x >= double_ptr(ptrcomp(m_x ) + (m_last_idx - 1 ) * sizeof(double ) )^ ) and
+ (x <= double_ptr(ptrcomp(m_x ) + m_last_idx * sizeof(double ) )^ ) then
+ // x is between pevious points
+ dec(m_last_idx )
+ else
+ // Else perform full search
+ bsearch(m_num ,m_x ,x ,@m_last_idx );
+
+ result:=interpolation(x ,m_last_idx );
+
+ exit;
+
+ end
+ else
+ begin
+ // Interpolation
+ bsearch(m_num ,m_x ,x ,@m_last_idx );
+
+ result:=interpolation(x ,m_last_idx );
+
+ exit;
+
+ end;
+
+ end;
+
+ result:=0.0;
+
+end;
+
+{ BSEARCH }
+procedure bspline.bsearch;
+var
+ j ,k : int;
+
+begin
+ j :=n - 1;
+ i^:=0;
+
+ while j - i^ > 1 do
+ begin
+ k:=shr_int32(i^ + j ,1 );
+
+ if x0 < double_ptr(ptrcomp(x ) + k * sizeof(double ) )^ then
+ j:=k
+ else
+ i^:=k;
+
+ end;
+
+end;
+
+{ EXTRAPOLATION_LEFT }
+function bspline.extrapolation_left;
+var
+ d : double;
+
+begin
+ d:=double_ptr(ptrcomp(m_x ) + sizeof(double ) )^ - m_x^;
+
+ result:=
+ (-d * double_ptr(ptrcomp(m_am ) + sizeof(double ) )^ / 6 +
+ (double_ptr(ptrcomp(m_y ) + sizeof(double ) )^ - m_y^ ) / d ) *
+ (x - m_x^ ) + m_y^;
+
+end;
+
+{ EXTRAPOLATION_RIGHT }
+function bspline.extrapolation_right;
+var
+ d : double;
+
+begin
+ d:=
+ double_ptr(ptrcomp(m_x ) + (m_num - 1 ) * sizeof(double ) )^ -
+ double_ptr(ptrcomp(m_x ) + (m_num - 2 ) * sizeof(double ) )^;
+
+ result:=
+ (d * double_ptr(ptrcomp(m_am ) + (m_num - 2 ) * sizeof(double ) )^ / 6 +
+ (double_ptr(ptrcomp(m_y ) + (m_num - 1 ) * sizeof(double ) )^ -
+ double_ptr(ptrcomp(m_y ) + (m_num - 2 ) * sizeof(double ) )^ ) / d ) *
+ (x - double_ptr(ptrcomp(m_x ) + (m_num - 1 ) * sizeof(double ) )^ ) +
+ double_ptr(ptrcomp(m_y ) + (m_num - 1 ) * sizeof(double ) )^;
+
+end;
+
+{ INTERPOLATION }
+function bspline.interpolation;
+var
+ j : int;
+
+ d ,h ,r ,p : double;
+
+begin
+ j:=i + 1;
+ d:=double_ptr(ptrcomp(m_x ) + i * sizeof(double ) )^ - double_ptr(ptrcomp(m_x ) + j * sizeof(double ) )^;
+ h:=x - double_ptr(ptrcomp(m_x ) + j * sizeof(double ) )^;
+ r:=double_ptr(ptrcomp(m_x ) + i * sizeof(double ) )^ - x;
+ p:=d * d / 6.0;
+
+ result:=
+ (double_ptr(ptrcomp(m_am ) + j * sizeof(double ) )^ * r * r * r +
+ double_ptr(ptrcomp(m_am ) + i * sizeof(double ) )^ * h * h * h ) / 6.0 / d +
+ ((double_ptr(ptrcomp(m_y ) + j * sizeof(double ) )^ -
+ double_ptr(ptrcomp(m_am ) + j * sizeof(double ) )^ * p ) * r +
+ (double_ptr(ptrcomp(m_y ) + i * sizeof(double ) )^ -
+ double_ptr(ptrcomp(m_am ) + i * sizeof(double ) )^ * p ) * h ) / d;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_clip_liang_barsky.pas b/src/corelib/render/software/agg_clip_liang_barsky.pas
new file mode 100644
index 00000000..ee0840bc
--- /dev/null
+++ b/src/corelib/render/software/agg_clip_liang_barsky.pas
@@ -0,0 +1,511 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 20.01.2006-Milano: Unit port establishment
+//
+{ agg_clip_liang_barsky.pas }
+unit
+ agg_clip_liang_barsky ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ;
+
+{ GLOBAL PROCEDURES }
+ function clipping_flags_int(x ,y : int; clip_box : rect_ptr ) : unsigned;
+ function clipping_flags_dbl(x ,y : double; clip_box : rect_d_ptr ) : unsigned;
+
+ function clipping_flags_x_int(x : int; clip_box : rect_ptr ) : unsigned;
+ function clipping_flags_x_dbl(x : double; clip_box : rect_d_ptr ) : unsigned;
+
+ function clipping_flags_y_int(y : int; clip_box : rect_ptr ) : unsigned;
+ function clipping_flags_y_dbl(y : double; clip_box : rect_d_ptr ) : unsigned;
+
+ function clip_liang_barsky_int(x1 ,y1 ,x2 ,y2 : int; clip_box : rect_ptr; x ,y : int_ptr ) : unsigned;
+ function clip_liang_barsky_d (x1 ,y1 ,x2 ,y2 : double; clip_box : rect_d_ptr; x ,y : double_ptr ) : unsigned;
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CLIPPING_FLAGS_INT }
+//
+// Determine the clipping code of the vertex according to the
+// Cyrus-Beck line clipping algorithm
+//
+// | |
+// 0110 | 0010 | 0011
+// | |
+// -------+--------+-------- clip_box.y2
+// | |
+// 0100 | 0000 | 0001
+// | |
+// -------+--------+-------- clip_box.y1
+// | |
+// 1100 | 1000 | 1001
+// | |
+// clip_box.x1 clip_box.x2
+//
+//
+function clipping_flags_int;
+begin
+ result:=
+ unsigned(x > clip_box.x2 ) or
+ (unsigned(y > clip_box.y2 ) shl 1 ) or
+ (unsigned(x < clip_box.x1 ) shl 2 ) or
+ (unsigned(y < clip_box.y1 ) shl 3 );
+
+end;
+
+{ CLIPPING_FLAGS_DBL }
+function clipping_flags_dbl(x ,y : double; clip_box : rect_d_ptr ) : unsigned;
+begin
+ result:=
+ unsigned(x > clip_box.x2 ) or
+ (unsigned(y > clip_box.y2 ) shl 1 ) or
+ (unsigned(x < clip_box.x1 ) shl 2 ) or
+ (unsigned(y < clip_box.y1 ) shl 3 );
+
+end;
+
+{ CLIPPING_FLAGS_X_INT }
+function clipping_flags_x_int(x : int; clip_box : rect_ptr ) : unsigned;
+begin
+ result:=
+ unsigned(x > clip_box.x2 ) or
+ (unsigned(x < clip_box.x1 ) shl 2 );
+
+end;
+
+{ CLIPPING_FLAGS_X_DBL }
+function clipping_flags_x_dbl(x : double; clip_box : rect_d_ptr ) : unsigned;
+begin
+ result:=
+ unsigned(x > clip_box.x2 ) or
+ (unsigned(x < clip_box.x1 ) shl 2 );
+
+end;
+
+{ CLIPPING_FLAGS_Y_INT }
+function clipping_flags_y_int(y : int; clip_box : rect_ptr ) : unsigned;
+begin
+ result:=
+ (unsigned(y > clip_box.y2 ) shl 1 ) or
+ (unsigned(y < clip_box.y1 ) shl 3 );
+
+end;
+
+{ CLIPPING_FLAGS_Y_DBL }
+function clipping_flags_y_dbl(y : double; clip_box : rect_d_ptr ) : unsigned;
+begin
+ result:=
+ (unsigned(y > clip_box.y2 ) shl 1 ) or
+ (unsigned(y < clip_box.y1 ) shl 3 );
+
+end;
+
+{ CLIP_LIANG_BARSKY_INT }
+function clip_liang_barsky_int;
+const
+ nearzero = 1e-30;
+
+var
+ deltax ,
+ deltay ,
+ xin ,
+ xout ,
+ yin ,
+ yout ,
+ tinx ,
+ tiny ,
+ toutx ,
+ touty ,
+ tin1 ,
+ tin2 ,
+ tout1 : double;
+
+ np : unsigned;
+
+begin
+ deltax:=x2 - x1;
+ deltay:=y2 - y1;
+
+ np:=0;
+
+// bump off of the vertical
+ if deltax = 0.0 then
+ if x1 > clip_box.x1 then
+ deltax:=-nearzero
+ else
+ deltax:=nearzero;
+
+// bump off of the horizontal
+ if deltay = 0.0 then
+ if y1 > clip_box.y1 then
+ deltay:=-nearzero
+ else
+ deltay:=nearzero;
+
+ if deltax > 0.0 then
+ begin
+ // points to right
+ xin :=clip_box.x1;
+ xout:=clip_box.x2;
+
+ end
+ else
+ begin
+ xin :=clip_box.x2;
+ xout:=clip_box.x1;
+
+ end;
+
+ if deltay > 0.0 then
+ begin
+ // points up
+ yin :=clip_box.y1;
+ yout:=clip_box.y2;
+
+ end
+ else
+ begin
+ yin :=clip_box.y2;
+ yout:=clip_box.y1;
+
+ end;
+
+ tinx:=(xin - x1 ) / deltax;
+ tiny:=(yin - y1 ) / deltay;
+
+ if tinx < tiny then
+ begin
+ // hits x first
+ tin1:=tinx;
+ tin2:=tiny;
+
+ end
+ else
+ begin
+ // hits y first
+ tin1:=tiny;
+ tin2:=tinx;
+
+ end;
+
+ if tin1 <= 1.0 then
+ begin
+ if 0.0 < tin1 then
+ begin
+ x^:=trunc(xin );
+ y^:=trunc(yin );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(np );
+
+ end;
+
+ if tin2 <= 1.0 then
+ begin
+ toutx:=(xout - x1 ) / deltax;
+ touty:=(yout - y1 ) / deltay;
+
+ if toutx < touty then
+ tout1:=toutx
+ else
+ tout1:=touty;
+
+ if (tin2 > 0.0 ) or
+ (tout1 > 0.0 ) then
+ if tin2 <= tout1 then
+ begin
+ if tin2 > 0.0 then
+ begin
+ if tinx > tiny then
+ begin
+ x^:=trunc(xin );
+ y^:=trunc(y1 + tinx * deltay );
+
+ end
+ else
+ begin
+ x^:=trunc(x1 + tiny * deltax );
+ y^:=trunc(yin );
+
+ end;
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(np );
+
+ end;
+
+ if tout1 < 1.0 then
+ if toutx < touty then
+ begin
+ x^:=trunc(xout );
+ y^:=trunc(y1 + toutx * deltay );
+
+ end
+ else
+ begin
+ x^:=trunc(x1 + touty * deltax );
+ y^:=trunc(yout );
+
+ end
+ else
+ begin
+ x^:=x2;
+ y^:=y2;
+
+ end;
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(np );
+
+ end
+ else
+ begin
+ if tinx > tiny then
+ begin
+ x^:=trunc(xin );
+ y^:=trunc(yout );
+
+ end
+ else
+ begin
+ x^:=trunc(xout );
+ y^:=trunc(yin );
+
+ end;
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(np );
+
+ end;
+
+ end;
+
+ end;
+
+ result:=np;
+
+end;
+
+{ CLIP_LIANG_BARSKY_D }
+function clip_liang_barsky_d;
+const
+ nearzero = 1e-30;
+
+var
+ deltax ,
+ deltay ,
+ xin ,
+ xout ,
+ yin ,
+ yout ,
+ tinx ,
+ tiny ,
+ toutx ,
+ touty ,
+ tin1 ,
+ tin2 ,
+ tout1 : double;
+
+ np : unsigned;
+
+begin
+ deltax:=x2 - x1;
+ deltay:=y2 - y1;
+
+ np:=0;
+
+// bump off of the vertical
+ if deltax = 0.0 then
+ if x1 > clip_box.x1 then
+ deltax:=-nearzero
+ else
+ deltax:=nearzero;
+
+// bump off of the horizontal
+ if deltay = 0.0 then
+ if y1 > clip_box.y1 then
+ deltay:=-nearzero
+ else
+ deltay:=nearzero;
+
+ if deltax > 0.0 then
+ begin
+ // points to right
+ xin :=clip_box.x1;
+ xout:=clip_box.x2;
+
+ end
+ else
+ begin
+ xin :=clip_box.x2;
+ xout:=clip_box.x1;
+
+ end;
+
+ if deltay > 0.0 then
+ begin
+ // points up
+ yin :=clip_box.y1;
+ yout:=clip_box.y2;
+
+ end
+ else
+ begin
+ yin :=clip_box.y2;
+ yout:=clip_box.y1;
+
+ end;
+
+ tinx:=(xin - x1 ) / deltax;
+ tiny:=(yin - y1 ) / deltay;
+
+ if tinx < tiny then
+ begin
+ // hits x first
+ tin1:=tinx;
+ tin2:=tiny;
+
+ end
+ else
+ begin
+ // hits y first
+ tin1:=tiny;
+ tin2:=tinx;
+
+ end;
+
+ if tin1 <= 1.0 then
+ begin
+ if 0.0 < tin1 then
+ begin
+ x^:=xin;
+ y^:=yin;
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(np );
+
+ end;
+
+ if tin2 <= 1.0 then
+ begin
+ toutx:=(xout - x1 ) / deltax;
+ touty:=(yout - y1 ) / deltay;
+
+ if toutx < touty then
+ tout1:=toutx
+ else
+ tout1:=touty;
+
+ if (tin2 > 0.0 ) or
+ (tout1 > 0.0 ) then
+ if tin2 <= tout1 then
+ begin
+ if tin2 > 0.0 then
+ begin
+ if tinx > tiny then
+ begin
+ x^:=xin;
+ y^:=y1 + tinx * deltay;
+
+ end
+ else
+ begin
+ x^:=x1 + tiny * deltax;
+ y^:=yin;
+
+ end;
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(np );
+
+ end;
+
+ if tout1 < 1.0 then
+ if toutx < touty then
+ begin
+ x^:=xout;
+ y^:=y1 + toutx * deltay;
+
+ end
+ else
+ begin
+ x^:=x1 + touty * deltax;
+ y^:=yout;
+
+ end
+ else
+ begin
+ x^:=x2;
+ y^:=y2;
+
+ end;
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(np );
+
+ end
+ else
+ begin
+ if tinx > tiny then
+ begin
+ x^:=xin;
+ y^:=yout;
+
+ end
+ else
+ begin
+ x^:=xout;
+ y^:=yin;
+
+ end;
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(np );
+
+ end;
+
+ end;
+
+ end;
+
+ result:=np;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_color.pas b/src/corelib/render/software/agg_color.pas
new file mode 100644
index 00000000..089b2c95
--- /dev/null
+++ b/src/corelib/render/software/agg_color.pas
@@ -0,0 +1,515 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// Adaptation for high precision colors has been sponsored by
+// Liberty Technology Systems, Inc., visit http://lib-sys.com
+//
+// Liberty Technology Systems, Inc. is the provider of
+// PostScript and PDF technology for software developers.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 16.11.2005-Milano: Unit port establishment
+//
+{ agg_color.pas }
+unit
+ agg_color ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+{$Q- }
+{$R- }
+
+uses
+ Math ,
+ agg_basics ;
+
+{ TYPES DEFINITION }
+type
+ order_rgb = record R ,G ,B : byte end;
+ order_bgr = record B ,G ,R : byte end;
+ order_rgba = record R ,G ,B ,A : byte end;
+ order_bgra = record B ,G ,R ,A : byte end;
+ order_argb = record A ,R ,G ,B : byte end;
+ order_abgr = record A ,B ,G ,R : byte end;
+
+ order_type = record
+ R ,G ,B ,A : int8u;
+
+ end;
+
+const
+ base_shift = 8;
+ base_size = 1 shl base_shift;
+ base_mask = base_size - 1;
+
+ rgb_order : order_type = (R:0; G:1; B:2; A:3 );
+ bgr_order : order_type = (R:2; G:1; B:0; A:3 );
+ rgba_order : order_type = (R:0; G:1; B:2; A:3 );
+ bgra_order : order_type = (R:2; G:1; B:0; A:3 );
+ argb_order : order_type = (R:1; G:2; B:3; A:0 );
+ abgr_order : order_type = (R:3; G:2; B:1; A:0 );
+
+type
+ rgba8_ptr_ptr = ^rgba8_ptr;
+ rgba8_ptr = ^rgba8;
+ rgba8 = object
+ r ,g ,b ,a : int8u;
+
+ constructor Construct(r_ ,g_ ,b_ : unsigned; a_ : unsigned = base_mask );
+
+ procedure no_color;
+ function gradient(c : rgba8; k : double ) : rgba8;
+
+ end;
+
+ aggclr_ptr = ^aggclr;
+ aggclr = object
+ v ,r ,g ,b ,a : int8u;
+
+ constructor Construct; overload;
+ constructor Construct(rgba : rgba8 ); overload;
+ constructor Construct(clr : aggclr_ptr ); overload;
+ constructor ConstrInt(v_ : unsigned; a_ : unsigned = base_mask ); overload;
+ constructor ConstrInt(r_ ,g_ ,b_ : unsigned; a_ : unsigned = base_mask ); overload;
+ constructor ConstrMix(r_ ,g_ ,b_ : unsigned; a_ : double = 1.0 );
+ constructor ConstrDbl(r_ ,g_ ,b_ : double; a_ : double = 1.0 );
+ constructor ConstrPre(r_ ,g_ ,b_ : double; a_ : double = 1.0 );
+
+ constructor from_wavelength(wl ,gamma : double );
+
+ function gradient (c : aggclr_ptr; k : double ) : aggclr;
+ function gradient8(c : aggclr_ptr; k : double ) : rgba8;
+
+ procedure add(c : aggclr_ptr; cover : unsigned );
+
+ function opacity_(a_ : double ) : aggclr_ptr;
+ function _opacity : double;
+
+ procedure clear;
+ function premultiply : aggclr_ptr;
+ procedure apply_gamma_dir(gamma_ : gamma_ptr );
+
+ end;
+
+{ GLOBAL PROCEDURES }
+ function rgb8_packed (v : unsigned ) : rgba8;
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor rgba8.Construct;
+begin
+ b{*}:=int8u(r_ );
+ g:=int8u(g_ );
+ r:=int8u(b_ );
+ a:=int8u(a_ );
+
+end;
+
+{ NO_COLOR }
+procedure rgba8.no_color;
+begin
+ r:=0;
+ g:=0;
+ b:=0;
+ a:=0;
+
+end;
+
+{ GRADIENT }
+function rgba8.gradient(c : rgba8; k : double ) : rgba8;
+var
+ ik : int32u; // calc_type
+
+begin
+ ik:=Trunc(k * base_size );
+
+ result.r:=int8u(int32u(r ) + (((int32u(c.r ) - r ) * ik ) shr base_shift ) );
+ result.g:=int8u(int32u(g ) + (((int32u(c.g ) - g ) * ik ) shr base_shift ) );
+ result.b:=int8u(int32u(b ) + (((int32u(c.b ) - b ) * ik ) shr base_shift ) );
+ result.a:=int8u(int32u(a ) + (((int32u(c.a ) - a ) * ik ) shr base_shift ) );
+
+end;
+
+{ CONSTRUCT }
+constructor aggclr.Construct;
+begin
+ v:=0;
+ r:=0;
+ g:=0;
+ b:=0;
+ a:=0;
+
+end;
+
+{ CONSTRUCT }
+constructor aggclr.Construct(rgba : rgba8 );
+begin
+ v:=(rgba.r * 77 + rgba.g * 150 + rgba.b * 29 ) shr 8;
+ r:=rgba.r;
+ g:=rgba.g;
+ b:=rgba.b;
+ a:=rgba.a;
+
+end;
+
+{ CONSTRUCT }
+constructor aggclr.Construct(clr : aggclr_ptr );
+begin
+ v:=clr.v;
+ r:=clr.r;
+ g:=clr.g;
+ b:=clr.b;
+ a:=clr.a;
+
+end;
+
+{ CONSTRINT }
+constructor aggclr.ConstrInt(v_ : unsigned; a_ : unsigned = base_mask );
+begin
+ v:=int8u(v_ );
+ r:=0;
+ g:=0;
+ b:=0;
+ a:=int8u(a_ );
+
+end;
+
+{ CONSTRINT }
+constructor aggclr.ConstrInt(r_ ,g_ ,b_ : unsigned; a_ : unsigned = base_mask );
+begin
+ v:=(r_ * 77 + g_ * 150 + b_ * 29 ) shr 8;
+ r:=int8u(r_ );
+ g:=int8u(g_ );
+ b:=int8u(b_ );
+ a:=int8u(a_ );
+
+end;
+
+{ CONSTRDBL }
+constructor aggclr.ConstrDbl;
+begin
+ v:=trunc((0.299 * r_ + 0.587 * g_ + 0.114 * b_ ) * base_mask + 0.5 );
+ r:=trunc(r_ * base_mask + 0.5 );
+ g:=trunc(g_ * base_mask + 0.5 );
+ b:=trunc(b_ * base_mask + 0.5 );
+ a:=trunc(a_ * base_mask + 0.5 );
+
+end;
+
+{ CONSTRPRE }
+constructor aggclr.ConstrPre;
+begin
+ r_:=r_ * a_;
+ g_:=g_ * a_;
+ b_:=b_ * a_;
+
+ ConstrDbl(r_ ,g_ ,b_ ,a_ );
+
+end;
+
+{ CONSTRMIX }
+constructor aggclr.ConstrMix;
+begin
+ v:=(r_ * 77 + g_ * 150 + b_ * 29 ) shr 8;
+ r:=r_;
+ g:=g_;
+ b:=b_;
+ a:=trunc(a_ * base_mask + 0.5 );
+
+end;
+
+{ FROM_WAVELENGTH }
+constructor aggclr.from_wavelength(wl ,gamma : double );
+var
+ tr ,tg ,tb ,ta ,s : double;
+
+begin
+ tr:=0;
+ tg:=0;
+ tb:=0;
+ ta:=0;
+
+ if (wl >= 380.0 ) and
+ (wl <= 440.0 ) then
+ begin
+ tr:=-1.0 * (wl - 440.0 ) / (440.0 - 380.0 );
+ tb:=1.0;
+
+ end
+ else
+ if (wl >= 440.0 ) and
+ (wl <= 490.0 ) then
+ begin
+ tg:=(wl - 440.0 ) / (490.0 - 440.0 );
+ tb:=1.0;
+
+ end
+ else
+ if (wl >= 490.0 ) and
+ (wl <= 510.0 ) then
+ begin
+ tg:=1.0;
+ tb:=-1.0 * (wl - 510.0 ) / (510.0 - 490.0 );
+
+ end
+ else
+ if (wl >= 510.0 ) and
+ (wl <= 580.0 ) then
+ begin
+ tr:=(wl - 510.0 ) / (580.0 - 510.0 );
+ tg:=1.0;
+
+ end
+ else
+ if (wl >= 580.0 ) and
+ (wl <= 645.0 ) then
+ begin
+ tr:=1.0;
+ tg:=-1.0 * (wl - 645.0 ) / (645.0 - 580.0 );
+
+ end
+ else
+ if (wl >= 645.0 ) and
+ (wl <= 780.0 ) then
+ tr:=1.0;
+
+ s:=1.0;
+
+ if wl > 700.0 then
+ s:=0.3 + 0.7 * (780.0 - wl ) / (780.0 - 700.0 )
+ else
+ if wl < 420.0 then
+ s:=0.3 + 0.7 * (wl - 380.0 ) / (420.0 - 380.0 );
+
+ tr:=Power(tr * s ,gamma );
+ tg:=Power(tg * s ,gamma );
+ tb:=Power(tb * s ,gamma );
+
+ ConstrDbl(tr ,tg ,tb );
+
+end;
+
+{ GRADIENT }
+function aggclr.gradient;
+var
+ ik : unsigned;
+
+begin
+ ik:=trunc(k * base_size );
+
+ result.r:=int8u(r + (((c.r - r ) * ik ) shr base_shift ) );
+ result.g:=int8u(g + (((c.g - g ) * ik ) shr base_shift ) );
+ result.b:=int8u(b + (((c.b - b ) * ik ) shr base_shift ) );
+ result.a:=int8u(a + (((c.a - a ) * ik ) shr base_shift ) );
+
+end;
+
+{ GRADIENT8 }
+function aggclr.gradient8;
+var
+ ik : unsigned;
+
+begin
+ ik:=trunc(k * base_size );
+
+ result.r:=int8u(r + (((c.r - r ) * ik ) shr base_shift ) );
+ result.g:=int8u(g + (((c.g - g ) * ik ) shr base_shift ) );
+ result.b:=int8u(b + (((c.b - b ) * ik ) shr base_shift ) );
+ result.a:=int8u(a + (((c.a - a ) * ik ) shr base_shift ) );
+
+end;
+
+{ ADD }
+procedure aggclr.add(c : aggclr_ptr; cover : unsigned );
+var
+ cv ,cr ,cg ,cb ,ca : int32u;
+
+begin
+ if cover = cover_mask then
+ if c.a = base_mask then
+ Construct(c )
+ else
+ begin
+ cv:=v + c.v;
+
+ if cv > int32u(base_mask ) then
+ v:=int8u(base_mask )
+ else
+ v:=int8u(cv );
+
+ cr:=r + c.r;
+
+ if cr > int32u(base_mask ) then
+ r:=int8u(base_mask )
+ else
+ r:=int8u(cr );
+
+ cg:=g + c.g;
+
+ if cg > int32u(base_mask ) then
+ g:=int8u(base_mask )
+ else
+ g:=int8u(cg );
+
+ cb:=b + c.b;
+
+ if cb > int32u(base_mask ) then
+ b:=int8u(base_mask )
+ else
+ b:=int8u(cb );
+
+ ca:=a + c.a;
+
+ if ca > int32u(base_mask ) then
+ a:=int8u(base_mask )
+ else
+ a:=int8u(ca );
+
+ end
+ else
+ begin
+ cv:=v + ((c.v * cover + cover_mask div 2 ) shr cover_shift );
+ cr:=r + ((c.r * cover + cover_mask div 2 ) shr cover_shift );
+ cg:=g + ((c.g * cover + cover_mask div 2 ) shr cover_shift );
+ cb:=b + ((c.b * cover + cover_mask div 2 ) shr cover_shift );
+ ca:=a + ((c.a * cover + cover_mask div 2 ) shr cover_shift );
+
+ if cv > int32u(base_mask ) then
+ v:=int8u(base_mask )
+ else
+ v:=int8u(cv );
+
+ if cr > int32u(base_mask ) then
+ r:=int8u(base_mask )
+ else
+ r:=int8u(cr );
+
+ if cg > int32u(base_mask ) then
+ g:=int8u(base_mask )
+ else
+ g:=int8u(cg );
+
+ if cb > int32u(base_mask ) then
+ b:=int8u(base_mask )
+ else
+ b:=int8u(cb );
+
+ if ca > int32u(base_mask ) then
+ a:=int8u(base_mask )
+ else
+ a:=int8u(ca );
+
+ end;
+
+end;
+
+{ OPACITY_ }
+function aggclr.opacity_;
+begin
+ if a_ < 0.0 then
+ a_:=0.0;
+
+ if a_ > 1.0 then
+ a_:=1.0;
+
+ a:=trunc(a_ * base_mask + 0.5 );
+
+ result:=@self;
+
+end;
+
+{ _OPACITY }
+function aggclr._opacity;
+begin
+ result:=a / base_mask;
+
+end;
+
+{ CLEAR }
+procedure aggclr.clear;
+begin
+ v:=0;
+ r:=0;
+ g:=0;
+ b:=0;
+ a:=0;
+
+end;
+
+{ PREMULTIPLY }
+function aggclr.premultiply : aggclr_ptr;
+begin
+ if a = base_mask then
+ begin
+ result:=@self;
+
+ exit;
+
+ end;
+
+ if a = 0 then
+ begin
+ v:=0;
+ r:=0;
+ g:=0;
+ b:=0;
+
+ result:=@self;
+
+ exit;
+
+ end;
+
+ v:=int8u((v * a ) shr base_shift );
+ r:=int8u((r * a ) shr base_shift );
+ g:=int8u((g * a ) shr base_shift );
+ b:=int8u((b * a ) shr base_shift );
+
+end;
+
+{ APPLY_GAMMA_DIR }
+procedure aggclr.apply_gamma_dir;
+begin
+ v:=int8u(gamma_.dir(v ) );
+ r:=int8u(gamma_.dir(r ) );
+ g:=int8u(gamma_.dir(g ) );
+ b:=int8u(gamma_.dir(b ) );
+
+end;
+
+{ RGB8_PACKED }
+function rgb8_packed;
+begin
+ result.r:=(v shr 16) and $FF;
+ result.g:=(v shr 8) and $FF;
+ result.b:=v and $FF;
+ result.a:=base_mask;
+
+end;
+
+END.
+
+{*}
diff --git a/src/corelib/render/software/agg_conv_adaptor_vcgen.pas b/src/corelib/render/software/agg_conv_adaptor_vcgen.pas
new file mode 100644
index 00000000..d98e6ba5
--- /dev/null
+++ b/src/corelib/render/software/agg_conv_adaptor_vcgen.pas
@@ -0,0 +1,321 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 20.12.2005-Milano: Unit port establishment
+//
+{ agg_conv_adaptor_vcgen.pas }
+unit
+ agg_conv_adaptor_vcgen ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_vertex_source ;
+
+{ TYPES DEFINITION }
+type
+//------------------------------------------------------------null_markers
+ null_markers_ptr = ^null_markers;
+ null_markers = object(vertex_source )
+ m_markers : vertex_source_ptr;
+
+ constructor Construct;
+
+ procedure remove_all; virtual;
+ procedure add_vertex(x ,y : double; cmd : unsigned ); virtual;
+ procedure prepare_src;
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ procedure set_markers(m : vertex_source_ptr );
+
+ end;
+
+//------------------------------------------------------conv_adaptor_vcgen
+ status = (initial ,accumulate ,generate );
+
+ conv_adaptor_vcgen_ptr = ^conv_adaptor_vcgen;
+ conv_adaptor_vcgen = object(vertex_source )
+ m_source ,
+ m_generator : vertex_source_ptr;
+ m_markers : null_markers;
+ m_status : status;
+ m_last_cmd : unsigned;
+ m_start_x ,
+ m_start_y : double;
+
+ constructor Construct(source ,gen : vertex_source_ptr );
+
+ procedure set_source (source : vertex_source_ptr );
+ procedure set_markers(m : vertex_source_ptr );
+
+ function generator : vertex_source_ptr;
+ function markers : vertex_source_ptr;
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor null_markers.Construct;
+begin
+ inherited Construct;
+
+ m_markers:=NIL;
+
+end;
+
+{ REMOVE_ALL }
+procedure null_markers.remove_all;
+begin
+ if m_markers <> NIL then
+ m_markers.remove_all;
+
+end;
+
+{ ADD_VERTEX }
+procedure null_markers.add_vertex;
+begin
+ if m_markers <> NIL then
+ m_markers.add_vertex(x ,y ,cmd );
+
+end;
+
+{ PREPARE_SRC }
+procedure null_markers.prepare_src;
+begin
+end;
+
+{ REWIND }
+procedure null_markers.rewind;
+begin
+ if m_markers <> NIL then
+ m_markers.rewind(path_id );
+
+end;
+
+{ VERTEX }
+function null_markers.vertex;
+begin
+ if m_markers <> NIL then
+ result:=m_markers.vertex(x ,y )
+ else
+ result:=path_cmd_stop;
+
+end;
+
+{ SET_MARKERS }
+procedure null_markers.set_markers;
+begin
+ m_markers:=m;
+
+end;
+
+{ CONSTRUCT }
+constructor conv_adaptor_vcgen.Construct;
+begin
+ inherited Construct;
+
+ m_source:=source;
+ m_status:=initial;
+
+ m_generator:=gen;
+
+ m_markers.Construct;
+
+ m_last_cmd:=0;
+ m_start_x :=0;
+ m_start_y :=0;
+
+end;
+
+{ SET_SOURCE }
+procedure conv_adaptor_vcgen.set_source;
+begin
+ m_source:=source;
+
+end;
+
+{ SET_MARKERS }
+procedure conv_adaptor_vcgen.set_markers;
+begin
+ m_markers.set_markers(m );
+
+end;
+
+{ GENERATOR }
+function conv_adaptor_vcgen.generator;
+begin
+ result:=m_generator;
+
+end;
+
+{ MARKERS }
+function conv_adaptor_vcgen.markers;
+begin
+ if m_markers.m_markers <> NIL then
+ result:=m_markers.m_markers
+ else
+ result:=@m_markers;
+
+end;
+
+{ REWIND }
+procedure conv_adaptor_vcgen.rewind;
+begin
+ m_source.rewind(path_id );
+
+ m_status:=initial;
+
+end;
+
+{ VERTEX }
+function conv_adaptor_vcgen.vertex;
+var
+ cmd : unsigned;
+ done : boolean;
+
+label
+ _acc ,_gen ,_end ;
+
+begin
+ cmd :=path_cmd_stop;
+ done:=false;
+
+ while not done do
+ begin
+ case m_status of
+ initial :
+ begin
+ m_markers.remove_all;
+
+ m_last_cmd:=m_source.vertex(@m_start_x ,@m_start_y );
+ m_status :=accumulate;
+
+ goto _acc;
+
+ end;
+
+ accumulate :
+ begin
+ _acc:
+ if is_stop(m_last_cmd ) then
+ begin
+ result:=path_cmd_stop;
+
+ exit;
+
+ end;
+
+ m_generator.remove_all;
+ m_generator.add_vertex(m_start_x ,m_start_y ,path_cmd_move_to );
+ m_markers.add_vertex (m_start_x ,m_start_y ,path_cmd_move_to );
+
+ repeat
+ cmd:=m_source.vertex(x ,y );
+
+ if is_vertex(cmd ) then
+ begin
+ m_last_cmd:=cmd;
+
+ if is_move_to(cmd ) then
+ begin
+ m_start_x:=x^;
+ m_start_y:=y^;
+
+ break;
+
+ end;
+
+ m_generator.add_vertex(x^ ,y^ ,cmd );
+ m_markers.add_vertex(x^ ,y^ ,path_cmd_line_to );
+
+ end
+ else
+ begin
+ if is_stop(cmd ) then
+ begin
+ m_last_cmd:=path_cmd_stop;
+
+ break;
+
+ end;
+
+ if is_end_poly(cmd ) then
+ begin
+ m_generator.add_vertex(x^ ,y^ ,cmd );
+
+ break;
+
+ end;
+
+ end;
+
+ until false;
+
+ m_generator.rewind(0 );
+
+ m_status:=generate;
+
+ goto _gen;
+
+ end;
+
+ generate :
+ begin
+ _gen:
+ cmd:=m_generator.vertex(x ,y );
+
+ if is_stop(cmd ) then
+ begin
+ m_status:=accumulate;
+
+ goto _end;
+
+ end;
+
+ done:=true;
+
+ end;
+
+ end;
+
+ _end:
+ end;
+
+ result:=cmd;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_conv_adaptor_vpgen.pas b/src/corelib/render/software/agg_conv_adaptor_vpgen.pas
new file mode 100644
index 00000000..1b6f83c0
--- /dev/null
+++ b/src/corelib/render/software/agg_conv_adaptor_vpgen.pas
@@ -0,0 +1,234 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 24.01.2006-Milano: Unit port establishment
+//
+{ agg_conv_adaptor_vpgen.pas }
+unit
+ agg_conv_adaptor_vpgen ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_vertex_source ,
+ agg_vpgen_segmentator ;
+
+{ TYPES DEFINITION }
+type
+ conv_adaptor_vpgen = object(vertex_source )
+ m_source ,
+ m_vpgen : vertex_source_ptr;
+ m_start_x ,
+ m_start_y : double;
+
+ m_poly_flags : unsigned;
+ m_vertices : int;
+
+ constructor Construct(source ,gen : vertex_source_ptr );
+
+ procedure set_source(source : vertex_source_ptr );
+
+ function vpgen : vpgen_segmentator_ptr;
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor conv_adaptor_vpgen.Construct;
+begin
+ m_source :=source;
+ m_vpgen :=gen;
+ m_start_x:=0;
+ m_start_y:=0;
+
+ m_poly_flags:=0;
+ m_vertices :=0;
+
+end;
+
+{ SET_SOURCE }
+procedure conv_adaptor_vpgen.set_source;
+begin
+ m_source:=source;
+
+end;
+
+{ VPGEN }
+function conv_adaptor_vpgen.vpgen;
+begin
+ result:=vpgen_segmentator_ptr(m_vpgen );
+
+end;
+
+{ REWIND }
+procedure conv_adaptor_vpgen.rewind;
+begin
+ m_source.rewind(path_id );
+
+ vpgen_segmentator_ptr(m_vpgen ).reset;
+
+ m_start_x :=0;
+ m_start_y :=0;
+ m_poly_flags:=0;
+ m_vertices :=0;
+
+end;
+
+{ VERTEX }
+function conv_adaptor_vpgen.vertex;
+var
+ cmd : unsigned;
+
+ tx ,ty : double;
+
+begin
+ cmd:=path_cmd_stop;
+
+ repeat
+ cmd:=m_vpgen.vertex(x ,y );
+
+ if not is_stop(cmd ) then
+ break;
+
+ if (m_poly_flags <> 0 ) and
+ not vpgen_segmentator_ptr(m_vpgen )._auto_unclose then
+ begin
+ x^ :=0.0;
+ y^ :=0.0;
+ cmd:=m_poly_flags;
+
+ m_poly_flags:=0;
+
+ break;
+
+ end;
+
+ if m_vertices < 0 then
+ begin
+ if m_vertices < -1 then
+ begin
+ m_vertices:=0;
+
+ result:=path_cmd_stop;
+
+ exit;
+
+ end;
+
+ vpgen_segmentator_ptr(m_vpgen ).move_to(m_start_x ,m_start_y );
+
+ m_vertices:=1;
+
+ continue;
+
+ end;
+
+ cmd:=m_source.vertex(@tx ,@ty );
+
+ if is_vertex(cmd ) then
+ if is_move_to(cmd ) then
+ begin
+ if vpgen_segmentator_ptr(m_vpgen )._auto_close and
+ (m_vertices > 2 ) then
+ begin
+ vpgen_segmentator_ptr(m_vpgen ).line_to(m_start_x ,m_start_y );
+
+ m_poly_flags:=path_cmd_end_poly or path_flags_close;
+ m_start_x :=tx;
+ m_start_y :=ty;
+ m_vertices :=-1;
+
+ continue;
+
+ end;
+
+ vpgen_segmentator_ptr(m_vpgen ).move_to(tx ,ty );
+
+ m_start_x :=tx;
+ m_start_y :=ty;
+ m_vertices:=1;
+
+ end
+ else
+ begin
+ vpgen_segmentator_ptr(m_vpgen ).line_to(tx ,ty );
+
+ inc(m_vertices );
+
+ end
+ else
+ if is_end_poly(cmd ) then
+ begin
+ m_poly_flags:=cmd;
+
+ if is_closed(cmd ) or
+ vpgen_segmentator_ptr(m_vpgen )._auto_close then
+ begin
+ if vpgen_segmentator_ptr(m_vpgen )._auto_close then
+ m_poly_flags:=m_poly_flags or path_flags_close;
+
+ if m_vertices > 2 then
+ vpgen_segmentator_ptr(m_vpgen ).line_to(m_start_x ,m_start_y );
+
+ m_vertices:=0;
+
+ end;
+
+ end
+ else
+ begin
+ // path_cmd_stop
+ if vpgen_segmentator_ptr(m_vpgen )._auto_close and
+ (m_vertices > 2 ) then
+ begin
+ vpgen_segmentator_ptr(m_vpgen ).line_to(m_start_x ,m_start_y );
+
+ m_poly_flags:=path_cmd_end_poly or path_flags_close;
+ m_vertices :=-2;
+
+ continue;
+
+ end;
+
+ break;
+
+ end;
+
+ until false;
+
+ result:=cmd;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_conv_bspline.pas b/src/corelib/render/software/agg_conv_bspline.pas
new file mode 100644
index 00000000..8429c465
--- /dev/null
+++ b/src/corelib/render/software/agg_conv_bspline.pas
@@ -0,0 +1,91 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 18.01.2006-Milano: Unit port establishment
+//
+{ agg_conv_bspline.pas }
+unit
+ agg_conv_bspline ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_vcgen_bspline ,
+ agg_conv_adaptor_vcgen ,
+ agg_vertex_source ;
+
+{ TYPES DEFINITION }
+type
+ conv_bspline = object(conv_adaptor_vcgen )
+ the_generator : vcgen_bspline;
+
+ constructor Construct(vs : vertex_source_ptr );
+ destructor Destruct; virtual;
+
+ procedure interpolation_step_(v : double );
+ function _interpolation_step : double;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor conv_bspline.Construct;
+begin
+ the_generator.Construct;
+
+ inherited Construct(vs ,@the_generator );
+
+end;
+
+{ DESTRUCT }
+destructor conv_bspline.Destruct;
+begin
+ inherited Destruct;
+
+ the_generator.Destruct;
+
+end;
+
+{ INTERPOLATION_STEP_ }
+procedure conv_bspline.interpolation_step_;
+begin
+ vcgen_bspline_ptr(generator ).interpolation_step_(v );
+
+end;
+
+{ _INTERPOLATION_STEP }
+function conv_bspline._interpolation_step;
+begin
+ result:=vcgen_bspline_ptr(generator )._interpolation_step;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_conv_clip_polygon.pas b/src/corelib/render/software/agg_conv_clip_polygon.pas
new file mode 100644
index 00000000..165a3bcc
--- /dev/null
+++ b/src/corelib/render/software/agg_conv_clip_polygon.pas
@@ -0,0 +1,127 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// Polygon clipping converter
+// There an optimized Liang-Basky algorithm is used.
+// The algorithm doesn't optimize the degenerate edges, i.e. it will never
+// break a closed polygon into two or more ones, instead, there will be
+// degenerate edges coinciding with the respective clipping boundaries.
+// This is a sub-optimal solution, because that optimization would require
+// extra, rather expensive math while the rasterizer tolerates it quite well,
+// without any considerable overhead.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 07.02.2006-Milano: Unit port establishment
+//
+{ agg_conv_clip_polygon.pas }
+unit
+ agg_conv_clip_polygon ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_conv_adaptor_vpgen ,
+ agg_vpgen_clip_polygon ,
+ agg_vertex_source ;
+
+{ TYPES DEFINITION }
+type
+ conv_clip_polygon = object(conv_adaptor_vpgen )
+ the_generator : vpgen_clip_polygon;
+
+ constructor Construct(vs : vertex_source_ptr );
+ destructor Destruct; virtual;
+
+ procedure clip_box(x1 ,y1 ,x2 ,y2 : double );
+
+ function _x1 : double;
+ function _y1 : double;
+ function _x2 : double;
+ function _y2 : double;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor conv_clip_polygon.Construct;
+begin
+ the_generator.Construct;
+
+ inherited Construct(vs ,@the_generator );
+
+end;
+
+{ DESTRUCT }
+destructor conv_clip_polygon.Destruct;
+begin
+ inherited Destruct;
+
+ the_generator.Destruct;
+
+end;
+
+{ CLIP_BOX_ }
+procedure conv_clip_polygon.clip_box;
+begin
+ vpgen_clip_polygon_ptr(vpgen ).clip_box_(x1 ,y1 ,x2 ,y2 );
+
+end;
+
+{ _X1 }
+function conv_clip_polygon._x1;
+begin
+ result:=vpgen_clip_polygon_ptr(vpgen )._x1;
+
+end;
+
+{ _Y1 }
+function conv_clip_polygon._y1;
+begin
+ result:=vpgen_clip_polygon_ptr(vpgen )._y1;
+
+end;
+
+{ _X2 }
+function conv_clip_polygon._x2;
+begin
+ result:=vpgen_clip_polygon_ptr(vpgen )._x2;
+
+end;
+
+{ _Y2 }
+function conv_clip_polygon._y2;
+begin
+ result:=vpgen_clip_polygon_ptr(vpgen )._y2;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_conv_clip_polyline.pas b/src/corelib/render/software/agg_conv_clip_polyline.pas
new file mode 100644
index 00000000..39ef9993
--- /dev/null
+++ b/src/corelib/render/software/agg_conv_clip_polyline.pas
@@ -0,0 +1,127 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// polyline clipping converter
+// There an optimized Liang-Basky algorithm is used.
+// The algorithm doesn't optimize the degenerate edges, i.e. it will never
+// break a closed polyline into two or more ones, instead, there will be
+// degenerate edges coinciding with the respective clipping boundaries.
+// This is a sub-optimal solution, because that optimization would require
+// extra, rather expensive math while the rasterizer tolerates it quite well,
+// without any considerable overhead.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 01.03.2006-Milano: Unit port establishment
+//
+{ agg_conv_clip_polyline.pas }
+unit
+ agg_conv_clip_polyline ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_conv_adaptor_vpgen ,
+ agg_vpgen_clip_polyline ,
+ agg_vertex_source ;
+
+{ TYPES DEFINITION }
+type
+ conv_clip_polyline = object(conv_adaptor_vpgen )
+ the_generator : vpgen_clip_polyline;
+
+ constructor Construct(vs : vertex_source_ptr );
+ destructor Destruct; virtual;
+
+ procedure clip_box_(x1 ,y1 ,x2 ,y2 : double );
+
+ function _x1 : double;
+ function _y1 : double;
+ function _x2 : double;
+ function _y2 : double;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor conv_clip_polyline.Construct;
+begin
+ the_generator.Construct;
+
+ inherited Construct(vs ,@the_generator );
+
+end;
+
+{ DESTRUCT }
+destructor conv_clip_polyline.Destruct;
+begin
+ inherited Destruct;
+
+ the_generator.Destruct;
+
+end;
+
+{ CLIP_BOX_ }
+procedure conv_clip_polyline.clip_box_;
+begin
+ vpgen_clip_polyline_ptr(vpgen ).clip_box_(x1 ,y1 ,x2 ,y2 );
+
+end;
+
+{ _X1 }
+function conv_clip_polyline._x1;
+begin
+ result:=vpgen_clip_polyline_ptr(vpgen )._x1;
+
+end;
+
+{ _Y1 }
+function conv_clip_polyline._y1;
+begin
+ result:=vpgen_clip_polyline_ptr(vpgen )._y1;
+
+end;
+
+{ _X2 }
+function conv_clip_polyline._x2;
+begin
+ result:=vpgen_clip_polyline_ptr(vpgen )._x2;
+
+end;
+
+{ _Y2 }
+function conv_clip_polyline._y2;
+begin
+ result:=vpgen_clip_polyline_ptr(vpgen )._y2;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_conv_concat.pas b/src/corelib/render/software/agg_conv_concat.pas
new file mode 100644
index 00000000..6657b9c0
--- /dev/null
+++ b/src/corelib/render/software/agg_conv_concat.pas
@@ -0,0 +1,141 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// Concatenation of two paths. Usually used to combine lines or curves
+// with markers such as arrowheads
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 26.02.2006-Milano: Unit port establishment
+//
+{ agg_conv_concat.pas }
+unit
+ agg_conv_concat ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_vertex_source ;
+
+{ TYPES DEFINITION }
+type
+ conv_concat = object(vertex_source )
+ m_source1 ,
+ m_source2 : vertex_source_ptr;
+ m_status : int;
+
+ constructor Construct(source1 ,source2 : vertex_source_ptr );
+
+ procedure set_source1(source : vertex_source_ptr );
+ procedure set_source2(source : vertex_source_ptr );
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor conv_concat.Construct;
+begin
+ m_source1:=source1;
+ m_source2:=source2;
+ m_status :=2;
+
+end;
+
+{ SET_SOURCE1 }
+procedure conv_concat.set_source1;
+begin
+ m_source1:=source;
+
+end;
+
+{ SET_SOURCE2 }
+procedure conv_concat.set_source2;
+begin
+ m_source2:=source;
+
+end;
+
+{ REWIND }
+procedure conv_concat.rewind;
+begin
+ m_source1.rewind(path_id );
+ m_source2.rewind(0 );
+
+ m_status:=0;
+
+end;
+
+{ VERTEX }
+function conv_concat.vertex;
+var
+ cmd : unsigned;
+
+begin
+ if m_status = 0 then
+ begin
+ cmd:=m_source1.vertex(x ,y );
+
+ if not is_stop(cmd ) then
+ begin
+ result:=cmd;
+
+ exit;
+
+ end;
+
+ m_status:=1;
+
+ end;
+
+ if m_status = 1 then
+ begin
+ cmd:=m_source2.vertex(x ,y );
+
+ if not is_stop(cmd ) then
+ begin
+ result:=cmd;
+
+ exit;
+
+ end;
+
+ m_status:=2;
+
+ end;
+
+ result:=path_cmd_stop;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_conv_contour.pas b/src/corelib/render/software/agg_conv_contour.pas
new file mode 100644
index 00000000..ee808e34
--- /dev/null
+++ b/src/corelib/render/software/agg_conv_contour.pas
@@ -0,0 +1,199 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 12.02.2006-Milano: Unit port establishment
+//
+{ agg_conv_contour.pas }
+unit
+ agg_conv_contour ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_vcgen_contour ,
+ agg_conv_adaptor_vcgen ,
+ agg_vertex_source ;
+
+{ TYPES DEFINITION }
+type
+ conv_contour = object(conv_adaptor_vcgen )
+ the_generator : vcgen_contour;
+
+ constructor Construct(vs : vertex_source_ptr );
+ destructor Destruct; virtual;
+
+ procedure line_join_ (lj : unsigned );
+ procedure inner_join_(ij : unsigned );
+
+ procedure width_(w : double );
+
+ procedure miter_limit_ (ml : double );
+ procedure miter_limit_theta_ (t : double );
+ procedure inner_miter_limit_ (ml : double );
+ procedure approximation_scale_(_as_ : double );
+
+ procedure auto_detect_orientation_(v : boolean );
+
+ function _line_join : unsigned;
+ function _inner_join : unsigned;
+ function _width : double;
+ function _miter_limit : double;
+ function _inner_miter_limit : double;
+ function _approximation_scale : double;
+ function _auto_detect_orientation : boolean;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor conv_contour.Construct;
+begin
+ the_generator.Construct;
+
+ inherited Construct(vs ,@the_generator );
+
+end;
+
+{ DESTRUCT }
+destructor conv_contour.Destruct;
+begin
+ inherited Destruct;
+
+ the_generator.Destruct;
+
+end;
+
+{ LINE_JOIN_ }
+procedure conv_contour.line_join_;
+begin
+ vcgen_contour_ptr(generator ).line_join_(lj );
+
+end;
+
+{ INNER_JOIN_ }
+procedure conv_contour.inner_join_;
+begin
+ vcgen_contour_ptr(generator ).inner_join_(ij );
+
+end;
+
+{ WIDTH_ }
+procedure conv_contour.width_;
+begin
+ vcgen_contour_ptr(generator ).width_(w );
+
+end;
+
+{ MITER_LIMIT_ }
+procedure conv_contour.miter_limit_;
+begin
+ vcgen_contour_ptr(generator ).miter_limit_(ml );
+
+end;
+
+{ MITER_LIMIT_THETA_ }
+procedure conv_contour.miter_limit_theta_;
+begin
+ vcgen_contour_ptr(generator ).miter_limit_theta_(t );
+
+end;
+
+{ INNER_MITER_LIMIT_ }
+procedure conv_contour.inner_miter_limit_;
+begin
+ vcgen_contour_ptr(generator ).inner_miter_limit_(ml);
+
+end;
+
+{ APPROXIMATION_SCALE_ }
+procedure conv_contour.approximation_scale_;
+begin
+ vcgen_contour_ptr(generator ).approximation_scale_(_as_ );
+
+end;
+
+{ AUTO_DETECT_ORIENTATION_ }
+procedure conv_contour.auto_detect_orientation_;
+begin
+ vcgen_contour_ptr(generator ).auto_detect_orientation_(v );
+
+end;
+
+{ _LINE_JOIN }
+function conv_contour._line_join;
+begin
+ result:=vcgen_contour_ptr(generator )._line_join;
+
+end;
+
+{ _INNER_JOIN }
+function conv_contour._inner_join;
+begin
+ result:=vcgen_contour_ptr(generator )._inner_join;
+
+end;
+
+{ _WIDTH }
+function conv_contour._width;
+begin
+ result:=vcgen_contour_ptr(generator )._width;
+
+end;
+
+{ _MITER_LIMIT }
+function conv_contour._miter_limit;
+begin
+ result:=vcgen_contour_ptr(generator )._miter_limit;
+
+end;
+
+{ _INNER_MITER_LIMIT }
+function conv_contour._inner_miter_limit;
+begin
+ result:=vcgen_contour_ptr(generator )._inner_miter_limit;
+
+end;
+
+{ _APPROXIMATION_SCALE }
+function conv_contour._approximation_scale;
+begin
+ result:=vcgen_contour_ptr(generator )._approximation_scale;
+
+end;
+
+{ _AUTO_DETECT_ORIENTATION }
+function conv_contour._auto_detect_orientation;
+begin
+ result:=vcgen_contour_ptr(generator )._auto_detect_orientation;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_conv_curve.pas b/src/corelib/render/software/agg_conv_curve.pas
new file mode 100644
index 00000000..d9386042
--- /dev/null
+++ b/src/corelib/render/software/agg_conv_curve.pas
@@ -0,0 +1,285 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// classes conv_curve
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 12.02.2006-Milano: Unit port establishment
+//
+{ agg_conv_curve.pas }
+unit
+ agg_conv_curve ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_curves ,
+ agg_vertex_source ;
+
+{ TYPES DEFINITION }
+type
+// Curve converter class. Any path storage can have Bezier curves defined
+// by their control points. There're two types of curves supported: curve3
+// and curve4. Curve3 is a conic Bezier curve with 2 endpoints and 1 control
+// point. Curve4 has 2 control points (4 points in total) and can be used
+// to interpolate more complicated curves. Curve4, unlike curve3 can be used
+// to approximate arcs, both circular and elliptical. Curves are approximated
+// with straight lines and one of the approaches is just to store the whole
+// sequence of vertices that approximate our curve. It takes additional
+// memory, and at the same time the consecutive vertices can be calculated
+// on demand.
+//
+// Initially, path storages are not suppose to keep all the vertices of the
+// curves (although, nothing prevents us from doing so). Instead, path_storage
+// keeps only vertices, needed to calculate a curve on demand. Those vertices
+// are marked with special commands. So, if the path_storage contains curves
+// (which are not real curves yet), and we render this storage directly,
+// all we will see is only 2 or 3 straight line segments (for curve3 and
+// curve4 respectively). If we need to see real curves drawn we need to
+// include this class into the conversion pipeline.
+//
+// Class conv_curve recognizes commands path_cmd_curve3 and path_cmd_curve4
+// and converts these vertices into a move_to/line_to sequence.
+ conv_curve_ptr = ^conv_curve;
+ conv_curve = object(curve )
+ m_source : vertex_source_ptr;
+ m_last_x ,
+ m_last_y : double;
+ m_curve3 ,
+ m_curve4 : curve_ptr;
+
+ constructor Construct(source : vertex_source_ptr; c3 : curve_ptr = NIL; c4 : curve_ptr = NIL );
+ destructor Destruct; virtual;
+
+ procedure set_source(source : vertex_source_ptr );
+
+ procedure approximation_method_(v : curve_approximation_method_e ); virtual;
+ function _approximation_method : curve_approximation_method_e; virtual;
+
+ procedure approximation_scale_(s : double ); virtual;
+ function _approximation_scale : double; virtual;
+
+ procedure angle_tolerance_(a : double ); virtual;
+ function _angle_tolerance : double; virtual;
+
+ procedure cusp_limit_(v : double ); virtual;
+ function _cusp_limit : double; virtual;
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor conv_curve.Construct;
+begin
+ if c3 <> NIL then
+ m_curve3:=c3
+ else
+ m_curve3:=new(curve3_ptr ,Construct );
+
+ if c4 <> NIL then
+ m_curve4:=c4
+ else
+ m_curve4:=new(curve4_ptr ,Construct );
+
+ m_source:=source;
+ m_last_x:=0.0;
+ m_last_y:=0.0;
+
+end;
+
+{ DESTRUCT }
+destructor conv_curve.Destruct;
+begin
+ if m_curve3 <> NIL then
+ dispose(m_curve3 ,Destruct );
+
+ if m_curve4 <> NIL then
+ dispose(m_curve4 ,Destruct );
+
+end;
+
+{ SET_SOURCE }
+procedure conv_curve.set_source;
+begin
+ m_source:=source;
+
+end;
+
+{ APPROXIMATION_METHOD_ }
+procedure conv_curve.approximation_method_;
+begin
+ m_curve3.approximation_method_(v );
+ m_curve4.approximation_method_(v );
+
+end;
+
+{ _APPROXIMATION_METHOD }
+function conv_curve._approximation_method;
+begin
+ result:=m_curve4._approximation_method;
+
+end;
+
+{ APPROXIMATION_SCALE_ }
+procedure conv_curve.approximation_scale_;
+begin
+ m_curve3.approximation_scale_(s );
+ m_curve4.approximation_scale_(s );
+
+end;
+
+{ _APPROXIMATION_SCALE }
+function conv_curve._approximation_scale;
+begin
+ result:=m_curve4._approximation_scale;
+
+end;
+
+{ ANGLE_TOLERANCE_ }
+procedure conv_curve.angle_tolerance_;
+begin
+ m_curve3.angle_tolerance_(a );
+ m_curve4.angle_tolerance_(a );
+
+end;
+
+{ _ANGLE_TOLERANCE }
+function conv_curve._angle_tolerance;
+begin
+ result:=m_curve4._angle_tolerance;
+
+end;
+
+{ CUSP_LIMIT_ }
+procedure conv_curve.cusp_limit_;
+begin
+ m_curve3.cusp_limit_(v );
+ m_curve4.cusp_limit_(v );
+
+end;
+
+{ _CUSP_LIMIT }
+function conv_curve._cusp_limit;
+begin
+ result:=m_curve4._cusp_limit;
+
+end;
+
+{ REWIND }
+procedure conv_curve.rewind;
+begin
+ m_source.rewind(path_id );
+
+ m_last_x:=0.0;
+ m_last_y:=0.0;
+
+ m_curve3.reset;
+ m_curve4.reset;
+
+end;
+
+{ VERTEX }
+function conv_curve.vertex;
+var
+ ct2_x ,ct2_y ,end_x ,end_y : double;
+
+ cmd : unsigned;
+
+begin
+ if not is_stop(m_curve3.vertex(x ,y ) ) then
+ begin
+ m_last_x:=x^;
+ m_last_y:=y^;
+
+ result:=path_cmd_line_to;
+
+ exit;
+
+ end;
+
+ if not is_stop(m_curve4.vertex(x ,y ) ) then
+ begin
+ m_last_x:=x^;
+ m_last_y:=y^;
+
+ result:=path_cmd_line_to;
+
+ exit;
+
+ end;
+
+ cmd:=m_source.vertex(x ,y );
+
+ case cmd of
+ path_cmd_move_to ,path_cmd_line_to :
+ begin
+ m_last_x:=x^;
+ m_last_y:=y^;
+
+ end;
+
+ path_cmd_curve3 :
+ begin
+ m_source.vertex(@end_x ,@end_y );
+ m_curve3.init3 (m_last_x ,m_last_y ,x^ ,y^ ,end_x ,end_y );
+
+ m_curve3.vertex(x ,y ); // First call returns path_cmd_move_to
+ m_curve3.vertex(x ,y ); // This is the first vertex of the curve
+
+ cmd:=path_cmd_line_to;
+
+ end;
+
+ path_cmd_curve4 :
+ begin
+ m_source.vertex(@ct2_x ,@ct2_y );
+ m_source.vertex(@end_x ,@end_y );
+
+ m_curve4.init4 (m_last_x ,m_last_y ,x^ ,y^ ,ct2_x ,ct2_y ,end_x ,end_y );
+
+ m_curve4.vertex(x ,y ); // First call returns path_cmd_move_to
+ m_curve4.vertex(x ,y ); // This is the first vertex of the curve
+
+ cmd:=path_cmd_line_to;
+
+ end;
+
+ end;
+
+ result:=cmd;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_conv_dash.pas b/src/corelib/render/software/agg_conv_dash.pas
new file mode 100644
index 00000000..8236d23e
--- /dev/null
+++ b/src/corelib/render/software/agg_conv_dash.pas
@@ -0,0 +1,120 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// conv_dash
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 26.01.2006-Milano: Unit port establishment
+//
+{ agg_conv_dash.pas }
+unit
+ agg_conv_dash ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_vertex_source ,
+ agg_conv_adaptor_vcgen ,
+ agg_vcgen_dash ;
+
+{ TYPES DEFINITION }
+type
+ conv_dash = object(conv_adaptor_vcgen )
+ the_generator : vcgen_dash;
+
+ constructor Construct(vs : vertex_source_ptr );
+ destructor Destruct; virtual;
+
+ procedure remove_all_dashes;
+ procedure add_dash (dash_len ,gap_len : double );
+ procedure dash_start(ds : double );
+
+ procedure shorten_(s : double );
+ function _shorten : double;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor conv_dash.Construct;
+begin
+ the_generator.Construct;
+
+ inherited Construct(vs ,@the_generator );
+
+end;
+
+{ DESTRUCT }
+destructor conv_dash.Destruct;
+begin
+ inherited Destruct;
+
+ the_generator.Destruct;
+
+end;
+
+{ REMOVE_ALL_DASHES }
+procedure conv_dash.remove_all_dashes;
+begin
+ vcgen_dash_ptr(generator ).remove_all_dashes;
+
+end;
+
+{ ADD_DASH }
+procedure conv_dash.add_dash;
+begin
+ vcgen_dash_ptr(generator ).add_dash(dash_len ,gap_len );
+
+end;
+
+{ DASH_START }
+procedure conv_dash.dash_start;
+begin
+ vcgen_dash_ptr(generator ).dash_start(ds );
+
+end;
+
+{ SHORTEN_ }
+procedure conv_dash.shorten_;
+begin
+ vcgen_dash_ptr(generator ).shorten_(s );
+
+end;
+
+{ _SHORTEN }
+function conv_dash._shorten;
+begin
+ result:=vcgen_dash_ptr(generator )._shorten;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_conv_gpc.pas b/src/corelib/render/software/agg_conv_gpc.pas
new file mode 100644
index 00000000..1a3c6283
--- /dev/null
+++ b/src/corelib/render/software/agg_conv_gpc.pas
@@ -0,0 +1,526 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// General Polygon Clipper based on the GPC library by Alan Murta
+// Union, Intersection, XOR, A-B, B-A
+// Contact the author if you intend to use it in commercial applications!
+// http://www.cs.man.ac.uk/aig/staff/alan/software/
+// Alan Murta (email: gpc@cs.man.ac.uk)
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 22.02.2006-Milano: Unit port establishment
+//
+{ agg_conv_gpc.pas }
+unit
+ agg_conv_gpc ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ gpc ,
+ agg_basics ,
+ agg_array ,
+ agg_vertex_source ;
+
+{ TYPES DEFINITION }
+type
+ gpc_op_e = (
+
+ gpc_or ,
+ gpc_and ,
+ gpc_xor ,
+ gpc_a_minus_b ,
+ gpc_b_minus_a
+
+ );
+
+ status = (status_move_to ,status_line_to ,status_stop );
+
+ gpc_vertex_ptr = ^Tgpc_vertex;
+
+ contour_header_type_ptr = ^contour_header_type;
+ contour_header_type = record
+ num_vertices ,
+ hole_flag : int;
+
+ vertices : gpc_vertex_ptr;
+
+ end;
+
+ conv_gpc_ptr = ^conv_gpc;
+ conv_gpc = object(vertex_source )
+ m_src_a ,
+ m_src_b : vertex_source_ptr;
+
+ m_status : status;
+ m_vertex ,
+ m_contour : int;
+ m_operation : gpc_op_e;
+
+ m_vertex_accumulator ,
+ m_contour_accumulator : pod_deque;
+
+ m_poly_a ,
+ m_poly_b ,
+ m_result : Tgpc_polygon;
+
+ constructor Construct(a ,b : vertex_source_ptr; op : gpc_op_e = gpc_or );
+ destructor Destruct; virtual;
+
+ procedure set_source1(source : vertex_source_ptr );
+ procedure set_source2(source : vertex_source_ptr );
+
+ procedure operation(v : gpc_op_e );
+
+ // Vertex Source Interface
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ // Private
+ procedure free_polygon(p : Pgpc_polygon );
+ procedure free_result;
+ procedure free_gpc_data;
+ procedure start_contour;
+ procedure add_vertex_ (x ,y : double );
+ procedure end_contour (orientation : unsigned );
+ procedure make_polygon(p : Pgpc_polygon );
+ procedure start_extracting;
+
+ function next_contour : boolean;
+ function next_vertex(x ,y : double_ptr ) : boolean;
+
+ procedure add(src : vertex_source_ptr; p : Pgpc_polygon );
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor conv_gpc.Construct;
+begin
+ m_vertex_accumulator.Construct (sizeof(Tgpc_vertex ) ,8 );
+ m_contour_accumulator.Construct(sizeof(contour_header_type ) ,6 );
+
+ m_src_a:=a;
+ m_src_b:=b;
+
+ m_status :=status_move_to;
+ m_vertex :=-1;
+ m_contour :=-1;
+ m_operation:=op;
+
+ fillchar(m_poly_a ,sizeof(m_poly_a ) ,0 );
+ fillchar(m_poly_b ,sizeof(m_poly_b ) ,0 );
+ fillchar(m_result ,sizeof(m_result ) ,0 );
+
+end;
+
+{ DESTRUCT }
+destructor conv_gpc.Destruct;
+begin
+ free_gpc_data;
+
+ m_vertex_accumulator.Destruct;
+ m_contour_accumulator.Destruct;
+
+end;
+
+{ SET_SOURCE1 }
+procedure conv_gpc.set_source1;
+begin
+ m_src_a:=source;
+
+end;
+
+{ SET_SOURCE2 }
+procedure conv_gpc.set_source2;
+begin
+ m_src_b:=source;
+
+end;
+
+{ OPERATION }
+procedure conv_gpc.operation;
+begin
+ m_operation:=v;
+
+end;
+
+{ REWIND }
+procedure conv_gpc.rewind;
+begin
+ free_result;
+
+ m_src_a.rewind(path_id );
+ m_src_b.rewind(path_id );
+
+ add(m_src_a ,@m_poly_a );
+ add(m_src_b ,@m_poly_b );
+
+ case m_operation of
+ gpc_or :
+ gpc_polygon_clip(gpc.GPC_UNION ,@m_poly_a ,@m_poly_b ,@m_result );
+
+ gpc_and :
+ gpc_polygon_clip(gpc.GPC_INT ,@m_poly_a ,@m_poly_b ,@m_result );
+
+ gpc_xor :
+ gpc_polygon_clip(gpc.GPC_XOR ,@m_poly_a ,@m_poly_b ,@m_result );
+
+ gpc_a_minus_b :
+ gpc_polygon_clip(gpc.GPC_DIFF ,@m_poly_a ,@m_poly_b ,@m_result );
+
+ gpc_b_minus_a :
+ gpc_polygon_clip(gpc.GPC_DIFF ,@m_poly_b ,@m_poly_a ,@m_result );
+
+ end;
+
+ start_extracting;
+
+end;
+
+{ VERTEX }
+function conv_gpc.vertex;
+begin
+ if m_status = status_move_to then
+ if next_contour then
+ begin
+ if next_vertex(x ,y ) then
+ begin
+ m_status:=status_line_to;
+ result :=path_cmd_move_to;
+
+ exit;
+
+ end;
+
+ m_status:=status_stop;
+ result :=path_cmd_end_poly or path_flags_close;
+
+ exit;
+
+ end
+ else
+ else
+ begin
+ if next_vertex(x ,y ) then
+ begin
+ result:=path_cmd_line_to;
+
+ exit;
+
+ end
+ else
+ m_status:=status_move_to;
+
+ result:=path_cmd_end_poly or path_flags_close;
+
+ exit;
+
+ end;
+
+ result:=path_cmd_stop;
+
+end;
+
+{ FREE_POLYGON }
+procedure conv_gpc.free_polygon;
+var
+ i : int;
+
+begin
+ i:=0;
+
+ while i < p.num_contours do
+ begin
+ agg_freemem(pointer(p.contour[i ].vertex ) ,p.contour[i].num_vertices * sizeof(Tgpc_vertex ) );
+
+ inc(i );
+
+ end;
+
+ //agg_freemem(pointer(p.hole ) ,? );
+ agg_freemem(pointer(p.contour ) ,p.num_contours * sizeof(Tgpc_vertex_list ) );
+
+ fillchar(p^ ,sizeof(Tgpc_polygon ) ,0 );
+
+end;
+
+{ FREE_RESULT }
+procedure conv_gpc.free_result;
+begin
+ if m_result.contour <> NIL then
+ gpc_free_polygon(@m_result );
+
+ fillchar(m_result ,sizeof(m_result ) ,0 );
+
+end;
+
+{ FREE_GPC_DATA }
+procedure conv_gpc.free_gpc_data;
+begin
+ free_polygon(@m_poly_a );
+ free_polygon(@m_poly_b );
+ free_result;
+
+end;
+
+{ START_CONTOUR }
+procedure conv_gpc.start_contour;
+var
+ h : contour_header_type;
+
+begin
+ fillchar(h ,sizeof(h ) ,0 );
+ m_contour_accumulator.add(@h );
+ m_vertex_accumulator.remove_all;
+
+end;
+
+{ ADD_VERTEX_ }
+procedure conv_gpc.add_vertex_;
+var
+ v : Tgpc_vertex;
+
+begin
+ v.x:=x;
+ v.y:=y;
+
+ m_vertex_accumulator.add(@v );
+
+end;
+
+{ END_CONTOUR }
+procedure conv_gpc.end_contour;
+var
+ h : contour_header_type_ptr;
+ d ,
+ s : gpc_vertex_ptr;
+ i : int;
+
+begin
+ if m_contour_accumulator.size <> 0 then
+ if m_vertex_accumulator.size > 2 then
+ begin
+ h:=m_contour_accumulator.array_operator(m_contour_accumulator.size - 1 );
+
+ h.num_vertices:=m_vertex_accumulator.size;
+ h.hole_flag :=0;
+
+ // TO DO: Clarify the "holes"
+ // if is_cw(orientation ) then h.hole_flag:=1;
+
+ agg_getmem(pointer(h.vertices ) ,h.num_vertices * sizeof(Tgpc_vertex ) );
+
+ d:=h.vertices;
+
+ for i:=0 to h.num_vertices - 1 do
+ begin
+ s:=m_vertex_accumulator.array_operator(i );
+
+ d.x:=s.x;
+ d.y:=s.y;
+
+ inc(ptrcomp(d ) ,sizeof(Tgpc_vertex ) );
+
+ end;
+
+ end
+ else
+ m_vertex_accumulator.remove_last;
+
+end;
+
+{ MAKE_POLYGON }
+procedure conv_gpc.make_polygon;
+var
+ i : int;
+ h : contour_header_type_ptr;
+
+//ph : int_ptr;
+ pv : Pgpc_vertex_list;
+
+begin
+ free_polygon(p );
+
+ if m_contour_accumulator.size <> 0 then
+ begin
+ p.num_contours:=m_contour_accumulator.size;
+
+ // TO DO: Clarify the "holes"
+ // p.hole = new int[p.num_contours];
+
+ p.hole:=NIL;
+
+ agg_getmem(pointer(p.contour ) ,p.num_contours * sizeof(Tgpc_vertex_list ) );
+
+ //ph:=p.hole;
+ pv:=Pgpc_vertex_list(p.contour );
+
+ if p.num_contours > 0 then
+ for i:=0 to p.num_contours - 1 do
+ begin
+ h:=m_contour_accumulator.array_operator(i );
+
+ //*ph++ = h.hole_flag;
+ pv.num_vertices:=h.num_vertices;
+ pv.vertex :=Pgpc_vertex_array(h.vertices );
+
+ inc(ptrcomp(pv ) ,sizeof(Tgpc_vertex_list ) );
+
+ end;
+
+ end;
+
+end;
+
+{ START_EXTRACTING }
+procedure conv_gpc.start_extracting;
+begin
+ m_status :=status_move_to;
+ m_contour:=-1;
+ m_vertex :=-1;
+
+end;
+
+{ NEXT_CONTOUR }
+function conv_gpc.next_contour;
+begin
+ inc(m_contour );
+
+ if m_contour < m_result.num_contours then
+ begin
+ m_vertex:=-1;
+
+ result:=true;
+
+ end
+ else
+ result:=false;
+
+end;
+
+{ NEXT_VERTEX }
+function conv_gpc.next_vertex;
+var
+ vlist : Pgpc_vertex_list;
+
+ v : gpc_vertex_ptr;
+
+begin
+ vlist:=@m_result.contour[m_contour ];
+
+ inc(m_vertex );
+
+ if m_vertex < vlist.num_vertices then
+ begin
+ v:=@vlist.vertex[m_vertex ];
+
+ x^:=v.x;
+ y^:=v.y;
+
+ result:=true;
+
+ end
+ else
+ result:=false;
+
+end;
+
+{ ADD }
+procedure conv_gpc.add;
+var
+ cmd ,orientation : unsigned;
+
+ x ,y ,start_x ,start_y : double;
+
+ line_to : boolean;
+
+begin
+ start_x:=0.0;
+ start_y:=0.0;
+ line_to:=false;
+
+ orientation:=0;
+
+ m_contour_accumulator.remove_all;
+
+ cmd:=src.vertex(@x ,@y );
+
+ while not is_stop(cmd ) do
+ begin
+ if is_vertex(cmd ) then
+ begin
+ if is_move_to(cmd ) then
+ begin
+ if line_to then
+ begin
+ end_contour(orientation );
+
+ orientation:=0;
+
+ end;
+
+ start_contour;
+
+ start_x:=x;
+ start_y:=y;
+
+ end;
+
+ add_vertex_(x ,y );
+
+ line_to:=true;
+
+ end
+ else
+ if is_end_poly(cmd ) then
+ begin
+ orientation:=get_orientation(cmd );
+
+ if line_to and
+ is_closed(cmd ) then
+ add_vertex_(start_x ,start_y );
+
+ end;
+
+ cmd:=src.vertex(@x ,@y );
+
+ end;
+
+ if line_to then
+ end_contour(orientation );
+
+ make_polygon(p );
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_conv_marker.pas b/src/corelib/render/software/agg_conv_marker.pas
new file mode 100644
index 00000000..567a76a8
--- /dev/null
+++ b/src/corelib/render/software/agg_conv_marker.pas
@@ -0,0 +1,216 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 25.02.2006-Milano: Unit port establishment
+//
+{ agg_conv_marker.pas }
+unit
+ agg_conv_marker ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ Math ,
+ agg_basics ,
+ agg_trans_affine ,
+ agg_vertex_source ;
+
+{ TYPES DEFINITION }
+type
+ status_e = (initial ,markers ,polygon ,stop );
+
+ conv_marker = object(vertex_source )
+ m_marker_locator ,
+ m_marker_shapes : vertex_source_ptr;
+
+ m_transform ,
+ m_mtx : trans_affine;
+
+ m_status : status_e;
+ m_marker ,
+ m_num_markers : unsigned;
+
+ constructor Construct(ml ,ms : vertex_source_ptr );
+
+ function _transform : trans_affine_ptr;
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor conv_marker.Construct;
+begin
+ m_transform.Construct;
+ m_mtx.Construct;
+
+ m_marker_locator:=ml;
+ m_marker_shapes :=ms;
+
+ m_status:=initial;
+ m_marker:=0;
+
+ m_num_markers:=1;
+
+end;
+
+{ _TRANSFORM }
+function conv_marker._transform;
+begin
+ result:=@m_transform;
+
+end;
+
+{ REWIND }
+procedure conv_marker.rewind;
+begin
+ m_status:=initial;
+ m_marker:=0;
+
+ m_num_markers:=1;
+
+end;
+
+{ VERTEX }
+function conv_marker.vertex;
+var
+ cmd : unsigned;
+
+ x1 ,y1 ,x2 ,y2 : double;
+
+ tar : trans_affine_rotation;
+ tat : trans_affine_translation;
+
+label
+ _next ,_markers ,_polygon ,_stop ;
+
+begin
+ cmd:=path_cmd_move_to;
+
+_next:
+ while not is_stop(cmd ) do
+ case m_status of
+ initial :
+ begin
+ if m_num_markers = 0 then
+ begin
+ cmd:=path_cmd_stop;
+
+ goto _next;
+
+ end;
+
+ m_marker_locator.rewind(m_marker );
+
+ inc(m_marker );
+
+ m_num_markers:=0;
+ m_status :=markers;
+
+ goto _markers;
+
+ end;
+
+ markers :
+ _markers:
+ begin
+ if is_stop(m_marker_locator.vertex(@x1 ,@y1 ) ) then
+ begin
+ m_status:=initial;
+
+ goto _next;
+
+ end;
+
+ if is_stop(m_marker_locator.vertex(@x2 ,@y2 ) ) then
+ begin
+ m_status:=initial;
+
+ goto _next;
+
+ end;
+
+ inc(m_num_markers );
+
+ m_mtx:=m_transform;
+
+ tar.Construct(ArcTan2(y2 - y1 ,x2 - x1 ) );
+ tat.Construct(x1 ,y1 );
+
+ m_mtx.multiply(@tar );
+ m_mtx.multiply(@tat );
+
+ m_marker_shapes.rewind(m_marker - 1 );
+
+ m_status:=polygon;
+
+ goto _polygon;
+
+ end;
+
+ polygon :
+ _polygon:
+ begin
+ cmd:=m_marker_shapes.vertex(x ,y );
+
+ if is_stop(cmd ) then
+ begin
+ cmd :=path_cmd_move_to;
+ m_status:=markers;
+
+ goto _next;
+
+ end;
+
+ m_mtx.transform(@m_mtx ,x ,y );
+
+ result:=cmd;
+
+ exit;
+
+ end;
+
+ stop :
+ begin
+ cmd:=path_cmd_stop;
+
+ goto _next;
+
+ end;
+
+ end;
+
+ result:=cmd;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_conv_marker_adaptor.pas b/src/corelib/render/software/agg_conv_marker_adaptor.pas
new file mode 100644
index 00000000..13ce23c9
--- /dev/null
+++ b/src/corelib/render/software/agg_conv_marker_adaptor.pas
@@ -0,0 +1,92 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 26.02.2006-Milano: Unit port establishment
+//
+{ agg_conv_marker_adaptor.pas }
+unit
+ agg_conv_marker_adaptor ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_conv_adaptor_vcgen ,
+ agg_vcgen_vertex_sequence ,
+ agg_vertex_source ;
+
+{ TYPES DEFINITION }
+type
+ conv_marker_adaptor_ptr = ^conv_marker_adaptor;
+ conv_marker_adaptor = object(conv_adaptor_vcgen )
+ the_generator : vcgen_vertex_sequence;
+
+ constructor Construct(vs : vertex_source_ptr );
+ destructor Destruct; virtual;
+
+ procedure shorten_(s : double );
+ function _shorten : double;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor conv_marker_adaptor.Construct;
+begin
+ the_generator.Construct;
+
+ inherited Construct(vs ,@the_generator );
+
+end;
+
+{ DESTRUCT }
+destructor conv_marker_adaptor.Destruct;
+begin
+ inherited Destruct;
+
+ the_generator.Destruct;
+
+end;
+
+{ SHORTEN_ }
+procedure conv_marker_adaptor.shorten_;
+begin
+ the_generator.shorten_(s );
+
+end;
+
+{ _SHORTEN }
+function conv_marker_adaptor._shorten;
+begin
+ result:=the_generator._shorten;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_conv_segmentator.pas b/src/corelib/render/software/agg_conv_segmentator.pas
new file mode 100644
index 00000000..2d0ee04b
--- /dev/null
+++ b/src/corelib/render/software/agg_conv_segmentator.pas
@@ -0,0 +1,91 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 25.01.2006-Milano: Unit port establishment
+//
+{ agg_conv_segmentator.pas }
+unit
+ agg_conv_segmentator ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_vertex_source ,
+ agg_conv_adaptor_vpgen ,
+ agg_vpgen_segmentator ;
+
+{ TYPES DEFINITION }
+type
+ conv_segmentator = object(conv_adaptor_vpgen )
+ the_generator : vpgen_segmentator;
+
+ constructor Construct(vs : vertex_source_ptr );
+ destructor Destruct; virtual;
+
+ procedure approximation_scale_(s : double );
+ function _approximation_scale : double;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor conv_segmentator.Construct;
+begin
+ the_generator.Construct;
+
+ inherited Construct(vs ,@the_generator );
+
+end;
+
+{ DESTRUCT }
+destructor conv_segmentator.Destruct;
+begin
+ inherited Destruct;
+
+ the_generator.Destruct;
+
+end;
+
+{ APPROXIMATION_SCALE_ }
+procedure conv_segmentator.approximation_scale_;
+begin
+ vpgen.approximation_scale_(s );
+
+end;
+
+{ _APPROXIMATION_SCALE }
+function conv_segmentator._approximation_scale;
+begin
+ result:=vpgen._approximation_scale;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_conv_shorten_path.pas b/src/corelib/render/software/agg_conv_shorten_path.pas
new file mode 100644
index 00000000..4461b61c
--- /dev/null
+++ b/src/corelib/render/software/agg_conv_shorten_path.pas
@@ -0,0 +1,91 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 26.02.2006-Milano: Unit port establishment
+//
+{ agg_conv_shorten_path.pas }
+unit
+ agg_conv_shorten_path ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_conv_adaptor_vcgen ,
+ agg_vcgen_vertex_sequence ,
+ agg_vertex_source ;
+
+{ TYPES DEFINITION }
+type
+ conv_shorten_path = object(conv_adaptor_vcgen )
+ the_generator : vcgen_vertex_sequence;
+
+ constructor Construct(vs : vertex_source_ptr );
+ destructor Destruct; virtual;
+
+ procedure shorten_(s : double );
+ function _shorten : double;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor conv_shorten_path.Construct;
+begin
+ the_generator.Construct;
+
+ inherited Construct(vs ,@the_generator );
+
+end;
+
+{ DESTRUCT }
+destructor conv_shorten_path.Destruct;
+begin
+ inherited Destruct;
+
+ the_generator.Destruct;
+
+end;
+
+{ SHORTEN_ }
+procedure conv_shorten_path.shorten_;
+begin
+ the_generator.shorten_(s );
+
+end;
+
+{ _SHORTEN }
+function conv_shorten_path._shorten;
+begin
+ result:=the_generator._shorten;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_conv_smooth_poly1.pas b/src/corelib/render/software/agg_conv_smooth_poly1.pas
new file mode 100644
index 00000000..23fd006c
--- /dev/null
+++ b/src/corelib/render/software/agg_conv_smooth_poly1.pas
@@ -0,0 +1,135 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 25.02.2006-Milano: Unit port establishment
+//
+{ agg_conv_smooth_poly1.pas }
+unit
+ agg_conv_smooth_poly1 ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_vcgen_smooth_poly1 ,
+ agg_conv_adaptor_vcgen ,
+ agg_conv_curve ,
+ agg_vertex_source ;
+
+{ TYPES DEFINITION }
+type
+ conv_smooth_poly1 = object(conv_adaptor_vcgen )
+ the_generator : vcgen_smooth_poly1;
+
+ constructor Construct(vs : vertex_source_ptr );
+ destructor Destruct; virtual;
+
+ procedure smooth_value_(v : double );
+ function _smooth_value : double;
+
+ end;
+
+ conv_smooth_poly1_curve = object(conv_curve )
+ m_smooth : conv_smooth_poly1;
+
+ constructor Construct(vs : vertex_source_ptr );
+ destructor Destruct; virtual;
+
+ procedure smooth_value_(v : double );
+ function _smooth_value : double;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor conv_smooth_poly1.Construct;
+begin
+ the_generator.Construct;
+
+ inherited Construct(vs ,@the_generator );
+
+end;
+
+{ DESTRUCT }
+destructor conv_smooth_poly1.Destruct;
+begin
+ inherited Destruct;
+
+ the_generator.Destruct;
+
+end;
+
+{ SMOOTH_VALUE_ }
+procedure conv_smooth_poly1.smooth_value_;
+begin
+ vcgen_smooth_poly1_ptr(generator ).smooth_value_(v );
+
+end;
+
+{ _SMOOTH_VALUE }
+function conv_smooth_poly1._smooth_value;
+begin
+ result:=vcgen_smooth_poly1_ptr(generator )._smooth_value;
+
+end;
+
+{ CONSTRUCT }
+constructor conv_smooth_poly1_curve.Construct;
+begin
+ m_smooth.Construct(vs );
+
+ inherited Construct(@m_smooth );
+
+end;
+
+{ DESTRUCT }
+destructor conv_smooth_poly1_curve.Destruct;
+begin
+ inherited Destruct;
+
+ m_smooth.Destruct;
+
+end;
+
+{ SMOOTH_VALUE_ }
+procedure conv_smooth_poly1_curve.smooth_value_;
+begin
+ vcgen_smooth_poly1_ptr(m_smooth.generator ).smooth_value_(v );
+
+end;
+
+{ _SMOOTH_VALUE }
+function conv_smooth_poly1_curve._smooth_value;
+begin
+ result:=vcgen_smooth_poly1_ptr(m_smooth.generator )._smooth_value;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_conv_stroke.pas b/src/corelib/render/software/agg_conv_stroke.pas
new file mode 100644
index 00000000..a36bc012
--- /dev/null
+++ b/src/corelib/render/software/agg_conv_stroke.pas
@@ -0,0 +1,388 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// conv_stroke
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 18.10.2007-Milano: conv_stroke_math
+// 21.12.2005-Milano: Unit port establishment
+//
+{ agg_conv_stroke.pas }
+unit
+ agg_conv_stroke ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_vertex_source ,
+ agg_vcgen_stroke ,
+ agg_conv_adaptor_vcgen ;
+
+{ TYPES DEFINITION }
+type
+ conv_stroke_ptr = ^conv_stroke;
+ conv_stroke = object(conv_adaptor_vcgen )
+ the_generator : vcgen_stroke;
+
+ constructor Construct(vs : vertex_source_ptr );
+ destructor Destruct; virtual;
+
+ procedure line_cap_ (lc : unsigned );
+ procedure line_join_ (lj : unsigned );
+ procedure inner_join_(ij : unsigned );
+
+ function _line_cap : unsigned;
+ function _line_join : unsigned;
+ function _inner_join : unsigned;
+
+ procedure width_ (w : double );
+ procedure miter_limit_ (ml : double );
+ procedure miter_limit_theta_ (t : double );
+ procedure inner_miter_limit_ (ml : double );
+ procedure approximation_scale_(_as_ : double );
+
+ function _width : double;
+ function _miter_limit : double;
+ function _inner_miter_limit : double;
+ function _approximation_scale : double;
+
+ procedure shorten_(s : double );
+ function _shorten : double;
+
+ end;
+
+ conv_stroke_math = object(conv_adaptor_vcgen )
+ the_generator : vcgen_stroke_math;
+
+ constructor Construct(vs : vertex_source_ptr );
+ destructor Destruct; virtual;
+
+ procedure line_cap_ (lc : unsigned );
+ procedure line_join_ (lj : unsigned );
+ procedure inner_join_(ij : unsigned );
+
+ function _line_cap : unsigned;
+ function _line_join : unsigned;
+ function _inner_join : unsigned;
+
+ procedure width_ (w : double );
+ procedure miter_limit_ (ml : double );
+ procedure miter_limit_theta_ (t : double );
+ procedure inner_miter_limit_ (ml : double );
+ procedure approximation_scale_(_as_ : double );
+
+ function _width : double;
+ function _miter_limit : double;
+ function _inner_miter_limit : double;
+ function _approximation_scale : double;
+
+ procedure shorten_(s : double );
+ function _shorten : double;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor conv_stroke.Construct;
+begin
+ the_generator.Construct;
+
+ inherited Construct(vs ,@the_generator );
+
+end;
+
+{ DESTRUCT }
+destructor conv_stroke.Destruct;
+begin
+ inherited Destruct;
+
+ the_generator.Destruct;
+
+end;
+
+{ LINE_CAP_ }
+procedure conv_stroke.line_cap_;
+begin
+ vcgen_stroke_ptr(generator ).line_cap_(lc );
+
+end;
+
+{ LINE_JOIN_ }
+procedure conv_stroke.line_join_;
+begin
+ vcgen_stroke_ptr(generator ).line_join_(lj );
+
+end;
+
+{ INNER_JOIN_ }
+procedure conv_stroke.inner_join_;
+begin
+ vcgen_stroke_ptr(generator ).inner_join_(ij );
+
+end;
+
+{ _LINE_CAP }
+function conv_stroke._line_cap;
+begin
+ result:=vcgen_stroke_ptr(generator )._line_cap;
+
+end;
+
+{ _LINE_JOIN }
+function conv_stroke._line_join;
+begin
+ result:=vcgen_stroke_ptr(generator )._line_join;
+
+end;
+
+{ _INNER_JOIN }
+function conv_stroke._inner_join;
+begin
+ result:=vcgen_stroke_ptr(generator )._inner_join;
+
+end;
+
+{ WIDHT_ }
+procedure conv_stroke.width_;
+begin
+ vcgen_stroke_ptr(generator ).width_(w );
+
+end;
+
+{ MITER_LIMIT_ }
+procedure conv_stroke.miter_limit_;
+begin
+ vcgen_stroke_ptr(generator ).miter_limit_(ml );
+
+end;
+
+{ MITER_LIMIT_THETA_ }
+procedure conv_stroke.miter_limit_theta_;
+begin
+ vcgen_stroke_ptr(generator ).miter_limit_theta_(t );
+
+end;
+
+{ INNER_MITER_LIMIT_ }
+procedure conv_stroke.inner_miter_limit_;
+begin
+ vcgen_stroke_ptr(generator ).inner_miter_limit_(ml );
+
+end;
+
+{ APPROXIMATION_SCALE_ }
+procedure conv_stroke.approximation_scale_;
+begin
+ vcgen_stroke_ptr(generator ).approximation_scale_(_as_ );
+
+end;
+
+{ _WIDTH }
+function conv_stroke._width;
+begin
+ result:=vcgen_stroke_ptr(generator )._width;
+
+end;
+
+{ _MITER_LIMIT }
+function conv_stroke._miter_limit;
+begin
+ result:=vcgen_stroke_ptr(generator )._miter_limit;
+
+end;
+
+{ _INNER_MITER_LIMIT }
+function conv_stroke._inner_miter_limit;
+begin
+ result:=vcgen_stroke_ptr(generator )._inner_miter_limit;
+
+end;
+
+{ _APPROXIMATION_SCALE }
+function conv_stroke._approximation_scale;
+begin
+ result:=vcgen_stroke_ptr(generator )._approximation_scale;
+
+end;
+
+{ SHORTEN_ }
+procedure conv_stroke.shorten_;
+begin
+ vcgen_stroke_ptr(generator ).shorten_(s );
+
+end;
+
+{ _SHORTEN }
+function conv_stroke._shorten;
+begin
+ result:=vcgen_stroke_ptr(generator )._shorten;
+
+end;
+
+{ CONSTRUCT }
+constructor conv_stroke_math.Construct;
+begin
+ the_generator.Construct;
+
+ inherited Construct(vs ,@the_generator );
+
+end;
+
+{ DESTRUCT }
+destructor conv_stroke_math.Destruct;
+begin
+ inherited Destruct;
+
+ the_generator.Destruct;
+
+end;
+
+{ LINE_CAP_ }
+procedure conv_stroke_math.line_cap_;
+begin
+ vcgen_stroke_math_ptr(generator ).line_cap_(lc );
+
+end;
+
+{ LINE_JOIN_ }
+procedure conv_stroke_math.line_join_;
+begin
+ vcgen_stroke_math_ptr(generator ).line_join_(lj );
+
+end;
+
+{ INNER_JOIN_ }
+procedure conv_stroke_math.inner_join_;
+begin
+ vcgen_stroke_math_ptr(generator ).inner_join_(ij );
+
+end;
+
+{ _LINE_CAP }
+function conv_stroke_math._line_cap;
+begin
+ result:=vcgen_stroke_math_ptr(generator )._line_cap;
+
+end;
+
+{ _LINE_JOIN }
+function conv_stroke_math._line_join;
+begin
+ result:=vcgen_stroke_math_ptr(generator )._line_join;
+
+end;
+
+{ _INNER_JOIN }
+function conv_stroke_math._inner_join;
+begin
+ result:=vcgen_stroke_math_ptr(generator )._inner_join;
+
+end;
+
+{ WIDHT_ }
+procedure conv_stroke_math.width_;
+begin
+ vcgen_stroke_math_ptr(generator ).width_(w );
+
+end;
+
+{ MITER_LIMIT_ }
+procedure conv_stroke_math.miter_limit_;
+begin
+ vcgen_stroke_math_ptr(generator ).miter_limit_(ml );
+
+end;
+
+{ MITER_LIMIT_THETA_ }
+procedure conv_stroke_math.miter_limit_theta_;
+begin
+ vcgen_stroke_math_ptr(generator ).miter_limit_theta_(t );
+
+end;
+
+{ INNER_MITER_LIMIT_ }
+procedure conv_stroke_math.inner_miter_limit_;
+begin
+ vcgen_stroke_math_ptr(generator ).inner_miter_limit_(ml );
+
+end;
+
+{ APPROXIMATION_SCALE_ }
+procedure conv_stroke_math.approximation_scale_;
+begin
+ vcgen_stroke_math_ptr(generator ).approximation_scale_(_as_ );
+
+end;
+
+{ _WIDTH }
+function conv_stroke_math._width;
+begin
+ result:=vcgen_stroke_math_ptr(generator )._width;
+
+end;
+
+{ _MITER_LIMIT }
+function conv_stroke_math._miter_limit;
+begin
+ result:=vcgen_stroke_math_ptr(generator )._miter_limit;
+
+end;
+
+{ _INNER_MITER_LIMIT }
+function conv_stroke_math._inner_miter_limit;
+begin
+ result:=vcgen_stroke_math_ptr(generator )._inner_miter_limit;
+
+end;
+
+{ _APPROXIMATION_SCALE }
+function conv_stroke_math._approximation_scale;
+begin
+ result:=vcgen_stroke_math_ptr(generator )._approximation_scale;
+
+end;
+
+{ SHORTEN_ }
+procedure conv_stroke_math.shorten_;
+begin
+ vcgen_stroke_math_ptr(generator ).shorten_(s );
+
+end;
+
+{ _SHORTEN }
+function conv_stroke_math._shorten;
+begin
+ result:=vcgen_stroke_math_ptr(generator )._shorten;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_conv_transform.pas b/src/corelib/render/software/agg_conv_transform.pas
new file mode 100644
index 00000000..f518d807
--- /dev/null
+++ b/src/corelib/render/software/agg_conv_transform.pas
@@ -0,0 +1,113 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// class conv_transform
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 21.12.2005-Milano: Unit port establishment
+//
+{ agg_conv_transform.pas }
+unit
+ agg_conv_transform ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_trans_affine ,
+ agg_vertex_source ;
+
+{ TYPES DEFINITION }
+type
+ conv_transform_ptr = ^conv_transform;
+ conv_transform = object(vertex_source )
+ m_source : vertex_source_ptr;
+ m_trans : trans_affine_ptr;
+
+ constructor Construct(source : vertex_source_ptr; tr : trans_affine_ptr );
+
+ procedure set_source(source : vertex_source_ptr );
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ procedure transformer_(tr : trans_affine_ptr );
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor conv_transform.Construct;
+begin
+ inherited Construct;
+
+ m_source:=source;
+ m_trans :=tr;
+
+end;
+
+{ SET_SOURCE }
+procedure conv_transform.set_source;
+begin
+ m_source:=source;
+
+end;
+
+{ REWIND }
+procedure conv_transform.rewind;
+begin
+ m_source.rewind(path_id );
+
+end;
+
+{ VERTEX }
+function conv_transform.vertex;
+var
+ cmd : unsigned;
+
+begin
+ cmd:=m_source.vertex(x ,y );
+
+ if is_vertex(cmd ) then
+ m_trans.transform(m_trans ,x ,y );
+
+ result:=cmd;
+
+end;
+
+{ TRANSFORMER_ }
+procedure conv_transform.transformer_;
+begin
+ m_trans:=tr;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_curves.pas b/src/corelib/render/software/agg_curves.pas
new file mode 100644
index 00000000..3382b683
--- /dev/null
+++ b/src/corelib/render/software/agg_curves.pas
@@ -0,0 +1,1929 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+// Copyright (C) 2005 Tony Juricic (tonygeek@yahoo.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 12.02.2006-Milano: Unit port establishment
+//
+{ agg_curves.pas }
+unit
+ agg_curves ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ Math ,
+ agg_basics ,
+ agg_array ,
+ agg_vertex_source ;
+
+{ TYPES DEFINITION }
+type
+ curve_approximation_method_e = (curve_inc ,curve_div );
+
+ curve_ptr = ^curve;
+ curve = object(vertex_source )
+ procedure reset; virtual; abstract;
+ procedure init3(x1 ,y1 ,x2, y2 ,x3 ,y3 : double ); virtual;
+ procedure init4(x1 ,y1 ,x2, y2 ,x3 ,y3 ,x4 ,y4 : double ); virtual;
+
+ procedure approximation_method_(v : curve_approximation_method_e ); virtual; abstract;
+ function _approximation_method : curve_approximation_method_e; virtual; abstract;
+
+ procedure approximation_scale_(s : double ); virtual; abstract;
+ function _approximation_scale : double; virtual; abstract;
+
+ procedure angle_tolerance_(a : double ); virtual; abstract;
+ function _angle_tolerance : double; virtual; abstract;
+
+ procedure cusp_limit_(v : double ); virtual; abstract;
+ function _cusp_limit : double; virtual; abstract;
+
+ end;
+
+ curve3_inc = object(curve )
+ m_num_steps ,
+ m_step : int;
+
+ m_scale ,
+ m_start_x ,
+ m_start_y ,
+ m_end_x ,
+ m_end_y ,
+
+ m_fx ,
+ m_fy ,
+ m_dfx ,
+ m_dfy ,
+ m_ddfx ,
+ m_ddfy ,
+
+ m_saved_fx ,
+ m_saved_fy ,
+ m_saved_dfx ,
+ m_saved_dfy : double;
+
+ constructor Construct; overload;
+ constructor Construct(x1 ,y1 ,x2, y2 ,x3 ,y3 : double ); overload;
+
+ procedure reset; virtual;
+ procedure init3(x1 ,y1 ,x2, y2 ,x3 ,y3 : double ); virtual;
+
+ procedure approximation_method_(v : curve_approximation_method_e ); virtual;
+ function _approximation_method : curve_approximation_method_e; virtual;
+
+ procedure approximation_scale_(s : double ); virtual;
+ function _approximation_scale : double; virtual;
+
+ procedure angle_tolerance_(a : double ); virtual;
+ function _angle_tolerance : double; virtual;
+
+ procedure cusp_limit_(v : double ); virtual;
+ function _cusp_limit : double; virtual;
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ end;
+
+ curve3_div = object(curve )
+ m_approximation_scale ,
+ m_distance_tolerance_square ,
+ m_distance_tolerance_manhattan ,
+ m_angle_tolerance : double;
+
+ m_count : unsigned;
+ m_points : pod_deque;
+
+ constructor Construct; overload;
+ constructor Construct(x1 ,y1 ,x2, y2 ,x3 ,y3 : double ); overload;
+ destructor Destruct; virtual;
+
+ procedure reset; virtual;
+ procedure init3(x1 ,y1 ,x2, y2 ,x3 ,y3 : double ); virtual;
+
+ procedure approximation_method_(v : curve_approximation_method_e ); virtual;
+ function _approximation_method : curve_approximation_method_e; virtual;
+
+ procedure approximation_scale_(s : double ); virtual;
+ function _approximation_scale : double; virtual;
+
+ procedure angle_tolerance_(a : double ); virtual;
+ function _angle_tolerance : double; virtual;
+
+ procedure cusp_limit_(v : double ); virtual;
+ function _cusp_limit : double; virtual;
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ procedure bezier (x1 ,y1 ,x2 ,y2 ,x3 ,y3 : double );
+ procedure recursive_bezier(x1 ,y1 ,x2 ,y2 ,x3 ,y3 : double; level : unsigned );
+
+ end;
+
+ curve4_points_ptr = ^curve4_points;
+ curve4_points = object
+ cp : array[0..7 ] of double;
+
+ constructor Construct; overload;
+ constructor Construct(x1 ,y1 ,x2, y2 ,x3 ,y3 ,x4 ,y4 : double ); overload;
+
+ procedure init(x1 ,y1 ,x2, y2 ,x3 ,y3 ,x4 ,y4 : double );
+
+ function array_operator (i : unsigned ) : double;
+ function array_operator_ptr(i : unsigned ) : double_ptr;
+
+ end;
+
+ curve4_inc = object(curve )
+ m_num_steps ,
+ m_step : int;
+
+ m_scale ,
+ m_start_x ,
+ m_start_y ,
+ m_end_x ,
+ m_end_y ,
+
+ m_fx ,
+ m_fy ,
+ m_dfx ,
+ m_dfy ,
+ m_ddfx ,
+ m_ddfy ,
+ m_dddfx ,
+ m_dddfy ,
+
+ m_saved_fx ,
+ m_saved_fy ,
+ m_saved_dfx ,
+ m_saved_dfy ,
+ m_saved_ddfx ,
+ m_saved_ddfy : double;
+
+ constructor Construct; overload;
+ constructor Construct(x1 ,y1 ,x2, y2 ,x3 ,y3 ,x4 ,y4 : double ); overload;
+ constructor Construct(cp : curve4_points_ptr ); overload;
+
+ procedure reset; virtual;
+ procedure init4(x1 ,y1 ,x2, y2 ,x3 ,y3 ,x4 ,y4 : double ); virtual;
+ procedure init (cp : curve4_points_ptr );
+
+ procedure approximation_method_(v : curve_approximation_method_e ); virtual;
+ function _approximation_method : curve_approximation_method_e; virtual;
+
+ procedure approximation_scale_(s : double ); virtual;
+ function _approximation_scale : double; virtual;
+
+ procedure angle_tolerance_(a : double ); virtual;
+ function _angle_tolerance : double; virtual;
+
+ procedure cusp_limit_(v : double ); virtual;
+ function _cusp_limit : double; virtual;
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ end;
+
+ curve4_div = object(curve )
+ m_approximation_scale ,
+ m_distance_tolerance_square ,
+ m_distance_tolerance_manhattan ,
+
+ m_angle_tolerance ,
+ m_cusp_limit : double;
+
+ m_count : unsigned;
+ m_points : pod_deque;
+
+ constructor Construct; overload;
+ constructor Construct(x1 ,y1 ,x2, y2 ,x3 ,y3 ,x4 ,y4 : double ); overload;
+ constructor Construct(cp : curve4_points_ptr ); overload;
+ destructor Destruct; virtual;
+
+ procedure reset; virtual;
+ procedure init4(x1 ,y1 ,x2, y2 ,x3 ,y3 ,x4 ,y4 : double ); virtual;
+ procedure init (cp : curve4_points_ptr );
+
+ procedure approximation_method_(v : curve_approximation_method_e ); virtual;
+ function _approximation_method : curve_approximation_method_e; virtual;
+
+ procedure approximation_scale_(s : double ); virtual;
+ function _approximation_scale : double; virtual;
+
+ procedure angle_tolerance_(a : double ); virtual;
+ function _angle_tolerance : double; virtual;
+
+ procedure cusp_limit_(v : double ); virtual;
+ function _cusp_limit : double; virtual;
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ procedure bezier (x1 ,y1 ,x2 ,y2 ,x3 ,y3 ,x4 ,y4 : double );
+ procedure recursive_bezier(x1 ,y1 ,x2 ,y2 ,x3 ,y3 ,x4 ,y4 : double; level : unsigned );
+
+ end;
+
+ curve3_ptr = ^curve3;
+ curve3 = object(curve )
+ m_curve_inc : curve3_inc;
+ m_curve_div : curve3_div;
+
+ m_approximation_method : curve_approximation_method_e;
+
+ constructor Construct; overload;
+ constructor Construct(x1 ,y1 ,x2, y2 ,x3 ,y3 : double ); overload;
+ destructor Destruct; virtual;
+
+ procedure reset; virtual;
+ procedure init3(x1 ,y1 ,x2, y2 ,x3 ,y3 : double ); virtual;
+
+ procedure approximation_method_(v : curve_approximation_method_e ); virtual;
+ function _approximation_method : curve_approximation_method_e; virtual;
+
+ procedure approximation_scale_(s : double ); virtual;
+ function _approximation_scale : double; virtual;
+
+ procedure angle_tolerance_(a : double ); virtual;
+ function _angle_tolerance : double; virtual;
+
+ procedure cusp_limit_(v : double ); virtual;
+ function _cusp_limit : double; virtual;
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ end;
+
+ curve4_ptr = ^curve4;
+ curve4 = object(curve )
+ m_curve_inc : curve4_inc;
+ m_curve_div : curve4_div;
+
+ m_approximation_method : curve_approximation_method_e;
+
+ constructor Construct; overload;
+ constructor Construct(x1 ,y1 ,x2, y2 ,x3 ,y3 ,x4 ,y4 : double ); overload;
+ constructor Construct(cp : curve4_points_ptr ); overload;
+ destructor Destruct; virtual;
+
+ procedure reset; virtual;
+ procedure init4(x1 ,y1 ,x2, y2 ,x3 ,y3 ,x4 ,y4 : double ); virtual;
+ procedure init (cp : curve4_points_ptr );
+
+ procedure approximation_method_(v : curve_approximation_method_e ); virtual;
+ function _approximation_method : curve_approximation_method_e; virtual;
+
+ procedure approximation_scale_(s : double ); virtual;
+ function _approximation_scale : double; virtual;
+
+ procedure angle_tolerance_(a : double ); virtual;
+ function _angle_tolerance : double; virtual;
+
+ procedure cusp_limit_(v : double ); virtual;
+ function _cusp_limit : double; virtual;
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+ function catrom_to_bezier(x1 ,y1 ,x2 ,y2 ,x3 ,y3 ,x4 ,y4 : double ) : curve4_points; overload;
+ function catrom_to_bezier(cp : curve4_points_ptr ) : curve4_points; overload;
+
+ function ubspline_to_bezier(x1 ,y1 ,x2 ,y2 ,x3 ,y3 ,x4 ,y4 : double ) : curve4_points; overload;
+ function ubspline_to_bezier(cp : curve4_points_ptr ) : curve4_points; overload;
+
+ function hermite_to_bezier(x1 ,y1 ,x2 ,y2 ,x3 ,y3 ,x4 ,y4 : double ) : curve4_points; overload;
+ function hermite_to_bezier(cp : curve4_points_ptr ) : curve4_points; overload;
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+const
+ curve_distance_epsilon = 1e-30;
+ curve_collinearity_epsilon = 1e-30;
+ curve_angle_tolerance_epsilon = 0.01;
+ curve_recursion_limit = 32;
+
+{ UNIT IMPLEMENTATION }
+{ CATROM_TO_BEZIER }
+function catrom_to_bezier(x1 ,y1 ,x2 ,y2 ,x3 ,y3 ,x4 ,y4 : double ) : curve4_points;
+begin
+// Trans. matrix Catmull-Rom to Bezier
+//
+// 0 1 0 0
+// -1/6 1 1/6 0
+// 0 1/6 1 -1/6
+// 0 0 1 0
+//
+ result.Construct(
+ x2 ,
+ y2 ,
+ (-x1 + 6 * x2 + x3 ) / 6 ,
+ (-y1 + 6 * y2 + y3 ) / 6 ,
+ ( x2 + 6 * x3 - x4 ) / 6 ,
+ ( y2 + 6 * y3 - y4 ) / 6 ,
+ x3 ,
+ y3 );
+
+end;
+
+{ CATROM_TO_BEZIER }
+function catrom_to_bezier(cp : curve4_points_ptr ) : curve4_points;
+begin
+ result:=
+ catrom_to_bezier(
+ cp.array_operator(0 ) ,
+ cp.array_operator(1 ) ,
+ cp.array_operator(2 ) ,
+ cp.array_operator(3 ) ,
+ cp.array_operator(4 ) ,
+ cp.array_operator(5 ) ,
+ cp.array_operator(6 ) ,
+ cp.array_operator(7 ) );
+
+end;
+
+{ UBSPLINE_TO_BEZIER }
+function ubspline_to_bezier(x1 ,y1 ,x2 ,y2 ,x3 ,y3 ,x4 ,y4 : double ) : curve4_points;
+begin
+// Trans. matrix Uniform BSpline to Bezier
+//
+// 1/6 4/6 1/6 0
+// 0 4/6 2/6 0
+// 0 2/6 4/6 0
+// 0 1/6 4/6 1/6
+//
+ result.Construct(
+ (x1 + 4 * x2 + x3 ) / 6 ,
+ (y1 + 4 * y2 + y3 ) / 6 ,
+ (4 * x2 + 2 * x3 ) / 6 ,
+ (4 * y2 + 2 * y3 ) / 6 ,
+ (2 * x2 + 4 * x3 ) / 6 ,
+ (2 * y2 + 4 * y3 ) / 6 ,
+ (x2 + 4 * x3 + x4 ) / 6 ,
+ (y2 + 4 * y3 + y4 ) / 6 );
+
+end;
+
+{ UBSPLINE_TO_BEZIER }
+function ubspline_to_bezier(cp : curve4_points_ptr ) : curve4_points;
+begin
+ result:=
+ ubspline_to_bezier(
+ cp.array_operator(0 ) ,
+ cp.array_operator(1 ) ,
+ cp.array_operator(2 ) ,
+ cp.array_operator(3 ) ,
+ cp.array_operator(4 ) ,
+ cp.array_operator(5 ) ,
+ cp.array_operator(6 ) ,
+ cp.array_operator(7 ) );
+
+end;
+
+{ HERMITE_TO_BEZIER }
+function hermite_to_bezier(x1 ,y1 ,x2 ,y2 ,x3 ,y3 ,x4 ,y4 : double ) : curve4_points;
+begin
+// Trans. matrix Hermite to Bezier
+//
+// 1 0 0 0
+// 1 0 1/3 0
+// 0 1 0 -1/3
+// 0 1 0 0
+//
+ result.Construct(
+ x1 ,
+ y1 ,
+ (3 * x1 + x3 ) / 3 ,
+ (3 * y1 + y3 ) / 3 ,
+ (3 * x2 - x4 ) / 3 ,
+ (3 * y2 - y4 ) / 3 ,
+ x2 ,
+ y2 );
+
+end;
+
+{ HERMITE_TO_BEZIER }
+function hermite_to_bezier(cp : curve4_points_ptr ) : curve4_points;
+begin
+ result:=
+ hermite_to_bezier(
+ cp.array_operator(0 ) ,
+ cp.array_operator(1 ) ,
+ cp.array_operator(2 ) ,
+ cp.array_operator(3 ) ,
+ cp.array_operator(4 ) ,
+ cp.array_operator(5 ) ,
+ cp.array_operator(6 ) ,
+ cp.array_operator(7 ) );
+
+end;
+
+{ INIT3 }
+procedure curve.init3;
+begin
+end;
+
+{ INIT4 }
+procedure curve.init4;
+begin
+end;
+
+{ CONSTRUCT }
+constructor curve3_inc.Construct;
+begin
+ m_num_steps:=0;
+ m_step :=0;
+ m_scale :=1.0;
+
+end;
+
+{ CONSTRUCT }
+constructor curve3_inc.Construct(x1 ,y1 ,x2, y2 ,x3 ,y3 : double );
+begin
+ m_num_steps:=0;
+ m_step :=0;
+ m_scale :=1.0;
+
+ init3(x1 ,y1 ,x2 ,y2 ,x3 ,y3 );
+
+end;
+
+{ RESET }
+procedure curve3_inc.reset;
+begin
+ m_num_steps:=0;
+ m_step :=-1;
+
+end;
+
+{ INIT3 }
+procedure curve3_inc.init3;
+var
+ dx1 ,dy1 ,dx2 ,dy2 ,len ,tmpx ,tmpy ,
+ subdivide_step ,subdivide_step2 : double;
+
+begin
+ m_start_x:=x1;
+ m_start_y:=y1;
+ m_end_x :=x3;
+ m_end_y :=y3;
+
+ dx1:=x2 - x1;
+ dy1:=y2 - y1;
+ dx2:=x3 - x2;
+ dy2:=y3 - y2;
+
+ len:=Sqrt(dx1 * dx1 + dy1 * dy1 ) + Sqrt(dx2 * dx2 + dy2 * dy2 );
+
+ m_num_steps:=trunc(len * 0.25 * m_scale );
+
+ if m_num_steps < 4 then
+ m_num_steps:=4;
+
+ subdivide_step :=1.0 / m_num_steps;
+ subdivide_step2:=subdivide_step * subdivide_step;
+
+ tmpx:=(x1 - x2 * 2.0 + x3 ) * subdivide_step2;
+ tmpy:=(y1 - y2 * 2.0 + y3 ) * subdivide_step2;
+
+ m_saved_fx:=x1;
+ m_fx :=x1;
+ m_saved_fy:=y1;
+ m_fy :=y1;
+
+ m_saved_dfx:=tmpx + (x2 - x1 ) * (2.0 * subdivide_step );
+ m_dfx :=m_saved_dfx;
+ m_saved_dfy:=tmpy + (y2 - y1 ) * (2.0 * subdivide_step );
+ m_dfy :=m_saved_dfy;
+
+ m_ddfx:=tmpx * 2.0;
+ m_ddfy:=tmpy * 2.0;
+
+ m_step:=m_num_steps;
+
+end;
+
+{ APPROXIMATION_METHOD_ }
+procedure curve3_inc.approximation_method_;
+begin
+end;
+
+{ _APPROXIMATION_METHOD }
+function curve3_inc._approximation_method;
+begin
+ result:=curve_inc;
+
+end;
+
+{ APPROXIMATION_SCALE_ }
+procedure curve3_inc.approximation_scale_;
+begin
+ m_scale:=s;
+
+end;
+
+{ _APPROXIMATION_SCALE }
+function curve3_inc._approximation_scale;
+begin
+ result:=m_scale;
+
+end;
+
+{ ANGLE_TOLERANCE_ }
+procedure curve3_inc.angle_tolerance_;
+begin
+end;
+
+{ _ANGLE_TOLERANCE }
+function curve3_inc._angle_tolerance;
+begin
+ result:=0.0;
+
+end;
+
+{ CUSP_LIMIT_ }
+procedure curve3_inc.cusp_limit_;
+begin
+end;
+
+{ _CUSP_LIMIT }
+function curve3_inc._cusp_limit;
+begin
+ result:=0.0;
+
+end;
+
+{ REWIND }
+procedure curve3_inc.rewind;
+begin
+ if m_num_steps = 0 then
+ begin
+ m_step:=-1;
+
+ exit;
+
+ end;
+
+ m_step:=m_num_steps;
+ m_fx :=m_saved_fx;
+ m_fy :=m_saved_fy;
+ m_dfx :=m_saved_dfx;
+ m_dfy :=m_saved_dfy;
+
+end;
+
+{ VERTEX }
+function curve3_inc.vertex;
+begin
+ if m_step < 0 then
+ begin
+ result:=path_cmd_stop;
+
+ exit;
+
+ end;
+
+ if m_step = m_num_steps then
+ begin
+ x^:=m_start_x;
+ y^:=m_start_y;
+
+ dec(m_step );
+
+ result:=path_cmd_move_to;
+
+ exit;
+
+ end;
+
+ if m_step = 0 then
+ begin
+ x^:=m_end_x;
+ y^:=m_end_y;
+
+ dec(m_step );
+
+ result:=path_cmd_line_to;
+
+ exit;
+
+ end;
+
+ m_fx :=m_fx + m_dfx;
+ m_fy :=m_fy + m_dfy;
+ m_dfx:=m_dfx + m_ddfx;
+ m_dfy:=m_dfy + m_ddfy;
+
+ x^:=m_fx;
+ y^:=m_fy;
+
+ dec(m_step );
+
+ result:=path_cmd_line_to;
+
+end;
+
+{ CONSTRUCT }
+constructor curve3_div.Construct;
+begin
+ m_points.Construct(sizeof(point_type ) );
+
+ m_approximation_scale:=1.0;
+ m_angle_tolerance :=0.0;
+ m_count :=0;
+
+end;
+
+{ CONSTRUCT }
+constructor curve3_div.Construct(x1 ,y1 ,x2, y2 ,x3 ,y3 : double );
+begin
+ m_points.Construct(sizeof(point_type ) );
+
+ m_approximation_scale:=1.0;
+ m_angle_tolerance :=0.0;
+ m_count :=0;
+
+ init3(x1 ,y1 ,x2, y2 ,x3 ,y3 );
+
+end;
+
+{ DESTRUCT }
+destructor curve3_div.Destruct;
+begin
+ m_points.Destruct;
+
+end;
+
+{ RESET }
+procedure curve3_div.reset;
+begin
+ m_points.remove_all;
+
+ m_count:=0;
+
+end;
+
+{ INIT3 }
+procedure curve3_div.init3;
+begin
+ m_points.remove_all;
+
+ m_distance_tolerance_square :=0.5 / m_approximation_scale;
+ m_distance_tolerance_square :=m_distance_tolerance_square * m_distance_tolerance_square;
+ m_distance_tolerance_manhattan:=4.0 / m_approximation_scale;
+
+ bezier(x1 ,y1 ,x2 ,y2 ,x3 ,y3 );
+
+ m_count:=0;
+
+end;
+
+{ APPROXIMATION_METHOD_ }
+procedure curve3_div.approximation_method_;
+begin
+end;
+
+{ _APPROXIMATION_METHOD }
+function curve3_div._approximation_method;
+begin
+ result:=curve_div;
+
+end;
+
+{ APPROXIMATION_SCALE_ }
+procedure curve3_div.approximation_scale_;
+begin
+ if s = 0 then
+ m_approximation_scale:=0.00001
+ else
+ m_approximation_scale:=s;
+
+end;
+
+{ _APPROXIMATION_SCALE }
+function curve3_div._approximation_scale;
+begin
+ result:=m_approximation_scale;
+
+end;
+
+{ ANGLE_TOLERANCE_ }
+procedure curve3_div.angle_tolerance_;
+begin
+ m_angle_tolerance:=a;
+
+end;
+
+{ _ANGLE_TOLERANCE }
+function curve3_div._angle_tolerance;
+begin
+ result:=m_angle_tolerance;
+
+end;
+
+{ CUSP_LIMIT_ }
+procedure curve3_div.cusp_limit_;
+begin
+end;
+
+{ _CUSP_LIMIT }
+function curve3_div._cusp_limit;
+begin
+ result:=0.0;
+
+end;
+
+{ REWIND }
+procedure curve3_div.rewind;
+begin
+ m_count:=0;
+
+end;
+
+{ VERTEX }
+function curve3_div.vertex;
+var
+ p : point_type_ptr;
+
+begin
+ if m_count >= m_points.size then
+ begin
+ result:=path_cmd_stop;
+
+ exit;
+
+ end;
+
+ p:=m_points.array_operator(m_count );
+
+ inc(m_count );
+
+ x^:=p.x;
+ y^:=p.y;
+
+ if m_count = 1 then
+ result:=path_cmd_move_to
+ else
+ result:=path_cmd_line_to;
+
+end;
+
+{ BEZIER }
+procedure curve3_div.bezier;
+var
+ pt : point_type;
+
+begin
+ pt.x:=x1;
+ pt.y:=y1;
+
+ m_points.add(@pt );
+
+ recursive_bezier(x1 ,y1 ,x2 ,y2 ,x3 ,y3 ,0 );
+
+ pt.x:=x3;
+ pt.y:=y3;
+
+ m_points.add(@pt );
+
+end;
+
+{ RECURSIVE_BEZIER }
+procedure curve3_div.recursive_bezier;
+var
+ x12 ,y12 ,x23 ,y23 ,x123 ,y123 ,dx ,dy ,d ,da : double;
+
+ pt : point_type;
+
+begin
+ if level > curve_recursion_limit then
+ exit;
+
+// Calculate all the mid-points of the line segments
+ x12 :=(x1 + x2 ) / 2;
+ y12 :=(y1 + y2 ) / 2;
+ x23 :=(x2 + x3 ) / 2;
+ y23 :=(y2 + y3 ) / 2;
+ x123:=(x12 + x23 ) / 2;
+ y123:=(y12 + y23 ) / 2;
+
+ dx:=x3 - x1;
+ dy:=y3 - y1;
+ d :=Abs((x2 - x3 ) * dy - (y2 - y3 ) * dx );
+
+ if d > curve_collinearity_epsilon then
+ // Regular care
+ if d * d <= m_distance_tolerance_square * (dx * dx + dy * dy ) then
+ begin
+ // If the curvature doesn't exceed the distance_tolerance value
+ // we tend to finish subdivisions.
+ if m_angle_tolerance < curve_angle_tolerance_epsilon then
+ begin
+ pt.x:=x123;
+ pt.y:=y123;
+
+ m_points.add(@pt );
+
+ exit;
+
+ end;
+
+ // Angle & Cusp Condition
+ da:=Abs(ArcTan2(y3 - y2 ,x3 - x2 ) - ArcTan2(y2 - y1 ,x2 - x1 ) );
+
+ if da >= pi then
+ da:=2 * pi - da;
+
+ if da < m_angle_tolerance then
+ begin
+ // Finally we can stop the recursion
+ pt.x:=x123;
+ pt.y:=y123;
+
+ m_points.add(@pt );
+
+ exit;
+
+ end;
+
+ end
+ else
+ else
+ if Abs(x1 + x3 - x2 - x2 ) + Abs(y1 + y3 - y2 - y2 ) <= m_distance_tolerance_manhattan then
+ begin
+ pt.x:=x123;
+ pt.y:=y123;
+
+ m_points.add(@pt );
+
+ exit;
+
+ end;
+
+// Continue subdivision
+ recursive_bezier(x1 ,y1 ,x12 ,y12 ,x123 ,y123 ,level + 1 );
+ recursive_bezier(x123 ,y123 ,x23 ,y23 ,x3 ,y3 ,level + 1 );
+
+end;
+
+{ CONSTRUCT }
+constructor curve4_points.Construct;
+begin
+end;
+
+{ CONSTRUCT }
+constructor curve4_points.Construct(x1 ,y1 ,x2, y2 ,x3 ,y3 ,x4 ,y4 : double );
+begin
+ cp[0 ]:=x1;
+ cp[1 ]:=y1;
+ cp[2 ]:=x2;
+ cp[3 ]:=y2;
+ cp[4 ]:=x3;
+ cp[5 ]:=y3;
+ cp[6 ]:=x4;
+ cp[7 ]:=y4;
+
+end;
+
+{ INIT }
+procedure curve4_points.init;
+begin
+ cp[0 ]:=x1;
+ cp[1 ]:=y1;
+ cp[2 ]:=x2;
+ cp[3 ]:=y2;
+ cp[4 ]:=x3;
+ cp[5 ]:=y3;
+ cp[6 ]:=x4;
+ cp[7 ]:=y4;
+
+end;
+
+{ ARRAY_OPERATOR }
+function curve4_points.array_operator;
+begin
+ result:=cp[i ];
+
+end;
+
+{ ARRAY_OPERATOR_PTR }
+function curve4_points.array_operator_ptr;
+begin
+ result:=@cp[i ];
+
+end;
+
+{ CONSTRUCT }
+constructor curve4_inc.Construct;
+begin
+ m_num_steps:=0;
+ m_step :=0;
+ m_scale :=1.0;
+
+end;
+
+{ CONSTRUCT }
+constructor curve4_inc.Construct(x1 ,y1 ,x2, y2 ,x3 ,y3 ,x4 ,y4 : double );
+begin
+ m_num_steps:=0;
+ m_step :=0;
+ m_scale :=1.0;
+
+ init4(x1 ,y1 ,x2, y2 ,x3 ,y3 ,x4 ,y4 );
+
+end;
+
+{ CONSTRUCT }
+constructor curve4_inc.Construct(cp : curve4_points_ptr );
+begin
+ m_num_steps:=0;
+ m_step :=0;
+ m_scale :=1.0;
+
+ init4(
+ cp.array_operator(0 ) ,
+ cp.array_operator(1 ) ,
+ cp.array_operator(2 ) ,
+ cp.array_operator(3 ) ,
+ cp.array_operator(4 ) ,
+ cp.array_operator(5 ) ,
+ cp.array_operator(6 ) ,
+ cp.array_operator(7 ) );
+
+end;
+
+{ RESET }
+procedure curve4_inc.reset;
+begin
+ m_num_steps:=0;
+ m_step :=-1;
+
+end;
+
+{ INIT4 }
+procedure curve4_inc.init4;
+var
+ dx1 ,dy1 ,dx2 ,dy2 ,dx3 ,dy3 ,len ,
+
+ subdivide_step ,
+ subdivide_step2 ,
+ subdivide_step3 ,
+
+ pre1 ,pre2 ,pre4 ,pre5 ,tmp1x ,tmp1y ,tmp2x ,tmp2y : double;
+
+begin
+ m_start_x:=x1;
+ m_start_y:=y1;
+ m_end_x :=x4;
+ m_end_y :=y4;
+
+ dx1:=x2 - x1;
+ dy1:=y2 - y1;
+ dx2:=x3 - x2;
+ dy2:=y3 - y2;
+ dx3:=x4 - x3;
+ dy3:=y4 - y3;
+
+ len:=
+ Sqrt(dx1 * dx1 + dy1 * dy1 ) +
+ Sqrt(dx2 * dx2 + dy2 * dy2 ) +
+ Sqrt(dx3 * dx3 + dy3 * dy3 );
+
+ m_num_steps:=trunc(len * 0.25 * m_scale );
+
+ if m_num_steps < 4 then
+ m_num_steps:=4;
+
+ subdivide_step :=1.0 / m_num_steps;
+ subdivide_step2:=subdivide_step * subdivide_step;
+ subdivide_step3:=subdivide_step * subdivide_step * subdivide_step;
+
+ pre1:=3.0 * subdivide_step;
+ pre2:=3.0 * subdivide_step2;
+ pre4:=6.0 * subdivide_step2;
+ pre5:=6.0 * subdivide_step3;
+
+ tmp1x:=x1 - x2 * 2.0 + x3;
+ tmp1y:=y1 - y2 * 2.0 + y3;
+
+ tmp2x:=(x2 - x3 ) * 3.0 - x1 + x4;
+ tmp2y:=(y2 - y3 ) * 3.0 - y1 + y4;
+
+ m_saved_fx:=x1;
+ m_fx :=x1;
+ m_saved_fy:=y1;
+ m_fy :=y1;
+
+ m_saved_dfx:=(x2 - x1 ) * pre1 + tmp1x * pre2 + tmp2x * subdivide_step3;
+ m_dfx :=m_saved_dfx;
+ m_saved_dfy:=(y2 - y1 ) * pre1 + tmp1y * pre2 + tmp2y * subdivide_step3;
+ m_dfy :=m_saved_dfy;
+
+ m_saved_ddfx:=tmp1x * pre4 + tmp2x * pre5;
+ m_ddfx :=m_saved_ddfx;
+ m_saved_ddfy:=tmp1y * pre4 + tmp2y * pre5;
+ m_ddfy :=m_saved_ddfy;
+
+ m_dddfx:=tmp2x * pre5;
+ m_dddfy:=tmp2y * pre5;
+
+ m_step:=m_num_steps;
+
+end;
+
+{ INIT }
+procedure curve4_inc.init;
+begin
+ init4(
+ cp.array_operator(0 ) ,
+ cp.array_operator(1 ) ,
+ cp.array_operator(2 ) ,
+ cp.array_operator(3 ) ,
+ cp.array_operator(4 ) ,
+ cp.array_operator(5 ) ,
+ cp.array_operator(6 ) ,
+ cp.array_operator(7 ) );
+
+end;
+
+{ APPROXIMATION_METHOD_ }
+procedure curve4_inc.approximation_method_;
+begin
+end;
+
+{ _APPROXIMATION_METHOD }
+function curve4_inc._approximation_method;
+begin
+ result:=curve_inc;
+
+end;
+
+{ APPROXIMATION_SCALE_ }
+procedure curve4_inc.approximation_scale_;
+begin
+ m_scale:=s;
+
+end;
+
+{ _APPROXIMATION_SCALE }
+function curve4_inc._approximation_scale;
+begin
+ result:=m_scale;
+
+end;
+
+{ ANGLE_TOLERANCE_ }
+procedure curve4_inc.angle_tolerance_;
+begin
+end;
+
+{ _ANGLE_TOLERANCE }
+function curve4_inc._angle_tolerance;
+begin
+ result:=0.0;
+
+end;
+
+{ CUSP_LIMIT_ }
+procedure curve4_inc.cusp_limit_;
+begin
+end;
+
+{ _CUSP_LIMIT }
+function curve4_inc._cusp_limit;
+begin
+ result:=0.0;
+
+end;
+
+{ REWIND }
+procedure curve4_inc.rewind;
+begin
+ if m_num_steps = 0 then
+ begin
+ m_step:=-1;
+
+ exit;
+
+ end;
+
+ m_step:=m_num_steps;
+ m_fx :=m_saved_fx;
+ m_fy :=m_saved_fy;
+ m_dfx :=m_saved_dfx;
+ m_dfy :=m_saved_dfy;
+ m_ddfx:=m_saved_ddfx;
+ m_ddfy:=m_saved_ddfy;
+
+end;
+
+{ VERTEX }
+function curve4_inc.vertex;
+begin
+ if m_step < 0 then
+ begin
+ result:=path_cmd_stop;
+
+ exit;
+
+ end;
+
+ if m_step = m_num_steps then
+ begin
+ x^:=m_start_x;
+ y^:=m_start_y;
+
+ dec(m_step );
+
+ result:=path_cmd_move_to;
+
+ exit;
+
+ end;
+
+ if m_step = 0 then
+ begin
+ x^:=m_end_x;
+ y^:=m_end_y;
+
+ dec(m_step );
+
+ result:=path_cmd_line_to;
+
+ exit;
+
+ end;
+
+ m_fx :=m_fx + m_dfx;
+ m_fy :=m_fy + m_dfy;
+ m_dfx :=m_dfx + m_ddfx;
+ m_dfy :=m_dfy + m_ddfy;
+ m_ddfx:=m_ddfx + m_dddfx;
+ m_ddfy:=m_ddfy + m_dddfy;
+
+ x^:=m_fx;
+ y^:=m_fy;
+
+ dec(m_step );
+
+ result:=path_cmd_line_to;
+
+end;
+
+{ CONSTRUCT }
+constructor curve4_div.Construct;
+begin
+ m_points.Construct(sizeof(point_type ) );
+
+ m_approximation_scale:=1.0;
+ m_angle_tolerance :=0.0;
+
+ m_cusp_limit:=0.0;
+ m_count :=0;
+
+end;
+
+{ CONSTRUCT }
+constructor curve4_div.Construct(x1 ,y1 ,x2, y2 ,x3 ,y3 ,x4 ,y4 : double );
+begin
+ m_points.Construct(sizeof(point_type ) );
+
+ m_approximation_scale:=1.0;
+ m_angle_tolerance :=0.0;
+
+ m_cusp_limit:=0.0;
+ m_count :=0;
+
+ init4(x1 ,y1 ,x2, y2 ,x3 ,y3 ,x4 ,y4 );
+
+end;
+
+{ CONSTRUCT }
+constructor curve4_div.Construct(cp : curve4_points_ptr );
+begin
+ m_points.Construct(sizeof(point_type ) );
+
+ m_approximation_scale:=1.0;
+ m_angle_tolerance :=0.0;
+
+ m_cusp_limit:=0.0;
+ m_count :=0;
+
+ init4(
+ cp.array_operator(0 ) ,
+ cp.array_operator(1 ) ,
+ cp.array_operator(2 ) ,
+ cp.array_operator(3 ) ,
+ cp.array_operator(4 ) ,
+ cp.array_operator(5 ) ,
+ cp.array_operator(6 ) ,
+ cp.array_operator(7 ) );
+
+end;
+
+{ DESTRUCT }
+destructor curve4_div.Destruct;
+begin
+ m_points.Destruct;
+
+end;
+
+{ RESET }
+procedure curve4_div.reset;
+begin
+ m_points.remove_all;
+
+ m_count:=0;
+
+end;
+
+{ INIT4 }
+procedure curve4_div.init4;
+begin
+ m_points.remove_all;
+
+ m_distance_tolerance_square :=0.5 / m_approximation_scale;
+ m_distance_tolerance_square :=m_distance_tolerance_square * m_distance_tolerance_square;
+ m_distance_tolerance_manhattan:=4.0 / m_approximation_scale;
+
+ bezier(x1 ,y1 ,x2 ,y2 ,x3 ,y3 ,x4 ,y4 );
+
+ m_count:=0;
+
+end;
+
+{ INIT }
+procedure curve4_div.init;
+begin
+ init4(
+ cp.array_operator(0 ) ,
+ cp.array_operator(1 ) ,
+ cp.array_operator(2 ) ,
+ cp.array_operator(3 ) ,
+ cp.array_operator(4 ) ,
+ cp.array_operator(5 ) ,
+ cp.array_operator(6 ) ,
+ cp.array_operator(7 ) );
+
+end;
+
+{ APPROXIMATION_METHOD_ }
+procedure curve4_div.approximation_method_;
+begin
+end;
+
+{ _APPROXIMATION_METHOD }
+function curve4_div._approximation_method;
+begin
+ result:=curve_div;
+
+end;
+
+{ APPROXIMATION_SCALE_ }
+procedure curve4_div.approximation_scale_;
+begin
+ if s = 0 then
+ m_approximation_scale:=0.00001
+ else
+ m_approximation_scale:=s;
+
+end;
+
+{ _APPROXIMATION_SCALE }
+function curve4_div._approximation_scale;
+begin
+ result:=m_approximation_scale;
+
+end;
+
+{ ANGLE_TOLERANCE_ }
+procedure curve4_div.angle_tolerance_;
+begin
+ m_angle_tolerance:=a;
+
+end;
+
+{ _ANGLE_TOLERANCE }
+function curve4_div._angle_tolerance;
+begin
+ result:=m_angle_tolerance;
+
+end;
+
+{ CUSP_LIMIT_ }
+procedure curve4_div.cusp_limit_;
+begin
+ if v = 0.0 then
+ m_cusp_limit:=0.0
+ else
+ m_cusp_limit:=pi - v;
+
+end;
+
+{ _CUSP_LIMIT }
+function curve4_div._cusp_limit;
+begin
+ if m_cusp_limit = 0.0 then
+ result:=0.0
+ else
+ result:=pi - m_cusp_limit;
+
+end;
+
+{ REWIND }
+procedure curve4_div.rewind;
+begin
+ m_count:=0;
+
+end;
+
+{ VERTEX }
+function curve4_div.vertex;
+var
+ p : point_type_ptr;
+
+begin
+ if m_count >= m_points.size then
+ begin
+ result:=path_cmd_stop;
+
+ exit;
+
+ end;
+
+ p:=m_points.array_operator(m_count );
+
+ inc(m_count );
+
+ x^:=p.x;
+ y^:=p.y;
+
+ if m_count = 1 then
+ result:=path_cmd_move_to
+ else
+ result:=path_cmd_line_to;
+
+end;
+
+{ BEZIER }
+procedure curve4_div.bezier;
+var
+ pt : point_type;
+
+begin
+ pt.x:=x1;
+ pt.y:=y1;
+
+ m_points.add(@pt );
+
+ recursive_bezier(x1 ,y1 ,x2 ,y2 ,x3 ,y3 ,x4 ,y4 ,0 );
+
+ pt.x:=x4;
+ pt.y:=y4;
+
+ m_points.add(@pt );
+
+end;
+
+{ RECURSIVE_BEZIER }
+procedure curve4_div.recursive_bezier;
+var
+ x12 ,y12 ,x23 ,y23 ,x34 ,y34 ,x123 ,y123 ,x234 ,y234 ,x1234 ,y1234 ,
+
+ dx ,dy ,d2 ,d3 ,da1 ,da2 ,a23 : double;
+
+ pt : point_type;
+
+begin
+ if level > curve_recursion_limit then
+ exit;
+
+// Calculate all the mid-points of the line segments
+ x12 :=(x1 + x2 ) / 2;
+ y12 :=(y1 + y2 ) / 2;
+ x23 :=(x2 + x3 ) / 2;
+ y23 :=(y2 + y3 ) / 2;
+ x34 :=(x3 + x4 ) / 2;
+ y34 :=(y3 + y4 ) / 2;
+ x123 :=(x12 + x23 ) / 2;
+ y123 :=(y12 + y23 ) / 2;
+ x234 :=(x23 + x34 ) / 2;
+ y234 :=(y23 + y34 ) / 2;
+ x1234:=(x123 + x234 ) / 2;
+ y1234:=(y123 + y234 ) / 2;
+
+// Try to approximate the full cubic curve by a single straight line
+ dx:=x4 - x1;
+ dy:=y4 - y1;
+
+ d2:=Abs((x2 - x4 ) * dy - (y2 - y4 ) * dx );
+ d3:=Abs((x3 - x4 ) * dy - (y3 - y4 ) * dx );
+
+ case ((int(d2 > curve_collinearity_epsilon) shl 1 ) +
+ int(d3 > curve_collinearity_epsilon ) ) of
+ // All collinear OR p1==p4
+ 0 :
+ if Abs(x1 + x3 - x2 - x2 ) +
+ Abs(y1 + y3 - y2 - y2 ) +
+ Abs(x2 + x4 - x3 - x3 ) +
+ Abs(y2 + y4 - y3 - y3 ) <= m_distance_tolerance_manhattan then
+ begin
+ pt.x:=x1234;
+ pt.y:=y1234;
+
+ m_points.add(@pt );
+
+ exit;
+
+ end;
+
+ // p1,p2,p4 are collinear, p3 is considerable
+ 1 :
+ if d3 * d3 <= m_distance_tolerance_square * (dx * dx + dy * dy ) then
+ begin
+ if m_angle_tolerance < curve_angle_tolerance_epsilon then
+ begin
+ pt.x:=x23;
+ pt.y:=y23;
+
+ m_points.add(@pt );
+
+ exit;
+
+ end;
+
+ // Angle Condition
+ da1:=Abs(ArcTan2(y4 - y3 ,x4 - x3 ) - ArcTan2(y3 - y2 ,x3 - x2 ) );
+
+ if da1 >= pi then
+ da1:=2 * pi - da1;
+
+ if da1 < m_angle_tolerance then
+ begin
+ pt.x:=x2;
+ pt.y:=y2;
+
+ m_points.add(@pt );
+
+ pt.x:=x3;
+ pt.y:=y3;
+
+ m_points.add(@pt );
+
+ exit;
+
+ end;
+
+ if m_cusp_limit <> 0.0 then
+ if da1 > m_cusp_limit then
+ begin
+ pt.x:=x3;
+ pt.y:=y3;
+
+ m_points.add(@pt );
+
+ exit;
+
+ end;
+
+ end;
+
+ // p1,p3,p4 are collinear, p2 is considerable
+ 2 :
+ if d2 * d2 <= m_distance_tolerance_square * (dx * dx + dy * dy ) then
+ begin
+ if m_angle_tolerance < curve_angle_tolerance_epsilon then
+ begin
+ pt.x:=x23;
+ pt.y:=y23;
+
+ m_points.add(@pt );
+
+ exit;
+
+ end;
+
+ // Angle Condition
+ da1:=Abs(ArcTan2(y3 - y2 ,x3 - x2 ) - ArcTan2(y2 - y1 ,x2 - x1 ) );
+
+ if da1 >= pi then
+ da1:=2 * pi - da1;
+
+ if da1 < m_angle_tolerance then
+ begin
+ pt.x:=x2;
+ pt.y:=y2;
+
+ m_points.add(@pt );
+
+ pt.x:=x3;
+ pt.y:=y3;
+
+ m_points.add(@pt );
+
+ exit;
+
+ end;
+
+ if m_cusp_limit <> 0.0 then
+ if da1 > m_cusp_limit then
+ begin
+ pt.x:=x2;
+ pt.y:=y2;
+
+ m_points.add(@pt );
+
+ exit;
+
+ end;
+
+ end;
+
+ // Regular care
+ 3 :
+ if (d2 + d3 ) * (d2 + d3 ) <= m_distance_tolerance_square * (dx * dx + dy * dy ) then
+ begin
+ // If the curvature doesn't exceed the distance_tolerance value
+ // we tend to finish subdivisions.
+ if m_angle_tolerance < curve_angle_tolerance_epsilon then
+ begin
+ pt.x:=x23;
+ pt.y:=y23;
+
+ m_points.add(@pt );
+
+ exit;
+
+ end;
+
+ // Angle & Cusp Condition
+ a23:=ArcTan2(y3 - y2 ,x3 - x2 );
+ da1:=Abs(a23 - ArcTan2(y2 - y1 ,x2 - x1 ) );
+ da2:=Abs(ArcTan2(y4 - y3 ,x4 - x3 ) - a23 );
+
+ if da1 >= pi then
+ da1:=2 * pi - da1;
+
+ if da2 >= pi then
+ da2:=2 * pi - da2;
+
+ if da1 + da2 < m_angle_tolerance then
+ begin
+ // Finally we can stop the recursion
+ pt.x:=x23;
+ pt.y:=y23;
+
+ m_points.add(@pt );
+
+ exit;
+
+ end;
+
+ if m_cusp_limit <> 0.0 then
+ begin
+ if da1 > m_cusp_limit then
+ begin
+ pt.x:=x2;
+ pt.y:=y2;
+
+ m_points.add(@pt );
+
+ exit;
+
+ end;
+
+ if da2 > m_cusp_limit then
+ begin
+ pt.x:=x3;
+ pt.y:=y3;
+
+ m_points.add(@pt );
+
+ exit;
+
+ end;
+
+ end;
+
+ end;
+
+ end;
+
+// Continue subdivision
+ recursive_bezier(x1 ,y1 ,x12 ,y12 ,x123 ,y123 ,x1234 ,y1234 ,level + 1 );
+ recursive_bezier(x1234 ,y1234 ,x234 ,y234 ,x34 ,y34 ,x4 ,y4 ,level + 1 );
+
+end;
+
+{ CONSTRUCT }
+constructor curve3.Construct;
+begin
+ m_curve_inc.Construct;
+ m_curve_div.Construct;
+
+ m_approximation_method:=curve_div;
+
+end;
+
+{ CONSTRUCT }
+constructor curve3.Construct(x1 ,y1 ,x2, y2 ,x3 ,y3 : double );
+begin
+ m_curve_inc.Construct;
+ m_curve_div.Construct;
+
+ m_approximation_method:=curve_div;
+
+ init3(x1 ,y1 ,x2, y2 ,x3 ,y3 );
+
+end;
+
+{ DESTRUCT }
+destructor curve3.Destruct;
+begin
+ m_curve_div.Destruct;
+
+end;
+
+{ RESET }
+procedure curve3.reset;
+begin
+ m_curve_inc.reset;
+ m_curve_div.reset;
+
+end;
+
+{ INIT3 }
+procedure curve3.init3;
+begin
+ if m_approximation_method = curve_inc then
+ m_curve_inc.init3(x1 ,y1 ,x2 ,y2 ,x3 ,y3 )
+ else
+ m_curve_div.init3(x1 ,y1 ,x2 ,y2 ,x3 ,y3 );
+
+end;
+
+{ APPROXIMATION_METHOD_ }
+procedure curve3.approximation_method_;
+begin
+ m_approximation_method:=v;
+
+end;
+
+{ _APPROXIMATION_METHOD }
+function curve3._approximation_method;
+begin
+ result:=m_approximation_method;
+
+end;
+
+{ APPROXIMATION_SCALE_ }
+procedure curve3.approximation_scale_;
+begin
+ m_curve_inc.approximation_scale_(s );
+ m_curve_div.approximation_scale_(s );
+
+end;
+
+{ _APPROXIMATION_SCALE }
+function curve3._approximation_scale;
+begin
+ result:=m_curve_inc._approximation_scale;
+
+end;
+
+{ ANGLE_TOLERANCE_ }
+procedure curve3.angle_tolerance_;
+begin
+ m_curve_div.angle_tolerance_(a );
+
+end;
+
+{ _ANGLE_TOLERANCE }
+function curve3._angle_tolerance;
+begin
+ result:=m_curve_div._angle_tolerance;
+
+end;
+
+{ CUSP_LIMIT_ }
+procedure curve3.cusp_limit_;
+begin
+ m_curve_div.cusp_limit_(v );
+
+end;
+
+{ _CUSP_LIMIT }
+function curve3._cusp_limit;
+begin
+ result:=m_curve_div._cusp_limit;
+
+end;
+
+{ REWIND }
+procedure curve3.rewind;
+begin
+ if m_approximation_method = curve_inc then
+ m_curve_inc.rewind(path_id )
+ else
+ m_curve_div.rewind(path_id )
+
+end;
+
+{ VERTEX }
+function curve3.vertex;
+begin
+ if m_approximation_method = curve_inc then
+ result:=m_curve_inc.vertex(x ,y )
+ else
+ result:=m_curve_div.vertex(x ,y );
+
+end;
+
+{ CONSTRUCT }
+constructor curve4.Construct;
+begin
+ m_curve_inc.Construct;
+ m_curve_div.Construct;
+
+ m_approximation_method:=curve_div;
+
+end;
+
+{ CONSTRUCT }
+constructor curve4.Construct(x1 ,y1 ,x2, y2 ,x3 ,y3 ,x4 ,y4 : double );
+begin
+ m_curve_inc.Construct;
+ m_curve_div.Construct;
+
+ m_approximation_method:=curve_div;
+
+ init4(x1 ,y1 ,x2, y2 ,x3 ,y3 ,x4 ,y4 );
+
+end;
+
+{ CONSTRUCT }
+constructor curve4.Construct(cp : curve4_points_ptr );
+begin
+ m_curve_inc.Construct;
+ m_curve_div.Construct;
+
+ m_approximation_method:=curve_div;
+
+ init4(
+ cp.array_operator(0 ) ,
+ cp.array_operator(1 ) ,
+ cp.array_operator(2 ) ,
+ cp.array_operator(3 ) ,
+ cp.array_operator(4 ) ,
+ cp.array_operator(5 ) ,
+ cp.array_operator(6 ) ,
+ cp.array_operator(7 ) );
+
+end;
+
+{ DESTRUCT }
+destructor curve4.Destruct;
+begin
+ m_curve_div.Destruct;
+
+end;
+
+{ RESET }
+procedure curve4.reset;
+begin
+ m_curve_inc.reset;
+ m_curve_div.reset;
+
+end;
+
+{ INIT4 }
+procedure curve4.init4;
+begin
+ if m_approximation_method = curve_inc then
+ m_curve_inc.init4(x1 ,y1 ,x2 ,y2 ,x3 ,y3 ,x4 ,y4 )
+ else
+ m_curve_div.init4(x1 ,y1 ,x2 ,y2 ,x3 ,y3 ,x4 ,y4 );
+
+end;
+
+{ INIT }
+procedure curve4.init;
+begin
+ init4(
+ cp.array_operator(0 ) ,
+ cp.array_operator(1 ) ,
+ cp.array_operator(2 ) ,
+ cp.array_operator(3 ) ,
+ cp.array_operator(4 ) ,
+ cp.array_operator(5 ) ,
+ cp.array_operator(6 ) ,
+ cp.array_operator(7 ) );
+
+end;
+
+{ APPROXIMATION_METHOD_ }
+procedure curve4.approximation_method_;
+begin
+ m_approximation_method:=v;
+
+end;
+
+{ _APPROXIMATION_METHOD }
+function curve4._approximation_method;
+begin
+ result:=m_approximation_method;
+
+end;
+
+{ APPROXIMATION_SCALE_ }
+procedure curve4.approximation_scale_;
+begin
+ m_curve_inc.approximation_scale_(s );
+ m_curve_div.approximation_scale_(s );
+
+end;
+
+{ _APPROXIMATION_SCALE }
+function curve4._approximation_scale;
+begin
+ result:=m_curve_inc._approximation_scale;
+
+end;
+
+{ ANGLE_TOLERANCE_ }
+procedure curve4.angle_tolerance_;
+begin
+ m_curve_div.angle_tolerance_(a );
+
+end;
+
+{ _ANGLE_TOLERANCE }
+function curve4._angle_tolerance;
+begin
+ result:=m_curve_div._angle_tolerance;
+
+end;
+
+{ CUSP_LIMIT_ }
+procedure curve4.cusp_limit_;
+begin
+ m_curve_div.cusp_limit_(v );
+
+end;
+
+{ _CUSP_LIMIT }
+function curve4._cusp_limit;
+begin
+ result:=m_curve_div._cusp_limit;
+
+end;
+
+{ REWIND }
+procedure curve4.rewind;
+begin
+ if m_approximation_method = curve_inc then
+ m_curve_inc.rewind(path_id )
+ else
+ m_curve_div.rewind(path_id );
+
+end;
+
+{ VERTEX }
+function curve4.vertex;
+begin
+ if m_approximation_method = curve_inc then
+ result:=m_curve_inc.vertex(x ,y )
+ else
+ result:=m_curve_div.vertex(x ,y );
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_dda_line.pas b/src/corelib/render/software/agg_dda_line.pas
new file mode 100644
index 00000000..9fdff2a8
--- /dev/null
+++ b/src/corelib/render/software/agg_dda_line.pas
@@ -0,0 +1,436 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// classes dda_line_interpolator, dda2_line_interpolator
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 27.01.2006-Milano: dda_line_interpolator
+// 16.01.2006-Milano: Unit port establishment
+//
+{ agg_dda_line.pas }
+unit
+ agg_dda_line ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+{$Q- }
+{$R- }
+uses
+ agg_basics ;
+
+{ TYPES DEFINITION }
+const
+ subpixel_shift = 8;
+ subpixel_size = 1 shl subpixel_shift;
+ subpixel_mask = subpixel_size - 1;
+
+type
+//===================================================dda_line_interpolator
+ dda_line_interpolator = object
+ m_y ,m_inc ,m_dy ,
+
+ FractionShift ,YShift : int;
+
+ constructor Construct(FS : int; YS : int = 0 ); overload;
+ constructor Construct(y1 ,y2 : int; count : unsigned; FS : int; YS : int = 0 ); overload;
+
+ procedure plus_operator;
+ procedure minus_operator;
+ procedure inc_operator(n : int );
+ procedure dec_operator(n : int );
+
+ function _y : int;
+ function _dy : int;
+
+ end;
+
+//---------------------------------------------line_bresenham_interpolator
+ dda2_line_interpolator = object
+ m_cnt ,
+ m_lft ,
+ m_rem ,
+ m_mod ,
+ m_y : int;
+
+ constructor Construct(y1 ,y2 ,count : int ); overload; // Forward-adjusted line
+ constructor Construct(y ,count : int ); overload; // Backward-adjusted line
+
+ procedure plus_operator;
+ procedure minus_operator;
+
+ function _mod : int;
+ function _rem : int;
+ function _lft : int;
+ function _y : int;
+
+ procedure adjust_forward;
+ procedure adjust_backward;
+
+ end;
+
+ line_bresenham_interpolator = object
+ m_x1_lr ,
+ m_y1_lr ,
+ m_x2_lr ,
+ m_y2_lr : int;
+
+ m_ver : boolean;
+ m_len : unsigned;
+ m_inc : int;
+
+ m_interpolator : dda2_line_interpolator;
+
+ constructor Construct(x1 ,y1 ,x2 ,y2 : int );
+
+ function line_lr(v : int ) : int;
+
+ function _is_ver : boolean;
+ function _len : unsigned;
+ function _inc : int;
+
+ procedure hstep;
+ procedure vstep;
+
+ function _x1 : int;
+ function _y1 : int;
+ function _x2 : int;
+ function _y2 : int;
+ function _x2_hr : int;
+ function _y2_hr : int;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor dda_line_interpolator.Construct(FS : int; YS : int = 0 );
+begin
+ FractionShift:=FS;
+
+ YShift:=YS;
+
+end;
+
+{ CONSTRUCT }
+constructor dda_line_interpolator.Construct(y1 ,y2 : int; count : unsigned; FS : int; YS : int = 0 );
+begin
+ Construct(FS ,YS );
+
+ m_y :=y1;
+ m_inc:=((y2 - y1 ) shl FractionShift ) div count;
+ m_dy :=0;
+
+end;
+
+{ PLUS_OPERATOR }
+procedure dda_line_interpolator.plus_operator;
+begin
+ inc(m_dy ,m_inc );
+
+end;
+
+{ MINUS_OPERATOR }
+procedure dda_line_interpolator.minus_operator;
+begin
+ dec(m_dy ,m_inc );
+
+end;
+
+{ INC_OPERATOR }
+procedure dda_line_interpolator.inc_operator;
+begin
+ inc(m_dy ,m_inc * n );
+
+end;
+
+{ DEC_OPERATOR }
+procedure dda_line_interpolator.dec_operator;
+begin
+ dec(m_dy ,m_inc * n );
+
+end;
+
+{ _Y }
+function dda_line_interpolator._y;
+begin
+ result:=m_y + (shr_int32(m_dy ,FractionShift - YShift ) );
+
+end;
+
+{ _DY }
+function dda_line_interpolator._dy;
+begin
+ result:=m_dy;
+
+end;
+
+{ CONSTRUCT }
+constructor dda2_line_interpolator.Construct(y1 ,y2 ,count : int );
+begin
+ if count <= 0 then
+ m_cnt:=1
+ else
+ m_cnt:=count;
+
+ m_lft:=trunc((y2 - y1 ) / m_cnt );
+ m_rem:=trunc((y2 - y1 ) mod m_cnt );
+ m_mod:=m_rem;
+ m_y :=y1;
+
+ if m_mod <= 0 then
+ begin
+ m_mod:=m_mod + count;
+ m_rem:=m_rem + count;
+
+ dec(m_lft );
+
+ end;
+
+ m_mod:=m_mod - count;
+
+end;
+
+{ CONSTRUCT }
+constructor dda2_line_interpolator.Construct(y ,count : int );
+begin
+ if count <= 0 then
+ m_cnt:=1
+ else
+ m_cnt:=count;
+
+ m_lft:=y div m_cnt;
+ m_rem:=y mod m_cnt;
+ m_mod:=m_rem;
+ m_y :=0;
+
+ if m_mod <= 0 then
+ begin
+ inc(m_mod ,count );
+ inc(m_rem ,count );
+ dec(m_lft );
+
+ end;
+
+end;
+
+{ PLUS_OPERATOR }
+procedure dda2_line_interpolator.plus_operator;
+begin
+ inc(m_mod ,m_rem );
+ inc(m_y ,m_lft );
+
+ if m_mod > 0 then
+ begin
+ dec(m_mod ,m_cnt );
+ inc(m_y );
+
+ end;
+
+end;
+
+{ MINUS_OPERATOR }
+procedure dda2_line_interpolator.minus_operator;
+begin
+ if m_mod <= m_rem then
+ begin
+ inc(m_mod ,m_cnt );
+ dec(m_y );
+
+ end;
+
+ dec(m_mod ,m_rem );
+ dec(m_y ,m_lft );
+
+end;
+
+{ _MOD }
+function dda2_line_interpolator._mod;
+begin
+ result:=m_mod;
+
+end;
+
+{ _REM }
+function dda2_line_interpolator._rem;
+begin
+ result:=m_rem;
+
+end;
+
+{ _LFT }
+function dda2_line_interpolator._lft;
+begin
+ result:=m_lft;
+
+end;
+
+{ _Y }
+function dda2_line_interpolator._y;
+begin
+ result:=m_y;
+
+end;
+
+{ ADJUST_FORWARD }
+procedure dda2_line_interpolator.adjust_forward;
+begin
+ dec(m_mod ,m_cnt );
+
+end;
+
+{ ADJUST_BACKWARD }
+procedure dda2_line_interpolator.adjust_backward;
+begin
+ inc(m_mod ,m_cnt );
+
+end;
+
+{ CONSTRUCT }
+constructor line_bresenham_interpolator.Construct;
+begin
+ m_x1_lr:=line_lr(x1 );
+ m_y1_lr:=line_lr(y1 );
+ m_x2_lr:=line_lr(x2 );
+ m_y2_lr:=line_lr(y2 );
+
+ m_ver:=Abs(m_x2_lr - m_x1_lr ) < Abs(m_y2_lr - m_y1_lr );
+
+ if m_ver then
+ m_len:=Abs(m_y2_lr - m_y1_lr )
+ else
+ m_len:=Abs(m_x2_lr - m_x1_lr );
+
+ if m_ver then
+ if y2 > y1 then
+ m_inc:=1
+ else
+ m_inc:=-1
+ else
+ if x2 > x1 then
+ m_inc:=1
+ else
+ m_inc:=-1;
+
+ if m_ver then
+ m_interpolator.Construct(x1 ,x2 ,m_len )
+ else
+ m_interpolator.Construct(y1 ,y2 ,m_len );
+
+end;
+
+{ LINE_LR }
+function line_bresenham_interpolator.line_lr;
+begin
+ result:=shr_int32(v ,subpixel_shift );
+
+end;
+
+{ _IS_VER }
+function line_bresenham_interpolator._is_ver;
+begin
+ result:=m_ver;
+
+end;
+
+{ _LEN }
+function line_bresenham_interpolator._len;
+begin
+ result:=m_len;
+
+end;
+
+{ _INC }
+function line_bresenham_interpolator._inc;
+begin
+ result:=m_inc;
+
+end;
+
+{ HSTEP }
+procedure line_bresenham_interpolator.hstep;
+begin
+ m_interpolator.plus_operator;
+
+ m_x1_lr:=m_x1_lr + m_inc;
+
+end;
+
+{ VSTEP }
+procedure line_bresenham_interpolator.vstep;
+begin
+ m_interpolator.plus_operator;
+
+ m_y1_lr:=m_y1_lr + m_inc;
+
+end;
+
+{ _X1 }
+function line_bresenham_interpolator._x1;
+begin
+ result:=m_x1_lr;
+
+end;
+
+{ _Y1 }
+function line_bresenham_interpolator._y1;
+begin
+ result:=m_y1_lr;
+
+end;
+
+{ _X2 }
+function line_bresenham_interpolator._x2;
+begin
+ result:=line_lr(m_interpolator._y );
+
+end;
+
+{ _Y2 }
+function line_bresenham_interpolator._y2;
+begin
+ result:=line_lr(m_interpolator._y );
+
+end;
+
+{ _X2_HR }
+function line_bresenham_interpolator._x2_hr;
+begin
+ result:=m_interpolator._y;
+
+end;
+
+{ _Y2_HR }
+function line_bresenham_interpolator._y2_hr;
+begin
+ result:=m_interpolator._y;
+
+end;
+
+END.
+
+
diff --git a/src/corelib/render/software/agg_ellipse.pas b/src/corelib/render/software/agg_ellipse.pas
new file mode 100644
index 00000000..44817ef0
--- /dev/null
+++ b/src/corelib/render/software/agg_ellipse.pas
@@ -0,0 +1,205 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// class ellipse
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 18.12.2005-Milano: Unit port establishment
+//
+{ agg_ellipse.pas }
+unit
+ agg_ellipse ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ Math ,
+ agg_basics ,
+ agg_vertex_source ;
+
+{ TYPES DEFINITION }
+type
+ ellipse_ptr = ^ellipse;
+ ellipse = object(vertex_source )
+ m_x ,
+ m_y ,
+ m_rx ,
+ m_ry ,
+
+ m_scale : double;
+
+ m_num ,
+ m_step : unsigned;
+ m_cw : boolean;
+
+ constructor Construct; overload;
+ constructor Construct(x ,y ,rx ,ry : double; num_steps : unsigned = 0; cw : boolean = false ); overload;
+
+ procedure init(x ,y ,rx ,ry : double; num_steps : unsigned = 0; cw : boolean = false );
+
+ procedure approximation_scale_(scale : double );
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ procedure calc_num_steps;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor ellipse.Construct;
+begin
+ inherited Construct;
+
+ m_x :=0.0;
+ m_y :=0.0;
+ m_rx:=1.0;
+ m_ry:=1.0;
+
+ m_scale:=1.0;
+
+ m_num :=4;
+ m_step:=0;
+ m_cw :=false;
+
+end;
+
+{ CONSTRUCT }
+constructor ellipse.Construct(x ,y ,rx ,ry : double; num_steps : unsigned = 0; cw : boolean = false );
+begin
+ inherited Construct;
+
+ m_x :=x;
+ m_y :=y;
+ m_rx:=rx;
+ m_ry:=ry;
+
+ m_scale:=1.0;
+
+ m_num :=num_steps;
+ m_step:=0;
+ m_cw :=cw;
+
+ if m_num = 0 then
+ calc_num_steps;
+
+end;
+
+{ INIT }
+procedure ellipse.init;
+begin
+ m_x :=x;
+ m_y :=y;
+ m_rx:=rx;
+ m_ry:=ry;
+
+ m_num :=num_steps;
+ m_step:=0;
+ m_cw :=cw;
+
+ if m_num = 0 then
+ calc_num_steps;
+
+end;
+
+{ APPROXIMATION_SCALE_ }
+procedure ellipse.approximation_scale_;
+begin
+ m_scale:=scale;
+
+ calc_num_steps;
+
+end;
+
+{ REWIND }
+procedure ellipse.rewind;
+begin
+ m_step:=0;
+
+end;
+
+{ VERTEX }
+function ellipse.vertex;
+var
+ angle : double;
+
+begin
+ if m_step = m_num then
+ begin
+ inc(m_step );
+
+ result:=path_cmd_end_poly or path_flags_close or path_flags_ccw;
+
+ exit;
+
+ end;
+
+ if m_step > m_num then
+ begin
+ result:=path_cmd_stop;
+
+ exit;
+
+ end;
+
+ angle:=m_step / m_num * 2.0 * pi;
+
+ if m_cw then
+ angle:=2.0 * pi - angle;
+
+ x^:=m_x + Cos(angle ) * m_rx;
+ y^:=m_y + Sin(angle ) * m_ry;
+
+ inc(m_step );
+
+ if m_step = 1 then
+ result:=path_cmd_move_to
+ else
+ result:=path_cmd_line_to;
+
+end;
+
+{ CALC_NUM_STEPS }
+procedure ellipse.calc_num_steps;
+var
+ ra ,
+ da : double;
+
+begin
+ ra:=(Abs(m_rx ) + Abs(m_ry ) ) / 2;
+ da:=ArcCos(ra / (ra + 0.125 / m_scale ) ) * 2;
+
+ m_num:=trunc(2 * pi / da );
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_ellipse_bresenham.pas b/src/corelib/render/software/agg_ellipse_bresenham.pas
new file mode 100644
index 00000000..1cd24a95
--- /dev/null
+++ b/src/corelib/render/software/agg_ellipse_bresenham.pas
@@ -0,0 +1,175 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// Simple Bresenham interpolator for ellipsees
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 31.01.2006-Milano: Unit port establishment
+//
+{ agg_ellipse_bresenham.pas }
+unit
+ agg_ellipse_bresenham ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ;
+
+{ TYPES DEFINITION }
+type
+ ellipse_bresenham_interpolator = object
+ m_rx2 ,
+ m_ry2 ,
+
+ m_two_rx2 ,
+ m_two_ry2 ,
+
+ m_dx ,
+ m_dy ,
+
+ m_inc_x ,
+ m_inc_y ,
+ m_cur_f : int;
+
+ constructor Construct(rx ,ry : int );
+
+ function _dx : int;
+ function _dy : int;
+
+ procedure inc_operator;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor ellipse_bresenham_interpolator.Construct;
+begin
+ m_rx2:=rx * rx;
+ m_ry2:=ry * ry;
+
+ m_two_rx2:=m_rx2 shl 1;
+ m_two_ry2:=m_ry2 shl 1;
+
+ m_dx:=0;
+ m_dy:=0;
+
+ m_inc_x:=0;
+ m_inc_y:=-ry * m_two_rx2;
+ m_cur_f:=0;
+
+end;
+
+{ _DX }
+function ellipse_bresenham_interpolator._dx;
+begin
+ result:=m_dx;
+
+end;
+
+{ _DY }
+function ellipse_bresenham_interpolator._dy;
+begin
+ result:=m_dy;
+
+end;
+
+{ INC_OPERATOR }
+procedure ellipse_bresenham_interpolator.inc_operator;
+var
+ mx ,my ,mxy ,min_m ,fx ,fy ,fxy : int;
+
+ flag : boolean;
+
+begin
+ mx:=m_cur_f + m_inc_x + m_ry2;
+ fx:=mx;
+
+ if mx < 0 then
+ mx:=-mx;
+
+ my:=m_cur_f + m_inc_y + m_rx2;
+ fy:=my;
+
+ if my < 0 then
+ my:=-my;
+
+ mxy:=m_cur_f + m_inc_x + m_ry2 + m_inc_y + m_rx2;
+ fxy:=mxy;
+
+ if mxy < 0 then
+ mxy:=-mxy;
+
+ min_m:=mx;
+ flag :=true;
+
+ if min_m > my then
+ begin
+ min_m:=my;
+ flag :=false;
+
+ end;
+
+ m_dx:=0;
+ m_dy:=0;
+
+ if min_m > mxy then
+ begin
+ inc(m_inc_x ,m_two_ry2 );
+ inc(m_inc_y ,m_two_rx2 );
+
+ m_cur_f:=fxy;
+
+ m_dx:=1;
+ m_dy:=1;
+
+ exit;
+
+ end;
+
+ if flag then
+ begin
+ inc(m_inc_x ,m_two_ry2 );
+
+ m_cur_f:=fx;
+ m_dx :=1;
+
+ exit;
+
+ end;
+
+ inc(m_inc_y ,m_two_rx2 );
+
+ m_cur_f:=fy;
+ m_dy :=1;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_embedded_raster_fonts.pas b/src/corelib/render/software/agg_embedded_raster_fonts.pas
new file mode 100644
index 00000000..eb2368af
--- /dev/null
+++ b/src/corelib/render/software/agg_embedded_raster_fonts.pas
@@ -0,0 +1,10382 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 13.02.2006-Milano: Unit port establishment
+//
+{ agg_embedded_raster_fonts.pas }
+unit
+ agg_embedded_raster_fonts ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ;
+
+{ GLOBAL VARIABLES & CONSTANTS }
+const
+ gse4x6 : array[0..868 ] of int8u = (
+ 6, 0, 32, 128-32,
+
+ $00,$00,$07,$00,$0e,$00,$15,$00,$1c,$00,$23,$00,$2a,$00,$31,$00,$38,$00,
+ $3f,$00,$46,$00,$4d,$00,$54,$00,$5b,$00,$62,$00,$69,$00,$70,$00,$77,$00,
+ $7e,$00,$85,$00,$8c,$00,$93,$00,$9a,$00,$a1,$00,$a8,$00,$af,$00,$b6,$00,
+ $bd,$00,$c4,$00,$cb,$00,$d2,$00,$d9,$00,$e0,$00,$e7,$00,$ee,$00,$f5,$00,
+ $fc,$00,$03,$01,$0a,$01,$11,$01,$18,$01,$1f,$01,$26,$01,$2d,$01,$34,$01,
+ $3b,$01,$42,$01,$49,$01,$50,$01,$57,$01,$5e,$01,$65,$01,$6c,$01,$73,$01,
+ $7a,$01,$81,$01,$88,$01,$8f,$01,$96,$01,$9d,$01,$a4,$01,$ab,$01,$b2,$01,
+ $b9,$01,$c0,$01,$c7,$01,$ce,$01,$d5,$01,$dc,$01,$e3,$01,$ea,$01,$f1,$01,
+ $f8,$01,$ff,$01,$06,$02,$0d,$02,$14,$02,$1b,$02,$22,$02,$29,$02,$30,$02,
+ $37,$02,$3e,$02,$45,$02,$4c,$02,$53,$02,$5a,$02,$61,$02,$68,$02,$6f,$02,
+ $76,$02,$7d,$02,$84,$02,$8b,$02,$92,$02,$99,$02,
+
+ 4, // $20 ' '
+ $00,$00,$00,$00,$00,$00,
+
+ 4, // $21 '!'
+ $40,$40,$40,$00,$40,$00,
+
+ 4, // $22 '"'
+ $a0,$a0,$00,$00,$00,$00,
+
+ 4, // $23 '#'
+ $60,$f0,$60,$f0,$60,$00,
+
+ 4, // $24 '$'
+ $40,$60,$c0,$60,$c0,$40,
+
+ 4, // $25 '%'
+ $a0,$20,$40,$80,$a0,$00,
+
+ 4, // $26 '&'
+ $e0,$a0,$50,$a0,$d0,$00,
+
+ 4, // $27 '''
+ $40,$40,$00,$00,$00,$00,
+
+ 4, // $28 '('
+ $20,$40,$40,$40,$20,$00,
+
+ 4, // $29 ')'
+ $40,$20,$20,$20,$40,$00,
+
+ 4, // $2a '*'
+ $a0,$40,$e0,$40,$a0,$00,
+
+ 4, // $2b '+'
+ $40,$40,$e0,$40,$40,$00,
+
+ 4, // $2c ','
+ $00,$00,$00,$40,$40,$80,
+
+ 4, // $2d '-'
+ $00,$00,$e0,$00,$00,$00,
+
+ 4, // $2e '.'
+ $00,$00,$00,$00,$40,$00,
+
+ 4, // $2f '/'
+ $10,$20,$20,$40,$40,$80,
+
+ 4, // $30 '0'
+ $e0,$a0,$a0,$a0,$e0,$00,
+
+ 4, // $31 '1'
+ $40,$c0,$40,$40,$e0,$00,
+
+ 4, // $32 '2'
+ $e0,$a0,$20,$40,$e0,$00,
+
+ 4, // $33 '3'
+ $e0,$20,$40,$20,$e0,$00,
+
+ 4, // $34 '4'
+ $a0,$a0,$e0,$20,$20,$00,
+
+ 4, // $35 '5'
+ $e0,$80,$c0,$20,$c0,$00,
+
+ 4, // $36 '6'
+ $40,$80,$e0,$a0,$e0,$00,
+
+ 4, // $37 '7'
+ $e0,$a0,$20,$40,$40,$00,
+
+ 4, // $38 '8'
+ $e0,$a0,$40,$a0,$e0,$00,
+
+ 4, // $39 '9'
+ $e0,$a0,$e0,$20,$c0,$00,
+
+ 4, // $3a ':'
+ $00,$40,$00,$40,$00,$00,
+
+ 4, // $3b ';'
+ $00,$40,$00,$40,$40,$80,
+
+ 4, // $3c '<'
+ $20,$40,$80,$40,$20,$00,
+
+ 4, // $3d '='
+ $00,$e0,$00,$e0,$00,$00,
+
+ 4, // $3e '>'
+ $80,$40,$20,$40,$80,$00,
+
+ 4, // $3f '?'
+ $c0,$20,$40,$00,$40,$00,
+
+ 4, // $40 '@'
+ $40,$a0,$e0,$e0,$80,$60,
+
+ 4, // $41 'A'
+ $40,$a0,$e0,$a0,$a0,$00,
+
+ 4, // $42 'B'
+ $c0,$a0,$c0,$a0,$c0,$00,
+
+ 4, // $43 'C'
+ $60,$80,$80,$80,$60,$00,
+
+ 4, // $44 'D'
+ $c0,$a0,$a0,$a0,$c0,$00,
+
+ 4, // $45 'E'
+ $e0,$80,$c0,$80,$e0,$00,
+
+ 4, // $46 'F'
+ $e0,$80,$c0,$80,$80,$00,
+
+ 4, // $47 'G'
+ $60,$80,$a0,$a0,$40,$00,
+
+ 4, // $48 'H'
+ $a0,$a0,$e0,$a0,$a0,$00,
+
+ 4, // $49 'I'
+ $e0,$40,$40,$40,$e0,$00,
+
+ 4, // $4a 'J'
+ $20,$20,$20,$20,$a0,$40,
+
+ 4, // $4b 'K'
+ $a0,$a0,$c0,$c0,$a0,$00,
+
+ 4, // $4c 'L'
+ $80,$80,$80,$80,$e0,$00,
+
+ 4, // $4d 'M'
+ $a0,$e0,$a0,$a0,$a0,$00,
+
+ 4, // $4e 'N'
+ $90,$d0,$b0,$90,$90,$00,
+
+ 4, // $4f 'O'
+ $40,$a0,$a0,$a0,$40,$00,
+
+ 4, // $50 'P'
+ $c0,$a0,$a0,$c0,$80,$00,
+
+ 4, // $51 'Q'
+ $40,$a0,$a0,$a0,$60,$00,
+
+ 4, // $52 'R'
+ $c0,$a0,$a0,$c0,$a0,$00,
+
+ 4, // $53 'S'
+ $60,$80,$40,$20,$c0,$00,
+
+ 4, // $54 'T'
+ $e0,$40,$40,$40,$40,$00,
+
+ 4, // $55 'U'
+ $a0,$a0,$a0,$a0,$e0,$00,
+
+ 4, // $56 'V'
+ $a0,$a0,$a0,$a0,$40,$00,
+
+ 4, // $57 'W'
+ $a0,$a0,$a0,$e0,$a0,$00,
+
+ 4, // $58 'X'
+ $a0,$a0,$40,$a0,$a0,$00,
+
+ 4, // $59 'Y'
+ $a0,$a0,$40,$40,$40,$00,
+
+ 4, // $5a 'Z'
+ $e0,$20,$40,$80,$e0,$00,
+
+ 4, // $5b '['
+ $c0,$80,$80,$80,$c0,$00,
+
+ 4, // $5c '\'
+ $80,$40,$40,$20,$20,$10,
+
+ 4, // $5d ']'
+ $c0,$40,$40,$40,$c0,$00,
+
+ 4, // $5e '^'
+ $40,$a0,$00,$00,$00,$00,
+
+ 4, // $5f '_'
+ $00,$00,$00,$00,$00,$f0,
+
+ 4, // $60 '`'
+ $40,$20,$00,$00,$00,$00,
+
+ 4, // $61 'a'
+ $00,$60,$a0,$a0,$70,$00,
+
+ 4, // $62 'b'
+ $80,$80,$c0,$a0,$c0,$00,
+
+ 4, // $63 'c'
+ $00,$60,$80,$80,$60,$00,
+
+ 4, // $64 'd'
+ $20,$20,$60,$a0,$60,$00,
+
+ 4, // $65 'e'
+ $00,$40,$e0,$80,$60,$00,
+
+ 4, // $66 'f'
+ $20,$40,$e0,$40,$40,$00,
+
+ 4, // $67 'g'
+ $00,$60,$a0,$60,$20,$c0,
+
+ 4, // $68 'h'
+ $80,$80,$c0,$a0,$a0,$00,
+
+ 4, // $69 'i'
+ $40,$00,$c0,$40,$e0,$00,
+
+ 4, // $6a 'j'
+ $40,$00,$c0,$40,$40,$80,
+
+ 4, // $6b 'k'
+ $80,$80,$a0,$c0,$a0,$00,
+
+ 4, // $6c 'l'
+ $c0,$40,$40,$40,$e0,$00,
+
+ 4, // $6d 'm'
+ $00,$a0,$f0,$f0,$90,$00,
+
+ 4, // $6e 'n'
+ $00,$c0,$a0,$a0,$a0,$00,
+
+ 4, // $6f 'o'
+ $00,$40,$a0,$a0,$40,$00,
+
+ 4, // $70 'p'
+ $00,$c0,$a0,$c0,$80,$80,
+
+ 4, // $71 'q'
+ $00,$60,$a0,$60,$20,$20,
+
+ 4, // $72 'r'
+ $00,$a0,$50,$40,$40,$00,
+
+ 4, // $73 's'
+ $00,$60,$c0,$20,$c0,$00,
+
+ 4, // $74 't'
+ $40,$40,$e0,$40,$60,$00,
+
+ 4, // $75 'u'
+ $00,$a0,$a0,$a0,$60,$00,
+
+ 4, // $76 'v'
+ $00,$a0,$a0,$a0,$40,$00,
+
+ 4, // $77 'w'
+ $00,$a0,$a0,$e0,$a0,$00,
+
+ 4, // $78 'x'
+ $00,$a0,$40,$a0,$a0,$00,
+
+ 4, // $79 'y'
+ $00,$a0,$a0,$60,$20,$c0,
+
+ 4, // $7a 'z'
+ $00,$e0,$40,$80,$e0,$00,
+
+ 4, // $7b '{'
+ $30,$20,$c0,$20,$30,$00,
+
+ 4, // $7c '|'
+ $40,$40,$00,$40,$40,$40,
+
+ 4, // $7d '}'
+ $c0,$40,$30,$40,$c0,$00,
+
+ 4, // $7e '~'
+ $50,$a0,$00,$00,$00,$00,
+
+ 4, // $7f ''
+ $00,$60,$90,$f0,$00,$00,
+ 0 );
+
+ gse4x8 : array[0..1060 ] of int8u = (
+ 8, 0, 32, 128-32,
+
+ $00,$00,$09,$00,$12,$00,$1b,$00,$24,$00,$2d,$00,$36,$00,$3f,$00,$48,$00,
+ $51,$00,$5a,$00,$63,$00,$6c,$00,$75,$00,$7e,$00,$87,$00,$90,$00,$99,$00,
+ $a2,$00,$ab,$00,$b4,$00,$bd,$00,$c6,$00,$cf,$00,$d8,$00,$e1,$00,$ea,$00,
+ $f3,$00,$fc,$00,$05,$01,$0e,$01,$17,$01,$20,$01,$29,$01,$32,$01,$3b,$01,
+ $44,$01,$4d,$01,$56,$01,$5f,$01,$68,$01,$71,$01,$7a,$01,$83,$01,$8c,$01,
+ $95,$01,$9e,$01,$a7,$01,$b0,$01,$b9,$01,$c2,$01,$cb,$01,$d4,$01,$dd,$01,
+ $e6,$01,$ef,$01,$f8,$01,$01,$02,$0a,$02,$13,$02,$1c,$02,$25,$02,$2e,$02,
+ $37,$02,$40,$02,$49,$02,$52,$02,$5b,$02,$64,$02,$6d,$02,$76,$02,$7f,$02,
+ $88,$02,$91,$02,$9a,$02,$a3,$02,$ac,$02,$b5,$02,$be,$02,$c7,$02,$d0,$02,
+ $d9,$02,$e2,$02,$eb,$02,$f4,$02,$fd,$02,$06,$03,$0f,$03,$18,$03,$21,$03,
+ $2a,$03,$33,$03,$3c,$03,$45,$03,$4e,$03,$57,$03,
+
+ 4, // $20 ' '
+ $00,$00,$00,$00,$00,$00,$00,$00,
+
+ 4, // $21 '!'
+ $00,$40,$40,$40,$40,$00,$40,$00,
+
+ 4, // $22 '"'
+ $00,$a0,$a0,$00,$00,$00,$00,$00,
+
+ 4, // $23 '#'
+ $60,$60,$f0,$60,$60,$f0,$60,$60,
+
+ 4, // $24 '$'
+ $40,$60,$c0,$c0,$60,$60,$c0,$40,
+
+ 4, // $25 '%'
+ $00,$a0,$20,$40,$40,$80,$a0,$00,
+
+ 4, // $26 '&'
+ $00,$40,$a0,$a0,$40,$b0,$a0,$70,
+
+ 4, // $27 '''
+ $00,$40,$40,$00,$00,$00,$00,$00,
+
+ 4, // $28 '('
+ $20,$40,$80,$80,$80,$80,$40,$20,
+
+ 4, // $29 ')'
+ $80,$40,$20,$20,$20,$20,$40,$80,
+
+ 4, // $2a '*'
+ $00,$a0,$40,$e0,$40,$a0,$00,$00,
+
+ 4, // $2b '+'
+ $00,$40,$40,$e0,$40,$40,$00,$00,
+
+ 4, // $2c ','
+ $00,$00,$00,$00,$00,$40,$40,$80,
+
+ 4, // $2d '-'
+ $00,$00,$00,$e0,$00,$00,$00,$00,
+
+ 4, // $2e '.'
+ $00,$00,$00,$00,$00,$00,$40,$00,
+
+ 4, // $2f '/'
+ $10,$10,$20,$20,$40,$40,$80,$80,
+
+ 4, // $30 '0'
+ $00,$e0,$a0,$a0,$a0,$a0,$e0,$00,
+
+ 4, // $31 '1'
+ $00,$40,$c0,$40,$40,$40,$e0,$00,
+
+ 4, // $32 '2'
+ $00,$e0,$a0,$20,$40,$80,$e0,$00,
+
+ 4, // $33 '3'
+ $00,$e0,$20,$40,$20,$20,$e0,$00,
+
+ 4, // $34 '4'
+ $00,$60,$a0,$a0,$f0,$20,$20,$00,
+
+ 4, // $35 '5'
+ $00,$e0,$80,$c0,$20,$20,$c0,$00,
+
+ 4, // $36 '6'
+ $00,$40,$80,$e0,$a0,$a0,$e0,$00,
+
+ 4, // $37 '7'
+ $00,$e0,$a0,$20,$40,$40,$40,$00,
+
+ 4, // $38 '8'
+ $00,$e0,$a0,$40,$a0,$a0,$e0,$00,
+
+ 4, // $39 '9'
+ $00,$e0,$a0,$e0,$20,$20,$40,$00,
+
+ 4, // $3a ':'
+ $00,$00,$40,$00,$00,$40,$00,$00,
+
+ 4, // $3b ';'
+ $00,$00,$40,$00,$00,$40,$40,$80,
+
+ 4, // $3c '<'
+ $00,$20,$40,$80,$40,$20,$00,$00,
+
+ 4, // $3d '='
+ $00,$00,$e0,$00,$e0,$00,$00,$00,
+
+ 4, // $3e '>'
+ $00,$80,$40,$20,$40,$80,$00,$00,
+
+ 4, // $3f '?'
+ $00,$40,$a0,$20,$40,$00,$40,$00,
+
+ 4, // $40 '@'
+ $00,$40,$a0,$e0,$e0,$80,$60,$00,
+
+ 4, // $41 'A'
+ $00,$40,$a0,$a0,$e0,$a0,$a0,$00,
+
+ 4, // $42 'B'
+ $00,$c0,$a0,$c0,$a0,$a0,$c0,$00,
+
+ 4, // $43 'C'
+ $00,$40,$a0,$80,$80,$a0,$40,$00,
+
+ 4, // $44 'D'
+ $00,$c0,$a0,$a0,$a0,$a0,$c0,$00,
+
+ 4, // $45 'E'
+ $00,$e0,$80,$c0,$80,$80,$e0,$00,
+
+ 4, // $46 'F'
+ $00,$e0,$80,$c0,$80,$80,$80,$00,
+
+ 4, // $47 'G'
+ $00,$60,$80,$a0,$a0,$a0,$40,$00,
+
+ 4, // $48 'H'
+ $00,$a0,$a0,$e0,$a0,$a0,$a0,$00,
+
+ 4, // $49 'I'
+ $00,$e0,$40,$40,$40,$40,$e0,$00,
+
+ 4, // $4a 'J'
+ $00,$20,$20,$20,$20,$a0,$40,$00,
+
+ 4, // $4b 'K'
+ $00,$a0,$a0,$c0,$c0,$a0,$a0,$00,
+
+ 4, // $4c 'L'
+ $00,$80,$80,$80,$80,$80,$e0,$00,
+
+ 4, // $4d 'M'
+ $00,$a0,$e0,$a0,$a0,$a0,$a0,$00,
+
+ 4, // $4e 'N'
+ $00,$90,$90,$d0,$b0,$90,$90,$00,
+
+ 4, // $4f 'O'
+ $00,$40,$a0,$a0,$a0,$a0,$40,$00,
+
+ 4, // $50 'P'
+ $00,$c0,$a0,$a0,$c0,$80,$80,$00,
+
+ 4, // $51 'Q'
+ $00,$40,$a0,$a0,$a0,$a0,$60,$00,
+
+ 4, // $52 'R'
+ $00,$c0,$a0,$a0,$c0,$c0,$a0,$00,
+
+ 4, // $53 'S'
+ $00,$60,$80,$40,$20,$20,$c0,$00,
+
+ 4, // $54 'T'
+ $00,$e0,$40,$40,$40,$40,$40,$00,
+
+ 4, // $55 'U'
+ $00,$a0,$a0,$a0,$a0,$a0,$40,$00,
+
+ 4, // $56 'V'
+ $00,$a0,$a0,$a0,$a0,$40,$40,$00,
+
+ 4, // $57 'W'
+ $00,$a0,$a0,$a0,$a0,$e0,$a0,$00,
+
+ 4, // $58 'X'
+ $00,$a0,$a0,$40,$a0,$a0,$a0,$00,
+
+ 4, // $59 'Y'
+ $00,$a0,$a0,$40,$40,$40,$40,$00,
+
+ 4, // $5a 'Z'
+ $00,$e0,$20,$40,$40,$80,$e0,$00,
+
+ 4, // $5b '['
+ $c0,$80,$80,$80,$80,$80,$80,$c0,
+
+ 4, // $5c '\'
+ $80,$80,$40,$40,$20,$20,$10,$10,
+
+ 4, // $5d ']'
+ $c0,$40,$40,$40,$40,$40,$40,$c0,
+
+ 4, // $5e '^'
+ $00,$40,$a0,$00,$00,$00,$00,$00,
+
+ 4, // $5f '_'
+ $00,$00,$00,$00,$00,$00,$00,$f0,
+
+ 4, // $60 '`'
+ $00,$40,$20,$00,$00,$00,$00,$00,
+
+ 4, // $61 'a'
+ $00,$00,$60,$a0,$a0,$a0,$70,$00,
+
+ 4, // $62 'b'
+ $00,$80,$80,$c0,$a0,$a0,$c0,$00,
+
+ 4, // $63 'c'
+ $00,$00,$40,$a0,$80,$a0,$40,$00,
+
+ 4, // $64 'd'
+ $00,$20,$20,$60,$a0,$a0,$60,$00,
+
+ 4, // $65 'e'
+ $00,$00,$40,$a0,$e0,$80,$60,$00,
+
+ 4, // $66 'f'
+ $00,$20,$40,$40,$e0,$40,$40,$00,
+
+ 4, // $67 'g'
+ $00,$00,$60,$a0,$a0,$60,$20,$c0,
+
+ 4, // $68 'h'
+ $00,$80,$80,$c0,$a0,$a0,$a0,$00,
+
+ 4, // $69 'i'
+ $00,$40,$00,$c0,$40,$40,$e0,$00,
+
+ 4, // $6a 'j'
+ $00,$40,$00,$c0,$40,$40,$40,$80,
+
+ 4, // $6b 'k'
+ $00,$80,$80,$a0,$c0,$c0,$a0,$00,
+
+ 4, // $6c 'l'
+ $00,$c0,$40,$40,$40,$40,$e0,$00,
+
+ 4, // $6d 'm'
+ $00,$00,$a0,$f0,$f0,$f0,$90,$00,
+
+ 4, // $6e 'n'
+ $00,$00,$c0,$a0,$a0,$a0,$a0,$00,
+
+ 4, // $6f 'o'
+ $00,$00,$40,$a0,$a0,$a0,$40,$00,
+
+ 4, // $70 'p'
+ $00,$00,$c0,$a0,$a0,$c0,$80,$80,
+
+ 4, // $71 'q'
+ $00,$00,$60,$a0,$a0,$60,$20,$20,
+
+ 4, // $72 'r'
+ $00,$00,$a0,$50,$40,$40,$40,$00,
+
+ 4, // $73 's'
+ $00,$00,$60,$80,$40,$20,$c0,$00,
+
+ 4, // $74 't'
+ $00,$40,$40,$e0,$40,$40,$20,$00,
+
+ 4, // $75 'u'
+ $00,$00,$a0,$a0,$a0,$a0,$60,$00,
+
+ 4, // $76 'v'
+ $00,$00,$a0,$a0,$a0,$40,$40,$00,
+
+ 4, // $77 'w'
+ $00,$00,$a0,$a0,$a0,$e0,$a0,$00,
+
+ 4, // $78 'x'
+ $00,$00,$a0,$a0,$40,$a0,$a0,$00,
+
+ 4, // $79 'y'
+ $00,$00,$a0,$a0,$a0,$60,$20,$c0,
+
+ 4, // $7a 'z'
+ $00,$00,$e0,$20,$40,$80,$e0,$00,
+
+ 4, // $7b '{'
+ $10,$20,$20,$c0,$20,$20,$10,$00,
+
+ 4, // $7c '|'
+ $00,$40,$40,$40,$00,$40,$40,$40,
+
+ 4, // $7d '}'
+ $80,$40,$40,$30,$40,$40,$80,$00,
+
+ 4, // $7e '~'
+ $00,$50,$a0,$00,$00,$00,$00,$00,
+
+ 4, // $7f ''
+ $00,$00,$00,$60,$90,$f0,$00,$00,
+ 0 );
+
+ gse5x7 : array[0..964 ] of int8u = (
+ 7, 0, 32, 128-32,
+
+ $00,$00,$08,$00,$10,$00,$18,$00,$20,$00,$28,$00,$30,$00,$38,$00,$40,$00,
+ $48,$00,$50,$00,$58,$00,$60,$00,$68,$00,$70,$00,$78,$00,$80,$00,$88,$00,
+ $90,$00,$98,$00,$a0,$00,$a8,$00,$b0,$00,$b8,$00,$c0,$00,$c8,$00,$d0,$00,
+ $d8,$00,$e0,$00,$e8,$00,$f0,$00,$f8,$00,$00,$01,$08,$01,$10,$01,$18,$01,
+ $20,$01,$28,$01,$30,$01,$38,$01,$40,$01,$48,$01,$50,$01,$58,$01,$60,$01,
+ $68,$01,$70,$01,$78,$01,$80,$01,$88,$01,$90,$01,$98,$01,$a0,$01,$a8,$01,
+ $b0,$01,$b8,$01,$c0,$01,$c8,$01,$d0,$01,$d8,$01,$e0,$01,$e8,$01,$f0,$01,
+ $f8,$01,$00,$02,$08,$02,$10,$02,$18,$02,$20,$02,$28,$02,$30,$02,$38,$02,
+ $40,$02,$48,$02,$50,$02,$58,$02,$60,$02,$68,$02,$70,$02,$78,$02,$80,$02,
+ $88,$02,$90,$02,$98,$02,$a0,$02,$a8,$02,$b0,$02,$b8,$02,$c0,$02,$c8,$02,
+ $d0,$02,$d8,$02,$e0,$02,$e8,$02,$f0,$02,$f8,$02,
+
+ 5, // $20 ' '
+ $00,$00,$00,$00,$00,$00,$00,
+
+ 5, // $21 '!'
+ $00,$20,$20,$20,$00,$20,$00,
+
+ 5, // $22 '"'
+ $00,$50,$50,$00,$00,$00,$00,
+
+ 5, // $23 '#'
+ $00,$50,$f8,$50,$f8,$50,$00,
+
+ 5, // $24 '$'
+ $20,$78,$a0,$70,$28,$f0,$20,
+
+ 5, // $25 '%'
+ $00,$88,$10,$20,$40,$88,$00,
+
+ 5, // $26 '&'
+ $00,$40,$a0,$68,$90,$68,$00,
+
+ 5, // $27 '''
+ $00,$20,$20,$00,$00,$00,$00,
+
+ 5, // $28 '('
+ $10,$20,$40,$40,$40,$20,$10,
+
+ 5, // $29 ')'
+ $80,$40,$20,$20,$20,$40,$80,
+
+ 5, // $2a '*'
+ $00,$20,$a8,$70,$a8,$20,$00,
+
+ 5, // $2b '+'
+ $00,$20,$20,$f8,$20,$20,$00,
+
+ 5, // $2c ','
+ $00,$00,$00,$00,$20,$20,$40,
+
+ 5, // $2d '-'
+ $00,$00,$00,$f0,$00,$00,$00,
+
+ 5, // $2e '.'
+ $00,$00,$00,$00,$00,$40,$00,
+
+ 5, // $2f '/'
+ $00,$08,$10,$20,$40,$80,$00,
+
+ 5, // $30 '0'
+ $00,$60,$90,$90,$90,$60,$00,
+
+ 5, // $31 '1'
+ $00,$20,$60,$20,$20,$70,$00,
+
+ 5, // $32 '2'
+ $00,$60,$90,$20,$40,$f0,$00,
+
+ 5, // $33 '3'
+ $00,$f0,$20,$60,$10,$e0,$00,
+
+ 5, // $34 '4'
+ $00,$30,$50,$90,$f0,$10,$00,
+
+ 5, // $35 '5'
+ $00,$f0,$80,$e0,$10,$e0,$00,
+
+ 5, // $36 '6'
+ $00,$60,$80,$e0,$90,$60,$00,
+
+ 5, // $37 '7'
+ $00,$f0,$90,$20,$40,$40,$00,
+
+ 5, // $38 '8'
+ $00,$60,$90,$60,$90,$60,$00,
+
+ 5, // $39 '9'
+ $00,$60,$90,$70,$10,$60,$00,
+
+ 5, // $3a ':'
+ $00,$00,$20,$00,$20,$00,$00,
+
+ 5, // $3b ';'
+ $00,$00,$20,$00,$20,$20,$40,
+
+ 5, // $3c '<'
+ $00,$10,$20,$40,$20,$10,$00,
+
+ 5, // $3d '='
+ $00,$00,$f0,$00,$f0,$00,$00,
+
+ 5, // $3e '>'
+ $00,$80,$40,$20,$40,$80,$00,
+
+ 5, // $3f '?'
+ $00,$60,$90,$20,$00,$20,$00,
+
+ 5, // $40 '@'
+ $00,$60,$90,$b0,$80,$70,$00,
+
+ 5, // $41 'A'
+ $00,$60,$90,$f0,$90,$90,$00,
+
+ 5, // $42 'B'
+ $00,$e0,$90,$e0,$90,$e0,$00,
+
+ 5, // $43 'C'
+ $00,$60,$90,$80,$90,$60,$00,
+
+ 5, // $44 'D'
+ $00,$e0,$90,$90,$90,$e0,$00,
+
+ 5, // $45 'E'
+ $00,$f0,$80,$e0,$80,$f0,$00,
+
+ 5, // $46 'F'
+ $00,$f0,$80,$e0,$80,$80,$00,
+
+ 5, // $47 'G'
+ $00,$70,$80,$b0,$90,$60,$00,
+
+ 5, // $48 'H'
+ $00,$90,$90,$f0,$90,$90,$00,
+
+ 5, // $49 'I'
+ $00,$70,$20,$20,$20,$70,$00,
+
+ 5, // $4a 'J'
+ $00,$70,$20,$20,$a0,$40,$00,
+
+ 5, // $4b 'K'
+ $00,$90,$a0,$c0,$a0,$90,$00,
+
+ 5, // $4c 'L'
+ $00,$80,$80,$80,$80,$f0,$00,
+
+ 5, // $4d 'M'
+ $00,$90,$f0,$90,$90,$90,$00,
+
+ 5, // $4e 'N'
+ $00,$90,$d0,$b0,$90,$90,$00,
+
+ 5, // $4f 'O'
+ $00,$60,$90,$90,$90,$60,$00,
+
+ 5, // $50 'P'
+ $00,$e0,$90,$e0,$80,$80,$00,
+
+ 5, // $51 'Q'
+ $00,$60,$90,$90,$a0,$50,$00,
+
+ 5, // $52 'R'
+ $00,$e0,$90,$e0,$a0,$90,$00,
+
+ 5, // $53 'S'
+ $00,$70,$80,$60,$10,$e0,$00,
+
+ 5, // $54 'T'
+ $00,$70,$20,$20,$20,$20,$00,
+
+ 5, // $55 'U'
+ $00,$90,$90,$90,$90,$60,$00,
+
+ 5, // $56 'V'
+ $00,$50,$50,$50,$20,$20,$00,
+
+ 5, // $57 'W'
+ $00,$90,$90,$90,$f0,$90,$00,
+
+ 5, // $58 'X'
+ $00,$90,$90,$60,$90,$90,$00,
+
+ 5, // $59 'Y'
+ $00,$50,$50,$20,$20,$20,$00,
+
+ 5, // $5a 'Z'
+ $00,$f0,$10,$20,$40,$f0,$00,
+
+ 5, // $5b '['
+ $70,$40,$40,$40,$40,$40,$70,
+
+ 5, // $5c '\'
+ $00,$80,$40,$20,$10,$08,$00,
+
+ 5, // $5d ']'
+ $e0,$20,$20,$20,$20,$20,$e0,
+
+ 5, // $5e '^'
+ $00,$20,$50,$00,$00,$00,$00,
+
+ 5, // $5f '_'
+ $00,$00,$00,$00,$00,$f8,$00,
+
+ 5, // $60 '`'
+ $00,$40,$20,$00,$00,$00,$00,
+
+ 5, // $61 'a'
+ $00,$00,$60,$a0,$a0,$50,$00,
+
+ 5, // $62 'b'
+ $00,$80,$80,$e0,$90,$e0,$00,
+
+ 5, // $63 'c'
+ $00,$00,$70,$80,$80,$70,$00,
+
+ 5, // $64 'd'
+ $00,$10,$10,$70,$90,$70,$00,
+
+ 5, // $65 'e'
+ $00,$00,$60,$f0,$80,$70,$00,
+
+ 5, // $66 'f'
+ $00,$30,$40,$e0,$40,$40,$00,
+
+ 5, // $67 'g'
+ $00,$00,$70,$90,$70,$10,$60,
+
+ 5, // $68 'h'
+ $00,$80,$80,$e0,$90,$90,$00,
+
+ 5, // $69 'i'
+ $20,$00,$60,$20,$20,$70,$00,
+
+ 5, // $6a 'j'
+ $20,$00,$60,$20,$20,$a0,$40,
+
+ 5, // $6b 'k'
+ $80,$80,$90,$a0,$e0,$90,$00,
+
+ 5, // $6c 'l'
+ $00,$60,$20,$20,$20,$70,$00,
+
+ 5, // $6d 'm'
+ $00,$00,$a0,$f0,$f0,$90,$00,
+
+ 5, // $6e 'n'
+ $00,$00,$a0,$d0,$90,$90,$00,
+
+ 5, // $6f 'o'
+ $00,$00,$60,$90,$90,$60,$00,
+
+ 5, // $70 'p'
+ $00,$00,$e0,$90,$e0,$80,$80,
+
+ 5, // $71 'q'
+ $00,$00,$70,$90,$70,$10,$10,
+
+ 5, // $72 'r'
+ $00,$00,$e0,$90,$80,$80,$00,
+
+ 5, // $73 's'
+ $00,$00,$70,$e0,$10,$e0,$00,
+
+ 5, // $74 't'
+ $40,$40,$e0,$40,$40,$70,$00,
+
+ 5, // $75 'u'
+ $00,$00,$90,$90,$90,$70,$00,
+
+ 5, // $76 'v'
+ $00,$00,$50,$50,$50,$20,$00,
+
+ 5, // $77 'w'
+ $00,$00,$90,$90,$f0,$90,$00,
+
+ 5, // $78 'x'
+ $00,$00,$90,$60,$60,$90,$00,
+
+ 5, // $79 'y'
+ $00,$00,$90,$90,$70,$10,$60,
+
+ 5, // $7a 'z'
+ $00,$00,$f0,$20,$40,$f0,$00,
+
+ 5, // $7b '{'
+ $10,$20,$20,$c0,$20,$20,$10,
+
+ 5, // $7c '|'
+ $20,$20,$20,$00,$20,$20,$20,
+
+ 5, // $7d '}'
+ $40,$20,$20,$18,$20,$20,$40,
+
+ 5, // $7e '~'
+ $00,$40,$a8,$10,$00,$00,$00,
+
+ 5, // $7f ''
+ $00,$00,$20,$50,$88,$f8,$00,
+ 0 );
+
+ gse5x9 : array[0..1156 ] of int8u = (
+ 9, 0, 32, 128-32,
+
+ $00,$00,$0a,$00,$14,$00,$1e,$00,$28,$00,$32,$00,$3c,$00,$46,$00,$50,$00,
+ $5a,$00,$64,$00,$6e,$00,$78,$00,$82,$00,$8c,$00,$96,$00,$a0,$00,$aa,$00,
+ $b4,$00,$be,$00,$c8,$00,$d2,$00,$dc,$00,$e6,$00,$f0,$00,$fa,$00,$04,$01,
+ $0e,$01,$18,$01,$22,$01,$2c,$01,$36,$01,$40,$01,$4a,$01,$54,$01,$5e,$01,
+ $68,$01,$72,$01,$7c,$01,$86,$01,$90,$01,$9a,$01,$a4,$01,$ae,$01,$b8,$01,
+ $c2,$01,$cc,$01,$d6,$01,$e0,$01,$ea,$01,$f4,$01,$fe,$01,$08,$02,$12,$02,
+ $1c,$02,$26,$02,$30,$02,$3a,$02,$44,$02,$4e,$02,$58,$02,$62,$02,$6c,$02,
+ $76,$02,$80,$02,$8a,$02,$94,$02,$9e,$02,$a8,$02,$b2,$02,$bc,$02,$c6,$02,
+ $d0,$02,$da,$02,$e4,$02,$ee,$02,$f8,$02,$02,$03,$0c,$03,$16,$03,$20,$03,
+ $2a,$03,$34,$03,$3e,$03,$48,$03,$52,$03,$5c,$03,$66,$03,$70,$03,$7a,$03,
+ $84,$03,$8e,$03,$98,$03,$a2,$03,$ac,$03,$b6,$03,
+
+ 5, // $20 ' '
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 5, // $21 '!'
+ $00,$20,$20,$20,$20,$20,$00,$20,$00,
+
+ 5, // $22 '"'
+ $00,$50,$50,$00,$00,$00,$00,$00,$00,
+
+ 5, // $23 '#'
+ $00,$50,$50,$f8,$50,$f8,$50,$50,$00,
+
+ 5, // $24 '$'
+ $00,$20,$78,$a0,$70,$28,$f0,$20,$00,
+
+ 5, // $25 '%'
+ $00,$c8,$c8,$10,$20,$40,$98,$98,$00,
+
+ 5, // $26 '&'
+ $00,$40,$a0,$a0,$40,$a8,$90,$68,$00,
+
+ 5, // $27 '''
+ $00,$20,$20,$00,$00,$00,$00,$00,$00,
+
+ 5, // $28 '('
+ $10,$20,$40,$40,$40,$40,$40,$20,$10,
+
+ 5, // $29 ')'
+ $80,$40,$20,$20,$20,$20,$20,$40,$80,
+
+ 5, // $2a '*'
+ $00,$00,$20,$a8,$70,$a8,$20,$00,$00,
+
+ 5, // $2b '+'
+ $00,$00,$20,$20,$f8,$20,$20,$00,$00,
+
+ 5, // $2c ','
+ $00,$00,$00,$00,$00,$00,$20,$20,$40,
+
+ 5, // $2d '-'
+ $00,$00,$00,$00,$f0,$00,$00,$00,$00,
+
+ 5, // $2e '.'
+ $00,$00,$00,$00,$00,$00,$00,$40,$00,
+
+ 5, // $2f '/'
+ $00,$10,$10,$20,$20,$40,$40,$80,$80,
+
+ 5, // $30 '0'
+ $00,$60,$90,$b0,$d0,$90,$90,$60,$00,
+
+ 5, // $31 '1'
+ $00,$20,$60,$20,$20,$20,$20,$70,$00,
+
+ 5, // $32 '2'
+ $00,$60,$90,$10,$20,$40,$80,$f0,$00,
+
+ 5, // $33 '3'
+ $00,$f0,$10,$20,$60,$10,$90,$60,$00,
+
+ 5, // $34 '4'
+ $00,$30,$50,$90,$90,$f8,$10,$10,$00,
+
+ 5, // $35 '5'
+ $00,$f0,$80,$e0,$10,$10,$10,$e0,$00,
+
+ 5, // $36 '6'
+ $00,$60,$80,$e0,$90,$90,$90,$60,$00,
+
+ 5, // $37 '7'
+ $00,$f0,$90,$10,$20,$40,$40,$40,$00,
+
+ 5, // $38 '8'
+ $00,$60,$90,$90,$60,$90,$90,$60,$00,
+
+ 5, // $39 '9'
+ $00,$60,$90,$90,$70,$10,$90,$60,$00,
+
+ 5, // $3a ':'
+ $00,$00,$00,$20,$00,$00,$20,$00,$00,
+
+ 5, // $3b ';'
+ $00,$00,$00,$20,$00,$00,$20,$20,$40,
+
+ 5, // $3c '<'
+ $00,$10,$20,$40,$80,$40,$20,$10,$00,
+
+ 5, // $3d '='
+ $00,$00,$00,$f0,$00,$f0,$00,$00,$00,
+
+ 5, // $3e '>'
+ $00,$80,$40,$20,$10,$20,$40,$80,$00,
+
+ 5, // $3f '?'
+ $00,$60,$90,$10,$20,$20,$00,$20,$00,
+
+ 5, // $40 '@'
+ $00,$60,$90,$b0,$b0,$b0,$80,$70,$00,
+
+ 5, // $41 'A'
+ $00,$60,$90,$90,$f0,$90,$90,$90,$00,
+
+ 5, // $42 'B'
+ $00,$e0,$90,$90,$e0,$90,$90,$e0,$00,
+
+ 5, // $43 'C'
+ $00,$60,$90,$80,$80,$80,$90,$60,$00,
+
+ 5, // $44 'D'
+ $00,$e0,$90,$90,$90,$90,$90,$e0,$00,
+
+ 5, // $45 'E'
+ $00,$f0,$80,$80,$e0,$80,$80,$f0,$00,
+
+ 5, // $46 'F'
+ $00,$f0,$80,$80,$e0,$80,$80,$80,$00,
+
+ 5, // $47 'G'
+ $00,$60,$90,$80,$b0,$90,$90,$60,$00,
+
+ 5, // $48 'H'
+ $00,$90,$90,$90,$f0,$90,$90,$90,$00,
+
+ 5, // $49 'I'
+ $00,$70,$20,$20,$20,$20,$20,$70,$00,
+
+ 5, // $4a 'J'
+ $00,$70,$20,$20,$20,$20,$a0,$40,$00,
+
+ 5, // $4b 'K'
+ $00,$90,$90,$a0,$c0,$a0,$90,$90,$00,
+
+ 5, // $4c 'L'
+ $00,$80,$80,$80,$80,$80,$80,$f0,$00,
+
+ 5, // $4d 'M'
+ $00,$90,$f0,$90,$90,$90,$90,$90,$00,
+
+ 5, // $4e 'N'
+ $00,$90,$90,$d0,$b0,$90,$90,$90,$00,
+
+ 5, // $4f 'O'
+ $00,$60,$90,$90,$90,$90,$90,$60,$00,
+
+ 5, // $50 'P'
+ $00,$e0,$90,$90,$e0,$80,$80,$80,$00,
+
+ 5, // $51 'Q'
+ $00,$60,$90,$90,$90,$90,$a0,$50,$00,
+
+ 5, // $52 'R'
+ $00,$e0,$90,$90,$e0,$a0,$90,$90,$00,
+
+ 5, // $53 'S'
+ $00,$60,$90,$80,$60,$10,$90,$60,$00,
+
+ 5, // $54 'T'
+ $00,$70,$20,$20,$20,$20,$20,$20,$00,
+
+ 5, // $55 'U'
+ $00,$90,$90,$90,$90,$90,$90,$60,$00,
+
+ 5, // $56 'V'
+ $00,$50,$50,$50,$50,$50,$20,$20,$00,
+
+ 5, // $57 'W'
+ $00,$90,$90,$90,$90,$90,$f0,$90,$00,
+
+ 5, // $58 'X'
+ $00,$90,$90,$60,$60,$90,$90,$90,$00,
+
+ 5, // $59 'Y'
+ $00,$50,$50,$50,$20,$20,$20,$20,$00,
+
+ 5, // $5a 'Z'
+ $00,$f0,$10,$10,$20,$40,$80,$f0,$00,
+
+ 5, // $5b '['
+ $70,$40,$40,$40,$40,$40,$40,$70,$00,
+
+ 5, // $5c '\'
+ $80,$80,$40,$40,$20,$20,$10,$10,$00,
+
+ 5, // $5d ']'
+ $e0,$20,$20,$20,$20,$20,$20,$e0,$00,
+
+ 5, // $5e '^'
+ $00,$20,$50,$88,$00,$00,$00,$00,$00,
+
+ 5, // $5f '_'
+ $00,$00,$00,$00,$00,$00,$00,$f8,$00,
+
+ 5, // $60 '`'
+ $00,$40,$20,$00,$00,$00,$00,$00,$00,
+
+ 5, // $61 'a'
+ $00,$00,$60,$10,$70,$90,$90,$70,$00,
+
+ 5, // $62 'b'
+ $00,$80,$80,$e0,$90,$90,$90,$e0,$00,
+
+ 5, // $63 'c'
+ $00,$00,$60,$90,$80,$80,$90,$60,$00,
+
+ 5, // $64 'd'
+ $00,$10,$10,$70,$90,$90,$90,$70,$00,
+
+ 5, // $65 'e'
+ $00,$00,$60,$90,$f0,$80,$80,$70,$00,
+
+ 5, // $66 'f'
+ $00,$30,$40,$40,$e0,$40,$40,$40,$00,
+
+ 5, // $67 'g'
+ $00,$00,$70,$90,$90,$70,$10,$90,$60,
+
+ 5, // $68 'h'
+ $00,$80,$80,$e0,$90,$90,$90,$90,$00,
+
+ 5, // $69 'i'
+ $00,$20,$00,$60,$20,$20,$20,$70,$00,
+
+ 5, // $6a 'j'
+ $00,$20,$00,$60,$20,$20,$20,$a0,$40,
+
+ 5, // $6b 'k'
+ $00,$80,$80,$90,$a0,$c0,$a0,$90,$00,
+
+ 5, // $6c 'l'
+ $00,$60,$20,$20,$20,$20,$20,$70,$00,
+
+ 5, // $6d 'm'
+ $00,$00,$a0,$f0,$f0,$f0,$90,$90,$00,
+
+ 5, // $6e 'n'
+ $00,$00,$a0,$d0,$90,$90,$90,$90,$00,
+
+ 5, // $6f 'o'
+ $00,$00,$60,$90,$90,$90,$90,$60,$00,
+
+ 5, // $70 'p'
+ $00,$00,$e0,$90,$90,$90,$e0,$80,$80,
+
+ 5, // $71 'q'
+ $00,$00,$70,$90,$90,$90,$70,$10,$10,
+
+ 5, // $72 'r'
+ $00,$00,$e0,$90,$80,$80,$80,$80,$00,
+
+ 5, // $73 's'
+ $00,$00,$60,$90,$40,$20,$90,$60,$00,
+
+ 5, // $74 't'
+ $00,$40,$40,$e0,$40,$40,$50,$20,$00,
+
+ 5, // $75 'u'
+ $00,$00,$90,$90,$90,$90,$90,$70,$00,
+
+ 5, // $76 'v'
+ $00,$00,$50,$50,$50,$50,$20,$20,$00,
+
+ 5, // $77 'w'
+ $00,$00,$90,$90,$90,$90,$f0,$90,$00,
+
+ 5, // $78 'x'
+ $00,$00,$90,$90,$60,$60,$90,$90,$00,
+
+ 5, // $79 'y'
+ $00,$00,$90,$90,$90,$90,$70,$10,$e0,
+
+ 5, // $7a 'z'
+ $00,$00,$f0,$10,$20,$40,$80,$f0,$00,
+
+ 5, // $7b '{'
+ $10,$20,$20,$20,$c0,$20,$20,$20,$10,
+
+ 5, // $7c '|'
+ $00,$20,$20,$20,$00,$20,$20,$20,$00,
+
+ 5, // $7d '}'
+ $80,$40,$40,$40,$30,$40,$40,$40,$80,
+
+ 5, // $7e '~'
+ $00,$40,$a8,$10,$00,$00,$00,$00,$00,
+
+ 5, // $7f ''
+ $00,$00,$00,$20,$50,$88,$f8,$00,$00,
+ 0 );
+
+ gse6x12 : array[0..1444 ] of int8u = (
+ 12, 0, 32, 128-32,
+
+ $00,$00,$0d,$00,$1a,$00,$27,$00,$34,$00,$41,$00,$4e,$00,$5b,$00,$68,$00,
+ $75,$00,$82,$00,$8f,$00,$9c,$00,$a9,$00,$b6,$00,$c3,$00,$d0,$00,$dd,$00,
+ $ea,$00,$f7,$00,$04,$01,$11,$01,$1e,$01,$2b,$01,$38,$01,$45,$01,$52,$01,
+ $5f,$01,$6c,$01,$79,$01,$86,$01,$93,$01,$a0,$01,$ad,$01,$ba,$01,$c7,$01,
+ $d4,$01,$e1,$01,$ee,$01,$fb,$01,$08,$02,$15,$02,$22,$02,$2f,$02,$3c,$02,
+ $49,$02,$56,$02,$63,$02,$70,$02,$7d,$02,$8a,$02,$97,$02,$a4,$02,$b1,$02,
+ $be,$02,$cb,$02,$d8,$02,$e5,$02,$f2,$02,$ff,$02,$0c,$03,$19,$03,$26,$03,
+ $33,$03,$40,$03,$4d,$03,$5a,$03,$67,$03,$74,$03,$81,$03,$8e,$03,$9b,$03,
+ $a8,$03,$b5,$03,$c2,$03,$cf,$03,$dc,$03,$e9,$03,$f6,$03,$03,$04,$10,$04,
+ $1d,$04,$2a,$04,$37,$04,$44,$04,$51,$04,$5e,$04,$6b,$04,$78,$04,$85,$04,
+ $92,$04,$9f,$04,$ac,$04,$b9,$04,$c6,$04,$d3,$04,
+
+ 6, // $20 ' '
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 6, // $21 '!'
+ $00,$20,$20,$20,$20,$20,$20,$20,$00,$20,$00,$00,
+
+ 6, // $22 '"'
+ $00,$50,$50,$50,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 6, // $23 '#'
+ $00,$50,$50,$f8,$50,$50,$50,$f8,$50,$50,$00,$00,
+
+ 6, // $24 '$'
+ $00,$20,$70,$a8,$a0,$70,$28,$a8,$70,$20,$00,$00,
+
+ 6, // $25 '%'
+ $00,$c8,$d8,$10,$30,$20,$60,$40,$d8,$98,$00,$00,
+
+ 6, // $26 '&'
+ $00,$60,$90,$90,$90,$60,$a8,$90,$90,$68,$00,$00,
+
+ 6, // $27 '''
+ $00,$20,$20,$20,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 6, // $28 '('
+ $00,$10,$20,$40,$40,$40,$40,$40,$20,$10,$00,$00,
+
+ 6, // $29 ')'
+ $00,$40,$20,$10,$10,$10,$10,$10,$20,$40,$00,$00,
+
+ 6, // $2a '*'
+ $00,$00,$00,$50,$20,$f8,$20,$50,$00,$00,$00,$00,
+
+ 6, // $2b '+'
+ $00,$00,$20,$20,$20,$f8,$20,$20,$20,$00,$00,$00,
+
+ 6, // $2c ','
+ $00,$00,$00,$00,$00,$00,$00,$00,$20,$20,$20,$40,
+
+ 6, // $2d '-'
+ $00,$00,$00,$00,$00,$f8,$00,$00,$00,$00,$00,$00,
+
+ 6, // $2e '.'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$20,$00,$00,
+
+ 6, // $2f '/'
+ $08,$08,$10,$10,$20,$20,$40,$40,$80,$80,$00,$00,
+
+ 6, // $30 '0'
+ $00,$70,$88,$88,$98,$a8,$c8,$88,$88,$70,$00,$00,
+
+ 6, // $31 '1'
+ $00,$20,$20,$60,$20,$20,$20,$20,$20,$70,$00,$00,
+
+ 6, // $32 '2'
+ $00,$70,$88,$88,$08,$10,$20,$40,$80,$f8,$00,$00,
+
+ 6, // $33 '3'
+ $00,$f8,$10,$20,$70,$08,$08,$08,$88,$70,$00,$00,
+
+ 6, // $34 '4'
+ $00,$10,$20,$40,$90,$90,$f8,$10,$10,$10,$00,$00,
+
+ 6, // $35 '5'
+ $00,$f8,$80,$80,$f0,$08,$08,$08,$88,$70,$00,$00,
+
+ 6, // $36 '6'
+ $00,$70,$88,$80,$80,$f0,$88,$88,$88,$70,$00,$00,
+
+ 6, // $37 '7'
+ $00,$f8,$88,$08,$08,$10,$20,$20,$20,$20,$00,$00,
+
+ 6, // $38 '8'
+ $00,$70,$88,$88,$88,$70,$88,$88,$88,$70,$00,$00,
+
+ 6, // $39 '9'
+ $00,$70,$88,$88,$88,$78,$08,$08,$88,$70,$00,$00,
+
+ 6, // $3a ':'
+ $00,$00,$00,$00,$20,$00,$00,$00,$20,$00,$00,$00,
+
+ 6, // $3b ';'
+ $00,$00,$00,$00,$20,$00,$00,$00,$20,$20,$20,$40,
+
+ 6, // $3c '<'
+ $00,$08,$10,$20,$40,$80,$40,$20,$10,$08,$00,$00,
+
+ 6, // $3d '='
+ $00,$00,$00,$00,$f8,$00,$f8,$00,$00,$00,$00,$00,
+
+ 6, // $3e '>'
+ $00,$80,$40,$20,$10,$08,$10,$20,$40,$80,$00,$00,
+
+ 6, // $3f '?'
+ $00,$70,$88,$88,$08,$10,$20,$20,$00,$20,$00,$00,
+
+ 6, // $40 '@'
+ $00,$70,$88,$88,$b8,$b8,$b0,$80,$88,$70,$00,$00,
+
+ 6, // $41 'A'
+ $00,$20,$50,$88,$88,$88,$f8,$88,$88,$88,$00,$00,
+
+ 6, // $42 'B'
+ $00,$f0,$88,$88,$88,$f0,$88,$88,$88,$f0,$00,$00,
+
+ 6, // $43 'C'
+ $00,$70,$88,$88,$80,$80,$80,$88,$88,$70,$00,$00,
+
+ 6, // $44 'D'
+ $00,$e0,$90,$88,$88,$88,$88,$88,$90,$e0,$00,$00,
+
+ 6, // $45 'E'
+ $00,$f8,$80,$80,$80,$f0,$80,$80,$80,$f8,$00,$00,
+
+ 6, // $46 'F'
+ $00,$f8,$80,$80,$80,$f0,$80,$80,$80,$80,$00,$00,
+
+ 6, // $47 'G'
+ $00,$70,$88,$80,$80,$b8,$88,$88,$88,$70,$00,$00,
+
+ 6, // $48 'H'
+ $00,$88,$88,$88,$88,$f8,$88,$88,$88,$88,$00,$00,
+
+ 6, // $49 'I'
+ $00,$70,$20,$20,$20,$20,$20,$20,$20,$70,$00,$00,
+
+ 6, // $4a 'J'
+ $00,$38,$10,$10,$10,$10,$10,$10,$90,$60,$00,$00,
+
+ 6, // $4b 'K'
+ $00,$88,$88,$90,$a0,$c0,$a0,$90,$88,$88,$00,$00,
+
+ 6, // $4c 'L'
+ $00,$80,$80,$80,$80,$80,$80,$80,$80,$f8,$00,$00,
+
+ 6, // $4d 'M'
+ $00,$88,$88,$d8,$a8,$88,$88,$88,$88,$88,$00,$00,
+
+ 6, // $4e 'N'
+ $00,$88,$88,$c8,$a8,$98,$88,$88,$88,$88,$00,$00,
+
+ 6, // $4f 'O'
+ $00,$70,$88,$88,$88,$88,$88,$88,$88,$70,$00,$00,
+
+ 6, // $50 'P'
+ $00,$f0,$88,$88,$88,$f0,$80,$80,$80,$80,$00,$00,
+
+ 6, // $51 'Q'
+ $00,$70,$88,$88,$88,$88,$88,$a8,$90,$68,$00,$00,
+
+ 6, // $52 'R'
+ $00,$f0,$88,$88,$88,$88,$f0,$a0,$90,$88,$00,$00,
+
+ 6, // $53 'S'
+ $00,$70,$88,$80,$80,$70,$08,$08,$88,$70,$00,$00,
+
+ 6, // $54 'T'
+ $00,$f8,$20,$20,$20,$20,$20,$20,$20,$20,$00,$00,
+
+ 6, // $55 'U'
+ $00,$88,$88,$88,$88,$88,$88,$88,$88,$70,$00,$00,
+
+ 6, // $56 'V'
+ $00,$88,$88,$88,$88,$88,$50,$50,$20,$20,$00,$00,
+
+ 6, // $57 'W'
+ $00,$88,$88,$88,$88,$88,$a8,$a8,$d8,$88,$00,$00,
+
+ 6, // $58 'X'
+ $00,$88,$88,$88,$50,$20,$50,$88,$88,$88,$00,$00,
+
+ 6, // $59 'Y'
+ $00,$88,$88,$88,$50,$20,$20,$20,$20,$20,$00,$00,
+
+ 6, // $5a 'Z'
+ $00,$f8,$08,$08,$10,$20,$40,$80,$80,$f8,$00,$00,
+
+ 6, // $5b '['
+ $70,$40,$40,$40,$40,$40,$40,$40,$40,$40,$70,$00,
+
+ 6, // $5c '\'
+ $80,$80,$40,$40,$20,$20,$10,$10,$08,$08,$00,$00,
+
+ 6, // $5d ']'
+ $70,$10,$10,$10,$10,$10,$10,$10,$10,$10,$70,$00,
+
+ 6, // $5e '^'
+ $00,$00,$20,$50,$88,$00,$00,$00,$00,$00,$00,$00,
+
+ 6, // $5f '_'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$f8,$00,$00,
+
+ 6, // $60 '`'
+ $00,$40,$20,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 6, // $61 'a'
+ $00,$00,$00,$70,$88,$08,$78,$88,$88,$78,$00,$00,
+
+ 6, // $62 'b'
+ $00,$80,$80,$80,$f0,$88,$88,$88,$88,$f0,$00,$00,
+
+ 6, // $63 'c'
+ $00,$00,$00,$70,$88,$80,$80,$80,$88,$70,$00,$00,
+
+ 6, // $64 'd'
+ $00,$08,$08,$08,$78,$88,$88,$88,$88,$78,$00,$00,
+
+ 6, // $65 'e'
+ $00,$00,$00,$70,$88,$88,$f8,$80,$80,$78,$00,$00,
+
+ 6, // $66 'f'
+ $00,$18,$20,$20,$f8,$20,$20,$20,$20,$20,$00,$00,
+
+ 6, // $67 'g'
+ $00,$00,$00,$78,$88,$88,$88,$88,$78,$08,$08,$f0,
+
+ 6, // $68 'h'
+ $00,$80,$80,$80,$f0,$88,$88,$88,$88,$88,$00,$00,
+
+ 6, // $69 'i'
+ $00,$20,$00,$00,$60,$20,$20,$20,$20,$70,$00,$00,
+
+ 6, // $6a 'j'
+ $00,$10,$00,$00,$30,$10,$10,$10,$10,$10,$90,$60,
+
+ 6, // $6b 'k'
+ $00,$80,$80,$80,$88,$90,$a0,$d0,$88,$88,$00,$00,
+
+ 6, // $6c 'l'
+ $00,$60,$20,$20,$20,$20,$20,$20,$20,$70,$00,$00,
+
+ 6, // $6d 'm'
+ $00,$00,$00,$d0,$a8,$a8,$a8,$a8,$a8,$a8,$00,$00,
+
+ 6, // $6e 'n'
+ $00,$00,$00,$b0,$c8,$88,$88,$88,$88,$88,$00,$00,
+
+ 6, // $6f 'o'
+ $00,$00,$00,$70,$88,$88,$88,$88,$88,$70,$00,$00,
+
+ 6, // $70 'p'
+ $00,$00,$00,$f0,$88,$88,$88,$88,$f0,$80,$80,$80,
+
+ 6, // $71 'q'
+ $00,$00,$00,$78,$88,$88,$88,$88,$78,$08,$08,$08,
+
+ 6, // $72 'r'
+ $00,$00,$00,$b0,$c8,$88,$80,$80,$80,$80,$00,$00,
+
+ 6, // $73 's'
+ $00,$00,$00,$70,$88,$80,$70,$08,$88,$70,$00,$00,
+
+ 6, // $74 't'
+ $00,$40,$40,$40,$e0,$40,$40,$40,$48,$30,$00,$00,
+
+ 6, // $75 'u'
+ $00,$00,$00,$88,$88,$88,$88,$88,$88,$78,$00,$00,
+
+ 6, // $76 'v'
+ $00,$00,$00,$88,$88,$88,$50,$50,$20,$20,$00,$00,
+
+ 6, // $77 'w'
+ $00,$00,$00,$88,$88,$88,$a8,$a8,$d8,$88,$00,$00,
+
+ 6, // $78 'x'
+ $00,$00,$00,$88,$88,$50,$20,$50,$88,$88,$00,$00,
+
+ 6, // $79 'y'
+ $00,$00,$00,$88,$88,$88,$88,$88,$78,$08,$10,$e0,
+
+ 6, // $7a 'z'
+ $00,$00,$00,$f8,$08,$10,$20,$40,$80,$f8,$00,$00,
+
+ 6, // $7b '{'
+ $18,$20,$20,$20,$20,$c0,$20,$20,$20,$20,$18,$00,
+
+ 6, // $7c '|'
+ $00,$20,$20,$20,$20,$00,$20,$20,$20,$20,$00,$00,
+
+ 6, // $7d '}'
+ $c0,$20,$20,$20,$20,$18,$20,$20,$20,$20,$c0,$00,
+
+ 6, // $7e '~'
+ $00,$00,$40,$a8,$10,$00,$00,$00,$00,$00,$00,$00,
+
+ 6, // $7f ''
+ $00,$00,$00,$00,$20,$50,$88,$f8,$00,$00,$00,$00,
+ 0 );
+
+ gse6x9 : array[0..1156 ] of int8u = (
+ 9, 0, 32, 128-32,
+
+ $00,$00,$0a,$00,$14,$00,$1e,$00,$28,$00,$32,$00,$3c,$00,$46,$00,$50,$00,
+ $5a,$00,$64,$00,$6e,$00,$78,$00,$82,$00,$8c,$00,$96,$00,$a0,$00,$aa,$00,
+ $b4,$00,$be,$00,$c8,$00,$d2,$00,$dc,$00,$e6,$00,$f0,$00,$fa,$00,$04,$01,
+ $0e,$01,$18,$01,$22,$01,$2c,$01,$36,$01,$40,$01,$4a,$01,$54,$01,$5e,$01,
+ $68,$01,$72,$01,$7c,$01,$86,$01,$90,$01,$9a,$01,$a4,$01,$ae,$01,$b8,$01,
+ $c2,$01,$cc,$01,$d6,$01,$e0,$01,$ea,$01,$f4,$01,$fe,$01,$08,$02,$12,$02,
+ $1c,$02,$26,$02,$30,$02,$3a,$02,$44,$02,$4e,$02,$58,$02,$62,$02,$6c,$02,
+ $76,$02,$80,$02,$8a,$02,$94,$02,$9e,$02,$a8,$02,$b2,$02,$bc,$02,$c6,$02,
+ $d0,$02,$da,$02,$e4,$02,$ee,$02,$f8,$02,$02,$03,$0c,$03,$16,$03,$20,$03,
+ $2a,$03,$34,$03,$3e,$03,$48,$03,$52,$03,$5c,$03,$66,$03,$70,$03,$7a,$03,
+ $84,$03,$8e,$03,$98,$03,$a2,$03,$ac,$03,$b6,$03,
+
+ 6, // $20 ' '
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 6, // $21 '!'
+ $00,$20,$20,$20,$20,$20,$00,$20,$00,
+
+ 6, // $22 '"'
+ $00,$50,$50,$00,$00,$00,$00,$00,$00,
+
+ 6, // $23 '#'
+ $00,$50,$50,$f8,$50,$f8,$50,$50,$00,
+
+ 6, // $24 '$'
+ $00,$70,$a8,$a0,$70,$28,$a8,$70,$00,
+
+ 6, // $25 '%'
+ $00,$c8,$c8,$10,$20,$40,$98,$98,$00,
+
+ 6, // $26 '&'
+ $00,$60,$90,$90,$60,$a8,$90,$68,$00,
+
+ 6, // $27 '''
+ $00,$20,$20,$00,$00,$00,$00,$00,$00,
+
+ 6, // $28 '('
+ $10,$20,$40,$40,$40,$40,$40,$20,$10,
+
+ 6, // $29 ')'
+ $40,$20,$10,$10,$10,$10,$10,$20,$40,
+
+ 6, // $2a '*'
+ $00,$00,$20,$a8,$70,$a8,$20,$00,$00,
+
+ 6, // $2b '+'
+ $00,$00,$20,$20,$f8,$20,$20,$00,$00,
+
+ 6, // $2c ','
+ $00,$00,$00,$00,$00,$00,$20,$20,$40,
+
+ 6, // $2d '-'
+ $00,$00,$00,$00,$f8,$00,$00,$00,$00,
+
+ 6, // $2e '.'
+ $00,$00,$00,$00,$00,$00,$00,$40,$00,
+
+ 6, // $2f '/'
+ $00,$08,$08,$10,$20,$40,$80,$80,$00,
+
+ 6, // $30 '0'
+ $00,$70,$88,$98,$a8,$c8,$88,$70,$00,
+
+ 6, // $31 '1'
+ $00,$20,$60,$20,$20,$20,$20,$70,$00,
+
+ 6, // $32 '2'
+ $00,$70,$88,$08,$10,$20,$40,$f8,$00,
+
+ 6, // $33 '3'
+ $00,$f8,$10,$20,$70,$08,$88,$70,$00,
+
+ 6, // $34 '4'
+ $00,$10,$20,$40,$90,$f8,$10,$10,$00,
+
+ 6, // $35 '5'
+ $00,$f8,$80,$f0,$08,$08,$88,$70,$00,
+
+ 6, // $36 '6'
+ $00,$70,$88,$80,$f0,$88,$88,$70,$00,
+
+ 6, // $37 '7'
+ $00,$f8,$08,$08,$10,$20,$40,$40,$00,
+
+ 6, // $38 '8'
+ $00,$70,$88,$88,$70,$88,$88,$70,$00,
+
+ 6, // $39 '9'
+ $00,$70,$88,$88,$78,$08,$88,$70,$00,
+
+ 6, // $3a ':'
+ $00,$00,$00,$20,$00,$00,$20,$00,$00,
+
+ 6, // $3b ';'
+ $00,$00,$00,$20,$00,$00,$20,$20,$40,
+
+ 6, // $3c '<'
+ $00,$08,$10,$20,$40,$20,$10,$08,$00,
+
+ 6, // $3d '='
+ $00,$00,$00,$f8,$00,$f8,$00,$00,$00,
+
+ 6, // $3e '>'
+ $00,$80,$40,$20,$10,$20,$40,$80,$00,
+
+ 6, // $3f '?'
+ $00,$70,$88,$08,$10,$20,$00,$20,$00,
+
+ 6, // $40 '@'
+ $00,$70,$88,$88,$b8,$b8,$80,$70,$00,
+
+ 6, // $41 'A'
+ $00,$20,$50,$88,$88,$f8,$88,$88,$00,
+
+ 6, // $42 'B'
+ $00,$f0,$88,$88,$f0,$88,$88,$f0,$00,
+
+ 6, // $43 'C'
+ $00,$70,$88,$80,$80,$80,$88,$70,$00,
+
+ 6, // $44 'D'
+ $00,$e0,$90,$88,$88,$88,$90,$e0,$00,
+
+ 6, // $45 'E'
+ $00,$f8,$80,$80,$f0,$80,$80,$f8,$00,
+
+ 6, // $46 'F'
+ $00,$f8,$80,$80,$f0,$80,$80,$80,$00,
+
+ 6, // $47 'G'
+ $00,$70,$88,$80,$b8,$88,$88,$70,$00,
+
+ 6, // $48 'H'
+ $00,$88,$88,$88,$f8,$88,$88,$88,$00,
+
+ 6, // $49 'I'
+ $00,$70,$20,$20,$20,$20,$20,$70,$00,
+
+ 6, // $4a 'J'
+ $00,$38,$10,$10,$10,$10,$90,$60,$00,
+
+ 6, // $4b 'K'
+ $00,$88,$90,$a0,$c0,$a0,$90,$88,$00,
+
+ 6, // $4c 'L'
+ $00,$80,$80,$80,$80,$80,$80,$f8,$00,
+
+ 6, // $4d 'M'
+ $00,$88,$d8,$a8,$88,$88,$88,$88,$00,
+
+ 6, // $4e 'N'
+ $00,$88,$88,$c8,$a8,$98,$88,$88,$00,
+
+ 6, // $4f 'O'
+ $00,$70,$88,$88,$88,$88,$88,$70,$00,
+
+ 6, // $50 'P'
+ $00,$f0,$88,$88,$f0,$80,$80,$80,$00,
+
+ 6, // $51 'Q'
+ $00,$70,$88,$88,$88,$a8,$90,$68,$00,
+
+ 6, // $52 'R'
+ $00,$f0,$88,$88,$88,$f0,$90,$88,$00,
+
+ 6, // $53 'S'
+ $00,$70,$88,$80,$70,$08,$88,$70,$00,
+
+ 6, // $54 'T'
+ $00,$f8,$20,$20,$20,$20,$20,$20,$00,
+
+ 6, // $55 'U'
+ $00,$88,$88,$88,$88,$88,$88,$70,$00,
+
+ 6, // $56 'V'
+ $00,$88,$88,$88,$50,$50,$20,$20,$00,
+
+ 6, // $57 'W'
+ $00,$88,$88,$88,$a8,$a8,$d8,$88,$00,
+
+ 6, // $58 'X'
+ $00,$88,$88,$50,$20,$50,$88,$88,$00,
+
+ 6, // $59 'Y'
+ $00,$88,$88,$50,$20,$20,$20,$20,$00,
+
+ 6, // $5a 'Z'
+ $00,$f8,$08,$10,$20,$40,$80,$f8,$00,
+
+ 6, // $5b '['
+ $70,$40,$40,$40,$40,$40,$40,$40,$70,
+
+ 6, // $5c '\'
+ $00,$80,$80,$40,$20,$10,$08,$08,$00,
+
+ 6, // $5d ']'
+ $70,$10,$10,$10,$10,$10,$10,$10,$70,
+
+ 6, // $5e '^'
+ $00,$00,$20,$50,$88,$00,$00,$00,$00,
+
+ 6, // $5f '_'
+ $00,$00,$00,$00,$00,$00,$00,$f8,$00,
+
+ 6, // $60 '`'
+ $00,$40,$20,$00,$00,$00,$00,$00,$00,
+
+ 6, // $61 'a'
+ $00,$00,$00,$70,$08,$78,$88,$78,$00,
+
+ 6, // $62 'b'
+ $00,$80,$80,$f0,$88,$88,$88,$f0,$00,
+
+ 6, // $63 'c'
+ $00,$00,$00,$70,$88,$80,$88,$70,$00,
+
+ 6, // $64 'd'
+ $00,$08,$08,$78,$88,$88,$88,$78,$00,
+
+ 6, // $65 'e'
+ $00,$00,$00,$70,$88,$f8,$80,$78,$00,
+
+ 6, // $66 'f'
+ $00,$18,$20,$20,$f8,$20,$20,$20,$00,
+
+ 6, // $67 'g'
+ $00,$00,$00,$78,$88,$88,$78,$08,$70,
+
+ 6, // $68 'h'
+ $00,$80,$80,$f0,$88,$88,$88,$88,$00,
+
+ 6, // $69 'i'
+ $00,$20,$00,$60,$20,$20,$20,$70,$00,
+
+ 6, // $6a 'j'
+ $00,$10,$00,$30,$10,$10,$10,$90,$60,
+
+ 6, // $6b 'k'
+ $00,$00,$80,$88,$90,$a0,$d0,$88,$00,
+
+ 6, // $6c 'l'
+ $00,$60,$20,$20,$20,$20,$20,$70,$00,
+
+ 6, // $6d 'm'
+ $00,$00,$00,$d0,$a8,$a8,$a8,$a8,$00,
+
+ 6, // $6e 'n'
+ $00,$00,$00,$b0,$c8,$88,$88,$88,$00,
+
+ 6, // $6f 'o'
+ $00,$00,$00,$70,$88,$88,$88,$70,$00,
+
+ 6, // $70 'p'
+ $00,$00,$00,$f0,$88,$88,$f0,$80,$80,
+
+ 6, // $71 'q'
+ $00,$00,$00,$78,$88,$88,$78,$08,$08,
+
+ 6, // $72 'r'
+ $00,$00,$00,$b8,$c0,$80,$80,$80,$00,
+
+ 6, // $73 's'
+ $00,$00,$00,$78,$80,$70,$08,$f0,$00,
+
+ 6, // $74 't'
+ $00,$40,$40,$e0,$40,$40,$48,$30,$00,
+
+ 6, // $75 'u'
+ $00,$00,$00,$88,$88,$88,$88,$78,$00,
+
+ 6, // $76 'v'
+ $00,$00,$00,$88,$88,$88,$50,$20,$00,
+
+ 6, // $77 'w'
+ $00,$00,$00,$88,$88,$a8,$d8,$88,$00,
+
+ 6, // $78 'x'
+ $00,$00,$00,$88,$50,$20,$50,$88,$00,
+
+ 6, // $79 'y'
+ $00,$00,$00,$88,$88,$88,$78,$08,$70,
+
+ 6, // $7a 'z'
+ $00,$00,$00,$f8,$10,$20,$40,$f8,$00,
+
+ 6, // $7b '{'
+ $18,$20,$20,$20,$c0,$20,$20,$20,$18,
+
+ 6, // $7c '|'
+ $00,$20,$20,$20,$00,$20,$20,$20,$00,
+
+ 6, // $7d '}'
+ $c0,$20,$20,$20,$18,$20,$20,$20,$c0,
+
+ 6, // $7e '~'
+ $00,$40,$a8,$10,$00,$00,$00,$00,$00,
+
+ 6, // $7f ''
+ $00,$00,$00,$20,$50,$88,$f8,$00,$00,
+ 0 );
+
+ gse7x11 : array[0..1348 ] of int8u = (
+ 11, 0, 32, 128-32,
+
+ $00,$00,$0c,$00,$18,$00,$24,$00,$30,$00,$3c,$00,$48,$00,$54,$00,$60,$00,
+ $6c,$00,$78,$00,$84,$00,$90,$00,$9c,$00,$a8,$00,$b4,$00,$c0,$00,$cc,$00,
+ $d8,$00,$e4,$00,$f0,$00,$fc,$00,$08,$01,$14,$01,$20,$01,$2c,$01,$38,$01,
+ $44,$01,$50,$01,$5c,$01,$68,$01,$74,$01,$80,$01,$8c,$01,$98,$01,$a4,$01,
+ $b0,$01,$bc,$01,$c8,$01,$d4,$01,$e0,$01,$ec,$01,$f8,$01,$04,$02,$10,$02,
+ $1c,$02,$28,$02,$34,$02,$40,$02,$4c,$02,$58,$02,$64,$02,$70,$02,$7c,$02,
+ $88,$02,$94,$02,$a0,$02,$ac,$02,$b8,$02,$c4,$02,$d0,$02,$dc,$02,$e8,$02,
+ $f4,$02,$00,$03,$0c,$03,$18,$03,$24,$03,$30,$03,$3c,$03,$48,$03,$54,$03,
+ $60,$03,$6c,$03,$78,$03,$84,$03,$90,$03,$9c,$03,$a8,$03,$b4,$03,$c0,$03,
+ $cc,$03,$d8,$03,$e4,$03,$f0,$03,$fc,$03,$08,$04,$14,$04,$20,$04,$2c,$04,
+ $38,$04,$44,$04,$50,$04,$5c,$04,$68,$04,$74,$04,
+
+ 7, // $20 ' '
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $21 '!'
+ $00,$10,$38,$38,$38,$10,$10,$00,$10,$00,$00,
+
+ 7, // $22 '"'
+ $00,$00,$24,$24,$24,$00,$00,$00,$00,$00,$00,
+
+ 7, // $23 '#'
+ $00,$48,$48,$fc,$48,$48,$fc,$48,$48,$00,$00,
+
+ 7, // $24 '$'
+ $00,$10,$38,$54,$50,$38,$14,$54,$38,$10,$00,
+
+ 7, // $25 '%'
+ $00,$00,$42,$a4,$48,$10,$24,$4a,$84,$00,$00,
+
+ 7, // $26 '&'
+ $00,$30,$48,$48,$30,$60,$94,$98,$6c,$00,$00,
+
+ 7, // $27 '''
+ $00,$20,$20,$40,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $28 '('
+ $00,$04,$08,$10,$10,$10,$10,$08,$04,$00,$00,
+
+ 7, // $29 ')'
+ $00,$40,$20,$10,$10,$10,$10,$20,$40,$00,$00,
+
+ 7, // $2a '*'
+ $00,$00,$00,$20,$a8,$70,$a8,$20,$00,$00,$00,
+
+ 7, // $2b '+'
+ $00,$00,$00,$10,$10,$7c,$10,$10,$00,$00,$00,
+
+ 7, // $2c ','
+ $00,$00,$00,$00,$00,$00,$00,$30,$30,$30,$60,
+
+ 7, // $2d '-'
+ $00,$00,$00,$00,$00,$fc,$00,$00,$00,$00,$00,
+
+ 7, // $2e '.'
+ $00,$00,$00,$00,$00,$00,$00,$30,$30,$00,$00,
+
+ 7, // $2f '/'
+ $00,$08,$08,$10,$10,$20,$20,$40,$40,$00,$00,
+
+ 7, // $30 '0'
+ $00,$38,$44,$4c,$54,$64,$44,$44,$38,$00,$00,
+
+ 7, // $31 '1'
+ $00,$10,$30,$10,$10,$10,$10,$10,$7c,$00,$00,
+
+ 7, // $32 '2'
+ $00,$38,$44,$04,$08,$10,$20,$44,$7c,$00,$00,
+
+ 7, // $33 '3'
+ $00,$7c,$48,$10,$38,$04,$04,$44,$38,$00,$00,
+
+ 7, // $34 '4'
+ $00,$08,$10,$20,$48,$48,$7c,$08,$1c,$00,$00,
+
+ 7, // $35 '5'
+ $00,$7c,$40,$40,$78,$04,$04,$44,$38,$00,$00,
+
+ 7, // $36 '6'
+ $00,$18,$20,$40,$78,$44,$44,$44,$38,$00,$00,
+
+ 7, // $37 '7'
+ $00,$7c,$44,$04,$08,$10,$10,$10,$10,$00,$00,
+
+ 7, // $38 '8'
+ $00,$38,$44,$44,$38,$44,$44,$44,$38,$00,$00,
+
+ 7, // $39 '9'
+ $00,$38,$44,$44,$44,$3c,$04,$08,$30,$00,$00,
+
+ 7, // $3a ':'
+ $00,$00,$00,$30,$00,$00,$00,$30,$00,$00,$00,
+
+ 7, // $3b ';'
+ $00,$00,$00,$30,$00,$00,$00,$30,$30,$60,$00,
+
+ 7, // $3c '<'
+ $00,$00,$04,$08,$10,$20,$10,$08,$04,$00,$00,
+
+ 7, // $3d '='
+ $00,$00,$00,$00,$fc,$00,$fc,$00,$00,$00,$00,
+
+ 7, // $3e '>'
+ $00,$00,$40,$20,$10,$08,$10,$20,$40,$00,$00,
+
+ 7, // $3f '?'
+ $00,$70,$88,$88,$10,$20,$20,$00,$20,$00,$00,
+
+ 7, // $40 '@'
+ $00,$30,$48,$04,$34,$54,$54,$54,$28,$00,$00,
+
+ 7, // $41 'A'
+ $00,$10,$28,$44,$44,$7c,$44,$44,$44,$00,$00,
+
+ 7, // $42 'B'
+ $00,$78,$44,$44,$78,$44,$44,$44,$78,$00,$00,
+
+ 7, // $43 'C'
+ $00,$38,$44,$40,$40,$40,$40,$44,$38,$00,$00,
+
+ 7, // $44 'D'
+ $00,$70,$48,$44,$44,$44,$44,$48,$70,$00,$00,
+
+ 7, // $45 'E'
+ $00,$7c,$40,$40,$70,$40,$40,$40,$7c,$00,$00,
+
+ 7, // $46 'F'
+ $00,$7c,$40,$40,$70,$40,$40,$40,$40,$00,$00,
+
+ 7, // $47 'G'
+ $00,$38,$44,$40,$40,$5c,$44,$44,$38,$00,$00,
+
+ 7, // $48 'H'
+ $00,$44,$44,$44,$7c,$44,$44,$44,$44,$00,$00,
+
+ 7, // $49 'I'
+ $00,$38,$10,$10,$10,$10,$10,$10,$38,$00,$00,
+
+ 7, // $4a 'J'
+ $00,$1c,$08,$08,$08,$08,$08,$48,$30,$00,$00,
+
+ 7, // $4b 'K'
+ $00,$44,$48,$50,$60,$50,$48,$44,$44,$00,$00,
+
+ 7, // $4c 'L'
+ $00,$40,$40,$40,$40,$40,$40,$40,$7c,$00,$00,
+
+ 7, // $4d 'M'
+ $00,$44,$6c,$54,$54,$44,$44,$44,$44,$00,$00,
+
+ 7, // $4e 'N'
+ $00,$44,$44,$64,$54,$4c,$44,$44,$44,$00,$00,
+
+ 7, // $4f 'O'
+ $00,$38,$44,$44,$44,$44,$44,$44,$38,$00,$00,
+
+ 7, // $50 'P'
+ $00,$78,$44,$44,$44,$78,$40,$40,$40,$00,$00,
+
+ 7, // $51 'Q'
+ $00,$38,$44,$44,$44,$44,$54,$48,$34,$00,$00,
+
+ 7, // $52 'R'
+ $00,$78,$44,$44,$44,$78,$50,$48,$44,$00,$00,
+
+ 7, // $53 'S'
+ $00,$38,$44,$40,$38,$04,$44,$44,$38,$00,$00,
+
+ 7, // $54 'T'
+ $00,$7c,$54,$10,$10,$10,$10,$10,$10,$00,$00,
+
+ 7, // $55 'U'
+ $00,$44,$44,$44,$44,$44,$44,$44,$38,$00,$00,
+
+ 7, // $56 'V'
+ $00,$44,$44,$44,$44,$28,$28,$10,$10,$00,$00,
+
+ 7, // $57 'W'
+ $00,$44,$44,$44,$44,$54,$54,$6c,$44,$00,$00,
+
+ 7, // $58 'X'
+ $00,$44,$44,$28,$10,$28,$44,$44,$44,$00,$00,
+
+ 7, // $59 'Y'
+ $00,$44,$44,$44,$28,$10,$10,$10,$38,$00,$00,
+
+ 7, // $5a 'Z'
+ $00,$7c,$04,$08,$10,$20,$40,$44,$7c,$00,$00,
+
+ 7, // $5b '['
+ $00,$38,$20,$20,$20,$20,$20,$20,$38,$00,$00,
+
+ 7, // $5c '\'
+ $00,$40,$40,$20,$20,$10,$10,$08,$08,$00,$00,
+
+ 7, // $5d ']'
+ $00,$38,$08,$08,$08,$08,$08,$08,$38,$00,$00,
+
+ 7, // $5e '^'
+ $00,$10,$28,$44,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $5f '_'
+ $00,$00,$00,$00,$00,$00,$00,$00,$fc,$00,$00,
+
+ 7, // $60 '`'
+ $00,$20,$20,$10,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $61 'a'
+ $00,$00,$00,$38,$04,$3c,$44,$44,$3c,$00,$00,
+
+ 7, // $62 'b'
+ $00,$40,$40,$78,$44,$44,$44,$44,$78,$00,$00,
+
+ 7, // $63 'c'
+ $00,$00,$00,$38,$44,$40,$40,$44,$38,$00,$00,
+
+ 7, // $64 'd'
+ $00,$04,$04,$3c,$44,$44,$44,$44,$3c,$00,$00,
+
+ 7, // $65 'e'
+ $00,$00,$00,$38,$44,$7c,$40,$44,$38,$00,$00,
+
+ 7, // $66 'f'
+ $00,$18,$24,$20,$70,$20,$20,$20,$70,$00,$00,
+
+ 7, // $67 'g'
+ $00,$00,$00,$3c,$44,$44,$44,$3c,$04,$44,$38,
+
+ 7, // $68 'h'
+ $00,$40,$40,$40,$58,$64,$44,$44,$44,$00,$00,
+
+ 7, // $69 'i'
+ $00,$10,$00,$30,$10,$10,$10,$10,$38,$00,$00,
+
+ 7, // $6a 'j'
+ $00,$08,$00,$18,$08,$08,$08,$08,$48,$30,$00,
+
+ 7, // $6b 'k'
+ $00,$40,$40,$44,$48,$50,$68,$44,$44,$00,$00,
+
+ 7, // $6c 'l'
+ $00,$30,$10,$10,$10,$10,$10,$10,$38,$00,$00,
+
+ 7, // $6d 'm'
+ $00,$00,$00,$a8,$54,$54,$54,$54,$54,$00,$00,
+
+ 7, // $6e 'n'
+ $00,$00,$00,$b8,$44,$44,$44,$44,$44,$00,$00,
+
+ 7, // $6f 'o'
+ $00,$00,$00,$38,$44,$44,$44,$44,$38,$00,$00,
+
+ 7, // $70 'p'
+ $00,$00,$00,$78,$44,$44,$44,$44,$78,$40,$40,
+
+ 7, // $71 'q'
+ $00,$00,$00,$3c,$44,$44,$44,$44,$3c,$04,$04,
+
+ 7, // $72 'r'
+ $00,$00,$00,$58,$64,$44,$40,$40,$40,$00,$00,
+
+ 7, // $73 's'
+ $00,$00,$00,$3c,$40,$38,$04,$04,$78,$00,$00,
+
+ 7, // $74 't'
+ $00,$20,$20,$70,$20,$20,$20,$24,$18,$00,$00,
+
+ 7, // $75 'u'
+ $00,$00,$00,$44,$44,$44,$44,$44,$3a,$00,$00,
+
+ 7, // $76 'v'
+ $00,$00,$00,$44,$44,$44,$44,$28,$10,$00,$00,
+
+ 7, // $77 'w'
+ $00,$00,$00,$44,$44,$54,$54,$6c,$44,$00,$00,
+
+ 7, // $78 'x'
+ $00,$00,$00,$44,$28,$10,$28,$44,$44,$00,$00,
+
+ 7, // $79 'y'
+ $00,$00,$00,$44,$44,$44,$3c,$04,$08,$30,$00,
+
+ 7, // $7a 'z'
+ $00,$00,$00,$7c,$08,$10,$20,$44,$7c,$00,$00,
+
+ 7, // $7b '{'
+ $00,$0c,$10,$10,$10,$60,$10,$10,$0c,$00,$00,
+
+ 7, // $7c '|'
+ $00,$20,$20,$20,$00,$20,$20,$20,$20,$00,$00,
+
+ 7, // $7d '}'
+ $00,$60,$10,$10,$10,$0c,$10,$10,$60,$00,$00,
+
+ 7, // $7e '~'
+ $00,$00,$64,$98,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $7f ''
+ $00,$00,$00,$10,$28,$44,$44,$7c,$00,$00,$00,
+ 0 );
+
+ gse7x11_bold : array[0..1348 ] of int8u = (
+ 11, 0, 32, 128-32,
+
+ $00,$00,$0c,$00,$18,$00,$24,$00,$30,$00,$3c,$00,$48,$00,$54,$00,$60,$00,
+ $6c,$00,$78,$00,$84,$00,$90,$00,$9c,$00,$a8,$00,$b4,$00,$c0,$00,$cc,$00,
+ $d8,$00,$e4,$00,$f0,$00,$fc,$00,$08,$01,$14,$01,$20,$01,$2c,$01,$38,$01,
+ $44,$01,$50,$01,$5c,$01,$68,$01,$74,$01,$80,$01,$8c,$01,$98,$01,$a4,$01,
+ $b0,$01,$bc,$01,$c8,$01,$d4,$01,$e0,$01,$ec,$01,$f8,$01,$04,$02,$10,$02,
+ $1c,$02,$28,$02,$34,$02,$40,$02,$4c,$02,$58,$02,$64,$02,$70,$02,$7c,$02,
+ $88,$02,$94,$02,$a0,$02,$ac,$02,$b8,$02,$c4,$02,$d0,$02,$dc,$02,$e8,$02,
+ $f4,$02,$00,$03,$0c,$03,$18,$03,$24,$03,$30,$03,$3c,$03,$48,$03,$54,$03,
+ $60,$03,$6c,$03,$78,$03,$84,$03,$90,$03,$9c,$03,$a8,$03,$b4,$03,$c0,$03,
+ $cc,$03,$d8,$03,$e4,$03,$f0,$03,$fc,$03,$08,$04,$14,$04,$20,$04,$2c,$04,
+ $38,$04,$44,$04,$50,$04,$5c,$04,$68,$04,$74,$04,
+
+ 7, // $20 ' '
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $21 '!'
+ $00,$30,$30,$30,$30,$30,$00,$30,$30,$00,$00,
+
+ 7, // $22 '"'
+ $00,$6c,$6c,$28,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $23 '#'
+ $00,$48,$48,$fc,$48,$48,$fc,$48,$48,$00,$00,
+
+ 7, // $24 '$'
+ $30,$30,$78,$cc,$c0,$78,$0c,$cc,$78,$30,$30,
+
+ 7, // $25 '%'
+ $00,$00,$c4,$0c,$18,$30,$60,$c0,$8c,$00,$00,
+
+ 7, // $26 '&'
+ $00,$30,$58,$58,$30,$74,$dc,$d8,$6c,$00,$00,
+
+ 7, // $27 '''
+ $00,$30,$30,$60,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $28 '('
+ $00,$0c,$18,$30,$30,$30,$30,$18,$0c,$00,$00,
+
+ 7, // $29 ')'
+ $00,$c0,$60,$30,$30,$30,$30,$60,$c0,$00,$00,
+
+ 7, // $2a '*'
+ $00,$00,$00,$20,$a8,$70,$a8,$20,$00,$00,$00,
+
+ 7, // $2b '+'
+ $00,$00,$00,$30,$30,$fc,$30,$30,$00,$00,$00,
+
+ 7, // $2c ','
+ $00,$00,$00,$00,$00,$00,$00,$30,$30,$60,$00,
+
+ 7, // $2d '-'
+ $00,$00,$00,$00,$00,$fc,$00,$00,$00,$00,$00,
+
+ 7, // $2e '.'
+ $00,$00,$00,$00,$00,$00,$00,$30,$30,$00,$00,
+
+ 7, // $2f '/'
+ $00,$0c,$0c,$18,$18,$30,$30,$60,$60,$00,$00,
+
+ 7, // $30 '0'
+ $00,$78,$cc,$cc,$dc,$ec,$cc,$cc,$78,$00,$00,
+
+ 7, // $31 '1'
+ $00,$30,$70,$f0,$30,$30,$30,$30,$fc,$00,$00,
+
+ 7, // $32 '2'
+ $00,$78,$cc,$cc,$18,$30,$60,$cc,$fc,$00,$00,
+
+ 7, // $33 '3'
+ $00,$fc,$98,$30,$78,$0c,$0c,$cc,$78,$00,$00,
+
+ 7, // $34 '4'
+ $00,$18,$30,$68,$d8,$d8,$fc,$18,$3c,$00,$00,
+
+ 7, // $35 '5'
+ $00,$fc,$c0,$c0,$f8,$0c,$0c,$cc,$78,$00,$00,
+
+ 7, // $36 '6'
+ $00,$38,$60,$c0,$f8,$cc,$cc,$cc,$78,$00,$00,
+
+ 7, // $37 '7'
+ $00,$fc,$8c,$0c,$18,$30,$30,$30,$30,$00,$00,
+
+ 7, // $38 '8'
+ $00,$78,$cc,$cc,$78,$cc,$cc,$cc,$78,$00,$00,
+
+ 7, // $39 '9'
+ $00,$78,$cc,$cc,$cc,$7c,$0c,$18,$70,$00,$00,
+
+ 7, // $3a ':'
+ $00,$00,$30,$30,$00,$00,$30,$30,$00,$00,$00,
+
+ 7, // $3b ';'
+ $00,$00,$30,$30,$00,$00,$30,$30,$30,$60,$00,
+
+ 7, // $3c '<'
+ $00,$00,$0c,$18,$30,$60,$30,$18,$0c,$00,$00,
+
+ 7, // $3d '='
+ $00,$00,$00,$00,$fc,$00,$fc,$00,$00,$00,$00,
+
+ 7, // $3e '>'
+ $00,$00,$60,$30,$18,$0c,$18,$30,$60,$00,$00,
+
+ 7, // $3f '?'
+ $00,$78,$cc,$cc,$18,$30,$30,$00,$30,$00,$00,
+
+ 7, // $40 '@'
+ $00,$70,$88,$04,$74,$b4,$b4,$b4,$68,$00,$00,
+
+ 7, // $41 'A'
+ $00,$30,$78,$cc,$cc,$fc,$cc,$cc,$cc,$00,$00,
+
+ 7, // $42 'B'
+ $00,$f8,$cc,$cc,$f8,$cc,$cc,$cc,$f8,$00,$00,
+
+ 7, // $43 'C'
+ $00,$78,$cc,$c0,$c0,$c0,$c0,$cc,$78,$00,$00,
+
+ 7, // $44 'D'
+ $00,$f0,$d8,$cc,$cc,$cc,$cc,$d8,$f0,$00,$00,
+
+ 7, // $45 'E'
+ $00,$fc,$c4,$d0,$f0,$d0,$c0,$c4,$fc,$00,$00,
+
+ 7, // $46 'F'
+ $00,$fc,$c4,$d0,$f0,$d0,$c0,$c0,$c0,$00,$00,
+
+ 7, // $47 'G'
+ $00,$78,$cc,$c0,$c0,$dc,$cc,$cc,$78,$00,$00,
+
+ 7, // $48 'H'
+ $00,$cc,$cc,$cc,$fc,$cc,$cc,$cc,$cc,$00,$00,
+
+ 7, // $49 'I'
+ $00,$78,$30,$30,$30,$30,$30,$30,$78,$00,$00,
+
+ 7, // $4a 'J'
+ $00,$3c,$18,$18,$18,$18,$d8,$d8,$70,$00,$00,
+
+ 7, // $4b 'K'
+ $00,$cc,$cc,$d8,$f0,$d8,$cc,$cc,$cc,$00,$00,
+
+ 7, // $4c 'L'
+ $00,$c0,$c0,$c0,$c0,$c0,$c0,$c4,$fc,$00,$00,
+
+ 7, // $4d 'M'
+ $00,$84,$cc,$fc,$b4,$cc,$cc,$cc,$cc,$00,$00,
+
+ 7, // $4e 'N'
+ $00,$cc,$cc,$ec,$fc,$dc,$cc,$cc,$cc,$00,$00,
+
+ 7, // $4f 'O'
+ $00,$78,$cc,$cc,$cc,$cc,$cc,$cc,$78,$00,$00,
+
+ 7, // $50 'P'
+ $00,$f8,$cc,$cc,$cc,$f8,$c0,$c0,$c0,$00,$00,
+
+ 7, // $51 'Q'
+ $00,$78,$cc,$cc,$cc,$cc,$dc,$78,$18,$0c,$00,
+
+ 7, // $52 'R'
+ $00,$f8,$cc,$cc,$cc,$f8,$d8,$cc,$cc,$00,$00,
+
+ 7, // $53 'S'
+ $00,$78,$cc,$e0,$70,$38,$1c,$cc,$78,$00,$00,
+
+ 7, // $54 'T'
+ $00,$fc,$b4,$30,$30,$30,$30,$30,$30,$00,$00,
+
+ 7, // $55 'U'
+ $00,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$78,$00,$00,
+
+ 7, // $56 'V'
+ $00,$cc,$cc,$cc,$cc,$cc,$cc,$78,$30,$00,$00,
+
+ 7, // $57 'W'
+ $00,$cc,$cc,$cc,$cc,$b4,$fc,$cc,$84,$00,$00,
+
+ 7, // $58 'X'
+ $00,$cc,$cc,$78,$30,$78,$cc,$cc,$cc,$00,$00,
+
+ 7, // $59 'Y'
+ $00,$cc,$cc,$cc,$78,$30,$30,$30,$78,$00,$00,
+
+ 7, // $5a 'Z'
+ $00,$fc,$8c,$18,$30,$60,$c0,$c4,$fc,$00,$00,
+
+ 7, // $5b '['
+ $00,$78,$60,$60,$60,$60,$60,$60,$78,$00,$00,
+
+ 7, // $5c '\'
+ $00,$60,$60,$30,$30,$18,$18,$0c,$0c,$00,$00,
+
+ 7, // $5d ']'
+ $00,$78,$18,$18,$18,$18,$18,$18,$78,$00,$00,
+
+ 7, // $5e '^'
+ $00,$10,$38,$6c,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $5f '_'
+ $00,$00,$00,$00,$00,$00,$00,$00,$fc,$00,$00,
+
+ 7, // $60 '`'
+ $00,$30,$30,$18,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $61 'a'
+ $00,$00,$00,$70,$18,$78,$d8,$d8,$6c,$00,$00,
+
+ 7, // $62 'b'
+ $00,$60,$60,$60,$78,$6c,$6c,$6c,$78,$00,$00,
+
+ 7, // $63 'c'
+ $00,$00,$00,$78,$cc,$c0,$c0,$cc,$78,$00,$00,
+
+ 7, // $64 'd'
+ $00,$18,$18,$18,$78,$d8,$d8,$d8,$6c,$00,$00,
+
+ 7, // $65 'e'
+ $00,$00,$00,$78,$cc,$fc,$c0,$cc,$78,$00,$00,
+
+ 7, // $66 'f'
+ $00,$18,$34,$30,$78,$30,$30,$30,$78,$00,$00,
+
+ 7, // $67 'g'
+ $00,$00,$00,$6c,$d8,$d8,$d8,$78,$18,$d8,$70,
+
+ 7, // $68 'h'
+ $00,$c0,$c0,$d8,$ec,$cc,$cc,$cc,$cc,$00,$00,
+
+ 7, // $69 'i'
+ $00,$30,$00,$70,$30,$30,$30,$30,$78,$00,$00,
+
+ 7, // $6a 'j'
+ $00,$0c,$00,$1c,$0c,$0c,$0c,$0c,$6c,$6c,$38,
+
+ 7, // $6b 'k'
+ $00,$c0,$c0,$cc,$cc,$d8,$f0,$d8,$cc,$00,$00,
+
+ 7, // $6c 'l'
+ $00,$70,$30,$30,$30,$30,$30,$30,$78,$00,$00,
+
+ 7, // $6d 'm'
+ $00,$00,$00,$e8,$fc,$d4,$d4,$c4,$c4,$00,$00,
+
+ 7, // $6e 'n'
+ $00,$00,$00,$d8,$6c,$6c,$6c,$6c,$6c,$00,$00,
+
+ 7, // $6f 'o'
+ $00,$00,$00,$78,$cc,$cc,$cc,$cc,$78,$00,$00,
+
+ 7, // $70 'p'
+ $00,$00,$00,$f8,$cc,$cc,$cc,$f8,$c0,$c0,$c0,
+
+ 7, // $71 'q'
+ $00,$00,$00,$7c,$cc,$cc,$cc,$7c,$0c,$0c,$0c,
+
+ 7, // $72 'r'
+ $00,$00,$00,$d8,$ec,$cc,$c0,$c0,$c0,$00,$00,
+
+ 7, // $73 's'
+ $00,$00,$00,$78,$cc,$60,$18,$cc,$78,$00,$00,
+
+ 7, // $74 't'
+ $00,$20,$60,$60,$f0,$60,$60,$68,$30,$00,$00,
+
+ 7, // $75 'u'
+ $00,$00,$00,$d8,$d8,$d8,$d8,$d8,$6c,$00,$00,
+
+ 7, // $76 'v'
+ $00,$00,$00,$cc,$cc,$cc,$cc,$78,$30,$00,$00,
+
+ 7, // $77 'w'
+ $00,$00,$00,$cc,$cc,$b4,$fc,$cc,$84,$00,$00,
+
+ 7, // $78 'x'
+ $00,$00,$00,$cc,$78,$30,$78,$cc,$cc,$00,$00,
+
+ 7, // $79 'y'
+ $00,$00,$00,$cc,$cc,$cc,$cc,$7c,$0c,$18,$f0,
+
+ 7, // $7a 'z'
+ $00,$00,$00,$fc,$98,$30,$60,$c4,$fc,$00,$00,
+
+ 7, // $7b '{'
+ $1c,$30,$30,$30,$e0,$30,$30,$30,$1c,$00,$00,
+
+ 7, // $7c '|'
+ $30,$30,$30,$30,$00,$30,$30,$30,$30,$00,$00,
+
+ 7, // $7d '}'
+ $e0,$30,$30,$30,$1c,$30,$30,$30,$e0,$00,$00,
+
+ 7, // $7e '~'
+ $00,$34,$58,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $7f ''
+ $00,$00,$00,$30,$78,$cc,$cc,$fc,$00,$00,$00,
+ 0 );
+
+ gse7x15 : array[0..1732 ] of int8u = (
+ 15, 0, 32, 128-32,
+
+ $00,$00,$10,$00,$20,$00,$30,$00,$40,$00,$50,$00,$60,$00,$70,$00,$80,$00,
+ $90,$00,$a0,$00,$b0,$00,$c0,$00,$d0,$00,$e0,$00,$f0,$00,$00,$01,$10,$01,
+ $20,$01,$30,$01,$40,$01,$50,$01,$60,$01,$70,$01,$80,$01,$90,$01,$a0,$01,
+ $b0,$01,$c0,$01,$d0,$01,$e0,$01,$f0,$01,$00,$02,$10,$02,$20,$02,$30,$02,
+ $40,$02,$50,$02,$60,$02,$70,$02,$80,$02,$90,$02,$a0,$02,$b0,$02,$c0,$02,
+ $d0,$02,$e0,$02,$f0,$02,$00,$03,$10,$03,$20,$03,$30,$03,$40,$03,$50,$03,
+ $60,$03,$70,$03,$80,$03,$90,$03,$a0,$03,$b0,$03,$c0,$03,$d0,$03,$e0,$03,
+ $f0,$03,$00,$04,$10,$04,$20,$04,$30,$04,$40,$04,$50,$04,$60,$04,$70,$04,
+ $80,$04,$90,$04,$a0,$04,$b0,$04,$c0,$04,$d0,$04,$e0,$04,$f0,$04,$00,$05,
+ $10,$05,$20,$05,$30,$05,$40,$05,$50,$05,$60,$05,$70,$05,$80,$05,$90,$05,
+ $a0,$05,$b0,$05,$c0,$05,$d0,$05,$e0,$05,$f0,$05,
+
+ 7, // $20 ' '
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $21 '!'
+ $00,$00,$10,$38,$38,$38,$38,$10,$10,$00,$10,$10,$00,$00,$00,
+
+ 7, // $22 '"'
+ $00,$00,$24,$24,$24,$24,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $23 '#'
+ $00,$00,$48,$48,$48,$fc,$48,$48,$fc,$48,$48,$48,$00,$00,$00,
+
+ 7, // $24 '$'
+ $00,$00,$10,$38,$54,$50,$38,$14,$54,$54,$38,$10,$00,$00,$00,
+
+ 7, // $25 '%'
+ $00,$00,$44,$44,$08,$08,$10,$10,$20,$20,$44,$44,$00,$00,$00,
+
+ 7, // $26 '&'
+ $00,$00,$00,$30,$48,$48,$30,$60,$94,$98,$90,$6c,$00,$00,$00,
+
+ 7, // $27 '''
+ $00,$00,$20,$20,$20,$40,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $28 '('
+ $00,$04,$08,$10,$20,$20,$20,$20,$20,$10,$08,$04,$00,$00,$00,
+
+ 7, // $29 ')'
+ $00,$40,$20,$10,$08,$08,$08,$08,$08,$10,$20,$40,$00,$00,$00,
+
+ 7, // $2a '*'
+ $00,$00,$00,$00,$00,$20,$a8,$70,$a8,$20,$00,$00,$00,$00,$00,
+
+ 7, // $2b '+'
+ $00,$00,$00,$00,$10,$10,$10,$7c,$10,$10,$10,$00,$00,$00,$00,
+
+ 7, // $2c ','
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$30,$30,$30,$60,$00,
+
+ 7, // $2d '-'
+ $00,$00,$00,$00,$00,$00,$00,$fc,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $2e '.'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$30,$30,$00,$00,$00,
+
+ 7, // $2f '/'
+ $00,$00,$04,$04,$08,$08,$10,$10,$20,$20,$40,$40,$00,$00,$00,
+
+ 7, // $30 '0'
+ $00,$00,$38,$44,$44,$4c,$54,$64,$44,$44,$44,$38,$00,$00,$00,
+
+ 7, // $31 '1'
+ $00,$00,$10,$10,$30,$10,$10,$10,$10,$10,$10,$7c,$00,$00,$00,
+
+ 7, // $32 '2'
+ $00,$00,$38,$44,$44,$04,$08,$10,$20,$40,$44,$7c,$00,$00,$00,
+
+ 7, // $33 '3'
+ $00,$00,$7c,$44,$08,$10,$38,$04,$04,$04,$44,$38,$00,$00,$00,
+
+ 7, // $34 '4'
+ $00,$00,$08,$10,$20,$40,$48,$48,$7c,$08,$08,$1c,$00,$00,$00,
+
+ 7, // $35 '5'
+ $00,$00,$7c,$40,$40,$40,$78,$04,$04,$04,$44,$38,$00,$00,$00,
+
+ 7, // $36 '6'
+ $00,$00,$18,$20,$40,$40,$78,$44,$44,$44,$44,$38,$00,$00,$00,
+
+ 7, // $37 '7'
+ $00,$00,$7c,$44,$04,$04,$08,$08,$10,$10,$10,$10,$00,$00,$00,
+
+ 7, // $38 '8'
+ $00,$00,$38,$44,$44,$44,$38,$44,$44,$44,$44,$38,$00,$00,$00,
+
+ 7, // $39 '9'
+ $00,$00,$38,$44,$44,$44,$44,$3c,$04,$04,$08,$30,$00,$00,$00,
+
+ 7, // $3a ':'
+ $00,$00,$00,$00,$00,$30,$00,$00,$00,$00,$30,$00,$00,$00,$00,
+
+ 7, // $3b ';'
+ $00,$00,$00,$00,$00,$30,$00,$00,$00,$00,$30,$30,$60,$00,$00,
+
+ 7, // $3c '<'
+ $00,$00,$00,$04,$08,$10,$20,$40,$20,$10,$08,$04,$00,$00,$00,
+
+ 7, // $3d '='
+ $00,$00,$00,$00,$00,$fc,$00,$fc,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $3e '>'
+ $00,$00,$00,$40,$20,$10,$08,$04,$08,$10,$20,$40,$00,$00,$00,
+
+ 7, // $3f '?'
+ $00,$00,$78,$84,$84,$84,$08,$10,$20,$20,$00,$20,$00,$00,$00,
+
+ 7, // $40 '@'
+ $00,$00,$00,$30,$48,$04,$34,$54,$54,$54,$54,$28,$00,$00,$00,
+
+ 7, // $41 'A'
+ $00,$00,$10,$28,$44,$44,$44,$7c,$44,$44,$44,$44,$00,$00,$00,
+
+ 7, // $42 'B'
+ $00,$00,$78,$44,$44,$44,$78,$44,$44,$44,$44,$78,$00,$00,$00,
+
+ 7, // $43 'C'
+ $00,$00,$38,$44,$44,$40,$40,$40,$40,$44,$44,$38,$00,$00,$00,
+
+ 7, // $44 'D'
+ $00,$00,$70,$48,$44,$44,$44,$44,$44,$44,$48,$70,$00,$00,$00,
+
+ 7, // $45 'E'
+ $00,$00,$7c,$40,$40,$40,$70,$40,$40,$40,$40,$7c,$00,$00,$00,
+
+ 7, // $46 'F'
+ $00,$00,$7c,$40,$40,$40,$70,$40,$40,$40,$40,$40,$00,$00,$00,
+
+ 7, // $47 'G'
+ $00,$00,$38,$44,$40,$40,$40,$5c,$44,$44,$44,$38,$00,$00,$00,
+
+ 7, // $48 'H'
+ $00,$00,$44,$44,$44,$44,$7c,$44,$44,$44,$44,$44,$00,$00,$00,
+
+ 7, // $49 'I'
+ $00,$00,$38,$10,$10,$10,$10,$10,$10,$10,$10,$38,$00,$00,$00,
+
+ 7, // $4a 'J'
+ $00,$00,$1c,$08,$08,$08,$08,$08,$08,$48,$48,$30,$00,$00,$00,
+
+ 7, // $4b 'K'
+ $00,$00,$44,$44,$48,$50,$60,$50,$48,$44,$44,$44,$00,$00,$00,
+
+ 7, // $4c 'L'
+ $00,$00,$40,$40,$40,$40,$40,$40,$40,$40,$40,$7c,$00,$00,$00,
+
+ 7, // $4d 'M'
+ $00,$00,$44,$6c,$54,$54,$44,$44,$44,$44,$44,$44,$00,$00,$00,
+
+ 7, // $4e 'N'
+ $00,$00,$44,$44,$44,$64,$54,$4c,$44,$44,$44,$44,$00,$00,$00,
+
+ 7, // $4f 'O'
+ $00,$00,$38,$44,$44,$44,$44,$44,$44,$44,$44,$38,$00,$00,$00,
+
+ 7, // $50 'P'
+ $00,$00,$78,$44,$44,$44,$44,$78,$40,$40,$40,$40,$00,$00,$00,
+
+ 7, // $51 'Q'
+ $00,$00,$38,$44,$44,$44,$44,$44,$44,$54,$48,$34,$00,$00,$00,
+
+ 7, // $52 'R'
+ $00,$00,$78,$44,$44,$44,$44,$78,$50,$48,$44,$44,$00,$00,$00,
+
+ 7, // $53 'S'
+ $00,$00,$38,$44,$44,$40,$38,$04,$04,$44,$44,$38,$00,$00,$00,
+
+ 7, // $54 'T'
+ $00,$00,$7c,$54,$10,$10,$10,$10,$10,$10,$10,$10,$00,$00,$00,
+
+ 7, // $55 'U'
+ $00,$00,$44,$44,$44,$44,$44,$44,$44,$44,$44,$38,$00,$00,$00,
+
+ 7, // $56 'V'
+ $00,$00,$44,$44,$44,$44,$44,$44,$28,$28,$10,$10,$00,$00,$00,
+
+ 7, // $57 'W'
+ $00,$00,$44,$44,$44,$44,$44,$44,$54,$54,$6c,$44,$00,$00,$00,
+
+ 7, // $58 'X'
+ $00,$00,$44,$44,$44,$28,$10,$28,$44,$44,$44,$44,$00,$00,$00,
+
+ 7, // $59 'Y'
+ $00,$00,$44,$44,$44,$44,$28,$10,$10,$10,$10,$38,$00,$00,$00,
+
+ 7, // $5a 'Z'
+ $00,$00,$7c,$04,$04,$08,$10,$20,$40,$40,$40,$7c,$00,$00,$00,
+
+ 7, // $5b '['
+ $00,$38,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$38,$00,$00,
+
+ 7, // $5c '\'
+ $00,$00,$40,$40,$20,$20,$10,$10,$08,$08,$04,$04,$00,$00,$00,
+
+ 7, // $5d ']'
+ $00,$38,$08,$08,$08,$08,$08,$08,$08,$08,$08,$08,$38,$00,$00,
+
+ 7, // $5e '^'
+ $00,$10,$28,$44,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $5f '_'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$fc,$00,$00,$00,
+
+ 7, // $60 '`'
+ $00,$20,$20,$20,$10,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $61 'a'
+ $00,$00,$00,$00,$38,$44,$04,$3c,$44,$44,$44,$3a,$00,$00,$00,
+
+ 7, // $62 'b'
+ $00,$00,$40,$40,$40,$78,$44,$44,$44,$44,$44,$78,$00,$00,$00,
+
+ 7, // $63 'c'
+ $00,$00,$00,$00,$38,$44,$40,$40,$40,$40,$44,$38,$00,$00,$00,
+
+ 7, // $64 'd'
+ $00,$00,$04,$04,$04,$3c,$44,$44,$44,$44,$44,$3a,$00,$00,$00,
+
+ 7, // $65 'e'
+ $00,$00,$00,$00,$38,$44,$44,$7c,$40,$40,$44,$38,$00,$00,$00,
+
+ 7, // $66 'f'
+ $00,$00,$18,$24,$20,$70,$20,$20,$20,$20,$20,$70,$00,$00,$00,
+
+ 7, // $67 'g'
+ $00,$00,$00,$00,$3a,$44,$44,$44,$44,$44,$3c,$04,$44,$38,$00,
+
+ 7, // $68 'h'
+ $00,$00,$40,$40,$40,$58,$64,$44,$44,$44,$44,$44,$00,$00,$00,
+
+ 7, // $69 'i'
+ $00,$00,$10,$10,$00,$30,$10,$10,$10,$10,$10,$38,$00,$00,$00,
+
+ 7, // $6a 'j'
+ $00,$00,$08,$08,$00,$18,$08,$08,$08,$08,$08,$48,$48,$30,$00,
+
+ 7, // $6b 'k'
+ $00,$00,$40,$40,$44,$44,$48,$50,$60,$50,$48,$44,$00,$00,$00,
+
+ 7, // $6c 'l'
+ $00,$00,$30,$10,$10,$10,$10,$10,$10,$10,$10,$38,$00,$00,$00,
+
+ 7, // $6d 'm'
+ $00,$00,$00,$00,$a8,$54,$54,$54,$54,$54,$54,$54,$00,$00,$00,
+
+ 7, // $6e 'n'
+ $00,$00,$00,$00,$b8,$44,$44,$44,$44,$44,$44,$44,$00,$00,$00,
+
+ 7, // $6f 'o'
+ $00,$00,$00,$00,$38,$44,$44,$44,$44,$44,$44,$38,$00,$00,$00,
+
+ 7, // $70 'p'
+ $00,$00,$00,$00,$78,$44,$44,$44,$44,$44,$78,$40,$40,$40,$00,
+
+ 7, // $71 'q'
+ $00,$00,$00,$00,$3c,$44,$44,$44,$44,$44,$3c,$04,$04,$04,$00,
+
+ 7, // $72 'r'
+ $00,$00,$00,$00,$58,$64,$44,$40,$40,$40,$40,$40,$00,$00,$00,
+
+ 7, // $73 's'
+ $00,$00,$00,$00,$38,$44,$40,$38,$04,$44,$44,$38,$00,$00,$00,
+
+ 7, // $74 't'
+ $00,$00,$20,$20,$20,$70,$20,$20,$20,$20,$24,$18,$00,$00,$00,
+
+ 7, // $75 'u'
+ $00,$00,$00,$00,$44,$44,$44,$44,$44,$44,$44,$3a,$00,$00,$00,
+
+ 7, // $76 'v'
+ $00,$00,$00,$00,$44,$44,$44,$44,$28,$28,$10,$10,$00,$00,$00,
+
+ 7, // $77 'w'
+ $00,$00,$00,$00,$44,$44,$44,$44,$54,$54,$6c,$44,$00,$00,$00,
+
+ 7, // $78 'x'
+ $00,$00,$00,$00,$44,$44,$28,$10,$28,$44,$44,$44,$00,$00,$00,
+
+ 7, // $79 'y'
+ $00,$00,$00,$00,$44,$44,$44,$44,$44,$44,$3c,$04,$08,$70,$00,
+
+ 7, // $7a 'z'
+ $00,$00,$00,$00,$7c,$04,$08,$10,$20,$40,$40,$7c,$00,$00,$00,
+
+ 7, // $7b '{'
+ $00,$0c,$10,$10,$10,$10,$10,$60,$10,$10,$10,$10,$0c,$00,$00,
+
+ 7, // $7c '|'
+ $00,$20,$20,$20,$20,$20,$00,$00,$20,$20,$20,$20,$20,$00,$00,
+
+ 7, // $7d '}'
+ $00,$60,$10,$10,$10,$10,$10,$0c,$10,$10,$10,$10,$60,$00,$00,
+
+ 7, // $7e '~'
+ $00,$00,$64,$98,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $7f ''
+ $00,$00,$00,$00,$00,$10,$28,$44,$44,$7c,$00,$00,$00,$00,$00,
+ 0 );
+
+ gse7x15_bold : array[0..1732 ] of int8u = (
+ 15, 0, 32, 128-32,
+
+ $00,$00,$10,$00,$20,$00,$30,$00,$40,$00,$50,$00,$60,$00,$70,$00,$80,$00,
+ $90,$00,$a0,$00,$b0,$00,$c0,$00,$d0,$00,$e0,$00,$f0,$00,$00,$01,$10,$01,
+ $20,$01,$30,$01,$40,$01,$50,$01,$60,$01,$70,$01,$80,$01,$90,$01,$a0,$01,
+ $b0,$01,$c0,$01,$d0,$01,$e0,$01,$f0,$01,$00,$02,$10,$02,$20,$02,$30,$02,
+ $40,$02,$50,$02,$60,$02,$70,$02,$80,$02,$90,$02,$a0,$02,$b0,$02,$c0,$02,
+ $d0,$02,$e0,$02,$f0,$02,$00,$03,$10,$03,$20,$03,$30,$03,$40,$03,$50,$03,
+ $60,$03,$70,$03,$80,$03,$90,$03,$a0,$03,$b0,$03,$c0,$03,$d0,$03,$e0,$03,
+ $f0,$03,$00,$04,$10,$04,$20,$04,$30,$04,$40,$04,$50,$04,$60,$04,$70,$04,
+ $80,$04,$90,$04,$a0,$04,$b0,$04,$c0,$04,$d0,$04,$e0,$04,$f0,$04,$00,$05,
+ $10,$05,$20,$05,$30,$05,$40,$05,$50,$05,$60,$05,$70,$05,$80,$05,$90,$05,
+ $a0,$05,$b0,$05,$c0,$05,$d0,$05,$e0,$05,$f0,$05,
+
+ 7, // $20 ' '
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $21 '!'
+ $00,$00,$00,$30,$78,$78,$78,$30,$30,$00,$30,$30,$00,$00,$00,
+
+ 7, // $22 '"'
+ $00,$00,$6c,$6c,$6c,$28,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $23 '#'
+ $00,$00,$48,$48,$48,$fc,$48,$48,$fc,$48,$48,$48,$00,$00,$00,
+
+ 7, // $24 '$'
+ $00,$30,$30,$78,$cc,$e0,$70,$38,$1c,$cc,$78,$30,$30,$00,$00,
+
+ 7, // $25 '%'
+ $00,$00,$00,$64,$6c,$08,$18,$10,$30,$20,$6c,$4c,$00,$00,$00,
+
+ 7, // $26 '&'
+ $00,$00,$00,$30,$58,$58,$30,$74,$dc,$d8,$d8,$6c,$00,$00,$00,
+
+ 7, // $27 '''
+ $00,$00,$30,$30,$30,$60,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $28 '('
+ $00,$0c,$18,$30,$60,$60,$60,$60,$60,$30,$18,$0c,$00,$00,$00,
+
+ 7, // $29 ')'
+ $00,$c0,$60,$30,$18,$18,$18,$18,$18,$30,$60,$c0,$00,$00,$00,
+
+ 7, // $2a '*'
+ $00,$00,$00,$00,$00,$20,$a8,$70,$a8,$20,$00,$00,$00,$00,$00,
+
+ 7, // $2b '+'
+ $00,$00,$00,$00,$00,$30,$30,$fc,$30,$30,$00,$00,$00,$00,$00,
+
+ 7, // $2c ','
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$30,$30,$30,$60,$00,
+
+ 7, // $2d '-'
+ $00,$00,$00,$00,$00,$00,$00,$fc,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $2e '.'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$30,$30,$00,$00,$00,
+
+ 7, // $2f '/'
+ $00,$00,$0c,$0c,$18,$18,$30,$30,$60,$60,$c0,$c0,$00,$00,$00,
+
+ 7, // $30 '0'
+ $00,$00,$78,$cc,$cc,$cc,$dc,$ec,$cc,$cc,$cc,$78,$00,$00,$00,
+
+ 7, // $31 '1'
+ $00,$00,$30,$30,$70,$f0,$30,$30,$30,$30,$30,$fc,$00,$00,$00,
+
+ 7, // $32 '2'
+ $00,$00,$78,$cc,$cc,$0c,$18,$30,$60,$c0,$cc,$fc,$00,$00,$00,
+
+ 7, // $33 '3'
+ $00,$00,$fc,$8c,$18,$30,$78,$0c,$0c,$0c,$cc,$78,$00,$00,$00,
+
+ 7, // $34 '4'
+ $00,$00,$18,$30,$60,$c8,$d8,$d8,$fc,$18,$18,$3c,$00,$00,$00,
+
+ 7, // $35 '5'
+ $00,$00,$fc,$c0,$c0,$c0,$f8,$0c,$0c,$0c,$cc,$78,$00,$00,$00,
+
+ 7, // $36 '6'
+ $00,$00,$38,$60,$c0,$c0,$f8,$cc,$cc,$cc,$cc,$78,$00,$00,$00,
+
+ 7, // $37 '7'
+ $00,$00,$fc,$8c,$0c,$0c,$18,$18,$30,$30,$30,$30,$00,$00,$00,
+
+ 7, // $38 '8'
+ $00,$00,$78,$cc,$cc,$cc,$78,$cc,$cc,$cc,$cc,$78,$00,$00,$00,
+
+ 7, // $39 '9'
+ $00,$00,$78,$cc,$cc,$cc,$cc,$7c,$0c,$0c,$18,$70,$00,$00,$00,
+
+ 7, // $3a ':'
+ $00,$00,$00,$00,$30,$30,$00,$00,$00,$30,$30,$00,$00,$00,$00,
+
+ 7, // $3b ';'
+ $00,$00,$00,$00,$30,$30,$00,$00,$00,$00,$30,$30,$30,$60,$00,
+
+ 7, // $3c '<'
+ $00,$00,$00,$0c,$18,$30,$60,$c0,$60,$30,$18,$0c,$00,$00,$00,
+
+ 7, // $3d '='
+ $00,$00,$00,$00,$00,$00,$fc,$00,$fc,$00,$00,$00,$00,$00,$00,
+
+ 7, // $3e '>'
+ $00,$00,$00,$c0,$60,$30,$18,$0c,$18,$30,$60,$c0,$00,$00,$00,
+
+ 7, // $3f '?'
+ $00,$00,$78,$cc,$cc,$18,$30,$30,$30,$00,$30,$30,$00,$00,$00,
+
+ 7, // $40 '@'
+ $00,$00,$00,$70,$88,$04,$74,$b4,$b4,$b4,$b4,$68,$00,$00,$00,
+
+ 7, // $41 'A'
+ $00,$00,$30,$78,$cc,$cc,$cc,$fc,$cc,$cc,$cc,$cc,$00,$00,$00,
+
+ 7, // $42 'B'
+ $00,$00,$f8,$cc,$cc,$cc,$f8,$cc,$cc,$cc,$cc,$f8,$00,$00,$00,
+
+ 7, // $43 'C'
+ $00,$00,$78,$cc,$c4,$c0,$c0,$c0,$c0,$c4,$cc,$78,$00,$00,$00,
+
+ 7, // $44 'D'
+ $00,$00,$f0,$d8,$cc,$cc,$cc,$cc,$cc,$cc,$d8,$f0,$00,$00,$00,
+
+ 7, // $45 'E'
+ $00,$00,$fc,$c4,$c0,$d0,$f0,$d0,$c0,$c0,$c4,$fc,$00,$00,$00,
+
+ 7, // $46 'F'
+ $00,$00,$fc,$c4,$c0,$d0,$f0,$d0,$c0,$c0,$c0,$c0,$00,$00,$00,
+
+ 7, // $47 'G'
+ $00,$00,$78,$cc,$c0,$c0,$c0,$dc,$cc,$cc,$cc,$78,$00,$00,$00,
+
+ 7, // $48 'H'
+ $00,$00,$cc,$cc,$cc,$cc,$fc,$cc,$cc,$cc,$cc,$cc,$00,$00,$00,
+
+ 7, // $49 'I'
+ $00,$00,$78,$30,$30,$30,$30,$30,$30,$30,$30,$78,$00,$00,$00,
+
+ 7, // $4a 'J'
+ $00,$00,$3c,$18,$18,$18,$18,$18,$18,$d8,$d8,$70,$00,$00,$00,
+
+ 7, // $4b 'K'
+ $00,$00,$cc,$cc,$d8,$d8,$f0,$d8,$d8,$cc,$cc,$cc,$00,$00,$00,
+
+ 7, // $4c 'L'
+ $00,$00,$c0,$c0,$c0,$c0,$c0,$c0,$c0,$c0,$c4,$fc,$00,$00,$00,
+
+ 7, // $4d 'M'
+ $00,$00,$84,$cc,$fc,$b4,$cc,$cc,$cc,$cc,$cc,$cc,$00,$00,$00,
+
+ 7, // $4e 'N'
+ $00,$00,$cc,$cc,$cc,$ec,$fc,$dc,$cc,$cc,$cc,$cc,$00,$00,$00,
+
+ 7, // $4f 'O'
+ $00,$00,$78,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$78,$00,$00,$00,
+
+ 7, // $50 'P'
+ $00,$00,$f8,$cc,$cc,$cc,$cc,$f8,$c0,$c0,$c0,$c0,$00,$00,$00,
+
+ 7, // $51 'Q'
+ $00,$00,$78,$cc,$cc,$cc,$cc,$cc,$cc,$dc,$78,$18,$0c,$00,$00,
+
+ 7, // $52 'R'
+ $00,$00,$f8,$cc,$cc,$cc,$cc,$f8,$d8,$cc,$cc,$cc,$00,$00,$00,
+
+ 7, // $53 'S'
+ $00,$00,$78,$cc,$cc,$e0,$70,$38,$1c,$cc,$cc,$78,$00,$00,$00,
+
+ 7, // $54 'T'
+ $00,$00,$fc,$b4,$30,$30,$30,$30,$30,$30,$30,$30,$00,$00,$00,
+
+ 7, // $55 'U'
+ $00,$00,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$78,$00,$00,$00,
+
+ 7, // $56 'V'
+ $00,$00,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$78,$30,$00,$00,$00,
+
+ 7, // $57 'W'
+ $00,$00,$cc,$cc,$cc,$cc,$cc,$cc,$b4,$fc,$cc,$84,$00,$00,$00,
+
+ 7, // $58 'X'
+ $00,$00,$cc,$cc,$cc,$78,$30,$78,$cc,$cc,$cc,$cc,$00,$00,$00,
+
+ 7, // $59 'Y'
+ $00,$00,$cc,$cc,$cc,$cc,$78,$30,$30,$30,$30,$78,$00,$00,$00,
+
+ 7, // $5a 'Z'
+ $00,$00,$fc,$8c,$0c,$18,$30,$60,$c0,$c0,$c4,$fc,$00,$00,$00,
+
+ 7, // $5b '['
+ $00,$78,$60,$60,$60,$60,$60,$60,$60,$60,$60,$60,$78,$00,$00,
+
+ 7, // $5c '\'
+ $00,$00,$c0,$c0,$60,$60,$30,$30,$18,$18,$0c,$0c,$00,$00,$00,
+
+ 7, // $5d ']'
+ $00,$78,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$78,$00,$00,
+
+ 7, // $5e '^'
+ $00,$10,$38,$6c,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $5f '_'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$fc,$00,$00,$00,
+
+ 7, // $60 '`'
+ $00,$30,$30,$30,$18,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $61 'a'
+ $00,$00,$00,$00,$70,$d8,$18,$78,$d8,$d8,$d8,$6c,$00,$00,$00,
+
+ 7, // $62 'b'
+ $00,$00,$60,$60,$60,$78,$6c,$6c,$6c,$6c,$6c,$78,$00,$00,$00,
+
+ 7, // $63 'c'
+ $00,$00,$00,$00,$78,$cc,$c0,$c0,$c0,$c0,$cc,$78,$00,$00,$00,
+
+ 7, // $64 'd'
+ $00,$00,$18,$18,$18,$78,$d8,$d8,$d8,$d8,$d8,$6c,$00,$00,$00,
+
+ 7, // $65 'e'
+ $00,$00,$00,$00,$78,$cc,$cc,$fc,$c0,$c0,$cc,$78,$00,$00,$00,
+
+ 7, // $66 'f'
+ $00,$00,$30,$68,$60,$60,$f0,$60,$60,$60,$60,$f0,$00,$00,$00,
+
+ 7, // $67 'g'
+ $00,$00,$00,$00,$6c,$d8,$d8,$d8,$d8,$d8,$78,$18,$d8,$70,$00,
+
+ 7, // $68 'h'
+ $00,$00,$c0,$c0,$c0,$d8,$ec,$cc,$cc,$cc,$cc,$cc,$00,$00,$00,
+
+ 7, // $69 'i'
+ $00,$00,$30,$30,$00,$70,$30,$30,$30,$30,$30,$78,$00,$00,$00,
+
+ 7, // $6a 'j'
+ $00,$00,$18,$18,$00,$38,$18,$18,$18,$18,$18,$d8,$d8,$70,$00,
+
+ 7, // $6b 'k'
+ $00,$00,$c0,$c0,$cc,$cc,$cc,$d8,$f0,$d8,$cc,$cc,$00,$00,$00,
+
+ 7, // $6c 'l'
+ $00,$00,$70,$30,$30,$30,$30,$30,$30,$30,$30,$78,$00,$00,$00,
+
+ 7, // $6d 'm'
+ $00,$00,$00,$00,$e8,$fc,$d4,$d4,$d4,$c4,$c4,$c4,$00,$00,$00,
+
+ 7, // $6e 'n'
+ $00,$00,$00,$00,$d8,$6c,$6c,$6c,$6c,$6c,$6c,$6c,$00,$00,$00,
+
+ 7, // $6f 'o'
+ $00,$00,$00,$00,$78,$cc,$cc,$cc,$cc,$cc,$cc,$78,$00,$00,$00,
+
+ 7, // $70 'p'
+ $00,$00,$00,$00,$f8,$cc,$cc,$cc,$cc,$cc,$f8,$c0,$c0,$c0,$00,
+
+ 7, // $71 'q'
+ $00,$00,$00,$00,$7c,$cc,$cc,$cc,$cc,$cc,$7c,$0c,$0c,$0c,$00,
+
+ 7, // $72 'r'
+ $00,$00,$00,$00,$d8,$ec,$cc,$c0,$c0,$c0,$c0,$c0,$00,$00,$00,
+
+ 7, // $73 's'
+ $00,$00,$00,$00,$78,$cc,$e0,$70,$38,$1c,$cc,$78,$00,$00,$00,
+
+ 7, // $74 't'
+ $00,$00,$20,$60,$60,$f0,$60,$60,$60,$60,$6c,$38,$00,$00,$00,
+
+ 7, // $75 'u'
+ $00,$00,$00,$00,$d8,$d8,$d8,$d8,$d8,$d8,$d8,$6c,$00,$00,$00,
+
+ 7, // $76 'v'
+ $00,$00,$00,$00,$cc,$cc,$cc,$cc,$cc,$cc,$78,$30,$00,$00,$00,
+
+ 7, // $77 'w'
+ $00,$00,$00,$00,$cc,$cc,$cc,$cc,$b4,$fc,$cc,$84,$00,$00,$00,
+
+ 7, // $78 'x'
+ $00,$00,$00,$00,$cc,$cc,$78,$30,$78,$cc,$cc,$cc,$00,$00,$00,
+
+ 7, // $79 'y'
+ $00,$00,$00,$00,$cc,$cc,$cc,$cc,$cc,$cc,$7c,$0c,$18,$f0,$00,
+
+ 7, // $7a 'z'
+ $00,$00,$00,$00,$fc,$8c,$18,$30,$60,$c0,$c4,$fc,$00,$00,$00,
+
+ 7, // $7b '{'
+ $00,$1c,$30,$30,$30,$30,$30,$e0,$30,$30,$30,$30,$1c,$00,$00,
+
+ 7, // $7c '|'
+ $00,$30,$30,$30,$30,$30,$00,$00,$30,$30,$30,$30,$30,$00,$00,
+
+ 7, // $7d '}'
+ $00,$e0,$30,$30,$30,$30,$30,$1c,$30,$30,$30,$30,$e0,$00,$00,
+
+ 7, // $7e '~'
+ $00,$00,$34,$58,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $7f ''
+ $00,$00,$00,$00,$00,$30,$78,$cc,$cc,$fc,$00,$00,$00,$00,$00,
+ 0 );
+
+ gse8x16 : array[0..1828 ] of int8u = (
+ 16, 0, 32, 128-32,
+
+ $00,$00,$11,$00,$22,$00,$33,$00,$44,$00,$55,$00,$66,$00,$77,$00,$88,$00,
+ $99,$00,$aa,$00,$bb,$00,$cc,$00,$dd,$00,$ee,$00,$ff,$00,$10,$01,$21,$01,
+ $32,$01,$43,$01,$54,$01,$65,$01,$76,$01,$87,$01,$98,$01,$a9,$01,$ba,$01,
+ $cb,$01,$dc,$01,$ed,$01,$fe,$01,$0f,$02,$20,$02,$31,$02,$42,$02,$53,$02,
+ $64,$02,$75,$02,$86,$02,$97,$02,$a8,$02,$b9,$02,$ca,$02,$db,$02,$ec,$02,
+ $fd,$02,$0e,$03,$1f,$03,$30,$03,$41,$03,$52,$03,$63,$03,$74,$03,$85,$03,
+ $96,$03,$a7,$03,$b8,$03,$c9,$03,$da,$03,$eb,$03,$fc,$03,$0d,$04,$1e,$04,
+ $2f,$04,$40,$04,$51,$04,$62,$04,$73,$04,$84,$04,$95,$04,$a6,$04,$b7,$04,
+ $c8,$04,$d9,$04,$ea,$04,$fb,$04,$0c,$05,$1d,$05,$2e,$05,$3f,$05,$50,$05,
+ $61,$05,$72,$05,$83,$05,$94,$05,$a5,$05,$b6,$05,$c7,$05,$d8,$05,$e9,$05,
+ $fa,$05,$0b,$06,$1c,$06,$2d,$06,$3e,$06,$4f,$06,
+
+ 8, // $20 ' '
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 8, // $21 '!'
+ $00,$00,$10,$38,$38,$38,$38,$10,$10,$00,$10,$10,$00,$00,$00,$00,
+
+ 8, // $22 '"'
+ $00,$24,$24,$24,$24,$48,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 8, // $23 '#'
+ $00,$00,$24,$24,$24,$7e,$24,$24,$7e,$24,$24,$24,$00,$00,$00,$00,
+
+ 8, // $24 '$'
+ $00,$14,$14,$3e,$55,$54,$54,$3e,$15,$15,$55,$3e,$14,$14,$00,$00,
+
+ 8, // $25 '%'
+ $00,$00,$32,$56,$6c,$04,$08,$08,$10,$13,$25,$26,$00,$00,$00,$00,
+
+ 8, // $26 '&'
+ $00,$00,$18,$24,$24,$24,$18,$28,$45,$46,$44,$3b,$00,$00,$00,$00,
+
+ 8, // $27 '''
+ $00,$00,$08,$08,$08,$10,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 8, // $28 '('
+ $00,$04,$08,$10,$10,$20,$20,$20,$20,$10,$10,$08,$04,$00,$00,$00,
+
+ 8, // $29 ')'
+ $00,$10,$08,$04,$04,$02,$02,$02,$02,$04,$04,$08,$10,$00,$00,$00,
+
+ 8, // $2a '*'
+ $00,$00,$00,$00,$66,$24,$18,$ff,$18,$24,$66,$00,$00,$00,$00,$00,
+
+ 8, // $2b '+'
+ $00,$00,$00,$00,$08,$08,$08,$7f,$08,$08,$08,$00,$00,$00,$00,$00,
+
+ 8, // $2c ','
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$18,$18,$18,$30,$20,$00,
+
+ 8, // $2d '-'
+ $00,$00,$00,$00,$00,$00,$00,$7f,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 8, // $2e '.'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$18,$18,$00,$00,$00,$00,
+
+ 8, // $2f '/'
+ $00,$02,$02,$04,$04,$08,$08,$10,$10,$20,$20,$40,$40,$00,$00,$00,
+
+ 8, // $30 '0'
+ $00,$00,$3c,$42,$42,$46,$4a,$52,$62,$42,$42,$3c,$00,$00,$00,$00,
+
+ 8, // $31 '1'
+ $00,$00,$08,$08,$18,$38,$08,$08,$08,$08,$08,$3e,$00,$00,$00,$00,
+
+ 8, // $32 '2'
+ $00,$00,$3c,$42,$42,$02,$04,$08,$10,$20,$42,$7e,$00,$00,$00,$00,
+
+ 8, // $33 '3'
+ $00,$00,$7e,$42,$04,$08,$1c,$02,$02,$02,$42,$3c,$00,$00,$00,$00,
+
+ 8, // $34 '4'
+ $00,$00,$04,$08,$10,$24,$44,$44,$7e,$04,$04,$0e,$00,$00,$00,$00,
+
+ 8, // $35 '5'
+ $00,$00,$7e,$42,$40,$40,$7c,$02,$02,$02,$42,$3c,$00,$00,$00,$00,
+
+ 8, // $36 '6'
+ $00,$00,$1c,$20,$40,$40,$7c,$42,$42,$42,$42,$3c,$00,$00,$00,$00,
+
+ 8, // $37 '7'
+ $00,$00,$7e,$42,$42,$02,$04,$08,$10,$10,$10,$10,$00,$00,$00,$00,
+
+ 8, // $38 '8'
+ $00,$00,$3c,$42,$42,$42,$3c,$42,$42,$42,$42,$3c,$00,$00,$00,$00,
+
+ 8, // $39 '9'
+ $00,$00,$3c,$42,$42,$42,$42,$3e,$02,$02,$04,$38,$00,$00,$00,$00,
+
+ 8, // $3a ':'
+ $00,$00,$00,$00,$18,$00,$00,$00,$00,$18,$00,$00,$00,$00,$00,$00,
+
+ 8, // $3b ';'
+ $00,$00,$00,$00,$30,$00,$00,$00,$00,$00,$30,$30,$30,$60,$40,$00,
+
+ 8, // $3c '<'
+ $00,$00,$00,$02,$04,$08,$10,$20,$10,$08,$04,$02,$00,$00,$00,$00,
+
+ 8, // $3d '='
+ $00,$00,$00,$00,$00,$00,$7f,$00,$7f,$00,$00,$00,$00,$00,$00,$00,
+
+ 8, // $3e '>'
+ $00,$00,$00,$20,$10,$08,$04,$02,$04,$08,$10,$20,$00,$00,$00,$00,
+
+ 8, // $3f '?'
+ $00,$00,$3c,$42,$42,$42,$04,$08,$08,$00,$08,$08,$00,$00,$00,$00,
+
+ 8, // $40 '@'
+ $00,$00,$3c,$42,$01,$39,$49,$49,$49,$49,$49,$36,$00,$00,$00,$00,
+
+ 8, // $41 'A'
+ $00,$00,$18,$24,$42,$42,$42,$7e,$42,$42,$42,$42,$00,$00,$00,$00,
+
+ 8, // $42 'B'
+ $00,$00,$7c,$22,$22,$22,$3c,$22,$22,$22,$22,$7c,$00,$00,$00,$00,
+
+ 8, // $43 'C'
+ $00,$00,$3c,$42,$42,$40,$40,$40,$40,$42,$42,$3c,$00,$00,$00,$00,
+
+ 8, // $44 'D'
+ $00,$00,$7c,$22,$22,$22,$22,$22,$22,$22,$22,$7c,$00,$00,$00,$00,
+
+ 8, // $45 'E'
+ $00,$00,$7e,$22,$20,$28,$38,$28,$20,$20,$22,$7e,$00,$00,$00,$00,
+
+ 8, // $46 'F'
+ $00,$00,$7e,$22,$20,$28,$38,$28,$20,$20,$20,$70,$00,$00,$00,$00,
+
+ 8, // $47 'G'
+ $00,$00,$3c,$42,$42,$40,$40,$4e,$42,$42,$42,$3c,$00,$00,$00,$00,
+
+ 8, // $48 'H'
+ $00,$00,$42,$42,$42,$42,$7e,$42,$42,$42,$42,$42,$00,$00,$00,$00,
+
+ 8, // $49 'I'
+ $00,$00,$1c,$08,$08,$08,$08,$08,$08,$08,$08,$1c,$00,$00,$00,$00,
+
+ 8, // $4a 'J'
+ $00,$00,$0e,$04,$04,$04,$04,$04,$04,$44,$44,$38,$00,$00,$00,$00,
+
+ 8, // $4b 'K'
+ $00,$00,$62,$22,$24,$28,$30,$28,$24,$22,$22,$62,$00,$00,$00,$00,
+
+ 8, // $4c 'L'
+ $00,$00,$70,$20,$20,$20,$20,$20,$20,$20,$22,$7e,$00,$00,$00,$00,
+
+ 8, // $4d 'M'
+ $00,$00,$41,$63,$55,$49,$41,$41,$41,$41,$41,$41,$00,$00,$00,$00,
+
+ 8, // $4e 'N'
+ $00,$00,$42,$42,$62,$52,$4a,$46,$42,$42,$42,$42,$00,$00,$00,$00,
+
+ 8, // $4f 'O'
+ $00,$00,$3c,$42,$42,$42,$42,$42,$42,$42,$42,$3c,$00,$00,$00,$00,
+
+ 8, // $50 'P'
+ $00,$00,$7c,$22,$22,$22,$22,$3c,$20,$20,$20,$70,$00,$00,$00,$00,
+
+ 8, // $51 'Q'
+ $00,$00,$3c,$42,$42,$42,$42,$42,$42,$4a,$44,$3a,$02,$00,$00,$00,
+
+ 8, // $52 'R'
+ $00,$00,$7c,$22,$22,$22,$22,$3c,$28,$24,$22,$62,$00,$00,$00,$00,
+
+ 8, // $53 'S'
+ $00,$00,$3c,$42,$42,$40,$30,$0c,$02,$42,$42,$3c,$00,$00,$00,$00,
+
+ 8, // $54 'T'
+ $00,$00,$7f,$49,$08,$08,$08,$08,$08,$08,$08,$1c,$00,$00,$00,$00,
+
+ 8, // $55 'U'
+ $00,$00,$42,$42,$42,$42,$42,$42,$42,$42,$42,$3c,$00,$00,$00,$00,
+
+ 8, // $56 'V'
+ $00,$00,$41,$41,$41,$41,$22,$22,$14,$14,$08,$08,$00,$00,$00,$00,
+
+ 8, // $57 'W'
+ $00,$00,$41,$41,$41,$41,$41,$49,$49,$55,$63,$41,$00,$00,$00,$00,
+
+ 8, // $58 'X'
+ $00,$00,$42,$42,$42,$24,$18,$18,$24,$42,$42,$42,$00,$00,$00,$00,
+
+ 8, // $59 'Y'
+ $00,$00,$22,$22,$22,$22,$14,$08,$08,$08,$08,$1c,$00,$00,$00,$00,
+
+ 8, // $5a 'Z'
+ $00,$00,$7e,$42,$02,$04,$08,$10,$20,$40,$42,$7e,$00,$00,$00,$00,
+
+ 8, // $5b '['
+ $00,$1e,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$1e,$00,$00,$00,
+
+ 8, // $5c '\'
+ $00,$40,$40,$20,$20,$10,$10,$08,$08,$04,$04,$02,$02,$00,$00,$00,
+
+ 8, // $5d ']'
+ $00,$3c,$04,$04,$04,$04,$04,$04,$04,$04,$04,$04,$3c,$00,$00,$00,
+
+ 8, // $5e '^'
+ $00,$00,$08,$14,$22,$41,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 8, // $5f '_'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$ff,$00,$00,$00,$00,
+
+ 8, // $60 '`'
+ $00,$00,$08,$08,$08,$04,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 8, // $61 'a'
+ $00,$00,$00,$00,$00,$38,$44,$04,$3c,$44,$44,$3e,$00,$00,$00,$00,
+
+ 8, // $62 'b'
+ $00,$00,$60,$20,$20,$38,$24,$22,$22,$22,$22,$3c,$00,$00,$00,$00,
+
+ 8, // $63 'c'
+ $00,$00,$00,$00,$00,$3c,$42,$40,$40,$40,$42,$3c,$00,$00,$00,$00,
+
+ 8, // $64 'd'
+ $00,$00,$0c,$04,$04,$1c,$24,$44,$44,$44,$44,$3e,$00,$00,$00,$00,
+
+ 8, // $65 'e'
+ $00,$00,$00,$00,$00,$3c,$42,$42,$7e,$40,$42,$3c,$00,$00,$00,$00,
+
+ 8, // $66 'f'
+ $00,$00,$0c,$12,$10,$10,$38,$10,$10,$10,$10,$38,$00,$00,$00,$00,
+
+ 8, // $67 'g'
+ $00,$00,$00,$00,$00,$3e,$44,$44,$44,$44,$44,$3c,$04,$44,$38,$00,
+
+ 8, // $68 'h'
+ $00,$00,$60,$20,$20,$2c,$32,$22,$22,$22,$22,$62,$00,$00,$00,$00,
+
+ 8, // $69 'i'
+ $00,$00,$08,$08,$00,$18,$08,$08,$08,$08,$08,$1c,$00,$00,$00,$00,
+
+ 8, // $6a 'j'
+ $00,$00,$04,$04,$00,$0c,$04,$04,$04,$04,$04,$44,$44,$38,$00,$00,
+
+ 8, // $6b 'k'
+ $00,$00,$60,$20,$20,$22,$24,$28,$38,$24,$22,$62,$00,$00,$00,$00,
+
+ 8, // $6c 'l'
+ $00,$00,$18,$08,$08,$08,$08,$08,$08,$08,$08,$1c,$00,$00,$00,$00,
+
+ 8, // $6d 'm'
+ $00,$00,$00,$00,$00,$76,$49,$49,$49,$49,$41,$41,$00,$00,$00,$00,
+
+ 8, // $6e 'n'
+ $00,$00,$00,$00,$00,$5c,$22,$22,$22,$22,$22,$22,$00,$00,$00,$00,
+
+ 8, // $6f 'o'
+ $00,$00,$00,$00,$00,$3c,$42,$42,$42,$42,$42,$3c,$00,$00,$00,$00,
+
+ 8, // $70 'p'
+ $00,$00,$00,$00,$00,$7c,$22,$22,$22,$22,$22,$3c,$20,$20,$70,$00,
+
+ 8, // $71 'q'
+ $00,$00,$00,$00,$00,$3e,$44,$44,$44,$44,$44,$3c,$04,$04,$0e,$00,
+
+ 8, // $72 'r'
+ $00,$00,$00,$00,$00,$7c,$22,$22,$20,$20,$20,$70,$00,$00,$00,$00,
+
+ 8, // $73 's'
+ $00,$00,$00,$00,$00,$3c,$42,$40,$3c,$02,$42,$3c,$00,$00,$00,$00,
+
+ 8, // $74 't'
+ $00,$00,$10,$10,$10,$7c,$10,$10,$10,$10,$12,$0c,$00,$00,$00,$00,
+
+ 8, // $75 'u'
+ $00,$00,$00,$00,$00,$44,$44,$44,$44,$44,$44,$3e,$00,$00,$00,$00,
+
+ 8, // $76 'v'
+ $00,$00,$00,$00,$00,$41,$41,$41,$41,$22,$14,$08,$00,$00,$00,$00,
+
+ 8, // $77 'w'
+ $00,$00,$00,$00,$00,$41,$41,$41,$49,$49,$55,$22,$00,$00,$00,$00,
+
+ 8, // $78 'x'
+ $00,$00,$00,$00,$00,$42,$42,$24,$18,$24,$42,$42,$00,$00,$00,$00,
+
+ 8, // $79 'y'
+ $00,$00,$00,$00,$00,$42,$42,$42,$42,$42,$42,$3e,$02,$04,$78,$00,
+
+ 8, // $7a 'z'
+ $00,$00,$00,$00,$00,$7e,$44,$08,$10,$20,$42,$7e,$00,$00,$00,$00,
+
+ 8, // $7b '{'
+ $00,$06,$08,$08,$08,$08,$08,$30,$08,$08,$08,$08,$08,$06,$00,$00,
+
+ 8, // $7c '|'
+ $00,$00,$08,$08,$08,$08,$08,$00,$08,$08,$08,$08,$08,$00,$00,$00,
+
+ 8, // $7d '}'
+ $00,$30,$08,$08,$08,$08,$08,$06,$08,$08,$08,$08,$08,$30,$00,$00,
+
+ 8, // $7e '~'
+ $00,$00,$39,$4e,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 8, // $7f ''
+ $00,$00,$00,$00,$00,$08,$14,$22,$41,$41,$7f,$00,$00,$00,$00,$00,
+ 0 );
+
+ gse8x16_bold : array[0..1828 ] of int8u = (
+ 16, 0, 32, 128-32,
+
+ $00,$00,$11,$00,$22,$00,$33,$00,$44,$00,$55,$00,$66,$00,$77,$00,$88,$00,
+ $99,$00,$aa,$00,$bb,$00,$cc,$00,$dd,$00,$ee,$00,$ff,$00,$10,$01,$21,$01,
+ $32,$01,$43,$01,$54,$01,$65,$01,$76,$01,$87,$01,$98,$01,$a9,$01,$ba,$01,
+ $cb,$01,$dc,$01,$ed,$01,$fe,$01,$0f,$02,$20,$02,$31,$02,$42,$02,$53,$02,
+ $64,$02,$75,$02,$86,$02,$97,$02,$a8,$02,$b9,$02,$ca,$02,$db,$02,$ec,$02,
+ $fd,$02,$0e,$03,$1f,$03,$30,$03,$41,$03,$52,$03,$63,$03,$74,$03,$85,$03,
+ $96,$03,$a7,$03,$b8,$03,$c9,$03,$da,$03,$eb,$03,$fc,$03,$0d,$04,$1e,$04,
+ $2f,$04,$40,$04,$51,$04,$62,$04,$73,$04,$84,$04,$95,$04,$a6,$04,$b7,$04,
+ $c8,$04,$d9,$04,$ea,$04,$fb,$04,$0c,$05,$1d,$05,$2e,$05,$3f,$05,$50,$05,
+ $61,$05,$72,$05,$83,$05,$94,$05,$a5,$05,$b6,$05,$c7,$05,$d8,$05,$e9,$05,
+ $fa,$05,$0b,$06,$1c,$06,$2d,$06,$3e,$06,$4f,$06,
+
+ 8, // $20 ' '
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 8, // $21 '!'
+ $00,$00,$18,$3c,$3c,$3c,$3c,$18,$18,$00,$18,$18,$00,$00,$00,$00,
+
+ 8, // $22 '"'
+ $00,$66,$66,$66,$66,$24,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 8, // $23 '#'
+ $00,$00,$66,$66,$66,$ff,$66,$66,$ff,$66,$66,$66,$00,$00,$00,$00,
+
+ 8, // $24 '$'
+ $00,$08,$08,$3e,$6b,$6b,$68,$3e,$0b,$6b,$6b,$3e,$08,$08,$00,$00,
+
+ 8, // $25 '%'
+ $00,$00,$66,$be,$cc,$0c,$18,$18,$30,$33,$65,$66,$00,$00,$00,$00,
+
+ 8, // $26 '&'
+ $00,$00,$1c,$36,$36,$36,$1c,$3b,$6e,$66,$66,$3b,$00,$00,$00,$00,
+
+ 8, // $27 '''
+ $00,$00,$18,$18,$18,$30,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 8, // $28 '('
+ $00,$06,$0c,$18,$18,$30,$30,$30,$30,$18,$18,$0c,$06,$00,$00,$00,
+
+ 8, // $29 ')'
+ $00,$30,$18,$0c,$0c,$06,$06,$06,$06,$0c,$0c,$18,$30,$00,$00,$00,
+
+ 8, // $2a '*'
+ $00,$00,$00,$00,$66,$24,$18,$ff,$18,$24,$66,$00,$00,$00,$00,$00,
+
+ 8, // $2b '+'
+ $00,$00,$00,$00,$18,$18,$18,$ff,$18,$18,$18,$00,$00,$00,$00,$00,
+
+ 8, // $2c ','
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$18,$18,$18,$30,$20,$00,
+
+ 8, // $2d '-'
+ $00,$00,$00,$00,$00,$00,$00,$7f,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 8, // $2e '.'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$18,$18,$00,$00,$00,$00,
+
+ 8, // $2f '/'
+ $00,$03,$03,$06,$06,$0c,$0c,$18,$18,$30,$30,$60,$60,$00,$00,$00,
+
+ 8, // $30 '0'
+ $00,$00,$3e,$63,$63,$67,$6b,$73,$63,$63,$63,$3e,$00,$00,$00,$00,
+
+ 8, // $31 '1'
+ $00,$00,$0c,$0c,$1c,$3c,$0c,$0c,$0c,$0c,$0c,$3f,$00,$00,$00,$00,
+
+ 8, // $32 '2'
+ $00,$00,$3e,$63,$63,$03,$06,$0c,$18,$30,$61,$7f,$00,$00,$00,$00,
+
+ 8, // $33 '3'
+ $00,$00,$7f,$43,$06,$0c,$1e,$03,$03,$03,$63,$3e,$00,$00,$00,$00,
+
+ 8, // $34 '4'
+ $00,$00,$06,$0c,$18,$32,$66,$66,$7f,$06,$06,$0f,$00,$00,$00,$00,
+
+ 8, // $35 '5'
+ $00,$00,$7f,$61,$60,$60,$7e,$03,$03,$03,$63,$3e,$00,$00,$00,$00,
+
+ 8, // $36 '6'
+ $00,$00,$1e,$30,$60,$60,$7e,$63,$63,$63,$63,$3e,$00,$00,$00,$00,
+
+ 8, // $37 '7'
+ $00,$00,$7f,$63,$63,$03,$06,$0c,$18,$18,$18,$18,$00,$00,$00,$00,
+
+ 8, // $38 '8'
+ $00,$00,$3e,$63,$63,$63,$3e,$63,$63,$63,$63,$3e,$00,$00,$00,$00,
+
+ 8, // $39 '9'
+ $00,$00,$3e,$63,$63,$63,$63,$3f,$03,$03,$06,$3c,$00,$00,$00,$00,
+
+ 8, // $3a ':'
+ $00,$00,$00,$00,$18,$18,$00,$00,$00,$18,$18,$00,$00,$00,$00,$00,
+
+ 8, // $3b ';'
+ $00,$00,$00,$00,$30,$30,$00,$00,$00,$00,$30,$30,$30,$60,$40,$00,
+
+ 8, // $3c '<'
+ $00,$00,$00,$06,$0c,$18,$30,$60,$30,$18,$0c,$06,$00,$00,$00,$00,
+
+ 8, // $3d '='
+ $00,$00,$00,$00,$00,$00,$7f,$00,$7f,$00,$00,$00,$00,$00,$00,$00,
+
+ 8, // $3e '>'
+ $00,$00,$00,$30,$18,$0c,$06,$03,$06,$0c,$18,$30,$00,$00,$00,$00,
+
+ 8, // $3f '?'
+ $00,$00,$3e,$63,$63,$63,$06,$0c,$0c,$00,$0c,$0c,$00,$00,$00,$00,
+
+ 8, // $40 '@'
+ $00,$00,$7c,$86,$03,$73,$db,$db,$db,$db,$db,$6e,$00,$00,$00,$00,
+
+ 8, // $41 'A'
+ $00,$00,$08,$1c,$36,$63,$63,$63,$7f,$63,$63,$63,$00,$00,$00,$00,
+
+ 8, // $42 'B'
+ $00,$00,$7e,$33,$33,$33,$3e,$33,$33,$33,$33,$7e,$00,$00,$00,$00,
+
+ 8, // $43 'C'
+ $00,$00,$1e,$33,$61,$60,$60,$60,$60,$61,$33,$1e,$00,$00,$00,$00,
+
+ 8, // $44 'D'
+ $00,$00,$7c,$36,$33,$33,$33,$33,$33,$33,$36,$7c,$00,$00,$00,$00,
+
+ 8, // $45 'E'
+ $00,$00,$7f,$33,$31,$34,$3c,$34,$30,$31,$33,$7f,$00,$00,$00,$00,
+
+ 8, // $46 'F'
+ $00,$00,$7f,$33,$31,$34,$3c,$34,$30,$30,$30,$78,$00,$00,$00,$00,
+
+ 8, // $47 'G'
+ $00,$00,$1f,$33,$61,$60,$60,$6f,$63,$63,$33,$1e,$00,$00,$00,$00,
+
+ 8, // $48 'H'
+ $00,$00,$63,$63,$63,$63,$7f,$63,$63,$63,$63,$63,$00,$00,$00,$00,
+
+ 8, // $49 'I'
+ $00,$00,$1e,$0c,$0c,$0c,$0c,$0c,$0c,$0c,$0c,$1e,$00,$00,$00,$00,
+
+ 8, // $4a 'J'
+ $00,$00,$0f,$06,$06,$06,$06,$06,$06,$66,$66,$3c,$00,$00,$00,$00,
+
+ 8, // $4b 'K'
+ $00,$00,$73,$33,$36,$36,$3c,$36,$36,$33,$33,$73,$00,$00,$00,$00,
+
+ 8, // $4c 'L'
+ $00,$00,$78,$30,$30,$30,$30,$30,$30,$31,$33,$7f,$00,$00,$00,$00,
+
+ 8, // $4d 'M'
+ $00,$00,$63,$63,$77,$77,$7f,$6b,$6b,$63,$63,$63,$00,$00,$00,$00,
+
+ 8, // $4e 'N'
+ $00,$00,$63,$63,$73,$7b,$6f,$67,$63,$63,$63,$63,$00,$00,$00,$00,
+
+ 8, // $4f 'O'
+ $00,$00,$1c,$36,$63,$63,$63,$63,$63,$63,$36,$1c,$00,$00,$00,$00,
+
+ 8, // $50 'P'
+ $00,$00,$7e,$33,$33,$33,$33,$3e,$30,$30,$30,$78,$00,$00,$00,$00,
+
+ 8, // $51 'Q'
+ $00,$00,$1c,$36,$63,$63,$63,$63,$63,$6f,$36,$1e,$03,$00,$00,$00,
+
+ 8, // $52 'R'
+ $00,$00,$7e,$33,$33,$33,$33,$3e,$36,$33,$33,$73,$00,$00,$00,$00,
+
+ 8, // $53 'S'
+ $00,$00,$3e,$63,$63,$30,$18,$0c,$06,$63,$63,$3e,$00,$00,$00,$00,
+
+ 8, // $54 'T'
+ $00,$00,$3f,$3f,$2d,$0c,$0c,$0c,$0c,$0c,$0c,$1e,$00,$00,$00,$00,
+
+ 8, // $55 'U'
+ $00,$00,$63,$63,$63,$63,$63,$63,$63,$63,$63,$3e,$00,$00,$00,$00,
+
+ 8, // $56 'V'
+ $00,$00,$63,$63,$63,$63,$63,$63,$63,$36,$1c,$08,$00,$00,$00,$00,
+
+ 8, // $57 'W'
+ $00,$00,$63,$63,$63,$6b,$6b,$7f,$77,$77,$63,$63,$00,$00,$00,$00,
+
+ 8, // $58 'X'
+ $00,$00,$63,$63,$63,$36,$1c,$1c,$36,$63,$63,$63,$00,$00,$00,$00,
+
+ 8, // $59 'Y'
+ $00,$00,$33,$33,$33,$33,$1e,$0c,$0c,$0c,$0c,$1e,$00,$00,$00,$00,
+
+ 8, // $5a 'Z'
+ $00,$00,$7f,$63,$43,$06,$0c,$18,$30,$61,$63,$7f,$00,$00,$00,$00,
+
+ 8, // $5b '['
+ $00,$1f,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$1f,$00,$00,$00,
+
+ 8, // $5c '\'
+ $00,$60,$60,$30,$30,$18,$18,$0c,$0c,$06,$06,$03,$03,$00,$00,$00,
+
+ 8, // $5d ']'
+ $00,$7c,$0c,$0c,$0c,$0c,$0c,$0c,$0c,$0c,$0c,$0c,$7c,$00,$00,$00,
+
+ 8, // $5e '^'
+ $00,$00,$08,$1c,$36,$63,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 8, // $5f '_'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$ff,$00,$00,$00,$00,
+
+ 8, // $60 '`'
+ $00,$00,$18,$18,$18,$0c,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 8, // $61 'a'
+ $00,$00,$00,$00,$00,$3c,$66,$06,$3e,$66,$66,$3b,$00,$00,$00,$00,
+
+ 8, // $62 'b'
+ $00,$00,$70,$30,$30,$3c,$36,$33,$33,$33,$33,$3e,$00,$00,$00,$00,
+
+ 8, // $63 'c'
+ $00,$00,$00,$00,$00,$3e,$63,$63,$60,$60,$63,$3e,$00,$00,$00,$00,
+
+ 8, // $64 'd'
+ $00,$00,$0e,$06,$06,$1e,$36,$66,$66,$66,$66,$3b,$00,$00,$00,$00,
+
+ 8, // $65 'e'
+ $00,$00,$00,$00,$00,$3e,$63,$63,$7f,$60,$63,$3e,$00,$00,$00,$00,
+
+ 8, // $66 'f'
+ $00,$00,$0e,$1b,$1b,$18,$3c,$18,$18,$18,$18,$3c,$00,$00,$00,$00,
+
+ 8, // $67 'g'
+ $00,$00,$00,$00,$00,$3b,$66,$66,$66,$66,$66,$3e,$06,$66,$3c,$00,
+
+ 8, // $68 'h'
+ $00,$00,$70,$30,$30,$36,$3b,$33,$33,$33,$33,$73,$00,$00,$00,$00,
+
+ 8, // $69 'i'
+ $00,$00,$0c,$0c,$00,$1c,$0c,$0c,$0c,$0c,$0c,$1e,$00,$00,$00,$00,
+
+ 8, // $6a 'j'
+ $00,$00,$06,$06,$00,$0e,$06,$06,$06,$06,$06,$66,$66,$3c,$00,$00,
+
+ 8, // $6b 'k'
+ $00,$00,$70,$30,$30,$33,$33,$36,$3c,$36,$33,$73,$00,$00,$00,$00,
+
+ 8, // $6c 'l'
+ $00,$00,$1c,$0c,$0c,$0c,$0c,$0c,$0c,$0c,$0c,$1e,$00,$00,$00,$00,
+
+ 8, // $6d 'm'
+ $00,$00,$00,$00,$00,$76,$7f,$6b,$6b,$6b,$63,$63,$00,$00,$00,$00,
+
+ 8, // $6e 'n'
+ $00,$00,$00,$00,$00,$6e,$33,$33,$33,$33,$33,$33,$00,$00,$00,$00,
+
+ 8, // $6f 'o'
+ $00,$00,$00,$00,$00,$3e,$63,$63,$63,$63,$63,$3e,$00,$00,$00,$00,
+
+ 8, // $70 'p'
+ $00,$00,$00,$00,$00,$6e,$33,$33,$33,$33,$33,$3e,$30,$30,$78,$00,
+
+ 8, // $71 'q'
+ $00,$00,$00,$00,$00,$3b,$66,$66,$66,$66,$66,$3e,$06,$06,$0f,$00,
+
+ 8, // $72 'r'
+ $00,$00,$00,$00,$00,$6e,$3b,$33,$30,$30,$30,$78,$00,$00,$00,$00,
+
+ 8, // $73 's'
+ $00,$00,$00,$00,$00,$3e,$63,$60,$3e,$03,$63,$3e,$00,$00,$00,$00,
+
+ 8, // $74 't'
+ $00,$00,$08,$18,$18,$7e,$18,$18,$18,$18,$1b,$0e,$00,$00,$00,$00,
+
+ 8, // $75 'u'
+ $00,$00,$00,$00,$00,$66,$66,$66,$66,$66,$66,$3b,$00,$00,$00,$00,
+
+ 8, // $76 'v'
+ $00,$00,$00,$00,$00,$63,$63,$63,$63,$36,$1c,$08,$00,$00,$00,$00,
+
+ 8, // $77 'w'
+ $00,$00,$00,$00,$00,$63,$63,$6b,$6b,$7f,$36,$36,$00,$00,$00,$00,
+
+ 8, // $78 'x'
+ $00,$00,$00,$00,$00,$63,$63,$36,$1c,$36,$63,$63,$00,$00,$00,$00,
+
+ 8, // $79 'y'
+ $00,$00,$00,$00,$00,$63,$63,$63,$63,$63,$63,$3f,$03,$06,$7c,$00,
+
+ 8, // $7a 'z'
+ $00,$00,$00,$00,$00,$7f,$63,$06,$0c,$18,$31,$7f,$00,$00,$00,$00,
+
+ 8, // $7b '{'
+ $00,$03,$04,$0c,$0c,$0c,$08,$30,$08,$0c,$0c,$0c,$04,$03,$00,$00,
+
+ 8, // $7c '|'
+ $00,$00,$0c,$0c,$0c,$0c,$0c,$00,$0c,$0c,$0c,$0c,$0c,$00,$00,$00,
+
+ 8, // $7d '}'
+ $00,$60,$10,$18,$18,$18,$08,$06,$08,$18,$18,$18,$10,$60,$00,$00,
+
+ 8, // $7e '~'
+ $00,$00,$3b,$6e,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 8, // $7f ''
+ $00,$00,$00,$00,$00,$08,$1c,$36,$63,$63,$7f,$00,$00,$00,$00,$00,
+ 0 );
+
+ mcs11_prop : array[0..1348 ] of int8u = (
+ 11, 2, 32, 128-32,
+ $00,$00,$0C,$00,$18,$00,$24,$00,$30,$00,$3C,$00,$48,$00,$54,$00,$60,$00,
+ $6C,$00,$78,$00,$84,$00,$90,$00,$9C,$00,$A8,$00,$B4,$00,$C0,$00,$CC,$00,
+ $D8,$00,$E4,$00,$F0,$00,$FC,$00,$08,$01,$14,$01,$20,$01,$2C,$01,$38,$01,
+ $44,$01,$50,$01,$5C,$01,$68,$01,$74,$01,$80,$01,$8C,$01,$98,$01,$A4,$01,
+ $B0,$01,$BC,$01,$C8,$01,$D4,$01,$E0,$01,$EC,$01,$F8,$01,$04,$02,$10,$02,
+ $1C,$02,$28,$02,$34,$02,$40,$02,$4C,$02,$58,$02,$64,$02,$70,$02,$7C,$02,
+ $88,$02,$94,$02,$A0,$02,$AC,$02,$B8,$02,$C4,$02,$D0,$02,$DC,$02,$E8,$02,
+ $F4,$02,$00,$03,$0C,$03,$18,$03,$24,$03,$30,$03,$3C,$03,$48,$03,$54,$03,
+ $60,$03,$6C,$03,$78,$03,$84,$03,$90,$03,$9C,$03,$A8,$03,$B4,$03,$C0,$03,
+ $CC,$03,$D8,$03,$E4,$03,$F0,$03,$FC,$03,$08,$04,$14,$04,$20,$04,$2C,$04,
+ $38,$04,$44,$04,$50,$04,$5C,$04,$68,$04,$74,$04,
+
+ 5, // $20 ' '
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 4, // $21 '!'
+ $00,$20,$20,$20,$20,$20,$20,$20,$00,$20,$00,
+
+ 4, // $22 '"'
+ $50,$50,$A0,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 6, // $23 '#'
+ $00,$28,$28,$7C,$28,$28,$28,$7C,$28,$28,$00,
+
+ 6, // $24 '$'
+ $10,$10,$38,$54,$50,$38,$14,$54,$38,$10,$10,
+
+ 6, // $25 '%'
+ $00,$00,$68,$A8,$D0,$10,$20,$2C,$54,$58,$00,
+
+ 6, // $26 '&'
+ $00,$20,$50,$50,$50,$20,$54,$54,$48,$34,$00,
+
+ 3, // $27 '''
+ $40,$40,$80,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 4, // $28 '('
+ $10,$20,$20,$40,$40,$40,$40,$40,$20,$20,$10,
+
+ 5, // $29 ')'
+ $40,$20,$20,$10,$10,$10,$10,$10,$20,$20,$40,
+
+ 6, // $2A '*'
+ $00,$00,$28,$7C,$38,$7C,$28,$00,$00,$00,$00,
+
+ 6, // $2B '+'
+ $00,$00,$00,$10,$10,$7C,$10,$10,$00,$00,$00,
+
+ 4, // $2C ','
+ $00,$00,$00,$00,$00,$00,$00,$00,$60,$60,$C0,
+
+ 6, // $2D '-'
+ $00,$00,$00,$00,$00,$7C,$00,$00,$00,$00,$00,
+
+ 4, // $2E '.'
+ $00,$00,$00,$00,$00,$00,$00,$00,$60,$60,$00,
+
+ 7, // $2F '/'
+ $00,$04,$04,$08,$08,$10,$10,$20,$20,$40,$40,
+
+ 6, // $30 '0'
+ $00,$38,$44,$44,$54,$54,$54,$44,$44,$38,$00,
+
+ 4, // $31 '1'
+ $00,$20,$60,$20,$20,$20,$20,$20,$20,$20,$00,
+
+ 6, // $32 '2'
+ $00,$38,$44,$44,$04,$08,$10,$20,$40,$7C,$00,
+
+ 6, // $33 '3'
+ $00,$38,$44,$04,$04,$38,$04,$04,$44,$38,$00,
+
+ 6, // $34 '4'
+ $00,$08,$18,$18,$28,$28,$48,$7C,$08,$08,$00,
+
+ 6, // $35 '5'
+ $00,$7C,$40,$40,$78,$44,$04,$04,$44,$38,$00,
+
+ 6, // $36 '6'
+ $00,$38,$44,$40,$40,$78,$44,$44,$44,$38,$00,
+
+ 6, // $37 '7'
+ $00,$7C,$04,$08,$08,$10,$10,$20,$20,$20,$00,
+
+ 6, // $38 '8'
+ $00,$38,$44,$44,$44,$38,$44,$44,$44,$38,$00,
+
+ 6, // $39 '9'
+ $00,$38,$44,$44,$44,$3C,$04,$04,$44,$38,$00,
+
+ 4, // $3A ':'
+ $00,$00,$00,$60,$60,$00,$00,$00,$60,$60,$00,
+
+ 4, // $3B ';'
+ $00,$00,$00,$60,$60,$00,$00,$00,$60,$60,$C0,
+
+ 6, // $3C '<'
+ $00,$04,$08,$10,$20,$40,$20,$10,$08,$04,$00,
+
+ 6, // $3D '='
+ $00,$00,$00,$00,$7C,$00,$00,$7C,$00,$00,$00,
+
+ 6, // $3E '>'
+ $00,$40,$20,$10,$08,$04,$08,$10,$20,$40,$00,
+
+ 6, // $3F '?'
+ $00,$38,$44,$04,$04,$08,$10,$10,$00,$10,$00,
+
+ 6, // $40 '@'
+ $00,$38,$44,$44,$5C,$54,$54,$4C,$40,$38,$00,
+
+ 6, // $41 'A'
+ $00,$38,$44,$44,$44,$44,$7C,$44,$44,$44,$00,
+
+ 6, // $42 'B'
+ $00,$78,$44,$44,$44,$78,$44,$44,$44,$78,$00,
+
+ 6, // $43 'C'
+ $00,$38,$44,$40,$40,$40,$40,$40,$44,$38,$00,
+
+ 6, // $44 'D'
+ $00,$70,$48,$44,$44,$44,$44,$44,$48,$70,$00,
+
+ 6, // $45 'E'
+ $00,$7C,$40,$40,$40,$78,$40,$40,$40,$7C,$00,
+
+ 6, // $46 'F'
+ $00,$7C,$40,$40,$40,$78,$40,$40,$40,$40,$00,
+
+ 6, // $47 'G'
+ $00,$38,$44,$40,$40,$5C,$44,$44,$4C,$34,$00,
+
+ 6, // $48 'H'
+ $00,$44,$44,$44,$44,$7C,$44,$44,$44,$44,$00,
+
+ 4, // $49 'I'
+ $00,$70,$20,$20,$20,$20,$20,$20,$20,$70,$00,
+
+ 6, // $4A 'J'
+ $00,$1C,$08,$08,$08,$08,$08,$08,$48,$30,$00,
+
+ 6, // $4B 'K'
+ $00,$44,$48,$50,$60,$60,$50,$48,$44,$44,$00,
+
+ 6, // $4C 'L'
+ $00,$40,$40,$40,$40,$40,$40,$40,$40,$7C,$00,
+
+ 8, // $4D 'M'
+ $00,$41,$63,$55,$49,$49,$41,$41,$41,$41,$00,
+
+ 7, // $4E 'N'
+ $00,$42,$42,$62,$52,$4A,$46,$42,$42,$42,$00,
+
+ 6, // $4F 'O'
+ $00,$38,$44,$44,$44,$44,$44,$44,$44,$38,$00,
+
+ 6, // $50 'P'
+ $00,$78,$44,$44,$44,$78,$40,$40,$40,$40,$00,
+
+ 6, // $51 'Q'
+ $00,$38,$44,$44,$44,$44,$44,$54,$48,$34,$00,
+
+ 6, // $52 'R'
+ $00,$78,$44,$44,$44,$78,$44,$44,$44,$44,$00,
+
+ 6, // $53 'S'
+ $00,$38,$44,$40,$40,$38,$04,$04,$44,$38,$00,
+
+ 6, // $54 'T'
+ $00,$7C,$10,$10,$10,$10,$10,$10,$10,$10,$00,
+
+ 6, // $55 'U'
+ $00,$44,$44,$44,$44,$44,$44,$44,$44,$38,$00,
+
+ 6, // $56 'V'
+ $00,$44,$44,$44,$44,$28,$28,$28,$10,$10,$00,
+
+ 8, // $57 'W'
+ $00,$41,$41,$41,$41,$49,$49,$49,$55,$22,$00,
+
+ 6, // $58 'X'
+ $00,$44,$44,$44,$28,$10,$28,$44,$44,$44,$00,
+
+ 6, // $59 'Y'
+ $00,$44,$44,$44,$28,$10,$10,$10,$10,$10,$00,
+
+ 6, // $5A 'Z'
+ $00,$7C,$04,$04,$08,$10,$20,$40,$40,$7C,$00,
+
+ 5, // $5B '['
+ $30,$20,$20,$20,$20,$20,$20,$20,$20,$20,$30,
+
+ 7, // $5C '\'
+ $40,$40,$20,$20,$10,$10,$08,$08,$04,$04,$00,
+
+ 4, // $5D ']'
+ $60,$20,$20,$20,$20,$20,$20,$20,$20,$20,$60,
+
+ 6, // $5E '^'
+ $00,$10,$28,$44,$00,$00,$00,$00,$00,$00,$00,
+
+ 6, // $5F '_'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$7C,$00,
+
+ 4, // $60 '`'
+ $00,$40,$40,$20,$00,$00,$00,$00,$00,$00,$00,
+
+ 6, // $61 'a'
+ $00,$00,$00,$38,$04,$3C,$44,$44,$44,$3C,$00,
+
+ 6, // $62 'b'
+ $00,$40,$40,$78,$44,$44,$44,$44,$44,$78,$00,
+
+ 6, // $63 'c'
+ $00,$00,$00,$38,$44,$40,$40,$40,$44,$38,$00,
+
+ 6, // $64 'd'
+ $00,$04,$04,$3C,$44,$44,$44,$44,$44,$3C,$00,
+
+ 6, // $65 'e'
+ $00,$00,$00,$38,$44,$44,$7C,$40,$44,$38,$00,
+
+ 4, // $66 'f'
+ $00,$10,$20,$70,$20,$20,$20,$20,$20,$20,$00,
+
+ 6, // $67 'g'
+ $00,$00,$00,$3C,$44,$44,$44,$3C,$04,$44,$38,
+
+ 6, // $68 'h'
+ $00,$40,$40,$78,$44,$44,$44,$44,$44,$44,$00,
+
+ 2, // $69 'i'
+ $00,$40,$00,$40,$40,$40,$40,$40,$40,$40,$00,
+
+ 3, // $6A 'j'
+ $00,$20,$00,$20,$20,$20,$20,$20,$20,$A0,$40,
+
+ 5, // $6B 'k'
+ $00,$40,$40,$48,$50,$60,$60,$50,$48,$48,$00,
+
+ 2, // $6C 'l'
+ $00,$40,$40,$40,$40,$40,$40,$40,$40,$40,$00,
+
+ 8, // $6D 'm'
+ $00,$00,$00,$76,$49,$49,$49,$49,$41,$41,$00,
+
+ 6, // $6E 'n'
+ $00,$00,$00,$78,$44,$44,$44,$44,$44,$44,$00,
+
+ 6, // $6F 'o'
+ $00,$00,$00,$38,$44,$44,$44,$44,$44,$38,$00,
+
+ 6, // $70 'p'
+ $00,$00,$00,$78,$44,$44,$44,$44,$78,$40,$40,
+
+ 6, // $71 'q'
+ $00,$00,$00,$3C,$44,$44,$44,$44,$3C,$04,$04,
+
+ 6, // $72 'r'
+ $00,$00,$00,$58,$24,$20,$20,$20,$20,$20,$00,
+
+ 6, // $73 's'
+ $00,$00,$00,$38,$44,$40,$38,$04,$44,$38,$00,
+
+ 5, // $74 't'
+ $00,$20,$20,$70,$20,$20,$20,$20,$28,$10,$00,
+
+ 6, // $75 'u'
+ $00,$00,$00,$44,$44,$44,$44,$44,$4C,$34,$00,
+
+ 6, // $76 'v'
+ $00,$00,$00,$44,$44,$44,$28,$28,$10,$10,$00,
+
+ 8, // $77 'w'
+ $00,$00,$00,$41,$41,$41,$41,$49,$49,$36,$00,
+
+ 6, // $78 'x'
+ $00,$00,$00,$44,$44,$28,$10,$28,$44,$44,$00,
+
+ 6, // $79 'y'
+ $00,$00,$00,$44,$44,$44,$44,$3C,$04,$08,$70,
+
+ 6, // $7A 'z'
+ $00,$00,$00,$7C,$04,$08,$10,$20,$40,$7C,$00,
+
+ 5, // $7B '{'
+ $18,$20,$20,$20,$20,$C0,$20,$20,$20,$20,$18,
+
+ 3, // $7C '|'
+ $00,$40,$40,$40,$40,$00,$40,$40,$40,$40,$00,
+
+ 5, // $7D '}'
+ $C0,$20,$20,$20,$20,$18,$20,$20,$20,$20,$C0,
+
+ 6, // $7E '~'
+ $00,$24,$54,$48,$00,$00,$00,$00,$00,$00,$00,
+
+ 6, // $7F ''
+ $00,$10,$38,$6C,$44,$44,$7C,$00,$00,$00,$00,
+
+ 0 );
+
+ mcs11_prop_condensed : array[0..1348 ] of int8u = (
+ 11, 2, 32, 128-32,
+ $00,$00,$0C,$00,$18,$00,$24,$00,$30,$00,$3C,$00,$48,$00,$54,$00,$60,$00,
+ $6C,$00,$78,$00,$84,$00,$90,$00,$9C,$00,$A8,$00,$B4,$00,$C0,$00,$CC,$00,
+ $D8,$00,$E4,$00,$F0,$00,$FC,$00,$08,$01,$14,$01,$20,$01,$2C,$01,$38,$01,
+ $44,$01,$50,$01,$5C,$01,$68,$01,$74,$01,$80,$01,$8C,$01,$98,$01,$A4,$01,
+ $B0,$01,$BC,$01,$C8,$01,$D4,$01,$E0,$01,$EC,$01,$F8,$01,$04,$02,$10,$02,
+ $1C,$02,$28,$02,$34,$02,$40,$02,$4C,$02,$58,$02,$64,$02,$70,$02,$7C,$02,
+ $88,$02,$94,$02,$A0,$02,$AC,$02,$B8,$02,$C4,$02,$D0,$02,$DC,$02,$E8,$02,
+ $F4,$02,$00,$03,$0C,$03,$18,$03,$24,$03,$30,$03,$3C,$03,$48,$03,$54,$03,
+ $60,$03,$6C,$03,$78,$03,$84,$03,$90,$03,$9C,$03,$A8,$03,$B4,$03,$C0,$03,
+ $CC,$03,$D8,$03,$E4,$03,$F0,$03,$FC,$03,$08,$04,$14,$04,$20,$04,$2C,$04,
+ $38,$04,$44,$04,$50,$04,$5C,$04,$68,$04,$74,$04,
+
+ 3, // $20 ' '
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 3, // $21 '!'
+ $00,$40,$40,$40,$40,$40,$40,$40,$00,$40,$00,
+
+ 4, // $22 '"'
+ $50,$50,$A0,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 5, // $23 '#'
+ $00,$50,$50,$F8,$50,$50,$50,$F8,$50,$50,$00,
+
+ 5, // $24 '$'
+ $00,$40,$60,$90,$80,$60,$10,$90,$60,$20,$00,
+
+ 5, // $25 '%'
+ $00,$00,$90,$90,$20,$20,$40,$40,$90,$90,$00,
+
+ 5, // $26 '&'
+ $00,$40,$A0,$A0,$A0,$40,$A8,$90,$90,$68,$00,
+
+ 5, // $27 '''
+ $00,$00,$20,$40,$00,$00,$00,$00,$00,$00,$00,
+
+ 5, // $28 '('
+ $10,$20,$20,$40,$40,$40,$40,$40,$20,$20,$10,
+
+ 4, // $29 ')'
+ $80,$40,$40,$20,$20,$20,$20,$20,$40,$40,$80,
+
+ 5, // $2A '*'
+ $00,$00,$90,$60,$F0,$60,$90,$00,$00,$00,$00,
+
+ 5, // $2B '+'
+ $00,$00,$00,$20,$20,$F8,$20,$20,$00,$00,$00,
+
+ 4, // $2C ','
+ $00,$00,$00,$00,$00,$00,$00,$00,$60,$60,$C0,
+
+ 5, // $2D '-'
+ $00,$00,$00,$00,$00,$F0,$00,$00,$00,$00,$00,
+
+ 4, // $2E '.'
+ $00,$00,$00,$00,$00,$00,$00,$00,$C0,$C0,$00,
+
+ 6, // $2F '/'
+ $08,$08,$10,$10,$20,$20,$40,$40,$80,$80,$00,
+
+ 5, // $30 '0'
+ $00,$70,$90,$90,$90,$90,$90,$90,$90,$E0,$00,
+
+ 3, // $31 '1'
+ $00,$40,$C0,$40,$40,$40,$40,$40,$40,$40,$00,
+
+ 5, // $32 '2'
+ $00,$60,$90,$90,$10,$10,$20,$40,$80,$F0,$00,
+
+ 5, // $33 '3'
+ $00,$60,$90,$10,$10,$60,$10,$10,$90,$60,$00,
+
+ 5, // $34 '4'
+ $00,$10,$30,$30,$50,$50,$90,$F0,$10,$10,$00,
+
+ 5, // $35 '5'
+ $00,$F0,$80,$80,$E0,$90,$10,$10,$90,$60,$00,
+
+ 5, // $36 '6'
+ $00,$60,$90,$80,$80,$E0,$90,$90,$90,$60,$00,
+
+ 5, // $37 '7'
+ $00,$F0,$10,$10,$10,$20,$20,$40,$40,$40,$00,
+
+ 5, // $38 '8'
+ $00,$60,$90,$90,$90,$60,$90,$90,$90,$60,$00,
+
+ 5, // $39 '9'
+ $00,$60,$90,$90,$90,$70,$10,$10,$90,$60,$00,
+
+ 4, // $3A ':'
+ $00,$00,$00,$60,$60,$00,$00,$00,$60,$60,$00,
+
+ 4, // $3B ';'
+ $00,$00,$00,$60,$60,$00,$00,$00,$60,$60,$C0,
+
+ 6, // $3C '<'
+ $00,$08,$10,$20,$40,$80,$40,$20,$10,$08,$00,
+
+ 5, // $3D '='
+ $00,$00,$00,$00,$F0,$00,$00,$F0,$00,$00,$00,
+
+ 6, // $3E '>'
+ $00,$80,$40,$20,$10,$08,$10,$20,$40,$80,$00,
+
+ 5, // $3F '?'
+ $00,$60,$90,$10,$10,$20,$40,$00,$40,$00,$00,
+
+ 5, // $40 '@'
+ $00,$60,$90,$90,$B0,$B0,$B0,$80,$80,$70,$00,
+
+ 5, // $41 'A'
+ $00,$60,$90,$90,$90,$F0,$90,$90,$90,$90,$00,
+
+ 5, // $42 'B'
+ $00,$E0,$90,$90,$90,$E0,$90,$90,$90,$E0,$00,
+
+ 5, // $43 'C'
+ $00,$60,$90,$80,$80,$80,$80,$80,$90,$60,$00,
+
+ 5, // $44 'D'
+ $00,$E0,$90,$90,$90,$90,$90,$90,$90,$E0,$00,
+
+ 5, // $45 'E'
+ $00,$F0,$80,$80,$80,$F0,$80,$80,$80,$F0,$00,
+
+ 5, // $46 'F'
+ $00,$F0,$80,$80,$80,$F0,$80,$80,$80,$80,$00,
+
+ 5, // $47 'G'
+ $00,$70,$80,$80,$80,$B0,$90,$90,$90,$60,$00,
+
+ 5, // $48 'H'
+ $00,$90,$90,$90,$90,$F0,$90,$90,$90,$90,$00,
+
+ 4, // $49 'I'
+ $00,$E0,$40,$40,$40,$40,$40,$40,$40,$E0,$00,
+
+ 5, // $4A 'J'
+ $00,$70,$20,$20,$20,$20,$20,$A0,$A0,$40,$00,
+
+ 5, // $4B 'K'
+ $00,$90,$90,$A0,$A0,$C0,$A0,$A0,$90,$90,$00,
+
+ 5, // $4C 'L'
+ $00,$80,$80,$80,$80,$80,$80,$80,$80,$F0,$00,
+
+ 6, // $4D 'M'
+ $00,$88,$D8,$A8,$A8,$A8,$88,$88,$88,$88,$00,
+
+ 5, // $4E 'N'
+ $00,$90,$90,$D0,$D0,$B0,$B0,$90,$90,$90,$00,
+
+ 5, // $4F 'O'
+ $00,$60,$90,$90,$90,$90,$90,$90,$90,$60,$00,
+
+ 5, // $50 'P'
+ $00,$E0,$90,$90,$90,$90,$E0,$80,$80,$80,$00,
+
+ 5, // $51 'Q'
+ $00,$60,$90,$90,$90,$90,$90,$90,$90,$60,$30,
+
+ 5, // $52 'R'
+ $00,$E0,$90,$90,$90,$90,$E0,$A0,$90,$90,$00,
+
+ 5, // $53 'S'
+ $00,$60,$90,$80,$80,$60,$10,$10,$90,$60,$00,
+
+ 6, // $54 'T'
+ $00,$F8,$20,$20,$20,$20,$20,$20,$20,$20,$00,
+
+ 5, // $55 'U'
+ $00,$90,$90,$90,$90,$90,$90,$90,$90,$60,$00,
+
+ 6, // $56 'V'
+ $00,$88,$88,$88,$88,$50,$50,$50,$20,$20,$00,
+
+ 6, // $57 'W'
+ $00,$88,$88,$88,$A8,$A8,$A8,$A8,$A8,$50,$00,
+
+ 5, // $58 'X'
+ $00,$90,$90,$90,$60,$60,$90,$90,$90,$90,$00,
+
+ 6, // $59 'Y'
+ $00,$88,$88,$88,$50,$20,$20,$20,$20,$20,$00,
+
+ 5, // $5A 'Z'
+ $00,$F0,$10,$20,$20,$40,$40,$80,$80,$F0,$00,
+
+ 4, // $5B '['
+ $60,$40,$40,$40,$40,$40,$40,$40,$40,$60,$00,
+
+ 6, // $5C '\'
+ $80,$80,$40,$40,$20,$20,$10,$10,$08,$08,$00,
+
+ 4, // $5D ']'
+ $60,$20,$20,$20,$20,$20,$20,$20,$20,$60,$00,
+
+ 5, // $5E '^'
+ $00,$20,$50,$88,$00,$00,$00,$00,$00,$00,$00,
+
+ 5, // $5F '_'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$F0,$00,
+
+ 5, // $60 '`'
+ $00,$40,$20,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 5, // $61 'a'
+ $00,$00,$00,$60,$90,$10,$70,$90,$90,$70,$00,
+
+ 5, // $62 'b'
+ $00,$80,$80,$80,$E0,$90,$90,$90,$90,$E0,$00,
+
+ 5, // $63 'c'
+ $00,$00,$00,$60,$90,$80,$80,$80,$90,$60,$00,
+
+ 5, // $64 'd'
+ $00,$10,$10,$10,$70,$90,$90,$90,$90,$70,$00,
+
+ 5, // $65 'e'
+ $00,$00,$00,$60,$90,$90,$F0,$80,$90,$60,$00,
+
+ 4, // $66 'f'
+ $00,$20,$40,$40,$E0,$40,$40,$40,$40,$40,$00,
+
+ 5, // $67 'g'
+ $00,$00,$00,$70,$90,$90,$90,$70,$10,$90,$60,
+
+ 5, // $68 'h'
+ $00,$80,$80,$80,$E0,$90,$90,$90,$90,$90,$00,
+
+ 2, // $69 'i'
+ $00,$80,$00,$80,$80,$80,$80,$80,$80,$80,$00,
+
+ 4, // $6A 'j'
+ $00,$20,$00,$20,$20,$20,$20,$20,$20,$A0,$40,
+
+ 5, // $6B 'k'
+ $00,$80,$80,$90,$90,$A0,$C0,$A0,$90,$90,$00,
+
+ 2, // $6C 'l'
+ $00,$80,$80,$80,$80,$80,$80,$80,$80,$80,$00,
+
+ 6, // $6D 'm'
+ $00,$00,$00,$D0,$A8,$A8,$A8,$88,$88,$88,$00,
+
+ 5, // $6E 'n'
+ $00,$00,$00,$A0,$D0,$90,$90,$90,$90,$90,$00,
+
+ 5, // $6F 'o'
+ $00,$00,$00,$60,$90,$90,$90,$90,$90,$60,$00,
+
+ 5, // $70 'p'
+ $00,$00,$00,$E0,$90,$90,$90,$90,$E0,$80,$80,
+
+ 5, // $71 'q'
+ $00,$00,$00,$70,$90,$90,$90,$90,$70,$10,$10,
+
+ 6, // $72 'r'
+ $00,$00,$00,$B8,$48,$40,$40,$40,$40,$40,$00,
+
+ 5, // $73 's'
+ $00,$00,$00,$60,$90,$40,$20,$10,$90,$60,$00,
+
+ 4, // $74 't'
+ $00,$40,$40,$E0,$40,$40,$40,$40,$40,$20,$00,
+
+ 5, // $75 'u'
+ $00,$00,$00,$90,$90,$90,$90,$90,$90,$70,$00,
+
+ 6, // $76 'v'
+ $00,$00,$00,$88,$88,$88,$50,$50,$20,$20,$00,
+
+ 6, // $77 'w'
+ $00,$00,$00,$88,$88,$88,$A8,$A8,$A8,$50,$00,
+
+ 5, // $78 'x'
+ $00,$00,$00,$90,$90,$60,$60,$90,$90,$90,$00,
+
+ 5, // $79 'y'
+ $00,$00,$00,$90,$90,$90,$90,$70,$10,$20,$C0,
+
+ 5, // $7A 'z'
+ $00,$00,$00,$F0,$10,$20,$40,$80,$80,$F0,$00,
+
+ 5, // $7B '{'
+ $30,$40,$40,$40,$40,$80,$40,$40,$40,$40,$30,
+
+ 3, // $7C '|'
+ $00,$40,$40,$40,$40,$00,$40,$40,$40,$40,$00,
+
+ 5, // $7D '}'
+ $C0,$20,$20,$20,$20,$10,$20,$20,$20,$20,$C0,
+
+ 5, // $7E '~'
+ $00,$40,$A8,$10,$00,$00,$00,$00,$00,$00,$00,
+
+ 5, // $7F ''
+ $00,$20,$70,$D8,$88,$88,$F8,$00,$00,$00,$00,
+
+ 0 );
+
+ mcs12_prop : array[0..1492 ] of int8u = (
+ 12, 3, 32, 128-32,
+ $00,$00,$0D,$00,$1A,$00,$27,$00,$34,$00,$41,$00,$4E,$00,$5B,$00,$68,$00,
+ $75,$00,$82,$00,$8F,$00,$9C,$00,$A9,$00,$B6,$00,$C3,$00,$D0,$00,$DD,$00,
+ $EA,$00,$F7,$00,$04,$01,$11,$01,$1E,$01,$2B,$01,$38,$01,$45,$01,$52,$01,
+ $5F,$01,$6C,$01,$79,$01,$86,$01,$93,$01,$A0,$01,$AD,$01,$BA,$01,$C7,$01,
+ $D4,$01,$E1,$01,$EE,$01,$FB,$01,$08,$02,$15,$02,$22,$02,$2F,$02,$3C,$02,
+ $49,$02,$62,$02,$6F,$02,$7C,$02,$89,$02,$96,$02,$A3,$02,$B0,$02,$BD,$02,
+ $CA,$02,$D7,$02,$F0,$02,$FD,$02,$0A,$03,$17,$03,$24,$03,$31,$03,$3E,$03,
+ $4B,$03,$58,$03,$65,$03,$72,$03,$7F,$03,$8C,$03,$99,$03,$A6,$03,$B3,$03,
+ $C0,$03,$CD,$03,$DA,$03,$E7,$03,$F4,$03,$01,$04,$1A,$04,$27,$04,$34,$04,
+ $41,$04,$4E,$04,$5B,$04,$68,$04,$75,$04,$82,$04,$8F,$04,$A8,$04,$B5,$04,
+ $C2,$04,$CF,$04,$DC,$04,$E9,$04,$F6,$04,$03,$05,
+
+ 5, // $20 ' '
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 4, // $21 '!'
+ $00,$20,$20,$20,$20,$20,$20,$20,$00,$20,$00,$00,
+
+ 4, // $22 '"'
+ $50,$50,$A0,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 6, // $23 '#'
+ $28,$28,$28,$7C,$28,$28,$28,$7C,$28,$28,$28,$00,
+
+ 6, // $24 '$'
+ $10,$10,$38,$54,$50,$38,$14,$54,$38,$10,$10,$00,
+
+ 7, // $25 '%'
+ $32,$54,$64,$08,$08,$10,$10,$26,$2A,$4C,$00,$00,
+
+ 7, // $26 '&'
+ $00,$30,$48,$48,$48,$30,$4A,$4A,$44,$3A,$00,$00,
+
+ 3, // $27 '''
+ $40,$40,$80,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 5, // $28 '('
+ $10,$20,$20,$40,$40,$40,$40,$40,$20,$20,$10,$00,
+
+ 5, // $29 ')'
+ $40,$20,$20,$10,$10,$10,$10,$10,$20,$20,$40,$00,
+
+ 6, // $2A '*'
+ $00,$00,$10,$54,$38,$7C,$38,$54,$10,$00,$00,$00,
+
+ 6, // $2B '+'
+ $00,$00,$00,$00,$10,$10,$7C,$10,$10,$00,$00,$00,
+
+ 4, // $2C ','
+ $00,$00,$00,$00,$00,$00,$00,$00,$60,$60,$40,$80,
+
+ 6, // $2D '-'
+ $00,$00,$00,$00,$00,$00,$7C,$00,$00,$00,$00,$00,
+
+ 4, // $2E '.'
+ $00,$00,$00,$00,$00,$00,$00,$00,$60,$60,$00,$00,
+
+ 7, // $2F '/'
+ $00,$04,$04,$08,$08,$10,$10,$20,$20,$40,$40,$00,
+
+ 7, // $30 '0'
+ $00,$38,$44,$44,$54,$54,$54,$44,$44,$38,$00,$00,
+
+ 4, // $31 '1'
+ $00,$20,$60,$20,$20,$20,$20,$20,$20,$20,$00,$00,
+
+ 7, // $32 '2'
+ $00,$38,$44,$04,$04,$08,$10,$20,$40,$7C,$00,$00,
+
+ 7, // $33 '3'
+ $00,$38,$44,$04,$04,$38,$04,$04,$44,$38,$00,$00,
+
+ 6, // $34 '4'
+ $00,$08,$18,$28,$28,$48,$48,$7C,$08,$08,$00,$00,
+
+ 7, // $35 '5'
+ $00,$7C,$40,$40,$78,$44,$04,$04,$44,$38,$00,$00,
+
+ 7, // $36 '6'
+ $00,$38,$44,$40,$78,$44,$44,$44,$44,$38,$00,$00,
+
+ 6, // $37 '7'
+ $00,$7C,$04,$08,$08,$10,$10,$20,$20,$20,$00,$00,
+
+ 7, // $38 '8'
+ $00,$38,$44,$44,$44,$38,$44,$44,$44,$38,$00,$00,
+
+ 7, // $39 '9'
+ $00,$38,$44,$44,$44,$3C,$04,$04,$44,$38,$00,$00,
+
+ 4, // $3A ':'
+ $00,$00,$00,$60,$60,$00,$00,$00,$60,$60,$00,$00,
+
+ 4, // $3B ';'
+ $00,$00,$00,$60,$60,$00,$00,$00,$60,$60,$40,$80,
+
+ 6, // $3C '<'
+ $00,$00,$04,$08,$10,$20,$40,$20,$10,$08,$04,$00,
+
+ 6, // $3D '='
+ $00,$00,$00,$00,$7C,$00,$00,$7C,$00,$00,$00,$00,
+
+ 6, // $3E '>'
+ $00,$00,$40,$20,$10,$08,$04,$08,$10,$20,$40,$00,
+
+ 6, // $3F '?'
+ $00,$38,$44,$04,$04,$08,$10,$10,$00,$10,$00,$00,
+
+ 7, // $40 '@'
+ $00,$38,$44,$44,$5C,$54,$54,$4C,$40,$38,$00,$00,
+
+ 7, // $41 'A'
+ $00,$38,$44,$44,$44,$7C,$44,$44,$44,$44,$00,$00,
+
+ 7, // $42 'B'
+ $00,$78,$44,$44,$44,$78,$44,$44,$44,$78,$00,$00,
+
+ 6, // $43 'C'
+ $00,$38,$44,$40,$40,$40,$40,$40,$44,$38,$00,$00,
+
+ 7, // $44 'D'
+ $00,$70,$48,$44,$44,$44,$44,$44,$48,$70,$00,$00,
+
+ 6, // $45 'E'
+ $00,$7C,$40,$40,$40,$78,$40,$40,$40,$7C,$00,$00,
+
+ 6, // $46 'F'
+ $00,$7C,$40,$40,$40,$78,$40,$40,$40,$40,$00,$00,
+
+ 7, // $47 'G'
+ $00,$38,$44,$40,$40,$5C,$44,$44,$4C,$34,$00,$00,
+
+ 7, // $48 'H'
+ $00,$44,$44,$44,$44,$7C,$44,$44,$44,$44,$00,$00,
+
+ 5, // $49 'I'
+ $00,$70,$20,$20,$20,$20,$20,$20,$20,$70,$00,$00,
+
+ 6, // $4A 'J'
+ $00,$1C,$08,$08,$08,$08,$08,$48,$48,$30,$00,$00,
+
+ 6, // $4B 'K'
+ $00,$44,$48,$50,$60,$60,$50,$48,$44,$44,$00,$00,
+
+ 6, // $4C 'L'
+ $00,$40,$40,$40,$40,$40,$40,$40,$40,$7C,$00,$00,
+
+ 9, // $4D 'M'
+ $00,$00,$41,$00,$63,$00,$55,$00,$49,$00,$49,$00,$41,$00,$41,$00,$41,$00,$41,$00,$00,$00,$00,$00,
+
+ 7, // $4E 'N'
+ $00,$44,$64,$64,$54,$54,$4C,$4C,$44,$44,$00,$00,
+
+ 7, // $4F 'O'
+ $00,$38,$44,$44,$44,$44,$44,$44,$44,$38,$00,$00,
+
+ 7, // $50 'P'
+ $00,$78,$44,$44,$44,$44,$78,$40,$40,$40,$00,$00,
+
+ 7, // $51 'Q'
+ $00,$38,$44,$44,$44,$44,$44,$54,$48,$34,$00,$00,
+
+ 7, // $52 'R'
+ $00,$78,$44,$44,$44,$44,$78,$48,$44,$44,$00,$00,
+
+ 7, // $53 'S'
+ $00,$38,$44,$40,$40,$38,$04,$04,$44,$38,$00,$00,
+
+ 6, // $54 'T'
+ $00,$7C,$10,$10,$10,$10,$10,$10,$10,$10,$00,$00,
+
+ 7, // $55 'U'
+ $00,$44,$44,$44,$44,$44,$44,$44,$44,$38,$00,$00,
+
+ 6, // $56 'V'
+ $00,$44,$44,$44,$44,$28,$28,$28,$10,$10,$00,$00,
+
+ 9, // $57 'W'
+ $00,$00,$41,$00,$41,$00,$41,$00,$41,$00,$41,$00,$49,$00,$49,$00,$55,$00,$22,$00,$00,$00,$00,$00,
+
+ 7, // $58 'X'
+ $00,$44,$44,$44,$28,$10,$28,$44,$44,$44,$00,$00,
+
+ 7, // $59 'Y'
+ $00,$44,$44,$44,$44,$28,$10,$10,$10,$10,$00,$00,
+
+ 6, // $5A 'Z'
+ $00,$7C,$04,$04,$08,$10,$20,$40,$40,$7C,$00,$00,
+
+ 4, // $5B '['
+ $70,$40,$40,$40,$40,$40,$40,$40,$40,$40,$70,$00,
+
+ 7, // $5C '\'
+ $00,$40,$40,$20,$20,$10,$10,$08,$08,$04,$04,$00,
+
+ 4, // $5D ']'
+ $E0,$20,$20,$20,$20,$20,$20,$20,$20,$20,$E0,$00,
+
+ 6, // $5E '^'
+ $00,$10,$28,$44,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 6, // $5F '_'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$7C,$00,$00,
+
+ 4, // $60 '`'
+ $00,$40,$40,$20,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $61 'a'
+ $00,$00,$00,$38,$04,$3C,$44,$44,$44,$3C,$00,$00,
+
+ 7, // $62 'b'
+ $00,$40,$40,$78,$44,$44,$44,$44,$44,$78,$00,$00,
+
+ 6, // $63 'c'
+ $00,$00,$00,$38,$44,$40,$40,$40,$44,$38,$00,$00,
+
+ 7, // $64 'd'
+ $00,$04,$04,$3C,$44,$44,$44,$44,$44,$3C,$00,$00,
+
+ 7, // $65 'e'
+ $00,$00,$00,$38,$44,$44,$7C,$40,$44,$38,$00,$00,
+
+ 4, // $66 'f'
+ $00,$30,$40,$E0,$40,$40,$40,$40,$40,$40,$00,$00,
+
+ 7, // $67 'g'
+ $00,$00,$00,$3C,$44,$44,$44,$44,$44,$3C,$04,$78,
+
+ 7, // $68 'h'
+ $00,$40,$40,$78,$44,$44,$44,$44,$44,$44,$00,$00,
+
+ 3, // $69 'i'
+ $00,$40,$00,$40,$40,$40,$40,$40,$40,$40,$00,$00,
+
+ 5, // $6A 'j'
+ $00,$10,$00,$10,$10,$10,$10,$10,$10,$10,$90,$60,
+
+ 6, // $6B 'k'
+ $00,$40,$40,$44,$48,$50,$60,$50,$48,$44,$00,$00,
+
+ 3, // $6C 'l'
+ $00,$40,$40,$40,$40,$40,$40,$40,$40,$40,$00,$00,
+
+ 9, // $6D 'm'
+ $00,$00,$00,$00,$00,$00,$76,$00,$49,$00,$49,$00,$49,$00,$41,$00,$41,$00,$41,$00,$00,$00,$00,$00,
+
+ 7, // $6E 'n'
+ $00,$00,$00,$58,$64,$44,$44,$44,$44,$44,$00,$00,
+
+ 7, // $6F 'o'
+ $00,$00,$00,$38,$44,$44,$44,$44,$44,$38,$00,$00,
+
+ 7, // $70 'p'
+ $00,$00,$00,$78,$44,$44,$44,$44,$44,$78,$40,$40,
+
+ 7, // $71 'q'
+ $00,$00,$00,$3C,$44,$44,$44,$44,$44,$3C,$04,$04,
+
+ 6, // $72 'r'
+ $00,$00,$00,$58,$24,$20,$20,$20,$20,$70,$00,$00,
+
+ 7, // $73 's'
+ $00,$00,$00,$38,$44,$40,$38,$04,$44,$38,$00,$00,
+
+ 5, // $74 't'
+ $00,$20,$20,$70,$20,$20,$20,$20,$20,$18,$00,$00,
+
+ 7, // $75 'u'
+ $00,$00,$00,$44,$44,$44,$44,$44,$4C,$34,$00,$00,
+
+ 6, // $76 'v'
+ $00,$00,$00,$44,$44,$44,$28,$28,$10,$10,$00,$00,
+
+ 9, // $77 'w'
+ $00,$00,$00,$00,$00,$00,$41,$00,$41,$00,$41,$00,$49,$00,$49,$00,$49,$00,$36,$00,$00,$00,$00,$00,
+
+ 7, // $78 'x'
+ $00,$00,$00,$44,$44,$28,$10,$28,$44,$44,$00,$00,
+
+ 7, // $79 'y'
+ $00,$00,$00,$44,$44,$44,$44,$44,$44,$3C,$08,$70,
+
+ 6, // $7A 'z'
+ $00,$00,$00,$7C,$04,$08,$10,$20,$40,$7C,$00,$00,
+
+ 5, // $7B '{'
+ $18,$20,$20,$20,$20,$C0,$20,$20,$20,$20,$18,$00,
+
+ 3, // $7C '|'
+ $00,$40,$40,$40,$40,$40,$40,$40,$40,$40,$40,$00,
+
+ 5, // $7D '}'
+ $C0,$20,$20,$20,$20,$18,$20,$20,$20,$20,$C0,$00,
+
+ 7, // $7E '~'
+ $00,$60,$92,$92,$0C,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $7F ''
+ $00,$10,$38,$6C,$44,$44,$7C,$00,$00,$00,$00,$00,
+
+ 0 );
+
+ mcs13_prop : array[0..1592 ] of int8u = (
+ 13, 4, 32, 128-32,
+ $00,$00,$0E,$00,$1C,$00,$2A,$00,$38,$00,$46,$00,$54,$00,$62,$00,$70,$00,
+ $7E,$00,$8C,$00,$9A,$00,$A8,$00,$B6,$00,$C4,$00,$D2,$00,$E0,$00,$EE,$00,
+ $FC,$00,$0A,$01,$18,$01,$26,$01,$34,$01,$42,$01,$50,$01,$5E,$01,$6C,$01,
+ $7A,$01,$88,$01,$96,$01,$A4,$01,$B2,$01,$C0,$01,$CE,$01,$DC,$01,$EA,$01,
+ $F8,$01,$06,$02,$14,$02,$22,$02,$30,$02,$3E,$02,$4C,$02,$5A,$02,$68,$02,
+ $76,$02,$91,$02,$9F,$02,$AD,$02,$BB,$02,$C9,$02,$D7,$02,$E5,$02,$F3,$02,
+ $01,$03,$0F,$03,$2A,$03,$38,$03,$46,$03,$54,$03,$62,$03,$70,$03,$7E,$03,
+ $8C,$03,$9A,$03,$A8,$03,$B6,$03,$C4,$03,$D2,$03,$E0,$03,$EE,$03,$FC,$03,
+ $0A,$04,$18,$04,$26,$04,$34,$04,$42,$04,$50,$04,$6B,$04,$79,$04,$87,$04,
+ $95,$04,$A3,$04,$B1,$04,$BF,$04,$CD,$04,$DB,$04,$E9,$04,$04,$05,$12,$05,
+ $20,$05,$2E,$05,$3C,$05,$4A,$05,$58,$05,$66,$05,
+
+ 5, // $20 ' '
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 4, // $21 '!'
+ $00,$20,$20,$20,$20,$20,$20,$20,$20,$00,$20,$00,$00,
+
+ 4, // $22 '"'
+ $00,$50,$50,$A0,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 6, // $23 '#'
+ $00,$28,$28,$28,$7C,$28,$28,$28,$7C,$28,$28,$28,$00,
+
+ 6, // $24 '$'
+ $00,$10,$10,$38,$54,$50,$38,$14,$54,$38,$10,$10,$00,
+
+ 7, // $25 '%'
+ $00,$32,$54,$64,$08,$08,$10,$10,$26,$2A,$4C,$00,$00,
+
+ 7, // $26 '&'
+ $00,$30,$48,$48,$48,$30,$4A,$4A,$44,$3A,$00,$00,$00,
+
+ 3, // $27 '''
+ $00,$40,$40,$80,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 5, // $28 '('
+ $10,$20,$20,$40,$40,$40,$40,$40,$20,$20,$10,$00,$00,
+
+ 5, // $29 ')'
+ $40,$20,$20,$10,$10,$10,$10,$10,$20,$20,$40,$00,$00,
+
+ 6, // $2A '*'
+ $00,$00,$10,$54,$38,$7C,$38,$54,$10,$00,$00,$00,$00,
+
+ 6, // $2B '+'
+ $00,$00,$00,$00,$10,$10,$7C,$10,$10,$00,$00,$00,$00,
+
+ 4, // $2C ','
+ $00,$00,$00,$00,$00,$00,$00,$00,$60,$60,$20,$40,$80,
+
+ 6, // $2D '-'
+ $00,$00,$00,$00,$00,$00,$7C,$00,$00,$00,$00,$00,$00,
+
+ 4, // $2E '.'
+ $00,$00,$00,$00,$00,$00,$00,$00,$60,$60,$00,$00,$00,
+
+ 7, // $2F '/'
+ $00,$04,$04,$08,$08,$10,$10,$20,$20,$40,$40,$00,$00,
+
+ 7, // $30 '0'
+ $00,$38,$44,$44,$54,$54,$54,$44,$44,$38,$00,$00,$00,
+
+ 4, // $31 '1'
+ $00,$20,$60,$20,$20,$20,$20,$20,$20,$20,$00,$00,$00,
+
+ 7, // $32 '2'
+ $00,$38,$44,$04,$04,$08,$10,$20,$40,$7C,$00,$00,$00,
+
+ 7, // $33 '3'
+ $00,$38,$44,$04,$04,$38,$04,$04,$44,$38,$00,$00,$00,
+
+ 6, // $34 '4'
+ $00,$08,$18,$28,$28,$48,$48,$7C,$08,$08,$00,$00,$00,
+
+ 7, // $35 '5'
+ $00,$7C,$40,$40,$78,$44,$04,$04,$44,$38,$00,$00,$00,
+
+ 7, // $36 '6'
+ $00,$38,$44,$40,$78,$44,$44,$44,$44,$38,$00,$00,$00,
+
+ 6, // $37 '7'
+ $00,$7C,$04,$08,$08,$10,$10,$20,$20,$20,$00,$00,$00,
+
+ 7, // $38 '8'
+ $00,$38,$44,$44,$44,$38,$44,$44,$44,$38,$00,$00,$00,
+
+ 7, // $39 '9'
+ $00,$38,$44,$44,$44,$3C,$04,$04,$44,$38,$00,$00,$00,
+
+ 4, // $3A ':'
+ $00,$00,$00,$60,$60,$00,$00,$00,$60,$60,$00,$00,$00,
+
+ 4, // $3B ';'
+ $00,$00,$00,$60,$60,$00,$00,$00,$60,$60,$20,$40,$80,
+
+ 6, // $3C '<'
+ $00,$00,$04,$08,$10,$20,$40,$20,$10,$08,$04,$00,$00,
+
+ 6, // $3D '='
+ $00,$00,$00,$00,$7C,$00,$00,$7C,$00,$00,$00,$00,$00,
+
+ 6, // $3E '>'
+ $00,$00,$40,$20,$10,$08,$04,$08,$10,$20,$40,$00,$00,
+
+ 6, // $3F '?'
+ $00,$38,$44,$04,$04,$08,$10,$10,$00,$10,$00,$00,$00,
+
+ 7, // $40 '@'
+ $00,$38,$44,$44,$5C,$54,$54,$4C,$40,$38,$00,$00,$00,
+
+ 7, // $41 'A'
+ $00,$38,$44,$44,$44,$7C,$44,$44,$44,$44,$00,$00,$00,
+
+ 7, // $42 'B'
+ $00,$78,$44,$44,$44,$78,$44,$44,$44,$78,$00,$00,$00,
+
+ 6, // $43 'C'
+ $00,$38,$44,$40,$40,$40,$40,$40,$44,$38,$00,$00,$00,
+
+ 7, // $44 'D'
+ $00,$70,$48,$44,$44,$44,$44,$44,$48,$70,$00,$00,$00,
+
+ 6, // $45 'E'
+ $00,$7C,$40,$40,$40,$78,$40,$40,$40,$7C,$00,$00,$00,
+
+ 6, // $46 'F'
+ $00,$7C,$40,$40,$40,$78,$40,$40,$40,$40,$00,$00,$00,
+
+ 7, // $47 'G'
+ $00,$38,$44,$40,$40,$5C,$44,$44,$4C,$34,$00,$00,$00,
+
+ 7, // $48 'H'
+ $00,$44,$44,$44,$44,$7C,$44,$44,$44,$44,$00,$00,$00,
+
+ 5, // $49 'I'
+ $00,$70,$20,$20,$20,$20,$20,$20,$20,$70,$00,$00,$00,
+
+ 6, // $4A 'J'
+ $00,$1C,$08,$08,$08,$08,$08,$48,$48,$30,$00,$00,$00,
+
+ 6, // $4B 'K'
+ $00,$44,$48,$50,$60,$60,$50,$48,$44,$44,$00,$00,$00,
+
+ 6, // $4C 'L'
+ $00,$40,$40,$40,$40,$40,$40,$40,$40,$7C,$00,$00,$00,
+
+ 9, // $4D 'M'
+ $00,$00,$41,$00,$63,$00,$55,$00,$49,$00,$49,$00,$41,$00,$41,$00,$41,$00,$41,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $4E 'N'
+ $00,$44,$64,$64,$54,$54,$4C,$4C,$44,$44,$00,$00,$00,
+
+ 7, // $4F 'O'
+ $00,$38,$44,$44,$44,$44,$44,$44,$44,$38,$00,$00,$00,
+
+ 7, // $50 'P'
+ $00,$78,$44,$44,$44,$44,$78,$40,$40,$40,$00,$00,$00,
+
+ 7, // $51 'Q'
+ $00,$38,$44,$44,$44,$44,$44,$54,$48,$34,$00,$00,$00,
+
+ 7, // $52 'R'
+ $00,$78,$44,$44,$44,$44,$78,$48,$44,$44,$00,$00,$00,
+
+ 7, // $53 'S'
+ $00,$38,$44,$40,$40,$38,$04,$04,$44,$38,$00,$00,$00,
+
+ 6, // $54 'T'
+ $00,$7C,$10,$10,$10,$10,$10,$10,$10,$10,$00,$00,$00,
+
+ 7, // $55 'U'
+ $00,$44,$44,$44,$44,$44,$44,$44,$44,$38,$00,$00,$00,
+
+ 6, // $56 'V'
+ $00,$44,$44,$44,$44,$28,$28,$28,$10,$10,$00,$00,$00,
+
+ 9, // $57 'W'
+ $00,$00,$41,$00,$41,$00,$41,$00,$41,$00,$41,$00,$49,$00,$49,$00,$55,$00,$22,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $58 'X'
+ $00,$44,$44,$44,$28,$10,$28,$44,$44,$44,$00,$00,$00,
+
+ 7, // $59 'Y'
+ $00,$44,$44,$44,$44,$28,$10,$10,$10,$10,$00,$00,$00,
+
+ 6, // $5A 'Z'
+ $00,$7C,$04,$04,$08,$10,$20,$40,$40,$7C,$00,$00,$00,
+
+ 4, // $5B '['
+ $70,$40,$40,$40,$40,$40,$40,$40,$40,$40,$70,$00,$00,
+
+ 7, // $5C '\'
+ $00,$40,$40,$20,$20,$10,$10,$08,$08,$04,$04,$00,$00,
+
+ 4, // $5D ']'
+ $E0,$20,$20,$20,$20,$20,$20,$20,$20,$20,$E0,$00,$00,
+
+ 6, // $5E '^'
+ $00,$10,$28,$44,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 6, // $5F '_'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$7C,$00,$00,$00,
+
+ 4, // $60 '`'
+ $00,$40,$40,$20,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $61 'a'
+ $00,$00,$00,$38,$04,$3C,$44,$44,$44,$3C,$00,$00,$00,
+
+ 7, // $62 'b'
+ $00,$40,$40,$78,$44,$44,$44,$44,$44,$78,$00,$00,$00,
+
+ 6, // $63 'c'
+ $00,$00,$00,$38,$44,$40,$40,$40,$44,$38,$00,$00,$00,
+
+ 7, // $64 'd'
+ $00,$04,$04,$3C,$44,$44,$44,$44,$44,$3C,$00,$00,$00,
+
+ 7, // $65 'e'
+ $00,$00,$00,$38,$44,$44,$7C,$40,$44,$38,$00,$00,$00,
+
+ 4, // $66 'f'
+ $00,$30,$40,$E0,$40,$40,$40,$40,$40,$40,$00,$00,$00,
+
+ 7, // $67 'g'
+ $00,$00,$00,$3C,$44,$44,$44,$44,$44,$3C,$04,$44,$38,
+
+ 7, // $68 'h'
+ $00,$40,$40,$78,$44,$44,$44,$44,$44,$44,$00,$00,$00,
+
+ 3, // $69 'i'
+ $00,$40,$00,$40,$40,$40,$40,$40,$40,$40,$00,$00,$00,
+
+ 5, // $6A 'j'
+ $00,$10,$00,$10,$10,$10,$10,$10,$10,$10,$90,$60,$00,
+
+ 6, // $6B 'k'
+ $00,$40,$40,$44,$48,$50,$60,$50,$48,$44,$00,$00,$00,
+
+ 3, // $6C 'l'
+ $00,$40,$40,$40,$40,$40,$40,$40,$40,$40,$00,$00,$00,
+
+ 9, // $6D 'm'
+ $00,$00,$00,$00,$00,$00,$76,$00,$49,$00,$49,$00,$49,$00,$41,$00,$41,$00,$41,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $6E 'n'
+ $00,$00,$00,$58,$64,$44,$44,$44,$44,$44,$00,$00,$00,
+
+ 7, // $6F 'o'
+ $00,$00,$00,$38,$44,$44,$44,$44,$44,$38,$00,$00,$00,
+
+ 7, // $70 'p'
+ $00,$00,$00,$78,$44,$44,$44,$44,$44,$78,$40,$40,$40,
+
+ 7, // $71 'q'
+ $00,$00,$00,$3C,$44,$44,$44,$44,$44,$3C,$04,$04,$04,
+
+ 6, // $72 'r'
+ $00,$00,$00,$58,$24,$20,$20,$20,$20,$70,$00,$00,$00,
+
+ 7, // $73 's'
+ $00,$00,$00,$38,$44,$40,$38,$04,$44,$38,$00,$00,$00,
+
+ 5, // $74 't'
+ $00,$20,$20,$70,$20,$20,$20,$20,$20,$18,$00,$00,$00,
+
+ 7, // $75 'u'
+ $00,$00,$00,$44,$44,$44,$44,$44,$4C,$34,$00,$00,$00,
+
+ 6, // $76 'v'
+ $00,$00,$00,$44,$44,$44,$28,$28,$10,$10,$00,$00,$00,
+
+ 9, // $77 'w'
+ $00,$00,$00,$00,$00,$00,$41,$00,$41,$00,$41,$00,$49,$00,$49,$00,$49,$00,$36,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $78 'x'
+ $00,$00,$00,$44,$44,$28,$10,$28,$44,$44,$00,$00,$00,
+
+ 7, // $79 'y'
+ $00,$00,$00,$44,$44,$44,$44,$44,$44,$3C,$04,$08,$70,
+
+ 6, // $7A 'z'
+ $00,$00,$00,$7C,$04,$08,$10,$20,$40,$7C,$00,$00,$00,
+
+ 5, // $7B '{'
+ $18,$20,$20,$20,$20,$C0,$20,$20,$20,$20,$18,$00,$00,
+
+ 3, // $7C '|'
+ $00,$40,$40,$40,$40,$40,$40,$40,$40,$40,$40,$00,$00,
+
+ 5, // $7D '}'
+ $C0,$20,$20,$20,$20,$18,$20,$20,$20,$20,$C0,$00,$00,
+
+ 7, // $7E '~'
+ $00,$60,$92,$92,$0C,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $7F ''
+ $00,$10,$38,$6C,$44,$44,$7C,$00,$00,$00,$00,$00,$00,
+
+ 0 );
+
+ mcs5x10_mono : array[0..1252 ] of int8u = (
+ 10, 2, 32, 128-32,
+ $00,$00,$0B,$00,$16,$00,$21,$00,$2C,$00,$37,$00,$42,$00,$4D,$00,$58,$00,
+ $63,$00,$6E,$00,$79,$00,$84,$00,$8F,$00,$9A,$00,$A5,$00,$B0,$00,$BB,$00,
+ $C6,$00,$D1,$00,$DC,$00,$E7,$00,$F2,$00,$FD,$00,$08,$01,$13,$01,$1E,$01,
+ $29,$01,$34,$01,$3F,$01,$4A,$01,$55,$01,$60,$01,$6B,$01,$76,$01,$81,$01,
+ $8C,$01,$97,$01,$A2,$01,$AD,$01,$B8,$01,$C3,$01,$CE,$01,$D9,$01,$E4,$01,
+ $EF,$01,$FA,$01,$05,$02,$10,$02,$1B,$02,$26,$02,$31,$02,$3C,$02,$47,$02,
+ $52,$02,$5D,$02,$68,$02,$73,$02,$7E,$02,$89,$02,$94,$02,$9F,$02,$AA,$02,
+ $B5,$02,$C0,$02,$CB,$02,$D6,$02,$E1,$02,$EC,$02,$F7,$02,$02,$03,$0D,$03,
+ $18,$03,$23,$03,$2E,$03,$39,$03,$44,$03,$4F,$03,$5A,$03,$65,$03,$70,$03,
+ $7B,$03,$86,$03,$91,$03,$9C,$03,$A7,$03,$B2,$03,$BD,$03,$C8,$03,$D3,$03,
+ $DE,$03,$E9,$03,$F4,$03,$FF,$03,$0A,$04,$15,$04,
+
+ 5, // $20 ' '
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 5, // $21 '!'
+ $00,$20,$20,$20,$20,$20,$20,$00,$20,$00,
+
+ 5, // $22 '"'
+ $00,$50,$50,$A0,$00,$00,$00,$00,$00,$00,
+
+ 5, // $23 '#'
+ $00,$50,$50,$F8,$50,$50,$50,$F8,$50,$50,
+
+ 5, // $24 '$'
+ $00,$40,$60,$90,$80,$60,$10,$90,$60,$20,
+
+ 5, // $25 '%'
+ $00,$00,$90,$90,$20,$20,$40,$40,$90,$90,
+
+ 5, // $26 '&'
+ $00,$40,$A0,$A0,$A0,$40,$A8,$90,$90,$68,
+
+ 5, // $27 '''
+ $00,$20,$20,$40,$00,$00,$00,$00,$00,$00,
+
+ 5, // $28 '('
+ $10,$20,$20,$40,$40,$40,$40,$20,$20,$10,
+
+ 5, // $29 ')'
+ $40,$20,$20,$10,$10,$10,$10,$20,$20,$40,
+
+ 5, // $2A '*'
+ $00,$00,$90,$60,$F0,$60,$90,$00,$00,$00,
+
+ 5, // $2B '+'
+ $00,$00,$00,$20,$20,$F8,$20,$20,$00,$00,
+
+ 5, // $2C ','
+ $00,$00,$00,$00,$00,$00,$00,$60,$60,$C0,
+
+ 5, // $2D '-'
+ $00,$00,$00,$00,$00,$F0,$00,$00,$00,$00,
+
+ 5, // $2E '.'
+ $00,$00,$00,$00,$00,$00,$00,$60,$60,$00,
+
+ 5, // $2F '/'
+ $00,$08,$10,$10,$20,$20,$40,$40,$80,$00,
+
+ 5, // $30 '0'
+ $00,$70,$90,$90,$90,$90,$90,$90,$E0,$00,
+
+ 5, // $31 '1'
+ $00,$20,$60,$20,$20,$20,$20,$20,$70,$00,
+
+ 5, // $32 '2'
+ $00,$60,$90,$90,$10,$20,$40,$80,$F0,$00,
+
+ 5, // $33 '3'
+ $00,$60,$90,$10,$60,$10,$10,$90,$60,$00,
+
+ 5, // $34 '4'
+ $00,$10,$30,$50,$50,$90,$F0,$10,$10,$00,
+
+ 5, // $35 '5'
+ $00,$F0,$80,$80,$E0,$10,$10,$90,$60,$00,
+
+ 5, // $36 '6'
+ $00,$60,$80,$80,$E0,$90,$90,$90,$60,$00,
+
+ 5, // $37 '7'
+ $00,$F0,$10,$10,$20,$20,$40,$40,$40,$00,
+
+ 5, // $38 '8'
+ $00,$60,$90,$90,$60,$90,$90,$90,$60,$00,
+
+ 5, // $39 '9'
+ $00,$60,$90,$90,$90,$70,$10,$10,$60,$00,
+
+ 5, // $3A ':'
+ $00,$00,$00,$60,$60,$00,$00,$60,$60,$00,
+
+ 5, // $3B ';'
+ $00,$00,$00,$60,$60,$00,$00,$60,$60,$C0,
+
+ 5, // $3C '<'
+ $00,$08,$10,$20,$40,$80,$40,$20,$10,$08,
+
+ 5, // $3D '='
+ $00,$00,$00,$00,$F0,$00,$F0,$00,$00,$00,
+
+ 5, // $3E '>'
+ $00,$80,$40,$20,$10,$08,$10,$20,$40,$80,
+
+ 5, // $3F '?'
+ $00,$60,$90,$10,$10,$20,$40,$00,$40,$00,
+
+ 5, // $40 '@'
+ $00,$60,$90,$90,$B0,$B0,$80,$80,$70,$00,
+
+ 5, // $41 'A'
+ $00,$60,$90,$90,$90,$F0,$90,$90,$90,$00,
+
+ 5, // $42 'B'
+ $00,$E0,$90,$90,$E0,$90,$90,$90,$E0,$00,
+
+ 5, // $43 'C'
+ $00,$60,$90,$80,$80,$80,$80,$90,$60,$00,
+
+ 5, // $44 'D'
+ $00,$E0,$90,$90,$90,$90,$90,$90,$E0,$00,
+
+ 5, // $45 'E'
+ $00,$F0,$80,$80,$F0,$80,$80,$80,$F0,$00,
+
+ 5, // $46 'F'
+ $00,$F0,$80,$80,$F0,$80,$80,$80,$80,$00,
+
+ 5, // $47 'G'
+ $00,$60,$90,$80,$80,$B0,$90,$90,$60,$00,
+
+ 5, // $48 'H'
+ $00,$90,$90,$90,$90,$F0,$90,$90,$90,$00,
+
+ 5, // $49 'I'
+ $00,$70,$20,$20,$20,$20,$20,$20,$70,$00,
+
+ 5, // $4A 'J'
+ $00,$70,$20,$20,$20,$20,$20,$A0,$40,$00,
+
+ 5, // $4B 'K'
+ $00,$90,$A0,$A0,$C0,$C0,$A0,$A0,$90,$00,
+
+ 5, // $4C 'L'
+ $00,$80,$80,$80,$80,$80,$80,$80,$F0,$00,
+
+ 5, // $4D 'M'
+ $00,$90,$90,$F0,$F0,$90,$90,$90,$90,$00,
+
+ 5, // $4E 'N'
+ $00,$90,$90,$D0,$D0,$B0,$B0,$90,$90,$00,
+
+ 5, // $4F 'O'
+ $00,$60,$90,$90,$90,$90,$90,$90,$60,$00,
+
+ 5, // $50 'P'
+ $00,$E0,$90,$90,$90,$E0,$80,$80,$80,$00,
+
+ 5, // $51 'Q'
+ $00,$60,$90,$90,$90,$90,$90,$90,$60,$30,
+
+ 5, // $52 'R'
+ $00,$E0,$90,$90,$90,$E0,$A0,$90,$90,$00,
+
+ 5, // $53 'S'
+ $00,$60,$90,$80,$60,$10,$90,$90,$60,$00,
+
+ 5, // $54 'T'
+ $00,$F8,$20,$20,$20,$20,$20,$20,$20,$00,
+
+ 5, // $55 'U'
+ $00,$90,$90,$90,$90,$90,$90,$90,$60,$00,
+
+ 5, // $56 'V'
+ $00,$90,$90,$90,$50,$50,$50,$20,$20,$00,
+
+ 5, // $57 'W'
+ $00,$90,$90,$90,$90,$90,$F0,$F0,$90,$00,
+
+ 5, // $58 'X'
+ $00,$90,$90,$90,$60,$60,$90,$90,$90,$00,
+
+ 5, // $59 'Y'
+ $00,$88,$88,$88,$50,$20,$20,$20,$20,$00,
+
+ 5, // $5A 'Z'
+ $00,$F0,$10,$20,$20,$40,$40,$80,$F0,$00,
+
+ 5, // $5B '['
+ $60,$40,$40,$40,$40,$40,$40,$40,$40,$60,
+
+ 5, // $5C '\'
+ $80,$80,$40,$40,$20,$20,$10,$10,$08,$08,
+
+ 5, // $5D ']'
+ $60,$20,$20,$20,$20,$20,$20,$20,$20,$60,
+
+ 5, // $5E '^'
+ $00,$20,$50,$00,$00,$00,$00,$00,$00,$00,
+
+ 5, // $5F '_'
+ $00,$00,$00,$00,$00,$00,$00,$00,$F0,$00,
+
+ 5, // $60 '`'
+ $00,$40,$20,$00,$00,$00,$00,$00,$00,$00,
+
+ 5, // $61 'a'
+ $00,$00,$00,$60,$10,$70,$90,$90,$70,$00,
+
+ 5, // $62 'b'
+ $00,$80,$80,$E0,$90,$90,$90,$90,$E0,$00,
+
+ 5, // $63 'c'
+ $00,$00,$00,$60,$90,$80,$80,$90,$60,$00,
+
+ 5, // $64 'd'
+ $00,$10,$10,$70,$90,$90,$90,$90,$70,$00,
+
+ 5, // $65 'e'
+ $00,$00,$00,$60,$90,$90,$F0,$80,$70,$00,
+
+ 5, // $66 'f'
+ $00,$30,$40,$E0,$40,$40,$40,$40,$40,$00,
+
+ 5, // $67 'g'
+ $00,$00,$00,$70,$90,$90,$90,$70,$10,$E0,
+
+ 5, // $68 'h'
+ $00,$80,$80,$E0,$90,$90,$90,$90,$90,$00,
+
+ 5, // $69 'i'
+ $00,$20,$00,$60,$20,$20,$20,$20,$70,$00,
+
+ 5, // $6A 'j'
+ $00,$20,$00,$60,$20,$20,$20,$20,$20,$C0,
+
+ 5, // $6B 'k'
+ $00,$80,$80,$90,$A0,$C0,$A0,$90,$90,$00,
+
+ 5, // $6C 'l'
+ $00,$60,$20,$20,$20,$20,$20,$20,$70,$00,
+
+ 5, // $6D 'm'
+ $00,$00,$00,$90,$F0,$90,$90,$90,$90,$00,
+
+ 5, // $6E 'n'
+ $00,$00,$00,$E0,$90,$90,$90,$90,$90,$00,
+
+ 5, // $6F 'o'
+ $00,$00,$00,$60,$90,$90,$90,$90,$60,$00,
+
+ 5, // $70 'p'
+ $00,$00,$00,$E0,$90,$90,$90,$E0,$80,$80,
+
+ 5, // $71 'q'
+ $00,$00,$00,$70,$90,$90,$90,$70,$10,$10,
+
+ 5, // $72 'r'
+ $00,$00,$00,$B0,$50,$40,$40,$40,$E0,$00,
+
+ 5, // $73 's'
+ $00,$00,$00,$60,$90,$40,$20,$90,$60,$00,
+
+ 5, // $74 't'
+ $00,$40,$40,$E0,$40,$40,$40,$50,$20,$00,
+
+ 5, // $75 'u'
+ $00,$00,$00,$90,$90,$90,$90,$90,$70,$00,
+
+ 5, // $76 'v'
+ $00,$00,$00,$90,$90,$50,$50,$20,$20,$00,
+
+ 5, // $77 'w'
+ $00,$00,$00,$90,$90,$90,$90,$F0,$90,$00,
+
+ 5, // $78 'x'
+ $00,$00,$00,$90,$90,$60,$60,$90,$90,$00,
+
+ 5, // $79 'y'
+ $00,$00,$00,$90,$90,$90,$90,$70,$10,$E0,
+
+ 5, // $7A 'z'
+ $00,$00,$00,$F0,$10,$20,$40,$80,$F0,$00,
+
+ 5, // $7B '{'
+ $30,$40,$40,$40,$80,$40,$40,$40,$40,$30,
+
+ 5, // $7C '|'
+ $00,$20,$20,$20,$20,$20,$20,$20,$20,$20,
+
+ 5, // $7D '}'
+ $C0,$20,$20,$20,$10,$20,$20,$20,$20,$C0,
+
+ 5, // $7E '~'
+ $00,$40,$A8,$10,$00,$00,$00,$00,$00,$00,
+
+ 5, // $7F ''
+ $00,$20,$70,$D8,$88,$88,$F8,$00,$00,$00,
+
+ 0 );
+
+ mcs5x11_mono : array[0..1348 ] of int8u = (
+ 11, 3, 32, 128-32,
+ $00,$00,$0C,$00,$18,$00,$24,$00,$30,$00,$3C,$00,$48,$00,$54,$00,$60,$00,
+ $6C,$00,$78,$00,$84,$00,$90,$00,$9C,$00,$A8,$00,$B4,$00,$C0,$00,$CC,$00,
+ $D8,$00,$E4,$00,$F0,$00,$FC,$00,$08,$01,$14,$01,$20,$01,$2C,$01,$38,$01,
+ $44,$01,$50,$01,$5C,$01,$68,$01,$74,$01,$80,$01,$8C,$01,$98,$01,$A4,$01,
+ $B0,$01,$BC,$01,$C8,$01,$D4,$01,$E0,$01,$EC,$01,$F8,$01,$04,$02,$10,$02,
+ $1C,$02,$28,$02,$34,$02,$40,$02,$4C,$02,$58,$02,$64,$02,$70,$02,$7C,$02,
+ $88,$02,$94,$02,$A0,$02,$AC,$02,$B8,$02,$C4,$02,$D0,$02,$DC,$02,$E8,$02,
+ $F4,$02,$00,$03,$0C,$03,$18,$03,$24,$03,$30,$03,$3C,$03,$48,$03,$54,$03,
+ $60,$03,$6C,$03,$78,$03,$84,$03,$90,$03,$9C,$03,$A8,$03,$B4,$03,$C0,$03,
+ $CC,$03,$D8,$03,$E4,$03,$F0,$03,$FC,$03,$08,$04,$14,$04,$20,$04,$2C,$04,
+ $38,$04,$44,$04,$50,$04,$5C,$04,$68,$04,$74,$04,
+
+ 5, // $20 ' '
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 5, // $21 '!'
+ $00,$20,$20,$20,$20,$20,$20,$00,$20,$00,$00,
+
+ 5, // $22 '"'
+ $00,$50,$50,$A0,$00,$00,$00,$00,$00,$00,$00,
+
+ 5, // $23 '#'
+ $00,$50,$50,$F8,$50,$50,$50,$F8,$50,$50,$00,
+
+ 5, // $24 '$'
+ $00,$40,$60,$90,$80,$60,$10,$90,$60,$20,$00,
+
+ 5, // $25 '%'
+ $00,$00,$90,$90,$20,$20,$40,$40,$90,$90,$00,
+
+ 5, // $26 '&'
+ $00,$40,$A0,$A0,$40,$A8,$90,$90,$68,$00,$00,
+
+ 5, // $27 '''
+ $00,$20,$20,$40,$00,$00,$00,$00,$00,$00,$00,
+
+ 5, // $28 '('
+ $00,$10,$20,$20,$40,$40,$40,$40,$20,$20,$10,
+
+ 5, // $29 ')'
+ $00,$40,$20,$20,$10,$10,$10,$10,$20,$20,$40,
+
+ 5, // $2A '*'
+ $00,$00,$90,$60,$F0,$60,$90,$00,$00,$00,$00,
+
+ 5, // $2B '+'
+ $00,$00,$00,$20,$20,$F8,$20,$20,$00,$00,$00,
+
+ 5, // $2C ','
+ $00,$00,$00,$00,$00,$00,$00,$60,$60,$40,$80,
+
+ 5, // $2D '-'
+ $00,$00,$00,$00,$00,$F0,$00,$00,$00,$00,$00,
+
+ 5, // $2E '.'
+ $00,$00,$00,$00,$00,$00,$00,$60,$60,$00,$00,
+
+ 5, // $2F '/'
+ $08,$08,$10,$10,$20,$20,$40,$40,$80,$80,$00,
+
+ 5, // $30 '0'
+ $00,$70,$90,$90,$90,$90,$90,$90,$E0,$00,$00,
+
+ 5, // $31 '1'
+ $00,$20,$60,$20,$20,$20,$20,$20,$70,$00,$00,
+
+ 5, // $32 '2'
+ $00,$60,$90,$90,$10,$20,$40,$80,$F0,$00,$00,
+
+ 5, // $33 '3'
+ $00,$60,$90,$10,$60,$10,$10,$90,$60,$00,$00,
+
+ 5, // $34 '4'
+ $00,$10,$30,$50,$50,$90,$F8,$10,$10,$00,$00,
+
+ 5, // $35 '5'
+ $00,$F0,$80,$E0,$90,$10,$10,$90,$60,$00,$00,
+
+ 5, // $36 '6'
+ $00,$60,$90,$80,$E0,$90,$90,$90,$60,$00,$00,
+
+ 5, // $37 '7'
+ $00,$F0,$10,$10,$20,$20,$40,$40,$40,$00,$00,
+
+ 5, // $38 '8'
+ $00,$60,$90,$90,$60,$90,$90,$90,$60,$00,$00,
+
+ 5, // $39 '9'
+ $00,$60,$90,$90,$90,$70,$10,$90,$60,$00,$00,
+
+ 5, // $3A ':'
+ $00,$00,$00,$60,$60,$00,$00,$60,$60,$00,$00,
+
+ 5, // $3B ';'
+ $00,$00,$00,$60,$60,$00,$00,$60,$60,$40,$80,
+
+ 5, // $3C '<'
+ $00,$08,$10,$20,$40,$80,$40,$20,$10,$08,$00,
+
+ 5, // $3D '='
+ $00,$00,$00,$00,$F0,$00,$00,$F0,$00,$00,$00,
+
+ 5, // $3E '>'
+ $00,$80,$40,$20,$10,$08,$10,$20,$40,$80,$00,
+
+ 5, // $3F '?'
+ $00,$60,$90,$10,$10,$20,$40,$00,$40,$00,$00,
+
+ 5, // $40 '@'
+ $00,$60,$90,$90,$B0,$B0,$80,$80,$70,$00,$00,
+
+ 5, // $41 'A'
+ $00,$60,$90,$90,$90,$F0,$90,$90,$90,$00,$00,
+
+ 5, // $42 'B'
+ $00,$E0,$90,$90,$E0,$90,$90,$90,$E0,$00,$00,
+
+ 5, // $43 'C'
+ $00,$60,$90,$80,$80,$80,$80,$90,$60,$00,$00,
+
+ 5, // $44 'D'
+ $00,$E0,$90,$90,$90,$90,$90,$90,$E0,$00,$00,
+
+ 5, // $45 'E'
+ $00,$F0,$80,$80,$E0,$80,$80,$80,$F0,$00,$00,
+
+ 5, // $46 'F'
+ $00,$F0,$80,$80,$E0,$80,$80,$80,$80,$00,$00,
+
+ 5, // $47 'G'
+ $00,$60,$90,$80,$80,$B0,$90,$90,$60,$00,$00,
+
+ 5, // $48 'H'
+ $00,$90,$90,$90,$F0,$90,$90,$90,$90,$00,$00,
+
+ 5, // $49 'I'
+ $00,$70,$20,$20,$20,$20,$20,$20,$70,$00,$00,
+
+ 5, // $4A 'J'
+ $00,$70,$20,$20,$20,$20,$A0,$A0,$40,$00,$00,
+
+ 5, // $4B 'K'
+ $00,$90,$A0,$A0,$C0,$A0,$A0,$90,$90,$00,$00,
+
+ 5, // $4C 'L'
+ $00,$80,$80,$80,$80,$80,$80,$80,$F0,$00,$00,
+
+ 5, // $4D 'M'
+ $00,$90,$F0,$F0,$90,$90,$90,$90,$90,$00,$00,
+
+ 5, // $4E 'N'
+ $00,$90,$90,$D0,$D0,$B0,$B0,$90,$90,$00,$00,
+
+ 5, // $4F 'O'
+ $00,$60,$90,$90,$90,$90,$90,$90,$60,$00,$00,
+
+ 5, // $50 'P'
+ $00,$E0,$90,$90,$90,$E0,$80,$80,$80,$00,$00,
+
+ 5, // $51 'Q'
+ $00,$60,$90,$90,$90,$90,$90,$90,$60,$30,$00,
+
+ 5, // $52 'R'
+ $00,$E0,$90,$90,$90,$E0,$A0,$90,$90,$00,$00,
+
+ 5, // $53 'S'
+ $00,$60,$90,$80,$60,$10,$90,$90,$60,$00,$00,
+
+ 5, // $54 'T'
+ $00,$F8,$20,$20,$20,$20,$20,$20,$20,$00,$00,
+
+ 5, // $55 'U'
+ $00,$90,$90,$90,$90,$90,$90,$90,$60,$00,$00,
+
+ 5, // $56 'V'
+ $00,$90,$90,$90,$50,$50,$50,$20,$20,$00,$00,
+
+ 5, // $57 'W'
+ $00,$90,$90,$90,$90,$90,$F0,$F0,$90,$00,$00,
+
+ 5, // $58 'X'
+ $00,$90,$90,$90,$60,$60,$90,$90,$90,$00,$00,
+
+ 5, // $59 'Y'
+ $00,$88,$88,$88,$50,$20,$20,$20,$20,$00,$00,
+
+ 5, // $5A 'Z'
+ $00,$F0,$10,$20,$20,$40,$40,$80,$F0,$00,$00,
+
+ 5, // $5B '['
+ $00,$60,$40,$40,$40,$40,$40,$40,$40,$40,$60,
+
+ 5, // $5C '\'
+ $80,$80,$40,$40,$20,$20,$10,$10,$08,$08,$00,
+
+ 5, // $5D ']'
+ $00,$60,$20,$20,$20,$20,$20,$20,$20,$20,$60,
+
+ 5, // $5E '^'
+ $00,$20,$50,$88,$00,$00,$00,$00,$00,$00,$00,
+
+ 5, // $5F '_'
+ $00,$00,$00,$00,$00,$00,$00,$00,$F0,$00,$00,
+
+ 5, // $60 '`'
+ $00,$40,$40,$20,$00,$00,$00,$00,$00,$00,$00,
+
+ 5, // $61 'a'
+ $00,$00,$00,$60,$10,$70,$90,$90,$70,$00,$00,
+
+ 5, // $62 'b'
+ $00,$80,$80,$E0,$90,$90,$90,$90,$E0,$00,$00,
+
+ 5, // $63 'c'
+ $00,$00,$00,$60,$90,$80,$80,$90,$60,$00,$00,
+
+ 5, // $64 'd'
+ $00,$10,$10,$70,$90,$90,$90,$90,$70,$00,$00,
+
+ 5, // $65 'e'
+ $00,$00,$00,$60,$90,$90,$F0,$80,$70,$00,$00,
+
+ 5, // $66 'f'
+ $00,$30,$40,$E0,$40,$40,$40,$40,$40,$00,$00,
+
+ 5, // $67 'g'
+ $00,$00,$00,$70,$90,$90,$90,$90,$70,$10,$E0,
+
+ 5, // $68 'h'
+ $00,$80,$80,$E0,$90,$90,$90,$90,$90,$00,$00,
+
+ 5, // $69 'i'
+ $00,$20,$00,$60,$20,$20,$20,$20,$70,$00,$00,
+
+ 5, // $6A 'j'
+ $00,$20,$00,$60,$20,$20,$20,$20,$20,$A0,$40,
+
+ 5, // $6B 'k'
+ $00,$80,$80,$90,$A0,$C0,$A0,$90,$90,$00,$00,
+
+ 5, // $6C 'l'
+ $00,$60,$20,$20,$20,$20,$20,$20,$70,$00,$00,
+
+ 5, // $6D 'm'
+ $00,$00,$00,$90,$F0,$90,$90,$90,$90,$00,$00,
+
+ 5, // $6E 'n'
+ $00,$00,$00,$E0,$90,$90,$90,$90,$90,$00,$00,
+
+ 5, // $6F 'o'
+ $00,$00,$00,$60,$90,$90,$90,$90,$60,$00,$00,
+
+ 5, // $70 'p'
+ $00,$00,$00,$E0,$90,$90,$90,$90,$E0,$80,$80,
+
+ 5, // $71 'q'
+ $00,$00,$00,$70,$90,$90,$90,$90,$70,$10,$10,
+
+ 5, // $72 'r'
+ $00,$00,$00,$A0,$50,$40,$40,$40,$E0,$00,$00,
+
+ 5, // $73 's'
+ $00,$00,$00,$60,$90,$40,$20,$90,$60,$00,$00,
+
+ 5, // $74 't'
+ $00,$40,$40,$E0,$40,$40,$40,$40,$30,$00,$00,
+
+ 5, // $75 'u'
+ $00,$00,$00,$90,$90,$90,$90,$90,$70,$00,$00,
+
+ 5, // $76 'v'
+ $00,$00,$00,$90,$90,$50,$50,$20,$20,$00,$00,
+
+ 5, // $77 'w'
+ $00,$00,$00,$90,$90,$90,$90,$F0,$90,$00,$00,
+
+ 5, // $78 'x'
+ $00,$00,$00,$90,$90,$60,$60,$90,$90,$00,$00,
+
+ 5, // $79 'y'
+ $00,$00,$00,$90,$90,$90,$90,$90,$70,$10,$E0,
+
+ 5, // $7A 'z'
+ $00,$00,$00,$F0,$10,$20,$40,$80,$F0,$00,$00,
+
+ 5, // $7B '{'
+ $30,$40,$40,$40,$40,$80,$40,$40,$40,$40,$30,
+
+ 5, // $7C '|'
+ $00,$20,$20,$20,$20,$00,$20,$20,$20,$20,$00,
+
+ 5, // $7D '}'
+ $C0,$20,$20,$20,$20,$10,$20,$20,$20,$20,$C0,
+
+ 5, // $7E '~'
+ $00,$40,$A8,$10,$00,$00,$00,$00,$00,$00,$00,
+
+ 5, // $7F ''
+ $00,$20,$70,$D8,$88,$88,$F8,$00,$00,$00,$00,
+
+ 0 );
+
+ mcs6x10_mono : array[0..1252 ] of int8u = (
+ 10, 3, 32, 128-32,
+ $00,$00,$0B,$00,$16,$00,$21,$00,$2C,$00,$37,$00,$42,$00,$4D,$00,$58,$00,
+ $63,$00,$6E,$00,$79,$00,$84,$00,$8F,$00,$9A,$00,$A5,$00,$B0,$00,$BB,$00,
+ $C6,$00,$D1,$00,$DC,$00,$E7,$00,$F2,$00,$FD,$00,$08,$01,$13,$01,$1E,$01,
+ $29,$01,$34,$01,$3F,$01,$4A,$01,$55,$01,$60,$01,$6B,$01,$76,$01,$81,$01,
+ $8C,$01,$97,$01,$A2,$01,$AD,$01,$B8,$01,$C3,$01,$CE,$01,$D9,$01,$E4,$01,
+ $EF,$01,$FA,$01,$05,$02,$10,$02,$1B,$02,$26,$02,$31,$02,$3C,$02,$47,$02,
+ $52,$02,$5D,$02,$68,$02,$73,$02,$7E,$02,$89,$02,$94,$02,$9F,$02,$AA,$02,
+ $B5,$02,$C0,$02,$CB,$02,$D6,$02,$E1,$02,$EC,$02,$F7,$02,$02,$03,$0D,$03,
+ $18,$03,$23,$03,$2E,$03,$39,$03,$44,$03,$4F,$03,$5A,$03,$65,$03,$70,$03,
+ $7B,$03,$86,$03,$91,$03,$9C,$03,$A7,$03,$B2,$03,$BD,$03,$C8,$03,$D3,$03,
+ $DE,$03,$E9,$03,$F4,$03,$FF,$03,$0A,$04,$15,$04,
+
+ 6, // $20 ' '
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 6, // $21 '!'
+ $00,$10,$10,$10,$10,$10,$00,$10,$00,$00,
+
+ 6, // $22 '"'
+ $00,$28,$28,$50,$00,$00,$00,$00,$00,$00,
+
+ 6, // $23 '#'
+ $00,$28,$28,$7C,$28,$28,$7C,$28,$28,$00,
+
+ 6, // $24 '$'
+ $10,$38,$54,$50,$38,$14,$54,$38,$10,$00,
+
+ 6, // $25 '%'
+ $00,$08,$C8,$D0,$10,$20,$2C,$4C,$40,$00,
+
+ 6, // $26 '&'
+ $00,$20,$50,$50,$24,$54,$48,$34,$00,$00,
+
+ 6, // $27 '''
+ $00,$10,$10,$20,$00,$00,$00,$00,$00,$00,
+
+ 6, // $28 '('
+ $08,$10,$10,$20,$20,$20,$10,$10,$08,$00,
+
+ 6, // $29 ')'
+ $20,$10,$10,$08,$08,$08,$10,$10,$20,$00,
+
+ 6, // $2A '*'
+ $00,$00,$28,$7C,$38,$7C,$28,$00,$00,$00,
+
+ 6, // $2B '+'
+ $00,$00,$10,$10,$7C,$10,$10,$00,$00,$00,
+
+ 6, // $2C ','
+ $00,$00,$00,$00,$00,$00,$30,$30,$20,$40,
+
+ 6, // $2D '-'
+ $00,$00,$00,$00,$7C,$00,$00,$00,$00,$00,
+
+ 6, // $2E '.'
+ $00,$00,$00,$00,$00,$00,$30,$30,$00,$00,
+
+ 6, // $2F '/'
+ $00,$08,$08,$10,$10,$20,$20,$40,$40,$00,
+
+ 6, // $30 '0'
+ $00,$38,$44,$4C,$54,$64,$44,$38,$00,$00,
+
+ 6, // $31 '1'
+ $00,$10,$30,$10,$10,$10,$10,$38,$00,$00,
+
+ 6, // $32 '2'
+ $00,$38,$44,$04,$18,$20,$40,$7C,$00,$00,
+
+ 6, // $33 '3'
+ $00,$38,$44,$04,$38,$04,$44,$38,$00,$00,
+
+ 6, // $34 '4'
+ $00,$08,$18,$28,$48,$7C,$08,$08,$00,$00,
+
+ 6, // $35 '5'
+ $00,$7C,$40,$40,$78,$04,$44,$38,$00,$00,
+
+ 6, // $36 '6'
+ $00,$38,$40,$40,$78,$44,$44,$38,$00,$00,
+
+ 6, // $37 '7'
+ $00,$7C,$04,$08,$10,$20,$20,$20,$00,$00,
+
+ 6, // $38 '8'
+ $00,$38,$44,$44,$38,$44,$44,$38,$00,$00,
+
+ 6, // $39 '9'
+ $00,$38,$44,$44,$3C,$04,$04,$38,$00,$00,
+
+ 6, // $3A ':'
+ $00,$00,$30,$30,$00,$00,$30,$30,$00,$00,
+
+ 6, // $3B ';'
+ $00,$00,$30,$30,$00,$00,$30,$30,$20,$40,
+
+ 6, // $3C '<'
+ $04,$08,$10,$20,$40,$20,$10,$08,$04,$00,
+
+ 6, // $3D '='
+ $00,$00,$00,$7C,$00,$00,$7C,$00,$00,$00,
+
+ 6, // $3E '>'
+ $40,$20,$10,$08,$04,$08,$10,$20,$40,$00,
+
+ 6, // $3F '?'
+ $00,$38,$44,$04,$18,$10,$00,$10,$00,$00,
+
+ 6, // $40 '@'
+ $00,$38,$44,$5C,$54,$5C,$40,$38,$00,$00,
+
+ 6, // $41 'A'
+ $00,$38,$44,$44,$44,$7C,$44,$44,$00,$00,
+
+ 6, // $42 'B'
+ $00,$78,$44,$44,$78,$44,$44,$78,$00,$00,
+
+ 6, // $43 'C'
+ $00,$38,$44,$40,$40,$40,$44,$38,$00,$00,
+
+ 6, // $44 'D'
+ $00,$78,$44,$44,$44,$44,$44,$78,$00,$00,
+
+ 6, // $45 'E'
+ $00,$7C,$40,$40,$78,$40,$40,$7C,$00,$00,
+
+ 6, // $46 'F'
+ $00,$7C,$40,$40,$78,$40,$40,$40,$00,$00,
+
+ 6, // $47 'G'
+ $00,$38,$44,$40,$4C,$44,$44,$3C,$00,$00,
+
+ 6, // $48 'H'
+ $00,$44,$44,$44,$7C,$44,$44,$44,$00,$00,
+
+ 6, // $49 'I'
+ $00,$38,$10,$10,$10,$10,$10,$38,$00,$00,
+
+ 6, // $4A 'J'
+ $00,$1C,$08,$08,$08,$48,$48,$30,$00,$00,
+
+ 6, // $4B 'K'
+ $00,$44,$48,$50,$60,$50,$48,$44,$00,$00,
+
+ 6, // $4C 'L'
+ $00,$40,$40,$40,$40,$40,$40,$7C,$00,$00,
+
+ 6, // $4D 'M'
+ $00,$44,$6C,$54,$54,$44,$44,$44,$00,$00,
+
+ 6, // $4E 'N'
+ $00,$44,$44,$64,$54,$4C,$44,$44,$00,$00,
+
+ 6, // $4F 'O'
+ $00,$38,$44,$44,$44,$44,$44,$38,$00,$00,
+
+ 6, // $50 'P'
+ $00,$78,$44,$44,$78,$40,$40,$40,$00,$00,
+
+ 6, // $51 'Q'
+ $00,$38,$44,$44,$44,$54,$48,$34,$00,$00,
+
+ 6, // $52 'R'
+ $00,$78,$44,$44,$78,$48,$44,$44,$00,$00,
+
+ 6, // $53 'S'
+ $00,$38,$44,$40,$38,$04,$44,$38,$00,$00,
+
+ 6, // $54 'T'
+ $00,$7C,$10,$10,$10,$10,$10,$10,$00,$00,
+
+ 6, // $55 'U'
+ $00,$44,$44,$44,$44,$44,$44,$38,$00,$00,
+
+ 6, // $56 'V'
+ $00,$44,$44,$44,$44,$28,$28,$10,$00,$00,
+
+ 6, // $57 'W'
+ $00,$44,$44,$54,$54,$54,$54,$28,$00,$00,
+
+ 6, // $58 'X'
+ $00,$44,$44,$28,$10,$28,$44,$44,$00,$00,
+
+ 6, // $59 'Y'
+ $00,$44,$44,$44,$28,$10,$10,$10,$00,$00,
+
+ 6, // $5A 'Z'
+ $00,$78,$08,$10,$20,$40,$40,$78,$00,$00,
+
+ 6, // $5B '['
+ $38,$20,$20,$20,$20,$20,$20,$20,$38,$00,
+
+ 6, // $5C '\'
+ $00,$40,$40,$20,$20,$10,$10,$08,$08,$00,
+
+ 6, // $5D ']'
+ $38,$08,$08,$08,$08,$08,$08,$08,$38,$00,
+
+ 6, // $5E '^'
+ $10,$28,$44,$00,$00,$00,$00,$00,$00,$00,
+
+ 6, // $5F '_'
+ $00,$00,$00,$00,$00,$00,$00,$7C,$00,$00,
+
+ 6, // $60 '`'
+ $00,$10,$10,$20,$00,$00,$00,$00,$00,$00,
+
+ 6, // $61 'a'
+ $00,$00,$00,$38,$04,$3C,$44,$3C,$00,$00,
+
+ 6, // $62 'b'
+ $00,$40,$40,$78,$44,$44,$44,$78,$00,$00,
+
+ 6, // $63 'c'
+ $00,$00,$00,$38,$44,$40,$40,$3C,$00,$00,
+
+ 6, // $64 'd'
+ $00,$04,$04,$3C,$44,$44,$44,$3C,$00,$00,
+
+ 6, // $65 'e'
+ $00,$00,$00,$38,$44,$78,$40,$3C,$00,$00,
+
+ 6, // $66 'f'
+ $00,$0C,$10,$10,$38,$10,$10,$10,$00,$00,
+
+ 6, // $67 'g'
+ $00,$00,$00,$3C,$44,$44,$44,$3C,$04,$38,
+
+ 6, // $68 'h'
+ $00,$40,$40,$78,$44,$44,$44,$44,$00,$00,
+
+ 6, // $69 'i'
+ $00,$10,$00,$30,$10,$10,$10,$38,$00,$00,
+
+ 6, // $6A 'j'
+ $00,$08,$00,$18,$08,$08,$08,$08,$48,$30,
+
+ 6, // $6B 'k'
+ $00,$40,$40,$48,$50,$60,$50,$48,$00,$00,
+
+ 6, // $6C 'l'
+ $00,$30,$10,$10,$10,$10,$10,$38,$00,$00,
+
+ 6, // $6D 'm'
+ $00,$00,$00,$68,$54,$54,$44,$44,$00,$00,
+
+ 6, // $6E 'n'
+ $00,$00,$00,$58,$64,$44,$44,$44,$00,$00,
+
+ 6, // $6F 'o'
+ $00,$00,$00,$38,$44,$44,$44,$38,$00,$00,
+
+ 6, // $70 'p'
+ $00,$00,$00,$78,$44,$44,$44,$78,$40,$40,
+
+ 6, // $71 'q'
+ $00,$00,$00,$3C,$44,$44,$44,$3C,$04,$04,
+
+ 6, // $72 'r'
+ $00,$00,$00,$58,$24,$20,$20,$70,$00,$00,
+
+ 6, // $73 's'
+ $00,$00,$00,$38,$40,$38,$04,$78,$00,$00,
+
+ 6, // $74 't'
+ $00,$10,$10,$38,$10,$10,$14,$08,$00,$00,
+
+ 6, // $75 'u'
+ $00,$00,$00,$44,$44,$44,$4C,$34,$00,$00,
+
+ 6, // $76 'v'
+ $00,$00,$00,$44,$44,$44,$28,$10,$00,$00,
+
+ 6, // $77 'w'
+ $00,$00,$00,$44,$44,$54,$7C,$28,$00,$00,
+
+ 6, // $78 'x'
+ $00,$00,$00,$48,$48,$30,$48,$48,$00,$00,
+
+ 6, // $79 'y'
+ $00,$00,$00,$44,$44,$44,$44,$3C,$04,$38,
+
+ 6, // $7A 'z'
+ $00,$00,$00,$78,$08,$30,$40,$78,$00,$00,
+
+ 6, // $7B '{'
+ $18,$20,$20,$20,$C0,$20,$20,$20,$18,$00,
+
+ 6, // $7C '|'
+ $10,$10,$10,$10,$00,$10,$10,$10,$10,$00,
+
+ 6, // $7D '}'
+ $60,$10,$10,$10,$0C,$10,$10,$10,$60,$00,
+
+ 6, // $7E '~'
+ $00,$48,$A8,$90,$00,$00,$00,$00,$00,$00,
+
+ 6, // $7F ''
+ $00,$10,$38,$6C,$44,$44,$7C,$00,$00,$00,
+
+ 0 );
+
+ mcs6x11_mono : array[0..1348 ] of int8u = (
+ 11, 3, 32, 128-32,
+ $00,$00,$0C,$00,$18,$00,$24,$00,$30,$00,$3C,$00,$48,$00,$54,$00,$60,$00,
+ $6C,$00,$78,$00,$84,$00,$90,$00,$9C,$00,$A8,$00,$B4,$00,$C0,$00,$CC,$00,
+ $D8,$00,$E4,$00,$F0,$00,$FC,$00,$08,$01,$14,$01,$20,$01,$2C,$01,$38,$01,
+ $44,$01,$50,$01,$5C,$01,$68,$01,$74,$01,$80,$01,$8C,$01,$98,$01,$A4,$01,
+ $B0,$01,$BC,$01,$C8,$01,$D4,$01,$E0,$01,$EC,$01,$F8,$01,$04,$02,$10,$02,
+ $1C,$02,$28,$02,$34,$02,$40,$02,$4C,$02,$58,$02,$64,$02,$70,$02,$7C,$02,
+ $88,$02,$94,$02,$A0,$02,$AC,$02,$B8,$02,$C4,$02,$D0,$02,$DC,$02,$E8,$02,
+ $F4,$02,$00,$03,$0C,$03,$18,$03,$24,$03,$30,$03,$3C,$03,$48,$03,$54,$03,
+ $60,$03,$6C,$03,$78,$03,$84,$03,$90,$03,$9C,$03,$A8,$03,$B4,$03,$C0,$03,
+ $CC,$03,$D8,$03,$E4,$03,$F0,$03,$FC,$03,$08,$04,$14,$04,$20,$04,$2C,$04,
+ $38,$04,$44,$04,$50,$04,$5C,$04,$68,$04,$74,$04,
+
+ 6, // $20 ' '
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 6, // $21 '!'
+ $00,$20,$20,$20,$20,$20,$20,$00,$20,$00,$00,
+
+ 6, // $22 '"'
+ $00,$28,$28,$50,$00,$00,$00,$00,$00,$00,$00,
+
+ 6, // $23 '#'
+ $00,$28,$28,$7C,$28,$28,$7C,$28,$28,$00,$00,
+
+ 6, // $24 '$'
+ $00,$10,$38,$54,$50,$38,$14,$54,$38,$10,$00,
+
+ 6, // $25 '%'
+ $00,$68,$A8,$D0,$10,$20,$2C,$54,$58,$00,$00,
+
+ 6, // $26 '&'
+ $00,$20,$50,$50,$20,$54,$54,$48,$34,$00,$00,
+
+ 6, // $27 '''
+ $00,$10,$10,$20,$00,$00,$00,$00,$00,$00,$00,
+
+ 6, // $28 '('
+ $08,$10,$10,$20,$20,$20,$20,$10,$10,$08,$00,
+
+ 6, // $29 ')'
+ $20,$10,$10,$08,$08,$08,$08,$10,$10,$20,$00,
+
+ 6, // $2A '*'
+ $00,$00,$28,$7C,$38,$7C,$28,$00,$00,$00,$00,
+
+ 6, // $2B '+'
+ $00,$00,$00,$10,$10,$7C,$10,$10,$00,$00,$00,
+
+ 6, // $2C ','
+ $00,$00,$00,$00,$00,$00,$00,$30,$30,$20,$40,
+
+ 6, // $2D '-'
+ $00,$00,$00,$00,$00,$7C,$00,$00,$00,$00,$00,
+
+ 6, // $2E '.'
+ $00,$00,$00,$00,$00,$00,$00,$30,$30,$00,$00,
+
+ 6, // $2F '/'
+ $04,$04,$08,$08,$10,$10,$20,$20,$40,$40,$00,
+
+ 6, // $30 '0'
+ $00,$38,$44,$44,$54,$54,$44,$44,$38,$00,$00,
+
+ 6, // $31 '1'
+ $00,$10,$30,$10,$10,$10,$10,$10,$38,$00,$00,
+
+ 6, // $32 '2'
+ $00,$38,$44,$44,$08,$10,$20,$40,$7C,$00,$00,
+
+ 6, // $33 '3'
+ $00,$38,$44,$04,$38,$04,$04,$44,$38,$00,$00,
+
+ 6, // $34 '4'
+ $00,$08,$18,$28,$28,$48,$7C,$08,$08,$00,$00,
+
+ 6, // $35 '5'
+ $00,$7C,$40,$78,$44,$04,$04,$44,$38,$00,$00,
+
+ 6, // $36 '6'
+ $00,$38,$44,$40,$78,$44,$44,$44,$38,$00,$00,
+
+ 6, // $37 '7'
+ $00,$7C,$04,$08,$08,$10,$10,$20,$20,$00,$00,
+
+ 6, // $38 '8'
+ $00,$38,$44,$44,$38,$44,$44,$44,$38,$00,$00,
+
+ 6, // $39 '9'
+ $00,$38,$44,$44,$3C,$04,$04,$44,$38,$00,$00,
+
+ 6, // $3A ':'
+ $00,$00,$00,$30,$30,$00,$00,$30,$30,$00,$00,
+
+ 6, // $3B ';'
+ $00,$00,$00,$30,$30,$00,$00,$30,$30,$20,$40,
+
+ 6, // $3C '<'
+ $00,$04,$08,$10,$20,$40,$20,$10,$08,$04,$00,
+
+ 6, // $3D '='
+ $00,$00,$00,$00,$7C,$00,$00,$7C,$00,$00,$00,
+
+ 6, // $3E '>'
+ $00,$40,$20,$10,$08,$04,$08,$10,$20,$40,$00,
+
+ 6, // $3F '?'
+ $00,$38,$44,$04,$08,$10,$10,$00,$10,$00,$00,
+
+ 6, // $40 '@'
+ $00,$38,$44,$5C,$54,$54,$4C,$40,$38,$00,$00,
+
+ 6, // $41 'A'
+ $00,$38,$44,$44,$44,$7C,$44,$44,$44,$00,$00,
+
+ 6, // $42 'B'
+ $00,$78,$44,$44,$78,$44,$44,$44,$78,$00,$00,
+
+ 6, // $43 'C'
+ $00,$38,$44,$40,$40,$40,$40,$44,$38,$00,$00,
+
+ 6, // $44 'D'
+ $00,$70,$48,$44,$44,$44,$44,$48,$70,$00,$00,
+
+ 6, // $45 'E'
+ $00,$7C,$40,$40,$78,$40,$40,$40,$7C,$00,$00,
+
+ 6, // $46 'F'
+ $00,$7C,$40,$40,$78,$40,$40,$40,$40,$00,$00,
+
+ 6, // $47 'G'
+ $00,$38,$44,$40,$40,$5C,$44,$4C,$34,$00,$00,
+
+ 6, // $48 'H'
+ $00,$44,$44,$44,$7C,$44,$44,$44,$44,$00,$00,
+
+ 6, // $49 'I'
+ $00,$38,$10,$10,$10,$10,$10,$10,$38,$00,$00,
+
+ 6, // $4A 'J'
+ $00,$1C,$08,$08,$08,$08,$48,$48,$30,$00,$00,
+
+ 6, // $4B 'K'
+ $00,$44,$48,$50,$60,$50,$48,$44,$44,$00,$00,
+
+ 6, // $4C 'L'
+ $00,$40,$40,$40,$40,$40,$40,$40,$7C,$00,$00,
+
+ 6, // $4D 'M'
+ $00,$44,$6C,$54,$54,$54,$44,$44,$44,$00,$00,
+
+ 6, // $4E 'N'
+ $00,$44,$64,$64,$54,$54,$4C,$4C,$44,$00,$00,
+
+ 6, // $4F 'O'
+ $00,$38,$44,$44,$44,$44,$44,$44,$38,$00,$00,
+
+ 6, // $50 'P'
+ $00,$78,$44,$44,$44,$78,$40,$40,$40,$00,$00,
+
+ 6, // $51 'Q'
+ $00,$38,$44,$44,$44,$44,$54,$48,$34,$00,$00,
+
+ 6, // $52 'R'
+ $00,$78,$44,$44,$44,$78,$48,$44,$44,$00,$00,
+
+ 6, // $53 'S'
+ $00,$38,$44,$40,$38,$04,$04,$44,$38,$00,$00,
+
+ 6, // $54 'T'
+ $00,$7C,$10,$10,$10,$10,$10,$10,$10,$00,$00,
+
+ 6, // $55 'U'
+ $00,$44,$44,$44,$44,$44,$44,$44,$38,$00,$00,
+
+ 6, // $56 'V'
+ $00,$44,$44,$44,$28,$28,$28,$10,$10,$00,$00,
+
+ 6, // $57 'W'
+ $00,$44,$44,$54,$54,$54,$54,$54,$28,$00,$00,
+
+ 6, // $58 'X'
+ $00,$44,$44,$28,$10,$28,$44,$44,$44,$00,$00,
+
+ 6, // $59 'Y'
+ $00,$44,$44,$44,$28,$10,$10,$10,$10,$00,$00,
+
+ 6, // $5A 'Z'
+ $00,$7C,$04,$08,$10,$20,$40,$40,$7C,$00,$00,
+
+ 6, // $5B '['
+ $38,$20,$20,$20,$20,$20,$20,$20,$20,$38,$00,
+
+ 6, // $5C '\'
+ $80,$80,$40,$40,$20,$20,$10,$10,$08,$08,$00,
+
+ 6, // $5D ']'
+ $38,$08,$08,$08,$08,$08,$08,$08,$08,$38,$00,
+
+ 6, // $5E '^'
+ $00,$10,$28,$44,$00,$00,$00,$00,$00,$00,$00,
+
+ 6, // $5F '_'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7C,$00,$00,
+
+ 6, // $60 '`'
+ $00,$20,$20,$10,$00,$00,$00,$00,$00,$00,$00,
+
+ 6, // $61 'a'
+ $00,$00,$00,$38,$04,$3C,$44,$44,$3C,$00,$00,
+
+ 6, // $62 'b'
+ $00,$40,$40,$78,$44,$44,$44,$44,$78,$00,$00,
+
+ 6, // $63 'c'
+ $00,$00,$00,$38,$44,$40,$40,$44,$38,$00,$00,
+
+ 6, // $64 'd'
+ $00,$04,$04,$3C,$44,$44,$44,$44,$3C,$00,$00,
+
+ 6, // $65 'e'
+ $00,$00,$00,$38,$44,$7C,$40,$44,$38,$00,$00,
+
+ 6, // $66 'f'
+ $00,$0C,$10,$38,$10,$10,$10,$10,$10,$00,$00,
+
+ 6, // $67 'g'
+ $00,$00,$00,$3C,$44,$44,$44,$44,$3C,$04,$78,
+
+ 6, // $68 'h'
+ $00,$40,$40,$78,$44,$44,$44,$44,$44,$00,$00,
+
+ 6, // $69 'i'
+ $00,$10,$00,$30,$10,$10,$10,$10,$38,$00,$00,
+
+ 6, // $6A 'j'
+ $00,$10,$00,$30,$10,$10,$10,$10,$10,$50,$20,
+
+ 6, // $6B 'k'
+ $00,$40,$40,$4C,$50,$60,$50,$48,$44,$00,$00,
+
+ 6, // $6C 'l'
+ $00,$30,$10,$10,$10,$10,$10,$10,$38,$00,$00,
+
+ 6, // $6D 'm'
+ $00,$00,$00,$68,$54,$54,$54,$44,$44,$00,$00,
+
+ 6, // $6E 'n'
+ $00,$00,$00,$78,$44,$44,$44,$44,$44,$00,$00,
+
+ 6, // $6F 'o'
+ $00,$00,$00,$38,$44,$44,$44,$44,$38,$00,$00,
+
+ 6, // $70 'p'
+ $00,$00,$00,$78,$44,$44,$44,$44,$78,$40,$40,
+
+ 6, // $71 'q'
+ $00,$00,$00,$3C,$44,$44,$44,$44,$3C,$04,$04,
+
+ 6, // $72 'r'
+ $00,$00,$00,$58,$24,$20,$20,$20,$70,$00,$00,
+
+ 6, // $73 's'
+ $00,$00,$00,$38,$44,$30,$08,$44,$38,$00,$00,
+
+ 6, // $74 't'
+ $00,$20,$20,$70,$20,$20,$20,$20,$18,$00,$00,
+
+ 6, // $75 'u'
+ $00,$00,$00,$44,$44,$44,$44,$4C,$34,$00,$00,
+
+ 6, // $76 'v'
+ $00,$00,$00,$44,$44,$28,$28,$10,$10,$00,$00,
+
+ 6, // $77 'w'
+ $00,$00,$00,$44,$44,$44,$54,$7C,$28,$00,$00,
+
+ 6, // $78 'x'
+ $00,$00,$00,$44,$28,$10,$28,$44,$44,$00,$00,
+
+ 6, // $79 'y'
+ $00,$00,$00,$44,$44,$44,$44,$44,$3C,$08,$70,
+
+ 6, // $7A 'z'
+ $00,$00,$00,$7C,$08,$10,$20,$40,$7C,$00,$00,
+
+ 6, // $7B '{'
+ $18,$20,$20,$20,$C0,$C0,$20,$20,$20,$18,$00,
+
+ 6, // $7C '|'
+ $00,$10,$10,$10,$10,$00,$10,$10,$10,$10,$00,
+
+ 6, // $7D '}'
+ $60,$10,$10,$10,$0C,$0C,$10,$10,$10,$60,$00,
+
+ 6, // $7E '~'
+ $00,$24,$54,$48,$00,$00,$00,$00,$00,$00,$00,
+
+ 6, // $7F ''
+ $00,$10,$38,$6C,$44,$44,$7C,$00,$00,$00,$00,
+
+ 0 );
+
+ mcs7x12_mono_high : array[0..1444 ] of int8u = (
+ 12, 3, 32, 128-32,
+ $00,$00,$0D,$00,$1A,$00,$27,$00,$34,$00,$41,$00,$4E,$00,$5B,$00,$68,$00,
+ $75,$00,$82,$00,$8F,$00,$9C,$00,$A9,$00,$B6,$00,$C3,$00,$D0,$00,$DD,$00,
+ $EA,$00,$F7,$00,$04,$01,$11,$01,$1E,$01,$2B,$01,$38,$01,$45,$01,$52,$01,
+ $5F,$01,$6C,$01,$79,$01,$86,$01,$93,$01,$A0,$01,$AD,$01,$BA,$01,$C7,$01,
+ $D4,$01,$E1,$01,$EE,$01,$FB,$01,$08,$02,$15,$02,$22,$02,$2F,$02,$3C,$02,
+ $49,$02,$56,$02,$63,$02,$70,$02,$7D,$02,$8A,$02,$97,$02,$A4,$02,$B1,$02,
+ $BE,$02,$CB,$02,$D8,$02,$E5,$02,$F2,$02,$FF,$02,$0C,$03,$19,$03,$26,$03,
+ $33,$03,$40,$03,$4D,$03,$5A,$03,$67,$03,$74,$03,$81,$03,$8E,$03,$9B,$03,
+ $A8,$03,$B5,$03,$C2,$03,$CF,$03,$DC,$03,$E9,$03,$F6,$03,$03,$04,$10,$04,
+ $1D,$04,$2A,$04,$37,$04,$44,$04,$51,$04,$5E,$04,$6B,$04,$78,$04,$85,$04,
+ $92,$04,$9F,$04,$AC,$04,$B9,$04,$C6,$04,$D3,$04,
+
+ 7, // $20 ' '
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $21 '!'
+ $10,$10,$10,$10,$10,$10,$10,$10,$00,$10,$00,$00,
+
+ 7, // $22 '"'
+ $28,$28,$50,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $23 '#'
+ $24,$24,$24,$7E,$24,$24,$24,$7E,$24,$24,$24,$00,
+
+ 7, // $24 '$'
+ $10,$10,$38,$54,$50,$38,$14,$54,$38,$10,$10,$00,
+
+ 7, // $25 '%'
+ $32,$54,$64,$08,$08,$10,$10,$26,$2A,$4C,$00,$00,
+
+ 7, // $26 '&'
+ $00,$20,$50,$50,$50,$20,$54,$54,$48,$34,$00,$00,
+
+ 7, // $27 '''
+ $10,$10,$20,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $28 '('
+ $08,$10,$10,$20,$20,$20,$20,$20,$10,$10,$08,$00,
+
+ 7, // $29 ')'
+ $20,$10,$10,$08,$08,$08,$08,$08,$10,$10,$20,$00,
+
+ 7, // $2A '*'
+ $00,$00,$10,$54,$38,$7C,$38,$54,$10,$00,$00,$00,
+
+ 7, // $2B '+'
+ $00,$00,$00,$00,$10,$10,$7C,$10,$10,$00,$00,$00,
+
+ 7, // $2C ','
+ $00,$00,$00,$00,$00,$00,$00,$00,$30,$30,$20,$40,
+
+ 7, // $2D '-'
+ $00,$00,$00,$00,$00,$00,$7C,$00,$00,$00,$00,$00,
+
+ 7, // $2E '.'
+ $00,$00,$00,$00,$00,$00,$00,$00,$30,$30,$00,$00,
+
+ 7, // $2F '/'
+ $04,$04,$08,$08,$10,$10,$20,$20,$40,$40,$00,$00,
+
+ 7, // $30 '0'
+ $00,$38,$44,$44,$54,$54,$54,$44,$44,$38,$00,$00,
+
+ 7, // $31 '1'
+ $00,$10,$30,$10,$10,$10,$10,$10,$10,$38,$00,$00,
+
+ 7, // $32 '2'
+ $00,$38,$44,$04,$04,$08,$10,$20,$40,$7C,$00,$00,
+
+ 7, // $33 '3'
+ $00,$38,$44,$04,$04,$38,$04,$04,$44,$38,$00,$00,
+
+ 7, // $34 '4'
+ $00,$08,$18,$28,$28,$48,$48,$7C,$08,$08,$00,$00,
+
+ 7, // $35 '5'
+ $00,$7C,$40,$40,$78,$44,$04,$04,$44,$38,$00,$00,
+
+ 7, // $36 '6'
+ $00,$38,$44,$40,$78,$44,$44,$44,$44,$38,$00,$00,
+
+ 7, // $37 '7'
+ $00,$7C,$04,$08,$08,$10,$10,$20,$20,$20,$00,$00,
+
+ 7, // $38 '8'
+ $00,$38,$44,$44,$44,$38,$44,$44,$44,$38,$00,$00,
+
+ 7, // $39 '9'
+ $00,$38,$44,$44,$44,$3C,$04,$04,$44,$38,$00,$00,
+
+ 7, // $3A ':'
+ $00,$00,$00,$30,$30,$00,$00,$00,$30,$30,$00,$00,
+
+ 7, // $3B ';'
+ $00,$00,$00,$30,$30,$00,$00,$00,$30,$30,$20,$40,
+
+ 7, // $3C '<'
+ $00,$04,$08,$10,$20,$40,$20,$10,$08,$04,$00,$00,
+
+ 7, // $3D '='
+ $00,$00,$00,$00,$7C,$00,$00,$7C,$00,$00,$00,$00,
+
+ 7, // $3E '>'
+ $00,$40,$20,$10,$08,$04,$08,$10,$20,$40,$00,$00,
+
+ 7, // $3F '?'
+ $00,$38,$44,$04,$04,$08,$10,$10,$00,$10,$00,$00,
+
+ 7, // $40 '@'
+ $00,$38,$44,$44,$5C,$54,$54,$4C,$40,$38,$00,$00,
+
+ 7, // $41 'A'
+ $00,$38,$44,$44,$44,$7C,$44,$44,$44,$44,$00,$00,
+
+ 7, // $42 'B'
+ $00,$78,$44,$44,$44,$78,$44,$44,$44,$78,$00,$00,
+
+ 7, // $43 'C'
+ $00,$38,$44,$40,$40,$40,$40,$40,$44,$38,$00,$00,
+
+ 7, // $44 'D'
+ $00,$70,$48,$44,$44,$44,$44,$44,$48,$70,$00,$00,
+
+ 7, // $45 'E'
+ $00,$7C,$40,$40,$40,$78,$40,$40,$40,$7C,$00,$00,
+
+ 7, // $46 'F'
+ $00,$7C,$40,$40,$40,$78,$40,$40,$40,$40,$00,$00,
+
+ 7, // $47 'G'
+ $00,$38,$44,$40,$40,$5C,$44,$44,$4C,$34,$00,$00,
+
+ 7, // $48 'H'
+ $00,$44,$44,$44,$44,$7C,$44,$44,$44,$44,$00,$00,
+
+ 7, // $49 'I'
+ $00,$38,$10,$10,$10,$10,$10,$10,$10,$38,$00,$00,
+
+ 7, // $4A 'J'
+ $00,$1C,$08,$08,$08,$08,$08,$48,$48,$30,$00,$00,
+
+ 7, // $4B 'K'
+ $00,$44,$48,$50,$60,$60,$50,$48,$44,$44,$00,$00,
+
+ 7, // $4C 'L'
+ $00,$40,$40,$40,$40,$40,$40,$40,$40,$7C,$00,$00,
+
+ 7, // $4D 'M'
+ $00,$44,$6C,$6C,$54,$54,$44,$44,$44,$44,$00,$00,
+
+ 7, // $4E 'N'
+ $00,$44,$64,$64,$54,$54,$4C,$4C,$44,$44,$00,$00,
+
+ 7, // $4F 'O'
+ $00,$38,$44,$44,$44,$44,$44,$44,$44,$38,$00,$00,
+
+ 7, // $50 'P'
+ $00,$78,$44,$44,$44,$44,$78,$40,$40,$40,$00,$00,
+
+ 7, // $51 'Q'
+ $00,$38,$44,$44,$44,$44,$44,$54,$48,$34,$00,$00,
+
+ 7, // $52 'R'
+ $00,$78,$44,$44,$44,$44,$78,$48,$44,$44,$00,$00,
+
+ 7, // $53 'S'
+ $00,$38,$44,$40,$40,$38,$04,$04,$44,$38,$00,$00,
+
+ 7, // $54 'T'
+ $00,$7C,$10,$10,$10,$10,$10,$10,$10,$10,$00,$00,
+
+ 7, // $55 'U'
+ $00,$44,$44,$44,$44,$44,$44,$44,$44,$38,$00,$00,
+
+ 7, // $56 'V'
+ $00,$44,$44,$44,$44,$28,$28,$28,$10,$10,$00,$00,
+
+ 7, // $57 'W'
+ $00,$44,$44,$44,$44,$44,$44,$54,$54,$28,$00,$00,
+
+ 7, // $58 'X'
+ $00,$44,$44,$44,$28,$10,$28,$44,$44,$44,$00,$00,
+
+ 7, // $59 'Y'
+ $00,$44,$44,$44,$44,$28,$10,$10,$10,$10,$00,$00,
+
+ 7, // $5A 'Z'
+ $00,$7C,$04,$04,$08,$10,$20,$40,$40,$7C,$00,$00,
+
+ 7, // $5B '['
+ $38,$20,$20,$20,$20,$20,$20,$20,$20,$20,$38,$00,
+
+ 7, // $5C '\'
+ $00,$40,$40,$20,$20,$10,$10,$08,$08,$04,$04,$00,
+
+ 7, // $5D ']'
+ $38,$08,$08,$08,$08,$08,$08,$08,$08,$08,$38,$00,
+
+ 7, // $5E '^'
+ $00,$10,$28,$44,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $5F '_'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$7C,$00,$00,
+
+ 7, // $60 '`'
+ $00,$20,$20,$10,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $61 'a'
+ $00,$00,$00,$38,$04,$3C,$44,$44,$44,$3C,$00,$00,
+
+ 7, // $62 'b'
+ $00,$40,$40,$78,$44,$44,$44,$44,$44,$78,$00,$00,
+
+ 7, // $63 'c'
+ $00,$00,$00,$38,$44,$40,$40,$40,$44,$38,$00,$00,
+
+ 7, // $64 'd'
+ $00,$04,$04,$3C,$44,$44,$44,$44,$44,$3C,$00,$00,
+
+ 7, // $65 'e'
+ $00,$00,$00,$38,$44,$44,$7C,$40,$44,$38,$00,$00,
+
+ 7, // $66 'f'
+ $00,$0C,$10,$38,$10,$10,$10,$10,$10,$10,$00,$00,
+
+ 7, // $67 'g'
+ $00,$00,$00,$3C,$44,$44,$44,$44,$44,$3C,$04,$78,
+
+ 7, // $68 'h'
+ $00,$40,$40,$78,$44,$44,$44,$44,$44,$44,$00,$00,
+
+ 7, // $69 'i'
+ $00,$10,$00,$30,$10,$10,$10,$10,$10,$38,$00,$00,
+
+ 7, // $6A 'j'
+ $00,$08,$00,$18,$08,$08,$08,$08,$08,$08,$48,$30,
+
+ 7, // $6B 'k'
+ $00,$40,$40,$44,$48,$50,$60,$50,$48,$44,$00,$00,
+
+ 7, // $6C 'l'
+ $00,$30,$10,$10,$10,$10,$10,$10,$10,$38,$00,$00,
+
+ 7, // $6D 'm'
+ $00,$00,$00,$68,$54,$54,$44,$44,$44,$44,$00,$00,
+
+ 7, // $6E 'n'
+ $00,$00,$00,$58,$64,$44,$44,$44,$44,$44,$00,$00,
+
+ 7, // $6F 'o'
+ $00,$00,$00,$38,$44,$44,$44,$44,$44,$38,$00,$00,
+
+ 7, // $70 'p'
+ $00,$00,$00,$78,$44,$44,$44,$44,$44,$78,$40,$40,
+
+ 7, // $71 'q'
+ $00,$00,$00,$3C,$44,$44,$44,$44,$44,$3C,$04,$04,
+
+ 7, // $72 'r'
+ $00,$00,$00,$58,$24,$20,$20,$20,$20,$70,$00,$00,
+
+ 7, // $73 's'
+ $00,$00,$00,$38,$44,$40,$38,$04,$44,$38,$00,$00,
+
+ 7, // $74 't'
+ $00,$20,$20,$70,$20,$20,$20,$20,$24,$18,$00,$00,
+
+ 7, // $75 'u'
+ $00,$00,$00,$44,$44,$44,$44,$44,$4C,$34,$00,$00,
+
+ 7, // $76 'v'
+ $00,$00,$00,$44,$44,$44,$28,$28,$10,$10,$00,$00,
+
+ 7, // $77 'w'
+ $00,$00,$00,$44,$44,$44,$44,$54,$54,$28,$00,$00,
+
+ 7, // $78 'x'
+ $00,$00,$00,$44,$44,$28,$10,$28,$44,$44,$00,$00,
+
+ 7, // $79 'y'
+ $00,$00,$00,$44,$44,$44,$44,$44,$44,$3C,$08,$70,
+
+ 7, // $7A 'z'
+ $00,$00,$00,$7C,$04,$08,$10,$20,$40,$7C,$00,$00,
+
+ 7, // $7B '{'
+ $18,$20,$20,$20,$20,$C0,$20,$20,$20,$20,$18,$00,
+
+ 7, // $7C '|'
+ $00,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$00,
+
+ 7, // $7D '}'
+ $60,$10,$10,$10,$10,$0C,$10,$10,$10,$10,$60,$00,
+
+ 7, // $7E '~'
+ $00,$60,$92,$92,$0C,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $7F ''
+ $00,$10,$38,$6C,$44,$44,$7C,$00,$00,$00,$00,$00,
+
+ 0 );
+
+ mcs7x12_mono_low : array[0..1444 ] of int8u = (
+ 12, 4, 32, 128-32,
+ $00,$00,$0D,$00,$1A,$00,$27,$00,$34,$00,$41,$00,$4E,$00,$5B,$00,$68,$00,
+ $75,$00,$82,$00,$8F,$00,$9C,$00,$A9,$00,$B6,$00,$C3,$00,$D0,$00,$DD,$00,
+ $EA,$00,$F7,$00,$04,$01,$11,$01,$1E,$01,$2B,$01,$38,$01,$45,$01,$52,$01,
+ $5F,$01,$6C,$01,$79,$01,$86,$01,$93,$01,$A0,$01,$AD,$01,$BA,$01,$C7,$01,
+ $D4,$01,$E1,$01,$EE,$01,$FB,$01,$08,$02,$15,$02,$22,$02,$2F,$02,$3C,$02,
+ $49,$02,$56,$02,$63,$02,$70,$02,$7D,$02,$8A,$02,$97,$02,$A4,$02,$B1,$02,
+ $BE,$02,$CB,$02,$D8,$02,$E5,$02,$F2,$02,$FF,$02,$0C,$03,$19,$03,$26,$03,
+ $33,$03,$40,$03,$4D,$03,$5A,$03,$67,$03,$74,$03,$81,$03,$8E,$03,$9B,$03,
+ $A8,$03,$B5,$03,$C2,$03,$CF,$03,$DC,$03,$E9,$03,$F6,$03,$03,$04,$10,$04,
+ $1D,$04,$2A,$04,$37,$04,$44,$04,$51,$04,$5E,$04,$6B,$04,$78,$04,$85,$04,
+ $92,$04,$9F,$04,$AC,$04,$B9,$04,$C6,$04,$D3,$04,
+
+ 7, // $20 ' '
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $21 '!'
+ $00,$10,$10,$10,$10,$10,$10,$10,$00,$10,$00,$00,
+
+ 7, // $22 '"'
+ $28,$28,$50,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $23 '#'
+ $00,$28,$28,$7C,$28,$28,$28,$7C,$28,$28,$00,$00,
+
+ 7, // $24 '$'
+ $00,$10,$38,$54,$50,$38,$14,$54,$38,$10,$00,$00,
+
+ 7, // $25 '%'
+ $34,$54,$68,$08,$10,$10,$20,$2C,$54,$58,$00,$00,
+
+ 7, // $26 '&'
+ $00,$20,$50,$50,$20,$54,$54,$48,$34,$00,$00,$00,
+
+ 7, // $27 '''
+ $00,$10,$10,$20,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $28 '('
+ $08,$10,$10,$20,$20,$20,$20,$20,$10,$10,$08,$00,
+
+ 7, // $29 ')'
+ $20,$10,$10,$08,$08,$08,$08,$08,$10,$10,$20,$00,
+
+ 7, // $2A '*'
+ $00,$00,$10,$54,$38,$7C,$38,$54,$10,$00,$00,$00,
+
+ 7, // $2B '+'
+ $00,$00,$00,$10,$10,$7C,$10,$10,$00,$00,$00,$00,
+
+ 7, // $2C ','
+ $00,$00,$00,$00,$00,$00,$00,$30,$30,$20,$40,$00,
+
+ 7, // $2D '-'
+ $00,$00,$00,$00,$00,$7C,$00,$00,$00,$00,$00,$00,
+
+ 7, // $2E '.'
+ $00,$00,$00,$00,$00,$00,$00,$30,$30,$00,$00,$00,
+
+ 7, // $2F '/'
+ $04,$04,$08,$08,$10,$10,$20,$20,$40,$40,$00,$00,
+
+ 7, // $30 '0'
+ $00,$38,$44,$44,$54,$54,$44,$44,$38,$00,$00,$00,
+
+ 7, // $31 '1'
+ $00,$10,$30,$10,$10,$10,$10,$10,$38,$00,$00,$00,
+
+ 7, // $32 '2'
+ $00,$38,$44,$44,$08,$10,$20,$40,$7C,$00,$00,$00,
+
+ 7, // $33 '3'
+ $00,$38,$44,$04,$38,$04,$04,$44,$38,$00,$00,$00,
+
+ 7, // $34 '4'
+ $00,$08,$18,$28,$28,$48,$7C,$08,$08,$00,$00,$00,
+
+ 7, // $35 '5'
+ $00,$7C,$40,$78,$44,$04,$04,$44,$38,$00,$00,$00,
+
+ 7, // $36 '6'
+ $00,$38,$44,$40,$78,$44,$44,$44,$38,$00,$00,$00,
+
+ 7, // $37 '7'
+ $00,$7C,$04,$08,$08,$10,$10,$20,$20,$00,$00,$00,
+
+ 7, // $38 '8'
+ $00,$38,$44,$44,$38,$44,$44,$44,$38,$00,$00,$00,
+
+ 7, // $39 '9'
+ $00,$38,$44,$44,$44,$3C,$04,$44,$38,$00,$00,$00,
+
+ 7, // $3A ':'
+ $00,$00,$00,$30,$30,$00,$00,$30,$30,$00,$00,$00,
+
+ 7, // $3B ';'
+ $00,$00,$00,$30,$30,$00,$00,$30,$30,$20,$40,$00,
+
+ 7, // $3C '<'
+ $00,$04,$08,$10,$20,$40,$20,$10,$08,$04,$00,$00,
+
+ 7, // $3D '='
+ $00,$00,$00,$00,$7C,$00,$00,$7C,$00,$00,$00,$00,
+
+ 7, // $3E '>'
+ $00,$40,$20,$10,$08,$04,$08,$10,$20,$40,$00,$00,
+
+ 7, // $3F '?'
+ $00,$38,$44,$04,$04,$08,$10,$10,$00,$10,$00,$00,
+
+ 7, // $40 '@'
+ $00,$38,$44,$44,$5C,$54,$4C,$40,$38,$00,$00,$00,
+
+ 7, // $41 'A'
+ $00,$38,$44,$44,$44,$7C,$44,$44,$44,$00,$00,$00,
+
+ 7, // $42 'B'
+ $00,$78,$44,$44,$78,$44,$44,$44,$78,$00,$00,$00,
+
+ 7, // $43 'C'
+ $00,$38,$44,$40,$40,$40,$40,$44,$38,$00,$00,$00,
+
+ 7, // $44 'D'
+ $00,$70,$48,$44,$44,$44,$44,$48,$70,$00,$00,$00,
+
+ 7, // $45 'E'
+ $00,$7C,$40,$40,$78,$40,$40,$40,$7C,$00,$00,$00,
+
+ 7, // $46 'F'
+ $00,$7C,$40,$40,$78,$40,$40,$40,$40,$00,$00,$00,
+
+ 7, // $47 'G'
+ $00,$38,$44,$40,$40,$4C,$44,$4C,$34,$00,$00,$00,
+
+ 7, // $48 'H'
+ $00,$44,$44,$44,$7C,$44,$44,$44,$44,$00,$00,$00,
+
+ 7, // $49 'I'
+ $00,$38,$10,$10,$10,$10,$10,$10,$38,$00,$00,$00,
+
+ 7, // $4A 'J'
+ $00,$1C,$08,$08,$08,$08,$48,$48,$30,$00,$00,$00,
+
+ 7, // $4B 'K'
+ $00,$44,$48,$50,$60,$60,$50,$48,$44,$00,$00,$00,
+
+ 7, // $4C 'L'
+ $00,$40,$40,$40,$40,$40,$40,$40,$7C,$00,$00,$00,
+
+ 7, // $4D 'M'
+ $00,$44,$6C,$54,$54,$44,$44,$44,$44,$00,$00,$00,
+
+ 7, // $4E 'N'
+ $00,$44,$64,$64,$54,$54,$4C,$4C,$44,$00,$00,$00,
+
+ 7, // $4F 'O'
+ $00,$38,$44,$44,$44,$44,$44,$44,$38,$00,$00,$00,
+
+ 7, // $50 'P'
+ $00,$78,$44,$44,$44,$78,$40,$40,$40,$00,$00,$00,
+
+ 7, // $51 'Q'
+ $00,$38,$44,$44,$44,$44,$54,$48,$34,$00,$00,$00,
+
+ 7, // $52 'R'
+ $00,$78,$44,$44,$44,$78,$48,$44,$44,$00,$00,$00,
+
+ 7, // $53 'S'
+ $00,$38,$44,$40,$38,$04,$44,$44,$38,$00,$00,$00,
+
+ 7, // $54 'T'
+ $00,$7C,$10,$10,$10,$10,$10,$10,$10,$00,$00,$00,
+
+ 7, // $55 'U'
+ $00,$44,$44,$44,$44,$44,$44,$44,$38,$00,$00,$00,
+
+ 7, // $56 'V'
+ $00,$44,$44,$44,$28,$28,$28,$10,$10,$00,$00,$00,
+
+ 7, // $57 'W'
+ $00,$44,$44,$44,$44,$44,$54,$54,$28,$00,$00,$00,
+
+ 7, // $58 'X'
+ $00,$44,$44,$28,$10,$28,$44,$44,$44,$00,$00,$00,
+
+ 7, // $59 'Y'
+ $00,$44,$44,$44,$28,$10,$10,$10,$10,$00,$00,$00,
+
+ 7, // $5A 'Z'
+ $00,$7C,$04,$08,$10,$20,$40,$40,$7C,$00,$00,$00,
+
+ 7, // $5B '['
+ $38,$20,$20,$20,$20,$20,$20,$20,$20,$20,$38,$00,
+
+ 7, // $5C '\'
+ $00,$40,$40,$20,$20,$10,$10,$08,$08,$04,$04,$00,
+
+ 7, // $5D ']'
+ $38,$08,$08,$08,$08,$08,$08,$08,$08,$08,$38,$00,
+
+ 7, // $5E '^'
+ $00,$10,$28,$44,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $5F '_'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7C,$00,$00,$00,
+
+ 7, // $60 '`'
+ $00,$20,$20,$10,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $61 'a'
+ $00,$00,$00,$38,$04,$3C,$44,$44,$3C,$00,$00,$00,
+
+ 7, // $62 'b'
+ $00,$40,$40,$78,$44,$44,$44,$44,$78,$00,$00,$00,
+
+ 7, // $63 'c'
+ $00,$00,$00,$38,$44,$40,$40,$44,$38,$00,$00,$00,
+
+ 7, // $64 'd'
+ $00,$04,$04,$3C,$44,$44,$44,$44,$3C,$00,$00,$00,
+
+ 7, // $65 'e'
+ $00,$00,$00,$38,$44,$7C,$40,$44,$38,$00,$00,$00,
+
+ 7, // $66 'f'
+ $00,$0C,$10,$38,$10,$10,$10,$10,$10,$00,$00,$00,
+
+ 7, // $67 'g'
+ $00,$00,$00,$3C,$44,$44,$44,$44,$3C,$04,$44,$38,
+
+ 7, // $68 'h'
+ $00,$40,$40,$78,$44,$44,$44,$44,$44,$00,$00,$00,
+
+ 7, // $69 'i'
+ $00,$10,$00,$30,$10,$10,$10,$10,$38,$00,$00,$00,
+
+ 7, // $6A 'j'
+ $00,$08,$00,$18,$08,$08,$08,$08,$08,$48,$48,$30,
+
+ 7, // $6B 'k'
+ $00,$40,$40,$4C,$50,$60,$50,$48,$44,$00,$00,$00,
+
+ 7, // $6C 'l'
+ $00,$30,$10,$10,$10,$10,$10,$10,$38,$00,$00,$00,
+
+ 7, // $6D 'm'
+ $00,$00,$00,$68,$54,$54,$44,$44,$44,$00,$00,$00,
+
+ 7, // $6E 'n'
+ $00,$00,$00,$58,$64,$44,$44,$44,$44,$00,$00,$00,
+
+ 7, // $6F 'o'
+ $00,$00,$00,$38,$44,$44,$44,$44,$38,$00,$00,$00,
+
+ 7, // $70 'p'
+ $00,$00,$00,$78,$44,$44,$44,$44,$78,$40,$40,$40,
+
+ 7, // $71 'q'
+ $00,$00,$00,$3C,$44,$44,$44,$44,$3C,$04,$04,$04,
+
+ 7, // $72 'r'
+ $00,$00,$00,$58,$24,$20,$20,$20,$70,$00,$00,$00,
+
+ 7, // $73 's'
+ $00,$00,$00,$38,$44,$30,$08,$44,$38,$00,$00,$00,
+
+ 7, // $74 't'
+ $00,$20,$20,$70,$20,$20,$20,$24,$18,$00,$00,$00,
+
+ 7, // $75 'u'
+ $00,$00,$00,$44,$44,$44,$44,$4C,$34,$00,$00,$00,
+
+ 7, // $76 'v'
+ $00,$00,$00,$44,$44,$28,$28,$10,$10,$00,$00,$00,
+
+ 7, // $77 'w'
+ $00,$00,$00,$44,$44,$44,$54,$54,$28,$00,$00,$00,
+
+ 7, // $78 'x'
+ $00,$00,$00,$44,$28,$10,$28,$44,$44,$00,$00,$00,
+
+ 7, // $79 'y'
+ $00,$00,$00,$44,$44,$44,$44,$44,$3C,$04,$08,$70,
+
+ 7, // $7A 'z'
+ $00,$00,$00,$7C,$08,$10,$20,$40,$7C,$00,$00,$00,
+
+ 7, // $7B '{'
+ $18,$20,$20,$20,$20,$C0,$20,$20,$20,$20,$18,$00,
+
+ 7, // $7C '|'
+ $00,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$00,
+
+ 7, // $7D '}'
+ $60,$10,$10,$10,$10,$0C,$10,$10,$10,$10,$60,$00,
+
+ 7, // $7E '~'
+ $00,$24,$54,$48,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $7F ''
+ $00,$10,$38,$6C,$44,$44,$7C,$00,$00,$00,$00,$00,
+
+ 0 );
+
+ verdana12 : array[0..1540 ] of int8u = (
+ 12, 3, 32, 128-32,
+ $00,$00,$0D,$00,$1A,$00,$27,$00,$34,$00,$41,$00,$5A,$00,$67,$00,$74,$00,
+ $81,$00,$8E,$00,$9B,$00,$A8,$00,$B5,$00,$C2,$00,$CF,$00,$DC,$00,$E9,$00,
+ $F6,$00,$03,$01,$10,$01,$1D,$01,$2A,$01,$37,$01,$44,$01,$51,$01,$5E,$01,
+ $6B,$01,$78,$01,$85,$01,$92,$01,$9F,$01,$AC,$01,$C5,$01,$D2,$01,$DF,$01,
+ $EC,$01,$F9,$01,$06,$02,$13,$02,$20,$02,$2D,$02,$3A,$02,$47,$02,$54,$02,
+ $61,$02,$7A,$02,$87,$02,$A0,$02,$AD,$02,$C6,$02,$D3,$02,$E0,$02,$ED,$02,
+ $FA,$02,$07,$03,$20,$03,$2D,$03,$3A,$03,$47,$03,$54,$03,$61,$03,$6E,$03,
+ $7B,$03,$88,$03,$95,$03,$A2,$03,$AF,$03,$BC,$03,$C9,$03,$D6,$03,$E3,$03,
+ $F0,$03,$FD,$03,$0A,$04,$17,$04,$24,$04,$31,$04,$4A,$04,$57,$04,$64,$04,
+ $71,$04,$7E,$04,$8B,$04,$98,$04,$A5,$04,$B2,$04,$BF,$04,$CC,$04,$D9,$04,
+ $E6,$04,$F3,$04,$00,$05,$0D,$05,$1A,$05,$27,$05,
+
+ 3, // $20 ' '
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 5, // $21 '!'
+ $00,$00,$00,$20,$20,$20,$20,$20,$00,$20,$00,$00,
+
+ 5, // $22 '"'
+ $00,$00,$50,$50,$50,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $23 '#'
+ $00,$00,$00,$00,$28,$7C,$28,$7C,$28,$00,$00,$00,
+
+ 7, // $24 '$'
+ $00,$00,$10,$10,$3C,$50,$30,$18,$14,$78,$10,$10,
+
+ 11, // $25 '%'
+ $00,$00,$00,$00,$00,$00,$31,$00,$4A,$00,$4A,$00,$35,$80,$0A,$40,$0A,$40,$11,$80,$00,$00,$00,$00,
+
+ 7, // $26 '&'
+ $00,$00,$00,$30,$48,$48,$32,$4A,$44,$3A,$00,$00,
+
+ 3, // $27 '''
+ $00,$00,$40,$40,$40,$00,$00,$00,$00,$00,$00,$00,
+
+ 4, // $28 '('
+ $00,$00,$10,$20,$40,$40,$40,$40,$40,$40,$20,$10,
+
+ 4, // $29 ')'
+ $00,$00,$80,$40,$20,$20,$20,$20,$20,$20,$40,$80,
+
+ 7, // $2A '*'
+ $00,$10,$54,$38,$54,$10,$00,$00,$00,$00,$00,$00,
+
+ 7, // $2B '+'
+ $00,$00,$00,$00,$10,$10,$7C,$10,$10,$00,$00,$00,
+
+ 3, // $2C ','
+ $00,$00,$00,$00,$00,$00,$00,$00,$40,$40,$80,$00,
+
+ 5, // $2D '-'
+ $00,$00,$00,$00,$00,$00,$70,$00,$00,$00,$00,$00,
+
+ 3, // $2E '.'
+ $00,$00,$00,$00,$00,$00,$00,$00,$40,$40,$00,$00,
+
+ 4, // $2F '/'
+ $00,$00,$10,$10,$20,$20,$40,$40,$40,$80,$80,$00,
+
+ 7, // $30 '0'
+ $00,$00,$00,$38,$44,$44,$44,$44,$44,$38,$00,$00,
+
+ 7, // $31 '1'
+ $00,$00,$00,$10,$30,$10,$10,$10,$10,$38,$00,$00,
+
+ 7, // $32 '2'
+ $00,$00,$00,$38,$44,$04,$08,$10,$20,$7C,$00,$00,
+
+ 7, // $33 '3'
+ $00,$00,$00,$38,$44,$04,$18,$04,$44,$38,$00,$00,
+
+ 7, // $34 '4'
+ $00,$00,$00,$08,$18,$28,$48,$7C,$08,$08,$00,$00,
+
+ 7, // $35 '5'
+ $00,$00,$00,$7C,$40,$78,$04,$04,$44,$38,$00,$00,
+
+ 7, // $36 '6'
+ $00,$00,$00,$18,$20,$40,$78,$44,$44,$38,$00,$00,
+
+ 7, // $37 '7'
+ $00,$00,$00,$7C,$04,$08,$08,$10,$10,$10,$00,$00,
+
+ 7, // $38 '8'
+ $00,$00,$00,$38,$44,$44,$38,$44,$44,$38,$00,$00,
+
+ 7, // $39 '9'
+ $00,$00,$00,$38,$44,$44,$3C,$04,$08,$30,$00,$00,
+
+ 4, // $3A ':'
+ $00,$00,$00,$00,$00,$40,$40,$00,$40,$40,$00,$00,
+
+ 4, // $3B ';'
+ $00,$00,$00,$00,$00,$40,$40,$00,$40,$40,$80,$00,
+
+ 7, // $3C '<'
+ $00,$00,$00,$00,$04,$18,$60,$18,$04,$00,$00,$00,
+
+ 7, // $3D '='
+ $00,$00,$00,$00,$00,$7C,$00,$7C,$00,$00,$00,$00,
+
+ 7, // $3E '>'
+ $00,$00,$00,$00,$40,$30,$0C,$30,$40,$00,$00,$00,
+
+ 6, // $3F '?'
+ $00,$00,$00,$70,$08,$08,$10,$20,$00,$20,$00,$00,
+
+ 10, // $40 '@'
+ $00,$00,$00,$00,$00,$00,$1F,$00,$20,$80,$4E,$80,$52,$80,$52,$80,$4D,$00,$20,$00,$1F,$00,$00,$00,
+
+ 8, // $41 'A'
+ $00,$00,$00,$18,$18,$24,$24,$7E,$42,$42,$00,$00,
+
+ 7, // $42 'B'
+ $00,$00,$00,$70,$48,$48,$78,$44,$44,$78,$00,$00,
+
+ 8, // $43 'C'
+ $00,$00,$00,$1C,$22,$40,$40,$40,$22,$1C,$00,$00,
+
+ 8, // $44 'D'
+ $00,$00,$00,$78,$44,$42,$42,$42,$44,$78,$00,$00,
+
+ 7, // $45 'E'
+ $00,$00,$00,$7C,$40,$40,$78,$40,$40,$7C,$00,$00,
+
+ 6, // $46 'F'
+ $00,$00,$00,$7C,$40,$40,$78,$40,$40,$40,$00,$00,
+
+ 8, // $47 'G'
+ $00,$00,$00,$1C,$22,$40,$4E,$42,$22,$1C,$00,$00,
+
+ 8, // $48 'H'
+ $00,$00,$00,$42,$42,$42,$7E,$42,$42,$42,$00,$00,
+
+ 5, // $49 'I'
+ $00,$00,$00,$70,$20,$20,$20,$20,$20,$70,$00,$00,
+
+ 5, // $4A 'J'
+ $00,$00,$00,$30,$10,$10,$10,$10,$10,$E0,$00,$00,
+
+ 7, // $4B 'K'
+ $00,$00,$00,$44,$48,$50,$60,$50,$48,$44,$00,$00,
+
+ 6, // $4C 'L'
+ $00,$00,$00,$40,$40,$40,$40,$40,$40,$7C,$00,$00,
+
+ 9, // $4D 'M'
+ $00,$00,$00,$00,$00,$00,$63,$00,$63,$00,$55,$00,$55,$00,$49,$00,$49,$00,$41,$00,$00,$00,$00,$00,
+
+ 8, // $4E 'N'
+ $00,$00,$00,$42,$62,$52,$4A,$46,$42,$42,$00,$00,
+
+ 9, // $4F 'O'
+ $00,$00,$00,$00,$00,$00,$1C,$00,$22,$00,$41,$00,$41,$00,$41,$00,$22,$00,$1C,$00,$00,$00,$00,$00,
+
+ 7, // $50 'P'
+ $00,$00,$00,$78,$44,$44,$44,$78,$40,$40,$00,$00,
+
+ 9, // $51 'Q'
+ $00,$00,$00,$00,$00,$00,$1C,$00,$22,$00,$41,$00,$41,$00,$41,$00,$22,$00,$1C,$00,$04,$00,$03,$00,
+
+ 7, // $52 'R'
+ $00,$00,$00,$78,$44,$44,$78,$50,$48,$44,$00,$00,
+
+ 7, // $53 'S'
+ $00,$00,$00,$38,$44,$40,$38,$04,$44,$38,$00,$00,
+
+ 7, // $54 'T'
+ $00,$00,$00,$FE,$10,$10,$10,$10,$10,$10,$00,$00,
+
+ 8, // $55 'U'
+ $00,$00,$00,$42,$42,$42,$42,$42,$42,$3C,$00,$00,
+
+ 8, // $56 'V'
+ $00,$00,$00,$42,$42,$42,$24,$24,$18,$18,$00,$00,
+
+ 9, // $57 'W'
+ $00,$00,$00,$00,$00,$00,$41,$00,$49,$00,$49,$00,$55,$00,$55,$00,$22,$00,$22,$00,$00,$00,$00,$00,
+
+ 7, // $58 'X'
+ $00,$00,$00,$44,$44,$28,$10,$28,$44,$44,$00,$00,
+
+ 7, // $59 'Y'
+ $00,$00,$00,$44,$44,$28,$28,$10,$10,$10,$00,$00,
+
+ 7, // $5A 'Z'
+ $00,$00,$00,$7C,$04,$08,$10,$20,$40,$7C,$00,$00,
+
+ 4, // $5B '['
+ $00,$00,$60,$40,$40,$40,$40,$40,$40,$40,$40,$60,
+
+ 4, // $5C '\'
+ $00,$00,$80,$80,$40,$40,$40,$20,$20,$10,$10,$00,
+
+ 4, // $5D ']'
+ $00,$00,$60,$20,$20,$20,$20,$20,$20,$20,$20,$60,
+
+ 7, // $5E '^'
+ $00,$00,$00,$10,$28,$44,$00,$00,$00,$00,$00,$00,
+
+ 6, // $5F '_'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FC,
+
+ 6, // $60 '`'
+ $00,$00,$20,$10,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 6, // $61 'a'
+ $00,$00,$00,$00,$00,$30,$08,$38,$48,$38,$00,$00,
+
+ 6, // $62 'b'
+ $00,$00,$40,$40,$40,$70,$48,$48,$48,$70,$00,$00,
+
+ 6, // $63 'c'
+ $00,$00,$00,$00,$00,$38,$40,$40,$40,$38,$00,$00,
+
+ 6, // $64 'd'
+ $00,$00,$08,$08,$08,$38,$48,$48,$48,$38,$00,$00,
+
+ 6, // $65 'e'
+ $00,$00,$00,$00,$00,$30,$48,$78,$40,$38,$00,$00,
+
+ 4, // $66 'f'
+ $00,$00,$30,$40,$40,$E0,$40,$40,$40,$40,$00,$00,
+
+ 6, // $67 'g'
+ $00,$00,$00,$00,$00,$38,$48,$48,$48,$38,$08,$30,
+
+ 6, // $68 'h'
+ $00,$00,$40,$40,$40,$70,$48,$48,$48,$48,$00,$00,
+
+ 3, // $69 'i'
+ $00,$00,$00,$40,$00,$40,$40,$40,$40,$40,$00,$00,
+
+ 3, // $6A 'j'
+ $00,$00,$00,$40,$00,$C0,$40,$40,$40,$40,$40,$80,
+
+ 6, // $6B 'k'
+ $00,$00,$40,$40,$40,$48,$50,$60,$50,$48,$00,$00,
+
+ 3, // $6C 'l'
+ $00,$00,$40,$40,$40,$40,$40,$40,$40,$40,$00,$00,
+
+ 9, // $6D 'm'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$76,$00,$49,$00,$49,$00,$49,$00,$49,$00,$00,$00,$00,$00,
+
+ 6, // $6E 'n'
+ $00,$00,$00,$00,$00,$70,$48,$48,$48,$48,$00,$00,
+
+ 6, // $6F 'o'
+ $00,$00,$00,$00,$00,$30,$48,$48,$48,$30,$00,$00,
+
+ 6, // $70 'p'
+ $00,$00,$00,$00,$00,$70,$48,$48,$48,$70,$40,$40,
+
+ 6, // $71 'q'
+ $00,$00,$00,$00,$00,$38,$48,$48,$48,$38,$08,$08,
+
+ 4, // $72 'r'
+ $00,$00,$00,$00,$00,$50,$60,$40,$40,$40,$00,$00,
+
+ 6, // $73 's'
+ $00,$00,$00,$00,$00,$38,$40,$30,$08,$70,$00,$00,
+
+ 4, // $74 't'
+ $00,$00,$00,$00,$40,$F0,$40,$40,$40,$30,$00,$00,
+
+ 6, // $75 'u'
+ $00,$00,$00,$00,$00,$48,$48,$48,$48,$38,$00,$00,
+
+ 6, // $76 'v'
+ $00,$00,$00,$00,$00,$48,$48,$48,$30,$30,$00,$00,
+
+ 7, // $77 'w'
+ $00,$00,$00,$00,$00,$44,$54,$54,$28,$28,$00,$00,
+
+ 6, // $78 'x'
+ $00,$00,$00,$00,$00,$48,$48,$30,$48,$48,$00,$00,
+
+ 6, // $79 'y'
+ $00,$00,$00,$00,$00,$48,$48,$48,$30,$10,$20,$20,
+
+ 5, // $7A 'z'
+ $00,$00,$00,$00,$00,$70,$10,$20,$40,$70,$00,$00,
+
+ 6, // $7B '{'
+ $00,$00,$18,$20,$20,$20,$20,$C0,$20,$20,$20,$18,
+
+ 5, // $7C '|'
+ $00,$00,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,
+
+ 6, // $7D '}'
+ $00,$00,$60,$10,$10,$10,$10,$0C,$10,$10,$10,$60,
+
+ 7, // $7E '~'
+ $00,$00,$00,$00,$00,$00,$34,$58,$00,$00,$00,$00,
+
+ 9, // $7F ''
+ $00,$00,$00,$00,$00,$00,$7F,$00,$41,$00,$41,$00,$41,$00,$41,$00,$41,$00,$7F,$00,$00,$00,$00,$00,
+
+ 0 );
+
+ verdana12_bold : array[0..1516 ] of int8u = (
+ 12, 3, 32, 128-32,
+ $00,$00,$0D,$00,$1A,$00,$27,$00,$34,$00,$41,$00,$5A,$00,$67,$00,$74,$00,
+ $81,$00,$8E,$00,$9B,$00,$A8,$00,$B5,$00,$C2,$00,$CF,$00,$DC,$00,$E9,$00,
+ $F6,$00,$03,$01,$10,$01,$1D,$01,$2A,$01,$37,$01,$44,$01,$51,$01,$5E,$01,
+ $6B,$01,$78,$01,$85,$01,$92,$01,$9F,$01,$AC,$01,$C5,$01,$D2,$01,$DF,$01,
+ $EC,$01,$F9,$01,$06,$02,$13,$02,$20,$02,$2D,$02,$3A,$02,$47,$02,$54,$02,
+ $61,$02,$6E,$02,$7B,$02,$88,$02,$95,$02,$A2,$02,$AF,$02,$BC,$02,$C9,$02,
+ $D6,$02,$E3,$02,$FC,$02,$09,$03,$16,$03,$23,$03,$30,$03,$3D,$03,$4A,$03,
+ $57,$03,$64,$03,$71,$03,$7E,$03,$8B,$03,$98,$03,$A5,$03,$B2,$03,$BF,$03,
+ $CC,$03,$D9,$03,$E6,$03,$F3,$03,$00,$04,$0D,$04,$26,$04,$33,$04,$40,$04,
+ $4D,$04,$5A,$04,$67,$04,$74,$04,$81,$04,$8E,$04,$9B,$04,$B4,$04,$C1,$04,
+ $CE,$04,$DB,$04,$E8,$04,$F5,$04,$02,$05,$0F,$05,
+
+ 3, // $20 ' '
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 4, // $21 '!'
+ $00,$00,$00,$60,$60,$60,$60,$60,$00,$60,$00,$00,
+
+ 5, // $22 '"'
+ $00,$00,$D8,$D8,$D8,$00,$00,$00,$00,$00,$00,$00,
+
+ 8, // $23 '#'
+ $00,$00,$00,$14,$14,$7E,$28,$FC,$50,$50,$00,$00,
+
+ 6, // $24 '$'
+ $00,$00,$20,$20,$70,$E8,$E0,$38,$B8,$70,$20,$20,
+
+ 11, // $25 '%'
+ $00,$00,$00,$00,$00,$00,$62,$00,$94,$00,$94,$00,$69,$80,$0A,$40,$0A,$40,$11,$80,$00,$00,$00,$00,
+
+ 8, // $26 '&'
+ $00,$00,$00,$70,$D8,$D8,$76,$DC,$CC,$76,$00,$00,
+
+ 3, // $27 '''
+ $00,$00,$C0,$C0,$C0,$00,$00,$00,$00,$00,$00,$00,
+
+ 5, // $28 '('
+ $00,$00,$30,$60,$C0,$C0,$C0,$C0,$C0,$C0,$60,$30,
+
+ 5, // $29 ')'
+ $00,$00,$C0,$60,$30,$30,$30,$30,$30,$30,$60,$C0,
+
+ 6, // $2A '*'
+ $00,$00,$20,$A8,$70,$A8,$20,$00,$00,$00,$00,$00,
+
+ 8, // $2B '+'
+ $00,$00,$00,$00,$10,$10,$7C,$10,$10,$00,$00,$00,
+
+ 3, // $2C ','
+ $00,$00,$00,$00,$00,$00,$00,$00,$C0,$C0,$80,$00,
+
+ 4, // $2D '-'
+ $00,$00,$00,$00,$00,$00,$E0,$00,$00,$00,$00,$00,
+
+ 3, // $2E '.'
+ $00,$00,$00,$00,$00,$00,$00,$00,$C0,$C0,$00,$00,
+
+ 6, // $2F '/'
+ $00,$00,$08,$08,$10,$10,$20,$40,$40,$80,$80,$00,
+
+ 6, // $30 '0'
+ $00,$00,$00,$70,$D8,$D8,$D8,$D8,$D8,$70,$00,$00,
+
+ 6, // $31 '1'
+ $00,$00,$00,$30,$70,$30,$30,$30,$30,$78,$00,$00,
+
+ 6, // $32 '2'
+ $00,$00,$00,$70,$98,$18,$30,$60,$C0,$F8,$00,$00,
+
+ 6, // $33 '3'
+ $00,$00,$00,$70,$98,$18,$70,$18,$98,$70,$00,$00,
+
+ 6, // $34 '4'
+ $00,$00,$00,$18,$38,$58,$98,$FC,$18,$18,$00,$00,
+
+ 6, // $35 '5'
+ $00,$00,$00,$F8,$C0,$F0,$18,$18,$98,$70,$00,$00,
+
+ 6, // $36 '6'
+ $00,$00,$00,$70,$C0,$F0,$D8,$D8,$D8,$70,$00,$00,
+
+ 6, // $37 '7'
+ $00,$00,$00,$F8,$18,$30,$30,$60,$60,$C0,$00,$00,
+
+ 6, // $38 '8'
+ $00,$00,$00,$70,$D8,$D8,$70,$D8,$D8,$70,$00,$00,
+
+ 6, // $39 '9'
+ $00,$00,$00,$70,$D8,$D8,$D8,$78,$18,$70,$00,$00,
+
+ 4, // $3A ':'
+ $00,$00,$00,$00,$00,$60,$60,$00,$60,$60,$00,$00,
+
+ 4, // $3B ';'
+ $00,$00,$00,$00,$00,$60,$60,$00,$60,$60,$40,$00,
+
+ 8, // $3C '<'
+ $00,$00,$00,$00,$04,$18,$60,$60,$18,$04,$00,$00,
+
+ 8, // $3D '='
+ $00,$00,$00,$00,$00,$7C,$00,$7C,$00,$00,$00,$00,
+
+ 8, // $3E '>'
+ $00,$00,$00,$00,$40,$30,$0C,$0C,$30,$40,$00,$00,
+
+ 6, // $3F '?'
+ $00,$00,$00,$F0,$18,$18,$30,$60,$00,$60,$00,$00,
+
+ 9, // $40 '@'
+ $00,$00,$00,$00,$00,$00,$3C,$00,$42,$00,$9D,$00,$A5,$00,$A5,$00,$9E,$00,$40,$00,$3C,$00,$00,$00,
+
+ 8, // $41 'A'
+ $00,$00,$00,$38,$38,$6C,$6C,$7C,$C6,$C6,$00,$00,
+
+ 7, // $42 'B'
+ $00,$00,$00,$F8,$CC,$CC,$F8,$CC,$CC,$F8,$00,$00,
+
+ 6, // $43 'C'
+ $00,$00,$00,$70,$C8,$C0,$C0,$C0,$C8,$70,$00,$00,
+
+ 7, // $44 'D'
+ $00,$00,$00,$F8,$CC,$CC,$CC,$CC,$CC,$F8,$00,$00,
+
+ 6, // $45 'E'
+ $00,$00,$00,$F8,$C0,$C0,$F8,$C0,$C0,$F8,$00,$00,
+
+ 6, // $46 'F'
+ $00,$00,$00,$F8,$C0,$C0,$F8,$C0,$C0,$C0,$00,$00,
+
+ 7, // $47 'G'
+ $00,$00,$00,$78,$C4,$C0,$C0,$DC,$CC,$7C,$00,$00,
+
+ 7, // $48 'H'
+ $00,$00,$00,$CC,$CC,$CC,$FC,$CC,$CC,$CC,$00,$00,
+
+ 5, // $49 'I'
+ $00,$00,$00,$F0,$60,$60,$60,$60,$60,$F0,$00,$00,
+
+ 5, // $4A 'J'
+ $00,$00,$00,$70,$30,$30,$30,$30,$30,$E0,$00,$00,
+
+ 7, // $4B 'K'
+ $00,$00,$00,$CC,$D8,$F0,$E0,$F0,$D8,$CC,$00,$00,
+
+ 6, // $4C 'L'
+ $00,$00,$00,$C0,$C0,$C0,$C0,$C0,$C0,$F8,$00,$00,
+
+ 8, // $4D 'M'
+ $00,$00,$00,$82,$C6,$EE,$B6,$B6,$86,$86,$00,$00,
+
+ 7, // $4E 'N'
+ $00,$00,$00,$84,$C4,$E4,$B4,$9C,$8C,$84,$00,$00,
+
+ 8, // $4F 'O'
+ $00,$00,$00,$7C,$C6,$C6,$C6,$C6,$C6,$7C,$00,$00,
+
+ 7, // $50 'P'
+ $00,$00,$00,$F8,$CC,$CC,$CC,$F8,$C0,$C0,$00,$00,
+
+ 8, // $51 'Q'
+ $00,$00,$00,$7C,$C6,$C6,$C6,$C6,$C6,$7C,$18,$0E,
+
+ 7, // $52 'R'
+ $00,$00,$00,$F8,$CC,$CC,$F8,$D8,$CC,$C6,$00,$00,
+
+ 6, // $53 'S'
+ $00,$00,$00,$70,$C8,$C0,$70,$18,$98,$70,$00,$00,
+
+ 6, // $54 'T'
+ $00,$00,$00,$FC,$30,$30,$30,$30,$30,$30,$00,$00,
+
+ 7, // $55 'U'
+ $00,$00,$00,$CC,$CC,$CC,$CC,$CC,$CC,$78,$00,$00,
+
+ 7, // $56 'V'
+ $00,$00,$00,$CC,$CC,$78,$78,$78,$30,$30,$00,$00,
+
+ 11, // $57 'W'
+ $00,$00,$00,$00,$00,$00,$CC,$C0,$CC,$C0,$6D,$80,$6D,$80,$73,$80,$33,$00,$33,$00,$00,$00,$00,$00,
+
+ 7, // $58 'X'
+ $00,$00,$00,$CC,$CC,$78,$30,$78,$CC,$CC,$00,$00,
+
+ 7, // $59 'Y'
+ $00,$00,$00,$CC,$CC,$78,$30,$30,$30,$30,$00,$00,
+
+ 6, // $5A 'Z'
+ $00,$00,$00,$F8,$18,$30,$60,$C0,$C0,$F8,$00,$00,
+
+ 5, // $5B '['
+ $00,$00,$70,$60,$60,$60,$60,$60,$60,$60,$60,$70,
+
+ 6, // $5C '\'
+ $00,$00,$80,$80,$40,$40,$20,$10,$10,$08,$08,$00,
+
+ 5, // $5D ']'
+ $00,$00,$70,$30,$30,$30,$30,$30,$30,$30,$30,$70,
+
+ 8, // $5E '^'
+ $00,$00,$00,$18,$3C,$66,$00,$00,$00,$00,$00,$00,
+
+ 6, // $5F '_'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FC,
+
+ 6, // $60 '`'
+ $00,$00,$30,$18,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 6, // $61 'a'
+ $00,$00,$00,$00,$00,$70,$18,$78,$D8,$78,$00,$00,
+
+ 6, // $62 'b'
+ $00,$00,$C0,$C0,$C0,$F0,$D8,$D8,$D8,$F0,$00,$00,
+
+ 5, // $63 'c'
+ $00,$00,$00,$00,$00,$70,$C0,$C0,$C0,$70,$00,$00,
+
+ 6, // $64 'd'
+ $00,$00,$18,$18,$18,$78,$D8,$D8,$D8,$78,$00,$00,
+
+ 6, // $65 'e'
+ $00,$00,$00,$00,$00,$70,$D8,$F8,$C0,$78,$00,$00,
+
+ 5, // $66 'f'
+ $00,$00,$38,$60,$60,$F8,$60,$60,$60,$60,$00,$00,
+
+ 6, // $67 'g'
+ $00,$00,$00,$00,$00,$78,$D8,$D8,$D8,$78,$18,$70,
+
+ 6, // $68 'h'
+ $00,$00,$C0,$C0,$C0,$F0,$D8,$D8,$D8,$D8,$00,$00,
+
+ 3, // $69 'i'
+ $00,$00,$00,$C0,$00,$C0,$C0,$C0,$C0,$C0,$00,$00,
+
+ 4, // $6A 'j'
+ $00,$00,$00,$60,$00,$E0,$60,$60,$60,$60,$60,$C0,
+
+ 6, // $6B 'k'
+ $00,$00,$C0,$C0,$C0,$D8,$D8,$F0,$D8,$D8,$00,$00,
+
+ 3, // $6C 'l'
+ $00,$00,$C0,$C0,$C0,$C0,$C0,$C0,$C0,$C0,$00,$00,
+
+ 9, // $6D 'm'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$F6,$00,$DB,$00,$DB,$00,$DB,$00,$DB,$00,$00,$00,$00,$00,
+
+ 6, // $6E 'n'
+ $00,$00,$00,$00,$00,$F0,$D8,$D8,$D8,$D8,$00,$00,
+
+ 6, // $6F 'o'
+ $00,$00,$00,$00,$00,$70,$D8,$D8,$D8,$70,$00,$00,
+
+ 6, // $70 'p'
+ $00,$00,$00,$00,$00,$F0,$D8,$D8,$D8,$F0,$C0,$C0,
+
+ 6, // $71 'q'
+ $00,$00,$00,$00,$00,$78,$D8,$D8,$D8,$78,$18,$18,
+
+ 4, // $72 'r'
+ $00,$00,$00,$00,$00,$D0,$E0,$C0,$C0,$C0,$00,$00,
+
+ 5, // $73 's'
+ $00,$00,$00,$00,$00,$70,$C0,$F0,$30,$E0,$00,$00,
+
+ 5, // $74 't'
+ $00,$00,$00,$60,$60,$F8,$60,$60,$60,$38,$00,$00,
+
+ 6, // $75 'u'
+ $00,$00,$00,$00,$00,$D8,$D8,$D8,$D8,$78,$00,$00,
+
+ 6, // $76 'v'
+ $00,$00,$00,$00,$00,$D8,$D8,$D8,$70,$70,$00,$00,
+
+ 9, // $77 'w'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$DB,$00,$DB,$00,$DB,$00,$66,$00,$66,$00,$00,$00,$00,$00,
+
+ 6, // $78 'x'
+ $00,$00,$00,$00,$00,$D8,$D8,$70,$D8,$D8,$00,$00,
+
+ 6, // $79 'y'
+ $00,$00,$00,$00,$00,$D8,$D8,$D8,$70,$70,$30,$60,
+
+ 5, // $7A 'z'
+ $00,$00,$00,$00,$00,$F0,$30,$60,$C0,$F0,$00,$00,
+
+ 6, // $7B '{'
+ $00,$00,$18,$30,$30,$30,$E0,$30,$30,$30,$30,$18,
+
+ 5, // $7C '|'
+ $00,$00,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,
+
+ 6, // $7D '}'
+ $00,$00,$C0,$60,$60,$60,$38,$60,$60,$60,$60,$C0,
+
+ 8, // $7E '~'
+ $00,$00,$00,$00,$00,$00,$62,$92,$8C,$00,$00,$00,
+
+ 9, // $7F ''
+ $00,$00,$00,$00,$00,$00,$7F,$00,$41,$00,$41,$00,$41,$00,$41,$00,$41,$00,$7F,$00,$00,$00,$00,$00,
+
+ 0 );
+
+ verdana13 : array[0..1787 ] of int8u = (
+ 13, 3, 32, 128-32,
+ $00,$00,$0E,$00,$1C,$00,$2A,$00,$45,$00,$53,$00,$6E,$00,$7C,$00,$8A,$00,
+ $98,$00,$A6,$00,$B4,$00,$CF,$00,$DD,$00,$EB,$00,$F9,$00,$07,$01,$15,$01,
+ $23,$01,$31,$01,$3F,$01,$4D,$01,$5B,$01,$69,$01,$77,$01,$85,$01,$93,$01,
+ $A1,$01,$AF,$01,$CA,$01,$E5,$01,$00,$02,$0E,$02,$29,$02,$37,$02,$45,$02,
+ $60,$02,$7B,$02,$89,$02,$97,$02,$B2,$02,$C0,$02,$CE,$02,$DC,$02,$EA,$02,
+ $F8,$02,$13,$03,$21,$03,$3C,$03,$4A,$03,$65,$03,$73,$03,$81,$03,$8F,$03,
+ $9D,$03,$AB,$03,$C6,$03,$D4,$03,$E2,$03,$F0,$03,$FE,$03,$0C,$04,$1A,$04,
+ $35,$04,$43,$04,$51,$04,$5F,$04,$6D,$04,$7B,$04,$89,$04,$97,$04,$A5,$04,
+ $B3,$04,$C1,$04,$CF,$04,$DD,$04,$EB,$04,$F9,$04,$14,$05,$22,$05,$30,$05,
+ $3E,$05,$4C,$05,$5A,$05,$68,$05,$76,$05,$84,$05,$92,$05,$AD,$05,$BB,$05,
+ $C9,$05,$D7,$05,$E5,$05,$F3,$05,$01,$06,$1C,$06,
+
+ 4, // $20 ' '
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 4, // $21 '!'
+ $00,$00,$00,$20,$20,$20,$20,$20,$20,$00,$20,$00,$00,
+
+ 5, // $22 '"'
+ $00,$00,$50,$50,$50,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $23 '#'
+ $00,$00,$00,$00,$00,$00,$0A,$00,$0A,$00,$3F,$00,$14,$00,$14,$00,$7E,$00,$28,$00,$28,$00,$00,$00,$00,$00,
+
+ 7, // $24 '$'
+ $00,$00,$10,$10,$3C,$50,$50,$38,$14,$14,$78,$10,$10,
+
+ 12, // $25 '%'
+ $00,$00,$00,$00,$00,$00,$31,$00,$49,$00,$4A,$00,$32,$00,$04,$C0,$05,$20,$09,$20,$08,$C0,$00,$00,$00,$00,
+
+ 8, // $26 '&'
+ $00,$00,$00,$30,$48,$48,$32,$4A,$44,$46,$39,$00,$00,
+
+ 3, // $27 '''
+ $00,$00,$40,$40,$40,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 5, // $28 '('
+ $00,$00,$10,$20,$20,$40,$40,$40,$40,$40,$20,$20,$10,
+
+ 5, // $29 ')'
+ $00,$00,$40,$20,$20,$10,$10,$10,$10,$10,$20,$20,$40,
+
+ 7, // $2A '*'
+ $00,$00,$10,$54,$38,$54,$10,$00,$00,$00,$00,$00,$00,
+
+ 9, // $2B '+'
+ $00,$00,$00,$00,$00,$00,$00,$00,$08,$00,$08,$00,$08,$00,$7F,$00,$08,$00,$08,$00,$08,$00,$00,$00,$00,$00,
+
+ 4, // $2C ','
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$20,$20,$20,$40,
+
+ 5, // $2D '-'
+ $00,$00,$00,$00,$00,$00,$00,$70,$00,$00,$00,$00,$00,
+
+ 4, // $2E '.'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$20,$20,$00,$00,
+
+ 5, // $2F '/'
+ $00,$00,$08,$08,$10,$10,$20,$20,$40,$40,$80,$80,$00,
+
+ 7, // $30 '0'
+ $00,$00,$00,$38,$44,$44,$44,$44,$44,$44,$38,$00,$00,
+
+ 7, // $31 '1'
+ $00,$00,$00,$10,$70,$10,$10,$10,$10,$10,$7C,$00,$00,
+
+ 7, // $32 '2'
+ $00,$00,$00,$38,$44,$04,$08,$10,$20,$40,$7C,$00,$00,
+
+ 7, // $33 '3'
+ $00,$00,$00,$38,$44,$04,$18,$04,$04,$44,$38,$00,$00,
+
+ 7, // $34 '4'
+ $00,$00,$00,$08,$18,$28,$48,$88,$FC,$08,$08,$00,$00,
+
+ 7, // $35 '5'
+ $00,$00,$00,$7C,$40,$40,$78,$04,$04,$44,$38,$00,$00,
+
+ 7, // $36 '6'
+ $00,$00,$00,$18,$20,$40,$78,$44,$44,$44,$38,$00,$00,
+
+ 7, // $37 '7'
+ $00,$00,$00,$7C,$04,$08,$08,$10,$10,$20,$20,$00,$00,
+
+ 7, // $38 '8'
+ $00,$00,$00,$38,$44,$44,$38,$44,$44,$44,$38,$00,$00,
+
+ 7, // $39 '9'
+ $00,$00,$00,$38,$44,$44,$44,$3C,$04,$08,$30,$00,$00,
+
+ 5, // $3A ':'
+ $00,$00,$00,$00,$00,$20,$20,$00,$00,$20,$20,$00,$00,
+
+ 5, // $3B ';'
+ $00,$00,$00,$00,$00,$20,$20,$00,$00,$20,$20,$20,$40,
+
+ 9, // $3C '<'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$06,$00,$18,$00,$60,$00,$18,$00,$06,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $3D '='
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$7F,$00,$00,$00,$7F,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $3E '>'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$30,$00,$0C,$00,$03,$00,$0C,$00,$30,$00,$00,$00,$00,$00,$00,$00,
+
+ 6, // $3F '?'
+ $00,$00,$00,$70,$08,$08,$10,$20,$20,$00,$20,$00,$00,
+
+ 10, // $40 '@'
+ $00,$00,$00,$00,$00,$00,$1F,$00,$20,$80,$4E,$80,$52,$80,$52,$80,$52,$80,$4D,$00,$20,$00,$1E,$00,$00,$00,
+
+ 8, // $41 'A'
+ $00,$00,$00,$18,$18,$24,$24,$24,$7E,$42,$42,$00,$00,
+
+ 8, // $42 'B'
+ $00,$00,$00,$78,$44,$44,$7C,$42,$42,$42,$7C,$00,$00,
+
+ 9, // $43 'C'
+ $00,$00,$00,$00,$00,$00,$1E,$00,$21,$00,$40,$00,$40,$00,$40,$00,$40,$00,$21,$00,$1E,$00,$00,$00,$00,$00,
+
+ 9, // $44 'D'
+ $00,$00,$00,$00,$00,$00,$7C,$00,$42,$00,$41,$00,$41,$00,$41,$00,$41,$00,$42,$00,$7C,$00,$00,$00,$00,$00,
+
+ 7, // $45 'E'
+ $00,$00,$00,$7C,$40,$40,$7C,$40,$40,$40,$7C,$00,$00,
+
+ 6, // $46 'F'
+ $00,$00,$00,$7C,$40,$40,$78,$40,$40,$40,$40,$00,$00,
+
+ 9, // $47 'G'
+ $00,$00,$00,$00,$00,$00,$1E,$00,$21,$00,$40,$00,$40,$00,$47,$00,$41,$00,$21,$00,$1E,$00,$00,$00,$00,$00,
+
+ 8, // $48 'H'
+ $00,$00,$00,$42,$42,$42,$7E,$42,$42,$42,$42,$00,$00,
+
+ 5, // $49 'I'
+ $00,$00,$00,$70,$20,$20,$20,$20,$20,$20,$70,$00,$00,
+
+ 5, // $4A 'J'
+ $00,$00,$00,$70,$10,$10,$10,$10,$10,$10,$E0,$00,$00,
+
+ 8, // $4B 'K'
+ $00,$00,$00,$42,$44,$48,$50,$70,$48,$44,$42,$00,$00,
+
+ 6, // $4C 'L'
+ $00,$00,$00,$40,$40,$40,$40,$40,$40,$40,$7C,$00,$00,
+
+ 9, // $4D 'M'
+ $00,$00,$00,$00,$00,$00,$63,$00,$63,$00,$55,$00,$55,$00,$49,$00,$49,$00,$41,$00,$41,$00,$00,$00,$00,$00,
+
+ 8, // $4E 'N'
+ $00,$00,$00,$62,$62,$52,$52,$4A,$4A,$46,$46,$00,$00,
+
+ 9, // $4F 'O'
+ $00,$00,$00,$00,$00,$00,$1C,$00,$22,$00,$41,$00,$41,$00,$41,$00,$41,$00,$22,$00,$1C,$00,$00,$00,$00,$00,
+
+ 7, // $50 'P'
+ $00,$00,$00,$78,$44,$44,$44,$78,$40,$40,$40,$00,$00,
+
+ 9, // $51 'Q'
+ $00,$00,$00,$00,$00,$00,$1C,$00,$22,$00,$41,$00,$41,$00,$41,$00,$41,$00,$22,$00,$1C,$00,$04,$00,$03,$00,
+
+ 8, // $52 'R'
+ $00,$00,$00,$78,$44,$44,$44,$78,$48,$44,$42,$00,$00,
+
+ 8, // $53 'S'
+ $00,$00,$00,$3C,$42,$40,$30,$0C,$02,$42,$3C,$00,$00,
+
+ 7, // $54 'T'
+ $00,$00,$00,$FE,$10,$10,$10,$10,$10,$10,$10,$00,$00,
+
+ 8, // $55 'U'
+ $00,$00,$00,$42,$42,$42,$42,$42,$42,$42,$3C,$00,$00,
+
+ 8, // $56 'V'
+ $00,$00,$00,$42,$42,$42,$24,$24,$24,$18,$18,$00,$00,
+
+ 11, // $57 'W'
+ $00,$00,$00,$00,$00,$00,$44,$40,$44,$40,$2A,$80,$2A,$80,$2A,$80,$2A,$80,$11,$00,$11,$00,$00,$00,$00,$00,
+
+ 8, // $58 'X'
+ $00,$00,$00,$42,$42,$24,$18,$18,$24,$42,$42,$00,$00,
+
+ 7, // $59 'Y'
+ $00,$00,$00,$82,$44,$28,$10,$10,$10,$10,$10,$00,$00,
+
+ 8, // $5A 'Z'
+ $00,$00,$00,$7E,$02,$04,$08,$10,$20,$40,$7E,$00,$00,
+
+ 5, // $5B '['
+ $00,$00,$70,$40,$40,$40,$40,$40,$40,$40,$40,$40,$70,
+
+ 5, // $5C '\'
+ $00,$00,$80,$80,$40,$40,$20,$20,$10,$10,$08,$08,$00,
+
+ 5, // $5D ']'
+ $00,$00,$70,$10,$10,$10,$10,$10,$10,$10,$10,$10,$70,
+
+ 9, // $5E '^'
+ $00,$00,$00,$00,$00,$00,$08,$00,$14,$00,$22,$00,$41,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $5F '_'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FE,
+
+ 7, // $60 '`'
+ $00,$00,$20,$10,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $61 'a'
+ $00,$00,$00,$00,$00,$38,$04,$3C,$44,$44,$3C,$00,$00,
+
+ 7, // $62 'b'
+ $00,$00,$40,$40,$40,$78,$44,$44,$44,$44,$78,$00,$00,
+
+ 6, // $63 'c'
+ $00,$00,$00,$00,$00,$38,$44,$40,$40,$44,$38,$00,$00,
+
+ 7, // $64 'd'
+ $00,$00,$04,$04,$04,$3C,$44,$44,$44,$44,$3C,$00,$00,
+
+ 7, // $65 'e'
+ $00,$00,$00,$00,$00,$38,$44,$7C,$40,$44,$38,$00,$00,
+
+ 4, // $66 'f'
+ $00,$00,$30,$40,$40,$F0,$40,$40,$40,$40,$40,$00,$00,
+
+ 7, // $67 'g'
+ $00,$00,$00,$00,$00,$3C,$44,$44,$44,$44,$3C,$04,$38,
+
+ 7, // $68 'h'
+ $00,$00,$40,$40,$40,$78,$44,$44,$44,$44,$44,$00,$00,
+
+ 3, // $69 'i'
+ $00,$00,$40,$00,$00,$40,$40,$40,$40,$40,$40,$00,$00,
+
+ 4, // $6A 'j'
+ $00,$00,$20,$00,$00,$60,$20,$20,$20,$20,$20,$20,$C0,
+
+ 7, // $6B 'k'
+ $00,$00,$40,$40,$40,$44,$48,$50,$70,$48,$44,$00,$00,
+
+ 3, // $6C 'l'
+ $00,$00,$40,$40,$40,$40,$40,$40,$40,$40,$40,$00,$00,
+
+ 11, // $6D 'm'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$7B,$80,$44,$40,$44,$40,$44,$40,$44,$40,$44,$40,$00,$00,$00,$00,
+
+ 7, // $6E 'n'
+ $00,$00,$00,$00,$00,$78,$44,$44,$44,$44,$44,$00,$00,
+
+ 7, // $6F 'o'
+ $00,$00,$00,$00,$00,$38,$44,$44,$44,$44,$38,$00,$00,
+
+ 7, // $70 'p'
+ $00,$00,$00,$00,$00,$78,$44,$44,$44,$44,$78,$40,$40,
+
+ 7, // $71 'q'
+ $00,$00,$00,$00,$00,$3C,$44,$44,$44,$44,$3C,$04,$04,
+
+ 5, // $72 'r'
+ $00,$00,$00,$00,$00,$58,$60,$40,$40,$40,$40,$00,$00,
+
+ 6, // $73 's'
+ $00,$00,$00,$00,$00,$38,$40,$60,$18,$08,$70,$00,$00,
+
+ 4, // $74 't'
+ $00,$00,$00,$40,$40,$F0,$40,$40,$40,$40,$30,$00,$00,
+
+ 7, // $75 'u'
+ $00,$00,$00,$00,$00,$44,$44,$44,$44,$44,$3C,$00,$00,
+
+ 7, // $76 'v'
+ $00,$00,$00,$00,$00,$44,$44,$28,$28,$10,$10,$00,$00,
+
+ 9, // $77 'w'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$49,$00,$49,$00,$55,$00,$55,$00,$22,$00,$22,$00,$00,$00,$00,$00,
+
+ 7, // $78 'x'
+ $00,$00,$00,$00,$00,$44,$28,$10,$10,$28,$44,$00,$00,
+
+ 7, // $79 'y'
+ $00,$00,$00,$00,$00,$44,$28,$28,$28,$10,$10,$10,$20,
+
+ 6, // $7A 'z'
+ $00,$00,$00,$00,$00,$78,$08,$10,$20,$40,$78,$00,$00,
+
+ 7, // $7B '{'
+ $00,$00,$0C,$10,$10,$10,$10,$60,$10,$10,$10,$10,$0C,
+
+ 5, // $7C '|'
+ $00,$00,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,
+
+ 7, // $7D '}'
+ $00,$00,$60,$10,$10,$10,$10,$0C,$10,$10,$10,$10,$60,
+
+ 9, // $7E '~'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$31,$00,$49,$00,$46,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 11, // $7F ''
+ $00,$00,$00,$00,$00,$00,$7F,$80,$40,$80,$40,$80,$40,$80,$40,$80,$40,$80,$40,$80,$7F,$80,$00,$00,$00,$00,
+
+ 0 );
+
+ verdana13_bold : array[0..1839 ] of int8u = (
+ 13, 3, 32, 128-32,
+ $00,$00,$0E,$00,$1C,$00,$2A,$00,$45,$00,$53,$00,$6E,$00,$89,$00,$97,$00,
+ $A5,$00,$B3,$00,$C1,$00,$DC,$00,$EA,$00,$F8,$00,$06,$01,$14,$01,$22,$01,
+ $30,$01,$3E,$01,$4C,$01,$5A,$01,$68,$01,$76,$01,$84,$01,$92,$01,$A0,$01,
+ $AE,$01,$BC,$01,$D7,$01,$F2,$01,$0D,$02,$1B,$02,$36,$02,$51,$02,$5F,$02,
+ $6D,$02,$88,$02,$96,$02,$A4,$02,$BF,$02,$DA,$02,$E8,$02,$F6,$02,$04,$03,
+ $12,$03,$2D,$03,$48,$03,$63,$03,$71,$03,$8C,$03,$9A,$03,$A8,$03,$B6,$03,
+ $D1,$03,$DF,$03,$FA,$03,$08,$04,$16,$04,$24,$04,$32,$04,$40,$04,$4E,$04,
+ $69,$04,$77,$04,$85,$04,$93,$04,$A1,$04,$AF,$04,$BD,$04,$CB,$04,$D9,$04,
+ $E7,$04,$F5,$04,$03,$05,$11,$05,$1F,$05,$2D,$05,$48,$05,$56,$05,$64,$05,
+ $72,$05,$80,$05,$8E,$05,$9C,$05,$AA,$05,$B8,$05,$C6,$05,$E1,$05,$EF,$05,
+ $FD,$05,$0B,$06,$19,$06,$27,$06,$35,$06,$50,$06,
+
+ 4, // $20 ' '
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 4, // $21 '!'
+ $00,$00,$00,$60,$60,$60,$60,$60,$60,$00,$60,$00,$00,
+
+ 7, // $22 '"'
+ $00,$00,$6C,$6C,$6C,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $23 '#'
+ $00,$00,$00,$00,$00,$00,$0A,$00,$0A,$00,$3F,$00,$14,$00,$14,$00,$7E,$00,$28,$00,$28,$00,$00,$00,$00,$00,
+
+ 8, // $24 '$'
+ $00,$00,$08,$08,$3C,$6A,$68,$3C,$16,$56,$3C,$10,$10,
+
+ 14, // $25 '%'
+ $00,$00,$00,$00,$00,$00,$38,$80,$6C,$80,$6D,$00,$6D,$70,$3A,$D8,$02,$D8,$04,$D8,$04,$70,$00,$00,$00,$00,
+
+ 10, // $26 '&'
+ $00,$00,$00,$00,$00,$00,$38,$00,$6C,$00,$6C,$00,$39,$80,$6D,$00,$66,$00,$63,$00,$3D,$80,$00,$00,$00,$00,
+
+ 4, // $27 '''
+ $00,$00,$60,$60,$60,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 6, // $28 '('
+ $00,$00,$18,$30,$30,$60,$60,$60,$60,$60,$30,$30,$18,
+
+ 6, // $29 ')'
+ $00,$00,$60,$30,$30,$18,$18,$18,$18,$18,$30,$30,$60,
+
+ 8, // $2A '*'
+ $00,$00,$10,$54,$38,$54,$10,$00,$00,$00,$00,$00,$00,
+
+ 9, // $2B '+'
+ $00,$00,$00,$00,$00,$00,$00,$00,$08,$00,$08,$00,$08,$00,$7F,$00,$08,$00,$08,$00,$08,$00,$00,$00,$00,$00,
+
+ 4, // $2C ','
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$60,$60,$60,$40,
+
+ 6, // $2D '-'
+ $00,$00,$00,$00,$00,$00,$00,$78,$00,$00,$00,$00,$00,
+
+ 4, // $2E '.'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$60,$60,$00,$00,
+
+ 8, // $2F '/'
+ $00,$00,$06,$06,$0C,$0C,$18,$18,$18,$30,$30,$60,$60,
+
+ 8, // $30 '0'
+ $00,$00,$00,$3C,$66,$66,$66,$66,$66,$66,$3C,$00,$00,
+
+ 8, // $31 '1'
+ $00,$00,$00,$18,$38,$18,$18,$18,$18,$18,$3C,$00,$00,
+
+ 8, // $32 '2'
+ $00,$00,$00,$3C,$66,$06,$0C,$18,$30,$60,$7E,$00,$00,
+
+ 8, // $33 '3'
+ $00,$00,$00,$3C,$66,$06,$1C,$06,$06,$66,$3C,$00,$00,
+
+ 8, // $34 '4'
+ $00,$00,$00,$04,$0C,$1C,$2C,$4C,$7E,$0C,$0C,$00,$00,
+
+ 8, // $35 '5'
+ $00,$00,$00,$3E,$30,$30,$3C,$06,$06,$66,$3C,$00,$00,
+
+ 8, // $36 '6'
+ $00,$00,$00,$1C,$30,$60,$7C,$66,$66,$66,$3C,$00,$00,
+
+ 8, // $37 '7'
+ $00,$00,$00,$7E,$06,$0C,$0C,$18,$18,$30,$30,$00,$00,
+
+ 8, // $38 '8'
+ $00,$00,$00,$3C,$66,$66,$3C,$66,$66,$66,$3C,$00,$00,
+
+ 8, // $39 '9'
+ $00,$00,$00,$3C,$66,$66,$66,$3E,$06,$0C,$38,$00,$00,
+
+ 4, // $3A ':'
+ $00,$00,$00,$00,$00,$60,$60,$00,$00,$60,$60,$00,$00,
+
+ 4, // $3B ';'
+ $00,$00,$00,$00,$00,$60,$60,$00,$00,$60,$60,$60,$40,
+
+ 9, // $3C '<'
+ $00,$00,$00,$00,$00,$00,$00,$00,$03,$00,$0C,$00,$30,$00,$40,$00,$30,$00,$0C,$00,$03,$00,$00,$00,$00,$00,
+
+ 9, // $3D '='
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$7F,$00,$00,$00,$00,$00,$7F,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $3E '>'
+ $00,$00,$00,$00,$00,$00,$00,$00,$60,$00,$18,$00,$06,$00,$01,$00,$06,$00,$18,$00,$60,$00,$00,$00,$00,$00,
+
+ 7, // $3F '?'
+ $00,$00,$00,$38,$4C,$0C,$18,$30,$30,$00,$30,$00,$00,
+
+ 11, // $40 '@'
+ $00,$00,$00,$00,$00,$00,$1F,$80,$20,$40,$4F,$40,$5B,$40,$5B,$40,$5B,$40,$4F,$80,$20,$00,$1F,$00,$00,$00,
+
+ 9, // $41 'A'
+ $00,$00,$00,$00,$00,$00,$1C,$00,$1C,$00,$36,$00,$36,$00,$36,$00,$7F,$00,$63,$00,$63,$00,$00,$00,$00,$00,
+
+ 8, // $42 'B'
+ $00,$00,$00,$7C,$66,$66,$7C,$66,$66,$66,$7C,$00,$00,
+
+ 8, // $43 'C'
+ $00,$00,$00,$3C,$62,$60,$60,$60,$60,$62,$3C,$00,$00,
+
+ 9, // $44 'D'
+ $00,$00,$00,$00,$00,$00,$7C,$00,$66,$00,$63,$00,$63,$00,$63,$00,$63,$00,$66,$00,$7C,$00,$00,$00,$00,$00,
+
+ 8, // $45 'E'
+ $00,$00,$00,$7E,$60,$60,$7E,$60,$60,$60,$7E,$00,$00,
+
+ 8, // $46 'F'
+ $00,$00,$00,$7E,$60,$60,$7E,$60,$60,$60,$60,$00,$00,
+
+ 9, // $47 'G'
+ $00,$00,$00,$00,$00,$00,$3E,$00,$61,$00,$60,$00,$60,$00,$67,$00,$63,$00,$63,$00,$3F,$00,$00,$00,$00,$00,
+
+ 9, // $48 'H'
+ $00,$00,$00,$00,$00,$00,$63,$00,$63,$00,$63,$00,$7F,$00,$63,$00,$63,$00,$63,$00,$63,$00,$00,$00,$00,$00,
+
+ 6, // $49 'I'
+ $00,$00,$00,$78,$30,$30,$30,$30,$30,$30,$78,$00,$00,
+
+ 6, // $4A 'J'
+ $00,$00,$00,$78,$18,$18,$18,$18,$18,$18,$F0,$00,$00,
+
+ 8, // $4B 'K'
+ $00,$00,$00,$66,$6C,$78,$70,$70,$78,$6C,$66,$00,$00,
+
+ 7, // $4C 'L'
+ $00,$00,$00,$60,$60,$60,$60,$60,$60,$60,$7E,$00,$00,
+
+ 10, // $4D 'M'
+ $00,$00,$00,$00,$00,$00,$60,$80,$71,$80,$7B,$80,$5D,$80,$49,$80,$41,$80,$41,$80,$41,$80,$00,$00,$00,$00,
+
+ 9, // $4E 'N'
+ $00,$00,$00,$00,$00,$00,$41,$00,$61,$00,$71,$00,$59,$00,$4D,$00,$47,$00,$43,$00,$41,$00,$00,$00,$00,$00,
+
+ 9, // $4F 'O'
+ $00,$00,$00,$00,$00,$00,$3E,$00,$63,$00,$63,$00,$63,$00,$63,$00,$63,$00,$63,$00,$3E,$00,$00,$00,$00,$00,
+
+ 8, // $50 'P'
+ $00,$00,$00,$7C,$66,$66,$66,$7C,$60,$60,$60,$00,$00,
+
+ 9, // $51 'Q'
+ $00,$00,$00,$00,$00,$00,$3E,$00,$63,$00,$63,$00,$63,$00,$63,$00,$63,$00,$63,$00,$3E,$00,$0C,$00,$07,$00,
+
+ 8, // $52 'R'
+ $00,$00,$00,$7C,$66,$66,$66,$7C,$6C,$66,$63,$00,$00,
+
+ 8, // $53 'S'
+ $00,$00,$00,$3C,$62,$60,$7C,$3E,$06,$46,$3C,$00,$00,
+
+ 8, // $54 'T'
+ $00,$00,$00,$FF,$18,$18,$18,$18,$18,$18,$18,$00,$00,
+
+ 9, // $55 'U'
+ $00,$00,$00,$00,$00,$00,$63,$00,$63,$00,$63,$00,$63,$00,$63,$00,$63,$00,$63,$00,$3E,$00,$00,$00,$00,$00,
+
+ 8, // $56 'V'
+ $00,$00,$00,$66,$66,$66,$3C,$3C,$3C,$18,$18,$00,$00,
+
+ 12, // $57 'W'
+ $00,$00,$00,$00,$00,$00,$66,$60,$66,$60,$66,$60,$36,$C0,$3F,$C0,$39,$C0,$19,$80,$19,$80,$00,$00,$00,$00,
+
+ 8, // $58 'X'
+ $00,$00,$00,$66,$66,$3C,$18,$18,$3C,$66,$66,$00,$00,
+
+ 8, // $59 'Y'
+ $00,$00,$00,$66,$66,$3C,$3C,$18,$18,$18,$18,$00,$00,
+
+ 8, // $5A 'Z'
+ $00,$00,$00,$7E,$06,$0E,$1C,$38,$70,$60,$7E,$00,$00,
+
+ 6, // $5B '['
+ $00,$00,$78,$60,$60,$60,$60,$60,$60,$60,$60,$60,$78,
+
+ 8, // $5C '\'
+ $00,$00,$60,$60,$30,$30,$18,$18,$18,$0C,$0C,$06,$06,
+
+ 6, // $5D ']'
+ $00,$00,$78,$18,$18,$18,$18,$18,$18,$18,$18,$18,$78,
+
+ 10, // $5E '^'
+ $00,$00,$00,$00,$00,$00,$0C,$00,$1E,$00,$33,$00,$61,$80,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 8, // $5F '_'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,
+
+ 8, // $60 '`'
+ $00,$00,$30,$18,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 8, // $61 'a'
+ $00,$00,$00,$00,$00,$3C,$06,$3E,$66,$66,$3E,$00,$00,
+
+ 8, // $62 'b'
+ $00,$00,$60,$60,$60,$7C,$66,$66,$66,$66,$7C,$00,$00,
+
+ 7, // $63 'c'
+ $00,$00,$00,$00,$00,$3C,$60,$60,$60,$60,$3C,$00,$00,
+
+ 8, // $64 'd'
+ $00,$00,$06,$06,$06,$3E,$66,$66,$66,$66,$3E,$00,$00,
+
+ 8, // $65 'e'
+ $00,$00,$00,$00,$00,$3C,$66,$7E,$60,$62,$3C,$00,$00,
+
+ 5, // $66 'f'
+ $00,$00,$38,$60,$60,$F8,$60,$60,$60,$60,$60,$00,$00,
+
+ 8, // $67 'g'
+ $00,$00,$00,$00,$00,$3E,$66,$66,$66,$66,$3E,$06,$3C,
+
+ 8, // $68 'h'
+ $00,$00,$60,$60,$60,$7C,$66,$66,$66,$66,$66,$00,$00,
+
+ 4, // $69 'i'
+ $00,$00,$00,$60,$00,$60,$60,$60,$60,$60,$60,$00,$00,
+
+ 5, // $6A 'j'
+ $00,$00,$00,$30,$00,$70,$30,$30,$30,$30,$30,$30,$E0,
+
+ 8, // $6B 'k'
+ $00,$00,$60,$60,$60,$66,$6C,$78,$78,$6C,$66,$00,$00,
+
+ 4, // $6C 'l'
+ $00,$00,$60,$60,$60,$60,$60,$60,$60,$60,$60,$00,$00,
+
+ 12, // $6D 'm'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$7D,$C0,$66,$60,$66,$60,$66,$60,$66,$60,$66,$60,$00,$00,$00,$00,
+
+ 8, // $6E 'n'
+ $00,$00,$00,$00,$00,$7C,$66,$66,$66,$66,$66,$00,$00,
+
+ 8, // $6F 'o'
+ $00,$00,$00,$00,$00,$3C,$66,$66,$66,$66,$3C,$00,$00,
+
+ 8, // $70 'p'
+ $00,$00,$00,$00,$00,$7C,$66,$66,$66,$66,$7C,$60,$60,
+
+ 8, // $71 'q'
+ $00,$00,$00,$00,$00,$3E,$66,$66,$66,$66,$3E,$06,$06,
+
+ 6, // $72 'r'
+ $00,$00,$00,$00,$00,$6C,$7C,$60,$60,$60,$60,$00,$00,
+
+ 7, // $73 's'
+ $00,$00,$00,$00,$00,$3C,$60,$78,$3C,$0C,$78,$00,$00,
+
+ 5, // $74 't'
+ $00,$00,$00,$60,$60,$F8,$60,$60,$60,$60,$38,$00,$00,
+
+ 8, // $75 'u'
+ $00,$00,$00,$00,$00,$66,$66,$66,$66,$66,$3E,$00,$00,
+
+ 8, // $76 'v'
+ $00,$00,$00,$00,$00,$66,$66,$66,$3C,$3C,$18,$00,$00,
+
+ 10, // $77 'w'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$6D,$80,$6D,$80,$6D,$80,$6D,$80,$33,$00,$33,$00,$00,$00,$00,$00,
+
+ 8, // $78 'x'
+ $00,$00,$00,$00,$00,$66,$66,$3C,$3C,$66,$66,$00,$00,
+
+ 8, // $79 'y'
+ $00,$00,$00,$00,$00,$66,$66,$3C,$3C,$18,$18,$30,$30,
+
+ 7, // $7A 'z'
+ $00,$00,$00,$00,$00,$7C,$0C,$18,$30,$60,$7C,$00,$00,
+
+ 8, // $7B '{'
+ $00,$00,$0E,$18,$18,$18,$18,$70,$18,$18,$18,$18,$0E,
+
+ 6, // $7C '|'
+ $00,$00,$30,$30,$30,$30,$30,$30,$30,$30,$30,$30,$30,
+
+ 8, // $7D '}'
+ $00,$00,$70,$18,$18,$18,$18,$0E,$18,$18,$18,$18,$70,
+
+ 9, // $7E '~'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$31,$00,$49,$00,$49,$00,$46,$00,$00,$00,$00,$00,$00,$00,
+
+ 11, // $7F ''
+ $00,$00,$00,$00,$00,$00,$7F,$80,$40,$80,$40,$80,$40,$80,$40,$80,$40,$80,$40,$80,$7F,$80,$00,$00,$00,$00,
+
+ 0 );
+
+ verdana14 : array[0..1958 ] of int8u = (
+ 14, 3, 32, 128-32,
+ $00,$00,$0F,$00,$1E,$00,$2D,$00,$4A,$00,$59,$00,$76,$00,$93,$00,$A2,$00,
+ $B1,$00,$C0,$00,$CF,$00,$EC,$00,$FB,$00,$0A,$01,$19,$01,$28,$01,$37,$01,
+ $46,$01,$55,$01,$64,$01,$73,$01,$82,$01,$91,$01,$A0,$01,$AF,$01,$BE,$01,
+ $CD,$01,$DC,$01,$F9,$01,$16,$02,$33,$02,$42,$02,$5F,$02,$6E,$02,$7D,$02,
+ $9A,$02,$B7,$02,$C6,$02,$D5,$02,$F2,$02,$0F,$03,$1E,$03,$2D,$03,$3C,$03,
+ $4B,$03,$68,$03,$85,$03,$A2,$03,$B1,$03,$CE,$03,$DD,$03,$EC,$03,$FB,$03,
+ $18,$04,$27,$04,$44,$04,$53,$04,$62,$04,$71,$04,$80,$04,$8F,$04,$9E,$04,
+ $BB,$04,$CA,$04,$D9,$04,$E8,$04,$F7,$04,$06,$05,$15,$05,$24,$05,$33,$05,
+ $42,$05,$51,$05,$60,$05,$6F,$05,$7E,$05,$8D,$05,$AA,$05,$B9,$05,$C8,$05,
+ $D7,$05,$E6,$05,$F5,$05,$04,$06,$13,$06,$22,$06,$31,$06,$4E,$06,$5D,$06,
+ $6C,$06,$7B,$06,$8A,$06,$99,$06,$A8,$06,$C5,$06,
+
+ 4, // $20 ' '
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 5, // $21 '!'
+ $00,$00,$00,$20,$20,$20,$20,$20,$20,$20,$00,$20,$00,$00,
+
+ 6, // $22 '"'
+ $00,$00,$48,$48,$48,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $23 '#'
+ $00,$00,$00,$00,$00,$00,$09,$00,$09,$00,$12,$00,$3F,$80,$12,$00,$12,$00,$7F,$00,$24,$00,$24,$00,$00,$00,$00,$00,
+
+ 8, // $24 '$'
+ $00,$00,$10,$10,$3E,$50,$50,$30,$1C,$12,$12,$7C,$10,$10,
+
+ 13, // $25 '%'
+ $00,$00,$00,$00,$00,$00,$30,$80,$49,$00,$49,$00,$4A,$00,$32,$60,$02,$90,$04,$90,$04,$90,$08,$60,$00,$00,$00,$00,
+
+ 10, // $26 '&'
+ $00,$00,$00,$00,$00,$00,$38,$00,$44,$00,$44,$00,$44,$00,$39,$00,$45,$00,$42,$00,$43,$00,$3C,$80,$00,$00,$00,$00,
+
+ 3, // $27 '''
+ $00,$00,$40,$40,$40,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 5, // $28 '('
+ $00,$00,$10,$20,$20,$40,$40,$40,$40,$40,$40,$20,$20,$10,
+
+ 5, // $29 ')'
+ $00,$00,$40,$20,$20,$10,$10,$10,$10,$10,$10,$20,$20,$40,
+
+ 8, // $2A '*'
+ $00,$00,$10,$54,$38,$54,$10,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $2B '+'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$08,$00,$08,$00,$08,$00,$7F,$00,$08,$00,$08,$00,$08,$00,$00,$00,$00,$00,
+
+ 4, // $2C ','
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$20,$20,$20,$40,
+
+ 5, // $2D '-'
+ $00,$00,$00,$00,$00,$00,$00,$00,$78,$00,$00,$00,$00,$00,
+
+ 4, // $2E '.'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$20,$20,$00,$00,
+
+ 5, // $2F '/'
+ $00,$00,$08,$08,$10,$10,$10,$20,$20,$20,$40,$40,$40,$80,
+
+ 8, // $30 '0'
+ $00,$00,$00,$3C,$42,$42,$42,$42,$42,$42,$42,$3C,$00,$00,
+
+ 8, // $31 '1'
+ $00,$00,$00,$08,$38,$08,$08,$08,$08,$08,$08,$3E,$00,$00,
+
+ 8, // $32 '2'
+ $00,$00,$00,$3C,$42,$42,$02,$04,$18,$20,$40,$7E,$00,$00,
+
+ 8, // $33 '3'
+ $00,$00,$00,$3C,$42,$02,$02,$1C,$02,$02,$42,$3C,$00,$00,
+
+ 8, // $34 '4'
+ $00,$00,$00,$04,$0C,$14,$24,$44,$7F,$04,$04,$04,$00,$00,
+
+ 8, // $35 '5'
+ $00,$00,$00,$7E,$40,$40,$7C,$02,$02,$02,$42,$3C,$00,$00,
+
+ 8, // $36 '6'
+ $00,$00,$00,$1C,$20,$40,$7C,$42,$42,$42,$42,$3C,$00,$00,
+
+ 8, // $37 '7'
+ $00,$00,$00,$7E,$02,$04,$04,$08,$08,$10,$10,$20,$00,$00,
+
+ 8, // $38 '8'
+ $00,$00,$00,$3C,$42,$42,$42,$3C,$42,$42,$42,$3C,$00,$00,
+
+ 8, // $39 '9'
+ $00,$00,$00,$3C,$42,$42,$42,$42,$3E,$02,$04,$38,$00,$00,
+
+ 5, // $3A ':'
+ $00,$00,$00,$00,$00,$20,$20,$00,$00,$00,$20,$20,$00,$00,
+
+ 5, // $3B ';'
+ $00,$00,$00,$00,$00,$20,$20,$00,$00,$00,$20,$20,$20,$40,
+
+ 9, // $3C '<'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$03,$00,$0C,$00,$30,$00,$40,$00,$30,$00,$0C,$00,$03,$00,$00,$00,$00,$00,
+
+ 9, // $3D '='
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$7F,$00,$00,$00,$7F,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $3E '>'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$60,$00,$18,$00,$06,$00,$01,$00,$06,$00,$18,$00,$60,$00,$00,$00,$00,$00,
+
+ 7, // $3F '?'
+ $00,$00,$00,$38,$44,$04,$04,$08,$10,$10,$00,$10,$00,$00,
+
+ 12, // $40 '@'
+ $00,$00,$00,$00,$00,$00,$0F,$00,$30,$C0,$27,$40,$49,$20,$49,$20,$49,$20,$49,$20,$27,$C0,$30,$00,$0F,$00,$00,$00,
+
+ 8, // $41 'A'
+ $00,$00,$00,$18,$18,$24,$24,$42,$42,$7E,$81,$81,$00,$00,
+
+ 8, // $42 'B'
+ $00,$00,$00,$78,$44,$44,$44,$7C,$42,$42,$42,$7C,$00,$00,
+
+ 9, // $43 'C'
+ $00,$00,$00,$00,$00,$00,$1E,$00,$21,$00,$40,$00,$40,$00,$40,$00,$40,$00,$40,$00,$21,$00,$1E,$00,$00,$00,$00,$00,
+
+ 9, // $44 'D'
+ $00,$00,$00,$00,$00,$00,$7C,$00,$42,$00,$41,$00,$41,$00,$41,$00,$41,$00,$41,$00,$42,$00,$7C,$00,$00,$00,$00,$00,
+
+ 8, // $45 'E'
+ $00,$00,$00,$7E,$40,$40,$40,$7E,$40,$40,$40,$7E,$00,$00,
+
+ 7, // $46 'F'
+ $00,$00,$00,$7E,$40,$40,$40,$7C,$40,$40,$40,$40,$00,$00,
+
+ 9, // $47 'G'
+ $00,$00,$00,$00,$00,$00,$1E,$00,$21,$00,$40,$00,$40,$00,$47,$00,$41,$00,$41,$00,$21,$00,$1E,$00,$00,$00,$00,$00,
+
+ 9, // $48 'H'
+ $00,$00,$00,$00,$00,$00,$41,$00,$41,$00,$41,$00,$41,$00,$7F,$00,$41,$00,$41,$00,$41,$00,$41,$00,$00,$00,$00,$00,
+
+ 5, // $49 'I'
+ $00,$00,$00,$70,$20,$20,$20,$20,$20,$20,$20,$70,$00,$00,
+
+ 5, // $4A 'J'
+ $00,$00,$00,$70,$10,$10,$10,$10,$10,$10,$10,$E0,$00,$00,
+
+ 8, // $4B 'K'
+ $00,$00,$00,$42,$44,$48,$50,$60,$50,$48,$44,$42,$00,$00,
+
+ 7, // $4C 'L'
+ $00,$00,$00,$40,$40,$40,$40,$40,$40,$40,$40,$7E,$00,$00,
+
+ 10, // $4D 'M'
+ $00,$00,$00,$00,$00,$00,$61,$80,$61,$80,$52,$80,$52,$80,$52,$80,$4C,$80,$4C,$80,$40,$80,$40,$80,$00,$00,$00,$00,
+
+ 9, // $4E 'N'
+ $00,$00,$00,$00,$00,$00,$61,$00,$61,$00,$51,$00,$51,$00,$49,$00,$45,$00,$45,$00,$43,$00,$43,$00,$00,$00,$00,$00,
+
+ 10, // $4F 'O'
+ $00,$00,$00,$00,$00,$00,$1E,$00,$21,$00,$40,$80,$40,$80,$40,$80,$40,$80,$40,$80,$21,$00,$1E,$00,$00,$00,$00,$00,
+
+ 8, // $50 'P'
+ $00,$00,$00,$7C,$42,$42,$42,$42,$7C,$40,$40,$40,$00,$00,
+
+ 10, // $51 'Q'
+ $00,$00,$00,$00,$00,$00,$1E,$00,$21,$00,$40,$80,$40,$80,$40,$80,$40,$80,$40,$80,$21,$00,$1E,$00,$02,$00,$01,$80,
+
+ 8, // $52 'R'
+ $00,$00,$00,$7C,$42,$42,$42,$7C,$48,$44,$42,$41,$00,$00,
+
+ 8, // $53 'S'
+ $00,$00,$00,$3C,$42,$40,$40,$3C,$02,$02,$42,$3C,$00,$00,
+
+ 7, // $54 'T'
+ $00,$00,$00,$FE,$10,$10,$10,$10,$10,$10,$10,$10,$00,$00,
+
+ 9, // $55 'U'
+ $00,$00,$00,$00,$00,$00,$41,$00,$41,$00,$41,$00,$41,$00,$41,$00,$41,$00,$41,$00,$22,$00,$1C,$00,$00,$00,$00,$00,
+
+ 8, // $56 'V'
+ $00,$00,$00,$81,$81,$42,$42,$42,$24,$24,$18,$18,$00,$00,
+
+ 13, // $57 'W'
+ $00,$00,$00,$00,$00,$00,$42,$10,$42,$10,$45,$10,$45,$10,$25,$20,$28,$A0,$28,$A0,$10,$40,$10,$40,$00,$00,$00,$00,
+
+ 8, // $58 'X'
+ $00,$00,$00,$42,$42,$24,$18,$18,$18,$24,$42,$42,$00,$00,
+
+ 7, // $59 'Y'
+ $00,$00,$00,$82,$44,$44,$28,$10,$10,$10,$10,$10,$00,$00,
+
+ 8, // $5A 'Z'
+ $00,$00,$00,$7E,$02,$04,$08,$10,$10,$20,$40,$7E,$00,$00,
+
+ 5, // $5B '['
+ $00,$00,$70,$40,$40,$40,$40,$40,$40,$40,$40,$40,$40,$70,
+
+ 5, // $5C '\'
+ $00,$00,$80,$80,$40,$40,$40,$20,$20,$10,$10,$10,$08,$08,
+
+ 5, // $5D ']'
+ $00,$00,$70,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$70,
+
+ 10, // $5E '^'
+ $00,$00,$00,$00,$00,$00,$0C,$00,$12,$00,$21,$00,$40,$80,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 8, // $5F '_'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,
+
+ 8, // $60 '`'
+ $00,$00,$20,$10,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 8, // $61 'a'
+ $00,$00,$00,$00,$00,$3C,$02,$02,$3E,$42,$42,$3E,$00,$00,
+
+ 8, // $62 'b'
+ $00,$00,$40,$40,$40,$5C,$62,$42,$42,$42,$42,$7C,$00,$00,
+
+ 6, // $63 'c'
+ $00,$00,$00,$00,$00,$38,$44,$40,$40,$40,$44,$38,$00,$00,
+
+ 8, // $64 'd'
+ $00,$00,$02,$02,$02,$3E,$42,$42,$42,$42,$46,$3A,$00,$00,
+
+ 8, // $65 'e'
+ $00,$00,$00,$00,$00,$3C,$42,$42,$7E,$40,$42,$3C,$00,$00,
+
+ 4, // $66 'f'
+ $00,$00,$30,$40,$40,$F0,$40,$40,$40,$40,$40,$40,$00,$00,
+
+ 8, // $67 'g'
+ $00,$00,$00,$00,$00,$3E,$42,$42,$42,$42,$46,$3A,$02,$3C,
+
+ 8, // $68 'h'
+ $00,$00,$40,$40,$40,$5C,$62,$42,$42,$42,$42,$42,$00,$00,
+
+ 3, // $69 'i'
+ $00,$00,$40,$00,$00,$40,$40,$40,$40,$40,$40,$40,$00,$00,
+
+ 4, // $6A 'j'
+ $00,$00,$20,$00,$00,$60,$20,$20,$20,$20,$20,$20,$20,$C0,
+
+ 7, // $6B 'k'
+ $00,$00,$40,$40,$40,$44,$48,$50,$60,$50,$48,$44,$00,$00,
+
+ 3, // $6C 'l'
+ $00,$00,$40,$40,$40,$40,$40,$40,$40,$40,$40,$40,$00,$00,
+
+ 11, // $6D 'm'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$7B,$80,$44,$40,$44,$40,$44,$40,$44,$40,$44,$40,$44,$40,$00,$00,$00,$00,
+
+ 8, // $6E 'n'
+ $00,$00,$00,$00,$00,$5C,$62,$42,$42,$42,$42,$42,$00,$00,
+
+ 8, // $6F 'o'
+ $00,$00,$00,$00,$00,$3C,$42,$42,$42,$42,$42,$3C,$00,$00,
+
+ 8, // $70 'p'
+ $00,$00,$00,$00,$00,$5C,$62,$42,$42,$42,$42,$7C,$40,$40,
+
+ 8, // $71 'q'
+ $00,$00,$00,$00,$00,$3E,$42,$42,$42,$42,$46,$3A,$02,$02,
+
+ 5, // $72 'r'
+ $00,$00,$00,$00,$00,$58,$60,$40,$40,$40,$40,$40,$00,$00,
+
+ 7, // $73 's'
+ $00,$00,$00,$00,$00,$3C,$40,$40,$38,$04,$04,$78,$00,$00,
+
+ 5, // $74 't'
+ $00,$00,$00,$40,$40,$F8,$40,$40,$40,$40,$40,$38,$00,$00,
+
+ 8, // $75 'u'
+ $00,$00,$00,$00,$00,$42,$42,$42,$42,$42,$46,$3A,$00,$00,
+
+ 7, // $76 'v'
+ $00,$00,$00,$00,$00,$44,$44,$28,$28,$28,$10,$10,$00,$00,
+
+ 11, // $77 'w'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$44,$40,$44,$40,$2A,$80,$2A,$80,$2A,$80,$11,$00,$11,$00,$00,$00,$00,$00,
+
+ 7, // $78 'x'
+ $00,$00,$00,$00,$00,$44,$44,$28,$10,$28,$44,$44,$00,$00,
+
+ 7, // $79 'y'
+ $00,$00,$00,$00,$00,$44,$44,$28,$28,$28,$10,$10,$10,$20,
+
+ 7, // $7A 'z'
+ $00,$00,$00,$00,$00,$7C,$04,$08,$10,$20,$40,$7C,$00,$00,
+
+ 8, // $7B '{'
+ $00,$00,$0C,$10,$10,$10,$10,$60,$10,$10,$10,$10,$10,$0C,
+
+ 5, // $7C '|'
+ $00,$00,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,
+
+ 8, // $7D '}'
+ $00,$00,$30,$08,$08,$08,$08,$06,$08,$08,$08,$08,$08,$30,
+
+ 10, // $7E '~'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$30,$80,$4C,$80,$43,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 12, // $7F ''
+ $00,$00,$00,$00,$00,$00,$3F,$E0,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$3F,$E0,$00,$00,$00,$00,
+
+ 0 );
+
+ verdana14_bold : array[0..2308 ] of int8u = (
+ 14, 3, 32, 128-32,
+ $00,$00,$0F,$00,$1E,$00,$2D,$00,$4A,$00,$67,$00,$84,$00,$A1,$00,$B0,$00,
+ $BF,$00,$CE,$00,$EB,$00,$08,$01,$17,$01,$26,$01,$35,$01,$44,$01,$61,$01,
+ $7E,$01,$9B,$01,$B8,$01,$D5,$01,$F2,$01,$0F,$02,$2C,$02,$49,$02,$66,$02,
+ $75,$02,$84,$02,$A1,$02,$BE,$02,$DB,$02,$EA,$02,$07,$03,$24,$03,$41,$03,
+ $5E,$03,$7B,$03,$8A,$03,$99,$03,$B6,$03,$D3,$03,$E2,$03,$F1,$03,$0E,$04,
+ $1D,$04,$3A,$04,$57,$04,$74,$04,$91,$04,$AE,$04,$CB,$04,$E8,$04,$F7,$04,
+ $14,$05,$31,$05,$4E,$05,$6B,$05,$88,$05,$97,$05,$A6,$05,$B5,$05,$C4,$05,
+ $E1,$05,$FE,$05,$1B,$06,$2A,$06,$39,$06,$48,$06,$57,$06,$66,$06,$75,$06,
+ $84,$06,$93,$06,$A2,$06,$B1,$06,$C0,$06,$CF,$06,$EC,$06,$FB,$06,$0A,$07,
+ $19,$07,$28,$07,$37,$07,$46,$07,$55,$07,$64,$07,$73,$07,$90,$07,$9F,$07,
+ $AE,$07,$BD,$07,$DA,$07,$E9,$07,$06,$08,$23,$08,
+
+ 4, // $20 ' '
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 5, // $21 '!'
+ $00,$00,$00,$60,$60,$60,$60,$60,$60,$00,$60,$60,$00,$00,
+
+ 7, // $22 '"'
+ $00,$00,$6C,$6C,$6C,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $23 '#'
+ $00,$00,$00,$00,$00,$00,$09,$00,$09,$00,$3F,$80,$3F,$80,$12,$00,$7F,$00,$7F,$00,$24,$00,$24,$00,$00,$00,$00,$00,
+
+ 9, // $24 '$'
+ $00,$00,$00,$00,$08,$00,$08,$00,$3E,$00,$69,$00,$68,$00,$7E,$00,$3F,$00,$0B,$00,$4B,$00,$3E,$00,$08,$00,$08,$00,
+
+ 15, // $25 '%'
+ $00,$00,$00,$00,$00,$00,$38,$40,$6C,$40,$6C,$80,$6C,$B8,$6D,$6C,$3A,$6C,$02,$6C,$04,$6C,$04,$38,$00,$00,$00,$00,
+
+ 10, // $26 '&'
+ $00,$00,$00,$00,$00,$00,$38,$00,$6C,$00,$6C,$00,$6C,$00,$39,$80,$6D,$00,$66,$00,$63,$00,$3D,$80,$00,$00,$00,$00,
+
+ 4, // $27 '''
+ $00,$00,$60,$60,$60,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $28 '('
+ $00,$00,$18,$30,$30,$60,$60,$60,$60,$60,$60,$30,$30,$18,
+
+ 7, // $29 ')'
+ $00,$00,$30,$18,$18,$0C,$0C,$0C,$0C,$0C,$0C,$18,$18,$30,
+
+ 9, // $2A '*'
+ $00,$00,$00,$00,$08,$00,$2A,$00,$1C,$00,$1C,$00,$2A,$00,$08,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $2B '+'
+ $00,$00,$00,$00,$00,$00,$00,$00,$08,$00,$08,$00,$08,$00,$7F,$00,$08,$00,$08,$00,$08,$00,$00,$00,$00,$00,$00,$00,
+
+ 4, // $2C ','
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$60,$60,$60,$40,
+
+ 6, // $2D '-'
+ $00,$00,$00,$00,$00,$00,$00,$78,$00,$00,$00,$00,$00,$00,
+
+ 4, // $2E '.'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$60,$60,$00,$00,
+
+ 8, // $2F '/'
+ $00,$00,$06,$06,$0C,$0C,$0C,$18,$18,$30,$30,$30,$60,$60,
+
+ 9, // $30 '0'
+ $00,$00,$00,$00,$00,$00,$3E,$00,$63,$00,$63,$00,$63,$00,$63,$00,$63,$00,$63,$00,$63,$00,$3E,$00,$00,$00,$00,$00,
+
+ 9, // $31 '1'
+ $00,$00,$00,$00,$00,$00,$0C,$00,$3C,$00,$0C,$00,$0C,$00,$0C,$00,$0C,$00,$0C,$00,$0C,$00,$3F,$00,$00,$00,$00,$00,
+
+ 9, // $32 '2'
+ $00,$00,$00,$00,$00,$00,$3E,$00,$63,$00,$03,$00,$03,$00,$06,$00,$0C,$00,$18,$00,$30,$00,$7F,$00,$00,$00,$00,$00,
+
+ 9, // $33 '3'
+ $00,$00,$00,$00,$00,$00,$3E,$00,$63,$00,$03,$00,$03,$00,$1E,$00,$03,$00,$03,$00,$63,$00,$3E,$00,$00,$00,$00,$00,
+
+ 9, // $34 '4'
+ $00,$00,$00,$00,$00,$00,$06,$00,$0E,$00,$16,$00,$16,$00,$26,$00,$46,$00,$7F,$00,$06,$00,$06,$00,$00,$00,$00,$00,
+
+ 9, // $35 '5'
+ $00,$00,$00,$00,$00,$00,$3F,$00,$30,$00,$30,$00,$3E,$00,$03,$00,$03,$00,$03,$00,$63,$00,$3E,$00,$00,$00,$00,$00,
+
+ 9, // $36 '6'
+ $00,$00,$00,$00,$00,$00,$1E,$00,$30,$00,$60,$00,$7E,$00,$63,$00,$63,$00,$63,$00,$63,$00,$3E,$00,$00,$00,$00,$00,
+
+ 9, // $37 '7'
+ $00,$00,$00,$00,$00,$00,$7F,$00,$03,$00,$06,$00,$06,$00,$0C,$00,$0C,$00,$18,$00,$18,$00,$30,$00,$00,$00,$00,$00,
+
+ 9, // $38 '8'
+ $00,$00,$00,$00,$00,$00,$3E,$00,$63,$00,$63,$00,$63,$00,$3E,$00,$63,$00,$63,$00,$63,$00,$3E,$00,$00,$00,$00,$00,
+
+ 9, // $39 '9'
+ $00,$00,$00,$00,$00,$00,$3E,$00,$63,$00,$63,$00,$63,$00,$63,$00,$3F,$00,$03,$00,$06,$00,$3C,$00,$00,$00,$00,$00,
+
+ 5, // $3A ':'
+ $00,$00,$00,$00,$00,$60,$60,$00,$00,$00,$60,$60,$00,$00,
+
+ 5, // $3B ';'
+ $00,$00,$00,$00,$00,$60,$60,$00,$00,$00,$60,$60,$60,$40,
+
+ 10, // $3C '<'
+ $00,$00,$00,$00,$00,$00,$00,$00,$01,$00,$06,$00,$18,$00,$60,$00,$60,$00,$18,$00,$06,$00,$01,$00,$00,$00,$00,$00,
+
+ 10, // $3D '='
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$7F,$00,$00,$00,$00,$00,$7F,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $3E '>'
+ $00,$00,$00,$00,$00,$00,$00,$00,$40,$00,$30,$00,$0C,$00,$03,$00,$03,$00,$0C,$00,$30,$00,$40,$00,$00,$00,$00,$00,
+
+ 7, // $3F '?'
+ $00,$00,$00,$38,$4C,$0C,$18,$30,$30,$00,$30,$30,$00,$00,
+
+ 12, // $40 '@'
+ $00,$00,$00,$00,$00,$00,$0F,$00,$30,$C0,$2F,$40,$5B,$20,$5B,$20,$5B,$20,$5B,$20,$2F,$C0,$30,$00,$0F,$00,$00,$00,
+
+ 9, // $41 'A'
+ $00,$00,$00,$00,$00,$00,$1C,$00,$1C,$00,$36,$00,$36,$00,$36,$00,$36,$00,$7F,$00,$63,$00,$63,$00,$00,$00,$00,$00,
+
+ 9, // $42 'B'
+ $00,$00,$00,$00,$00,$00,$7C,$00,$66,$00,$66,$00,$66,$00,$7E,$00,$63,$00,$63,$00,$63,$00,$7E,$00,$00,$00,$00,$00,
+
+ 9, // $43 'C'
+ $00,$00,$00,$00,$00,$00,$1E,$00,$31,$00,$60,$00,$60,$00,$60,$00,$60,$00,$60,$00,$31,$00,$1E,$00,$00,$00,$00,$00,
+
+ 10, // $44 'D'
+ $00,$00,$00,$00,$00,$00,$7E,$00,$63,$00,$61,$80,$61,$80,$61,$80,$61,$80,$61,$80,$63,$00,$7E,$00,$00,$00,$00,$00,
+
+ 8, // $45 'E'
+ $00,$00,$00,$7E,$60,$60,$60,$7E,$60,$60,$60,$7E,$00,$00,
+
+ 8, // $46 'F'
+ $00,$00,$00,$7E,$60,$60,$60,$7E,$60,$60,$60,$60,$00,$00,
+
+ 10, // $47 'G'
+ $00,$00,$00,$00,$00,$00,$1F,$00,$30,$80,$60,$00,$60,$00,$60,$00,$67,$80,$61,$80,$31,$80,$1F,$80,$00,$00,$00,$00,
+
+ 10, // $48 'H'
+ $00,$00,$00,$00,$00,$00,$61,$80,$61,$80,$61,$80,$61,$80,$7F,$80,$61,$80,$61,$80,$61,$80,$61,$80,$00,$00,$00,$00,
+
+ 6, // $49 'I'
+ $00,$00,$00,$78,$30,$30,$30,$30,$30,$30,$30,$78,$00,$00,
+
+ 7, // $4A 'J'
+ $00,$00,$00,$7C,$0C,$0C,$0C,$0C,$0C,$0C,$0C,$F8,$00,$00,
+
+ 9, // $4B 'K'
+ $00,$00,$00,$00,$00,$00,$63,$00,$66,$00,$6C,$00,$78,$00,$70,$00,$78,$00,$6C,$00,$66,$00,$63,$00,$00,$00,$00,$00,
+
+ 8, // $4C 'L'
+ $00,$00,$00,$60,$60,$60,$60,$60,$60,$60,$60,$7F,$00,$00,
+
+ 11, // $4D 'M'
+ $00,$00,$00,$00,$00,$00,$60,$C0,$71,$C0,$71,$C0,$5A,$C0,$5A,$C0,$4C,$C0,$4C,$C0,$40,$C0,$40,$C0,$00,$00,$00,$00,
+
+ 10, // $4E 'N'
+ $00,$00,$00,$00,$00,$00,$60,$80,$70,$80,$58,$80,$58,$80,$4C,$80,$46,$80,$46,$80,$43,$80,$41,$80,$00,$00,$00,$00,
+
+ 11, // $4F 'O'
+ $00,$00,$00,$00,$00,$00,$1F,$00,$31,$80,$60,$C0,$60,$C0,$60,$C0,$60,$C0,$60,$C0,$31,$80,$1F,$00,$00,$00,$00,$00,
+
+ 9, // $50 'P'
+ $00,$00,$00,$00,$00,$00,$7E,$00,$63,$00,$63,$00,$63,$00,$63,$00,$7E,$00,$60,$00,$60,$00,$60,$00,$00,$00,$00,$00,
+
+ 11, // $51 'Q'
+ $00,$00,$00,$00,$00,$00,$1F,$00,$31,$80,$60,$C0,$60,$C0,$60,$C0,$60,$C0,$60,$C0,$31,$80,$1F,$00,$06,$00,$03,$C0,
+
+ 9, // $52 'R'
+ $00,$00,$00,$00,$00,$00,$7E,$00,$63,$00,$63,$00,$63,$00,$7E,$00,$6C,$00,$66,$00,$63,$00,$61,$80,$00,$00,$00,$00,
+
+ 9, // $53 'S'
+ $00,$00,$00,$00,$00,$00,$3E,$00,$61,$00,$60,$00,$70,$00,$3E,$00,$07,$00,$03,$00,$43,$00,$3E,$00,$00,$00,$00,$00,
+
+ 8, // $54 'T'
+ $00,$00,$00,$FF,$18,$18,$18,$18,$18,$18,$18,$18,$00,$00,
+
+ 10, // $55 'U'
+ $00,$00,$00,$00,$00,$00,$61,$80,$61,$80,$61,$80,$61,$80,$61,$80,$61,$80,$61,$80,$61,$80,$3F,$00,$00,$00,$00,$00,
+
+ 9, // $56 'V'
+ $00,$00,$00,$00,$00,$00,$63,$00,$63,$00,$63,$00,$36,$00,$36,$00,$36,$00,$1C,$00,$1C,$00,$1C,$00,$00,$00,$00,$00,
+
+ 14, // $57 'W'
+ $00,$00,$00,$00,$00,$00,$63,$18,$63,$18,$63,$18,$33,$30,$37,$B0,$34,$B0,$1C,$E0,$18,$60,$18,$60,$00,$00,$00,$00,
+
+ 9, // $58 'X'
+ $00,$00,$00,$00,$00,$00,$63,$00,$63,$00,$36,$00,$1C,$00,$1C,$00,$1C,$00,$36,$00,$63,$00,$63,$00,$00,$00,$00,$00,
+
+ 10, // $59 'Y'
+ $00,$00,$00,$00,$00,$00,$61,$80,$61,$80,$33,$00,$1E,$00,$0C,$00,$0C,$00,$0C,$00,$0C,$00,$0C,$00,$00,$00,$00,$00,
+
+ 8, // $5A 'Z'
+ $00,$00,$00,$7E,$0C,$0C,$18,$18,$30,$30,$60,$7E,$00,$00,
+
+ 6, // $5B '['
+ $00,$00,$78,$60,$60,$60,$60,$60,$60,$60,$60,$60,$60,$78,
+
+ 8, // $5C '\'
+ $00,$00,$60,$60,$30,$30,$30,$18,$18,$0C,$0C,$0C,$06,$06,
+
+ 6, // $5D ']'
+ $00,$00,$78,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$78,
+
+ 10, // $5E '^'
+ $00,$00,$00,$00,$00,$00,$0C,$00,$1E,$00,$33,$00,$61,$80,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $5F '_'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$80,
+
+ 9, // $60 '`'
+ $00,$00,$00,$00,$30,$00,$18,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 8, // $61 'a'
+ $00,$00,$00,$00,$00,$3C,$06,$3E,$66,$66,$66,$3E,$00,$00,
+
+ 8, // $62 'b'
+ $00,$00,$60,$60,$60,$7C,$66,$66,$66,$66,$66,$7C,$00,$00,
+
+ 7, // $63 'c'
+ $00,$00,$00,$00,$00,$3C,$62,$60,$60,$60,$62,$3C,$00,$00,
+
+ 8, // $64 'd'
+ $00,$00,$06,$06,$06,$3E,$66,$66,$66,$66,$66,$3E,$00,$00,
+
+ 8, // $65 'e'
+ $00,$00,$00,$00,$00,$3C,$66,$66,$7E,$60,$62,$3C,$00,$00,
+
+ 5, // $66 'f'
+ $00,$00,$38,$60,$60,$F8,$60,$60,$60,$60,$60,$60,$00,$00,
+
+ 8, // $67 'g'
+ $00,$00,$00,$00,$00,$3E,$66,$66,$66,$66,$66,$3E,$06,$3C,
+
+ 8, // $68 'h'
+ $00,$00,$60,$60,$60,$7C,$66,$66,$66,$66,$66,$66,$00,$00,
+
+ 4, // $69 'i'
+ $00,$00,$60,$60,$00,$60,$60,$60,$60,$60,$60,$60,$00,$00,
+
+ 5, // $6A 'j'
+ $00,$00,$30,$30,$00,$70,$30,$30,$30,$30,$30,$30,$30,$E0,
+
+ 8, // $6B 'k'
+ $00,$00,$60,$60,$60,$66,$6C,$78,$78,$6C,$66,$63,$00,$00,
+
+ 4, // $6C 'l'
+ $00,$00,$60,$60,$60,$60,$60,$60,$60,$60,$60,$60,$00,$00,
+
+ 12, // $6D 'm'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$6C,$C0,$77,$60,$66,$60,$66,$60,$66,$60,$66,$60,$66,$60,$00,$00,$00,$00,
+
+ 8, // $6E 'n'
+ $00,$00,$00,$00,$00,$7C,$66,$66,$66,$66,$66,$66,$00,$00,
+
+ 8, // $6F 'o'
+ $00,$00,$00,$00,$00,$3C,$66,$66,$66,$66,$66,$3C,$00,$00,
+
+ 8, // $70 'p'
+ $00,$00,$00,$00,$00,$7C,$66,$66,$66,$66,$66,$7C,$60,$60,
+
+ 8, // $71 'q'
+ $00,$00,$00,$00,$00,$3E,$66,$66,$66,$66,$66,$3E,$06,$06,
+
+ 6, // $72 'r'
+ $00,$00,$00,$00,$00,$6C,$7C,$60,$60,$60,$60,$60,$00,$00,
+
+ 7, // $73 's'
+ $00,$00,$00,$00,$00,$3C,$60,$60,$38,$0C,$0C,$78,$00,$00,
+
+ 5, // $74 't'
+ $00,$00,$00,$60,$60,$F8,$60,$60,$60,$60,$60,$38,$00,$00,
+
+ 8, // $75 'u'
+ $00,$00,$00,$00,$00,$66,$66,$66,$66,$66,$66,$3E,$00,$00,
+
+ 8, // $76 'v'
+ $00,$00,$00,$00,$00,$66,$66,$66,$3C,$3C,$3C,$18,$00,$00,
+
+ 12, // $77 'w'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$60,$66,$60,$66,$60,$69,$60,$39,$C0,$30,$C0,$30,$C0,$00,$00,$00,$00,
+
+ 8, // $78 'x'
+ $00,$00,$00,$00,$00,$66,$66,$3C,$18,$3C,$66,$66,$00,$00,
+
+ 8, // $79 'y'
+ $00,$00,$00,$00,$00,$66,$66,$66,$3C,$3C,$3C,$18,$18,$30,
+
+ 7, // $7A 'z'
+ $00,$00,$00,$00,$00,$7C,$0C,$18,$38,$30,$60,$7C,$00,$00,
+
+ 9, // $7B '{'
+ $00,$00,$00,$00,$0E,$00,$18,$00,$18,$00,$18,$00,$18,$00,$70,$00,$18,$00,$18,$00,$18,$00,$18,$00,$18,$00,$0E,$00,
+
+ 6, // $7C '|'
+ $00,$00,$30,$30,$30,$30,$30,$30,$30,$30,$30,$30,$30,$30,
+
+ 9, // $7D '}'
+ $00,$00,$00,$00,$38,$00,$0C,$00,$0C,$00,$0C,$00,$0C,$00,$07,$00,$0C,$00,$0C,$00,$0C,$00,$0C,$00,$0C,$00,$38,$00,
+
+ 10, // $7E '~'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$30,$80,$48,$80,$44,$80,$43,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 12, // $7F ''
+ $00,$00,$00,$00,$00,$00,$3F,$E0,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$3F,$E0,$00,$00,$00,$00,
+
+ 0 );
+
+ verdana16 : array[0..2340 ] of int8u = (
+ 16, 4, 32, 128-32,
+ $00,$00,$11,$00,$22,$00,$33,$00,$54,$00,$65,$00,$86,$00,$A7,$00,$B8,$00,
+ $C9,$00,$DA,$00,$FB,$00,$1C,$01,$2D,$01,$3E,$01,$4F,$01,$60,$01,$71,$01,
+ $82,$01,$93,$01,$A4,$01,$B5,$01,$C6,$01,$D7,$01,$E8,$01,$F9,$01,$0A,$02,
+ $1B,$02,$2C,$02,$4D,$02,$6E,$02,$8F,$02,$A0,$02,$C1,$02,$E2,$02,$F3,$02,
+ $14,$03,$35,$03,$46,$03,$57,$03,$78,$03,$99,$03,$AA,$03,$BB,$03,$CC,$03,
+ $DD,$03,$FE,$03,$1F,$04,$40,$04,$51,$04,$72,$04,$93,$04,$B4,$04,$D5,$04,
+ $F6,$04,$17,$05,$38,$05,$59,$05,$7A,$05,$9B,$05,$AC,$05,$BD,$05,$CE,$05,
+ $EF,$05,$00,$06,$11,$06,$22,$06,$33,$06,$44,$06,$55,$06,$66,$06,$77,$06,
+ $88,$06,$99,$06,$AA,$06,$BB,$06,$CC,$06,$DD,$06,$FE,$06,$0F,$07,$20,$07,
+ $31,$07,$42,$07,$53,$07,$64,$07,$75,$07,$86,$07,$97,$07,$B8,$07,$C9,$07,
+ $DA,$07,$EB,$07,$FC,$07,$0D,$08,$1E,$08,$3F,$08,
+
+ 5, // $20 ' '
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 5, // $21 '!'
+ $00,$00,$00,$00,$20,$20,$20,$20,$20,$20,$00,$20,$20,$00,$00,$00,
+
+ 5, // $22 '"'
+ $00,$00,$00,$50,$50,$50,$50,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $23 '#'
+ $00,$00,$00,$00,$00,$00,$00,$00,$09,$00,$09,$00,$3F,$80,$12,$00,$12,$00,$7F,$00,$24,$00,$24,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 8, // $24 '$'
+ $00,$00,$00,$10,$10,$3E,$50,$50,$30,$1C,$12,$12,$7C,$10,$10,$00,
+
+ 13, // $25 '%'
+ $00,$00,$00,$00,$00,$00,$00,$00,$38,$40,$44,$80,$45,$00,$45,$00,$3A,$E0,$05,$10,$05,$10,$09,$10,$10,$E0,$00,$00,$00,$00,$00,$00,
+
+ 10, // $26 '&'
+ $00,$00,$00,$00,$00,$00,$00,$00,$38,$00,$44,$00,$44,$00,$44,$00,$38,$80,$45,$00,$42,$00,$46,$00,$39,$80,$00,$00,$00,$00,$00,$00,
+
+ 3, // $27 '''
+ $00,$00,$00,$40,$40,$40,$40,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 6, // $28 '('
+ $00,$00,$00,$08,$10,$20,$20,$40,$40,$40,$40,$40,$20,$20,$10,$08,
+
+ 6, // $29 ')'
+ $00,$00,$00,$40,$20,$10,$10,$08,$08,$08,$08,$08,$10,$10,$20,$40,
+
+ 9, // $2A '*'
+ $00,$00,$00,$00,$00,$00,$08,$00,$2A,$00,$1C,$00,$2A,$00,$08,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $2B '+'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$08,$00,$08,$00,$08,$00,$7F,$00,$08,$00,$08,$00,$08,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 5, // $2C ','
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$20,$20,$20,$40,$00,
+
+ 7, // $2D '-'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7C,$00,$00,$00,$00,$00,$00,$00,
+
+ 5, // $2E '.'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$20,$20,$00,$00,$00,
+
+ 6, // $2F '/'
+ $00,$00,$00,$04,$04,$08,$08,$10,$10,$20,$20,$40,$40,$80,$80,$00,
+
+ 8, // $30 '0'
+ $00,$00,$00,$00,$3C,$42,$42,$42,$42,$42,$42,$42,$3C,$00,$00,$00,
+
+ 8, // $31 '1'
+ $00,$00,$00,$00,$08,$38,$08,$08,$08,$08,$08,$08,$3E,$00,$00,$00,
+
+ 8, // $32 '2'
+ $00,$00,$00,$00,$3C,$42,$42,$02,$04,$18,$20,$40,$7E,$00,$00,$00,
+
+ 8, // $33 '3'
+ $00,$00,$00,$00,$3C,$42,$02,$02,$1C,$02,$02,$42,$3C,$00,$00,$00,
+
+ 8, // $34 '4'
+ $00,$00,$00,$00,$04,$0C,$14,$24,$44,$7F,$04,$04,$04,$00,$00,$00,
+
+ 8, // $35 '5'
+ $00,$00,$00,$00,$3E,$20,$20,$20,$3C,$02,$02,$42,$3C,$00,$00,$00,
+
+ 8, // $36 '6'
+ $00,$00,$00,$00,$1C,$20,$40,$7C,$42,$42,$42,$42,$3C,$00,$00,$00,
+
+ 8, // $37 '7'
+ $00,$00,$00,$00,$7E,$02,$04,$04,$08,$08,$10,$10,$10,$00,$00,$00,
+
+ 8, // $38 '8'
+ $00,$00,$00,$00,$3C,$42,$42,$42,$3C,$42,$42,$42,$3C,$00,$00,$00,
+
+ 8, // $39 '9'
+ $00,$00,$00,$00,$3C,$42,$42,$42,$42,$3E,$02,$04,$38,$00,$00,$00,
+
+ 6, // $3A ':'
+ $00,$00,$00,$00,$00,$00,$20,$20,$00,$00,$00,$20,$20,$00,$00,$00,
+
+ 6, // $3B ';'
+ $00,$00,$00,$00,$00,$00,$20,$20,$00,$00,$00,$20,$20,$20,$40,$00,
+
+ 9, // $3C '<'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$03,$00,$0C,$00,$30,$00,$40,$00,$30,$00,$0C,$00,$03,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $3D '='
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$7F,$00,$00,$00,$00,$00,$7F,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $3E '>'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$60,$00,$18,$00,$06,$00,$01,$00,$06,$00,$18,$00,$60,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $3F '?'
+ $00,$00,$00,$00,$38,$44,$04,$08,$10,$10,$00,$10,$10,$00,$00,$00,
+
+ 13, // $40 '@'
+ $00,$00,$00,$00,$00,$00,$00,$00,$0F,$80,$10,$40,$27,$A0,$48,$90,$48,$90,$48,$90,$48,$90,$48,$90,$27,$E0,$10,$00,$0F,$80,$00,$00,
+
+ 9, // $41 'A'
+ $00,$00,$00,$00,$00,$00,$00,$00,$08,$00,$08,$00,$14,$00,$14,$00,$22,$00,$22,$00,$3E,$00,$41,$00,$41,$00,$00,$00,$00,$00,$00,$00,
+
+ 8, // $42 'B'
+ $00,$00,$00,$00,$78,$44,$44,$44,$7C,$42,$42,$42,$7C,$00,$00,$00,
+
+ 9, // $43 'C'
+ $00,$00,$00,$00,$00,$00,$00,$00,$1E,$00,$21,$00,$40,$00,$40,$00,$40,$00,$40,$00,$40,$00,$21,$00,$1E,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $44 'D'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7C,$00,$42,$00,$41,$00,$41,$00,$41,$00,$41,$00,$41,$00,$42,$00,$7C,$00,$00,$00,$00,$00,$00,$00,
+
+ 8, // $45 'E'
+ $00,$00,$00,$00,$7E,$40,$40,$40,$7E,$40,$40,$40,$7E,$00,$00,$00,
+
+ 8, // $46 'F'
+ $00,$00,$00,$00,$7E,$40,$40,$40,$7C,$40,$40,$40,$40,$00,$00,$00,
+
+ 9, // $47 'G'
+ $00,$00,$00,$00,$00,$00,$00,$00,$1E,$00,$21,$00,$40,$00,$40,$00,$40,$00,$47,$00,$41,$00,$21,$00,$1F,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $48 'H'
+ $00,$00,$00,$00,$00,$00,$00,$00,$41,$00,$41,$00,$41,$00,$41,$00,$7F,$00,$41,$00,$41,$00,$41,$00,$41,$00,$00,$00,$00,$00,$00,$00,
+
+ 5, // $49 'I'
+ $00,$00,$00,$00,$70,$20,$20,$20,$20,$20,$20,$20,$70,$00,$00,$00,
+
+ 6, // $4A 'J'
+ $00,$00,$00,$00,$38,$08,$08,$08,$08,$08,$08,$08,$F0,$00,$00,$00,
+
+ 8, // $4B 'K'
+ $00,$00,$00,$00,$42,$44,$48,$50,$60,$50,$48,$44,$42,$00,$00,$00,
+
+ 7, // $4C 'L'
+ $00,$00,$00,$00,$40,$40,$40,$40,$40,$40,$40,$40,$7E,$00,$00,$00,
+
+ 11, // $4D 'M'
+ $00,$00,$00,$00,$00,$00,$00,$00,$60,$C0,$60,$C0,$51,$40,$51,$40,$4A,$40,$4A,$40,$44,$40,$44,$40,$40,$40,$00,$00,$00,$00,$00,$00,
+
+ 9, // $4E 'N'
+ $00,$00,$00,$00,$00,$00,$00,$00,$61,$00,$61,$00,$51,$00,$51,$00,$49,$00,$45,$00,$45,$00,$43,$00,$43,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $4F 'O'
+ $00,$00,$00,$00,$00,$00,$00,$00,$1E,$00,$21,$00,$40,$80,$40,$80,$40,$80,$40,$80,$40,$80,$21,$00,$1E,$00,$00,$00,$00,$00,$00,$00,
+
+ 8, // $50 'P'
+ $00,$00,$00,$00,$7C,$42,$42,$42,$42,$7C,$40,$40,$40,$00,$00,$00,
+
+ 10, // $51 'Q'
+ $00,$00,$00,$00,$00,$00,$00,$00,$1E,$00,$21,$00,$40,$80,$40,$80,$40,$80,$40,$80,$40,$80,$21,$00,$1E,$00,$02,$00,$01,$80,$00,$00,
+
+ 9, // $52 'R'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7C,$00,$42,$00,$42,$00,$42,$00,$44,$00,$78,$00,$44,$00,$42,$00,$41,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $53 'S'
+ $00,$00,$00,$00,$00,$00,$00,$00,$3E,$00,$41,$00,$40,$00,$40,$00,$3E,$00,$01,$00,$01,$00,$41,$00,$3E,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $54 'T'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7F,$00,$08,$00,$08,$00,$08,$00,$08,$00,$08,$00,$08,$00,$08,$00,$08,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $55 'U'
+ $00,$00,$00,$00,$00,$00,$00,$00,$41,$00,$41,$00,$41,$00,$41,$00,$41,$00,$41,$00,$41,$00,$22,$00,$1C,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $56 'V'
+ $00,$00,$00,$00,$00,$00,$00,$00,$41,$00,$41,$00,$41,$00,$22,$00,$22,$00,$14,$00,$14,$00,$08,$00,$08,$00,$00,$00,$00,$00,$00,$00,
+
+ 13, // $57 'W'
+ $00,$00,$00,$00,$00,$00,$00,$00,$42,$10,$42,$10,$45,$10,$45,$10,$25,$20,$28,$A0,$28,$A0,$10,$40,$10,$40,$00,$00,$00,$00,$00,$00,
+
+ 9, // $58 'X'
+ $00,$00,$00,$00,$00,$00,$00,$00,$41,$00,$41,$00,$22,$00,$14,$00,$08,$00,$14,$00,$22,$00,$41,$00,$41,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $59 'Y'
+ $00,$00,$00,$00,$00,$00,$00,$00,$41,$00,$22,$00,$22,$00,$14,$00,$14,$00,$08,$00,$08,$00,$08,$00,$08,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $5A 'Z'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7F,$00,$01,$00,$02,$00,$04,$00,$08,$00,$10,$00,$20,$00,$40,$00,$7F,$00,$00,$00,$00,$00,$00,$00,
+
+ 6, // $5B '['
+ $00,$00,$00,$38,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$38,$00,
+
+ 6, // $5C '\'
+ $00,$00,$00,$80,$80,$40,$40,$20,$20,$10,$10,$08,$08,$04,$04,$00,
+
+ 6, // $5D ']'
+ $00,$00,$00,$70,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$70,$00,
+
+ 11, // $5E '^'
+ $00,$00,$00,$00,$00,$00,$00,$00,$04,$00,$0A,$00,$11,$00,$20,$80,$40,$40,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 8, // $5F '_'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$00,
+
+ 8, // $60 '`'
+ $00,$00,$00,$10,$08,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 8, // $61 'a'
+ $00,$00,$00,$00,$00,$00,$3C,$02,$02,$3E,$42,$42,$3E,$00,$00,$00,
+
+ 8, // $62 'b'
+ $00,$00,$00,$40,$40,$40,$5C,$62,$42,$42,$42,$42,$7C,$00,$00,$00,
+
+ 8, // $63 'c'
+ $00,$00,$00,$00,$00,$00,$3C,$42,$40,$40,$40,$42,$3C,$00,$00,$00,
+
+ 8, // $64 'd'
+ $00,$00,$00,$02,$02,$02,$3E,$42,$42,$42,$42,$46,$3A,$00,$00,$00,
+
+ 8, // $65 'e'
+ $00,$00,$00,$00,$00,$00,$3C,$42,$42,$7E,$40,$42,$3C,$00,$00,$00,
+
+ 6, // $66 'f'
+ $00,$00,$00,$1C,$20,$20,$78,$20,$20,$20,$20,$20,$20,$00,$00,$00,
+
+ 8, // $67 'g'
+ $00,$00,$00,$00,$00,$00,$3E,$42,$42,$42,$42,$46,$3A,$02,$02,$3C,
+
+ 8, // $68 'h'
+ $00,$00,$00,$40,$40,$40,$5C,$62,$42,$42,$42,$42,$42,$00,$00,$00,
+
+ 3, // $69 'i'
+ $00,$00,$00,$40,$00,$00,$40,$40,$40,$40,$40,$40,$40,$00,$00,$00,
+
+ 4, // $6A 'j'
+ $00,$00,$00,$20,$00,$00,$60,$20,$20,$20,$20,$20,$20,$20,$20,$C0,
+
+ 7, // $6B 'k'
+ $00,$00,$00,$40,$40,$40,$44,$48,$50,$60,$50,$48,$44,$00,$00,$00,
+
+ 3, // $6C 'l'
+ $00,$00,$00,$40,$40,$40,$40,$40,$40,$40,$40,$40,$40,$00,$00,$00,
+
+ 11, // $6D 'm'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$59,$80,$66,$40,$44,$40,$44,$40,$44,$40,$44,$40,$44,$40,$00,$00,$00,$00,$00,$00,
+
+ 8, // $6E 'n'
+ $00,$00,$00,$00,$00,$00,$5C,$62,$42,$42,$42,$42,$42,$00,$00,$00,
+
+ 8, // $6F 'o'
+ $00,$00,$00,$00,$00,$00,$3C,$42,$42,$42,$42,$42,$3C,$00,$00,$00,
+
+ 8, // $70 'p'
+ $00,$00,$00,$00,$00,$00,$5C,$62,$42,$42,$42,$42,$7C,$40,$40,$40,
+
+ 8, // $71 'q'
+ $00,$00,$00,$00,$00,$00,$3E,$42,$42,$42,$42,$46,$3A,$02,$02,$02,
+
+ 5, // $72 'r'
+ $00,$00,$00,$00,$00,$00,$58,$60,$40,$40,$40,$40,$40,$00,$00,$00,
+
+ 7, // $73 's'
+ $00,$00,$00,$00,$00,$00,$3C,$40,$40,$38,$04,$04,$78,$00,$00,$00,
+
+ 6, // $74 't'
+ $00,$00,$00,$00,$20,$20,$78,$20,$20,$20,$20,$20,$18,$00,$00,$00,
+
+ 8, // $75 'u'
+ $00,$00,$00,$00,$00,$00,$42,$42,$42,$42,$42,$46,$3A,$00,$00,$00,
+
+ 8, // $76 'v'
+ $00,$00,$00,$00,$00,$00,$42,$42,$24,$24,$24,$18,$18,$00,$00,$00,
+
+ 11, // $77 'w'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$44,$40,$44,$40,$2A,$80,$2A,$80,$2A,$80,$11,$00,$11,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $78 'x'
+ $00,$00,$00,$00,$00,$00,$44,$44,$28,$10,$28,$44,$44,$00,$00,$00,
+
+ 8, // $79 'y'
+ $00,$00,$00,$00,$00,$00,$42,$42,$24,$24,$24,$18,$18,$10,$10,$20,
+
+ 7, // $7A 'z'
+ $00,$00,$00,$00,$00,$00,$7C,$04,$08,$10,$20,$40,$7C,$00,$00,$00,
+
+ 8, // $7B '{'
+ $00,$00,$00,$0C,$10,$10,$10,$10,$60,$10,$10,$10,$10,$10,$0C,$00,
+
+ 7, // $7C '|'
+ $00,$00,$00,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$00,
+
+ 8, // $7D '}'
+ $00,$00,$00,$30,$08,$08,$08,$08,$06,$08,$08,$08,$08,$08,$30,$00,
+
+ 11, // $7E '~'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$30,$80,$4C,$80,$43,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 13, // $7F ''
+ $00,$00,$00,$00,$00,$00,$3F,$F0,$20,$10,$20,$10,$20,$10,$20,$10,$20,$10,$20,$10,$20,$10,$20,$10,$3F,$F0,$00,$00,$00,$00,$00,$00,
+
+ 0 );
+
+ verdana16_bold : array[0..2916 ] of int8u = (
+ 16, 4, 32, 128-32,
+ $00,$00,$11,$00,$22,$00,$33,$00,$54,$00,$75,$00,$A6,$00,$C7,$00,$D8,$00,
+ $E9,$00,$FA,$00,$1B,$01,$3C,$01,$4D,$01,$5E,$01,$6F,$01,$90,$01,$B1,$01,
+ $D2,$01,$F3,$01,$14,$02,$35,$02,$56,$02,$77,$02,$98,$02,$B9,$02,$DA,$02,
+ $EB,$02,$FC,$02,$1D,$03,$3E,$03,$5F,$03,$70,$03,$91,$03,$B2,$03,$D3,$03,
+ $F4,$03,$15,$04,$36,$04,$57,$04,$78,$04,$99,$04,$AA,$04,$BB,$04,$DC,$04,
+ $ED,$04,$0E,$05,$2F,$05,$50,$05,$71,$05,$92,$05,$B3,$05,$D4,$05,$E5,$05,
+ $06,$06,$27,$06,$48,$06,$69,$06,$8A,$06,$AB,$06,$BC,$06,$DD,$06,$EE,$06,
+ $0F,$07,$30,$07,$51,$07,$72,$07,$93,$07,$A4,$07,$C5,$07,$E6,$07,$F7,$07,
+ $18,$08,$39,$08,$4A,$08,$5B,$08,$6C,$08,$7D,$08,$9E,$08,$BF,$08,$E0,$08,
+ $01,$09,$22,$09,$33,$09,$44,$09,$55,$09,$76,$09,$97,$09,$B8,$09,$D9,$09,
+ $FA,$09,$0B,$0A,$2C,$0A,$3D,$0A,$5E,$0A,$7F,$0A,
+
+ 4, // $20 ' '
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 6, // $21 '!'
+ $00,$00,$00,$00,$30,$30,$30,$30,$30,$30,$00,$30,$30,$00,$00,$00,
+
+ 7, // $22 '"'
+ $00,$00,$00,$6C,$6C,$6C,$6C,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 11, // $23 '#'
+ $00,$00,$00,$00,$00,$00,$00,$00,$09,$00,$09,$00,$3F,$80,$3F,$80,$12,$00,$7F,$00,$7F,$00,$24,$00,$24,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $24 '$'
+ $00,$00,$00,$00,$08,$00,$08,$00,$3E,$00,$69,$00,$68,$00,$78,$00,$3E,$00,$0F,$00,$0B,$00,$4B,$00,$3E,$00,$08,$00,$08,$00,$00,$00,
+
+ 17, // $25 '%'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3C,$20,$00,$66,$20,$00,$66,$40,$00,$66,$5E,$00,$66,$B3,$00,$3D,$33,$00,$01,$33,$00,$02,$33,$00,$02,$1E,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 11, // $26 '&'
+ $00,$00,$00,$00,$00,$00,$00,$00,$3C,$00,$66,$00,$66,$00,$66,$C0,$3C,$C0,$66,$80,$63,$00,$63,$80,$3C,$C0,$00,$00,$00,$00,$00,$00,
+
+ 4, // $27 '''
+ $00,$00,$00,$60,$60,$60,$60,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $28 '('
+ $00,$00,$00,$0C,$18,$30,$30,$60,$60,$60,$60,$60,$30,$30,$18,$0C,
+
+ 7, // $29 ')'
+ $00,$00,$00,$60,$30,$18,$18,$0C,$0C,$0C,$0C,$0C,$18,$18,$30,$60,
+
+ 9, // $2A '*'
+ $00,$00,$00,$00,$00,$00,$08,$00,$49,$00,$2A,$00,$1C,$00,$2A,$00,$49,$00,$08,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 11, // $2B '+'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$04,$00,$04,$00,$04,$00,$3F,$80,$04,$00,$04,$00,$04,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 5, // $2C ','
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$70,$60,$60,$C0,$C0,
+
+ 7, // $2D '-'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7C,$00,$00,$00,$00,$00,$00,$00,
+
+ 5, // $2E '.'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$30,$30,$00,$00,$00,
+
+ 9, // $2F '/'
+ $00,$00,$00,$00,$00,$00,$03,$00,$03,$00,$06,$00,$06,$00,$0C,$00,$0C,$00,$18,$00,$18,$00,$30,$00,$30,$00,$60,$00,$60,$00,$00,$00,
+
+ 9, // $30 '0'
+ $00,$00,$00,$00,$00,$00,$00,$00,$3E,$00,$63,$00,$63,$00,$63,$00,$63,$00,$63,$00,$63,$00,$63,$00,$3E,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $31 '1'
+ $00,$00,$00,$00,$00,$00,$00,$00,$0C,$00,$3C,$00,$0C,$00,$0C,$00,$0C,$00,$0C,$00,$0C,$00,$0C,$00,$3F,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $32 '2'
+ $00,$00,$00,$00,$00,$00,$00,$00,$3E,$00,$63,$00,$63,$00,$03,$00,$06,$00,$0C,$00,$18,$00,$30,$00,$7F,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $33 '3'
+ $00,$00,$00,$00,$00,$00,$00,$00,$3E,$00,$63,$00,$63,$00,$03,$00,$0E,$00,$03,$00,$63,$00,$63,$00,$3E,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $34 '4'
+ $00,$00,$00,$00,$00,$00,$00,$00,$06,$00,$0E,$00,$16,$00,$26,$00,$46,$00,$7F,$80,$06,$00,$06,$00,$06,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $35 '5'
+ $00,$00,$00,$00,$00,$00,$00,$00,$3F,$00,$30,$00,$30,$00,$3E,$00,$03,$00,$03,$00,$63,$00,$63,$00,$3E,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $36 '6'
+ $00,$00,$00,$00,$00,$00,$00,$00,$1E,$00,$30,$00,$60,$00,$7E,$00,$63,$00,$63,$00,$63,$00,$63,$00,$3E,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $37 '7'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7F,$00,$03,$00,$03,$00,$06,$00,$06,$00,$0C,$00,$0C,$00,$18,$00,$18,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $38 '8'
+ $00,$00,$00,$00,$00,$00,$00,$00,$3E,$00,$63,$00,$63,$00,$63,$00,$3E,$00,$63,$00,$63,$00,$63,$00,$3E,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $39 '9'
+ $00,$00,$00,$00,$00,$00,$00,$00,$3E,$00,$63,$00,$63,$00,$63,$00,$63,$00,$3F,$00,$03,$00,$06,$00,$3C,$00,$00,$00,$00,$00,$00,$00,
+
+ 5, // $3A ':'
+ $00,$00,$00,$00,$00,$00,$30,$30,$00,$00,$00,$30,$30,$00,$00,$00,
+
+ 5, // $3B ';'
+ $00,$00,$00,$00,$00,$00,$30,$30,$00,$00,$00,$38,$30,$30,$60,$60,
+
+ 11, // $3C '<'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$80,$03,$00,$0C,$00,$30,$00,$40,$00,$30,$00,$0C,$00,$03,$00,$00,$80,$00,$00,$00,$00,$00,$00,
+
+ 11, // $3D '='
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3F,$80,$00,$00,$00,$00,$3F,$80,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 11, // $3E '>'
+ $00,$00,$00,$00,$00,$00,$00,$00,$20,$00,$18,$00,$06,$00,$01,$80,$00,$40,$01,$80,$06,$00,$18,$00,$20,$00,$00,$00,$00,$00,$00,$00,
+
+ 8, // $3F '?'
+ $00,$00,$00,$00,$3C,$66,$06,$0C,$18,$18,$00,$18,$18,$00,$00,$00,
+
+ 13, // $40 '@'
+ $00,$00,$00,$00,$00,$00,$00,$00,$0F,$80,$30,$60,$27,$A0,$4D,$90,$4D,$90,$4D,$90,$4D,$90,$27,$E0,$30,$00,$0F,$80,$00,$00,$00,$00,
+
+ 10, // $41 'A'
+ $00,$00,$00,$00,$00,$00,$00,$00,$0C,$00,$0C,$00,$1E,$00,$1E,$00,$33,$00,$33,$00,$7F,$80,$61,$80,$61,$80,$00,$00,$00,$00,$00,$00,
+
+ 10, // $42 'B'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7E,$00,$63,$00,$63,$00,$63,$00,$7F,$00,$61,$80,$61,$80,$61,$80,$7F,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $43 'C'
+ $00,$00,$00,$00,$00,$00,$00,$00,$1F,$00,$31,$80,$61,$80,$60,$00,$60,$00,$60,$00,$61,$80,$31,$80,$1F,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $44 'D'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7E,$00,$63,$00,$61,$80,$61,$80,$61,$80,$61,$80,$61,$80,$63,$00,$7E,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $45 'E'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7F,$00,$60,$00,$60,$00,$60,$00,$7F,$00,$60,$00,$60,$00,$60,$00,$7F,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $46 'F'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7F,$00,$60,$00,$60,$00,$60,$00,$7F,$00,$60,$00,$60,$00,$60,$00,$60,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $47 'G'
+ $00,$00,$00,$00,$00,$00,$00,$00,$1F,$00,$31,$80,$61,$80,$60,$00,$60,$00,$63,$80,$61,$80,$31,$80,$1F,$80,$00,$00,$00,$00,$00,$00,
+
+ 11, // $48 'H'
+ $00,$00,$00,$00,$00,$00,$00,$00,$60,$C0,$60,$C0,$60,$C0,$60,$C0,$7F,$C0,$60,$C0,$60,$C0,$60,$C0,$60,$C0,$00,$00,$00,$00,$00,$00,
+
+ 6, // $49 'I'
+ $00,$00,$00,$00,$78,$30,$30,$30,$30,$30,$30,$30,$78,$00,$00,$00,
+
+ 7, // $4A 'J'
+ $00,$00,$00,$00,$7C,$0C,$0C,$0C,$0C,$0C,$0C,$0C,$F8,$00,$00,$00,
+
+ 9, // $4B 'K'
+ $00,$00,$00,$00,$00,$00,$00,$00,$63,$00,$66,$00,$6C,$00,$78,$00,$78,$00,$6C,$00,$66,$00,$63,$00,$61,$80,$00,$00,$00,$00,$00,$00,
+
+ 8, // $4C 'L'
+ $00,$00,$00,$00,$60,$60,$60,$60,$60,$60,$60,$60,$7F,$00,$00,$00,
+
+ 12, // $4D 'M'
+ $00,$00,$00,$00,$00,$00,$00,$00,$70,$E0,$70,$E0,$59,$60,$59,$60,$4E,$60,$4E,$60,$44,$60,$44,$60,$40,$60,$00,$00,$00,$00,$00,$00,
+
+ 10, // $4E 'N'
+ $00,$00,$00,$00,$00,$00,$00,$00,$70,$80,$70,$80,$58,$80,$58,$80,$4C,$80,$46,$80,$46,$80,$43,$80,$43,$80,$00,$00,$00,$00,$00,$00,
+
+ 11, // $4F 'O'
+ $00,$00,$00,$00,$00,$00,$00,$00,$1F,$00,$31,$80,$60,$C0,$60,$C0,$60,$C0,$60,$C0,$60,$C0,$31,$80,$1F,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $50 'P'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7E,$00,$63,$00,$63,$00,$63,$00,$63,$00,$7E,$00,$60,$00,$60,$00,$60,$00,$00,$00,$00,$00,$00,$00,
+
+ 11, // $51 'Q'
+ $00,$00,$00,$00,$00,$00,$00,$00,$1F,$00,$31,$80,$60,$C0,$60,$C0,$60,$C0,$60,$C0,$60,$C0,$31,$80,$1F,$00,$03,$00,$01,$C0,$00,$00,
+
+ 9, // $52 'R'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7E,$00,$63,$00,$63,$00,$63,$00,$7E,$00,$6C,$00,$66,$00,$63,$00,$61,$80,$00,$00,$00,$00,$00,$00,
+
+ 9, // $53 'S'
+ $00,$00,$00,$00,$00,$00,$00,$00,$3E,$00,$63,$00,$63,$00,$70,$00,$3E,$00,$07,$00,$63,$00,$63,$00,$3E,$00,$00,$00,$00,$00,$00,$00,
+
+ 8, // $54 'T'
+ $00,$00,$00,$00,$FF,$18,$18,$18,$18,$18,$18,$18,$18,$00,$00,$00,
+
+ 10, // $55 'U'
+ $00,$00,$00,$00,$00,$00,$00,$00,$61,$80,$61,$80,$61,$80,$61,$80,$61,$80,$61,$80,$61,$80,$61,$80,$3F,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $56 'V'
+ $00,$00,$00,$00,$00,$00,$00,$00,$61,$80,$61,$80,$61,$80,$33,$00,$33,$00,$1E,$00,$1E,$00,$0C,$00,$0C,$00,$00,$00,$00,$00,$00,$00,
+
+ 14, // $57 'W'
+ $00,$00,$00,$00,$00,$00,$00,$00,$63,$18,$63,$18,$63,$18,$33,$30,$37,$B0,$34,$B0,$1C,$E0,$18,$60,$18,$60,$00,$00,$00,$00,$00,$00,
+
+ 10, // $58 'X'
+ $00,$00,$00,$00,$00,$00,$00,$00,$61,$80,$33,$00,$33,$00,$1E,$00,$0C,$00,$1E,$00,$33,$00,$33,$00,$61,$80,$00,$00,$00,$00,$00,$00,
+
+ 10, // $59 'Y'
+ $00,$00,$00,$00,$00,$00,$00,$00,$61,$80,$61,$80,$33,$00,$1E,$00,$0C,$00,$0C,$00,$0C,$00,$0C,$00,$0C,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $5A 'Z'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7F,$00,$06,$00,$0C,$00,$0C,$00,$18,$00,$18,$00,$30,$00,$30,$00,$7F,$00,$00,$00,$00,$00,$00,$00,
+
+ 6, // $5B '['
+ $00,$00,$00,$78,$60,$60,$60,$60,$60,$60,$60,$60,$60,$60,$78,$00,
+
+ 9, // $5C '\'
+ $00,$00,$00,$00,$00,$00,$60,$00,$60,$00,$30,$00,$30,$00,$18,$00,$18,$00,$0C,$00,$0C,$00,$06,$00,$06,$00,$03,$00,$03,$00,$00,$00,
+
+ 6, // $5D ']'
+ $00,$00,$00,$78,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$78,$00,
+
+ 10, // $5E '^'
+ $00,$00,$00,$00,$00,$00,$00,$00,$0C,$00,$1E,$00,$33,$00,$61,$80,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $5F '_'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$80,$00,$00,
+
+ 9, // $60 '`'
+ $00,$00,$00,$00,$00,$00,$30,$00,$18,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $61 'a'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3E,$00,$03,$00,$3F,$00,$63,$00,$63,$00,$63,$00,$3F,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $62 'b'
+ $00,$00,$00,$00,$00,$00,$60,$00,$60,$00,$60,$00,$6E,$00,$73,$00,$63,$00,$63,$00,$63,$00,$63,$00,$7E,$00,$00,$00,$00,$00,$00,$00,
+
+ 8, // $63 'c'
+ $00,$00,$00,$00,$00,$00,$3E,$63,$60,$60,$60,$63,$3E,$00,$00,$00,
+
+ 9, // $64 'd'
+ $00,$00,$00,$00,$00,$00,$03,$00,$03,$00,$03,$00,$3F,$00,$63,$00,$63,$00,$63,$00,$63,$00,$67,$00,$3B,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $65 'e'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3E,$00,$63,$00,$63,$00,$7F,$00,$60,$00,$63,$00,$3E,$00,$00,$00,$00,$00,$00,$00,
+
+ 5, // $66 'f'
+ $00,$00,$00,$38,$60,$60,$F8,$60,$60,$60,$60,$60,$60,$00,$00,$00,
+
+ 9, // $67 'g'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3F,$00,$63,$00,$63,$00,$63,$00,$63,$00,$67,$00,$3B,$00,$03,$00,$03,$00,$3E,$00,
+
+ 9, // $68 'h'
+ $00,$00,$00,$00,$00,$00,$60,$00,$60,$00,$60,$00,$6E,$00,$73,$00,$63,$00,$63,$00,$63,$00,$63,$00,$63,$00,$00,$00,$00,$00,$00,$00,
+
+ 4, // $69 'i'
+ $00,$00,$00,$60,$60,$00,$60,$60,$60,$60,$60,$60,$60,$00,$00,$00,
+
+ 5, // $6A 'j'
+ $00,$00,$00,$30,$30,$00,$70,$30,$30,$30,$30,$30,$30,$30,$30,$E0,
+
+ 8, // $6B 'k'
+ $00,$00,$00,$60,$60,$60,$66,$6C,$78,$78,$6C,$66,$63,$00,$00,$00,
+
+ 4, // $6C 'l'
+ $00,$00,$00,$60,$60,$60,$60,$60,$60,$60,$60,$60,$60,$00,$00,$00,
+
+ 14, // $6D 'm'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$6E,$70,$73,$98,$63,$18,$63,$18,$63,$18,$63,$18,$63,$18,$00,$00,$00,$00,$00,$00,
+
+ 9, // $6E 'n'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$6E,$00,$73,$00,$63,$00,$63,$00,$63,$00,$63,$00,$63,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $6F 'o'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3E,$00,$63,$00,$63,$00,$63,$00,$63,$00,$63,$00,$3E,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $70 'p'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$6E,$00,$73,$00,$63,$00,$63,$00,$63,$00,$63,$00,$7E,$00,$60,$00,$60,$00,$60,$00,
+
+ 9, // $71 'q'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3F,$00,$63,$00,$63,$00,$63,$00,$63,$00,$67,$00,$3B,$00,$03,$00,$03,$00,$03,$00,
+
+ 6, // $72 'r'
+ $00,$00,$00,$00,$00,$00,$6C,$7C,$60,$60,$60,$60,$60,$00,$00,$00,
+
+ 8, // $73 's'
+ $00,$00,$00,$00,$00,$00,$3E,$60,$70,$3C,$0E,$06,$7C,$00,$00,$00,
+
+ 6, // $74 't'
+ $00,$00,$00,$00,$60,$60,$F8,$60,$60,$60,$60,$60,$38,$00,$00,$00,
+
+ 9, // $75 'u'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$63,$00,$63,$00,$63,$00,$63,$00,$63,$00,$67,$00,$3B,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $76 'v'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$63,$00,$63,$00,$63,$00,$36,$00,$36,$00,$1C,$00,$1C,$00,$00,$00,$00,$00,$00,$00,
+
+ 12, // $77 'w'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$60,$66,$60,$66,$60,$69,$60,$39,$C0,$30,$C0,$30,$C0,$00,$00,$00,$00,$00,$00,
+
+ 9, // $78 'x'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$63,$00,$63,$00,$36,$00,$1C,$00,$36,$00,$63,$00,$63,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $79 'y'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$63,$00,$63,$00,$63,$00,$36,$00,$36,$00,$1C,$00,$1C,$00,$0C,$00,$18,$00,$18,$00,
+
+ 8, // $7A 'z'
+ $00,$00,$00,$00,$00,$00,$7E,$06,$0C,$18,$30,$60,$7E,$00,$00,$00,
+
+ 9, // $7B '{'
+ $00,$00,$00,$00,$00,$00,$07,$00,$0C,$00,$0C,$00,$0C,$00,$18,$00,$70,$00,$18,$00,$0C,$00,$0C,$00,$0C,$00,$0C,$00,$07,$00,$00,$00,
+
+ 8, // $7C '|'
+ $00,$00,$00,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$00,
+
+ 9, // $7D '}'
+ $00,$00,$00,$00,$00,$00,$70,$00,$18,$00,$18,$00,$18,$00,$0C,$00,$07,$00,$0C,$00,$18,$00,$18,$00,$18,$00,$18,$00,$70,$00,$00,$00,
+
+ 11, // $7E '~'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$38,$40,$44,$40,$44,$40,$43,$80,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 13, // $7F ''
+ $00,$00,$00,$00,$00,$00,$3F,$F0,$20,$10,$20,$10,$20,$10,$20,$10,$20,$10,$20,$10,$20,$10,$20,$10,$3F,$F0,$00,$00,$00,$00,$00,$00,
+
+ 0 );
+
+ verdana17 : array[0..2944 ] of int8u = (
+ 17, 4, 32, 128-32,
+ $00,$00,$12,$00,$24,$00,$36,$00,$59,$00,$7C,$00,$9F,$00,$C2,$00,$D4,$00,
+ $E6,$00,$F8,$00,$1B,$01,$3E,$01,$50,$01,$62,$01,$74,$01,$86,$01,$A9,$01,
+ $CC,$01,$EF,$01,$12,$02,$35,$02,$58,$02,$7B,$02,$9E,$02,$C1,$02,$E4,$02,
+ $F6,$02,$08,$03,$2B,$03,$4E,$03,$71,$03,$83,$03,$A6,$03,$C9,$03,$EC,$03,
+ $0F,$04,$32,$04,$55,$04,$67,$04,$8A,$04,$AD,$04,$BF,$04,$D1,$04,$F4,$04,
+ $06,$05,$29,$05,$4C,$05,$6F,$05,$81,$05,$A4,$05,$C7,$05,$EA,$05,$0D,$06,
+ $30,$06,$53,$06,$76,$06,$99,$06,$BC,$06,$DF,$06,$F1,$06,$03,$07,$15,$07,
+ $38,$07,$5B,$07,$7E,$07,$90,$07,$B3,$07,$C5,$07,$E8,$07,$FA,$07,$0C,$08,
+ $2F,$08,$52,$08,$64,$08,$76,$08,$88,$08,$9A,$08,$BD,$08,$E0,$08,$03,$09,
+ $26,$09,$49,$09,$5B,$09,$6D,$09,$7F,$09,$A2,$09,$B4,$09,$D7,$09,$FA,$09,
+ $0C,$0A,$1E,$0A,$41,$0A,$53,$0A,$76,$0A,$99,$0A,
+
+ 5, // $20 ' '
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 6, // $21 '!'
+ $00,$00,$00,$00,$20,$20,$20,$20,$20,$20,$20,$00,$20,$20,$00,$00,$00,
+
+ 6, // $22 '"'
+ $00,$00,$00,$48,$48,$48,$48,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 11, // $23 '#'
+ $00,$00,$00,$00,$00,$00,$00,$00,$04,$80,$04,$80,$09,$00,$3F,$C0,$09,$00,$12,$00,$7F,$80,$12,$00,$24,$00,$24,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $24 '$'
+ $00,$00,$00,$00,$00,$00,$08,$00,$08,$00,$3E,$00,$49,$00,$48,$00,$48,$00,$3E,$00,$09,$00,$09,$00,$49,$00,$3E,$00,$08,$00,$08,$00,$00,$00,
+
+ 15, // $25 '%'
+ $00,$00,$00,$00,$00,$00,$00,$00,$38,$20,$44,$40,$44,$80,$44,$80,$45,$38,$39,$44,$02,$44,$04,$44,$04,$44,$08,$38,$00,$00,$00,$00,$00,$00,
+
+ 11, // $26 '&'
+ $00,$00,$00,$00,$00,$00,$00,$00,$3C,$00,$42,$00,$42,$00,$44,$00,$38,$80,$44,$80,$42,$80,$41,$00,$22,$80,$1C,$40,$00,$00,$00,$00,$00,$00,
+
+ 4, // $27 '''
+ $00,$00,$00,$40,$40,$40,$40,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 6, // $28 '('
+ $00,$00,$00,$08,$10,$20,$20,$40,$40,$40,$40,$40,$40,$20,$20,$10,$08,
+
+ 6, // $29 ')'
+ $00,$00,$00,$40,$20,$10,$10,$08,$08,$08,$08,$08,$08,$10,$10,$20,$40,
+
+ 9, // $2A '*'
+ $00,$00,$00,$00,$00,$00,$08,$00,$49,$00,$2A,$00,$1C,$00,$2A,$00,$49,$00,$08,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 11, // $2B '+'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$04,$00,$04,$00,$04,$00,$04,$00,$7F,$C0,$04,$00,$04,$00,$04,$00,$04,$00,$00,$00,$00,$00,$00,$00,
+
+ 5, // $2C ','
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$20,$20,$20,$40,$00,
+
+ 7, // $2D '-'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$7C,$00,$00,$00,$00,$00,$00,$00,
+
+ 5, // $2E '.'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$20,$20,$00,$00,$00,
+
+ 6, // $2F '/'
+ $00,$00,$00,$04,$08,$08,$08,$10,$10,$20,$20,$20,$40,$40,$80,$80,$00,
+
+ 9, // $30 '0'
+ $00,$00,$00,$00,$00,$00,$00,$00,$1C,$00,$22,$00,$41,$00,$41,$00,$41,$00,$41,$00,$41,$00,$41,$00,$22,$00,$1C,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $31 '1'
+ $00,$00,$00,$00,$00,$00,$00,$00,$08,$00,$38,$00,$08,$00,$08,$00,$08,$00,$08,$00,$08,$00,$08,$00,$08,$00,$3E,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $32 '2'
+ $00,$00,$00,$00,$00,$00,$00,$00,$3E,$00,$41,$00,$01,$00,$01,$00,$02,$00,$0C,$00,$10,$00,$20,$00,$40,$00,$7F,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $33 '3'
+ $00,$00,$00,$00,$00,$00,$00,$00,$3E,$00,$41,$00,$01,$00,$02,$00,$1C,$00,$02,$00,$01,$00,$01,$00,$42,$00,$3C,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $34 '4'
+ $00,$00,$00,$00,$00,$00,$00,$00,$02,$00,$06,$00,$0A,$00,$12,$00,$22,$00,$42,$00,$7F,$80,$02,$00,$02,$00,$02,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $35 '5'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7F,$00,$40,$00,$40,$00,$40,$00,$7C,$00,$02,$00,$01,$00,$01,$00,$42,$00,$3C,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $36 '6'
+ $00,$00,$00,$00,$00,$00,$00,$00,$0E,$00,$30,$00,$20,$00,$40,$00,$7C,$00,$42,$00,$41,$00,$41,$00,$22,$00,$1C,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $37 '7'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7F,$00,$01,$00,$02,$00,$02,$00,$04,$00,$04,$00,$08,$00,$10,$00,$10,$00,$20,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $38 '8'
+ $00,$00,$00,$00,$00,$00,$00,$00,$3E,$00,$41,$00,$41,$00,$41,$00,$3E,$00,$41,$00,$41,$00,$41,$00,$41,$00,$3E,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $39 '9'
+ $00,$00,$00,$00,$00,$00,$00,$00,$1C,$00,$22,$00,$41,$00,$41,$00,$21,$00,$1F,$00,$01,$00,$02,$00,$06,$00,$38,$00,$00,$00,$00,$00,$00,$00,
+
+ 6, // $3A ':'
+ $00,$00,$00,$00,$00,$00,$20,$20,$00,$00,$00,$00,$20,$20,$00,$00,$00,
+
+ 6, // $3B ';'
+ $00,$00,$00,$00,$00,$00,$20,$20,$00,$00,$00,$00,$20,$20,$20,$40,$00,
+
+ 11, // $3C '<'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$01,$80,$06,$00,$18,$00,$60,$00,$60,$00,$18,$00,$06,$00,$01,$80,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 11, // $3D '='
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3F,$C0,$00,$00,$00,$00,$3F,$C0,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 11, // $3E '>'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$30,$00,$0C,$00,$03,$00,$00,$C0,$00,$C0,$03,$00,$0C,$00,$30,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 8, // $3F '?'
+ $00,$00,$00,$00,$3C,$42,$02,$02,$0C,$10,$10,$00,$10,$10,$00,$00,$00,
+
+ 14, // $40 '@'
+ $00,$00,$00,$00,$00,$00,$00,$00,$07,$C0,$18,$20,$20,$10,$27,$C8,$48,$48,$48,$48,$48,$48,$48,$48,$27,$F0,$20,$00,$18,$00,$07,$C0,$00,$00,
+
+ 10, // $41 'A'
+ $00,$00,$00,$00,$00,$00,$00,$00,$0C,$00,$12,$00,$12,$00,$21,$00,$21,$00,$21,$00,$7F,$80,$40,$80,$80,$40,$80,$40,$00,$00,$00,$00,$00,$00,
+
+ 10, // $42 'B'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7E,$00,$41,$00,$41,$00,$41,$00,$7E,$00,$41,$00,$40,$80,$40,$80,$41,$00,$7E,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $43 'C'
+ $00,$00,$00,$00,$00,$00,$00,$00,$0F,$00,$30,$80,$20,$00,$40,$00,$40,$00,$40,$00,$40,$00,$20,$00,$30,$80,$0F,$00,$00,$00,$00,$00,$00,$00,
+
+ 11, // $44 'D'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7E,$00,$41,$80,$40,$80,$40,$40,$40,$40,$40,$40,$40,$40,$40,$80,$41,$80,$7E,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $45 'E'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7F,$00,$40,$00,$40,$00,$40,$00,$7F,$00,$40,$00,$40,$00,$40,$00,$40,$00,$7F,$00,$00,$00,$00,$00,$00,$00,
+
+ 8, // $46 'F'
+ $00,$00,$00,$00,$7F,$40,$40,$40,$7E,$40,$40,$40,$40,$40,$00,$00,$00,
+
+ 11, // $47 'G'
+ $00,$00,$00,$00,$00,$00,$00,$00,$0F,$00,$30,$C0,$20,$40,$40,$00,$40,$00,$43,$C0,$40,$40,$20,$40,$30,$40,$0F,$80,$00,$00,$00,$00,$00,$00,
+
+ 10, // $48 'H'
+ $00,$00,$00,$00,$00,$00,$00,$00,$40,$80,$40,$80,$40,$80,$40,$80,$7F,$80,$40,$80,$40,$80,$40,$80,$40,$80,$40,$80,$00,$00,$00,$00,$00,$00,
+
+ 5, // $49 'I'
+ $00,$00,$00,$00,$70,$20,$20,$20,$20,$20,$20,$20,$20,$70,$00,$00,$00,
+
+ 6, // $4A 'J'
+ $00,$00,$00,$00,$38,$08,$08,$08,$08,$08,$08,$08,$08,$F0,$00,$00,$00,
+
+ 10, // $4B 'K'
+ $00,$00,$00,$00,$00,$00,$00,$00,$41,$00,$42,$00,$44,$00,$48,$00,$50,$00,$68,$00,$44,$00,$42,$00,$41,$00,$40,$80,$00,$00,$00,$00,$00,$00,
+
+ 8, // $4C 'L'
+ $00,$00,$00,$00,$40,$40,$40,$40,$40,$40,$40,$40,$40,$7F,$00,$00,$00,
+
+ 11, // $4D 'M'
+ $00,$00,$00,$00,$00,$00,$00,$00,$60,$C0,$60,$C0,$51,$40,$51,$40,$4A,$40,$4A,$40,$44,$40,$44,$40,$40,$40,$40,$40,$00,$00,$00,$00,$00,$00,
+
+ 10, // $4E 'N'
+ $00,$00,$00,$00,$00,$00,$00,$00,$60,$80,$60,$80,$50,$80,$48,$80,$48,$80,$44,$80,$44,$80,$42,$80,$41,$80,$41,$80,$00,$00,$00,$00,$00,$00,
+
+ 11, // $4F 'O'
+ $00,$00,$00,$00,$00,$00,$00,$00,$0E,$00,$31,$80,$20,$80,$40,$40,$40,$40,$40,$40,$40,$40,$20,$80,$31,$80,$0E,$00,$00,$00,$00,$00,$00,$00,
+
+ 8, // $50 'P'
+ $00,$00,$00,$00,$7C,$42,$41,$41,$42,$7C,$40,$40,$40,$40,$00,$00,$00,
+
+ 11, // $51 'Q'
+ $00,$00,$00,$00,$00,$00,$00,$00,$0E,$00,$31,$80,$20,$80,$40,$40,$40,$40,$40,$40,$40,$40,$20,$80,$31,$80,$0E,$00,$02,$00,$02,$00,$01,$C0,
+
+ 10, // $52 'R'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7C,$00,$42,$00,$42,$00,$42,$00,$44,$00,$78,$00,$44,$00,$42,$00,$41,$00,$40,$80,$00,$00,$00,$00,$00,$00,
+
+ 10, // $53 'S'
+ $00,$00,$00,$00,$00,$00,$00,$00,$1F,$00,$20,$80,$40,$00,$40,$00,$38,$00,$07,$00,$00,$80,$40,$80,$21,$00,$1E,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $54 'T'
+ $00,$00,$00,$00,$00,$00,$00,$00,$FF,$80,$08,$00,$08,$00,$08,$00,$08,$00,$08,$00,$08,$00,$08,$00,$08,$00,$08,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $55 'U'
+ $00,$00,$00,$00,$00,$00,$00,$00,$40,$80,$40,$80,$40,$80,$40,$80,$40,$80,$40,$80,$40,$80,$40,$80,$21,$00,$1E,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $56 'V'
+ $00,$00,$00,$00,$00,$00,$00,$00,$80,$40,$80,$40,$40,$80,$40,$80,$21,$00,$21,$00,$21,$00,$12,$00,$12,$00,$0C,$00,$00,$00,$00,$00,$00,$00,
+
+ 15, // $57 'W'
+ $00,$00,$00,$00,$00,$00,$00,$00,$41,$04,$41,$04,$22,$88,$22,$88,$22,$88,$14,$50,$14,$50,$14,$50,$08,$20,$08,$20,$00,$00,$00,$00,$00,$00,
+
+ 10, // $58 'X'
+ $00,$00,$00,$00,$00,$00,$00,$00,$40,$80,$21,$00,$12,$00,$12,$00,$0C,$00,$0C,$00,$12,$00,$12,$00,$21,$00,$40,$80,$00,$00,$00,$00,$00,$00,
+
+ 9, // $59 'Y'
+ $00,$00,$00,$00,$00,$00,$00,$00,$80,$80,$41,$00,$22,$00,$22,$00,$14,$00,$08,$00,$08,$00,$08,$00,$08,$00,$08,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $5A 'Z'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7F,$80,$00,$80,$01,$00,$02,$00,$04,$00,$08,$00,$10,$00,$20,$00,$40,$00,$7F,$80,$00,$00,$00,$00,$00,$00,
+
+ 6, // $5B '['
+ $00,$00,$00,$3C,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$3C,
+
+ 6, // $5C '\'
+ $00,$00,$00,$80,$40,$40,$40,$20,$20,$10,$10,$10,$08,$08,$08,$04,$00,
+
+ 6, // $5D ']'
+ $00,$00,$00,$78,$08,$08,$08,$08,$08,$08,$08,$08,$08,$08,$08,$08,$78,
+
+ 11, // $5E '^'
+ $00,$00,$00,$00,$00,$00,$00,$00,$04,$00,$0A,$00,$11,$00,$20,$80,$40,$40,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $5F '_'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$80,$00,$00,
+
+ 9, // $60 '`'
+ $00,$00,$00,$00,$00,$00,$10,$00,$08,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 8, // $61 'a'
+ $00,$00,$00,$00,$00,$00,$1C,$22,$02,$3E,$42,$42,$46,$3A,$00,$00,$00,
+
+ 9, // $62 'b'
+ $00,$00,$00,$00,$00,$00,$40,$00,$40,$00,$40,$00,$5C,$00,$62,$00,$41,$00,$41,$00,$41,$00,$41,$00,$42,$00,$7C,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $63 'c'
+ $00,$00,$00,$00,$00,$00,$1C,$22,$40,$40,$40,$40,$22,$1C,$00,$00,$00,
+
+ 9, // $64 'd'
+ $00,$00,$00,$00,$00,$00,$01,$00,$01,$00,$01,$00,$1F,$00,$21,$00,$41,$00,$41,$00,$41,$00,$41,$00,$23,$00,$1D,$00,$00,$00,$00,$00,$00,$00,
+
+ 8, // $65 'e'
+ $00,$00,$00,$00,$00,$00,$18,$24,$42,$7E,$40,$40,$22,$1C,$00,$00,$00,
+
+ 6, // $66 'f'
+ $00,$00,$00,$1C,$20,$20,$7C,$20,$20,$20,$20,$20,$20,$20,$00,$00,$00,
+
+ 9, // $67 'g'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$1F,$00,$21,$00,$41,$00,$41,$00,$41,$00,$41,$00,$23,$00,$1D,$00,$01,$00,$22,$00,$1C,$00,
+
+ 9, // $68 'h'
+ $00,$00,$00,$00,$00,$00,$40,$00,$40,$00,$40,$00,$5E,$00,$61,$00,$41,$00,$41,$00,$41,$00,$41,$00,$41,$00,$41,$00,$00,$00,$00,$00,$00,$00,
+
+ 3, // $69 'i'
+ $00,$00,$00,$00,$40,$00,$40,$40,$40,$40,$40,$40,$40,$40,$00,$00,$00,
+
+ 5, // $6A 'j'
+ $00,$00,$00,$00,$10,$00,$70,$10,$10,$10,$10,$10,$10,$10,$10,$10,$E0,
+
+ 8, // $6B 'k'
+ $00,$00,$00,$40,$40,$40,$42,$44,$48,$50,$70,$48,$44,$42,$00,$00,$00,
+
+ 3, // $6C 'l'
+ $00,$00,$00,$40,$40,$40,$40,$40,$40,$40,$40,$40,$40,$40,$00,$00,$00,
+
+ 13, // $6D 'm'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$5C,$E0,$63,$10,$42,$10,$42,$10,$42,$10,$42,$10,$42,$10,$42,$10,$00,$00,$00,$00,$00,$00,
+
+ 9, // $6E 'n'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$5E,$00,$61,$00,$41,$00,$41,$00,$41,$00,$41,$00,$41,$00,$41,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $6F 'o'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$1C,$00,$22,$00,$41,$00,$41,$00,$41,$00,$41,$00,$22,$00,$1C,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $70 'p'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$5C,$00,$62,$00,$41,$00,$41,$00,$41,$00,$41,$00,$42,$00,$7C,$00,$40,$00,$40,$00,$40,$00,
+
+ 9, // $71 'q'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$1F,$00,$21,$00,$41,$00,$41,$00,$41,$00,$41,$00,$23,$00,$1D,$00,$01,$00,$01,$00,$01,$00,
+
+ 6, // $72 'r'
+ $00,$00,$00,$00,$00,$00,$5C,$60,$40,$40,$40,$40,$40,$40,$00,$00,$00,
+
+ 8, // $73 's'
+ $00,$00,$00,$00,$00,$00,$3C,$42,$40,$30,$0C,$02,$42,$3C,$00,$00,$00,
+
+ 6, // $74 't'
+ $00,$00,$00,$00,$20,$20,$7C,$20,$20,$20,$20,$20,$20,$1C,$00,$00,$00,
+
+ 9, // $75 'u'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$41,$00,$41,$00,$41,$00,$41,$00,$41,$00,$41,$00,$43,$00,$3D,$00,$00,$00,$00,$00,$00,$00,
+
+ 8, // $76 'v'
+ $00,$00,$00,$00,$00,$00,$42,$42,$24,$24,$24,$18,$18,$18,$00,$00,$00,
+
+ 11, // $77 'w'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$44,$40,$44,$40,$2A,$80,$2A,$80,$2A,$80,$2A,$80,$11,$00,$11,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $78 'x'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$41,$00,$22,$00,$14,$00,$08,$00,$08,$00,$14,$00,$22,$00,$41,$00,$00,$00,$00,$00,$00,$00,
+
+ 8, // $79 'y'
+ $00,$00,$00,$00,$00,$00,$42,$42,$24,$24,$24,$18,$18,$18,$10,$10,$20,
+
+ 8, // $7A 'z'
+ $00,$00,$00,$00,$00,$00,$7E,$02,$04,$08,$10,$20,$40,$7E,$00,$00,$00,
+
+ 9, // $7B '{'
+ $00,$00,$00,$00,$00,$00,$07,$00,$08,$00,$08,$00,$08,$00,$08,$00,$10,$00,$60,$00,$10,$00,$08,$00,$08,$00,$08,$00,$08,$00,$08,$00,$07,$00,
+
+ 6, // $7C '|'
+ $00,$00,$00,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,
+
+ 9, // $7D '}'
+ $00,$00,$00,$00,$00,$00,$70,$00,$08,$00,$08,$00,$08,$00,$08,$00,$04,$00,$03,$00,$04,$00,$08,$00,$08,$00,$08,$00,$08,$00,$08,$00,$70,$00,
+
+ 11, // $7E '~'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$38,$40,$44,$40,$44,$40,$43,$80,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 14, // $7F ''
+ $00,$00,$00,$00,$00,$00,$3F,$F8,$20,$08,$20,$08,$20,$08,$20,$08,$20,$08,$20,$08,$20,$08,$20,$08,$20,$08,$3F,$F8,$00,$00,$00,$00,$00,$00,
+
+ 0 );
+
+ verdana17_bold : array[0..3148 ] of int8u = (
+ 17, 4, 32, 128-32,
+ $00,$00,$12,$00,$24,$00,$36,$00,$59,$00,$7C,$00,$B0,$00,$D3,$00,$E5,$00,
+ $F7,$00,$09,$01,$2C,$01,$4F,$01,$61,$01,$73,$01,$85,$01,$A8,$01,$CB,$01,
+ $EE,$01,$11,$02,$34,$02,$57,$02,$7A,$02,$9D,$02,$C0,$02,$E3,$02,$06,$03,
+ $18,$03,$2A,$03,$4D,$03,$70,$03,$93,$03,$B6,$03,$D9,$03,$FC,$03,$1F,$04,
+ $42,$04,$65,$04,$88,$04,$AB,$04,$CE,$04,$F1,$04,$03,$05,$15,$05,$38,$05,
+ $5B,$05,$7E,$05,$A1,$05,$C4,$05,$E7,$05,$0A,$06,$2D,$06,$50,$06,$73,$06,
+ $96,$06,$B9,$06,$DC,$06,$FF,$06,$22,$07,$45,$07,$57,$07,$7A,$07,$8C,$07,
+ $AF,$07,$D2,$07,$F5,$07,$18,$08,$3B,$08,$4D,$08,$70,$08,$93,$08,$A5,$08,
+ $C8,$08,$EB,$08,$FD,$08,$0F,$09,$32,$09,$44,$09,$67,$09,$8A,$09,$AD,$09,
+ $D0,$09,$F3,$09,$05,$0A,$17,$0A,$29,$0A,$4C,$0A,$6F,$0A,$92,$0A,$B5,$0A,
+ $D8,$0A,$EA,$0A,$0D,$0B,$1F,$0B,$42,$0B,$65,$0B,
+
+ 5, // $20 ' '
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 6, // $21 '!'
+ $00,$00,$00,$00,$30,$30,$30,$30,$30,$30,$30,$00,$30,$30,$00,$00,$00,
+
+ 8, // $22 '"'
+ $00,$00,$00,$66,$66,$66,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 12, // $23 '#'
+ $00,$00,$00,$00,$00,$00,$00,$00,$04,$40,$04,$40,$3F,$E0,$3F,$E0,$08,$80,$11,$00,$7F,$C0,$7F,$C0,$22,$00,$22,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $24 '$'
+ $00,$00,$00,$00,$04,$00,$04,$00,$1F,$00,$34,$80,$64,$00,$74,$00,$3C,$00,$0F,$00,$0B,$80,$09,$80,$4B,$00,$3E,$00,$08,$00,$08,$00,$00,$00,
+
+ 18, // $25 '%'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3C,$08,$00,$66,$10,$00,$66,$20,$00,$66,$2F,$00,$66,$59,$80,$66,$99,$80,$3D,$19,$80,$01,$19,$80,$02,$19,$80,$04,$0F,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 12, // $26 '&'
+ $00,$00,$00,$00,$00,$00,$00,$00,$1E,$00,$33,$00,$33,$00,$36,$00,$1C,$60,$36,$60,$63,$60,$61,$C0,$31,$C0,$1F,$60,$00,$00,$00,$00,$00,$00,
+
+ 5, // $27 '''
+ $00,$00,$00,$60,$60,$60,$60,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 8, // $28 '('
+ $00,$00,$00,$0C,$18,$30,$30,$60,$60,$60,$60,$60,$60,$30,$30,$18,$0C,
+
+ 8, // $29 ')'
+ $00,$00,$00,$30,$18,$0C,$0C,$06,$06,$06,$06,$06,$06,$0C,$0C,$18,$30,
+
+ 10, // $2A '*'
+ $00,$00,$00,$00,$00,$00,$08,$00,$49,$00,$2A,$00,$1C,$00,$2A,$00,$49,$00,$08,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 12, // $2B '+'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$04,$00,$04,$00,$04,$00,$04,$00,$7F,$C0,$04,$00,$04,$00,$04,$00,$04,$00,$00,$00,$00,$00,$00,$00,
+
+ 5, // $2C ','
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$70,$60,$60,$C0,$C0,$00,
+
+ 7, // $2D '-'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7C,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 5, // $2E '.'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$30,$30,$30,$00,$00,$00,
+
+ 10, // $2F '/'
+ $00,$00,$00,$00,$00,$00,$01,$80,$01,$80,$03,$00,$03,$00,$06,$00,$06,$00,$0C,$00,$18,$00,$18,$00,$30,$00,$30,$00,$60,$00,$60,$00,$00,$00,
+
+ 10, // $30 '0'
+ $00,$00,$00,$00,$00,$00,$00,$00,$1E,$00,$33,$00,$61,$80,$61,$80,$61,$80,$61,$80,$61,$80,$61,$80,$33,$00,$1E,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $31 '1'
+ $00,$00,$00,$00,$00,$00,$00,$00,$0C,$00,$3C,$00,$0C,$00,$0C,$00,$0C,$00,$0C,$00,$0C,$00,$0C,$00,$0C,$00,$3F,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $32 '2'
+ $00,$00,$00,$00,$00,$00,$00,$00,$3F,$00,$61,$80,$61,$80,$01,$80,$03,$00,$06,$00,$0C,$00,$18,$00,$30,$00,$7F,$80,$00,$00,$00,$00,$00,$00,
+
+ 10, // $33 '3'
+ $00,$00,$00,$00,$00,$00,$00,$00,$3F,$00,$61,$80,$61,$80,$01,$80,$0F,$00,$03,$00,$01,$80,$61,$80,$63,$00,$3E,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $34 '4'
+ $00,$00,$00,$00,$00,$00,$00,$00,$03,$00,$07,$00,$0B,$00,$13,$00,$23,$00,$43,$00,$7F,$C0,$03,$00,$03,$00,$03,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $35 '5'
+ $00,$00,$00,$00,$00,$00,$00,$00,$3F,$80,$30,$00,$30,$00,$3E,$00,$03,$00,$01,$80,$01,$80,$61,$80,$63,$00,$3E,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $36 '6'
+ $00,$00,$00,$00,$00,$00,$00,$00,$0F,$00,$38,$00,$30,$00,$6E,$00,$73,$00,$61,$80,$61,$80,$61,$80,$33,$00,$1E,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $37 '7'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7F,$80,$01,$80,$03,$00,$03,$00,$06,$00,$06,$00,$0C,$00,$0C,$00,$18,$00,$18,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $38 '8'
+ $00,$00,$00,$00,$00,$00,$00,$00,$3F,$00,$61,$80,$61,$80,$61,$80,$3F,$00,$61,$80,$61,$80,$61,$80,$61,$80,$3F,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $39 '9'
+ $00,$00,$00,$00,$00,$00,$00,$00,$1E,$00,$33,$00,$61,$80,$61,$80,$61,$80,$33,$80,$1D,$80,$03,$00,$07,$00,$3C,$00,$00,$00,$00,$00,$00,$00,
+
+ 6, // $3A ':'
+ $00,$00,$00,$00,$00,$00,$30,$30,$30,$00,$00,$30,$30,$30,$00,$00,$00,
+
+ 6, // $3B ';'
+ $00,$00,$00,$00,$00,$00,$30,$30,$30,$00,$00,$38,$30,$30,$60,$60,$00,
+
+ 12, // $3C '<'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$C0,$03,$00,$0C,$00,$30,$00,$40,$00,$30,$00,$0C,$00,$03,$00,$00,$C0,$00,$00,$00,$00,$00,$00,
+
+ 12, // $3D '='
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$7F,$C0,$00,$00,$00,$00,$00,$00,$7F,$C0,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 12, // $3E '>'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$60,$00,$18,$00,$06,$00,$01,$80,$00,$40,$01,$80,$06,$00,$18,$00,$60,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $3F '?'
+ $00,$00,$00,$00,$00,$00,$00,$00,$3E,$00,$63,$00,$03,$00,$06,$00,$0C,$00,$18,$00,$18,$00,$00,$00,$18,$00,$18,$00,$00,$00,$00,$00,$00,$00,
+
+ 14, // $40 '@'
+ $00,$00,$00,$00,$00,$00,$00,$00,$07,$C0,$18,$20,$20,$10,$27,$C8,$4C,$C8,$4C,$C8,$4C,$C8,$4C,$C8,$27,$F0,$20,$00,$18,$00,$07,$C0,$00,$00,
+
+ 11, // $41 'A'
+ $00,$00,$00,$00,$00,$00,$00,$00,$0E,$00,$0E,$00,$0E,$00,$1B,$00,$1B,$00,$31,$80,$3F,$80,$31,$80,$60,$C0,$60,$C0,$00,$00,$00,$00,$00,$00,
+
+ 11, // $42 'B'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7F,$00,$61,$80,$61,$80,$61,$80,$7F,$00,$61,$80,$60,$C0,$60,$C0,$61,$80,$7F,$00,$00,$00,$00,$00,$00,$00,
+
+ 11, // $43 'C'
+ $00,$00,$00,$00,$00,$00,$00,$00,$0F,$80,$30,$C0,$30,$C0,$60,$00,$60,$00,$60,$00,$60,$00,$30,$C0,$30,$C0,$0F,$80,$00,$00,$00,$00,$00,$00,
+
+ 11, // $44 'D'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7E,$00,$61,$80,$61,$80,$60,$C0,$60,$C0,$60,$C0,$60,$C0,$61,$80,$61,$80,$7E,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $45 'E'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7F,$80,$60,$00,$60,$00,$60,$00,$7F,$80,$60,$00,$60,$00,$60,$00,$60,$00,$7F,$80,$00,$00,$00,$00,$00,$00,
+
+ 9, // $46 'F'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7F,$00,$60,$00,$60,$00,$60,$00,$7F,$00,$60,$00,$60,$00,$60,$00,$60,$00,$60,$00,$00,$00,$00,$00,$00,$00,
+
+ 11, // $47 'G'
+ $00,$00,$00,$00,$00,$00,$00,$00,$0F,$80,$30,$C0,$30,$C0,$60,$00,$60,$00,$63,$C0,$60,$C0,$30,$C0,$30,$C0,$0F,$80,$00,$00,$00,$00,$00,$00,
+
+ 11, // $48 'H'
+ $00,$00,$00,$00,$00,$00,$00,$00,$60,$C0,$60,$C0,$60,$C0,$60,$C0,$7F,$C0,$60,$C0,$60,$C0,$60,$C0,$60,$C0,$60,$C0,$00,$00,$00,$00,$00,$00,
+
+ 8, // $49 'I'
+ $00,$00,$00,$00,$7E,$18,$18,$18,$18,$18,$18,$18,$18,$7E,$00,$00,$00,
+
+ 8, // $4A 'J'
+ $00,$00,$00,$00,$3E,$06,$06,$06,$06,$06,$06,$06,$0C,$F8,$00,$00,$00,
+
+ 11, // $4B 'K'
+ $00,$00,$00,$00,$00,$00,$00,$00,$60,$C0,$61,$80,$63,$00,$66,$00,$6C,$00,$7C,$00,$76,$00,$63,$00,$61,$80,$60,$C0,$00,$00,$00,$00,$00,$00,
+
+ 9, // $4C 'L'
+ $00,$00,$00,$00,$00,$00,$00,$00,$60,$00,$60,$00,$60,$00,$60,$00,$60,$00,$60,$00,$60,$00,$60,$00,$60,$00,$7F,$80,$00,$00,$00,$00,$00,$00,
+
+ 13, // $4D 'M'
+ $00,$00,$00,$00,$00,$00,$00,$00,$60,$70,$70,$70,$70,$F0,$58,$B0,$59,$B0,$4D,$30,$4F,$30,$46,$30,$46,$30,$40,$30,$00,$00,$00,$00,$00,$00,
+
+ 11, // $4E 'N'
+ $00,$00,$00,$00,$00,$00,$00,$00,$60,$40,$70,$40,$58,$40,$4C,$40,$4C,$40,$46,$40,$43,$40,$43,$40,$41,$C0,$40,$C0,$00,$00,$00,$00,$00,$00,
+
+ 12, // $4F 'O'
+ $00,$00,$00,$00,$00,$00,$00,$00,$0F,$00,$30,$C0,$30,$C0,$60,$60,$60,$60,$60,$60,$60,$60,$30,$C0,$30,$C0,$0F,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $50 'P'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7E,$00,$63,$00,$61,$80,$61,$80,$61,$80,$63,$00,$7E,$00,$60,$00,$60,$00,$60,$00,$00,$00,$00,$00,$00,$00,
+
+ 12, // $51 'Q'
+ $00,$00,$00,$00,$00,$00,$00,$00,$0F,$00,$30,$C0,$30,$C0,$60,$60,$60,$60,$60,$60,$60,$60,$30,$C0,$30,$C0,$0F,$80,$03,$00,$03,$00,$01,$E0,
+
+ 11, // $52 'R'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7F,$00,$61,$80,$60,$C0,$60,$C0,$61,$80,$7F,$00,$63,$00,$61,$80,$60,$C0,$60,$60,$00,$00,$00,$00,$00,$00,
+
+ 10, // $53 'S'
+ $00,$00,$00,$00,$00,$00,$00,$00,$1F,$00,$31,$80,$61,$80,$60,$00,$3E,$00,$1F,$00,$01,$80,$61,$80,$63,$00,$3E,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $54 'T'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7F,$80,$0C,$00,$0C,$00,$0C,$00,$0C,$00,$0C,$00,$0C,$00,$0C,$00,$0C,$00,$0C,$00,$00,$00,$00,$00,$00,$00,
+
+ 11, // $55 'U'
+ $00,$00,$00,$00,$00,$00,$00,$00,$60,$C0,$60,$C0,$60,$C0,$60,$C0,$60,$C0,$60,$C0,$60,$C0,$60,$C0,$31,$80,$1F,$00,$00,$00,$00,$00,$00,$00,
+
+ 11, // $56 'V'
+ $00,$00,$00,$00,$00,$00,$00,$00,$60,$C0,$60,$C0,$60,$C0,$31,$80,$31,$80,$31,$80,$1B,$00,$1B,$00,$0E,$00,$0E,$00,$00,$00,$00,$00,$00,$00,
+
+ 16, // $57 'W'
+ $00,$00,$00,$00,$00,$00,$00,$00,$61,$86,$61,$86,$63,$C6,$32,$4C,$36,$6C,$36,$6C,$34,$2C,$1C,$38,$18,$18,$18,$18,$00,$00,$00,$00,$00,$00,
+
+ 11, // $58 'X'
+ $00,$00,$00,$00,$00,$00,$00,$00,$60,$C0,$31,$80,$31,$80,$1B,$00,$0E,$00,$0E,$00,$1B,$00,$31,$80,$31,$80,$60,$C0,$00,$00,$00,$00,$00,$00,
+
+ 10, // $59 'Y'
+ $00,$00,$00,$00,$00,$00,$00,$00,$C0,$C0,$61,$80,$61,$80,$33,$00,$1E,$00,$0C,$00,$0C,$00,$0C,$00,$0C,$00,$0C,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $5A 'Z'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7F,$80,$01,$80,$03,$00,$06,$00,$0C,$00,$0C,$00,$18,$00,$30,$00,$60,$00,$7F,$80,$00,$00,$00,$00,$00,$00,
+
+ 8, // $5B '['
+ $00,$00,$00,$3E,$30,$30,$30,$30,$30,$30,$30,$30,$30,$30,$30,$30,$3E,
+
+ 10, // $5C '\'
+ $00,$00,$00,$00,$00,$00,$60,$00,$60,$00,$30,$00,$30,$00,$18,$00,$18,$00,$0C,$00,$06,$00,$06,$00,$03,$00,$03,$00,$01,$80,$01,$80,$00,$00,
+
+ 8, // $5D ']'
+ $00,$00,$00,$7C,$0C,$0C,$0C,$0C,$0C,$0C,$0C,$0C,$0C,$0C,$0C,$0C,$7C,
+
+ 12, // $5E '^'
+ $00,$00,$00,$00,$00,$00,$00,$00,$04,$00,$0E,$00,$1B,$00,$31,$80,$60,$C0,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $5F '_'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$C0,$00,$00,
+
+ 10, // $60 '`'
+ $00,$00,$00,$00,$00,$00,$18,$00,$0C,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $61 'a'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3E,$00,$03,$00,$03,$00,$3F,$00,$63,$00,$63,$00,$63,$00,$3F,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $62 'b'
+ $00,$00,$00,$00,$00,$00,$60,$00,$60,$00,$60,$00,$6E,$00,$73,$00,$61,$80,$61,$80,$61,$80,$61,$80,$63,$00,$7E,$00,$00,$00,$00,$00,$00,$00,
+
+ 8, // $63 'c'
+ $00,$00,$00,$00,$00,$00,$1E,$33,$60,$60,$60,$60,$33,$1E,$00,$00,$00,
+
+ 10, // $64 'd'
+ $00,$00,$00,$00,$00,$00,$01,$80,$01,$80,$01,$80,$1F,$80,$31,$80,$61,$80,$61,$80,$61,$80,$61,$80,$33,$80,$1D,$80,$00,$00,$00,$00,$00,$00,
+
+ 9, // $65 'e'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$1E,$00,$33,$00,$63,$00,$7F,$00,$60,$00,$60,$00,$33,$00,$1E,$00,$00,$00,$00,$00,$00,$00,
+
+ 6, // $66 'f'
+ $00,$00,$00,$1C,$30,$30,$7C,$30,$30,$30,$30,$30,$30,$30,$00,$00,$00,
+
+ 10, // $67 'g'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$1F,$80,$31,$80,$61,$80,$61,$80,$61,$80,$61,$80,$33,$80,$1D,$80,$01,$80,$03,$00,$3E,$00,
+
+ 10, // $68 'h'
+ $00,$00,$00,$00,$00,$00,$60,$00,$60,$00,$60,$00,$6F,$00,$71,$80,$61,$80,$61,$80,$61,$80,$61,$80,$61,$80,$61,$80,$00,$00,$00,$00,$00,$00,
+
+ 4, // $69 'i'
+ $00,$00,$00,$60,$60,$00,$60,$60,$60,$60,$60,$60,$60,$60,$00,$00,$00,
+
+ 6, // $6A 'j'
+ $00,$00,$00,$18,$18,$00,$38,$18,$18,$18,$18,$18,$18,$18,$18,$18,$F0,
+
+ 9, // $6B 'k'
+ $00,$00,$00,$00,$00,$00,$60,$00,$60,$00,$60,$00,$63,$00,$66,$00,$6C,$00,$78,$00,$7C,$00,$66,$00,$63,$00,$61,$80,$00,$00,$00,$00,$00,$00,
+
+ 4, // $6C 'l'
+ $00,$00,$00,$60,$60,$60,$60,$60,$60,$60,$60,$60,$60,$60,$00,$00,$00,
+
+ 14, // $6D 'm'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$6E,$70,$73,$98,$63,$18,$63,$18,$63,$18,$63,$18,$63,$18,$63,$18,$00,$00,$00,$00,$00,$00,
+
+ 10, // $6E 'n'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$6F,$00,$71,$80,$61,$80,$61,$80,$61,$80,$61,$80,$61,$80,$61,$80,$00,$00,$00,$00,$00,$00,
+
+ 10, // $6F 'o'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$1E,$00,$33,$00,$61,$80,$61,$80,$61,$80,$61,$80,$33,$00,$1E,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $70 'p'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$6E,$00,$73,$00,$61,$80,$61,$80,$61,$80,$61,$80,$63,$00,$7E,$00,$60,$00,$60,$00,$60,$00,
+
+ 10, // $71 'q'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$1F,$80,$31,$80,$61,$80,$61,$80,$61,$80,$61,$80,$33,$80,$1D,$80,$01,$80,$01,$80,$01,$80,
+
+ 7, // $72 'r'
+ $00,$00,$00,$00,$00,$00,$6E,$7E,$60,$60,$60,$60,$60,$60,$00,$00,$00,
+
+ 8, // $73 's'
+ $00,$00,$00,$00,$00,$00,$3C,$62,$60,$7C,$3E,$06,$46,$3C,$00,$00,$00,
+
+ 6, // $74 't'
+ $00,$00,$00,$00,$60,$60,$FC,$60,$60,$60,$60,$60,$60,$3C,$00,$00,$00,
+
+ 10, // $75 'u'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$61,$80,$61,$80,$61,$80,$61,$80,$61,$80,$61,$80,$63,$80,$3D,$80,$00,$00,$00,$00,$00,$00,
+
+ 9, // $76 'v'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$63,$00,$63,$00,$63,$00,$36,$00,$36,$00,$36,$00,$1C,$00,$1C,$00,$00,$00,$00,$00,$00,$00,
+
+ 14, // $77 'w'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$63,$18,$63,$18,$33,$30,$37,$B0,$34,$B0,$1C,$E0,$1C,$E0,$0C,$C0,$00,$00,$00,$00,$00,$00,
+
+ 9, // $78 'x'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$63,$00,$63,$00,$36,$00,$1C,$00,$1C,$00,$36,$00,$63,$00,$63,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $79 'y'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$63,$00,$63,$00,$63,$00,$36,$00,$36,$00,$36,$00,$1C,$00,$1C,$00,$0C,$00,$18,$00,$18,$00,
+
+ 8, // $7A 'z'
+ $00,$00,$00,$00,$00,$00,$7E,$06,$0C,$18,$18,$30,$60,$7E,$00,$00,$00,
+
+ 10, // $7B '{'
+ $00,$00,$00,$00,$00,$00,$07,$80,$0C,$00,$0C,$00,$0C,$00,$0C,$00,$18,$00,$70,$00,$18,$00,$0C,$00,$0C,$00,$0C,$00,$0C,$00,$0C,$00,$07,$80,
+
+ 8, // $7C '|'
+ $00,$00,$00,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,
+
+ 10, // $7D '}'
+ $00,$00,$00,$00,$00,$00,$78,$00,$0C,$00,$0C,$00,$0C,$00,$0C,$00,$06,$00,$03,$80,$06,$00,$0C,$00,$0C,$00,$0C,$00,$0C,$00,$0C,$00,$78,$00,
+
+ 12, // $7E '~'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$18,$20,$24,$20,$46,$20,$42,$40,$41,$80,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 14, // $7F ''
+ $00,$00,$00,$00,$00,$00,$3F,$F8,$20,$08,$20,$08,$20,$08,$20,$08,$20,$08,$20,$08,$20,$08,$20,$08,$20,$08,$3F,$F8,$00,$00,$00,$00,$00,$00,
+
+ 0 );
+
+ verdana18 : array[0..3244 ] of int8u = (
+ 18, 4, 32, 128-32,
+ $00,$00,$13,$00,$26,$00,$39,$00,$5E,$00,$83,$00,$A8,$00,$CD,$00,$E0,$00,
+ $F3,$00,$06,$01,$2B,$01,$50,$01,$63,$01,$76,$01,$89,$01,$9C,$01,$C1,$01,
+ $E6,$01,$0B,$02,$30,$02,$55,$02,$7A,$02,$9F,$02,$C4,$02,$E9,$02,$0E,$03,
+ $21,$03,$34,$03,$59,$03,$7E,$03,$A3,$03,$B6,$03,$DB,$03,$00,$04,$25,$04,
+ $4A,$04,$6F,$04,$94,$04,$B9,$04,$DE,$04,$03,$05,$16,$05,$29,$05,$4E,$05,
+ $61,$05,$86,$05,$AB,$05,$D0,$05,$F5,$05,$1A,$06,$3F,$06,$64,$06,$89,$06,
+ $AE,$06,$D3,$06,$F8,$06,$1D,$07,$42,$07,$67,$07,$7A,$07,$8D,$07,$A0,$07,
+ $C5,$07,$EA,$07,$0F,$08,$34,$08,$59,$08,$6C,$08,$91,$08,$B6,$08,$C9,$08,
+ $EE,$08,$13,$09,$26,$09,$39,$09,$5E,$09,$71,$09,$96,$09,$BB,$09,$E0,$09,
+ $05,$0A,$2A,$0A,$3D,$0A,$50,$0A,$63,$0A,$88,$0A,$AD,$0A,$D2,$0A,$F7,$0A,
+ $1C,$0B,$41,$0B,$66,$0B,$79,$0B,$9E,$0B,$C3,$0B,
+
+ 5, // $20 ' '
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 6, // $21 '!'
+ $00,$00,$00,$00,$20,$20,$20,$20,$20,$20,$20,$20,$00,$20,$20,$00,$00,$00,
+
+ 7, // $22 '"'
+ $00,$00,$00,$48,$48,$48,$48,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 12, // $23 '#'
+ $00,$00,$00,$00,$00,$00,$00,$00,$04,$80,$04,$80,$09,$00,$3F,$C0,$09,$00,$11,$00,$12,$00,$7F,$80,$12,$00,$24,$00,$24,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $24 '$'
+ $00,$00,$00,$00,$00,$00,$08,$00,$08,$00,$3E,$00,$49,$00,$48,$00,$48,$00,$38,$00,$0E,$00,$09,$00,$09,$00,$49,$00,$3E,$00,$08,$00,$08,$00,$08,$00,
+
+ 16, // $25 '%'
+ $00,$00,$00,$00,$00,$00,$00,$00,$38,$20,$44,$40,$44,$40,$44,$80,$44,$80,$38,$9C,$01,$22,$01,$22,$02,$22,$02,$22,$04,$1C,$00,$00,$00,$00,$00,$00,
+
+ 12, // $26 '&'
+ $00,$00,$00,$00,$00,$00,$00,$00,$1E,$00,$21,$00,$21,$00,$21,$00,$1E,$40,$24,$40,$42,$40,$41,$40,$40,$80,$21,$40,$1E,$20,$00,$00,$00,$00,$00,$00,
+
+ 4, // $27 '''
+ $00,$00,$00,$40,$40,$40,$40,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $28 '('
+ $00,$00,$00,$08,$10,$20,$20,$40,$40,$40,$40,$40,$40,$40,$20,$20,$10,$08,
+
+ 7, // $29 ')'
+ $00,$00,$00,$20,$10,$08,$08,$04,$04,$04,$04,$04,$04,$04,$08,$08,$10,$20,
+
+ 10, // $2A '*'
+ $00,$00,$00,$00,$00,$00,$08,$00,$49,$00,$2A,$00,$1C,$00,$2A,$00,$49,$00,$08,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 12, // $2B '+'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$02,$00,$02,$00,$02,$00,$02,$00,$3F,$E0,$02,$00,$02,$00,$02,$00,$02,$00,$00,$00,$00,$00,$00,$00,
+
+ 5, // $2C ','
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$20,$20,$20,$40,$40,
+
+ 7, // $2D '-'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$7C,$00,$00,$00,$00,$00,$00,$00,
+
+ 5, // $2E '.'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$20,$20,$00,$00,$00,
+
+ 7, // $2F '/'
+ $00,$00,$00,$02,$04,$04,$04,$08,$08,$10,$10,$20,$20,$40,$40,$40,$80,$00,
+
+ 10, // $30 '0'
+ $00,$00,$00,$00,$00,$00,$00,$00,$1E,$00,$21,$00,$40,$80,$40,$80,$40,$80,$40,$80,$40,$80,$40,$80,$40,$80,$21,$00,$1E,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $31 '1'
+ $00,$00,$00,$00,$00,$00,$00,$00,$04,$00,$04,$00,$1C,$00,$04,$00,$04,$00,$04,$00,$04,$00,$04,$00,$04,$00,$04,$00,$1F,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $32 '2'
+ $00,$00,$00,$00,$00,$00,$00,$00,$3E,$00,$41,$00,$00,$80,$00,$80,$00,$80,$01,$00,$02,$00,$0C,$00,$30,$00,$40,$00,$7F,$80,$00,$00,$00,$00,$00,$00,
+
+ 10, // $33 '3'
+ $00,$00,$00,$00,$00,$00,$00,$00,$3F,$00,$40,$80,$00,$80,$01,$00,$0E,$00,$01,$00,$00,$80,$00,$80,$00,$80,$41,$00,$3E,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $34 '4'
+ $00,$00,$00,$00,$00,$00,$00,$00,$01,$00,$03,$00,$05,$00,$09,$00,$11,$00,$21,$00,$41,$00,$7F,$C0,$01,$00,$01,$00,$01,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $35 '5'
+ $00,$00,$00,$00,$00,$00,$00,$00,$3F,$80,$20,$00,$20,$00,$20,$00,$3E,$00,$01,$00,$00,$80,$00,$80,$00,$80,$41,$00,$3E,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $36 '6'
+ $00,$00,$00,$00,$00,$00,$00,$00,$0F,$00,$10,$00,$20,$00,$40,$00,$5E,$00,$61,$00,$40,$80,$40,$80,$40,$80,$21,$00,$1E,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $37 '7'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7F,$00,$01,$00,$02,$00,$02,$00,$04,$00,$04,$00,$08,$00,$08,$00,$10,$00,$10,$00,$20,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $38 '8'
+ $00,$00,$00,$00,$00,$00,$00,$00,$1E,$00,$21,$00,$40,$80,$40,$80,$21,$00,$1E,$00,$21,$00,$40,$80,$40,$80,$21,$00,$1E,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $39 '9'
+ $00,$00,$00,$00,$00,$00,$00,$00,$1E,$00,$21,$00,$40,$80,$40,$80,$40,$80,$20,$80,$1F,$80,$00,$80,$01,$00,$02,$00,$3C,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $3A ':'
+ $00,$00,$00,$00,$00,$00,$00,$10,$10,$00,$00,$00,$00,$10,$10,$00,$00,$00,
+
+ 7, // $3B ';'
+ $00,$00,$00,$00,$00,$00,$00,$10,$10,$00,$00,$00,$00,$10,$10,$10,$20,$20,
+
+ 12, // $3C '<'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$C0,$03,$00,$0C,$00,$30,$00,$30,$00,$0C,$00,$03,$00,$00,$C0,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 12, // $3D '='
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3F,$E0,$00,$00,$00,$00,$3F,$E0,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 12, // $3E '>'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$30,$00,$0C,$00,$03,$00,$00,$C0,$00,$C0,$03,$00,$0C,$00,$30,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 8, // $3F '?'
+ $00,$00,$00,$00,$3C,$42,$02,$02,$04,$08,$10,$10,$00,$10,$10,$00,$00,$00,
+
+ 15, // $40 '@'
+ $00,$00,$00,$00,$00,$00,$00,$00,$07,$80,$18,$60,$20,$10,$23,$D0,$44,$48,$48,$48,$48,$48,$48,$48,$44,$48,$23,$F0,$20,$00,$18,$00,$07,$C0,$00,$00,
+
+ 10, // $41 'A'
+ $00,$00,$00,$00,$00,$00,$00,$00,$0C,$00,$12,$00,$12,$00,$12,$00,$21,$00,$21,$00,$40,$80,$7F,$80,$40,$80,$80,$40,$80,$40,$00,$00,$00,$00,$00,$00,
+
+ 10, // $42 'B'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7E,$00,$41,$00,$41,$00,$41,$00,$7E,$00,$41,$00,$40,$80,$40,$80,$40,$80,$41,$00,$7E,$00,$00,$00,$00,$00,$00,$00,
+
+ 11, // $43 'C'
+ $00,$00,$00,$00,$00,$00,$00,$00,$0F,$00,$30,$C0,$20,$40,$40,$00,$40,$00,$40,$00,$40,$00,$40,$00,$20,$40,$30,$C0,$0F,$00,$00,$00,$00,$00,$00,$00,
+
+ 11, // $44 'D'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7E,$00,$41,$80,$40,$80,$40,$40,$40,$40,$40,$40,$40,$40,$40,$40,$40,$80,$41,$80,$7E,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $45 'E'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7F,$00,$40,$00,$40,$00,$40,$00,$7F,$00,$40,$00,$40,$00,$40,$00,$40,$00,$40,$00,$7F,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $46 'F'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7F,$80,$40,$00,$40,$00,$40,$00,$7F,$00,$40,$00,$40,$00,$40,$00,$40,$00,$40,$00,$40,$00,$00,$00,$00,$00,$00,$00,
+
+ 12, // $47 'G'
+ $00,$00,$00,$00,$00,$00,$00,$00,$0F,$80,$30,$60,$20,$20,$40,$00,$40,$00,$41,$E0,$40,$20,$40,$20,$20,$20,$30,$20,$0F,$C0,$00,$00,$00,$00,$00,$00,
+
+ 11, // $48 'H'
+ $00,$00,$00,$00,$00,$00,$00,$00,$40,$40,$40,$40,$40,$40,$40,$40,$7F,$C0,$40,$40,$40,$40,$40,$40,$40,$40,$40,$40,$40,$40,$00,$00,$00,$00,$00,$00,
+
+ 5, // $49 'I'
+ $00,$00,$00,$00,$70,$20,$20,$20,$20,$20,$20,$20,$20,$20,$70,$00,$00,$00,
+
+ 7, // $4A 'J'
+ $00,$00,$00,$00,$3C,$04,$04,$04,$04,$04,$04,$04,$04,$08,$F0,$00,$00,$00,
+
+ 10, // $4B 'K'
+ $00,$00,$00,$00,$00,$00,$00,$00,$40,$80,$41,$00,$42,$00,$44,$00,$48,$00,$50,$00,$68,$00,$44,$00,$42,$00,$41,$00,$40,$80,$00,$00,$00,$00,$00,$00,
+
+ 8, // $4C 'L'
+ $00,$00,$00,$00,$40,$40,$40,$40,$40,$40,$40,$40,$40,$40,$7F,$00,$00,$00,
+
+ 13, // $4D 'M'
+ $00,$00,$00,$00,$00,$00,$00,$00,$60,$30,$50,$50,$50,$50,$48,$90,$48,$90,$45,$10,$45,$10,$42,$10,$42,$10,$40,$10,$40,$10,$00,$00,$00,$00,$00,$00,
+
+ 11, // $4E 'N'
+ $00,$00,$00,$00,$00,$00,$00,$00,$40,$40,$60,$40,$50,$40,$48,$40,$48,$40,$44,$40,$42,$40,$42,$40,$41,$40,$40,$C0,$40,$40,$00,$00,$00,$00,$00,$00,
+
+ 12, // $4F 'O'
+ $00,$00,$00,$00,$00,$00,$00,$00,$0F,$00,$30,$C0,$20,$40,$40,$20,$40,$20,$40,$20,$40,$20,$40,$20,$20,$40,$30,$C0,$0F,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $50 'P'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7E,$00,$41,$00,$40,$80,$40,$80,$40,$80,$41,$00,$7E,$00,$40,$00,$40,$00,$40,$00,$40,$00,$00,$00,$00,$00,$00,$00,
+
+ 12, // $51 'Q'
+ $00,$00,$00,$00,$00,$00,$00,$00,$0F,$00,$30,$C0,$20,$40,$40,$20,$40,$20,$40,$20,$40,$20,$40,$20,$20,$40,$30,$C0,$0F,$00,$01,$00,$01,$00,$00,$E0,
+
+ 10, // $52 'R'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7C,$00,$42,$00,$41,$00,$41,$00,$41,$00,$42,$00,$7C,$00,$42,$00,$41,$00,$40,$80,$40,$40,$00,$00,$00,$00,$00,$00,
+
+ 10, // $53 'S'
+ $00,$00,$00,$00,$00,$00,$00,$00,$1F,$00,$20,$80,$40,$00,$40,$00,$20,$00,$1E,$00,$01,$00,$00,$80,$40,$80,$21,$00,$1E,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $54 'T'
+ $00,$00,$00,$00,$00,$00,$00,$00,$FF,$80,$08,$00,$08,$00,$08,$00,$08,$00,$08,$00,$08,$00,$08,$00,$08,$00,$08,$00,$08,$00,$00,$00,$00,$00,$00,$00,
+
+ 11, // $55 'U'
+ $00,$00,$00,$00,$00,$00,$00,$00,$40,$40,$40,$40,$40,$40,$40,$40,$40,$40,$40,$40,$40,$40,$40,$40,$40,$40,$20,$80,$1F,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $56 'V'
+ $00,$00,$00,$00,$00,$00,$00,$00,$80,$40,$80,$40,$40,$80,$40,$80,$40,$80,$21,$00,$21,$00,$12,$00,$12,$00,$12,$00,$0C,$00,$00,$00,$00,$00,$00,$00,
+
+ 15, // $57 'W'
+ $00,$00,$00,$00,$00,$00,$00,$00,$41,$04,$41,$04,$22,$88,$22,$88,$22,$88,$12,$90,$14,$50,$14,$50,$14,$50,$08,$20,$08,$20,$00,$00,$00,$00,$00,$00,
+
+ 10, // $58 'X'
+ $00,$00,$00,$00,$00,$00,$00,$00,$40,$80,$21,$00,$21,$00,$12,$00,$0C,$00,$0C,$00,$0C,$00,$12,$00,$21,$00,$21,$00,$40,$80,$00,$00,$00,$00,$00,$00,
+
+ 9, // $59 'Y'
+ $00,$00,$00,$00,$00,$00,$00,$00,$80,$80,$41,$00,$22,$00,$22,$00,$14,$00,$08,$00,$08,$00,$08,$00,$08,$00,$08,$00,$08,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $5A 'Z'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7F,$80,$00,$80,$01,$00,$02,$00,$04,$00,$08,$00,$08,$00,$10,$00,$20,$00,$40,$00,$7F,$80,$00,$00,$00,$00,$00,$00,
+
+ 7, // $5B '['
+ $00,$00,$00,$3C,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$3C,
+
+ 7, // $5C '\'
+ $00,$00,$00,$80,$40,$40,$40,$20,$20,$10,$10,$08,$08,$04,$04,$04,$02,$00,
+
+ 7, // $5D ']'
+ $00,$00,$00,$78,$08,$08,$08,$08,$08,$08,$08,$08,$08,$08,$08,$08,$08,$78,
+
+ 12, // $5E '^'
+ $00,$00,$00,$00,$00,$00,$00,$00,$06,$00,$09,$00,$10,$80,$20,$40,$40,$20,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $5F '_'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$C0,$00,$00,
+
+ 10, // $60 '`'
+ $00,$00,$00,$00,$00,$00,$10,$00,$08,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $61 'a'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$1E,$00,$21,$00,$01,$00,$3F,$00,$41,$00,$41,$00,$43,$00,$3D,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $62 'b'
+ $00,$00,$00,$00,$00,$00,$40,$00,$40,$00,$40,$00,$40,$00,$5C,$00,$62,$00,$41,$00,$41,$00,$41,$00,$41,$00,$42,$00,$7C,$00,$00,$00,$00,$00,$00,$00,
+
+ 8, // $63 'c'
+ $00,$00,$00,$00,$00,$00,$00,$1E,$21,$40,$40,$40,$40,$21,$1E,$00,$00,$00,
+
+ 9, // $64 'd'
+ $00,$00,$00,$00,$00,$00,$01,$00,$01,$00,$01,$00,$01,$00,$1F,$00,$21,$00,$41,$00,$41,$00,$41,$00,$41,$00,$23,$00,$1D,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $65 'e'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$1C,$00,$22,$00,$41,$00,$7F,$00,$40,$00,$40,$00,$21,$00,$1E,$00,$00,$00,$00,$00,$00,$00,
+
+ 6, // $66 'f'
+ $00,$00,$00,$1C,$20,$20,$20,$7C,$20,$20,$20,$20,$20,$20,$20,$00,$00,$00,
+
+ 9, // $67 'g'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$1F,$00,$21,$00,$41,$00,$41,$00,$41,$00,$41,$00,$23,$00,$1D,$00,$01,$00,$22,$00,$1C,$00,
+
+ 9, // $68 'h'
+ $00,$00,$00,$00,$00,$00,$40,$00,$40,$00,$40,$00,$40,$00,$5E,$00,$61,$00,$41,$00,$41,$00,$41,$00,$41,$00,$41,$00,$41,$00,$00,$00,$00,$00,$00,$00,
+
+ 3, // $69 'i'
+ $00,$00,$00,$00,$40,$00,$00,$40,$40,$40,$40,$40,$40,$40,$40,$00,$00,$00,
+
+ 5, // $6A 'j'
+ $00,$00,$00,$00,$10,$00,$00,$70,$10,$10,$10,$10,$10,$10,$10,$10,$10,$E0,
+
+ 9, // $6B 'k'
+ $00,$00,$00,$00,$00,$00,$40,$00,$40,$00,$40,$00,$40,$00,$42,$00,$44,$00,$48,$00,$50,$00,$68,$00,$44,$00,$42,$00,$41,$00,$00,$00,$00,$00,$00,$00,
+
+ 3, // $6C 'l'
+ $00,$00,$00,$40,$40,$40,$40,$40,$40,$40,$40,$40,$40,$40,$40,$00,$00,$00,
+
+ 15, // $6D 'm'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$2E,$70,$31,$88,$21,$08,$21,$08,$21,$08,$21,$08,$21,$08,$21,$08,$00,$00,$00,$00,$00,$00,
+
+ 9, // $6E 'n'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$5E,$00,$61,$00,$41,$00,$41,$00,$41,$00,$41,$00,$41,$00,$41,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $6F 'o'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$1E,$00,$21,$00,$40,$80,$40,$80,$40,$80,$40,$80,$21,$00,$1E,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $70 'p'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$5C,$00,$62,$00,$41,$00,$41,$00,$41,$00,$41,$00,$42,$00,$7C,$00,$40,$00,$40,$00,$40,$00,
+
+ 9, // $71 'q'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$1F,$00,$21,$00,$41,$00,$41,$00,$41,$00,$41,$00,$23,$00,$1D,$00,$01,$00,$01,$00,$01,$00,
+
+ 6, // $72 'r'
+ $00,$00,$00,$00,$00,$00,$00,$5C,$60,$40,$40,$40,$40,$40,$40,$00,$00,$00,
+
+ 8, // $73 's'
+ $00,$00,$00,$00,$00,$00,$00,$3C,$42,$40,$30,$0C,$02,$42,$3C,$00,$00,$00,
+
+ 6, // $74 't'
+ $00,$00,$00,$00,$00,$20,$20,$7C,$20,$20,$20,$20,$20,$20,$1C,$00,$00,$00,
+
+ 9, // $75 'u'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$41,$00,$41,$00,$41,$00,$41,$00,$41,$00,$41,$00,$43,$00,$3D,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $76 'v'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$41,$00,$41,$00,$22,$00,$22,$00,$22,$00,$14,$00,$14,$00,$08,$00,$00,$00,$00,$00,$00,$00,
+
+ 13, // $77 'w'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$42,$10,$42,$10,$25,$20,$25,$20,$28,$A0,$28,$A0,$10,$40,$10,$40,$00,$00,$00,$00,$00,$00,
+
+ 9, // $78 'x'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$41,$00,$22,$00,$14,$00,$08,$00,$08,$00,$14,$00,$22,$00,$41,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $79 'y'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$41,$00,$41,$00,$22,$00,$22,$00,$22,$00,$14,$00,$14,$00,$08,$00,$08,$00,$10,$00,$10,$00,
+
+ 9, // $7A 'z'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$7F,$00,$02,$00,$04,$00,$08,$00,$10,$00,$20,$00,$40,$00,$7F,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $7B '{'
+ $00,$00,$00,$00,$00,$00,$07,$00,$08,$00,$08,$00,$08,$00,$08,$00,$08,$00,$10,$00,$60,$00,$10,$00,$08,$00,$08,$00,$08,$00,$08,$00,$08,$00,$07,$00,
+
+ 7, // $7C '|'
+ $00,$00,$00,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,
+
+ 10, // $7D '}'
+ $00,$00,$00,$00,$00,$00,$38,$00,$04,$00,$04,$00,$04,$00,$04,$00,$04,$00,$02,$00,$01,$80,$02,$00,$04,$00,$04,$00,$04,$00,$04,$00,$04,$00,$38,$00,
+
+ 12, // $7E '~'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$18,$20,$24,$20,$42,$40,$41,$80,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 15, // $7F ''
+ $00,$00,$00,$00,$00,$00,$00,$00,$3F,$F8,$20,$08,$20,$08,$20,$08,$20,$08,$20,$08,$20,$08,$20,$08,$20,$08,$20,$08,$3F,$F8,$00,$00,$00,$00,$00,$00,
+
+ 0 );
+
+ verdana18_bold : array[0..3370 ] of int8u = (
+ 18, 4, 32, 128-32,
+ $00,$00,$13,$00,$26,$00,$4B,$00,$70,$00,$95,$00,$CC,$00,$F1,$00,$04,$01,
+ $17,$01,$2A,$01,$4F,$01,$74,$01,$87,$01,$9A,$01,$AD,$01,$D2,$01,$F7,$01,
+ $1C,$02,$41,$02,$66,$02,$8B,$02,$B0,$02,$D5,$02,$FA,$02,$1F,$03,$44,$03,
+ $57,$03,$6A,$03,$8F,$03,$B4,$03,$D9,$03,$FE,$03,$23,$04,$48,$04,$6D,$04,
+ $92,$04,$B7,$04,$DC,$04,$01,$05,$26,$05,$4B,$05,$5E,$05,$71,$05,$96,$05,
+ $BB,$05,$E0,$05,$05,$06,$2A,$06,$4F,$06,$74,$06,$99,$06,$BE,$06,$E3,$06,
+ $08,$07,$2D,$07,$52,$07,$77,$07,$9C,$07,$C1,$07,$D4,$07,$F9,$07,$0C,$08,
+ $31,$08,$56,$08,$7B,$08,$A0,$08,$C5,$08,$D8,$08,$FD,$08,$22,$09,$35,$09,
+ $5A,$09,$7F,$09,$92,$09,$A5,$09,$CA,$09,$DD,$09,$02,$0A,$27,$0A,$4C,$0A,
+ $71,$0A,$96,$0A,$A9,$0A,$CE,$0A,$E1,$0A,$06,$0B,$2B,$0B,$50,$0B,$75,$0B,
+ $9A,$0B,$BF,$0B,$E4,$0B,$F7,$0B,$1C,$0C,$41,$0C,
+
+ 5, // $20 ' '
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 6, // $21 '!'
+ $00,$00,$00,$00,$30,$30,$30,$30,$30,$30,$30,$30,$00,$30,$30,$00,$00,$00,
+
+ 9, // $22 '"'
+ $00,$00,$00,$00,$00,$00,$36,$00,$36,$00,$36,$00,$36,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 13, // $23 '#'
+ $00,$00,$00,$00,$00,$00,$00,$00,$04,$20,$04,$20,$08,$40,$3F,$F0,$3F,$F0,$08,$40,$10,$80,$7F,$E0,$7F,$E0,$21,$00,$21,$00,$00,$00,$00,$00,$00,$00,
+
+ 11, // $24 '$'
+ $00,$00,$00,$00,$00,$00,$04,$00,$04,$00,$1F,$80,$34,$C0,$64,$C0,$64,$00,$3C,$00,$07,$80,$04,$C0,$64,$C0,$65,$80,$3F,$00,$04,$00,$04,$00,$00,$00,
+
+ 19, // $25 '%'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3E,$08,$00,$63,$10,$00,$63,$10,$00,$63,$20,$00,$63,$2F,$80,$63,$58,$C0,$3E,$98,$C0,$00,$98,$C0,$01,$18,$C0,$01,$18,$C0,$02,$0F,$80,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 13, // $26 '&'
+ $00,$00,$00,$00,$00,$00,$00,$00,$1E,$00,$33,$00,$33,$00,$33,$00,$1E,$60,$36,$60,$63,$60,$61,$C0,$60,$C0,$30,$E0,$1F,$30,$00,$00,$00,$00,$00,$00,
+
+ 5, // $27 '''
+ $00,$00,$00,$60,$60,$60,$60,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 8, // $28 '('
+ $00,$00,$00,$06,$0C,$18,$30,$30,$60,$60,$60,$60,$60,$30,$30,$18,$0C,$06,
+
+ 8, // $29 ')'
+ $00,$00,$00,$60,$30,$18,$0C,$0C,$06,$06,$06,$06,$06,$0C,$0C,$18,$30,$60,
+
+ 11, // $2A '*'
+ $00,$00,$00,$00,$00,$00,$04,$00,$24,$80,$15,$00,$0E,$00,$15,$00,$24,$80,$04,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 13, // $2B '+'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$02,$00,$02,$00,$02,$00,$02,$00,$3F,$E0,$02,$00,$02,$00,$02,$00,$02,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 5, // $2C ','
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$70,$60,$60,$60,$C0,$C0,
+
+ 7, // $2D '-'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$7C,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 5, // $2E '.'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$30,$30,$30,$00,$00,$00,
+
+ 10, // $2F '/'
+ $00,$00,$00,$00,$00,$00,$01,$80,$01,$80,$03,$00,$03,$00,$06,$00,$06,$00,$0C,$00,$0C,$00,$18,$00,$18,$00,$30,$00,$30,$00,$60,$00,$60,$00,$00,$00,
+
+ 11, // $30 '0'
+ $00,$00,$00,$00,$00,$00,$00,$00,$1F,$00,$31,$80,$60,$C0,$60,$C0,$60,$C0,$60,$C0,$60,$C0,$60,$C0,$60,$C0,$31,$80,$1F,$00,$00,$00,$00,$00,$00,$00,
+
+ 11, // $31 '1'
+ $00,$00,$00,$00,$00,$00,$00,$00,$06,$00,$1E,$00,$06,$00,$06,$00,$06,$00,$06,$00,$06,$00,$06,$00,$06,$00,$06,$00,$1F,$80,$00,$00,$00,$00,$00,$00,
+
+ 11, // $32 '2'
+ $00,$00,$00,$00,$00,$00,$00,$00,$3F,$00,$61,$80,$60,$C0,$00,$C0,$01,$80,$03,$00,$06,$00,$0C,$00,$18,$00,$30,$00,$7F,$C0,$00,$00,$00,$00,$00,$00,
+
+ 11, // $33 '3'
+ $00,$00,$00,$00,$00,$00,$00,$00,$3F,$00,$61,$80,$60,$C0,$00,$C0,$01,$80,$0F,$00,$01,$80,$00,$C0,$60,$C0,$61,$80,$3F,$00,$00,$00,$00,$00,$00,$00,
+
+ 11, // $34 '4'
+ $00,$00,$00,$00,$00,$00,$00,$00,$01,$80,$03,$80,$05,$80,$09,$80,$11,$80,$21,$80,$41,$80,$7F,$E0,$01,$80,$01,$80,$01,$80,$00,$00,$00,$00,$00,$00,
+
+ 11, // $35 '5'
+ $00,$00,$00,$00,$00,$00,$00,$00,$3F,$C0,$30,$00,$30,$00,$30,$00,$3F,$00,$01,$80,$00,$C0,$00,$C0,$60,$C0,$61,$80,$3F,$00,$00,$00,$00,$00,$00,$00,
+
+ 11, // $36 '6'
+ $00,$00,$00,$00,$00,$00,$00,$00,$0F,$80,$18,$00,$30,$00,$60,$00,$6F,$00,$71,$80,$60,$C0,$60,$C0,$60,$C0,$31,$80,$1F,$00,$00,$00,$00,$00,$00,$00,
+
+ 11, // $37 '7'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7F,$C0,$00,$C0,$01,$80,$01,$80,$03,$00,$03,$00,$06,$00,$06,$00,$0C,$00,$0C,$00,$18,$00,$00,$00,$00,$00,$00,$00,
+
+ 11, // $38 '8'
+ $00,$00,$00,$00,$00,$00,$00,$00,$1F,$00,$31,$80,$60,$C0,$60,$C0,$31,$80,$1F,$00,$31,$80,$60,$C0,$60,$C0,$31,$80,$1F,$00,$00,$00,$00,$00,$00,$00,
+
+ 11, // $39 '9'
+ $00,$00,$00,$00,$00,$00,$00,$00,$1F,$00,$31,$80,$60,$C0,$60,$C0,$60,$C0,$31,$C0,$1E,$C0,$00,$C0,$01,$80,$03,$00,$3E,$00,$00,$00,$00,$00,$00,$00,
+
+ 6, // $3A ':'
+ $00,$00,$00,$00,$00,$00,$00,$30,$30,$30,$00,$00,$30,$30,$30,$00,$00,$00,
+
+ 6, // $3B ';'
+ $00,$00,$00,$00,$00,$00,$00,$30,$30,$30,$00,$00,$38,$30,$30,$30,$60,$60,
+
+ 13, // $3C '<'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$20,$00,$C0,$03,$00,$0C,$00,$30,$00,$30,$00,$0C,$00,$03,$00,$00,$C0,$00,$20,$00,$00,$00,$00,$00,$00,
+
+ 13, // $3D '='
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3F,$E0,$00,$00,$00,$00,$00,$00,$3F,$E0,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 13, // $3E '>'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$20,$00,$18,$00,$06,$00,$01,$80,$00,$60,$00,$60,$01,$80,$06,$00,$18,$00,$20,$00,$00,$00,$00,$00,$00,$00,
+
+ 9, // $3F '?'
+ $00,$00,$00,$00,$00,$00,$00,$00,$3E,$00,$63,$00,$03,$00,$03,$00,$06,$00,$0C,$00,$18,$00,$18,$00,$00,$00,$18,$00,$18,$00,$00,$00,$00,$00,$00,$00,
+
+ 14, // $40 '@'
+ $00,$00,$00,$00,$00,$00,$00,$00,$07,$80,$18,$60,$20,$10,$27,$D0,$4C,$C8,$4C,$C8,$4C,$C8,$4C,$C8,$4C,$C8,$27,$F0,$20,$00,$18,$00,$07,$C0,$00,$00,
+
+ 12, // $41 'A'
+ $00,$00,$00,$00,$00,$00,$00,$00,$06,$00,$06,$00,$0F,$00,$0F,$00,$19,$80,$19,$80,$30,$C0,$3F,$C0,$30,$C0,$60,$60,$60,$60,$00,$00,$00,$00,$00,$00,
+
+ 11, // $42 'B'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7F,$00,$61,$80,$61,$80,$61,$80,$63,$00,$7F,$00,$61,$80,$60,$C0,$60,$C0,$61,$80,$7F,$00,$00,$00,$00,$00,$00,$00,
+
+ 11, // $43 'C'
+ $00,$00,$00,$00,$00,$00,$00,$00,$0F,$80,$38,$C0,$30,$C0,$60,$00,$60,$00,$60,$00,$60,$00,$60,$00,$30,$C0,$38,$C0,$0F,$80,$00,$00,$00,$00,$00,$00,
+
+ 12, // $44 'D'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7F,$00,$61,$C0,$60,$C0,$60,$60,$60,$60,$60,$60,$60,$60,$60,$60,$60,$C0,$61,$C0,$7F,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $45 'E'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7F,$80,$60,$00,$60,$00,$60,$00,$60,$00,$7F,$80,$60,$00,$60,$00,$60,$00,$60,$00,$7F,$80,$00,$00,$00,$00,$00,$00,
+
+ 10, // $46 'F'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7F,$80,$60,$00,$60,$00,$60,$00,$60,$00,$7F,$80,$60,$00,$60,$00,$60,$00,$60,$00,$60,$00,$00,$00,$00,$00,$00,$00,
+
+ 12, // $47 'G'
+ $00,$00,$00,$00,$00,$00,$00,$00,$0F,$C0,$38,$60,$30,$60,$60,$00,$60,$00,$63,$E0,$60,$60,$60,$60,$30,$60,$38,$60,$0F,$C0,$00,$00,$00,$00,$00,$00,
+
+ 12, // $48 'H'
+ $00,$00,$00,$00,$00,$00,$00,$00,$60,$60,$60,$60,$60,$60,$60,$60,$60,$60,$7F,$E0,$60,$60,$60,$60,$60,$60,$60,$60,$60,$60,$00,$00,$00,$00,$00,$00,
+
+ 8, // $49 'I'
+ $00,$00,$00,$00,$7E,$18,$18,$18,$18,$18,$18,$18,$18,$18,$7E,$00,$00,$00,
+
+ 8, // $4A 'J'
+ $00,$00,$00,$00,$3E,$06,$06,$06,$06,$06,$06,$06,$06,$0C,$F8,$00,$00,$00,
+
+ 12, // $4B 'K'
+ $00,$00,$00,$00,$00,$00,$00,$00,$60,$60,$60,$C0,$61,$80,$63,$00,$66,$00,$6C,$00,$7E,$00,$73,$00,$61,$80,$60,$C0,$60,$60,$00,$00,$00,$00,$00,$00,
+
+ 10, // $4C 'L'
+ $00,$00,$00,$00,$00,$00,$00,$00,$60,$00,$60,$00,$60,$00,$60,$00,$60,$00,$60,$00,$60,$00,$60,$00,$60,$00,$60,$00,$7F,$80,$00,$00,$00,$00,$00,$00,
+
+ 14, // $4D 'M'
+ $00,$00,$00,$00,$00,$00,$00,$00,$60,$38,$70,$38,$70,$78,$58,$58,$58,$D8,$4C,$98,$4D,$98,$47,$18,$47,$18,$42,$18,$40,$18,$00,$00,$00,$00,$00,$00,
+
+ 12, // $4E 'N'
+ $00,$00,$00,$00,$00,$00,$00,$00,$70,$20,$70,$20,$58,$20,$4C,$20,$4C,$20,$46,$20,$43,$20,$43,$20,$41,$A0,$40,$E0,$40,$E0,$00,$00,$00,$00,$00,$00,
+
+ 13, // $4F 'O'
+ $00,$00,$00,$00,$00,$00,$00,$00,$0F,$80,$38,$E0,$30,$60,$60,$30,$60,$30,$60,$30,$60,$30,$60,$30,$30,$60,$38,$E0,$0F,$80,$00,$00,$00,$00,$00,$00,
+
+ 11, // $50 'P'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7F,$00,$61,$80,$60,$C0,$60,$C0,$60,$C0,$61,$80,$7F,$00,$60,$00,$60,$00,$60,$00,$60,$00,$00,$00,$00,$00,$00,$00,
+
+ 13, // $51 'Q'
+ $00,$00,$00,$00,$00,$00,$00,$00,$0F,$80,$38,$E0,$30,$60,$60,$30,$60,$30,$60,$30,$60,$30,$60,$30,$30,$60,$38,$E0,$0F,$80,$03,$00,$03,$80,$01,$F0,
+
+ 12, // $52 'R'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7F,$00,$61,$80,$60,$C0,$60,$C0,$60,$C0,$61,$80,$7F,$00,$61,$80,$60,$C0,$60,$60,$60,$30,$00,$00,$00,$00,$00,$00,
+
+ 11, // $53 'S'
+ $00,$00,$00,$00,$00,$00,$00,$00,$1F,$80,$30,$C0,$60,$C0,$60,$00,$7C,$00,$3F,$80,$03,$C0,$00,$C0,$60,$C0,$61,$80,$3F,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $54 'T'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7F,$80,$0C,$00,$0C,$00,$0C,$00,$0C,$00,$0C,$00,$0C,$00,$0C,$00,$0C,$00,$0C,$00,$0C,$00,$00,$00,$00,$00,$00,$00,
+
+ 12, // $55 'U'
+ $00,$00,$00,$00,$00,$00,$00,$00,$60,$60,$60,$60,$60,$60,$60,$60,$60,$60,$60,$60,$60,$60,$60,$60,$60,$60,$30,$C0,$1F,$80,$00,$00,$00,$00,$00,$00,
+
+ 11, // $56 'V'
+ $00,$00,$00,$00,$00,$00,$00,$00,$60,$C0,$60,$C0,$60,$C0,$31,$80,$31,$80,$31,$80,$1B,$00,$1B,$00,$1B,$00,$0E,$00,$0E,$00,$00,$00,$00,$00,$00,$00,
+
+ 16, // $57 'W'
+ $00,$00,$00,$00,$00,$00,$00,$00,$61,$86,$61,$86,$63,$C6,$33,$CC,$32,$4C,$32,$4C,$1E,$78,$1C,$38,$1C,$38,$0C,$30,$0C,$30,$00,$00,$00,$00,$00,$00,
+
+ 11, // $58 'X'
+ $00,$00,$00,$00,$00,$00,$00,$00,$60,$C0,$31,$80,$31,$80,$1B,$00,$0E,$00,$0E,$00,$0E,$00,$1B,$00,$31,$80,$31,$80,$60,$C0,$00,$00,$00,$00,$00,$00,
+
+ 11, // $59 'Y'
+ $00,$00,$00,$00,$00,$00,$00,$00,$C0,$C0,$61,$80,$61,$80,$33,$00,$1E,$00,$1E,$00,$0C,$00,$0C,$00,$0C,$00,$0C,$00,$0C,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $5A 'Z'
+ $00,$00,$00,$00,$00,$00,$00,$00,$7F,$80,$01,$80,$03,$00,$06,$00,$06,$00,$0C,$00,$18,$00,$18,$00,$30,$00,$60,$00,$7F,$80,$00,$00,$00,$00,$00,$00,
+
+ 8, // $5B '['
+ $00,$00,$00,$3E,$30,$30,$30,$30,$30,$30,$30,$30,$30,$30,$30,$30,$30,$3E,
+
+ 10, // $5C '\'
+ $00,$00,$00,$00,$00,$00,$60,$00,$60,$00,$30,$00,$30,$00,$18,$00,$18,$00,$0C,$00,$0C,$00,$06,$00,$06,$00,$03,$00,$03,$00,$01,$80,$01,$80,$00,$00,
+
+ 8, // $5D ']'
+ $00,$00,$00,$7C,$0C,$0C,$0C,$0C,$0C,$0C,$0C,$0C,$0C,$0C,$0C,$0C,$0C,$7C,
+
+ 13, // $5E '^'
+ $00,$00,$00,$00,$00,$00,$00,$00,$06,$00,$0F,$00,$19,$80,$30,$C0,$60,$60,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 11, // $5F '_'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$E0,$00,$00,
+
+ 11, // $60 '`'
+ $00,$00,$00,$00,$00,$00,$00,$00,$18,$00,$0C,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $61 'a'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3F,$00,$01,$80,$01,$80,$3F,$80,$61,$80,$61,$80,$63,$80,$3D,$80,$00,$00,$00,$00,$00,$00,
+
+ 10, // $62 'b'
+ $00,$00,$00,$00,$00,$00,$60,$00,$60,$00,$60,$00,$60,$00,$6E,$00,$73,$00,$61,$80,$61,$80,$61,$80,$61,$80,$63,$00,$7E,$00,$00,$00,$00,$00,$00,$00,
+
+ 8, // $63 'c'
+ $00,$00,$00,$00,$00,$00,$00,$1E,$33,$60,$60,$60,$60,$33,$1E,$00,$00,$00,
+
+ 10, // $64 'd'
+ $00,$00,$00,$00,$00,$00,$01,$80,$01,$80,$01,$80,$01,$80,$1F,$80,$31,$80,$61,$80,$61,$80,$61,$80,$61,$80,$33,$80,$1D,$80,$00,$00,$00,$00,$00,$00,
+
+ 10, // $65 'e'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$1E,$00,$33,$00,$61,$80,$7F,$80,$60,$00,$60,$00,$31,$80,$1F,$00,$00,$00,$00,$00,$00,$00,
+
+ 6, // $66 'f'
+ $00,$00,$00,$1C,$30,$30,$30,$7C,$30,$30,$30,$30,$30,$30,$30,$00,$00,$00,
+
+ 10, // $67 'g'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$1F,$80,$31,$80,$61,$80,$61,$80,$61,$80,$61,$80,$33,$80,$1D,$80,$01,$80,$03,$00,$3E,$00,
+
+ 10, // $68 'h'
+ $00,$00,$00,$00,$00,$00,$60,$00,$60,$00,$60,$00,$60,$00,$6F,$00,$71,$80,$61,$80,$61,$80,$61,$80,$61,$80,$61,$80,$61,$80,$00,$00,$00,$00,$00,$00,
+
+ 4, // $69 'i'
+ $00,$00,$00,$60,$60,$00,$00,$60,$60,$60,$60,$60,$60,$60,$60,$00,$00,$00,
+
+ 6, // $6A 'j'
+ $00,$00,$00,$18,$18,$00,$00,$78,$18,$18,$18,$18,$18,$18,$18,$18,$18,$F0,
+
+ 10, // $6B 'k'
+ $00,$00,$00,$00,$00,$00,$60,$00,$60,$00,$60,$00,$60,$00,$61,$80,$63,$00,$66,$00,$6C,$00,$7E,$00,$73,$00,$61,$80,$60,$C0,$00,$00,$00,$00,$00,$00,
+
+ 4, // $6C 'l'
+ $00,$00,$00,$60,$60,$60,$60,$60,$60,$60,$60,$60,$60,$60,$60,$00,$00,$00,
+
+ 16, // $6D 'm'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$6F,$3C,$71,$C6,$61,$86,$61,$86,$61,$86,$61,$86,$61,$86,$61,$86,$00,$00,$00,$00,$00,$00,
+
+ 10, // $6E 'n'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$6F,$00,$71,$80,$61,$80,$61,$80,$61,$80,$61,$80,$61,$80,$61,$80,$00,$00,$00,$00,$00,$00,
+
+ 10, // $6F 'o'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$1E,$00,$33,$00,$61,$80,$61,$80,$61,$80,$61,$80,$33,$00,$1E,$00,$00,$00,$00,$00,$00,$00,
+
+ 10, // $70 'p'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$6E,$00,$73,$00,$61,$80,$61,$80,$61,$80,$61,$80,$63,$00,$7E,$00,$60,$00,$60,$00,$60,$00,
+
+ 10, // $71 'q'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$1F,$80,$31,$80,$61,$80,$61,$80,$61,$80,$61,$80,$33,$80,$1D,$80,$01,$80,$01,$80,$01,$80,
+
+ 7, // $72 'r'
+ $00,$00,$00,$00,$00,$00,$00,$6E,$7E,$60,$60,$60,$60,$60,$60,$00,$00,$00,
+
+ 9, // $73 's'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3E,$00,$61,$00,$60,$00,$7E,$00,$3F,$00,$03,$00,$43,$00,$3E,$00,$00,$00,$00,$00,$00,$00,
+
+ 7, // $74 't'
+ $00,$00,$00,$00,$00,$30,$30,$7E,$30,$30,$30,$30,$30,$30,$1E,$00,$00,$00,
+
+ 10, // $75 'u'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$61,$80,$61,$80,$61,$80,$61,$80,$61,$80,$61,$80,$63,$80,$3D,$80,$00,$00,$00,$00,$00,$00,
+
+ 10, // $76 'v'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$61,$80,$61,$80,$33,$00,$33,$00,$33,$00,$1E,$00,$1E,$00,$0C,$00,$00,$00,$00,$00,$00,$00,
+
+ 14, // $77 'w'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$63,$18,$63,$18,$63,$18,$37,$B0,$34,$B0,$3C,$F0,$18,$60,$18,$60,$00,$00,$00,$00,$00,$00,
+
+ 10, // $78 'x'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$61,$80,$33,$00,$33,$00,$1E,$00,$1E,$00,$33,$00,$33,$00,$61,$80,$00,$00,$00,$00,$00,$00,
+
+ 10, // $79 'y'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$61,$80,$61,$80,$33,$00,$33,$00,$33,$00,$1E,$00,$1E,$00,$0C,$00,$0C,$00,$18,$00,$18,$00,
+
+ 9, // $7A 'z'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$7F,$00,$03,$00,$06,$00,$0C,$00,$18,$00,$30,$00,$60,$00,$7F,$00,$00,$00,$00,$00,$00,$00,
+
+ 11, // $7B '{'
+ $00,$00,$00,$00,$00,$00,$07,$80,$0C,$00,$0C,$00,$0C,$00,$0C,$00,$0C,$00,$18,$00,$70,$00,$18,$00,$0C,$00,$0C,$00,$0C,$00,$0C,$00,$0C,$00,$07,$80,
+
+ 8, // $7C '|'
+ $00,$00,$00,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,
+
+ 11, // $7D '}'
+ $00,$00,$00,$00,$00,$00,$3C,$00,$06,$00,$06,$00,$06,$00,$06,$00,$06,$00,$03,$00,$01,$C0,$03,$00,$06,$00,$06,$00,$06,$00,$06,$00,$06,$00,$3C,$00,
+
+ 13, // $7E '~'
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$18,$10,$24,$10,$42,$10,$41,$20,$40,$C0,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+
+ 15, // $7F ''
+ $00,$00,$00,$00,$00,$00,$00,$00,$3F,$F8,$20,$08,$20,$08,$20,$08,$20,$08,$20,$08,$20,$08,$20,$08,$20,$08,$20,$08,$3F,$F8,$00,$00,$00,$00,$00,$00,
+
+ 0 );
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+
+END.
+
diff --git a/src/corelib/render/software/agg_font_cache_manager.pas b/src/corelib/render/software/agg_font_cache_manager.pas
new file mode 100644
index 00000000..4e12ef1e
--- /dev/null
+++ b/src/corelib/render/software/agg_font_cache_manager.pas
@@ -0,0 +1,612 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 16.02.2006-Milano: Unit port establishment
+//
+{ agg_font_cache_manager.pas }
+unit
+ agg_font_cache_manager ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ SysUtils ,
+ agg_basics ,
+ agg_array ,
+ agg_font_engine ,
+ agg_path_storage_integer ;
+
+{ TYPES DEFINITION }
+const
+ glyph_data_invalid = 0;
+ glyph_data_mono = 1;
+ glyph_data_gray8 = 2;
+ glyph_data_outline = 3;
+
+ block_size = 16384 - 16;
+
+type
+ glyph_cache_ptr_ptr = ^glyph_cache_ptr;
+ glyph_cache_ptr = ^glyph_cache;
+ glyph_cache = record
+ glyph_index : unsigned;
+
+ data : int8u_ptr;
+
+ data_size ,
+ data_type : unsigned;//: int8u;
+
+ bounds : rect;
+
+ advance_x ,
+ advance_y : double;
+
+ end;
+
+ font_cache_ptr_ptr = ^font_cache_ptr;
+ font_cache_ptr = ^font_cache;
+ font_cache = object
+ m_allocator : pod_allocator;
+ m_glyphs : array[0..256] of glyph_cache_ptr_ptr;
+ m_font_signature : PChar;
+
+ constructor Construct(font_signature : PChar );
+ destructor Destruct;
+
+ function font_is(font_signature : PChar ) : boolean;
+
+ function find_glyph(glyph_code : unsigned ) : glyph_cache_ptr;
+
+ function cache_glyph(
+ glyph_code ,
+ glyph_index ,
+ data_size : unsigned;
+ data_type : int8u;
+ bounds : rect_ptr;
+ advance_x ,
+ advance_y : double ) : glyph_cache_ptr;
+
+ end;
+
+ font_cache_pool = object
+ m_fonts : font_cache_ptr_ptr;
+ m_max_fonts ,
+ m_num_fonts : unsigned;
+ m_cur_font : font_cache_ptr;
+
+ constructor Construct(max_fonts : unsigned = 32 );
+ destructor Destruct;
+
+ procedure font_(font_signature : PChar; reset_cache : boolean = false );
+ function _font : font_cache_ptr;
+
+ function find_glyph(glyph_code : unsigned ) : glyph_cache_ptr;
+
+ function cache_glyph(
+ glyph_code ,
+ glyph_index ,
+ data_size : unsigned;
+ data_type : int8u;
+ bounds : rect_ptr;
+ advance_x ,
+ advance_y : double ) : glyph_cache_ptr;
+
+ function find_font(font_signature : PChar ) : int;
+
+ end;
+
+ glyph_rendering = (
+ glyph_ren_native_mono ,
+ glyph_ren_native_gray8 ,
+ glyph_ren_outline ,
+ glyph_ren_agg_mono ,
+ glyph_ren_agg_gray8 );
+
+ font_cache_manager_ptr = ^font_cache_manager;
+ font_cache_manager = object
+ m_fonts : font_cache_pool;
+ m_engine : font_engine_ptr;
+
+ m_change_stamp : int;
+
+ m_dx ,
+ m_dy : double;
+
+ m_prev_glyph ,
+ m_last_glyph : glyph_cache_ptr;
+
+ m_path_adaptor : path_adaptor_type_ptr;
+ m_gray8_adaptor : gray8_adaptor_type;
+ m_gray8_scanline : gray8_scanline_type;
+ m_mono_adaptor : mono_adaptor_type;
+ m_mono_scanline : mono_scanline_type;
+
+ constructor Construct(engine : font_engine_ptr; max_fonts : unsigned = 32 );
+ destructor Destruct;
+
+ function glyph(glyph_code : unsigned ) : glyph_cache_ptr;
+
+ procedure init_embedded_adaptors(gl : glyph_cache_ptr; x ,y : double; scale : double = 1.0 );
+
+ function path_adaptor : path_adaptor_type_ptr;
+ function gray8_adaptor : gray8_adaptor_type_ptr;
+ function gray8_scanline : gray8_scanline_type_ptr;
+ function mono_adaptor : mono_adaptor_type_ptr;
+ function mono_scanline : mono_scanline_type_ptr;
+
+ function prev_glyph : glyph_cache_ptr;
+ function last_glyph : glyph_cache_ptr;
+
+ function add_kerning(x ,y : double_ptr ) : boolean;
+
+ procedure precache(from ,to_ : unsigned );
+ procedure reset_cache;
+ procedure synchronize;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor font_cache.Construct;
+begin
+ m_allocator.Construct(block_size );
+
+ m_font_signature:=PChar(m_allocator.allocate(StrLen(font_signature ) + 1 ) );
+
+ StrCopy (m_font_signature ,font_signature );
+ fillchar(m_glyphs ,sizeof(m_glyphs ) ,0 );
+
+end;
+
+{ DESTRUCT }
+destructor font_cache.Destruct;
+begin
+ m_allocator.Destruct;
+
+end;
+
+{ FONT_IS }
+function font_cache.font_is;
+begin
+ result:=StrComp(font_signature ,m_font_signature ) = 0;
+
+end;
+
+{ FIND_GLYPH }
+function font_cache.find_glyph;
+var
+ msb : unsigned;
+
+begin
+ msb:=(glyph_code shr 8 ) and $FF;
+
+ if m_glyphs[msb ] <> NIL then
+ result:=
+ glyph_cache_ptr_ptr(
+ ptrcomp(m_glyphs[msb ] ) + (glyph_code and $FF ) * sizeof(glyph_cache_ptr ) )^
+ else
+ result:=NIL;
+
+end;
+
+{ CACHE_GLYPH }
+function font_cache.cache_glyph;
+var
+ msb ,lsb : unsigned;
+
+ glyph : glyph_cache_ptr;
+
+begin
+ msb:=(glyph_code shr 8 ) and $FF;
+
+ if m_glyphs[msb ] = NIL then
+ begin
+ m_glyphs[msb ]:=glyph_cache_ptr_ptr(
+ m_allocator.allocate(sizeof(glyph_cache_ptr ) * 256 ,sizeof(glyph_cache_ptr ) ) );
+
+ fillchar(m_glyphs[msb ]^ ,sizeof(glyph_cache_ptr ) * 256 ,0 );
+
+ end;
+
+ lsb:=glyph_code and $FF;
+
+ if glyph_cache_ptr_ptr(ptrcomp(m_glyphs[msb ] ) + lsb * sizeof(glyph_cache_ptr ) )^ <> NIL then
+ begin
+ result:=NIL; // Already exists, do not overwrite
+
+ exit;
+
+ end;
+
+ glyph:=glyph_cache_ptr(m_allocator.allocate(sizeof(glyph_cache ) ,sizeof(double ) ) );
+
+ glyph.glyph_index:=glyph_index;
+ glyph.data :=m_allocator.allocate(data_size );
+ glyph.data_size :=data_size;
+ glyph.data_type :=data_type;
+ glyph.bounds :=bounds^;
+ glyph.advance_x :=advance_x;
+ glyph.advance_y :=advance_y;
+
+ glyph_cache_ptr_ptr(ptrcomp(m_glyphs[msb ] ) + lsb * sizeof(glyph_cache_ptr ) )^:=glyph;
+
+ result:=glyph;
+
+end;
+
+{ CONSTRUCT }
+constructor font_cache_pool.Construct;
+begin
+ agg_getmem(pointer(m_fonts ) ,max_fonts * sizeof(font_cache_ptr ) );
+
+ m_max_fonts:=max_fonts;
+ m_num_fonts:=0;
+ m_cur_font :=NIL;
+
+end;
+
+{ DESTRUCT }
+destructor font_cache_pool.Destruct;
+var
+ i : unsigned;
+
+ fnt : font_cache_ptr_ptr;
+
+begin
+ fnt:=m_fonts;
+ i :=0;
+
+ while i < m_num_fonts do
+ begin
+ dispose(fnt^ ,Destruct );
+
+ inc(ptrcomp(fnt ) ,sizeof(font_cache_ptr ) );
+ inc(i );
+
+ end;
+
+ agg_freemem(pointer(m_fonts ) ,m_max_fonts * sizeof(font_cache_ptr ) );
+
+end;
+
+{ FONT_ }
+procedure font_cache_pool.font_;
+var
+ idx : int;
+ fnt : font_cache_ptr_ptr;
+
+begin
+ idx:=find_font(font_signature );
+
+ if idx >= 0 then
+ begin
+ fnt:=font_cache_ptr_ptr(ptrcomp(m_fonts ) + idx * sizeof(font_cache_ptr ) );
+
+ if reset_cache then
+ begin
+ dispose(fnt^ ,Destruct );
+
+ fnt^:=new(font_cache_ptr ,Construct(font_signature ) );
+
+ end;
+
+ m_cur_font:=fnt^;
+
+ end
+ else
+ begin
+ if m_num_fonts >= m_max_fonts then
+ begin
+ fnt:=font_cache_ptr_ptr(ptrcomp(m_fonts ) + 1 * sizeof(font_cache_ptr ) );
+
+ dispose(m_fonts^ ,Destruct );
+ move (fnt^ ,m_fonts^ ,(m_max_fonts - 1 ) * sizeof(font_cache_ptr ) );
+
+ m_num_fonts:=m_max_fonts - 1;
+
+ end;
+
+ fnt :=font_cache_ptr_ptr(ptrcomp(m_fonts ) + m_num_fonts * sizeof(font_cache_ptr ) );
+ fnt^:=new(font_cache_ptr ,Construct(font_signature ) );
+
+ m_cur_font:=fnt^;
+
+ inc(m_num_fonts );
+
+ end;
+
+end;
+
+{ _FONT }
+function font_cache_pool._font;
+begin
+ result:=m_cur_font;
+
+end;
+
+{ FIND_GLYPH }
+function font_cache_pool.find_glyph;
+begin
+ if m_cur_font <> NIL then
+ result:=m_cur_font.find_glyph(glyph_code )
+ else
+ result:=NIL;
+
+end;
+
+{ CACHE_GLYPH }
+function font_cache_pool.cache_glyph;
+begin
+ if m_cur_font <> NIL then
+ result:=
+ m_cur_font.cache_glyph(
+ glyph_code ,
+ glyph_index ,
+ data_size ,
+ data_type ,
+ bounds ,
+ advance_x ,
+ advance_y )
+ else
+ result:=NIL;
+
+end;
+
+{ FIND_FONT }
+function font_cache_pool.find_font;
+var
+ i : unsigned;
+ f : font_cache_ptr_ptr;
+
+begin
+ i:=0;
+ f:=m_fonts;
+
+ while i < m_num_fonts do
+ begin
+ if f^.font_is(font_signature ) then
+ begin
+ result:=i;
+
+ exit;
+
+ end;
+
+ inc(ptrcomp(f ) ,sizeof(font_cache_ptr ) );
+ inc(i );
+
+ end;
+
+ result:=-1;
+
+end;
+
+{ CONSTRUCT }
+constructor font_cache_manager.Construct;
+begin
+ m_fonts.Construct(max_fonts );
+
+ m_engine:=engine;
+
+ m_change_stamp:=-1;
+
+ m_prev_glyph:=NIL;
+ m_last_glyph:=NIL;
+
+ if m_engine.flag32 then
+ m_path_adaptor:=new(serialized_int32_path_adaptor_ptr ,Construct )
+ else
+ m_path_adaptor:=new(serialized_int16_path_adaptor_ptr ,Construct );
+
+ m_gray8_adaptor.Construct;
+ m_gray8_scanline.Construct(m_gray8_adaptor.m_sz );
+ m_mono_adaptor.Construct;
+ m_mono_scanline.Construct;
+
+end;
+
+{ DESTRUCT }
+destructor font_cache_manager.Destruct;
+begin
+ m_fonts.Destruct;
+
+ dispose(m_path_adaptor ,Destruct );
+
+end;
+
+{ GLYPH }
+function font_cache_manager.glyph;
+var
+ gl : glyph_cache_ptr;
+
+begin
+ synchronize;
+
+ gl:=m_fonts.find_glyph(glyph_code );
+
+ if gl <> NIL then
+ begin
+ m_prev_glyph:=m_last_glyph;
+ m_last_glyph:=gl;
+
+ result:=gl;
+
+ exit;
+
+ end
+ else
+ if m_engine.prepare_glyph(glyph_code ) then
+ begin
+ m_prev_glyph:=m_last_glyph;
+ m_last_glyph:=
+ m_fonts.cache_glyph(
+ glyph_code ,
+ m_engine.glyph_index ,
+ m_engine.data_size ,
+ m_engine.data_type ,
+ m_engine.bounds ,
+ m_engine.advance_x ,
+ m_engine.advance_y );
+
+ m_engine.write_glyph_to(m_last_glyph.data );
+
+ result:=m_last_glyph;
+
+ exit;
+
+ end;
+
+ result:=NIL;
+
+end;
+
+{ INIT_EMBEDDED_ADAPTORS }
+procedure font_cache_manager.init_embedded_adaptors;
+begin
+ if gl <> NIL then
+ case gl.data_type of
+ glyph_data_mono :
+ m_mono_adaptor.init(gl.data ,gl.data_size ,x ,y );
+
+ glyph_data_gray8 :
+ m_gray8_adaptor.init(gl.data ,gl.data_size ,x ,y );
+
+ glyph_data_outline :
+ m_path_adaptor.init(gl.data ,gl.data_size ,x ,y ,scale );
+
+ end;
+
+end;
+
+{ PATH_ADAPTOR }
+function font_cache_manager.path_adaptor;
+begin
+ result:=m_path_adaptor;
+
+end;
+
+{ GRAY8_ADAPTOR }
+function font_cache_manager.gray8_adaptor;
+begin
+ result:=@m_gray8_adaptor;
+
+end;
+
+{ GRAY8_SCANLINE }
+function font_cache_manager.gray8_scanline;
+begin
+ result:=@m_gray8_scanline;
+
+end;
+
+{ MONO_ADAPTOR }
+function font_cache_manager.mono_adaptor;
+begin
+ result:=@m_mono_adaptor;
+
+end;
+
+{ MONO_SCANLINE }
+function font_cache_manager.mono_scanline;
+begin
+ result:=@m_mono_scanline;
+
+end;
+
+{ PREV_GLYPH }
+function font_cache_manager.prev_glyph;
+begin
+ result:=m_prev_glyph;
+
+end;
+
+{ LAST_GLYPH }
+function font_cache_manager.last_glyph;
+begin
+ result:=@m_last_glyph;
+
+end;
+
+{ ADD_KERNING }
+function font_cache_manager.add_kerning;
+begin
+ if (m_prev_glyph <> NIL ) and
+ (m_last_glyph <> NIL ) then
+ result:=
+ m_engine.add_kerning(
+ m_prev_glyph.glyph_index ,
+ m_last_glyph.glyph_index ,x ,y )
+ else
+ result:=false;
+
+end;
+
+{ PRECACHE }
+procedure font_cache_manager.precache;
+begin
+ while from <= to_ do
+ begin
+ glyph(from );
+ inc (from );
+
+ end;
+
+end;
+
+{ RESET_CACHE }
+procedure font_cache_manager.reset_cache;
+begin
+ m_fonts.font_(m_engine.font_signature ,true );
+
+ m_change_stamp:=m_engine.change_stamp;
+
+ m_prev_glyph:=NIL;
+ m_last_glyph:=NIL;
+
+end;
+
+{ SYNCHRONIZE }
+procedure font_cache_manager.synchronize;
+begin
+ if m_change_stamp <> m_engine.change_stamp then
+ begin
+ m_fonts.font_(m_engine.font_signature );
+
+ m_change_stamp:=m_engine.change_stamp;
+
+ m_prev_glyph:=NIL;
+ m_last_glyph:=NIL;
+
+ end;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_font_engine.pas b/src/corelib/render/software/agg_font_engine.pas
new file mode 100644
index 00000000..4591d077
--- /dev/null
+++ b/src/corelib/render/software/agg_font_engine.pas
@@ -0,0 +1,94 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 16.02.2006-Milano: Unit port establishment
+//
+{ agg_font_engine.pas }
+unit
+ agg_font_engine ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_scanline_storage_aa ,
+ agg_scanline_storage_bin ,
+ agg_path_storage_integer ;
+
+{ TYPES DEFINITION }
+type
+ gray8_adaptor_type_ptr = ^gray8_adaptor_type;
+ gray8_adaptor_type = serialized_scanlines_adaptor_aa8;
+
+ gray8_scanline_type_ptr = ^gray8_scanline_type;
+ gray8_scanline_type = embedded_scanline_sa;
+
+ mono_adaptor_type_ptr = ^mono_adaptor_type;
+ mono_adaptor_type = serialized_scanlines_adaptor_bin;
+
+ mono_scanline_type_ptr = ^mono_scanline_type;
+ mono_scanline_type = embedded_scanline_a;
+
+ scanlines_aa_type_ptr = ^scanlines_aa_type;
+ scanlines_aa_type = scanline_storage_aa8;
+
+ scanlines_bin_type_ptr = ^scanlines_bin_type;
+ scanlines_bin_type = scanline_storage_bin;
+
+ path_adaptor_type_ptr = ^path_adaptor_type;
+ path_adaptor_type = serialized_integer_path_adaptor;
+
+ font_engine_ptr = ^font_engine;
+ font_engine = object
+ // Interface mandatory to implement for font_cache_manager
+ function font_signature : PChar; virtual; abstract;
+ function change_stamp : int; virtual; abstract;
+
+ function prepare_glyph(glyph_code : unsigned ) : boolean; virtual; abstract;
+
+ function glyph_index : unsigned; virtual; abstract;
+ function data_size : unsigned; virtual; abstract;
+ function data_type : unsigned; virtual; abstract;
+ function bounds : rect_ptr; virtual; abstract;
+ function advance_x : double; virtual; abstract;
+ function advance_y : double; virtual; abstract;
+
+ procedure write_glyph_to(data : int8u_ptr ); virtual; abstract;
+ function add_kerning (first ,second : unsigned; x ,y : double_ptr ) : boolean; virtual; abstract;
+
+ function flag32 : boolean; virtual; abstract;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+
+
+
+END.
+
diff --git a/src/corelib/render/software/agg_font_freetype.pas b/src/corelib/render/software/agg_font_freetype.pas
new file mode 100644
index 00000000..25a21892
--- /dev/null
+++ b/src/corelib/render/software/agg_font_freetype.pas
@@ -0,0 +1,1731 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2007
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 17.09.2007-Milano: Porting & Finished OK
+// 16.09.2007-Milano: Unit port establishment
+//
+{ agg_font_freetype.pas }
+unit
+ agg_font_freetype ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ SysUtils ,Math ,
+ agg_font_freetype_lib ,
+ agg_basics ,
+ agg_font_engine ,
+ agg_font_cache_manager ,
+ agg_trans_affine ,
+ agg_vertex_source ,
+ agg_path_storage_integer ,
+ agg_conv_curve ,
+ agg_scanline ,
+ agg_scanline_u ,
+ agg_scanline_bin ,
+ agg_rasterizer_scanline_aa ,
+ agg_renderer_scanline ,
+ agg_render_scanlines ,
+ agg_bitset_iterator ;
+
+{ GLOBAL VARIABLES & CONSTANTS }
+{ TYPES DEFINITION }
+type
+ face_name_ptr = ^face_name;
+ face_name = record
+ name : char_ptr; //PChar;
+ size : unsigned;
+
+ end;
+
+//-----------------------------------------------font_engine_freetype_base
+ font_engine_freetype_base = object(font_engine )
+ m_flag32 : boolean;
+
+ m_change_stamp ,
+ m_last_error : int;
+
+ m_name : PChar;
+ m_name_len ,
+ m_face_index : unsigned;
+ m_char_map : FT_Encoding;
+ m_signature : face_name;
+
+ m_height ,
+ m_width : unsigned;
+
+ m_hinting ,
+ m_flip_y ,
+ m_library_initialized : boolean;
+
+ m_library : FT_Library_ptr; // handle to library
+ m_faces : FT_Face_ptr_ptr; // A pool of font faces
+
+ m_face_names : face_name_ptr;
+ m_num_faces ,
+ m_max_faces : unsigned;
+ m_cur_face : FT_Face_ptr; // handle to the current face object
+ m_resolution : int;
+
+ m_glyph_rendering : glyph_rendering;
+ m_glyph_index ,
+ m_data_size ,
+ m_data_type : unsigned;
+
+ m_bounds : agg_basics.rect;
+ m_advance_x ,
+ m_advance_y : double;
+ m_affine : trans_affine;
+
+ m_path16 : path_storage_int16;
+ m_path32 : path_storage_int32;
+ m_curves16 ,
+ m_curves32 : conv_curve;
+
+ m_scanline_aa : scanline_u8;
+ m_scanline_bin : scanline_bin;
+ m_scanlines_aa : scanlines_aa_type;
+ m_scanlines_bin : scanlines_bin_type;
+ m_rasterizer : rasterizer_scanline_aa;
+
+ constructor Construct(flag32_ : boolean; max_faces : unsigned = 32 );
+ destructor Destruct;
+
+ // Set font parameters
+ procedure resolution_(dpi : unsigned );
+
+ function load_font(
+ font_name : PChar; face_index : unsigned; ren_type : glyph_rendering;
+ font_mem : PChar = NIL; font_mem_size : int = 0 ) : boolean;
+
+ function attach(file_name : PChar ) : boolean;
+
+ function char_map_ (map : FT_Encoding ) : boolean;
+ function height_ (h : double ) : boolean;
+ function width_ (w : double ) : boolean;
+ procedure hinting_ (h : boolean );
+ procedure flip_y_ (flip : boolean );
+ procedure transform_(affine : trans_affine_ptr );
+
+ // Set Gamma
+ procedure gamma_(f : vertex_source_ptr );
+
+ // Accessors
+ function _last_error : int;
+ function _resolution : unsigned;
+ function _name : PChar;
+ function _num_faces : unsigned;
+ function _char_map : FT_Encoding;
+ function _height : double;
+ function _width : double;
+ function _ascender : double;
+ function _descender : double;
+ function _hinting : boolean;
+ function _flip_y : boolean;
+
+ // Interface mandatory to implement for font_cache_manager
+ function font_signature : PChar; virtual;
+ function change_stamp : int; virtual;
+
+ function prepare_glyph(glyph_code : unsigned ) : boolean; virtual;
+
+ function glyph_index : unsigned; virtual;
+ function data_size : unsigned; virtual;
+ function data_type : unsigned; virtual;
+ function bounds : rect_ptr; virtual;
+ function advance_x : double; virtual;
+ function advance_y : double; virtual;
+
+ procedure write_glyph_to(data : int8u_ptr ); virtual;
+ function add_kerning (first ,second : unsigned; x ,y : double_ptr ) : boolean; virtual;
+
+ function flag32 : boolean; virtual;
+
+ // private
+ procedure update_char_size;
+ procedure update_signature;
+
+ function find_face(name : PChar ) : int;
+
+ end;
+
+//------------------------------------------------font_engine_freetype_int16
+// This class uses values of type int16 (10.6 format) for the vector cache.
+// The vector cache is compact, but when rendering glyphs of height
+// more that 200 there integer overflow can occur.
+ font_engine_freetype_int16 = object(font_engine_freetype_base )
+ constructor Construct(max_faces : unsigned = 32 );
+
+ end;
+
+//------------------------------------------------font_engine_freetype_int32
+// This class uses values of type int32 (26.6 format) for the vector cache.
+// The vector cache is twice larger than in font_engine_freetype_int16,
+// but it allows you to render glyphs of very large sizes.
+ font_engine_freetype_int32 = object(font_engine_freetype_base )
+ constructor Construct(max_faces : unsigned = 32 );
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+//------------------------------------------------------------------------------
+//
+// This code implements the AUTODIN II polynomial
+// The variable corresponding to the macro argument "crc" should
+// be an unsigned long.
+// Oroginal code by Spencer Garrett <srg@quick.com>
+//
+// generated using the AUTODIN II polynomial
+// x^32 + x^26 + x^23 + x^22 + x^16 +
+// x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + 1
+//
+//------------------------------------------------------------------------------
+const
+ crc32tab : array[0..255 ] of unsigned = (
+ $00000000, $77073096, $ee0e612c, $990951ba,
+ $076dc419, $706af48f, $e963a535, $9e6495a3,
+ $0edb8832, $79dcb8a4, $e0d5e91e, $97d2d988,
+ $09b64c2b, $7eb17cbd, $e7b82d07, $90bf1d91,
+ $1db71064, $6ab020f2, $f3b97148, $84be41de,
+ $1adad47d, $6ddde4eb, $f4d4b551, $83d385c7,
+ $136c9856, $646ba8c0, $fd62f97a, $8a65c9ec,
+ $14015c4f, $63066cd9, $fa0f3d63, $8d080df5,
+ $3b6e20c8, $4c69105e, $d56041e4, $a2677172,
+ $3c03e4d1, $4b04d447, $d20d85fd, $a50ab56b,
+ $35b5a8fa, $42b2986c, $dbbbc9d6, $acbcf940,
+ $32d86ce3, $45df5c75, $dcd60dcf, $abd13d59,
+ $26d930ac, $51de003a, $c8d75180, $bfd06116,
+ $21b4f4b5, $56b3c423, $cfba9599, $b8bda50f,
+ $2802b89e, $5f058808, $c60cd9b2, $b10be924,
+ $2f6f7c87, $58684c11, $c1611dab, $b6662d3d,
+ $76dc4190, $01db7106, $98d220bc, $efd5102a,
+ $71b18589, $06b6b51f, $9fbfe4a5, $e8b8d433,
+ $7807c9a2, $0f00f934, $9609a88e, $e10e9818,
+ $7f6a0dbb, $086d3d2d, $91646c97, $e6635c01,
+ $6b6b51f4, $1c6c6162, $856530d8, $f262004e,
+ $6c0695ed, $1b01a57b, $8208f4c1, $f50fc457,
+ $65b0d9c6, $12b7e950, $8bbeb8ea, $fcb9887c,
+ $62dd1ddf, $15da2d49, $8cd37cf3, $fbd44c65,
+ $4db26158, $3ab551ce, $a3bc0074, $d4bb30e2,
+ $4adfa541, $3dd895d7, $a4d1c46d, $d3d6f4fb,
+ $4369e96a, $346ed9fc, $ad678846, $da60b8d0,
+ $44042d73, $33031de5, $aa0a4c5f, $dd0d7cc9,
+ $5005713c, $270241aa, $be0b1010, $c90c2086,
+ $5768b525, $206f85b3, $b966d409, $ce61e49f,
+ $5edef90e, $29d9c998, $b0d09822, $c7d7a8b4,
+ $59b33d17, $2eb40d81, $b7bd5c3b, $c0ba6cad,
+ $edb88320, $9abfb3b6, $03b6e20c, $74b1d29a,
+ $ead54739, $9dd277af, $04db2615, $73dc1683,
+ $e3630b12, $94643b84, $0d6d6a3e, $7a6a5aa8,
+ $e40ecf0b, $9309ff9d, $0a00ae27, $7d079eb1,
+ $f00f9344, $8708a3d2, $1e01f268, $6906c2fe,
+ $f762575d, $806567cb, $196c3671, $6e6b06e7,
+ $fed41b76, $89d32be0, $10da7a5a, $67dd4acc,
+ $f9b9df6f, $8ebeeff9, $17b7be43, $60b08ed5,
+ $d6d6a3e8, $a1d1937e, $38d8c2c4, $4fdff252,
+ $d1bb67f1, $a6bc5767, $3fb506dd, $48b2364b,
+ $d80d2bda, $af0a1b4c, $36034af6, $41047a60,
+ $df60efc3, $a867df55, $316e8eef, $4669be79,
+ $cb61b38c, $bc66831a, $256fd2a0, $5268e236,
+ $cc0c7795, $bb0b4703, $220216b9, $5505262f,
+ $c5ba3bbe, $b2bd0b28, $2bb45a92, $5cb36a04,
+ $c2d7ffa7, $b5d0cf31, $2cd99e8b, $5bdeae1d,
+ $9b64c2b0, $ec63f226, $756aa39c, $026d930a,
+ $9c0906a9, $eb0e363f, $72076785, $05005713,
+ $95bf4a82, $e2b87a14, $7bb12bae, $0cb61b38,
+ $92d28e9b, $e5d5be0d, $7cdcefb7, $0bdbdf21,
+ $86d3d2d4, $f1d4e242, $68ddb3f8, $1fda836e,
+ $81be16cd, $f6b9265b, $6fb077e1, $18b74777,
+ $88085ae6, $ff0f6a70, $66063bca, $11010b5c,
+ $8f659eff, $f862ae69, $616bffd3, $166ccf45,
+ $a00ae278, $d70dd2ee, $4e048354, $3903b3c2,
+ $a7672661, $d06016f7, $4969474d, $3e6e77db,
+ $aed16a4a, $d9d65adc, $40df0b66, $37d83bf0,
+ $a9bcae53, $debb9ec5, $47b2cf7f, $30b5ffe9,
+ $bdbdf21c, $cabac28a, $53b39330, $24b4a3a6,
+ $bad03605, $cdd70693, $54de5729, $23d967bf,
+ $b3667a2e, $c4614ab8, $5d681b02, $2a6f2b94,
+ $b40bbe37, $c30c8ea1, $5a05df1b, $2d02ef8d );
+
+{ UNIT IMPLEMENTATION }
+{ calc_crc32 }
+function calc_crc32(buf : int8u_ptr; size : unsigned ) : unsigned;
+var
+ crc ,len ,nr : unsigned;
+
+ p : int8u_ptr;
+
+begin
+ crc:=unsigned(not 0 );
+ len:=0;
+ nr :=size;
+ len:=len + nr;
+ p :=buf;
+
+ while nr <> 0 do
+ begin
+ dec(nr );
+
+ crc:=(crc shr 8 ) xor crc32tab[(crc xor p^ ) and $ff ];
+
+ inc(ptrcomp(p ) ,sizeof(int8u ) );
+
+ end;
+
+ result:=not crc;
+
+end;
+
+{ dbl_to_plain_fx }
+function dbl_to_plain_fx(d : double ) : int;
+begin
+ result:=Trunc(d * 65536.0 )
+
+end;
+
+{ int26p6_to_dbl }
+function int26p6_to_dbl(p : int ) : double;
+begin
+ result:=p / 64.0;
+
+end;
+
+{ dbl_to_int26p6 }
+function dbl_to_int26p6(p : double ) : int;
+begin
+ result:=Trunc(p * 64.0 + 0.5 );
+
+end;
+
+{ decompose_ft_outline }
+function decompose_ft_outline(
+ outline : FT_Outline_ptr;
+ flip_y : boolean;
+ mtx : trans_affine_ptr;
+ path : path_storage_integer_ptr ) : boolean;
+var
+ v_last ,v_control ,v_start ,vec ,v_middle ,vec1 ,vec2 : FT_Vector;
+
+ x1 ,y1 ,x2 ,y2 ,x3 ,y3 : double;
+
+ point ,limit : FT_Vector_ptr;
+
+ tags : char_ptr;
+
+ n , // index of contour in outline
+ first , // index of first point in contour
+ last : int; // index of last point in contour
+
+ tag : char; // current point's state
+
+label
+ Do_Conic ,Close ;
+
+begin
+ first:=0;
+ n :=0;
+
+ while n < outline.n_contours do
+ begin
+ last :=FT_Short_ptr(ptrcomp(outline.contours ) + n * sizeof(FT_Short ) )^;
+ limit:=FT_Vector_ptr(ptrcomp(outline.points ) + last * sizeof(FT_Vector ) );
+
+ v_start:=FT_Vector_ptr(ptrcomp(outline.points ) + first * sizeof(FT_Vector) )^;
+ v_last :=FT_Vector_ptr(ptrcomp(outline.points ) + last * sizeof(FT_Vector) )^;
+
+ v_control:=v_start;
+
+ point:=FT_Vector_ptr(ptrcomp(outline.points ) + first * sizeof(FT_Vector ) );
+ tags :=char_ptr (ptrcomp(outline.tags ) + first * sizeof(char ) );
+ tag :=FT_CURVE_TAG (tags^ );
+
+ // A contour cannot start with a cubic control point!
+ if tag = char(FT_CURVE_TAG_CUBIC ) then
+ begin
+ result:=false;
+
+ exit;
+
+ end;
+
+ // check first point to determine origin
+ if tag = char(FT_CURVE_TAG_CONIC ) then
+ begin
+ // first point is conic control. Yes, this happens.
+ if FT_CURVE_TAG(char_ptr(ptrcomp(outline.tags ) + last )^ ) = char(FT_CURVE_TAG_ON ) then
+ begin
+ // start at last point if it is on the curve
+ v_start:=v_last;
+
+ dec(limit );
+
+ end
+ else
+ begin
+ // if both first and last points are conic,
+ // start at their middle and record its position
+ // for closure
+ v_start.x:=(v_start.x + v_last.x ) div 2;
+ v_start.y:=(v_start.y + v_last.y ) div 2;
+
+ v_last:=v_start;
+
+ end;
+
+ dec(ptrcomp(point ) ,sizeof(FT_Vector ) );
+ dec(ptrcomp(tags ) );
+
+ end;
+
+ x1:=int26p6_to_dbl(v_start.x );
+ y1:=int26p6_to_dbl(v_start.y );
+
+ if flip_y then
+ y1:=-y1;
+
+ mtx.transform(mtx ,@x1 ,@y1 );
+ path.move_to (dbl_to_int26p6(x1 ) ,dbl_to_int26p6(y1 ) );
+
+ while ptrcomp(point ) < ptrcomp(limit ) do
+ begin
+ inc(ptrcomp(point ) ,sizeof(FT_Vector ) );
+ inc(ptrcomp(tags ) );
+
+ tag:=FT_CURVE_TAG(tags^ );
+
+ case tag of
+ // emit a single line_to
+ char(FT_CURVE_TAG_ON ) :
+ begin
+ x1:=int26p6_to_dbl(point.x );
+ y1:=int26p6_to_dbl(point.y );
+
+ if flip_y then
+ y1:=-y1;
+
+ mtx.transform(mtx ,@x1 ,@y1 );
+ path.line_to (dbl_to_int26p6(x1 ) ,dbl_to_int26p6(y1 ) );
+
+ continue;
+
+ end;
+
+ // consume conic arcs
+ char(FT_CURVE_TAG_CONIC ) :
+ begin
+ v_control.x:=point.x;
+ v_control.y:=point.y;
+
+ Do_Conic:
+ if ptrcomp(point ) < ptrcomp(limit ) then
+ begin
+ inc(ptrcomp(point ) ,sizeof(FT_Vector ) );
+ inc(ptrcomp(tags ) );
+
+ tag:=FT_CURVE_TAG(tags^ );
+
+ vec.x:=point.x;
+ vec.y:=point.y;
+
+ if tag = char(FT_CURVE_TAG_ON ) then
+ begin
+ x1:=int26p6_to_dbl(v_control.x );
+ y1:=int26p6_to_dbl(v_control.y );
+ x2:=int26p6_to_dbl(vec.x );
+ y2:=int26p6_to_dbl(vec.y );
+
+ if flip_y then
+ begin
+ y1:=-y1;
+ y2:=-y2;
+
+ end;
+
+ mtx.transform(mtx ,@x1 ,@y1 );
+ mtx.transform(mtx ,@x2 ,@y2 );
+
+ path.curve3(
+ dbl_to_int26p6(x1 ) ,
+ dbl_to_int26p6(y1 ) ,
+ dbl_to_int26p6(x2 ) ,
+ dbl_to_int26p6(y2 ) );
+
+ continue;
+
+ end;
+
+ if tag <> char(FT_CURVE_TAG_CONIC ) then
+ begin
+ result:=false;
+
+ exit;
+
+ end;
+
+ v_middle.x:=(v_control.x + vec.x ) div 2;
+ v_middle.y:=(v_control.y + vec.y ) div 2;
+
+ x1:=int26p6_to_dbl(v_control.x );
+ y1:=int26p6_to_dbl(v_control.y );
+ x2:=int26p6_to_dbl(v_middle.x );
+ y2:=int26p6_to_dbl(v_middle.y );
+
+ if flip_y then
+ begin
+ y1:=-y1;
+ y2:=-y2;
+
+ end;
+
+ mtx.transform(mtx ,@x1 ,@y1 );
+ mtx.transform(mtx ,@x2 ,@y2 );
+
+ path.curve3(
+ dbl_to_int26p6(x1 ) ,
+ dbl_to_int26p6(y1 ) ,
+ dbl_to_int26p6(x2 ) ,
+ dbl_to_int26p6(y2 ) );
+
+ v_control:=vec;
+
+ goto Do_Conic;
+
+ end;
+
+ x1:=int26p6_to_dbl(v_control.x );
+ y1:=int26p6_to_dbl(v_control.y );
+ x2:=int26p6_to_dbl(v_start.x );
+ y2:=int26p6_to_dbl(v_start.y );
+
+ if flip_y then
+ begin
+ y1:=-y1;
+ y2:=-y2;
+
+ end;
+
+ mtx.transform(mtx ,@x1 ,@y1 );
+ mtx.transform(mtx ,@x2 ,@y2 );
+
+ path.curve3(
+ dbl_to_int26p6(x1 ) ,
+ dbl_to_int26p6(y1 ) ,
+ dbl_to_int26p6(x2 ) ,
+ dbl_to_int26p6(y2 ) );
+
+ goto Close;
+
+ end;
+
+ // FT_CURVE_TAG_CUBIC
+ else
+ begin
+ if (ptrcomp(point ) + sizeof(FT_Vector ) > ptrcomp(limit ) ) or
+ (FT_CURVE_TAG(char_ptr(ptrcomp(tags ) + 1 )^ ) <> char(FT_CURVE_TAG_CUBIC ) ) then
+ begin
+ result:=false;
+
+ exit;
+
+ end;
+
+ vec1.x:=point.x;
+ vec1.y:=point.y;
+ vec2.x:=FT_Vector_ptr(ptrcomp(point ) + sizeof(FT_Vector ) ).x;
+ vec2.y:=FT_Vector_ptr(ptrcomp(point ) + sizeof(FT_Vector ) ).y;
+
+ inc(ptrcomp(point ) ,2 * sizeof(FT_Vector ) );
+ inc(ptrcomp(tags ) ,2 );
+
+ if ptrcomp(point ) <= ptrcomp(limit ) then
+ begin
+ vec.x:=point.x;
+ vec.y:=point.y;
+
+ x1:=int26p6_to_dbl(vec1.x );
+ y1:=int26p6_to_dbl(vec1.y );
+ x2:=int26p6_to_dbl(vec2.x );
+ y2:=int26p6_to_dbl(vec2.y );
+ x3:=int26p6_to_dbl(vec.x );
+ y3:=int26p6_to_dbl(vec.y );
+
+ if flip_y then
+ begin
+ y1:=-y1;
+ y2:=-y2;
+ y3:=-y3;
+
+ end;
+
+ mtx.transform(mtx ,@x1 ,@y1 );
+ mtx.transform(mtx ,@x2 ,@y2 );
+ mtx.transform(mtx ,@x3 ,@y3 );
+
+ path.curve4(
+ dbl_to_int26p6(x1 ) ,
+ dbl_to_int26p6(y1 ) ,
+ dbl_to_int26p6(x2 ) ,
+ dbl_to_int26p6(y2 ) ,
+ dbl_to_int26p6(x3 ) ,
+ dbl_to_int26p6(y3 ) );
+
+ continue;
+
+ end;
+
+ x1:=int26p6_to_dbl(vec1.x );
+ y1:=int26p6_to_dbl(vec1.y );
+ x2:=int26p6_to_dbl(vec2.x );
+ y2:=int26p6_to_dbl(vec2.y );
+ x3:=int26p6_to_dbl(v_start.x );
+ y3:=int26p6_to_dbl(v_start.y );
+
+ if flip_y then
+ begin
+ y1:=-y1;
+ y2:=-y2;
+ y3:=-y3;
+
+ end;
+
+ mtx.transform(mtx ,@x1 ,@y1 );
+ mtx.transform(mtx ,@x2 ,@y2 );
+ mtx.transform(mtx ,@x3 ,@y3 );
+
+ path.curve4(
+ dbl_to_int26p6(x1) ,
+ dbl_to_int26p6(y1) ,
+ dbl_to_int26p6(x2) ,
+ dbl_to_int26p6(y2) ,
+ dbl_to_int26p6(x3) ,
+ dbl_to_int26p6(y3) );
+
+ goto Close;
+
+ end;
+
+ end;
+
+ end;
+
+ path.close_polygon;
+
+ Close:
+ first:=last + 1;
+
+ inc(n );
+
+ end;
+
+ result:=true;
+
+end;
+
+{ decompose_ft_bitmap_mono }
+procedure decompose_ft_bitmap_mono(
+ bitmap : FT_Bitmap_ptr;
+ x ,y : int;
+ flip_y : boolean;
+ sl : scanline_ptr;
+ storage : renderer_scanline_ptr );
+var
+ i ,pitch ,j : int;
+
+ buf : int8u_ptr;
+ bits : bitset_iterator;
+
+begin
+ buf :=int8u_ptr(bitmap.buffer );
+ pitch:=bitmap.pitch;
+
+ sl.reset (x ,x + bitmap.width );
+ storage.prepare(bitmap.width + 2 );
+
+ if flip_y then
+ begin
+ inc(ptrcomp(buf ) ,bitmap.pitch * (bitmap.rows - 1 ) );
+ inc(y ,bitmap.rows );
+
+ pitch:=-pitch;
+
+ end;
+
+ i:=0;
+
+ while i < bitmap.rows do
+ begin
+ sl.reset_spans;
+
+ bits.Construct(buf ,0 );
+
+ j:=0;
+
+ while j < bitmap.width do
+ begin
+ if bits.bit <> 0 then
+ sl.add_cell(x + j ,cover_full );
+
+ bits.inc_operator;
+
+ inc(j );
+
+ end;
+
+ inc(ptrcomp(buf ) ,pitch * sizeof(int8u ) );
+
+ if sl.num_spans <> 0 then
+ begin
+ sl.finalize (y - i - 1 );
+ storage.render(sl );
+
+ end;
+
+ inc(i );
+
+ end;
+
+end;
+
+{ decompose_ft_bitmap_gray8 }
+procedure decompose_ft_bitmap_gray8(
+ bitmap : FT_Bitmap_ptr;
+ x ,y : int;
+ flip_y : boolean;
+ ras : rasterizer_scanline_aa_ptr;
+ sl : scanline_ptr;
+ storage : renderer_scanline_ptr );
+var
+ i ,j ,pitch : int;
+
+ buf ,p : int8u_ptr;
+
+begin
+ buf :=int8u_ptr(bitmap.buffer );
+ pitch:=bitmap.pitch;
+
+ sl.reset (x ,x + bitmap.width );
+ storage.prepare(bitmap.width + 2 );
+
+ if flip_y then
+ begin
+ inc(ptrcomp(buf ) ,bitmap.pitch * (bitmap.rows - 1 ) );
+ inc(y ,bitmap.rows );
+
+ pitch:=-pitch;
+
+ end;
+
+ i:=0;
+
+ while i < bitmap.rows do
+ begin
+ sl.reset_spans;
+
+ p:=buf;
+ j:=0;
+
+ while j < bitmap.width do
+ begin
+ if p^ <> 0 then
+ sl.add_cell(x + j ,ras.apply_gamma(p^ ) );
+
+ inc(ptrcomp(p ) ,sizeof(int8u ) );
+ inc(j );
+
+ end;
+
+ inc(ptrcomp(buf ) ,pitch * sizeof(int8u ) );
+
+ if sl.num_spans <> 0 then
+ begin
+ sl.finalize (y - i - 1 );
+ storage.render(sl );
+
+ end;
+
+ inc(i );
+
+ end;
+
+end;
+
+{ CONSTRUCT }
+constructor font_engine_freetype_base.Construct(flag32_ : boolean; max_faces : unsigned = 32 );
+begin
+ m_flag32:=flag32_;
+
+ m_change_stamp:=0;
+ m_last_error :=0;
+
+ m_name :=NIL;
+ m_name_len :=256 - 16 - 1;
+ m_face_index:=0;
+
+ m_char_map:=FT_ENCODING_NONE;
+
+ m_signature.size:=256 + 256 - 16;
+
+ agg_getmem(pointer(m_signature.name ) ,m_signature.size );
+
+ m_height :=0;
+ m_width :=0;
+ m_hinting:=true;
+ m_flip_y :=false;
+
+ m_library_initialized:=false;
+
+ m_library:=NIL;
+
+ agg_getmem(pointer(m_faces ) ,max_faces * sizeof(FT_Face_ptr ) );
+ agg_getmem(pointer(m_face_names ) ,max_faces * sizeof(face_name ) );
+
+ m_num_faces :=0;
+ m_max_faces :=max_faces;
+ m_cur_face :=NIL;
+ m_resolution:=0;
+
+ m_glyph_rendering:=glyph_ren_native_gray8;
+ m_glyph_index :=0;
+ m_data_size :=0;
+ m_data_type :=glyph_data_invalid;
+
+ m_bounds.Construct(1 ,1 ,0 ,0 );
+
+ m_advance_x:=0.0;
+ m_advance_y:=0.0;
+
+ m_affine.Construct;
+
+ m_path16.Construct;
+ m_path32.Construct;
+ m_curves16.Construct(@m_path16 );
+ m_curves32.Construct(@m_path32 );
+ m_scanline_aa.Construct;
+ m_scanline_bin.Construct;
+ m_scanlines_aa.Construct;
+ m_scanlines_bin.Construct;
+ m_rasterizer.Construct;
+
+ m_curves16.approximation_scale_(4.0 );
+ m_curves32.approximation_scale_(4.0 );
+
+ m_last_error:=FT_Init_FreeType(@m_library );
+
+ if m_last_error = 0 then
+ m_library_initialized:=true;
+
+end;
+
+{ DESTRUCT }
+destructor font_engine_freetype_base.Destruct;
+var
+ i : unsigned;
+ n : face_name_ptr;
+
+begin
+ i:=0;
+ n:=m_face_names;
+
+ while i < m_num_faces do
+ begin
+ agg_freemem (pointer(n.name ) ,n.size );
+ FT_Done_Face(FT_Face_ptr_ptr(ptrcomp(m_faces ) + i * sizeof(FT_Face_ptr ) )^ );
+
+ inc(ptrcomp(n ) ,sizeof(face_name ) );
+ inc(i );
+
+ end;
+
+ agg_freemem(pointer(m_face_names ) ,m_max_faces * sizeof(face_name ) );
+ agg_freemem(pointer(m_faces ) ,m_max_faces * sizeof(FT_Face_ptr ) );
+ agg_freemem(pointer(m_signature.name ) ,m_signature.size );
+
+ if m_library_initialized then
+ FT_Done_FreeType(m_library );
+
+ m_path16.Destruct;
+ m_path32.Destruct;
+ m_curves16.Destruct;
+ m_curves32.Destruct;
+ m_scanline_aa.Destruct;
+ m_scanline_bin.Destruct;
+ m_scanlines_aa.Destruct;
+ m_scanlines_bin.Destruct;
+ m_rasterizer.Destruct;
+
+end;
+
+{ RESOLUTION_ }
+procedure font_engine_freetype_base.resolution_(dpi : unsigned );
+begin
+ m_resolution:=dpi;
+
+ update_char_size;
+
+end;
+
+{ LOAD_FONT }
+function font_engine_freetype_base.load_font(
+ font_name : PChar; face_index : unsigned; ren_type : glyph_rendering;
+ font_mem : PChar = NIL; font_mem_size : int = 0 ) : boolean;
+var
+ idx : int;
+
+begin
+ result:=false;
+
+ if m_library_initialized then
+ begin
+ m_last_error:=0;
+
+ idx:=find_face(font_name );
+
+ if idx >= 0 then
+ begin
+ m_cur_face:=FT_Face_ptr_ptr(ptrcomp(m_faces ) + idx * sizeof(FT_Face_ptr ) )^;
+ m_name :=PChar(face_name_ptr(ptrcomp(m_face_names ) + idx * sizeof(face_name ) ).name );
+
+ end
+ else
+ begin
+ if m_num_faces >= m_max_faces then
+ begin
+ agg_freemem (pointer(m_face_names.name ) ,m_face_names.size );
+ FT_Done_Face(m_faces^ );
+
+ move(
+ FT_Face_ptr_ptr(ptrcomp(m_faces ) + sizeof(FT_Face_ptr ) )^ ,
+ m_faces^ ,
+ (m_max_faces - 1 ) * sizeof(FT_Face_ptr ) );
+
+ move(
+ face_name_ptr(ptrcomp(m_face_names ) + sizeof(face_name ) )^ ,
+ m_face_names^ ,
+ (m_max_faces - 1 ) * sizeof(face_name ) );
+
+ dec(m_num_faces );
+
+ end;
+
+ if (font_mem <> NIL ) and
+ (font_mem_size > 0 ) then
+ m_last_error:=
+ FT_New_Memory_Face(
+ m_library ,
+ FT_Byte_ptr(font_mem ) ,
+ font_mem_size ,
+ face_index ,
+ FT_Face_ptr_ptr(ptrcomp(m_faces ) + m_num_faces * sizeof(FT_Face_ptr ) )^ )
+ else
+ m_last_error:=
+ FT_New_Face(
+ m_library ,
+ font_name ,
+ face_index ,
+ FT_Face_ptr_ptr(ptrcomp(m_faces ) + m_num_faces * sizeof(FT_Face_ptr ) )^ );
+
+ if m_last_error = 0 then
+ begin
+ face_name_ptr(ptrcomp(m_face_names ) + m_num_faces * sizeof(face_name ) ).size:=
+ StrLen(font_name ) + 1;
+
+ agg_getmem(
+ pointer(face_name_ptr(ptrcomp(m_face_names ) + m_num_faces * sizeof(face_name ) ).name ) ,
+ face_name_ptr(ptrcomp(m_face_names ) + m_num_faces * sizeof(face_name ) ).size );
+
+ StrCopy(
+ PChar(face_name_ptr(ptrcomp(m_face_names ) + m_num_faces * sizeof(face_name ) ).name ) ,
+ font_name );
+
+ m_cur_face:=FT_Face_ptr_ptr(ptrcomp(m_faces ) + m_num_faces * sizeof(FT_Face_ptr ) )^;
+ m_name :=PChar(face_name_ptr(ptrcomp(m_face_names ) + m_num_faces * sizeof(face_name ) ).name );
+
+ inc(m_num_faces );
+
+ end
+ else
+ begin
+ PChar(face_name_ptr(ptrcomp(m_face_names ) + m_num_faces * sizeof(face_name ) ).name ):=NIL;
+
+ m_cur_face:=NIL;
+ m_name :=NIL;
+
+ end;
+
+ end;
+
+ if m_last_error = 0 then
+ begin
+ result:=true;
+
+ case ren_type of
+ glyph_ren_native_mono :
+ m_glyph_rendering:=glyph_ren_native_mono;
+
+ glyph_ren_native_gray8 :
+ m_glyph_rendering:=glyph_ren_native_gray8;
+
+ glyph_ren_outline :
+ if FT_IS_SCALABLE(m_cur_face ) then
+ m_glyph_rendering:=glyph_ren_outline
+ else
+ m_glyph_rendering:=glyph_ren_native_gray8;
+
+ glyph_ren_agg_mono :
+ if FT_IS_SCALABLE(m_cur_face ) then
+ m_glyph_rendering:=glyph_ren_agg_mono
+ else
+ m_glyph_rendering:=glyph_ren_native_mono;
+
+ glyph_ren_agg_gray8 :
+ if FT_IS_SCALABLE(m_cur_face ) then
+ m_glyph_rendering:=glyph_ren_agg_gray8
+ else
+ m_glyph_rendering:=glyph_ren_native_gray8;
+
+ end;
+
+ update_signature;
+
+ end;
+
+ end;
+
+end;
+
+{ ATTACH }
+function font_engine_freetype_base.attach(file_name : PChar ) : boolean;
+begin
+ result:=false;
+
+ if m_cur_face <> NIL then
+ begin
+ m_last_error:=FT_Attach_File(m_cur_face ,file_name );
+
+ result:=m_last_error = 0;
+
+ end;
+
+end;
+
+{ CHAR_MAP_ }
+function font_engine_freetype_base.char_map_(map : FT_Encoding ) : boolean;
+begin
+ result:=false;
+
+ if m_cur_face <> NIL then
+ begin
+ m_last_error:=FT_Select_Charmap(m_cur_face ,map );
+
+ if m_last_error = 0 then
+ begin
+ m_char_map:=map;
+
+ update_signature;
+
+ result:=true;
+
+ end;
+
+ end;
+
+end;
+
+{ HEIGHT_ }
+function font_engine_freetype_base.height_(h : double ) : boolean;
+begin
+ result :=false;
+ m_height:=Trunc(h * 64.0 );
+
+ if m_cur_face <> NIL then
+ begin
+ update_char_size;
+
+ result:=true;
+
+ end;
+
+end;
+
+{ WIDTH_ }
+function font_engine_freetype_base.width_(w : double ) : boolean;
+begin
+ result :=false;
+ m_width:=Trunc(w * 64.0 );
+
+ if m_cur_face <> NIL then
+ begin
+ update_char_size;
+
+ result:=true;
+
+ end;
+
+end;
+
+{ HINTING_ }
+procedure font_engine_freetype_base.hinting_(h : boolean );
+begin
+ m_hinting:=h;
+
+ if m_cur_face <> NIL then
+ update_signature;
+
+end;
+
+{ FLIP_Y_ }
+procedure font_engine_freetype_base.flip_y_(flip : boolean );
+begin
+ m_flip_y:=flip;
+
+ if m_cur_face <> NIL then
+ update_signature;
+
+end;
+
+{ TRANSFORM_ }
+procedure font_engine_freetype_base.transform_(affine : trans_affine_ptr );
+begin
+ m_affine.assign_all(affine );
+
+ if m_cur_face <> NIL then
+ update_signature;
+
+end;
+
+{ GAMMA_ }
+procedure font_engine_freetype_base.gamma_(f : vertex_source_ptr );
+begin
+ m_rasterizer.gamma(f );
+
+end;
+
+{ LAST_ERROR_ }
+function font_engine_freetype_base._last_error : int;
+begin
+ result:=m_last_error;
+
+end;
+
+{ _RESOLUTION }
+function font_engine_freetype_base._resolution : unsigned;
+begin
+ result:=m_resolution;
+
+end;
+
+{ _NAME }
+function font_engine_freetype_base._name : PChar;
+begin
+ result:=m_name;
+
+end;
+
+{ _NUM_FACES }
+function font_engine_freetype_base._num_faces : unsigned;
+begin
+ if m_cur_face <> NIL then
+ result:=m_cur_face.num_faces
+ else
+ result:=0;
+
+end;
+
+{ _CHAR_MAP }
+function font_engine_freetype_base._char_map : FT_Encoding;
+begin
+ result:=m_char_map;
+
+end;
+
+{ _HEIGHT }
+function font_engine_freetype_base._height : double;
+begin
+ result:=m_height / 64.0;
+
+end;
+
+{ _WIDTH }
+function font_engine_freetype_base._width : double;
+begin
+ result:=m_width / 64.0;
+
+end;
+
+{ _ASCENDER }
+function font_engine_freetype_base._ascender : double;
+begin
+ if m_cur_face <> NIL then
+ result:=m_cur_face.ascender * _height / m_cur_face.height
+ else
+ result:=0.0;
+
+end;
+
+{ _DESCENDER }
+function font_engine_freetype_base._descender : double;
+begin
+ if m_cur_face <> NIL then
+ result:=m_cur_face.descender * _height / m_cur_face.height
+ else
+ result:=0.0;
+
+end;
+
+{ _HINTING }
+function font_engine_freetype_base._hinting : boolean;
+begin
+ result:=m_hinting;
+
+end;
+
+{ _FLIP_Y }
+function font_engine_freetype_base._flip_y : boolean;
+begin
+ result:=m_flip_y;
+
+end;
+
+{ FONT_SIGNATURE }
+function font_engine_freetype_base.font_signature : PChar;
+begin
+ result:=PChar(m_signature.name );
+
+end;
+
+{ CHANGE_STAMP }
+function font_engine_freetype_base.change_stamp : int;
+begin
+ result:=m_change_stamp;
+
+end;
+
+{ PREPARE_GLYPH }
+function font_engine_freetype_base.prepare_glyph(glyph_code : unsigned ) : boolean;
+var
+ fl : int;
+
+ bnd : rect_d;
+
+begin
+ result:=false;
+
+ m_glyph_index:=FT_Get_Char_Index(m_cur_face ,glyph_code );
+
+ if m_hinting then
+ m_last_error:=FT_Load_Glyph(m_cur_face ,m_glyph_index ,FT_LOAD_DEFAULT{} {FT_LOAD_FORCE_AUTOHINT{} )
+ else
+ m_last_error:=FT_Load_Glyph(m_cur_face ,m_glyph_index ,FT_LOAD_NO_HINTING );
+
+ if m_last_error = 0 then
+ case m_glyph_rendering of
+ glyph_ren_native_mono :
+ begin
+ m_last_error:=FT_Render_Glyph(m_cur_face.glyph ,FT_RENDER_MODE_MONO );
+
+ if m_last_error = 0 then
+ begin
+ if m_flip_y then
+ fl:=-m_cur_face.glyph.bitmap_top
+ else
+ fl:=m_cur_face.glyph.bitmap_top;
+
+ decompose_ft_bitmap_mono(
+ @m_cur_face.glyph.bitmap ,
+ m_cur_face.glyph.bitmap_left ,
+ fl ,
+ m_flip_y ,
+ @m_scanline_bin ,
+ @m_scanlines_bin );
+
+ m_bounds.x1:=m_scanlines_bin._min_x;
+ m_bounds.y1:=m_scanlines_bin._min_y;
+ m_bounds.x2:=m_scanlines_bin._max_x;
+ m_bounds.y2:=m_scanlines_bin._max_y;
+ m_data_size:=m_scanlines_bin.byte_size;
+ m_data_type:=glyph_data_mono;
+ m_advance_x:=int26p6_to_dbl(m_cur_face.glyph.advance.x );
+ m_advance_y:=int26p6_to_dbl(m_cur_face.glyph.advance.y );
+
+ result:=true;
+
+ end;
+
+ end;
+
+ glyph_ren_native_gray8 :
+ begin
+ m_last_error:=FT_Render_Glyph(m_cur_face.glyph ,FT_RENDER_MODE_NORMAL );
+
+ if m_last_error = 0 then
+ begin
+ if m_flip_y then
+ fl:=-m_cur_face.glyph.bitmap_top
+ else
+ fl:=m_cur_face.glyph.bitmap_top;
+
+ decompose_ft_bitmap_gray8(
+ @m_cur_face.glyph.bitmap ,
+ m_cur_face.glyph.bitmap_left ,
+ fl ,
+ m_flip_y ,
+ @m_rasterizer ,
+ @m_scanline_aa ,
+ @m_scanlines_aa );
+
+ m_bounds.x1:=m_scanlines_aa._min_x;
+ m_bounds.y1:=m_scanlines_aa._min_y;
+ m_bounds.x2:=m_scanlines_aa._max_x;
+ m_bounds.y2:=m_scanlines_aa._max_y;
+ m_data_size:=m_scanlines_aa.byte_size;
+ m_data_type:=glyph_data_gray8;
+ m_advance_x:=int26p6_to_dbl(m_cur_face.glyph.advance.x );
+ m_advance_y:=int26p6_to_dbl(m_cur_face.glyph.advance.y );
+
+ result:=true;
+
+ end;
+
+ end;
+
+ glyph_ren_outline :
+ if m_last_error = 0 then
+ if m_flag32 then
+ begin
+ m_path32.remove_all;
+
+ if decompose_ft_outline(
+ @m_cur_face.glyph.outline ,
+ m_flip_y ,
+ @m_affine ,
+ @m_path32 ) then
+ begin
+ bnd:=m_path32.bounding_rect;
+
+ m_data_size:=m_path32.byte_size;
+ m_data_type:=glyph_data_outline;
+ m_bounds.x1:=Floor(bnd.x1 );
+ m_bounds.y1:=Floor(bnd.y1 );
+ m_bounds.x2:=Ceil(bnd.x2 );
+ m_bounds.y2:=Ceil(bnd.y2 );
+ m_advance_x:=int26p6_to_dbl(m_cur_face.glyph.advance.x );
+ m_advance_y:=int26p6_to_dbl(m_cur_face.glyph.advance.y );
+
+ m_affine.transform(@m_affine ,@m_advance_x ,@m_advance_y );
+
+ result:=true;
+
+ end;
+
+ end
+ else
+ begin
+ m_path16.remove_all;
+
+ if decompose_ft_outline(
+ @m_cur_face.glyph.outline ,
+ m_flip_y ,
+ @m_affine ,
+ @m_path16 ) then
+ begin
+ bnd:=m_path16.bounding_rect;
+
+ m_data_size:=m_path16.byte_size;
+ m_data_type:=glyph_data_outline;
+ m_bounds.x1:=Floor(bnd.x1 );
+ m_bounds.y1:=Floor(bnd.y1 );
+ m_bounds.x2:=Ceil(bnd.x2 );
+ m_bounds.y2:=Ceil(bnd.y2 );
+ m_advance_x:=int26p6_to_dbl(m_cur_face.glyph.advance.x );
+ m_advance_y:=int26p6_to_dbl(m_cur_face.glyph.advance.y );
+
+ m_affine.transform(@m_affine ,@m_advance_x ,@m_advance_y );
+
+ result:=true;
+
+ end;
+
+ end;
+
+ glyph_ren_agg_mono :
+ if m_last_error = 0 then
+ begin
+ m_rasterizer.reset;
+
+ if m_flag32 then
+ begin
+ m_path32.remove_all;
+
+ decompose_ft_outline(
+ @m_cur_face.glyph.outline ,
+ m_flip_y ,
+ @m_affine ,
+ @m_path32 );
+
+ m_rasterizer.add_path(@m_curves32 );
+
+ end
+ else
+ begin
+ m_path16.remove_all;
+
+ decompose_ft_outline(
+ @m_cur_face.glyph.outline ,
+ m_flip_y ,
+ @m_affine ,
+ @m_path16 );
+
+ m_rasterizer.add_path(@m_curves16 );
+
+ end;
+
+ m_scanlines_bin.prepare(1 ); // Remove all
+
+ render_scanlines(@m_rasterizer ,@m_scanline_bin ,@m_scanlines_bin );
+
+ m_bounds.x1:=m_scanlines_bin._min_x;
+ m_bounds.y1:=m_scanlines_bin._min_y;
+ m_bounds.x2:=m_scanlines_bin._max_x;
+ m_bounds.y2:=m_scanlines_bin._max_y;
+ m_data_size:=m_scanlines_bin.byte_size;
+ m_data_type:=glyph_data_mono;
+ m_advance_x:=int26p6_to_dbl(m_cur_face.glyph.advance.x );
+ m_advance_y:=int26p6_to_dbl(m_cur_face.glyph.advance.y );
+
+ m_affine.transform(@m_affine ,@m_advance_x ,@m_advance_y );
+
+ result:=true;
+
+ end;
+
+ glyph_ren_agg_gray8 :
+ if m_last_error = 0 then
+ begin
+ m_rasterizer.reset;
+
+ if m_flag32 then
+ begin
+ m_path32.remove_all;
+
+ decompose_ft_outline(
+ @m_cur_face.glyph.outline ,
+ m_flip_y ,
+ @m_affine ,
+ @m_path32 );
+
+ m_rasterizer.add_path(@m_curves32 );
+
+ end
+ else
+ begin
+ m_path16.remove_all;
+
+ decompose_ft_outline(
+ @m_cur_face.glyph.outline ,
+ m_flip_y ,
+ @m_affine ,
+ @m_path16 );
+
+ m_rasterizer.add_path(@m_curves16 );
+
+ end;
+
+ m_scanlines_aa.prepare(1 ); // Remove all
+
+ render_scanlines(@m_rasterizer ,@m_scanline_aa ,@m_scanlines_aa );
+
+ m_bounds.x1:=m_scanlines_aa._min_x;
+ m_bounds.y1:=m_scanlines_aa._min_y;
+ m_bounds.x2:=m_scanlines_aa._max_x;
+ m_bounds.y2:=m_scanlines_aa._max_y;
+ m_data_size:=m_scanlines_aa.byte_size;
+ m_data_type:=glyph_data_gray8;
+ m_advance_x:=int26p6_to_dbl(m_cur_face.glyph.advance.x );
+ m_advance_y:=int26p6_to_dbl(m_cur_face.glyph.advance.y );
+
+ m_affine.transform(@m_affine ,@m_advance_x ,@m_advance_y );
+
+ result:=true;
+
+ end;
+
+ end;
+
+end;
+
+{ GLYPH_INDEX }
+function font_engine_freetype_base.glyph_index : unsigned;
+begin
+ result:=m_glyph_index;
+
+end;
+
+{ DATA_SIZE }
+function font_engine_freetype_base.data_size : unsigned;
+begin
+ result:=m_data_size;
+
+end;
+
+{ DATA_TYPE }
+function font_engine_freetype_base.data_type : unsigned;
+begin
+ result:=m_data_type;
+
+end;
+
+{ BOUNDS }
+function font_engine_freetype_base.bounds : rect_ptr;
+begin
+ result:=@m_bounds;
+
+end;
+
+{ ADVANCE_X }
+function font_engine_freetype_base.advance_x : double;
+begin
+ result:=m_advance_x;
+
+end;
+
+{ ADVANCE_Y }
+function font_engine_freetype_base.advance_y : double;
+begin
+ result:=m_advance_y;
+
+end;
+
+{ WRITE_GLYPH_TO }
+procedure font_engine_freetype_base.write_glyph_to(data : int8u_ptr );
+begin
+ if (data <> NIL ) and
+ (m_data_size <> 0 ) then
+ case m_data_type of
+ glyph_data_mono :
+ m_scanlines_bin.serialize(data );
+
+ glyph_data_gray8 :
+ m_scanlines_aa.serialize(data );
+
+ glyph_data_outline :
+ if m_flag32 then
+ m_path32.serialize(data )
+ else
+ m_path16.serialize(data );
+
+ end;
+
+end;
+
+{ ADD_KERNING }
+function font_engine_freetype_base.add_kerning(first ,second : unsigned; x ,y : double_ptr ) : boolean;
+var
+ delta : FT_Vector;
+ dx ,dy : double;
+
+begin
+ if (m_cur_face <> NIL ) and
+ (first <> 0 ) and
+ (second <> 0 ) and
+ FT_HAS_KERNING(m_cur_face ) then
+ begin
+ FT_Get_Kerning(m_cur_face ,first ,second ,FT_KERNING_DEFAULT ,@delta );
+
+ dx:=int26p6_to_dbl(delta.x );
+ dy:=int26p6_to_dbl(delta.y );
+
+ if (m_glyph_rendering = glyph_ren_outline ) or
+ (m_glyph_rendering = glyph_ren_agg_mono ) or
+ (m_glyph_rendering = glyph_ren_agg_gray8 ) then
+ m_affine.transform_2x2(@m_affine ,@dx ,@dy );
+
+ x^:=x^ + dx;
+ y^:=y^ + dy;
+
+ result:=true;
+
+ end
+ else
+ result:=false;
+
+end;
+
+{ FLAG32 }
+function font_engine_freetype_base.flag32;
+begin
+ result:=m_flag32;
+
+end;
+
+{ UPDATE_CHAR_SIZE }
+procedure font_engine_freetype_base.update_char_size;
+begin
+ if m_cur_face <> NIL then
+ begin
+ if m_resolution <> 0 then
+ FT_Set_Char_Size(
+ m_cur_face ,
+ m_width , // char_width in 1/64th of points
+ m_height , // char_height in 1/64th of points
+ m_resolution , // horizontal device resolution
+ m_resolution ) // vertical device resolution
+ else
+ FT_Set_Pixel_Sizes(
+ m_cur_face ,
+ m_width shr 6 , // pixel_width
+ m_height shr 6 ); // pixel_height
+
+ update_signature;
+
+ end;
+
+end;
+
+{ UPDATE_SIGNATURE }
+procedure font_engine_freetype_base.update_signature;
+var
+ name_len ,gamma_hash ,i : unsigned;
+
+ gamma_table : array[0..aa_num - 1 ] of int8u;
+
+ mtx : array[0..5 ] of double;
+ buf : array[0..99 ] of char;
+ str : char_ptr;
+
+begin
+ if (m_cur_face <> NIL ) and
+ (m_name <> NIL ) then
+ begin
+ name_len:=StrLen(m_name );
+
+ if name_len > m_name_len then
+ begin
+ agg_freemem(pointer(m_signature.name ) ,m_signature.size );
+
+ m_signature.size:=name_len + 32 + 256;
+
+ agg_getmem(pointer(m_signature.name ) ,m_signature.size );
+
+ m_name_len:=name_len + 32 - 1;
+
+ end;
+
+ gamma_hash:=0;
+
+ if (m_glyph_rendering = glyph_ren_native_gray8 ) or
+ (m_glyph_rendering = glyph_ren_agg_mono ) or
+ (m_glyph_rendering = glyph_ren_agg_gray8 ) then
+ begin
+ for i:=0 to aa_num - 1 do
+ gamma_table[i ]:=m_rasterizer.apply_gamma(i );
+
+ gamma_hash:=calc_crc32(@gamma_table ,sizeof(gamma_table ) );
+
+ end;
+
+ str:=m_signature.name;
+
+ sprintf(str ,'%s,' ,ptrcomp(m_name ) );
+ sprintf(char_ptr(ptrcomp(str ) + StrLen(PChar(str ) ) ) ,'%u,' ,int(m_char_map ) );
+ sprintf(char_ptr(ptrcomp(str ) + StrLen(PChar(str ) ) ) ,'%d,' ,m_face_index );
+ sprintf(char_ptr(ptrcomp(str ) + StrLen(PChar(str ) ) ) ,'%d,' ,int(m_glyph_rendering ) );
+ sprintf(char_ptr(ptrcomp(str ) + StrLen(PChar(str ) ) ) ,'%d:' ,m_resolution );
+ sprintf(char_ptr(ptrcomp(str ) + StrLen(PChar(str ) ) ) ,'%dx' ,m_height );
+ sprintf(char_ptr(ptrcomp(str ) + StrLen(PChar(str ) ) ) ,'%d,' ,m_width );
+ sprintf(char_ptr(ptrcomp(str ) + StrLen(PChar(str ) ) ) ,'%d,' ,int(m_hinting ) );
+ sprintf(char_ptr(ptrcomp(str ) + StrLen(PChar(str ) ) ) ,'%d,' ,int(m_flip_y ) );
+ sprintf(char_ptr(ptrcomp(str ) + StrLen(PChar(str ) ) ) ,'%08X' ,gamma_hash );
+
+ if (m_glyph_rendering = glyph_ren_outline ) or
+ (m_glyph_rendering = glyph_ren_agg_mono ) or
+ (m_glyph_rendering = glyph_ren_agg_gray8 ) then
+ begin
+ m_affine.store_to(@mtx );
+
+ sprintf(@buf[0 ] ,',%08X' ,dbl_to_plain_fx(mtx[0 ] ) );
+ sprintf(@buf[StrLen(@buf[0 ] ) ] ,'%08X' ,dbl_to_plain_fx(mtx[1 ] ) );
+ sprintf(@buf[StrLen(@buf[0 ] ) ] ,'%08X' ,dbl_to_plain_fx(mtx[2 ] ) );
+ sprintf(@buf[StrLen(@buf[0 ] ) ] ,'%08X' ,dbl_to_plain_fx(mtx[3 ] ) );
+ sprintf(@buf[StrLen(@buf[0 ] ) ] ,'%08X' ,dbl_to_plain_fx(mtx[4 ] ) );
+ sprintf(@buf[StrLen(@buf[0 ] ) ] ,'%08X' ,dbl_to_plain_fx(mtx[5 ] ) );
+
+ StrCat(PChar(m_signature.name ) ,buf );
+
+ end;
+
+ inc(m_change_stamp );
+
+ end;
+
+end;
+
+{ FIND_FACE }
+function font_engine_freetype_base.find_face(name : PChar ) : int;
+var
+ i : unsigned;
+ n : face_name_ptr;
+
+begin
+ result:=-1;
+
+ n:=m_face_names;
+ i:=0;
+
+ while i < m_num_faces do
+ begin
+ if StrComp(name ,PChar(n.name ) ) = 0 then
+ begin
+ result:=i;
+
+ exit;
+
+ end;
+
+ inc(ptrcomp(n ) ,sizeof(face_name ) );
+ inc(i );
+
+ end;
+
+end;
+
+{ CONSTRUCT }
+constructor font_engine_freetype_int16.Construct(max_faces : unsigned = 32 );
+begin
+ inherited Construct(false ,max_faces );
+
+end;
+
+{ CONSTRUCT }
+constructor font_engine_freetype_int32.Construct(max_faces : unsigned = 32 );
+begin
+ inherited Construct(true ,max_faces );
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_font_freetype_lib.pas b/src/corelib/render/software/agg_font_freetype_lib.pas
new file mode 100644
index 00000000..2f206919
--- /dev/null
+++ b/src/corelib/render/software/agg_font_freetype_lib.pas
@@ -0,0 +1,369 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2007
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 17.09.2007-Milano: Finished OK
+// 16.09.2007-Milano: Unit port establishment
+//
+{ agg_font_freetype_lib.pas }
+unit
+ agg_font_freetype_lib ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ;
+
+{ GLOBAL VARIABLES & CONSTANTS }
+type
+ FT_Encoding = array[0..3 ] of char;
+
+const
+{$IFDEF AGG_WINDOWS }
+ ft_lib = 'freetype.dll';
+
+{$ENDIF }
+
+{$IFDEF AGG_LINUX }
+ ft_lib = 'freetype.so';
+
+{$ENDIF }
+
+{$IFDEF AGG_MACOSX }
+ ft_lib = 'libfreetype';
+
+{$ENDIF }
+
+ FT_CURVE_TAG_ON = 1;
+ FT_CURVE_TAG_CONIC = 0;
+ FT_CURVE_TAG_CUBIC = 2;
+
+ FT_FACE_FLAG_SCALABLE = 1 shl 0;
+ FT_FACE_FLAG_KERNING = 1 shl 6;
+
+ FT_ENCODING_NONE : FT_Encoding = (#0 ,#0 ,#0 ,#0 );
+
+ FT_LOAD_DEFAULT = $0000;
+ FT_LOAD_NO_HINTING = $0002;
+ FT_LOAD_FORCE_AUTOHINT = $0020;
+
+ FT_RENDER_MODE_NORMAL = 0;
+ FT_RENDER_MODE_LIGHT = FT_RENDER_MODE_NORMAL + 1;
+ FT_RENDER_MODE_MONO = FT_RENDER_MODE_LIGHT + 1;
+ FT_RENDER_MODE_LCD = FT_RENDER_MODE_MONO + 1;
+ FT_RENDER_MODE_LCD_V = FT_RENDER_MODE_LCD + 1;
+ FT_RENDER_MODE_MAX = FT_RENDER_MODE_LCD_V + 1;
+
+ FT_KERNING_DEFAULT = 0;
+ FT_KERNING_UNFITTED = 1;
+ FT_KERNING_UNSCALED = 2;
+
+ FT_STYLE_FLAG_ITALIC = 1 shl 0;
+ FT_STYLE_FLAG_BOLD = 1 shl 1;
+
+{ TYPES DEFINITION }
+type
+ FT_Byte = byte;
+ FT_Short = smallint;
+ FT_UShort = word;
+ FT_Int = longint;
+ FT_UInt = longword;
+ FT_Int32 = longint;
+ FT_Long = longint;
+ FT_ULong = longword;
+ FT_Fixed = longint;
+ FT_Pos = longint;
+ FT_Error = longint;
+ FT_F26Dot6 = longint;
+
+ FT_Byte_ptr = ^FT_Byte;
+ FT_Short_ptr = ^FT_Short;
+
+ FT_Render_Mode = FT_Int;
+
+ FT_Library_ptr_ptr = ^FT_Library_ptr;
+ FT_Library_ptr = ^FT_Library;
+ FT_Library = packed record
+ end;
+
+ FT_Subglyph_ptr = ^FT_Subglyph;
+ FT_Subglyph = packed record // TODO
+ end;
+
+ FT_Bitmap_Size = record
+ height ,
+ width : FT_Short;
+
+ end;
+
+ AFT_Bitmap_Size = array [0..1023] of FT_Bitmap_Size;
+ FT_Bitmap_Size_ptr = ^AFT_Bitmap_Size;
+
+ FT_Charmap_ptr = ^FT_Charmap;
+ FT_Charmap_ptr_ptr = ^FT_Charmap_ptr;
+
+ FT_Generic_Finalizer = procedure(AnObject : pointer ); cdecl;
+
+ FT_Generic = packed record
+ data : pointer;
+ finalizer : FT_Generic_Finalizer;
+
+ end;
+
+ FT_BBox_ptr = ^FT_BBox;
+ FT_BBox = packed record
+ xMin ,
+ yMin ,
+ xMax ,
+ yMax : FT_Pos;
+
+ end;
+
+ FT_Vector_ptr = ^FT_Vector;
+ FT_Vector = packed record
+ x ,
+ y : FT_Pos;
+
+ end;
+
+ FT_Bitmap_ptr = ^FT_Bitmap;
+ FT_Bitmap = packed record
+ rows ,
+ width ,
+ pitch : FT_Int;
+
+ buffer : pointer;
+
+ num_grays : FT_Short;
+ pixel_mode ,
+ palette_mode : char;
+
+ palette : pointer;
+
+ end;
+
+ FT_Outline_ptr = ^FT_Outline;
+ FT_Outline = packed record
+ n_contours ,
+ n_points : FT_Short;
+
+ points : FT_Vector_ptr;
+ tags : PChar;
+
+ contours : FT_Short_ptr;
+ flags : FT_Int;
+
+ end;
+
+ FT_Glyph_Metrics = packed record
+ width ,
+ height ,
+
+ horiBearingX ,
+ horiBearingY ,
+ horiAdvance ,
+ vertBearingX ,
+ vertBearingY ,
+ vertAdvance : FT_Pos;
+
+ end;
+
+ FT_Face_ptr_ptr = ^FT_Face_ptr;
+ FT_Face_ptr = ^FT_Face;
+
+ FT_GlyphSlot_ptr = ^FT_GlyphSlot;
+ FT_GlyphSlot = packed record
+ alibrary : FT_Library_ptr;
+
+ face : FT_Face_ptr;
+ next : FT_GlyphSlot_ptr;
+ flags : FT_UInt;
+
+ generic : FT_Generic;
+ metrics : FT_Glyph_Metrics;
+
+ linearHoriAdvance ,
+ linearVertAdvance : FT_Fixed;
+
+ advance : FT_Vector;
+ format : longword;
+ bitmap : FT_Bitmap;
+
+ bitmap_left ,
+ bitmap_top : FT_Int;
+
+ outline : FT_Outline;
+
+ num_subglyphs : FT_UInt;
+ subglyphs : FT_SubGlyph_ptr;
+ control_data : pointer;
+ control_len : longint;
+
+ other : pointer;
+
+ end;
+
+ FT_Size_Metrics = record
+ x_ppem ,
+ y_ppem : FT_UShort;
+ x_scale ,
+ y_scale : FT_Fixed;
+
+ ascender ,
+ descender ,
+ height ,
+ max_advance : FT_Pos;
+
+ end;
+
+ FT_Size_ptr = ^FT_Size;
+ FT_Size = record
+ face : FT_Face_ptr;
+ generic : FT_Generic;
+ metrics : FT_Size_Metrics;
+ //internal : FT_Size_Internal;
+
+ end;
+
+ FT_Face = packed record
+ num_faces ,
+ face_index ,
+ face_flags ,
+ style_flags ,
+ num_glyphs : FT_Long;
+ family_name ,
+ style_name : PChar;
+
+ num_fixed_sizes : FT_Int;
+ available_sizes : FT_Bitmap_Size_ptr; // is array
+
+ num_charmaps : FT_Int;
+ charmaps : FT_CharMap_ptr_ptr; // is array
+
+ generic : FT_Generic;
+ bbox : FT_BBox;
+
+ units_per_EM : FT_UShort;
+
+ ascender ,
+ descender ,
+ height ,
+
+ max_advance_width ,
+ max_advance_height ,
+ underline_position ,
+ underline_thickness : FT_Short;
+
+ glyph : FT_GlyphSlot_ptr;
+ size : FT_Size_ptr;
+ charmap : FT_CharMap_ptr;
+
+ end;
+
+ FT_Charmap = packed record
+ face : FT_Face_ptr;
+ encoding : FT_Encoding;
+
+ platform_id ,
+ encoding_id : FT_UShort;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+ function FT_CURVE_TAG (flag : char ) : char;
+ function FT_IS_SCALABLE(face : FT_Face_ptr ) : boolean;
+ function FT_HAS_KERNING(face : FT_Face_ptr ) : boolean;
+
+ function FT_Init_FreeType(alibrary : FT_Library_ptr ) : FT_Error; cdecl; external ft_lib name 'FT_Init_FreeType';
+
+ function FT_Done_FreeType(alibrary : FT_Library_ptr ) : FT_Error; cdecl; external ft_lib name 'FT_Done_FreeType';
+
+ function FT_Attach_File(face : FT_Face_ptr; filepathname : PChar ) : FT_Error; cdecl; external ft_lib name 'FT_Attach_File';
+
+ function FT_New_Memory_Face(
+ library_ : FT_Library_ptr;
+ file_base : FT_Byte_ptr;
+ file_size ,
+ face_index : FT_Long;
+ var aface : FT_Face_ptr ) : FT_Error; cdecl; external ft_lib name 'FT_New_Memory_Face';
+
+ function FT_New_Face(
+ library_ : FT_Library_ptr;
+ filepathname : PChar;
+ face_index : FT_Long;
+ var aface : FT_Face_ptr ) : FT_Error; cdecl; external ft_lib name 'FT_New_Face';
+
+ function FT_Done_Face(face : FT_Face_ptr ) : FT_Error; cdecl; external ft_lib name 'FT_Done_Face';
+
+ function FT_Select_Charmap(face : FT_Face_ptr; encoding : FT_Encoding ) : FT_Error; cdecl; external ft_lib name 'FT_Select_Charmap';
+
+ function FT_Get_Char_Index(face : FT_Face_ptr; charcode : FT_ULong ) : FT_UInt; cdecl; external ft_lib name 'FT_Get_Char_Index';
+
+ function FT_Load_Glyph(
+ face : FT_Face_ptr;
+ glyph_index : FT_UInt ;
+ load_flags : FT_Int32 ) : FT_Error; cdecl; external ft_lib name 'FT_Load_Glyph';
+
+ function FT_Render_Glyph(slot : FT_GlyphSlot_ptr; render_mode : FT_Render_Mode ) : FT_Error; cdecl; external ft_lib name 'FT_Render_Glyph';
+
+ function FT_Get_Kerning(
+ face : FT_Face_ptr;
+ left_glyph ,right_glyph ,kern_mode : FT_UInt;
+ akerning : FT_Vector_ptr ) : FT_Error; cdecl; external ft_lib name 'FT_Get_Kerning';
+
+ function FT_Set_Char_Size(
+ face : FT_Face_ptr;
+ char_width ,char_height : FT_F26dot6;
+ horz_res ,vert_res : FT_UInt) : FT_Error; cdecl; external ft_lib name 'FT_Set_Char_Size';
+
+ function FT_Set_Pixel_Sizes(
+ face : FT_Face_ptr;
+ pixel_width ,pixel_height : FT_UInt ) : FT_Error; cdecl; external ft_lib name 'FT_Set_Pixel_Sizes';
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ FT_CURVE_TAG }
+function FT_CURVE_TAG(flag : char ) : char;
+begin
+ result:=char(int8u(flag ) and 3 );
+
+end;
+
+{ FT_IS_SCALABLE }
+function FT_IS_SCALABLE(face : FT_Face_ptr ) : boolean;
+begin
+ result:=boolean(face.face_flags and FT_FACE_FLAG_SCALABLE );
+
+end;
+
+{ FT_HAS_KERNING }
+function FT_HAS_KERNING(face : FT_Face_ptr ) : boolean;
+begin
+ result:=boolean(face.face_flags and FT_FACE_FLAG_KERNING );
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_font_win32_tt.pas b/src/corelib/render/software/agg_font_win32_tt.pas
new file mode 100644
index 00000000..de2c94c4
--- /dev/null
+++ b/src/corelib/render/software/agg_font_win32_tt.pas
@@ -0,0 +1,1774 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 18.02.2006-Milano: Complete unit port
+// 17.02.2006-Milano: Unit port establishment
+//
+{ agg_font_win32_tt.pas }
+unit
+ agg_font_win32_tt ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ Windows ,SysUtils ,Math ,
+ agg_basics ,
+ agg_array ,
+ agg_bitset_iterator ,
+ agg_scanline_storage_aa ,
+ agg_scanline_storage_bin ,
+ agg_scanline ,
+ agg_scanline_u ,
+ agg_scanline_bin ,
+ agg_renderer_scanline ,
+ agg_render_scanlines ,
+ agg_path_storage_integer ,
+ agg_rasterizer_scanline_aa ,
+ agg_conv_curve ,
+ agg_trans_affine ,
+ agg_font_cache_manager ,
+ agg_font_engine ,
+ agg_vertex_source ;
+
+{ TYPES DEFINITION }
+const
+ buf_size = 32768 - 32;
+
+type
+ winapi_GetGlyphOutlineX = function (DC: HDC; p2, p3: UINT; const p4: TGlyphMetrics; p5: DWORD; p6: Pointer; const p7: TMat2): DWORD; stdcall;
+
+ HFONT_ptr = ^HFONT;
+ PChar_ptr = ^PChar;
+
+ KERNINGPAIR_ptr = ^KERNINGPAIR;
+
+ FIXED_ptr = ^FIXED;
+
+ TTPOLYGONHEADER_ptr = ^TTPOLYGONHEADER;
+
+ TTPOLYCURVE_ptr = ^TTPOLYCURVE;
+
+ POINTFX_ptr = ^POINTFX;
+
+ font_name_ptr = ^font_name;
+ font_name = record
+ name : char_ptr; //PChar;
+ size : unsigned;
+
+ end;
+
+//-----------------------------------------------font_engine_win32_tt_base
+ font_engine_win32_tt_base = object(font_engine )
+ m_flag32 : boolean;
+ m_dc : HDC;
+
+ m_old_font : HFONT;
+ m_fonts : HFONT_ptr;
+
+ m_num_fonts ,
+ m_max_fonts : unsigned;
+ m_font_names : font_name_ptr;
+ m_cur_font : HFONT;
+
+ m_change_stamp : int;
+ m_typeface : font_name;
+ m_typeface_len : unsigned;
+ m_signature : font_name;
+
+ m_height ,
+ m_width : unsigned;
+ m_weight : int;
+ m_italic : boolean;
+ m_char_set : DWORD;
+
+ m_pitch_and_family : DWORD;
+
+ m_hinting ,
+ m_flip_y : boolean;
+
+ m_font_created : boolean;
+ m_resolution : unsigned;
+ m_glyph_rendering : glyph_rendering;
+ m_glyph_index : unsigned;
+
+ m_data_size ,
+ m_data_type : unsigned;
+ m_bounds : rect;
+ m_advance_x ,
+ m_advance_y : double;
+
+ m_matrix : TMAT2;
+ m_gbuf : int8u_ptr;
+
+ m_kerning_pairs : KERNINGPAIR_ptr;
+ m_num_kerning_pairs ,
+ m_max_kerning_pairs : unsigned;
+
+ m_affine : trans_affine;
+
+ m_path16 : path_storage_int16;
+ m_path32 : path_storage_int32;
+ m_curves16 ,
+ m_curves32 : conv_curve;
+
+ m_scanline_aa : scanline_u8;
+ m_scanline_bin : scanline_bin;
+ m_scanlines_aa : scanlines_aa_type;
+ m_scanlines_bin : scanlines_bin_type;
+ m_rasterizer : rasterizer_scanline_aa;
+
+ constructor Construct(flag32_ : boolean; dc : HDC; max_fonts : unsigned = 32 );
+ destructor Destruct;
+
+ // Set font parameters
+ procedure resolution_(dpi : unsigned );
+ procedure height_ (h : double );
+ procedure width_ (w : double );
+ procedure weight_ (w : int );
+ procedure italic_ (it : boolean );
+ procedure char_set_ (c : DWORD );
+
+ procedure pitch_and_family_(p : DWORD );
+
+ procedure flip_y_ (flip : boolean );
+ procedure hinting_(h : boolean );
+
+ function create_font (typeface_ : PChar; ren_type : glyph_rendering ) : boolean;
+ function create_font_(
+ typeface : PChar;
+ ren_type : glyph_rendering;
+ height : double;
+ width : double = 0.0;
+ weight : int = FW_REGULAR;
+ italic : boolean = false;
+ char_set : DWORD = ANSI_CHARSET;
+ pitch_and_family : DWORD = FF_DONTCARE ) : boolean;
+
+ // Set Gamma
+ procedure gamma_ (f : vertex_source_ptr );
+ procedure transform_(mtx : trans_affine_ptr );
+
+ // Accessors
+ function _resolution : unsigned;
+ function _typeface : PChar;
+ function _height : double;
+ function _width : double;
+ function _weight : int;
+ function _italic : boolean;
+ function _char_set : DWORD;
+ function _pitch_and_family : DWORD;
+ function _hinting : boolean;
+ function _flip_y : boolean;
+
+ // Interface mandatory to implement for font_cache_manager
+ function font_signature : PChar; virtual;
+ function change_stamp : int; virtual;
+
+ function prepare_glyph(glyph_code : unsigned ) : boolean; virtual;
+
+ function glyph_index : unsigned; virtual;
+ function data_size : unsigned; virtual;
+ function data_type : unsigned; virtual;
+ function bounds : rect_ptr; virtual;
+ function advance_x : double; virtual;
+ function advance_y : double; virtual;
+
+ procedure write_glyph_to(data : int8u_ptr ); virtual;
+ function add_kerning (first ,second : unsigned; x ,y : double_ptr ) : boolean; virtual;
+
+ function flag32 : boolean; virtual;
+
+ // Private
+ procedure update_signature;
+ function pair_less(v1 ,v2 : KERNINGPAIR_ptr ) : boolean;
+
+ procedure load_kerning_pairs;
+ procedure sort_kerning_pairs;
+
+ function find_font(name : PChar ) : int;
+
+ end;
+
+//------------------------------------------------font_engine_win32_tt_int16
+// This class uses values of type int16 (10.6 format) for the vector cache.
+// The vector cache is compact, but when rendering glyphs of height
+// more that 200 there integer overflow can occur.
+ font_engine_win32_tt_int16 = object(font_engine_win32_tt_base )
+ constructor Construct(dc : HDC; max_fonts : unsigned = 32 );
+
+ end;
+
+
+//------------------------------------------------font_engine_win32_tt_int32
+// This class uses values of type int32 (26.6 format) for the vector cache.
+// The vector cache is twice larger than in font_engine_win32_tt_int16,
+// but it allows you to render glyphs of very large sizes.
+ font_engine_win32_tt_int32 = object(font_engine_win32_tt_base )
+ constructor Construct(dc : HDC; max_fonts : unsigned = 32 );
+
+ end;
+
+var
+ GetGlyphOutlineX : winapi_GetGlyphOutlineX;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+//------------------------------------------------------------------------------
+//
+// This code implements the AUTODIN II polynomial
+// The variable corresponding to the macro argument "crc" should
+// be an unsigned long.
+// Oroginal code by Spencer Garrett <srg@quick.com>
+//
+// generated using the AUTODIN II polynomial
+// x^32 + x^26 + x^23 + x^22 + x^16 +
+// x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + 1
+//
+//------------------------------------------------------------------------------
+const
+ crc32tab : array[0..255 ] of unsigned = (
+ $00000000, $77073096, $ee0e612c, $990951ba,
+ $076dc419, $706af48f, $e963a535, $9e6495a3,
+ $0edb8832, $79dcb8a4, $e0d5e91e, $97d2d988,
+ $09b64c2b, $7eb17cbd, $e7b82d07, $90bf1d91,
+ $1db71064, $6ab020f2, $f3b97148, $84be41de,
+ $1adad47d, $6ddde4eb, $f4d4b551, $83d385c7,
+ $136c9856, $646ba8c0, $fd62f97a, $8a65c9ec,
+ $14015c4f, $63066cd9, $fa0f3d63, $8d080df5,
+ $3b6e20c8, $4c69105e, $d56041e4, $a2677172,
+ $3c03e4d1, $4b04d447, $d20d85fd, $a50ab56b,
+ $35b5a8fa, $42b2986c, $dbbbc9d6, $acbcf940,
+ $32d86ce3, $45df5c75, $dcd60dcf, $abd13d59,
+ $26d930ac, $51de003a, $c8d75180, $bfd06116,
+ $21b4f4b5, $56b3c423, $cfba9599, $b8bda50f,
+ $2802b89e, $5f058808, $c60cd9b2, $b10be924,
+ $2f6f7c87, $58684c11, $c1611dab, $b6662d3d,
+ $76dc4190, $01db7106, $98d220bc, $efd5102a,
+ $71b18589, $06b6b51f, $9fbfe4a5, $e8b8d433,
+ $7807c9a2, $0f00f934, $9609a88e, $e10e9818,
+ $7f6a0dbb, $086d3d2d, $91646c97, $e6635c01,
+ $6b6b51f4, $1c6c6162, $856530d8, $f262004e,
+ $6c0695ed, $1b01a57b, $8208f4c1, $f50fc457,
+ $65b0d9c6, $12b7e950, $8bbeb8ea, $fcb9887c,
+ $62dd1ddf, $15da2d49, $8cd37cf3, $fbd44c65,
+ $4db26158, $3ab551ce, $a3bc0074, $d4bb30e2,
+ $4adfa541, $3dd895d7, $a4d1c46d, $d3d6f4fb,
+ $4369e96a, $346ed9fc, $ad678846, $da60b8d0,
+ $44042d73, $33031de5, $aa0a4c5f, $dd0d7cc9,
+ $5005713c, $270241aa, $be0b1010, $c90c2086,
+ $5768b525, $206f85b3, $b966d409, $ce61e49f,
+ $5edef90e, $29d9c998, $b0d09822, $c7d7a8b4,
+ $59b33d17, $2eb40d81, $b7bd5c3b, $c0ba6cad,
+ $edb88320, $9abfb3b6, $03b6e20c, $74b1d29a,
+ $ead54739, $9dd277af, $04db2615, $73dc1683,
+ $e3630b12, $94643b84, $0d6d6a3e, $7a6a5aa8,
+ $e40ecf0b, $9309ff9d, $0a00ae27, $7d079eb1,
+ $f00f9344, $8708a3d2, $1e01f268, $6906c2fe,
+ $f762575d, $806567cb, $196c3671, $6e6b06e7,
+ $fed41b76, $89d32be0, $10da7a5a, $67dd4acc,
+ $f9b9df6f, $8ebeeff9, $17b7be43, $60b08ed5,
+ $d6d6a3e8, $a1d1937e, $38d8c2c4, $4fdff252,
+ $d1bb67f1, $a6bc5767, $3fb506dd, $48b2364b,
+ $d80d2bda, $af0a1b4c, $36034af6, $41047a60,
+ $df60efc3, $a867df55, $316e8eef, $4669be79,
+ $cb61b38c, $bc66831a, $256fd2a0, $5268e236,
+ $cc0c7795, $bb0b4703, $220216b9, $5505262f,
+ $c5ba3bbe, $b2bd0b28, $2bb45a92, $5cb36a04,
+ $c2d7ffa7, $b5d0cf31, $2cd99e8b, $5bdeae1d,
+ $9b64c2b0, $ec63f226, $756aa39c, $026d930a,
+ $9c0906a9, $eb0e363f, $72076785, $05005713,
+ $95bf4a82, $e2b87a14, $7bb12bae, $0cb61b38,
+ $92d28e9b, $e5d5be0d, $7cdcefb7, $0bdbdf21,
+ $86d3d2d4, $f1d4e242, $68ddb3f8, $1fda836e,
+ $81be16cd, $f6b9265b, $6fb077e1, $18b74777,
+ $88085ae6, $ff0f6a70, $66063bca, $11010b5c,
+ $8f659eff, $f862ae69, $616bffd3, $166ccf45,
+ $a00ae278, $d70dd2ee, $4e048354, $3903b3c2,
+ $a7672661, $d06016f7, $4969474d, $3e6e77db,
+ $aed16a4a, $d9d65adc, $40df0b66, $37d83bf0,
+ $a9bcae53, $debb9ec5, $47b2cf7f, $30b5ffe9,
+ $bdbdf21c, $cabac28a, $53b39330, $24b4a3a6,
+ $bad03605, $cdd70693, $54de5729, $23d967bf,
+ $b3667a2e, $c4614ab8, $5d681b02, $2a6f2b94,
+ $b40bbe37, $c30c8ea1, $5a05df1b, $2d02ef8d );
+
+{ UNIT IMPLEMENTATION }
+{ calc_crc32 }
+function calc_crc32(buf : int8u_ptr; size : unsigned ) : unsigned;
+var
+ crc ,len ,nr : unsigned;
+
+ p : int8u_ptr;
+
+begin
+ crc:=unsigned(not 0 );
+ len:=0;
+ nr :=size;
+ len:=len + nr;
+ p :=buf;
+
+ while nr <> 0 do
+ begin
+ dec(nr );
+
+ crc:=(crc shr 8 ) xor crc32tab[(crc xor p^ ) and $ff ];
+
+ inc(ptrcomp(p ) ,sizeof(int8u ) );
+
+ end;
+
+ result:=not crc;
+
+end;
+
+{ dbl_to_fx }
+function dbl_to_fx(d : double ) : FIXED;
+var
+ l : int;
+
+begin
+ l:=trunc(d * 65536.0 );
+
+ move(l ,result ,sizeof(int ) );
+
+end;
+
+{ dbl_to_plain_fx }
+function dbl_to_plain_fx(d : double ) : int;
+begin
+ result:=trunc(d * 65536.0 );
+
+end;
+
+{ negate_fx }
+function negate_fx(fx : FIXED_ptr ) : FIXED;
+var
+ l : int;
+
+begin
+ l:=-int(fx );
+
+ move(l ,result ,sizeof(int ) );
+
+end;
+
+{ fx_to_dbl }
+function fx_to_dbl(p : FIXED_ptr ) : double;
+begin
+ result:=p.value + p.fract * (1.0 / 65536.0 );
+
+end;
+
+{ fx_to_plain_int }
+function fx_to_plain_int(fx : FIXED_ptr ) : int;
+begin
+ result:=int(fx );
+
+end;
+
+{ fx_to_int26p6 }
+function fx_to_int26p6(p : FIXED_ptr ) : int;
+begin
+ result:=(int(p.value ) shl 6 ) + (shr_int32(int(p.fract ) ,10 ) );
+
+end;
+
+{ dbl_to_int26p6 }
+function dbl_to_int26p6(p : double ) : int;
+begin
+ result:=trunc(p * 64.0 + 0.5 );
+
+end;
+
+{ decompose_win32_glyph_bitmap_mono }
+procedure decompose_win32_glyph_bitmap_mono(
+ gbuf : int8u_ptr;
+ w ,h ,x ,y : int;
+ flip_y : boolean;
+ sl : scanline_ptr;
+ storage : renderer_scanline_ptr );
+var
+ i ,pitch ,j : int;
+
+ buf : int8u_ptr;
+ bits : bitset_iterator;
+
+begin
+ pitch:=shr_int32(w + 31 ,5 ) shl 2;
+ buf :=gbuf;
+
+ sl.reset (x ,x + w );
+ storage.prepare(w + 2 );
+
+ if flip_y then
+ begin
+ inc(ptrcomp(buf ) ,(pitch * (h - 1 ) ) * sizeof(int8u ) );
+ inc(y ,h );
+
+ pitch:=-pitch;
+
+ end;
+
+ i:=0;
+
+ while i < h do
+ begin
+ sl.reset_spans;
+
+ bits.Construct(buf ,0 );
+
+ j:=0;
+
+ while j < w do
+ begin
+ if bits.bit <> 0 then
+ sl.add_cell(x + j ,cover_full );
+
+ bits.inc_operator;
+
+ inc(j );
+
+ end;
+
+ inc(ptrcomp(buf ) ,pitch * sizeof(int8u ) );
+
+ if sl.num_spans <> 0 then
+ begin
+ sl.finalize (y - i - 1 );
+ storage.render(sl );
+
+ end;
+
+ inc(i );
+
+ end;
+
+end;
+
+{ decompose_win32_glyph_bitmap_gray8 }
+procedure decompose_win32_glyph_bitmap_gray8(
+ gbuf : int8u_ptr;
+ w ,h ,x ,y : int;
+ flip_y : boolean;
+ ras : rasterizer_scanline_aa_ptr;
+ sl : scanline_ptr;
+ storage : renderer_scanline_ptr );
+var
+ i ,j ,pitch : int;
+
+ buf ,p : int8u_ptr;
+
+ v : unsigned;
+
+begin
+ pitch:=shr_int32(w + 3 ,2 ) shl 2;
+ buf :=gbuf;
+
+ sl.reset (x ,x + w );
+ storage.prepare(w + 2 );
+
+ if flip_y then
+ begin
+ inc(ptrcomp(buf ) ,(pitch * (h - 1 ) ) * sizeof(int8u ) );
+ inc(y ,h );
+
+ pitch:=-pitch;
+
+ end;
+
+ i:=0;
+
+ while i < h do
+ begin
+ sl.reset_spans;
+
+ p:=buf;
+ j:=0;
+
+ while j < w do
+ begin
+ if p^ <> 0 then
+ begin
+ v:=p^;
+
+ if v = 64 then
+ v:=255
+ else
+ v:=v shl 2;
+
+ sl.add_cell(x + j ,ras.apply_gamma(v ) );
+
+ end;
+
+ inc(ptrcomp(p ) ,sizeof(int8u ) );
+ inc(j );
+
+ end;
+
+ inc(ptrcomp(buf ) ,pitch * sizeof(int8u ) );
+
+ if sl.num_spans <> 0 then
+ begin
+ sl.finalize (y - i - 1 );
+ storage.render(sl );
+
+ end;
+
+ inc(i );
+
+ end;
+
+end;
+
+{ decompose_win32_glyph_outline }
+function decompose_win32_glyph_outline(
+ gbuf : int8u_ptr;
+ total_size : unsigned;
+ flip_y : boolean;
+ mtx : trans_affine_ptr;
+ path : path_storage_integer_ptr ) : boolean;
+var
+ cur_glyph ,end_glyph ,end_poly ,cur_poly : int8u_ptr;
+
+ x ,y ,x2 ,y2 : double;
+
+ i ,u : int;
+
+ th : TTPOLYGONHEADER_ptr;
+ pc : TTPOLYCURVE_ptr;
+
+ pnt_b ,pnt_c : POINTFX;
+
+ cx ,cy ,bx ,by : int;
+
+begin
+ cur_glyph:=gbuf;
+ end_glyph:=int8u_ptr(ptrcomp(gbuf ) + total_size * sizeof(int8u ) );
+
+ while ptrcomp(cur_glyph ) < ptrcomp(end_glyph ) do
+ begin
+ th:=TTPOLYGONHEADER_ptr(cur_glyph );
+
+ end_poly:=int8u_ptr(ptrcomp(cur_glyph ) + th.cb );
+ cur_poly:=int8u_ptr(ptrcomp(cur_glyph ) + sizeof(TTPOLYGONHEADER ) );
+
+ x:=fx_to_dbl(@th.pfxStart.x );
+ y:=fx_to_dbl(@th.pfxStart.y );
+
+ if flip_y then
+ y:=-y;
+
+ mtx.transform(mtx ,@x ,@y );
+ path.move_to (dbl_to_int26p6(x ) ,dbl_to_int26p6(y ) );
+
+ while ptrcomp(cur_poly ) < ptrcomp(end_poly ) do
+ begin
+ pc:=TTPOLYCURVE_ptr(cur_poly );
+
+ if pc.wType = TT_PRIM_LINE then
+ begin
+ i:=0;
+
+ while i < pc.cpfx do
+ begin
+ x:=fx_to_dbl(@POINTFX_ptr(ptrcomp(@pc.apfx ) + i * sizeof(POINTFX ) ).x );
+ y:=fx_to_dbl(@POINTFX_ptr(ptrcomp(@pc.apfx ) + i * sizeof(POINTFX ) ).y );
+
+ if flip_y then
+ y:=-y;
+
+ mtx.transform(mtx ,@x ,@y );
+ path.line_to (dbl_to_int26p6(x ) ,dbl_to_int26p6(y ) );
+
+ inc(i );
+
+ end;
+
+ end;
+
+ if pc.wType = TT_PRIM_QSPLINE then
+ begin
+ u:=0;
+
+ while u < pc.cpfx - 1 do // Walk through points in spline
+ begin
+ // B is always the current point
+ pnt_b:=POINTFX_ptr(ptrcomp(@pc.apfx ) + u * sizeof(POINTFX ) )^;
+ pnt_c:=POINTFX_ptr(ptrcomp(@pc.apfx ) + (u + 1 ) * sizeof(POINTFX ) )^;
+
+ if u < pc.cpfx - 2 then // If not on last spline, compute C
+ begin
+ // midpoint (x,y)
+ // int(pnt_c.x ):=int(pnt_b.x ) + int(pnt_c.x ) div 2;
+ // int(pnt_c.y ):=int(pnt_b.y ) + int(pnt_c.y ) div 2;
+ move(pnt_b.x ,bx ,sizeof(int ) );
+ move(pnt_b.y ,by ,sizeof(int ) );
+ move(pnt_c.x ,cx ,sizeof(int ) );
+ move(pnt_c.y ,cy ,sizeof(int ) );
+
+ cx:=(bx + cx ) div 2;
+ cy:=(by + cy ) div 2;
+
+ move(cx ,pnt_c.x ,sizeof(int ) );
+ move(cy ,pnt_c.y ,sizeof(int ) );
+
+ end;
+
+ x :=fx_to_dbl(@pnt_b.x );
+ y :=fx_to_dbl(@pnt_b.y );
+ x2:=fx_to_dbl(@pnt_c.x );
+ y2:=fx_to_dbl(@pnt_c.y );
+
+ if flip_y then
+ begin
+ y :=-y;
+ y2:=-y2;
+
+ end;
+
+ mtx.transform(mtx ,@x ,@y );
+ mtx.transform(mtx ,@x2 ,@y2 );
+
+ path.curve3(
+ dbl_to_int26p6(x ) ,dbl_to_int26p6(y ) ,
+ dbl_to_int26p6(x2 ) ,dbl_to_int26p6(y2 ) );
+
+ inc(u );
+
+ end;
+
+ end;
+
+ inc(ptrcomp(cur_poly ) ,sizeof(WORD ) * 2 + sizeof(POINTFX ) * pc.cpfx );
+
+ end;
+
+ inc(ptrcomp(cur_glyph ) ,th.cb );
+
+ end;
+
+ result:=true;
+
+end;
+
+{ CONSTRUCT }
+constructor font_engine_win32_tt_base.Construct;
+begin
+ m_flag32:=flag32_;
+ m_dc :=dc;
+
+ if m_dc <> 0 then
+ m_old_font:=GetCurrentObject(m_dc ,OBJ_FONT )
+ else
+ m_old_font:=0;
+
+ agg_getmem(pointer(m_fonts ) ,sizeof(HFONT ) * max_fonts );
+
+ m_num_fonts:=0;
+ m_max_fonts:=max_fonts;
+
+ agg_getmem(pointer(m_font_names ) ,sizeof(font_name ) * max_fonts );
+
+ m_cur_font :=0;
+ m_change_stamp:=0;
+
+ m_typeface.size:=sizeof(char ) * (256 - 16 );
+
+ agg_getmem(pointer(m_typeface.name ) ,m_typeface.size );
+
+ m_typeface_len:=256 - 16 - 1;
+
+ m_signature.size:=sizeof(char ) * (256 + 256 - 16 );
+
+ agg_getmem(pointer(m_signature.name ) ,m_signature.size );
+
+ m_height :=0;
+ m_width :=0;
+ m_weight :=FW_REGULAR;
+ m_italic :=false;
+ m_char_set:=DEFAULT_CHARSET;
+
+ m_pitch_and_family:=FF_DONTCARE;
+
+ m_hinting:=true;
+ m_flip_y :=false;
+
+ m_font_created :=false;
+ m_resolution :=0;
+ m_glyph_rendering:=glyph_ren_native_gray8;
+
+ m_glyph_index:=0;
+ m_data_size :=0;
+ m_data_type :=glyph_data_invalid;
+
+ m_bounds.Construct(1 ,1 ,0 ,0 );
+
+ m_advance_x:=0.0;
+ m_advance_y:=0.0;
+
+ agg_getmem(pointer(m_gbuf ) ,sizeof(int8u ) * buf_size );
+
+ m_kerning_pairs :=NIL;
+ m_num_kerning_pairs:=0;
+ m_max_kerning_pairs:=0;
+
+ m_affine.Construct;
+
+ m_path16.Construct;
+ m_path32.Construct;
+ m_curves16.Construct(@m_path16 );
+ m_curves32.Construct(@m_path32 );
+ m_scanline_aa.Construct;
+ m_scanline_bin.Construct;
+ m_scanlines_aa.Construct;
+ m_scanlines_bin.Construct;
+ m_rasterizer.Construct;
+
+ m_curves16.approximation_scale_(4.0 );
+ m_curves32.approximation_scale_(4.0 );
+
+ fillchar(m_matrix ,sizeof(m_matrix ) ,0 );
+
+ m_matrix.eM11.value:=1;
+ m_matrix.eM22.value:=1;
+
+end;
+
+{ DESTRUCT }
+destructor font_engine_win32_tt_base.Destruct;
+var
+ i : unsigned;
+ f : HFONT_ptr;
+ n : font_name_ptr;
+
+begin
+ agg_freemem(pointer(m_kerning_pairs ) ,m_max_kerning_pairs * sizeof(KERNINGPAIR ) );
+ agg_freemem(pointer(m_gbuf ) ,sizeof(int8u ) * buf_size );
+ agg_freemem(pointer(m_signature.name ) ,m_signature.size );
+ agg_freemem(pointer(m_typeface.name ) ,m_typeface.size );
+
+ if (m_dc <> 0 ) and
+ (m_old_font <> 0 ) then
+ SelectObject(m_dc ,m_old_font );
+
+ i:=0;
+ f:=m_fonts;
+ n:=m_font_names;
+
+ while i < m_num_fonts do
+ begin
+ agg_freemem (pointer(n.name ) ,n.size );
+ DeleteObject(f^ );
+
+ inc(ptrcomp(n ) ,sizeof(font_name ) );
+ inc(ptrcomp(f ) ,sizeof(HFONT ) );
+ inc(i );
+
+ end;
+
+ agg_freemem(pointer(m_font_names ) ,sizeof(font_name ) * m_max_fonts );
+ agg_freemem(pointer(m_fonts ) ,sizeof(HFONT ) * m_max_fonts );
+
+ m_path16.Destruct;
+ m_path32.Destruct;
+ m_curves16.Destruct;
+ m_curves32.Destruct;
+ m_scanline_aa.Destruct;
+ m_scanline_bin.Destruct;
+ m_scanlines_aa.Destruct;
+ m_scanlines_bin.Destruct;
+ m_rasterizer.Destruct;
+
+end;
+
+{ RESOLUTION_ }
+procedure font_engine_win32_tt_base.resolution_;
+begin
+ m_resolution:=dpi;
+
+end;
+
+{ HEIGHT_ }
+procedure font_engine_win32_tt_base.height_;
+begin
+ m_height:=trunc(h );
+
+end;
+
+{ WIDTH_ }
+procedure font_engine_win32_tt_base.width_;
+begin
+ m_width:=trunc(w );
+
+end;
+
+{ WEIGHT_ }
+procedure font_engine_win32_tt_base.weight_;
+begin
+ m_weight:=w;
+
+end;
+
+{ ITALIC_ }
+procedure font_engine_win32_tt_base.italic_;
+begin
+ m_italic:=it;
+
+end;
+
+{ CHAR_SET_ }
+procedure font_engine_win32_tt_base.char_set_;
+begin
+ m_char_set:=c;
+
+end;
+
+{ PITCH_AND_FAMILY_ }
+procedure font_engine_win32_tt_base.pitch_and_family_;
+begin
+ m_pitch_and_family:=p;
+
+end;
+
+{ FLIP_Y_ }
+procedure font_engine_win32_tt_base.flip_y_;
+begin
+ m_flip_y:=flip;
+
+end;
+
+{ HINTING_ }
+procedure font_engine_win32_tt_base.hinting_;
+begin
+ m_hinting:=h;
+
+end;
+
+{ CREATE_FONT }
+function font_engine_win32_tt_base.create_font;
+var
+ len : unsigned;
+
+ h ,w ,idx : int;
+
+ f : HFONT_ptr;
+ n : font_name_ptr;
+
+begin
+ if m_dc <> 0 then
+ begin
+ len:=StrLen(typeface_ );
+
+ if len > m_typeface_len then
+ begin
+ agg_freemem(pointer(m_signature.name ) ,m_signature.size );
+ agg_freemem(pointer(m_typeface.name ) ,m_typeface.size );
+
+ m_typeface.size :=sizeof(char ) * (len + 32 );
+ m_signature.size:=sizeof(char ) * (len + 32 + 256 );
+
+ agg_getmem(pointer(m_typeface.name ) ,m_typeface.size );
+ agg_getmem(pointer(m_signature.name ) ,m_signature.size );
+
+ m_typeface_len:=len + 32 - 1;
+
+ end;
+
+ StrCopy(PChar(m_typeface.name ) ,typeface_ );
+
+ h:=m_height;
+ w:=m_width;
+
+ if m_resolution <> 0 then
+ begin
+ h:=MulDiv(m_height ,m_resolution ,72 );
+ w:=MulDiv(m_width ,m_resolution ,72 );
+
+ end;
+
+ m_glyph_rendering:=ren_type;
+
+ update_signature;
+
+ idx:=find_font(PChar(m_signature.name ) );
+
+ if idx >= 0 then
+ begin
+ m_cur_font:=HFONT_ptr(ptrcomp(m_fonts ) + idx * sizeof(HFONT ) )^;
+
+ SelectObject(m_dc ,m_cur_font );
+
+ m_num_kerning_pairs:=0;
+
+ result:=true;
+
+ exit;
+
+ end
+ else
+ begin
+ m_cur_font:=
+ CreateFont(
+ -h , // height of font
+ w , // average character width
+ 0 , // angle of escapement
+ 0 , // base-line orientation angle
+ m_weight , // font weight
+ unsigned(m_italic ) , // italic attribute option
+ 0 , // underline attribute option
+ 0 , // strikeout attribute option
+ m_char_set , // character set identifier
+ OUT_DEFAULT_PRECIS , // output precision
+ CLIP_DEFAULT_PRECIS , // clipping precision
+ ANTIALIASED_QUALITY , // output quality
+ m_pitch_and_family , // pitch and family
+ PChar(m_typeface.name ) // typeface name
+ );
+
+ if m_cur_font <> 0 then
+ begin
+ if m_num_fonts >= m_max_fonts then
+ begin
+ agg_freemem(pointer(m_font_names.name ) ,m_font_names.size );
+
+ if m_old_font <> 0 then
+ SelectObject(m_dc ,m_old_font );
+
+ DeleteObject(m_fonts^ );
+
+ move(
+ HFONT_ptr(ptrcomp(m_fonts ) + 1 * sizeof(HFONT ) )^ ,
+ m_fonts^ ,
+ (m_max_fonts - 1 ) * sizeof(HFONT ) );
+
+ move(
+ font_name_ptr(ptrcomp(m_font_names ) + 1 * sizeof(font_name ) )^ ,
+ m_font_names^ ,
+ (m_max_fonts - 1 ) * sizeof(font_name ) );
+
+ m_num_fonts:=m_max_fonts - 1;
+
+ end;
+
+ update_signature;
+
+ n:=font_name_ptr(ptrcomp(m_font_names ) + m_num_fonts * sizeof(font_name ) );
+ f:=HFONT_ptr(ptrcomp(m_fonts ) + m_num_fonts * sizeof(HFONT ) );
+
+ n.size:=sizeof(char ) * (StrLen(PChar(m_signature.name ) ) + 1 );
+
+ agg_getmem(pointer(n.name ) ,n.size );
+ StrCopy (PChar(n.name ) ,PChar(m_signature.name ) );
+
+ f^:=m_cur_font;
+
+ inc(m_num_fonts );
+
+ SelectObject(m_dc ,m_cur_font );
+
+ m_num_kerning_pairs:=0;
+
+ result:=true;
+
+ exit;
+
+ end;
+
+ end;
+
+ end;
+
+ result:=false;
+
+end;
+
+{ CREATE_FONT_ }
+function font_engine_win32_tt_base.create_font_;
+begin
+ height_ (height );
+ width_ (width );
+ weight_ (weight );
+ italic_ (italic );
+ char_set_(char_set );
+
+ pitch_and_family_(pitch_and_family );
+
+ result:=create_font(typeface ,ren_type );
+
+end;
+
+{ GAMMA_ }
+procedure font_engine_win32_tt_base.gamma_;
+begin
+ m_rasterizer.gamma(f );
+
+end;
+
+{ TRANSFORM_ }
+procedure font_engine_win32_tt_base.transform_;
+begin
+ m_affine.assign_all(mtx );
+
+end;
+
+{ _RESOLUTION }
+function font_engine_win32_tt_base._resolution;
+begin
+ result:=m_resolution;
+
+end;
+
+{ _TYPEFACE }
+function font_engine_win32_tt_base._typeface;
+begin
+ result:=PChar(m_typeface.name );
+
+end;
+
+{ _HEIGHT }
+function font_engine_win32_tt_base._height;
+begin
+ result:=m_height;
+
+end;
+
+{ _WIDTH }
+function font_engine_win32_tt_base._width;
+begin
+ result:=m_width;
+
+end;
+
+{ _WEIGHT }
+function font_engine_win32_tt_base._weight;
+begin
+ result:=m_weight;
+
+end;
+
+{ _ITALIC }
+function font_engine_win32_tt_base._italic;
+begin
+ result:=m_italic;
+
+end;
+
+{ _CHAR_SET }
+function font_engine_win32_tt_base._char_set;
+begin
+ result:=m_char_set;
+
+end;
+
+{ _PITCH_AND_FAMILY }
+function font_engine_win32_tt_base._pitch_and_family;
+begin
+ result:=m_pitch_and_family;
+
+end;
+
+{ _HINTING }
+function font_engine_win32_tt_base._hinting;
+begin
+ result:=m_hinting;
+
+end;
+
+{ _FLIP_Y }
+function font_engine_win32_tt_base._flip_y;
+begin
+ result:=m_flip_y;
+
+end;
+
+{ FONT_SIGNATURE }
+function font_engine_win32_tt_base.font_signature;
+begin
+ result:=PChar(m_signature.name );
+
+end;
+
+{ CHANGE_STAMP }
+function font_engine_win32_tt_base.change_stamp;
+begin
+ result:=m_change_stamp;
+
+end;
+
+{ PREPARE_GLYPH }
+function font_engine_win32_tt_base.prepare_glyph;
+const
+ GGO_UNHINTED = $0100; // For compatibility with old SDKs.
+
+var
+ format ,total_size : int;
+
+ gm : TGLYPHMETRICS;
+ fl : longint;
+ ts : DWORD;
+
+ bnd : rect_d;
+
+begin
+ if (m_dc <> 0 ) and
+ (m_cur_font <> 0 ) then
+ begin
+ format:=GGO_BITMAP;
+
+ case m_glyph_rendering of
+ glyph_ren_native_gray8 :
+ format:=GGO_GRAY8_BITMAP;
+
+ glyph_ren_outline ,
+ glyph_ren_agg_mono ,
+ glyph_ren_agg_gray8 :
+ format:=GGO_NATIVE;
+
+ end;
+
+ if not m_hinting then
+ format:=format or GGO_UNHINTED;
+
+ ts:=
+ GetGlyphOutlineX(
+ m_dc ,
+ glyph_code ,
+ format ,
+ gm ,
+ buf_size ,
+ m_gbuf ,
+ m_matrix );
+
+ move(ts ,total_size ,sizeof(int ) );
+
+ if total_size < 0 then
+ begin
+ // GetGlyphOutline() fails when being called for
+ // GGO_GRAY8_BITMAP and white space (stupid Microsoft).
+ // It doesn't even initialize the glyph metrics
+ // structure. So, we have to query the metrics
+ // separately (basically we need gmCellIncX).
+ ts:=
+ GetGlyphOutlineX(
+ m_dc ,
+ glyph_code ,
+ GGO_METRICS ,
+ gm ,
+ buf_size ,
+ m_gbuf ,
+ m_matrix );
+
+ move(ts ,total_size ,sizeof(int ) );
+
+ if total_size < 0 then
+ begin
+ result:=false;
+
+ exit;
+
+ end;
+
+ gm.gmBlackBoxX:=0;
+ gm.gmBlackBoxY:=0;
+
+ total_size:=0;
+
+ end;
+
+ m_glyph_index:=glyph_code;
+ m_advance_x :=gm.gmCellIncX;
+ m_advance_y :=-gm.gmCellIncY;
+
+ case m_glyph_rendering of
+ glyph_ren_native_mono :
+ begin
+ if m_flip_y then
+ fl:=-gm.gmptGlyphOrigin.y
+ else
+ fl:=gm.gmptGlyphOrigin.y;
+
+ decompose_win32_glyph_bitmap_mono(
+ m_gbuf ,
+ gm.gmBlackBoxX ,
+ gm.gmBlackBoxY ,
+ gm.gmptGlyphOrigin.x ,
+ fl ,
+ m_flip_y ,
+ @m_scanline_bin ,
+ @m_scanlines_bin );
+
+ m_bounds.x1:=m_scanlines_bin._min_x;
+ m_bounds.y1:=m_scanlines_bin._min_y;
+ m_bounds.x2:=m_scanlines_bin._max_x;
+ m_bounds.y2:=m_scanlines_bin._max_y;
+ m_data_size:=m_scanlines_bin.byte_size;
+ m_data_type:=glyph_data_mono;
+
+ result:=true;
+
+ exit;
+
+ end;
+
+ glyph_ren_native_gray8 :
+ begin
+ if m_flip_y then
+ fl:=-gm.gmptGlyphOrigin.y
+ else
+ fl:=gm.gmptGlyphOrigin.y;
+
+ decompose_win32_glyph_bitmap_gray8(
+ m_gbuf ,
+ gm.gmBlackBoxX ,
+ gm.gmBlackBoxY ,
+ gm.gmptGlyphOrigin.x ,
+ fl ,
+ m_flip_y ,
+ @m_rasterizer ,
+ @m_scanline_aa ,
+ @m_scanlines_aa );
+
+ m_bounds.x1:=m_scanlines_aa._min_x;
+ m_bounds.y1:=m_scanlines_aa._min_y;
+ m_bounds.x2:=m_scanlines_aa._max_x;
+ m_bounds.y2:=m_scanlines_aa._max_y;
+ m_data_size:=m_scanlines_aa.byte_size;
+ m_data_type:=glyph_data_gray8;
+
+ result:=true;
+
+ exit;
+
+ end;
+
+ glyph_ren_outline :
+ begin
+ m_affine.transform(@m_affine ,@m_advance_x ,@m_advance_y );
+
+ if m_flag32 then
+ begin
+ m_path32.remove_all;
+
+ if decompose_win32_glyph_outline(
+ m_gbuf ,
+ total_size ,
+ m_flip_y ,
+ @m_affine ,
+ @m_path32 ) then
+ begin
+ bnd:=m_path32.bounding_rect;
+
+ m_data_size:=m_path32.byte_size;
+ m_data_type:=glyph_data_outline;
+ m_bounds.x1:=Floor(bnd.x1 );
+ m_bounds.y1:=Floor(bnd.y1 );
+ m_bounds.x2:=Ceil(bnd.x2 );
+ m_bounds.y2:=Ceil(bnd.y2 );
+
+ result:=true;
+
+ exit;
+
+ end;
+
+ end
+ else
+ begin
+ m_path16.remove_all;
+
+ if decompose_win32_glyph_outline(
+ m_gbuf ,
+ total_size ,
+ m_flip_y ,
+ @m_affine ,
+ @m_path16 ) then
+ begin
+ bnd:=m_path16.bounding_rect;
+
+ m_data_size:=m_path16.byte_size;
+ m_data_type:=glyph_data_outline;
+ m_bounds.x1:=Floor(bnd.x1 );
+ m_bounds.y1:=Floor(bnd.y1 );
+ m_bounds.x2:=Ceil(bnd.x2 );
+ m_bounds.y2:=Ceil(bnd.y2 );
+
+ result:=true;
+
+ exit;
+
+ end;
+
+ end;
+
+ end;
+
+ glyph_ren_agg_mono :
+ begin
+ m_rasterizer.reset;
+ m_affine.transform(@m_affine ,@m_advance_x ,@m_advance_y );
+
+ if m_flag32 then
+ begin
+ m_path32.remove_all;
+
+ decompose_win32_glyph_outline(
+ m_gbuf ,
+ total_size ,
+ m_flip_y ,
+ @m_affine ,
+ @m_path32 );
+
+ m_rasterizer.add_path(@m_curves32 );
+
+ end
+ else
+ begin
+ m_path16.remove_all;
+
+ decompose_win32_glyph_outline(
+ m_gbuf ,
+ total_size ,
+ m_flip_y ,
+ @m_affine ,
+ @m_path16 );
+
+ m_rasterizer.add_path(@m_curves16 );
+
+ end;
+
+ m_scanlines_bin.prepare(1 ); // Remove all
+
+ render_scanlines(@m_rasterizer ,@m_scanline_bin ,@m_scanlines_bin );
+
+ m_bounds.x1:=m_scanlines_bin._min_x;
+ m_bounds.y1:=m_scanlines_bin._min_y;
+ m_bounds.x2:=m_scanlines_bin._max_x;
+ m_bounds.y2:=m_scanlines_bin._max_y;
+ m_data_size:=m_scanlines_bin.byte_size;
+ m_data_type:=glyph_data_mono;
+
+ result:=true;
+
+ exit;
+
+ end;
+
+ glyph_ren_agg_gray8 :
+ begin
+ m_rasterizer.reset;
+ m_affine.transform(@m_affine ,@m_advance_x ,@m_advance_y );
+
+ if m_flag32 then
+ begin
+ m_path32.remove_all;
+
+ decompose_win32_glyph_outline(
+ m_gbuf ,
+ total_size ,
+ m_flip_y ,
+ @m_affine ,
+ @m_path32 );
+
+ m_rasterizer.add_path(@m_curves32 );
+
+ end
+ else
+ begin
+ m_path16.remove_all;
+
+ decompose_win32_glyph_outline(
+ m_gbuf ,
+ total_size,
+ m_flip_y ,
+ @m_affine ,
+ @m_path16 );
+
+ m_rasterizer.add_path(@m_curves16 );
+
+ end;
+
+ m_scanlines_aa.prepare(1 ); // Remove all
+
+ render_scanlines(@m_rasterizer ,@m_scanline_aa ,@m_scanlines_aa );
+
+ m_bounds.x1:=m_scanlines_aa._min_x;
+ m_bounds.y1:=m_scanlines_aa._min_y;
+ m_bounds.x2:=m_scanlines_aa._max_x;
+ m_bounds.y2:=m_scanlines_aa._max_y;
+ m_data_size:=m_scanlines_aa.byte_size;
+ m_data_type:=glyph_data_gray8;
+
+ result:=true;
+
+ exit;
+
+ end;
+
+ end;
+
+ end;
+
+ result:=false;
+
+end;
+
+{ GLYPH_INDEX }
+function font_engine_win32_tt_base.glyph_index;
+begin
+ result:=m_glyph_index;
+
+end;
+
+{ DATA_SIZE }
+function font_engine_win32_tt_base.data_size;
+begin
+ result:=m_data_size;
+
+end;
+
+{ DATA_TYPE }
+function font_engine_win32_tt_base.data_type;
+begin
+ result:=m_data_type;
+
+end;
+
+{ BOUNDS }
+function font_engine_win32_tt_base.bounds;
+begin
+ result:=@m_bounds;
+
+end;
+
+{ ADVANCE_X }
+function font_engine_win32_tt_base.advance_x;
+begin
+ result:=m_advance_x;
+
+end;
+
+{ ADVANCE_Y }
+function font_engine_win32_tt_base.advance_y;
+begin
+ result:=m_advance_y;
+
+end;
+
+{ WRITE_GLYPH_TO }
+procedure font_engine_win32_tt_base.write_glyph_to;
+begin
+ if (data <> NIL ) and
+ (m_data_size <> 0 ) then
+ case m_data_type of
+ glyph_data_mono :
+ m_scanlines_bin.serialize(data );
+
+ glyph_data_gray8 :
+ m_scanlines_aa.serialize(data );
+
+ glyph_data_outline :
+ if m_flag32 then
+ m_path32.serialize(data )
+ else
+ m_path16.serialize(data );
+
+ end;
+
+end;
+
+{ ADD_KERNING }
+function font_engine_win32_tt_base.add_kerning;
+var
+ end_ ,beg_ ,mid : int;
+
+ dx ,dy : double;
+
+ t : KERNINGPAIR;
+ kp : KERNINGPAIR_ptr;
+
+begin
+ if (m_dc <> 0 ) and
+ (m_cur_font <> 0 ) then
+ begin
+ if m_num_kerning_pairs = 0 then
+ load_kerning_pairs;
+
+ end_:=m_num_kerning_pairs; dec(end_ );
+ beg_:=0;
+
+ t.wFirst :=WORD(first );
+ t.wSecond:=WORD(second );
+
+ while beg_ <= end_ do
+ begin
+ mid:=(end_ + beg_ ) div 2;
+ kp :=KERNINGPAIR_ptr(ptrcomp(m_kerning_pairs ) + mid * sizeof(KERNINGPAIR ) );
+
+ if (kp.wFirst = t.wFirst ) and
+ (kp.wSecond = t.wSecond ) then
+ begin
+ dx:=kp.iKernAmount;
+ dy:=0.0;
+
+ if (m_glyph_rendering = glyph_ren_outline ) or
+ (m_glyph_rendering = glyph_ren_agg_mono ) or
+ (m_glyph_rendering = glyph_ren_agg_gray8 ) then
+ m_affine.transform_2x2(@m_affine ,@dx ,@dy );
+
+ x^:=x^ + dx;
+ y^:=y^ + dy;
+
+ result:=true;
+
+ exit;
+
+ end
+ else
+ if pair_less(@t ,kp ) then
+ end_:=mid - 1
+ else
+ beg_:=mid + 1;
+
+ end;
+
+ end;
+
+ result:=false;
+
+end;
+
+{ FLAG32 }
+function font_engine_win32_tt_base.flag32;
+begin
+ result:=m_flag32;
+
+end;
+
+{ UPDATE_SIGNATURE }
+procedure font_engine_win32_tt_base.update_signature;
+var
+ gamma_hash ,i : unsigned;
+
+ gamma_table : array[0..aa_num - 1 ] of int8u;
+
+ mtx : array[0..5 ] of double;
+ buf : array[0..99 ] of char;
+ str : char_ptr;
+
+begin
+ m_signature.name^:=#0;
+
+ if (m_dc <> 0 ) and
+ (m_cur_font <> 0 ) then
+ begin
+ gamma_hash:=0;
+
+ if (m_glyph_rendering = glyph_ren_native_gray8 ) or
+ (m_glyph_rendering = glyph_ren_agg_mono ) or
+ (m_glyph_rendering = glyph_ren_agg_gray8 ) then
+ begin
+ for i:=0 to aa_num - 1 do
+ gamma_table[i ]:=m_rasterizer.apply_gamma(i );
+
+ gamma_hash:=calc_crc32(@gamma_table ,sizeof(gamma_table ) );
+
+ end;
+
+ str:=m_signature.name;
+
+ sprintf(str ,'%s,' ,ptrcomp(m_typeface.name ) );
+ sprintf(char_ptr(ptrcomp(str ) + StrLen(PChar(str ) ) ) ,'%u,' ,m_char_set );
+ sprintf(char_ptr(ptrcomp(str ) + StrLen(PChar(str ) ) ) ,'%d,' ,int(m_glyph_rendering ) );
+ sprintf(char_ptr(ptrcomp(str ) + StrLen(PChar(str ) ) ) ,'%d:' ,m_resolution );
+ sprintf(char_ptr(ptrcomp(str ) + StrLen(PChar(str ) ) ) ,'%dx' ,m_height );
+ sprintf(char_ptr(ptrcomp(str ) + StrLen(PChar(str ) ) ) ,'%d,' ,m_width );
+ sprintf(char_ptr(ptrcomp(str ) + StrLen(PChar(str ) ) ) ,'%d,' ,m_weight );
+ sprintf(char_ptr(ptrcomp(str ) + StrLen(PChar(str ) ) ) ,'%d,' ,int(m_italic ) );
+ sprintf(char_ptr(ptrcomp(str ) + StrLen(PChar(str ) ) ) ,'%d,' ,int(m_hinting) );
+ sprintf(char_ptr(ptrcomp(str ) + StrLen(PChar(str ) ) ) ,'%d,' ,int(m_flip_y ) );
+ sprintf(char_ptr(ptrcomp(str ) + StrLen(PChar(str ) ) ) ,'%d,' ,int(m_pitch_and_family ) );
+ sprintf(char_ptr(ptrcomp(str ) + StrLen(PChar(str ) ) ) ,'%08X' ,gamma_hash );
+
+ if (m_glyph_rendering = glyph_ren_outline ) or
+ (m_glyph_rendering = glyph_ren_agg_mono ) or
+ (m_glyph_rendering = glyph_ren_agg_gray8 ) then
+ begin
+ m_affine.store_to(@mtx );
+
+ sprintf(@buf[0 ] ,',%08X' ,dbl_to_plain_fx(mtx[0 ] ) );
+ sprintf(@buf[StrLen(@buf[0 ] ) ] ,'%08X' ,dbl_to_plain_fx(mtx[1 ] ) );
+ sprintf(@buf[StrLen(@buf[0 ] ) ] ,'%08X' ,dbl_to_plain_fx(mtx[2 ] ) );
+ sprintf(@buf[StrLen(@buf[0 ] ) ] ,'%08X' ,dbl_to_plain_fx(mtx[3 ] ) );
+ sprintf(@buf[StrLen(@buf[0 ] ) ] ,'%08X' ,dbl_to_plain_fx(mtx[4 ] ) );
+ sprintf(@buf[StrLen(@buf[0 ] ) ] ,'%08X' ,dbl_to_plain_fx(mtx[5 ] ) );
+
+ StrCat(PChar(m_signature.name ) ,buf );
+
+ end;
+
+ inc(m_change_stamp );
+
+ end;
+
+end;
+
+{ PAIR_LESS }
+function font_engine_win32_tt_base.pair_less;
+begin
+ if v1.wFirst <> v2.wFirst then
+ result:=v1.wFirst < v2.wFirst
+ else
+ result:=v1.wSecond < v2.wSecond;
+
+end;
+
+{ LOAD_KERNING_PAIRS }
+procedure font_engine_win32_tt_base.load_kerning_pairs;
+var
+ i : unsigned;
+
+begin
+ if (m_dc <> 0 ) and
+ (m_cur_font <> 0 ) then
+ begin
+ if m_kerning_pairs = NIL then
+ begin
+ m_max_kerning_pairs:=16384 - 16;
+
+ agg_getmem(pointer(m_kerning_pairs ) ,m_max_kerning_pairs * sizeof(KERNINGPAIR ) );
+
+ end;
+
+ m_num_kerning_pairs:=
+ GetKerningPairs(m_dc ,m_max_kerning_pairs ,m_kerning_pairs^ );
+
+ if m_num_kerning_pairs <> 0 then
+ begin
+ // Check to see if the kerning pairs are sorted and
+ // sort them if they are not.
+ i:=1;
+
+ while i < m_num_kerning_pairs do
+ begin
+ if not pair_less(
+ KERNINGPAIR_ptr(ptrcomp(m_kerning_pairs ) + (i - 1 ) * sizeof(KERNINGPAIR ) ) ,
+ KERNINGPAIR_ptr(ptrcomp(m_kerning_pairs ) + i * sizeof(KERNINGPAIR ) ) ) then
+ begin
+ sort_kerning_pairs;
+
+ break;
+
+ end;
+
+ inc(i );
+
+ end;
+
+ end;
+
+ end;
+
+end;
+
+{ _pair_less }
+function _pair_less(v1 ,v2 : KERNINGPAIR_ptr ) : boolean;
+begin
+ if v1.wFirst <> v2.wFirst then
+ result:=v1.wFirst < v2.wFirst
+ else
+ result:=v1.wSecond < v2.wSecond;
+
+end;
+
+{ SORT_KERNING_PAIRS }
+procedure font_engine_win32_tt_base.sort_kerning_pairs;
+var
+ pairs : pod_array_adaptor;
+
+begin
+ pairs.Construct(m_kerning_pairs ,m_num_kerning_pairs ,sizeof(KERNINGPAIR ) );
+
+ quick_sort(@pairs ,@_pair_less );
+
+end;
+
+{ FIND_FONT }
+function font_engine_win32_tt_base.find_font;
+var
+ i : unsigned;
+ n : font_name_ptr;
+
+begin
+ n:=m_font_names;
+ i:=0;
+
+ while i < m_num_fonts do
+ begin
+ if StrComp(name ,PChar(n.name ) ) = 0 then
+ begin
+ result:=i;
+
+ exit;
+
+ end;
+
+ inc(ptrcomp(n ) ,sizeof(font_name ) );
+ inc(i );
+
+ end;
+
+ result:=-1;
+
+end;
+
+{ CONSTRUCT }
+constructor font_engine_win32_tt_int16.Construct;
+begin
+ inherited Construct(false ,dc ,max_fonts );
+
+end;
+
+{ CONSTRUCT }
+constructor font_engine_win32_tt_int32.Construct;
+begin
+ inherited Construct(true ,dc ,max_fonts );
+
+end;
+
+{ UNIT CONSTRUCTOR }
+INITIALIZATION
+{$IFDEF AGG_WIN9X_COMPLIANT }
+ GetGlyphOutlineX:=@GetGlyphOutline;
+
+{$ELSE }
+ GetGlyphOutlineX:=@GetGlyphOutlineW;
+
+{$ENDIF }
+
+END.
+
diff --git a/src/corelib/render/software/agg_gamma_functions.pas b/src/corelib/render/software/agg_gamma_functions.pas
new file mode 100644
index 00000000..253995b2
--- /dev/null
+++ b/src/corelib/render/software/agg_gamma_functions.pas
@@ -0,0 +1,297 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 15.01.2006-Milano: Unit port establishment
+//
+{ agg_gamma_functions.pas }
+unit
+ agg_gamma_functions ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ Math ,
+ agg_basics ,
+ agg_vertex_source ;
+
+{ TYPES DEFINITION }
+type
+ gamma_none = object(vertex_source )
+ end;
+
+ gamma_power = object(vertex_source )
+ m_gamma : double;
+
+ constructor Construct; overload;
+ constructor Construct(g : double ); overload;
+
+ procedure gamma_(g : double );
+ function _gamma : double;
+
+ function func_operator_gamma(x : double ) : double; virtual;
+
+ end;
+
+ gamma_threshold = object(vertex_source )
+ m_threshold : double;
+
+ constructor Construct; overload;
+ constructor Construct(t : double ); overload;
+
+ procedure threshold_(t : double );
+ function _threshold : double;
+
+ function func_operator_gamma(x : double ) : double; virtual;
+
+ end;
+
+ gamma_linear = object(vertex_source )
+ m_start ,
+ m_end : double;
+
+ constructor Construct; overload;
+ constructor Construct(s ,e : double ); overload;
+
+ procedure set_ (s ,e : double );
+ procedure start_(s : double );
+ procedure end_ (e : double );
+
+ function _start : double;
+ function _end : double;
+
+ function func_operator_gamma(x : double ) : double; virtual;
+
+ end;
+
+ gamma_multiply = object(vertex_source )
+ m_mul : double;
+
+ constructor Construct; overload;
+ constructor Construct(v : double ); overload;
+
+ procedure value_(v : double );
+ function _value : double;
+
+ function func_operator_gamma(x : double ) : double; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor gamma_power.Construct;
+begin
+ m_gamma:=1.0;
+
+end;
+
+{ CONSTRUCT }
+constructor gamma_power.Construct(g : double );
+begin
+ m_gamma:=g;
+
+end;
+
+{ GAMMA_ }
+procedure gamma_power.gamma_;
+begin
+ m_gamma:=g;
+
+end;
+
+{ _GAMMA }
+function gamma_power._gamma;
+begin
+ result:=m_gamma;
+
+end;
+
+{ FUNC_OPERATOR_GAMMA }
+function gamma_power.func_operator_gamma;
+begin
+ try
+ result:=power(x ,m_gamma );
+
+ except
+ result:=1;
+
+ end;
+
+end;
+
+{ CONSTRUCT }
+constructor gamma_threshold.Construct;
+begin
+ m_threshold:=0.5;
+
+end;
+
+{ CONSTRUCT }
+constructor gamma_threshold.Construct(t : double );
+begin
+ m_threshold:=t;
+
+end;
+
+{ THRESHOLD_ }
+procedure gamma_threshold.threshold_;
+begin
+ m_threshold:=t;
+
+end;
+
+{ _THRESHOLD }
+function gamma_threshold._threshold;
+begin
+ result:=m_threshold;
+
+end;
+
+{ FUNC_OPERATOR_GAMMA }
+function gamma_threshold.func_operator_gamma;
+begin
+ if x < m_threshold then
+ result:=0.0
+ else
+ result:=1.0;
+
+end;
+
+{ CONSTRUCT }
+constructor gamma_linear.Construct;
+begin
+ m_start:=0;
+ m_end :=1;
+
+end;
+
+{ CONSTRUCT }
+constructor gamma_linear.Construct(s ,e : double );
+begin
+ m_start:=s;
+ m_end :=e;
+
+end;
+
+{ SET_ }
+procedure gamma_linear.set_;
+begin
+ m_start:=s;
+ m_end :=e;
+
+end;
+
+{ START_ }
+procedure gamma_linear.start_;
+begin
+ m_start:=s;
+
+end;
+
+{ END_ }
+procedure gamma_linear.end_;
+begin
+ m_end:=e;
+
+end;
+
+{ _START }
+function gamma_linear._start;
+begin
+ result:=m_start;
+
+end;
+
+{ _END }
+function gamma_linear._end;
+begin
+ result:=m_end;
+
+end;
+
+{ FUNC_OPERATOR_GAMMA }
+function gamma_linear.func_operator_gamma;
+begin
+ if x < m_start then
+ result:=0
+ else
+ if x > m_end then
+ result:=1
+ else
+ if m_end - m_start <> 0 then
+ result:=(x - m_start ) / (m_end - m_start )
+ else
+ result:=0;
+
+end;
+
+{ CONSTRUCT }
+constructor gamma_multiply.Construct;
+begin
+ m_mul:=1.0;
+
+end;
+
+{ CONSTRUCT }
+constructor gamma_multiply.Construct(v : double );
+begin
+ m_mul:=v;
+
+end;
+
+{ VALUE_ }
+procedure gamma_multiply.value_;
+begin
+ m_mul:=v;
+
+end;
+
+{ _VALUE }
+function gamma_multiply._value;
+begin
+ result:=m_mul;
+
+end;
+
+{ FUNC_OPERATOR_GAMMA }
+function gamma_multiply.func_operator_gamma;
+var
+ y : double;
+
+begin
+ y:=x * m_mul;
+
+ if y > 1.0 then
+ y:=1.0;
+
+ result:=y;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_gamma_lut.pas b/src/corelib/render/software/agg_gamma_lut.pas
new file mode 100644
index 00000000..ef77ef4b
--- /dev/null
+++ b/src/corelib/render/software/agg_gamma_lut.pas
@@ -0,0 +1,278 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 16.01.2006-Milano: Unit port establishment
+//
+{ agg_gamma_lut.pas }
+unit
+ agg_gamma_lut ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ Math ,
+ agg_basics ,
+ agg_pixfmt ;
+
+{ TYPES DEFINITION }
+type
+ gamma_lut = object(gamma )
+ gamma_shift ,
+ gamma_size ,
+ gamma_mask ,
+
+ hi_res_shift ,
+ hi_res_size ,
+ hi_res_mask ,
+
+ HiResT ,
+ LoResT : unsigned;
+
+ m_gamma : double;
+
+ m_dir_gamma ,
+ m_inv_gamma : int8u_ptr;
+
+ constructor Construct_(GammaShift : unsigned = 8; HiResShift : unsigned = 8 );
+ constructor Construct (g : double; GammaShift : unsigned = 8; HiResShift : unsigned = 8 );
+ destructor Destruct;
+
+ procedure gamma_(g : double );
+ function _gamma : double;
+
+ function dir(v : unsigned ) : unsigned; virtual;
+ function inv(v : unsigned ) : unsigned; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor gamma_lut.Construct_;
+var
+ i : unsigned;
+
+begin
+ gamma_shift:=GammaShift;
+ gamma_size :=1 shl gamma_shift;
+ gamma_mask :=gamma_size - 1;
+
+ hi_res_shift:=HiResShift;
+ hi_res_size :=1 shl hi_res_shift;
+ hi_res_mask :=hi_res_size - 1;
+
+ HiResT:=hi_res_shift div 8;
+ LoResT:=gamma_shift div 8;
+
+ agg_getmem(pointer(m_dir_gamma ) ,gamma_size * HiResT );
+ agg_getmem(pointer(m_inv_gamma ) ,hi_res_size * LoResT );
+
+// dir_gamma
+ for i:=0 to gamma_size - 1 do
+ try
+ case HiResT of
+ 1 :
+ int8u_ptr(ptrcomp(m_dir_gamma ) + i * HiResT )^:=
+ int8u(i shl (hi_res_shift - gamma_shift ) );
+
+ 2 :
+ int16u_ptr(ptrcomp(m_dir_gamma ) + i * HiResT )^:=
+ int16u(i shl (hi_res_shift - gamma_shift ) );
+
+ 4 :
+ int32u_ptr(ptrcomp(m_dir_gamma ) + i * HiResT )^:=
+ int32u(i shl (hi_res_shift - gamma_shift ) );
+
+ end;
+ except
+ end;
+
+// inv_gamma
+ for i:=0 to hi_res_size - 1 do
+ try
+ case LoResT of
+ 1 :
+ int8u_ptr(ptrcomp(m_inv_gamma ) + i * LoResT )^:=
+ int8u(i shr (hi_res_shift - gamma_shift ) );
+
+ 2 :
+ int16u_ptr(ptrcomp(m_inv_gamma ) + i * LoResT )^:=
+ int16u(i shr (hi_res_shift - gamma_shift ) );
+
+ 4 :
+ int32u_ptr(ptrcomp(m_inv_gamma ) + i * LoResT )^:=
+ int32u(i shr (hi_res_shift - gamma_shift ) );
+
+ end;
+ except
+ end;
+
+end;
+
+{ CONSTRUCT }
+constructor gamma_lut.Construct;
+begin
+ gamma_shift:=GammaShift;
+ gamma_size :=1 shl gamma_shift;
+ gamma_mask :=gamma_size - 1;
+
+ hi_res_shift:=HiResShift;
+ hi_res_size :=1 shl hi_res_shift;
+ hi_res_mask :=hi_res_size - 1;
+
+ HiResT:=hi_res_shift div 8;
+ LoResT:=gamma_shift div 8;
+
+ m_gamma:=1;
+
+ agg_getmem(pointer(m_dir_gamma ) ,gamma_size * HiResT );
+ agg_getmem(pointer(m_inv_gamma ) ,hi_res_size * LoResT );
+
+ gamma_(g );
+
+end;
+
+{ DESTRUCT }
+destructor gamma_lut.Destruct;
+begin
+ agg_freemem(pointer(m_dir_gamma ) ,gamma_size * HiResT );
+ agg_freemem(pointer(m_inv_gamma ) ,hi_res_size * LoResT );
+
+end;
+
+{ GAMMA_ }
+procedure gamma_lut.gamma_;
+var
+ i : unsigned;
+
+ inv_g : double;
+
+begin
+ m_gamma:=g;
+
+// dir_gamma
+ for i:=0 to gamma_size - 1 do
+ try
+ case HiResT of
+ 1 :
+ int8u_ptr(ptrcomp(m_dir_gamma ) + i * HiResT )^:=
+ int8u(trunc(Power(i / gamma_mask ,m_gamma ) * hi_res_mask + 0.5 ) );
+
+ 2 :
+ int16u_ptr(ptrcomp(m_dir_gamma ) + i * HiResT )^:=
+ int16u(trunc(Power(i / gamma_mask ,m_gamma ) * hi_res_mask + 0.5 ) );
+
+ 4 :
+ int32u_ptr(ptrcomp(m_dir_gamma ) + i * HiResT )^:=
+ int32u(trunc(Power(i / gamma_mask ,m_gamma ) * hi_res_mask + 0.5 ) );
+
+ end;
+ except
+ end;
+
+// inv_gamma
+ if g = 0 then
+ fillchar(m_inv_gamma^ ,hi_res_size * LoResT ,0 )
+
+ else
+ begin
+ inv_g:=1 / g;
+
+ for i:=0 to hi_res_size - 1 do
+ try
+ case LoResT of
+ 1 :
+ int8u_ptr(ptrcomp(m_inv_gamma ) + i * LoResT )^:=
+ int8u(trunc(Power(i / hi_res_mask ,inv_g ) * gamma_mask + 0.5 ) );
+
+ 2 :
+ int16u_ptr(ptrcomp(m_inv_gamma ) + i * LoResT )^:=
+ int16u(trunc(Power(i / hi_res_mask ,inv_g ) * gamma_mask + 0.5 ) );
+
+ 4 :
+ int32u_ptr(ptrcomp(m_inv_gamma ) + i * LoResT )^:=
+ int32u(trunc(Power(i / hi_res_mask ,inv_g ) * gamma_mask + 0.5 ) );
+
+ end;
+ except
+ end;
+
+ end;
+
+end;
+
+{ _GAMMA }
+function gamma_lut._gamma : double;
+begin
+ result:=m_gamma;
+
+end;
+
+{ DIR }
+function gamma_lut.dir;
+begin
+ case HiResT of
+ 1 :
+ result:=int8u_ptr(ptrcomp(m_dir_gamma ) + v * HiResT )^;
+
+ 2 :
+ result:=int16u_ptr(ptrcomp(m_dir_gamma ) + v * HiResT )^;
+
+ 4 :
+ result:=int32u_ptr(ptrcomp(m_dir_gamma ) + v * HiResT )^;
+
+ else
+ result:=0;
+
+ end;
+
+end;
+
+{ INV }
+function gamma_lut.inv;
+begin
+ case LoResT of
+ 1 :
+ result:=int8u_ptr(ptrcomp(m_inv_gamma ) + v * LoResT )^;
+
+ 2 :
+ result:=int16u_ptr(ptrcomp(m_inv_gamma ) + v * LoResT )^;
+
+ 4 :
+ result:=int32u_ptr(ptrcomp(m_inv_gamma ) + v * LoResT )^;
+
+ else
+ result:=0;
+
+ end;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_glyph_raster_bin.pas b/src/corelib/render/software/agg_glyph_raster_bin.pas
new file mode 100644
index 00000000..75dc8d80
--- /dev/null
+++ b/src/corelib/render/software/agg_glyph_raster_bin.pas
@@ -0,0 +1,268 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 13.02.2006-Milano: Unit port establishment
+//
+{ agg_glyph_raster_bin.pas }
+unit
+ agg_glyph_raster_bin ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ;
+
+{ TYPES DEFINITION }
+type
+ glyph_rect_ptr = ^glyph_rect;
+ glyph_rect = record
+ x1 ,y1 ,x2 ,y2 : int;
+
+ dx ,dy : double;
+
+ end;
+
+ glyph_raster_bin_ptr = ^glyph_raster_bin;
+ glyph_raster_bin = object
+ m_font : int8u_ptr;
+
+ m_big_endian : boolean;
+
+ m_span : array[0..31 ] of int8u;
+ m_bits : int8u_ptr;
+
+ m_glyph_width ,
+ m_glyph_byte_width : unsigned;
+
+ constructor Construct(font : int8u_ptr );
+
+ function _font : int8u_ptr;
+ procedure font_(f : int8u_ptr );
+
+ function height : double;
+ function base_line : double;
+
+ function width (str : PChar ) : double;
+ procedure prepare(r : glyph_rect_ptr; x ,y : double; glyph : unsigned; flip : boolean );
+ function span (i : unsigned ) : int8u_ptr;
+
+ function value(p : int8u_ptr ) : int16u;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor glyph_raster_bin.Construct;
+var
+ t : int;
+
+begin
+ m_font:=font;
+
+ t:=1;
+
+ if byte(pointer(@t )^ ) = 0 then
+ m_big_endian:=true
+ else
+ m_big_endian:=false;
+
+ fillchar(m_span ,sizeof(m_span ) ,0 );
+
+end;
+
+{ _FONT }
+function glyph_raster_bin._font;
+begin
+ result:=m_font;
+
+end;
+
+{ FONT_ }
+procedure glyph_raster_bin.font_;
+begin
+ m_font:=f;
+
+end;
+
+{ HEIGHT }
+function glyph_raster_bin.height;
+begin
+ result:=int8u_ptr(ptrcomp(m_font ) + 0 * sizeof(int8u ) )^;
+
+end;
+
+{ BASE_LINE }
+function glyph_raster_bin.base_line;
+begin
+ result:=int8u_ptr(ptrcomp(m_font ) + 1 * sizeof(int8u ) )^;
+
+end;
+
+{ WIDTH }
+function glyph_raster_bin.width;
+var
+ start_char ,num_chars ,w ,glyph : unsigned;
+
+ bits : int8u_ptr;
+
+begin
+ start_char:=int8u_ptr(ptrcomp(m_font ) + 2 * sizeof(int8u ) )^;
+ num_chars :=int8u_ptr(ptrcomp(m_font ) + 3 * sizeof(int8u ) )^;
+
+ w:=0;
+
+ while str <> #0 do
+ begin
+ glyph:=int8u_ptr(str )^;
+
+ bits:=
+ int8u_ptr(
+ ptrcomp(m_font ) + 4 + num_chars * 2 +
+ value(int8u_ptr(ptrcomp(m_font ) + 4 + (glyph - start_char ) * 2 ) ) );
+
+ inc(w ,bits^ );
+ inc(ptrcomp(str ) );
+
+ end;
+
+ result:=w;
+
+end;
+
+{ PREPARE }
+procedure glyph_raster_bin.prepare;
+var
+ start_char ,num_chars : unsigned;
+
+begin
+ start_char:=int8u_ptr(ptrcomp(m_font ) + 2 * sizeof(int8u ) )^;
+ num_chars :=int8u_ptr(ptrcomp(m_font ) + 3 * sizeof(int8u ) )^;
+
+ m_bits:=
+ int8u_ptr(
+ ptrcomp(m_font ) + 4 + num_chars * 2 +
+ value(int8u_ptr(ptrcomp(m_font ) + 4 + (glyph - start_char ) * 2 ) ) );
+
+ m_glyph_width:=m_bits^;
+
+ inc(ptrcomp(m_bits ) );
+
+ m_glyph_byte_width:=(m_glyph_width + 7 ) shr 3;
+
+ r.x1:=trunc(x );
+ r.x2:=r.x1 + m_glyph_width - 1;
+
+ if flip then
+ begin
+ r.y1:=
+ trunc(y ) -
+ int8u_ptr(ptrcomp(m_font ) + 0 * sizeof(int8u ) )^ +
+ int8u_ptr(ptrcomp(m_font ) + 1 * sizeof(int8u ) )^;
+
+ r.y2:=r.y1 + int8u_ptr(ptrcomp(m_font ) + 0 * sizeof(int8u ) )^ - 1;
+
+ end
+ else
+ begin
+ r.y1:=trunc(y ) - int8u_ptr(ptrcomp(m_font ) + 1 * sizeof(int8u ) )^ + 1;
+ r.y2:=r.y1 + int8u_ptr(ptrcomp(m_font ) + 0 * sizeof(int8u ) )^ - 1;
+
+ end;
+
+ r.dx:=m_glyph_width;
+ r.dy:=0;
+
+end;
+
+{ SPAN }
+function glyph_raster_bin.span;
+var
+ bits : int8u_ptr;
+
+ j ,val ,nb : unsigned;
+
+begin
+ i:=int8u_ptr(ptrcomp(m_font ) + 0 * sizeof(int8u ) )^ - i - 1;
+
+ bits:=int8u_ptr(ptrcomp(m_bits ) + i * m_glyph_byte_width );
+ val :=bits^;
+ nb :=0;
+
+ for j:=0 to m_glyph_width - 1 do
+ begin
+ if val and $80 <> 0 then
+ m_span[j ]:=int8u(cover_full )
+ else
+ m_span[j ]:=int8u(cover_none );
+
+ val:=val shl 1;
+
+ inc(nb );
+
+ if nb >= 8 then
+ begin
+ inc(ptrcomp(bits ) );
+
+ val:=bits^;
+ nb :=0;
+
+ end;
+
+ end;
+
+ result:=@m_span[0 ];
+
+end;
+
+{ VALUE }
+function glyph_raster_bin.value;
+var
+ v : int16u;
+
+begin
+ if m_big_endian then
+ begin
+ int16u_(v ).Low :=int8u_ptr(ptrcomp(p ) + 1 )^;
+ int16u_(v ).High:=p^;
+
+ end
+ else
+ begin
+ int16u_(v ).Low :=p^;
+ int16u_(v ).High:=int8u_ptr(ptrcomp(p ) + 1 )^;
+
+ end;
+
+ result:=v;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_gradient_lut.pas b/src/corelib/render/software/agg_gradient_lut.pas
new file mode 100644
index 00000000..6b529244
--- /dev/null
+++ b/src/corelib/render/software/agg_gradient_lut.pas
@@ -0,0 +1,334 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2007
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 12.10.2007-Milano: Unit port establishment
+//
+{ agg_gradient_lut.pas }
+unit
+ agg_gradient_lut ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_array ,
+ agg_dda_line ,
+ agg_color ;
+
+{ TYPES DEFINITION }
+type
+ gradient_lut_ptr = ^gradient_lut;
+ gradient_lut = object(array_base )
+ private
+ m_color_lut_size : unsigned;
+ m_color_profile : pod_bvector;
+ m_color_lut : pod_array;
+
+ public
+ constructor Construct(size_ : unsigned = 256 );
+ destructor Destruct;
+
+ // Build Gradient Lut
+ // First, call remove_all(), then add_color() at least twice,
+ // then build_lut(). Argument "offset" in add_color must be
+ // in range [0...1] and defines a color stop as it is described
+ // in SVG specification, section Gradients and Patterns.
+ // The simplest linear gradient is:
+ // gradient_lut.add_color(0.0, start_color);
+ // gradient_lut.add_color(1.0, end_color);
+ procedure remove_all;
+ procedure add_color(offset : double; color : aggclr_ptr );
+ procedure build_lut;
+
+ // Size-index Interface. This class can be used directly as the
+ // ColorF in span_gradient. All it needs is two access methods
+ // size() and operator [].
+ function size : unsigned; virtual;
+ function entry : unsigned; virtual;
+ function array_operator(i : unsigned ) : pointer; virtual;
+
+ end;
+
+{ GLOBAL VARIABLES & CONSTANTS }
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+type
+ color_point_ptr = ^color_point;
+ color_point = object
+ offset : double;
+ color : aggclr;
+
+ constructor Construct; overload;
+ constructor Construct(off : double; c : aggclr_ptr ); overload;
+
+ end;
+
+ color_interpolator = object
+ m_c1 ,
+ m_c2 : aggclr;
+
+ m_len ,
+ m_count : unsigned;
+
+ v ,r ,g ,b ,a : dda_line_interpolator;
+
+ m_is_gray : boolean;
+
+ constructor Construct(c1 ,c2 : aggclr_ptr; len : unsigned; is_gray : boolean = false );
+
+ procedure operator_inc;
+
+ function color : aggclr;
+
+ end;
+
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor color_point.Construct;
+begin
+ offset:=0;
+
+ color.Construct;
+
+end;
+
+{ CONSTRUCT }
+constructor color_point.Construct(off : double; c : aggclr_ptr );
+begin
+ offset:=off;
+
+ color.Construct(c );
+
+ if offset < 0.0 then
+ offset:=0.0;
+
+ if offset > 1.0 then
+ offset:=1.0;
+
+end;
+
+{ CONSTRUCT }
+constructor color_interpolator.Construct(c1 ,c2 : aggclr_ptr; len : unsigned; is_gray : boolean = false );
+begin
+ m_c1.Construct(c1 );
+ m_c2.Construct(c2 );
+
+ m_len :=len;
+ m_count:=0;
+
+ m_is_gray:=is_gray;
+
+ if m_is_gray then
+ v.Construct(c1.v ,c2.v ,len ,14 )
+
+ else
+ begin
+ r.Construct(c1.r ,c2.r ,len ,14 );
+ g.Construct(c1.g ,c2.g ,len ,14 );
+ b.Construct(c1.b ,c2.b ,len ,14 );
+
+ end;
+
+ a.Construct(c1.a ,c2.a ,len ,14 );
+
+end;
+
+{ OPERATOR_INC }
+procedure color_interpolator.operator_inc;
+begin
+ inc(m_count );
+
+ if m_is_gray then
+ v.plus_operator
+
+ else
+ begin
+ r.plus_operator;
+ g.plus_operator;
+ b.plus_operator;
+
+ end;
+
+ a.plus_operator;
+
+end;
+
+{ COLOR }
+function color_interpolator.color : aggclr;
+begin
+// result:=m_c1.gradient(@m_c2 ,m_count / m_len );
+
+ if m_is_gray then
+ result.ConstrInt(r._y ,a._y )
+ else
+ result.ConstrInt(r._y ,g._y ,b._y ,a._y )
+
+end;
+
+{ CONSTRUCT }
+constructor gradient_lut.Construct(size_ : unsigned = 256 );
+begin
+ m_color_lut_size:=size_;
+
+ m_color_profile.Construct(sizeof(color_point ) ,4 );
+ m_color_lut.Construct(sizeof(aggclr ) ,m_color_lut_size );
+
+end;
+
+{ DESTRUCT }
+destructor gradient_lut.Destruct;
+begin
+ m_color_profile.Destruct;
+ m_color_lut.Destruct;
+
+end;
+
+{ REMOVE_ALL }
+procedure gradient_lut.remove_all;
+begin
+ m_color_profile.remove_all;
+
+end;
+
+{ ADD_COLOR }
+procedure gradient_lut.add_color(offset : double; color : aggclr_ptr );
+var
+ cp : color_point;
+
+begin
+ cp.Construct(offset ,color );
+
+ m_color_profile.add(@cp );
+
+end;
+
+{ offset_less }
+function offset_less(a ,b : color_point_ptr ) : boolean;
+begin
+ result:=a.offset < b.offset;
+
+end;
+
+{ offset_equal }
+function offset_equal(a ,b : color_point_ptr ) : boolean;
+begin
+ result:=a.offset = b.offset;
+
+end;
+
+{ BUILD_LUT }
+procedure gradient_lut.build_lut;
+var
+ i ,start ,end_ : unsigned;
+
+ c : aggclr;
+
+ ci : color_interpolator;
+
+begin
+ quick_sort (@m_color_profile ,@offset_less );
+ m_color_profile.cut_at(remove_duplicates(@m_color_profile ,@offset_equal ) );
+
+ if m_color_profile.size >= 2 then
+ begin
+ start:=
+ uround(
+ color_point_ptr(m_color_profile.array_operator(0 ) ).offset * m_color_lut_size );
+
+ c:=color_point_ptr(m_color_profile.array_operator(0 ) ).color;
+ i:=0;
+
+ while i < start do
+ begin
+ aggclr_ptr(m_color_lut.array_operator(i ) )^:=c;
+
+ inc(i );
+
+ end;
+
+ i:=1;
+
+ while i < m_color_profile.size do
+ begin
+ end_:=uround(color_point_ptr(m_color_profile.array_operator(i ) ).offset * m_color_lut_size );
+
+ ci.Construct(
+ @color_point_ptr(m_color_profile.array_operator(i - 1 ) ).color ,
+ @color_point_ptr(m_color_profile.array_operator(i ) ).color ,
+ end_ - start + 1 );
+
+ while start < end_ do
+ begin
+ aggclr_ptr(m_color_lut.array_operator(start ) )^:=ci.color;
+
+ ci.operator_inc;
+
+ inc(start );
+
+ end;
+
+ inc(i );
+
+ end;
+
+ c:=color_point_ptr(m_color_profile.last ).color;
+
+ while end_ < m_color_lut.size do
+ begin
+ aggclr_ptr(m_color_lut.array_operator(end_ ) )^:=c;
+
+ inc(end_ );
+
+ end;
+
+ end;
+
+end;
+
+{ SIZE }
+function gradient_lut.size : unsigned;
+begin
+ result:=m_color_lut_size;
+
+end;
+
+{ ENTRY }
+function gradient_lut.entry : unsigned;
+begin
+ result:=m_color_lut.m_entry_sz;
+
+end;
+
+{ ARRAY_OPERATOR }
+function gradient_lut.array_operator(i : unsigned ) : pointer;
+begin
+ result:=m_color_lut.array_operator(i );
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_gsv_text.pas b/src/corelib/render/software/agg_gsv_text.pas
new file mode 100644
index 00000000..81935e76
--- /dev/null
+++ b/src/corelib/render/software/agg_gsv_text.pas
@@ -0,0 +1,974 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 21.12.2005-Milano: Unit port establishment
+//
+{ agg_gsv_text.pas }
+unit
+ agg_gsv_text ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+{$Q- }
+{$R- }
+uses
+ SysUtils ,
+ agg_basics ,
+ agg_vertex_source ,
+ agg_conv_stroke ,
+ agg_conv_transform ,
+ agg_trans_affine ,
+ agg_math_stroke ;
+
+{ TYPES DEFINITION }
+type
+ status = (
+ initial,
+ next_char,
+ start_glyph,
+ glyph );
+
+//---------------------------------------------------------------gsv_text
+ gsv_text_ptr = ^gsv_text;
+ gsv_text = object(vertex_source )
+ m_x ,
+ m_y ,
+ m_start_x ,
+ m_width ,
+ m_height ,
+ m_space ,
+ m_line_space : double;
+ m_chr : array[0..1 ] of byte;
+ m_text ,
+ m_text_buf : pointer;
+ m_buf_size : unsigned;
+ m_cur_chr : int8u_ptr;
+ m_font ,
+ m_loaded_font : pointer;
+ m_loadfont_sz : unsigned;
+ m_status : status;
+ m_big_endian ,
+ m_flip : boolean;
+
+ m_indices : int8u_ptr;
+ m_glyphs ,
+ m_bglyph ,
+ m_eglyph : int8_ptr;
+ m_w ,
+ m_h : double;
+
+ constructor Construct;
+ destructor Destruct; virtual;
+
+ procedure font_ (font : pointer );
+ procedure flip_ (flip_y : boolean );
+ procedure load_font_ (_file_ : shortstring );
+ procedure size_ (height : double; width : double = 0.0 );
+ procedure space_ (space : double );
+ procedure line_space_ (line_space : double );
+ procedure start_point_(x ,y : double );
+ procedure text_ (text : PChar );
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ function _value(p : int8u_ptr ) : int16u;
+
+ end;
+
+//--------------------------------------------------------gsv_text_outline
+ gsv_text_outline = object(vertex_source )
+ m_polyline : conv_stroke;
+ m_trans : conv_transform;
+
+ constructor Construct(text : gsv_text_ptr; trans : trans_affine_ptr );
+ destructor Destruct; virtual;
+
+ procedure width_(w : double );
+
+ procedure transformer_(trans : trans_affine_ptr );
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+const
+ gsv_default_font : array[0..4525 ] of int8u = (
+ $40,$00,$6c,$0f,$15,$00,$0e,$00,$f9,$ff,
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+ $0d,$0a,$0d,$0a,$46,$6f,$6e,$74,$20,$28,
+ $63,$29,$20,$4d,$69,$63,$72,$6f,$50,$72,
+ $6f,$66,$20,$32,$37,$20,$53,$65,$70,$74,
+ $65,$6d,$62,$2e,$31,$39,$38,$39,$00,$0d,
+ $0a,$0d,$0a,$00,$00,$00,$00,$00,$00,$00,
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+ $02,$00,$12,$00,$34,$00,$46,$00,$94,$00,
+ $d0,$00,$2e,$01,$3e,$01,$64,$01,$8a,$01,
+ $98,$01,$a2,$01,$b4,$01,$ba,$01,$c6,$01,
+ $cc,$01,$f0,$01,$fa,$01,$18,$02,$38,$02,
+ $44,$02,$68,$02,$98,$02,$a2,$02,$de,$02,
+ $0e,$03,$24,$03,$40,$03,$48,$03,$52,$03,
+ $5a,$03,$82,$03,$ec,$03,$fa,$03,$26,$04,
+ $4c,$04,$6a,$04,$7c,$04,$8a,$04,$b6,$04,
+ $c4,$04,$ca,$04,$e0,$04,$ee,$04,$f8,$04,
+ $0a,$05,$18,$05,$44,$05,$5e,$05,$8e,$05,
+ $ac,$05,$d6,$05,$e0,$05,$f6,$05,$00,$06,
+ $12,$06,$1c,$06,$28,$06,$36,$06,$48,$06,
+ $4e,$06,$60,$06,$6e,$06,$74,$06,$84,$06,
+ $a6,$06,$c8,$06,$e6,$06,$08,$07,$2c,$07,
+ $3c,$07,$68,$07,$7c,$07,$8c,$07,$a2,$07,
+ $b0,$07,$b6,$07,$d8,$07,$ec,$07,$10,$08,
+ $32,$08,$54,$08,$64,$08,$88,$08,$98,$08,
+ $ac,$08,$b6,$08,$c8,$08,$d2,$08,$e4,$08,
+ $f2,$08,$3e,$09,$48,$09,$94,$09,$c2,$09,
+ $c4,$09,$d0,$09,$e2,$09,$04,$0a,$0e,$0a,
+ $26,$0a,$34,$0a,$4a,$0a,$66,$0a,$70,$0a,
+ $7e,$0a,$8e,$0a,$9a,$0a,$a6,$0a,$b4,$0a,
+ $d8,$0a,$e2,$0a,$f6,$0a,$18,$0b,$22,$0b,
+ $32,$0b,$56,$0b,$60,$0b,$6e,$0b,$7c,$0b,
+ $8a,$0b,$9c,$0b,$9e,$0b,$b2,$0b,$c2,$0b,
+ $d8,$0b,$f4,$0b,$08,$0c,$30,$0c,$56,$0c,
+ $72,$0c,$90,$0c,$b2,$0c,$ce,$0c,$e2,$0c,
+ $fe,$0c,$10,$0d,$26,$0d,$36,$0d,$42,$0d,
+ $4e,$0d,$5c,$0d,$78,$0d,$8c,$0d,$8e,$0d,
+ $90,$0d,$92,$0d,$94,$0d,$96,$0d,$98,$0d,
+ $9a,$0d,$9c,$0d,$9e,$0d,$a0,$0d,$a2,$0d,
+ $a4,$0d,$a6,$0d,$a8,$0d,$aa,$0d,$ac,$0d,
+ $ae,$0d,$b0,$0d,$b2,$0d,$b4,$0d,$b6,$0d,
+ $b8,$0d,$ba,$0d,$bc,$0d,$be,$0d,$c0,$0d,
+ $c2,$0d,$c4,$0d,$c6,$0d,$c8,$0d,$ca,$0d,
+ $cc,$0d,$ce,$0d,$d0,$0d,$d2,$0d,$d4,$0d,
+ $d6,$0d,$d8,$0d,$da,$0d,$dc,$0d,$de,$0d,
+ $e0,$0d,$e2,$0d,$e4,$0d,$e6,$0d,$e8,$0d,
+ $ea,$0d,$ec,$0d,$0c,$0e,$26,$0e,$48,$0e,
+ $64,$0e,$88,$0e,$92,$0e,$a6,$0e,$b4,$0e,
+ $d0,$0e,$ee,$0e,$02,$0f,$16,$0f,$26,$0f,
+ $3c,$0f,$58,$0f,$6c,$0f,$6c,$0f,$6c,$0f,
+ $6c,$0f,$6c,$0f,$6c,$0f,$6c,$0f,$6c,$0f,
+ $6c,$0f,$6c,$0f,$6c,$0f,$6c,$0f,$6c,$0f,
+ $6c,$0f,$6c,$0f,$6c,$0f,$6c,$0f,$10,$80,
+ $05,$95,$00,$72,$00,$fb,$ff,$7f,$01,$7f,
+ $01,$01,$ff,$01,$05,$fe,$05,$95,$ff,$7f,
+ $00,$7a,$01,$86,$ff,$7a,$01,$87,$01,$7f,
+ $fe,$7a,$0a,$87,$ff,$7f,$00,$7a,$01,$86,
+ $ff,$7a,$01,$87,$01,$7f,$fe,$7a,$05,$f2,
+ $0b,$95,$f9,$64,$0d,$9c,$f9,$64,$fa,$91,
+ $0e,$00,$f1,$fa,$0e,$00,$04,$fc,$08,$99,
+ $00,$63,$04,$9d,$00,$63,$04,$96,$ff,$7f,
+ $01,$7f,$01,$01,$00,$01,$fe,$02,$fd,$01,
+ $fc,$00,$fd,$7f,$fe,$7e,$00,$7e,$01,$7e,
+ $01,$7f,$02,$7f,$06,$7e,$02,$7f,$02,$7e,
+ $f2,$89,$02,$7e,$02,$7f,$06,$7e,$02,$7f,
+ $01,$7f,$01,$7e,$00,$7c,$fe,$7e,$fd,$7f,
+ $fc,$00,$fd,$01,$fe,$02,$00,$01,$01,$01,
+ $01,$7f,$ff,$7f,$10,$fd,$15,$95,$ee,$6b,
+ $05,$95,$02,$7e,$00,$7e,$ff,$7e,$fe,$7f,
+ $fe,$00,$fe,$02,$00,$02,$01,$02,$02,$01,
+ $02,$00,$02,$7f,$03,$7f,$03,$00,$03,$01,
+ $02,$01,$fc,$f2,$fe,$7f,$ff,$7e,$00,$7e,
+ $02,$7e,$02,$00,$02,$01,$01,$02,$00,$02,
+ $fe,$02,$fe,$00,$07,$f9,$15,$8d,$ff,$7f,
+ $01,$7f,$01,$01,$00,$01,$ff,$01,$ff,$00,
+ $ff,$7f,$ff,$7e,$fe,$7b,$fe,$7d,$fe,$7e,
+ $fe,$7f,$fd,$00,$fd,$01,$ff,$02,$00,$03,
+ $01,$02,$06,$04,$02,$02,$01,$02,$00,$02,
+ $ff,$02,$fe,$01,$fe,$7f,$ff,$7e,$00,$7e,
+ $01,$7d,$02,$7d,$05,$79,$02,$7e,$03,$7f,
+ $01,$00,$01,$01,$00,$01,$f1,$fe,$fe,$01,
+ $ff,$02,$00,$03,$01,$02,$02,$02,$00,$86,
+ $01,$7e,$08,$75,$02,$7e,$02,$7f,$05,$80,
+ $05,$93,$ff,$01,$01,$01,$01,$7f,$00,$7e,
+ $ff,$7e,$ff,$7f,$06,$f1,$0b,$99,$fe,$7e,
+ $fe,$7d,$fe,$7c,$ff,$7b,$00,$7c,$01,$7b,
+ $02,$7c,$02,$7d,$02,$7e,$fe,$9e,$fe,$7c,
+ $ff,$7d,$ff,$7b,$00,$7c,$01,$7b,$01,$7d,
+ $02,$7c,$05,$85,$03,$99,$02,$7e,$02,$7d,
+ $02,$7c,$01,$7b,$00,$7c,$ff,$7b,$fe,$7c,
+ $fe,$7d,$fe,$7e,$02,$9e,$02,$7c,$01,$7d,
+ $01,$7b,$00,$7c,$ff,$7b,$ff,$7d,$fe,$7c,
+ $09,$85,$08,$95,$00,$74,$fb,$89,$0a,$7a,
+ $00,$86,$f6,$7a,$0d,$f4,$0d,$92,$00,$6e,
+ $f7,$89,$12,$00,$04,$f7,$06,$81,$ff,$7f,
+ $ff,$01,$01,$01,$01,$7f,$00,$7e,$ff,$7e,
+ $ff,$7f,$06,$84,$04,$89,$12,$00,$04,$f7,
+ $05,$82,$ff,$7f,$01,$7f,$01,$01,$ff,$01,
+ $05,$fe,$00,$fd,$0e,$18,$00,$eb,$09,$95,
+ $fd,$7f,$fe,$7d,$ff,$7b,$00,$7d,$01,$7b,
+ $02,$7d,$03,$7f,$02,$00,$03,$01,$02,$03,
+ $01,$05,$00,$03,$ff,$05,$fe,$03,$fd,$01,
+ $fe,$00,$0b,$eb,$06,$91,$02,$01,$03,$03,
+ $00,$6b,$09,$80,$04,$90,$00,$01,$01,$02,
+ $01,$01,$02,$01,$04,$00,$02,$7f,$01,$7f,
+ $01,$7e,$00,$7e,$ff,$7e,$fe,$7d,$f6,$76,
+ $0e,$00,$03,$80,$05,$95,$0b,$00,$fa,$78,
+ $03,$00,$02,$7f,$01,$7f,$01,$7d,$00,$7e,
+ $ff,$7d,$fe,$7e,$fd,$7f,$fd,$00,$fd,$01,
+ $ff,$01,$ff,$02,$11,$fc,$0d,$95,$f6,$72,
+ $0f,$00,$fb,$8e,$00,$6b,$07,$80,$0f,$95,
+ $f6,$00,$ff,$77,$01,$01,$03,$01,$03,$00,
+ $03,$7f,$02,$7e,$01,$7d,$00,$7e,$ff,$7d,
+ $fe,$7e,$fd,$7f,$fd,$00,$fd,$01,$ff,$01,
+ $ff,$02,$11,$fc,$10,$92,$ff,$02,$fd,$01,
+ $fe,$00,$fd,$7f,$fe,$7d,$ff,$7b,$00,$7b,
+ $01,$7c,$02,$7e,$03,$7f,$01,$00,$03,$01,
+ $02,$02,$01,$03,$00,$01,$ff,$03,$fe,$02,
+ $fd,$01,$ff,$00,$fd,$7f,$fe,$7e,$ff,$7d,
+ $10,$f9,$11,$95,$f6,$6b,$fc,$95,$0e,$00,
+ $03,$eb,$08,$95,$fd,$7f,$ff,$7e,$00,$7e,
+ $01,$7e,$02,$7f,$04,$7f,$03,$7f,$02,$7e,
+ $01,$7e,$00,$7d,$ff,$7e,$ff,$7f,$fd,$7f,
+ $fc,$00,$fd,$01,$ff,$01,$ff,$02,$00,$03,
+ $01,$02,$02,$02,$03,$01,$04,$01,$02,$01,
+ $01,$02,$00,$02,$ff,$02,$fd,$01,$fc,$00,
+ $0c,$eb,$10,$8e,$ff,$7d,$fe,$7e,$fd,$7f,
+ $ff,$00,$fd,$01,$fe,$02,$ff,$03,$00,$01,
+ $01,$03,$02,$02,$03,$01,$01,$00,$03,$7f,
+ $02,$7e,$01,$7c,$00,$7b,$ff,$7b,$fe,$7d,
+ $fd,$7f,$fe,$00,$fd,$01,$ff,$02,$10,$fd,
+ $05,$8e,$ff,$7f,$01,$7f,$01,$01,$ff,$01,
+ $00,$f4,$ff,$7f,$01,$7f,$01,$01,$ff,$01,
+ $05,$fe,$05,$8e,$ff,$7f,$01,$7f,$01,$01,
+ $ff,$01,$01,$f3,$ff,$7f,$ff,$01,$01,$01,
+ $01,$7f,$00,$7e,$ff,$7e,$ff,$7f,$06,$84,
+ $14,$92,$f0,$77,$10,$77,$04,$80,$04,$8c,
+ $12,$00,$ee,$fa,$12,$00,$04,$fa,$04,$92,
+ $10,$77,$f0,$77,$14,$80,$03,$90,$00,$01,
+ $01,$02,$01,$01,$02,$01,$04,$00,$02,$7f,
+ $01,$7f,$01,$7e,$00,$7e,$ff,$7e,$ff,$7f,
+ $fc,$7e,$00,$7d,$00,$fb,$ff,$7f,$01,$7f,
+ $01,$01,$ff,$01,$09,$fe,$12,$8d,$ff,$02,
+ $fe,$01,$fd,$00,$fe,$7f,$ff,$7f,$ff,$7d,
+ $00,$7d,$01,$7e,$02,$7f,$03,$00,$02,$01,
+ $01,$02,$fb,$88,$fe,$7e,$ff,$7d,$00,$7d,
+ $01,$7e,$01,$7f,$07,$8b,$ff,$78,$00,$7e,
+ $02,$7f,$02,$00,$02,$02,$01,$03,$00,$02,
+ $ff,$03,$ff,$02,$fe,$02,$fe,$01,$fd,$01,
+ $fd,$00,$fd,$7f,$fe,$7f,$fe,$7e,$ff,$7e,
+ $ff,$7d,$00,$7d,$01,$7d,$01,$7e,$02,$7e,
+ $02,$7f,$03,$7f,$03,$00,$03,$01,$02,$01,
+ $01,$01,$fe,$8d,$ff,$78,$00,$7e,$01,$7f,
+ $08,$fb,$09,$95,$f8,$6b,$08,$95,$08,$6b,
+ $f3,$87,$0a,$00,$04,$f9,$04,$95,$00,$6b,
+ $00,$95,$09,$00,$03,$7f,$01,$7f,$01,$7e,
+ $00,$7e,$ff,$7e,$ff,$7f,$fd,$7f,$f7,$80,
+ $09,$00,$03,$7f,$01,$7f,$01,$7e,$00,$7d,
+ $ff,$7e,$ff,$7f,$fd,$7f,$f7,$00,$11,$80,
+ $12,$90,$ff,$02,$fe,$02,$fe,$01,$fc,$00,
+ $fe,$7f,$fe,$7e,$ff,$7e,$ff,$7d,$00,$7b,
+ $01,$7d,$01,$7e,$02,$7e,$02,$7f,$04,$00,
+ $02,$01,$02,$02,$01,$02,$03,$fb,$04,$95,
+ $00,$6b,$00,$95,$07,$00,$03,$7f,$02,$7e,
+ $01,$7e,$01,$7d,$00,$7b,$ff,$7d,$ff,$7e,
+ $fe,$7e,$fd,$7f,$f9,$00,$11,$80,$04,$95,
+ $00,$6b,$00,$95,$0d,$00,$f3,$f6,$08,$00,
+ $f8,$f5,$0d,$00,$02,$80,$04,$95,$00,$6b,
+ $00,$95,$0d,$00,$f3,$f6,$08,$00,$06,$f5,
+ $12,$90,$ff,$02,$fe,$02,$fe,$01,$fc,$00,
+ $fe,$7f,$fe,$7e,$ff,$7e,$ff,$7d,$00,$7b,
+ $01,$7d,$01,$7e,$02,$7e,$02,$7f,$04,$00,
+ $02,$01,$02,$02,$01,$02,$00,$03,$fb,$80,
+ $05,$00,$03,$f8,$04,$95,$00,$6b,$0e,$95,
+ $00,$6b,$f2,$8b,$0e,$00,$04,$f5,$04,$95,
+ $00,$6b,$04,$80,$0c,$95,$00,$70,$ff,$7d,
+ $ff,$7f,$fe,$7f,$fe,$00,$fe,$01,$ff,$01,
+ $ff,$03,$00,$02,$0e,$f9,$04,$95,$00,$6b,
+ $0e,$95,$f2,$72,$05,$85,$09,$74,$03,$80,
+ $04,$95,$00,$6b,$00,$80,$0c,$00,$01,$80,
+ $04,$95,$00,$6b,$00,$95,$08,$6b,$08,$95,
+ $f8,$6b,$08,$95,$00,$6b,$04,$80,$04,$95,
+ $00,$6b,$00,$95,$0e,$6b,$00,$95,$00,$6b,
+ $04,$80,$09,$95,$fe,$7f,$fe,$7e,$ff,$7e,
+ $ff,$7d,$00,$7b,$01,$7d,$01,$7e,$02,$7e,
+ $02,$7f,$04,$00,$02,$01,$02,$02,$01,$02,
+ $01,$03,$00,$05,$ff,$03,$ff,$02,$fe,$02,
+ $fe,$01,$fc,$00,$0d,$eb,$04,$95,$00,$6b,
+ $00,$95,$09,$00,$03,$7f,$01,$7f,$01,$7e,
+ $00,$7d,$ff,$7e,$ff,$7f,$fd,$7f,$f7,$00,
+ $11,$f6,$09,$95,$fe,$7f,$fe,$7e,$ff,$7e,
+ $ff,$7d,$00,$7b,$01,$7d,$01,$7e,$02,$7e,
+ $02,$7f,$04,$00,$02,$01,$02,$02,$01,$02,
+ $01,$03,$00,$05,$ff,$03,$ff,$02,$fe,$02,
+ $fe,$01,$fc,$00,$03,$ef,$06,$7a,$04,$82,
+ $04,$95,$00,$6b,$00,$95,$09,$00,$03,$7f,
+ $01,$7f,$01,$7e,$00,$7e,$ff,$7e,$ff,$7f,
+ $fd,$7f,$f7,$00,$07,$80,$07,$75,$03,$80,
+ $11,$92,$fe,$02,$fd,$01,$fc,$00,$fd,$7f,
+ $fe,$7e,$00,$7e,$01,$7e,$01,$7f,$02,$7f,
+ $06,$7e,$02,$7f,$01,$7f,$01,$7e,$00,$7d,
+ $fe,$7e,$fd,$7f,$fc,$00,$fd,$01,$fe,$02,
+ $11,$fd,$08,$95,$00,$6b,$f9,$95,$0e,$00,
+ $01,$eb,$04,$95,$00,$71,$01,$7d,$02,$7e,
+ $03,$7f,$02,$00,$03,$01,$02,$02,$01,$03,
+ $00,$0f,$04,$eb,$01,$95,$08,$6b,$08,$95,
+ $f8,$6b,$09,$80,$02,$95,$05,$6b,$05,$95,
+ $fb,$6b,$05,$95,$05,$6b,$05,$95,$fb,$6b,
+ $07,$80,$03,$95,$0e,$6b,$00,$95,$f2,$6b,
+ $11,$80,$01,$95,$08,$76,$00,$75,$08,$95,
+ $f8,$76,$09,$f5,$11,$95,$f2,$6b,$00,$95,
+ $0e,$00,$f2,$eb,$0e,$00,$03,$80,$03,$93,
+ $00,$6c,$01,$94,$00,$6c,$ff,$94,$05,$00,
+ $fb,$ec,$05,$00,$02,$81,$00,$95,$0e,$68,
+ $00,$83,$06,$93,$00,$6c,$01,$94,$00,$6c,
+ $fb,$94,$05,$00,$fb,$ec,$05,$00,$03,$81,
+ $03,$87,$08,$05,$08,$7b,$f0,$80,$08,$04,
+ $08,$7c,$03,$f9,$01,$80,$10,$00,$01,$80,
+ $06,$95,$ff,$7f,$ff,$7e,$00,$7e,$01,$7f,
+ $01,$01,$ff,$01,$05,$ef,$0f,$8e,$00,$72,
+ $00,$8b,$fe,$02,$fe,$01,$fd,$00,$fe,$7f,
+ $fe,$7e,$ff,$7d,$00,$7e,$01,$7d,$02,$7e,
+ $02,$7f,$03,$00,$02,$01,$02,$02,$04,$fd,
+ $04,$95,$00,$6b,$00,$8b,$02,$02,$02,$01,
+ $03,$00,$02,$7f,$02,$7e,$01,$7d,$00,$7e,
+ $ff,$7d,$fe,$7e,$fe,$7f,$fd,$00,$fe,$01,
+ $fe,$02,$0f,$fd,$0f,$8b,$fe,$02,$fe,$01,
+ $fd,$00,$fe,$7f,$fe,$7e,$ff,$7d,$00,$7e,
+ $01,$7d,$02,$7e,$02,$7f,$03,$00,$02,$01,
+ $02,$02,$03,$fd,$0f,$95,$00,$6b,$00,$8b,
+ $fe,$02,$fe,$01,$fd,$00,$fe,$7f,$fe,$7e,
+ $ff,$7d,$00,$7e,$01,$7d,$02,$7e,$02,$7f,
+ $03,$00,$02,$01,$02,$02,$04,$fd,$03,$88,
+ $0c,$00,$00,$02,$ff,$02,$ff,$01,$fe,$01,
+ $fd,$00,$fe,$7f,$fe,$7e,$ff,$7d,$00,$7e,
+ $01,$7d,$02,$7e,$02,$7f,$03,$00,$02,$01,
+ $02,$02,$03,$fd,$0a,$95,$fe,$00,$fe,$7f,
+ $ff,$7d,$00,$6f,$fd,$8e,$07,$00,$03,$f2,
+ $0f,$8e,$00,$70,$ff,$7d,$ff,$7f,$fe,$7f,
+ $fd,$00,$fe,$01,$09,$91,$fe,$02,$fe,$01,
+ $fd,$00,$fe,$7f,$fe,$7e,$ff,$7d,$00,$7e,
+ $01,$7d,$02,$7e,$02,$7f,$03,$00,$02,$01,
+ $02,$02,$04,$fd,$04,$95,$00,$6b,$00,$8a,
+ $03,$03,$02,$01,$03,$00,$02,$7f,$01,$7d,
+ $00,$76,$04,$80,$03,$95,$01,$7f,$01,$01,
+ $ff,$01,$ff,$7f,$01,$f9,$00,$72,$04,$80,
+ $05,$95,$01,$7f,$01,$01,$ff,$01,$ff,$7f,
+ $01,$f9,$00,$6f,$ff,$7d,$fe,$7f,$fe,$00,
+ $09,$87,$04,$95,$00,$6b,$0a,$8e,$f6,$76,
+ $04,$84,$07,$78,$02,$80,$04,$95,$00,$6b,
+ $04,$80,$04,$8e,$00,$72,$00,$8a,$03,$03,
+ $02,$01,$03,$00,$02,$7f,$01,$7d,$00,$76,
+ $00,$8a,$03,$03,$02,$01,$03,$00,$02,$7f,
+ $01,$7d,$00,$76,$04,$80,$04,$8e,$00,$72,
+ $00,$8a,$03,$03,$02,$01,$03,$00,$02,$7f,
+ $01,$7d,$00,$76,$04,$80,$08,$8e,$fe,$7f,
+ $fe,$7e,$ff,$7d,$00,$7e,$01,$7d,$02,$7e,
+ $02,$7f,$03,$00,$02,$01,$02,$02,$01,$03,
+ $00,$02,$ff,$03,$fe,$02,$fe,$01,$fd,$00,
+ $0b,$f2,$04,$8e,$00,$6b,$00,$92,$02,$02,
+ $02,$01,$03,$00,$02,$7f,$02,$7e,$01,$7d,
+ $00,$7e,$ff,$7d,$fe,$7e,$fe,$7f,$fd,$00,
+ $fe,$01,$fe,$02,$0f,$fd,$0f,$8e,$00,$6b,
+ $00,$92,$fe,$02,$fe,$01,$fd,$00,$fe,$7f,
+ $fe,$7e,$ff,$7d,$00,$7e,$01,$7d,$02,$7e,
+ $02,$7f,$03,$00,$02,$01,$02,$02,$04,$fd,
+ $04,$8e,$00,$72,$00,$88,$01,$03,$02,$02,
+ $02,$01,$03,$00,$01,$f2,$0e,$8b,$ff,$02,
+ $fd,$01,$fd,$00,$fd,$7f,$ff,$7e,$01,$7e,
+ $02,$7f,$05,$7f,$02,$7f,$01,$7e,$00,$7f,
+ $ff,$7e,$fd,$7f,$fd,$00,$fd,$01,$ff,$02,
+ $0e,$fd,$05,$95,$00,$6f,$01,$7d,$02,$7f,
+ $02,$00,$f8,$8e,$07,$00,$03,$f2,$04,$8e,
+ $00,$76,$01,$7d,$02,$7f,$03,$00,$02,$01,
+ $03,$03,$00,$8a,$00,$72,$04,$80,$02,$8e,
+ $06,$72,$06,$8e,$fa,$72,$08,$80,$03,$8e,
+ $04,$72,$04,$8e,$fc,$72,$04,$8e,$04,$72,
+ $04,$8e,$fc,$72,$07,$80,$03,$8e,$0b,$72,
+ $00,$8e,$f5,$72,$0e,$80,$02,$8e,$06,$72,
+ $06,$8e,$fa,$72,$fe,$7c,$fe,$7e,$fe,$7f,
+ $ff,$00,$0f,$87,$0e,$8e,$f5,$72,$00,$8e,
+ $0b,$00,$f5,$f2,$0b,$00,$03,$80,$09,$99,
+ $fe,$7f,$ff,$7f,$ff,$7e,$00,$7e,$01,$7e,
+ $01,$7f,$01,$7e,$00,$7e,$fe,$7e,$01,$8e,
+ $ff,$7e,$00,$7e,$01,$7e,$01,$7f,$01,$7e,
+ $00,$7e,$ff,$7e,$fc,$7e,$04,$7e,$01,$7e,
+ $00,$7e,$ff,$7e,$ff,$7f,$ff,$7e,$00,$7e,
+ $01,$7e,$ff,$8e,$02,$7e,$00,$7e,$ff,$7e,
+ $ff,$7f,$ff,$7e,$00,$7e,$01,$7e,$01,$7f,
+ $02,$7f,$05,$87,$04,$95,$00,$77,$00,$fd,
+ $00,$77,$04,$80,$05,$99,$02,$7f,$01,$7f,
+ $01,$7e,$00,$7e,$ff,$7e,$ff,$7f,$ff,$7e,
+ $00,$7e,$02,$7e,$ff,$8e,$01,$7e,$00,$7e,
+ $ff,$7e,$ff,$7f,$ff,$7e,$00,$7e,$01,$7e,
+ $04,$7e,$fc,$7e,$ff,$7e,$00,$7e,$01,$7e,
+ $01,$7f,$01,$7e,$00,$7e,$ff,$7e,$01,$8e,
+ $fe,$7e,$00,$7e,$01,$7e,$01,$7f,$01,$7e,
+ $00,$7e,$ff,$7e,$ff,$7f,$fe,$7f,$09,$87,
+ $03,$86,$00,$02,$01,$03,$02,$01,$02,$00,
+ $02,$7f,$04,$7d,$02,$7f,$02,$00,$02,$01,
+ $01,$02,$ee,$fe,$01,$02,$02,$01,$02,$00,
+ $02,$7f,$04,$7d,$02,$7f,$02,$00,$02,$01,
+ $01,$03,$00,$02,$03,$f4,$10,$80,$03,$80,
+ $07,$15,$08,$6b,$fe,$85,$f5,$00,$10,$fb,
+ $0d,$95,$f6,$00,$00,$6b,$0a,$00,$02,$02,
+ $00,$08,$fe,$02,$f6,$00,$0e,$f4,$03,$80,
+ $00,$15,$0a,$00,$02,$7e,$00,$7e,$00,$7d,
+ $00,$7e,$fe,$7f,$f6,$00,$0a,$80,$02,$7e,
+ $01,$7e,$00,$7d,$ff,$7d,$fe,$7f,$f6,$00,
+ $10,$80,$03,$80,$00,$15,$0c,$00,$ff,$7e,
+ $03,$ed,$03,$fd,$00,$03,$02,$00,$00,$12,
+ $02,$03,$0a,$00,$00,$6b,$02,$00,$00,$7d,
+ $fe,$83,$f4,$00,$11,$80,$0f,$80,$f4,$00,
+ $00,$15,$0c,$00,$ff,$f6,$f5,$00,$0f,$f5,
+ $04,$95,$07,$76,$00,$0a,$07,$80,$f9,$76,
+ $00,$75,$f8,$80,$07,$0c,$09,$f4,$f9,$0c,
+ $09,$f4,$03,$92,$02,$03,$07,$00,$03,$7d,
+ $00,$7b,$fc,$7e,$04,$7d,$00,$7a,$fd,$7e,
+ $f9,$00,$fe,$02,$06,$89,$02,$00,$06,$f5,
+ $03,$95,$00,$6b,$0c,$15,$00,$6b,$02,$80,
+ $03,$95,$00,$6b,$0c,$15,$00,$6b,$f8,$96,
+ $03,$00,$07,$ea,$03,$80,$00,$15,$0c,$80,
+ $f7,$76,$fd,$00,$03,$80,$0a,$75,$03,$80,
+ $03,$80,$07,$13,$02,$02,$03,$00,$00,$6b,
+ $02,$80,$03,$80,$00,$15,$09,$6b,$09,$15,
+ $00,$6b,$03,$80,$03,$80,$00,$15,$00,$f6,
+ $0d,$00,$00,$8a,$00,$6b,$03,$80,$07,$80,
+ $fd,$00,$ff,$03,$00,$04,$00,$07,$00,$04,
+ $01,$02,$03,$01,$06,$00,$03,$7f,$01,$7e,
+ $01,$7c,$00,$79,$ff,$7c,$ff,$7d,$fd,$00,
+ $fa,$00,$0e,$80,$03,$80,$00,$15,$0c,$00,
+ $00,$6b,$02,$80,$03,$80,$00,$15,$0a,$00,
+ $02,$7f,$01,$7d,$00,$7b,$ff,$7e,$fe,$7f,
+ $f6,$00,$10,$f7,$11,$8f,$ff,$03,$ff,$02,
+ $fe,$01,$fa,$00,$fd,$7f,$ff,$7e,$00,$7c,
+ $00,$79,$00,$7b,$01,$7e,$03,$00,$06,$00,
+ $02,$00,$01,$03,$01,$02,$03,$fb,$03,$95,
+ $0c,$00,$fa,$80,$00,$6b,$09,$80,$03,$95,
+ $00,$77,$06,$7a,$06,$06,$00,$09,$fa,$f1,
+ $fa,$7a,$0e,$80,$03,$87,$00,$0b,$02,$02,
+ $03,$00,$02,$7e,$01,$02,$04,$00,$02,$7e,
+ $00,$75,$fe,$7e,$fc,$00,$ff,$01,$fe,$7f,
+ $fd,$00,$fe,$02,$07,$8e,$00,$6b,$09,$80,
+ $03,$80,$0e,$15,$f2,$80,$0e,$6b,$03,$80,
+ $03,$95,$00,$6b,$0e,$00,$00,$7d,$fe,$98,
+ $00,$6b,$05,$80,$03,$95,$00,$75,$02,$7d,
+ $0a,$00,$00,$8e,$00,$6b,$02,$80,$03,$95,
+ $00,$6b,$10,$00,$00,$15,$f8,$80,$00,$6b,
+ $0a,$80,$03,$95,$00,$6b,$10,$00,$00,$15,
+ $f8,$80,$00,$6b,$0a,$00,$00,$7d,$02,$83,
+ $10,$80,$03,$95,$00,$6b,$09,$00,$03,$02,
+ $00,$08,$fd,$02,$f7,$00,$0e,$89,$00,$6b,
+ $03,$80,$03,$95,$00,$6b,$09,$00,$03,$02,
+ $00,$08,$fd,$02,$f7,$00,$0e,$f4,$03,$92,
+ $02,$03,$07,$00,$03,$7d,$00,$70,$fd,$7e,
+ $f9,$00,$fe,$02,$03,$89,$09,$00,$02,$f5,
+ $03,$80,$00,$15,$00,$f5,$07,$00,$00,$08,
+ $02,$03,$06,$00,$02,$7d,$00,$70,$fe,$7e,
+ $fa,$00,$fe,$02,$00,$08,$0c,$f6,$0f,$80,
+ $00,$15,$f6,$00,$fe,$7d,$00,$79,$02,$7e,
+ $0a,$00,$f4,$f7,$07,$09,$07,$f7,$03,$8c,
+ $01,$02,$01,$01,$05,$00,$02,$7f,$01,$7e,
+ $00,$74,$00,$86,$ff,$01,$fe,$01,$fb,$00,
+ $ff,$7f,$ff,$7f,$00,$7c,$01,$7e,$01,$00,
+ $05,$00,$02,$00,$01,$02,$03,$fe,$04,$8e,
+ $02,$01,$04,$00,$02,$7f,$01,$7e,$00,$77,
+ $ff,$7e,$fe,$7f,$fc,$00,$fe,$01,$ff,$02,
+ $00,$09,$01,$02,$02,$02,$03,$01,$02,$01,
+ $01,$01,$01,$02,$02,$eb,$03,$80,$00,$15,
+ $03,$00,$02,$7e,$00,$7b,$fe,$7e,$fd,$00,
+ $03,$80,$04,$00,$03,$7e,$00,$78,$fd,$7e,
+ $f9,$00,$0c,$80,$03,$8c,$02,$02,$02,$01,
+ $03,$00,$02,$7f,$01,$7d,$fe,$7e,$f9,$7d,
+ $ff,$7e,$00,$7d,$03,$7f,$02,$00,$03,$01,
+ $02,$01,$02,$fe,$0d,$8c,$ff,$02,$fe,$01,
+ $fc,$00,$fe,$7f,$ff,$7e,$00,$77,$01,$7e,
+ $02,$7f,$04,$00,$02,$01,$01,$02,$00,$0f,
+ $ff,$02,$fe,$01,$f9,$00,$0c,$eb,$03,$88,
+ $0a,$00,$00,$02,$00,$03,$fe,$02,$fa,$00,
+ $ff,$7e,$ff,$7d,$00,$7b,$01,$7c,$01,$7f,
+ $06,$00,$02,$02,$03,$fe,$03,$8f,$06,$77,
+ $06,$09,$fa,$80,$00,$71,$ff,$87,$fb,$79,
+ $07,$87,$05,$79,$02,$80,$03,$8d,$02,$02,
+ $06,$00,$02,$7e,$00,$7d,$fc,$7d,$04,$7e,
+ $00,$7d,$fe,$7e,$fa,$00,$fe,$02,$04,$85,
+ $02,$00,$06,$f9,$03,$8f,$00,$73,$01,$7e,
+ $07,$00,$02,$02,$00,$0d,$00,$f3,$01,$7e,
+ $03,$80,$03,$8f,$00,$73,$01,$7e,$07,$00,
+ $02,$02,$00,$0d,$00,$f3,$01,$7e,$f8,$90,
+ $03,$00,$08,$f0,$03,$80,$00,$15,$00,$f3,
+ $02,$00,$06,$07,$fa,$f9,$07,$78,$03,$80,
+ $03,$80,$04,$0c,$02,$03,$04,$00,$00,$71,
+ $02,$80,$03,$80,$00,$0f,$06,$77,$06,$09,
+ $00,$71,$02,$80,$03,$80,$00,$0f,$0a,$f1,
+ $00,$0f,$f6,$f8,$0a,$00,$02,$f9,$05,$80,
+ $ff,$01,$ff,$04,$00,$05,$01,$03,$01,$02,
+ $06,$00,$02,$7e,$00,$7d,$00,$7b,$00,$7c,
+ $fe,$7f,$fa,$00,$0b,$80,$03,$80,$00,$0f,
+ $00,$fb,$01,$03,$01,$02,$05,$00,$02,$7e,
+ $01,$7d,$00,$76,$03,$80,$10,$80,$10,$80,
+ $10,$80,$10,$80,$10,$80,$10,$80,$10,$80,
+ $10,$80,$10,$80,$10,$80,$10,$80,$10,$80,
+ $10,$80,$10,$80,$10,$80,$10,$80,$10,$80,
+ $10,$80,$10,$80,$10,$80,$10,$80,$10,$80,
+ $10,$80,$10,$80,$10,$80,$10,$80,$10,$80,
+ $10,$80,$10,$80,$10,$80,$10,$80,$10,$80,
+ $10,$80,$10,$80,$10,$80,$10,$80,$10,$80,
+ $10,$80,$10,$80,$10,$80,$10,$80,$10,$80,
+ $10,$80,$10,$80,$10,$80,$10,$80,$10,$80,
+ $10,$80,$0a,$8f,$02,$7f,$01,$7e,$00,$76,
+ $ff,$7f,$fe,$7f,$fb,$00,$ff,$01,$ff,$01,
+ $00,$0a,$01,$02,$01,$01,$05,$00,$f9,$80,
+ $00,$6b,$0c,$86,$0d,$8a,$ff,$03,$fe,$02,
+ $fb,$00,$ff,$7e,$ff,$7d,$00,$7b,$01,$7c,
+ $01,$7f,$05,$00,$02,$01,$01,$03,$03,$fc,
+ $03,$80,$00,$0f,$00,$fb,$01,$03,$01,$02,
+ $04,$00,$01,$7e,$01,$7d,$00,$76,$00,$8a,
+ $01,$03,$02,$02,$03,$00,$02,$7e,$01,$7d,
+ $00,$76,$03,$80,$03,$8f,$00,$74,$01,$7e,
+ $02,$7f,$04,$00,$02,$01,$01,$01,$00,$8d,
+ $00,$6e,$ff,$7e,$fe,$7f,$fb,$00,$fe,$01,
+ $0c,$85,$03,$8d,$01,$02,$03,$00,$02,$7e,
+ $01,$02,$03,$00,$02,$7e,$00,$74,$fe,$7f,
+ $fd,$00,$ff,$01,$fe,$7f,$fd,$00,$ff,$01,
+ $00,$0c,$06,$82,$00,$6b,$08,$86,$03,$80,
+ $0a,$0f,$f6,$80,$0a,$71,$03,$80,$03,$8f,
+ $00,$73,$01,$7e,$07,$00,$02,$02,$00,$0d,
+ $00,$f3,$01,$7e,$00,$7e,$03,$82,$03,$8f,
+ $00,$79,$02,$7e,$08,$00,$00,$89,$00,$71,
+ $02,$80,$03,$8f,$00,$73,$01,$7e,$03,$00,
+ $02,$02,$00,$0d,$00,$f3,$01,$7e,$03,$00,
+ $02,$02,$00,$0d,$00,$f3,$01,$7e,$03,$80,
+ $03,$8f,$00,$73,$01,$7e,$03,$00,$02,$02,
+ $00,$0d,$00,$f3,$01,$7e,$03,$00,$02,$02,
+ $00,$0d,$00,$f3,$01,$7e,$00,$7e,$03,$82,
+ $03,$8d,$00,$02,$02,$00,$00,$71,$08,$00,
+ $02,$02,$00,$06,$fe,$02,$f8,$00,$0c,$f6,
+ $03,$8f,$00,$71,$07,$00,$02,$02,$00,$06,
+ $fe,$02,$f9,$00,$0c,$85,$00,$71,$02,$80,
+ $03,$8f,$00,$71,$07,$00,$03,$02,$00,$06,
+ $fd,$02,$f9,$00,$0c,$f6,$03,$8d,$02,$02,
+ $06,$00,$02,$7e,$00,$75,$fe,$7e,$fa,$00,
+ $fe,$02,$04,$85,$06,$00,$02,$f9,$03,$80,
+ $00,$0f,$00,$f8,$04,$00,$00,$06,$02,$02,
+ $04,$00,$02,$7e,$00,$75,$fe,$7e,$fc,$00,
+ $fe,$02,$00,$05,$0a,$f9,$0d,$80,$00,$0f,
+ $f7,$00,$ff,$7e,$00,$7b,$01,$7e,$09,$00,
+ $f6,$fa,$04,$06,$08,$fa );
+
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor gsv_text.Construct;
+var
+ t : int;
+
+begin
+ inherited Construct;
+
+ m_x :=0.0;
+ m_y :=0.0;
+ m_start_x :=0.0;
+ m_width :=10.0;
+ m_height :=0.0;
+ m_space :=0.0;
+ m_line_space :=0.0;
+ m_text :=@m_chr[0 ];
+ m_text_buf :=NIL;
+ m_buf_size :=0;
+ m_cur_chr :=@m_chr[0 ];
+ m_font :=@gsv_default_font[0 ];
+ m_loaded_font:=NIL;
+ m_loadfont_sz:=0;
+ m_status :=initial;
+ m_big_endian :=false;
+ m_flip :=false;
+
+ m_chr[0 ]:=0;
+ m_chr[1 ]:=0;
+
+ t:=1;
+
+ if byte(pointer(@t )^ ) = 0 then
+ m_big_endian:=true;
+
+end;
+
+{ DESTRUCT }
+destructor gsv_text.Destruct;
+begin
+ inherited Destruct;
+
+ if m_loaded_font <> NIL then
+ agg_freemem(m_loaded_font ,m_loadfont_sz );
+
+ if m_text_buf <> NIL then
+ agg_freemem(m_text_buf ,m_buf_size );
+
+end;
+
+{ FONT_ }
+procedure gsv_text.font_;
+begin
+ m_font:=font;
+
+ if m_font = NIL then
+ m_font:=m_loaded_font;
+
+end;
+
+{ FLIP_ }
+procedure gsv_text.flip_;
+begin
+ m_flip:=flip_y;
+
+end;
+
+{ LOAD_FONT_ }
+procedure gsv_text.load_font_;
+var
+ fd : file;
+ err : integer;
+
+begin
+ if m_loaded_font <> NIL then
+ agg_freemem(m_loaded_font ,m_loadfont_sz );
+
+{$I- }
+ err:=ioresult;
+
+ assignfile(fd ,_file_ );
+ reset (fd ,1 );
+
+ err:=ioresult;
+
+ if err = 0 then
+ begin
+ m_loadfont_sz:=filesize(fd );
+
+ if m_loadfont_sz > 0 then
+ begin
+ agg_getmem(m_loaded_font ,m_loadfont_sz );
+ blockread (fd ,m_loaded_font^ ,m_loadfont_sz );
+
+ m_font:=m_loaded_font;
+
+ end;
+
+ close(fd );
+
+ end;
+
+end;
+
+{ SIZE_ }
+procedure gsv_text.size_;
+begin
+ m_height:=height;
+ m_width :=width;
+
+end;
+
+{ SPACE_ }
+procedure gsv_text.space_;
+begin
+ m_space:=space;
+
+end;
+
+{ LINE_SPACE_ }
+procedure gsv_text.line_space_;
+begin
+ m_line_space:=line_space;
+
+end;
+
+{ START_POINT_ }
+procedure gsv_text.start_point_;
+begin
+ m_x:=x;
+ m_y:=y;
+
+ m_start_x:=x;
+
+end;
+
+{ TEXT_ }
+procedure gsv_text.text_;
+var
+ new_size : unsigned;
+
+begin
+ if text = NIL then
+ begin
+ m_chr[0 ]:=0;
+ m_text :=@m_chr[0 ];
+
+ exit;
+
+ end;
+
+ new_size:=StrLen(text ) + 1;
+
+ if new_size > m_buf_size then
+ begin
+ if m_text_buf <> NIL then
+ agg_freemem(m_text_buf ,m_buf_size );
+
+ agg_getmem(m_text_buf ,new_size );
+
+ m_buf_size:=new_size;
+
+ end;
+
+ move(text^ ,m_text_buf^ ,new_size );
+
+ m_text:=m_text_buf;
+
+end;
+
+{ REWIND }
+procedure gsv_text.rewind;
+var
+ base_height : double;
+
+begin
+ m_status:=initial;
+
+ if m_font = NIL then
+ exit;
+
+ m_indices:=m_font;
+
+ base_height:=_value(pointer(ptrcomp(m_indices ) + 4 * sizeof(int8u ) ) );
+
+ m_indices:=pointer(ptrcomp(m_indices ) + _value(m_indices ) );
+ m_glyphs :=pointer(ptrcomp(m_indices ) + 257 * 2 * sizeof(int8u ) );
+
+ m_h:= m_height / base_height;
+
+ if m_width = 0 then
+ m_w:=m_h
+ else
+ m_w:=m_width / base_height;
+
+ if m_flip then
+ m_h:=-m_h;
+
+ m_cur_chr:=m_text;
+
+end;
+
+{ VERTEX }
+function gsv_text.vertex;
+var
+ idx : unsigned;
+
+ yc ,yf : int8;
+ dx ,dy : int;
+
+ quit : boolean;
+
+label
+ _nxch ,_strt ;
+
+begin
+ quit:=false;
+
+ while not quit do
+ case m_status of
+ initial :
+ if m_font = NIL then
+ quit:=true
+
+ else
+ begin
+ m_status:=next_char;
+
+ goto _nxch;
+
+ end;
+
+ next_char :
+ _nxch:
+ if m_cur_chr^ = 0 then
+ quit:=true
+
+ else
+ begin
+ idx:=m_cur_chr^ and $FF;
+
+ inc(ptrcomp(m_cur_chr ) ,sizeof(int8u ) );
+
+ if idx = 13 then
+ begin
+ m_x:=m_start_x;
+
+ if m_flip then
+ m_y:=m_y - (-m_height - m_line_space )
+ else
+ m_y:=m_y - (m_height + m_line_space );
+
+ end
+ else
+ begin
+ idx:=idx shl 1;
+
+ m_bglyph:=pointer(ptrcomp(m_glyphs ) + _value(pointer(ptrcomp(m_indices ) + idx ) ) );
+ m_eglyph:=pointer(ptrcomp(m_glyphs ) + _value(pointer(ptrcomp(m_indices ) + idx + 2 ) ) );
+ m_status:=start_glyph;
+
+ goto _strt;
+
+ end;
+
+ end;
+
+ start_glyph :
+ _strt:
+ begin
+ x^:=m_x;
+ y^:=m_y;
+
+ m_status:=glyph;
+
+ result:=path_cmd_move_to;
+
+ exit;
+
+ end;
+
+ glyph :
+ if ptrcomp(m_bglyph ) >= ptrcomp(m_eglyph ) then
+ begin
+ m_status:=next_char;
+
+ m_x:=m_x + m_space;
+
+ end
+ else
+ begin
+ dx:=int(m_bglyph^ );
+
+ inc(ptrcomp(m_bglyph ) ,sizeof(int8u ) );
+
+ yc:=m_bglyph^;
+
+ inc(ptrcomp(m_bglyph ) ,sizeof(int8u ) );
+
+ yf:=yc and $80;
+ yc:=yc shl 1;
+ yc:=shr_int8(yc ,1 );
+
+ dy:=yc;
+
+ m_x:=m_x + (dx * m_w );
+ m_y:=m_y + (dy * m_h );
+
+ x^:=m_x;
+ y^:=m_y;
+
+ if yf <> 0 then
+ result:=path_cmd_move_to
+ else
+ result:=path_cmd_line_to;
+
+ exit;
+
+ end;
+
+ end;
+
+ result:=path_cmd_stop;
+
+end;
+
+{ _VALUE }
+function gsv_text._value;
+var
+ v : int16u;
+
+begin
+ if m_big_endian then
+ begin
+ int16u_(v ).Low :=int8u_ptr(ptrcomp(p ) + 1 )^;
+ int16u_(v ).High:=p^;
+
+ end
+ else
+ begin
+ int16u_(v ).Low :=p^;
+ int16u_(v ).High:=int8u_ptr(ptrcomp(p ) + 1 )^;
+
+ end;
+
+ result:=v;
+
+end;
+
+{ CONSTRUCT }
+constructor gsv_text_outline.Construct;
+begin
+ m_polyline.Construct(text );
+ m_trans.Construct (@m_polyline ,trans );
+
+end;
+
+{ DESTRUCT }
+destructor gsv_text_outline.Destruct;
+begin
+ m_polyline.Destruct;
+
+end;
+
+{ WIDTH_ }
+procedure gsv_text_outline.width_;
+begin
+ m_polyline.width_(w );
+
+end;
+
+{ TRANSFORMER_ }
+procedure gsv_text_outline.transformer_;
+begin
+ m_trans.transformer_(trans );
+
+end;
+
+{ REWIND }
+procedure gsv_text_outline.rewind;
+begin
+ m_trans.rewind(path_id );
+
+ m_polyline.line_join_(round_join );
+ m_polyline.line_cap_ (round_cap );
+
+end;
+
+{ VERTEX }
+function gsv_text_outline.vertex;
+begin
+ result:=m_trans.vertex(x ,y );
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_image_filters.pas b/src/corelib/render/software/agg_image_filters.pas
new file mode 100644
index 00000000..e908d0cd
--- /dev/null
+++ b/src/corelib/render/software/agg_image_filters.pas
@@ -0,0 +1,1143 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// Image transformation filters,
+// Filtering classes (image_filter_lut, image_filter),
+// Basic filter shape classes
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 01.03.2006-Milano: Unit port establishment
+//
+{ agg_image_filters.pas }
+unit
+ agg_image_filters ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+{$Q- }
+{$R- }
+uses
+ Math ,
+ agg_basics ,
+ agg_math ;
+
+{ TYPES DEFINITION }
+const
+ image_filter_shift = 14; //----image_filter_shift
+ image_filter_size = 1 shl image_filter_shift; //----image_filter_size
+ image_filter_mask = image_filter_size - 1; //----image_filter_mask
+
+ image_subpixel_shift = 8; //----image_subpixel_shift
+ image_subpixel_size = 1 shl image_subpixel_shift; //----image_subpixel_size
+ image_subpixel_mask = image_subpixel_size - 1; //----image_subpixel_mask
+
+type
+ image_filter_base_ptr = ^image_filter_base;
+ image_filter_base = object
+ constructor Construct;
+
+ function radius : double; virtual; abstract;
+ function calc_weight(x : double ) : double; virtual; abstract;
+
+ procedure set_radius(r : double ); virtual;
+
+ end;
+
+ image_filter_lut_ptr = ^image_filter_lut;
+ image_filter_lut = object
+ m_radius : double;
+ m_diameter : unsigned;
+ m_start : int;
+
+ m_weight_array : int16_ptr;
+ m_max_size : unsigned;
+
+ constructor Construct; overload;
+ constructor Construct(filter : image_filter_base_ptr; normalization : boolean = true ); overload;
+ destructor Destruct;
+
+ procedure calculate(filter : image_filter_base_ptr; normalization : boolean = true );
+
+ function radius : double;
+ function diameter : unsigned;
+ function start : int;
+ function weight_array : int16_ptr;
+
+ procedure normalize;
+ procedure realloc_lut(radius_ : double );
+
+ end;
+
+ image_filter_ptr = ^image_filter;
+ image_filter = object(image_filter_lut )
+ m_filter_function : image_filter_base_ptr;
+
+ constructor Construct(filter : image_filter_base_ptr );
+
+ end;
+
+ image_filter_bilinear_ptr = ^image_filter_bilinear;
+ image_filter_bilinear = object(image_filter_base )
+ function radius : double; virtual;
+ function calc_weight(x : double ) : double; virtual;
+
+ end;
+
+ image_filter_hanning_ptr = ^image_filter_hanning;
+ image_filter_hanning = object(image_filter_base )
+ function radius : double; virtual;
+ function calc_weight(x : double ) : double; virtual;
+
+ end;
+
+ image_filter_hamming_ptr = ^image_filter_hamming;
+ image_filter_hamming = object(image_filter_base )
+ function radius : double; virtual;
+ function calc_weight(x : double ) : double; virtual;
+
+ end;
+
+ image_filter_hermite_ptr = ^image_filter_hermite;
+ image_filter_hermite = object(image_filter_base )
+ function radius : double; virtual;
+ function calc_weight(x : double ) : double; virtual;
+
+ end;
+
+ image_filter_quadric_ptr = ^image_filter_quadric;
+ image_filter_quadric = object(image_filter_base )
+ function radius : double; virtual;
+ function calc_weight(x : double ) : double; virtual;
+
+ end;
+
+ image_filter_bicubic_ptr = ^image_filter_bicubic;
+ image_filter_bicubic = object(image_filter_base )
+ function pow3(x : double ) : double;
+
+ function radius : double; virtual;
+ function calc_weight(x : double ) : double; virtual;
+
+ end;
+
+ image_filter_kaiser_ptr = ^image_filter_kaiser;
+ image_filter_kaiser = object(image_filter_base )
+ a ,i0a ,epsilon : double;
+
+ constructor Construct(b : double = 6.33 );
+
+ function radius : double; virtual;
+ function calc_weight(x : double ) : double; virtual;
+
+ function bessel_i0(x : double ) : double;
+
+ end;
+
+ image_filter_catrom_ptr = ^image_filter_catrom;
+ image_filter_catrom = object(image_filter_base )
+ function radius : double; virtual;
+ function calc_weight(x : double ) : double; virtual;
+
+ end;
+
+ image_filter_mitchell_ptr = ^image_filter_mitchell;
+ image_filter_mitchell = object(image_filter_base )
+ p0 ,p2 ,p3 ,
+ q0 ,q1 ,q2 ,q3 : double;
+
+ constructor Construct(b : double = 1.0 / 3.0; c : double = 1.0 / 3.0 );
+
+ function radius : double; virtual;
+ function calc_weight(x : double ) : double; virtual;
+
+ end;
+
+ image_filter_spline16_ptr = ^image_filter_spline16;
+ image_filter_spline16 = object(image_filter_base )
+ function radius : double; virtual;
+ function calc_weight(x : double ) : double; virtual;
+
+ end;
+
+ image_filter_spline36_ptr = ^image_filter_spline36;
+ image_filter_spline36 = object(image_filter_base )
+ function radius : double; virtual;
+ function calc_weight(x : double ) : double; virtual;
+
+ end;
+
+ image_filter_gaussian_ptr = ^image_filter_gaussian;
+ image_filter_gaussian = object(image_filter_base )
+ function radius : double; virtual;
+ function calc_weight(x : double ) : double; virtual;
+
+ end;
+
+ image_filter_bessel_ptr = ^image_filter_bessel;
+ image_filter_bessel = object(image_filter_base )
+ function radius : double; virtual;
+ function calc_weight(x : double ) : double; virtual;
+
+ end;
+
+ image_filter_sinc_ptr = ^image_filter_sinc;
+ image_filter_sinc = object(image_filter_base )
+ m_radius : double;
+
+ constructor Construct(r : double );
+
+ function radius : double; virtual;
+ function calc_weight(x : double ) : double; virtual;
+
+ procedure set_radius(r : double ); virtual;
+
+ end;
+
+ image_filter_lanczos_ptr = ^image_filter_lanczos;
+ image_filter_lanczos = object(image_filter_base )
+ m_radius : double;
+
+ constructor Construct(r : double );
+
+ function radius : double; virtual;
+ function calc_weight(x : double ) : double; virtual;
+
+ procedure set_radius(r : double ); virtual;
+
+ end;
+
+ image_filter_blackman_ptr = ^image_filter_blackman;
+ image_filter_blackman = object(image_filter_base )
+ m_radius : double;
+
+ constructor Construct(r : double );
+
+ function radius : double; virtual;
+ function calc_weight(x : double ) : double; virtual;
+
+ procedure set_radius(r : double ); virtual;
+
+ end;
+
+ image_filter_sinc36_ptr = ^image_filter_sinc36;
+ image_filter_sinc36 = object(image_filter_sinc )
+ constructor Construct;
+
+ end;
+
+ image_filter_sinc64_ptr = ^image_filter_sinc64;
+ image_filter_sinc64 = object(image_filter_sinc )
+ constructor Construct;
+
+ end;
+
+ image_filter_sinc100_ptr = ^image_filter_sinc100;
+ image_filter_sinc100 = object(image_filter_sinc )
+ constructor Construct;
+
+ end;
+
+ image_filter_sinc144_ptr = ^image_filter_sinc144;
+ image_filter_sinc144 = object(image_filter_sinc )
+ constructor Construct;
+
+ end;
+
+ image_filter_sinc196_ptr = ^image_filter_sinc196;
+ image_filter_sinc196 = object(image_filter_sinc )
+ constructor Construct;
+
+ end;
+
+ image_filter_sinc256_ptr = ^image_filter_sinc256;
+ image_filter_sinc256 = object(image_filter_sinc )
+ constructor Construct;
+
+ end;
+
+ image_filter_lanczos36_ptr = ^image_filter_lanczos36;
+ image_filter_lanczos36 = object(image_filter_lanczos )
+ constructor Construct;
+
+ end;
+
+ image_filter_lanczos64_ptr = ^image_filter_lanczos64;
+ image_filter_lanczos64 = object(image_filter_lanczos )
+ constructor Construct;
+
+ end;
+
+ image_filter_lanczos100_ptr = ^image_filter_lanczos100;
+ image_filter_lanczos100 = object(image_filter_lanczos )
+ constructor Construct;
+
+ end;
+
+ image_filter_lanczos144_ptr = ^image_filter_lanczos144;
+ image_filter_lanczos144 = object(image_filter_lanczos )
+ constructor Construct;
+
+ end;
+
+ image_filter_lanczos196_ptr = ^image_filter_lanczos196;
+ image_filter_lanczos196 = object(image_filter_lanczos )
+ constructor Construct;
+
+ end;
+
+ image_filter_lanczos256_ptr = ^image_filter_lanczos256;
+ image_filter_lanczos256 = object(image_filter_lanczos )
+ constructor Construct;
+
+ end;
+
+ image_filter_blackman36_ptr = ^image_filter_blackman36;
+ image_filter_blackman36 = object(image_filter_blackman )
+ constructor Construct;
+
+ end;
+
+ image_filter_blackman64_ptr = ^image_filter_blackman64;
+ image_filter_blackman64 = object(image_filter_blackman )
+ constructor Construct;
+
+ end;
+
+ image_filter_blackman100_ptr = ^image_filter_blackman100;
+ image_filter_blackman100 = object(image_filter_blackman )
+ constructor Construct;
+
+ end;
+
+ image_filter_blackman144_ptr = ^image_filter_blackman144;
+ image_filter_blackman144 = object(image_filter_blackman )
+ constructor Construct;
+
+ end;
+
+ image_filter_blackman196_ptr = ^image_filter_blackman196;
+ image_filter_blackman196 = object(image_filter_blackman )
+ constructor Construct;
+
+ end;
+
+ image_filter_blackman256_ptr = ^image_filter_blackman256;
+ image_filter_blackman256 = object(image_filter_blackman )
+ constructor Construct;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor image_filter_base.Construct;
+begin
+end;
+
+{ SET_RADIUS }
+procedure image_filter_base.set_radius;
+begin
+end;
+
+{ CONSTRUCT }
+constructor image_filter_lut.Construct;
+begin
+ m_weight_array:=NIL;
+ m_max_size :=0;
+
+end;
+
+{ CONSTRUCT }
+constructor image_filter_lut.Construct(filter : image_filter_base_ptr; normalization : boolean = true );
+begin
+ m_weight_array:=NIL;
+ m_max_size :=0;
+
+ calculate(filter ,normalization );
+
+end;
+
+{ DESTRUCT }
+destructor image_filter_lut.Destruct;
+begin
+ agg_freemem(pointer(m_weight_array ) ,m_max_size * sizeof(int16 ) );
+
+end;
+
+{ CALCULATE }
+procedure image_filter_lut.calculate;
+var
+ r ,x ,y : double;
+
+ i ,pivot ,end_ : unsigned;
+
+begin
+ r:=filter.radius;
+
+ realloc_lut(r );
+
+ pivot:=diameter shl (image_subpixel_shift - 1 );
+
+ i:=0;
+
+ while i < pivot do
+ begin
+ x:=i / image_subpixel_size;
+ y:=filter.calc_weight(x );
+
+ int16_ptr(ptrcomp(m_weight_array ) + (pivot + i ) * sizeof(int16 ) )^:=
+ int16(trunc(y * image_filter_size + 0.5 ) );
+
+ int16_ptr(ptrcomp(m_weight_array ) + (pivot - i ) * sizeof(int16 ) )^:=
+ int16_ptr(ptrcomp(m_weight_array ) + (pivot + i ) * sizeof(int16 ) )^;
+
+ inc(i );
+
+ end;
+
+ end_:=(diameter shl image_subpixel_shift ) - 1;
+
+ int16_ptr(ptrcomp(m_weight_array ) + 0 * sizeof(int16 ) )^:=
+ int16_ptr(ptrcomp(m_weight_array ) + end_ * sizeof(int16 ) )^;
+
+ if normalization then
+ normalize;
+
+end;
+
+{ RADIUS }
+function image_filter_lut.radius;
+begin
+ result:=m_radius;
+
+end;
+
+{ DIAMETER }
+function image_filter_lut.diameter;
+begin
+ result:=m_diameter;
+
+end;
+
+{ START }
+function image_filter_lut.start;
+begin
+ result:=m_start;
+
+end;
+
+{ WEIGHT_ARRAY }
+function image_filter_lut.weight_array;
+begin
+ result:=m_weight_array;
+
+end;
+
+{ NORMALIZE }
+// This function normalizes integer values and corrects the rounding
+// errors. It doesn't do anything with the source floating point values
+// (m_weight_array_dbl), it corrects only integers according to the rule
+// of 1.0 which means that any sum of pixel weights must be equal to 1.0.
+// So, the filter function must produce a graph of the proper shape.
+procedure image_filter_lut.normalize;
+var
+ k : double;
+
+ i ,j ,idx ,pivot ,end_ : unsigned;
+
+ flip ,sum ,inc_ ,v : int;
+
+begin
+ flip:=1;
+ i :=0;
+
+ while i < image_subpixel_size do
+ begin
+ repeat
+ sum:=0;
+
+ for j:=0 to m_diameter - 1 do
+ inc(
+ sum ,
+ int16_ptr(ptrcomp(m_weight_array ) + (j * image_subpixel_size + i ) * sizeof(int16 ) )^ );
+
+ if sum = image_filter_size then
+ break;
+
+ k :=image_filter_size / sum;
+ sum:=0;
+
+ for j:=0 to m_diameter - 1 do
+ begin
+ int16_ptr(ptrcomp(m_weight_array ) + (j * image_subpixel_size + i ) * sizeof(int16 ) )^:=
+ int16(trunc(int16_ptr(ptrcomp(m_weight_array ) + (j * image_subpixel_size + i ) * sizeof(int16 ) )^ * k ) );
+
+ inc(sum ,int16_ptr(ptrcomp(m_weight_array ) + (j * image_subpixel_size + i ) * sizeof(int16 ) )^ );
+
+ end;
+
+ dec(sum ,image_filter_size );
+
+ if sum > 0 then
+ inc_:=-1
+ else
+ inc_:=1;
+
+ j:=0;
+
+ while (j < m_diameter ) and
+ (sum <> 0 ) do
+ begin
+ flip:=flip xor 1;
+
+ if flip <> 0 then
+ idx:=m_diameter div 2 + j div 2
+ else
+ idx:=m_diameter div 2 - j div 2;
+
+ v:=int16_ptr(ptrcomp(m_weight_array ) + (idx * image_subpixel_size + i ) * sizeof(int16 ) )^;
+
+ if v < image_filter_size then
+ begin
+ inc(
+ int16_ptr(ptrcomp(m_weight_array ) + (idx * image_subpixel_size + i ) * sizeof(int16 ) )^ ,
+ inc_ );
+
+ inc(sum ,inc_ );
+
+ end;
+
+ inc(j );
+
+ end;
+
+ until false;
+
+ inc(i );
+
+ end;
+
+ pivot:=m_diameter shl (image_subpixel_shift - 1 );
+
+ for i:=0 to pivot - 1 do
+ int16_ptr(ptrcomp(m_weight_array ) + (pivot + i ) * sizeof(int16 ) )^:=
+ int16_ptr(ptrcomp(m_weight_array ) + (pivot - i ) * sizeof(int16 ) )^;
+
+ end_:=(diameter shl image_subpixel_shift ) - 1;
+
+ int16_ptr(ptrcomp(m_weight_array ) + 0 * sizeof(int16 ) )^:=
+ int16_ptr(ptrcomp(m_weight_array ) + end_ * sizeof(int16 ) )^;
+
+end;
+
+{ REALLOC_LUT }
+procedure image_filter_lut.realloc_lut;
+var
+ size : unsigned;
+
+begin
+ m_radius :=radius_;
+ m_diameter:=unsigned(trunc(Ceil(radius_ ) ) ) * 2 ;
+ m_start :=-int(m_diameter div 2 - 1 );
+
+ size:=m_diameter shl image_subpixel_shift;
+
+ if size > m_max_size then
+ begin
+ agg_freemem(pointer(m_weight_array ) ,m_max_size * sizeof(int16 ) );
+ agg_getmem (pointer(m_weight_array ) ,size * sizeof(int16 ) );
+
+ m_max_size:=size;
+
+ end;
+
+end;
+
+{ CONSTRUCT }
+constructor image_filter.Construct;
+begin
+ inherited Construct;
+
+ m_filter_function:=filter;
+
+ calculate(m_filter_function );
+
+end;
+
+{ RADIUS }
+function image_filter_bilinear.radius;
+begin
+ result:=1.0;
+end;
+
+{ CALC_WEIGHT }
+function image_filter_bilinear.calc_weight;
+begin
+ result:=1.0 - x;
+
+end;
+
+{ RADIUS }
+function image_filter_hanning.radius;
+begin
+ result:=1.0;
+
+end;
+
+{ CALC_WEIGHT }
+function image_filter_hanning.calc_weight;
+begin
+ result:=0.5 + 0.5 * Cos(pi * x );
+
+end;
+
+{ RADIUS }
+function image_filter_hamming.radius;
+begin
+ result:=1.0;
+
+end;
+
+{ CALC_WEIGHT }
+function image_filter_hamming.calc_weight;
+begin
+ result:=0.54 + 0.46 * Cos(pi * x );
+
+end;
+
+{ RADIUS }
+function image_filter_hermite.radius;
+begin
+ result:=1.0;
+
+end;
+
+{ CALC_WEIGHT }
+function image_filter_hermite.calc_weight;
+begin
+ result:=(2.0 * x - 3.0 ) * x * x + 1.0;
+
+end;
+
+{ RADIUS }
+function image_filter_quadric.radius;
+begin
+ result:=1.5;
+
+end;
+
+{ CALC_WEIGHT }
+function image_filter_quadric.calc_weight;
+var
+ t : double;
+
+begin
+ if x < 0.5 then
+ result:=0.75 - x * x
+ else
+ if x < 1.5 then
+ begin
+ t:=x - 1.5;
+
+ result:=0.5 * t * t;
+
+ end
+ else
+ result:=0.0;
+
+end;
+
+{ POW3 }
+function image_filter_bicubic.pow3;
+begin
+ if x <= 0.0 then
+ result:=0.0
+ else
+ result:=x * x * x;
+
+end;
+
+{ RADIUS }
+function image_filter_bicubic.radius;
+begin
+ result:=2.0;
+
+end;
+
+{ CALC_WEIGHT }
+function image_filter_bicubic.calc_weight;
+begin
+ result:=
+ (1.0 / 6.0 ) *
+ (pow3(x + 2 ) - 4 * pow3(x + 1 ) + 6 * pow3(x ) - 4 * pow3(x - 1 ) );
+
+end;
+
+{ CONSTRUCT }
+constructor image_filter_kaiser.Construct;
+begin
+ a:=b;
+
+ epsilon:=1e-12;
+
+ i0a:=1.0 / bessel_i0(b );
+
+end;
+
+{ RADIUS }
+function image_filter_kaiser.radius;
+begin
+ result:=1.0;
+
+end;
+
+{ CALC_WEIGHT }
+function image_filter_kaiser.calc_weight;
+begin
+ result:=bessel_i0(a * Sqrt(1.0 - x * x ) ) * i0a;
+
+end;
+
+{ BESSEL_I0 }
+function image_filter_kaiser.bessel_i0;
+var
+ i : int;
+
+ sum ,y ,t : double;
+
+begin
+ sum:=1;
+
+ y:=x * x / 4.;
+ t:=y;
+ i:=2;
+
+ while t > epsilon do
+ begin
+ sum:=sum + t;
+
+ t:=t * (y / (i * i ) );
+
+ inc(i );
+
+ end;
+
+ result:=sum;
+
+end;
+
+{ RADIUS }
+function image_filter_catrom.radius;
+begin
+ result:=2.0;
+
+end;
+
+{ CALC_WEIGHT }
+function image_filter_catrom.calc_weight;
+begin
+ if x < 1.0 then
+ result:=0.5 * (2.0 + x * x * (-5.0 + x * 3.0 ) )
+ else
+ if x < 2.0 then
+ result:=0.5 * (4.0 + x * (-8.0 + x * (5.0 - x ) ) )
+ else
+ result:=0.0;
+
+end;
+
+{ CONSTRUCT }
+constructor image_filter_mitchell.Construct;
+begin
+ p0:=(6.0 - 2.0 * b ) / 6.0;
+ p2:=(-18.0 + 12.0 * b + 6.0 * c ) / 6.0;
+ p3:=(12.0 - 9.0 * b - 6.0 * c ) / 6.0;
+ q0:=(8.0 * b + 24.0 * c ) / 6.0;
+ q1:=(-12.0 * b - 48.0 * c ) / 6.0;
+ q2:=(6.0 * b + 30.0 * c ) / 6.0;
+ q3:=(-b - 6.0 * c ) / 6.0;
+
+end;
+
+{ RADIUS }
+function image_filter_mitchell.radius;
+begin
+ result:=2.0;
+
+end;
+
+{ CALC_WEIGHT }
+function image_filter_mitchell.calc_weight;
+begin
+ if x < 1.0 then
+ result:=p0 + x * x * (p2 + x * p3 )
+ else
+ if x < 2.0 then
+ result:=q0 + x * (q1 + x * (q2 + x * q3 ) )
+ else
+ result:=0.0;
+
+end;
+
+{ RADIUS }
+function image_filter_spline16.radius;
+begin
+ result:=2.0;
+
+end;
+
+{ CALC_WEIGHT }
+function image_filter_spline16.calc_weight;
+begin
+ if x < 1.0 then
+ result:=((x - 9.0 / 5.0 ) * x - 1.0 / 5.0 ) * x + 1.0
+ else
+ result:=((-1.0 / 3.0 * (x - 1 ) + 4.0 / 5.0) * (x - 1 ) - 7.0 / 15.0 ) * (x - 1 );
+
+end;
+
+{ RADIUS }
+function image_filter_spline36.radius;
+begin
+ result:=3.0;
+
+end;
+
+{ CALC_WEIGHT }
+function image_filter_spline36.calc_weight;
+begin
+ if x < 1.0 then
+ result:=((13.0 / 11.0 * x - 453.0 / 209.0 ) * x - 3.0 / 209.0 ) * x + 1.0
+ else
+ if x < 2.0 then
+ result:=((-6.0 / 11.0 * (x - 1 ) + 270.0 / 209.0 ) * (x - 1 ) - 156.0 / 209.0 ) * (x - 1 )
+ else
+ result:=((1.0 / 11.0 * (x - 2 ) - 45.0 / 209.0 ) * (x - 2 ) + 26.0 / 209.0 ) * (x - 2 );
+
+end;
+
+{ RADIUS }
+function image_filter_gaussian.radius;
+begin
+ result:=2.0;
+
+end;
+
+{ CALC_WEIGHT }
+function image_filter_gaussian.calc_weight;
+begin
+ result:=Exp(-2.0 * x * x ) * Sqrt(2.0 / pi );
+
+end;
+
+{ RADIUS }
+function image_filter_bessel.radius;
+begin
+ result:=3.2383;
+
+end;
+
+{ CALC_WEIGHT }
+function image_filter_bessel.calc_weight;
+begin
+ if x = 0.0 then
+ result:=pi / 4.0
+ else
+ result:=besj(pi * x ,1 ) / (2.0 * x );
+
+end;
+
+{ CONSTRUCT }
+constructor image_filter_sinc.Construct;
+begin
+ if r < 2.0 then
+ m_radius:=2.0
+ else
+ m_radius:=r;
+
+end;
+
+{ RADIUS }
+function image_filter_sinc.radius;
+begin
+ result:=m_radius;
+
+end;
+
+{ CALC_WEIGHT }
+function image_filter_sinc.calc_weight;
+begin
+ if x = 0.0 then
+ result:=1.0
+ else
+ begin
+ x:=x * pi;
+
+ result:=Sin(x ) / x;
+
+ end;
+
+end;
+
+{ SET_RADIUS }
+procedure image_filter_sinc.set_radius;
+begin
+ if r < 2.0 then
+ m_radius:=2.0
+ else
+ m_radius:=r;
+
+end;
+
+{ CONSTRUCT }
+constructor image_filter_lanczos.Construct;
+begin
+ if r < 2.0 then
+ m_radius:=2.0
+ else
+ m_radius:=r;
+
+end;
+
+{ RADIUS }
+function image_filter_lanczos.radius;
+begin
+ result:=m_radius;
+
+end;
+
+{ CALC_WEIGHT }
+function image_filter_lanczos.calc_weight;
+var
+ xr : double;
+
+begin
+ if x = 0.0 then
+ result:=1.0
+ else
+ if x > m_radius then
+ result:=0.0
+ else
+ begin
+ x :=x * pi;
+ xr:=x / m_radius;
+
+ result:=(Sin(x ) / x ) * (Sin(xr ) / xr );
+
+ end;
+
+end;
+
+{ SET_RADIUS }
+procedure image_filter_lanczos.set_radius;
+begin
+ if r < 2.0 then
+ m_radius:=2.0
+ else
+ m_radius:=r;
+
+end;
+
+{ CONSTRUCT }
+constructor image_filter_blackman.Construct;
+begin
+ if r < 2.0 then
+ m_radius:=2.0
+ else
+ m_radius:=r;
+
+end;
+
+{ RADIUS }
+function image_filter_blackman.radius;
+begin
+ result:=m_radius;
+
+end;
+
+{ CALC_WEIGHT }
+function image_filter_blackman.calc_weight;
+var
+ xr : double;
+
+begin
+ if x = 0.0 then
+ result:=1.0
+ else
+ if x > m_radius then
+ result:=0.0
+ else
+ begin
+ x :=x * pi;
+ xr:= x / m_radius;
+
+ result:=(Sin(x ) / x ) * (0.42 + 0.5 * Cos(xr ) + 0.08 * Cos(2 * xr ) );
+
+ end;
+
+end;
+
+{ SET_RADIUS }
+procedure image_filter_blackman.set_radius;
+begin
+ if r < 2.0 then
+ m_radius:=2.0
+ else
+ m_radius:=r;
+
+end;
+
+{ CONSTRUCT }
+constructor image_filter_sinc36.Construct;
+begin
+ inherited Construct(3.0 );
+
+end;
+
+{ CONSTRUCT }
+constructor image_filter_sinc64.Construct;
+begin
+ inherited Construct(4.0 );
+
+end;
+
+{ CONSTRUCT }
+constructor image_filter_sinc100.Construct;
+begin
+ inherited Construct(5.0 );
+
+end;
+
+{ CONSTRUCT }
+constructor image_filter_sinc144.Construct;
+begin
+ inherited Construct(6.0 );
+
+end;
+
+{ CONSTRUCT }
+constructor image_filter_sinc196.Construct;
+begin
+ inherited Construct(7.0 );
+
+end;
+
+{ CONSTRUCT }
+constructor image_filter_sinc256.Construct;
+begin
+ inherited Construct(8.0 );
+
+end;
+
+{ CONSTRUCT }
+constructor image_filter_lanczos36.Construct;
+begin
+ inherited Construct(3.0 );
+
+end;
+
+{ CONSTRUCT }
+constructor image_filter_lanczos64.Construct;
+begin
+ inherited Construct(4.0 );
+
+end;
+
+{ CONSTRUCT }
+constructor image_filter_lanczos100.Construct;
+begin
+ inherited Construct(5.0 );
+
+end;
+
+{ CONSTRUCT }
+constructor image_filter_lanczos144.Construct;
+begin
+ inherited Construct(6.0 );
+
+end;
+
+{ CONSTRUCT }
+constructor image_filter_lanczos196.Construct;
+begin
+ inherited Construct(7.0 );
+
+end;
+
+{ CONSTRUCT }
+constructor image_filter_lanczos256.Construct;
+begin
+ inherited Construct(8.0 );
+
+end;
+
+{ CONSTRUCT }
+constructor image_filter_blackman36.Construct;
+begin
+ inherited Construct(3.0 );
+
+end;
+
+{ CONSTRUCT }
+constructor image_filter_blackman64.Construct;
+begin
+ inherited Construct(4.0 );
+
+end;
+
+{ CONSTRUCT }
+constructor image_filter_blackman100.Construct;
+begin
+ inherited Construct(5.0 );
+
+end;
+
+{ CONSTRUCT }
+constructor image_filter_blackman144.Construct;
+begin
+ inherited Construct(6.0 );
+
+end;
+
+{ CONSTRUCT }
+constructor image_filter_blackman196.Construct;
+begin
+ inherited Construct(7.0 );
+
+end;
+
+{ CONSTRUCT }
+constructor image_filter_blackman256.Construct;
+begin
+ inherited Construct(8.0 );
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_line_aa_basics.pas b/src/corelib/render/software/agg_line_aa_basics.pas
new file mode 100644
index 00000000..35dbfeb2
--- /dev/null
+++ b/src/corelib/render/software/agg_line_aa_basics.pas
@@ -0,0 +1,281 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 31.10.2006-Milano: Unit port establishment
+//
+{ agg_line_aa_basics.pas }
+unit
+ agg_line_aa_basics ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ;
+
+{ TYPES DEFINITION }
+const
+ line_subpixel_shift = 8; //----line_subpixel_shift
+ line_subpixel_size = 1 shl line_subpixel_shift; //----line_subpixel_size
+ line_subpixel_mask = line_subpixel_size - 1; //----line_subpixel_mask
+
+ line_mr_subpixel_shift = 4; //----line_mr_subpixel_shift
+ line_mr_subpixel_size = 1 shl line_mr_subpixel_shift; //----line_mr_subpixel_size
+ line_mr_subpixel_mask = line_mr_subpixel_size - 1; //----line_mr_subpixel_mask
+
+type
+ line_parameters_ptr = ^line_parameters;
+ line_parameters = object
+ x1, y1, x2, y2, dx, dy, sx, sy : int;
+
+ vertical : boolean;
+
+ inc_ ,len ,octant : int;
+
+ constructor Construct; overload;
+ constructor Construct(x1_ ,y1_ ,x2_ ,y2_ ,len_ : int ); overload;
+
+ function orthogonal_quadrant : unsigned;
+ function diagonal_quadrant : unsigned;
+
+ function same_orthogonal_quadrant(lp : line_parameters_ptr ) : boolean;
+ function same_diagonal_quadrant (lp : line_parameters_ptr ) : boolean;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+ function line_mr(x : int ) : int;
+ function line_hr(x : int ) : int;
+
+ function line_dbl_hr(x : int ) : int;
+ function line_coord (x : double ) : int;
+
+ procedure bisectrix(l1 ,l2 : line_parameters_ptr; x ,y : int_ptr );
+
+ procedure fix_degenerate_bisectrix_start(lp : line_parameters_ptr; x ,y : int_ptr );
+ procedure fix_degenerate_bisectrix_end (lp : line_parameters_ptr; x ,y : int_ptr );
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+const
+// The number of the octant is determined as a 3-bit value as follows:
+// bit 0 = vertical flag
+// bit 1 = sx < 0
+// bit 2 = sy < 0
+//
+// [N] shows the number of the orthogonal quadrant
+// <M> shows the number of the diagonal quadrant
+// <1>
+// [1] | [0]
+// . (3)011 | 001(1) .
+// . | .
+// . | .
+// . | .
+// (2)010 .|. 000(0)
+// <2> ----------.+.----------- <0>
+// (6)110 . | . 100(4)
+// . | .
+// . | .
+// . | .
+// (7)111 | 101(5)
+// [2] | [3]
+// <3>
+// 0 ,1 ,2 ,3 ,4 ,5 ,6 ,7
+ s_orthogonal_quadrant : array[0..7 ] of int8u = (0 ,0 ,1 ,1 ,3 ,3 ,2 ,2 );
+ s_diagonal_quadrant : array[0..7 ] of int8u = (0 ,1 ,2 ,1 ,0 ,3 ,2 ,3 );
+
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor line_parameters.Construct;
+begin
+end;
+
+{ CONSTRUCT }
+constructor line_parameters.Construct(x1_ ,y1_ ,x2_ ,y2_ ,len_ : int );
+begin
+ x1:=x1_;
+ y1:=y1_;
+ x2:=x2_;
+ y2:=y2_;
+ dx:=Abs(x2_ - x1_ );
+ dy:=Abs(y2_ - y1_ );
+
+ if x2_ > x1_ then
+ sx:=1
+ else
+ sx:=-1;
+
+ if y2_ > y1_ then
+ sy:=1
+ else
+ sy:=-1;
+
+ vertical:=dy >= dx;
+
+ if vertical then
+ inc_:=sy
+ else
+ inc_:=sx;
+
+ len:=len_;
+
+ octant:=(sy and 4 ) or (sx and 2 ) or int(vertical );
+
+end;
+
+{ ORTHOGONAL_QUADRANT }
+function line_parameters.orthogonal_quadrant;
+begin
+ result:=s_orthogonal_quadrant[octant ];
+
+end;
+
+{ DIAGONAL_QUADRANT }
+function line_parameters.diagonal_quadrant;
+begin
+ result:=s_diagonal_quadrant[octant ];
+
+end;
+
+{ SAME_ORTHOGONAL_QUADRANT }
+function line_parameters.same_orthogonal_quadrant;
+begin
+ result:=s_orthogonal_quadrant[octant ] = s_orthogonal_quadrant[lp.octant ];
+
+end;
+
+{ SAME_DIAGONAL_QUADRANT }
+function line_parameters.same_diagonal_quadrant;
+begin
+ result:=s_diagonal_quadrant[octant ] = s_diagonal_quadrant[lp.octant ];
+
+end;
+
+{ LINE_MR }
+function line_mr;
+begin
+ result:=shr_int32(x ,line_subpixel_shift - line_mr_subpixel_shift );
+
+end;
+
+{ LINE_HR }
+function line_hr;
+begin
+ result:=x shl (line_subpixel_shift - line_mr_subpixel_shift );
+
+end;
+
+{ LINE_DBL_HR }
+function line_dbl_hr;
+begin
+ result:=x shl line_subpixel_shift;
+
+end;
+
+{ LINE_COORD }
+function line_coord;
+begin
+ result:=trunc(x * line_subpixel_size );
+
+end;
+
+{ BISECTRIX }
+procedure bisectrix;
+var
+ k ,tx ,ty ,dx ,dy : double;
+
+begin
+ k :=l2.len / l1.len;
+ tx:=l2.x2 - (l2.x1 - l1.x1 ) * k;
+ ty:=l2.y2 - (l2.y1 - l1.y1 ) * k;
+
+//All bisectrices must be on the right of the line
+//If the next point is on the left (l1 => l2.2)
+//then the bisectix should be rotated by 180 degrees.
+ if intdbl(l2.x2 - l2.x1 ) * intdbl(l2.y1 - l1.y1 ) <
+ intdbl(l2.y2 - l2.y1 ) * intdbl(l2.x1 - l1.x1 ) + 100.0 then
+ begin
+ tx:=tx - ((tx - l2.x1 ) * 2.0 );
+ ty:=ty - ((ty - l2.y1 ) * 2.0 );
+
+ end;
+
+// Check if the bisectrix is too short
+ dx:=tx - l2.x1;
+ dy:=ty - l2.y1;
+
+ if trunc(Sqrt(dx * dx + dy * dy ) ) < line_subpixel_size then
+ begin
+ x^:=shr_int32(l2.x1 + l2.x1 + (l2.y1 - l1.y1 ) + (l2.y2 - l2.y1 ) ,1 );
+ y^:=shr_int32(l2.y1 + l2.y1 - (l2.x1 - l1.x1 ) - (l2.x2 - l2.x1 ) ,1 );
+
+ exit;
+
+ end;
+
+ x^:=trunc(tx );
+ y^:=trunc(ty );
+
+end;
+
+{ FIX_DEGENERATE_BISECTRIX_START }
+procedure fix_degenerate_bisectrix_start;
+var
+ d : int;
+
+begin
+ d:=trunc(
+ (intdbl(x^ - lp.x2 ) * intdbl(lp.y2 - lp.y1 ) -
+ intdbl(y^ - lp.y2 ) * intdbl(lp.x2 - lp.x1 ) ) / lp.len );
+
+ if d < line_subpixel_size then
+ begin
+ x^:=lp.x1 + (lp.y2 - lp.y1 );
+ y^:=lp.y1 - (lp.x2 - lp.x1 );
+
+ end;
+
+end;
+
+{ FIX_DEGENERATE_BISECTRIX_END }
+procedure fix_degenerate_bisectrix_end;
+var
+ d : int;
+
+begin
+ d:=trunc(
+ (intdbl(x^ - lp.x2 ) * intdbl(lp.y2 - lp.y1 ) -
+ intdbl(y^ - lp.y2 ) * intdbl(lp.x2 - lp.x1 ) ) / lp.len );
+
+ if d < line_subpixel_size then
+ begin
+ x^:=lp.x2 + (lp.y2 - lp.y1 );
+ y^:=lp.y2 - (lp.x2 - lp.x1 );
+
+ end;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_math.pas b/src/corelib/render/software/agg_math.pas
new file mode 100644
index 00000000..4f3734ac
--- /dev/null
+++ b/src/corelib/render/software/agg_math.pas
@@ -0,0 +1,593 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+// Bessel function (besj) was adapted for use in AGG library by Andy Wilk
+// Contact: castor.vulgaris@gmail.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 18.12.2005-Milano: Unit port establishment
+//
+{ agg_math.pas }
+unit
+ agg_math ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+{$Q- }
+{$R- }
+uses
+ Math ,
+ agg_basics ,
+ agg_vertex_sequence ;
+
+{ GLOBAL VARIABLES & CONSTANTS }
+type
+ double_xy_ptr = ^double_xy;
+ double_xy = record
+ x ,y : double;
+
+ end;
+
+ poly_xy_ptr = ^poly_xy;
+ poly_xy = array[0..0 ] of double_xy;
+
+ storage_xy_ptr = ^storage_xy;
+ storage_xy = record
+ poly : poly_xy_ptr;
+ size : unsigned;
+
+ end;
+
+const
+ intersection_epsilon : double = 1.0e-30;
+
+// Tables for fast sqrt
+const
+ g_sqrt_table : array[0..1023 ] of int16u = (0 ,
+ 2048,2896,3547,4096,4579,5017,5418,5793,6144,6476,6792,7094,7384,7663,7932,8192,8444,
+ 8689,8927,9159,9385,9606,9822,10033,10240,10443,10642,10837,11029,11217,11403,11585,
+ 11765,11942,12116,12288,12457,12625,12790,12953,13114,13273,13430,13585,13738,13890,
+ 14040,14189,14336,14482,14626,14768,14910,15050,15188,15326,15462,15597,15731,15864,
+ 15995,16126,16255,16384,16512,16638,16764,16888,17012,17135,17257,17378,17498,17618,
+ 17736,17854,17971,18087,18203,18318,18432,18545,18658,18770,18882,18992,19102,19212,
+ 19321,19429,19537,19644,19750,19856,19961,20066,20170,20274,20377,20480,20582,20684,
+ 20785,20886,20986,21085,21185,21283,21382,21480,21577,21674,21771,21867,21962,22058,
+ 22153,22247,22341,22435,22528,22621,22713,22806,22897,22989,23080,23170,23261,23351,
+ 23440,23530,23619,23707,23796,23884,23971,24059,24146,24232,24319,24405,24491,24576,
+ 24661,24746,24831,24915,24999,25083,25166,25249,25332,25415,25497,25580,25661,25743,
+ 25824,25905,25986,26067,26147,26227,26307,26387,26466,26545,26624,26703,26781,26859,
+ 26937,27015,27092,27170,27247,27324,27400,27477,27553,27629,27705,27780,27856,27931,
+ 28006,28081,28155,28230,28304,28378,28452,28525,28599,28672,28745,28818,28891,28963,
+ 29035,29108,29180,29251,29323,29394,29466,29537,29608,29678,29749,29819,29890,29960,
+ 30030,30099,30169,30238,30308,30377,30446,30515,30583,30652,30720,30788,30856,30924,
+ 30992,31059,31127,31194,31261,31328,31395,31462,31529,31595,31661,31727,31794,31859,
+ 31925,31991,32056,32122,32187,32252,32317,32382,32446,32511,32575,32640,32704,32768,
+ 32832,32896,32959,33023,33086,33150,33213,33276,33339,33402,33465,33527,33590,33652,
+ 33714,33776,33839,33900,33962,34024,34086,34147,34208,34270,34331,34392,34453,34514,
+ 34574,34635,34695,34756,34816,34876,34936,34996,35056,35116,35176,35235,35295,35354,
+ 35413,35472,35531,35590,35649,35708,35767,35825,35884,35942,36001,36059,36117,36175,
+ 36233,36291,36348,36406,36464,36521,36578,36636,36693,36750,36807,36864,36921,36978,
+ 37034,37091,37147,37204,37260,37316,37372,37429,37485,37540,37596,37652,37708,37763,
+ 37819,37874,37929,37985,38040,38095,38150,38205,38260,38315,38369,38424,38478,38533,
+ 38587,38642,38696,38750,38804,38858,38912,38966,39020,39073,39127,39181,39234,39287,
+ 39341,39394,39447,39500,39553,39606,39659,39712,39765,39818,39870,39923,39975,40028,
+ 40080,40132,40185,40237,40289,40341,40393,40445,40497,40548,40600,40652,40703,40755,
+ 40806,40857,40909,40960,41011,41062,41113,41164,41215,41266,41317,41368,41418,41469,
+ 41519,41570,41620,41671,41721,41771,41821,41871,41922,41972,42021,42071,42121,42171,
+ 42221,42270,42320,42369,42419,42468,42518,42567,42616,42665,42714,42763,42813,42861,
+ 42910,42959,43008,43057,43105,43154,43203,43251,43300,43348,43396,43445,43493,43541,
+ 43589,43637,43685,43733,43781,43829,43877,43925,43972,44020,44068,44115,44163,44210,
+ 44258,44305,44352,44400,44447,44494,44541,44588,44635,44682,44729,44776,44823,44869,
+ 44916,44963,45009,45056,45103,45149,45195,45242,45288,45334,45381,45427,45473,45519,
+ 45565,45611,45657,45703,45749,45795,45840,45886,45932,45977,46023,46069,46114,46160,
+ 46205,46250,46296,46341,46386,46431,46477,46522,46567,46612,46657,46702,46746,46791,
+ 46836,46881,46926,46970,47015,47059,47104,47149,47193,47237,47282,47326,47370,47415,
+ 47459,47503,47547,47591,47635,47679,47723,47767,47811,47855,47899,47942,47986,48030,
+ 48074,48117,48161,48204,48248,48291,48335,48378,48421,48465,48508,48551,48594,48637,
+ 48680,48723,48766,48809,48852,48895,48938,48981,49024,49067,49109,49152,49195,49237,
+ 49280,49322,49365,49407,49450,49492,49535,49577,49619,49661,49704,49746,49788,49830,
+ 49872,49914,49956,49998,50040,50082,50124,50166,50207,50249,50291,50332,50374,50416,
+ 50457,50499,50540,50582,50623,50665,50706,50747,50789,50830,50871,50912,50954,50995,
+ 51036,51077,51118,51159,51200,51241,51282,51323,51364,51404,51445,51486,51527,51567,
+ 51608,51649,51689,51730,51770,51811,51851,51892,51932,51972,52013,52053,52093,52134,
+ 52174,52214,52254,52294,52334,52374,52414,52454,52494,52534,52574,52614,52654,52694,
+ 52734,52773,52813,52853,52892,52932,52972,53011,53051,53090,53130,53169,53209,53248,
+ 53287,53327,53366,53405,53445,53484,53523,53562,53601,53640,53679,53719,53758,53797,
+ 53836,53874,53913,53952,53991,54030,54069,54108,54146,54185,54224,54262,54301,54340,
+ 54378,54417,54455,54494,54532,54571,54609,54647,54686,54724,54762,54801,54839,54877,
+ 54915,54954,54992,55030,55068,55106,55144,55182,55220,55258,55296,55334,55372,55410,
+ 55447,55485,55523,55561,55599,55636,55674,55712,55749,55787,55824,55862,55900,55937,
+ 55975,56012,56049,56087,56124,56162,56199,56236,56273,56311,56348,56385,56422,56459,
+ 56497,56534,56571,56608,56645,56682,56719,56756,56793,56830,56867,56903,56940,56977,
+ 57014,57051,57087,57124,57161,57198,57234,57271,57307,57344,57381,57417,57454,57490,
+ 57527,57563,57599,57636,57672,57709,57745,57781,57817,57854,57890,57926,57962,57999,
+ 58035,58071,58107,58143,58179,58215,58251,58287,58323,58359,58395,58431,58467,58503,
+ 58538,58574,58610,58646,58682,58717,58753,58789,58824,58860,58896,58931,58967,59002,
+ 59038,59073,59109,59144,59180,59215,59251,59286,59321,59357,59392,59427,59463,59498,
+ 59533,59568,59603,59639,59674,59709,59744,59779,59814,59849,59884,59919,59954,59989,
+ 60024,60059,60094,60129,60164,60199,60233,60268,60303,60338,60373,60407,60442,60477,
+ 60511,60546,60581,60615,60650,60684,60719,60753,60788,60822,60857,60891,60926,60960,
+ 60995,61029,61063,61098,61132,61166,61201,61235,61269,61303,61338,61372,61406,61440,
+ 61474,61508,61542,61576,61610,61644,61678,61712,61746,61780,61814,61848,61882,61916,
+ 61950,61984,62018,62051,62085,62119,62153,62186,62220,62254,62287,62321,62355,62388,
+ 62422,62456,62489,62523,62556,62590,62623,62657,62690,62724,62757,62790,62824,62857,
+ 62891,62924,62957,62991,63024,63057,63090,63124,63157,63190,63223,63256,63289,63323,
+ 63356,63389,63422,63455,63488,63521,63554,63587,63620,63653,63686,63719,63752,63785,
+ 63817,63850,63883,63916,63949,63982,64014,64047,64080,64113,64145,64178,64211,64243,
+ 64276,64309,64341,64374,64406,64439,64471,64504,64536,64569,64601,64634,64666,64699,
+ 64731,64763,64796,64828,64861,64893,64925,64957,64990,65022,65054,65086,65119,65151,
+ 65183,65215,65247,65279,65312,65344,65376,65408,65440,65472,65504 );
+
+ g_elder_bit_table : array[0..255 ] of int8 = (
+ 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+ 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+ 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+ 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 );
+
+{ GLOBAL PROCEDURES }
+ function calc_point_location(x1 ,y1 ,x2 ,y2 ,x ,y : double ) : double;
+
+ function point_in_triangle(x1 ,y1 ,x2 ,y2 ,x3 ,y3 ,x ,y : double ) : boolean;
+
+ function calc_distance(x1 ,y1 ,x2 ,y2 : double ) : double;
+
+ function calc_line_point_distance(x1 ,y1 ,x2 ,y2 ,x ,y : double ) : double;
+
+ function calc_intersection(ax ,ay ,bx ,by ,cx ,cy ,dx ,dy : double; x ,y : double_ptr ) : boolean;
+
+ function intersection_exists(x1 ,y1 ,x2 ,y2 ,x3 ,y3 ,x4 ,y4 : double ) : boolean;
+
+ procedure calc_orthogonal(thickness ,x1 ,y1 ,x2 ,y2 : double; x ,y : double_ptr );
+
+ procedure dilate_triangle(x1 ,y1 ,x2 ,y2 ,x3 ,y3 : double; x ,y : double_ptr; d : double );
+
+ function calc_triangle_area(x1 ,y1 ,x2 ,y2 ,x3 ,y3 : double ) : double;
+
+ function calc_polygon_area(st : storage_xy_ptr ) : double;
+
+ function calc_polygon_area_vs(st : vertex_sequence_ptr ) : double;
+
+ function fast_sqrt(val : unsigned ) : unsigned;
+
+ function besj(x : double; n : int ) : double;
+
+ function cross_product(x1 ,y1 ,x2 ,y2 ,x ,y : double ) : double;
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ calc_point_location }
+function calc_point_location;
+begin
+ result:=(x - x2 ) * (y2 - y1 ) - (y - y2 ) * (x2 - x1 );
+
+end;
+
+{ point_in_triangle }
+function point_in_triangle;
+var
+ cp1 ,cp2 ,cp3 : boolean;
+
+begin
+ cp1:=calc_point_location(x1 ,y1 ,x2 ,y2 ,x ,y ) < 0.0;
+ cp2:=calc_point_location(x2 ,y2 ,x3 ,y3 ,x ,y ) < 0.0;
+ cp3:=calc_point_location(x3 ,y3 ,x1 ,y1 ,x ,y ) < 0.0;
+
+ result:=(cp1 = cp2 ) and (cp2 = cp3 ) and (cp3 = cp1 );
+
+end;
+
+{ calc_distance }
+function calc_distance;
+var
+ dx ,dy : double;
+
+begin
+ dx:=x2 - x1;
+ dy:=y2 - y1;
+
+ result:=sqrt(dx * dx + dy * dy );
+
+end;
+
+{ calc_line_point_distance }
+function calc_line_point_distance;
+var
+ d ,
+ dx ,
+ dy : double;
+
+begin
+ dx:=x2 - x1;
+ dy:=y2 - y1;
+ d :=sqrt(dx * dx + dy * dy );
+
+ if d < intersection_epsilon then
+ result:=calc_distance(x1 ,y1 ,x ,y )
+ else
+ result:=((x - x2 ) * dy - (y - y2 ) * dx) / d;
+
+end;
+
+{ calc_intersection }
+function calc_intersection;
+var
+ r ,
+
+ num ,
+ den : double;
+
+begin
+ num:=(ay - cy ) * (dx - cx ) - (ax - cx ) * (dy - cy );
+ den:=(bx - ax ) * (dy - cy ) - (by - ay ) * (dx - cx );
+
+ if Abs(den ) < intersection_epsilon then
+ result:=false
+
+ else
+ begin
+ r :=num / den;
+ x^:=ax + r * (bx - ax );
+ y^:=ay + r * (by - ay );
+
+ result:=true;
+
+ end;
+
+end;
+
+{ intersection_exists }
+function intersection_exists;
+var
+ dx1 ,dy1 ,
+ dx2 ,dy2 : double;
+
+begin
+ dx1:=x2 - x1;
+ dy1:=y2 - y1;
+ dx2:=x4 - x3;
+ dy2:=y4 - y3;
+
+ result:=
+ (((x3 - x2 ) * dy1 - (y3 - y2 ) * dx1 < 0.0 ) <>
+ ((x4 - x2 ) * dy1 - (y4 - y2 ) * dx1 < 0.0 ) ) and
+ (((x1 - x4 ) * dy2 - (y1 - y4 ) * dx2 < 0.0 ) <>
+ ((x2 - x4 ) * dy2 - (y2 - y4 ) * dx2 < 0.0 ) );
+
+end;
+
+{ calc_orthogonal }
+procedure calc_orthogonal;
+var
+ d ,dx ,dy : double;
+
+begin
+ dx:=x2 - x1;
+ dy:=y2 - y1;
+ d :=sqrt(dx * dx + dy * dy );
+ x^:=thickness * dy / d;
+ y^:=thickness * dx / d;
+
+end;
+
+{ dilate_triangle }
+procedure dilate_triangle;
+var
+ loc ,
+ dx1 ,dy1 ,
+ dx2 ,dy2 ,
+ dx3 ,dy3 : double;
+
+begin
+ dx1:=0.0;
+ dy1:=0.0;
+ dx2:=0.0;
+ dy2:=0.0;
+ dx3:=0.0;
+ dy3:=0.0;
+ loc:=calc_point_location(x1 ,y1 ,x2 ,y2 ,x3 ,y3 );
+
+ if Abs(loc ) > intersection_epsilon then
+ begin
+ if calc_point_location(x1 ,y1 ,x2 ,y2 ,x3 ,y3 ) > 0.0 then
+ d:=-d;
+
+ calc_orthogonal(d ,x1 ,y1 ,x2 ,y2 ,@dx1 ,@dy1 );
+ calc_orthogonal(d ,x2 ,y2 ,x3 ,y3 ,@dx2 ,@dy2 );
+ calc_orthogonal(d ,x3 ,y3 ,x1 ,y1 ,@dx3 ,@dy3 );
+
+ end;
+
+ x^:=x1 + dx1; inc(ptrcomp(x ) ,sizeof(double ) );
+ y^:=y1 - dy1; inc(ptrcomp(y ) ,sizeof(double ) );
+ x^:=x2 + dx1; inc(ptrcomp(x ) ,sizeof(double ) );
+ y^:=y2 - dy1; inc(ptrcomp(y ) ,sizeof(double ) );
+ x^:=x2 + dx2; inc(ptrcomp(x ) ,sizeof(double ) );
+ y^:=y2 - dy2; inc(ptrcomp(y ) ,sizeof(double ) );
+ x^:=x3 + dx2; inc(ptrcomp(x ) ,sizeof(double ) );
+ y^:=y3 - dy2; inc(ptrcomp(y ) ,sizeof(double ) );
+ x^:=x3 + dx3; inc(ptrcomp(x ) ,sizeof(double ) );
+ y^:=y3 - dy3; inc(ptrcomp(y ) ,sizeof(double ) );
+ x^:=x1 + dx3; inc(ptrcomp(x ) ,sizeof(double ) );
+ y^:=y1 - dy3; inc(ptrcomp(y ) ,sizeof(double ) );
+
+end;
+
+{ calc_triangle_area }
+function calc_triangle_area;
+begin
+ result:=(x1 * y2 - x2 * y1 + x2 * y3 - x3 * y2 + x3 * y1 - x1 * y3 ) * 0.5;
+
+end;
+
+{ calc_polygon_area }
+function calc_polygon_area;
+var
+ i : unsigned;
+ v : double_xy_ptr;
+
+ x ,y ,sum ,xs ,ys : double;
+
+begin
+ sum:=0.0;
+ x :=st.poly[0 ].x;
+ y :=st.poly[0 ].y;
+ xs :=x;
+ ys :=y;
+
+ if st.size > 0 then
+ for i:=1 to st.size - 1 do
+ begin
+ v:=@st.poly[i ];
+
+ sum:=sum + (x * v.y - y * v.x );
+
+ x:=v.x;
+ y:=v.y;
+
+ end;
+
+ result:=(sum + x * ys - y * xs ) * 0.5;
+
+end;
+
+{ calc_polygon_area_vs }
+function calc_polygon_area_vs;
+var
+ i : unsigned;
+ v : vertex_dist_ptr;
+
+ x ,y ,sum ,xs ,ys : double;
+
+begin
+ sum:=0.0;
+ x :=vertex_dist_ptr(st.array_operator(0 ) ).x;
+ y :=vertex_dist_ptr(st.array_operator(0 ) ).y;
+ xs :=x;
+ ys :=y;
+
+ if st.size > 0 then
+ for i:=1 to st.size - 1 do
+ begin
+ v:=st.array_operator(i );
+
+ sum:=sum + (x * v.y - y * v.x );
+
+ x:=v.x;
+ y:=v.y;
+
+ end;
+
+ result:=(sum + x * ys - y * xs ) * 0.5;
+
+end;
+
+{ fast_sqrt }
+function fast_sqrt;
+var
+ bit : int;
+
+ t ,shift : unsigned;
+
+begin
+ t :=val;
+ bit:=0;
+
+ shift:=11;
+
+//The following piece of code is just an emulation of the
+//Ix86 assembler command "bsr" (see below). However on old
+//Intels (like Intel MMX 233MHz) this code is about twice
+//faster (sic!) then just one "bsr". On PIII and PIV the
+//bsr is optimized quite well.
+ bit:=t shr 24;
+
+ if bit <> 0 then
+ bit:=g_elder_bit_table[bit ] + 24
+
+ else
+ begin
+ bit:=(t shr 16 ) and $FF;
+
+ if bit <> 0 then
+ bit:=g_elder_bit_table[bit ] + 16
+ else
+ begin
+ bit:=(t shr 8 ) and $FF;
+
+ if bit <> 0 then
+ bit:=g_elder_bit_table[bit ] + 8
+ else
+ bit:=g_elder_bit_table[t ];
+
+ end;
+
+ end;
+
+// This is calculation sqrt itself.
+ bit:=bit - 9;
+
+ if bit > 0 then
+ begin
+ bit :=(shr_int32(bit ,1 ) ) + (bit and 1 );
+ shift:=shift - bit;
+ val :=val shr (bit shl 1 );
+
+ end;
+
+ result:=g_sqrt_table[val ] shr shift;
+
+end;
+
+//--------------------------------------------------------------------besj
+// Function BESJ calculates Bessel function of first kind of order n
+// Arguments:
+// n - an integer (>=0), the order
+// x - value at which the Bessel function is required
+//--------------------
+// C++ Mathematical Library
+// Convereted from equivalent FORTRAN library
+// Converetd by Gareth Walker for use by course 392 computational project
+// All functions tested and yield the same results as the corresponding
+// FORTRAN versions.
+//
+// If you have any problems using these functions please report them to
+// M.Muldoon@UMIST.ac.uk
+//
+// Documentation available on the web
+// http://www.ma.umist.ac.uk/mrm/Teaching/392/libs/392.html
+// Version 1.0 8/98
+// 29 October, 1999
+//--------------------
+// Adapted for use in AGG library by Andy Wilk (castor.vulgaris@gmail.com)
+//------------------------------------------------------------------------
+{ besj }
+function besj;
+var
+ i ,m1 ,m2 ,m8 ,imax : int;
+
+ d ,b ,b1 ,c2 ,c3 ,c4 ,c6 : double;
+
+begin
+ if n < 0 then
+ begin
+ result:=0;
+
+ exit;
+
+ end;
+
+ d:=1E-6;
+ b:=0;
+
+ if Abs(x ) <= d then
+ begin
+ if n <> 0 then
+ result:=0
+ else
+ result:=1;
+
+ exit;
+
+ end;
+
+ b1:=0; // b1 is the value from the previous iteration
+
+// Set up a starting order for recurrence
+ m1:=trunc(Abs(x ) + 6 );
+
+ if Abs(x ) > 5 then
+ m1:=trunc(Abs(1.4 * x + 60 / x ) );
+
+ m2:=trunc(n + 2 + Abs(x ) / 4 );
+
+ if m1 > m2 then
+ m2:=m1;
+
+// Apply recurrence down from curent max order
+ repeat
+ c3:=0;
+ c2:=1E-30;
+ c4:=0;
+ m8:=1;
+
+ if m2 div 2 * 2 = m2 then
+ m8:=-1;
+
+ imax:=m2 - 2;
+
+ for i:=1 to imax do
+ begin
+ c6:=2 * (m2 - i ) * c2 / x - c3;
+ c3:=c2;
+ c2:=c6;
+
+ if m2 - i - 1 = n then
+ b:=c6;
+
+ m8:=-1 * m8;
+
+ if m8 > 0 then
+ c4:=c4 + 2 * c6;
+
+ end;
+
+ c6:=2 * c2 / x - c3;
+
+ if n = 0 then
+ b:=c6;
+
+ c4:=c4 + c6;
+ b :=b / c4;
+
+ if Abs(b - b1 ) < d then
+ begin
+ result:=b;
+
+ exit;
+
+ end;
+
+ b1:=b;
+
+ inc(m2 ,3 );
+
+ until false;
+
+end;
+
+{ CROSS_PRODUCT }
+function cross_product(x1 ,y1 ,x2 ,y2 ,x ,y : double ) : double;
+begin
+ result:=(x - x2 ) * (y2 - y1 ) - (y - y2 ) * (x2 - x1 );
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_math_stroke.pas b/src/corelib/render/software/agg_math_stroke.pas
new file mode 100644
index 00000000..1978be3e
--- /dev/null
+++ b/src/corelib/render/software/agg_math_stroke.pas
@@ -0,0 +1,1169 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// Stroke math
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 18.10.2007-Milano: math_stroke
+// 10.01.2006-Milano: stroke_calc_join ,stroke_calc_miter ,stroke_calc_arc
+// 09.01.2006-Milano: stroke_calc_cap
+// 19.12.2005-Milano: Unit port establishment
+//
+{ agg_math_stroke.pas }
+unit
+ agg_math_stroke ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ Math ,
+ agg_basics ,
+ agg_math ,
+ agg_vertex_sequence ,
+ agg_array ;
+
+{ TYPES DEFINITION }
+const
+ butt_cap = 0;
+ square_cap = 1;
+ round_cap = 2;
+
+ miter_join = 0;
+ miter_join_revert = 1;
+ miter_join_round = 4;
+ round_join = 2;
+ bevel_join = 3;
+
+ inner_bevel = 0;
+ inner_miter = 1;
+ inner_jag = 2;
+ inner_round = 3;
+
+// Minimal angle to calculate round joins, less than 0.1 degree.
+ stroke_theta = 0.001;
+
+type
+ line_cap_e = int;
+ line_join_e = int;
+ inner_join_e = int;
+
+//------------------------------------------------------------math_stroke
+ math_stroke = object
+ m_width ,
+ m_width_abs ,
+ m_width_eps : double;
+
+ m_width_sign : int;
+
+ m_miter_limit ,
+ m_inner_miter_limit ,
+ m_approx_scale : double;
+
+ m_line_cap : line_cap_e;
+ m_line_join : line_join_e;
+ m_inner_join : inner_join_e;
+
+ constructor Construct;
+
+ procedure line_cap_ (lc : line_cap_e );
+ procedure line_join_ (lj : line_join_e );
+ procedure inner_join_(ij : inner_join_e );
+
+ function _line_cap : line_cap_e;
+ function _line_join : line_join_e;
+ function _inner_join : inner_join_e;
+
+ procedure width_ (w : double );
+ procedure miter_limit_ (ml : double );
+ procedure miter_limit_theta_ (t : double );
+ procedure inner_miter_limit_ (ml : double );
+ procedure approximation_scale_(as_ : double );
+
+ function _width : double;
+ function _miter_limit : double;
+ function _inner_miter_limit : double;
+ function _approximation_scale : double;
+
+ procedure calc_cap(
+ vc : pod_bvector_ptr;
+ v0 ,v1 : vertex_dist_ptr;
+ len : double );
+
+ procedure calc_join(
+ vc : pod_bvector_ptr;
+ v0 ,v1 ,v2 : vertex_dist_ptr;
+ len1 ,len2 : double );
+
+ procedure add_vertex(vc : pod_bvector_ptr; x ,y : double );
+
+ procedure calc_arc(
+ vc : pod_bvector_ptr;
+ x ,y ,dx1 ,dy1 ,dx2 ,dy2 : double );
+
+ procedure calc_miter(
+ vc : pod_bvector_ptr;
+ v0 ,v1 ,v2 : vertex_dist_ptr;
+ dx1 ,dy1 ,dx2 ,dy2 : double;
+ lj : line_join_e;
+ mlimit ,dbevel : double );
+
+ end;
+
+{ GLOBAL PROCEDURES }
+ procedure stroke_calc_arc(
+ out_vertices : pod_deque_ptr;
+ x ,y ,dx1 ,dy1 ,dx2 ,dy2 ,width ,approximation_scale : double );
+
+ procedure stroke_calc_miter(
+ out_vertices : pod_deque_ptr;
+ v0 ,v1 ,v2 : vertex_dist_ptr;
+ dx1 ,dy1 ,dx2 ,dy2 ,width : double;
+ line_join : unsigned;
+ miter_limit ,approximation_scale : double );
+
+ procedure stroke_calc_cap(
+ out_vertices : pod_deque_ptr;
+ v0 ,v1 : vertex_dist_ptr;
+ len : double;
+ line_cap : unsigned;
+ width ,approximation_scale : double );
+
+ procedure stroke_calc_join(
+ out_vertices : pod_deque_ptr;
+ v0 ,v1 , v2 : vertex_dist_ptr;
+ len1 ,len2 ,width : double;
+ line_join ,inner_join : unsigned;
+ miter_limit ,inner_miter_limit ,approximation_scale : double );
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor math_stroke.Construct;
+begin
+ m_width :=0.5;
+ m_width_abs :=0.5;
+ m_width_eps :=0.5 / 1024.0;
+ m_width_sign:=1;
+
+ m_miter_limit :=4.0;
+ m_inner_miter_limit:=1.01;
+ m_approx_scale :=1.0;
+
+ m_line_cap :=butt_cap;
+ m_line_join :=miter_join;
+ m_inner_join:=inner_miter;
+
+end;
+
+{ LINE_CAP_ }
+procedure math_stroke.line_cap_(lc : line_cap_e );
+begin
+ m_line_cap:=lc;
+
+end;
+
+{ LINE_JOIN_ }
+procedure math_stroke.line_join_(lj : line_join_e );
+begin
+ m_line_join:=lj;
+
+end;
+
+{ INNER_JOIN_ }
+procedure math_stroke.inner_join_(ij : inner_join_e );
+begin
+ m_inner_join:=ij;
+
+end;
+
+{ _LINE_CAP }
+function math_stroke._line_cap : line_cap_e;
+begin
+ result:=m_line_cap;
+
+end;
+
+{ _LINE_JOIN }
+function math_stroke._line_join : line_join_e;
+begin
+ result:=m_line_join;
+
+end;
+
+{ _INNER_JOIN }
+function math_stroke._inner_join : inner_join_e;
+begin
+ result:=m_inner_join;
+
+end;
+
+{ WIDTH_ }
+procedure math_stroke.width_(w : double );
+begin
+ m_width:=w * 0.5;
+
+ if m_width < 0 then
+ begin
+ m_width_abs :=-m_width;
+ m_width_sign:=-1;
+
+ end
+ else
+ begin
+ m_width_abs :=m_width;
+ m_width_sign:=1;
+
+ end;
+
+ m_width_eps:=m_width / 1024.0;
+
+end;
+
+{ MITER_LIMIT_ }
+procedure math_stroke.miter_limit_(ml : double );
+begin
+ m_miter_limit:=ml;
+
+end;
+
+{ MITER_LIMIT_THETA_ }
+procedure math_stroke.miter_limit_theta_(t : double );
+begin
+ m_miter_limit:=1.0 / Sin(t * 0.5 ) ;
+
+end;
+
+{ INNER_MITER_LIMIT_ }
+procedure math_stroke.inner_miter_limit_(ml : double );
+begin
+ m_inner_miter_limit:=ml;
+
+end;
+
+{ APPROXIMATION_SCALE_ }
+procedure math_stroke.approximation_scale_(as_ : double );
+begin
+ m_approx_scale:=as_;
+
+end;
+
+{ _WIDTH }
+function math_stroke._width : double;
+begin
+ result:=m_width * 2.0;
+
+end;
+
+{ _MITER_LIMIT }
+function math_stroke._miter_limit : double;
+begin
+ result:=m_miter_limit;
+
+end;
+
+{ _INNER_MITER_LIMIT }
+function math_stroke._inner_miter_limit : double;
+begin
+ result:=m_inner_miter_limit;
+
+end;
+
+{ _APPROXIMATION_SCALE }
+function math_stroke._approximation_scale : double;
+begin
+ result:=m_approx_scale;
+
+end;
+
+{ CALC_CAP }
+procedure math_stroke.calc_cap(
+ vc : pod_bvector_ptr;
+ v0 ,v1 : vertex_dist_ptr;
+ len : double );
+var
+ dx1 ,dy1 ,dx2 ,dy2 ,da ,a1 : double;
+
+ i ,n : int;
+
+begin
+ vc.remove_all;
+
+ dx1:=(v1.y - v0.y ) / len;
+ dy1:=(v1.x - v0.x ) / len;
+ dx2:=0;
+ dy2:=0;
+
+ dx1:=dx1 * m_width;
+ dy1:=dy1 * m_width;
+
+ if m_line_cap <> round_cap then
+ begin
+ if m_line_cap = square_cap then
+ begin
+ dx2:=dy1 * m_width_sign;
+ dy2:=dx1 * m_width_sign;
+
+ end;
+
+ add_vertex(vc ,v0.x - dx1 - dx2 ,v0.y + dy1 - dy2 );
+ add_vertex(vc ,v0.x + dx1 - dx2 ,v0.y - dy1 - dy2 );
+
+ end
+ else
+ begin
+ da:=ArcCos(m_width_abs / (m_width_abs + 0.125 / m_approx_scale ) ) * 2;
+ n :=int(Trunc(pi / da ) );
+ da:=pi / (n + 1 );
+
+ add_vertex(vc ,v0.x - dx1 ,v0.y + dy1 );
+
+ if m_width_sign > 0 then
+ begin
+ a1:=ArcTan2(dy1 ,-dx1 );
+ a1:=a1 + da;
+ i :=0;
+
+ while i < n do
+ begin
+ add_vertex(
+ vc ,
+ v0.x + Cos(a1 ) * m_width ,
+ v0.y + Sin(a1 ) * m_width );
+
+ a1:=a1 + da;
+
+ inc(i );
+
+ end;
+
+ end
+ else
+ begin
+ a1:=ArcTan2(-dy1 ,dx1 );
+ a1:=a1 - da;
+ i :=0;
+
+ while i < n do
+ begin
+ add_vertex(
+ vc ,
+ v0.x + Cos(a1 ) * m_width ,
+ v0.y + Sin(a1 ) * m_width );
+
+ a1:=a1 - da;
+
+ inc(i );
+
+ end;
+
+
+ end;
+
+ add_vertex(vc ,v0.x + dx1 ,v0.y - dy1 );
+
+ end;
+
+end;
+
+{ CALC_JOIN }
+procedure math_stroke.calc_join(
+ vc : pod_bvector_ptr;
+ v0 ,v1 ,v2 : vertex_dist_ptr;
+ len1 ,len2 : double );
+var
+ dx1 ,dy1 ,dx2 ,dy2 ,cp ,limit ,dx ,dy ,dbevel : double;
+
+begin
+ dx1:=m_width * (v1.y - v0.y ) / len1;
+ dy1:=m_width * (v1.x - v0.x ) / len1;
+ dx2:=m_width * (v2.y - v1.y ) / len2;
+ dy2:=m_width * (v2.x - v1.x ) / len2;
+
+ vc.remove_all;
+
+ cp:=cross_product(v0.x ,v0.y ,v1.x ,v1.y ,v2.x ,v2.y );
+
+ if (cp <> 0 ) and
+ ((cp > 0 ) = (m_width > 0 ) ) then
+ begin
+ // Inner join
+ if len1 < len2 then
+ limit:=len1 / m_width_abs
+ else
+ limit:=len2 / m_width_abs;
+
+ if limit < m_inner_miter_limit then
+ limit:=m_inner_miter_limit;
+
+ case m_inner_join of
+ inner_miter :
+ calc_miter(vc ,v0 ,v1 ,v2 ,dx1 ,dy1 ,dx2 ,dy2 ,miter_join_revert ,limit ,0 );
+
+ inner_jag ,inner_round :
+ begin
+ cp:=(dx1 - dx2 ) * (dx1 - dx2 ) + (dy1 - dy2 ) * (dy1 - dy2 );
+
+ if (cp < len1 * len1 ) and
+ (cp < len2 * len2 ) then
+ calc_miter(vc ,v0 ,v1 ,v2 ,dx1 ,dy1 ,dx2 ,dy2 ,miter_join_revert ,limit ,0 )
+ else
+ if m_inner_join = inner_jag then
+ begin
+ add_vertex(vc ,v1.x + dx1 ,v1.y - dy1 );
+ add_vertex(vc ,v1.x ,v1.y );
+ add_vertex(vc ,v1.x + dx2 ,v1.y - dy2 );
+
+ end
+ else
+ begin
+ add_vertex(vc ,v1.x + dx1 ,v1.y - dy1 );
+ add_vertex(vc ,v1.x ,v1.y );
+ calc_arc (vc ,v1.x ,v1.y ,dx2 ,-dy2 ,dx1 ,-dy1 );
+ add_vertex(vc ,v1.x ,v1.y );
+ add_vertex(vc ,v1.x + dx2 ,v1.y - dy2 );
+
+ end;
+
+ end;
+
+ else
+ begin
+ // inner_bevel
+ add_vertex(vc ,v1.x + dx1 ,v1.y - dy1 );
+ add_vertex(vc ,v1.x + dx2 ,v1.y - dy2 );
+
+ end;
+
+ end;
+
+ end
+ else
+ begin
+ // Outer join
+ //---------------
+ // Calculate the distance between v1 and
+ // the central point of the bevel line segment
+ dx:=(dx1 + dx2 ) / 2;
+ dy:=(dy1 + dy2 ) / 2;
+
+ dbevel:=Sqrt(dx * dx + dy * dy );
+
+ if (m_line_join = round_join ) or
+ (m_line_join = bevel_join ) then
+ begin
+ // This is an optimization that reduces the number of points
+ // in cases of almost collinear segments. If there's no
+ // visible difference between bevel and miter joins we'd rather
+ // use miter join because it adds only one point instead of two.
+ //
+ // Here we calculate the middle point between the bevel points
+ // and then, the distance between v1 and this middle point.
+ // At outer joins this distance always less than stroke width,
+ // because it's actually the height of an isosceles triangle of
+ // v1 and its two bevel points. If the difference between this
+ // width and this value is small (no visible bevel) we can
+ // add just one point.
+ //
+ // The constant in the expression makes the result approximately
+ // the same as in round joins and caps. You can safely comment
+ // out this entire "if".
+ if m_approx_scale * (m_width_abs - dbevel ) < m_width_eps then
+ begin
+ if calc_intersection(
+ v0.x + dx1 ,v0.y - dy1 ,
+ v1.x + dx1 ,v1.y - dy1 ,
+ v1.x + dx2 ,v1.y - dy2 ,
+ v2.x + dx2 ,v2.y - dy2 ,
+ @dx ,@dy ) then
+ add_vertex(vc ,dx ,dy )
+ else
+ add_vertex(vc ,v1.x + dx1 ,v1.y - dy1 );
+
+ exit;
+
+ end;
+
+ end;
+
+ case m_line_join of
+ miter_join ,miter_join_revert ,miter_join_round :
+ calc_miter(
+ vc ,v0 ,v1 ,v2 ,dx1 ,dy1 ,dx2 ,dy2 ,
+ m_line_join ,m_miter_limit ,dbevel );
+
+ round_join :
+ calc_arc(vc ,v1.x ,v1.y ,dx1 ,-dy1 ,dx2 ,-dy2 );
+
+ else
+ begin
+ // Bevel join
+ add_vertex(vc ,v1.x + dx1 ,v1.y - dy1 );
+ add_vertex(vc ,v1.x + dx2 ,v1.y - dy2 );
+
+ end;
+
+ end;
+
+ end;
+
+end;
+
+{ ADD_VERTEX }
+procedure math_stroke.add_vertex(vc : pod_bvector_ptr; x ,y : double );
+var
+ pt : point_type;
+
+begin
+ pt.x:=x;
+ pt.y:=y;
+
+ vc.add(@pt );
+
+end;
+
+{ CALC_ARC }
+procedure math_stroke.calc_arc(
+ vc : pod_bvector_ptr;
+ x ,y ,dx1 ,dy1 ,dx2 ,dy2 : double );
+var
+ a1 ,a2 ,da : double;
+
+ i ,n : int;
+
+begin
+ a1:=ArcTan2(dy1 * m_width_sign ,dx1 * m_width_sign );
+ a2:=ArcTan2(dy2 * m_width_sign ,dx2 * m_width_sign );
+ da:=a1 - a2;
+ da:=ArcCos(m_width_abs / (m_width_abs + 0.125 / m_approx_scale ) ) * 2;
+
+ add_vertex(vc ,x + dx1 ,y + dy1 );
+
+ if m_width_sign > 0 then
+ begin
+ if a1 > a2 then
+ a2:=a2 + 2 * pi;
+
+ n :=int(Trunc((a2 - a1 ) / da ) );
+ da:=(a2 - a1 ) / (n + 1 );
+ a1:=a1 + da;
+ i :=0;
+
+ while i < n do
+ begin
+ add_vertex(vc ,x + Cos(a1 ) * m_width ,y + Sin(a1 ) * m_width );
+
+ a1:=a1 + da;
+
+ inc(i );
+
+ end;
+
+ end
+ else
+ begin
+ if a1 < a2 then
+ a2:=a2 - 2 * pi;
+
+ n :=int(Trunc((a1 - a2 ) / da ) );
+ da:=(a1 - a2 ) / (n + 1 );
+ a1:=a1 - da;
+ i :=0;
+
+ while i < n do
+ begin
+ add_vertex(vc ,x + Cos(a1 ) * m_width ,y + Sin(a1 ) * m_width );
+
+ a1:=a1 - da;
+
+ inc(i );
+
+ end;
+
+
+ end;
+
+ add_vertex(vc ,x + dx2 ,y + dy2 );
+
+end;
+
+{ CALC_MITER }
+procedure math_stroke.calc_miter(
+ vc : pod_bvector_ptr;
+ v0 ,v1 ,v2 : vertex_dist_ptr;
+ dx1 ,dy1 ,dx2 ,dy2 : double;
+ lj : line_join_e;
+ mlimit ,dbevel : double );
+var
+ xi ,yi ,di ,lim ,x2 ,y2 ,x1 ,y1 : double;
+
+ miter_limit_exceeded ,intersection_failed : boolean;
+
+begin
+ xi :=v1.x;
+ yi :=v1.y;
+ di :=1;
+ lim:=m_width_abs * mlimit;
+
+ miter_limit_exceeded:=true; // Assume the worst
+ intersection_failed :=true; // Assume the worst
+
+ if calc_intersection(
+ v0.x + dx1 ,v0.y - dy1 ,
+ v1.x + dx1 ,v1.y - dy1 ,
+ v1.x + dx2 ,v1.y - dy2 ,
+ v2.x + dx2 ,v2.y - dy2 ,
+ @xi ,@yi ) then
+ begin
+ // Calculation of the intersection succeeded
+ di:=calc_distance(v1.x ,v1.y ,xi ,yi );
+
+ if di <= lim then
+ begin
+ // Inside the miter limit
+ add_vertex(vc, xi, yi);
+
+ miter_limit_exceeded:=false;
+
+ end;
+
+ intersection_failed:=false;
+
+ end
+ else
+ begin
+ // Calculation of the intersection failed, most probably
+ // the three points lie one straight line.
+ // First check if v0 and v2 lie on the opposite sides of vector:
+ // (v1.x, v1.y) -> (v1.x+dx1, v1.y-dy1), that is, the perpendicular
+ // to the line determined by vertices v0 and v1.
+ // This condition determines whether the next line segments continues
+ // the previous one or goes back.
+ x2:=v1.x + dx1;
+ y2:=v1.y - dy1;
+
+ if (cross_product(v0.x ,v0.y ,v1.x ,v1.y ,x2 ,y2 ) < 0.0 ) =
+ (cross_product(v1.x ,v1.y ,v2.x ,v2.y ,x2 ,y2 ) < 0.0 ) then
+ begin
+ // This case means that the next segment continues
+ // the previous one (straight line)
+ add_vertex(vc ,v1.x + dx1 ,v1.y - dy1 );
+
+ miter_limit_exceeded:=false;
+
+ end;
+
+ end;
+
+// Miter limit exceeded
+ if miter_limit_exceeded then
+ case lj of
+ miter_join_revert :
+ begin
+ // For the compatibility with SVG, PDF, etc,
+ // we use a simple bevel join instead of
+ // "smart" bevel
+ add_vertex(vc ,v1.x + dx1 ,v1.y - dy1 );
+ add_vertex(vc ,v1.x + dx2 ,v1.y - dy2 );
+
+ end;
+
+ miter_join_round :
+ calc_arc(vc ,v1.x ,v1.y ,dx1 ,-dy1 ,dx2 ,-dy2 );
+
+ // If no miter-revert, calculate new dx1, dy1, dx2, dy2
+ else
+ if intersection_failed then
+ begin
+ mlimit:=mlimit * m_width_sign;
+
+ add_vertex(
+ vc ,
+ v1.x + dx1 + dy1 * mlimit ,
+ v1.y - dy1 + dx1 * mlimit );
+
+ add_vertex(
+ vc ,
+ v1.x + dx2 - dy2 * mlimit ,
+ v1.y - dy2 - dx2 * mlimit );
+
+ end
+ else
+ begin
+ x1:=v1.x + dx1;
+ y1:=v1.y - dy1;
+ x2:=v1.x + dx2;
+ y2:=v1.y - dy2;
+ di:=(lim - dbevel ) / (di - dbevel );
+
+ add_vertex(
+ vc ,
+ x1 + (xi - x1 ) * di ,
+ y1 + (yi - y1 ) * di );
+
+ add_vertex(
+ vc ,
+ x2 + (xi - x2 ) * di ,
+ y2 + (yi - y2 ) * di );
+
+ end;
+
+ end;
+
+end;
+
+{ STROKE_CALC_ARC }
+procedure stroke_calc_arc;
+var
+ pt : point_type;
+
+ a1 ,a2 ,da : double;
+
+ ccw : boolean;
+
+begin
+ a1:=ArcTan2(dy1 ,dx1 );
+ a2:=ArcTan2(dy2 ,dx2 );
+ da:=a1 - a2;
+
+// Possible optimization. Not important at all; consumes time but happens rarely
+// if Abs(da ) < stroke_theta then
+// begin
+// pt.x:=(x + x + dx1 + dx2 ) * 0.5;
+// pt.y:=(y + y + dy1 + dy2 ) * 0.5;
+//
+// out_vertices.add(@pt );
+// exit;
+//
+// end;
+ ccw:=(da > 0.0 ) and (da < pi );
+
+ if width < 0 then
+ width:=-width;
+
+ if approximation_scale = 0 then
+ approximation_scale:=0.00001;
+
+ da:=ArcCos(width / (width + 0.125 / approximation_scale ) ) * 2;
+
+ pt.x:=x + dx1;
+ pt.y:=y + dy1;
+
+ out_vertices.add(@pt );
+
+ if not ccw then
+ begin
+ if a1 > a2 then
+ a2:=a2 + (2 * pi );
+
+ a2:=a2 - (da / 4 );
+ a1:=a1 + da;
+
+ while a1 < a2 do
+ begin
+ pt.x:=x + Cos(a1 ) * width;
+ pt.y:=y + Sin(a1 ) * width;
+
+ out_vertices.add(@pt );
+
+ a1:=a1 + da;
+
+ end;
+
+ end
+ else
+ begin
+ if a1 < a2 then
+ a2:=a2 - (2 * pi );
+
+ a2:=a2 + (da / 4 );
+ a1:=a1 - da;
+
+ while a1 > a2 do
+ begin
+ pt.x:=x + Cos(a1 ) * width;
+ pt.y:=y + Sin(a1 ) * width;
+
+ out_vertices.add(@pt );
+
+ a1:=a1 - da;
+
+ end;
+
+ end;
+
+ pt.x:=x + dx2;
+ pt.y:=y + dy2;
+
+ out_vertices.add(@pt );
+
+end;
+
+{ STROKE_CALC_MITER }
+procedure stroke_calc_miter;
+var
+ pt : point_type;
+
+ xi ,yi ,d1 ,lim ,x2 ,y2 : double;
+
+ miter_limit_exceeded : boolean;
+
+begin
+ xi:=v1.x;
+ yi:=v1.y;
+
+ miter_limit_exceeded:=true; // Assume the worst
+
+ if calc_intersection(
+ v0.x + dx1 ,v0.y - dy1 ,
+ v1.x + dx1 ,v1.y - dy1 ,
+ v1.x + dx2 ,v1.y - dy2 ,
+ v2.x + dx2 ,v2.y - dy2 ,
+ @xi ,@yi ) then
+ begin
+ // Calculation of the intersection succeeded
+ //---------------------
+ d1 :=calc_distance(v1.x ,v1.y ,xi ,yi );
+ lim:=width * miter_limit;
+
+ if d1 <= lim then
+ begin
+ // Inside the miter limit
+ //---------------------
+ pt.x:=xi;
+ pt.y:=yi;
+
+ out_vertices.add(@pt );
+
+ miter_limit_exceeded:=false;
+
+ end;
+
+ end
+ else
+ begin
+ // Calculation of the intersection failed, most probably
+ // the three points lie one straight line.
+ // First check if v0 and v2 lie on the opposite sides of vector:
+ // (v1.x, v1.y) -> (v1.x+dx1, v1.y-dy1), that is, the perpendicular
+ // to the line determined by vertices v0 and v1.
+ // This condition determines whether the next line segments continues
+ // the previous one or goes back.
+ //----------------
+ x2:=v1.x + dx1;
+ y2:=v1.y - dy1;
+
+ if (((x2 - v0.x ) * dy1 - (v0.y - y2 ) * dx1 < 0.0 ) <>
+ ((x2 - v2.x ) * dy1 - (v2.y - y2 ) * dx1 < 0.0 ) ) then
+ begin
+ // This case means that the next segment continues
+ // the previous one (straight line)
+ //-----------------
+ pt.x:=v1.x + dx1;
+ pt.y:=v1.y - dy1;
+
+ out_vertices.add(@pt );
+
+ miter_limit_exceeded:=false;
+
+ end;
+
+ end;
+
+ if miter_limit_exceeded then
+ // Miter limit exceeded
+ //------------------------
+ case line_join of
+ miter_join_revert :
+ begin
+ // For the compatibility with SVG, PDF, etc,
+ // we use a simple bevel join instead of
+ // "smart" bevel
+ //-------------------
+ pt.x:=v1.x + dx1;
+ pt.y:=v1.y - dy1;
+
+ out_vertices.add(@pt );
+
+ pt.x:=v1.x + dx2;
+ pt.y:=v1.y - dy2;
+
+ out_vertices.add(@pt );
+
+ end;
+
+ miter_join_round :
+ stroke_calc_arc(
+ out_vertices ,
+ v1.x ,v1.y ,dx1 ,-dy1 ,dx2 ,-dy2 ,
+ width ,approximation_scale );
+
+ else
+ begin
+ // If no miter-revert, calculate new dx1, dy1, dx2, dy2
+ //----------------
+ pt.x:=v1.x + dx1 + dy1 * miter_limit;
+ pt.y:=v1.y - dy1 + dx1 * miter_limit;
+
+ out_vertices.add(@pt );
+
+ pt.x:=v1.x + dx2 - dy2 * miter_limit;
+ pt.y:=v1.y - dy2 - dx2 * miter_limit;
+
+ out_vertices.add(@pt );
+
+ end;
+
+ end;
+
+end;
+
+{ STROKE_CALC_CAP }
+procedure stroke_calc_cap;
+var
+ pt : point_type;
+
+ dx1 ,dy1 ,
+ dx2 ,dy2 ,
+
+ a1 ,a2 ,da : double;
+
+begin
+ out_vertices.remove_all;
+
+ dx1:=(v1.y - v0.y ) / len;
+ dy1:=(v1.x - v0.x ) / len;
+ dx2:=0;
+ dy2:=0;
+
+ dx1:=dx1 * width;
+ dy1:=dy1 * width;
+
+ if line_cap <> round_cap then
+ begin
+ if line_cap = square_cap then
+ begin
+ dx2:=dy1;
+ dy2:=dx1;
+
+ end;
+
+ pt.x:=v0.x - dx1 - dx2;
+ pt.y:=v0.y + dy1 - dy2;
+
+ out_vertices.add(@pt );
+
+ pt.x:=v0.x + dx1 - dx2;
+ pt.y:=v0.y - dy1 - dy2;
+
+ out_vertices.add(@pt );
+
+ end
+ else
+ begin
+ a1:=ArcTan2(dy1 ,-dx1 );
+ a2:=a1 + pi;
+
+ if approximation_scale = 0 then
+ approximation_scale:=0.00001;
+
+ da:=ArcCos(width / (width + 0.125 / approximation_scale ) ) * 2;
+
+ pt.x:=v0.x - dx1;
+ pt.y:=v0.y + dy1;
+
+ out_vertices.add(@pt );
+
+ a1:=a1 + da;
+ a2:=a2 - (da / 4 );
+
+ while a1 < a2 do
+ begin
+ pt.x:=v0.x + Cos(a1 ) * width;
+ pt.y:=v0.y + Sin(a1 ) * width;
+
+ out_vertices.add(@pt );
+
+ a1:=a1 + da;
+
+ end;
+
+ pt.x:=v0.x + dx1;
+ pt.y:=v0.y - dy1;
+
+ out_vertices.add(@pt );
+
+ end;
+
+end;
+
+{ STROKE_CALC_JOIN }
+procedure stroke_calc_join;
+var
+ pt : point_type;
+
+ d ,dx1 ,dy1 ,dx2 ,dy2 : double;
+
+begin
+ dx1:=width * (v1.y - v0.y ) / len1;
+ dy1:=width * (v1.x - v0.x ) / len1;
+
+ dx2:=width * (v2.y - v1.y ) / len2;
+ dy2:=width * (v2.x - v1.x ) / len2;
+
+ out_vertices.remove_all;
+
+ if calc_point_location(v0.x ,v0.y ,v1.x ,v1.y ,v2.x ,v2.y ) > 0 then
+ // Inner join
+ //---------------
+ case inner_join of
+ inner_miter :
+ stroke_calc_miter(
+ out_vertices ,
+ v0 ,v1 ,v2 ,dx1 ,dy1 ,dx2 ,dy2 ,
+ width ,
+ miter_join_revert ,
+ inner_miter_limit ,
+ 1.0 );
+
+ inner_jag ,inner_round :
+ begin
+ d:=(dx1 - dx2 ) * (dx1 - dx2 ) + (dy1 - dy2 ) * (dy1 - dy2 );
+
+ if (d < len1 * len1 ) and
+ (d < len2 * len2 ) then
+ stroke_calc_miter(
+ out_vertices ,
+ v0 ,v1 ,v2 ,dx1 ,dy1 ,dx2 ,dy2 ,
+ width ,
+ miter_join_revert ,
+ inner_miter_limit ,
+ 1.0 )
+
+ else
+ if inner_join = inner_jag then
+ begin
+ pt.x:=v1.x + dx1;
+ pt.y:=v1.y - dy1;
+
+ out_vertices.add(@pt );
+
+ pt.x:=v1.x;
+ pt.y:=v1.y;
+
+ out_vertices.add(@pt );
+
+ pt.x:=v1.x + dx2;
+ pt.y:=v1.y - dy2;
+
+ out_vertices.add(@pt );
+
+ end
+ else
+ begin
+ pt.x:=v1.x + dx1;
+ pt.y:=v1.y - dy1;
+
+ out_vertices.add(@pt );
+
+ pt.x:=v1.x;
+ pt.y:=v1.y;
+
+ out_vertices.add(@pt );
+
+ stroke_calc_arc(
+ out_vertices ,
+ v1.x ,v1.y ,dx2 ,-dy2 ,dx1 ,-dy1 ,
+ width ,approximation_scale );
+
+ pt.x:=v1.x;
+ pt.y:=v1.y;
+
+ out_vertices.add(@pt );
+
+ pt.x:=v1.x + dx2;
+ pt.y:=v1.y - dy2;
+
+ out_vertices.add(@pt );
+
+ end;
+
+ end;
+
+ else // inner_bevel
+ begin
+ pt.x:=v1.x + dx1;
+ pt.y:=v1.y - dy1;
+
+ out_vertices.add(@pt );
+
+ pt.x:=v1.x + dx2;
+ pt.y:=v1.y - dy2;
+
+ out_vertices.add(@pt );
+
+ end;
+
+ end
+ else
+ // Outer join
+ //---------------
+ case line_join of
+ miter_join ,miter_join_revert ,miter_join_round :
+ stroke_calc_miter(
+ out_vertices ,
+ v0 ,v1 ,v2 ,dx1 ,dy1 ,dx2 ,dy2 ,
+ width ,
+ line_join ,
+ miter_limit ,
+ approximation_scale );
+
+ round_join :
+ stroke_calc_arc(
+ out_vertices ,
+ v1.x ,v1.y ,dx1 ,-dy1 ,dx2 ,-dy2 ,
+ width ,approximation_scale );
+
+ else // Bevel join
+ begin
+ pt.x:=v1.x + dx1;
+ pt.y:=v1.y - dy1;
+
+ out_vertices.add(@pt );
+
+ pt.x:=v1.x + dx2;
+ pt.y:=v1.y - dy2;
+
+ out_vertices.add(@pt );
+
+ end;
+
+ end;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_mode.inc b/src/corelib/render/software/agg_mode.inc
new file mode 100644
index 00000000..0692f829
--- /dev/null
+++ b/src/corelib/render/software/agg_mode.inc
@@ -0,0 +1,101 @@
+//
+// AggPas 2.4 RM3 compiler options configuration file
+//
+
+{DEFINE AGG_DEBUG }
+
+//----------------------------------------------------------------------------
+{$IFDEF CPUPOWERPC }
+ {$DEFINE AGG_CPU_PPC }
+
+{$ENDIF }
+
+{$IFDEF CPUI386 }
+ {$DEFINE AGG_CPU_386 }
+
+{$ENDIF }
+
+{$IFDEF CPU386 }
+ {$DEFINE AGG_CPU_386 }
+
+{$ENDIF }
+
+{$IFDEF FPC }
+ {$MODE DELPHI }
+
+{$ENDIF }
+
+// OS
+
+{$IFDEF WIN32 }
+ {$DEFINE AGG_WINDOWS }
+
+{$ENDIF }
+
+{$IFDEF WINDOWS }
+ {$DEFINE AGG_WINDOWS }
+
+{$ENDIF }
+
+{$IFDEF LINUX }
+ {$DEFINE AGG_LINUX }
+
+{$ENDIF }
+
+{$IFDEF DARWIN }
+ {$DEFINE AGG_MACOSX }
+
+{$ENDIF }
+
+//----------------------------------------------------------------------------
+{$IFDEF AGG_DEBUG }
+ {$DEFINE AGG_FULL_DEBUG }
+
+{$ENDIF }
+
+//----------------------------------------------------------------------------
+{ SWITCHES CONFIGURATION }
+{$IFNDEF FPC }
+ {$A- }{ Fields alignment OFF }
+ {$F+ }{ Far code generation }
+{$ENDIF }
+
+{$HINTS OFF }
+{$WARNINGS OFF }
+
+{$B- }{ Complete boolean evaluation }
+{$V- }{ String type checking }
+{$X+ }{ Extended syntax }
+
+{$IFDEF AGG_FULL_DEBUG }
+ {$R+ }{ Range checking }
+ {$I+ }{ IO checking }
+ {$Q+ }{ Overflow checking }
+
+ {$IFNDEF FPC }
+ {$O- }{ Code Optimization }
+ {$ENDIF }
+
+ {$D+ }{ Debug Info ON }
+ {$Y+ }{ References Info ON }
+
+{$ELSE }
+ {$R- }{ Range checking }
+ {$I- }{ IO checking }
+ {$Q- }{ Overflow checking }
+
+ { Code Optimization }
+ {$IFNDEF FPC }
+ {$IFDEF AGG_OPTIMIZE }
+ {$O+ }
+ {$ELSE }
+ {$O- }
+ {$ENDIF }
+ {$ENDIF }
+
+ {$D- }{ Debug Info OFF }
+ {$Y- }{ References Info OFF }
+
+{$ENDIF }
+
+
diff --git a/src/corelib/render/software/agg_path_storage.pas b/src/corelib/render/software/agg_path_storage.pas
new file mode 100644
index 00000000..264a1730
--- /dev/null
+++ b/src/corelib/render/software/agg_path_storage.pas
@@ -0,0 +1,1262 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// Class path_storage
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 09.10.2007-Milano: Path Affine Transformations
+// 23.06.2006-Milano: ptrcomp adjustments
+// 19.12.2005-Milano: Unit port establishment
+//
+{ agg_path_storage.pas }
+unit
+ agg_path_storage ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_math ,
+ agg_bezier_arc ,
+ agg_vertex_source ,
+ agg_trans_affine ;
+
+{ TYPES DEFINITION }
+// Allocation parameters
+const
+ block_shift = 8;
+ block_size = 1 shl block_shift;
+ block_mask = block_size - 1;
+ block_pool = 256;
+
+type
+ path_storage_ptr = ^path_storage;
+
+ ps_vertex_source_ptr = ^ps_vertex_source;
+ ps_vertex_source = object(vertex_source )
+ m_path : path_storage_ptr;
+
+ m_vertex_idx : unsigned;
+
+ constructor Construct; overload;
+ constructor Construct(p : path_storage_ptr ); overload;
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ end;
+
+//------------------------------------------------------------path_storage
+// A container to store vertices with their flags.
+// A path consists of a number of contours separated with "move_to"
+// commands. The path storage can keep and maintain more than one
+// path.
+// To navigate to the beginning of a particular path, use rewind(path_id);
+// Where path_id is what start_new_path() returns. So, when you call
+// start_new_path() you need to store its return value somewhere else
+// to navigate to the path afterwards.
+ path_storage = object(vertex_source )
+ m_total_vertices ,
+ m_total_blocks ,
+ m_max_blocks : unsigned;
+
+ m_coord_blocks : double_ptr_ptr;
+ m_cmd_blocks : int8u_ptr_ptr;
+
+ m_iterator : unsigned;
+
+ constructor Construct; overload;
+ constructor Construct(ps : path_storage_ptr ); overload;
+ destructor Destruct; virtual;
+
+ procedure remove_all; virtual;
+
+ function last_vertex(x ,y : double_ptr ) : unsigned;
+ function prev_vertex(x ,y : double_ptr ) : unsigned;
+
+ function last_x : double;
+ function last_y : double;
+
+ procedure rel_to_abs(x ,y : double_ptr );
+
+ procedure move_to (x ,y : double );
+ procedure move_rel(dx ,dy : double );
+
+ procedure line_to (x ,y : double );
+ procedure line_rel(dx ,dy : double );
+
+ procedure hline_to (x : double );
+ procedure hline_rel(dx : double );
+
+ procedure vline_to (y : double );
+ procedure vline_rel(dy : double );
+
+ procedure arc_to (rx ,ry ,angle : double; large_arc_flag ,sweep_flag : boolean; x ,y : double );
+ procedure arc_rel(rx ,ry ,angle : double; large_arc_flag ,sweep_flag : boolean; dx ,dy : double );
+
+ procedure curve3 (x_ctrl ,y_ctrl ,x_to ,y_to : double ); overload;
+ procedure curve3_rel(dx_ctrl ,dy_ctrl ,dx_to ,dy_to : double ); overload;
+
+ procedure curve3 (x_to ,y_to : double ); overload;
+ procedure curve3_rel(dx_to ,dy_to : double ); overload;
+
+ procedure curve4 (x_ctrl1 ,y_ctrl1 ,x_ctrl2 ,y_ctrl2 ,x_to ,y_to : double ); overload;
+ procedure curve4_rel(dx_ctrl1 ,dy_ctrl1 ,dx_ctrl2 ,dy_ctrl2 ,dx_to ,dy_to : double ); overload;
+
+ procedure curve4 (x_ctrl2 ,y_ctrl2 ,x_to ,y_to : double ); overload;
+ procedure curve4_rel(dx_ctrl2 ,dy_ctrl2 ,dx_to ,dy_to : double ); overload;
+
+ procedure end_poly (flags : unsigned = path_flags_close );
+ procedure close_polygon(flags : unsigned = path_flags_none );
+
+ procedure add_poly(vertices : double_2_ptr; num : unsigned; solid_path : boolean = false; end_flags : unsigned = path_flags_none );
+ procedure add_path(vs : vertex_source_ptr; path_id : unsigned = 0; solid_path : boolean = true );
+
+ function start_new_path : unsigned;
+
+ procedure copy_from(ps : path_storage_ptr );
+
+ function total_vertices : unsigned;
+
+ function vertex_(idx : unsigned; x ,y : double_ptr ) : unsigned;
+ function command(idx : unsigned ) : unsigned;
+ procedure rewind (path_id : unsigned ); virtual;
+ function vertex (x ,y : double_ptr ) : unsigned; virtual;
+
+ // Arrange the orientation of a polygon, all polygons in a path,
+ // or in all paths. After calling arrange_orientations() or
+ // arrange_orientations_all_paths(), all the polygons will have
+ // the same orientation, i.e. path_flags_cw or path_flags_ccw
+ function arrange_polygon_orientation (start ,orientation : unsigned ) : unsigned;
+ function arrange_orientations (start ,orientation : unsigned ) : unsigned;
+ procedure arrange_orientations_all_paths(orientation : unsigned );
+
+ // Flip all the vertices horizontally or vertically
+ procedure flip_x(x1 ,x2 : double );
+ procedure flip_y(y1 ,y2 : double );
+
+ // This function adds a vertex with its flags directly. Since there's no
+ // checking for errors, keeping proper path integrity is the responsibility
+ // of the caller. It can be said the function is "not very public".
+ procedure add_vertex(x ,y : double; cmd : unsigned ); virtual;
+
+ // Allows you to modify vertex coordinates. The caller must know
+ // the index of the vertex.
+ procedure modify_vertex(idx : unsigned; x ,y : double );
+
+ // Allows you to modify vertex command. The caller must know
+ // the index of the vertex.
+ procedure modify_command(idx ,cmd : unsigned );
+
+ // Path Affine Transformations
+ procedure transform (trans : trans_affine_ptr; path_id : unsigned = 0 );
+ procedure transform_all_paths(trans : trans_affine_ptr );
+
+ // Private
+ procedure allocate_block(nb : unsigned );
+ function storage_ptrs (xy_ptr : double_ptr_ptr ) : int8u_ptr;
+
+ function perceive_polygon_orientation(start ,end_ : unsigned ) : unsigned;
+
+ procedure invert_polygon(start ,end_ : unsigned ); overload;
+ procedure invert_polygon(start : unsigned ); overload;
+
+ // from 2.4
+ procedure concat_path(vs : vertex_source_ptr; path_id : unsigned = 0 );
+
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor ps_vertex_source.Construct;
+begin
+ m_path:=NIL;
+
+ m_vertex_idx:=0;
+
+end;
+
+{ CONSTRUCT }
+constructor ps_vertex_source.Construct(p : path_storage_ptr );
+begin
+ m_path:=p;
+
+ m_vertex_idx:=0;
+
+end;
+
+{ REWIND }
+procedure ps_vertex_source.rewind;
+begin
+ m_vertex_idx:=path_id;
+
+end;
+
+{ VERTEX }
+function ps_vertex_source.vertex;
+begin
+ if m_vertex_idx < m_path.total_vertices then
+ begin
+ result:=m_path.vertex_(m_vertex_idx ,x ,y );
+
+ inc(m_vertex_idx );
+
+ end
+ else
+ result:=path_cmd_stop;
+
+end;
+
+{ CONSTRUCT }
+constructor path_storage.Construct;
+begin
+ m_total_vertices:=0;
+ m_total_blocks :=0;
+ m_max_blocks :=0;
+
+ m_coord_blocks:=NIL;
+ m_cmd_blocks :=NIL;
+
+ m_iterator:=0;
+
+end;
+
+{ CONSTRUCT }
+constructor path_storage.Construct(ps : path_storage_ptr );
+begin
+ m_total_vertices:=0;
+ m_total_blocks :=0;
+ m_max_blocks :=0;
+
+ m_coord_blocks:=NIL;
+ m_cmd_blocks :=NIL;
+
+ m_iterator:=0;
+
+ copy_from(ps );
+
+end;
+
+{ DESTRUCT }
+destructor path_storage.Destruct;
+var
+ coord_blk : double_ptr_ptr;
+
+begin
+ if m_total_blocks <> 0 then
+ begin
+ coord_blk:=double_ptr_ptr(ptrcomp(m_coord_blocks ) + (m_total_blocks - 1 ) * sizeof(double_ptr ) );
+
+ while m_total_blocks > 0 do
+ begin
+ agg_freemem(
+ p32(coord_blk^ ).ptr ,
+ (block_size * 2 + block_size div (sizeof(double ) div sizeof(int8u ) ) ) * sizeof(double ) );
+
+ dec(ptrcomp(coord_blk ) ,sizeof(double_ptr ) );
+ dec(m_total_blocks );
+
+ end;
+
+ agg_freemem(pointer(m_coord_blocks ) ,m_max_blocks * 2 * sizeof(double_ptr ) );
+
+ end;
+
+end;
+
+{ REMOVE_ALL }
+procedure path_storage.remove_all;
+begin
+ m_total_vertices:=0;
+ m_iterator :=0;
+
+end;
+
+{ LAST_VERTEX }
+function path_storage.last_vertex;
+begin
+ if m_total_vertices <> 0 then
+ result:=vertex_(m_total_vertices - 1 ,x ,y )
+ else
+ result:=path_cmd_stop;
+
+end;
+
+{ PREV_VERTEX }
+function path_storage.prev_vertex;
+begin
+ if m_total_vertices > 1 then
+ result:=vertex_(m_total_vertices - 2 ,x ,y )
+ else
+ result:=path_cmd_stop;
+
+end;
+
+{ LAST_X }
+function path_storage.last_x;
+var
+ idx : unsigned;
+
+begin
+ if m_total_vertices <> 0 then
+ begin
+ idx:=m_total_vertices - 1;
+
+ result:=
+ double_ptr(
+ ptrcomp(
+ p32_ptr(ptrcomp(m_coord_blocks ) + (idx shr block_shift ) * sizeof(double_ptr ) ).ptr ) +
+ ((idx and block_mask) shl 1 ) * sizeof(double ) )^;
+
+ end
+ else
+ result:=0.0;
+
+end;
+
+{ LAST_Y }
+function path_storage.last_y;
+var
+ idx : unsigned;
+
+begin
+ if m_total_vertices <> 0 then
+ begin
+ idx:=m_total_vertices - 1;
+
+ result:=
+ double_ptr(
+ ptrcomp(
+ p32_ptr(ptrcomp(m_coord_blocks ) + (idx shr block_shift ) * sizeof(double_ptr ) ).ptr ) +
+ (((idx and block_mask) shl 1 ) + 1 ) * sizeof(double ) )^;
+
+ end
+ else
+ result:=0.0;
+
+end;
+
+{ REL_TO_ABS }
+procedure path_storage.rel_to_abs;
+var
+ x2 ,y2 : double;
+
+begin
+ if m_total_vertices <> 0 then
+ if is_vertex(vertex_(m_total_vertices - 1 ,@x2 ,@y2 ) ) then
+ begin
+ x^:=x^ + x2;
+ y^:=y^ + y2;
+
+ end;
+
+end;
+
+{ MOVE_TO }
+procedure path_storage.move_to;
+begin
+ add_vertex(x ,y ,path_cmd_move_to );
+
+end;
+
+{ MOVE_REL }
+procedure path_storage.move_rel;
+begin
+ rel_to_abs(@dx ,@dy );
+ add_vertex(dx ,dy ,path_cmd_move_to );
+
+end;
+
+{ LINE_TO }
+procedure path_storage.line_to;
+begin
+ add_vertex(x ,y ,path_cmd_line_to );
+
+end;
+
+{ LINE_REL }
+procedure path_storage.line_rel;
+begin
+ rel_to_abs(@dx ,@dy);
+ add_vertex(dx ,dy ,path_cmd_line_to );
+
+end;
+
+{ HLINE_TO }
+procedure path_storage.hline_to;
+begin
+ add_vertex(x ,last_y ,path_cmd_line_to );
+
+end;
+
+{ HLINE_REL }
+procedure path_storage.hline_rel;
+var
+ dy : double;
+
+begin
+ dy:=0;
+
+ rel_to_abs(@dx ,@dy);
+ add_vertex(dx ,dy ,path_cmd_line_to );
+
+end;
+
+{ VLINE_TO }
+procedure path_storage.vline_to;
+begin
+ add_vertex(last_x ,y ,path_cmd_line_to );
+
+end;
+
+{ VLINE_REL }
+procedure path_storage.vline_rel;
+var
+ dx : double;
+
+begin
+ dx:=0;
+
+ rel_to_abs(@dx, @dy);
+ add_vertex(dx ,dy ,path_cmd_line_to );
+
+end;
+
+{ ARC_TO }
+procedure path_storage.arc_to;
+var
+ a : bezier_arc_svg_ptr;
+
+ x0 ,y0 ,epsilon : double;
+
+begin
+ a:=NIL;
+
+ if (m_total_vertices <> 0 ) and
+ is_vertex(command(m_total_vertices - 1 ) ) then
+ begin
+ epsilon:=1e-30;
+
+ x0:=0.0;
+ y0:=0.0;
+
+ last_vertex(@x0 ,@y0 );
+
+ rx:=Abs(rx );
+ ry:=Abs(ry );
+
+ // Ensure radii are valid
+ if (rx < epsilon ) or
+ (ry < epsilon ) then
+ begin
+ line_to(x ,y );
+ exit;
+
+ end;
+
+ // If the endpoints (x, y) and (x0, y0) are identical, then this
+ // is equivalent to omitting the elliptical arc segment entirely.
+ if calc_distance(x0 ,y0 ,x ,y ) < epsilon then
+ exit;
+
+ new(a ,Construct(x0 ,y0 ,rx ,ry ,angle ,large_arc_flag ,sweep_flag ,x ,y ) );
+
+ if a.radii_ok then
+ add_path(a ,0 ,true )
+ else
+ line_to(x ,y );
+
+ end
+ else
+ move_to(x ,y );
+
+ if a <> NIL then
+ dispose(a ,Destruct );
+
+end;
+
+{ ARC_REL }
+procedure path_storage.arc_rel;
+begin
+ rel_to_abs(@dx ,@dy );
+ arc_to (rx ,ry ,angle ,large_arc_flag ,sweep_flag ,dx ,dy );
+
+end;
+
+{ CURVE3 }
+procedure path_storage.curve3(x_ctrl ,y_ctrl ,x_to ,y_to : double );
+begin
+ add_vertex(x_ctrl ,y_ctrl ,path_cmd_curve3 );
+ add_vertex(x_to ,y_to ,path_cmd_curve3 );
+
+end;
+
+{ CURVE3_REL }
+procedure path_storage.curve3_rel(dx_ctrl ,dy_ctrl ,dx_to ,dy_to : double );
+begin
+ rel_to_abs(@dx_ctrl ,@dy_ctrl );
+ rel_to_abs(@dx_to ,@dy_to );
+ add_vertex(dx_ctrl ,dy_ctrl ,path_cmd_curve3 );
+ add_vertex(dx_to ,dy_to ,path_cmd_curve3 );
+
+end;
+
+{ CURVE3 }
+procedure path_storage.curve3(x_to ,y_to : double );
+var
+ cmd : unsigned;
+
+ x0 ,y0 ,x_ctrl ,y_ctrl : double;
+
+begin
+ if is_vertex(last_vertex(@x0 ,@y0 ) ) then
+ begin
+ cmd:=prev_vertex(@x_ctrl ,@y_ctrl );
+
+ if is_curve(cmd ) then
+ begin
+ x_ctrl:=x0 + x0 - x_ctrl;
+ y_ctrl:=y0 + y0 - y_ctrl;
+
+ end
+ else
+ begin
+ x_ctrl:=x0;
+ y_ctrl:=y0;
+
+ end;
+
+ curve3(x_ctrl ,y_ctrl ,x_to ,y_to );
+
+ end;
+
+end;
+
+{ CURVE3_REL }
+procedure path_storage.curve3_rel(dx_to ,dy_to : double );
+begin
+ rel_to_abs(@dx_to ,@dy_to );
+ curve3 (dx_to ,dy_to );
+
+end;
+
+{ CURVE4 }
+procedure path_storage.curve4(x_ctrl1 ,y_ctrl1 ,x_ctrl2 ,y_ctrl2 ,x_to ,y_to : double );
+begin
+ add_vertex(x_ctrl1 ,y_ctrl1 ,path_cmd_curve4 );
+ add_vertex(x_ctrl2 ,y_ctrl2 ,path_cmd_curve4 );
+ add_vertex(x_to ,y_to ,path_cmd_curve4 );
+
+end;
+
+{ CURVE4_REL }
+procedure path_storage.curve4_rel(dx_ctrl1 ,dy_ctrl1 ,dx_ctrl2 ,dy_ctrl2 ,dx_to ,dy_to : double );
+begin
+ rel_to_abs(@dx_ctrl1 ,@dy_ctrl1 );
+ rel_to_abs(@dx_ctrl2 ,@dy_ctrl2 );
+ rel_to_abs(@dx_to ,@dy_to );
+ add_vertex(dx_ctrl1 ,dy_ctrl1 ,path_cmd_curve4 );
+ add_vertex(dx_ctrl2 ,dy_ctrl2 ,path_cmd_curve4 );
+ add_vertex(dx_to ,dy_to ,path_cmd_curve4 );
+
+end;
+
+{ CURVE4 }
+procedure path_storage.curve4(x_ctrl2 ,y_ctrl2 ,x_to ,y_to : double );
+var
+ cmd : unsigned;
+
+ x0 ,y0 ,x_ctrl1 ,y_ctrl1 : double;
+
+begin
+ if is_vertex(last_vertex(@x0 ,@y0 ) ) then
+ begin
+ cmd:=prev_vertex(@x_ctrl1 ,@y_ctrl1 );
+
+ if is_curve(cmd ) then
+ begin
+ x_ctrl1:=x0 + x0 - x_ctrl1;
+ y_ctrl1:=y0 + y0 - y_ctrl1;
+
+ end
+ else
+ begin
+ x_ctrl1:=x0;
+ y_ctrl1:=y0;
+
+ end;
+
+ curve4(x_ctrl1 ,y_ctrl1 ,x_ctrl2 ,y_ctrl2 ,x_to ,y_to );
+
+ end;
+
+end;
+
+{ CURVE4_REL }
+procedure path_storage.curve4_rel(dx_ctrl2 ,dy_ctrl2 ,dx_to ,dy_to : double );
+begin
+ rel_to_abs(@dx_ctrl2 ,@dy_ctrl2 );
+ rel_to_abs(@dx_to ,@dy_to );
+
+ curve4(dx_ctrl2 ,dy_ctrl2 ,dx_to ,dy_to );
+
+end;
+
+{ END_POLY }
+procedure path_storage.end_poly;
+begin
+ if m_total_vertices <> 0 then
+ if is_vertex(command(m_total_vertices - 1 ) ) then
+ add_vertex(0.0 ,0.0 ,path_cmd_end_poly or flags );
+
+end;
+
+{ CLOSE_POLYGON }
+procedure path_storage.close_polygon;
+begin
+ end_poly(path_flags_close or flags );
+
+end;
+
+{ ADD_POLY }
+procedure path_storage.add_poly;
+begin
+ if num <> 0 then
+ begin
+ if not solid_path then
+ begin
+ move_to(vertices[0 ] ,vertices[1 ] );
+
+ inc(ptrcomp(vertices ) ,2 * sizeof(double ) );
+ dec(num );
+
+ end;
+
+ while num > 0 do
+ begin
+ line_to(vertices[0 ] ,vertices[1 ] );
+
+ inc(ptrcomp(vertices ) ,2 * sizeof(double ) );
+ dec(num );
+
+ end;
+
+ if end_flags <> 0 then
+ end_poly(end_flags );
+
+ end;
+
+end;
+
+{ ADD_PATH }
+procedure path_storage.add_path;
+var
+ cmd : unsigned;
+
+ x ,y : double;
+
+begin
+ vs.rewind(path_id );
+
+ cmd:=vs.vertex(@x ,@y );
+
+ while not is_stop(cmd ) do
+ begin
+ if is_move_to(cmd ) and
+ solid_path and
+ (m_total_vertices <> 0 ) then
+ cmd:=path_cmd_line_to;
+
+ add_vertex(x ,y ,cmd );
+
+ cmd:=vs.vertex(@x ,@y );
+
+ end;
+
+end;
+
+{ START_NEW_PATH }
+function path_storage.start_new_path;
+begin
+ if m_total_vertices <> 0 then
+ if not is_stop(command(m_total_vertices - 1 ) ) then
+ add_vertex(0.0 ,0.0 ,path_cmd_stop );
+
+ result:=m_total_vertices;
+
+end;
+
+{ COPY_FROM }
+procedure path_storage.copy_from;
+var
+ i ,cmd : unsigned;
+ x ,y : double;
+
+begin
+ remove_all;
+
+ for i:=0 to ps.total_vertices - 1 do
+ begin
+ cmd:=ps.vertex_(i ,@x ,@y );
+
+ add_vertex(x ,y ,cmd );
+
+ end;
+
+end;
+
+{ TOTAL_VERTICES }
+function path_storage.total_vertices;
+begin
+ result:=m_total_vertices
+
+end;
+
+{ VERTEX_ }
+function path_storage.vertex_;
+var
+ nb : unsigned;
+ pv : double_ptr;
+
+begin
+ nb:=idx shr block_shift;
+
+ pv:=
+ double_ptr(
+ ptrcomp(
+ p32_ptr(ptrcomp(m_coord_blocks ) + nb * sizeof(double_ptr ) ).ptr ) +
+ ((idx and block_mask ) shl 1 ) * sizeof(double ) );
+
+ x^:=pv^; inc(ptrcomp(pv ) ,sizeof(double ) );
+ y^:=pv^;
+
+ result:=
+ int8u_ptr(
+ ptrcomp(
+ p32_ptr(ptrcomp(m_cmd_blocks ) + nb * sizeof(int8u_ptr ) ).ptr ) +
+ (idx and block_mask ) * sizeof(int8u ) )^;
+
+end;
+
+{ COMMAND }
+function path_storage.command;
+begin
+ result:=
+ int8u_ptr(
+ ptrcomp(
+ p32_ptr(ptrcomp(m_cmd_blocks ) + (idx shr block_shift ) * sizeof(int8u_ptr ) ).ptr ) +
+ (idx and block_mask ) * sizeof(int8u ) )^;
+
+end;
+
+{ REWIND }
+procedure path_storage.rewind;
+begin
+ m_iterator:=path_id;
+
+end;
+
+{ VERTEX }
+function path_storage.vertex;
+begin
+ if m_iterator >= m_total_vertices then
+ result:=path_cmd_stop
+ else
+ begin
+ result:=vertex_(m_iterator ,x ,y );
+
+ inc(m_iterator );
+
+ end;
+
+end;
+
+{ ARRANGE_POLYGON_ORIENTATION }
+function path_storage.arrange_polygon_orientation;
+var
+ cmd ,
+ end_ : unsigned;
+
+begin
+ if orientation = path_flags_none then
+ begin
+ result:=start;
+
+ exit;
+
+ end;
+
+// Skip all non-vertices at the beginning
+ while (start < m_total_vertices ) and
+ not is_vertex(command(start ) ) do
+ inc(start );
+
+// Skip all insignificant move_to
+ while (start + 1 < m_total_vertices ) and
+ is_move_to(command(start ) ) and
+ is_move_to(command(start + 1 ) ) do
+ inc(start );
+
+// Find the last vertex
+ end_:=start + 1;
+
+ while (end_ < m_total_vertices ) and
+ not is_next_poly(command(end_ ) ) do
+ inc(end_ );
+
+ if end_ - start > 2 then
+ if perceive_polygon_orientation(start ,end_ ) <> orientation then
+ begin
+ // Invert polygon, set orientation flag, and skip all end_poly
+ invert_polygon(start ,end_ );
+
+ cmd:=command(end_ );
+
+ while (end_ < m_total_vertices ) and
+ is_end_poly(cmd ) do
+ begin
+ modify_command(end_ ,set_orientation(cmd ,orientation ) );
+
+ inc(end_ );
+
+ cmd:=command(end_ );
+
+ end;
+
+ end;
+
+ result:=end_;
+
+end;
+
+{ ARRANGE_ORIENTATIONS }
+function path_storage.arrange_orientations;
+begin
+ if orientation <> path_flags_none then
+ while start < m_total_vertices do
+ begin
+ start:=arrange_polygon_orientation(start ,orientation );
+
+ if is_stop(command(start ) ) then
+ begin
+ inc(start );
+
+ break;
+
+ end;
+
+ end;
+
+ result:=start;
+
+end;
+
+{ ARRANGE_ORIENTATIONS_ALL_PATHS }
+procedure path_storage.arrange_orientations_all_paths;
+var
+ start : unsigned;
+
+begin
+ if orientation <> path_flags_none then
+ begin
+ start:=0;
+
+ while start < m_total_vertices do
+ start:=arrange_orientations(start ,orientation );
+
+ end;
+
+end;
+
+{ FLIP_X }
+procedure path_storage.flip_x;
+var
+ i ,cmd : unsigned;
+ x ,y : double;
+
+begin
+ if m_total_vertices > 0 then
+ for i:=0 to m_total_vertices - 1 do
+ begin
+ cmd:=vertex_(i ,@x ,@y );
+
+ if is_vertex(cmd ) then
+ modify_vertex(i ,x2 - x + x1 ,y );
+
+ end;
+
+end;
+
+{ FLIP_Y }
+procedure path_storage.flip_y;
+var
+ i ,cmd : unsigned;
+ x ,y : double;
+
+begin
+ if m_total_vertices > 0 then
+ for i:=0 to m_total_vertices - 1 do
+ begin
+ cmd:=vertex_(i ,@x ,@y );
+
+ if is_vertex(cmd ) then
+ modify_vertex(i ,x ,y2 - y + y1 );
+
+ end;
+
+end;
+
+{ ADD_VERTEX }
+procedure path_storage.add_vertex;
+var
+ coord_ptr : double_ptr;
+ cmd_ptr : int8u_ptr;
+
+begin
+ coord_ptr:=NIL;
+
+ cmd_ptr:=storage_ptrs(@coord_ptr );
+
+ cmd_ptr^:=int8u(cmd );
+
+ coord_ptr^:=x; inc(ptrcomp(coord_ptr ) ,sizeof(double ) );
+ coord_ptr^:=y;
+
+ inc(m_total_vertices );
+
+end;
+
+{ MODIFY_VERTEX }
+procedure path_storage.modify_vertex;
+var
+ pv : double_ptr;
+
+begin
+ pv:=
+ double_ptr(
+ ptrcomp(
+ p32_ptr(ptrcomp(m_coord_blocks ) + (idx shr block_shift ) * sizeof(double_ptr ) ).ptr ) +
+ ((idx and block_mask ) shl 1 ) * sizeof(double ) );
+
+ pv^:=x; inc(ptrcomp(pv ) ,sizeof(double ) );
+ pv^:=y;
+
+end;
+
+{ MODIFY_COMMAND }
+procedure path_storage.modify_command;
+begin
+ int8u_ptr(
+ ptrcomp(
+ p32_ptr(ptrcomp(m_cmd_blocks ) + (idx shr block_shift ) * sizeof(int8u_ptr ) ).ptr ) +
+ (idx and block_mask ) * sizeof(int8u ) )^:=int8u(cmd );
+
+end;
+
+{ TRANSFORM }
+procedure path_storage.transform(trans : trans_affine_ptr; path_id : unsigned = 0 );
+var
+ x ,y : double;
+ cmd : unsigned;
+
+begin
+ while path_id < m_total_vertices do
+ begin
+ cmd:=vertex_(path_id ,@x ,@y );
+
+ if is_stop(cmd ) then
+ break;
+
+ if is_vertex(cmd ) then
+ begin
+ trans.transform(trans ,@x ,@y );
+ modify_vertex (path_id ,x ,y );
+
+ end;
+
+ inc(path_id );
+
+ end;
+
+end;
+
+{ TRANSFORM_ALL_PATHS }
+procedure path_storage.transform_all_paths(trans : trans_affine_ptr );
+var
+ x ,y : double;
+ idx : unsigned;
+
+begin
+ idx:=0;
+
+ while idx < m_total_vertices do
+ begin
+ if is_vertex(vertex_(idx ,@x ,@y ) ) then
+ begin
+ trans.transform(trans ,@x ,@y );
+ modify_vertex (idx ,x ,y );
+
+ end;
+
+ inc(idx );
+
+ end;
+
+end;
+
+{ ALLOCATE_BLOCK }
+procedure path_storage.allocate_block;
+var
+ new_coords : double_ptr_ptr;
+ new_cmds : int8u_ptr_ptr;
+
+begin
+ if nb >= m_max_blocks then
+ begin
+ agg_getmem(pointer(new_coords ) ,((m_max_blocks + block_pool ) * 2 ) * sizeof(double_ptr ) );
+
+ new_cmds:=int8u_ptr_ptr(ptrcomp(new_coords ) + (m_max_blocks + block_pool ) * sizeof(double_ptr ) );
+
+ if m_coord_blocks <> NIL then
+ begin
+ move(m_coord_blocks^ ,new_coords^ ,m_max_blocks * sizeof(double_ptr ) );
+ move(m_cmd_blocks^ ,new_cmds^ ,m_max_blocks * sizeof(int8u_ptr ) );
+
+ agg_freemem(pointer(m_coord_blocks ) ,m_max_blocks * 2 * sizeof(double_ptr ) );
+
+ end;
+
+ m_coord_blocks:=new_coords;
+ m_cmd_blocks :=new_cmds;
+
+ inc(m_max_blocks ,block_pool );
+
+ end;
+
+ agg_getmem(
+ p32_ptr(ptrcomp(m_coord_blocks ) + nb * sizeof(double_ptr ) ).ptr ,
+ (block_size * 2 + block_size div (sizeof(double ) div sizeof(int8u ) ) ) * sizeof(double ) );
+
+ p32_ptr(ptrcomp(m_cmd_blocks ) + nb * sizeof(int8u_ptr ) ).ptr:=
+ pointer(
+ ptrcomp(p32_ptr(ptrcomp(m_coord_blocks ) + nb * sizeof(double_ptr ) ).ptr ) +
+ block_size * 2 * sizeof(double ) );
+
+ inc(m_total_blocks );
+
+end;
+
+{ STORAGE_PTRS }
+function path_storage.storage_ptrs;
+var
+ nb : unsigned;
+
+begin
+ nb:=m_total_vertices shr block_shift;
+
+ if nb >= m_total_blocks then
+ allocate_block(nb );
+
+ xy_ptr^:=
+ double_ptr(
+ ptrcomp(
+ p32_ptr(ptrcomp(m_coord_blocks ) + nb * sizeof(double_ptr ) ).ptr ) +
+ ((m_total_vertices and block_mask ) shl 1 ) * sizeof(double ) );
+
+ result:=
+ int8u_ptr(
+ ptrcomp(
+ p32_ptr(ptrcomp(m_cmd_blocks ) + nb * sizeof(int8u_ptr ) ).ptr ) +
+ (m_total_vertices and block_mask ) * sizeof(int8u ) );
+
+end;
+
+{ PERCEIVE_POLYGON_ORIENTATION }
+function path_storage.perceive_polygon_orientation;
+var
+ np ,i : unsigned;
+
+ area ,x1 ,y1 ,x2 ,y2 : double;
+
+begin
+// Calculate signed area (double area to be exact)
+ np :=end_ - start;
+ area:=0.0;
+
+ if np > 0 then
+ for i:=0 to np - 1 do
+ begin
+ vertex_(start + i ,@x1 ,@y1 );
+ vertex_(start + (i + 1 ) mod np ,@x2 ,@y2 );
+
+ area:=area + (x1 * y2 - y1 * x2 );
+
+ end;
+
+ if area < 0.0 then
+ result:=path_flags_cw
+ else
+ result:=path_flags_ccw;
+
+end;
+
+{ INVERT_POLYGON }
+procedure path_storage.invert_polygon(start ,end_ : unsigned );
+var
+ i ,tmp_cmd ,start_nb ,end_nb : unsigned;
+
+ start_ptr ,end_ptr : double_ptr;
+
+ tmp_xy : double;
+
+begin
+ tmp_cmd:=command(start );
+
+ dec(end_ ); // Make "end" inclusive
+
+// Shift all commands to one position
+ i:=start;
+
+ while i < end_ do
+ begin
+ modify_command(i ,command(i + 1 ) );
+
+ inc(i );
+
+ end;
+
+// Assign starting command to the ending command
+ modify_command(end_ ,tmp_cmd );
+
+// Reverse the polygon
+ while end_ > start do
+ begin
+ start_nb:=start shr block_shift;
+ end_nb :=end_ shr block_shift;
+
+ start_ptr:=
+ double_ptr(
+ ptrcomp(
+ p32_ptr(ptrcomp(m_coord_blocks ) + start_nb * sizeof(double_ptr ) ).ptr ) +
+ ((start and block_mask ) shl 1 ) * sizeof(double ) );
+
+ end_ptr:=
+ double_ptr(
+ ptrcomp(
+ p32_ptr(ptrcomp(m_coord_blocks ) + end_nb * sizeof(double_ptr ) ).ptr ) +
+ ((end_ and block_mask ) shl 1 ) * sizeof(double ) );
+
+ tmp_xy :=start_ptr^;
+ start_ptr^:=end_ptr^; inc(ptrcomp(start_ptr ) ,sizeof(double ) );
+ end_ptr^ :=tmp_xy; inc(ptrcomp(end_ptr ) ,sizeof(double ) );
+
+ tmp_xy :=start_ptr^;
+ start_ptr^:=end_ptr^;
+ end_ptr^ :=tmp_xy;
+
+ tmp_cmd:=
+ int8u_ptr(
+ ptrcomp(
+ p32_ptr(ptrcomp(m_cmd_blocks ) + start_nb * sizeof(int8u_ptr ) ).ptr ) +
+ (start and block_mask ) * sizeof(int8u ) )^;
+
+ int8u_ptr(
+ ptrcomp(
+ p32_ptr(ptrcomp(m_cmd_blocks ) + start_nb * sizeof(int8u_ptr ) ).ptr ) +
+ (start and block_mask ) * sizeof(int8u ) )^:=
+ int8u_ptr(
+ ptrcomp(
+ p32_ptr(ptrcomp(m_cmd_blocks ) + end_nb * sizeof(int8u_ptr ) ).ptr ) +
+ (end_ and block_mask ) * sizeof(int8u ) )^;
+
+ int8u_ptr(
+ ptrcomp(
+ p32_ptr(ptrcomp(m_cmd_blocks ) + end_nb * sizeof(int8u_ptr ) ).ptr ) +
+ (end_ and block_mask ) * sizeof(int8u ) )^:=int8u(tmp_cmd );
+
+ inc(start );
+ dec(end_ );
+
+ end;
+
+end;
+
+{ INVERT_POLYGON }
+procedure path_storage.invert_polygon(start : unsigned );
+var
+ end_ : unsigned;
+
+begin
+// Skip all non-vertices at the beginning
+ while (start < m_total_vertices ) and
+ not is_vertex(command(start ) ) do
+ inc(start );
+
+// Skip all insignificant move_to
+ while (start + 1 < m_total_vertices ) and
+ is_move_to(command(start ) ) and
+ is_move_to(command(start + 1 ) ) do
+ inc(start );
+
+// Find the last vertex
+ end_:=start + 1;
+
+ while (end_ < m_total_vertices ) and
+ not is_next_poly(command(end_ ) ) do
+ inc(end_ );
+
+ invert_polygon(start ,end_ );
+
+end;
+
+{ CONCAT_PATH }
+procedure path_storage.concat_path(vs : vertex_source_ptr; path_id : unsigned = 0 );
+var
+ x ,y : double;
+ cmd : unsigned;
+
+begin
+ vs.rewind(path_id );
+
+ cmd:=vs.vertex(@x ,@y );
+
+ while not is_stop(cmd ) do
+ begin
+ add_vertex(x ,y ,cmd );
+
+ cmd:=vs.vertex(@x ,@y );
+
+ end;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_path_storage_integer.pas b/src/corelib/render/software/agg_path_storage_integer.pas
new file mode 100644
index 00000000..618a7594
--- /dev/null
+++ b/src/corelib/render/software/agg_path_storage_integer.pas
@@ -0,0 +1,965 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 14.02.2006-Milano: Unit port establishment
+//
+{ agg_path_storage_integer.pas }
+unit
+ agg_path_storage_integer ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_array ,
+ agg_vertex_source ;
+
+{ TYPES DEFINITION }
+const
+ cmd_move_to = 0;
+ cmd_line_to = 1;
+ cmd_curve3 = 2;
+ cmd_curve4 = 3;
+
+ coord_shift = 6;
+ coord_scale = 1 shl coord_shift;
+
+type
+ vertex_int16_ptr = ^vertex_int16;
+ vertex_int16 = object
+ x ,y : int16;
+
+ constructor Construct; overload;
+ constructor Construct(x_ ,y_ : int16; flag : unsigned ); overload;
+
+ function vertex(x_ ,y_ : double_ptr; dx : double = 0; dy : double = 0; scale : double = 1.0 ) : unsigned;
+
+ end;
+
+ vertex_int32_ptr = ^vertex_int32;
+ vertex_int32 = object
+ x ,y : int32;
+
+ constructor Construct; overload;
+ constructor Construct(x_ ,y_ : int32; flag : unsigned ); overload;
+
+ function vertex(x_ ,y_ : double_ptr; dx : double = 0; dy : double = 0; scale : double = 1.0 ) : unsigned;
+
+ end;
+
+ path_storage_integer_ptr = ^path_storage_integer;
+ path_storage_integer = object(vertex_source )
+ procedure move_to(x ,y : int32 ); virtual; abstract;
+ procedure line_to(x ,y : int32 ); virtual; abstract;
+ procedure curve3 (x_ctrl ,y_ctrl ,x_to ,y_to : int32 ); virtual; abstract;
+ procedure curve4 (x_ctrl1 ,y_ctrl1 ,x_ctrl2 ,y_ctrl2 ,x_to ,y_to : int32 ); virtual; abstract;
+
+ function vertex_(idx : unsigned; x ,y : int32_ptr ) : unsigned; virtual; abstract;
+
+ procedure close_polygon; virtual; abstract;
+
+ end;
+
+ path_storage_int16_ptr = ^path_storage_int16;
+ path_storage_int16 = object(path_storage_integer )
+ m_storage : pod_deque;
+ m_vertex_idx : unsigned;
+ m_closed : boolean;
+
+ constructor Construct;
+ destructor Destruct; virtual;
+
+ procedure remove_all; virtual;
+
+ procedure move_to(x ,y : int32 ); virtual;
+ procedure line_to(x ,y : int32 ); virtual;
+ procedure curve3 (x_ctrl ,y_ctrl ,x_to ,y_to : int32 ); virtual;
+ procedure curve4 (x_ctrl1 ,y_ctrl1 ,x_ctrl2 ,y_ctrl2 ,x_to ,y_to : int32 ); virtual;
+
+ procedure close_polygon; virtual;
+
+ function size : unsigned;
+ function vertex_(idx : unsigned; x ,y : int32_ptr ) : unsigned; virtual;
+
+ function byte_size : unsigned;
+ procedure serialize(ptr : int8u_ptr );
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ function bounding_rect : rect_d;
+
+ end;
+
+ path_storage_int32_ptr = ^path_storage_int32;
+ path_storage_int32 = object(path_storage_integer )
+ m_storage : pod_deque;
+ m_vertex_idx : unsigned;
+ m_closed : boolean;
+
+ constructor Construct;
+ destructor Destruct; virtual;
+
+ procedure remove_all; virtual;
+
+ procedure move_to(x ,y : int32 ); virtual;
+ procedure line_to(x ,y : int32 ); virtual;
+ procedure curve3 (x_ctrl ,y_ctrl ,x_to ,y_to : int32 ); virtual;
+ procedure curve4 (x_ctrl1 ,y_ctrl1 ,x_ctrl2 ,y_ctrl2 ,x_to ,y_to : int32 ); virtual;
+
+ procedure close_polygon; virtual;
+
+ function size : unsigned;
+ function vertex_(idx : unsigned; x ,y : int32_ptr ) : unsigned; virtual;
+
+ function byte_size : unsigned;
+ procedure serialize(ptr : int8u_ptr );
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ function bounding_rect : rect_d;
+
+ end;
+
+ serialized_integer_path_adaptor_ptr = ^serialized_integer_path_adaptor;
+ serialized_integer_path_adaptor = object(vertex_source )
+ procedure init(data : int8u_ptr; size : unsigned; dx ,dy : double; scale : double = 1.0 ); virtual; abstract;
+
+ end;
+
+ serialized_int16_path_adaptor_ptr = ^serialized_int16_path_adaptor;
+ serialized_int16_path_adaptor = object(serialized_integer_path_adaptor )
+ m_data ,
+ m_end ,
+ m_ptr : int8u_ptr;
+
+ m_dx ,
+ m_dy ,
+ m_scale : double;
+
+ m_vertices : unsigned;
+
+ constructor Construct; overload;
+ constructor Construct(data : int8u_ptr; size : unsigned; dx ,dy : double ); overload;
+
+ procedure init(data : int8u_ptr; size : unsigned; dx ,dy : double; scale : double = 1.0 ); virtual;
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ end;
+
+ serialized_int32_path_adaptor_ptr = ^serialized_int32_path_adaptor;
+ serialized_int32_path_adaptor = object(serialized_integer_path_adaptor )
+ m_data ,
+ m_end ,
+ m_ptr : int8u_ptr;
+
+ m_dx ,
+ m_dy ,
+ m_scale : double;
+
+ m_vertices : unsigned;
+
+ constructor Construct; overload;
+ constructor Construct(data : int8u_ptr; size : unsigned; dx ,dy : double ); overload;
+
+ procedure init(data : int8u_ptr; size : unsigned; dx ,dy : double; scale : double = 1.0 ); virtual;
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ end;
+
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor vertex_int16.Construct;
+begin
+ x:=0;
+ y:=0;
+
+end;
+
+{ CONSTRUCT }
+constructor vertex_int16.Construct(x_ ,y_ : int16; flag : unsigned );
+begin
+ x:=((x_ shl 1 ) and not 1 ) or (flag and 1 );
+ y:=((y_ shl 1 ) and not 1 ) or (flag shr 1 );
+
+end;
+
+{ VERTEX }
+function vertex_int16.vertex;
+begin
+ x_^:= dx + (shr_int16(x , 1 ) / coord_scale ) * scale;
+ y_^:= dy + (shr_int16(y , 1 ) / coord_scale ) * scale;
+
+ case ((y and 1 ) shl 1 ) or (x and 1 ) of
+ cmd_move_to :
+ result:=path_cmd_move_to;
+
+ cmd_line_to :
+ result:=path_cmd_line_to;
+
+ cmd_curve3 :
+ result:=path_cmd_curve3;
+
+ cmd_curve4 :
+ result:=path_cmd_curve4;
+
+ else
+ result:=path_cmd_stop;
+
+ end;
+
+end;
+
+{ CONSTRUCT }
+constructor vertex_int32.Construct;
+begin
+ x:=0;
+ y:=0;
+
+end;
+
+{ CONSTRUCT }
+constructor vertex_int32.Construct(x_ ,y_ : int32; flag : unsigned );
+begin
+ x:=((x_ shl 1 ) and not 1 ) or (flag and 1 );
+ y:=((y_ shl 1 ) and not 1 ) or (flag shr 1 );
+
+end;
+
+{ VERTEX }
+function vertex_int32.vertex;
+begin
+ x_^:= dx + (shr_int32(x , 1 ) / coord_scale ) * scale;
+ y_^:= dy + (shr_int32(y , 1 ) / coord_scale ) * scale;
+
+ case ((y and 1 ) shl 1 ) or (x and 1 ) of
+ cmd_move_to :
+ result:=path_cmd_move_to;
+
+ cmd_line_to :
+ result:=path_cmd_line_to;
+
+ cmd_curve3 :
+ result:=path_cmd_curve3;
+
+ cmd_curve4 :
+ result:=path_cmd_curve4;
+
+ else
+ result:=path_cmd_stop;
+
+ end;
+
+end;
+
+{ CONSTRUCT }
+constructor path_storage_int16.Construct;
+begin
+ m_storage.Construct(sizeof(vertex_int16 ) );
+
+ m_vertex_idx:=0;
+ m_closed :=true;
+
+end;
+
+{ DESTRUCT }
+destructor path_storage_int16.Destruct;
+begin
+ m_storage.Destruct;
+
+end;
+
+{ REMOVE_ALL }
+procedure path_storage_int16.remove_all;
+begin
+ m_storage.remove_all;
+
+end;
+
+{ MOVE_TO }
+procedure path_storage_int16.move_to;
+var
+ v : vertex_int16;
+
+begin
+ v.Construct (int16(x ) ,int16(y ) ,cmd_move_to );
+ m_storage.add(@v );
+
+end;
+
+{ LINE_TO }
+procedure path_storage_int16.line_to;
+var
+ v : vertex_int16;
+
+begin
+ v.Construct (int16(x ) ,int16(y ) ,cmd_line_to );
+ m_storage.add(@v );
+
+end;
+
+{ CURVE3 }
+procedure path_storage_int16.curve3;
+var
+ v : vertex_int16;
+
+begin
+ v.Construct (int16(x_ctrl ) ,int16(y_ctrl ) ,cmd_curve3 );
+ m_storage.add(@v );
+
+ v.Construct (int16(x_to ) ,int16(y_to ) ,cmd_curve3 );
+ m_storage.add(@v );
+
+end;
+
+{ CURVE4 }
+procedure path_storage_int16.curve4;
+var
+ v : vertex_int16;
+
+begin
+ v.Construct (int16(x_ctrl1 ) ,int16(y_ctrl1 ) ,cmd_curve4 );
+ m_storage.add(@v );
+
+ v.Construct (int16(x_ctrl2 ) ,int16(y_ctrl2 ) ,int16(cmd_curve4 ) );
+ m_storage.add(@v );
+
+ v.Construct (int16(x_to ) ,int16(y_to ) ,cmd_curve4 );
+ m_storage.add(@v );
+
+end;
+
+{ CLOSE_POLYGON }
+procedure path_storage_int16.close_polygon;
+begin
+end;
+
+{ SIZE }
+function path_storage_int16.size;
+begin
+ result:=m_storage.size;
+
+end;
+
+{ VERTEX_ }
+function path_storage_int16.vertex_;
+var
+ v : vertex_int16_ptr;
+
+begin
+ v:=m_storage.array_operator(idx );
+
+ int16_ptr(x )^:=shr_int16(v.x ,1 );
+ int16_ptr(y )^:=shr_int16(v.y ,1 );
+
+ result:=((v.y and 1 ) shl 1 ) or (v.x and 1 );
+
+end;
+
+{ BYTE_SIZE }
+function path_storage_int16.byte_size;
+begin
+ result:=m_storage.size * sizeof(vertex_int16 );
+
+end;
+
+{ SERIALIZE }
+procedure path_storage_int16.serialize;
+var
+ i : unsigned;
+
+begin
+ i:=0;
+
+ while i < m_storage.size do
+ begin
+ move(m_storage.array_operator(i )^ ,ptr^ ,sizeof(vertex_int16 ) );
+
+ inc(ptrcomp(ptr ) ,sizeof(vertex_int16 ) );
+ inc(i );
+
+ end;
+
+end;
+
+{ REWIND }
+procedure path_storage_int16.rewind;
+begin
+ m_vertex_idx:=0;
+ m_closed :=true;
+
+end;
+
+{ VERTEX }
+function path_storage_int16.vertex;
+var
+ cmd : unsigned;
+
+begin
+ if (m_storage.size < 2 ) or
+ (m_vertex_idx > m_storage.size ) then
+ begin
+ x^:=0;
+ y^:=0;
+
+ result:=path_cmd_stop;
+
+ exit;
+
+ end;
+
+ if m_vertex_idx = m_storage.size then
+ begin
+ x^:=0;
+ y^:=0;
+
+ inc(m_vertex_idx );
+
+ result:=path_cmd_end_poly or path_flags_close;
+
+ exit;
+
+ end;
+
+ cmd:=vertex_int16_ptr(m_storage.array_operator(m_vertex_idx ) ).vertex(x ,y );
+
+ if is_move_to(cmd ) and
+ not m_closed then
+ begin
+ x^:=0;
+ y^:=0;
+
+ m_closed:=true;
+
+ result:=path_cmd_end_poly or path_flags_close;
+
+ exit;
+
+ end;
+
+ m_closed:=false;
+
+ inc(m_vertex_idx );
+
+ result:=cmd;
+
+end;
+
+{ BOUNDING_RECT }
+function path_storage_int16.bounding_rect;
+var
+ i : unsigned;
+
+ x ,y : double;
+
+begin
+ result.Construct(1e100 ,1e100 ,-1e100 ,-1e100 );
+
+ if m_storage.size = 0 then
+ result.Construct(0.0 ,0.0 ,0.0 ,0.0 )
+ else
+ for i:=0 to m_storage.size - 1 do
+ begin
+ vertex_int16_ptr(m_storage.array_operator(i ) ).vertex(@x ,@y );
+
+ if x < result.x1 then
+ result.x1:=x;
+
+ if y < result.y1 then
+ result.y1:=y;
+
+ if x > result.x2 then
+ result.x2:=x;
+
+ if y > result.y2 then
+ result.y2:=y;
+
+ end;
+
+end;
+
+{ CONSTRUCT }
+constructor path_storage_int32.Construct;
+begin
+ m_storage.Construct(sizeof(vertex_int32 ) );
+
+ m_vertex_idx:=0;
+ m_closed :=true;
+
+end;
+
+{ DESTRUCT }
+destructor path_storage_int32.Destruct;
+begin
+ m_storage.Destruct;
+
+end;
+
+{ REMOVE_ALL }
+procedure path_storage_int32.remove_all;
+begin
+ m_storage.remove_all;
+
+end;
+
+{ MOVE_TO }
+procedure path_storage_int32.move_to;
+var
+ v : vertex_int32;
+
+begin
+ v.Construct (x ,y ,cmd_move_to );
+ m_storage.add(@v );
+
+end;
+
+{ LINE_TO }
+procedure path_storage_int32.line_to;
+var
+ v : vertex_int32;
+
+begin
+ v.Construct (x ,y ,cmd_line_to );
+ m_storage.add(@v );
+
+end;
+
+{ CURVE3 }
+procedure path_storage_int32.curve3;
+var
+ v : vertex_int32;
+
+begin
+ v.Construct (x_ctrl ,y_ctrl ,cmd_curve3 );
+ m_storage.add(@v );
+
+ v.Construct (x_to ,y_to ,cmd_curve3 );
+ m_storage.add(@v );
+
+end;
+
+{ CURVE4 }
+procedure path_storage_int32.curve4;
+var
+ v : vertex_int32;
+
+begin
+ v.Construct (x_ctrl1 ,y_ctrl1 ,cmd_curve4 );
+ m_storage.add(@v );
+
+ v.Construct (x_ctrl2 ,y_ctrl2 ,cmd_curve4 );
+ m_storage.add(@v );
+
+ v.Construct (x_to ,y_to ,cmd_curve4 );
+ m_storage.add(@v );
+
+end;
+
+{ CLOSE_POLYGON }
+procedure path_storage_int32.close_polygon;
+begin
+end;
+
+{ SIZE }
+function path_storage_int32.size;
+begin
+ result:=m_storage.size;
+
+end;
+
+{ VERTEX_ }
+function path_storage_int32.vertex_;
+var
+ v : vertex_int32_ptr;
+
+begin
+ v:=m_storage.array_operator(idx );
+
+ x^:=shr_int32(v.x ,1 );
+ y^:=shr_int32(v.y ,1 );
+
+ result:=((v.y and 1 ) shl 1 ) or (v.x and 1 );
+
+end;
+
+{ BYTE_SIZE }
+function path_storage_int32.byte_size;
+begin
+ result:=m_storage.size * sizeof(vertex_int32 );
+
+end;
+
+{ SERIALIZE }
+procedure path_storage_int32.serialize;
+var
+ i : unsigned;
+
+begin
+ i:=0;
+
+ while i < m_storage.size do
+ begin
+ move(m_storage.array_operator(i )^ ,ptr^ ,sizeof(vertex_int32 ) );
+
+ inc(ptrcomp(ptr ) ,sizeof(vertex_int32 ) );
+ inc(i );
+
+ end;
+
+end;
+
+{ REWIND }
+procedure path_storage_int32.rewind;
+begin
+ m_vertex_idx:=0;
+ m_closed :=true;
+
+end;
+
+{ VERTEX }
+function path_storage_int32.vertex;
+var
+ cmd : unsigned;
+
+begin
+ if (m_storage.size < 2 ) or
+ (m_vertex_idx > m_storage.size ) then
+ begin
+ x^:=0;
+ y^:=0;
+
+ result:=path_cmd_stop;
+
+ exit;
+
+ end;
+
+ if m_vertex_idx = m_storage.size then
+ begin
+ x^:=0;
+ y^:=0;
+
+ inc(m_vertex_idx );
+
+ result:=path_cmd_end_poly or path_flags_close;
+
+ exit;
+
+ end;
+
+ cmd:=vertex_int32_ptr(m_storage.array_operator(m_vertex_idx ) ).vertex(x ,y );
+
+ if is_move_to(cmd ) and
+ not m_closed then
+ begin
+ x^:=0;
+ y^:=0;
+
+ m_closed:=true;
+
+ result:=path_cmd_end_poly or path_flags_close;
+
+ exit;
+
+ end;
+
+ m_closed:=false;
+
+ inc(m_vertex_idx );
+
+ result:=cmd;
+
+end;
+
+{ BOUNDING_RECT }
+function path_storage_int32.bounding_rect;
+var
+ i : unsigned;
+
+ x ,y : double;
+
+begin
+ result.Construct(1e100 ,1e100 ,-1e100 ,-1e100 );
+
+ if m_storage.size = 0 then
+ result.Construct(0.0 ,0.0 ,0.0 ,0.0 )
+ else
+ for i:=0 to m_storage.size - 1 do
+ begin
+ vertex_int32_ptr(m_storage.array_operator(i ) ).vertex(@x ,@y );
+
+ if x < result.x1 then
+ result.x1:=x;
+
+ if y < result.y1 then
+ result.y1:=y;
+
+ if x > result.x2 then
+ result.x2:=x;
+
+ if y > result.y2 then
+ result.y2:=y;
+
+ end;
+
+end;
+
+{ CONSTRUCT }
+constructor serialized_int16_path_adaptor.Construct;
+begin
+ m_data:=NIL;
+ m_end :=NIL;
+ m_ptr :=NIL;
+
+ m_dx:=0.0;
+ m_dy:=0.0;
+
+ m_scale :=1.0;
+ m_vertices:=0;
+
+end;
+
+{ CONSTRUCT }
+constructor serialized_int16_path_adaptor.Construct(data : int8u_ptr; size : unsigned; dx ,dy : double );
+begin
+ m_data:=data;
+ m_end :=int8u_ptr(ptrcomp(data ) + size );
+ m_ptr :=data;
+
+ m_dx:=dx;
+ m_dy:=dy;
+
+ m_scale :=0.0;
+ m_vertices:=0;
+
+end;
+
+{ INIT }
+procedure serialized_int16_path_adaptor.init;
+begin
+ m_data:=data;
+ m_end :=int8u_ptr(ptrcomp(data ) + size );
+ m_ptr :=data;
+
+ m_dx:=dx;
+ m_dy:=dy;
+
+ m_scale :=scale;
+ m_vertices:=0;
+
+end;
+
+{ REWIND }
+procedure serialized_int16_path_adaptor.rewind;
+begin
+ m_ptr:=m_data;
+
+ m_vertices:=0;
+
+end;
+
+{ VERTEX }
+function serialized_int16_path_adaptor.vertex;
+var
+ v : vertex_int16;
+
+ cmd : unsigned;
+
+begin
+ if (m_data = NIL ) or
+ (ptrcomp(m_ptr ) > ptrcomp(m_end ) ) then
+ begin
+ x^:=0;
+ y^:=0;
+
+ result:=path_cmd_stop;
+
+ exit;
+
+ end;
+
+ if ptrcomp(m_ptr ) = ptrcomp(m_end ) then
+ begin
+ x^:=0;
+ y^:=0;
+
+ inc(ptrcomp(m_ptr ) ,sizeof(vertex_int16 ) );
+
+ result:=path_cmd_end_poly or path_flags_close;
+
+ exit;
+
+ end;
+
+ move(m_ptr^ ,v ,sizeof(vertex_int16 ) );
+
+ cmd:=v.vertex(x ,y ,m_dx ,m_dy ,m_scale );
+
+ if is_move_to(cmd ) and
+ (m_vertices > 2 ) then
+ begin
+ x^:=0;
+ y^:=0;
+
+ m_vertices:=0;
+
+ result:=path_cmd_end_poly or path_flags_close;
+
+ exit;
+
+ end;
+
+ inc(m_vertices );
+ inc(ptrcomp(m_ptr ) ,sizeof(vertex_int16 ) );
+
+ result:=cmd;
+
+end;
+
+{ CONSTRUCT }
+constructor serialized_int32_path_adaptor.Construct;
+begin
+ m_data:=NIL;
+ m_end :=NIL;
+ m_ptr :=NIL;
+
+ m_dx:=0.0;
+ m_dy:=0.0;
+
+ m_scale :=1.0;
+ m_vertices:=0;
+
+end;
+
+{ CONSTRUCT }
+constructor serialized_int32_path_adaptor.Construct(data : int8u_ptr; size : unsigned; dx ,dy : double );
+begin
+ m_data:=data;
+ m_end :=int8u_ptr(ptrcomp(data ) + size );
+ m_ptr :=data;
+
+ m_dx:=dx;
+ m_dy:=dy;
+
+ m_scale :=0.0;
+ m_vertices:=0;
+
+end;
+
+{ INIT }
+procedure serialized_int32_path_adaptor.init;
+begin
+ m_data:=data;
+ m_end :=int8u_ptr(ptrcomp(data ) + size );
+ m_ptr :=data;
+
+ m_dx:=dx;
+ m_dy:=dy;
+
+ m_scale :=scale;
+ m_vertices:=0;
+
+end;
+
+{ REWIND }
+procedure serialized_int32_path_adaptor.rewind;
+begin
+ m_ptr:=m_data;
+
+ m_vertices:=0;
+
+end;
+
+{ VERTEX }
+function serialized_int32_path_adaptor.vertex;
+var
+ v : vertex_int32;
+
+ cmd : unsigned;
+
+begin
+ if (m_data = NIL ) or
+ (ptrcomp(m_ptr ) > ptrcomp(m_end ) ) then
+ begin
+ x^:=0;
+ y^:=0;
+
+ result:=path_cmd_stop;
+
+ exit;
+
+ end;
+
+ if ptrcomp(m_ptr ) = ptrcomp(m_end ) then
+ begin
+ x^:=0;
+ y^:=0;
+
+ inc(ptrcomp(m_ptr ) ,sizeof(vertex_int32 ) );
+
+ result:=path_cmd_end_poly or path_flags_close;
+
+ exit;
+
+ end;
+
+ move(m_ptr^ ,v ,sizeof(vertex_int32 ) );
+
+ cmd:=v.vertex(x ,y ,m_dx ,m_dy ,m_scale );
+
+ if is_move_to(cmd ) and
+ (m_vertices > 2 ) then
+ begin
+ x^:=0;
+ y^:=0;
+
+ m_vertices:=0;
+
+ result:=path_cmd_end_poly or path_flags_close;
+
+ exit;
+
+ end;
+
+ inc(m_vertices );
+ inc(ptrcomp(m_ptr ) ,sizeof(vertex_int32 ) );
+
+ result:=cmd;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_pattern_filters_rgba.pas b/src/corelib/render/software/agg_pattern_filters_rgba.pas
new file mode 100644
index 00000000..34865d2e
--- /dev/null
+++ b/src/corelib/render/software/agg_pattern_filters_rgba.pas
@@ -0,0 +1,267 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 02.02.2006-Milano: Unit port establishment
+//
+{ agg_pattern_filters_rgba.pas }
+unit
+ agg_pattern_filters_rgba ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_line_aa_basics ,
+ agg_color ;
+
+{ TYPES DEFINITION }
+type
+ pattern_filter_ptr = ^pattern_filter;
+ pattern_filter = object
+ constructor Construct;
+
+ function dilation : unsigned; virtual; abstract;
+ procedure pixel_low_res (buf : pointer; p : aggclr_ptr; x ,y : int ); virtual; abstract;
+ procedure pixel_high_res(buf : pointer; p : aggclr_ptr; x ,y : int ); virtual; abstract;
+
+ end;
+
+ pattern_filter_nn = object(pattern_filter )
+ function dilation : unsigned; virtual;
+ procedure pixel_low_res (buf : pointer; p : aggclr_ptr; x ,y : int ); virtual;
+ procedure pixel_high_res(buf : pointer; p : aggclr_ptr; x ,y : int ); virtual;
+
+ end;
+
+ pattern_filter_bilinear_rgba = object(pattern_filter )
+ function dilation : unsigned; virtual;
+ procedure pixel_low_res (buf : pointer; p : aggclr_ptr; x ,y : int ); virtual;
+ procedure pixel_high_res(buf : pointer; p : aggclr_ptr; x ,y : int ); virtual;
+
+ end;
+
+ pattern_filter_bilinear_gray8 = object(pattern_filter_bilinear_rgba )
+ procedure pixel_high_res(buf : pointer; p : aggclr_ptr; x ,y : int ); virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor pattern_filter.Construct;
+begin
+end;
+
+{ DILATION }
+function pattern_filter_nn.dilation;
+begin
+ result:=0;
+
+end;
+
+{ PIXEL_LOW_RES }
+procedure pattern_filter_nn.pixel_low_res;
+begin
+ p^.Construct(
+ rgba8_ptr(
+ ptrcomp(rgba8_ptr_ptr(ptrcomp(buf ) + y * sizeof(pointer ) )^ ) +
+ x * sizeof(rgba8 ) )^ );
+
+end;
+
+{ PIXEL_HIGH_RES }
+procedure pattern_filter_nn.pixel_high_res;
+begin
+ p^.Construct(
+ rgba8_ptr(
+ ptrcomp(rgba8_ptr_ptr(ptrcomp(buf ) + shr_int32(y ,line_subpixel_shift ) * sizeof(pointer ) )^ ) +
+ shr_int32(x ,line_subpixel_shift ) * sizeof(rgba8 ) )^ );
+
+end;
+
+{ DILATION }
+function pattern_filter_bilinear_rgba.dilation;
+begin
+ result:=1;
+
+end;
+
+{ PIXEL_LOW_RES }
+procedure pattern_filter_bilinear_rgba.pixel_low_res;
+begin
+ p^.Construct(
+ rgba8_ptr(
+ ptrcomp(rgba8_ptr_ptr(ptrcomp(buf ) + y * sizeof(pointer ) )^ ) +
+ x * sizeof(rgba8 ) )^ );
+
+end;
+
+{ PIXEL_HIGH_RES }
+procedure pattern_filter_bilinear_rgba.pixel_high_res;
+var
+ r ,g ,b ,a ,weight : int32u;
+
+ x_lr ,y_lr : int;
+
+ ptr : rgba8_ptr;
+
+begin
+ r:=line_subpixel_size * line_subpixel_size div 2;
+ g:=r;
+ b:=g;
+ a:=b;
+
+ x_lr:=shr_int32(x ,line_subpixel_shift );
+ y_lr:=shr_int32(y ,line_subpixel_shift );
+
+ x:=x and line_subpixel_mask;
+ y:=y and line_subpixel_mask;
+
+ ptr:=
+ rgba8_ptr(
+ ptrcomp(rgba8_ptr_ptr(ptrcomp(buf ) + y_lr * sizeof(pointer ) )^ ) +
+ x_lr * sizeof(rgba8 ) );
+
+ weight:=(line_subpixel_size - x ) * (line_subpixel_size - y );
+
+ inc(r ,weight * ptr.r );
+ inc(g ,weight * ptr.g );
+ inc(b ,weight * ptr.b );
+ inc(a ,weight * ptr.a );
+
+ inc(ptrcomp(ptr ) ,sizeof(rgba8 ) );
+
+ weight:=x * (line_subpixel_size - y );
+
+ inc(r ,weight * ptr.r );
+ inc(g ,weight * ptr.g );
+ inc(b ,weight * ptr.b );
+ inc(a ,weight * ptr.a );
+
+ ptr:=
+ rgba8_ptr(
+ ptrcomp(rgba8_ptr_ptr(ptrcomp(buf ) + (y_lr + 1 ) * sizeof(pointer ) )^ ) +
+ x_lr * sizeof(rgba8 ) );
+
+ weight:=(line_subpixel_size - x ) * y;
+
+ inc(r ,weight * ptr.r );
+ inc(g ,weight * ptr.g );
+ inc(b ,weight * ptr.b );
+ inc(a ,weight * ptr.a );
+
+ inc(ptrcomp(ptr ) ,sizeof(rgba8 ) );
+
+ weight:=x * y;
+
+ inc(r ,weight * ptr.r );
+ inc(g ,weight * ptr.g );
+ inc(b ,weight * ptr.b );
+ inc(a ,weight * ptr.a );
+
+ p.r:=int8u(r shr (line_subpixel_shift * 2 ) );
+ p.g:=int8u(g shr (line_subpixel_shift * 2 ) );
+ p.b:=int8u(b shr (line_subpixel_shift * 2 ) );
+ p.a:=int8u(a shr (line_subpixel_shift * 2 ) );
+
+end;
+
+{ PIXEL_HIGH_RES }
+procedure pattern_filter_bilinear_gray8.pixel_high_res;
+var
+ r ,g ,b ,a ,weight : int32u;
+
+ x_lr ,y_lr : int;
+
+ ptr : rgba8_ptr;
+
+begin
+ r:=line_subpixel_size * line_subpixel_size div 2;
+ g:=r;
+ b:=g;
+ a:=b;
+
+ x_lr:=shr_int32(x ,line_subpixel_shift );
+ y_lr:=shr_int32(y ,line_subpixel_shift );
+
+ x:=x and line_subpixel_mask;
+ y:=y and line_subpixel_mask;
+
+ ptr:=
+ rgba8_ptr(
+ ptrcomp(rgba8_ptr_ptr(ptrcomp(buf ) + y_lr * sizeof(pointer ) )^ ) +
+ x_lr * sizeof(rgba8 ) );
+
+ weight:=(line_subpixel_size - x ) * (line_subpixel_size - y );
+
+ inc(r ,weight * ptr.r );
+ inc(g ,weight * ptr.g );
+ inc(b ,weight * ptr.b );
+ inc(a ,weight * ptr.a );
+
+ inc(ptrcomp(ptr ) ,sizeof(rgba8 ) );
+
+ weight:=x * (line_subpixel_size - y );
+
+ inc(r ,weight * ptr.r );
+ inc(g ,weight * ptr.g );
+ inc(b ,weight * ptr.b );
+ inc(a ,weight * ptr.a );
+
+ ptr:=
+ rgba8_ptr(
+ ptrcomp(rgba8_ptr_ptr(ptrcomp(buf ) + (y_lr + 1 ) * sizeof(pointer ) )^ ) +
+ x_lr * sizeof(rgba8 ) );
+
+ weight:=(line_subpixel_size - x ) * y;
+
+ inc(r ,weight * ptr.r );
+ inc(g ,weight * ptr.g );
+ inc(b ,weight * ptr.b );
+ inc(a ,weight * ptr.a );
+
+ inc(ptrcomp(ptr ) ,sizeof(rgba8 ) );
+
+ weight:=x * y;
+
+ inc(r ,weight * ptr.r );
+ inc(g ,weight * ptr.g );
+ inc(b ,weight * ptr.b );
+ inc(a ,weight * ptr.a );
+
+ p.r:=int8u(r shr (line_subpixel_shift * 2 ) );
+ p.g:=int8u(g shr (line_subpixel_shift * 2 ) );
+ p.b:=int8u(b shr (line_subpixel_shift * 2 ) );
+ p.v:=(p.r * 77 + p.g * 150 + p.b * 29 ) shr 8;
+ p.a:=int8u(a shr (line_subpixel_shift * 2 ) );
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_pixfmt.pas b/src/corelib/render/software/agg_pixfmt.pas
new file mode 100644
index 00000000..f7eab2ca
--- /dev/null
+++ b/src/corelib/render/software/agg_pixfmt.pas
@@ -0,0 +1,409 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//----------------------------------------------------------------------------
+//
+// This unit is originaly not the part of the AGG library.
+// agg_pixfmt unit & pixel_formats object substitutes the templetized
+// concept of a pixel polymorphism in c++.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 13.01.2006-Milano: Unit creation
+//
+{ agg_pixfmt.pas }
+unit
+ agg_pixfmt ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+{$Q- }
+{$R- }
+uses
+ agg_basics ,
+ agg_rendering_buffer ,
+ agg_color ;
+
+{ TYPES DEFINITION }
+type
+ pixel_formats_ptr = ^pixel_formats;
+
+ func_blender = procedure(this : pixel_formats_ptr; op : unsigned; p : int8u_ptr; cr ,cg ,cb ,ca ,cover : unsigned );
+ func_blend_pix = procedure(this : pixel_formats_ptr; p : int8u_ptr; cr ,cg ,cb ,alpha ,cover : unsigned );
+
+ func_copy_pixel = procedure(this : pixel_formats_ptr; x ,y : int; c : aggclr_ptr );
+ func_blend_pixel = procedure(this : pixel_formats_ptr; x ,y : int; c : aggclr_ptr; cover : int8u );
+
+ func_pixel = function(this : pixel_formats_ptr; x ,y : int ) : aggclr;
+ func_row = function(this : pixel_formats_ptr; x ,y : int ) : row_data_type;
+
+ func_copy_hline = procedure(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr );
+ func_copy_vline = procedure(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr );
+
+ func_blend_hline = procedure(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+ func_blend_vline = procedure(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+
+ func_blend_solid_hspan = procedure(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+ func_blend_solid_vspan = procedure(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+
+ func_copy_color_hspan = procedure(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr );
+ func_copy_color_vspan = procedure(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr );
+
+ func_blend_color_hspan = procedure(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+ func_blend_color_vspan = procedure(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+
+ func_copy_from = procedure(this : pixel_formats_ptr; from : rendering_buffer_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned );
+ func_blend_from = procedure(this : pixel_formats_ptr; from : pixel_formats_ptr; psrc_ : int8u_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+
+ func_blend_from_color = procedure(this : pixel_formats_ptr; from : pixel_formats_ptr; color : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+ func_blend_from_lut = procedure(this : pixel_formats_ptr; from : pixel_formats_ptr; color_lut : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+
+ func_apply_gamma = procedure(this : pixel_formats_ptr; p : int8u_ptr );
+ func_for_each_pixel = procedure(this : pixel_formats_ptr; f : func_apply_gamma );
+
+ pixel_formats = object
+ m_rbuf : rendering_buffer_ptr;
+ m_gamma ,
+ m_apply : gamma_ptr;
+ m_order : order_type;
+
+ m_comp_op ,
+ m_step ,
+ m_offset ,
+ m_pix_width : unsigned;
+
+ blender : func_blender;
+
+ copy_pixel : func_copy_pixel;
+ blend_pixel : func_blend_pixel;
+
+ pixel : func_pixel;
+ row : func_row;
+
+ copy_hline : func_copy_hline;
+ copy_vline : func_copy_vline;
+
+ blend_hline : func_blend_hline;
+ blend_vline : func_blend_vline;
+
+ blend_solid_hspan : func_blend_solid_hspan;
+ blend_solid_vspan : func_blend_solid_vspan;
+
+ copy_color_hspan : func_copy_color_hspan;
+ copy_color_vspan : func_copy_color_vspan;
+
+ blend_color_hspan : func_blend_color_hspan;
+ blend_color_vspan : func_blend_color_vspan;
+
+ copy_from : func_copy_from;
+ blend_from : func_blend_from;
+
+ blend_from_color : func_blend_from_color;
+ blend_from_lut : func_blend_from_lut;
+
+ for_each_pixel : func_for_each_pixel;
+ gamma_dir_apply ,
+ gamma_inv_apply : func_apply_gamma;
+
+ pixel_premultiply ,
+ pixel_demultiply : func_apply_gamma;
+
+ constructor Construct(rb : rendering_buffer_ptr; st : unsigned = 1; off : unsigned = 0 );
+
+ function attach (pixf : pixel_formats_ptr; x1 ,y1 ,x2 ,y2 : int ) : boolean;
+ function pix_ptr(x ,y : int ) : int8u_ptr;
+ function row_ptr(y : int ) : int8u_ptr;
+
+ function _width : unsigned; virtual;
+ function _height : unsigned; virtual;
+ function _stride : int;
+ function _pix_width : unsigned;
+
+ procedure apply_gamma_dir(g : gamma_ptr; order : order_type );
+ procedure apply_gamma_inv(g : gamma_ptr; order : order_type );
+
+ procedure comp_op_(op : unsigned );
+ function _comp_op : unsigned;
+
+ procedure premultiply;
+ procedure demultiply;
+
+ end;
+
+ define_pixfmt = procedure(var pixf : pixel_formats; rb : rendering_buffer_ptr );
+ define_pixfmt_gamma = procedure(var pixf : pixel_formats; rb : rendering_buffer_ptr; g : gamma_ptr );
+ define_pixfmt_blender = procedure(var pixf : pixel_formats; rb : rendering_buffer_ptr; bl : func_blender; order : order_type );
+
+ comp_op_e = (
+
+ comp_op_clear, //----comp_op_clear
+ comp_op_src, //----comp_op_src
+ comp_op_dst, //----comp_op_dst
+ comp_op_src_over, //----comp_op_src_over
+ comp_op_dst_over, //----comp_op_dst_over
+ comp_op_src_in, //----comp_op_src_in
+ comp_op_dst_in, //----comp_op_dst_in
+ comp_op_src_out, //----comp_op_src_out
+ comp_op_dst_out, //----comp_op_dst_out
+ comp_op_src_atop, //----comp_op_src_atop
+ comp_op_dst_atop, //----comp_op_dst_atop
+ comp_op_xor, //----comp_op_xor
+ comp_op_plus, //----comp_op_plus
+ comp_op_minus, //----comp_op_minus
+ comp_op_multiply, //----comp_op_multiply
+ comp_op_screen, //----comp_op_screen
+ comp_op_overlay, //----comp_op_overlay
+ comp_op_darken, //----comp_op_darken
+ comp_op_lighten, //----comp_op_lighten
+ comp_op_color_dodge, //----comp_op_color_dodge
+ comp_op_color_burn, //----comp_op_color_burn
+ comp_op_hard_light, //----comp_op_hard_light
+ comp_op_soft_light, //----comp_op_soft_light
+ comp_op_difference, //----comp_op_difference
+ comp_op_exclusion, //----comp_op_exclusion
+ comp_op_contrast, //----comp_op_contrast
+ comp_op_invert, //----comp_op_invert
+ comp_op_invert_rgb, //----comp_op_invert_rgb
+
+ end_of_comp_op_e );
+
+{ GLOBAL PROCEDURES }
+ procedure pixfmt_undefined(var pixf : pixel_formats );
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor pixel_formats.Construct;
+begin
+ m_rbuf :=rb;
+ m_gamma:=NIL;
+ m_apply:=NIL;
+ m_order:=bgra_order;
+
+ m_comp_op:=3;
+ m_step :=st;
+ m_offset :=off;
+
+ m_pix_width:=0;
+
+ blender:=NIL;
+
+ copy_pixel :=NIL;
+ blend_pixel:=NIL;
+
+ pixel:=NIL;
+ row :=NIL;
+
+ copy_hline:=NIL;
+ copy_vline:=NIL;
+
+ blend_hline:=NIL;
+ blend_vline:=NIL;
+
+ blend_solid_hspan:=NIL;
+ blend_solid_vspan:=NIL;
+
+ copy_color_hspan:=NIL;
+ copy_color_vspan:=NIL;
+
+ blend_color_hspan:=NIL;
+ blend_color_vspan:=NIL;
+
+ copy_from :=NIL;
+ blend_from:=NIL;
+
+ blend_from_color:=NIL;
+ blend_from_lut :=NIL;
+
+ for_each_pixel :=NIL;
+ gamma_dir_apply:=NIL;
+ gamma_inv_apply:=NIL;
+
+ pixel_premultiply:=NIL;
+ pixel_demultiply :=NIL;
+
+end;
+
+{ ATTACH }
+function pixel_formats.attach(pixf : pixel_formats_ptr; x1 ,y1 ,x2 ,y2 : int ) : boolean;
+var
+ r ,c : rect_i;
+
+ stride ,y : int;
+
+begin
+ r.Construct(x1 ,y1 ,x2 ,y2 );
+ c.Construct(0 ,0 ,pixf._width - 1 ,pixf._height - 1 );
+
+ if r.clip(@c ) then
+ begin
+ stride:=pixf.m_rbuf._stride;
+
+ if stride < 0 then
+ y:=r.y2
+ else
+ y:=r.y1;
+
+ m_rbuf.attach(
+ pixf.pix_ptr(r.x1 ,y ) ,
+ (r.x2 - r.x1 ) + 1 ,
+ (r.y2 - r.y1 ) + 1 ,
+ stride );
+
+ result:=true;
+
+ end
+ else
+ result:=false;
+
+end;
+
+{ PIX_PTR }
+function pixel_formats.pix_ptr(x ,y : int ) : int8u_ptr;
+begin
+ result:=int8u_ptr(ptrcomp(m_rbuf.row(y ) ) + x * m_pix_width + m_offset );
+
+end;
+
+{ ROW_PTR }
+function pixel_formats.row_ptr(y : int ) : int8u_ptr;
+begin
+ result:=m_rbuf.row(y );
+
+end;
+
+{ _WIDTH }
+function pixel_formats._width;
+begin
+ result:=m_rbuf._width;
+
+end;
+
+{ _HEIGHT }
+function pixel_formats._height;
+begin
+ result:=m_rbuf._height;
+
+end;
+
+{ _STRIDE }
+function pixel_formats._stride;
+begin
+ result:=m_rbuf._stride;
+
+end;
+
+{ _PIX_WIDTH }
+function pixel_formats._pix_width;
+begin
+ result:=m_pix_width;
+
+end;
+
+{ APPLY_GAMMA_DIR }
+procedure pixel_formats.apply_gamma_dir;
+begin
+ m_apply:=g;
+ m_order:=order;
+
+ for_each_pixel(@self ,@gamma_dir_apply );
+
+end;
+
+{ APPLY_GAMMA_INV }
+procedure pixel_formats.apply_gamma_inv;
+begin
+ m_apply:=g;
+ m_order:=order;
+
+ for_each_pixel(@self ,@gamma_inv_apply );
+
+end;
+
+{ COMP_OP_ }
+procedure pixel_formats.comp_op_;
+begin
+ m_comp_op:=op;
+
+end;
+
+{ _COMP_OP }
+function pixel_formats._comp_op;
+begin
+ result:=m_comp_op;
+
+end;
+
+{ PREMULTIPLY }
+procedure pixel_formats.premultiply;
+begin
+ for_each_pixel(@self ,@pixel_premultiply );
+
+end;
+
+{ DEMULTIPLY }
+procedure pixel_formats.demultiply;
+begin
+ for_each_pixel(@self ,@pixel_demultiply );
+
+end;
+
+{ PIXFMT_UNDEFINED }
+procedure pixfmt_undefined;
+begin
+ pixf.Construct(NIL );
+
+ pixf.copy_pixel :=NIL;
+ pixf.blend_pixel:=NIL;
+
+ pixf.pixel:=NIL;
+ pixf.row :=NIL;
+
+ pixf.copy_hline:=NIL;
+ pixf.copy_vline:=NIL;
+
+ pixf.blend_hline:=NIL;
+ pixf.blend_vline:=NIL;
+
+ pixf.blend_solid_hspan:=NIL;
+ pixf.blend_solid_vspan:=NIL;
+
+ pixf.copy_color_hspan:=NIL;
+ pixf.copy_color_vspan:=NIL;
+
+ pixf.blend_color_hspan:=NIL;
+ pixf.blend_color_vspan:=NIL;
+
+ pixf.copy_from :=NIL;
+ pixf.blend_from:=NIL;
+
+ pixf.blend_from_color:=NIL;
+ pixf.blend_from_lut :=NIL;
+
+ pixf.for_each_pixel :=NIL;
+ pixf.gamma_dir_apply:=NIL;
+ pixf.gamma_inv_apply:=NIL;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_pixfmt_amask_adaptor.pas b/src/corelib/render/software/agg_pixfmt_amask_adaptor.pas
new file mode 100644
index 00000000..3bc2b1b8
--- /dev/null
+++ b/src/corelib/render/software/agg_pixfmt_amask_adaptor.pas
@@ -0,0 +1,226 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 10.02.2006-Milano: Unit port establishment
+//
+{ agg_pixfmt_amask_adaptor.pas }
+unit
+ agg_pixfmt_amask_adaptor ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_color ,
+ agg_rendering_buffer ,
+ agg_pixfmt ,
+ agg_alpha_mask_u8 ;
+
+{ TYPES DEFINITION }
+const
+ span_extra_tail = 256;
+
+type
+ pixfmt_amask_adaptor_ptr = ^pixfmt_amask_adaptor;
+ pixfmt_amask_adaptor = object(pixel_formats )
+ m_pixf : pixel_formats_ptr;
+ m_mask : alpha_mask_ptr;
+
+ m_span : int8u_ptr;
+ m_max_len : unsigned;
+
+ constructor Construct(pixf : pixel_formats_ptr; mask : alpha_mask_ptr );
+ destructor Destruct;
+
+ procedure realloc_span(len : unsigned );
+
+ procedure init_span(len : unsigned ); overload;
+ procedure init_span(len : unsigned; covers : int8u_ptr ); overload;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ _copy_hline }
+procedure _copy_hline(this : pixfmt_amask_adaptor_ptr; x ,y : int; len : unsigned; c : aggclr_ptr );
+begin
+ this.realloc_span (len );
+ this.m_mask.fill_hspan (x ,y ,this.m_span ,len );
+ this.m_pixf.blend_solid_hspan(this.m_pixf ,x ,y ,len ,c ,this.m_span );
+
+end;
+
+{ _blend_hline }
+procedure _blend_hline(this : pixfmt_amask_adaptor_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+begin
+ this.init_span (len );
+ this.m_mask.combine_hspan (x ,y ,this.m_span ,len );
+ this.m_pixf.blend_solid_hspan(this.m_pixf ,x ,y ,len ,c ,this.m_span );
+
+end;
+
+{ _blend_vline }
+procedure _blend_vline(this : pixfmt_amask_adaptor_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+begin
+ this.init_span (len);
+ this.m_mask.combine_vspan (x ,y ,this.m_span ,len );
+ this.m_pixf.blend_solid_vspan(this.m_pixf ,x ,y ,len ,c ,this.m_span );
+
+end;
+
+{ _blend_solid_hspan }
+procedure _blend_solid_hspan(this : pixfmt_amask_adaptor_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+begin
+ this.init_span (len ,covers );
+ this.m_mask.combine_hspan (x ,y ,this.m_span ,len );
+ this.m_pixf.blend_solid_hspan(this.m_pixf ,x ,y ,len ,c ,this.m_span );
+
+end;
+
+{ _blend_solid_vspan }
+procedure _blend_solid_vspan(this : pixfmt_amask_adaptor_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+begin
+ this.init_span (len ,covers );
+ this.m_mask.combine_vspan (x ,y ,this.m_span ,len );
+ this.m_pixf.blend_solid_vspan(this.m_pixf ,x ,y ,len ,c ,this.m_span );
+
+end;
+
+{ _blend_color_hspan }
+procedure _blend_color_hspan(this : pixfmt_amask_adaptor_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+begin
+ if covers <> NIL then
+ begin
+ this.init_span (len ,covers );
+ this.m_mask.combine_hspan(x ,y ,this.m_span ,len );
+
+ end
+ else
+ begin
+ this.realloc_span (len );
+ this.m_mask.fill_hspan(x ,y ,this.m_span ,len );
+
+ end;
+
+ this.m_pixf.blend_color_hspan(this.m_pixf ,x ,y ,len ,colors ,this.m_span ,cover );
+
+end;
+
+{ _blend_color_vspan }
+procedure _blend_color_vspan(this : pixfmt_amask_adaptor_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+begin
+ if covers <> NIL then
+ begin
+ this.init_span (len ,covers );
+ this.m_mask.combine_vspan(x ,y ,this.m_span ,len );
+
+ end
+ else
+ begin
+ this.realloc_span (len );
+ this.m_mask.fill_vspan(x ,y ,this.m_span ,len );
+
+ end;
+
+ this.m_pixf.blend_color_vspan(this.m_pixf ,x ,y ,len ,colors ,this.m_span ,cover );
+
+end;
+
+{ _blend_pixel }
+procedure _blend_pixel(this : pixfmt_amask_adaptor_ptr; x ,y : int; c : pointer; cover : int8u );
+begin
+ this.m_pixf.blend_pixel(this.m_pixf ,x ,y ,c ,this.m_mask.combine_pixel(x ,y ,cover ) );
+
+end;
+
+{ CONSTRUCT }
+constructor pixfmt_amask_adaptor.Construct;
+begin
+ inherited Construct(pixf.m_rbuf );
+
+ m_pixf:=pixf;
+ m_mask:=mask;
+
+ m_span :=NIL;
+ m_max_len:=0;
+
+ copy_hline :=@_copy_hline;
+ blend_hline:=@_blend_hline;
+ blend_vline:=@_blend_vline;
+
+ blend_solid_hspan:=@_blend_solid_hspan;
+ blend_solid_vspan:=@_blend_solid_vspan;
+ blend_color_hspan:=@_blend_color_hspan;
+ blend_color_vspan:=@_blend_color_vspan;
+
+ blend_pixel:=@_blend_pixel;
+
+end;
+
+{ DESTRUCT }
+destructor pixfmt_amask_adaptor.Destruct;
+begin
+ agg_freemem(pointer(m_span ) ,m_max_len * sizeof(int8u ) );
+
+end;
+
+{ REALLOC_SPAN }
+procedure pixfmt_amask_adaptor.realloc_span;
+begin
+ if len > m_max_len then
+ begin
+ agg_freemem(pointer(m_span ) ,m_max_len * sizeof(int8u ) );
+
+ m_max_len:=len + span_extra_tail;
+
+ agg_getmem(pointer(m_span ) ,m_max_len * sizeof(int8u ) );
+
+ end;
+
+end;
+
+{ INIT_SPAN }
+procedure pixfmt_amask_adaptor.init_span(len : unsigned );
+begin
+ realloc_span(len );
+
+ fillchar(m_span^ ,len * sizeof(int8u ) ,cover_full );
+
+end;
+
+{ INIT_SPAN }
+procedure pixfmt_amask_adaptor.init_span(len : unsigned; covers : int8u_ptr );
+begin
+ realloc_span(len );
+
+ move(covers^ ,m_span^ ,len * sizeof(int8u ) );
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_pixfmt_gray.pas b/src/corelib/render/software/agg_pixfmt_gray.pas
new file mode 100644
index 00000000..cefd5304
--- /dev/null
+++ b/src/corelib/render/software/agg_pixfmt_gray.pas
@@ -0,0 +1,443 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//----------------------------------------------------------------------------
+//
+// Adaptation for high precision colors has been sponsored by
+// Liberty Technology Systems, Inc., visit http://lib-sys.com
+//
+// Liberty Technology Systems, Inc. is the provider of
+// PostScript and PDF technology for software developers.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 17.03.2006-Milano: pf_gray8.inc & pf_gray8_pre.inc, finished
+// 13.01.2006-Milano: Unit port establishment
+//
+{ agg_pixfmt_gray.pas }
+unit
+ agg_pixfmt_gray ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+{$Q- }
+{$R- }
+uses
+ agg_basics ,
+ agg_pixfmt ,
+ agg_color ,
+ agg_rendering_buffer ;
+
+{ GLOBAL PROCEDURES }
+ procedure pixfmt_gray8(var pixf : pixel_formats; rb : rendering_buffer_ptr );
+
+ procedure pixfmt_gray8_bgr24r(var pixf : pixel_formats; rb : rendering_buffer_ptr );
+ procedure pixfmt_gray8_bgr24g(var pixf : pixel_formats; rb : rendering_buffer_ptr );
+ procedure pixfmt_gray8_bgr24b(var pixf : pixel_formats; rb : rendering_buffer_ptr );
+
+ procedure pixfmt_gray8_pre(var pixf : pixel_formats; rb : rendering_buffer_ptr );
+
+ procedure pixfmt_gray8_pre_bgr24r(var pixf : pixel_formats; rb : rendering_buffer_ptr );
+ procedure pixfmt_gray8_pre_bgr24g(var pixf : pixel_formats; rb : rendering_buffer_ptr );
+ procedure pixfmt_gray8_pre_bgr24b(var pixf : pixel_formats; rb : rendering_buffer_ptr );
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ fmt8_row }
+function fmt8_row(this : pixel_formats_ptr; x ,y : int ) : row_data_type;
+begin
+ result.Construct(
+ x ,this._width - 1 ,
+ int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * this.m_step + this.m_offset ) );
+
+end;
+
+{ gray_gamma_dir_apply }
+procedure gray_gamma_dir_apply(this : pixel_formats; p : int8u_ptr );
+begin
+ p^:=this.m_apply.dir(p^ );
+
+end;
+
+{ gray_gamma_inv_apply }
+procedure gray_gamma_inv_apply(this : pixel_formats; p : int8u_ptr );
+begin
+ p^:=this.m_apply.inv(p^ );
+
+end;
+
+{ gray_for_each_pixel }
+procedure gray_for_each_pixel(this : pixel_formats_ptr; f : func_apply_gamma );
+var
+ y ,len : unsigned;
+
+ p : int8u_ptr;
+
+begin
+ y:=0;
+
+ while y < this._height do
+ begin
+ len:=this._width;
+ p :=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + this.m_offset );
+
+ repeat
+ f(this ,p );
+
+ inc(ptrcomp(p ) ,this.m_step );
+ dec(len );
+
+ until len = 0;
+
+ inc(y );
+
+ end;
+
+end;
+
+{$I pf_gray8.inc }
+
+{ PIXFMT_GRAY8 }
+procedure pixfmt_gray8;
+begin
+ pixf.Construct(rb ,1 ,0 );
+
+ pixf.m_pix_width:=1;
+
+ pixf.copy_pixel :=@gray8_copy_pixel;
+ pixf.blend_pixel:=@gray8_blend_pixel;
+
+ pixf.pixel:=@gray8_pixel;
+ pixf.row :=@fmt8_row;
+
+ pixf.copy_hline:=@gray8_copy_hline;
+ pixf.copy_vline:=@gray8_copy_vline;
+
+ pixf.blend_hline:=@gray8_blend_hline;
+ pixf.blend_vline:=@gray8_blend_vline;
+
+ pixf.blend_solid_hspan:=@gray8_blend_solid_hspan;
+ pixf.blend_solid_vspan:=@gray8_blend_solid_vspan;
+
+ pixf.copy_color_hspan:=@gray8_copy_color_hspan;
+ pixf.copy_color_vspan:=@gray8_copy_color_vspan;
+
+ pixf.blend_color_hspan:=@gray8_blend_color_hspan;
+ pixf.blend_color_vspan:=@gray8_blend_color_vspan;
+
+ pixf.copy_from :=@gray8_copy_from;
+ pixf.blend_from:=NIL; // not defined in agg_pixfmt_gray.h
+
+ pixf.blend_from_color:=@gray8_blend_from_color;
+ pixf.blend_from_lut :=@gray8_blend_from_lut;
+
+ pixf.for_each_pixel :=@gray_for_each_pixel;
+ pixf.gamma_dir_apply:=@gray_gamma_dir_apply;
+ pixf.gamma_inv_apply:=@gray_gamma_inv_apply;
+
+end;
+
+{ PIXFMT_GRAY8_BGR24R }
+procedure pixfmt_gray8_bgr24r;
+begin
+ pixf.Construct(rb ,3 ,2 );
+
+ pixf.m_pix_width:=3;
+
+ pixf.copy_pixel :=@gray8_copy_pixel;
+ pixf.blend_pixel:=@gray8_blend_pixel;
+
+ pixf.pixel:=@gray8_pixel;
+ pixf.row :=@fmt8_row;
+
+ pixf.copy_hline:=@gray8_copy_hline;
+ pixf.copy_vline:=@gray8_copy_vline;
+
+ pixf.blend_hline:=@gray8_blend_hline;
+ pixf.blend_vline:=@gray8_blend_vline;
+
+ pixf.blend_solid_hspan:=@gray8_blend_solid_hspan;
+ pixf.blend_solid_vspan:=@gray8_blend_solid_vspan;
+
+ pixf.copy_color_hspan:=@gray8_copy_color_hspan;
+ pixf.copy_color_vspan:=@gray8_copy_color_vspan;
+
+ pixf.blend_color_hspan:=@gray8_blend_color_hspan;
+ pixf.blend_color_vspan:=@gray8_blend_color_vspan;
+
+ pixf.copy_from :=@gray8_copy_from;
+ pixf.blend_from:=NIL; // not defined in agg_pixfmt_gray.h
+
+ pixf.blend_from_color:=@gray8_blend_from_color;
+ pixf.blend_from_lut :=@gray8_blend_from_lut;
+
+ pixf.for_each_pixel :=@gray_for_each_pixel;
+ pixf.gamma_dir_apply:=@gray_gamma_dir_apply;
+ pixf.gamma_inv_apply:=@gray_gamma_inv_apply;
+
+end;
+
+{ PIXFMT_GRAY8_BGR24G }
+procedure pixfmt_gray8_bgr24g;
+begin
+ pixf.Construct(rb ,3 ,1 );
+
+ pixf.m_pix_width:=3;
+
+ pixf.copy_pixel :=@gray8_copy_pixel;
+ pixf.blend_pixel:=@gray8_blend_pixel;
+
+ pixf.pixel:=@gray8_pixel;
+ pixf.row :=@fmt8_row;
+
+ pixf.copy_hline:=@gray8_copy_hline;
+ pixf.copy_vline:=@gray8_copy_vline;
+
+ pixf.blend_hline:=@gray8_blend_hline;
+ pixf.blend_vline:=@gray8_blend_vline;
+
+ pixf.blend_solid_hspan:=@gray8_blend_solid_hspan;
+ pixf.blend_solid_vspan:=@gray8_blend_solid_vspan;
+
+ pixf.copy_color_hspan:=@gray8_copy_color_hspan;
+ pixf.copy_color_vspan:=@gray8_copy_color_vspan;
+
+ pixf.blend_color_hspan:=@gray8_blend_color_hspan;
+ pixf.blend_color_vspan:=@gray8_blend_color_vspan;
+
+ pixf.copy_from :=@gray8_copy_from;
+ pixf.blend_from:=NIL; // not defined in agg_pixfmt_gray.h
+
+ pixf.blend_from_color:=@gray8_blend_from_color;
+ pixf.blend_from_lut :=@gray8_blend_from_lut;
+
+ pixf.for_each_pixel :=@gray_for_each_pixel;
+ pixf.gamma_dir_apply:=@gray_gamma_dir_apply;
+ pixf.gamma_inv_apply:=@gray_gamma_inv_apply;
+
+end;
+
+{ PIXFMT_GRAY8_BGR24B }
+procedure pixfmt_gray8_bgr24b;
+begin
+ pixf.Construct(rb ,3 ,0 );
+
+ pixf.m_pix_width:=3;
+
+ pixf.copy_pixel :=@gray8_copy_pixel;
+ pixf.blend_pixel:=@gray8_blend_pixel;
+
+ pixf.pixel:=@gray8_pixel;
+ pixf.row :=@fmt8_row;
+
+ pixf.copy_hline:=@gray8_copy_hline;
+ pixf.copy_vline:=@gray8_copy_vline;
+
+ pixf.blend_hline:=@gray8_blend_hline;
+ pixf.blend_vline:=@gray8_blend_vline;
+
+ pixf.blend_solid_hspan:=@gray8_blend_solid_hspan;
+ pixf.blend_solid_vspan:=@gray8_blend_solid_vspan;
+
+ pixf.copy_color_hspan:=@gray8_copy_color_hspan;
+ pixf.copy_color_vspan:=@gray8_copy_color_vspan;
+
+ pixf.blend_color_hspan:=@gray8_blend_color_hspan;
+ pixf.blend_color_vspan:=@gray8_blend_color_vspan;
+
+ pixf.copy_from :=@gray8_copy_from;
+ pixf.blend_from:=NIL; // not defined in agg_pixfmt_gray.h
+
+ pixf.blend_from_color:=@gray8_blend_from_color;
+ pixf.blend_from_lut :=@gray8_blend_from_lut;
+
+ pixf.for_each_pixel :=@gray_for_each_pixel;
+ pixf.gamma_dir_apply:=@gray_gamma_dir_apply;
+ pixf.gamma_inv_apply:=@gray_gamma_inv_apply;
+
+end;
+
+{$I pf_gray8_pre.inc }
+
+{ PIXFMT_GRAY8_PRE }
+procedure pixfmt_gray8_pre;
+begin
+ pixf.Construct(rb ,1 ,0 );
+
+ pixf.m_pix_width:=1;
+
+ pixf.copy_pixel :=@gray8_copy_pixel;
+ pixf.blend_pixel:=@gray8_pre_blend_pixel;
+
+ pixf.pixel:=@gray8_pixel;
+ pixf.row :=@fmt8_row;
+
+ pixf.copy_hline:=@gray8_copy_hline;
+ pixf.copy_vline:=@gray8_copy_vline;
+
+ pixf.blend_hline:=@gray8_pre_blend_hline;
+ pixf.blend_vline:=@gray8_pre_blend_vline;
+
+ pixf.blend_solid_hspan:=@gray8_pre_blend_solid_hspan;
+ pixf.blend_solid_vspan:=@gray8_pre_blend_solid_vspan;
+
+ pixf.copy_color_hspan:=@gray8_copy_color_hspan;
+ pixf.copy_color_vspan:=@gray8_copy_color_vspan;
+
+ pixf.blend_color_hspan:=@gray8_pre_blend_color_hspan;
+ pixf.blend_color_vspan:=@gray8_pre_blend_color_vspan;
+
+ pixf.copy_from :=@gray8_copy_from;
+ pixf.blend_from:=NIL; // not defined in agg_pixfmt_gray.h
+
+ pixf.blend_from_color:=@gray8_pre_blend_from_color;
+ pixf.blend_from_lut :=@gray8_pre_blend_from_lut;
+
+ pixf.for_each_pixel :=@gray_for_each_pixel;
+ pixf.gamma_dir_apply:=@gray_gamma_dir_apply;
+ pixf.gamma_inv_apply:=@gray_gamma_inv_apply;
+
+end;
+
+{ PIXFMT_GRAY8_PRE_BGR24R }
+procedure pixfmt_gray8_pre_bgr24r;
+begin
+ pixf.Construct(rb ,3 ,2 );
+
+ pixf.m_pix_width:=3;
+
+ pixf.copy_pixel :=@gray8_copy_pixel;
+ pixf.blend_pixel:=@gray8_pre_blend_pixel;
+
+ pixf.pixel:=@gray8_pixel;
+ pixf.row :=@fmt8_row;
+
+ pixf.copy_hline:=@gray8_copy_hline;
+ pixf.copy_vline:=@gray8_copy_vline;
+
+ pixf.blend_hline:=@gray8_pre_blend_hline;
+ pixf.blend_vline:=@gray8_pre_blend_vline;
+
+ pixf.blend_solid_hspan:=@gray8_pre_blend_solid_hspan;
+ pixf.blend_solid_vspan:=@gray8_pre_blend_solid_vspan;
+
+ pixf.copy_color_hspan:=@gray8_copy_color_hspan;
+ pixf.copy_color_vspan:=@gray8_copy_color_vspan;
+
+ pixf.blend_color_hspan:=@gray8_pre_blend_color_hspan;
+ pixf.blend_color_vspan:=@gray8_pre_blend_color_vspan;
+
+ pixf.copy_from :=@gray8_copy_from;
+ pixf.blend_from:=NIL; // not defined in agg_pixfmt_gray.h
+
+ pixf.blend_from_color:=@gray8_pre_blend_from_color;
+ pixf.blend_from_lut :=@gray8_pre_blend_from_lut;
+
+ pixf.for_each_pixel :=@gray_for_each_pixel;
+ pixf.gamma_dir_apply:=@gray_gamma_dir_apply;
+ pixf.gamma_inv_apply:=@gray_gamma_inv_apply;
+
+end;
+
+{ PIXFMT_GRAY8_PRE_BGR24G }
+procedure pixfmt_gray8_pre_bgr24g;
+begin
+ pixf.Construct(rb ,3 ,1 );
+
+ pixf.m_pix_width:=3;
+
+ pixf.copy_pixel :=@gray8_copy_pixel;
+ pixf.blend_pixel:=@gray8_pre_blend_pixel;
+
+ pixf.pixel:=@gray8_pixel;
+ pixf.row :=@fmt8_row;
+
+ pixf.copy_hline:=@gray8_copy_hline;
+ pixf.copy_vline:=@gray8_copy_vline;
+
+ pixf.blend_hline:=@gray8_pre_blend_hline;
+ pixf.blend_vline:=@gray8_pre_blend_vline;
+
+ pixf.blend_solid_hspan:=@gray8_pre_blend_solid_hspan;
+ pixf.blend_solid_vspan:=@gray8_pre_blend_solid_vspan;
+
+ pixf.copy_color_hspan:=@gray8_copy_color_hspan;
+ pixf.copy_color_vspan:=@gray8_copy_color_vspan;
+
+ pixf.blend_color_hspan:=@gray8_pre_blend_color_hspan;
+ pixf.blend_color_vspan:=@gray8_pre_blend_color_vspan;
+
+ pixf.copy_from :=@gray8_copy_from;
+ pixf.blend_from:=NIL; // not defined in agg_pixfmt_gray.h
+
+ pixf.blend_from_color:=@gray8_pre_blend_from_color;
+ pixf.blend_from_lut :=@gray8_pre_blend_from_lut;
+
+ pixf.for_each_pixel :=@gray_for_each_pixel;
+ pixf.gamma_dir_apply:=@gray_gamma_dir_apply;
+ pixf.gamma_inv_apply:=@gray_gamma_inv_apply;
+
+end;
+
+{ PIXFMT_GRAY8_PRE_BGR24B }
+procedure pixfmt_gray8_pre_bgr24b;
+begin
+ pixf.Construct(rb ,3 ,0 );
+
+ pixf.m_pix_width:=3;
+
+ pixf.copy_pixel :=@gray8_copy_pixel;
+ pixf.blend_pixel:=@gray8_pre_blend_pixel;
+
+ pixf.pixel:=@gray8_pixel;
+ pixf.row :=@fmt8_row;
+
+ pixf.copy_hline:=@gray8_copy_hline;
+ pixf.copy_vline:=@gray8_copy_vline;
+
+ pixf.blend_hline:=@gray8_pre_blend_hline;
+ pixf.blend_vline:=@gray8_pre_blend_vline;
+
+ pixf.blend_solid_hspan:=@gray8_pre_blend_solid_hspan;
+ pixf.blend_solid_vspan:=@gray8_pre_blend_solid_vspan;
+
+ pixf.copy_color_hspan:=@gray8_copy_color_hspan;
+ pixf.copy_color_vspan:=@gray8_copy_color_vspan;
+
+ pixf.blend_color_hspan:=@gray8_pre_blend_color_hspan;
+ pixf.blend_color_vspan:=@gray8_pre_blend_color_vspan;
+
+ pixf.copy_from :=@gray8_copy_from;
+ pixf.blend_from:=NIL; // not defined in agg_pixfmt_gray.h
+
+ pixf.blend_from_color:=@gray8_pre_blend_from_color;
+ pixf.blend_from_lut :=@gray8_pre_blend_from_lut;
+
+ pixf.for_each_pixel :=@gray_for_each_pixel;
+ pixf.gamma_dir_apply:=@gray_gamma_dir_apply;
+ pixf.gamma_inv_apply:=@gray_gamma_inv_apply;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_pixfmt_rgb.pas b/src/corelib/render/software/agg_pixfmt_rgb.pas
new file mode 100644
index 00000000..b2384142
--- /dev/null
+++ b/src/corelib/render/software/agg_pixfmt_rgb.pas
@@ -0,0 +1,397 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//----------------------------------------------------------------------------
+//
+// Adaptation for high precision colors has been sponsored by
+// Liberty Technology Systems, Inc., visit http://lib-sys.com
+//
+// Liberty Technology Systems, Inc. is the provider of
+// PostScript and PDF technology for software developers.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 18.03.2006-Milano: pf_xxx.inc completed
+// 13.01.2006-Milano: Unit port establishment
+//
+{ agg_pixfmt_rgb.pas }
+unit
+ agg_pixfmt_rgb ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+{$Q- }
+{$R- }
+uses
+ agg_basics ,
+ agg_pixfmt ,
+ agg_color ,
+ agg_rendering_buffer ;
+
+{ GLOBAL PROCEDURES }
+ procedure pixfmt_bgr24(var pixf : pixel_formats; rb : rendering_buffer_ptr );
+ procedure pixfmt_rgb24(var pixf : pixel_formats; rb : rendering_buffer_ptr );
+
+ procedure pixfmt_bgr24_pre(var pixf : pixel_formats; rb : rendering_buffer_ptr );
+ procedure pixfmt_rgb24_pre(var pixf : pixel_formats; rb : rendering_buffer_ptr );
+
+ procedure pixfmt_bgr24_gamma(var pixf : pixel_formats; rb : rendering_buffer_ptr; g : gamma_ptr );
+ procedure pixfmt_rgb24_gamma(var pixf : pixel_formats; rb : rendering_buffer_ptr; g : gamma_ptr );
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ fmt24_row }
+function fmt24_row(this : pixel_formats_ptr; x ,y : int ) : row_data_type;
+begin
+ result.Construct(
+ x ,this._width - 1 ,
+ int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * 3 * sizeof(int8u ) ) );
+
+end;
+
+{ fmt24_copy_from }
+procedure fmt24_copy_from(this : pixel_formats_ptr; from : rendering_buffer_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned );
+begin
+ move(
+ int8u_ptr(ptrcomp(from.row(ysrc ) ) + xsrc * 3 * sizeof(int8u ) )^ ,
+ int8u_ptr(ptrcomp(this.m_rbuf.row(ydst ) ) + xdst * 3 * sizeof(int8u ) )^ ,
+ sizeof(int8u ) * 3 * len );
+
+end;
+
+{ order24_gamma_dir_apply }
+procedure order24_gamma_dir_apply(this : pixel_formats; p : int8u_ptr );
+begin
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=int8u(this.m_apply.dir(int8u_ptr(ptrcomp(p ) + this.m_order.R )^ ) );
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=int8u(this.m_apply.dir(int8u_ptr(ptrcomp(p ) + this.m_order.G )^ ) );
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=int8u(this.m_apply.dir(int8u_ptr(ptrcomp(p ) + this.m_order.B )^ ) );
+
+end;
+
+{ order24_gamma_inv_apply }
+procedure order24_gamma_inv_apply(this : pixel_formats; p : int8u_ptr );
+begin
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=int8u(this.m_apply.inv(int8u_ptr(ptrcomp(p ) + this.m_order.R )^ ) );
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=int8u(this.m_apply.inv(int8u_ptr(ptrcomp(p ) + this.m_order.G )^ ) );
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=int8u(this.m_apply.inv(int8u_ptr(ptrcomp(p ) + this.m_order.B )^ ) );
+
+end;
+
+{ order24_for_each_pixel }
+procedure order24_for_each_pixel(this : pixel_formats_ptr; f : func_apply_gamma );
+var
+ y ,len : unsigned;
+
+ p : int8u_ptr;
+
+begin
+ y:=0;
+
+ while y < this._height do
+ begin
+ len:=this._width;
+
+ p:=this.m_rbuf.row(y );
+
+ repeat
+ f(this ,p );
+
+ inc(ptrcomp(p ) ,3 );
+ dec(len );
+
+ until len = 0;
+
+ inc(y );
+
+ end;
+
+end;
+
+{$I pf_bgr24.inc }
+
+{ PIXFMT_BGR24 }
+procedure pixfmt_bgr24;
+begin
+ pixf.Construct(rb );
+
+ pixf.m_order:=bgr_order;
+
+ pixf.m_pix_width:=3;
+
+ pixf.copy_pixel :=@bgr24_copy_pixel;
+ pixf.blend_pixel:=@bgr24_blend_pixel;
+
+ pixf.pixel:=@bgr24_pixel;
+ pixf.row :=@fmt24_row;
+
+ pixf.copy_hline:=@bgr24_copy_hline;
+ pixf.copy_vline:=@bgr24_copy_vline;
+
+ pixf.blend_hline:=@bgr24_blend_hline;
+ pixf.blend_vline:=@bgr24_blend_vline;
+
+ pixf.blend_solid_hspan:=@bgr24_blend_solid_hspan;
+ pixf.blend_solid_vspan:=@bgr24_blend_solid_vspan;
+
+ pixf.copy_color_hspan:=@bgr24_copy_color_hspan;
+ pixf.copy_color_vspan:=@bgr24_copy_color_vspan;
+
+ pixf.blend_color_hspan:=@bgr24_blend_color_hspan;
+ pixf.blend_color_vspan:=@bgr24_blend_color_vspan;
+
+ pixf.copy_from :=@fmt24_copy_from;
+ pixf.blend_from:=@bgr24_blend_from;
+
+ pixf.blend_from_color:=@bgr24_blend_from_color;
+ pixf.blend_from_lut :=@bgr24_blend_from_lut;
+
+ pixf.for_each_pixel :=@order24_for_each_pixel;
+ pixf.gamma_dir_apply:=@order24_gamma_dir_apply;
+ pixf.gamma_inv_apply:=@order24_gamma_inv_apply;
+
+end;
+
+{$I pf_rgb24.inc }
+
+{ PIXFMT_RGB24 }
+procedure pixfmt_rgb24;
+begin
+ pixf.Construct(rb );
+
+ pixf.m_order:=rgb_order;
+
+ pixf.m_pix_width:=3;
+
+ pixf.copy_pixel :=@rgb24_copy_pixel;
+ pixf.blend_pixel:=@rgb24_blend_pixel;
+
+ pixf.pixel:=@rgb24_pixel;
+ pixf.row :=@fmt24_row;
+
+ pixf.copy_hline:=@rgb24_copy_hline;
+ pixf.copy_vline:=@rgb24_copy_vline;
+
+ pixf.blend_hline:=@rgb24_blend_hline;
+ pixf.blend_vline:=@rgb24_blend_vline;
+
+ pixf.blend_solid_hspan:=@rgb24_blend_solid_hspan;
+ pixf.blend_solid_vspan:=@rgb24_blend_solid_vspan;
+
+ pixf.copy_color_hspan:=@rgb24_copy_color_hspan;
+ pixf.copy_color_vspan:=@rgb24_copy_color_vspan;
+
+ pixf.blend_color_hspan:=@rgb24_blend_color_hspan;
+ pixf.blend_color_vspan:=@rgb24_blend_color_vspan;
+
+ pixf.copy_from :=@fmt24_copy_from;
+ pixf.blend_from:=@rgb24_blend_from;
+
+ pixf.blend_from_color:=@rgb24_blend_from_color;
+ pixf.blend_from_lut :=@rgb24_blend_from_lut;
+
+ pixf.for_each_pixel :=@order24_for_each_pixel;
+ pixf.gamma_dir_apply:=@order24_gamma_dir_apply;
+ pixf.gamma_inv_apply:=@order24_gamma_inv_apply;
+
+end;
+
+{$I pf_bgr24_pre.inc }
+
+{ PIXFMT_BGR24_PRE }
+procedure pixfmt_bgr24_pre;
+begin
+ pixf.Construct(rb );
+
+ pixf.m_order:=bgr_order;
+
+ pixf.m_pix_width:=3;
+
+ pixf.copy_pixel :=@bgr24_copy_pixel;
+ pixf.blend_pixel:=@bgr24_pre_blend_pixel;
+
+ pixf.pixel:=@bgr24_pixel;
+ pixf.row :=@fmt24_row;
+
+ pixf.copy_hline:=@bgr24_copy_hline;
+ pixf.copy_vline:=@bgr24_copy_vline;
+
+ pixf.blend_hline:=@bgr24_pre_blend_hline;
+ pixf.blend_vline:=@bgr24_pre_blend_vline;
+
+ pixf.blend_solid_hspan:=@bgr24_pre_blend_solid_hspan;
+ pixf.blend_solid_vspan:=@bgr24_pre_blend_solid_vspan;
+
+ pixf.copy_color_hspan:=@bgr24_copy_color_hspan;
+ pixf.copy_color_vspan:=@bgr24_copy_color_vspan;
+
+ pixf.blend_color_hspan:=@bgr24_pre_blend_color_hspan;
+ pixf.blend_color_vspan:=@bgr24_pre_blend_color_vspan;
+
+ pixf.copy_from :=@fmt24_copy_from;
+ pixf.blend_from:=@bgr24_pre_blend_from;
+
+ pixf.blend_from_color:=@bgr24_pre_blend_from_color;
+ pixf.blend_from_lut :=@bgr24_pre_blend_from_lut;
+
+ pixf.for_each_pixel :=@order24_for_each_pixel;
+ pixf.gamma_dir_apply:=@order24_gamma_dir_apply;
+ pixf.gamma_inv_apply:=@order24_gamma_inv_apply;
+
+end;
+
+{$I pf_rgb24_pre.inc }
+
+{ PIXFMT_RGB24_PRE }
+procedure pixfmt_rgb24_pre;
+begin
+ pixf.Construct(rb );
+
+ pixf.m_order:=rgb_order;
+
+ pixf.m_pix_width:=3;
+
+ pixf.copy_pixel :=@rgb24_copy_pixel;
+ pixf.blend_pixel:=@rgb24_pre_blend_pixel;
+
+ pixf.pixel:=@rgb24_pixel;
+ pixf.row :=@fmt24_row;
+
+ pixf.copy_hline:=@rgb24_copy_hline;
+ pixf.copy_vline:=@rgb24_copy_vline;
+
+ pixf.blend_hline:=@rgb24_pre_blend_hline;
+ pixf.blend_vline:=@rgb24_pre_blend_vline;
+
+ pixf.blend_solid_hspan:=@rgb24_pre_blend_solid_hspan;
+ pixf.blend_solid_vspan:=@rgb24_pre_blend_solid_vspan;
+
+ pixf.copy_color_hspan:=@rgb24_copy_color_hspan;
+ pixf.copy_color_vspan:=@rgb24_copy_color_vspan;
+
+ pixf.blend_color_hspan:=@rgb24_pre_blend_color_hspan;
+ pixf.blend_color_vspan:=@rgb24_pre_blend_color_vspan;
+
+ pixf.copy_from :=@fmt24_copy_from;
+ pixf.blend_from:=@rgb24_pre_blend_from;
+
+ pixf.blend_from_color:=@rgb24_pre_blend_from_color;
+ pixf.blend_from_lut :=@rgb24_pre_blend_from_lut;
+
+ pixf.for_each_pixel :=@order24_for_each_pixel;
+ pixf.gamma_dir_apply:=@order24_gamma_dir_apply;
+ pixf.gamma_inv_apply:=@order24_gamma_inv_apply;
+
+end;
+
+{$I pf_bgr24_gamma.inc }
+
+{ PIXFMT_BGR24_GAMMA }
+procedure pixfmt_bgr24_gamma;
+begin
+ pixf.Construct(rb );
+
+ pixf.m_order:=bgr_order;
+ pixf.m_gamma:=g;
+
+ pixf.m_pix_width:=3;
+
+ pixf.copy_pixel :=@bgr24_copy_pixel;
+ pixf.blend_pixel:=@bgr24_gamma_blend_pixel;
+
+ pixf.pixel:=@bgr24_pixel;
+ pixf.row :=@fmt24_row;
+
+ pixf.copy_hline:=@bgr24_copy_hline;
+ pixf.copy_vline:=@bgr24_copy_vline;
+
+ pixf.blend_hline:=@bgr24_gamma_blend_hline;
+ pixf.blend_vline:=@bgr24_gamma_blend_vline;
+
+ pixf.blend_solid_hspan:=@bgr24_gamma_blend_solid_hspan;
+ pixf.blend_solid_vspan:=@bgr24_gamma_blend_solid_vspan;
+
+ pixf.copy_color_hspan:=@bgr24_copy_color_hspan;
+ pixf.copy_color_vspan:=@bgr24_copy_color_vspan;
+
+ pixf.blend_color_hspan:=@bgr24_gamma_blend_color_hspan;
+ pixf.blend_color_vspan:=@bgr24_gamma_blend_color_vspan;
+
+ pixf.copy_from :=@fmt24_copy_from;
+ pixf.blend_from:=@bgr24_gamma_blend_from;
+
+ pixf.blend_from_color:=@bgr24_gamma_blend_from_color;
+ pixf.blend_from_lut :=@bgr24_gamma_blend_from_lut;
+
+ pixf.for_each_pixel :=@order24_for_each_pixel;
+ pixf.gamma_dir_apply:=@order24_gamma_dir_apply;
+ pixf.gamma_inv_apply:=@order24_gamma_inv_apply;
+
+end;
+
+{$I pf_rgb24_gamma.inc }
+
+{ PIXFMT_RGB24_GAMMA }
+procedure pixfmt_rgb24_gamma;
+begin
+ pixf.Construct(rb );
+
+ pixf.m_order:=rgb_order;
+ pixf.m_gamma:=g;
+
+ pixf.m_pix_width:=3;
+
+ pixf.copy_pixel :=@rgb24_copy_pixel;
+ pixf.blend_pixel:=@rgb24_gamma_blend_pixel;
+
+ pixf.pixel:=@rgb24_pixel;
+ pixf.row :=@fmt24_row;
+
+ pixf.copy_hline:=@rgb24_copy_hline;
+ pixf.copy_vline:=@rgb24_copy_vline;
+
+ pixf.blend_hline:=@rgb24_gamma_blend_hline;
+ pixf.blend_vline:=@rgb24_gamma_blend_vline;
+
+ pixf.blend_solid_hspan:=@rgb24_gamma_blend_solid_hspan;
+ pixf.blend_solid_vspan:=@rgb24_gamma_blend_solid_vspan;
+
+ pixf.copy_color_hspan:=@rgb24_copy_color_hspan;
+ pixf.copy_color_vspan:=@rgb24_copy_color_vspan;
+
+ pixf.blend_color_hspan:=@rgb24_gamma_blend_color_hspan;
+ pixf.blend_color_vspan:=@rgb24_gamma_blend_color_vspan;
+
+ pixf.copy_from :=@fmt24_copy_from;
+ pixf.blend_from:=@rgb24_gamma_blend_from;
+
+ pixf.blend_from_color:=@rgb24_gamma_blend_from_color;
+ pixf.blend_from_lut :=@rgb24_gamma_blend_from_lut;
+
+ pixf.for_each_pixel :=@order24_for_each_pixel;
+ pixf.gamma_dir_apply:=@order24_gamma_dir_apply;
+ pixf.gamma_inv_apply:=@order24_gamma_inv_apply;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_pixfmt_rgb_packed.pas b/src/corelib/render/software/agg_pixfmt_rgb_packed.pas
new file mode 100644
index 00000000..e059f7a8
--- /dev/null
+++ b/src/corelib/render/software/agg_pixfmt_rgb_packed.pas
@@ -0,0 +1,329 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//----------------------------------------------------------------------------
+//
+// Adaptation for high precision colors has been sponsored by
+// Liberty Technology Systems, Inc., visit http://lib-sys.com
+//
+// Liberty Technology Systems, Inc. is the provider of
+// PostScript and PDF technology for software developers.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 18.03.2006-Milano: pf_xxx.inc completed
+// 13.01.2006-Milano: Unit port establishment
+//
+{ agg_pixfmt_rgb_packed.pas }
+unit
+ agg_pixfmt_rgb_packed ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+{$Q- }
+{$R- }
+uses
+ agg_basics ,
+ agg_pixfmt ,
+ agg_color ,
+ agg_rendering_buffer ;
+
+{ GLOBAL PROCEDURES }
+ procedure pixfmt_rgb555(var pixf : pixel_formats; rb : rendering_buffer_ptr );
+ procedure pixfmt_rgb565(var pixf : pixel_formats; rb : rendering_buffer_ptr );
+
+ procedure pixfmt_rgb555_pre(var pixf : pixel_formats; rb : rendering_buffer_ptr );
+ procedure pixfmt_rgb565_pre(var pixf : pixel_formats; rb : rendering_buffer_ptr );
+
+ procedure pixfmt_rgb555_gamma(var pixf : pixel_formats; rb : rendering_buffer_ptr; g : gamma_ptr );
+ procedure pixfmt_rgb565_gamma(var pixf : pixel_formats; rb : rendering_buffer_ptr; g : gamma_ptr );
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ fmt5x5_row }
+function fmt5x5_row(this : pixel_formats_ptr; x ,y : int ) : row_data_type;
+begin
+ result.Construct(
+ x ,this._width - 1 ,
+ int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) ) );
+
+end;
+
+{$I pf_rgb555.inc }
+
+{ PIXFMT_RGB555 }
+procedure pixfmt_rgb555;
+begin
+ pixf.Construct(rb );
+
+ pixf.m_pix_width:=2;
+
+ pixf.copy_pixel :=@rgb555_copy_pixel;
+ pixf.blend_pixel:=@rgb555_blend_pixel;
+
+ pixf.pixel:=@rgb555_pixel;
+ pixf.row :=@fmt5x5_row;
+
+ pixf.copy_hline:=@rgb555_copy_hline;
+ pixf.copy_vline:=@rgb555_copy_vline;
+
+ pixf.blend_hline:=@rgb555_blend_hline;
+ pixf.blend_vline:=@rgb555_blend_vline;
+
+ pixf.blend_solid_hspan:=@rgb555_blend_solid_hspan;
+ pixf.blend_solid_vspan:=@rgb555_blend_solid_vspan;
+
+ pixf.copy_color_hspan:=@rgb555_copy_color_hspan;
+ pixf.copy_color_vspan:=@rgb555_copy_color_vspan;
+
+ pixf.blend_color_hspan:=@rgb555_blend_color_hspan;
+ pixf.blend_color_vspan:=@rgb555_blend_color_vspan;
+
+ pixf.copy_from :=@rgb555_copy_from;
+ pixf.blend_from:=@rgb555_blend_from;
+
+ pixf.blend_from_color:=@rgb555_blend_from_color;
+ pixf.blend_from_lut :=@rgb555_blend_from_lut;
+
+ pixf.for_each_pixel :=NIL; // not implemented in agg_pixfmt_rgb_packed.h
+ pixf.gamma_dir_apply:=NIL;
+ pixf.gamma_inv_apply:=NIL;
+
+end;
+
+{$I pf_rgb565.inc }
+
+{ PIXFMT_RGB565 }
+procedure pixfmt_rgb565;
+begin
+ pixf.Construct(rb );
+
+ pixf.m_pix_width:=2;
+
+ pixf.copy_pixel :=@rgb565_copy_pixel;
+ pixf.blend_pixel:=@rgb565_blend_pixel;
+
+ pixf.pixel:=@rgb565_pixel;
+ pixf.row :=@fmt5x5_row;
+
+ pixf.copy_hline:=@rgb565_copy_hline;
+ pixf.copy_vline:=@rgb565_copy_vline;
+
+ pixf.blend_hline:=@rgb565_blend_hline;
+ pixf.blend_vline:=@rgb565_blend_vline;
+
+ pixf.blend_solid_hspan:=@rgb565_blend_solid_hspan;
+ pixf.blend_solid_vspan:=@rgb565_blend_solid_vspan;
+
+ pixf.copy_color_hspan:=@rgb565_copy_color_hspan;
+ pixf.copy_color_vspan:=@rgb565_copy_color_vspan;
+
+ pixf.blend_color_hspan:=@rgb565_blend_color_hspan;
+ pixf.blend_color_vspan:=@rgb565_blend_color_vspan;
+
+ pixf.copy_from :=@rgb565_copy_from;
+ pixf.blend_from:=@rgb565_blend_from;
+
+ pixf.blend_from_color:=@rgb565_blend_from_color;
+ pixf.blend_from_lut :=@rgb565_blend_from_lut;
+
+ pixf.for_each_pixel :=NIL; // not implemented in agg_pixfmt_rgb_packed.h
+ pixf.gamma_dir_apply:=NIL;
+ pixf.gamma_inv_apply:=NIL;
+
+end;
+
+{$I pf_rgb555_pre.inc }
+
+{ PIXFMT_RGB555_PRE }
+procedure pixfmt_rgb555_pre;
+begin
+ pixf.Construct(rb );
+
+ pixf.m_pix_width:=2;
+
+ pixf.copy_pixel :=@rgb555_pre_copy_pixel;
+ pixf.blend_pixel:=@rgb555_pre_blend_pixel;
+
+ pixf.pixel:=@rgb555_pre_pixel;
+ pixf.row :=@fmt5x5_row;
+
+ pixf.copy_hline:=@rgb555_pre_copy_hline;
+ pixf.copy_vline:=@rgb555_pre_copy_vline;
+
+ pixf.blend_hline:=@rgb555_pre_blend_hline;
+ pixf.blend_vline:=@rgb555_pre_blend_vline;
+
+ pixf.blend_solid_hspan:=@rgb555_pre_blend_solid_hspan;
+ pixf.blend_solid_vspan:=@rgb555_pre_blend_solid_vspan;
+
+ pixf.copy_color_hspan:=@rgb555_pre_copy_color_hspan;
+ pixf.copy_color_vspan:=@rgb555_pre_copy_color_vspan;
+
+ pixf.blend_color_hspan:=@rgb555_pre_blend_color_hspan;
+ pixf.blend_color_vspan:=@rgb555_pre_blend_color_vspan;
+
+ pixf.copy_from :=@rgb555_pre_copy_from;
+ pixf.blend_from:=@rgb555_pre_blend_from;
+
+ pixf.blend_from_color:=@rgb555_pre_blend_from_color;
+ pixf.blend_from_lut :=@rgb555_pre_blend_from_lut;
+
+ pixf.for_each_pixel :=NIL; // not implemented in agg_pixfmt_rgb_packed.h
+ pixf.gamma_dir_apply:=NIL;
+ pixf.gamma_inv_apply:=NIL;
+
+end;
+
+{$I pf_rgb565_pre.inc }
+
+{ PIXFMT_RGB565 }
+procedure pixfmt_rgb565_pre;
+begin
+ pixf.Construct(rb );
+
+ pixf.m_pix_width:=2;
+
+ pixf.copy_pixel :=@rgb565_pre_copy_pixel;
+ pixf.blend_pixel:=@rgb565_pre_blend_pixel;
+
+ pixf.pixel:=@rgb565_pre_pixel;
+ pixf.row :=@fmt5x5_row;
+
+ pixf.copy_hline:=@rgb565_pre_copy_hline;
+ pixf.copy_vline:=@rgb565_pre_copy_vline;
+
+ pixf.blend_hline:=@rgb565_pre_blend_hline;
+ pixf.blend_vline:=@rgb565_pre_blend_vline;
+
+ pixf.blend_solid_hspan:=@rgb565_pre_blend_solid_hspan;
+ pixf.blend_solid_vspan:=@rgb565_pre_blend_solid_vspan;
+
+ pixf.copy_color_hspan:=@rgb565_pre_copy_color_hspan;
+ pixf.copy_color_vspan:=@rgb565_pre_copy_color_vspan;
+
+ pixf.blend_color_hspan:=@rgb565_pre_blend_color_hspan;
+ pixf.blend_color_vspan:=@rgb565_pre_blend_color_vspan;
+
+ pixf.copy_from :=@rgb565_pre_copy_from;
+ pixf.blend_from:=@rgb565_pre_blend_from;
+
+ pixf.blend_from_color:=@rgb565_pre_blend_from_color;
+ pixf.blend_from_lut :=@rgb565_pre_blend_from_lut;
+
+ pixf.for_each_pixel :=NIL; // not implemented in agg_pixfmt_rgb_packed.h
+ pixf.gamma_dir_apply:=NIL;
+ pixf.gamma_inv_apply:=NIL;
+
+end;
+
+{$I pf_rgb555_gamma.inc }
+
+{ PIXFMT_RGB555_GAMMA }
+procedure pixfmt_rgb555_gamma;
+begin
+ pixf.Construct(rb );
+
+ pixf.m_pix_width:=2;
+
+ pixf.m_gamma:=g;
+
+ pixf.copy_pixel :=@rgb555_gamma_copy_pixel;
+ pixf.blend_pixel:=@rgb555_gamma_blend_pixel;
+
+ pixf.pixel:=@rgb555_gamma_pixel;
+ pixf.row :=@fmt5x5_row;
+
+ pixf.copy_hline:=@rgb555_gamma_copy_hline;
+ pixf.copy_vline:=@rgb555_gamma_copy_vline;
+
+ pixf.blend_hline:=@rgb555_gamma_blend_hline;
+ pixf.blend_vline:=@rgb555_gamma_blend_vline;
+
+ pixf.blend_solid_hspan:=@rgb555_gamma_blend_solid_hspan;
+ pixf.blend_solid_vspan:=@rgb555_gamma_blend_solid_vspan;
+
+ pixf.copy_color_hspan:=@rgb555_gamma_copy_color_hspan;
+ pixf.copy_color_vspan:=@rgb555_gamma_copy_color_vspan;
+
+ pixf.blend_color_hspan:=@rgb555_gamma_blend_color_hspan;
+ pixf.blend_color_vspan:=@rgb555_gamma_blend_color_vspan;
+
+ pixf.copy_from :=@rgb555_gamma_copy_from;
+ pixf.blend_from:=@rgb555_gamma_blend_from;
+
+ pixf.blend_from_color:=@rgb555_gamma_blend_from_color;
+ pixf.blend_from_lut :=@rgb555_gamma_blend_from_lut;
+
+ pixf.for_each_pixel :=NIL; // not implemented in agg_pixfmt_rgb_packed.h
+ pixf.gamma_dir_apply:=NIL;
+ pixf.gamma_inv_apply:=NIL;
+
+end;
+
+{$I pf_rgb565_gamma.inc }
+
+{ PIXFMT_RGB565 }
+procedure pixfmt_rgb565_gamma;
+begin
+ pixf.Construct(rb );
+
+ pixf.m_pix_width:=2;
+
+ pixf.m_gamma:=g;
+
+ pixf.copy_pixel :=@rgb565_gamma_copy_pixel;
+ pixf.blend_pixel:=@rgb565_gamma_blend_pixel;
+
+ pixf.pixel:=@rgb565_gamma_pixel;
+ pixf.row :=@fmt5x5_row;
+
+ pixf.copy_hline:=@rgb565_gamma_copy_hline;
+ pixf.copy_vline:=@rgb565_gamma_copy_vline;
+
+ pixf.blend_hline:=@rgb565_gamma_blend_hline;
+ pixf.blend_vline:=@rgb565_gamma_blend_vline;
+
+ pixf.blend_solid_hspan:=@rgb565_gamma_blend_solid_hspan;
+ pixf.blend_solid_vspan:=@rgb565_gamma_blend_solid_vspan;
+
+ pixf.copy_color_hspan:=@rgb565_gamma_copy_color_hspan;
+ pixf.copy_color_vspan:=@rgb565_gamma_copy_color_vspan;
+
+ pixf.blend_color_hspan:=@rgb565_gamma_blend_color_hspan;
+ pixf.blend_color_vspan:=@rgb565_gamma_blend_color_vspan;
+
+ pixf.copy_from :=@rgb565_gamma_copy_from;
+ pixf.blend_from:=@rgb565_gamma_blend_from;
+
+ pixf.blend_from_color:=@rgb565_gamma_blend_from_color;
+ pixf.blend_from_lut :=@rgb565_gamma_blend_from_lut;
+
+ pixf.for_each_pixel :=NIL; // not implemented in agg_pixfmt_rgb_packed.h
+ pixf.gamma_dir_apply:=NIL;
+ pixf.gamma_inv_apply:=NIL;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_pixfmt_rgba.pas b/src/corelib/render/software/agg_pixfmt_rgba.pas
new file mode 100644
index 00000000..2d567024
--- /dev/null
+++ b/src/corelib/render/software/agg_pixfmt_rgba.pas
@@ -0,0 +1,1771 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//----------------------------------------------------------------------------
+//
+// Adaptation for high precision colors has been sponsored by
+// Liberty Technology Systems, Inc., visit http://lib-sys.com
+//
+// Liberty Technology Systems, Inc. is the provider of
+// PostScript and PDF technology for software developers.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 12.10.2007-Milano: comp_op_rgba_invert & comp_op_rgba_invert_rgb
+// 08.10.2007-Milano: pixfmt_alpha_blend_rgba
+// 13.09.2007-Milano: comp_op_adaptor_clip_to_dst_rgba_pre
+// 23.06.2006-Milano: ptrcomp adjustments
+// 18.03.2006-Milano: pf_xxx.inc completed
+// 13.01.2006-Milano: rgba ,argb & abgr stuff
+// 16.11.2005-Milano: Unit port establishment
+//
+{ agg_pixfmt_rgba.pas }
+unit
+ agg_pixfmt_rgba ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+{$Q- }
+{$R- }
+uses
+ agg_basics ,
+ agg_pixfmt ,
+ agg_color ,
+ agg_rendering_buffer ;
+
+{ GLOBAL PROCEDURES }
+ procedure pixfmt_bgra32(var pixf : pixel_formats; rb : rendering_buffer_ptr );
+ procedure pixfmt_rgba32(var pixf : pixel_formats; rb : rendering_buffer_ptr );
+ procedure pixfmt_argb32(var pixf : pixel_formats; rb : rendering_buffer_ptr );
+ procedure pixfmt_abgr32(var pixf : pixel_formats; rb : rendering_buffer_ptr );
+
+ procedure pixfmt_bgra32_pre(var pixf : pixel_formats; rb : rendering_buffer_ptr );
+ procedure pixfmt_rgba32_pre(var pixf : pixel_formats; rb : rendering_buffer_ptr );
+ procedure pixfmt_argb32_pre(var pixf : pixel_formats; rb : rendering_buffer_ptr );
+ procedure pixfmt_abgr32_pre(var pixf : pixel_formats; rb : rendering_buffer_ptr );
+
+ procedure comp_op_adaptor_rgba (this : pixel_formats_ptr; op : unsigned; p : int8u_ptr; cr ,cg ,cb ,ca ,cover : unsigned );
+ procedure comp_op_adaptor_clip_to_dst_rgba_pre(this : pixel_formats_ptr; op : unsigned; p : int8u_ptr; cr ,cg ,cb ,ca ,cover : unsigned );
+
+ procedure pixfmt_alpha_blend_rgba (var pixf : pixel_formats; rb : rendering_buffer_ptr; order : order_type );
+ procedure pixfmt_custom_blend_rgba(var pixf : pixel_formats; rb : rendering_buffer_ptr; bl : func_blender; order : order_type );
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ fmt32_row }
+function fmt32_row(this : pixel_formats_ptr; x ,y : int ) : row_data_type;
+begin
+ result.Construct(
+ x ,this._width - 1 ,
+ int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * 4 * sizeof(int8u ) ) );
+
+end;
+
+{ fmt32_copy_from }
+procedure fmt32_copy_from(this : pixel_formats_ptr; from : rendering_buffer_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned );
+begin
+ move(
+ unsigned_ptr(ptrcomp(from.row(ysrc ) ) + xsrc * 4 )^ ,
+ unsigned_ptr(ptrcomp(this.m_rbuf.row(ydst ) ) + xdst * 4 )^ ,
+ len * 4 );
+
+end;
+
+{ order32_for_each_pixel }
+procedure order32_for_each_pixel(this : pixel_formats_ptr; f : func_apply_gamma );
+var
+ y ,len : unsigned;
+
+ p : int8u_ptr;
+
+begin
+ y:=0;
+
+ while y < this._height do
+ begin
+ len:=this._width;
+
+ p:=this.m_rbuf.row(y );
+
+ repeat
+ f(this ,p );
+
+ inc(ptrcomp(p ) ,4 );
+ dec(len );
+
+ until len = 0;
+
+ inc(y );
+
+ end;
+
+end;
+
+{ order32_gamma_dir_apply }
+procedure order32_gamma_dir_apply(this : pixel_formats_ptr; p : int8u_ptr );
+begin
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=int8u(this.m_apply.dir(int8u_ptr(ptrcomp(p ) + this.m_order.R )^ ) );
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=int8u(this.m_apply.dir(int8u_ptr(ptrcomp(p ) + this.m_order.G )^ ) );
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=int8u(this.m_apply.dir(int8u_ptr(ptrcomp(p ) + this.m_order.B )^ ) );
+
+end;
+
+{ order32_gamma_inv_apply }
+procedure order32_gamma_inv_apply(this : pixel_formats_ptr; p : int8u_ptr );
+begin
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=int8u(this.m_apply.inv(int8u_ptr(ptrcomp(p ) + this.m_order.R )^ ) );
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=int8u(this.m_apply.inv(int8u_ptr(ptrcomp(p ) + this.m_order.G )^ ) );
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=int8u(this.m_apply.inv(int8u_ptr(ptrcomp(p ) + this.m_order.B )^ ) );
+
+end;
+
+{ order32_pixel_premultiply }
+procedure order32_pixel_premultiply(this : pixel_formats_ptr; p : int8u_ptr );
+var
+ a : unsigned;
+
+begin
+ a:=int8u_ptr(ptrcomp(p ) + this.m_order.A )^;
+
+ if a = 0 then
+ begin
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=0;
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=0;
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=0;
+
+ end
+ else
+ begin
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=
+ int8u((int8u_ptr(ptrcomp(p ) + this.m_order.R )^ * a + base_mask ) shr base_shift );
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=
+ int8u((int8u_ptr(ptrcomp(p ) + this.m_order.G )^ * a + base_mask ) shr base_shift );
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=
+ int8u((int8u_ptr(ptrcomp(p ) + this.m_order.B )^ * a + base_mask ) shr base_shift );
+
+ end;
+
+end;
+
+{ order32_pixel_demultiply }
+procedure order32_pixel_demultiply(this : pixel_formats_ptr; p : int8u_ptr );
+var
+ r ,g ,b ,a : unsigned;
+
+begin
+ a:=int8u_ptr(ptrcomp(p ) + this.m_order.A )^;
+
+ if a = 0 then
+ begin
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=0;
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=0;
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=0;
+
+ end
+ else
+ begin
+ r:=(int8u_ptr(ptrcomp(p ) + this.m_order.R )^ * base_mask ) div a;
+ g:=(int8u_ptr(ptrcomp(p ) + this.m_order.G )^ * base_mask ) div a;
+ b:=(int8u_ptr(ptrcomp(p ) + this.m_order.B )^ * base_mask ) div a;
+
+ if r > base_mask then
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=base_mask
+ else
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=r;
+
+ if g > base_mask then
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=base_mask
+ else
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=g;
+
+ if b > base_mask then
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=base_mask
+ else
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=b;
+
+ end;
+
+end;
+
+{$I pf_bgra32.inc }
+
+{ PIXFMT_BGRA32 }
+procedure pixfmt_bgra32;
+begin
+ pixf.Construct(rb );
+
+ pixf.m_order:=bgra_order;
+
+ pixf.m_pix_width:=4;
+
+ pixf.copy_pixel :=@bgra32_copy_pixel;
+ pixf.blend_pixel:=@bgra32_blend_pixel;
+
+ pixf.pixel:=@bgra32_pixel;
+ pixf.row :=@fmt32_row;
+
+ pixf.copy_hline:=@bgra32_copy_hline;
+ pixf.copy_vline:=@bgra32_copy_vline;
+
+ pixf.blend_hline:=@bgra32_blend_hline;
+ pixf.blend_vline:=@bgra32_blend_vline;
+
+ pixf.blend_solid_hspan:=@bgra32_blend_solid_hspan;
+ pixf.blend_solid_vspan:=@bgra32_blend_solid_vspan;
+
+ pixf.copy_color_hspan:=@bgra32_copy_color_hspan;
+ pixf.copy_color_vspan:=@bgra32_copy_color_vspan;
+
+ pixf.blend_color_hspan:=@bgra32_blend_color_hspan;
+ pixf.blend_color_vspan:=@bgra32_blend_color_vspan;
+
+ pixf.copy_from :=@fmt32_copy_from;
+ pixf.blend_from:=@bgra32_blend_from;
+
+ pixf.blend_from_color:=@bgra32_blend_from_color;
+ pixf.blend_from_lut :=@bgra32_blend_from_lut;
+
+ pixf.for_each_pixel :=@order32_for_each_pixel;
+ pixf.gamma_dir_apply:=@order32_gamma_dir_apply;
+ pixf.gamma_inv_apply:=@order32_gamma_inv_apply;
+
+ pixf.pixel_premultiply:=@order32_pixel_premultiply;
+ pixf.pixel_demultiply :=@order32_pixel_demultiply;
+
+end;
+
+{$I pf_rgba32.inc }
+
+{ PIXFMT_RGBA32 }
+procedure pixfmt_rgba32;
+begin
+ pixf.Construct(rb );
+
+ pixf.m_order:=rgba_order;
+
+ pixf.m_pix_width:=4;
+
+ pixf.copy_pixel :=@rgba32_copy_pixel;
+ pixf.blend_pixel:=@rgba32_blend_pixel;
+
+ pixf.pixel:=@rgba32_pixel;
+ pixf.row :=@fmt32_row;
+
+ pixf.copy_hline:=@rgba32_copy_hline;
+ pixf.copy_vline:=@rgba32_copy_vline;
+
+ pixf.blend_hline:=@rgba32_blend_hline;
+ pixf.blend_vline:=@rgba32_blend_vline;
+
+ pixf.blend_solid_hspan:=@rgba32_blend_solid_hspan;
+ pixf.blend_solid_vspan:=@rgba32_blend_solid_vspan;
+
+ pixf.copy_color_hspan:=@rgba32_copy_color_hspan;
+ pixf.copy_color_vspan:=@rgba32_copy_color_vspan;
+
+ pixf.blend_color_hspan:=@rgba32_blend_color_hspan;
+ pixf.blend_color_vspan:=@rgba32_blend_color_vspan;
+
+ pixf.copy_from :=@fmt32_copy_from;
+ pixf.blend_from:=@rgba32_blend_from;
+
+ pixf.blend_from_color:=@rgba32_blend_from_color;
+ pixf.blend_from_lut :=@rgba32_blend_from_lut;
+
+ pixf.for_each_pixel :=@order32_for_each_pixel;
+ pixf.gamma_dir_apply:=@order32_gamma_dir_apply;
+ pixf.gamma_inv_apply:=@order32_gamma_inv_apply;
+
+ pixf.pixel_premultiply:=@order32_pixel_premultiply;
+ pixf.pixel_demultiply :=@order32_pixel_demultiply;
+
+end;
+
+{$I pf_argb32.inc }
+
+{ PIXFMT_ARGB32 }
+procedure pixfmt_argb32;
+begin
+ pixf.Construct(rb );
+
+ pixf.m_order:=argb_order;
+
+ pixf.m_pix_width:=4;
+
+ pixf.copy_pixel :=@argb32_copy_pixel;
+ pixf.blend_pixel:=@argb32_blend_pixel;
+
+ pixf.pixel:=@argb32_pixel;
+ pixf.row :=@fmt32_row;
+
+ pixf.copy_hline:=@argb32_copy_hline;
+ pixf.copy_vline:=@argb32_copy_vline;
+
+ pixf.blend_hline:=@argb32_blend_hline;
+ pixf.blend_vline:=@argb32_blend_vline;
+
+ pixf.blend_solid_hspan:=@argb32_blend_solid_hspan;
+ pixf.blend_solid_vspan:=@argb32_blend_solid_vspan;
+
+ pixf.copy_color_hspan:=@argb32_copy_color_hspan;
+ pixf.copy_color_vspan:=@argb32_copy_color_vspan;
+
+ pixf.blend_color_hspan:=@argb32_blend_color_hspan;
+ pixf.blend_color_vspan:=@argb32_blend_color_vspan;
+
+ pixf.copy_from :=@fmt32_copy_from;
+ pixf.blend_from:=@argb32_blend_from;
+
+ pixf.blend_from_color:=@argb32_blend_from_color;
+ pixf.blend_from_lut :=@argb32_blend_from_lut;
+
+ pixf.for_each_pixel :=@order32_for_each_pixel;
+ pixf.gamma_dir_apply:=@order32_gamma_dir_apply;
+ pixf.gamma_inv_apply:=@order32_gamma_inv_apply;
+
+ pixf.pixel_premultiply:=@order32_pixel_premultiply;
+ pixf.pixel_demultiply :=@order32_pixel_demultiply;
+
+end;
+
+{$I pf_abgr32.inc }
+
+{ PIXFMT_ABGR32 }
+procedure pixfmt_abgr32;
+begin
+ pixf.Construct(rb );
+
+ pixf.m_order:=abgr_order;
+
+ pixf.m_pix_width:=4;
+
+ pixf.copy_pixel :=@abgr32_copy_pixel;
+ pixf.blend_pixel:=@abgr32_blend_pixel;
+
+ pixf.pixel:=@abgr32_pixel;
+ pixf.row :=@fmt32_row;
+
+ pixf.copy_hline:=@abgr32_copy_hline;
+ pixf.copy_vline:=@abgr32_copy_vline;
+
+ pixf.blend_hline:=@abgr32_blend_hline;
+ pixf.blend_vline:=@abgr32_blend_vline;
+
+ pixf.blend_solid_hspan:=@abgr32_blend_solid_hspan;
+ pixf.blend_solid_vspan:=@abgr32_blend_solid_vspan;
+
+ pixf.copy_color_hspan:=@abgr32_copy_color_hspan;
+ pixf.copy_color_vspan:=@abgr32_copy_color_vspan;
+
+ pixf.blend_color_hspan:=@abgr32_blend_color_hspan;
+ pixf.blend_color_vspan:=@abgr32_blend_color_vspan;
+
+ pixf.copy_from :=@fmt32_copy_from;
+ pixf.blend_from:=@abgr32_blend_from;
+
+ pixf.blend_from_color:=@abgr32_blend_from_color;
+ pixf.blend_from_lut :=@abgr32_blend_from_lut;
+
+ pixf.for_each_pixel :=@order32_for_each_pixel;
+ pixf.gamma_dir_apply:=@order32_gamma_dir_apply;
+ pixf.gamma_inv_apply:=@order32_gamma_inv_apply;
+
+ pixf.pixel_premultiply:=@order32_pixel_premultiply;
+ pixf.pixel_demultiply :=@order32_pixel_demultiply;
+
+end;
+
+{$I pf_bgra32_pre.inc }
+
+{ PIXFMT_BGRA32_PRE }
+procedure pixfmt_bgra32_pre;
+begin
+ pixf.Construct(rb );
+
+ pixf.m_order:=bgra_order;
+
+ pixf.m_pix_width:=4;
+
+ pixf.copy_pixel :=@bgra32_copy_pixel;
+ pixf.blend_pixel:=@bgra32_pre_blend_pixel;
+
+ pixf.pixel:=@bgra32_pixel;
+ pixf.row :=@fmt32_row;
+
+ pixf.copy_hline:=@bgra32_copy_hline;
+ pixf.copy_vline:=@bgra32_copy_vline;
+
+ pixf.blend_hline:=@bgra32_pre_blend_hline;
+ pixf.blend_vline:=@bgra32_pre_blend_vline;
+
+ pixf.blend_solid_hspan:=@bgra32_pre_blend_solid_hspan;
+ pixf.blend_solid_vspan:=@bgra32_pre_blend_solid_vspan;
+
+ pixf.copy_color_hspan:=bgra32_copy_color_hspan;
+ pixf.copy_color_vspan:=bgra32_copy_color_vspan;
+
+ pixf.blend_color_hspan:=@bgra32_pre_blend_color_hspan;
+ pixf.blend_color_vspan:=@bgra32_pre_blend_color_vspan;
+
+ pixf.copy_from :=@fmt32_copy_from;
+ pixf.blend_from:=@bgra32_pre_blend_from;
+
+ pixf.blend_from_color:=@bgra32_pre_blend_from_color;
+ pixf.blend_from_lut :=@bgra32_pre_blend_from_lut;
+
+ pixf.for_each_pixel :=@order32_for_each_pixel;
+ pixf.gamma_dir_apply:=@order32_gamma_dir_apply;
+ pixf.gamma_inv_apply:=@order32_gamma_inv_apply;
+
+ pixf.pixel_premultiply:=@order32_pixel_premultiply;
+ pixf.pixel_demultiply :=@order32_pixel_demultiply;
+
+end;
+
+{$I pf_rgba32_pre.inc }
+
+{ PIXFMT_RGBA32_PRE }
+procedure pixfmt_rgba32_pre;
+begin
+ pixf.Construct(rb );
+
+ pixf.m_order:=rgba_order;
+
+ pixf.m_pix_width:=4;
+
+ pixf.copy_pixel :=@rgba32_copy_pixel;
+ pixf.blend_pixel:=@rgba32_pre_blend_pixel;
+
+ pixf.pixel:=@rgba32_pixel;
+ pixf.row :=@fmt32_row;
+
+ pixf.copy_hline:=@rgba32_copy_hline;
+ pixf.copy_vline:=@rgba32_copy_vline;
+
+ pixf.blend_hline:=@rgba32_pre_blend_hline;
+ pixf.blend_vline:=@rgba32_pre_blend_vline;
+
+ pixf.blend_solid_hspan:=@rgba32_pre_blend_solid_hspan;
+ pixf.blend_solid_vspan:=@rgba32_pre_blend_solid_vspan;
+
+ pixf.copy_color_hspan:=rgba32_copy_color_hspan;
+ pixf.copy_color_vspan:=rgba32_copy_color_vspan;
+
+ pixf.blend_color_hspan:=@rgba32_pre_blend_color_hspan;
+ pixf.blend_color_vspan:=@rgba32_pre_blend_color_vspan;
+
+ pixf.copy_from :=@fmt32_copy_from;
+ pixf.blend_from:=@rgba32_pre_blend_from;
+
+ pixf.blend_from_color:=@rgba32_pre_blend_from_color;
+ pixf.blend_from_lut :=@rgba32_pre_blend_from_lut;
+
+ pixf.for_each_pixel :=@order32_for_each_pixel;
+ pixf.gamma_dir_apply:=@order32_gamma_dir_apply;
+ pixf.gamma_inv_apply:=@order32_gamma_inv_apply;
+
+ pixf.pixel_premultiply:=@order32_pixel_premultiply;
+ pixf.pixel_demultiply :=@order32_pixel_demultiply;
+
+end;
+
+{$I pf_argb32_pre.inc }
+
+{ PIXFMT_ARGB32_PRE }
+procedure pixfmt_argb32_pre;
+begin
+ pixf.Construct(rb );
+
+ pixf.m_order:=argb_order;
+
+ pixf.m_pix_width:=4;
+
+ pixf.copy_pixel :=@argb32_copy_pixel;
+ pixf.blend_pixel:=@argb32_pre_blend_pixel;
+
+ pixf.pixel:=@argb32_pixel;
+ pixf.row :=@fmt32_row;
+
+ pixf.copy_hline:=@argb32_copy_hline;
+ pixf.copy_vline:=@argb32_copy_vline;
+
+ pixf.blend_hline:=@argb32_pre_blend_hline;
+ pixf.blend_vline:=@argb32_pre_blend_vline;
+
+ pixf.blend_solid_hspan:=@argb32_pre_blend_solid_hspan;
+ pixf.blend_solid_vspan:=@argb32_pre_blend_solid_vspan;
+
+ pixf.copy_color_hspan:=argb32_copy_color_hspan;
+ pixf.copy_color_vspan:=argb32_copy_color_vspan;
+
+ pixf.blend_color_hspan:=@argb32_pre_blend_color_hspan;
+ pixf.blend_color_vspan:=@argb32_pre_blend_color_vspan;
+
+ pixf.copy_from :=@fmt32_copy_from;
+ pixf.blend_from:=@argb32_pre_blend_from;
+
+ pixf.blend_from_color:=@argb32_pre_blend_from_color;
+ pixf.blend_from_lut :=@argb32_pre_blend_from_lut;
+
+ pixf.for_each_pixel :=@order32_for_each_pixel;
+ pixf.gamma_dir_apply:=@order32_gamma_dir_apply;
+ pixf.gamma_inv_apply:=@order32_gamma_inv_apply;
+
+ pixf.pixel_premultiply:=@order32_pixel_premultiply;
+ pixf.pixel_demultiply :=@order32_pixel_demultiply;
+
+end;
+
+{$I pf_abgr32_pre.inc }
+
+{ PIXFMT_ABGR32_PRE }
+procedure pixfmt_abgr32_pre;
+begin
+ pixf.Construct(rb );
+
+ pixf.m_order:=abgr_order;
+
+ pixf.m_pix_width:=4;
+
+ pixf.copy_pixel :=@abgr32_copy_pixel;
+ pixf.blend_pixel:=@abgr32_pre_blend_pixel;
+
+ pixf.pixel:=@abgr32_pixel;
+ pixf.row :=@fmt32_row;
+
+ pixf.copy_hline:=@abgr32_copy_hline;
+ pixf.copy_vline:=@abgr32_copy_vline;
+
+ pixf.blend_hline:=@abgr32_pre_blend_hline;
+ pixf.blend_vline:=@abgr32_pre_blend_vline;
+
+ pixf.blend_solid_hspan:=@abgr32_pre_blend_solid_hspan;
+ pixf.blend_solid_vspan:=@abgr32_pre_blend_solid_vspan;
+
+ pixf.copy_color_hspan:=abgr32_copy_color_hspan;
+ pixf.copy_color_vspan:=abgr32_copy_color_vspan;
+
+ pixf.blend_color_hspan:=@abgr32_pre_blend_color_hspan;
+ pixf.blend_color_vspan:=@abgr32_pre_blend_color_vspan;
+
+ pixf.copy_from :=@fmt32_copy_from;
+ pixf.blend_from:=@abgr32_pre_blend_from;
+
+ pixf.blend_from_color:=@abgr32_pre_blend_from_color;
+ pixf.blend_from_lut :=@abgr32_pre_blend_from_lut;
+
+ pixf.for_each_pixel :=@order32_for_each_pixel;
+ pixf.gamma_dir_apply:=@order32_gamma_dir_apply;
+ pixf.gamma_inv_apply:=@order32_gamma_inv_apply;
+
+ pixf.pixel_premultiply:=@order32_pixel_premultiply;
+ pixf.pixel_demultiply :=@order32_pixel_demultiply;
+
+end;
+
+{$I pf_alpha32.inc }
+
+{ PIXFMT_ALPHA_BLEND_RGBA }
+procedure pixfmt_alpha_blend_rgba;
+begin
+ pixf.Construct(rb );
+
+ pixf.m_order:=order;
+
+ pixf.m_pix_width:=4;
+
+ pixf.copy_pixel :=@alpha32_copy_pixel;
+ pixf.blend_pixel:=@alpha32_blend_pixel;
+
+ pixf.pixel:=@alpha32_pixel;
+ pixf.row :=@fmt32_row;
+
+ pixf.copy_hline:=@alpha32_copy_hline;
+ pixf.copy_vline:=@alpha32_copy_vline;
+
+ pixf.blend_hline:=@alpha32_blend_hline;
+ pixf.blend_vline:=@alpha32_blend_vline;
+
+ pixf.blend_solid_hspan:=@alpha32_blend_solid_hspan;
+ pixf.blend_solid_vspan:=@alpha32_blend_solid_vspan;
+
+ pixf.copy_color_hspan:=@alpha32_copy_color_hspan;
+ pixf.copy_color_vspan:=@alpha32_copy_color_vspan;
+
+ pixf.blend_color_hspan:=@alpha32_blend_color_hspan;
+ pixf.blend_color_vspan:=@alpha32_blend_color_vspan;
+
+ pixf.copy_from :=@fmt32_copy_from;
+ pixf.blend_from:=@alpha32_blend_from;
+
+ pixf.blend_from_color:=@alpha32_blend_from_color;
+ pixf.blend_from_lut :=@alpha32_blend_from_lut;
+
+ pixf.for_each_pixel :=@order32_for_each_pixel;
+ pixf.gamma_dir_apply:=@order32_gamma_dir_apply;
+ pixf.gamma_inv_apply:=@order32_gamma_inv_apply;
+
+ pixf.pixel_premultiply:=@order32_pixel_premultiply;
+ pixf.pixel_demultiply :=@order32_pixel_demultiply;
+
+end;
+
+{$I pf_cubl32.inc }
+
+{ PIXFMT_CUSTOM_BLEND_RGBA }
+procedure pixfmt_custom_blend_rgba;
+begin
+ pixf.Construct(rb );
+
+ pixf.m_order:=order;
+ pixf.blender:=bl;
+
+ pixf.m_pix_width:=4;
+
+ pixf.copy_pixel :=@cubl_copy_pixel;
+ pixf.blend_pixel:=@cubl_blend_pixel;
+
+ pixf.pixel:=@cubl_pixel;
+ pixf.row :=@fmt32_row;
+
+ pixf.copy_hline:=@cubl_copy_hline;
+ pixf.copy_vline:=@cubl_copy_vline;
+
+ pixf.blend_hline:=@cubl_blend_hline;
+ pixf.blend_vline:=@cubl_blend_vline;
+
+ pixf.blend_solid_hspan:=@cubl_blend_solid_hspan;
+ pixf.blend_solid_vspan:=@cubl_blend_solid_vspan;
+
+ pixf.copy_color_hspan:=@cubl_copy_color_hspan;
+ pixf.copy_color_vspan:=@cubl_copy_color_vspan;
+
+ pixf.blend_color_hspan:=@cubl_blend_color_hspan;
+ pixf.blend_color_vspan:=@cubl_blend_color_vspan;
+
+ pixf.copy_from :=@fmt32_copy_from;
+ pixf.blend_from:=@cubl_blend_from;
+
+ pixf.blend_from_color:=@cubl_blend_from_color;
+ pixf.blend_from_lut :=@cubl_blend_from_lut;
+
+ pixf.for_each_pixel :=@order32_for_each_pixel;
+ pixf.gamma_dir_apply:=@order32_gamma_dir_apply;
+ pixf.gamma_inv_apply:=@order32_gamma_inv_apply;
+
+ pixf.pixel_premultiply:=@order32_pixel_premultiply;
+ pixf.pixel_demultiply :=@order32_pixel_demultiply;
+
+end;
+
+{ comp_op_rgba_clear }
+procedure comp_op_rgba_clear(this : pixel_formats_ptr; p : int8u_ptr; cr ,cg ,cb ,alpha ,cover : unsigned );
+begin
+ if cover < 255 then
+ begin
+ cover:=255 - cover;
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=int8u((int8u_ptr(ptrcomp(p ) + this.m_order.R )^ * cover + 255 ) shr 8 );
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=int8u((int8u_ptr(ptrcomp(p ) + this.m_order.G )^ * cover + 255 ) shr 8 );
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=int8u((int8u_ptr(ptrcomp(p ) + this.m_order.B )^ * cover + 255 ) shr 8 );
+ int8u_ptr(ptrcomp(p ) + this.m_order.A )^:=int8u((int8u_ptr(ptrcomp(p ) + this.m_order.A )^ * cover + 255 ) shr 8 );
+
+ end
+ else
+ begin
+ int8u_ptr(ptrcomp(p ) + 0 )^:=0;
+ int8u_ptr(ptrcomp(p ) + 1 )^:=0;
+ int8u_ptr(ptrcomp(p ) + 2 )^:=0;
+ int8u_ptr(ptrcomp(p ) + 3 )^:=0;
+
+ end;
+
+end;
+
+{ comp_op_rgba_src }
+procedure comp_op_rgba_src(this : pixel_formats_ptr; p : int8u_ptr; sr ,sg ,sb ,sa ,cover : unsigned );
+var
+ alpha : unsigned;
+
+begin
+ if cover < 255 then
+ begin
+ alpha:=255 - cover;
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=int8u(((int8u_ptr(ptrcomp(p ) + this.m_order.R )^ * alpha + 255 ) shr 8 ) + ((sr * cover + 255 ) shr 8 ) );
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=int8u(((int8u_ptr(ptrcomp(p ) + this.m_order.G )^ * alpha + 255 ) shr 8 ) + ((sg * cover + 255 ) shr 8 ) );
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=int8u(((int8u_ptr(ptrcomp(p ) + this.m_order.B )^ * alpha + 255 ) shr 8 ) + ((sb * cover + 255 ) shr 8 ) );
+ int8u_ptr(ptrcomp(p ) + this.m_order.A )^:=int8u(((int8u_ptr(ptrcomp(p ) + this.m_order.A )^ * alpha + 255 ) shr 8 ) + ((sa * cover + 255 ) shr 8 ) );
+
+ end
+ else
+ begin
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=sr;
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=sg;
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=sb;
+ int8u_ptr(ptrcomp(p ) + this.m_order.A )^:=sa;
+
+ end;
+
+end;
+
+{ comp_op_rgba_dst }
+procedure comp_op_rgba_dst(this : pixel_formats_ptr; p : int8u_ptr; cr ,cg ,cb ,alpha ,cover : unsigned );
+begin
+end;
+
+{ comp_op_rgba_src_over }
+// Dca' = Sca + Dca.(1 - Sa)
+// Da' = Sa + Da - Sa.Da
+procedure comp_op_rgba_src_over(this : pixel_formats_ptr; p : int8u_ptr; sr ,sg ,sb ,sa ,cover : unsigned );
+var
+ s1a : unsigned;
+
+begin
+ if cover < 255 then
+ begin
+ sr:=(sr * cover + 255 ) shr 8;
+ sg:=(sg * cover + 255 ) shr 8;
+ sb:=(sb * cover + 255 ) shr 8;
+ sa:=(sa * cover + 255 ) shr 8;
+
+ end;
+
+ s1a:=base_mask - sa;
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=
+ int8u(sr + ((int8u_ptr(ptrcomp(p ) + this.m_order.R )^ * s1a + base_mask ) shr base_shift ) );
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=
+ int8u(sg + ((int8u_ptr(ptrcomp(p ) + this.m_order.G )^ * s1a + base_mask ) shr base_shift ) );
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=
+ int8u(sb + ((int8u_ptr(ptrcomp(p ) + this.m_order.B )^ * s1a + base_mask ) shr base_shift ) );
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.A )^:=
+ int8u(sa + int8u_ptr(ptrcomp(p ) + this.m_order.A )^ - ((sa * int8u_ptr(ptrcomp(p ) + this.m_order.A )^ + base_mask ) shr base_shift ) );
+
+end;
+
+{ comp_op_rgba_dst_over }
+// Dca' = Dca + Sca.(1 - Da)
+// Da' = Sa + Da - Sa.Da
+procedure comp_op_rgba_dst_over(this : pixel_formats_ptr; p : int8u_ptr; sr ,sg ,sb ,sa ,cover : unsigned );
+var
+ d1a : unsigned;
+
+begin
+ if cover < 255 then
+ begin
+ sr:=(sr * cover + 255 ) shr 8;
+ sg:=(sg * cover + 255 ) shr 8;
+ sb:=(sb * cover + 255 ) shr 8;
+ sa:=(sa * cover + 255 ) shr 8;
+
+ end;
+
+ d1a:=base_mask - int8u_ptr(ptrcomp(p ) + this.m_order.A )^;
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=
+ int8u(int8u_ptr(ptrcomp(p ) + this.m_order.R )^ + ((sr * d1a + base_mask ) shr base_shift ) );
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=
+ int8u(int8u_ptr(ptrcomp(p ) + this.m_order.G )^ + ((sg * d1a + base_mask ) shr base_shift ) );
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=
+ int8u(int8u_ptr(ptrcomp(p ) + this.m_order.B )^ + ((sb * d1a + base_mask ) shr base_shift ) );
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.A )^:=
+ int8u(sa + int8u_ptr(ptrcomp(p ) + this.m_order.A )^ - ((sa * int8u_ptr(ptrcomp(p ) + this.m_order.A )^ + base_mask ) shr base_shift ) );
+
+end;
+
+{ comp_op_rgba_src_in }
+// Dca' = Sca.Da
+// Da' = Sa.Da
+procedure comp_op_rgba_src_in(this : pixel_formats_ptr; p : int8u_ptr; sr ,sg ,sb ,sa ,cover : unsigned );
+var
+ da ,alpha : unsigned;
+
+begin
+ da:=int8u_ptr(ptrcomp(p ) + this.m_order.A )^;
+
+ if cover < 255 then
+ begin
+ alpha:=255 - cover;
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=
+ int8u(((int8u_ptr(ptrcomp(p ) + this.m_order.R )^ * alpha + 255 ) shr 8 ) + ((((sr * da + base_mask ) shr base_shift ) * cover + 255 ) shr 8 ) );
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=
+ int8u(((int8u_ptr(ptrcomp(p ) + this.m_order.G )^ * alpha + 255 ) shr 8 ) + ((((sg * da + base_mask ) shr base_shift ) * cover + 255 ) shr 8 ) );
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=
+ int8u(((int8u_ptr(ptrcomp(p ) + this.m_order.B )^ * alpha + 255 ) shr 8 ) + ((((sb * da + base_mask ) shr base_shift ) * cover + 255 ) shr 8 ) );
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.A )^:=
+ int8u(((int8u_ptr(ptrcomp(p ) + this.m_order.A )^ * alpha + 255 ) shr 8 ) + ((((sa * da + base_mask ) shr base_shift ) * cover + 255 ) shr 8 ) );
+
+ end
+ else
+ begin
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=int8u((sr * da + base_mask ) shr base_shift );
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=int8u((sg * da + base_mask ) shr base_shift );
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=int8u((sb * da + base_mask ) shr base_shift );
+ int8u_ptr(ptrcomp(p ) + this.m_order.A )^:=int8u((sa * da + base_mask ) shr base_shift );
+
+ end;
+
+end;
+
+{ comp_op_rgba_dst_in }
+// Dca' = Dca.Sa
+// Da' = Sa.Da
+procedure comp_op_rgba_dst_in(this : pixel_formats_ptr; p : int8u_ptr; cr ,cg ,cb ,sa ,cover : unsigned );
+begin
+ if cover < 255 then
+ sa:=base_mask - ((cover * (base_mask - sa ) + 255 ) shr 8 );
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=int8u((int8u_ptr(ptrcomp(p ) + this.m_order.R )^ * sa + base_mask ) shr base_shift );
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=int8u((int8u_ptr(ptrcomp(p ) + this.m_order.G )^ * sa + base_mask ) shr base_shift );
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=int8u((int8u_ptr(ptrcomp(p ) + this.m_order.B )^ * sa + base_mask ) shr base_shift );
+ int8u_ptr(ptrcomp(p ) + this.m_order.A )^:=int8u((int8u_ptr(ptrcomp(p ) + this.m_order.A )^ * sa + base_mask ) shr base_shift );
+
+end;
+
+{ comp_op_rgba_src_out }
+// Dca' = Sca.(1 - Da)
+// Da' = Sa.(1 - Da)
+procedure comp_op_rgba_src_out(this : pixel_formats_ptr; p : int8u_ptr; sr ,sg ,sb ,sa ,cover : unsigned );
+var
+ da ,alpha : unsigned;
+
+begin
+ da:=base_mask - int8u_ptr(ptrcomp(p ) + this.m_order.A )^;
+
+ if cover < 255 then
+ begin
+ alpha:=255 - cover;
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=
+ int8u(((int8u_ptr(ptrcomp(p ) + this.m_order.R )^ * alpha + 255 ) shr 8 ) + ((((sr * da + base_mask ) shr base_shift ) * cover + 255 ) shr 8 ) );
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=
+ int8u(((int8u_ptr(ptrcomp(p ) + this.m_order.G )^ * alpha + 255 ) shr 8 ) + ((((sg * da + base_mask ) shr base_shift ) * cover + 255 ) shr 8 ) );
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=
+ int8u(((int8u_ptr(ptrcomp(p ) + this.m_order.B )^ * alpha + 255 ) shr 8 ) + ((((sb * da + base_mask ) shr base_shift ) * cover + 255 ) shr 8 ) );
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.A )^:=
+ int8u(((int8u_ptr(ptrcomp(p ) + this.m_order.A )^ * alpha + 255 ) shr 8 ) + ((((sa * da + base_mask ) shr base_shift ) * cover + 255 ) shr 8 ) );
+
+ end
+ else
+ begin
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=int8u((sr * da + base_mask ) shr base_shift );
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=int8u((sg * da + base_mask ) shr base_shift );
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=int8u((sb * da + base_mask ) shr base_shift );
+ int8u_ptr(ptrcomp(p ) + this.m_order.A )^:=int8u((sa * da + base_mask ) shr base_shift );
+
+ end;
+
+end;
+
+{ comp_op_rgba_dst_out }
+// Dca' = Dca.(1 - Sa)
+// Da' = Da.(1 - Sa)
+procedure comp_op_rgba_dst_out(this : pixel_formats_ptr; p : int8u_ptr; cr ,cg ,cb ,sa ,cover : unsigned );
+begin
+ if cover < 255 then
+ sa:=(sa * cover + 255 ) shr 8;
+
+ sa:=base_mask - sa;
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=int8u((int8u_ptr(ptrcomp(p ) + this.m_order.R )^ * sa + base_shift ) shr base_shift );
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=int8u((int8u_ptr(ptrcomp(p ) + this.m_order.G )^ * sa + base_shift ) shr base_shift );
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=int8u((int8u_ptr(ptrcomp(p ) + this.m_order.B )^ * sa + base_shift ) shr base_shift );
+ int8u_ptr(ptrcomp(p ) + this.m_order.A )^:=int8u((int8u_ptr(ptrcomp(p ) + this.m_order.A )^ * sa + base_shift ) shr base_shift );
+
+end;
+
+{ comp_op_rgba_src_atop }
+// Dca' = Sca.Da + Dca.(1 - Sa)
+// Da' = Da
+procedure comp_op_rgba_src_atop(this : pixel_formats_ptr; p : int8u_ptr; sr ,sg ,sb ,sa ,cover : unsigned );
+var
+ da : unsigned;
+
+begin
+ if cover < 255 then
+ begin
+ sr:=(sr * cover + 255 ) shr 8;
+ sg:=(sg * cover + 255 ) shr 8;
+ sb:=(sb * cover + 255 ) shr 8;
+ sa:=(sa * cover + 255 ) shr 8;
+
+ end;
+
+ da:=int8u_ptr(ptrcomp(p ) + this.m_order.A )^;
+ sa:=base_mask - sa;
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=int8u((sr * da + int8u_ptr(ptrcomp(p ) + this.m_order.R )^ * sa + base_mask ) shr base_shift );
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=int8u((sg * da + int8u_ptr(ptrcomp(p ) + this.m_order.G )^ * sa + base_mask ) shr base_shift );
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=int8u((sb * da + int8u_ptr(ptrcomp(p ) + this.m_order.B )^ * sa + base_mask ) shr base_shift );
+
+end;
+
+{ comp_op_rgba_dst_atop }
+// Dca' = Dca.Sa + Sca.(1 - Da)
+// Da' = Sa
+procedure comp_op_rgba_dst_atop(this : pixel_formats_ptr; p : int8u_ptr; sr ,sg ,sb ,sa ,cover : unsigned );
+var
+ da ,alpha : unsigned;
+
+begin
+ da:=base_mask - int8u_ptr(ptrcomp(p ) + this.m_order.A )^;
+
+ if cover < 255 then
+ begin
+ alpha:=255 - cover;
+
+ sr:=(int8u_ptr(ptrcomp(p ) + this.m_order.R )^ * sa + sr * da + base_mask ) shr base_shift;
+ sg:=(int8u_ptr(ptrcomp(p ) + this.m_order.G )^ * sa + sg * da + base_mask ) shr base_shift;
+ sb:=(int8u_ptr(ptrcomp(p ) + this.m_order.B )^ * sa + sb * da + base_mask ) shr base_shift;
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=
+ int8u(((int8u_ptr(ptrcomp(p ) + this.m_order.R )^ * alpha + 255 ) shr 8) + ((sr * cover + 255 ) shr 8 ) );
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=
+ int8u(((int8u_ptr(ptrcomp(p ) + this.m_order.G )^ * alpha + 255 ) shr 8) + ((sg * cover + 255 ) shr 8 ) );
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=
+ int8u(((int8u_ptr(ptrcomp(p ) + this.m_order.B )^ * alpha + 255 ) shr 8) + ((sb * cover + 255 ) shr 8 ) );
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.A )^:=
+ int8u(((int8u_ptr(ptrcomp(p ) + this.m_order.A )^ * alpha + 255 ) shr 8) + ((sa * cover + 255 ) shr 8 ) );
+
+ end
+ else
+ begin
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=int8u((int8u_ptr(ptrcomp(p ) + this.m_order.R )^ * sa + sr * da + base_mask ) shr base_shift );
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=int8u((int8u_ptr(ptrcomp(p ) + this.m_order.G )^ * sa + sg * da + base_mask ) shr base_shift );
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=int8u((int8u_ptr(ptrcomp(p ) + this.m_order.B )^ * sa + sb * da + base_mask ) shr base_shift );
+ int8u_ptr(ptrcomp(p ) + this.m_order.A )^:=int8u(sa );
+
+ end;
+
+end;
+
+{ comp_op_rgba_xor }
+// Dca' = Sca.(1 - Da) + Dca.(1 - Sa)
+// Da' = Sa + Da - 2.Sa.Da
+procedure comp_op_rgba_xor(this : pixel_formats_ptr; p : int8u_ptr; sr ,sg ,sb ,sa ,cover : unsigned );
+var
+ s1a ,d1a : unsigned;
+
+begin
+ if cover < 255 then
+ begin
+ sr:=(sr * cover + 255 ) shr 8;
+ sg:=(sg * cover + 255 ) shr 8;
+ sb:=(sb * cover + 255 ) shr 8;
+ sa:=(sa * cover + 255 ) shr 8;
+
+ end;
+
+ s1a:=base_mask - sa;
+ d1a:=base_mask - int8u_ptr(ptrcomp(p ) + this.m_order.A )^;
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=
+ int8u((int8u_ptr(ptrcomp(p ) + this.m_order.R )^ * s1a + sr * d1a + base_mask ) shr base_shift );
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=
+ int8u((int8u_ptr(ptrcomp(p ) + this.m_order.G )^ * s1a + sg * d1a + base_mask ) shr base_shift );
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=
+ int8u((int8u_ptr(ptrcomp(p ) + this.m_order.B )^ * s1a + sb * d1a + base_mask ) shr base_shift );
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.A )^:=
+ int8u(sa + int8u_ptr(ptrcomp(p ) + this.m_order.A )^ - ((sa * int8u_ptr(ptrcomp(p ) + this.m_order.A )^ + base_mask div 2 ) shr (base_shift - 1 ) ) );
+
+end;
+
+{ comp_op_rgba_plus }
+// Dca' = Sca + Dca
+// Da' = Sa + Da
+procedure comp_op_rgba_plus(this : pixel_formats_ptr; p : int8u_ptr; sr ,sg ,sb ,sa ,cover : unsigned );
+var
+ dr ,dg ,db ,da : unsigned;
+
+begin
+ if cover < 255 then
+ begin
+ sr:=(sr * cover + 255 ) shr 8;
+ sg:=(sg * cover + 255 ) shr 8;
+ sb:=(sb * cover + 255 ) shr 8;
+ sa:=(sa * cover + 255 ) shr 8;
+
+ end;
+
+ dr:=int8u_ptr(ptrcomp(p ) + this.m_order.R )^ + sr;
+ dg:=int8u_ptr(ptrcomp(p ) + this.m_order.G )^ + sg;
+ db:=int8u_ptr(ptrcomp(p ) + this.m_order.B )^ + sb;
+ da:=int8u_ptr(ptrcomp(p ) + this.m_order.A )^ + sa;
+
+ if dr > base_mask then
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=base_mask
+ else
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=int8u(dr );
+
+ if dg > base_mask then
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=base_mask
+ else
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=int8u(dg );
+
+ if db > base_mask then
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=base_mask
+ else
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=int8u(db );
+
+ if da > base_mask then
+ int8u_ptr(ptrcomp(p ) + this.m_order.A )^:=base_mask
+ else
+ int8u_ptr(ptrcomp(p ) + this.m_order.A )^:=int8u(da );
+
+end;
+
+{ comp_op_rgba_minus }
+// Dca' = Dca - Sca
+// Da' = 1 - (1 - Sa).(1 - Da)
+procedure comp_op_rgba_minus(this : pixel_formats_ptr; p : int8u_ptr; sr ,sg ,sb ,sa ,cover : unsigned );
+var
+ dr ,dg ,db : unsigned;
+
+begin
+ if cover < 255 then
+ begin
+ sr:=(sr * cover + 255 ) shr 8;
+ sg:=(sg * cover + 255 ) shr 8;
+ sb:=(sb * cover + 255 ) shr 8;
+ sa:=(sa * cover + 255 ) shr 8;
+
+ end;
+
+ dr:=int8u_ptr(ptrcomp(p ) + this.m_order.R )^ - sr;
+ dg:=int8u_ptr(ptrcomp(p ) + this.m_order.G )^ - sg;
+ db:=int8u_ptr(ptrcomp(p ) + this.m_order.B )^ - sb;
+
+ if dr > base_mask then
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=0
+ else
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=int8u(dr );
+
+ if dg > base_mask then
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=0
+ else
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=int8u(dg );
+
+ if db > base_mask then
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=0
+ else
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=int8u(db );
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.A )^:=
+ int8u(base_mask - (((base_mask - sa ) * (base_mask - int8u_ptr(ptrcomp(p ) + this.m_order.A )^ ) + base_mask ) shr base_shift ) );
+
+end;
+
+{ comp_op_rgba_multiply }
+// Dca' = Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa)
+// Da' = Sa + Da - Sa.Da
+procedure comp_op_rgba_multiply(this : pixel_formats_ptr; p : int8u_ptr; sr ,sg ,sb ,sa ,cover : unsigned );
+var
+ s1a ,d1a ,dr ,dg ,db : unsigned;
+
+begin
+ if cover < 255 then
+ begin
+ sr:=(sr * cover + 255 ) shr 8;
+ sg:=(sg * cover + 255 ) shr 8;
+ sb:=(sb * cover + 255 ) shr 8;
+ sa:=(sa * cover + 255 ) shr 8;
+
+ end;
+
+ s1a:=base_mask - sa;
+ d1a:=base_mask - int8u_ptr(ptrcomp(p ) + this.m_order.A )^;
+ dr :=int8u_ptr(ptrcomp(p ) + this.m_order.R )^;
+ dg :=int8u_ptr(ptrcomp(p ) + this.m_order.G )^;
+ db :=int8u_ptr(ptrcomp(p ) + this.m_order.B )^;
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=int8u((sr * dr + sr * d1a + dr * s1a + base_mask ) shr base_shift );
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=int8u((sg * dg + sg * d1a + dg * s1a + base_mask ) shr base_shift );
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=int8u((sb * db + sb * d1a + db * s1a + base_mask ) shr base_shift );
+ int8u_ptr(ptrcomp(p ) + this.m_order.A )^:=
+ int8u(sa + int8u_ptr(ptrcomp(p ) + this.m_order.A )^ - ((sa * int8u_ptr(ptrcomp(p ) + this.m_order.A )^ + base_mask ) shr base_shift ) );
+
+end;
+
+{ comp_op_rgba_screen }
+// Dca' = Sca + Dca - Sca.Dca
+// Da' = Sa + Da - Sa.Da
+procedure comp_op_rgba_screen(this : pixel_formats_ptr; p : int8u_ptr; sr ,sg ,sb ,sa ,cover : unsigned );
+var
+ dr ,dg ,db ,da : unsigned;
+
+begin
+ if cover < 255 then
+ begin
+ sr:=(sr * cover + 255 ) shr 8;
+ sg:=(sg * cover + 255 ) shr 8;
+ sb:=(sb * cover + 255 ) shr 8;
+ sa:=(sa * cover + 255 ) shr 8;
+
+ end;
+
+ dr:=int8u_ptr(ptrcomp(p ) + this.m_order.R )^;
+ dg:=int8u_ptr(ptrcomp(p ) + this.m_order.G )^;
+ db:=int8u_ptr(ptrcomp(p ) + this.m_order.B )^;
+ da:=int8u_ptr(ptrcomp(p ) + this.m_order.A )^;
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=int8u(sr + dr - ((sr * dr + base_mask ) shr base_shift ) );
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=int8u(sg + dg - ((sg * dg + base_mask ) shr base_shift ) );
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=int8u(sb + db - ((sb * db + base_mask ) shr base_shift ) );
+ int8u_ptr(ptrcomp(p ) + this.m_order.A )^:=int8u(sa + da - ((sa * da + base_mask ) shr base_shift ) );
+
+end;
+
+{ comp_op_rgba_overlay }
+// if 2.Dca < Da
+// Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa)
+// otherwise
+// Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa)
+//
+// Da' = Sa + Da - Sa.Da
+procedure comp_op_rgba_overlay(this : pixel_formats_ptr; p : int8u_ptr; sr ,sg ,sb ,sa ,cover : unsigned );
+var
+ d1a ,s1a ,dr ,dg ,db ,da ,sada : unsigned;
+
+begin
+ if cover < 255 then
+ begin
+ sr:=(sr * cover + 255 ) shr 8;
+ sg:=(sg * cover + 255 ) shr 8;
+ sb:=(sb * cover + 255 ) shr 8;
+ sa:=(sa * cover + 255 ) shr 8;
+
+ end;
+
+ d1a :=base_mask - int8u_ptr(ptrcomp(p ) + this.m_order.A )^;
+ s1a :=base_mask - sa;
+ dr :=int8u_ptr(ptrcomp(p ) + this.m_order.R )^;
+ dg :=int8u_ptr(ptrcomp(p ) + this.m_order.G )^;
+ db :=int8u_ptr(ptrcomp(p ) + this.m_order.B )^;
+ da :=int8u_ptr(ptrcomp(p ) + this.m_order.A )^;
+ sada:=sa * int8u_ptr(ptrcomp(p ) + this.m_order.A )^;
+
+ if 2 * dr < da then
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=int8u((2 * sr * dr + sr * d1a + dr * s1a ) shr base_shift )
+ else
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=int8u((sada - 2 * (da - dr ) * (sa - sr ) + sr * d1a + dr * s1a ) shr base_shift );
+
+ if 2 * dg < da then
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=int8u((2 * sg * dg + sg * d1a + dg * s1a ) shr base_shift )
+ else
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=int8u((sada - 2 * (da - dg ) * (sa - sg ) + sg * d1a + dg * s1a ) shr base_shift );
+
+ if 2 * db < da then
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=int8u((2 * sb * db + sb * d1a + db * s1a ) shr base_shift )
+ else
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=int8u((sada - 2 * (da - db ) * (sa - sb ) + sb * d1a + db * s1a ) shr base_shift );
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.A )^:=int8u(sa + da - ((sa * da + base_mask ) shr base_shift ) );
+
+end;
+
+{ sd_min }
+function sd_min(a ,b : unsigned ) : unsigned;
+begin
+ if a < b then
+ result:=a
+ else
+ result:=b;
+
+end;
+
+{ sd_max }
+function sd_max(a ,b : unsigned ) : unsigned;
+begin
+ if a > b then
+ result:=a
+ else
+ result:=b;
+
+end;
+
+{ comp_op_rgba_darken }
+// Dca' = min(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa)
+// Da' = Sa + Da - Sa.Da
+procedure comp_op_rgba_darken(this : pixel_formats_ptr; p : int8u_ptr; sr ,sg ,sb ,sa ,cover : unsigned );
+var
+ d1a ,s1a ,dr ,dg ,db ,da : unsigned;
+
+begin
+ if cover < 255 then
+ begin
+ sr:=(sr * cover + 255 ) shr 8;
+ sg:=(sg * cover + 255 ) shr 8;
+ sb:=(sb * cover + 255 ) shr 8;
+ sa:=(sa * cover + 255 ) shr 8;
+
+ end;
+
+ d1a:=base_mask - int8u_ptr(ptrcomp(p ) + this.m_order.A )^;
+ s1a:=base_mask - sa;
+ dr :=int8u_ptr(ptrcomp(p ) + this.m_order.R )^;
+ dg :=int8u_ptr(ptrcomp(p ) + this.m_order.G )^;
+ db :=int8u_ptr(ptrcomp(p ) + this.m_order.B )^;
+ da :=int8u_ptr(ptrcomp(p ) + this.m_order.A )^;
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=int8u((sd_min(sr * da, dr * sa ) + sr * d1a + dr * s1a ) shr base_shift );
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=int8u((sd_min(sg * da, dg * sa ) + sg * d1a + dg * s1a ) shr base_shift );
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=int8u((sd_min(sb * da, db * sa ) + sb * d1a + db * s1a ) shr base_shift );
+ int8u_ptr(ptrcomp(p ) + this.m_order.A )^:=int8u(sa + da - ((sa * da + base_mask ) shr base_shift ) );
+
+end;
+
+{ comp_op_rgba_lighten }
+// Dca' = max(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa)
+// Da' = Sa + Da - Sa.Da
+procedure comp_op_rgba_lighten(this : pixel_formats_ptr; p : int8u_ptr; sr ,sg ,sb ,sa ,cover : unsigned );
+var
+ d1a ,s1a ,dr ,dg ,db ,da : unsigned;
+
+begin
+ if cover < 255 then
+ begin
+ sr:=(sr * cover + 255 ) shr 8;
+ sg:=(sg * cover + 255 ) shr 8;
+ sb:=(sb * cover + 255 ) shr 8;
+ sa:=(sa * cover + 255 ) shr 8;
+
+ end;
+
+ d1a:=base_mask - int8u_ptr(ptrcomp(p ) + this.m_order.A )^;
+ s1a:=base_mask - sa;
+ dr :=int8u_ptr(ptrcomp(p ) + this.m_order.R )^;
+ dg :=int8u_ptr(ptrcomp(p ) + this.m_order.G )^;
+ db :=int8u_ptr(ptrcomp(p ) + this.m_order.B )^;
+ da :=int8u_ptr(ptrcomp(p ) + this.m_order.A )^;
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=int8u((sd_max(sr * da, dr * sa ) + sr * d1a + dr * s1a ) shr base_shift );
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=int8u((sd_max(sg * da, dg * sa ) + sg * d1a + dg * s1a ) shr base_shift );
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=int8u((sd_max(sb * da, db * sa ) + sb * d1a + db * s1a ) shr base_shift );
+ int8u_ptr(ptrcomp(p ) + this.m_order.A )^:=int8u(sa + da - ((sa * da + base_mask ) shr base_shift ) );
+
+end;
+
+{ comp_op_rgba_color_dodge }
+// if Sca.Da + Dca.Sa >= Sa.Da
+// Dca' = Sa.Da + Sca.(1 - Da) + Dca.(1 - Sa)
+// otherwise
+// Dca' = Dca.Sa/(1-Sca/Sa) + Sca.(1 - Da) + Dca.(1 - Sa)
+//
+// Da' = Sa + Da - Sa.Da
+procedure comp_op_rgba_color_dodge(this : pixel_formats_ptr; p : int8u_ptr; sr ,sg ,sb ,sa ,cover : unsigned );
+var
+ d1a ,s1a ,dr ,dg ,db ,da : unsigned;
+
+ drsa ,dgsa ,dbsa ,srda ,sgda ,sbda ,sada : int;
+
+begin
+ if cover < 255 then
+ begin
+ sr:=(sr * cover + 255 ) shr 8;
+ sg:=(sg * cover + 255 ) shr 8;
+ sb:=(sb * cover + 255 ) shr 8;
+ sa:=(sa * cover + 255 ) shr 8;
+
+ end;
+
+ d1a :=base_mask - int8u_ptr(ptrcomp(p ) + this.m_order.A )^;
+ s1a :=base_mask - sa;
+ dr :=int8u_ptr(ptrcomp(p ) + this.m_order.R )^;
+ dg :=int8u_ptr(ptrcomp(p ) + this.m_order.G )^;
+ db :=int8u_ptr(ptrcomp(p ) + this.m_order.B )^;
+ da :=int8u_ptr(ptrcomp(p ) + this.m_order.A )^;
+ drsa:=dr * sa;
+ dgsa:=dg * sa;
+ dbsa:=db * sa;
+ srda:=sr * da;
+ sgda:=sg * da;
+ sbda:=sb * da;
+ sada:=sa * da;
+
+ if srda + drsa >= sada then
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=int8u(shr_int32(sada + sr * d1a + dr * s1a ,base_shift ) )
+ else
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=int8u(drsa div (base_mask - (sr shl base_shift ) div sa ) + ((sr * d1a + dr * s1a ) shr base_shift ) );
+
+ if sgda + dgsa >= sada then
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=int8u(shr_int32(sada + sg * d1a + dg * s1a ,base_shift ) )
+ else
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=int8u(dgsa div (base_mask - (sg shl base_shift ) div sa ) + ((sg * d1a + dg * s1a ) shr base_shift ) );
+
+ if sbda + dbsa >= sada then
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=int8u(shr_int32(sada + sb * d1a + db * s1a ,base_shift ) )
+ else
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=int8u(dbsa div (base_mask - (sb shl base_shift ) div sa ) + ((sb * d1a + db * s1a ) shr base_shift ) );
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.A )^:=int8u(sa + da - ((sa * da + base_mask) shr base_shift ) );
+
+end;
+
+{ comp_op_rgba_color_burn }
+// if Sca.Da + Dca.Sa <= Sa.Da
+// Dca' = Sca.(1 - Da) + Dca.(1 - Sa)
+// otherwise
+// Dca' = Sa.(Sca.Da + Dca.Sa - Sa.Da)/Sca + Sca.(1 - Da) + Dca.(1 - Sa)
+//
+// Da' = Sa + Da - Sa.Da
+procedure comp_op_rgba_color_burn(this : pixel_formats_ptr; p : int8u_ptr; sr ,sg ,sb ,sa ,cover : unsigned );
+var
+ d1a ,s1a ,dr ,dg ,db ,da : unsigned;
+
+ drsa ,dgsa ,dbsa ,srda ,sgda ,sbda ,sada : int;
+
+begin
+ if cover < 255 then
+ begin
+ sr:=(sr * cover + 255 ) shr 8;
+ sg:=(sg * cover + 255 ) shr 8;
+ sb:=(sb * cover + 255 ) shr 8;
+ sa:=(sa * cover + 255 ) shr 8;
+
+ end;
+
+ d1a :=base_mask - int8u_ptr(ptrcomp(p ) + this.m_order.A )^;
+ s1a :=base_mask - sa;
+ dr :=int8u_ptr(ptrcomp(p ) + this.m_order.R )^;
+ dg :=int8u_ptr(ptrcomp(p ) + this.m_order.G )^;
+ db :=int8u_ptr(ptrcomp(p ) + this.m_order.B )^;
+ da :=int8u_ptr(ptrcomp(p ) + this.m_order.A )^;
+ drsa:=dr * sa;
+ dgsa:=dg * sa;
+ dbsa:=db * sa;
+ srda:=sr * da;
+ sgda:=sg * da;
+ sbda:=sb * da;
+ sada:=sa * da;
+
+ if srda + drsa <= sada then
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=int8u((sr * d1a + dr * s1a ) shr base_shift )
+ else
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=int8u(shr_int32(sa * (srda + drsa - sada ) div sr + sr * d1a + dr * s1a ,base_shift ) );
+
+ if sgda + dgsa <= sada then
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=int8u((sg * d1a + dg * s1a ) shr base_shift)
+ else
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=int8u(shr_int32(sa * (sgda + dgsa - sada ) div sg + sg * d1a + dg * s1a ,base_shift ) );
+
+ if sbda + dbsa <= sada then
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=int8u((sb * d1a + db * s1a ) shr base_shift)
+ else
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=int8u(shr_int32(sa * (sbda + dbsa - sada ) div sb + sb * d1a + db * s1a ,base_shift ) );
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.A )^:=int8u(sa + da - ((sa * da + base_mask ) shr base_shift ) );
+
+end;
+
+{ comp_op_rgba_hard_light }
+// if 2.Sca < Sa
+// Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa)
+// otherwise
+// Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa)
+//
+// Da' = Sa + Da - Sa.Da
+procedure comp_op_rgba_hard_light(this : pixel_formats_ptr; p : int8u_ptr; sr ,sg ,sb ,sa ,cover : unsigned );
+var
+ d1a ,s1a ,dr ,dg ,db ,da ,sada : unsigned;
+
+begin
+ if cover < 255 then
+ begin
+ sr:=(sr * cover + 255 ) shr 8;
+ sg:=(sg * cover + 255 ) shr 8;
+ sb:=(sb * cover + 255 ) shr 8;
+ sa:=(sa * cover + 255 ) shr 8;
+
+ end;
+
+ d1a :=base_mask - int8u_ptr(ptrcomp(p ) + this.m_order.A )^;
+ s1a :=base_mask - sa;
+ dr :=int8u_ptr(ptrcomp(p ) + this.m_order.R )^;
+ dg :=int8u_ptr(ptrcomp(p ) + this.m_order.G )^;
+ db :=int8u_ptr(ptrcomp(p ) + this.m_order.B )^;
+ da :=int8u_ptr(ptrcomp(p ) + this.m_order.A )^;
+ sada:=sa * da;
+
+ if 2*sr < sa then
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=int8u((2 * sr * dr + sr * d1a + dr * s1a ) shr base_shift )
+ else
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=int8u((sada - 2 * (da - dr ) * (sa - sr ) + sr * d1a + dr * s1a ) shr base_shift );
+
+ if 2*sg < sa then
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=int8u((2 * sg * dg + sg * d1a + dg * s1a ) shr base_shift )
+ else
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=int8u((sada - 2 * (da - dg ) * (sa - sg ) + sg * d1a + dg * s1a ) shr base_shift );
+
+ if 2*sb < sa then
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=int8u((2 * sb * db + sb * d1a + db * s1a ) shr base_shift )
+ else
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=int8u((sada - 2 * (da - db ) * (sa - sb ) + sb * d1a + db * s1a ) shr base_shift );
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.A )^:=int8u(sa + da - ((sa * da + base_mask ) shr base_shift ) );
+
+end;
+
+{ comp_op_rgba_soft_light }
+// if 2.Sca < Sa
+// Dca' = Dca.(Sa + (1 - Dca/Da).(2.Sca - Sa)) + Sca.(1 - Da) + Dca.(1 - Sa)
+// otherwise if 8.Dca <= Da
+// Dca' = Dca.(Sa + (1 - Dca/Da).(2.Sca - Sa).(3 - 8.Dca/Da)) + Sca.(1 - Da) + Dca.(1 - Sa)
+// otherwise
+// Dca' = (Dca.Sa + ((Dca/Da)^(0.5).Da - Dca).(2.Sca - Sa)) + Sca.(1 - Da) + Dca.(1 - Sa)
+//
+// Da' = Sa + Da - Sa.Da
+procedure comp_op_rgba_soft_light(this : pixel_formats_ptr; p : int8u_ptr; r ,g ,b ,a ,cover : unsigned );
+var
+ sr ,sg ,sb ,sa ,dr ,dg ,db ,da : double;
+
+begin
+ sr:=(r * cover ) / (base_mask * 255 );
+ sg:=(g * cover ) / (base_mask * 255 );
+ sb:=(b * cover ) / (base_mask * 255 );
+ sa:=(a * cover ) / (base_mask * 255 );
+ dr:=int8u_ptr(ptrcomp(p ) + this.m_order.R )^ / base_mask;
+ dg:=int8u_ptr(ptrcomp(p ) + this.m_order.G )^ / base_mask;
+ db:=int8u_ptr(ptrcomp(p ) + this.m_order.B )^ / base_mask;
+
+ if int8u_ptr(ptrcomp(p ) + this.m_order.A )^ <> 0 then
+ da:=int8u_ptr(ptrcomp(p ) + this.m_order.A )^ / base_mask
+ else
+ da:=1 / base_mask;
+
+ if cover < 255 then
+ a:=(a * cover + 255 ) shr 8;
+
+ if 2 * sr < sa then
+ dr:=dr * (sa + (1 - dr / da ) * (2 * sr - sa ) ) + sr * (1 - da ) + dr * (1 - sa )
+ else
+ if 8 * dr <= da then
+ dr:=dr * (sa + (1 - dr / da ) * (2 * sr - sa ) * (3 - 8 * dr / da ) ) + sr * (1 - da ) + dr * (1 - sa )
+ else
+ dr:=(dr * sa + (Sqrt(dr / da ) * da - dr ) * (2 * sr - sa ) ) + sr * (1 - da ) + dr * (1 - sa );
+
+ if 2 * sg < sa then
+ dg:=dg * (sa + (1 - dg / da ) * (2 * sg - sa ) ) + sg * (1 - da ) + dg * (1 - sa )
+ else
+ if 8 * dg <= da then
+ dg:=dg * (sa + (1 - dg / da ) * (2 * sg - sa ) * (3 - 8 * dg / da ) ) + sg * (1 - da ) + dg * (1 - sa )
+ else
+ dg:=(dg * sa + (Sqrt(dg / da ) * da - dg ) * (2 * sg - sa ) ) + sg * (1 - da ) + dg * (1 - sa );
+
+ if 2 * sb < sa then
+ db:=db * (sa + (1 - db / da ) * (2 * sb - sa ) ) + sb * (1 - da ) + db * (1 - sa )
+ else
+ if 8 * db <= da then
+ db:=db * (sa + (1 - db / da ) * (2 * sb - sa ) * (3 - 8 * db / da ) ) + sb * (1 - da ) + db * (1 - sa )
+ else
+ db:=(db * sa + (Sqrt(db / da ) * da - db ) * (2 * sb - sa ) ) + sb * (1 - da ) + db * (1 - sa );
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=int8u(trunc(dr * base_mask ) );
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=int8u(trunc(dg * base_mask ) );
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=int8u(trunc(db * base_mask ) );
+ int8u_ptr(ptrcomp(p ) + this.m_order.A )^:=
+ int8u(a + int8u_ptr(ptrcomp(p ) + this.m_order.A )^ - ((a * int8u_ptr(ptrcomp(p ) + this.m_order.A )^ + base_mask ) shr base_shift ) );
+
+end;
+
+{ comp_op_rgba_difference }
+// Dca' = Sca + Dca - 2.min(Sca.Da, Dca.Sa)
+// Da' = Sa + Da - Sa.Da
+procedure comp_op_rgba_difference(this : pixel_formats_ptr; p : int8u_ptr; sr ,sg ,sb ,sa ,cover : unsigned );
+var
+ dr ,dg ,db ,da : unsigned;
+
+begin
+ if cover < 255 then
+ begin
+ sr:=(sr * cover + 255 ) shr 8;
+ sg:=(sg * cover + 255 ) shr 8;
+ sb:=(sb * cover + 255 ) shr 8;
+ sa:=(sa * cover + 255 ) shr 8;
+
+ end;
+
+ dr:=int8u_ptr(ptrcomp(p ) + this.m_order.R )^;
+ dg:=int8u_ptr(ptrcomp(p ) + this.m_order.G )^;
+ db:=int8u_ptr(ptrcomp(p ) + this.m_order.B )^;
+ da:=int8u_ptr(ptrcomp(p ) + this.m_order.A )^;
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=int8u(sr + dr - ((2 * sd_min(sr * da ,dr * sa ) ) shr base_shift ) );
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=int8u(sg + dg - ((2 * sd_min(sg * da ,dg * sa ) ) shr base_shift ) );
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=int8u(sb + db - ((2 * sd_min(sb * da ,db * sa ) ) shr base_shift ) );
+ int8u_ptr(ptrcomp(p ) + this.m_order.A )^:=int8u(sa + da - ((sa * da + base_mask ) shr base_shift ) );
+
+end;
+
+{ comp_op_rgba_exclusion }
+// Dca' = (Sca.Da + Dca.Sa - 2.Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa)
+// Da' = Sa + Da - Sa.Da
+procedure comp_op_rgba_exclusion(this : pixel_formats_ptr; p : int8u_ptr; sr ,sg ,sb ,sa ,cover : unsigned );
+var
+ d1a ,s1a ,dr ,dg ,db ,da : unsigned;
+
+begin
+ if cover < 255 then
+ begin
+ sr:=(sr * cover + 255 ) shr 8;
+ sg:=(sg * cover + 255 ) shr 8;
+ sb:=(sb * cover + 255 ) shr 8;
+ sa:=(sa * cover + 255 ) shr 8;
+
+ end;
+
+ d1a:=base_mask - int8u_ptr(ptrcomp(p ) + this.m_order.A )^;
+ s1a:=base_mask - sa;
+ dr :=int8u_ptr(ptrcomp(p ) + this.m_order.R )^;
+ dg :=int8u_ptr(ptrcomp(p ) + this.m_order.G )^;
+ db :=int8u_ptr(ptrcomp(p ) + this.m_order.B )^;
+ da :=int8u_ptr(ptrcomp(p ) + this.m_order.A )^;
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=int8u((sr * da + dr * sa - 2 * sr * dr + sr * d1a + dr * s1a ) shr base_shift );
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=int8u((sg * da + dg * sa - 2 * sg * dg + sg * d1a + dg * s1a ) shr base_shift );
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=int8u((sb * da + db * sa - 2 * sb * db + sb * d1a + db * s1a ) shr base_shift );
+ int8u_ptr(ptrcomp(p ) + this.m_order.A )^:=int8u(sa + da - ((sa * da + base_mask ) shr base_shift ) );
+
+end;
+
+{ comp_op_rgba_contrast }
+procedure comp_op_rgba_contrast(this : pixel_formats_ptr; p : int8u_ptr; sr ,sg ,sb ,sa ,cover : unsigned );
+var
+ dr ,dg ,db ,da ,d2a ,r ,g ,b : int;
+
+ s2a : unsigned;
+
+begin
+ if cover < 255 then
+ begin
+ sr:=(sr * cover + 255 ) shr 8;
+ sg:=(sg * cover + 255 ) shr 8;
+ sb:=(sb * cover + 255 ) shr 8;
+ sa:=(sa * cover + 255 ) shr 8;
+
+ end;
+
+ dr :=int8u_ptr(ptrcomp(p ) + this.m_order.R )^;
+ dg :=int8u_ptr(ptrcomp(p ) + this.m_order.G )^;
+ db :=int8u_ptr(ptrcomp(p ) + this.m_order.B )^;
+ da :=int8u_ptr(ptrcomp(p ) + this.m_order.A )^;
+ d2a:=shr_int32(da ,1 );
+ s2a:=sa shr 1;
+
+ r:=shr_int32((dr - d2a) * ((sr - s2a ) * 2 + base_mask ) ,base_shift ) + d2a;
+ g:=shr_int32((dg - d2a) * ((sg - s2a ) * 2 + base_mask ) ,base_shift ) + d2a;
+ b:=shr_int32((db - d2a) * ((sb - s2a ) * 2 + base_mask ) ,base_shift ) + d2a;
+
+ if r < 0 then
+ r:=0;
+
+ if g < 0 then
+ g:=0;
+
+ if b < 0 then
+ b:=0;
+
+ if r > da then
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=int8u(trunc(da ) )
+ else
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=int8u(trunc(r ) );
+
+ if g > da then
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=int8u(trunc(da ) )
+ else
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=int8u(trunc(g ) );
+
+ if b > da then
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=int8u(trunc(da ) )
+ else
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=int8u(trunc(b ) );
+
+end;
+
+{ comp_op_rgba_invert }
+// Dca' = (Da - Dca) * Sa + Dca.(1 - Sa)
+// Da' = Sa + Da - Sa.Da
+procedure comp_op_rgba_invert(this : pixel_formats_ptr; p : int8u_ptr; sr ,sg ,sb ,sa ,cover : unsigned );
+var
+ da ,dr ,dg ,db ,s1a : int;
+
+begin
+ sa:=(sa * cover + 255 ) shr 8;
+
+ if sa <> 0 then
+ begin
+ da :=int8u_ptr(ptrcomp(p ) + this.m_order.A )^;
+ dr :=shr_int32((da - int8u_ptr(ptrcomp(p ) + this.m_order.R )^ ) * sa + base_mask ,base_shift );
+ dg :=shr_int32((da - int8u_ptr(ptrcomp(p ) + this.m_order.G )^ ) * sa + base_mask ,base_shift );
+ db :=shr_int32((da - int8u_ptr(ptrcomp(p ) + this.m_order.B )^ ) * sa + base_mask ,base_shift );
+ s1a:=base_mask - sa;
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=
+ int8u(
+ dr + shr_int32(int8u_ptr(ptrcomp(p ) + this.m_order.R )^ * s1a + base_mask ,base_shift ) );
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=
+ int8u(
+ dg + shr_int32(int8u_ptr(ptrcomp(p ) + this.m_order.G )^ * s1a + base_mask ,base_shift ) );
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=
+ int8u(
+ db + shr_int32(int8u_ptr(ptrcomp(p ) + this.m_order.B )^ * s1a + base_mask ,base_shift ) );
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.A )^:=
+ int8u(
+ sa + da - shr_int32(sa * da + base_mask ,base_shift ) );
+
+ end;
+
+end;
+
+{ comp_op_rgba_invert_rgb }
+// Dca' = (Da - Dca) * Sca + Dca.(1 - Sa)
+// Da' = Sa + Da - Sa.Da
+procedure comp_op_rgba_invert_rgb(this : pixel_formats_ptr; p : int8u_ptr; sr ,sg ,sb ,sa ,cover : unsigned );
+var
+ da ,dr ,dg ,db ,s1a : int;
+
+begin
+ if cover < 255 then
+ begin
+ sr:=shr_int32(sr * cover + 255 ,8 );
+ sg:=shr_int32(sg * cover + 255 ,8 );
+ sb:=shr_int32(sb * cover + 255 ,8 );
+ sa:=shr_int32(sa * cover + 255 ,8 );
+
+ end;
+
+ if sa <> 0 then
+ begin
+ da :=int8u_ptr(ptrcomp(p ) + this.m_order.A )^;
+ dr :=shr_int32((da - int8u_ptr(ptrcomp(p ) + this.m_order.R )^ ) * sr + base_mask ,base_shift );
+ dg :=shr_int32((da - int8u_ptr(ptrcomp(p ) + this.m_order.G )^ ) * sg + base_mask ,base_shift );
+ db :=shr_int32((da - int8u_ptr(ptrcomp(p ) + this.m_order.B )^ ) * sb + base_mask ,base_shift );
+ s1a:=base_mask - sa;
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=
+ int8u(
+ dr + shr_int32(int8u_ptr(ptrcomp(p ) + this.m_order.R )^ * s1a + base_mask ,base_shift ) );
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=
+ int8u(
+ dg + shr_int32(int8u_ptr(ptrcomp(p ) + this.m_order.G )^ * s1a + base_mask ,base_shift ) );
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=
+ int8u(
+ db + shr_int32(int8u_ptr(ptrcomp(p ) + this.m_order.B )^ * s1a + base_mask ,base_shift ) );
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.A )^:=
+ int8u(
+ sa + da - shr_int32(sa * da + base_mask ,base_shift ) );
+
+ end;
+
+end;
+
+const
+ comp_op_table_rgba : array[0..byte(end_of_comp_op_e ) - 1 ] of func_blend_pix = (
+
+ comp_op_rgba_clear ,
+ comp_op_rgba_src ,
+ comp_op_rgba_dst ,
+ comp_op_rgba_src_over ,
+ comp_op_rgba_dst_over ,
+ comp_op_rgba_src_in ,
+ comp_op_rgba_dst_in ,
+ comp_op_rgba_src_out ,
+ comp_op_rgba_dst_out ,
+ comp_op_rgba_src_atop ,
+ comp_op_rgba_dst_atop ,
+ comp_op_rgba_xor ,
+ comp_op_rgba_plus ,
+ comp_op_rgba_minus ,
+ comp_op_rgba_multiply ,
+ comp_op_rgba_screen ,
+ comp_op_rgba_overlay ,
+ comp_op_rgba_darken ,
+ comp_op_rgba_lighten ,
+ comp_op_rgba_color_dodge ,
+ comp_op_rgba_color_burn ,
+ comp_op_rgba_hard_light ,
+ comp_op_rgba_soft_light ,
+ comp_op_rgba_difference ,
+ comp_op_rgba_exclusion ,
+ comp_op_rgba_contrast ,
+ comp_op_rgba_invert ,
+ comp_op_rgba_invert_rgb );
+
+{ COMP_OP_ADAPTOR_RGBA }
+procedure comp_op_adaptor_rgba;
+begin
+ comp_op_table_rgba[op ](
+ this ,p ,
+ (cr * ca + base_mask ) shr base_shift ,
+ (cg * ca + base_mask ) shr base_shift ,
+ (cb * ca + base_mask ) shr base_shift ,
+ ca ,cover );
+
+end;
+
+{ COMP_OP_ADAPTOR_CLIP_TO_DST_RGBA }
+procedure comp_op_adaptor_clip_to_dst_rgba_pre(this : pixel_formats_ptr; op : unsigned; p : int8u_ptr; cr ,cg ,cb ,ca ,cover : unsigned );
+var
+ da : unsigned;
+
+begin
+ da:=int8u_ptr(ptrcomp(p ) + this.m_order.A )^;
+
+ comp_op_table_rgba[op ](
+ this ,p ,
+ (cr * da + base_mask ) shr base_shift ,
+ (cg * da + base_mask ) shr base_shift ,
+ (cb * da + base_mask ) shr base_shift ,
+ (ca * da + base_mask ) shr base_shift ,
+ cover );
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_pixfmt_transposer.pas b/src/corelib/render/software/agg_pixfmt_transposer.pas
new file mode 100644
index 00000000..f11c876e
--- /dev/null
+++ b/src/corelib/render/software/agg_pixfmt_transposer.pas
@@ -0,0 +1,233 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 09.10.2006-Milano: Unit port establishment
+//
+{ agg_pixfmt_transposer.pas }
+unit
+ agg_pixfmt_transposer ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_pixfmt ,
+ agg_color ,
+ agg_rendering_buffer ;
+
+{ TYPES DEFINITION }
+type
+ pixel_formats_transposer_ptr = ^pixel_formats_transposer;
+ pixel_formats_transposer = object(pixel_formats )
+ private
+ m_pixf : pixel_formats_ptr;
+
+ public
+ constructor Construct(src : pixel_formats_ptr );
+
+ procedure attach(src : pixel_formats_ptr );
+
+ function _width : unsigned; virtual;
+ function _height : unsigned; virtual;
+
+ end;
+
+{ GLOBAL VARIABLES & CONSTANTS }
+{ GLOBAL PROCEDURES }
+ procedure pixfmt_transposer(var pixf : pixel_formats_transposer; src : pixel_formats_ptr );
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor pixel_formats_transposer.Construct;
+begin
+ inherited Construct(NIL );
+
+ attach(src );
+
+end;
+
+{ ATTACH }
+procedure pixel_formats_transposer.attach(src : pixel_formats_ptr );
+begin
+ m_pixf:=src;
+ m_rbuf:=src.m_rbuf;
+
+ m_gamma:=src.m_gamma;
+ m_apply:=src.m_apply;
+ m_order:=src.m_order;
+
+ m_comp_op :=src.m_comp_op;
+ m_step :=src.m_step;
+ m_offset :=src.m_offset;
+ m_pix_width:=src.m_pix_width;
+
+ blender:=src.blender;
+ row :=src.row;
+
+ copy_from :=src.copy_from;
+ blend_from:=src.blend_from;
+
+ for_each_pixel :=src.for_each_pixel;
+ gamma_dir_apply:=src.gamma_dir_apply;
+ gamma_inv_apply:=src.gamma_inv_apply;
+
+end;
+
+{ _WIDTH }
+function pixel_formats_transposer._width : unsigned;
+begin
+ result:=m_pixf._height;
+
+end;
+
+{ _HEIGHT }
+function pixel_formats_transposer._height : unsigned;
+begin
+ result:=m_pixf._width;
+
+end;
+
+{ transposer_copy_pixel }
+procedure transposer_copy_pixel(this : pixel_formats_transposer_ptr; x ,y : int; c : aggclr_ptr );
+begin
+ this.m_pixf.copy_pixel(this.m_pixf ,y ,x ,c );
+
+end;
+
+{ transposer_blend_pixel }
+procedure transposer_blend_pixel(this : pixel_formats_transposer_ptr; x ,y : int; c : aggclr_ptr; cover : int8u );
+begin
+ this.m_pixf.blend_pixel(this.m_pixf ,y ,x ,c ,cover );
+
+end;
+
+{ transposer_pixel }
+function transposer_pixel(this : pixel_formats_transposer_ptr; x ,y : int ) : aggclr;
+begin
+ result:=this.m_pixf.pixel(this.m_pixf ,y ,x );
+
+end;
+
+{ transposer_copy_hline }
+procedure transposer_copy_hline(this : pixel_formats_transposer_ptr; x ,y : int; len : unsigned; c : aggclr_ptr );
+begin
+ this.m_pixf.copy_vline(this.m_pixf ,y ,x ,len ,c );
+
+end;
+
+{ transposer_copy_vline }
+procedure transposer_copy_vline(this : pixel_formats_transposer_ptr; x ,y : int; len : unsigned; c : aggclr_ptr );
+begin
+ this.m_pixf.copy_hline(this.m_pixf ,y ,x ,len ,c );
+
+end;
+
+{ transposer_blend_hline }
+procedure transposer_blend_hline(this : pixel_formats_transposer_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+begin
+ this.m_pixf.blend_vline(this.m_pixf ,y ,x ,len ,c ,cover );
+
+end;
+
+{ transposer_blend_vline }
+procedure transposer_blend_vline(this : pixel_formats_transposer_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+begin
+ this.m_pixf.blend_hline(this.m_pixf ,y ,x ,len ,c ,cover );
+
+end;
+
+{ transposer_blend_solid_hspan }
+procedure transposer_blend_solid_hspan(this : pixel_formats_transposer_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+begin
+ this.m_pixf.blend_solid_vspan(this.m_pixf ,y ,x ,len ,c ,covers );
+
+end;
+
+{ transposer_blend_solid_vspan }
+procedure transposer_blend_solid_vspan(this : pixel_formats_transposer_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+begin
+ this.m_pixf.blend_solid_hspan(this.m_pixf ,y ,x ,len ,c ,covers );
+
+end;
+
+{ transposer_copy_color_hspan }
+procedure transposer_copy_color_hspan(this : pixel_formats_transposer_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr );
+begin
+ this.m_pixf.copy_color_vspan(this.m_pixf ,y ,x ,len ,colors );
+
+end;
+
+{ transposer_copy_color_vspan }
+procedure transposer_copy_color_vspan(this : pixel_formats_transposer_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr );
+begin
+ this.m_pixf.copy_color_hspan(this.m_pixf ,y ,x ,len ,colors );
+
+end;
+
+{ transposer_blend_color_hspan }
+procedure transposer_blend_color_hspan(this : pixel_formats_transposer_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+begin
+ this.m_pixf.blend_color_vspan(this.m_pixf ,y ,x ,len ,colors ,covers ,cover );
+
+end;
+
+{ transposer_blend_color_vspan }
+procedure transposer_blend_color_vspan(this : pixel_formats_transposer_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+begin
+ this.m_pixf.blend_color_hspan(this.m_pixf ,y ,x ,len ,colors ,covers ,cover );
+
+end;
+
+{ PIXFMT_TRANSPOSER }
+procedure pixfmt_transposer;
+begin
+ pixf.Construct(src );
+
+ pixf.copy_pixel :=@transposer_copy_pixel;
+ pixf.blend_pixel:=@transposer_blend_pixel;
+
+ pixf.pixel:=@transposer_pixel;
+
+ pixf.copy_hline:=@transposer_copy_hline;
+ pixf.copy_vline:=@transposer_copy_vline;
+
+ pixf.blend_hline:=@transposer_blend_hline;
+ pixf.blend_vline:=@transposer_blend_vline;
+
+ pixf.blend_solid_hspan:=@transposer_blend_solid_hspan;
+ pixf.blend_solid_vspan:=@transposer_blend_solid_vspan;
+
+ pixf.copy_color_hspan:=@transposer_copy_color_hspan;
+ pixf.copy_color_vspan:=@transposer_copy_color_vspan;
+
+ pixf.blend_color_hspan:=@transposer_blend_color_hspan;
+ pixf.blend_color_vspan:=@transposer_blend_color_vspan;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_rasterizer_cells_aa.pas b/src/corelib/render/software/agg_rasterizer_cells_aa.pas
new file mode 100644
index 00000000..61012525
--- /dev/null
+++ b/src/corelib/render/software/agg_rasterizer_cells_aa.pas
@@ -0,0 +1,1074 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+//
+// The author gratefully acknowleges the support of David Turner,
+// Robert Wilhelm, and Werner Lemberg - the authors of the FreeType
+// libray - in producing this work. See http://www.freetype.org for details.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//----------------------------------------------------------------------------
+//
+// Adaptation for 32-bit screen coordinates has been sponsored by
+// Liberty Technology Systems, Inc., visit http://lib-sys.com
+//
+// Liberty Technology Systems, Inc. is the provider of
+// PostScript and PDF technology for software developers.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 16.10.2007-Milano: Unit port establishment & Finished OK
+//
+{ agg_rasterizer_cells_aa.pas }
+unit
+ agg_rasterizer_cells_aa ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_math ,
+ agg_array ,
+ agg_scanline ;
+
+{ GLOBAL VARIABLES & CONSTANTS }
+const
+ cell_block_shift = 12;
+ cell_block_size = 1 shl cell_block_shift;
+ cell_block_mask = cell_block_size - 1;
+ cell_block_pool = 256;
+ cell_block_limit = 1024;
+
+{ TYPES DEFINITION }
+type
+// A pixel cell. There're no constructors defined and it was done
+// intentionally in order to avoid extra overhead when allocating an
+// array of cells.
+ cell_style_aa_ptr_ptr_ptr = ^cell_style_aa_ptr_ptr;
+ cell_style_aa_ptr_ptr = ^cell_style_aa_ptr;
+ cell_style_aa_ptr = ^cell_style_aa;
+ cell_style_aa = object
+ x ,y ,cover ,area : int;
+
+ left ,right : int16;
+
+ procedure initial;
+ procedure style (c : cell_style_aa_ptr );
+ function not_equal(ex ,ey : int; c : cell_style_aa_ptr ) : int;
+
+ end;
+
+ cell_block_scale_e = int;
+
+ sorted_y_ptr = ^sorted_y;
+ sorted_y = record
+ start ,
+ num : unsigned;
+
+ end;
+
+{ cell_type_ptr_ptr_ptr = ^cell_type_ptr_ptr;
+ cell_type_ptr_ptr = ^cell_type_ptr;
+ cell_type_ptr = ^cell_type;
+ cell_type = cell_style_aa; }
+
+// An internal class that implements the main rasterization algorithm.
+// Used in the rasterizer. Should not be used direcly.
+ rasterizer_cells_aa_ptr = ^rasterizer_cells_aa;
+ rasterizer_cells_aa = object
+ private
+ m_num_blocks ,
+ m_max_blocks ,
+ m_curr_block ,
+ m_num_cells : unsigned;
+
+ m_cells : cell_style_aa_ptr_ptr;
+
+ m_curr_cell_ptr : cell_style_aa_ptr;
+ m_sorted_cells ,
+ m_sorted_y : pod_vector;
+ m_curr_cell ,
+ m_style_cell : cell_style_aa;
+
+ m_min_x ,
+ m_min_y ,
+ m_max_x ,
+ m_max_y : int;
+
+ m_sorted : boolean;
+
+ public
+ constructor Construct;
+ destructor Destruct;
+
+ procedure reset;
+ procedure style(style_cell : cell_style_aa_ptr );
+ procedure line (x1 ,y1 ,x2 ,y2 : int );
+
+ function min_x : int;
+ function min_y : int;
+ function max_x : int;
+ function max_y : int;
+
+ procedure sort_cells;
+ function total_cells : unsigned;
+
+ function scanline_num_cells(y : unsigned ) : unsigned;
+ function scanline_cells (y : unsigned ) : cell_style_aa_ptr_ptr;
+
+ function sorted : boolean;
+
+ private
+ procedure set_curr_cell(x ,y : int );
+ procedure add_curr_cell;
+ procedure render_hline(ey ,x1 ,y1 ,x2 ,y2 : int );
+ procedure allocate_block;
+
+ end;
+
+//------------------------------------------------------scanline_hit_test
+ scanline_hit_test = object(scanline )
+ private
+ m_x : int;
+ m_hit : boolean;
+
+ public
+ constructor Construct(x : int );
+
+ procedure reset_spans; virtual;
+
+ procedure finalize(y_ : int ); virtual;
+ procedure add_cell(x : int; cover : unsigned ); virtual;
+ procedure add_span(x : int; len ,cover : unsigned ); virtual;
+
+ function num_spans : unsigned; virtual;
+
+ function hit : boolean;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ INITIAL }
+procedure cell_style_aa.initial;
+begin
+ x :=$7FFFFFFF;
+ y :=$7FFFFFFF;
+ cover:=0;
+ area :=0;
+ left :=-1;
+ right:=-1;
+
+end;
+
+{ STYLE }
+procedure cell_style_aa.style(c : cell_style_aa_ptr );
+begin
+ left :=c.left;
+ right:=c.right;
+
+end;
+
+{ NOT_EQUAL }
+function cell_style_aa.not_equal(ex ,ey : int; c : cell_style_aa_ptr ) : int;
+begin
+ result:=(ex - x ) or (ey - y ) or (left - c.left ) or (right - c.right );
+
+end;
+
+{ CONSTRUCT }
+constructor rasterizer_cells_aa.Construct;
+begin
+ m_num_blocks:=0;
+ m_max_blocks:=0;
+ m_curr_block:=0;
+ m_num_cells :=0;
+
+ m_cells :=NIL;
+ m_curr_cell_ptr:=NIL;
+
+ m_sorted_cells.Construct(sizeof(cell_style_aa_ptr ) );
+ m_sorted_y.Construct(sizeof(sorted_y ) );
+
+ m_min_x :=$7FFFFFFF;
+ m_min_y :=$7FFFFFFF;
+ m_max_x :=-$7FFFFFFF;
+ m_max_y :=-$7FFFFFFF;
+ m_sorted:=false;
+
+ m_style_cell.initial;
+ m_curr_cell.initial;
+
+end;
+
+{ DESTRUCT }
+destructor rasterizer_cells_aa.Destruct;
+var
+ ptr : cell_style_aa_ptr_ptr;
+
+begin
+ m_sorted_cells.Destruct;
+ m_sorted_y.Destruct;
+
+ if m_num_blocks <> 0 then
+ begin
+ ptr:=cell_style_aa_ptr_ptr(ptrcomp(m_cells ) + (m_num_blocks - 1 ) * sizeof(cell_style_aa_ptr ) );
+
+ while m_num_blocks <> 0 do
+ begin
+ dec(m_num_blocks );
+
+ agg_freemem(pointer(ptr^ ) ,cell_block_size * sizeof(cell_style_aa ) );
+
+ dec(ptrcomp(ptr ) ,sizeof(cell_style_aa_ptr ) );
+
+ end;
+
+ agg_freemem(pointer(m_cells ) ,m_max_blocks * sizeof(cell_style_aa_ptr ) );
+
+ end;
+
+end;
+
+{ RESET }
+procedure rasterizer_cells_aa.reset;
+begin
+ m_num_cells :=0;
+ m_curr_block:=0;
+
+ m_curr_cell.initial;
+ m_style_cell.initial;
+
+ m_sorted:=false;
+ m_min_x :=$7FFFFFFF;
+ m_min_y :=$7FFFFFFF;
+ m_max_x :=-$7FFFFFFF;
+ m_max_y :=-$7FFFFFFF;
+
+end;
+
+{ STYLE }
+procedure rasterizer_cells_aa.style(style_cell : cell_style_aa_ptr );
+begin
+ m_style_cell.style(style_cell );
+
+end;
+
+{ LINE }
+procedure rasterizer_cells_aa.line(x1 ,y1 ,x2 ,y2 : int );
+const
+ dx_limit = 16384 shl poly_subpixel_shift;
+
+var
+ dx ,cx ,cy ,dy ,ex1 ,ex2 ,ey1 ,ey2 ,fy1 ,fy2 ,ex ,two_fx ,area ,
+
+ x_from ,x_to ,p ,rem ,mod_ ,lift ,delta ,first ,incr : int;
+
+begin
+ dx:=x2 - x1;
+
+ if (dx >= dx_limit ) or
+ (dx <= -dx_limit ) then
+ begin
+ cx:=shr_int32(x1 + x2 ,1 );
+ cy:=shr_int32(y1 + y2 ,1 );
+
+ line(x1 ,y1 ,cx ,cy );
+ line(cx ,cy ,x2 ,y2 );
+
+ end;
+
+ dy := y2 - y1;
+ ex1:=shr_int32(x1 ,poly_subpixel_shift );
+ ex2:=shr_int32(x2 ,poly_subpixel_shift );
+ ey1:=shr_int32(y1 ,poly_subpixel_shift );
+ ey2:=shr_int32(y2 ,poly_subpixel_shift );
+ fy1:=y1 and poly_subpixel_mask;
+ fy2:=y2 and poly_subpixel_mask;
+
+ if ex1 < m_min_x then
+ m_min_x:=ex1;
+
+ if ex1 > m_max_x then
+ m_max_x:=ex1;
+
+ if ey1 < m_min_y then
+ m_min_y:=ey1;
+
+ if ey1 > m_max_y then
+ m_max_y:=ey1;
+
+ if ex2 < m_min_x then
+ m_min_x:=ex2;
+
+ if ex2 > m_max_x then
+ m_max_x:=ex2;
+
+ if ey2 < m_min_y then
+ m_min_y:=ey2;
+
+ if ey2 > m_max_y then
+ m_max_y:=ey2;
+
+ set_curr_cell(ex1 ,ey1 );
+
+// everything is on a single hline
+ if ey1 = ey2 then
+ begin
+ render_hline(ey1 ,x1 ,fy1 ,x2 ,fy2 );
+ exit;
+
+ end;
+
+// Vertical line - we have to calculate start and end cells,
+// and then - the common values of the area and coverage for
+// all cells of the line. We know exactly there's only one
+// cell, so, we don't have to call render_hline().
+ incr:=1;
+
+ if dx = 0 then
+ begin
+ ex :=shr_int32(x1 ,poly_subpixel_shift );
+ two_fx:=(x1 - (ex shl poly_subpixel_shift ) ) shl 1;
+ first :=poly_subpixel_scale;
+
+ if dy < 0 then
+ begin
+ first:=0;
+ incr :=-1;
+
+ end;
+
+ x_from:=x1;
+
+ // render_hline(ey1 ,x_from ,fy1 ,x_from ,first );
+ delta:=first - fy1;
+
+ inc(m_curr_cell.cover ,delta );
+ inc(m_curr_cell.area ,two_fx * delta );
+ inc(ey1 ,incr );
+
+ set_curr_cell(ex ,ey1 );
+
+ delta:=first + first - poly_subpixel_scale;
+ area :=two_fx * delta;
+
+ while ey1 <> ey2 do
+ begin
+ // render_hline(ey1 ,x_from ,poly_subpixel_scale - first ,x_from ,first );
+ m_curr_cell.cover:=delta;
+ m_curr_cell.area :=area;
+
+ inc(ey1 ,incr );
+
+ set_curr_cell(ex ,ey1 );
+
+ end;
+
+ // render_hline(ey1 ,x_from ,poly_subpixel_scale - first ,x_from ,fy2 );
+ delta:=fy2 - poly_subpixel_scale + first;
+
+ inc(m_curr_cell.cover ,delta );
+ inc(m_curr_cell.area ,two_fx * delta );
+
+ exit;
+
+ end;
+
+// ok, we have to render several hlines
+ p :=(poly_subpixel_scale - fy1 ) * dx;
+ first:=poly_subpixel_scale;
+
+ if dy < 0 then
+ begin
+ p :=fy1 * dx;
+ first:=0;
+ incr :=-1;
+ dy :=-dy;
+
+ end;
+
+ delta:=p div dy;
+ mod_ :=p mod dy;
+
+ if mod_ < 0 then
+ begin
+ dec(delta );
+ inc(mod_,dy );
+
+ end;
+
+ x_from:=x1 + delta;
+
+ render_hline(ey1 ,x1 ,fy1 ,x_from ,first );
+
+ inc(ey1 ,incr );
+
+ set_curr_cell(shr_int32(x_from ,poly_subpixel_shift ) ,ey1 );
+
+ if ey1 <> ey2 then
+ begin
+ p :=poly_subpixel_scale * dx;
+ lift:=p div dy;
+ rem :=p mod dy;
+
+ if rem < 0 then
+ begin
+ dec(lift );
+ inc(rem ,dy );
+
+ end;
+
+ dec(mod_ ,dy );
+
+ while ey1 <> ey2 do
+ begin
+ delta:=lift;
+
+ inc(mod_ ,rem );
+
+ if mod_ >= 0 then
+ begin
+ dec(mod_ ,dy );
+ inc(delta );
+
+ end;
+
+ x_to:=x_from + delta;
+
+ render_hline(ey1 ,x_from ,poly_subpixel_scale - first ,x_to ,first );
+
+ x_from:=x_to;
+
+ inc(ey1 ,incr );
+
+ set_curr_cell(shr_int32(x_from ,poly_subpixel_shift ) ,ey1 );
+
+ end;
+
+ end;
+
+ render_hline(ey1 ,x_from ,poly_subpixel_scale - first ,x2 ,fy2 );
+
+end;
+
+{ MIN_X }
+function rasterizer_cells_aa.min_x : int;
+begin
+ result:=m_min_x;
+
+end;
+
+{ MIN_Y }
+function rasterizer_cells_aa.min_y : int;
+begin
+ result:=m_min_y;
+
+end;
+
+{ MAX_X }
+function rasterizer_cells_aa.max_x : int;
+begin
+ result:=m_max_x;
+
+end;
+
+{ MAX_Y }
+function rasterizer_cells_aa.max_y : int;
+begin
+ result:=m_max_y;
+
+end;
+
+{ swap_cells }
+procedure swap_cells(a ,b : pointer );
+var
+ temp : pointer;
+
+begin
+ temp :=pointer(a^ );
+ pointer(a^ ):=pointer(b^ );
+ pointer(b^ ):=temp;
+
+end;
+
+const
+ qsort_threshold = 9;
+
+{ qsort_cells }
+procedure qsort_cells(start : cell_style_aa_ptr_ptr; num : unsigned );
+var
+ stack : array[0..79 ] of cell_style_aa_ptr_ptr;
+ top : cell_style_aa_ptr_ptr_ptr;
+ limit ,
+ base : cell_style_aa_ptr_ptr;
+
+ len ,x : int;
+
+ i ,j ,pivot : cell_style_aa_ptr_ptr;
+
+begin
+ limit:=cell_style_aa_ptr_ptr(ptrcomp(start ) + num * sizeof(cell_style_aa_ptr ) );
+ base :=start;
+ top :=@stack[0 ];
+
+ repeat
+ len:=(ptrcomp(limit ) - ptrcomp(base ) ) div sizeof(cell_style_aa_ptr );
+
+ if len > qsort_threshold then
+ begin
+ // we use base + len/2 as the pivot
+ pivot:=cell_style_aa_ptr_ptr(ptrcomp(base ) + (len div 2 ) * sizeof(cell_style_aa_ptr ) );
+
+ swap_cells(base ,pivot );
+
+ i:=cell_style_aa_ptr_ptr(ptrcomp(base ) + sizeof(cell_style_aa_ptr ) );
+ j:=cell_style_aa_ptr_ptr(ptrcomp(limit ) - sizeof(cell_style_aa_ptr ) );
+
+ // now ensure that *i <= *base <= *j
+ if j^^.x < i^^.x then
+ swap_cells(i ,j );
+
+ if base^^.x < i^^.x then
+ swap_cells(base ,i );
+
+ if j^^.x < base^^.x then
+ swap_cells(base ,j );
+
+ repeat
+ x:=base^^.x;
+
+ repeat
+ inc(ptrcomp(i ) ,sizeof(cell_style_aa_ptr ) );
+
+ until i^^.x >= x;
+
+ repeat
+ dec(ptrcomp(j ) ,sizeof(cell_style_aa_ptr ) );
+
+ until x >= j^^.x;
+
+ if ptrcomp(i ) > ptrcomp(j ) then
+ break;
+
+ swap_cells(i ,j );
+
+ until false;
+
+ swap_cells(base ,j );
+
+ // now, push the largest sub-array
+ if ptrcomp(j ) - ptrcomp(base ) > ptrcomp(limit ) - ptrcomp(i ) then
+ begin
+ top^:=base;
+
+ cell_style_aa_ptr_ptr_ptr(ptrcomp(top ) + sizeof(cell_style_aa_ptr_ptr ) )^:=j;
+
+ base:=i;
+
+ end
+ else
+ begin
+ top^:=i;
+
+ cell_style_aa_ptr_ptr_ptr(ptrcomp(top ) + sizeof(cell_style_aa_ptr_ptr ) )^:=limit;
+
+ limit:=j;
+
+ end;
+
+ inc(ptrcomp(top ) ,2 * sizeof(cell_style_aa_ptr_ptr ) );
+
+ end
+ else
+ begin
+ // the sub-array is small, perform insertion sort
+ j:=base;
+ i:=cell_style_aa_ptr_ptr(ptrcomp(j ) + sizeof(cell_style_aa_ptr ) );
+
+ while ptrcomp(i ) < ptrcomp(limit ) do
+ begin
+ while cell_style_aa_ptr_ptr(ptrcomp(j ) + sizeof(cell_style_aa_ptr ) )^^.x < j^^.x do
+ begin
+ swap_cells(cell_style_aa_ptr_ptr(ptrcomp(j ) + sizeof(cell_style_aa_ptr ) ) ,j );
+
+ if ptrcomp(j ) = ptrcomp(base ) then
+ break;
+
+ dec(ptrcomp(j ) ,sizeof(cell_style_aa_ptr ) );
+
+ end;
+
+ j:=i;
+
+ inc(ptrcomp(i ) ,sizeof(cell_style_aa_ptr ) );
+
+ end;
+
+ if ptrcomp(top ) > ptrcomp(@stack[0 ] ) then
+ begin
+ dec(ptrcomp(top ) ,2 * sizeof(cell_style_aa_ptr_ptr ) );
+
+ base :=top^;
+ limit:=cell_style_aa_ptr_ptr_ptr(ptrcomp(top ) + sizeof(cell_style_aa_ptr_ptr ) )^;
+
+ end
+ else
+ break;
+
+ end;
+
+ until false;
+
+end;
+
+{ SORT_CELLS }
+procedure rasterizer_cells_aa.sort_cells;
+var
+ block_ptr : cell_style_aa_ptr_ptr;
+ cell_ptr : cell_style_aa_ptr;
+
+ nb ,i ,start ,v : unsigned;
+
+ curr_y : sorted_y_ptr;
+
+begin
+//Perform sort only the first time.
+ if m_sorted then
+ exit;
+
+ add_curr_cell;
+
+ m_curr_cell.x :=$7FFFFFFF;
+ m_curr_cell.y :=$7FFFFFFF;
+ m_curr_cell.cover:=0;
+ m_curr_cell.area :=0;
+
+ if m_num_cells = 0 then
+ exit;
+
+// Allocate the array of cell pointers
+ m_sorted_cells.allocate(m_num_cells ,16 );
+
+// Allocate and zero the Y array
+ m_sorted_y.allocate(m_max_y - m_min_y + 1 ,16 );
+ m_sorted_y.zero;
+
+// Create the Y-histogram (count the numbers of cells for each Y)
+ block_ptr:=m_cells;
+
+ nb:=m_num_cells shr cell_block_shift;
+
+ while nb <> 0 do
+ begin
+ dec(nb );
+
+ cell_ptr:=block_ptr^;
+
+ inc(ptrcomp(block_ptr ) ,sizeof(cell_style_aa_ptr ) );
+
+ i:=cell_block_size;
+
+ while i <> 0 do
+ begin
+ dec(i );
+ inc(sorted_y_ptr(m_sorted_y.array_operator(cell_ptr.y - m_min_y ) ).start );
+ inc(ptrcomp(cell_ptr ) ,sizeof(cell_style_aa ) );
+
+ end;
+
+ end;
+
+ cell_ptr:=block_ptr^;
+
+ inc(ptrcomp(block_ptr ) ,sizeof(cell_style_aa_ptr ) );
+
+ i:=m_num_cells and cell_block_mask;
+
+ while i <> 0 do
+ begin
+ dec(i );
+ inc(sorted_y_ptr(m_sorted_y.array_operator(cell_ptr.y - m_min_y ) ).start );
+ inc(ptrcomp(cell_ptr ) ,sizeof(cell_style_aa ) );
+
+ end;
+
+// Convert the Y-histogram into the array of starting indexes
+ start:=0;
+ i :=0;
+
+ while i < m_sorted_y.size do
+ begin
+ v:=sorted_y_ptr(m_sorted_y.array_operator(i ) ).start;
+
+ sorted_y_ptr(m_sorted_y.array_operator(i ) ).start:=start;
+
+ inc(start ,v );
+ inc(i );
+
+ end;
+
+// Fill the cell pointer array sorted by Y
+ block_ptr:=m_cells;
+
+ nb:=m_num_cells shr cell_block_shift;
+
+ while nb <> 0 do
+ begin
+ dec(nb );
+
+ cell_ptr:=block_ptr^;
+
+ inc(ptrcomp(block_ptr ) ,sizeof(cell_style_aa_ptr ) );
+
+ i:=cell_block_size;
+
+ while i <> 0 do
+ begin
+ dec(i );
+
+ curr_y:=sorted_y_ptr(m_sorted_y.array_operator(cell_ptr.y - m_min_y ) );
+
+ cell_style_aa_ptr_ptr(m_sorted_cells.array_operator(curr_y.start + curr_y.num ) )^:=cell_ptr;
+
+ inc(curr_y.num );
+ inc(ptrcomp(cell_ptr ) ,sizeof(cell_style_aa ) );
+
+ end;
+
+ end;
+
+ cell_ptr:=block_ptr^;
+
+ inc(ptrcomp(block_ptr ) ,sizeof(cell_style_aa_ptr ) );
+
+ i:=m_num_cells and cell_block_mask;
+
+ while i <> 0 do
+ begin
+ dec(i );
+
+ curr_y:=sorted_y_ptr(m_sorted_y.array_operator(cell_ptr.y - m_min_y ) );
+
+ cell_style_aa_ptr_ptr(m_sorted_cells.array_operator(curr_y.start + curr_y.num ) )^:=cell_ptr;
+
+ inc(curr_y.num );
+ inc(ptrcomp(cell_ptr ) ,sizeof(cell_style_aa ) );
+
+ end;
+
+// Finally arrange the X-arrays
+ i:=0;
+
+ while i < m_sorted_y.size do
+ begin
+ curr_y:=sorted_y_ptr(m_sorted_y.array_operator(i ) );
+
+ if curr_y.num <> 0 then
+ qsort_cells(
+ cell_style_aa_ptr_ptr(ptrcomp(m_sorted_cells.data ) + curr_y.start * sizeof(cell_style_aa_ptr ) ) ,
+ curr_y.num );
+
+ inc(i );
+
+ end;
+
+ m_sorted:=true;
+
+end;
+
+{ TOTAL_CELLS }
+function rasterizer_cells_aa.total_cells : unsigned;
+begin
+ result:=m_num_cells;
+
+end;
+
+{ SCANLINE_NUM_CELLS }
+function rasterizer_cells_aa.scanline_num_cells(y : unsigned ) : unsigned;
+begin
+ result:=sorted_y_ptr(m_sorted_y.array_operator(y - m_min_y ) ).num;
+
+end;
+
+{ SCANLINE_CELLS }
+function rasterizer_cells_aa.scanline_cells(y : unsigned ) : cell_style_aa_ptr_ptr;
+begin
+ result:=cell_style_aa_ptr_ptr(ptrcomp(m_sorted_cells.data ) + sorted_y_ptr(m_sorted_y.array_operator(y - m_min_y ) ).start * sizeof(cell_style_aa_ptr ) );
+
+end;
+
+{ SORTED }
+function rasterizer_cells_aa.sorted : boolean;
+begin
+ result:=m_sorted;
+
+end;
+
+{ SET_CURR_CELL }
+procedure rasterizer_cells_aa.set_curr_cell(x ,y : int );
+begin
+ if m_curr_cell.not_equal(x ,y ,@m_style_cell ) <> 0 then
+ begin
+ add_curr_cell;
+
+ m_curr_cell.style(@m_style_cell );
+
+ m_curr_cell.x :=x;
+ m_curr_cell.y :=y;
+ m_curr_cell.cover:=0;
+ m_curr_cell.area :=0;
+
+ end;
+
+end;
+
+{ ADD_CURR_CELL }
+procedure rasterizer_cells_aa.add_curr_cell;
+begin
+ if m_curr_cell.area or m_curr_cell.cover <> 0 then
+ begin
+ if m_num_cells and cell_block_mask = 0 then
+ begin
+ if m_num_blocks >= cell_block_limit then
+ exit;
+
+ allocate_block;
+
+ end;
+
+ m_curr_cell_ptr^:=m_curr_cell;
+
+ inc(ptrcomp(m_curr_cell_ptr ) ,sizeof(cell_style_aa ) );
+ inc(m_num_cells );
+
+ end;
+
+end;
+
+{ RENDER_HLINE }
+procedure rasterizer_cells_aa.render_hline(ey ,x1 ,y1 ,x2 ,y2 : int );
+var
+ ex1 ,ex2 ,fx1 ,fx2 ,delta ,p ,first ,dx ,incr ,lift ,mod_ ,rem : int;
+
+begin
+ ex1:=shr_int32(x1 ,poly_subpixel_shift );
+ ex2:=shr_int32(x2 ,poly_subpixel_shift );
+ fx1:=x1 and poly_subpixel_mask;
+ fx2:=x2 and poly_subpixel_mask;
+
+// trivial case. Happens often
+ if y1 = y2 then
+ begin
+ set_curr_cell(ex2 ,ey );
+ exit;
+
+ end;
+
+// everything is located in a single cell. That is easy!
+ if ex1 = ex2 then
+ begin
+ delta:=y2 - y1;
+
+ inc(m_curr_cell.cover ,delta );
+ inc(m_curr_cell.area ,(fx1 + fx2 ) * delta );
+
+ exit;
+
+ end;
+
+// ok, we'll have to render a run of adjacent cells on the same
+// hline...
+ p :=(poly_subpixel_scale - fx1 ) * (y2 - y1 );
+ first:=poly_subpixel_scale;
+ incr :=1;
+
+ dx:=x2 - x1;
+
+ if dx < 0 then
+ begin
+ p :=fx1 * (y2 - y1 );
+ first:=0;
+ incr :=-1;
+ dx :=-dx;
+
+ end;
+
+ delta:=p div dx;
+ mod_ :=p mod dx;
+
+ if mod_ < 0 then
+ begin
+ dec(delta );
+ inc(mod_ ,dx );
+
+ end;
+
+ inc(m_curr_cell.cover ,delta );
+ inc(m_curr_cell.area ,(fx1 + first ) * delta );
+ inc(ex1 ,incr );
+
+ set_curr_cell(ex1 ,ey );
+
+ inc(y1 ,delta );
+
+ if ex1 <> ex2 then
+ begin
+ p :=poly_subpixel_scale * (y2 - y1 + delta );
+ lift:=p div dx;
+ rem :=p mod dx;
+
+ if rem < 0 then
+ begin
+ dec(lift );
+ inc(rem ,dx );
+
+ end;
+
+ dec(mod_ ,dx );
+
+ while ex1 <> ex2 do
+ begin
+ delta:=lift;
+
+ inc(mod_ ,rem );
+
+ if mod_ >= 0 then
+ begin
+ dec(mod_ ,dx );
+ inc(delta );
+
+ end;
+
+ inc(m_curr_cell.cover ,delta );
+ inc(m_curr_cell.area ,poly_subpixel_scale * delta );
+
+ inc(y1 ,delta );
+ inc(ex1 ,incr );
+
+ set_curr_cell(ex1 ,ey );
+
+ end;
+
+ end;
+
+ delta:=y2 - y1;
+
+ inc(m_curr_cell.cover ,delta );
+ inc(m_curr_cell.area ,(fx2 + poly_subpixel_scale - first ) * delta );
+
+end;
+
+{ ALLOCATE_BLOCK }
+procedure rasterizer_cells_aa.allocate_block;
+var
+ new_cells : cell_style_aa_ptr_ptr;
+
+begin
+ if m_curr_block >= m_num_blocks then
+ begin
+ if m_num_blocks >= m_max_blocks then
+ begin
+ agg_getmem(pointer(new_cells ) ,(m_max_blocks + cell_block_pool ) * sizeof(cell_style_aa_ptr ) );
+
+ if m_cells <> NIL then
+ begin
+ move(m_cells^ ,new_cells^ ,m_max_blocks * sizeof(cell_style_aa_ptr ) );
+
+ agg_freemem(pointer(m_cells ) ,m_max_blocks * sizeof(cell_style_aa_ptr ) );
+
+ end;
+
+ m_cells:=new_cells;
+
+ inc(m_max_blocks ,cell_block_pool );
+
+ end;
+
+ agg_getmem(
+ pointer(cell_style_aa_ptr_ptr(ptrcomp(m_cells ) + m_num_blocks * sizeof(cell_style_aa_ptr ) )^ ) ,
+ cell_block_size * sizeof(cell_style_aa ) );
+
+ inc(m_num_blocks );
+
+ end;
+
+ m_curr_cell_ptr:=cell_style_aa_ptr_ptr(ptrcomp(m_cells ) + m_curr_block * sizeof(cell_style_aa_ptr ) )^;
+
+ inc(m_curr_block );
+
+end;
+
+{ CONSTRUCT }
+constructor scanline_hit_test.Construct;
+begin
+ m_x :=x;
+ m_hit:=false;
+
+end;
+
+{ RESET_SPANS }
+procedure scanline_hit_test.reset_spans;
+begin
+end;
+
+{ FINALIZE }
+procedure scanline_hit_test.finalize;
+begin
+end;
+
+{ ADD_CELL }
+procedure scanline_hit_test.add_cell;
+begin
+ if m_x = x then
+ m_hit:=true;
+
+end;
+
+{ ADD_SPAN }
+procedure scanline_hit_test.add_span;
+begin
+ if (m_x >= x ) and
+ (m_x < x + len ) then
+ m_hit:=true;
+
+end;
+
+{ NUM_SPANS }
+function scanline_hit_test.num_spans;
+begin
+ result:=1;
+
+end;
+
+{ HIT }
+function scanline_hit_test.hit;
+begin
+ result:=m_hit;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_rasterizer_compound_aa.pas b/src/corelib/render/software/agg_rasterizer_compound_aa.pas
new file mode 100644
index 00000000..c14b78c7
--- /dev/null
+++ b/src/corelib/render/software/agg_rasterizer_compound_aa.pas
@@ -0,0 +1,1062 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+//
+// The author gratefully acknowleges the support of David Turner,
+// Robert Wilhelm, and Werner Lemberg - the authors of the FreeType
+// library - in producing this work. See http://www.freetype.org for details.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//----------------------------------------------------------------------------
+//
+// Adaptation for 32-bit screen coordinates has been sponsored by
+// Liberty Technology Systems, Inc., visit http://lib-sys.com
+//
+// Liberty Technology Systems, Inc. is the provider of
+// PostScript and PDF technology for software developers.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 17.10.2007-Milano: Finished OK
+// 16.10.2007-Milano: Unit port establishment
+//
+{ agg_rasterizer_compound_aa.pas }
+unit
+ agg_rasterizer_compound_aa ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_array ,
+ agg_rasterizer_cells_aa ,
+ agg_rasterizer_sl_clip ,
+ agg_vertex_source ,
+ agg_scanline ;
+
+{ GLOBAL VARIABLES & CONSTANTS }
+const
+ aa_shift = 8;
+ aa_scale = 1 shl aa_shift;
+ aa_mask = aa_scale - 1;
+ aa_scale2 = aa_scale * 2;
+ aa_mask2 = aa_scale2 - 1;
+
+{ TYPES DEFINITION }
+type
+ layer_order_e = (layer_unsorted ,layer_direct ,layer_inverse );
+
+ aa_scale_e = int;
+
+ style_info_ptr = ^style_info;
+ style_info = record
+ start_cell ,
+ num_cells : unsigned;
+
+ last_x : int;
+
+ end;
+
+ cell_info_ptr = ^cell_info;
+ cell_info = record
+ x ,area ,cover : int;
+
+ end;
+
+ rasterizer_compound_aa_ptr = ^rasterizer_compound_aa;
+ rasterizer_compound_aa = object
+ //private
+ t_conv : ras_conv_ptr;
+
+ m_outline : rasterizer_cells_aa;
+ m_clipper : rasterizer_sl_ptr;
+
+ m_filling_rule : filling_rule_e;
+ m_layer_order : layer_order_e;
+
+ m_styles , // Active Styles
+ m_ast , // Active Style Table (unique values)
+ m_asm , // Active Style Mask
+ m_cells ,
+
+ m_cover_buf : pod_vector;
+ m_master_alpha : pod_bvector;
+
+ m_min_style ,
+ m_max_style ,
+ m_scan_y ,
+ m_sl_start : int;
+ m_sl_len : unsigned;
+
+ public
+ constructor Construct(clip : rasterizer_sl_ptr );
+ destructor Destruct; virtual;
+
+ procedure reset;
+ procedure reset_clipping;
+ procedure clip_box(x1 ,y1 ,x2 ,y2 : double );
+
+ procedure filling_rule(filling_rule_ : filling_rule_e );
+ procedure layer_order (order : layer_order_e );
+ procedure master_alpha(style_ : int; alpha : double );
+
+ procedure styles (left ,right : int );
+ procedure move_to(x ,y : int ); virtual; abstract;
+ procedure line_to(x ,y : int );
+
+ procedure move_to_d(x ,y : double ); virtual; abstract;
+ procedure line_to_d(x ,y : double );
+
+ procedure add_vertex(x ,y : double; cmd : unsigned ); virtual; abstract;
+
+ procedure edge (x1 ,y1 ,x2 ,y2 : int );
+ procedure edge_d(x1 ,y1 ,x2 ,y2 : double );
+
+ procedure add_path(vs : vertex_source_ptr; path_id : unsigned = 0 );
+
+ function min_x : int;
+ function min_y : int;
+ function max_x : int;
+ function max_y : int;
+ function min_style : int;
+ function max_style : int;
+
+ procedure sort;
+ function rewind_scanlines : boolean;
+ function sweep_styles : unsigned;
+ function scanline_start : int;
+ function scanline_length : unsigned;
+ function style(style_idx : unsigned ) : unsigned;
+
+ function allocate_cover_buffer(len : unsigned ) : cover_type_ptr;
+
+ function navigate_scanline(y : int ) : boolean;
+
+ function hit_test(tx ,ty : int ) : boolean;
+
+ function calculate_alpha(area : int; master_alpha_ : unsigned ) : unsigned;
+ function sweep_scanline (sl : scanline_ptr; style_idx : int ) : boolean;
+
+ private
+ procedure add_style(style_id : int );
+ procedure allocate_master_alpha;
+
+ end;
+
+ rasterizer_compound_aa_int = object(rasterizer_compound_aa )
+ private
+ t_clip : rasterizer_sl_clip_int;
+
+ m_start_x ,
+ m_start_y : int;
+
+ public
+ constructor Construct(clip : rasterizer_sl_ptr = NIL );
+ destructor Destruct; virtual;
+
+ procedure move_to (x ,y : int ); virtual;
+ procedure move_to_d(x ,y : double ); virtual;
+
+ procedure add_vertex(x ,y : double; cmd : unsigned ); virtual;
+
+ end;
+
+ rasterizer_compound_aa_dbl = object(rasterizer_compound_aa )
+ private
+ t_clip : rasterizer_sl_clip_dbl;
+
+ m_start_x ,
+ m_start_y : double;
+
+ public
+ constructor Construct(clip : rasterizer_sl_ptr = NIL );
+ destructor Destruct; virtual;
+
+ procedure move_to (x ,y : int ); virtual;
+ procedure move_to_d(x ,y : double ); virtual;
+
+ procedure add_vertex(x ,y : double; cmd : unsigned ); virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor rasterizer_compound_aa.Construct(clip : rasterizer_sl_ptr );
+begin
+ m_clipper:=clip;
+ t_conv :=m_clipper.conv_type;
+
+ m_outline.Construct;
+
+ m_filling_rule:=fill_non_zero;
+ m_layer_order :=layer_direct;
+
+ m_styles.Construct(sizeof(style_info ) ); // Active Styles
+ m_ast.Construct(sizeof(unsigned ) ); // Active Style Table (unique values)
+ m_asm.Construct(sizeof(int8u ) ); // Active Style Mask
+ m_cells.Construct(sizeof(cell_info ) );
+ m_cover_buf.Construct(sizeof(cover_type ) );
+ m_master_alpha.Construct(sizeof(unsigned ) );
+
+ m_min_style:=$7FFFFFFF;
+ m_max_style:=-$7FFFFFFF;
+ m_scan_y :=$7FFFFFFF;
+ m_sl_start :=0;
+ m_sl_len :=0;
+
+end;
+
+{ DESTRUCT }
+destructor rasterizer_compound_aa.Destruct;
+begin
+ m_outline.Destruct;
+ m_styles.Destruct;
+ m_ast.Destruct;
+ m_asm.Destruct;
+ m_cells.Destruct;
+ m_cover_buf.Destruct;
+ m_master_alpha.Destruct;
+
+end;
+
+{ RESET }
+procedure rasterizer_compound_aa.reset;
+begin
+ m_outline.reset;
+
+ m_min_style:=$7FFFFFFF;
+ m_max_style:=-$7FFFFFFF;
+ m_scan_y :=$7FFFFFFF;
+ m_sl_start :=0;
+ m_sl_len :=0;
+
+end;
+
+{ RESET_CLIPPING }
+procedure rasterizer_compound_aa.reset_clipping;
+begin
+ reset;
+ m_clipper.reset_clipping;
+
+end;
+
+{ CLIP_BOX }
+procedure rasterizer_compound_aa.clip_box(x1 ,y1 ,x2 ,y2 : double );
+begin
+ reset;
+ m_clipper.clip_box(
+ t_conv.upscale(x1 ) ,t_conv.upscale(y1 ) ,
+ t_conv.upscale(x2 ) ,t_conv.upscale(y2 ) );
+
+end;
+
+{ FILLING_RULE }
+procedure rasterizer_compound_aa.filling_rule(filling_rule_ : filling_rule_e );
+begin
+ m_filling_rule:=filling_rule_;
+
+end;
+
+{ LAYER_ORDER }
+procedure rasterizer_compound_aa.layer_order(order : layer_order_e );
+begin
+ m_layer_order:=order;
+
+end;
+
+{ MASTER_ALPHA }
+procedure rasterizer_compound_aa.master_alpha(style_ : int; alpha : double );
+var
+ uv : unsigned;
+
+begin
+ if style_ >= 0 then
+ begin
+ uv:=aa_mask;
+
+ while int(m_master_alpha.size ) <= style_ do
+ m_master_alpha.add(@uv );
+
+ unsigned_ptr(m_master_alpha.array_operator(style_ ) )^:=uround(alpha * aa_mask );
+
+ end;
+
+end;
+
+{ STYLES }
+procedure rasterizer_compound_aa.styles(left ,right : int );
+var
+ cell : cell_style_aa;
+
+begin
+ cell.initial;
+
+ cell.left :=int16(left );
+ cell.right:=int16(right );
+
+ m_outline.style(@cell );
+
+ if (left >= 0 ) and
+ (left < m_min_style ) then
+ m_min_style:=left;
+
+ if (left >= 0 ) and
+ (left > m_max_style ) then
+ m_max_style:=left;
+
+ if (right >= 0 ) and
+ (right < m_min_style ) then
+ m_min_style:=right;
+
+ if (right >= 0 ) and
+ (right > m_max_style ) then
+ m_max_style:=right;
+
+end;
+
+{ LINE_TO }
+procedure rasterizer_compound_aa.line_to(x ,y : int );
+begin
+ m_clipper.line_to(@m_outline ,t_conv.downscale(x ) ,t_conv.downscale(y ) );
+
+end;
+
+{ LINE_TO_D }
+procedure rasterizer_compound_aa.line_to_d(x ,y : double );
+begin
+ m_clipper.line_to(@m_outline ,t_conv.upscale(x ) ,t_conv.upscale(y ) );
+
+end;
+
+{ EDGE }
+procedure rasterizer_compound_aa.edge(x1 ,y1 ,x2 ,y2 : int );
+begin
+ if m_outline.sorted then
+ reset;
+
+ m_clipper.move_to(t_conv.downscale(x1 ) ,t_conv.downscale(y1 ) );
+ m_clipper.line_to(@m_outline ,t_conv.downscale(x2 ) ,t_conv.downscale(y2 ) );
+
+end;
+
+{ EDGE_D }
+procedure rasterizer_compound_aa.edge_d(x1 ,y1 ,x2 ,y2 : double );
+begin
+ if m_outline.sorted then
+ reset;
+
+ m_clipper.move_to(t_conv.upscale(x1 ) ,t_conv.upscale(y1 ) );
+ m_clipper.line_to(@m_outline ,t_conv.upscale(x2 ) ,t_conv.upscale(y2 ) );
+
+end;
+
+{ ADD_PATH }
+procedure rasterizer_compound_aa.add_path(vs : vertex_source_ptr; path_id : unsigned = 0 );
+var
+ x ,y : double;
+ cmd : unsigned;
+
+begin
+ vs.rewind(path_id );
+
+ if m_outline.sorted then
+ reset;
+
+ cmd:=vs.vertex(@x ,@y );
+
+ while not is_stop(cmd ) do
+ begin
+ add_vertex(x ,y ,cmd );
+
+ cmd:=vs.vertex(@x ,@y );
+
+ end;
+
+end;
+
+{ MIN_X }
+function rasterizer_compound_aa.min_x : int;
+begin
+ result:=m_outline.min_x;
+
+end;
+
+{ MIN_Y }
+function rasterizer_compound_aa.min_y : int;
+begin
+ result:=m_outline.min_y;
+
+end;
+
+{ MAX_X }
+function rasterizer_compound_aa.max_x : int;
+begin
+ result:=m_outline.max_x;
+
+end;
+
+{ MAX_Y }
+function rasterizer_compound_aa.max_y : int;
+begin
+ result:=m_outline.max_y;
+
+end;
+
+{ MIN_STYLE }
+function rasterizer_compound_aa.min_style : int;
+begin
+ result:=m_min_style
+
+end;
+
+{ MAX_STYLE }
+function rasterizer_compound_aa.max_style : int;
+begin
+ result:=m_max_style
+
+end;
+
+{ SORT }
+procedure rasterizer_compound_aa.sort;
+begin
+ m_outline.sort_cells;
+
+end;
+
+{ REWIND_SCANLINES }
+function rasterizer_compound_aa.rewind_scanlines : boolean;
+begin
+ m_outline.sort_cells;
+
+ if m_outline.total_cells = 0 then
+ begin
+ result:=false;
+
+ exit;
+
+ end;
+
+ if m_max_style < m_min_style then
+ begin
+ result:=false;
+
+ exit;
+
+ end;
+
+ m_scan_y:=m_outline.min_y;
+
+ m_styles.allocate(m_max_style - m_min_style + 2 ,128 );
+
+ allocate_master_alpha;
+
+ result:=true;
+
+end;
+
+{ SWEEP_STYLES }
+function rasterizer_compound_aa.sweep_styles : unsigned;
+var
+ num_cells ,num_styles ,i ,start_cell ,uv ,v ,style_id : unsigned;
+
+ curr_cell : cell_style_aa_ptr;
+ style_ ,st : style_info_ptr;
+
+ cells : cell_style_aa_ptr_ptr;
+ cell : cell_info_ptr;
+
+ ra : range_adaptor;
+
+begin
+ repeat
+ if m_scan_y > m_outline.max_y then
+ begin
+ result:=0;
+
+ exit;
+
+ end;
+
+ num_cells :=m_outline.scanline_num_cells(m_scan_y );
+ cells :=m_outline.scanline_cells (m_scan_y );
+ num_styles:=m_max_style - m_min_style + 2;
+
+ m_cells.allocate(num_cells * 2 ,256 ); // Each cell can have two styles
+ m_ast.capacity (num_styles ,64 );
+ m_asm.allocate (shr_int32(num_styles + 7 ,3 ) , 8 );
+ m_asm.zero;
+
+ if num_cells <> 0 then
+ begin
+ // Pre-add zero (for no-fill style, that is, -1).
+ // We need that to ensure that the "-1 style" would go first.
+ int8u_ptr(m_asm.array_operator(0 ) )^:=int8u_ptr(m_asm.array_operator(0 ) )^ or 1;
+
+ uv:=0;
+
+ m_ast.add(@uv );
+
+ style_:=m_styles.array_operator(0 );
+
+ style_.start_cell:=0;
+ style_.num_cells :=0;
+ style_.last_x :=-$7FFFFFFF;
+
+ m_sl_start:=cells^^.x;
+ m_sl_len :=
+ cell_style_aa_ptr_ptr(ptrcomp(cells ) + (num_cells - 1 ) * sizeof(cell_style_aa_ptr ) )^^.x
+ - m_sl_start + 1;
+
+ while num_cells <> 0 do
+ begin
+ dec(num_cells );
+
+ curr_cell:=cells^;
+
+ inc(ptrcomp(cells ) ,sizeof(cell_style_aa_ptr ) );
+
+ add_style(curr_cell.left );
+ add_style(curr_cell.right );
+
+ end;
+
+ // Convert the Y-histogram into the array of starting indexes
+ start_cell:=0;
+
+ i:=0;
+
+ while i < m_ast.size do
+ begin
+ st:=style_info_ptr(m_styles.array_operator(unsigned_ptr(m_ast.array_operator(i ) )^ ) );
+
+ v:=st.start_cell;
+
+ st.start_cell:=start_cell;
+
+ inc(start_cell ,v );
+ inc(i );
+
+ end;
+
+ cells :=m_outline.scanline_cells (m_scan_y );
+ num_cells:=m_outline.scanline_num_cells(m_scan_y );
+
+ while num_cells <> 0 do
+ begin
+ dec(num_cells );
+
+ curr_cell:=cells^;
+
+ inc(ptrcomp(cells ) ,sizeof(cell_style_aa_ptr ) );
+
+ if curr_cell.left < 0 then
+ style_id:=0
+ else
+ style_id:=curr_cell.left - m_min_style + 1;
+
+ style_:=m_styles.array_operator(style_id );
+
+ if curr_cell.x = style_.last_x then
+ begin
+ cell:=m_cells.array_operator(style_.start_cell + style_.num_cells - 1 );
+
+ inc(cell.area ,curr_cell.area );
+ inc(cell.cover ,curr_cell.cover );
+
+ end
+ else
+ begin
+ cell:=m_cells.array_operator(style_.start_cell + style_.num_cells );
+
+ cell.x :=curr_cell.x;
+ cell.area :=curr_cell.area;
+ cell.cover :=curr_cell.cover;
+ style_.last_x:=curr_cell.x;
+
+ inc(style_.num_cells );
+
+ end;
+
+ if curr_cell.right < 0 then
+ style_id:=0
+ else
+ style_id:=curr_cell.right - m_min_style + 1;
+
+ style_:=m_styles.array_operator(style_id );
+
+ if curr_cell.x = style_.last_x then
+ begin
+ cell:=m_cells.array_operator(style_.start_cell + style_.num_cells - 1 );
+
+ dec(cell.area ,curr_cell.area );
+ dec(cell.cover ,curr_cell.cover );
+
+ end
+ else
+ begin
+ cell:=m_cells.array_operator(style_.start_cell + style_.num_cells );
+
+ cell.x :=curr_cell.x;
+ cell.area :=-curr_cell.area;
+ cell.cover :=-curr_cell.cover;
+ style_.last_x:=curr_cell.x;
+
+ inc(style_.num_cells );
+
+ end;
+
+ end;
+
+ end;
+
+ if m_ast.size > 1 then
+ break;
+
+ inc(m_scan_y );
+
+ until false;
+
+ inc(m_scan_y );
+
+ if m_layer_order <> layer_unsorted then
+ begin
+ ra.Construct(@m_ast ,1 ,m_ast.size - 1 );
+
+ if m_layer_order = layer_direct then
+ quick_sort(@ra ,@unsigned_greater )
+ else
+ quick_sort(@ra ,@unsigned_less );
+
+ end;
+
+ result:=m_ast.size - 1;
+
+end;
+
+{ SCANLINE_START }
+function rasterizer_compound_aa.scanline_start : int;
+begin
+ result:=m_sl_start;
+
+end;
+
+{ SCANLINE_LENGTH }
+function rasterizer_compound_aa.scanline_length : unsigned;
+begin
+ result:=m_sl_len;
+
+end;
+
+{ STYLE }
+function rasterizer_compound_aa.style(style_idx : unsigned ) : unsigned;
+begin
+ result:=unsigned_ptr(m_ast.array_operator(style_idx + 1 ) )^ + m_min_style - 1;
+
+end;
+
+{ ALLOCATE_COVER_BUFFER }
+function rasterizer_compound_aa.allocate_cover_buffer(len : unsigned ) : cover_type_ptr;
+begin
+ m_cover_buf.allocate(len ,256 );
+
+ result:=m_cover_buf.array_operator(0 );
+
+end;
+
+{ NAVIGATE_SCANLINE }
+function rasterizer_compound_aa.navigate_scanline(y : int ) : boolean;
+begin
+ m_outline.sort_cells;
+
+ if m_outline.total_cells = 0 then
+ begin
+ result:=false;
+
+ exit;
+
+ end;
+
+ if m_max_style < m_min_style then
+ begin
+ result:=false;
+
+ exit;
+
+ end;
+
+ if (y < m_outline.min_y ) or
+ (y > m_outline.max_y ) then
+ begin
+ result:=false;
+
+ exit;
+
+ end;
+
+ m_scan_y:=y;
+
+ m_styles.allocate(m_max_style - m_min_style + 2 ,128 );
+ allocate_master_alpha;
+
+ result:=true;
+
+end;
+
+{ HIT_TEST }
+function rasterizer_compound_aa.hit_test(tx ,ty : int ) : boolean;
+var
+ num_styles : unsigned;
+
+ sl : scanline_hit_test;
+
+begin
+ if not navigate_scanline(ty ) then
+ begin
+ result:=false;
+
+ exit;
+
+ end;
+
+ num_styles:=sweep_styles;
+
+ if num_styles <= 0 then
+ begin
+ result:=false;
+
+ exit;
+
+ end;
+
+ sl.Construct (tx );
+ sweep_scanline(@sl ,-1 );
+
+ result:=sl.hit();
+
+end;
+
+{ CALCULATE_ALPHA }
+function rasterizer_compound_aa.calculate_alpha(area : int; master_alpha_ : unsigned ) : unsigned;
+var
+ cover : int;
+
+begin
+ cover:=shr_int32(area ,poly_subpixel_shift * 2 + 1 - aa_shift );
+
+ if cover < 0 then
+ cover:=-cover;
+
+ if m_filling_rule = fill_even_odd then
+ begin
+ cover:=cover and aa_mask2;
+
+ if cover > aa_scale then
+ cover:=aa_scale2 - cover;
+
+ end;
+
+ if cover > aa_mask then
+ cover:=aa_mask;
+
+ result:=shr_int32(cover * master_alpha_ + aa_mask ,aa_shift );
+
+end;
+
+{ SWEEP_SCANLINE }
+function rasterizer_compound_aa.sweep_scanline(sl : scanline_ptr; style_idx : int ) : boolean;
+var
+ scan_y ,cover ,x ,area : int;
+
+ master_alpha_ ,num_cells ,alpha : unsigned;
+
+ st : style_info_ptr;
+
+ cell : cell_info_ptr;
+
+begin
+ scan_y:=m_scan_y - 1;
+
+ if scan_y > m_outline.max_y then
+ begin
+ result:=false;
+
+ exit;
+
+ end;
+
+ sl.reset_spans;
+
+ master_alpha_:=aa_mask;
+
+ if style_idx < 0 then
+ style_idx:=0
+ else
+ begin
+ inc(style_idx );
+
+ master_alpha_:=
+ unsigned_ptr(
+ m_master_alpha.array_operator(
+ unsigned_ptr(
+ m_ast.array_operator(style_idx ) )^ + m_min_style - 1 ) )^;
+
+ end;
+
+ st :=m_styles.array_operator(unsigned_ptr(m_ast.array_operator(style_idx ) )^ );
+ num_cells:=st.num_cells;
+ cell :=m_cells.array_operator(st.start_cell );
+ cover :=0;
+
+ while num_cells <> 0 do
+ begin
+ dec(num_cells );
+
+ x :=cell.x;
+ area:=cell.area;
+
+ inc(cover ,cell.cover );
+ inc(ptrcomp(cell ) ,sizeof(cell_info ) );
+
+ if area <> 0 then
+ begin
+ alpha:=calculate_alpha((cover shl (poly_subpixel_shift + 1 ) ) - area ,master_alpha_ );
+
+ sl.add_cell(x ,alpha );
+
+ inc(x );
+
+ end;
+
+ if (num_cells <> 0 ) and
+ (cell.x > x ) then
+ begin
+ alpha:=calculate_alpha(cover shl (poly_subpixel_shift + 1 ) ,master_alpha_ );
+
+ if alpha <> 0 then
+ sl.add_span(x ,cell.x - x ,alpha );
+
+ end;
+
+ end;
+
+ if sl.num_spans = 0 then
+ begin
+ result:=false;
+
+ exit;
+
+ end;
+
+ sl.finalize(scan_y );
+
+ result:=true;
+
+end;
+
+{ ADD_STYLE }
+procedure rasterizer_compound_aa.add_style(style_id : int );
+var
+ nbyte ,mask : unsigned;
+
+ style_ : style_info_ptr;
+
+ uv : unsigned;
+
+begin
+ if style_id < 0 then
+ style_id:=0
+ else
+ dec(style_id ,m_min_style - 1 );
+
+ nbyte:=shr_int32(style_id ,3 );
+ mask :=1 shl (style_id and 7 );
+
+ style_:=m_styles.array_operator(style_id );
+
+ if int8u_ptr(m_asm.array_operator(nbyte ) )^ and mask = 0 then
+ begin
+ uv:=style_id;
+
+ m_ast.add(@uv );
+
+ int8u_ptr(m_asm.array_operator(nbyte ) )^:=
+ int8u_ptr(m_asm.array_operator(nbyte ) )^ or mask;
+
+ style_.start_cell:=0;
+ style_.num_cells :=0;
+ style_.last_x :=-$7FFFFFFF;
+
+ end;
+
+ inc(style_.start_cell );
+
+end;
+
+{ ALLOCATE_MASTER_ALPHA }
+procedure rasterizer_compound_aa.allocate_master_alpha;
+var
+ uv : unsigned;
+
+begin
+ uv:=aa_mask;
+
+ while int(m_master_alpha.size ) <= m_max_style do
+ m_master_alpha.add(@uv );
+
+end;
+
+{ CONSTRUCT }
+constructor rasterizer_compound_aa_int.Construct(clip : rasterizer_sl_ptr = NIL );
+begin
+ if clip <> NIL then
+ inherited Construct(clip )
+ else
+ begin
+ t_clip.Construct;
+
+ inherited Construct(@t_clip );
+
+ end;
+
+ m_start_x:=0;
+ m_start_y:=0;
+
+end;
+
+{ DESTRUCT }
+destructor rasterizer_compound_aa_int.Destruct;
+begin
+ inherited Destruct;
+
+end;
+
+{ MOVE_TO }
+procedure rasterizer_compound_aa_int.move_to(x ,y : int );
+begin
+ if m_outline.sorted then
+ reset;
+
+ m_start_x:=int_ptr(t_conv.downscale(x ) )^;
+ m_start_y:=int_ptr(t_conv.downscale(y ) )^;
+
+ m_clipper.move_to(@m_start_x ,@m_start_y );
+
+end;
+
+{ MOVE_TO_D }
+procedure rasterizer_compound_aa_int.move_to_d(x ,y : double );
+begin
+ if m_outline.sorted then
+ reset;
+
+ m_start_x:=int_ptr(t_conv.upscale(x ) )^;
+ m_start_y:=int_ptr(t_conv.upscale(y ) )^;
+
+ m_clipper.move_to(@m_start_x ,@m_start_y );
+
+end;
+
+{ ADD_VERTEX }
+procedure rasterizer_compound_aa_int.add_vertex(x ,y : double; cmd : unsigned );
+begin
+ if is_move_to(cmd ) then
+ move_to_d(x ,y )
+ else
+ if is_vertex(cmd ) then
+ line_to_d(x ,y )
+ else
+ if is_close(cmd ) then
+ m_clipper.line_to(@m_outline ,@m_start_x ,@m_start_y );
+
+end;
+
+{ CONSTRUCT }
+constructor rasterizer_compound_aa_dbl.Construct(clip : rasterizer_sl_ptr = NIL );
+begin
+ if clip <> NIL then
+ inherited Construct(clip )
+ else
+ begin
+ t_clip.Construct;
+
+ inherited Construct(@t_clip );
+
+ end;
+
+ m_start_x:=0;
+ m_start_y:=0;
+
+end;
+
+{ DESTRUCT }
+destructor rasterizer_compound_aa_dbl.Destruct;
+begin
+ inherited Destruct;
+
+end;
+
+{ MOVE_TO }
+procedure rasterizer_compound_aa_dbl.move_to(x ,y : int );
+begin
+ if m_outline.sorted then
+ reset;
+
+ m_start_x:=double_ptr(t_conv.downscale(x ) )^;
+ m_start_y:=double_ptr(t_conv.downscale(y ) )^;
+
+ m_clipper.move_to(@m_start_x ,@m_start_y );
+
+end;
+
+{ MOVE_TO_D }
+procedure rasterizer_compound_aa_dbl.move_to_d(x ,y : double );
+begin
+ if m_outline.sorted then
+ reset;
+
+ m_start_x:=double_ptr(t_conv.upscale(x ) )^;
+ m_start_y:=double_ptr(t_conv.upscale(y ) )^;
+
+ m_clipper.move_to(@m_start_x ,@m_start_y );
+
+end;
+
+{ ADD_VERTEX }
+procedure rasterizer_compound_aa_dbl.add_vertex(x ,y : double; cmd : unsigned );
+begin
+ if is_move_to(cmd ) then
+ move_to_d(x ,y )
+ else
+ if is_vertex(cmd ) then
+ line_to_d(x ,y )
+ else
+ if is_close(cmd ) then
+ m_clipper.line_to(@m_outline ,@m_start_x ,@m_start_y );
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_rasterizer_outline.pas b/src/corelib/render/software/agg_rasterizer_outline.pas
new file mode 100644
index 00000000..084f1082
--- /dev/null
+++ b/src/corelib/render/software/agg_rasterizer_outline.pas
@@ -0,0 +1,163 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 15.01.2006-Milano: Unit port establishment
+//
+{ agg_rasterizer_outline.pas }
+unit
+ agg_rasterizer_outline ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_renderer_primitives ,
+ agg_vertex_source ;
+
+{ TYPES DEFINITION }
+type
+ rasterizer_outline_ptr = ^rasterizer_outline;
+ rasterizer_outline = object
+ m_ren : renderer_primitives_ptr;
+
+ m_start_x ,
+ m_start_y : int;
+
+ m_vertices : unsigned;
+
+ constructor Construct(ren : renderer_primitives_ptr );
+
+ procedure move_to(x ,y : int );
+ procedure line_to(x ,y : int );
+
+ procedure move_to_d(x ,y : double );
+ procedure line_to_d(x ,y : double );
+ procedure close;
+
+ procedure add_vertex(x ,y : double; cmd : unsigned );
+ procedure add_path (vs : vertex_source_ptr; path_id : unsigned = 0 );
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor rasterizer_outline.Construct;
+begin
+ m_ren:=ren;
+
+ m_start_x:=0;
+ m_start_y:=0;
+
+ m_vertices:=0;
+
+end;
+
+{ MOVE_TO }
+procedure rasterizer_outline.move_to;
+begin
+ m_vertices:=1;
+
+ m_start_x:=x;
+ m_start_y:=y;
+
+ m_ren.move_to(x ,y );
+
+end;
+
+{ LINE_TO }
+procedure rasterizer_outline.line_to;
+begin
+ inc(m_vertices );
+
+ m_ren.line_to(x ,y );
+
+end;
+
+{ MOVE_TO_D }
+procedure rasterizer_outline.move_to_d;
+begin
+ move_to(m_ren.coord(x ) ,m_ren.coord(y ) );
+
+end;
+
+{ LINE_TO_D }
+procedure rasterizer_outline.line_to_d;
+begin
+ line_to(m_ren.coord(x ) ,m_ren.coord(y ) );
+
+end;
+
+{ CLOSE }
+procedure rasterizer_outline.close;
+begin
+ if m_vertices > 2 then
+ line_to(m_start_x ,m_start_y );
+
+ m_vertices:=0;
+
+end;
+
+{ ADD_VERTEX }
+procedure rasterizer_outline.add_vertex;
+begin
+ if is_move_to(cmd ) then
+ move_to_d(x ,y )
+ else
+ if is_end_poly(cmd ) then
+ if is_closed(cmd ) then
+ close
+ else
+ else
+ line_to_d(x ,y );
+
+end;
+
+{ ADD_PATH }
+procedure rasterizer_outline.add_path;
+var
+ cmd : unsigned;
+ x ,y : double;
+
+begin
+ vs.rewind(path_id );
+
+ cmd:=vs.vertex(@x ,@y );
+
+ while not is_stop(cmd ) do
+ begin
+ add_vertex(x ,y ,cmd );
+
+ cmd:=vs.vertex(@x ,@y );
+
+ end;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_rasterizer_outline_aa.pas b/src/corelib/render/software/agg_rasterizer_outline_aa.pas
new file mode 100644
index 00000000..50436219
--- /dev/null
+++ b/src/corelib/render/software/agg_rasterizer_outline_aa.pas
@@ -0,0 +1,643 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 01.02.2006-Milano: Complete unit port
+// 31.01.2006-Milano: Unit port establishment
+//
+{ agg_rasterizer_outline_aa.pas }
+unit
+ agg_rasterizer_outline_aa ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_color ,
+ agg_line_aa_basics ,
+ agg_vertex_source ,
+ agg_vertex_sequence ,
+ agg_renderer_outline_aa ,
+ agg_ctrl ;
+
+{ TYPES DEFINITION }
+type
+// Vertex (x, y) with the distance to the next one. The last vertex has
+// the distance between the last and the first points
+ line_aa_vertex_ptr = ^line_aa_vertex;
+ line_aa_vertex = object
+ x ,y ,len : int;
+
+ constructor Construct; overload;
+ constructor Construct(x_ ,y_ : int ); overload;
+
+ end;
+
+ draw_vars_ptr = ^draw_vars;
+ draw_vars = record
+ idx : unsigned;
+
+ x1 ,y1 ,x2 ,y2 : int;
+
+ curr ,next : line_parameters;
+
+ lcurr ,lnext ,xb1 ,yb1 ,xb2 ,yb2 : int;
+
+ flags : unsigned;
+
+ end;
+
+ rasterizer_outline_aa_ptr = ^rasterizer_outline_aa;
+ rasterizer_outline_aa = object
+ m_ren : renderer_outline_ptr;
+
+ m_src_vertices : vertex_sequence;
+
+ m_accurate_join ,
+ m_round_cap : boolean;
+
+ m_start_x ,
+ m_start_y : int;
+
+ constructor Construct(ren : renderer_outline_ptr );
+ destructor Destruct;
+
+ procedure renderer(ren : renderer_outline_ptr );
+
+ procedure draw(dv : draw_vars_ptr; start ,end_ : unsigned );
+
+ procedure accurate_join_(v : boolean );
+ function _accurate_join : boolean;
+
+ procedure round_cap_(v : boolean );
+ function _round_cap : boolean;
+
+ procedure move_to(x ,y : int );
+ procedure line_to(x ,y : int );
+
+ procedure move_to_d(x ,y : double );
+ procedure line_to_d(x ,y : double );
+
+ procedure render(close_polygon : boolean );
+
+ procedure add_vertex(x ,y : double; cmd : unsigned );
+ procedure add_path (vs : vertex_source_ptr; path_id : unsigned = 0 );
+
+ procedure render_all_paths(
+ vs : vertex_source_ptr;
+ colors : aggclr_ptr;
+ path_id : unsigned_ptr;
+ num_paths : unsigned );
+
+ procedure render_ctrl(c : ctrl_ptr );
+
+ end;
+
+{ GLOBAL PROCEDURES }
+ function cmp_dist_start(d : int ) : boolean;
+ function cmp_dist_end (d : int ) : boolean;
+
+ function line_aa_vertex_func_operator(this ,val : line_aa_vertex_ptr ) : boolean;
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CMP_DIST_START }
+function cmp_dist_start;
+begin
+ result:=d > 0;
+
+end;
+
+{ CMP_DIST_END }
+function cmp_dist_end;
+begin
+ result:=d <= 0;
+
+end;
+
+{ CONSTRUCT }
+constructor line_aa_vertex.Construct;
+begin
+end;
+
+{ CONSTRUCT }
+constructor line_aa_vertex.Construct(x_ ,y_ : int );
+begin
+ x :=x_;
+ y :=y_;
+ len:=0;
+
+end;
+
+{ LINE_AA_VERTEX_FUNC_OPERATOR }
+function line_aa_vertex_func_operator;
+var
+ dx ,dy : double;
+
+begin
+ dx:=val.x - this.x;
+ dy:=val.y - this.y;
+
+ this.len:=trunc(Sqrt(dx * dx + dy * dy ) );
+
+ result:=this.len > (line_subpixel_size + line_subpixel_size div 2 );
+
+end;
+
+{ CONSTRUCT }
+constructor rasterizer_outline_aa.Construct;
+begin
+ m_src_vertices.Construct(sizeof(line_aa_vertex ) ,6 ,@line_aa_vertex_func_operator );
+
+ m_ren:=ren;
+
+ m_accurate_join:=m_ren.accurate_join_only;
+ m_round_cap :=false;
+
+ m_start_x:=0;
+ m_start_y:=0;
+
+end;
+
+{ DESTRUCT }
+destructor rasterizer_outline_aa.Destruct;
+begin
+ m_src_vertices.Destruct;
+
+end;
+
+{ RENDERER }
+procedure rasterizer_outline_aa.renderer(ren : renderer_outline_ptr );
+begin
+ m_ren:=ren;
+
+end;
+
+{ DRAW }
+procedure rasterizer_outline_aa.draw;
+var
+ i : unsigned;
+ v : line_aa_vertex_ptr;
+
+begin
+ i:=start;
+
+ while i < end_ do
+ begin
+ case dv.flags of
+ 0 : m_ren.line3(@dv.curr ,dv.xb1 ,dv.yb1 ,dv.xb2 ,dv.yb2 );
+ 1 : m_ren.line2(@dv.curr ,dv.xb2 ,dv.yb2 );
+ 2 : m_ren.line1(@dv.curr ,dv.xb1 ,dv.yb1 );
+ 3 : m_ren.line0(@dv.curr );
+
+ end;
+
+ dv.x1:=dv.x2;
+ dv.y1:=dv.y2;
+
+ dv.lcurr:=dv.lnext;
+ dv.lnext:=line_aa_vertex_ptr(m_src_vertices.array_operator(dv.idx ) ).len;
+
+ inc(dv.idx );
+
+ if dv.idx >= m_src_vertices.size then
+ dv.idx:=0;
+
+ v:=m_src_vertices.array_operator(dv.idx );
+
+ dv.x2:=v.x;
+ dv.y2:=v.y;
+
+ dv.curr:=dv.next;
+
+ dv.next.Construct(dv.x1 ,dv.y1 ,dv.x2 ,dv.y2 ,dv.lnext );
+
+ dv.xb1:=dv.xb2;
+ dv.yb1:=dv.yb2;
+
+ if m_accurate_join then
+ dv.flags:=0
+ else
+ begin
+ dv.flags:=dv.flags shr 1;
+
+ dv.flags:=
+ dv.flags or (
+ unsigned(
+ dv.curr.diagonal_quadrant =
+ dv.next.diagonal_quadrant ) shl 1 );
+
+ end;
+
+ if dv.flags and 2 = 0 then
+ bisectrix(@dv.curr ,@dv.next ,@dv.xb2 ,@dv.yb2 );
+
+ inc(i )
+
+ end;
+
+end;
+
+{ ACCURATE_JOIN_ }
+procedure rasterizer_outline_aa.accurate_join_;
+begin
+ if m_ren.accurate_join_only then
+ m_accurate_join:=true
+ else
+ m_accurate_join:=v;
+
+end;
+
+{ _ACCURATE_JOIN }
+function rasterizer_outline_aa._accurate_join;
+begin
+ result:=m_accurate_join;
+
+end;
+
+{ ROUND_CAP_ }
+procedure rasterizer_outline_aa.round_cap_;
+begin
+ m_round_cap:=v;
+
+end;
+
+{ _ROUND_CAP }
+function rasterizer_outline_aa._round_cap;
+begin
+ result:=m_round_cap;
+
+end;
+
+{ MOVE_TO }
+procedure rasterizer_outline_aa.move_to;
+var
+ vt : line_aa_vertex;
+
+begin
+ m_start_x:=x;
+ m_start_y:=y;
+
+ vt.Construct(x ,y );
+
+ m_src_vertices.modify_last(@vt );
+
+end;
+
+{ LINE_TO }
+procedure rasterizer_outline_aa.line_to;
+var
+ vt : line_aa_vertex;
+
+begin
+ vt.Construct(x ,y );
+
+ m_src_vertices.add(@vt );
+
+end;
+
+{ MOVE_TO_D }
+procedure rasterizer_outline_aa.move_to_d;
+begin
+ move_to(line_coord(x ) ,line_coord(y ) );
+
+end;
+
+{ LINE_TO_D }
+procedure rasterizer_outline_aa.line_to_d;
+begin
+ line_to(line_coord(x ) ,line_coord(y ) );
+
+end;
+
+{ RENDER }
+procedure rasterizer_outline_aa.render;
+var
+ dv : draw_vars;
+ v : line_aa_vertex_ptr;
+
+ x1 ,y1 ,x2 ,y2 ,lprev ,x3 ,y3 ,lnext : int;
+
+ prev ,lp ,lp1 ,lp2 : line_parameters;
+
+begin
+ m_src_vertices.close(close_polygon );
+
+ if close_polygon then
+ if m_src_vertices.size >= 3 then
+ begin
+ dv.idx:=2;
+
+ v :=m_src_vertices.array_operator(m_src_vertices.size - 1 );
+ x1 :=v.x;
+ y1 :=v.y;
+ lprev:=v.len;
+
+ v :=m_src_vertices.array_operator(0 );
+ x2:=v.x;
+ y2:=v.y;
+
+ dv.lcurr:=v.len;
+
+ prev.Construct(x1 ,y1 ,x2 ,y2 ,lprev );
+
+ v :=m_src_vertices.array_operator(1 );
+ dv.x1:=v.x;
+ dv.y1:=v.y;
+
+ dv.lnext:=v.len;
+
+ dv.curr.Construct(x2 ,y2 ,dv.x1 ,dv.y1 ,dv.lcurr );
+
+ v :=m_src_vertices.array_operator(dv.idx );
+ dv.x2:=v.x;
+ dv.y2:=v.y;
+
+ dv.next.Construct(dv.x1 ,dv.y1 ,dv.x2 ,dv.y2 ,dv.lnext );
+
+ dv.xb1:=0;
+ dv.yb1:=0;
+ dv.xb2:=0;
+ dv.yb2:=0;
+
+ if m_accurate_join then
+ dv.flags:=0
+ else
+ dv.flags:=
+ unsigned(prev.diagonal_quadrant = dv.curr.diagonal_quadrant ) or
+ (unsigned(dv.curr.diagonal_quadrant = dv.next.diagonal_quadrant ) shl 1 );
+
+ if dv.flags and 1 = 0 then
+ bisectrix(@prev ,@dv.curr ,@dv.xb1 ,@dv.yb1 );
+
+ if dv.flags and 2 = 0 then
+ bisectrix(@dv.curr ,@dv.next ,@dv.xb2 ,@dv.yb2 );
+
+ draw(@dv ,0 ,m_src_vertices.size );
+
+ end
+ else
+ else
+ case m_src_vertices.size of
+ 2 :
+ begin
+ v :=m_src_vertices.array_operator(0 );
+ x1 :=v.x;
+ y1 :=v.y;
+ lprev:=v.len;
+ v :=m_src_vertices.array_operator(1 );
+ x2 :=v.x;
+ y2 :=v.y;
+
+ lp.Construct(x1 ,y1 ,x2 ,y2 ,lprev );
+
+ if m_round_cap then
+ m_ren.semidot(@cmp_dist_start ,x1 ,y1 ,x1 + (y2 - y1 ) ,y1 - (x2 - x1 ) );
+
+ m_ren.line3(
+ @lp ,
+ x1 + (y2 - y1 ) ,
+ y1 - (x2 - x1 ) ,
+ x2 + (y2 - y1 ) ,
+ y2 - (x2 - x1 ) );
+
+ if m_round_cap then
+ m_ren.semidot(@cmp_dist_end ,x2 ,y2 ,x2 + (y2 - y1 ) ,y2 - (x2 - x1 ) );
+
+ end;
+
+ 3 :
+ begin
+ v :=m_src_vertices.array_operator(0 );
+ x1 :=v.x;
+ y1 :=v.y;
+ lprev:=v.len;
+ v :=m_src_vertices.array_operator(1 );
+ x2 :=v.x;
+ y2 :=v.y;
+ lnext:=v.len;
+ v :=m_src_vertices.array_operator(2 );
+ x3 :=v.x;
+ y3 :=v.y;
+
+ lp1.Construct(x1 ,y1 ,x2 ,y2 ,lprev );
+ lp2.Construct(x2 ,y2 ,x3 ,y3 ,lnext );
+
+ bisectrix(@lp1 ,@lp2 ,@dv.xb1 ,@dv.yb1 );
+
+ if m_round_cap then
+ m_ren.semidot(@cmp_dist_start ,x1 ,y1 ,x1 + (y2 - y1 ) ,y1 - (x2 - x1 ) );
+
+ m_ren.line3(
+ @lp1 ,
+ x1 + (y2 - y1 ) ,
+ y1 - (x2 - x1 ) ,
+ dv.xb1 ,
+ dv.yb1 );
+
+ m_ren.line3(
+ @lp2 ,
+ dv.xb1 ,
+ dv.yb1 ,
+ x3 + (y3 - y2 ) ,
+ y3 - (x3 - x2 ) );
+
+ if m_round_cap then
+ m_ren.semidot(@cmp_dist_end ,x3 ,y3 ,x3 + (y3 - y2 ) ,y3 - (x3 - x2 ) );
+
+ end;
+
+ 0 ,1 :
+ else
+ begin
+ dv.idx:=3;
+
+ v :=m_src_vertices.array_operator(0 );
+ x1 :=v.x;
+ y1 :=v.y;
+ lprev:=v.len;
+
+ v :=m_src_vertices.array_operator(1 );
+ x2:=v.x;
+ y2:=v.y;
+
+ dv.lcurr:=v.len;
+
+ prev.Construct(x1 ,y1 ,x2 ,y2 ,lprev );
+
+ v :=m_src_vertices.array_operator(2 );
+ dv.x1:=v.x;
+ dv.y1:=v.y;
+
+ dv.lnext:=v.len;
+
+ dv.curr.Construct(x2 ,y2 ,dv.x1 ,dv.y1 ,dv.lcurr );
+
+ v :=m_src_vertices.array_operator(dv.idx );
+ dv.x2:=v.x;
+ dv.y2:=v.y;
+
+ dv.next.Construct(dv.x1 ,dv.y1 ,dv.x2 ,dv.y2 ,dv.lnext );
+
+ dv.xb1:=0;
+ dv.yb1:=0;
+ dv.xb2:=0;
+ dv.yb2:=0;
+
+ if m_accurate_join then
+ dv.flags:=0
+ else
+ dv.flags:=
+ unsigned(prev.diagonal_quadrant = dv.curr.diagonal_quadrant ) or
+ (unsigned(dv.curr.diagonal_quadrant = dv.next.diagonal_quadrant ) shl 1 );
+
+ if dv.flags and 1 = 0 then
+ begin
+ bisectrix (@prev ,@dv.curr ,@dv.xb1 ,@dv.yb1 );
+ m_ren.line3(
+ @prev ,
+ x1 + (y2 - y1 ) ,
+ y1 - (x2 - x1 ) ,
+ dv.xb1 ,
+ dv.yb1 );
+
+ end
+ else
+ m_ren.line1(@prev ,x1 + (y2 - y1 ) ,y1 - (x2 - x1 ) );
+
+ if m_round_cap then
+ m_ren.semidot(@cmp_dist_start ,x1 ,y1 ,x1 + (y2 - y1 ) ,y1 - (x2 - x1 ) );
+
+ if dv.flags and 2 = 0 then
+ bisectrix(@dv.curr ,@dv.next ,@dv.xb2 ,@dv.yb2 );
+
+ draw(@dv ,1 ,m_src_vertices.size - 2 );
+
+ if dv.flags and 1 = 0 then
+ m_ren.line3(
+ @dv.curr ,
+ dv.xb1 ,
+ dv.yb1 ,
+ dv.curr.x2 + (dv.curr.y2 - dv.curr.y1 ) ,
+ dv.curr.y2 - (dv.curr.x2 - dv.curr.x1 ) )
+ else
+ m_ren.line2(
+ @dv.curr ,
+ dv.curr.x2 + (dv.curr.y2 - dv.curr.y1 ) ,
+ dv.curr.y2 - (dv.curr.x2 - dv.curr.x1 ) );
+
+ if m_round_cap then
+ m_ren.semidot(
+ @cmp_dist_end ,dv.curr.x2 ,dv.curr.y2 ,
+ dv.curr.x2 + (dv.curr.y2 - dv.curr.y1 ) ,
+ dv.curr.y2 - (dv.curr.x2 - dv.curr.x1 ) );
+
+ end;
+
+ end;
+
+ m_src_vertices.remove_all;
+
+end;
+
+{ ADD_VERTEX }
+procedure rasterizer_outline_aa.add_vertex;
+begin
+ if is_move_to(cmd ) then
+ begin
+ render (false );
+ move_to_d(x ,y );
+
+ end
+ else
+ if is_end_poly(cmd ) then
+ begin
+ render(is_closed(cmd ) );
+
+ if is_closed(cmd ) then
+ move_to(m_start_x ,m_start_y );
+
+ end
+ else
+ line_to_d(x ,y );
+
+end;
+
+{ ADD_PATH }
+procedure rasterizer_outline_aa.add_path;
+var
+ x ,y : double;
+ cmd : unsigned;
+
+begin
+ vs.rewind(path_id );
+
+ cmd:=vs.vertex(@x ,@y );
+
+ while not is_stop(cmd ) do
+ begin
+ add_vertex(x ,y ,cmd );
+
+ cmd:=vs.vertex(@x ,@y );
+
+ end;
+
+ render(false );
+
+end;
+
+{ RENDER_ALL_PATHS }
+procedure rasterizer_outline_aa.render_all_paths;
+var
+ i : unsigned;
+
+begin
+ for i:=0 to num_paths - 1 do
+ begin
+ m_ren.color_(aggclr_ptr(ptrcomp(colors ) + i * sizeof(aggclr ) ) );
+ add_path (vs ,unsigned_ptr(ptrcomp(path_id ) + i * sizeof(unsigned ) )^ );
+
+ end;
+
+end;
+
+{ RENDER_CTRL }
+procedure rasterizer_outline_aa.render_ctrl;
+var
+ i : unsigned;
+
+begin
+ for i:=0 to c.num_paths - 1 do
+ begin
+ m_ren.color_(c._color(i ) );
+ add_path (c ,i );
+
+ end;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_rasterizer_scanline_aa.pas b/src/corelib/render/software/agg_rasterizer_scanline_aa.pas
new file mode 100644
index 00000000..b5d91ae6
--- /dev/null
+++ b/src/corelib/render/software/agg_rasterizer_scanline_aa.pas
@@ -0,0 +1,1824 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+//
+// The author gratefully acknowleges the support of David Turner,
+// Robert Wilhelm, and Werner Lemberg - the authors of the FreeType
+// libray - in producing this work. See http://www.freetype.org for details.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// Adaptation for 32-bit screen coordinates has been sponsored by
+// Liberty Technology Systems, Inc., visit http://lib-sys.com
+//
+// Liberty Technology Systems, Inc. is the provider of
+// PostScript and PDF technology for software developers.
+//
+//----------------------------------------------------------------------------
+//
+// Class outline_aa - implementation.
+//
+// Initially the rendering algorithm was designed by David Turner and the
+// other authors of the FreeType library - see the above notice. I nearly
+// created a similar renderer, but still I was far from David's work.
+// I completely redesigned the original code and adapted it for Anti-Grain
+// ideas. Two functions - render_line and render_hline are the core of
+// the algorithm - they calculate the exact coverage of each pixel cell
+// of the polygon. I left these functions almost as is, because there's
+// no way to improve the perfection - hats off to David and his group!
+//
+// All other code is very different from the original.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 28.02.2006-Milano: scanline_hit_test
+// 23.11.2005-Milano: outline_aa.sort_cells, rasterizer.rewind,sweep, ...
+// 21.11.2005-Milano: outline_aa ,rasterizer_scanline_aa.line_to.move_to
+// 17.11.2005-Milano: Unit port establishment
+//
+{ agg_rasterizer_scanline_aa.pas }
+unit
+ agg_rasterizer_scanline_aa ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+{$Q- }
+{$R- }
+uses
+ agg_basics ,
+ agg_array ,
+ agg_scanline ,
+ agg_vertex_source ,
+ agg_gamma_functions ,
+ agg_clip_liang_barsky ;
+
+{ TYPES DEFINITION }
+const
+ aa_shift = 8;
+ aa_num = 1 shl aa_shift;
+ aa_mask = aa_num - 1;
+ aa_2num = aa_num * 2;
+ aa_2mask = aa_2num - 1;
+
+ cell_block_shift = 12;
+ cell_block_size = 1 shl cell_block_shift;
+ cell_block_mask = cell_block_size - 1;
+ cell_block_pool = 256;
+ cell_block_limit = 1024;
+
+// These constants determine the subpixel accuracy, to be more precise,
+// the number of bits of the fractional part of the coordinates.
+// The possible coordinate capacity in bits can be calculated by formula:
+// sizeof(int) * 8 - poly_base_shift * 2, i.e, for 32-bit integers and
+// 8-bits fractional part the capacity is 16 bits or [-32768...32767].
+ poly_base_shift = 8; //----poly_base_shift
+ poly_base_size = 1 shl poly_base_shift; //----poly_base_size
+ poly_base_mask = poly_base_size - 1; //----poly_base_mask
+
+type
+//-----------------------------------------------------------------cell_aa
+// A pixel cell. There're no constructors defined and it was done
+// intentionally in order to avoid extra overhead when allocating an
+// array of cells.
+ cell_aa_ptr_ptr = ^cell_aa_ptr;
+ cell_aa_ptr = ^cell_aa;
+ cell_aa = record
+ x ,y ,
+ cover ,
+ area : int;
+
+ end;
+
+//--------------------------------------------------------------outline_aa
+// An internal class that implements the main rasterization algorithm.
+// Used in the rasterizer. Should not be used direcly.
+ sorted_y_ptr = ^sorted_y;
+ sorted_y = record
+ start ,
+ num : unsigned;
+
+ end;
+
+ outline_aa = object
+ m_num_blocks ,
+ m_max_blocks ,
+ m_cur_block ,
+ m_num_cells : unsigned;
+
+ m_cur_x ,
+ m_cur_y ,
+ m_min_x ,
+ m_min_y ,
+ m_max_x ,
+ m_max_y : int;
+
+ m_sorted : boolean;
+
+ m_cells : cell_aa_ptr_ptr;
+ m_cur_cell_ptr : cell_aa_ptr;
+ m_cur_cell : cell_aa;
+
+ m_sorted_cells : pod_array;
+ m_sorted_y : pod_array;
+
+ constructor Construct;
+ destructor Destruct;
+
+ procedure move_to(x ,y : int );
+ procedure line_to(x ,y : int );
+
+ procedure reset;
+
+ procedure add_cur_cell;
+ procedure set_cur_cell(x ,y : int );
+
+ procedure sort_cells;
+ function total_cells : unsigned;
+ function scanline_num_cells(y : unsigned ) : unsigned;
+ function scanline_cells (y : unsigned ) : cell_aa_ptr_ptr;
+ function sorted : boolean;
+
+ procedure render_line (x1 ,y1 ,x2 ,y2 : int );
+ procedure render_hline(ey ,x1 ,y1 ,x2 ,y2 : int );
+
+ procedure allocate_block;
+
+ function _min_x : int;
+ function _min_y : int;
+ function _max_x : int;
+ function _max_y : int;
+
+ end;
+
+//------------------------------------------------------scanline_hit_test
+ scanline_hit_test = object(scanline )
+ m_x : int;
+ m_hit : boolean;
+
+ constructor Construct(x : int );
+
+ procedure reset_spans; virtual;
+
+ procedure finalize(y_ : int ); virtual;
+ procedure add_cell(x : int; cover : unsigned ); virtual;
+ procedure add_span(x : int; len ,cover : unsigned ); virtual;
+
+ function num_spans : unsigned; virtual;
+
+ function hit : boolean;
+
+ end;
+
+//==================================================rasterizer_scanline_aa
+// Polygon rasterizer that is used to render filled polygons with
+// high-quality Anti-Aliasing. Internally, by default, the class uses
+// integer coordinates in format 24.8, i.e. 24 bits for integer part
+// and 8 bits for fractional - see poly_base_shift. This class can be
+// used in the following way:
+//
+// 1. filling_rule(filling_rule_e ft) - optional.
+//
+// 2. gamma() - optional.
+//
+// 3. reset()
+//
+// 4. move_to(x, y) / line_to(x, y) - make the polygon. One can create
+// more than one contour, but each contour must consist of at least 3
+// vertices, i.e. move_to(x1, y1); line_to(x2, y2); line_to(x3, y3);
+// is the absolute minimum of vertices that define a triangle.
+// The algorithm does not check either the number of vertices nor
+// coincidence of their coordinates, but in the worst case it just
+// won't draw anything.
+// The orger of the vertices (clockwise or counterclockwise)
+// is important when using the non-zero filling rule (fill_non_zero).
+// In this case the vertex order of all the contours must be the same
+// if you want your intersecting polygons to be without "holes".
+// You actually can use different vertices order. If the contours do not
+// intersect each other the order is not important anyway. If they do,
+// contours with the same vertex order will be rendered without "holes"
+// while the intersecting contours with different orders will have "holes".
+//
+// filling_rule() and gamma() can be called anytime before "sweeping".
+//------------------------------------------------------------------------
+// filling_rule_e = (fill_non_zero ,fill_even_odd );
+ status = (status_initial ,status_line_to ,status_closed );
+
+ rasterizer_scanline_ptr = ^rasterizer_scanline;
+ rasterizer_scanline = object
+ procedure reset; virtual; abstract;
+ procedure filling_rule(filling_rule_ : filling_rule_e ); virtual; abstract;
+ procedure clip_box (x1 ,y1 ,x2 ,y2 : double ); virtual; abstract;
+
+ procedure gamma(gamma_function : vertex_source_ptr ); virtual; abstract;
+
+ procedure add_path (vs : vertex_source_ptr; path_id : unsigned = 0 ); virtual; abstract;
+ procedure add_vertex(x ,y : double; cmd : unsigned ); virtual; abstract;
+
+ procedure sort; virtual; abstract;
+ function rewind_scanlines : boolean; virtual; abstract;
+ function sweep_scanline (sl : scanline_ptr ) : boolean; virtual; abstract;
+ function sweep_scanline_em(sl : scanline_ptr ) : boolean; virtual; abstract;
+
+ function hit_test(tx ,ty : int ) : boolean; virtual; abstract;
+
+ function _min_x : int; virtual; abstract;
+ function _min_y : int; virtual; abstract;
+ function _max_x : int; virtual; abstract;
+ function _max_y : int; virtual; abstract;
+
+ end;
+
+ rasterizer_scanline_aa_ptr = ^rasterizer_scanline_aa;
+ rasterizer_scanline_aa = object(rasterizer_scanline )
+ m_outline : outline_aa;
+ m_gamma : array [0..aa_num - 1 ] of int;
+
+ m_filling_rule : filling_rule_e;
+ m_clipped_start_x ,
+ m_clipped_start_y ,
+
+ m_start_x ,
+ m_start_y ,
+ m_prev_x ,
+ m_prev_y : int;
+
+ m_prev_flags : unsigned;
+ m_status : status;
+
+ m_clip_box : rect;
+ m_clipping : boolean;
+
+ m_cur_y ,
+ XScale : int;
+
+ m_auto_close : boolean;
+
+ constructor Construct;
+ destructor Destruct;
+
+ procedure reset; virtual;
+ procedure filling_rule(filling_rule_ : filling_rule_e ); virtual;
+ procedure auto_close (flag : boolean );
+ procedure clip_box (x1 ,y1 ,x2 ,y2 : double ); virtual;
+
+ procedure gamma (gamma_function : vertex_source_ptr ); virtual;
+ function apply_gamma(cover : unsigned ) : unsigned;
+
+ procedure move_to_no_clip(x ,y : int );
+ procedure line_to_no_clip(x ,y : int );
+
+ procedure close_polygon;
+ procedure close_polygon_no_clip;
+ procedure clip_segment(x ,y : int );
+
+ procedure move_to_d(x ,y : double );
+ procedure line_to_d(x ,y : double );
+
+ procedure move_to(x ,y : int );
+ procedure line_to(x ,y : int );
+
+ procedure sort; virtual;
+ function rewind_scanlines : boolean; virtual;
+ function sweep_scanline(sl : scanline_ptr ) : boolean; virtual;
+
+ function navigate_scanline(y : int ) : boolean;
+
+ function hit_test(tx ,ty : int ) : boolean; virtual;
+
+ function _min_x : int; virtual;
+ function _min_y : int; virtual;
+ function _max_x : int; virtual;
+ function _max_y : int; virtual;
+
+ function calculate_alpha(area : int ) : unsigned;
+
+ procedure add_path (vs : vertex_source_ptr; path_id : unsigned = 0 ); virtual;
+ procedure add_vertex(x ,y : double; cmd : unsigned ); virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+ function poly_coord(c : double ) : int;
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor outline_aa.Construct;
+begin
+ m_sorted_cells.Construct(sizeof(cell_aa_ptr ) );
+ m_sorted_y.Construct (sizeof(sorted_y ) );
+
+ m_num_blocks:=0;
+ m_max_blocks:=0;
+ m_cur_block :=0;
+ m_num_cells :=0;
+
+ m_cur_x:=0;
+ m_cur_y:=0;
+ m_min_x:=$7FFFFFFF;
+ m_min_y:=$7FFFFFFF;
+ m_max_x:=-$7FFFFFFF;
+ m_max_y:=-$7FFFFFFF;
+
+ m_sorted:=false;
+
+ m_cells :=NIL;
+ m_cur_cell_ptr:=NIL;
+
+ with m_cur_cell do
+ begin
+ x:=$7FFF;
+ y:=$7FFF;
+
+ cover:=0;
+ area :=0;
+
+ end;
+
+end;
+
+{ DESTRUCT }
+destructor outline_aa.Destruct;
+begin
+ m_sorted_cells.Destruct;
+ m_sorted_y.Destruct;
+
+ if m_num_blocks > 0 then
+ begin
+ repeat
+ dec(m_num_blocks );
+
+ agg_freemem(
+ pointer(pointer(ptrcomp(m_cells ) + m_num_blocks * sizeof(cell_aa_ptr ) )^ ) ,
+ cell_block_size * sizeof(cell_aa ) );
+
+ until m_num_blocks = 0;
+
+ agg_freemem(pointer(m_cells ) ,sizeof(cell_aa_ptr ) * m_max_blocks );
+
+ end;
+
+end;
+
+{ MOVE_TO }
+procedure outline_aa.move_to;
+begin
+ if m_sorted then
+ reset;
+
+// set_cur_cell(x shr poly_base_shift ,y shr poly_base_shift );
+ set_cur_cell(shr_int32(x ,poly_base_shift ) ,shr_int32(y ,poly_base_shift ) );
+
+ m_cur_x:=x;
+ m_cur_y:=y;
+
+end;
+
+{ LINE_TO }
+procedure outline_aa.line_to;
+begin
+ render_line(m_cur_x ,m_cur_y ,x ,y );
+
+ m_cur_x:=x;
+ m_cur_y:=y;
+
+ m_sorted:=false;
+
+end;
+
+{ RESET }
+procedure outline_aa.reset;
+begin
+ m_num_cells:=0;
+ m_cur_block:=0;
+
+ m_cur_cell.x :=$7FFF;
+ m_cur_cell.y :=$7FFF;
+ m_cur_cell.cover:=0;
+ m_cur_cell.area :=0;
+
+ m_sorted:=false;
+
+ m_min_x:=$7FFFFFFF;
+ m_min_y:=$7FFFFFFF;
+ m_max_x:=-$7FFFFFFF;
+ m_max_y:=-$7FFFFFFF;
+
+end;
+
+{ ADD_CUR_CELL }
+procedure outline_aa.add_cur_cell;
+begin
+ if (m_cur_cell.area or m_cur_cell.cover ) <> 0 then
+ begin
+ if (m_num_cells and cell_block_mask ) = 0 then
+ begin
+ if m_num_blocks >= cell_block_limit then
+ exit;
+
+ allocate_block;
+
+ end;
+
+ m_cur_cell_ptr^:=m_cur_cell;
+
+ inc(ptrcomp(m_cur_cell_ptr ) ,sizeof(cell_aa ) );
+ inc(m_num_cells );
+
+ if m_cur_cell.x < m_min_x then
+ m_min_x:=m_cur_cell.x;
+
+ if m_cur_cell.x > m_max_x then
+ m_max_x:=m_cur_cell.x;
+
+ if m_cur_cell.y < m_min_y then
+ m_min_y:=m_cur_cell.y;
+
+ if m_cur_cell.y > m_max_y then
+ m_max_y:=m_cur_cell.y;
+
+ end;
+
+end;
+
+{ SET_CUR_CELL }
+procedure outline_aa.set_cur_cell;
+begin
+ if (m_cur_cell.x <> x ) or
+ (m_cur_cell.y <> y ) then
+ begin
+ add_cur_cell;
+
+ m_cur_cell.x:=x;
+ m_cur_cell.y:=y;
+
+ m_cur_cell.cover:=0;
+ m_cur_cell.area :=0;
+
+ end;
+
+end;
+
+{ qsort_cells }
+procedure qsort_cells(start : cell_aa_ptr_ptr; num : unsigned );
+var
+ len ,x : int;
+ temp : pointer;
+
+ stack : array[0..79 ] of cell_aa_ptr_ptr;
+ limit ,
+ base ,
+ i ,j ,
+ pivot : cell_aa_ptr_ptr;
+ top : ^cell_aa_ptr_ptr;
+
+const
+ qsort_threshold = 9;
+
+begin
+ limit:=cell_aa_ptr_ptr(ptrcomp(start ) + num * 4 );
+ base :=start;
+ top :=@stack[0 ];
+
+ repeat
+ len:=(ptrcomp(limit ) - ptrcomp(base ) ) div 4;
+
+ if len > qsort_threshold then
+ begin
+ // we use base + len/2 as the pivot
+ pivot:=cell_aa_ptr_ptr(ptrcomp(base ) + (len div 2 ) * 4 );
+
+ temp:=p32_ptr(base ).ptr;
+
+ p32_ptr(base ).ptr :=p32_ptr(pivot ).ptr;
+ p32_ptr(pivot ).ptr:=temp;
+
+ i:=cell_aa_ptr_ptr(ptrcomp(base ) + 4 );
+ j:=cell_aa_ptr_ptr(ptrcomp(limit ) - 4 );
+
+ // now ensure that *i <= *base <= *j
+ if j^.x < i^.x then
+ begin
+ temp:=p32_ptr(i ).ptr;
+
+ p32_ptr(i ).ptr:=p32_ptr(j ).ptr;
+ p32_ptr(j ).ptr:=temp;
+
+ end;
+
+ if base^.x < i^.x then
+ begin
+ temp:=p32_ptr(base ).ptr;
+
+ p32_ptr(base ).ptr:=p32_ptr(i ).ptr;
+ p32_ptr(i ).ptr :=temp;
+
+ end;
+
+ if j^.x < base^.x then
+ begin
+ temp:=p32_ptr(base ).ptr;
+
+ p32_ptr(base ).ptr:=p32_ptr(j ).ptr;
+ p32_ptr(j ).ptr :=temp;
+
+ end;
+
+ repeat
+ x:=base^.x;
+
+ inc(ptrcomp(i ) ,sizeof(cell_aa_ptr ) );
+
+ while i^.x < x do
+ inc(ptrcomp(i ) ,sizeof(cell_aa_ptr ) );
+
+ dec(ptrcomp(j ) ,sizeof(cell_aa_ptr ) );
+
+ while x < j^.x do
+ dec(ptrcomp(j ) ,sizeof(cell_aa_ptr ) );
+
+ if ptrcomp(i ) > ptrcomp(j ) then
+ break;
+
+ temp:=p32_ptr(i ).ptr;
+
+ p32_ptr(i ).ptr:=p32_ptr(j ).ptr;
+ p32_ptr(j ).ptr:=temp;
+
+ until false;
+
+ temp:=p32_ptr(base ).ptr;
+
+ p32_ptr(base ).ptr:=p32_ptr(j ).ptr;
+ p32_ptr(j ).ptr :=temp;
+
+ // now, push the largest sub-array
+ if (ptrcomp(j ) - ptrcomp(base ) ) div 4 > (ptrcomp(limit ) - ptrcomp(i ) ) div 4 then
+ begin
+ top^:=base;
+
+ inc(ptrcomp(top ) ,sizeof(cell_aa_ptr_ptr ) );
+
+ top^:=j;
+ base:=i;
+
+ end
+ else
+ begin
+ top^:=i;
+
+ inc(ptrcomp(top ) ,sizeof(cell_aa_ptr_ptr ) );
+
+ top^ :=limit;
+ limit:=j;
+
+ end;
+
+ inc(ptrcomp(top ) ,sizeof(cell_aa_ptr_ptr ) );
+
+ end
+ else
+ begin
+ // the sub-array is small, perform insertion sort
+ j:=base;
+ i:=cell_aa_ptr_ptr(ptrcomp(j ) + 1 * 4 );
+
+ while ptrcomp(i ) < ptrcomp(limit ) do
+ begin
+ try
+ while cell_aa_ptr_ptr(ptrcomp(j ) + 1 * 4 )^^.x < j^.x do
+ begin
+ //swap_ptrs(cell_aa_ptr_ptr(ptrcomp(j ) + 1 * 4 ) ,j );
+ temp:=p32_ptr(cell_aa_ptr_ptr(ptrcomp(j ) + 1 * 4 ) ).ptr;
+
+ p32_ptr(cell_aa_ptr_ptr(ptrcomp(j ) + 1 * 4 ) ).ptr:=p32_ptr(j ).ptr;
+ p32_ptr(j ).ptr:=temp;
+
+ if j = base then
+ break;
+
+ dec(ptrcomp(j ) ,sizeof(cell_aa_ptr ) );
+
+ end;
+
+ except
+ end;
+
+ j:=i;
+
+ inc(ptrcomp(i ) ,sizeof(cell_aa_ptr ) );
+
+ end;
+
+ if ptrcomp(top ) > ptrcomp(@stack[0 ] ) then
+ begin
+ dec(ptrcomp(top ) ,sizeof(cell_aa_ptr_ptr ) );
+
+ limit:=top^;
+
+ dec(ptrcomp(top ) ,sizeof(cell_aa_ptr_ptr ) );
+
+ base:=top^;
+
+ end
+ else
+ break;
+
+ end;
+
+ until false;
+
+end;
+
+{ SORT_CELLS }
+procedure outline_aa.sort_cells;
+var
+ nb ,i ,
+ v ,
+ start : unsigned;
+ cur_y : sorted_y_ptr;
+
+ block_ptr : cell_aa_ptr_ptr;
+ cell_ptr : cell_aa_ptr;
+
+// fout : text;
+
+begin
+//Perform sort only the first time
+ if m_sorted then
+ exit;
+
+ add_cur_cell;
+
+ if m_num_cells = 0 then
+ exit;
+
+// Allocate the array of cell pointers
+ m_sorted_cells.allocate(m_num_cells ,16 );
+
+// Allocate and zero the Y array
+ m_sorted_y.allocate(m_max_y - m_min_y + 1 ,16 );
+ m_sorted_y.zero;
+
+// Create the Y-histogram (count the numbers of cells for each Y)
+ block_ptr:=m_cells;
+
+ nb:=m_num_cells shr cell_block_shift;
+
+ while nb > 0 do
+ begin
+ dec(nb );
+
+ cell_ptr:=block_ptr^;
+
+ inc(ptrcomp(block_ptr ) ,sizeof(cell_aa_ptr ) );
+
+ i:=cell_block_size;
+
+ while i > 0 do
+ begin
+ dec(i );
+ inc(sorted_y_ptr(ptrcomp(m_sorted_y.m_array ) + unsigned(cell_ptr^.y - m_min_y ) * m_sorted_y.m_entry_sz ).start );
+ inc(ptrcomp(cell_ptr ) ,sizeof(cell_aa ) );
+
+ end;
+
+ end;
+
+ cell_ptr:=block_ptr^;
+
+ inc(ptrcomp(block_ptr ) ,sizeof(cell_aa_ptr ) );
+
+ i:=m_num_cells and cell_block_mask;
+
+ while i > 0 do
+ begin
+ dec(i );
+ inc(sorted_y_ptr(ptrcomp(m_sorted_y.m_array ) + unsigned(cell_ptr^.y - m_min_y ) * m_sorted_y.m_entry_sz ).start );
+ inc(ptrcomp(cell_ptr ) ,sizeof(cell_aa ) );
+
+ end;
+
+// Convert the Y-histogram into the array of starting indexes
+ start:=0;
+
+ for i:=0 to m_sorted_y.size - 1 do
+ begin
+ v:=sorted_y_ptr(ptrcomp(m_sorted_y.m_array ) + i * m_sorted_y.m_entry_sz ).start;
+
+ sorted_y_ptr(ptrcomp(m_sorted_y.m_array ) + i * m_sorted_y.m_entry_sz ).start:=start;
+
+ inc(start ,v );
+
+ end;
+
+// Fill the cell pointer array sorted by Y
+ block_ptr:=m_cells;
+
+ nb:=m_num_cells shr cell_block_shift;
+
+ while nb > 0 do
+ begin
+ dec(nb );
+
+ cell_ptr:=block_ptr^;
+
+ inc(ptrcomp(block_ptr ) ,sizeof(cell_aa_ptr ) );
+
+ i:=cell_block_size;
+
+ while i > 0 do
+ begin
+ dec(i );
+
+ cur_y:=sorted_y_ptr(ptrcomp(m_sorted_y.m_array ) + unsigned(cell_ptr.y - m_min_y ) * m_sorted_y.m_entry_sz );
+
+ p32_ptr(ptrcomp(m_sorted_cells.m_array ) + unsigned(cur_y.start + cur_y.num ) * m_sorted_cells.m_entry_sz ).ptr:=cell_ptr;
+
+ inc(cur_y.num );
+ inc(ptrcomp(cell_ptr ) ,sizeof(cell_aa ) );
+
+ end;
+
+ end;
+
+ cell_ptr:=block_ptr^;
+
+ inc(ptrcomp(block_ptr ) ,sizeof(cell_aa_ptr ) );
+
+ i:=m_num_cells and cell_block_mask;
+
+ while i > 0 do
+ begin
+ dec(i );
+
+ cur_y:=sorted_y_ptr(ptrcomp(m_sorted_y.m_array ) + unsigned(cell_ptr.y - m_min_y ) * m_sorted_y.m_entry_sz );
+
+ p32_ptr(ptrcomp(m_sorted_cells.m_array ) + unsigned(cur_y.start + cur_y.num ) * m_sorted_cells.m_entry_sz ).ptr:=cell_ptr;
+
+ inc(cur_y.num );
+ inc(ptrcomp(cell_ptr ) ,sizeof(cell_aa ) );
+
+ end;
+
+// Finally arrange the X-arrays
+ for i:=0 to m_sorted_y.size - 1 do
+ begin
+ cur_y:=sorted_y_ptr(ptrcomp(m_sorted_y.m_array ) + i * m_sorted_y.m_entry_sz );
+
+ if cur_y.num > 0 then
+ qsort_cells(cell_aa_ptr_ptr(ptrcomp(m_sorted_cells.m_array ) + cur_y.start * m_sorted_cells.m_entry_sz ) ,cur_y.num );
+
+ end;
+
+ m_sorted:=true;
+
+// M_SORTED_CELLS
+(* assignfile(fout ,'sorted.yes' );
+ rewrite(fout );
+
+ for i:=0 to m_sorted_cells.size - 1 do
+ begin
+ cell_ptr:=p32_ptr(ptrcomp(m_sorted_cells.m_array ) + i * m_sorted_cells.m_entry_sz ).ptr;
+
+ write(fout ,cell_ptr.x ,' ,' ,cell_ptr.y ,' ,' );
+ write(fout ,cell_ptr.cover ,' ,' ,cell_ptr.area );
+
+ writeln(fout );
+
+ end;
+
+ close(fout );*)
+
+// M_SORTED_Y
+(* assignfile(fout ,'y.yes' );
+ rewrite(fout );
+
+ for i:=0 to m_sorted_y.size - 1 do
+ begin
+ cur_y:=sorted_y_ptr(ptrcomp(m_sorted_y.m_array ) + i * m_sorted_y.m_entry_sz );
+
+ writeln(fout ,cur_y.start ,' ,' ,cur_y.num );
+
+ end;
+
+ close(fout );*)
+
+end;
+
+{ TOTAL_CELLS }
+function outline_aa.total_cells;
+begin
+ result:=m_num_cells;
+
+end;
+
+{ SCANLINE_NUM_CELLS }
+function outline_aa.scanline_num_cells;
+begin
+ result:=sorted_y_ptr(ptrcomp(m_sorted_y.m_array ) + unsigned(y - m_min_y ) * m_sorted_y.m_entry_sz ).num;
+
+end;
+
+{ SCANLINE_CELLS }
+function outline_aa.scanline_cells;
+begin
+ result:=
+ cell_aa_ptr_ptr(
+ ptrcomp(m_sorted_cells.m_array ) +
+ sorted_y_ptr(ptrcomp(m_sorted_y.m_array ) + unsigned(y - m_min_y ) * m_sorted_y.m_entry_sz ).start
+ * m_sorted_cells.m_entry_sz );
+
+end;
+
+{ SORTED }
+function outline_aa.sorted;
+begin
+ result:=m_sorted;
+
+end;
+
+{ RENDER_LINE }
+procedure outline_aa.render_line;
+var
+ p ,
+
+ cx ,
+ cy ,
+ dx ,
+ dy ,
+ ex ,
+
+ ey1 ,
+ ey2 ,
+ fy1 ,
+ fy2 ,
+ rem ,
+ m_d ,
+
+ x_from ,
+ x_to ,
+ lift ,
+ delta ,
+ first ,
+ incr ,
+ two_fx ,
+ area : int;
+
+const
+ dx_limit = 16384 shl poly_base_shift;
+
+begin
+ dx:=x2 - x1;
+
+ if (dx >= dx_limit ) or
+ (dx <= -dx_limit ) then
+ begin
+ cx:=(x1 + x2) shr 1;
+ cy:=(y1 + y2) shr 1;
+
+ render_line(x1 ,y1 ,cx ,cy );
+ render_line(cx ,cy ,x2 ,y2 );
+
+ end;
+
+ dy:=y2 - y1;
+
+// ey1:=y1 shr poly_base_shift;
+// ey2:=y2 shr poly_base_shift;
+ ey1:=shr_int32(y1 ,poly_base_shift );
+ ey2:=shr_int32(y2 ,poly_base_shift );
+
+ fy1:=y1 and poly_base_mask;
+ fy2:=y2 and poly_base_mask;
+
+//everything is on a single hline
+ if ey1 = ey2 then
+ begin
+ render_hline(ey1 ,x1 ,fy1 ,x2 ,fy2 );
+ exit;
+
+ end;
+
+//Vertical line - we have to calculate start and end cells,
+//and then - the common values of the area and coverage for
+//all cells of the line. We know exactly there's only one
+//cell, so, we don't have to call render_hline().
+ incr:=1;
+
+ if dx = 0 then
+ begin
+ // ex:=x1 shr poly_base_shift;
+ ex:=shr_int32(x1 ,poly_base_shift );
+
+ two_fx:=(x1 - (ex shl poly_base_shift ) ) shl 1;
+ first :=poly_base_size;
+
+ if dy < 0 then
+ begin
+ first:=0;
+ incr :=-1;
+
+ end;
+
+ x_from:=x1;
+
+ //render_hline(ey1 ,x_from ,fy1 ,x_from ,first );
+ delta:=first - fy1;
+
+ inc(m_cur_cell.cover ,delta );
+ inc(m_cur_cell.area ,two_fx * delta );
+ inc(ey1 ,incr );
+
+ set_cur_cell(ex, ey1);
+
+ delta:=first + first - poly_base_size;
+ area :=two_fx * delta;
+
+ while ey1 <> ey2 do
+ begin
+ //render_hline(ey1 ,x_from ,poly_base_size - first ,x_from ,first );
+ m_cur_cell.cover:=delta;
+ m_cur_cell.area :=area;
+
+ inc(ey1 ,incr );
+
+ set_cur_cell(ex ,ey1 );
+
+ end;
+
+ //render_hline(ey1, x_from, poly_base_size - first, x_from, fy2);
+ delta:=fy2 - poly_base_size + first;
+
+ inc(m_cur_cell.cover ,delta );
+ inc(m_cur_cell.area ,two_fx * delta );
+
+ exit;
+
+ end;
+
+//ok, we have to render several hlines
+ p :=(poly_base_size - fy1 ) * dx;
+ first:=poly_base_size;
+
+ if dy < 0 then
+ begin
+ p :=fy1 * dx;
+ first:=0;
+ incr :=-1;
+ dy :=-dy;
+
+ end;
+
+ delta:=p div dy;
+ m_d :=p mod dy;
+
+ if m_d < 0 then
+ begin
+ dec(delta );
+ inc(m_d ,dy );
+
+ end;
+
+ x_from:=x1 + delta;
+
+ render_hline(ey1 ,x1 ,fy1 ,x_from ,first );
+
+ inc(ey1 ,incr );
+
+// set_cur_cell(x_from shr poly_base_shift ,ey1 );
+ set_cur_cell(shr_int32(x_from ,poly_base_shift ) ,ey1 );
+
+ if ey1 <> ey2 then
+ begin
+ p :=poly_base_size * dx;
+ lift:=p div dy;
+ rem :=p mod dy;
+
+ if rem < 0 then
+ begin
+ dec(lift );
+ inc(rem ,dy );
+
+ end;
+
+ dec(m_d ,dy );
+
+ while ey1 <> ey2 do
+ begin
+ delta:=lift;
+
+ inc(m_d ,rem );
+
+ if m_d >= 0 then
+ begin
+ dec(m_d ,dy );
+ inc(delta );
+
+ end;
+
+ x_to:=x_from + delta;
+
+ render_hline(ey1 ,x_from ,poly_base_size - first ,x_to ,first );
+
+ x_from:=x_to;
+
+ inc(ey1 ,incr );
+
+ // set_cur_cell(x_from shr poly_base_shift ,ey1 );
+ set_cur_cell(shr_int32(x_from ,poly_base_shift ) ,ey1 );
+
+ end;
+
+ end;
+
+ render_hline(ey1 ,x_from ,poly_base_size - first ,x2 ,fy2 );
+
+end;
+
+{ RENDER_HLINE }
+procedure outline_aa.render_hline;
+var
+ p ,
+ dx ,
+
+ ex1 ,
+ ex2 ,
+ fx1 ,
+ fx2 ,
+
+ delta ,
+ first ,
+ incr ,
+ lift ,
+ m_d ,
+ rem : int;
+
+begin
+// ex1:=x1 shr poly_base_shift;
+// ex2:=x2 shr poly_base_shift;
+ ex1:=shr_int32(x1 ,poly_base_shift );
+ ex2:=shr_int32(x2 ,poly_base_shift );
+
+ fx1:=x1 and poly_base_mask;
+ fx2:=x2 and poly_base_mask;
+
+//trivial case. Happens often
+ if y1 = y2 then
+ begin
+ set_cur_cell(ex2 ,ey );
+
+ exit;
+
+ end;
+
+//everything is located in a single cell. That is easy!
+ if ex1 = ex2 then
+ begin
+ delta:=y2 - y1;
+
+ inc(m_cur_cell.cover ,delta );
+ inc(m_cur_cell.area ,(fx1 + fx2 ) * delta );
+
+ exit;
+
+ end;
+
+//ok, we'll have to render a run of adjacent cells on the same
+//hline...
+ p :=(poly_base_size - fx1 ) * (y2 - y1 );
+ first:=poly_base_size;
+ incr :=1;
+ dx :=x2 - x1;
+
+ if dx < 0 then
+ begin
+ p :=fx1 * (y2 - y1 );
+ first:=0;
+ incr :=-1;
+ dx :=-dx;
+
+ end;
+
+ delta:=p div dx;
+ m_d :=p mod dx;
+
+ if m_d < 0 then
+ begin
+ dec(delta );
+ inc(m_d ,dx );
+
+ end;
+
+ inc(m_cur_cell.cover ,delta );
+ inc(m_cur_cell.area ,(fx1 + first ) * delta );
+
+ inc(ex1 ,incr );
+
+ set_cur_cell(ex1 ,ey );
+
+ inc(y1 ,delta );
+
+ if ex1 <> ex2 then
+ begin
+ p :=poly_base_size * (y2 - y1 + delta );
+ lift:=p div dx;
+ rem :=p mod dx;
+
+ if rem < 0 then
+ begin
+ dec(lift );
+ inc(rem ,dx );
+
+ end;
+
+ dec(m_d ,dx );
+
+ while ex1 <> ex2 do
+ begin
+ delta:=lift;
+
+ inc(m_d ,rem );
+
+ if m_d >= 0 then
+ begin
+ dec(m_d ,dx );
+ inc(delta );
+
+ end;
+
+ inc(m_cur_cell.cover ,delta );
+ inc(m_cur_cell.area ,(poly_base_size ) * delta );
+ inc(y1 ,delta );
+ inc(ex1 ,incr );
+
+ set_cur_cell(ex1 ,ey );
+
+ end;
+
+ end;
+
+ delta:=y2 - y1;
+
+ inc(m_cur_cell.cover ,delta );
+ inc(m_cur_cell.area ,(fx2 + poly_base_size - first ) * delta );
+
+end;
+
+{ ALLOCATE_BLOCK }
+procedure outline_aa.allocate_block;
+var
+ new_cells : cell_aa_ptr_ptr;
+
+begin
+ if m_cur_block >= m_num_blocks then
+ begin
+ if m_num_blocks >= m_max_blocks then
+ begin
+ agg_getmem(pointer(new_cells ) ,sizeof(cell_aa_ptr ) * (m_max_blocks + cell_block_pool ) );
+
+ if m_cells <> NIL then
+ begin
+ move(m_cells^ ,new_cells^ ,sizeof(cell_aa_ptr ) * m_max_blocks );
+
+ agg_freemem(pointer(m_cells ) ,sizeof(cell_aa_ptr ) * m_max_blocks );
+
+ end;
+
+ m_cells:=new_cells;
+
+ inc(m_max_blocks ,cell_block_pool );
+
+ end;
+
+ agg_getmem(
+ pointer(pointer(ptrcomp(m_cells ) + m_num_blocks * sizeof(cell_aa_ptr ) )^ ) ,
+ cell_block_size * sizeof(cell_aa ) );
+
+ inc(m_num_blocks );
+
+ end;
+
+ m_cur_cell_ptr:=cell_aa_ptr_ptr(ptrcomp(m_cells ) + m_cur_block * sizeof(cell_aa_ptr ) )^;
+
+ inc(m_cur_block );
+
+end;
+
+{ _MIN_X }
+function outline_aa._min_x;
+begin
+ result:=m_min_x;
+
+end;
+
+{ _MIN_Y }
+function outline_aa._min_y;
+begin
+ result:=m_min_y;
+
+end;
+
+{ _MAX_X }
+function outline_aa._max_x;
+begin
+ result:=m_max_x;
+
+end;
+
+{ _MAX_Y }
+function outline_aa._max_y;
+begin
+ result:=m_max_y;
+
+end;
+
+{ CONSTRUCT }
+constructor scanline_hit_test.Construct;
+begin
+ m_x :=x;
+ m_hit:=false;
+
+end;
+
+{ RESET_SPANS }
+procedure scanline_hit_test.reset_spans;
+begin
+end;
+
+{ FINALIZE }
+procedure scanline_hit_test.finalize;
+begin
+end;
+
+{ ADD_CELL }
+procedure scanline_hit_test.add_cell;
+begin
+ if m_x = x then
+ m_hit:=true;
+
+end;
+
+{ ADD_SPAN }
+procedure scanline_hit_test.add_span;
+begin
+ if (m_x >= x ) and
+ (m_x < x + len ) then
+ m_hit:=true;
+
+end;
+
+{ NUM_SPANS }
+function scanline_hit_test.num_spans;
+begin
+ result:=1;
+
+end;
+
+{ HIT }
+function scanline_hit_test.hit;
+begin
+ result:=m_hit;
+
+end;
+
+{ CONSTRUCT }
+constructor rasterizer_scanline_aa.Construct;
+var
+ i : integer;
+
+begin
+ m_outline.Construct;
+ m_clip_box.Construct;
+
+ m_filling_rule:=fill_non_zero;
+ m_auto_close :=true;
+
+ m_clipped_start_x:=0;
+ m_clipped_start_y:=0;
+
+ m_start_x:=0;
+ m_start_y:=0;
+ m_prev_x :=0;
+ m_prev_y :=0;
+
+ m_prev_flags:=0;
+ m_status :=status_initial;
+ m_clipping :=false;
+
+ for i:=0 to aa_num - 1 do
+ m_gamma[i ]:=i;
+
+ XScale:=1;
+
+end;
+
+{ DESTRUCT }
+destructor rasterizer_scanline_aa.Destruct;
+begin
+ m_outline.Destruct;
+
+end;
+
+{ RESET }
+procedure rasterizer_scanline_aa.reset;
+begin
+ m_outline.reset;
+
+ m_status:=status_initial;
+
+end;
+
+{ FILLING_RULE }
+procedure rasterizer_scanline_aa.filling_rule;
+begin
+ m_filling_rule:=filling_rule_;
+
+end;
+
+{ AUTO_CLOSE }
+procedure rasterizer_scanline_aa.auto_close;
+begin
+ m_auto_close:=flag;
+
+end;
+
+{ CLIP_BOX }
+procedure rasterizer_scanline_aa.clip_box;
+begin
+ reset;
+
+ m_clip_box.x1:=poly_coord(x1 );
+ m_clip_box.y1:=poly_coord(y1 );
+ m_clip_box.x2:=poly_coord(x2 );
+ m_clip_box.y2:=poly_coord(y2 );
+
+ m_clip_box.normalize;
+
+ m_clipping:=true;
+
+end;
+
+{ GAMMA }
+procedure rasterizer_scanline_aa.gamma;
+var
+ i : int;
+
+begin
+ for i:=0 to aa_num - 1 do
+ m_gamma[i ]:=
+ trunc(
+ gamma_function.func_operator_gamma(i / aa_mask ) * aa_mask + 0.5 );
+
+end;
+
+{ APPLY_GAMMA }
+function rasterizer_scanline_aa.apply_gamma;
+begin
+ result:=m_gamma[cover ];
+
+end;
+
+{ MOVE_TO_NO_CLIP }
+procedure rasterizer_scanline_aa.move_to_no_clip;
+begin
+ if (m_status = status_line_to ) and
+ m_auto_close then
+ close_polygon_no_clip;
+
+ m_outline.move_to(x * XScale ,y );
+
+ m_clipped_start_x:=x;
+ m_clipped_start_y:=y;
+
+ m_status:=status_line_to;
+
+end;
+
+{ LINE_TO_NO_CLIP }
+procedure rasterizer_scanline_aa.line_to_no_clip;
+begin
+if m_status <> status_initial then
+ begin
+ m_outline.line_to(x * XScale ,y );
+
+ m_status:=status_line_to;
+
+ end;
+
+end;
+
+{ CLOSE_POLYGON }
+procedure rasterizer_scanline_aa.close_polygon;
+begin
+ if m_clipping then
+ clip_segment(m_start_x ,m_start_y );
+
+ if m_auto_close then
+ close_polygon_no_clip;
+
+end;
+
+{ CLOSE_POLYGON_NO_CLIP }
+procedure rasterizer_scanline_aa.close_polygon_no_clip;
+begin
+ if m_status = status_line_to then
+ begin
+ m_outline.line_to(m_clipped_start_x * XScale ,m_clipped_start_y );
+
+ m_status:=status_closed;
+
+ end;
+
+end;
+
+{ CLIP_SEGMENT }
+procedure rasterizer_scanline_aa.clip_segment;
+var
+ flags ,n : unsigned;
+
+ cx ,cy : array[0..3 ] of int;
+ px ,py : int_ptr;
+
+begin
+ flags:=clipping_flags_int(x ,y ,@m_clip_box );
+
+ if m_prev_flags = flags then
+ if flags = 0 then
+ if m_status = status_initial then
+ move_to_no_clip(x ,y )
+ else
+ line_to_no_clip(x ,y )
+ else
+ else
+ begin
+ n:=clip_liang_barsky_int(m_prev_x ,m_prev_y ,x ,y ,@m_clip_box ,@cx[0 ] ,@cy[0 ] );
+
+ px:=@cx[0 ];
+ py:=@cy[0 ];
+
+ while n > 0 do
+ begin
+ if m_status = status_initial then
+ move_to_no_clip(px^ ,py^ )
+ else
+ line_to_no_clip(px^ ,py^ );
+
+ inc(ptrcomp(px ) ,sizeof(int ) );
+ inc(ptrcomp(py ) ,sizeof(int ) );
+ dec(n );
+
+ end;
+
+ end;
+
+ m_prev_flags:=flags;
+
+ m_prev_x:=x;
+ m_prev_y:=y;
+
+end;
+
+{ MOVE_TO_D }
+procedure rasterizer_scanline_aa.move_to_d;
+begin
+ move_to(poly_coord(x ) ,poly_coord(y ) );
+
+end;
+
+{ LINE_TO_D }
+procedure rasterizer_scanline_aa.line_to_d;
+begin
+ line_to(poly_coord(x ) ,poly_coord(y ) );
+
+end;
+
+{ MOVE_TO }
+procedure rasterizer_scanline_aa.move_to;
+begin
+ if m_clipping then
+ begin
+ if m_outline.sorted then
+ reset;
+
+ if (m_status = status_line_to ) and
+ m_auto_close then
+ close_polygon;
+
+ m_prev_x :=x;
+ m_start_x:=x;
+ m_prev_y :=y;
+ m_start_y:=y;
+ m_status :=status_initial;
+
+ m_prev_flags:=clipping_flags_int(x ,y ,@m_clip_box );
+
+ if m_prev_flags = 0 then
+ move_to_no_clip(x ,y );
+
+ end
+ else
+ move_to_no_clip(x ,y );
+
+end;
+
+{ LINE_TO }
+procedure rasterizer_scanline_aa.line_to;
+begin
+ if m_clipping then
+ clip_segment(x ,y )
+ else
+ line_to_no_clip(x ,y );
+
+end;
+
+{ SORT }
+procedure rasterizer_scanline_aa.sort;
+begin
+ m_outline.sort_cells;
+
+end;
+
+{ REWIND_SCANLINES }
+function rasterizer_scanline_aa.rewind_scanlines;
+begin
+ if m_auto_close then
+ close_polygon;
+
+ m_outline.sort_cells;
+
+ if m_outline.total_cells = 0 then
+ begin
+ result:=false;
+
+ exit;
+
+ end;
+
+ m_cur_y:=m_outline._min_y;
+ result :=true;
+
+end;
+
+{ SWEEP_SCANLINE }
+function rasterizer_scanline_aa.sweep_scanline;
+var
+ x ,
+ area ,
+ cover : int;
+ alpha : unsigned;
+ cells : cell_aa_ptr_ptr;
+
+ cur_cell : cell_aa_ptr;
+ num_cells : unsigned;
+
+begin
+ repeat
+ if m_cur_y > m_outline._max_y then
+ begin
+ result:=false;
+
+ exit;
+
+ end;
+
+ sl.reset_spans;
+
+ num_cells:=m_outline.scanline_num_cells(m_cur_y );
+ cells :=m_outline.scanline_cells (m_cur_y );
+
+ cover:=0;
+
+ while num_cells > 0 do
+ begin
+ cur_cell:=cells^;
+
+ x :=cur_cell.x;
+ area:=cur_cell.area;
+
+ inc(cover ,cur_cell.cover );
+
+ //accumulate all cells with the same X
+ dec(num_cells );
+
+ while num_cells > 0 do
+ begin
+ inc(ptrcomp(cells ) ,sizeof(cell_aa_ptr ) );
+
+ cur_cell:=cells^;
+
+ if cur_cell.x <> x then
+ break;
+
+ inc(area ,cur_cell.area );
+ inc(cover ,cur_cell.cover );
+
+ dec(num_cells );
+
+ end;
+
+ if area <> 0 then
+ begin
+ alpha:=calculate_alpha((cover shl (poly_base_shift + 1 ) ) - area );
+
+ if alpha <> 0 then
+ sl.add_cell(x ,alpha );
+
+ inc(x );
+
+ end;
+
+ if (num_cells <> 0 ) and
+ (cur_cell.x > x ) then
+ begin
+ alpha:=calculate_alpha(cover shl (poly_base_shift + 1 ) );
+
+ if alpha <> 0 then
+ sl.add_span(x ,cur_cell.x - x ,alpha );
+
+ end;
+
+ end;
+
+ if boolean(sl.num_spans ) then
+ break;
+
+ inc(m_cur_y );
+
+ until false;
+
+ sl.finalize(m_cur_y);
+
+ inc(m_cur_y );
+
+ result:=true;
+
+end;
+
+{ NAVIGATE_SCANLINE }
+function rasterizer_scanline_aa.navigate_scanline;
+begin
+ if m_auto_close then
+ close_polygon;
+
+ m_outline.sort_cells;
+
+ if (m_outline.total_cells = 0 ) or
+ (y < m_outline._min_y ) or
+ (y > m_outline._max_y ) then
+ begin
+ result:=false;
+
+ exit;
+
+ end;
+
+ m_cur_y:=y;
+ result :=true;
+
+end;
+
+{ HIT_TEST }
+function rasterizer_scanline_aa.hit_test;
+var
+ sl : scanline_hit_test;
+
+begin
+ if not navigate_scanline(ty ) then
+ begin
+ result:=false;
+
+ exit;
+
+ end;
+
+ sl.Construct (tx );
+ sweep_scanline(@sl );
+
+ result:=sl.hit;
+
+end;
+
+{ _MIN_X }
+function rasterizer_scanline_aa._min_x;
+begin
+ result:=m_outline._min_x;
+
+end;
+
+{ _MIN_Y }
+function rasterizer_scanline_aa._min_y;
+begin
+ result:=m_outline._min_y;
+
+end;
+
+{ _MAX_X }
+function rasterizer_scanline_aa._max_x;
+begin
+ result:=m_outline._max_x;
+
+end;
+
+{ _MAX_Y }
+function rasterizer_scanline_aa._max_y;
+begin
+ result:=m_outline._max_y;
+
+end;
+
+{ CALCULATE_ALPHA }
+function rasterizer_scanline_aa.calculate_alpha;
+var
+ cover : system.integer;
+
+begin
+// 1: cover:=area shr (poly_base_shift * 2 + 1 - aa_shift );
+// 2: cover:=round(area / (1 shl (poly_base_shift * 2 + 1 - aa_shift ) ) );
+ cover:=shr_int32(area ,poly_base_shift * 2 + 1 - aa_shift );
+
+ if cover < 0 then
+ cover:=-cover;
+
+ if m_filling_rule = fill_even_odd then
+ begin
+ cover:=cover and aa_2mask;
+
+ if cover > aa_num then
+ cover:=aa_2num - cover;
+
+ end;
+
+ if cover > aa_mask then
+ cover:=aa_mask;
+
+ result:=m_gamma[cover ];
+
+end;
+
+{ ADD_PATH }
+procedure rasterizer_scanline_aa.add_path;
+var
+ cmd : unsigned;
+ x ,y : double;
+
+begin
+ vs.rewind(path_id );
+
+ cmd:=vs.vertex(@x ,@y );
+
+ while not is_stop(cmd ) do
+ begin
+ add_vertex(x ,y ,cmd );
+
+ cmd:=vs.vertex(@x ,@y );
+
+ end;
+
+end;
+
+{ ADD_VERTEX }
+procedure rasterizer_scanline_aa.add_vertex;
+begin
+ if is_close(cmd ) then
+ close_polygon
+ else
+ if is_move_to(cmd ) then
+ move_to(poly_coord(x ) ,poly_coord(y ) )
+ else
+ if is_vertex(cmd ) then
+ line_to(poly_coord(x ) ,poly_coord(y ) );
+
+end;
+
+{ POLY_COORD }
+function poly_coord;
+begin
+ result:=trunc(c * poly_base_size );
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_rasterizer_sl_clip.pas b/src/corelib/render/software/agg_rasterizer_sl_clip.pas
new file mode 100644
index 00000000..6ad96f81
--- /dev/null
+++ b/src/corelib/render/software/agg_rasterizer_sl_clip.pas
@@ -0,0 +1,1154 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2007
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 16.10.2007-Milano: Finished OK
+// 15.10.2007-Milano: Unit port establishment
+//
+{ agg_rasterizer_sl_clip.pas }
+unit
+ agg_rasterizer_sl_clip ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_clip_liang_barsky ,
+ agg_rasterizer_cells_aa ;
+
+{ GLOBAL VARIABLES & CONSTANTS }
+const
+ poly_max_coord = (1 shl 30 ) - 1; //----poly_max_coord
+
+ max_stack = 4;
+
+{ TYPES DEFINITION }
+type
+ poly_max_coord_e = int;
+
+ ras_conv_ptr = ^ras_conv;
+ ras_conv = object
+ function mul_div(a ,b ,c : double ) : pointer; virtual; abstract;
+
+ function xi(v : pointer ) : int; virtual; abstract;
+ function yi(v : pointer ) : int; virtual; abstract;
+
+ function upscale (v : double ) : pointer; virtual; abstract;
+ function downscale(v : int ) : pointer; virtual; abstract;
+
+ end;
+
+ ras_conv_int = object(ras_conv )
+ result_ : array[1..max_stack ] of int;
+ stack_ : int;
+
+ constructor Construct;
+
+ function mul_div(a ,b ,c : double ) : pointer; virtual;
+
+ function xi(v : pointer ) : int; virtual;
+ function yi(v : pointer ) : int; virtual;
+
+ function upscale (v : double ) : pointer; virtual;
+ function downscale(v : int ) : pointer; virtual;
+
+ end;
+
+ ras_conv_int_sat = object(ras_conv )
+ result_ : array[1..max_stack ] of int;
+ stack_ : int;
+
+ constructor Construct;
+
+ function mul_div(a ,b ,c : double ) : pointer; virtual;
+
+ function xi(v : pointer ) : int; virtual;
+ function yi(v : pointer ) : int; virtual;
+
+ function upscale (v : double ) : pointer; virtual;
+ function downscale(v : int ) : pointer; virtual;
+
+ end;
+
+ ras_conv_int_3x = object(ras_conv )
+ result_ : array[1..max_stack ] of int;
+ stack_ : int;
+
+ constructor Construct;
+
+ function mul_div(a ,b ,c : double ) : pointer; virtual;
+
+ function xi(v : pointer ) : int; virtual;
+ function yi(v : pointer ) : int; virtual;
+
+ function upscale (v : double ) : pointer; virtual;
+ function downscale(v : int ) : pointer; virtual;
+
+ end;
+
+ ras_conv_dbl = object(ras_conv )
+ result_ : array[1..max_stack ] of double;
+ stack_ : int;
+
+ constructor Construct;
+
+ function mul_div(a ,b ,c : double ) : pointer; virtual;
+
+ function xi(v : pointer ) : int; virtual;
+ function yi(v : pointer ) : int; virtual;
+
+ function upscale (v : double ) : pointer; virtual;
+ function downscale(v : int ) : pointer; virtual;
+
+ end;
+
+ ras_conv_dbl_3x = object(ras_conv )
+ result_ : array[1..max_stack ] of double;
+ stack_ : int;
+
+ constructor Construct;
+
+ function mul_div(a ,b ,c : double ) : pointer; virtual;
+
+ function xi(v : pointer ) : int; virtual;
+ function yi(v : pointer ) : int; virtual;
+
+ function upscale (v : double ) : pointer; virtual;
+ function downscale(v : int ) : pointer; virtual;
+
+ end;
+
+ rasterizer_sl_ptr = ^rasterizer_sl;
+ rasterizer_sl = object
+ procedure reset_clipping; virtual; abstract;
+ procedure clip_box(x1 ,y1 ,x2 ,y2 : pointer ); virtual; abstract;
+ procedure move_to (x1 ,y1 : pointer ); virtual; abstract;
+ procedure line_to (ras : rasterizer_cells_aa_ptr; x2 ,y2 : pointer ); virtual; abstract;
+
+ function conv_type : ras_conv_ptr; virtual; abstract;
+
+ end;
+
+ rasterizer_sl_clip_int_ = object(rasterizer_sl )
+ private
+ t_conv : ras_conv_ptr;
+
+ m_clip_box : rect;
+
+ m_x1 ,
+ m_y1 : int;
+
+ m_f1 : unsigned;
+
+ m_clipping : boolean;
+
+ public
+ constructor Construct(conv : ras_conv_ptr );
+
+ procedure reset_clipping; virtual;
+ procedure clip_box(x1 ,y1 ,x2 ,y2 : pointer ); virtual;
+ procedure move_to (x1 ,y1 : pointer ); virtual;
+ procedure line_to (ras : rasterizer_cells_aa_ptr; x2 ,y2 : pointer ); virtual;
+
+ function conv_type : ras_conv_ptr; virtual;
+
+ private
+ procedure line_clip_y(ras : rasterizer_cells_aa_ptr; x1 ,y1 ,x2 ,y2 : int; f1 ,f2 : unsigned );
+
+ end;
+
+ rasterizer_sl_clip_dbl_ = object(rasterizer_sl )
+ private
+ t_conv : ras_conv_ptr;
+
+ m_clip_box : rect_d;
+
+ m_x1 ,
+ m_y1 : double;
+
+ m_f1 : unsigned;
+
+ m_clipping : boolean;
+
+ public
+ constructor Construct(conv : ras_conv_ptr );
+
+ procedure reset_clipping; virtual;
+ procedure clip_box(x1 ,y1 ,x2 ,y2 : pointer ); virtual;
+ procedure move_to (x1 ,y1 : pointer ); virtual;
+ procedure line_to (ras : rasterizer_cells_aa_ptr; x2 ,y2 : pointer ); virtual;
+
+ function conv_type : ras_conv_ptr; virtual;
+
+ private
+ procedure line_clip_y(ras : rasterizer_cells_aa_ptr; x1 ,y1 ,x2 ,y2 : double; f1 ,f2 : unsigned );
+
+ end;
+
+ rasterizer_sl_no_clip = object(rasterizer_sl )
+ private
+ m_x1 ,
+ m_y1 : int;
+
+ m_conv : ras_conv_int;
+
+ public
+ constructor Construct;
+
+ procedure reset_clipping; virtual;
+ procedure clip_box(x1 ,y1 ,x2 ,y2 : pointer ); virtual;
+ procedure move_to (x1 ,y1 : pointer ); virtual;
+ procedure line_to (ras : rasterizer_cells_aa_ptr; x2 ,y2 : pointer ); virtual;
+
+ function conv_type : ras_conv_ptr; virtual;
+
+ end;
+
+ rasterizer_sl_clip_int = object(rasterizer_sl_clip_int_ )
+ private
+ m_conv : ras_conv_int;
+
+ public
+ constructor Construct;
+
+ end;
+
+ rasterizer_sl_clip_int_sat = object(rasterizer_sl_clip_int_ )
+ private
+ m_conv : ras_conv_int_sat;
+
+ public
+ constructor Construct;
+
+ end;
+
+ rasterizer_sl_clip_int_3x = object(rasterizer_sl_clip_int_ )
+ private
+ m_conv : ras_conv_int_3x;
+
+ public
+ constructor Construct;
+
+ end;
+
+ rasterizer_sl_clip_dbl = object(rasterizer_sl_clip_dbl_ )
+ private
+ m_conv : ras_conv_dbl;
+
+ public
+ constructor Construct;
+
+ end;
+
+ rasterizer_sl_clip_dbl_3x = object(rasterizer_sl_clip_dbl_ )
+ private
+ m_conv : ras_conv_dbl_3x;
+
+ public
+ constructor Construct;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor ras_conv_int.Construct;
+begin
+ stack_:=1;
+
+end;
+
+{ MUL_DIV }
+function ras_conv_int.mul_div(a ,b ,c : double ) : pointer;
+begin
+ result_[stack_ ]:=iround(a * b / c );
+
+ result:=@result_[stack_ ];
+
+ inc(stack_ );
+
+ if stack_ > max_stack then
+ stack_:=1;
+
+end;
+
+{ XI }
+function ras_conv_int.xi(v : pointer ) : int;
+begin
+ result:=int_ptr(v )^;
+
+end;
+
+{ YI }
+function ras_conv_int.yi(v : pointer ) : int;
+begin
+ result:=int_ptr(v )^;
+
+end;
+
+{ UPSCALE }
+function ras_conv_int.upscale(v : double ) : pointer;
+begin
+ result_[stack_ ]:=iround(v * poly_subpixel_scale );
+
+ result:=@result_[stack_ ];
+
+ inc(stack_ );
+
+ if stack_ > max_stack then
+ stack_:=1;
+
+end;
+
+{ DOWNSCALE }
+function ras_conv_int.downscale(v : int ) : pointer;
+begin
+ result_[stack_ ]:=v;
+
+ result:=@result_[stack_ ];
+
+ inc(stack_ );
+
+ if stack_ > max_stack then
+ stack_:=1;
+
+end;
+
+{ CONSTRUCT }
+constructor ras_conv_int_sat.Construct;
+begin
+ stack_:=1;
+
+end;
+
+{ MUL_DIV }
+function ras_conv_int_sat.mul_div(a ,b ,c : double ) : pointer;
+begin
+ result_[stack_ ]:=saturation_iround(poly_max_coord ,a * b / c );
+
+ result:=@result_[stack_ ];
+
+ inc(stack_ );
+
+ if stack_ > max_stack then
+ stack_:=1;
+
+end;
+
+{ XI }
+function ras_conv_int_sat.xi(v : pointer ) : int;
+begin
+ result:=int_ptr(v )^;
+
+end;
+
+{ YI }
+function ras_conv_int_sat.yi(v : pointer ) : int;
+begin
+ result:=int_ptr(v )^;
+
+end;
+
+{ UPSCALE }
+function ras_conv_int_sat.upscale(v : double ) : pointer;
+begin
+ result_[stack_ ]:=saturation_iround(poly_max_coord ,v * poly_subpixel_scale );
+
+ result:=@result_[stack_ ];
+
+ inc(stack_ );
+
+ if stack_ > max_stack then
+ stack_:=1;
+
+end;
+
+{ DOWNSCALE }
+function ras_conv_int_sat.downscale(v : int ) : pointer;
+begin
+ result_[stack_ ]:=v;
+
+ result:=@result_[stack_ ];
+
+ inc(stack_ );
+
+ if stack_ > max_stack then
+ stack_:=1;
+
+end;
+
+{ CONSTRUCT }
+constructor ras_conv_int_3x.Construct;
+begin
+ stack_:=1;
+
+end;
+
+{ MUL_DIV }
+function ras_conv_int_3x.mul_div(a ,b ,c : double ) : pointer;
+begin
+ result_[stack_ ]:=iround(a * b / c );
+
+ result:=@result_[stack_ ];
+
+ inc(stack_ );
+
+ if stack_ > max_stack then
+ stack_:=1;
+
+end;
+
+{ XI }
+function ras_conv_int_3x.xi(v : pointer ) : int;
+begin
+ result:=int_ptr(v )^ * 3;
+
+end;
+
+{ YI }
+function ras_conv_int_3x.yi(v : pointer ) : int;
+begin
+ result:=int_ptr(v )^;
+
+end;
+
+{ UPSCALE }
+function ras_conv_int_3x.upscale(v : double ) : pointer;
+begin
+ result_[stack_ ]:=iround(v * poly_subpixel_scale );
+
+ result:=@result_[stack_ ];
+
+ inc(stack_ );
+
+ if stack_ > max_stack then
+ stack_:=1;
+
+end;
+
+{ DOWNSCALE }
+function ras_conv_int_3x.downscale(v : int ) : pointer;
+begin
+ result_[stack_ ]:=v;
+
+ result:=@result_[stack_ ];
+
+ inc(stack_ );
+
+ if stack_ > max_stack then
+ stack_:=1;
+
+end;
+
+{ CONSTRUCT }
+constructor ras_conv_dbl.Construct;
+begin
+ stack_:=1;
+
+end;
+
+{ MUL_DIV }
+function ras_conv_dbl.mul_div(a ,b ,c : double ) : pointer;
+begin
+ result_[stack_ ]:=a * b / c;
+
+ result:=@result_[stack_ ];
+
+ inc(stack_ );
+
+ if stack_ > max_stack then
+ stack_:=1;
+
+end;
+
+{ XI }
+function ras_conv_dbl.xi(v : pointer ) : int;
+begin
+ result:=iround(double_ptr(v )^ * poly_subpixel_scale );
+
+end;
+
+{ YI }
+function ras_conv_dbl.yi(v : pointer ) : int;
+begin
+ result:=iround(double_ptr(v )^ * poly_subpixel_scale );
+
+end;
+
+{ UPSCALE }
+function ras_conv_dbl.upscale(v : double ) : pointer;
+begin
+ result_[stack_ ]:=v;
+
+ result:=@result_[stack_ ];
+
+ inc(stack_ );
+
+ if stack_ > max_stack then
+ stack_:=1;
+
+end;
+
+{ DOWNSCALE }
+function ras_conv_dbl.downscale(v : int ) : pointer;
+begin
+ result_[stack_ ]:=v / poly_subpixel_scale;
+
+ result:=@result_[stack_ ];
+
+ inc(stack_ );
+
+ if stack_ > max_stack then
+ stack_:=1;
+
+end;
+
+{ CONSTRUCT }
+constructor ras_conv_dbl_3x.Construct;
+begin
+ stack_:=1;
+
+end;
+
+{ MUL_DIV }
+function ras_conv_dbl_3x.mul_div(a ,b ,c : double ) : pointer;
+begin
+ result_[stack_ ]:=a * b / c;
+
+ result:=@result_[stack_ ];
+
+ inc(stack_ );
+
+ if stack_ > max_stack then
+ stack_:=1;
+
+end;
+
+{ XI }
+function ras_conv_dbl_3x.xi(v : pointer ) : int;
+begin
+ result:=iround(double_ptr(v )^ * poly_subpixel_scale * 3 );
+
+end;
+
+{ YI }
+function ras_conv_dbl_3x.yi(v : pointer ) : int;
+begin
+ result:=iround(double_ptr(v )^ * poly_subpixel_scale );
+
+end;
+
+{ UPSCALE }
+function ras_conv_dbl_3x.upscale(v : double ) : pointer;
+begin
+ result_[stack_ ]:=v;
+
+ result:=@result_[stack_ ];
+
+ inc(stack_ );
+
+ if stack_ > max_stack then
+ stack_:=1;
+
+end;
+
+{ DOWNSCALE }
+function ras_conv_dbl_3x.downscale(v : int ) : pointer;
+begin
+ result_[stack_ ]:=v / poly_subpixel_scale;
+
+ result:=@result_[stack_ ];
+
+ inc(stack_ );
+
+ if stack_ > max_stack then
+ stack_:=1;
+
+end;
+
+{ CONSTRUCT }
+constructor rasterizer_sl_clip_int_.Construct(conv : ras_conv_ptr );
+begin
+ t_conv:=conv;
+
+ m_clip_box.Construct(0 ,0 ,0 ,0 );
+
+ m_x1:=0;
+ m_y1:=0;
+ m_f1:=0;
+
+ m_clipping:=false;
+
+end;
+
+{ RESET_CLIPPING }
+procedure rasterizer_sl_clip_int_.reset_clipping;
+begin
+ m_clipping:=false;
+
+end;
+
+{ CLIP_BOX }
+procedure rasterizer_sl_clip_int_.clip_box(x1 ,y1 ,x2 ,y2 : pointer );
+begin
+ m_clip_box.Construct(int_ptr(x1 )^ ,int_ptr(y1 )^ ,int_ptr(x2 )^ ,int_ptr(y2 )^ );
+ m_clip_box.normalize;
+
+ m_clipping:=true;
+
+end;
+
+{ MOVE_TO }
+procedure rasterizer_sl_clip_int_.move_to(x1 ,y1 : pointer );
+begin
+ m_x1:=int_ptr(x1 )^;
+ m_y1:=int_ptr(y1 )^;
+
+ if m_clipping then
+ m_f1:=clipping_flags_int(int_ptr(x1 )^ ,int_ptr(y1 )^ ,@m_clip_box );
+
+end;
+
+{ LINE_TO }
+procedure rasterizer_sl_clip_int_.line_to(ras : rasterizer_cells_aa_ptr; x2 ,y2 : pointer );
+var
+ f1 ,f2 ,f3 ,f4 : unsigned;
+ x1 ,y1 ,y3 ,y4 : int;
+
+begin
+ if m_clipping then
+ begin
+ f2:=clipping_flags_int(int_ptr(x2 )^ ,int_ptr(y2 )^ ,@m_clip_box );
+
+ // Invisible by Y
+ if ((m_f1 and 10) = (f2 and 10) ) and
+ (m_f1 and 10 <> 0 ) then
+ begin
+ m_x1:=int_ptr(x2 )^;
+ m_y1:=int_ptr(y2 )^;
+ m_f1:=f2;
+
+ exit;
+
+ end;
+
+ x1:=m_x1;
+ y1:=m_y1;
+ f1:=m_f1;
+
+ case ((f1 and 5 ) shl 1 ) or (f2 and 5 ) of
+ // Visible by X
+ 0 : line_clip_y(ras ,x1 ,y1 ,int_ptr(x2 )^ ,int_ptr(y2 )^ ,f1 ,f2 );
+
+ // x2 > clip.x2
+ 1 :
+ begin
+ y3:=y1 + int_ptr(t_conv.mul_div(m_clip_box.x2 - x1 ,int_ptr(y2 )^ - y1 ,int_ptr(x2 )^ - x1 ) )^;
+ f3:=clipping_flags_y_int(y3 ,@m_clip_box );
+
+ line_clip_y(ras ,x1 ,y1 ,m_clip_box.x2 ,y3 ,f1 ,f3 );
+ line_clip_y(ras ,m_clip_box.x2 ,y3 ,m_clip_box.x2 ,int_ptr(y2 )^ ,f3 ,f2 );
+
+ end;
+
+ // x1 > clip.x2
+ 2 :
+ begin
+ y3:=y1 + int_ptr(t_conv.mul_div(m_clip_box.x2 - x1 ,int_ptr(y2 )^ - y1 ,int_ptr(x2 )^ - x1 ) )^;
+ f3:=clipping_flags_y_int(y3 ,@m_clip_box );
+
+ line_clip_y(ras ,m_clip_box.x2 ,y1 ,m_clip_box.x2 ,y3 ,f1 ,f3 );
+ line_clip_y(ras ,m_clip_box.x2 ,y3 ,int_ptr(x2 )^ ,int_ptr(y2 )^ ,f3 ,f2 );
+
+ end;
+
+ // x1 > clip.x2 && x2 > clip.x2
+ 3 : line_clip_y(ras ,m_clip_box.x2 ,y1 ,m_clip_box.x2 ,int_ptr(y2 )^ ,f1 ,f2 );
+
+ // x2 < clip.x1
+ 4 :
+ begin
+ y3:=y1 + int_ptr(t_conv.mul_div(m_clip_box.x1 - x1 ,int_ptr(y2 )^ - y1 ,int_ptr(x2 )^ - x1 ) )^;
+ f3:=clipping_flags_y_int(y3 ,@m_clip_box );
+
+ line_clip_y(ras ,x1 ,y1 ,m_clip_box.x1 ,y3 ,f1 ,f3 );
+ line_clip_y(ras ,m_clip_box.x1 ,y3 ,m_clip_box.x1 ,int_ptr(y2 )^ ,f3 ,f2 );
+
+ end;
+
+ // x1 > clip.x2 && x2 < clip.x1
+ 6 :
+ begin
+ y3:=y1 + int_ptr(t_conv.mul_div(m_clip_box.x2 - x1 ,int_ptr(y2 )^ - y1 ,int_ptr(x2 )^ - x1 ) )^;
+ y4:=y1 + int_ptr(t_conv.mul_div(m_clip_box.x1 - x1 ,int_ptr(y2 )^ - y1 ,int_ptr(x2 )^ - x1 ) )^;
+
+ f3:=clipping_flags_y_int(y3 ,@m_clip_box );
+ f4:=clipping_flags_y_int(y4 ,@m_clip_box );
+
+ line_clip_y(ras ,m_clip_box.x2 ,y1 ,m_clip_box.x2 ,y3 ,f1 ,f3 );
+ line_clip_y(ras ,m_clip_box.x2 ,y3 ,m_clip_box.x1 ,y4 ,f3 ,f4 );
+ line_clip_y(ras ,m_clip_box.x1 ,y4 ,m_clip_box.x1 ,int_ptr(y2 )^ ,f4 ,f2 );
+
+ end;
+
+ // x1 < clip.x1
+ 8 :
+ begin
+ y3:=y1 + int_ptr(t_conv.mul_div(m_clip_box.x1 - x1 ,int_ptr(y2 )^ - y1 ,int_ptr(x2 )^ - x1 ) )^;
+ f3:=clipping_flags_y_int(y3 ,@m_clip_box );
+
+ line_clip_y(ras ,m_clip_box.x1 ,y1 ,m_clip_box.x1 ,y3 ,f1 ,f3 );
+ line_clip_y(ras ,m_clip_box.x1 ,y3 ,int_ptr(x2 )^ ,int_ptr(y2 )^ ,f3 ,f2 );
+
+ end;
+
+ // x1 < clip.x1 && x2 > clip.x2
+ 9 :
+ begin
+ y3:=y1 + int_ptr(t_conv.mul_div(m_clip_box.x1 - x1 ,int_ptr(y2 )^ - y1 ,int_ptr(x2 )^ - x1 ) )^;
+ y4:=y1 + int_ptr(t_conv.mul_div(m_clip_box.x2 - x1 ,int_ptr(y2 )^ - y1 ,int_ptr(x2 )^ - x1 ) )^;
+ f3:=clipping_flags_y_int(y3 ,@m_clip_box );
+ f4:=clipping_flags_y_int(y4 ,@m_clip_box );
+
+ line_clip_y(ras ,m_clip_box.x1 ,y1 ,m_clip_box.x1 ,y3 ,f1 ,f3 );
+ line_clip_y(ras ,m_clip_box.x1 ,y3 ,m_clip_box.x2 ,y4 ,f3 ,f4 );
+ line_clip_y(ras ,m_clip_box.x2 ,y4 ,m_clip_box.x2 ,int_ptr(y2 )^ ,f4 ,f2 );
+
+ end;
+
+ // x1 < clip.x1 && x2 < clip.x1
+ 12 : line_clip_y(ras ,m_clip_box.x1 ,y1 ,m_clip_box.x1 ,int_ptr(y2 )^ ,f1 ,f2 );
+
+ end;
+
+ m_f1:=f2;
+
+ end
+ else
+ ras.line(t_conv.xi(@m_x1 ) ,t_conv.yi(@m_y1 ) ,t_conv.xi(x2 ) ,t_conv.yi(y2 ) );
+
+ m_x1:=int_ptr(x2 )^;
+ m_y1:=int_ptr(y2 )^;
+
+end;
+
+{ CONV_TYPE }
+function rasterizer_sl_clip_int_.conv_type : ras_conv_ptr;
+begin
+ result:=t_conv;
+
+end;
+
+{ LINE_CLIP_Y }
+procedure rasterizer_sl_clip_int_.line_clip_y(ras : rasterizer_cells_aa_ptr; x1 ,y1 ,x2 ,y2 : int; f1 ,f2 : unsigned );
+var
+ tx1 ,ty1 ,tx2 ,ty2 : int;
+
+begin
+ f1:=f1 and 10;
+ f2:=f2 and 10;
+
+ if f1 or f2 = 0 then
+ // Fully visible
+ ras.line(t_conv.xi(@x1 ) ,t_conv.yi(@y1 ) ,t_conv.xi(@x2 ) ,t_conv.yi(@y2 ) )
+
+ else
+ begin
+ // Invisible by Y
+ if f1 = f2 then
+ exit;
+
+ tx1:=x1;
+ ty1:=y1;
+ tx2:=x2;
+ ty2:=y2;
+
+ // y1 < clip.y1
+ if f1 and 8 <> 0 then
+ begin
+ tx1:=x1 + int_ptr(t_conv.mul_div(m_clip_box.y1 - y1 ,x2 - x1 ,y2 - y1 ) )^;
+ ty1:=m_clip_box.y1;
+
+ end;
+
+ // y1 > clip.y2
+ if f1 and 2 <> 0 then
+ begin
+ tx1:=x1 + int_ptr(t_conv.mul_div(m_clip_box.y2 - y1 ,x2 - x1 ,y2 - y1 ) )^;
+ ty1:=m_clip_box.y2;
+
+ end;
+
+ // y2 < clip.y1
+ if f2 and 8 <> 0 then
+ begin
+ tx2:=x1 + int_ptr(t_conv.mul_div(m_clip_box.y1 - y1 ,x2 - x1 ,y2 - y1 ) )^;
+ ty2:=m_clip_box.y1;
+
+ end;
+
+ // y2 > clip.y2
+ if f2 and 2 <> 0 then
+ begin
+ tx2:=x1 + int_ptr(t_conv.mul_div(m_clip_box.y2 - y1 ,x2 - x1 ,y2 - y1 ) )^;
+ ty2:=m_clip_box.y2;
+
+ end;
+
+ ras.line(t_conv.xi(@tx1 ) ,t_conv.yi(@ty1 ) ,t_conv.xi(@tx2 ) ,t_conv.yi(@ty2 ) );
+
+ end;
+
+end;
+
+{ CONSTRUCT }
+constructor rasterizer_sl_clip_dbl_.Construct(conv : ras_conv_ptr );
+begin
+ t_conv:=conv;
+
+ m_clip_box.Construct(0 ,0 ,0 ,0 );
+
+ m_x1:=0;
+ m_y1:=0;
+ m_f1:=0;
+
+ m_clipping:=false;
+
+end;
+
+{ RESET_CLIPPING }
+procedure rasterizer_sl_clip_dbl_.reset_clipping;
+begin
+ m_clipping:=false;
+
+end;
+
+{ CLIP_BOX }
+procedure rasterizer_sl_clip_dbl_.clip_box(x1 ,y1 ,x2 ,y2 : pointer );
+begin
+ m_clip_box.Construct(double_ptr(x1 )^ ,double_ptr(y1 )^ ,double_ptr(x2 )^ ,double_ptr(y2 )^ );
+ m_clip_box.normalize;
+
+ m_clipping:=true;
+
+end;
+
+{ MOVE_TO }
+procedure rasterizer_sl_clip_dbl_.move_to(x1 ,y1 : pointer );
+begin
+ m_x1:=double_ptr(x1 )^;
+ m_y1:=double_ptr(y1 )^;
+
+ if m_clipping then
+ m_f1:=clipping_flags_dbl(double_ptr(x1 )^ ,double_ptr(y1 )^ ,@m_clip_box );
+
+end;
+
+{ LINE_TO }
+procedure rasterizer_sl_clip_dbl_.line_to(ras : rasterizer_cells_aa_ptr; x2 ,y2 : pointer );
+var
+ f1 ,f2 ,f3 ,f4 : unsigned;
+ x1 ,y1 ,y3 ,y4 : double;
+
+begin
+ if m_clipping then
+ begin
+ f2:=clipping_flags_dbl(double_ptr(x2 )^ ,double_ptr(y2 )^ ,@m_clip_box );
+
+ // Invisible by Y
+ if ((m_f1 and 10) = (f2 and 10) ) and
+ (m_f1 and 10 <> 0 ) then
+ begin
+ m_x1:=double_ptr(x2 )^;
+ m_y1:=double_ptr(y2 )^;
+ m_f1:=f2;
+
+ exit;
+
+ end;
+
+ x1:=m_x1;
+ y1:=m_y1;
+ f1:=m_f1;
+
+ case ((f1 and 5 ) shl 1 ) or (f2 and 5 ) of
+ // Visible by X
+ 0 : line_clip_y(ras ,x1 ,y1 ,double_ptr(x2 )^ ,double_ptr(y2 )^ ,f1 ,f2 );
+
+ // x2 > clip.x2
+ 1 :
+ begin
+ y3:=y1 + double_ptr(t_conv.mul_div(m_clip_box.x2 - x1 ,double_ptr(y2 )^ - y1 ,double_ptr(x2 )^ - x1 ) )^;
+ f3:=clipping_flags_y_dbl(y3 ,@m_clip_box );
+
+ line_clip_y(ras ,x1 ,y1 ,m_clip_box.x2 ,y3 ,f1 ,f3 );
+ line_clip_y(ras ,m_clip_box.x2 ,y3 ,m_clip_box.x2 ,double_ptr(y2 )^ ,f3 ,f2 );
+
+ end;
+
+ // x1 > clip.x2
+ 2 :
+ begin
+ y3:=y1 + double_ptr(t_conv.mul_div(m_clip_box.x2 - x1 ,double_ptr(y2 )^ - y1 ,double_ptr(x2 )^ - x1 ) )^;
+ f3:=clipping_flags_y_dbl(y3 ,@m_clip_box );
+
+ line_clip_y(ras ,m_clip_box.x2 ,y1 ,m_clip_box.x2 ,y3 ,f1 ,f3 );
+ line_clip_y(ras ,m_clip_box.x2 ,y3 ,double_ptr(x2 )^ ,double_ptr(y2 )^ ,f3 ,f2 );
+
+ end;
+
+ // x1 > clip.x2 && x2 > clip.x2
+ 3 : line_clip_y(ras ,m_clip_box.x2 ,y1 ,m_clip_box.x2 ,double_ptr(y2 )^ ,f1 ,f2 );
+
+ // x2 < clip.x1
+ 4 :
+ begin
+ y3:=y1 + double_ptr(t_conv.mul_div(m_clip_box.x1 - x1 ,double_ptr(y2 )^ - y1 ,double_ptr(x2 )^ - x1 ) )^;
+ f3:=clipping_flags_y_dbl(y3 ,@m_clip_box );
+
+ line_clip_y(ras ,x1 ,y1 ,m_clip_box.x1 ,y3 ,f1 ,f3 );
+ line_clip_y(ras ,m_clip_box.x1 ,y3 ,m_clip_box.x1 ,double_ptr(y2 )^ ,f3 ,f2 );
+
+ end;
+
+ // x1 > clip.x2 && x2 < clip.x1
+ 6 :
+ begin
+ y3:=y1 + double_ptr(t_conv.mul_div(m_clip_box.x2 - x1 ,double_ptr(y2 )^ - y1 ,double_ptr(x2 )^ - x1 ) )^;
+ y4:=y1 + double_ptr(t_conv.mul_div(m_clip_box.x1 - x1 ,double_ptr(y2 )^ - y1 ,double_ptr(x2 )^ - x1 ) )^;
+
+ f3:=clipping_flags_y_dbl(y3 ,@m_clip_box );
+ f4:=clipping_flags_y_dbl(y4 ,@m_clip_box );
+
+ line_clip_y(ras ,m_clip_box.x2 ,y1 ,m_clip_box.x2 ,y3 ,f1 ,f3 );
+ line_clip_y(ras ,m_clip_box.x2 ,y3 ,m_clip_box.x1 ,y4 ,f3 ,f4 );
+ line_clip_y(ras ,m_clip_box.x1 ,y4 ,m_clip_box.x1 ,double_ptr(y2 )^ ,f4 ,f2 );
+
+ end;
+
+ // x1 < clip.x1
+ 8 :
+ begin
+ y3:=y1 + double_ptr(t_conv.mul_div(m_clip_box.x1 - x1 ,double_ptr(y2 )^ - y1 ,double_ptr(x2 )^ - x1 ) )^;
+ f3:=clipping_flags_y_dbl(y3 ,@m_clip_box );
+
+ line_clip_y(ras ,m_clip_box.x1 ,y1 ,m_clip_box.x1 ,y3 ,f1 ,f3 );
+ line_clip_y(ras ,m_clip_box.x1 ,y3 ,double_ptr(x2 )^ ,double_ptr(y2 )^ ,f3 ,f2 );
+
+ end;
+
+ // x1 < clip.x1 && x2 > clip.x2
+ 9 :
+ begin
+ y3:=y1 + double_ptr(t_conv.mul_div(m_clip_box.x1 - x1 ,double_ptr(y2 )^ - y1 ,double_ptr(x2 )^ - x1 ) )^;
+ y4:=y1 + double_ptr(t_conv.mul_div(m_clip_box.x2 - x1 ,double_ptr(y2 )^ - y1 ,double_ptr(x2 )^ - x1 ) )^;
+ f3:=clipping_flags_y_dbl(y3 ,@m_clip_box );
+ f4:=clipping_flags_y_dbl(y4 ,@m_clip_box );
+
+ line_clip_y(ras ,m_clip_box.x1 ,y1 ,m_clip_box.x1 ,y3 ,f1 ,f3 );
+ line_clip_y(ras ,m_clip_box.x1 ,y3 ,m_clip_box.x2 ,y4 ,f3 ,f4 );
+ line_clip_y(ras ,m_clip_box.x2 ,y4 ,m_clip_box.x2 ,double_ptr(y2 )^ ,f4 ,f2 );
+
+ end;
+
+ // x1 < clip.x1 && x2 < clip.x1
+ 12 : line_clip_y(ras ,m_clip_box.x1 ,y1 ,m_clip_box.x1 ,double_ptr(y2 )^ ,f1 ,f2 );
+
+ end;
+
+ m_f1:=f2;
+
+ end
+ else
+ ras.line(t_conv.xi(@m_x1 ) ,t_conv.yi(@m_y1 ) ,t_conv.xi(x2 ) ,t_conv.yi(y2 ) );
+
+ m_x1:=double_ptr(x2 )^;
+ m_y1:=double_ptr(y2 )^;
+
+end;
+
+{ CONV_TYPE }
+function rasterizer_sl_clip_dbl_.conv_type : ras_conv_ptr;
+begin
+ result:=t_conv;
+
+end;
+
+{ LINE_CLIP_Y }
+procedure rasterizer_sl_clip_dbl_.line_clip_y(ras : rasterizer_cells_aa_ptr; x1 ,y1 ,x2 ,y2 : double; f1 ,f2 : unsigned );
+var
+ tx1 ,ty1 ,tx2 ,ty2 : double;
+
+begin
+ f1:=f1 and 10;
+ f2:=f2 and 10;
+
+ if f1 or f2 = 0 then
+ // Fully visible
+ ras.line(t_conv.xi(@x1 ) ,t_conv.yi(@y1 ) ,t_conv.xi(@x2 ) ,t_conv.yi(@y2 ) )
+
+ else
+ begin
+ // Invisible by Y
+ if f1 = f2 then
+ exit;
+
+ tx1:=x1;
+ ty1:=y1;
+ tx2:=x2;
+ ty2:=y2;
+
+ // y1 < clip.y1
+ if f1 and 8 <> 0 then
+ begin
+ tx1:=x1 + double_ptr(t_conv.mul_div(m_clip_box.y1 - y1 ,x2 - x1 ,y2 - y1 ) )^;
+ ty1:=m_clip_box.y1;
+
+ end;
+
+ // y1 > clip.y2
+ if f1 and 2 <> 0 then
+ begin
+ tx1:=x1 + double_ptr(t_conv.mul_div(m_clip_box.y2 - y1 ,x2 - x1 ,y2 - y1 ) )^;
+ ty1:=m_clip_box.y2;
+
+ end;
+
+ // y2 < clip.y1
+ if f2 and 8 <> 0 then
+ begin
+ tx2:=x1 + double_ptr(t_conv.mul_div(m_clip_box.y1 - y1 ,x2 - x1 ,y2 - y1 ) )^;
+ ty2:=m_clip_box.y1;
+
+ end;
+
+ // y2 > clip.y2
+ if f2 and 2 <> 0 then
+ begin
+ tx2:=x1 + double_ptr(t_conv.mul_div(m_clip_box.y2 - y1 ,x2 - x1 ,y2 - y1 ) )^;
+ ty2:=m_clip_box.y2;
+
+ end;
+
+ ras.line(t_conv.xi(@tx1 ) ,t_conv.yi(@ty1 ) ,t_conv.xi(@tx2 ) ,t_conv.yi(@ty2 ) );
+
+ end;
+
+end;
+
+{ CONSTRUCT }
+constructor rasterizer_sl_no_clip.Construct;
+begin
+ m_x1:=0;
+ m_y1:=0;
+
+ m_conv.Construct;
+
+end;
+
+{ RESET_CLIPPING }
+procedure rasterizer_sl_no_clip.reset_clipping;
+begin
+end;
+
+{ CLIP_BOX }
+procedure rasterizer_sl_no_clip.clip_box(x1 ,y1 ,x2 ,y2 : pointer );
+begin
+end;
+
+{ MOVE_TO }
+procedure rasterizer_sl_no_clip.move_to(x1 ,y1 : pointer );
+begin
+ m_x1:=int_ptr(x1 )^;
+ m_y1:=int_ptr(y1 )^;
+
+end;
+
+{ LINE_TO }
+procedure rasterizer_sl_no_clip.line_to(ras : rasterizer_cells_aa_ptr; x2 ,y2 : pointer );
+begin
+ ras.line(m_x1 ,m_y1 ,int_ptr(x2 )^ ,int_ptr(y2 )^ );
+
+ m_x1:=int_ptr(x2 )^;
+ m_y1:=int_ptr(y2 )^;
+
+end;
+
+{ CONV_TYPE }
+function rasterizer_sl_no_clip.conv_type : ras_conv_ptr;
+begin
+ result:=@m_conv;
+
+end;
+
+{ CONSTRUCT }
+constructor rasterizer_sl_clip_int.Construct;
+begin
+ m_conv.Construct;
+
+ inherited Construct(@m_conv );
+
+end;
+
+{ CONSTRUCT }
+constructor rasterizer_sl_clip_int_sat.Construct;
+begin
+ m_conv.Construct;
+
+ inherited Construct(@m_conv );
+
+end;
+
+{ CONSTRUCT }
+constructor rasterizer_sl_clip_int_3x.Construct;
+begin
+ m_conv.Construct;
+
+ inherited Construct(@m_conv );
+
+end;
+
+{ CONSTRUCT }
+constructor rasterizer_sl_clip_dbl.Construct;
+begin
+ m_conv.Construct;
+
+ inherited Construct(@m_conv );
+
+end;
+
+{ CONSTRUCT }
+constructor rasterizer_sl_clip_dbl_3x.Construct;
+begin
+ m_conv.Construct;
+
+ inherited Construct(@m_conv );
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_render_scanlines.pas b/src/corelib/render/software/agg_render_scanlines.pas
new file mode 100644
index 00000000..d378373e
--- /dev/null
+++ b/src/corelib/render/software/agg_render_scanlines.pas
@@ -0,0 +1,103 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 05.02.2006-Milano: render_all_paths
+// 21.11.2005-Milano: Unit port establishment, render_scanlines
+//
+{ agg_render_scanlines.pas }
+unit
+ agg_render_scanlines ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+{$Q- }
+{$R- }
+uses
+ agg_basics ,
+ agg_color ,
+ agg_rasterizer_scanline_aa ,
+ agg_scanline ,
+ agg_renderer_scanline ,
+ agg_vertex_source ;
+
+{ GLOBAL PROCEDURES }
+ procedure render_scanlines(ras : rasterizer_scanline_ptr; sl : scanline_ptr; ren : renderer_scanline_ptr );
+ procedure render_all_paths(
+ ras : rasterizer_scanline_ptr;
+ sl : scanline_ptr;
+ r : renderer_scanline_ptr;
+ vs : vertex_source_ptr;
+ cs : aggclr_ptr;
+ path_id : unsigned_ptr;
+ num_paths : unsigned );
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ RENDER_SCANLINES }
+procedure render_scanlines;
+begin
+ if ras.rewind_scanlines then
+ begin
+ sl.reset (ras._min_x ,ras._max_x );
+ ren.prepare(unsigned(ras._max_x - ras._min_x + 2 ) );
+
+ if sl.is_embedded then
+ while ras.sweep_scanline_em(sl ) do
+ ren.render(sl )
+ else
+ while ras.sweep_scanline(sl ) do
+ ren.render(sl );
+
+ end;
+
+end;
+
+{ RENDER_ALL_PATHS }
+procedure render_all_paths;
+var
+ i : unsigned;
+
+begin
+ i:=0;
+
+ while i < num_paths do
+ begin
+ ras.reset;
+ ras.add_path(vs ,path_id^ );
+ r.color_ (cs );
+
+ render_scanlines(ras ,sl ,r );
+
+ inc(ptrcomp(cs ) ,sizeof(aggclr ) );
+ inc(ptrcomp(path_id ) ,sizeof(unsigned ) );
+ inc(i );
+
+ end;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_renderer_base.pas b/src/corelib/render/software/agg_renderer_base.pas
new file mode 100644
index 00000000..8ec06ef1
--- /dev/null
+++ b/src/corelib/render/software/agg_renderer_base.pas
@@ -0,0 +1,1162 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2007
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// Class renderer_base
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 19.10.2007-Milano: blend_from_color & blend_from_lut
+// 23.06.2006-Milano: ptrcomp adjustments
+// 03.02.2006-Milano: blend_color_h(v)span
+// 24.11.2005-Milano: renderer_base.blends...
+// 28.09.2005-Milano: Unit port establishment
+//
+{ agg_renderer_base.pas }
+unit
+ agg_renderer_base ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_rendering_buffer ,
+ agg_pixfmt ,
+ agg_color ;
+
+{ TYPES DEFINITION }
+type
+ renderer_base_ptr = ^renderer_base;
+ renderer_base = object
+ m_ren : pixel_formats_ptr;
+ m_clip_box : rect;
+
+ constructor Construct(ren_ : pixel_formats_ptr );
+
+ function ren : pixel_formats_ptr;
+ function width : unsigned;
+ function height : unsigned;
+
+ function clip_box_ (x1 ,y1 ,x2 ,y2 : int ) : boolean;
+ procedure reset_clipping(visibility : boolean ); virtual;
+ procedure clip_box_naked(x1 ,y1 ,x2 ,y2 : int );
+
+ function inbox(x ,y : int ) : boolean;
+
+ procedure first_clip_box; virtual;
+ function next_clip_box : boolean; virtual;
+
+ function _clip_box : rect_ptr;
+ function _xmin : int;
+ function _ymin : int;
+ function _xmax : int;
+ function _ymax : int;
+
+ function bounding_clip_box : rect_ptr; virtual;
+ function bounding_xmin : int; virtual;
+ function bounding_ymin : int; virtual;
+ function bounding_xmax : int; virtual;
+ function bounding_ymax : int; virtual;
+
+ procedure clear(c : aggclr_ptr );
+
+ procedure copy_pixel (x ,y : int; c : aggclr_ptr ); virtual;
+ procedure blend_pixel(x ,y : int; c : aggclr_ptr; cover : int8u ); virtual;
+ function pixel (x ,y : int ) : aggclr; virtual;
+
+ procedure copy_hline(x1 ,y ,x2 : int; c : aggclr_ptr ); virtual;
+ procedure copy_vline(x ,y1 ,y2 : int; c : aggclr_ptr ); virtual;
+
+ procedure blend_hline(x1 ,y ,x2 : int; c : aggclr_ptr; cover : int8u ); virtual;
+ procedure blend_vline(x ,y1 ,y2 : int; c : aggclr_ptr; cover : int8u ); virtual;
+
+ procedure copy_bar (x1 ,y1 ,x2 ,y2 : int; c : aggclr_ptr ); virtual;
+ procedure blend_bar(x1 ,y1 ,x2 ,y2 : int; c : aggclr_ptr; cover : int8u ); virtual;
+
+ function span(x ,y : int; len : unsigned ) : pointer;
+
+ procedure blend_solid_hspan(x ,y ,len : int; c : aggclr_ptr; covers : int8u_ptr ); virtual;
+ procedure blend_solid_vspan(x ,y ,len : int; c : aggclr_ptr; covers : int8u_ptr ); virtual;
+
+ procedure copy_color_hspan (x ,y ,len : int; colors : aggclr_ptr ); virtual;
+ procedure blend_color_hspan(x ,y ,len : int; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u = cover_full ); virtual;
+ procedure blend_color_vspan(x ,y ,len : int; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u = cover_full ); virtual;
+
+ procedure copy_color_hspan_no_clip (x ,y ,len : int; colors : aggclr_ptr );
+ procedure blend_color_hspan_no_clip(x ,y ,len : int; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u = cover_full );
+ procedure blend_color_vspan_no_clip(x ,y ,len : int; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u = cover_full );
+
+ function clip_rect_area(dst ,src : rect_ptr; wsrc ,hsrc : int ) : rect;
+
+ procedure copy_from (src : rendering_buffer_ptr; rect_src_ptr : rect_ptr = NIL; dx : int = 0; dy : int = 0 ); virtual;
+ procedure blend_from(src : pixel_formats_ptr; rect_src_ptr : rect_ptr = NIL; dx : int = 0; dy : int = 0; cover : int8u = cover_full ); virtual;
+
+ procedure blend_from_color(
+ src : pixel_formats_ptr;
+ color : aggclr_ptr;
+ rect_src_ptr : rect_ptr = NIL;
+ dx : int = 0;
+ dy : int = 0;
+ cover : int8u = cover_full );
+
+ procedure blend_from_lut(
+ src : pixel_formats_ptr;
+ color_lut : aggclr_ptr;
+ rect_src_ptr : rect_ptr = NIL;
+ dx : int = 0;
+ dy : int = 0;
+ cover : int8u = cover_full );
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor renderer_base.Construct;
+var
+ w ,h : int;
+
+begin
+ m_ren:=ren_;
+
+ if (ren_ <> NIL ) and
+ (ren_._width > 0 ) then
+ w:=ren_._width - 1
+ else
+ w:=0;
+
+ if (ren_ <> NIL ) and
+ (ren_._height > 0 ) then
+ h:=ren_._height - 1
+ else
+ h:=0;
+
+ m_clip_box.Construct(0 ,0 ,w ,h );
+
+end;
+
+{ REN }
+function renderer_base.ren;
+begin
+ result:=m_ren;
+
+end;
+
+{ WIDTH }
+function renderer_base.width;
+begin
+ result:=m_ren._width;
+
+end;
+
+{ HEIGHT }
+function renderer_base.height;
+begin
+ result:=m_ren._height;
+
+end;
+
+{ CLIP_BOX_NAKED }
+procedure renderer_base.clip_box_naked;
+begin
+ m_clip_box.x1:=x1;
+ m_clip_box.y1:=y1;
+ m_clip_box.x2:=x2;
+ m_clip_box.y2:=y2;
+
+end;
+
+{ INBOX }
+function renderer_base.inbox;
+begin
+ result:=
+ (x >= m_clip_box.x1 ) and
+ (y >= m_clip_box.y1 ) and
+ (x <= m_clip_box.x2 ) and
+ (y <= m_clip_box.y2 );
+
+end;
+
+{ CLIP_BOX_ }
+function renderer_base.clip_box_;
+var
+ cb ,
+ rc : rect;
+
+begin
+ cb.Construct(x1 ,y1 ,x2 ,y2 );
+ cb.normalize;
+
+ rc.Construct(0 ,0 ,width - 1 ,height - 1 );
+
+ if cb.clip(@rc ) then
+ begin
+ m_clip_box:=cb;
+
+ result:=true;
+
+ exit;
+
+ end;
+
+ m_clip_box.x1:=1;
+ m_clip_box.y1:=1;
+ m_clip_box.x2:=0;
+ m_clip_box.y2:=0;
+
+ result:=false;
+
+end;
+
+{ RESET_CLIPPING }
+procedure renderer_base.reset_clipping;
+begin
+ if visibility then
+ begin
+ m_clip_box.x1:=0;
+ m_clip_box.y1:=0;
+ m_clip_box.x2:=width - 1;
+ m_clip_box.y2:=height - 1;
+
+ end
+ else
+ begin
+ m_clip_box.x1:=1;
+ m_clip_box.y1:=1;
+ m_clip_box.x2:=0;
+ m_clip_box.y2:=0;
+
+ end;
+
+end;
+
+{ FIRST_CLIP_BOX }
+procedure renderer_base.first_clip_box;
+begin
+end;
+
+{ NEXT_CLIP_BOX }
+function renderer_base.next_clip_box;
+begin
+ result:=false;
+
+end;
+
+{ _CLIP_BOX }
+function renderer_base._clip_box;
+begin
+ result:=@m_clip_box;
+
+end;
+
+{ _XMIN }
+function renderer_base._xmin;
+begin
+ result:=m_clip_box.x1;
+
+end;
+
+{ _YMIN }
+function renderer_base._ymin;
+begin
+ result:=m_clip_box.y1;
+
+end;
+
+{ _XMAX }
+function renderer_base._xmax;
+begin
+ result:=m_clip_box.x2;
+
+end;
+
+{ _YMAX }
+function renderer_base._ymax;
+begin
+ result:=m_clip_box.y2;
+
+end;
+
+{ BOUNDING_CLIP_BOX }
+function renderer_base.bounding_clip_box;
+begin
+ result:=@m_clip_box;
+
+end;
+
+{ BOUNDING_XMIN }
+function renderer_base.bounding_xmin;
+begin
+ result:=m_clip_box.x1;
+
+end;
+
+{ BOUNDING_YMIN }
+function renderer_base.bounding_ymin;
+begin
+ result:=m_clip_box.y1;
+
+end;
+
+{ BOUNDING_XMAX }
+function renderer_base.bounding_xmax;
+begin
+ result:=m_clip_box.x2;
+
+end;
+
+{ BOUNDING_YMAX }
+function renderer_base.bounding_ymax;
+begin
+ result:=m_clip_box.y2;
+
+end;
+
+{ CLEAR }
+procedure renderer_base.clear;
+var
+ y : unsigned;
+
+begin
+ if (width > 0 ) and
+ (height > 0 ) then
+ for y:=0 to height - 1 do
+ m_ren.copy_hline(m_ren ,0 ,y ,width ,c );
+
+end;
+
+{ COPY_PIXEL }
+procedure renderer_base.copy_pixel;
+begin
+ if inbox(x ,y ) then
+ m_ren.copy_pixel(m_ren ,x ,y ,c );
+
+end;
+
+{ BLEND_PIXEL }
+procedure renderer_base.blend_pixel;
+begin
+ if inbox(x ,y ) then
+ m_ren.blend_pixel(m_ren ,x ,y ,c ,cover );
+
+end;
+
+{ PIXEL }
+function renderer_base.pixel;
+begin
+ if inbox(x ,y ) then
+ result:=m_ren.pixel(m_ren ,x ,y )
+ else
+ result.Construct;
+
+end;
+
+{ COPY_HLINE }
+procedure renderer_base.copy_hline;
+var
+ t : int;
+
+begin
+ if x1 > x2 then
+ begin
+ t :=x2;
+ x2:=x1;
+ x1:=t;
+
+ end;
+
+ if y > _ymax then
+ exit;
+
+ if y < _ymin then
+ exit;
+
+ if x1 > _xmax then
+ exit;
+
+ if x2 < _xmin then
+ exit;
+
+ if x1 < _xmin then
+ x1:=_xmin;
+
+ if x2 > _xmax then
+ x2:=_xmax;
+
+ m_ren.copy_hline(m_ren ,x1 ,y ,x2 - x1 + 1 ,c );
+
+end;
+
+{ COPY_VLINE }
+procedure renderer_base.copy_vline;
+var
+ t : int;
+
+begin
+ if y1 > y2 then
+ begin
+ t :=y2;
+ y2:=y1;
+ y1:=t;
+
+ end;
+
+ if x > _xmax then
+ exit;
+
+ if x < _xmin then
+ exit;
+
+ if y1 > _ymax then
+ exit;
+
+ if y2 < _ymin then
+ exit;
+
+ if y1 < _ymin then
+ y1:=_ymin;
+
+ if y2 > _ymax then
+ y2:=_ymax;
+
+ m_ren.copy_vline(m_ren ,x ,y1 ,y2 - y1 + 1 ,c );
+
+end;
+
+{ BLEND_HLINE }
+procedure renderer_base.blend_hline;
+var
+ t : int;
+
+begin
+ if x1 > x2 then
+ begin
+ t :=x2;
+ x2:=x1;
+ x1:=t;
+
+ end;
+
+ if y > _ymax then
+ exit;
+
+ if y < _ymin then
+ exit;
+
+ if x1 > _xmax then
+ exit;
+
+ if x2 < _xmin then
+ exit;
+
+ if x1 < _xmin then
+ x1:=_xmin;
+
+ if x2 > _xmax then
+ x2:=_xmax;
+
+ m_ren.blend_hline(m_ren ,x1 ,y ,x2 - x1 + 1 ,c ,cover );
+
+end;
+
+{ BLEND_VLINE }
+procedure renderer_base.blend_vline;
+var
+ t : int;
+
+begin
+ if y1 > y2 then
+ begin
+ t :=y2;
+ y2:=y1;
+ y1:=t;
+
+ end;
+
+ if x > _xmax then
+ exit;
+
+ if x < _xmin then
+ exit;
+
+ if y1 > _ymax then
+ exit;
+
+ if y2 < _ymin then
+ exit;
+
+ if y1 < _ymin then
+ y1:=_ymin;
+
+ if y2 > _ymax then
+ y2:=_ymax;
+
+ m_ren.blend_vline(m_ren ,x ,y1 ,y2 - y1 + 1 ,c ,cover );
+
+end;
+
+{ COPY_BAR }
+procedure renderer_base.copy_bar;
+var
+ y : int;
+ rc : rect;
+
+begin
+ rc.Construct(x1 ,y1 ,x2 ,y2 );
+ rc.normalize;
+
+ if rc.clip(_clip_box ) then
+ begin
+ y:=rc.y1;
+
+ while y <= rc.y2 do
+ begin
+ m_ren.copy_hline(m_ren ,rc.x1 ,y ,rc.x2 - rc.x1 + 1 ,c );
+
+ inc(y );
+
+ end;
+
+ end;
+
+end;
+
+{ BLEND_BAR }
+procedure renderer_base.blend_bar;
+var
+ rc : rect;
+ y : int;
+
+begin
+ rc.Construct(x1 ,y1 ,x2 ,y2 );
+ rc.normalize;
+
+ if rc.clip(_clip_box ) then
+ begin
+ y:=rc.y1;
+
+ while y <= rc.y2 do
+ begin
+ m_ren.blend_hline(m_ren ,rc.x1 ,y ,unsigned(rc.x2 - rc.x1 + 1 ) ,c ,cover );
+
+ inc(y );
+
+ end;
+
+ end;
+
+end;
+
+{ SPAN {not_implemented}
+function renderer_base.span;
+begin
+end;
+
+{ BLEND_SOLID_HSPAN }
+procedure renderer_base.blend_solid_hspan;
+begin
+ if y > _ymax then
+ exit;
+
+ if y < _ymin then
+ exit;
+
+ if x < _xmin then
+ begin
+ dec(len ,_xmin - x );
+
+ if len <= 0 then
+ exit;
+
+ inc(ptrcomp(covers ) ,(_xmin - x ) * sizeof(int8u ) );
+
+ x:=_xmin;
+
+ end;
+
+ if x + len > _xmax then
+ begin
+ len:=_xmax - x + 1;
+
+ if len <= 0 then
+ exit;
+
+ end;
+
+ m_ren.blend_solid_hspan(m_ren ,x ,y ,len ,c ,covers );
+
+end;
+
+{ BLEND_SOLID_VSPAN }
+procedure renderer_base.blend_solid_vspan;
+begin
+ if x > _xmax then
+ exit;
+
+ if x < _xmin then
+ exit;
+
+ if y < _ymin then
+ begin
+ dec(len ,_ymin - y );
+
+ if len <= 0 then
+ exit;
+
+ inc(ptrcomp(covers ) ,(_ymin - y ) * sizeof(int8u ) );
+
+ y:=_ymin;
+
+ end;
+
+ if y + len > _ymax then
+ begin
+ len:=_ymax - y + 1;
+
+ if len <= 0 then
+ exit;
+
+ end;
+
+ m_ren.blend_solid_vspan(m_ren ,x ,y ,len ,c ,covers );
+
+end;
+
+{ COPY_COLOR_HSPAN }
+procedure renderer_base.copy_color_hspan;
+var
+ d : int;
+
+begin
+ if y > _ymax then
+ exit;
+
+ if y < _ymin then
+ exit;
+
+ if x < _xmin then
+ begin
+ d:=_xmin - x;
+
+ dec(len ,d );
+
+ if len <= 0 then
+ exit;
+
+ inc(ptrcomp(colors ) ,d * sizeof(aggclr ) );
+
+ x:=_xmin;
+
+ end;
+
+ if x + len > _xmax then
+ begin
+ len:=_xmax - x + 1;
+
+ if len <= 0 then
+ exit;
+
+ end;
+
+ m_ren.copy_color_hspan(m_ren ,x ,y ,len ,colors );
+
+end;
+
+{ BLEND_COLOR_HSPAN }
+procedure renderer_base.blend_color_hspan;
+var
+ d : int;
+
+begin
+ if y > _ymax then
+ exit;
+
+ if y < _ymin then
+ exit;
+
+ if x < _xmin then
+ begin
+ d:=_xmin - x;
+
+ dec(len ,d );
+
+ if len <= 0 then
+ exit;
+
+ if covers <> NIL then
+ inc(ptrcomp(covers ) ,d * sizeof(int8u ) );
+
+ inc(ptrcomp(colors ) ,d * sizeof(aggclr ) );
+
+ x:=_xmin;
+
+ end;
+
+ if x + len > _xmax then
+ begin
+ len:=_xmax - x + 1;
+
+ if len <= 0 then
+ exit;
+
+ end;
+
+ m_ren.blend_color_hspan(m_ren ,x ,y ,len ,colors ,covers ,cover );
+
+end;
+
+{ BLEND_COLOR_VSPAN }
+procedure renderer_base.blend_color_vspan;
+var
+ d : int;
+
+begin
+ if x > _xmax then
+ exit;
+
+ if x < _xmin then
+ exit;
+
+ if y < _ymin then
+ begin
+ d:=_ymin - y;
+
+ dec(len ,d );
+
+ if len <= 0 then
+ exit;
+
+ if covers <> NIL then
+ inc(ptrcomp(covers ) ,d * sizeof(int8u ) );
+
+ inc(ptrcomp(colors ) ,d * sizeof(aggclr ) );
+
+ y:=_ymin;
+
+ end;
+
+ if y + len > _ymax then
+ begin
+ len:=_ymax - y + 1;
+
+ if len <= 0 then
+ exit;
+
+ end;
+
+ m_ren.blend_color_vspan(m_ren ,x ,y ,len ,colors ,covers ,cover );
+
+end;
+
+{ COPY_COLOR_HSPAN_NO_CLIP {not_implemented}
+procedure renderer_base.copy_color_hspan_no_clip;
+begin
+end;
+
+{ BLEND_COLOR_HSPAN_NO_CLIP }
+procedure renderer_base.blend_color_hspan_no_clip;
+begin
+ m_ren.blend_color_hspan(m_ren ,x ,y ,len ,colors ,covers ,cover );
+
+end;
+
+{ BLEND_COLOR_VSPAN_NO_CLIP }
+procedure renderer_base.blend_color_vspan_no_clip;
+begin
+ m_ren.blend_color_vspan(m_ren ,x ,y ,len ,colors ,covers ,cover );
+
+end;
+
+{ CLIP_RECT_AREA }
+function renderer_base.clip_rect_area;
+var
+ rc ,cb : rect;
+
+begin
+ rc.Construct(0 ,0 ,0 ,0 );
+
+ cb:=_clip_box^;
+
+ inc(cb.x2 );
+ inc(cb.y2 );
+
+ if src.x1 < 0 then
+ begin
+ dst.x1:=dst.x1 - src.x1;
+ src.x1:=0;
+
+ end;
+
+ if src.y1 < 0 then
+ begin
+ dst.y1:=dst.y1 - src.y1;
+ src.y1:=0;
+
+ end;
+
+ if src.x2 > wsrc then
+ src.x2:=wsrc;
+
+ if src.y2 > hsrc then
+ src.y2:=hsrc;
+
+ if dst.x1 < cb.x1 then
+ begin
+ src.x1:=src.x1 + (cb.x1 - dst.x1 );
+ dst.x1:=cb.x1;
+
+ end;
+
+ if dst.y1 < cb.y1 then
+ begin
+ src.y1:=src.y1 + (cb.y1 - dst.y1 );
+ dst.y1:=cb.y1;
+
+ end;
+
+ if dst.x2 > cb.x2 then
+ dst.x2:=cb.x2;
+
+ if dst.y2 > cb.y2 then
+ dst.y2:=cb.y2;
+
+ rc.x2:=dst.x2 - dst.x1;
+ rc.y2:=dst.y2 - dst.y1;
+
+ if rc.x2 > src.x2 - src.x1 then
+ rc.x2:=src.x2 - src.x1;
+
+ if rc.y2 > src.y2 - src.y1 then
+ rc.y2:=src.y2 - src.y1;
+
+ result:=rc;
+
+end;
+
+{ COPY_FROM }
+procedure renderer_base.copy_from;
+var
+ rsrc ,rdst ,rc : rect;
+
+ incy : int;
+
+begin
+ rsrc.Construct(0 ,0 ,src._width ,src._height );
+
+ if rect_src_ptr <> NIL then
+ begin
+ rsrc.x1:=rect_src_ptr.x1;
+ rsrc.y1:=rect_src_ptr.y1;
+ rsrc.x2:=rect_src_ptr.x2 + 1;
+ rsrc.y2:=rect_src_ptr.y2 + 1;
+
+ end;
+
+ rdst.Construct(rsrc.x1 + dx ,rsrc.y1 + dy ,rsrc.x2 + dx ,rsrc.y2 + dy );
+
+ rc:=clip_rect_area(@rdst ,@rsrc ,src._width ,src._height );
+
+ if rc.x2 > 0 then
+ begin
+ incy:=1;
+
+ if rdst.y1 > rsrc.y1 then
+ begin
+ rsrc.y1:=rsrc.y1 + (rc.y2 - 1 );
+ rdst.y1:=rdst.y1 + (rc.y2 - 1 );
+
+ incy:=-1;
+
+ end;
+
+ while rc.y2 > 0 do
+ begin
+ m_ren.copy_from(m_ren ,src ,rdst.x1 ,rdst.y1 ,rsrc.x1 ,rsrc.y1 ,rc.x2 );
+
+ rdst.y1:=rdst.y1 + incy;
+ rsrc.y1:=rsrc.y1 + incy;
+
+ dec(rc.y2 );
+
+ end;
+
+ end;
+
+end;
+
+{ BLEND_FROM }
+procedure renderer_base.blend_from;
+var
+ rsrc ,rdst ,rc : rect;
+
+ incy ,x1src ,x1dst ,len : int;
+
+ rw : row_data_type;
+
+begin
+ rsrc.Construct(0 ,0 ,src._width ,src._height );
+
+ if rect_src_ptr <> NIL then
+ begin
+ rsrc.x1:=rect_src_ptr.x1;
+ rsrc.y1:=rect_src_ptr.y1;
+ rsrc.x2:=rect_src_ptr.x2 + 1;
+ rsrc.y2:=rect_src_ptr.y2 + 1;
+
+ end;
+
+ rdst.Construct(rsrc.x1 + dx ,rsrc.y1 + dy ,rsrc.x2 + dx ,rsrc.y2 + dy );
+
+ rc:=clip_rect_area(@rdst ,@rsrc ,src._width ,src._height );
+
+ if rc.x2 > 0 then
+ begin
+ incy:=1;
+
+ if rdst.y1 > rsrc.y1 then
+ begin
+ rsrc.y1:=rsrc.y1 + (rc.y2 - 1 );
+ rdst.y1:=rdst.y1 + (rc.y2 - 1 );
+
+ incy:=-1;
+
+ end;
+
+ while rc.y2 > 0 do
+ begin
+ rw:=src.row(src ,rsrc.x1 ,rsrc.y1 );
+
+ if rw.ptr <> NIL then
+ begin
+ x1src:=rsrc.x1;
+ x1dst:=rdst.x1;
+ len :=rc.x2;
+
+ if rw.x1 > x1src then
+ begin
+ inc(x1dst ,rw.x1 - x1src );
+ dec(len ,rw.x1 - x1src );
+
+ x1src:=rw.x1;
+
+ end;
+
+ if len > 0 then
+ begin
+ if x1src + len - 1 > rw.x2 then
+ dec(len ,x1src + len - rw.x2 - 1 );
+
+ if len > 0 then
+ m_ren.blend_from(
+ m_ren ,src ,rw.ptr ,
+ x1dst ,rdst.y1 ,
+ x1src ,rsrc.y1 ,
+ len ,cover );
+
+ end;
+
+ end;
+
+ inc(rdst.y1 ,incy );
+ inc(rsrc.y1 ,incy );
+ dec(rc.y2 );
+
+ end;
+
+ end;
+
+end;
+
+{ BLEND_FROM_COLOR }
+procedure renderer_base.blend_from_color(
+ src : pixel_formats_ptr;
+ color : aggclr_ptr;
+ rect_src_ptr : rect_ptr = NIL;
+ dx : int = 0;
+ dy : int = 0;
+ cover : int8u = cover_full );
+var
+ rsrc ,rdst ,rc : rect;
+
+ rw : row_data_type;
+
+ incy ,x1src ,x1dst ,len : int;
+
+begin
+ rsrc.Construct(0 ,0 ,src._width ,src._height );
+
+ if rect_src_ptr <> NIL then
+ begin
+ rsrc.x1:=rect_src_ptr.x1;
+ rsrc.y1:=rect_src_ptr.y1;
+ rsrc.x2:=rect_src_ptr.x2 + 1;
+ rsrc.y2:=rect_src_ptr.y2 + 1;
+
+ end;
+
+ rdst.Construct(rsrc.x1 + dx ,rsrc.y1 + dy ,rsrc.x2 + dx ,rsrc.y2 + dy );
+
+ rc:=clip_rect_area(@rdst ,@rsrc ,src._width ,src._height );
+
+ if rc.x2 > 0 then
+ begin
+ incy:=1;
+
+ if rdst.y1 > rsrc.y1 then
+ begin
+ rsrc.y1:=rsrc.y1 + rc.y2 - 1;
+ rdst.y1:=rdst.y1 + rc.y2 - 1;
+ incy :=-1;
+
+ end;
+
+ while rc.y2 > 0 do
+ begin
+ rw:=src.row(src ,0 ,rsrc.y1 );
+
+ if rw.ptr <> NIL then
+ begin
+ x1src:=rsrc.x1;
+ x1dst:=rdst.x1;
+ len :=rc.x2;
+
+ if rw.x1 > x1src then
+ begin
+ inc(x1dst ,rw.x1 - x1src );
+ dec(len ,rw.x1 - x1src );
+
+ x1src:=rw.x1;
+
+ end;
+
+ if len > 0 then
+ begin
+ if x1src + len - 1 > rw.x2 then
+ dec(len ,x1src + len - rw.x2 - 1 );
+
+ if len > 0 then
+ m_ren.blend_from_color(m_ren ,src ,color ,x1dst ,rdst.y1 ,x1src ,rsrc.y1 ,len ,cover );
+
+ end;
+
+ end;
+
+ inc(rdst.y1 ,incy );
+ inc(rsrc.y1 ,incy );
+ dec(rc.y2 );
+
+ end;
+
+ end;
+
+end;
+
+{ BLEND_FROM_LUT }
+procedure renderer_base.blend_from_lut(
+ src : pixel_formats_ptr;
+ color_lut : aggclr_ptr;
+ rect_src_ptr : rect_ptr = NIL;
+ dx : int = 0;
+ dy : int = 0;
+ cover : int8u = cover_full );
+var
+ rsrc ,rdst ,rc : rect;
+
+ rw : row_data_type;
+
+ incy ,x1src ,x1dst ,len : int;
+
+begin
+ rsrc.Construct(0 ,0 ,src._width ,src._height );
+
+ if rect_src_ptr <> NIL then
+ begin
+ rsrc.x1:=rect_src_ptr.x1;
+ rsrc.y1:=rect_src_ptr.y1;
+ rsrc.x2:=rect_src_ptr.x2 + 1;
+ rsrc.y2:=rect_src_ptr.y2 + 1;
+
+ end;
+
+ rdst.Construct(rsrc.x1 + dx ,rsrc.y1 + dy ,rsrc.x2 + dx ,rsrc.y2 + dy );
+
+ rc:=clip_rect_area(@rdst ,@rsrc ,src._width ,src._height );
+
+ if rc.x2 > 0 then
+ begin
+ incy:=1;
+
+ if rdst.y1 > rsrc.y1 then
+ begin
+ rsrc.y1:=rsrc.y1 + rc.y2 - 1;
+ rdst.y1:=rdst.y1 + rc.y2 - 1;
+ incy :=-1;
+
+ end;
+
+ while rc.y2 > 0 do
+ begin
+ rw:=src.row(src ,0 ,rsrc.y1 );
+
+ if rw.ptr <> NIL then
+ begin
+ x1src:=rsrc.x1;
+ x1dst:=rdst.x1;
+ len :=rc.x2;
+
+ if rw.x1 > x1src then
+ begin
+ inc(x1dst ,rw.x1 - x1src );
+ dec(len ,rw.x1 - x1src );
+
+ x1src:=rw.x1;
+
+ end;
+
+ if len > 0 then
+ begin
+ if x1src + len - 1 > rw.x2 then
+ dec(len ,x1src + len - rw.x2 - 1 );
+
+ if len > 0 then
+ m_ren.blend_from_lut(m_ren ,src ,color_lut ,x1dst ,rdst.y1 ,x1src ,rsrc.y1 ,len ,cover );
+
+ end;
+
+ end;
+
+ inc(rdst.y1 ,incy );
+ inc(rsrc.y1 ,incy );
+ dec(rc.y2 );
+
+ end;
+
+ end;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_renderer_markers.pas b/src/corelib/render/software/agg_renderer_markers.pas
new file mode 100644
index 00000000..0f826402
--- /dev/null
+++ b/src/corelib/render/software/agg_renderer_markers.pas
@@ -0,0 +1,1648 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// class renderer_markers
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 11.02.2006-Milano: Unit port establishment
+//
+{ agg_renderer_markers.pas }
+unit
+ agg_renderer_markers ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_color ,
+ agg_renderer_base ,
+ agg_renderer_primitives ,
+ agg_ellipse_bresenham ;
+
+{ TYPES DEFINITION }
+type
+ marker_e = (
+
+ marker_square ,
+ marker_diamond ,
+ marker_circle ,
+ marker_crossed_circle ,
+ marker_semiellipse_left ,
+ marker_semiellipse_right ,
+ marker_semiellipse_up ,
+ marker_semiellipse_down ,
+ marker_triangle_left ,
+ marker_triangle_right ,
+ marker_triangle_up ,
+ marker_triangle_down ,
+ marker_four_rays ,
+ marker_cross ,
+ marker_x ,
+ marker_dash ,
+ marker_dot ,
+ marker_pixel ,
+
+ end_of_markers );
+
+ renderer_markers = object(renderer_primitives )
+ constructor Construct(rbuf : renderer_base_ptr );
+
+ function visible(x ,y ,r : int ) : boolean;
+
+ procedure square (x ,y ,r : int );
+ procedure diamond(x ,y ,r : int );
+
+ procedure circle (x ,y ,r : int );
+ procedure crossed_circle(x ,y ,r : int );
+
+ procedure semiellipse_left (x ,y ,r : int );
+ procedure semiellipse_right(x ,y ,r : int );
+ procedure semiellipse_up (x ,y ,r : int );
+ procedure semiellipse_down (x ,y ,r : int );
+
+ procedure triangle_left (x ,y ,r : int );
+ procedure triangle_right(x ,y ,r : int );
+ procedure triangle_up (x ,y ,r : int );
+ procedure triangle_down (x ,y ,r : int );
+
+ procedure four_rays(x ,y ,r : int );
+
+ procedure cross(x ,y ,r : int );
+ procedure xing (x ,y ,r : int );
+ procedure dash (x ,y ,r : int );
+ procedure dot (x ,y ,r : int );
+ procedure pixel(x ,y ,r : int );
+
+ procedure marker(x ,y ,r : int; type_ : marker_e );
+
+ procedure markers(n : int; x ,y : int_ptr; r : int; type_ : marker_e ); overload;
+ procedure markers(n : int; x ,y ,r : int_ptr; type_ : marker_e ); overload;
+ procedure markers(n : int; x ,y ,r : int_ptr; fc : aggclr_ptr; type_ : marker_e ); overload;
+ procedure markers(n : int; x ,y ,r : int_ptr; fc ,lc : aggclr_ptr; type_ : marker_e ); overload;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor renderer_markers.Construct;
+begin
+ inherited Construct(rbuf );
+
+end;
+
+{ VISIBLE }
+function renderer_markers.visible;
+var
+ rc : rect;
+
+begin
+ rc.Construct(x - r ,y - r ,x + y ,y + r );
+
+ result:=rc.clip(ren.bounding_clip_box );
+
+end;
+
+{ SQUARE }
+procedure renderer_markers.square;
+begin
+ if visible(x ,y ,r ) then
+ if r <> 0 then
+ outlined_rectangle(x - r ,y - r ,x + r ,y + r )
+ else
+ ren.blend_pixel(x ,y ,_fill_color ,cover_full );
+
+end;
+
+{ DIAMOND }
+procedure renderer_markers.diamond;
+var
+ dx ,dy : int;
+
+begin
+ if visible(x ,y ,r ) then
+ if r <> 0 then
+ begin
+ dy:=-r;
+ dx:=0;
+
+ repeat
+ ren.blend_pixel(x - dx ,y + dy ,_line_color ,cover_full );
+ ren.blend_pixel(x + dx ,y + dy ,_line_color ,cover_full );
+ ren.blend_pixel(x - dx ,y - dy ,_line_color ,cover_full );
+ ren.blend_pixel(x + dx ,y - dy ,_line_color ,cover_full );
+
+ if dx <> 0 then
+ begin
+ ren.blend_hline(x - dx + 1 ,y + dy ,x + dx - 1 ,_fill_color ,cover_full );
+ ren.blend_hline(x - dx + 1 ,y - dy ,x + dx - 1 ,_fill_color ,cover_full );
+
+ end;
+
+ inc(dy );
+ inc(dx );
+
+ until dy > 0;
+
+ end
+ else
+ ren.blend_pixel(x ,y ,_fill_color ,cover_full );
+
+end;
+
+{ CIRCLE }
+procedure renderer_markers.circle;
+begin
+ if visible(x ,y ,r ) then
+ if r <> 0 then
+ outlined_ellipse(x ,y ,r ,r )
+ else
+ ren.blend_pixel(x ,y ,_fill_color ,cover_full );
+
+end;
+
+{ CROSSED_CIRCLE }
+procedure renderer_markers.crossed_circle;
+var
+ r6 : int;
+
+begin
+ if visible(x ,y ,r ) then
+ if r <> 0 then
+ begin
+ outlined_ellipse(x ,y ,r ,r );
+
+ r6:=r + shr_int32(r ,1 );
+
+ if r <= 2 then
+ inc(r6 );
+
+ r:=shr_int32(r ,1 );
+
+ ren.blend_hline(x - r6 ,y ,x - r ,_line_color ,cover_full );
+ ren.blend_hline(x + r ,y ,x + r6 ,_line_color ,cover_full );
+ ren.blend_vline(x ,y - r6 ,y - r ,_line_color ,cover_full );
+ ren.blend_vline(x ,y + r ,y + r6 ,_line_color ,cover_full );
+
+ end
+ else
+ ren.blend_pixel(x ,y ,_fill_color ,cover_full );
+
+end;
+
+{ SEMIELLIPSE_LEFT }
+procedure renderer_markers.semiellipse_left;
+var
+ r8 ,dy ,dx : int;
+
+ ei : ellipse_bresenham_interpolator;
+
+begin
+ if visible(x ,y ,r ) then
+ if r <> 0 then
+ begin
+ r8:=r * 4 div 5;
+ dy:=-r;
+ dx:=0;
+
+ ei.Construct(r * 3 div 5 ,r + r8 );
+
+ repeat
+ inc(dx ,ei._dx );
+ inc(dy ,ei._dy );
+
+ ren.blend_pixel(x + dy ,y + dx ,_line_color ,cover_full );
+ ren.blend_pixel(x + dy ,y - dx ,_line_color ,cover_full );
+
+ if (ei._dy <> 0 ) and
+ (dx <> 0 ) then
+ ren.blend_vline(x + dy ,y - dx + 1 ,y + dx - 1 ,_fill_color ,cover_full );
+
+ ei.inc_operator;
+
+ until dy >= r8;
+
+ ren.blend_vline(x + dy ,y - dx ,y + dx ,_line_color ,cover_full );
+
+ end
+ else
+ ren.blend_pixel(x ,y ,_fill_color ,cover_full );
+
+end;
+
+{ SEMIELLIPSE_RIGHT }
+procedure renderer_markers.semiellipse_right;
+var
+ r8 ,dy ,dx : int;
+
+ ei : ellipse_bresenham_interpolator;
+
+begin
+ if visible(x ,y ,r ) then
+ if r <> 0 then
+ begin
+ r8:=r * 4 div 5;
+ dy:=-r;
+ dx:=0;
+
+ ei.Construct(r * 3 div 5 ,r + r8 );
+
+ repeat
+ inc(dx ,ei._dx );
+ inc(dy ,ei._dy );
+
+ ren.blend_pixel(x - dy ,y + dx ,_line_color ,cover_full );
+ ren.blend_pixel(x - dy ,y - dx ,_line_color ,cover_full );
+
+ if (ei._dy <> 0 ) and
+ (dx <> 0 ) then
+ ren.blend_vline(x - dy ,y - dx + 1 ,y + dx - 1 ,_fill_color ,cover_full );
+
+ ei.inc_operator;
+
+ until dy >= r8;
+
+ ren.blend_vline(x - dy ,y - dx ,y + dx ,_line_color ,cover_full );
+
+ end
+ else
+ ren.blend_pixel(x ,y ,_fill_color ,cover_full );
+
+end;
+
+{ SEMIELLIPSE_UP }
+procedure renderer_markers.semiellipse_up;
+var
+ r8 ,dy ,dx : int;
+
+ ei : ellipse_bresenham_interpolator;
+
+begin
+ if visible(x ,y ,r ) then
+ if r <> 0 then
+ begin
+ r8:=r * 4 div 5;
+ dy:=-r;
+ dx:=0;
+
+ ei.Construct(r * 3 div 5 ,r + r8 );
+
+ repeat
+ inc(dx ,ei._dx );
+ inc(dy ,ei._dy );
+
+ ren.blend_pixel(x + dx ,y - dy ,_line_color ,cover_full );
+ ren.blend_pixel(x - dx ,y - dy ,_line_color ,cover_full );
+
+ if (ei._dy <> 0 ) and
+ (dx <> 0 ) then
+ ren.blend_hline(x - dx + 1 ,y - dy ,x + dx - 1 ,_fill_color ,cover_full );
+
+ ei.inc_operator;
+
+ until dy >= r8;
+
+ ren.blend_hline(x - dx ,y - dy - 1 ,x + dx ,_line_color ,cover_full );
+
+ end
+ else
+ ren.blend_pixel(x ,y ,_fill_color ,cover_full );
+
+end;
+
+{ SEMIELLIPSE_DOWN }
+procedure renderer_markers.semiellipse_down;
+var
+ r8 ,dy ,dx : int;
+
+ ei : ellipse_bresenham_interpolator;
+
+begin
+ if visible(x ,y ,r ) then
+ if r <> 0 then
+ begin
+ r8:=r * 4 div 5;
+ dy:=-r;
+ dx:=0;
+
+ ei.Construct(r * 3 div 5 ,r + r8 );
+
+ repeat
+ inc(dx ,ei._dx );
+ inc(dy ,ei._dy );
+
+ ren.blend_pixel(x + dx ,y + dy ,_line_color ,cover_full );
+ ren.blend_pixel(x - dx ,y + dy ,_line_color ,cover_full );
+
+ if (ei._dy <> 0 ) and
+ (dx <> 0 ) then
+ ren.blend_hline(x - dx + 1 ,y + dy ,x + dx - 1 ,_fill_color ,cover_full );
+
+ ei.inc_operator;
+
+ until dy >= r8;
+
+ ren.blend_hline(x - dx ,y + dy + 1 ,x + dx ,_line_color ,cover_full );
+
+ end
+ else
+ ren.blend_pixel(x ,y ,_fill_color ,cover_full );
+
+end;
+
+{ TRIANGLE_LEFT }
+procedure renderer_markers.triangle_left;
+var
+ dy ,dx ,flip ,r6 : int;
+
+begin
+ if visible(x ,y ,r ) then
+ if r <> 0 then
+ begin
+ dy :=-r;
+ dx :=0;
+ flip:=0;
+ r6 :=r * 3 div 5;
+
+ repeat
+ ren.blend_pixel(x + dy ,y - dx ,_line_color ,cover_full );
+ ren.blend_pixel(x + dy ,y + dx ,_line_color ,cover_full );
+
+ if dx <> 0 then
+ ren.blend_vline(x + dy ,y - dx + 1 ,y + dx - 1 ,_fill_color ,cover_full );
+
+ inc(dy );
+ inc(dx ,flip );
+
+ flip:=flip xor 1;
+
+ until dy >= r6;
+
+ ren.blend_vline(x + dy ,y - dx ,y + dx ,_line_color ,cover_full );
+
+ end
+ else
+ ren.blend_pixel(x ,y ,_fill_color ,cover_full );
+
+end;
+
+{ TRIANGLE_RIGHT }
+procedure renderer_markers.triangle_right;
+var
+ dy ,dx ,flip ,r6 : int;
+
+begin
+ if visible(x ,y ,r ) then
+ if r <> 0 then
+ begin
+ dy :=-r;
+ dx :=0;
+ flip:=0;
+ r6 :=r * 3 div 5;
+
+ repeat
+ ren.blend_pixel(x - dy ,y - dx ,_line_color ,cover_full );
+ ren.blend_pixel(x - dy ,y + dx ,_line_color ,cover_full );
+
+ if dx <> 0 then
+ ren.blend_vline(x - dy ,y - dx + 1 ,y + dx - 1 ,_fill_color ,cover_full );
+
+ inc(dy );
+ inc(dx ,flip );
+
+ flip:=flip xor 1;
+
+ until dy >= r6;
+
+ ren.blend_vline(x - dy ,y - dx ,y + dx ,_line_color ,cover_full );
+
+ end
+ else
+ ren.blend_pixel(x ,y ,_fill_color ,cover_full );
+
+end;
+
+{ TRIANGLE_UP }
+procedure renderer_markers.triangle_up;
+var
+ dy ,dx ,flip ,r6 : int;
+
+begin
+ if visible(x ,y ,r ) then
+ if r <> 0 then
+ begin
+ dy :=-r;
+ dx :=0;
+ flip:=0;
+ r6 :=r * 3 div 5;
+
+ repeat
+ ren.blend_pixel(x - dx ,y - dy ,_line_color ,cover_full );
+ ren.blend_pixel(x + dx ,y - dy ,_line_color ,cover_full );
+
+ if dx <> 0 then
+ ren.blend_hline(x - dx + 1 ,y - dy ,x + dx - 1 ,_fill_color ,cover_full );
+
+ inc(dy );
+ inc(dx ,flip );
+
+ flip:=flip xor 1;
+
+ until dy >= r6;
+
+ ren.blend_hline(x - dx ,y - dy ,x + dx ,_line_color ,cover_full );
+
+ end
+ else
+ ren.blend_pixel(x ,y ,_fill_color ,cover_full );
+
+end;
+
+{ TRIANGLE_DOWN }
+procedure renderer_markers.triangle_down;
+var
+ dy ,dx ,flip ,r6 : int;
+
+begin
+ if visible(x ,y ,r ) then
+ if r <> 0 then
+ begin
+ dy :=-r;
+ dx :=0;
+ flip:=0;
+ r6 :=r * 3 div 5;
+
+ repeat
+ ren.blend_pixel(x - dx ,y + dy ,_line_color ,cover_full );
+ ren.blend_pixel(x + dx ,y + dy ,_line_color ,cover_full );
+
+ if dx <> 0 then
+ ren.blend_hline(x - dx + 1 ,y + dy ,x + dx - 1 ,_fill_color ,cover_full );
+
+ inc(dy );
+ inc(dx ,flip );
+
+ flip:=flip xor 1;
+
+ until dy >= r6;
+
+ ren.blend_hline(x - dx ,y + dy ,x + dx ,_line_color ,cover_full );
+
+ end
+ else
+ ren.blend_pixel(x ,y ,_fill_color ,cover_full );
+
+end;
+
+{ FOUR_RAYS }
+procedure renderer_markers.four_rays;
+var
+ dy ,dx ,flip ,r3 : int;
+
+begin
+ if visible(x ,y ,r ) then
+ if r <> 0 then
+ begin
+ dy :=-r;
+ dx :=0;
+ flip:=0;
+ r3 :=-(r div 3);
+
+ repeat
+ ren.blend_pixel(x - dx ,y + dy ,_line_color ,cover_full );
+ ren.blend_pixel(x + dx ,y + dy ,_line_color ,cover_full );
+ ren.blend_pixel(x - dx ,y - dy ,_line_color ,cover_full );
+ ren.blend_pixel(x + dx ,y - dy ,_line_color ,cover_full );
+ ren.blend_pixel(x + dy ,y - dx ,_line_color ,cover_full );
+ ren.blend_pixel(x + dy ,y + dx ,_line_color ,cover_full );
+ ren.blend_pixel(x - dy ,y - dx ,_line_color ,cover_full );
+ ren.blend_pixel(x - dy ,y + dx ,_line_color ,cover_full );
+
+ if dx <> 0 then
+ begin
+ ren.blend_hline(x - dx + 1 ,y + dy ,x + dx - 1 ,_fill_color ,cover_full );
+ ren.blend_hline(x - dx + 1 ,y - dy ,x + dx - 1 ,_fill_color ,cover_full );
+ ren.blend_vline(x + dy ,y - dx + 1 ,y + dx - 1 ,_fill_color ,cover_full );
+ ren.blend_vline(x - dy ,y - dx + 1 ,y + dx - 1 ,_fill_color ,cover_full );
+
+ end;
+
+ inc(dy );
+ inc(dx ,flip );
+
+ flip:=flip xor 1;
+
+ until dy > r3;
+
+ solid_rectangle(x + r3 + 1 ,y + r3 + 1 ,x - r3 - 1 ,y - r3 - 1 );
+
+ end
+ else
+ ren.blend_pixel(x ,y ,_fill_color ,cover_full );
+
+end;
+
+{ CROSS }
+procedure renderer_markers.cross;
+begin
+ if visible(x ,y ,r ) then
+ if r <> 0 then
+ begin
+ ren.blend_vline(x ,y - r ,y + r ,_line_color ,cover_full );
+ ren.blend_hline(x - r ,y ,x + r ,_line_color ,cover_full );
+
+ end
+ else
+ ren.blend_pixel(x ,y ,_fill_color ,cover_full );
+
+end;
+
+{ XING }
+procedure renderer_markers.xing;
+var
+ dy : int;
+
+begin
+ if visible(x ,y ,r ) then
+ if r <> 0 then
+ begin
+ dy:=-r * 7 div 10;
+
+ repeat
+ ren.blend_pixel(x + dy ,y + dy ,_line_color ,cover_full );
+ ren.blend_pixel(x - dy ,y + dy ,_line_color ,cover_full );
+ ren.blend_pixel(x + dy ,y - dy ,_line_color ,cover_full );
+ ren.blend_pixel(x - dy ,y - dy ,_line_color ,cover_full );
+
+ inc(dy );
+
+ until dy >= 0;
+
+ end
+ else
+ ren.blend_pixel(x ,y ,_fill_color ,cover_full );
+
+end;
+
+{ DASH }
+procedure renderer_markers.dash;
+begin
+ if visible(x ,y ,r ) then
+ if r <> 0 then
+ ren.blend_hline(x - r ,y ,x + r ,_line_color ,cover_full )
+ else
+ ren.blend_pixel(x ,y ,_fill_color ,cover_full );
+
+end;
+
+{ DOT }
+procedure renderer_markers.dot;
+begin
+ if visible(x ,y ,r ) then
+ if r <> 0 then
+ solid_ellipse(x ,y ,r ,r )
+ else
+ ren.blend_pixel(x ,y ,_fill_color ,cover_full );
+
+end;
+
+{ PIXEL }
+procedure renderer_markers.pixel;
+begin
+ ren.blend_pixel(x ,y ,_fill_color ,cover_full );
+
+end;
+
+{ MARKER }
+procedure renderer_markers.marker;
+begin
+ case type_ of
+ marker_square : square (x ,y ,r );
+ marker_diamond : diamond (x ,y ,r );
+ marker_circle : circle (x ,y ,r );
+ marker_crossed_circle : crossed_circle (x ,y ,r );
+ marker_semiellipse_left : semiellipse_left (x ,y ,r );
+ marker_semiellipse_right : semiellipse_right(x ,y ,r );
+ marker_semiellipse_up : semiellipse_up (x ,y ,r );
+ marker_semiellipse_down : semiellipse_down (x ,y ,r );
+ marker_triangle_left : triangle_left (x ,y ,r );
+ marker_triangle_right : triangle_right (x ,y ,r );
+ marker_triangle_up : triangle_up (x ,y ,r );
+ marker_triangle_down : triangle_down (x ,y ,r );
+ marker_four_rays : four_rays (x ,y ,r );
+ marker_cross : cross (x ,y ,r );
+ marker_x : xing (x ,y ,r );
+ marker_dash : dash (x ,y ,r );
+ marker_dot : dot (x ,y ,r );
+ marker_pixel : pixel (x ,y ,r );
+
+ end;
+
+end;
+
+{ MARKERS }
+procedure renderer_markers.markers(n : int; x ,y : int_ptr; r : int; type_ : marker_e );
+begin
+ if n <= 0 then
+ exit;
+
+ if r = 0 then
+ begin
+ repeat
+ ren.blend_pixel(x^ ,y^ ,_fill_color ,cover_full );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ dec(n );
+
+ until n = 0;
+
+ exit;
+
+ end;
+
+ case type_ of
+ marker_square :
+ repeat
+ square(x^ ,y^ ,r );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_diamond :
+ repeat
+ diamond(x^ ,y^ ,r );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_circle :
+ repeat
+ circle(x^ ,y^ ,r );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_crossed_circle :
+ repeat
+ crossed_circle(x^ ,y^ ,r );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_semiellipse_left :
+ repeat
+ semiellipse_left(x^ ,y^ ,r );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_semiellipse_right :
+ repeat
+ semiellipse_right(x^ ,y^ ,r );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_semiellipse_up :
+ repeat
+ semiellipse_up(x^ ,y^ ,r );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_semiellipse_down :
+ repeat
+ semiellipse_down(x^ ,y^ ,r );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_triangle_left :
+ repeat
+ triangle_left(x^ ,y^ ,r );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_triangle_right :
+ repeat
+ triangle_right(x^ ,y^ ,r );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_triangle_up :
+ repeat
+ triangle_up(x^ ,y^ ,r );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_triangle_down :
+ repeat
+ triangle_down(x^ ,y^ ,r );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_four_rays :
+ repeat
+ four_rays(x^ ,y^ ,r );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_cross :
+ repeat
+ cross(x^ ,y^ ,r );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_x :
+ repeat
+ xing(x^ ,y^ ,r );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_dash :
+ repeat
+ dash(x^ ,y^ ,r );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_dot :
+ repeat
+ dot(x^ ,y^ ,r );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_pixel :
+ repeat
+ pixel(x^ ,y^ ,r );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ dec(n );
+
+ until n = 0;
+
+ end;
+
+end;
+
+{ MARKERS }
+procedure renderer_markers.markers(n : int; x ,y ,r : int_ptr; type_ : marker_e );
+begin
+ if n <= 0 then
+ exit;
+
+ case type_ of
+ marker_square :
+ repeat
+ square(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_diamond :
+ repeat
+ diamond(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_circle :
+ repeat
+ circle(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_crossed_circle :
+ repeat
+ crossed_circle(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_semiellipse_left :
+ repeat
+ semiellipse_left(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_semiellipse_right :
+ repeat
+ semiellipse_right(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_semiellipse_up :
+ repeat
+ semiellipse_up(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_semiellipse_down :
+ repeat
+ semiellipse_down(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_triangle_left :
+ repeat
+ triangle_left(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_triangle_right :
+ repeat
+ triangle_right(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_triangle_up :
+ repeat
+ triangle_up(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_triangle_down :
+ repeat
+ triangle_down(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_four_rays :
+ repeat
+ four_rays(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_cross :
+ repeat
+ cross(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_x :
+ repeat
+ xing(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_dash :
+ repeat
+ dash(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_dot :
+ repeat
+ dot(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_pixel :
+ repeat
+ pixel(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ dec(n );
+
+ until n = 0;
+
+ end;
+
+end;
+
+{ MARKERS }
+procedure renderer_markers.markers(n : int; x ,y ,r : int_ptr; fc : aggclr_ptr; type_ : marker_e );
+begin
+ if n <= 0 then
+ exit;
+
+ case type_ of
+ marker_square :
+ repeat
+ fill_color_(fc );
+
+ square(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ inc(ptrcomp(fc ) ,sizeof(aggclr ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_diamond :
+ repeat
+ fill_color_(fc );
+
+ diamond(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ inc(ptrcomp(fc ) ,sizeof(aggclr ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_circle :
+ repeat
+ fill_color_(fc );
+
+ circle(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ inc(ptrcomp(fc ) ,sizeof(aggclr ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_crossed_circle :
+ repeat
+ fill_color_(fc );
+
+ crossed_circle(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ inc(ptrcomp(fc ) ,sizeof(aggclr ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_semiellipse_left :
+ repeat
+ fill_color_(fc );
+
+ semiellipse_left(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ inc(ptrcomp(fc ) ,sizeof(aggclr ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_semiellipse_right :
+ repeat
+ fill_color_(fc );
+
+ semiellipse_right(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ inc(ptrcomp(fc ) ,sizeof(aggclr ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_semiellipse_up :
+ repeat
+ fill_color_(fc );
+
+ semiellipse_up(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ inc(ptrcomp(fc ) ,sizeof(aggclr ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_semiellipse_down :
+ repeat
+ fill_color_(fc );
+
+ semiellipse_down(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ inc(ptrcomp(fc ) ,sizeof(aggclr ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_triangle_left :
+ repeat
+ fill_color_(fc );
+
+ triangle_left(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ inc(ptrcomp(fc ) ,sizeof(aggclr ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_triangle_right :
+ repeat
+ fill_color_(fc );
+
+ triangle_right(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ inc(ptrcomp(fc ) ,sizeof(aggclr ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_triangle_up :
+ repeat
+ fill_color_(fc );
+
+ triangle_up(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ inc(ptrcomp(fc ) ,sizeof(aggclr ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_triangle_down :
+ repeat
+ fill_color_(fc );
+
+ triangle_down(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ inc(ptrcomp(fc ) ,sizeof(aggclr ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_four_rays :
+ repeat
+ fill_color_(fc );
+
+ four_rays(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ inc(ptrcomp(fc ) ,sizeof(aggclr ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_cross :
+ repeat
+ fill_color_(fc );
+
+ cross(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ inc(ptrcomp(fc ) ,sizeof(aggclr ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_x :
+ repeat
+ fill_color_(fc );
+
+ xing(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ inc(ptrcomp(fc ) ,sizeof(aggclr ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_dash :
+ repeat
+ fill_color_(fc );
+
+ dash(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ inc(ptrcomp(fc ) ,sizeof(aggclr ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_dot :
+ repeat
+ fill_color_(fc );
+
+ dot(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ inc(ptrcomp(fc ) ,sizeof(aggclr ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_pixel :
+ repeat
+ fill_color_(fc );
+
+ pixel(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ inc(ptrcomp(fc ) ,sizeof(aggclr ) );
+ dec(n );
+
+ until n = 0;
+
+ end;
+
+end;
+
+{ MARKERS }
+procedure renderer_markers.markers(n : int; x ,y ,r : int_ptr; fc ,lc : aggclr_ptr; type_ : marker_e );
+begin
+ if n <= 0 then
+ exit;
+
+ case type_ of
+ marker_square :
+ repeat
+ fill_color_(fc );
+ line_color_(lc );
+
+ square(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ inc(ptrcomp(fc ) ,sizeof(aggclr ) );
+ inc(ptrcomp(lc ) ,sizeof(aggclr ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_diamond :
+ repeat
+ fill_color_(fc );
+ line_color_(lc );
+
+ diamond(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ inc(ptrcomp(fc ) ,sizeof(aggclr ) );
+ inc(ptrcomp(lc ) ,sizeof(aggclr ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_circle :
+ repeat
+ fill_color_(fc );
+ line_color_(lc );
+
+ circle(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ inc(ptrcomp(fc ) ,sizeof(aggclr ) );
+ inc(ptrcomp(lc ) ,sizeof(aggclr ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_crossed_circle :
+ repeat
+ fill_color_(fc );
+ line_color_(lc );
+
+ crossed_circle(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ inc(ptrcomp(fc ) ,sizeof(aggclr ) );
+ inc(ptrcomp(lc ) ,sizeof(aggclr ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_semiellipse_left :
+ repeat
+ fill_color_(fc );
+ line_color_(lc );
+
+ semiellipse_left(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ inc(ptrcomp(fc ) ,sizeof(aggclr ) );
+ inc(ptrcomp(lc ) ,sizeof(aggclr ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_semiellipse_right :
+ repeat
+ fill_color_(fc );
+ line_color_(lc );
+
+ semiellipse_right(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ inc(ptrcomp(fc ) ,sizeof(aggclr ) );
+ inc(ptrcomp(lc ) ,sizeof(aggclr ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_semiellipse_up :
+ repeat
+ fill_color_(fc );
+ line_color_(lc );
+
+ semiellipse_up(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ inc(ptrcomp(fc ) ,sizeof(aggclr ) );
+ inc(ptrcomp(lc ) ,sizeof(aggclr ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_semiellipse_down :
+ repeat
+ fill_color_(fc );
+ line_color_(lc );
+
+ semiellipse_down(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ inc(ptrcomp(fc ) ,sizeof(aggclr ) );
+ inc(ptrcomp(lc ) ,sizeof(aggclr ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_triangle_left :
+ repeat
+ fill_color_(fc );
+ line_color_(lc );
+
+ triangle_left(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ inc(ptrcomp(fc ) ,sizeof(aggclr ) );
+ inc(ptrcomp(lc ) ,sizeof(aggclr ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_triangle_right :
+ repeat
+ fill_color_(fc );
+ line_color_(lc );
+
+ triangle_right(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ inc(ptrcomp(fc ) ,sizeof(aggclr ) );
+ inc(ptrcomp(lc ) ,sizeof(aggclr ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_triangle_up :
+ repeat
+ fill_color_(fc );
+ line_color_(lc );
+
+ triangle_up(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ inc(ptrcomp(fc ) ,sizeof(aggclr ) );
+ inc(ptrcomp(lc ) ,sizeof(aggclr ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_triangle_down :
+ repeat
+ fill_color_(fc );
+ line_color_(lc );
+
+ triangle_down(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ inc(ptrcomp(fc ) ,sizeof(aggclr ) );
+ inc(ptrcomp(lc ) ,sizeof(aggclr ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_four_rays :
+ repeat
+ fill_color_(fc );
+ line_color_(lc );
+
+ four_rays(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ inc(ptrcomp(fc ) ,sizeof(aggclr ) );
+ inc(ptrcomp(lc ) ,sizeof(aggclr ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_cross :
+ repeat
+ fill_color_(fc );
+ line_color_(lc );
+
+ cross(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ inc(ptrcomp(fc ) ,sizeof(aggclr ) );
+ inc(ptrcomp(lc ) ,sizeof(aggclr ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_x :
+ repeat
+ fill_color_(fc );
+ line_color_(lc );
+
+ xing(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ inc(ptrcomp(fc ) ,sizeof(aggclr ) );
+ inc(ptrcomp(lc ) ,sizeof(aggclr ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_dash :
+ repeat
+ fill_color_(fc );
+ line_color_(lc );
+
+ dash(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ inc(ptrcomp(fc ) ,sizeof(aggclr ) );
+ inc(ptrcomp(lc ) ,sizeof(aggclr ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_dot :
+ repeat
+ fill_color_(fc );
+ line_color_(lc );
+
+ dot(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ inc(ptrcomp(fc ) ,sizeof(aggclr ) );
+ inc(ptrcomp(lc ) ,sizeof(aggclr ) );
+ dec(n );
+
+ until n = 0;
+
+ marker_pixel :
+ repeat
+ fill_color_(fc );
+ line_color_(lc );
+
+ pixel(x^ ,y^ ,r^ );
+
+ inc(ptrcomp(x ) ,sizeof(int ) );
+ inc(ptrcomp(y ) ,sizeof(int ) );
+ inc(ptrcomp(r ) ,sizeof(int ) );
+ inc(ptrcomp(fc ) ,sizeof(aggclr ) );
+ inc(ptrcomp(lc ) ,sizeof(aggclr ) );
+ dec(n );
+
+ until n = 0;
+
+ end;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_renderer_mclip.pas b/src/corelib/render/software/agg_renderer_mclip.pas
new file mode 100644
index 00000000..28fcb49c
--- /dev/null
+++ b/src/corelib/render/software/agg_renderer_mclip.pas
@@ -0,0 +1,439 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// class renderer_mclip
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 11.02.2006-Milano: Unit port establishment
+//
+{ agg_renderer_mclip.pas }
+unit
+ agg_renderer_mclip ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_array ,
+ agg_color ,
+ agg_rendering_buffer ,
+ agg_renderer_base ,
+ agg_pixfmt ;
+
+{ TYPES DEFINITION }
+type
+ renderer_mclip = object(renderer_base )
+ m_clip : pod_deque;
+ m_curr_cb : unsigned;
+ m_bounds : rect;
+
+ constructor Construct(ren_ : pixel_formats_ptr );
+ destructor Destruct;
+
+ function bounding_clip_box : rect_ptr; virtual;
+ function bounding_xmin : int; virtual;
+ function bounding_ymin : int; virtual;
+ function bounding_xmax : int; virtual;
+ function bounding_ymax : int; virtual;
+
+ procedure first_clip_box; virtual;
+ function next_clip_box : boolean; virtual;
+
+ procedure reset_clipping(visibility : boolean ); virtual;
+
+ procedure add_clip_box(x1 ,y1 ,x2 ,y2 : int );
+
+ procedure copy_pixel (x ,y : int; c : aggclr_ptr ); virtual;
+ procedure blend_pixel(x ,y : int; c : aggclr_ptr; cover : int8u ); virtual;
+ function pixel (x ,y : int ) : aggclr; virtual;
+
+ procedure copy_hline(x1 ,y ,x2 : int; c : aggclr_ptr ); virtual;
+ procedure copy_vline(x ,y1 ,y2 : int; c : aggclr_ptr ); virtual;
+
+ procedure blend_hline(x1 ,y ,x2 : int; c : aggclr_ptr; cover : int8u ); virtual;
+ procedure blend_vline(x ,y1 ,y2 : int; c : aggclr_ptr; cover : int8u ); virtual;
+
+ procedure copy_bar (x1 ,y1 ,x2 ,y2 : int; c : aggclr_ptr ); virtual;
+ procedure blend_bar(x1 ,y1 ,x2 ,y2 : int; c : aggclr_ptr; cover : int8u ); virtual;
+
+ procedure blend_solid_hspan(x ,y ,len : int; c : aggclr_ptr; covers : int8u_ptr ); virtual;
+ procedure blend_solid_vspan(x ,y ,len : int; c : aggclr_ptr; covers : int8u_ptr ); virtual;
+
+ procedure copy_color_hspan (x ,y ,len : int; colors : aggclr_ptr ); virtual;
+ procedure blend_color_hspan(x ,y ,len : int; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u = cover_full ); virtual;
+ procedure blend_color_vspan(x ,y ,len : int; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u = cover_full ); virtual;
+
+ procedure copy_from(from : rendering_buffer_ptr; rc : rect_ptr = NIL; x_to : int = 0; y_to : int = 0 ); virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor renderer_mclip.Construct;
+begin
+ inherited Construct(ren_ );
+
+ m_clip.Construct (sizeof(rect ) ,4 );
+ m_bounds.Construct(_xmin ,_ymin ,_xmax ,_ymax );
+
+ m_curr_cb:=0;
+
+end;
+
+{ DESTRUCT }
+destructor renderer_mclip.Destruct;
+begin
+ m_clip.Destruct;
+
+end;
+
+{ BOUNDING_CLIP_BOX }
+function renderer_mclip.bounding_clip_box;
+begin
+ result:=@m_bounds;
+
+end;
+
+{ BOUNDING_XMIN }
+function renderer_mclip.bounding_xmin;
+begin
+ result:=m_bounds.x1;
+
+end;
+
+{ BOUNDING_YMIN }
+function renderer_mclip.bounding_ymin;
+begin
+ result:=m_bounds.y1;
+
+end;
+
+{ BOUNDING_XMAX }
+function renderer_mclip.bounding_xmax;
+begin
+ result:=m_bounds.x2;
+
+end;
+
+{ BOUNDING_YMAX }
+function renderer_mclip.bounding_ymax;
+begin
+ result:=m_bounds.y2;
+
+end;
+
+{ FIRST_CLIP_BOX }
+procedure renderer_mclip.first_clip_box;
+var
+ cb : rect_ptr;
+
+begin
+ m_curr_cb:=0;
+
+ if m_clip.size <> 0 then
+ begin
+ cb:=m_clip.array_operator(0 );
+
+ clip_box_naked(cb.x1 ,cb.y1 ,cb.x2 ,cb.y2 );
+
+ end;
+
+end;
+
+{ NEXT_CLIP_BOX }
+function renderer_mclip.next_clip_box;
+var
+ cb : rect_ptr;
+
+begin
+ inc(m_curr_cb );
+
+ if m_curr_cb < m_clip.size then
+ begin
+ cb:=m_clip.array_operator(m_curr_cb );
+
+ clip_box_naked(cb.x1 ,cb.y1 ,cb.x2 ,cb.y2 );
+
+ result:=true;
+
+ exit;
+
+ end;
+
+ result:=false;
+
+end;
+
+{ RESET_CLIPPING }
+procedure renderer_mclip.reset_clipping;
+begin
+ inherited reset_clipping(visibility );
+
+ m_clip.remove_all;
+
+ m_curr_cb:=0;
+
+ m_bounds.Construct(_clip_box );
+
+end;
+
+{ ADD_CLIP_BOX }
+procedure renderer_mclip.add_clip_box;
+var
+ cb ,
+ rc : rect;
+
+begin
+ cb.Construct(x1 ,y1 ,x2 ,y2 );
+ cb.normalize;
+ rc.Construct(0 ,0 ,width - 1 ,height - 1 );
+
+ if cb.clip(@rc ) then
+ begin
+ m_clip.add(@cb );
+
+ if cb.x1 < m_bounds.x1 then
+ m_bounds.x1:=cb.x1;
+
+ if cb.y1 < m_bounds.y1 then
+ m_bounds.y1:=cb.y1;
+
+ if cb.x2 > m_bounds.x2 then
+ m_bounds.x2:=cb.x2;
+
+ if cb.y2 > m_bounds.y2 then
+ m_bounds.y2:=cb.y2;
+
+ end;
+
+end;
+
+{ COPY_PIXEL }
+procedure renderer_mclip.copy_pixel;
+begin
+ first_clip_box;
+
+ repeat
+ if inbox(x ,y ) then
+ begin
+ m_ren.copy_pixel(m_ren ,x ,y ,c );
+
+ break;
+
+ end;
+
+ until not next_clip_box;
+
+end;
+
+{ BLEND_PIXEL }
+procedure renderer_mclip.blend_pixel;
+begin
+ first_clip_box;
+
+ repeat
+ if inbox(x ,y ) then
+ begin
+ m_ren.blend_pixel(m_ren ,x ,y ,c ,cover );
+
+ break;
+
+ end;
+
+ until not next_clip_box;
+
+end;
+
+{ PIXEL }
+function renderer_mclip.pixel;
+begin
+ first_clip_box;
+
+ repeat
+ if inbox(x ,y ) then
+ begin
+ result:=m_ren.pixel(m_ren ,x ,y );
+
+ exit;
+
+ end;
+
+ until not next_clip_box;
+
+ result.clear;
+
+end;
+
+{ COPY_HLINE }
+procedure renderer_mclip.copy_hline;
+begin
+ first_clip_box;
+
+ repeat
+ inherited copy_hline(x1 ,y ,x2 ,c );
+
+ until not next_clip_box;
+
+end;
+
+{ COPY_VLINE }
+procedure renderer_mclip.copy_vline;
+begin
+ first_clip_box;
+
+ repeat
+ inherited copy_vline(x ,y1 ,y2 ,c );
+
+ until not next_clip_box;
+
+end;
+
+{ BLEND_HLINE }
+procedure renderer_mclip.blend_hline;
+begin
+ first_clip_box;
+
+ repeat
+ inherited blend_hline(x1 ,y ,x2 ,c ,cover );
+
+ until not next_clip_box;
+
+end;
+
+{ BLEND_VLINE }
+procedure renderer_mclip.blend_vline;
+begin
+ first_clip_box;
+
+ repeat
+ inherited blend_vline(x ,y1 ,y2 ,c ,cover );
+
+ until not next_clip_box;
+
+end;
+
+{ COPY_BAR }
+procedure renderer_mclip.copy_bar;
+begin
+ first_clip_box;
+
+ repeat
+ inherited copy_bar(x1 ,y1 ,x2 ,y2 ,c );
+
+ until not next_clip_box;
+
+end;
+
+{ BLEND_BAR }
+procedure renderer_mclip.blend_bar;
+begin
+ first_clip_box;
+
+ repeat
+ inherited blend_bar(x1 ,y1 ,x2 ,y2 ,c ,cover );
+
+ until not next_clip_box;
+
+end;
+
+{ BLEND_SOLID_HSPAN }
+procedure renderer_mclip.blend_solid_hspan;
+begin
+ first_clip_box;
+
+ repeat
+ inherited blend_solid_hspan(x ,y ,len ,c ,covers );
+
+ until not next_clip_box;
+
+end;
+
+{ BLEND_SOLID_VSPAN }
+procedure renderer_mclip.blend_solid_vspan;
+begin
+ first_clip_box;
+
+ repeat
+ inherited blend_solid_vspan(x ,y ,len ,c ,covers );
+
+ until not next_clip_box;
+
+end;
+
+{ COPY_COLOR_HSPAN }
+procedure renderer_mclip.copy_color_hspan;
+begin
+ first_clip_box;
+
+ repeat
+ inherited copy_color_hspan(x ,y ,len ,colors );
+
+ until not next_clip_box;
+
+end;
+
+{ BLEND_COLOR_HSPAN }
+procedure renderer_mclip.blend_color_hspan;
+begin
+ first_clip_box;
+
+ repeat
+ inherited blend_color_hspan(x ,y ,len ,colors ,covers ,cover );
+
+ until not next_clip_box;
+
+end;
+
+{ BLEND_COLOR_VSPAN }
+procedure renderer_mclip.blend_color_vspan;
+begin
+ first_clip_box;
+
+ repeat
+ inherited blend_color_vspan(x ,y ,len ,colors ,covers ,cover );
+
+ until not next_clip_box;
+
+end;
+
+{ COPY_FROM }
+procedure renderer_mclip.copy_from;
+begin
+ first_clip_box;
+
+ repeat
+ inherited copy_from(from ,rc ,x_to ,y_to );
+
+ until not next_clip_box;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_renderer_outline_aa.pas b/src/corelib/render/software/agg_renderer_outline_aa.pas
new file mode 100644
index 00000000..d66eb1f7
--- /dev/null
+++ b/src/corelib/render/software/agg_renderer_outline_aa.pas
@@ -0,0 +1,2599 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 01.02.2006-Milano: Complete unit port
+// 31.01.2006-Milano: Unit port establishment
+//
+{ agg_renderer_outline_aa.pas }
+unit
+ agg_renderer_outline_aa ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+{$Q- }
+{$R- }
+uses
+ agg_basics ,
+ agg_color ,
+ agg_math ,
+ agg_line_aa_basics ,
+ agg_dda_line ,
+ agg_ellipse_bresenham ,
+ agg_renderer_base ,
+ agg_gamma_functions ,
+ agg_vertex_source ;
+
+{ TYPES DEFINITION }
+const
+ max_half_width = 64;
+
+ subpixel_shift = line_subpixel_shift;
+ subpixel_size = 1 shl subpixel_shift;
+ subpixel_mask = subpixel_size - 1;
+
+ aa_shift = 8;
+ aa_num = 1 shl aa_shift;
+ aa_mask = aa_num - 1;
+
+type
+ distance_interpolator_ptr = ^distance_interpolator;
+ distance_interpolator = object
+ procedure inc_x_; virtual; abstract;
+ procedure dec_x_; virtual; abstract;
+ procedure inc_y_; virtual; abstract;
+ procedure dec_y_; virtual; abstract;
+
+ procedure inc_x(dy_ : int ); virtual; abstract;
+ procedure dec_x(dy_ : int ); virtual; abstract;
+ procedure inc_y(dx_ : int ); virtual; abstract;
+ procedure dec_y(dx_ : int ); virtual; abstract;
+
+ function dist : int; virtual; abstract;
+ function dist_start : int; virtual; abstract;
+ function dist_end : int; virtual; abstract;
+
+ function dx : int; virtual; abstract;
+ function dy : int; virtual; abstract;
+ function dx_start : int; virtual; abstract;
+ function dy_start : int; virtual; abstract;
+ function dx_end : int; virtual; abstract;
+ function dy_end : int; virtual; abstract;
+
+ end;
+
+ distance_interpolator0 = object(distance_interpolator )
+ m_dx ,
+ m_dy ,
+ m_dist : int;
+
+ constructor Construct; overload;
+ constructor Construct(x1 ,y1 ,x2 ,y2 ,x ,y : int ); overload;
+
+ procedure inc_x_; virtual;
+ procedure dec_x_; virtual;
+ procedure inc_y_; virtual;
+ procedure dec_y_; virtual;
+
+ procedure inc_x(dy_ : int ); virtual;
+ procedure dec_x(dy_ : int ); virtual;
+ procedure inc_y(dx_ : int ); virtual;
+ procedure dec_y(dx_ : int ); virtual;
+
+ function dist : int; virtual;
+ function dx : int; virtual;
+ function dy : int; virtual;
+
+ end;
+
+ distance_interpolator1 = object(distance_interpolator )
+ m_dx ,
+ m_dy ,
+ m_dist : int;
+
+ constructor Construct; overload;
+ constructor Construct(x1 ,y1 ,x2 ,y2 ,x ,y : int ); overload;
+
+ procedure inc_x_; virtual;
+ procedure dec_x_; virtual;
+ procedure inc_y_; virtual;
+ procedure dec_y_; virtual;
+
+ procedure inc_x(dy_ : int ); virtual;
+ procedure dec_x(dy_ : int ); virtual;
+ procedure inc_y(dx_ : int ); virtual;
+ procedure dec_y(dx_ : int ); virtual;
+
+ function dist : int; virtual;
+ function dx : int; virtual;
+ function dy : int; virtual;
+
+ end;
+
+ distance_interpolator2 = object(distance_interpolator )
+ m_dx ,
+ m_dy ,
+
+ m_dx_start ,
+ m_dy_start ,
+
+ m_dist ,m_dist_start : int;
+
+ constructor Construct; overload;
+ constructor Construct(x1 ,y1 ,x2 ,y2 ,sx ,sy ,x ,y : int ); overload;
+ constructor Construct(x1 ,y1 ,x2 ,y2 ,ex ,ey ,x ,y ,z : int ); overload;
+
+ procedure inc_x_; virtual;
+ procedure dec_x_; virtual;
+ procedure inc_y_; virtual;
+ procedure dec_y_; virtual;
+
+ procedure inc_x(dy_ : int ); virtual;
+ procedure dec_x(dy_ : int ); virtual;
+ procedure inc_y(dx_ : int ); virtual;
+ procedure dec_y(dx_ : int ); virtual;
+
+ function dist : int; virtual;
+ function dist_start : int; virtual;
+ function dist_end : int; virtual;
+
+ function dx : int; virtual;
+ function dy : int; virtual;
+ function dx_start : int; virtual;
+ function dy_start : int; virtual;
+ function dx_end : int; virtual;
+ function dy_end : int; virtual;
+
+ end;
+
+ distance_interpolator3 = object(distance_interpolator )
+ m_dx ,
+ m_dy ,
+
+ m_dx_start ,
+ m_dy_start ,
+
+ m_dx_end ,
+ m_dy_end ,
+
+ m_dist ,m_dist_start ,m_dist_end : int;
+
+ constructor Construct; overload;
+ constructor Construct(x1 ,y1 ,x2 ,y2 ,sx ,sy ,ex ,ey ,x ,y : int ); overload;
+
+ procedure inc_x_; virtual;
+ procedure dec_x_; virtual;
+ procedure inc_y_; virtual;
+ procedure dec_y_; virtual;
+
+ procedure inc_x(dy_ : int ); virtual;
+ procedure dec_x(dy_ : int ); virtual;
+ procedure inc_y(dx_ : int ); virtual;
+ procedure dec_y(dx_ : int ); virtual;
+
+ function dist : int; virtual;
+ function dist_start : int; virtual;
+ function dist_end : int; virtual;
+
+ function dx : int; virtual;
+ function dy : int; virtual;
+ function dx_start : int; virtual;
+ function dy_start : int; virtual;
+ function dx_end : int; virtual;
+ function dy_end : int; virtual;
+
+ end;
+
+ renderer_outline_aa_ptr = ^renderer_outline_aa;
+
+ line_interpolator = object
+ function step_hor : boolean; virtual; abstract;
+ function step_ver : boolean; virtual; abstract;
+
+ function width : int; virtual; abstract;
+ function count : int; virtual; abstract;
+
+ end;
+
+ line_interpolator_aa_base = object //(line_interpolator )
+ m_lp : line_parameters_ptr;
+ m_li : dda2_line_interpolator;
+ m_ren : renderer_outline_aa_ptr;
+
+ m_len ,
+ m_x ,
+ m_y ,
+
+ m_old_x ,
+ m_old_y ,
+ m_count ,
+ m_width ,
+
+ m_max_extent ,
+ m_step : int;
+
+ m_dist : array[0..max_half_width + 1 - 1 ] of int;
+ m_covers : array[0..max_half_width * 2 + 4 - 1 ] of int8u;
+
+ constructor Construct(ren : renderer_outline_aa_ptr; lp : line_parameters_ptr );
+
+ function step_hor : boolean; virtual; abstract;
+ function step_ver : boolean; virtual; abstract;
+
+ function step_hor_base(di : distance_interpolator_ptr ) : int;
+ function step_ver_base(di : distance_interpolator_ptr ) : int;
+
+ function vertical : boolean;
+
+ function width : int; virtual;
+ function count : int; virtual;
+
+ end;
+
+ line_interpolator_aa0_ptr = ^line_interpolator_aa0;
+ line_interpolator_aa0 = object(line_interpolator_aa_base )
+ m_di : distance_interpolator1;
+
+ constructor Construct(ren : renderer_outline_aa_ptr; lp : line_parameters_ptr );
+
+ function step_hor : boolean; virtual;
+ function step_ver : boolean; virtual;
+
+ end;
+
+ line_interpolator_aa1_ptr = ^line_interpolator_aa1;
+ line_interpolator_aa1 = object(line_interpolator_aa_base )
+ m_di : distance_interpolator2;
+
+ constructor Construct(ren : renderer_outline_aa_ptr; lp : line_parameters_ptr; sx ,sy : int );
+
+ function step_hor : boolean; virtual;
+ function step_ver : boolean; virtual;
+
+ end;
+
+ line_interpolator_aa2_ptr = ^line_interpolator_aa2;
+ line_interpolator_aa2 = object(line_interpolator_aa_base )
+ m_di : distance_interpolator2;
+
+ constructor Construct(ren : renderer_outline_aa_ptr; lp : line_parameters_ptr; ex ,ey : int );
+
+ function step_hor : boolean; virtual;
+ function step_ver : boolean; virtual;
+
+ end;
+
+ line_interpolator_aa3_ptr = ^line_interpolator_aa3;
+ line_interpolator_aa3 = object(line_interpolator_aa_base )
+ m_di : distance_interpolator3;
+
+ constructor Construct(ren : renderer_outline_aa_ptr; lp : line_parameters_ptr; sx ,sy ,ex ,ey : int );
+
+ function step_hor : boolean; virtual;
+ function step_ver : boolean; virtual;
+
+ end;
+
+ line_profile_aa_ptr = ^line_profile_aa;
+ line_profile_aa = object
+ m_size : unsigned;
+ m_profile : int8u_ptr;
+ m_gamma : array[0..aa_num - 1 ] of int8u;
+
+ m_subpixel_width : int;
+ m_min_width ,
+ m_smoother_width : double;
+
+ constructor Construct; overload;
+ constructor Construct(w : double; gamma_function : vertex_source_ptr ); overload;
+ destructor Destruct;
+
+ procedure min_width_ (w : double );
+ procedure smoother_width_(w : double );
+
+ procedure gamma_(gamma_function : vertex_source_ptr );
+ procedure width_(w : double );
+
+ function _profile_size : unsigned;
+ function _subpixel_width : int;
+
+ function _min_width : double;
+ function _smoother_width : double;
+
+ function value(dist : int ) : int8u;
+
+ function profile(w : double ) : int8u_ptr;
+ procedure set_ (center_width ,smoother_width : double );
+
+ end;
+
+ cmp_function = function(d : int ) : boolean;
+
+ renderer_outline_ptr = ^renderer_outline;
+ renderer_outline = object
+ procedure color_(c : aggclr_ptr ); virtual; abstract;
+
+ function subpixel_width : int; virtual; abstract;
+ function accurate_join_only : boolean; virtual; abstract;
+
+ procedure semidot(cmp : cmp_function; xc1 ,yc1 ,xc2 ,yc2 : int ); virtual; abstract;
+
+ procedure line0(lp : line_parameters_ptr ); virtual; abstract;
+ procedure line1(lp : line_parameters_ptr; sx ,sy : int ); virtual; abstract;
+ procedure line2(lp : line_parameters_ptr; ex ,ey : int ); virtual; abstract;
+ procedure line3(lp : line_parameters_ptr; sx ,sy ,ex ,ey : int ); virtual; abstract;
+
+ end;
+
+ renderer_outline_aa = object(renderer_outline )
+ m_ren : renderer_base_ptr;
+ m_profile : line_profile_aa_ptr;
+ m_color : aggclr;
+
+ constructor Construct(ren : renderer_base_ptr; prof : line_profile_aa_ptr );
+
+ procedure color_(c : aggclr_ptr ); virtual;
+ function _color : aggclr_ptr;
+
+ procedure profile_(prof : line_profile_aa_ptr );
+ function _profile : line_profile_aa_ptr;
+
+ function subpixel_width : int; virtual;
+ function cover(d : int ) : int8u;
+
+ procedure blend_solid_hspan(x ,y : int; len : unsigned; covers : int8u_ptr );
+ procedure blend_solid_vspan(x ,y : int; len : unsigned; covers : int8u_ptr );
+
+ function accurate_join_only : boolean; virtual;
+
+ procedure semidot_hline(cmp : cmp_function; xc1 ,yc1 ,xc2 ,yc2 ,x1 ,y1 ,x2 : int );
+ procedure semidot (cmp : cmp_function; xc1 ,yc1 ,xc2 ,yc2 : int ); virtual;
+
+ procedure line0(lp : line_parameters_ptr ); virtual;
+ procedure line1(lp : line_parameters_ptr; sx ,sy : int ); virtual;
+ procedure line2(lp : line_parameters_ptr; ex ,ey : int ); virtual;
+ procedure line3(lp : line_parameters_ptr; sx ,sy ,ex ,ey : int ); virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor distance_interpolator0.Construct;
+begin
+end;
+
+{ CONSTRUCT }
+constructor distance_interpolator0.Construct(x1 ,y1 ,x2 ,y2 ,x ,y : int );
+begin
+ m_dx:=line_mr(x2 ) - line_mr(x1 );
+ m_dy:=line_mr(y2 ) - line_mr(y1 );
+
+ m_dist:=
+ (line_mr(x + line_subpixel_size div 2 ) - line_mr(x2 ) ) * m_dy -
+ (line_mr(y + line_subpixel_size div 2 ) - line_mr(y2 ) ) * m_dx;
+
+ m_dx:=m_dx shl line_mr_subpixel_shift;
+ m_dy:=m_dy shl line_mr_subpixel_shift;
+
+end;
+
+{ INC_X_ }
+procedure distance_interpolator0.inc_x_;
+begin
+ inc(m_dist ,m_dy );
+
+end;
+
+{ DEC_X_ }
+procedure distance_interpolator0.dec_x_;
+begin
+ dec(m_dist ,m_dy );
+
+end;
+
+{ INC_Y_ }
+procedure distance_interpolator0.inc_y_;
+begin
+ inc(m_dist ,m_dx );
+
+end;
+
+{ DEC_Y_ }
+procedure distance_interpolator0.dec_y_;
+begin
+ inc(m_dist ,m_dx );
+
+end;
+
+{ INC_X }
+procedure distance_interpolator0.inc_x(dy_ : int );
+begin
+ inc(m_dist ,m_dy );
+
+ if dy_ > 0 then
+ dec(m_dist ,m_dx );
+
+ if dy_ < 0 then
+ inc(m_dist ,m_dx );
+
+end;
+
+{ DEC_X }
+procedure distance_interpolator0.dec_x(dy_ : int );
+begin
+ dec(m_dist ,m_dy );
+
+ if dy_ > 0 then
+ dec(m_dist ,m_dx );
+
+ if dy_ < 0 then
+ inc(m_dist ,m_dx );
+
+end;
+
+{ INC_Y }
+procedure distance_interpolator0.inc_y(dx_ : int );
+begin
+ dec(m_dist ,m_dx );
+
+ if dx_ > 0 then
+ inc(m_dist ,m_dy );
+
+ if dx_ < 0 then
+ dec(m_dist ,m_dy );
+
+end;
+
+{ DEC_Y }
+procedure distance_interpolator0.dec_y(dx_ : int );
+begin
+ inc(m_dist ,m_dx );
+
+ if dx_ > 0 then
+ inc(m_dist ,m_dy );
+
+ if dx_ < 0 then
+ dec(m_dist ,m_dy );
+
+end;
+
+{ DIST }
+function distance_interpolator0.dist;
+begin
+ result:=m_dist;
+
+end;
+
+{ DX }
+function distance_interpolator0.dx;
+begin
+ result:=m_dx;
+
+end;
+
+{ DY }
+function distance_interpolator0.dy;
+begin
+ result:=m_dy;
+
+end;
+
+{ CONSTRUCT }
+constructor distance_interpolator1.Construct;
+begin
+end;
+
+{ CONSTRUCT }
+constructor distance_interpolator1.Construct(x1 ,y1 ,x2 ,y2 ,x ,y : int );
+begin
+ m_dx:=x2 - x1;
+ m_dy:=y2 - y1;
+
+ m_dist:=
+ trunc(
+ (x + line_subpixel_size / 2 - x2 ) * m_dy -
+ (y + line_subpixel_size / 2 - y2 ) * m_dx );
+
+ m_dx:=m_dx shl line_subpixel_shift;
+ m_dy:=m_dy shl line_subpixel_shift;
+
+end;
+
+{ INC_X_ }
+procedure distance_interpolator1.inc_x_;
+begin
+ inc(m_dist ,m_dy );
+
+end;
+
+{ DEC_X_ }
+procedure distance_interpolator1.dec_x_;
+begin
+ dec(m_dist ,m_dy );
+
+end;
+
+{ INC_Y_ }
+procedure distance_interpolator1.inc_y_;
+begin
+ dec(m_dist ,m_dx );
+
+end;
+
+{ DEC_Y_ }
+procedure distance_interpolator1.dec_y_;
+begin
+ inc(m_dist ,m_dx );
+
+end;
+
+{ INC_X }
+procedure distance_interpolator1.inc_x(dy_ : int );
+begin
+ inc(m_dist ,m_dy );
+
+ if dy_ > 0 then
+ dec(m_dist ,m_dx );
+
+ if dy_ < 0 then
+ inc(m_dist ,m_dx );
+
+end;
+
+{ DEC_X }
+procedure distance_interpolator1.dec_x(dy_ : int );
+begin
+ dec(m_dist ,m_dy );
+
+ if dy_ > 0 then
+ dec(m_dist ,m_dx );
+
+ if dy_ < 0 then
+ inc(m_dist ,m_dx );
+
+end;
+
+{ INC_Y }
+procedure distance_interpolator1.inc_y(dx_ : int );
+begin
+ dec(m_dist ,m_dx );
+
+ if dx_ > 0 then
+ inc(m_dist ,m_dy );
+
+ if dx_ < 0 then
+ dec(m_dist ,m_dy );
+
+end;
+
+{ DEC_Y }
+procedure distance_interpolator1.dec_y(dx_ : int );
+begin
+ inc(m_dist ,m_dx );
+
+ if dx_ > 0 then
+ inc(m_dist ,m_dy );
+
+ if dx_ < 0 then
+ dec(m_dist ,m_dy );
+
+end;
+
+{ DIST }
+function distance_interpolator1.dist;
+begin
+ result:=m_dist;
+
+end;
+
+{ DX }
+function distance_interpolator1.dx;
+begin
+ result:=m_dx;
+
+end;
+
+{ DY }
+function distance_interpolator1.dy;
+begin
+ result:=m_dy;
+
+end;
+
+{ CONSTRUCT }
+constructor distance_interpolator2.Construct;
+begin
+end;
+
+{ CONSTRUCT }
+constructor distance_interpolator2.Construct(x1 ,y1 ,x2 ,y2 ,sx ,sy ,x ,y : int );
+begin
+ m_dx:=x2 - x1;
+ m_dy:=y2 - y1;
+
+ m_dx_start:=line_mr(sx ) - line_mr(x1 );
+ m_dy_start:=line_mr(sy ) - line_mr(y1 );
+
+ m_dist:=
+ trunc(
+ (x + line_subpixel_size / 2 - x2 ) * m_dy -
+ (y + line_subpixel_size / 2 - y2 ) * m_dx );
+
+ m_dist_start:=
+ (line_mr(x + line_subpixel_size div 2 ) - line_mr(sx ) ) * m_dy_start -
+ (line_mr(y + line_subpixel_size div 2 ) - line_mr(sy ) ) * m_dx_start;
+
+ m_dx:=m_dx shl line_subpixel_shift;
+ m_dy:=m_dy shl line_subpixel_shift;
+
+ m_dx_start:=m_dx_start shl line_mr_subpixel_shift;
+ m_dy_start:=m_dy_start shl line_mr_subpixel_shift;
+
+end;
+
+{ CONSTRUCT }
+constructor distance_interpolator2.Construct(x1 ,y1 ,x2 ,y2 ,ex ,ey ,x ,y ,z : int );
+begin
+ m_dx:=x2 - x1;
+ m_dy:=y2 - y1;
+
+ m_dx_start:=line_mr(ex ) - line_mr(x2 );
+ m_dy_start:=line_mr(ey ) - line_mr(y2 );
+
+ m_dist:=
+ trunc(
+ (x + line_subpixel_size / 2 - x2 ) * m_dy -
+ (y + line_subpixel_size / 2 - y2 ) * m_dx );
+
+ m_dist_start:=
+ (line_mr(x + line_subpixel_size div 2 ) - line_mr(ex ) ) * m_dy_start -
+ (line_mr(y + line_subpixel_size div 2 ) - line_mr(ey ) ) * m_dx_start;
+
+ m_dx:=m_dx shl line_subpixel_shift;
+ m_dy:=m_dy shl line_subpixel_shift;
+
+ m_dx_start:=m_dx_start shl line_mr_subpixel_shift;
+ m_dy_start:=m_dy_start shl line_mr_subpixel_shift;
+
+end;
+
+{ INC_X_ }
+procedure distance_interpolator2.inc_x_;
+begin
+ inc(m_dist ,m_dy );
+ inc(m_dist_start ,m_dy_start );
+
+end;
+
+{ DEC_X_ }
+procedure distance_interpolator2.dec_x_;
+begin
+ dec(m_dist ,m_dy );
+ dec(m_dist_start ,m_dy_start );
+
+end;
+
+{ INC_Y_ }
+procedure distance_interpolator2.inc_y_;
+begin
+ dec(m_dist ,m_dx );
+ dec(m_dist_start ,m_dx_start );
+
+end;
+
+{ DEC_Y_ }
+procedure distance_interpolator2.dec_y_;
+begin
+ inc(m_dist ,m_dx );
+ inc(m_dist_start ,m_dx_start );
+
+end;
+
+{ INC_X }
+procedure distance_interpolator2.inc_x(dy_ : int );
+begin
+ inc(m_dist ,m_dy );
+ inc(m_dist_start ,m_dy_start );
+
+ if dy_ > 0 then
+ begin
+ dec(m_dist ,m_dx );
+ dec(m_dist_start ,m_dx_start );
+
+ end;
+
+ if dy_ < 0 then
+ begin
+ inc(m_dist ,m_dx );
+ inc(m_dist_start ,m_dx_start );
+
+ end;
+
+end;
+
+{ DEC_X }
+procedure distance_interpolator2.dec_x(dy_ : int );
+begin
+ dec(m_dist ,m_dy );
+ dec(m_dist_start ,m_dy_start );
+
+ if dy_ > 0 then
+ begin
+ dec(m_dist ,m_dx );
+ dec(m_dist_start ,m_dx_start );
+
+ end;
+
+ if dy_ < 0 then
+ begin
+ inc(m_dist ,m_dx );
+ inc(m_dist_start ,m_dx_start );
+
+ end;
+
+end;
+
+{ INC_Y }
+procedure distance_interpolator2.inc_y(dx_ : int );
+begin
+ dec(m_dist ,m_dx );
+ dec(m_dist_start ,m_dx_start );
+
+ if dx_ > 0 then
+ begin
+ inc(m_dist ,m_dy );
+ inc(m_dist_start ,m_dy_start );
+
+ end;
+
+ if dx_ < 0 then
+ begin
+ dec(m_dist ,m_dy );
+ dec(m_dist_start ,m_dy_start );
+
+ end;
+
+end;
+
+{ DEC_Y }
+procedure distance_interpolator2.dec_y(dx_ : int );
+begin
+ inc(m_dist ,m_dx );
+ inc(m_dist_start ,m_dx_start );
+
+ if dx_ > 0 then
+ begin
+ inc(m_dist ,m_dy );
+ inc(m_dist_start ,m_dy_start );
+
+ end;
+
+ if dx_ < 0 then
+ begin
+ dec(m_dist ,m_dy );
+ dec(m_dist_start ,m_dy_start );
+
+ end;
+
+end;
+
+{ DIST }
+function distance_interpolator2.dist;
+begin
+ result:=m_dist;
+
+end;
+
+{ DIST_START }
+function distance_interpolator2.dist_start;
+begin
+ result:=m_dist_start;
+
+end;
+
+{ DIST_END }
+function distance_interpolator2.dist_end;
+begin
+ result:=m_dist_start;
+
+end;
+
+{ DX }
+function distance_interpolator2.dx;
+begin
+ result:=m_dx;
+
+end;
+
+{ DY }
+function distance_interpolator2.dy;
+begin
+ result:=m_dy;
+
+end;
+
+{ DX_START }
+function distance_interpolator2.dx_start;
+begin
+ result:=m_dx_start;
+
+end;
+
+{ DY_START }
+function distance_interpolator2.dy_start;
+begin
+ result:=m_dy_start;
+
+end;
+
+{ DX_END }
+function distance_interpolator2.dx_end;
+begin
+ result:=m_dx_start;
+
+end;
+
+{ DY_END }
+function distance_interpolator2.dy_end;
+begin
+ result:=m_dy_start;
+
+end;
+
+{ CONSTRUCT }
+constructor distance_interpolator3.Construct;
+begin
+end;
+
+{ CONSTRUCT }
+constructor distance_interpolator3.Construct(x1 ,y1 ,x2 ,y2 ,sx ,sy ,ex ,ey ,x ,y : int );
+begin
+ m_dx:=x2 - x1;
+ m_dy:=y2 - y1;
+
+ m_dx_start:=line_mr(sx ) - line_mr(x1 );
+ m_dy_start:=line_mr(sy ) - line_mr(y1 );
+
+ m_dx_end:=line_mr(ex ) - line_mr(x2 );
+ m_dy_end:=line_mr(ey ) - line_mr(y2 );
+
+ m_dist:=
+ trunc(
+ (x + line_subpixel_size / 2 - x2 ) * m_dy -
+ (y + line_subpixel_size / 2 - y2 ) * m_dx );
+
+ m_dist_start:=
+ (line_mr(x + line_subpixel_size div 2 ) - line_mr(sx ) ) * m_dy_start -
+ (line_mr(y + line_subpixel_size div 2 ) - line_mr(sy ) ) * m_dx_start;
+
+ m_dist_end:=
+ (line_mr(x + line_subpixel_size div 2 ) - line_mr(ex ) ) * m_dy_end -
+ (line_mr(y + line_subpixel_size div 2 ) - line_mr(ey ) ) * m_dx_end;
+
+ m_dx:=m_dx shl line_subpixel_shift;
+ m_dy:=m_dy shl line_subpixel_shift;
+
+ m_dx_start:=m_dx_start shl line_mr_subpixel_shift;
+ m_dy_start:=m_dy_start shl line_mr_subpixel_shift;
+
+ m_dx_end:=m_dx_end shl line_mr_subpixel_shift;
+ m_dy_end:=m_dy_end shl line_mr_subpixel_shift;
+
+end;
+
+{ INC_X_ }
+procedure distance_interpolator3.inc_x_;
+begin
+ inc(m_dist ,m_dy );
+ inc(m_dist_start ,m_dy_start );
+ inc(m_dist_end ,m_dy_end );
+
+end;
+
+{ DEC_X_ }
+procedure distance_interpolator3.dec_x_;
+begin
+ dec(m_dist ,m_dy );
+ dec(m_dist_start ,m_dy_start );
+ dec(m_dist_end ,m_dy_end );
+
+end;
+
+{ INC_Y_ }
+procedure distance_interpolator3.inc_y_;
+begin
+ dec(m_dist ,m_dx );
+ dec(m_dist_start ,m_dx_start );
+ dec(m_dist_end ,m_dx_end );
+
+end;
+
+{ DEC_Y_ }
+procedure distance_interpolator3.dec_y_;
+begin
+ inc(m_dist ,m_dx );
+ inc(m_dist_start ,m_dx_start );
+ inc(m_dist_end ,m_dx_end );
+
+end;
+
+{ INC_X }
+procedure distance_interpolator3.inc_x(dy_ : int );
+begin
+ inc(m_dist ,m_dy );
+ inc(m_dist_start ,m_dy_start );
+ inc(m_dist_end ,m_dy_end );
+
+ if dy_ > 0 then
+ begin
+ dec(m_dist ,m_dx );
+ dec(m_dist_start ,m_dx_start );
+ dec(m_dist_end ,m_dx_end );
+
+ end;
+
+ if dy_ < 0 then
+ begin
+ inc(m_dist ,m_dx );
+ inc(m_dist_start ,m_dx_start );
+ inc(m_dist_end ,m_dx_end );
+
+ end;
+
+end;
+
+{ DEC_X }
+procedure distance_interpolator3.dec_x(dy_ : int );
+begin
+ dec(m_dist ,m_dy );
+ dec(m_dist_start ,m_dy_start );
+ dec(m_dist_end ,m_dy_end );
+
+ if dy_ > 0 then
+ begin
+ dec(m_dist ,m_dx );
+ dec(m_dist_start ,m_dx_start );
+ dec(m_dist_end ,m_dx_end );
+
+ end;
+
+ if dy_ < 0 then
+ begin
+ inc(m_dist ,m_dx );
+ inc(m_dist_start ,m_dx_start );
+ inc(m_dist_end ,m_dx_end );
+
+ end;
+
+end;
+
+{ INC_Y }
+procedure distance_interpolator3.inc_y(dx_ : int );
+begin
+ dec(m_dist ,m_dx );
+ dec(m_dist_start ,m_dx_start );
+ dec(m_dist_end ,m_dx_end );
+
+ if dx_ > 0 then
+ begin
+ inc(m_dist ,m_dy );
+ inc(m_dist_start ,m_dy_start );
+ inc(m_dist_end ,m_dy_end );
+
+ end;
+
+ if dx_ < 0 then
+ begin
+ dec(m_dist ,m_dy );
+ dec(m_dist_start ,m_dy_start );
+ dec(m_dist_end ,m_dy_end );
+
+ end;
+
+end;
+
+{ DEC_Y }
+procedure distance_interpolator3.dec_y(dx_ : int );
+begin
+ inc(m_dist ,m_dx );
+ inc(m_dist_start ,m_dx_start );
+ inc(m_dist_end ,m_dx_end );
+
+ if dx_ > 0 then
+ begin
+ inc(m_dist ,m_dy );
+ inc(m_dist_start ,m_dy_start );
+ inc(m_dist_end ,m_dy_end );
+
+ end;
+
+ if dx_ < 0 then
+ begin
+ dec(m_dist ,m_dy );
+ dec(m_dist_start ,m_dy_start );
+ dec(m_dist_end ,m_dy_end );
+
+ end;
+
+end;
+
+{ DIST }
+function distance_interpolator3.dist;
+begin
+ result:=m_dist;
+
+end;
+
+{ DIST_START }
+function distance_interpolator3.dist_start;
+begin
+ result:=m_dist_start;
+
+end;
+
+{ DIST_END }
+function distance_interpolator3.dist_end;
+begin
+ result:=m_dist_end;
+
+end;
+
+{ DX }
+function distance_interpolator3.dx;
+begin
+ result:=m_dx;
+
+end;
+
+{ DY }
+function distance_interpolator3.dy;
+begin
+ result:=m_dy;
+
+end;
+
+{ DX_START }
+function distance_interpolator3.dx_start;
+begin
+ result:=m_dx_start;
+
+end;
+
+{ DY_START }
+function distance_interpolator3.dy_start;
+begin
+ result:=m_dy_start;
+
+end;
+
+{ DX_END }
+function distance_interpolator3.dx_end;
+begin
+ result:=m_dx_end;
+
+end;
+
+{ DY_END }
+function distance_interpolator3.dy_end;
+begin
+ result:=m_dy_end;
+
+end;
+
+{ CONSTRUCT }
+constructor line_interpolator_aa_base.Construct;
+var
+ li : dda2_line_interpolator;
+ i : unsigned;
+
+ stop : int;
+
+begin
+ m_lp:=lp;
+
+ if lp.vertical then
+ m_li.Construct(line_dbl_hr(lp.x2 - lp.x1 ) ,Abs(lp.y2 - lp.y1 ) )
+ else
+ m_li.Construct(line_dbl_hr(lp.y2 - lp.y1 ) ,Abs(lp.x2 - lp.x1) + 1 );
+
+ m_ren:=ren;
+
+ if lp.vertical = (lp.inc_ > 0 ) then
+ m_len:=-lp.len
+ else
+ m_len:=lp.len;
+
+ m_x:=shr_int32(lp.x1 ,line_subpixel_shift );
+ m_y:=shr_int32(lp.y1 ,line_subpixel_shift );
+
+ m_old_x:=m_x;
+ m_old_y:=m_y;
+
+ if lp.vertical then
+ m_count:=Abs(shr_int32(lp.y2 ,line_subpixel_shift) - m_y )
+ else
+ m_count:=Abs(shr_int32(lp.x2 ,line_subpixel_shift) - m_x );
+
+ m_width :=ren.subpixel_width;
+ m_max_extent:=shr_int32(m_width ,line_subpixel_shift - 2 );
+ m_step :=0;
+
+ if lp.vertical then
+ li.Construct(0 ,lp.dy shl line_subpixel_shift ,lp.len )
+ else
+ li.Construct(0 ,lp.dx shl line_subpixel_shift ,lp.len );
+
+ stop:=m_width + line_subpixel_size * 2;
+
+ i:=0;
+
+ while i < max_half_width do
+ begin
+ m_dist[i ]:=li._y;
+
+ if m_dist[i ] >= stop then
+ break;
+
+ li.plus_operator;
+
+ inc(i );
+
+ end;
+
+ m_dist[i ]:=$7FFF0000;
+
+end;
+
+{ STEP_HOR_BASE }
+function line_interpolator_aa_base.step_hor_base;
+begin
+ m_li.plus_operator;
+
+ inc(m_x ,m_lp.inc_ );
+
+ m_y:=shr_int32(m_lp.y1 + m_li._y ,line_subpixel_shift );
+
+ if m_lp.inc_ > 0 then
+ di.inc_x(m_y - m_old_y )
+ else
+ di.dec_x(m_y - m_old_y );
+
+ m_old_y:=m_y;
+
+ result:=di.dist div m_len;
+
+end;
+
+{ STEP_VER_BASE }
+function line_interpolator_aa_base.step_ver_base;
+begin
+ m_li.plus_operator;
+
+ inc(m_y ,m_lp.inc_ );
+
+ m_x:=shr_int32(m_lp.x1 + m_li._y ,line_subpixel_shift );
+
+ if m_lp.inc_ > 0 then
+ di.inc_y(m_x - m_old_x )
+ else
+ di.dec_y(m_x - m_old_x );
+
+ m_old_x:=m_x;
+
+ result:=di.dist div m_len;
+
+end;
+
+{ VERTICAL }
+function line_interpolator_aa_base.vertical;
+begin
+ result:=m_lp.vertical;
+
+end;
+
+{ WIDTH }
+function line_interpolator_aa_base.width;
+begin
+ result:=m_width;
+
+end;
+
+{ COUNT }
+function line_interpolator_aa_base.count;
+begin
+ result:=m_count;
+
+end;
+
+{ CONSTRUCT }
+constructor line_interpolator_aa0.Construct;
+begin
+ inherited Construct(ren ,lp );
+
+ m_di.Construct(
+ lp.x1 ,lp.y1 ,lp.x2 ,lp.y2 ,
+ lp.x1 and not line_subpixel_mask ,
+ lp.y1 and not line_subpixel_mask );
+
+ m_li.adjust_forward;
+
+end;
+
+{ STEP_HOR }
+function line_interpolator_aa0.step_hor;
+var
+ dist ,dy ,s1 : int;
+
+ p0 ,p1 : int8u_ptr;
+
+begin
+ s1:=step_hor_base(@m_di );
+ p0:=int8u_ptr(ptrcomp(@m_covers[0 ] ) + (max_half_width + 2 ) * sizeof(int8u ) );
+ p1:=p0;
+
+ p1^:=int8u(m_ren.cover(s1 ) );
+
+ inc(ptrcomp(p1 ) ,sizeof(int8u ) );
+
+ dy :=1;
+ dist:=m_dist[dy ] - s1;
+
+ while dist <= m_width do
+ begin
+ p1^:=int8u(m_ren.cover(dist ) );
+
+ inc(ptrcomp(p1 ) ,sizeof(int8u ) );
+ inc(dy );
+
+ dist:=m_dist[dy ] - s1;
+
+ end;
+
+ dy :=1;
+ dist:=m_dist[dy ] + s1;
+
+ while dist <= m_width do
+ begin
+ dec(ptrcomp(p0 ) ,sizeof(int8u ) );
+
+ p0^:=int8u(m_ren.cover(dist ) );
+
+ inc(dy );
+
+ dist:=m_dist[dy ] + s1;
+
+ end;
+
+ m_ren.blend_solid_vspan(
+ m_x ,m_y - dy + 1 ,
+ unsigned((ptrcomp(p1 ) - ptrcomp(p0 ) ) div sizeof(int8u ) ) ,
+ p0 );
+
+ inc(m_step );
+
+ result:=m_step < m_count;
+
+end;
+
+{ STEP_VER }
+function line_interpolator_aa0.step_ver;
+var
+ dist ,dx ,s1 : int;
+
+ p0 ,p1 : int8u_ptr;
+
+begin
+ s1:=step_ver_base(@m_di );
+ p0:=int8u_ptr(ptrcomp(@m_covers[0 ] ) + (max_half_width + 2 ) * sizeof(int8u ) );
+ p1:=p0;
+
+ p1^:=int8u(m_ren.cover(s1 ) );
+
+ inc(ptrcomp(p1 ) ,sizeof(int8u ) );
+
+ dx :=1;
+ dist:=m_dist[dx ] - s1;
+
+ while dist <= m_width do
+ begin
+ p1^:=int8u(m_ren.cover(dist ) );
+
+ inc(ptrcomp(p1 ) ,sizeof(int8u ) );
+ inc(dx );
+
+ dist:=m_dist[dx ] - s1;
+
+ end;
+
+ dx :=1;
+ dist:=m_dist[dx ] + s1;
+
+ while dist <= m_width do
+ begin
+ dec(ptrcomp(p0 ) ,sizeof(int8u ) );
+
+ p0^:=int8u(m_ren.cover(dist ) );
+
+ inc(dx );
+
+ dist:=m_dist[dx ] + s1;
+
+ end;
+
+ m_ren.blend_solid_hspan(
+ m_x - dx + 1 ,m_y ,
+ unsigned((ptrcomp(p1 ) - ptrcomp(p0 ) ) div sizeof(int8u ) ) ,
+ p0 );
+
+ inc(m_step );
+
+ result:=m_step < m_count;
+
+end;
+
+{ CONSTRUCT }
+constructor line_interpolator_aa1.Construct;
+var
+ dist1_start ,dist2_start ,npix ,dx ,dy : int;
+
+begin
+ inherited Construct(ren ,lp );
+
+ m_di.Construct(
+ lp.x1 ,lp.y1 ,lp.x2 ,lp.y2 ,sx ,sy ,
+ lp.x1 and not line_subpixel_mask ,
+ lp.y1 and not line_subpixel_mask );
+
+ npix:=1;
+
+ if lp.vertical then
+ repeat
+ m_li.minus_operator;
+
+ dec(m_y ,lp.inc_ );
+
+ m_x:=shr_int32(m_lp.x1 + m_li._y ,line_subpixel_shift );
+
+ if lp.inc_ > 0 then
+ m_di.dec_y(m_x - m_old_x )
+ else
+ m_di.inc_y(m_x - m_old_x );
+
+ m_old_x:=m_x;
+
+ dist1_start:=m_di.dist_start;
+ dist2_start:=dist1_start;
+
+ dx:=0;
+
+ if dist1_start < 0 then
+ inc(npix );
+
+ repeat
+ inc(dist1_start ,m_di.dy_start );
+ dec(dist2_start ,m_di.dy_start );
+
+ if dist1_start < 0 then
+ inc(npix );
+
+ if dist2_start < 0 then
+ inc(npix );
+
+ inc(dx );
+
+ until m_dist[dx ] > m_width;
+
+ dec(m_step );
+
+ if npix = 0 then
+ break;
+
+ npix:=0;
+
+ until m_step < -m_max_extent
+ else
+ repeat
+ m_li.minus_operator;
+
+ dec(m_x ,lp.inc_ );
+
+ m_y:=shr_int32(m_lp.y1 + m_li._y ,line_subpixel_shift );
+
+ if lp.inc_ > 0 then
+ m_di.dec_x(m_y - m_old_y )
+ else
+ m_di.inc_x(m_y - m_old_y );
+
+ m_old_y:=m_y;
+
+ dist1_start:=m_di.dist_start;
+ dist2_start:=dist1_start;
+
+ dy:=0;
+
+ if dist1_start < 0 then
+ inc(npix );
+
+ repeat
+ dec(dist1_start ,m_di.dx_start );
+ inc(dist2_start ,m_di.dx_start );
+
+ if dist1_start < 0 then
+ inc(npix );
+
+ if dist2_start < 0 then
+ inc(npix );
+
+ inc(dy );
+
+ until m_dist[dy ] > m_width;
+
+ dec(m_step );
+
+ if npix = 0 then
+ break;
+
+ npix:=0;
+
+ until m_step < -m_max_extent;
+
+ m_li.adjust_forward;
+
+end;
+
+{ STEP_HOR }
+function line_interpolator_aa1.step_hor;
+var
+ dist_start ,dist ,dy ,s1 : int;
+
+ p0 ,p1 : int8u_ptr;
+
+begin
+ s1:=step_hor_base(@m_di );
+
+ dist_start:=m_di.dist_start;
+
+ p0:=int8u_ptr(ptrcomp(@m_covers[0 ] ) + (max_half_width + 2 ) * sizeof(int8u ) );
+ p1:=p0;
+
+ p1^:=0;
+
+ if dist_start <= 0 then
+ p1^:=int8u(m_ren.cover(s1 ) );
+
+ inc(ptrcomp(p1 ) ,sizeof(int8u ) );
+
+ dy :=1;
+ dist:=m_dist[dy ] - s1;
+
+ while dist <= m_width do
+ begin
+ dec(dist_start ,m_di.dx_start );
+
+ p1^:=0;
+
+ if dist_start <= 0 then
+ p1^:=int8u(m_ren.cover(dist ) );
+
+ inc(ptrcomp(p1 ) ,sizeof(int8u ) );
+ inc(dy );
+
+ dist:=m_dist[dy ] - s1;
+
+ end;
+
+ dy :=1;
+ dist_start:=m_di.dist_start;
+ dist :=m_dist[dy ] + s1;
+
+ while dist <= m_width do
+ begin
+ inc(dist_start ,m_di.dx_start );
+ dec(ptrcomp(p0 ) ,sizeof(int8u ) );
+
+ p0^:=0;
+
+ if dist_start <= 0 then
+ p0^:=int8u(m_ren.cover(dist ) );
+
+ inc(dy );
+
+ dist:=m_dist[dy ] + s1;
+
+ end;
+
+ m_ren.blend_solid_vspan(
+ m_x ,m_y - dy + 1 ,
+ unsigned((ptrcomp(p1 ) - ptrcomp(p0 ) ) div sizeof(int8u ) ) ,
+ p0 );
+
+ inc(m_step );
+
+ result:=m_step < m_count;
+
+end;
+
+{ STEP_VER }
+function line_interpolator_aa1.step_ver;
+var
+ dist_start ,dist ,dx ,s1 : int;
+
+ p0 ,p1 : int8u_ptr;
+
+begin
+ s1:=step_ver_base(@m_di );
+ p0:=int8u_ptr(ptrcomp(@m_covers[0 ] ) + (max_half_width + 2 ) * sizeof(int8u ) );
+ p1:=p0;
+
+ dist_start:=m_di.dist_start;
+
+ p1^:=0;
+
+ if dist_start <= 0 then
+ p1^:=int8u(m_ren.cover(s1 ) );
+
+ inc(ptrcomp(p1 ) ,sizeof(int8u ) );
+
+ dx :=1;
+ dist:=m_dist[dx ] - s1;
+
+ while dist <= m_width do
+ begin
+ inc(dist_start ,m_di.dy_start );
+
+ p1^:=0;
+
+ if dist_start <= 0 then
+ p1^:=int8u(m_ren.cover(dist ) );
+
+ inc(ptrcomp(p1 ) ,sizeof(int8u ) );
+ inc(dx );
+
+ dist:=m_dist[dx ] - s1;
+
+ end;
+
+ dx :=1;
+ dist_start:=m_di.dist_start;
+ dist :=m_dist[dx ] + s1;
+
+ while dist <= m_width do
+ begin
+ dec(dist_start ,m_di.dy_start );
+ dec(ptrcomp(p0 ) ,sizeof(int8u ) );
+
+ p0^:=0;
+
+ if dist_start <= 0 then
+ p0^:=int8u(m_ren.cover(dist ) );
+
+ inc(dx );
+
+ dist:=m_dist[dx ] + s1;
+
+ end;
+
+ m_ren.blend_solid_hspan(
+ m_x - dx + 1 ,m_y ,
+ unsigned((ptrcomp(p1 ) - ptrcomp(p0 ) ) div sizeof(int8u ) ) ,
+ p0 );
+
+ inc(m_step );
+
+ result:=m_step < m_count;
+
+end;
+
+{ CONSTRUCT }
+constructor line_interpolator_aa2.Construct;
+begin
+ inherited Construct(ren ,lp );
+
+ m_di.Construct(
+ lp.x1 ,lp.y1 ,lp.x2 ,lp.y2 ,ex ,ey ,
+ lp.x1 and not line_subpixel_mask ,
+ lp.y1 and not line_subpixel_mask ,
+ 0 );
+
+ m_li.adjust_forward;
+
+ dec(m_step ,m_max_extent );
+
+end;
+
+{ STEP_HOR }
+function line_interpolator_aa2.step_hor;
+var
+ dist_end ,dist ,dy ,s1 ,npix : int;
+
+ p0 ,p1 : int8u_ptr;
+
+begin
+ s1:=step_hor_base(@m_di );
+ p0:=int8u_ptr(ptrcomp(@m_covers[0 ] ) + (max_half_width + 2 ) * sizeof(int8u ) );
+ p1:=p0;
+
+ dist_end:=m_di.dist_end;
+
+ npix:=0;
+ p1^ :=0;
+
+ if dist_end > 0 then
+ begin
+ p1^:=int8u(m_ren.cover(s1 ) );
+
+ inc(npix );
+
+ end;
+
+ inc(ptrcomp(p1 ) ,sizeof(int8u ) );
+
+ dy :=1;
+ dist:=m_dist[dy ] - s1;
+
+ while dist <= m_width do
+ begin
+ dec(dist_end ,m_di.dx_end );
+
+ p1^:=0;
+
+ if dist_end > 0 then
+ begin
+ p1^:=int8u(m_ren.cover(dist ) );
+
+ inc(npix );
+
+ end;
+
+ inc(ptrcomp(p1 ) ,sizeof(int8u ) );
+ inc(dy );
+
+ dist:=m_dist[dy ] - s1;
+
+ end;
+
+ dy :=1;
+ dist_end:=m_di.dist_end;
+ dist :=m_dist[dy ] + s1;
+
+ while dist <= m_width do
+ begin
+ inc(dist_end ,m_di.dx_end );
+ dec(ptrcomp(p0 ) ,sizeof(int8u ) );
+
+ p0^:=0;
+
+ if dist_end > 0 then
+ begin
+ p0^:=int8u(m_ren.cover(dist ) );
+
+ inc(npix );
+
+ end;
+
+ inc(dy );
+
+ dist:=m_dist[dy ] + s1;
+
+ end;
+
+ m_ren.blend_solid_vspan(
+ m_x ,m_y - dy + 1 ,
+ unsigned((ptrcomp(p1 ) - ptrcomp(p0 ) ) div sizeof(int8u ) ) ,
+ p0 );
+
+ inc(m_step );
+
+ result:=
+ (npix <> 0 ) and
+ (m_step < m_count );
+
+end;
+
+{ STEP_VER }
+function line_interpolator_aa2.step_ver;
+var
+ dist_end ,dist ,dx ,s1 ,npix : int;
+
+ p0 ,p1 : int8u_ptr;
+
+begin
+ s1:=step_ver_base(@m_di );
+ p0:=int8u_ptr(ptrcomp(@m_covers[0 ] ) + (max_half_width + 2 ) * sizeof(int8u ) );
+ p1:=p0;
+
+ dist_end:=m_di.dist_end;
+
+ npix:=0;
+ p1^ :=0;
+
+ if dist_end > 0 then
+ begin
+ p1^:=int8u(m_ren.cover(s1 ) );
+
+ inc(npix );
+
+ end;
+
+ inc(ptrcomp(p1 ) ,sizeof(int8u ) );
+
+ dx :=1;
+ dist:=m_dist[dx ] - s1;
+
+ while dist <= m_width do
+ begin
+ inc(dist_end ,m_di.dy_end );
+
+ p1^:=0;
+
+ if dist_end > 0 then
+ begin
+ p1^:=int8u(m_ren.cover(dist ) );
+
+ inc(npix );
+
+ end;
+
+ inc(ptrcomp(p1 ) ,sizeof(int8u ) );
+ inc(dx );
+
+ dist:=m_dist[dx ] - s1;
+
+ end;
+
+ dx :=1;
+ dist_end:=m_di.dist_end;
+ dist :=m_dist[dx ] + s1;
+
+ while dist <= m_width do
+ begin
+ dec(dist_end ,m_di.dy_end );
+ dec(ptrcomp(p0 ) ,sizeof(int8u ) );
+
+ p0^:=0;
+
+ if dist_end > 0 then
+ begin
+ p0^:=int8u(m_ren.cover(dist ) );
+
+ inc(npix );
+
+ end;
+
+ inc(dx );
+
+ dist:=m_dist[dx ] + s1;
+
+ end;
+
+ m_ren.blend_solid_hspan(
+ m_x - dx + 1 ,m_y ,
+ unsigned((ptrcomp(p1 ) - ptrcomp(p0 ) ) div sizeof(int8u ) ) ,
+ p0 );
+
+ inc(m_step );
+
+ result:=
+ (npix <> 0 ) and
+ (m_step < m_count );
+
+end;
+
+{ CONSTRUCT }
+constructor line_interpolator_aa3.Construct;
+var
+ dist1_start ,dist2_start ,npix ,dx ,dy : int;
+
+begin
+ inherited Construct(ren ,lp );
+
+ m_di.Construct(
+ lp.x1 ,lp.y1 ,lp.x2 ,lp.y2 ,sx ,sy ,ex ,ey ,
+ lp.x1 and not line_subpixel_mask ,
+ lp.y1 and not line_subpixel_mask );
+
+ npix:=1;
+
+ if lp.vertical then
+ repeat
+ m_li.minus_operator;
+
+ dec(m_y ,lp.inc_ );
+
+ m_x:=shr_int32(m_lp.x1 + m_li._y ,line_subpixel_shift );
+
+ if lp.inc_ > 0 then
+ m_di.dec_y(m_x - m_old_x )
+ else
+ m_di.inc_y(m_x - m_old_x );
+
+ m_old_x:=m_x;
+
+ dist1_start:=m_di.dist_start;
+ dist2_start:=dist1_start;
+
+ dx:=0;
+
+ if dist1_start < 0 then
+ inc(npix );
+
+ repeat
+ inc(dist1_start ,m_di.dy_start );
+ dec(dist2_start ,m_di.dy_start );
+
+ if dist1_start < 0 then
+ inc(npix );
+
+ if dist2_start < 0 then
+ inc(npix );
+
+ inc(dx );
+
+ until m_dist[dx ] > m_width;
+
+ if npix = 0 then
+ break;
+
+ npix:=0;
+
+ dec(m_step );
+
+ until m_step < -m_max_extent
+ else
+ repeat
+ m_li.minus_operator;
+
+ dec(m_x ,lp.inc_ );
+
+ m_y:=shr_int32(m_lp.y1 + m_li._y ,line_subpixel_shift );
+
+ if lp.inc_ > 0 then
+ m_di.dec_x(m_y - m_old_y )
+ else
+ m_di.inc_x(m_y - m_old_y );
+
+ m_old_y:=m_y;
+
+ dist1_start:=m_di.dist_start;
+ dist2_start:=dist1_start;
+
+ dy:=0;
+
+ if dist1_start < 0 then
+ inc(npix );
+
+ repeat
+ dec(dist1_start ,m_di.dx_start );
+ inc(dist2_start ,m_di.dx_start );
+
+ if dist1_start < 0 then
+ inc(npix );
+
+ if dist2_start < 0 then
+ inc(npix );
+
+ inc(dy );
+
+ until m_dist[dy ] > m_width;
+
+ if npix = 0 then
+ break;
+
+ npix:=0;
+
+ dec(m_step );
+
+ until m_step < -m_max_extent;
+
+ m_li.adjust_forward;
+
+ dec(m_step ,m_max_extent );
+
+end;
+
+{ STEP_HOR }
+function line_interpolator_aa3.step_hor;
+var
+ dist_start ,dist_end ,dist ,dy ,s1 ,npix : int;
+
+ p0 ,p1 : int8u_ptr;
+
+begin
+ s1:=step_hor_base(@m_di );
+ p0:=int8u_ptr(ptrcomp(@m_covers[0 ] ) + (max_half_width + 2 ) * sizeof(int8u ) );
+ p1:=p0;
+
+ dist_start:=m_di.dist_start;
+ dist_end :=m_di.dist_end;
+
+ npix:=0;
+ p1^ :=0;
+
+ if dist_end > 0 then
+ begin
+ if dist_start <= 0 then
+ p1^:=int8u(m_ren.cover(s1 ) );
+
+ inc(npix );
+
+ end;
+
+ inc(ptrcomp(p1 ) ,sizeof(int8u ) );
+
+ dy :=1;
+ dist:=m_dist[dy ] - s1;
+
+ while dist <= m_width do
+ begin
+ dec(dist_start ,m_di.dx_start );
+ dec(dist_end ,m_di.dx_end );
+
+ p1^:=0;
+
+ if (dist_end > 0 ) and
+ (dist_start <= 0 ) then
+ begin
+ p1^:=int8u(m_ren.cover(dist ) );
+
+ inc(npix );
+
+ end;
+
+ inc(ptrcomp(p1 ) ,sizeof(int8u ) );
+ inc(dy );
+
+ dist:=m_dist[dy ] - s1;
+
+ end;
+
+ dy :=1;
+ dist_start:=m_di.dist_start;
+ dist_end :=m_di.dist_end;
+ dist :=m_dist[dy ] + s1;
+
+ while dist <= m_width do
+ begin
+ inc(dist_start ,m_di.dx_start );
+ inc(dist_end ,m_di.dx_end );
+ dec(ptrcomp(p0 ) ,sizeof(int8u ) );
+
+ p0^:=0;
+
+ if (dist_end > 0 ) and
+ (dist_start <= 0 ) then
+ begin
+ p0^:=int8u(m_ren.cover(dist ) );
+
+ inc(npix );
+
+ end;
+
+ inc(dy );
+
+ dist:=m_dist[dy ] + s1;
+
+ end;
+
+ m_ren.blend_solid_vspan(
+ m_x ,m_y - dy + 1 ,
+ unsigned((ptrcomp(p1 ) - ptrcomp(p0 ) ) div sizeof(int8u ) ) ,
+ p0 );
+
+ inc(m_step );
+
+ result:=
+ (npix <> 0 ) and
+ (m_step < m_count );
+
+end;
+
+{ STEP_VER }
+function line_interpolator_aa3.step_ver;
+var
+ dist_start ,dist_end ,dist ,dx ,s1 ,npix : int;
+
+ p0 ,p1 : int8u_ptr;
+
+begin
+ s1:=step_ver_base(@m_di );
+ p0:=int8u_ptr(ptrcomp(@m_covers[0 ] ) + (max_half_width + 2 ) * sizeof(int8u ) );
+ p1:=p0;
+
+ dist_start:=m_di.dist_start;
+ dist_end :=m_di.dist_end;
+
+ npix:=0;
+ p1^ :=0;
+
+ if dist_end > 0 then
+ begin
+ if dist_start <= 0 then
+ p1^:=int8u(m_ren.cover(s1 ) );
+
+ inc(npix );
+
+ end;
+
+ inc(ptrcomp(p1 ) ,sizeof(int8u ) );
+
+ dx :=1;
+ dist:=m_dist[dx ] - s1;
+
+ while dist <= m_width do
+ begin
+ inc(dist_start ,m_di.dy_start );
+ inc(dist_end ,m_di.dy_end );
+
+ p1^:=0;
+
+ if (dist_end > 0 ) and
+ (dist_start <= 0 ) then
+ begin
+ p1^:=int8u(m_ren.cover(dist ) );
+
+ inc(npix );
+
+ end;
+
+ inc(ptrcomp(p1 ) ,sizeof(int8u ) );
+ inc(dx );
+
+ dist:=m_dist[dx ] - s1;
+
+ end;
+
+ dx :=1;
+ dist_start:=m_di.dist_start;
+ dist_end :=m_di.dist_end;
+ dist :=m_dist[dx ] + s1;
+
+ while dist <= m_width do
+ begin
+ dec(dist_start ,m_di.dy_start );
+ dec(dist_end ,m_di.dy_end );
+ dec(ptrcomp(p0 ) ,sizeof(int8u ) );
+
+ p0^:=0;
+
+ if (dist_end > 0 ) and
+ (dist_start <= 0 ) then
+ begin
+ p0^:=int8u(m_ren.cover(dist ) );
+
+ inc(npix );
+
+ end;
+
+ inc(dx );
+
+ dist:=m_dist[dx ] + s1;
+
+ end;
+
+ m_ren.blend_solid_hspan(
+ m_x - dx + 1 ,m_y ,
+ unsigned((ptrcomp(p1 ) - ptrcomp(p0 ) ) div sizeof(int8u ) ) ,
+ p0 );
+
+ inc(m_step );
+
+ result:=
+ (npix <> 0 ) and
+ (m_step < m_count );
+
+end;
+
+{ CONSTRUCT }
+constructor line_profile_aa.Construct;
+var
+ i : int;
+
+begin
+ m_size :=0;
+ m_profile:=0;
+
+ m_subpixel_width:=0;
+ m_min_width :=1.0;
+ m_smoother_width:=1.0;
+
+ for i:=0 to aa_num - 1 do
+ m_gamma[i ]:=int8u(i );
+
+end;
+
+{ CONSTRUCT }
+constructor line_profile_aa.Construct(w : double; gamma_function : vertex_source_ptr );
+begin
+ m_size :=0;
+ m_profile:=0;
+
+ m_subpixel_width:=0;
+ m_min_width :=1.0;
+ m_smoother_width:=1.0;
+
+ gamma_(gamma_function );
+ width_(w );
+
+end;
+
+{ DESTRUCT }
+destructor line_profile_aa.Destruct;
+begin
+ agg_freemem(pointer(m_profile ) ,m_size * sizeof(int8u ) );
+
+end;
+
+{ MIN_WIDTH_ }
+procedure line_profile_aa.min_width_;
+begin
+ m_min_width:=w;
+
+end;
+
+{ SMOOTHER_WIDTH_ }
+procedure line_profile_aa.smoother_width_;
+begin
+ m_smoother_width:=w;
+
+end;
+
+{ GAMMA_ }
+procedure line_profile_aa.gamma_;
+var
+ i : int;
+
+begin
+ for i:=0 to aa_num - 1 do
+ m_gamma[i ]:=int8u(trunc(gamma_function.func_operator_gamma(i / aa_mask ) * aa_mask + 0.5 ) );
+
+end;
+
+{ WIDTH_ }
+procedure line_profile_aa.width_;
+var
+ s : double;
+
+begin
+ if w < 0.0 then
+ w:=0.0;
+
+ if w < m_smoother_width then
+ w:=w + w
+ else
+ w:=w + m_smoother_width;
+
+ w:=w * 0.5;
+ w:=w - m_smoother_width;
+ s:=m_smoother_width;
+
+ if w < 0.0 then
+ begin
+ s:=s + w;
+ w:=0.0;
+
+ end;
+
+ set_(w ,s );
+
+end;
+
+{ _PROFILE_SIZE }
+function line_profile_aa._profile_size;
+begin
+ result:=m_size;
+
+end;
+
+{ _SUBPIXEL_WIDTH }
+function line_profile_aa._subpixel_width;
+begin
+ result:=m_subpixel_width;
+
+end;
+
+{ _MIN_WIDTH }
+function line_profile_aa._min_width;
+begin
+ result:=m_min_width;
+
+end;
+
+{ _SMOOTHER_WIDTH }
+function line_profile_aa._smoother_width;
+begin
+ result:=m_smoother_width;
+
+end;
+
+{ VALUE }
+function line_profile_aa.value;
+begin
+ result:=
+ int8u_ptr(
+ ptrcomp(m_profile ) + (dist + subpixel_size * 2 ) * sizeof(int8u ) )^;
+
+end;
+
+{ PROFILE }
+function line_profile_aa.profile;
+var
+ size : unsigned;
+
+begin
+ m_subpixel_width:=trunc(w * subpixel_size );
+
+ size:=m_subpixel_width + subpixel_size * 6;
+
+ if size > m_size then
+ begin
+ agg_freemem(pointer(m_profile ) ,m_size * sizeof(int8u ) );
+ agg_getmem (pointer(m_profile ) ,size * sizeof(int8u ) );
+
+ m_size:=size;
+
+ end;
+
+ result:=m_profile;
+
+end;
+
+{ SET_ }
+procedure line_profile_aa.set_;
+var
+ base_val ,width ,k : double;
+
+ subpixel_center_width ,subpixel_smoother_width ,i ,val ,n_smoother : unsigned;
+
+ ch ,ch_center ,ch_smoother : int8u_ptr;
+
+begin
+ base_val:=1.0;
+
+ if center_width = 0.0 then
+ center_width:=1.0 / subpixel_size;
+
+ if smoother_width = 0.0 then
+ smoother_width:=1.0 / subpixel_size;
+
+ width:=center_width + smoother_width;
+
+ if width < m_min_width then
+ begin
+ k:=width / m_min_width;
+
+ base_val :=base_val * k;
+ center_width :=center_width / k;
+ smoother_width:=smoother_width / k;
+
+ end;
+
+ ch:=profile(center_width + smoother_width );
+
+ subpixel_center_width :=trunc(center_width * subpixel_size);
+ subpixel_smoother_width:=trunc(smoother_width * subpixel_size);
+
+ ch_center :=int8u_ptr(ptrcomp(ch ) + subpixel_size * 2 * sizeof(int8u ) );
+ ch_smoother:=int8u_ptr(ptrcomp(ch_center ) + subpixel_center_width * sizeof(int8u ) );
+
+ val:=m_gamma[trunc(base_val * aa_mask ) ];
+
+ ch:=ch_center;
+
+ i:=0;
+
+ while i < subpixel_center_width do
+ begin
+ ch^:=int8u(val );
+
+ inc(ptrcomp(ch ) ,sizeof(int8u ) );
+ inc(i );
+
+ end;
+
+ i:=0;
+
+ while i < subpixel_smoother_width do
+ begin
+ ch_smoother^:=
+ m_gamma[
+ trunc(
+ (base_val - base_val * (i / subpixel_smoother_width ) ) * aa_mask ) ];
+
+ inc(ptrcomp(ch_smoother ) ,sizeof(int8u ) );
+ inc(i );
+
+ end;
+
+ n_smoother:=
+ _profile_size -
+ subpixel_smoother_width -
+ subpixel_center_width -
+ subpixel_size * 2;
+
+ val:=m_gamma[0 ];
+
+ for i:=0 to n_smoother - 1 do
+ begin
+ ch_smoother^:=int8u(val );
+
+ inc(ptrcomp(ch_smoother ) ,sizeof(int8u ) );
+
+ end;
+
+ ch:=ch_center;
+
+ for i:=0 to subpixel_size * 2 - 1 do
+ begin
+ ch^:=ch_center^;
+
+ dec(ptrcomp(ch ) ,sizeof(int8u ) );
+ inc(ptrcomp(ch_center ) ,sizeof(int8u ) );
+
+ end;
+
+end;
+
+{ CONSTRUCT }
+constructor renderer_outline_aa.Construct;
+begin
+ m_ren :=ren;
+ m_profile:=prof;
+
+ m_color.Construct;
+
+end;
+
+{ COLOR_ }
+procedure renderer_outline_aa.color_;
+begin
+ m_color:=c^;
+
+end;
+
+{ _COLOR }
+function renderer_outline_aa._color;
+begin
+ result:=@m_color;
+
+end;
+
+{ PROFILE_ }
+procedure renderer_outline_aa.profile_;
+begin
+ m_profile:=prof;
+
+end;
+
+{ _PROFILE }
+function renderer_outline_aa._profile;
+begin
+ result:=m_profile;
+
+end;
+
+{ SUBPIXEL_WIDTH }
+function renderer_outline_aa.subpixel_width;
+begin
+ result:=m_profile._subpixel_width;
+
+end;
+
+{ COVER }
+function renderer_outline_aa.cover;
+begin
+ result:=int8u(m_profile.value(d ) );
+
+end;
+
+{ BLEND_SOLID_HSPAN }
+procedure renderer_outline_aa.blend_solid_hspan;
+begin
+ m_ren.blend_solid_hspan(x ,y ,len ,@m_color ,covers );
+
+end;
+
+{ BLEND_SOLID_VSPAN }
+procedure renderer_outline_aa.blend_solid_vspan;
+begin
+ m_ren.blend_solid_vspan(x ,y ,len ,@m_color ,covers );
+
+end;
+
+{ ACCURATE_JOIN_ONLY }
+function renderer_outline_aa.accurate_join_only;
+begin
+ result:=false;
+
+end;
+
+{ SEMIDOT_HLINE }
+procedure renderer_outline_aa.semidot_hline;
+var
+ covers : array[0..max_half_width * 2 + 4 - 1 ] of int8u;
+ p0 ,p1 : int8u_ptr;
+
+ x ,y ,w ,x0 ,dx ,dy ,d : int;
+
+ di : distance_interpolator0;
+
+begin
+ p0:=@covers[0 ];
+ p1:=@covers[0 ];
+
+ x:=x1 shl line_subpixel_shift;
+ y:=y1 shl line_subpixel_shift;
+ w:=subpixel_width;
+
+ di.Construct(xc1 ,yc1 ,xc2 ,yc2 ,x ,y );
+
+ inc(x ,line_subpixel_size div 2 );
+ inc(y ,line_subpixel_size div 2 );
+
+ x0:=x1;
+ dx:=x - xc1;
+ dy:=y - yc1;
+
+ repeat
+ d:=trunc(fast_sqrt(dx * dx + dy * dy ) );
+
+ p1^:=0;
+
+ if cmp(di.dist ) and
+ (d <= w ) then
+ p1^:=int8u(cover(d ) );
+
+ inc(ptrcomp(p1 ) ,sizeof(int8u ) );
+ inc(dx ,line_subpixel_size );
+
+ di.inc_x_;
+
+ inc(x1 );
+
+ until x1 > x2;
+
+ m_ren.blend_solid_hspan(
+ x0 ,y1 ,
+ unsigned((ptrcomp(p1 ) - ptrcomp(p0 ) ) div sizeof(int8u ) ) ,
+ _color ,p0 );
+
+end;
+
+{ SEMIDOT }
+procedure renderer_outline_aa.semidot;
+var
+ r ,dx ,dy ,dy0 ,dx0 ,x ,y : int;
+
+ ei : ellipse_bresenham_interpolator;
+
+begin
+ r:=shr_int32(subpixel_width + line_subpixel_mask ,line_subpixel_shift);
+
+ if r < 1 then
+ r:=1;
+
+ ei.Construct(r ,r );
+
+ dx :=0;
+ dy :=-r;
+ dy0:=dy;
+ dx0:=dx;
+ x :=shr_int32(xc1 ,line_subpixel_shift );
+ y :=shr_int32(yc1 ,line_subpixel_shift );
+
+ repeat
+ inc(dx ,ei._dx );
+ inc(dy ,ei._dy );
+
+ if dy <> dy0 then
+ begin
+ semidot_hline(cmp ,xc1 ,yc1 ,xc2 ,yc2 ,x - dx0 ,y + dy0 ,x + dx0 );
+ semidot_hline(cmp ,xc1 ,yc1 ,xc2 ,yc2 ,x - dx0 ,y - dy0 ,x + dx0 );
+
+ end;
+
+ dx0:=dx;
+ dy0:=dy;
+
+ ei.inc_operator;
+
+ until dy >= 0;
+
+ semidot_hline(cmp ,xc1 ,yc1 ,xc2 ,yc2 ,x - dx0 ,y + dy0 ,x + dx0 );
+
+end;
+
+{ LINE0 }
+procedure renderer_outline_aa.line0;
+var
+ li : line_interpolator_aa0;
+
+begin
+ li.Construct(@self ,lp );
+
+ if li.count <> 0 then
+ if li.vertical then
+ while li.step_ver do
+ else
+ while li.step_hor do;
+
+end;
+
+{ LINE1 }
+procedure renderer_outline_aa.line1;
+var
+ li : line_interpolator_aa1;
+
+begin
+ fix_degenerate_bisectrix_start(lp ,@sx ,@sy );
+
+ li.Construct(@self ,lp ,sx ,sy );
+
+ if li.vertical then
+ while li.step_ver do
+ else
+ while li.step_hor do;
+
+end;
+
+{ LINE2 }
+procedure renderer_outline_aa.line2;
+var
+ li : line_interpolator_aa2;
+
+begin
+ fix_degenerate_bisectrix_end(lp ,@ex ,@ey );
+
+ li.Construct(@self ,lp ,ex ,ey );
+
+ if li.vertical then
+ while li.step_ver do
+ else
+ while li.step_hor do;
+
+end;
+
+{ LINE3 }
+procedure renderer_outline_aa.line3;
+var
+ li : line_interpolator_aa3;
+
+begin
+ fix_degenerate_bisectrix_start(lp ,@sx ,@sy );
+ fix_degenerate_bisectrix_end (lp ,@ex ,@ey );
+
+ li.Construct(@self ,lp ,sx ,sy ,ex ,ey );
+
+ if li.vertical then
+ while li.step_ver do
+ else
+ while li.step_hor do;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_renderer_outline_image.pas b/src/corelib/render/software/agg_renderer_outline_image.pas
new file mode 100644
index 00000000..20f7ff00
--- /dev/null
+++ b/src/corelib/render/software/agg_renderer_outline_image.pas
@@ -0,0 +1,1453 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 03.02.2006-Milano: Complete unit port
+// 02.02.2006-Milano: Unit port establishment
+//
+{ agg_renderer_outline_image.pas }
+unit
+ agg_renderer_outline_image ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+{$Q- }
+{$R- }
+
+uses
+ Math ,
+ agg_basics ,
+ agg_color ,
+ agg_line_aa_basics ,
+ agg_dda_line ,
+ agg_rendering_buffer ,
+ agg_renderer_base ,
+ agg_renderer_outline_aa ,
+ agg_pattern_filters_rgba ;
+
+{ TYPES DEFINITION }
+type
+ pixel_source_ptr = ^pixel_source;
+ pixel_source = object
+ function _width : unsigned; virtual; abstract;
+ function _height : unsigned; virtual; abstract;
+
+ function _width_d : double; virtual;
+ function _height_d : double; virtual;
+
+ function pixel(x ,y : int ) : rgba8; virtual; abstract;
+
+ end;
+
+ line_image_scale = object(pixel_source )
+ m_source : pixel_source_ptr;
+ m_height ,
+ m_scale : double;
+
+ constructor Construct(src : pixel_source_ptr; height_ : double );
+
+ function _width_d : double; virtual;
+ function _height_d : double; virtual;
+
+ function pixel(x ,y : int ) : rgba8; virtual;
+
+ end;
+
+ line_image_pattern_ptr = ^line_image_pattern;
+ line_image_pattern = object
+ m_buf : rendering_buffer;
+ m_filter : pattern_filter_ptr;
+
+ m_dilation : unsigned;
+ m_dilation_hr : int;
+
+ m_data : aggclr_ptr;
+ m_dt_sz ,
+ m_width ,
+ m_height : unsigned;
+
+ m_width_hr ,
+ m_half_height_hr ,
+ m_offset_y_hr : int;
+
+ constructor Construct(filter_ : pattern_filter_ptr ); overload;
+ constructor Construct(filter_ : pattern_filter_ptr; src : pixel_source_ptr ); overload;
+ destructor Destruct;
+
+ procedure create(src : pixel_source_ptr ); virtual;
+
+ function pattern_width : int;
+ function line_width : int;
+
+ procedure pixel(p : aggclr_ptr; x ,y : int ); virtual;
+
+ procedure filter(filter_ : pattern_filter_ptr ); overload;
+ function filter : pattern_filter_ptr; overload;
+
+ end;
+
+ line_image_pattern_pow2 = object(line_image_pattern )
+ m_mask : unsigned;
+
+ constructor Construct(filter_ : pattern_filter_ptr ); overload;
+ constructor Construct(filter_ : pattern_filter_ptr; src : pixel_source_ptr ); overload;
+
+ procedure create(src : pixel_source_ptr ); virtual;
+ procedure pixel (p : aggclr_ptr; x ,y : int ); virtual;
+
+ end;
+
+ distance_interpolator4 = object(distance_interpolator )
+ m_dx ,
+ m_dy ,
+
+ m_dx_start ,
+ m_dy_start ,
+ m_dx_pict ,
+ m_dy_pict ,
+ m_dx_end ,
+ m_dy_end ,
+
+ m_dist ,
+ m_dist_start ,
+ m_dist_pict ,
+ m_dist_end ,
+
+ m_len : int;
+
+ constructor Construct; overload;
+ constructor Construct(x1 ,y1 ,x2 ,y2 ,sx ,sy ,ex ,ey ,len_ : int; scale : double; x ,y : int ); overload;
+
+ procedure inc_x_; virtual;
+ procedure dec_x_; virtual;
+ procedure inc_y_; virtual;
+ procedure dec_y_; virtual;
+
+ procedure inc_x(dy_ : int ); virtual;
+ procedure dec_x(dy_ : int ); virtual;
+ procedure inc_y(dx_ : int ); virtual;
+ procedure dec_y(dx_ : int ); virtual;
+
+ function dist : int; virtual;
+ function dist_start : int; virtual;
+ function dist_pict : int;
+ function dist_end : int; virtual;
+
+ function dx : int; virtual;
+ function dy : int; virtual;
+ function dx_start : int; virtual;
+ function dy_start : int; virtual;
+ function dx_pict : int;
+ function dy_pict : int;
+ function dx_end : int; virtual;
+ function dy_end : int; virtual;
+ function len : int;
+
+ end;
+
+ renderer_outline_image_ptr = ^renderer_outline_image;
+
+ line_interpolator_image = object //(line_interpolator )
+ m_lp : line_parameters_ptr;
+ m_li : dda2_line_interpolator;
+ m_di : distance_interpolator4;
+ m_ren : renderer_outline_image_ptr;
+
+ m_plen ,
+ m_x ,
+ m_y ,
+
+ m_old_x ,
+ m_old_y ,
+ m_count ,
+ m_width ,
+
+ m_max_extent ,
+
+ m_start ,
+ m_step : int;
+
+ m_dist_pos : array[0..max_half_width + 1 - 1 ] of int;
+ m_colors : array[0..max_half_width * 2 + 4 - 1 ] of aggclr;
+
+ constructor Construct(
+ ren : renderer_outline_image_ptr;
+ lp : line_parameters_ptr;
+ sx ,sy ,ex ,ey ,pattern_start : int;
+ scale_x : double );
+
+ function step_hor : boolean;
+ function step_ver : boolean;
+
+ function pattern_end : int;
+ function vertical : boolean;
+ function width : int;
+ function count : int;
+
+ end;
+
+ renderer_outline_image = object(renderer_outline )
+ m_ren : renderer_base_ptr;
+ m_pattern : line_image_pattern_ptr;
+ m_start : int;
+ m_scale_x : double;
+
+ constructor Construct(ren : renderer_base_ptr; patt : line_image_pattern_ptr );
+
+ procedure pattern_(p : line_image_pattern_ptr );
+ function _pattern : line_image_pattern_ptr;
+
+ procedure scale_x_(s : double );
+ function _scale_x : double;
+
+ procedure start_x_(s : double );
+ function _start_x : double;
+
+ function subpixel_width : int; virtual;
+ function _pattern_width : int;
+
+ procedure pixel(p : aggclr_ptr; x ,y : int );
+
+ procedure blend_color_hspan(x ,y : int; len : unsigned; colors : aggclr_ptr );
+ procedure blend_color_vspan(x ,y : int; len : unsigned; colors : aggclr_ptr );
+
+ function accurate_join_only : boolean; virtual;
+
+ procedure semidot(cmp : cmp_function; xc1 ,yc1 ,xc2 ,yc2 : int ); virtual;
+
+ procedure line0(lp : line_parameters_ptr ); virtual;
+ procedure line1(lp : line_parameters_ptr; sx ,sy : int ); virtual;
+ procedure line2(lp : line_parameters_ptr; ex ,ey : int ); virtual;
+ procedure line3(lp : line_parameters_ptr; sx ,sy ,ex ,ey : int ); virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ _WIDTH_D }
+function pixel_source._width_d;
+begin
+ result:=_width;
+
+end;
+
+{ _HEIGHT_D }
+function pixel_source._height_d;
+begin
+ result:=_height;
+
+end;
+
+{ CONSTRUCT }
+constructor line_image_scale.Construct;
+begin
+ m_source:=src;
+ m_height:=height_;
+
+ if height_ <> 0 then
+ m_scale:=src._height / height_
+ else
+ m_scale:=0;
+
+end;
+
+{ _WIDTH_D }
+function line_image_scale._width_d;
+begin
+ result:=m_source._width;
+
+end;
+
+{ _HEIGHT_D }
+function line_image_scale._height_d;
+begin
+ result:=m_height;
+
+end;
+
+{ PIXEL }
+function line_image_scale.pixel;
+var
+ src_y : double;
+
+ h ,y1 ,y2 : int;
+
+ pix1 ,pix2 : aggclr;
+
+begin
+ src_y:=(y + 0.5 ) * m_scale - 0.5;
+
+ h :=trunc(m_source._height ) - 1;
+ y1:=trunc(src_y );
+ y2:=y1 + 1;
+
+ if y1 < 0 then
+ pix1.Construct
+ else
+ pix1.Construct(m_source.pixel(x ,y1 ) );
+
+ if y2 > h then
+ pix2.Construct
+ else
+ pix2.Construct(m_source.pixel(x ,y2 ) );
+
+ result:=pix1.gradient8(@pix2 ,src_y - y1 );
+
+end;
+
+{ CONSTRUCT }
+constructor line_image_pattern.Construct(filter_ : pattern_filter_ptr );
+begin
+ m_buf.Construct;
+
+ m_filter:=filter_;
+
+ m_dilation :=filter_.dilation + 1;
+ m_dilation_hr:=m_dilation shl line_subpixel_shift;
+
+ m_data :=0;
+ m_dt_sz :=0;
+ m_width :=0;
+ m_height:=0;
+
+ m_width_hr :=0;
+ m_half_height_hr:=0;
+ m_offset_y_hr :=0;
+
+end;
+
+{ CONSTRUCT }
+constructor line_image_pattern.Construct(filter_ : pattern_filter_ptr; src : pixel_source_ptr );
+begin
+ m_buf.Construct;
+
+ m_filter:=filter_;
+
+ m_dilation :=filter_.dilation + 1;
+ m_dilation_hr:=m_dilation shl line_subpixel_shift;
+
+ m_data :=0;
+ m_dt_sz :=0;
+ m_width :=0;
+ m_height:=0;
+
+ m_width_hr :=0;
+ m_half_height_hr:=0;
+ m_offset_y_hr :=0;
+
+ create(src );
+
+end;
+
+{ DESTRUCT }
+destructor line_image_pattern.Destruct;
+begin
+ agg_freemem(pointer(m_data ) ,m_dt_sz );
+
+ m_buf.Destruct;
+
+end;
+
+{ CREATE }
+procedure line_image_pattern.create;
+var
+ x ,y ,h : unsigned;
+
+ d1 ,d2 ,s1 ,s2 : rgba8_ptr;
+
+begin
+ m_height:=Ceil(src._height_d );
+ m_width :=Ceil(src._width_d );
+
+ m_width_hr :=trunc(src._width_d * line_subpixel_size );
+ m_half_height_hr:=trunc(src._height_d * line_subpixel_size / 2 );
+ m_offset_y_hr :=m_dilation_hr + m_half_height_hr - line_subpixel_size div 2;
+
+ inc(m_half_height_hr ,line_subpixel_size div 2 );
+
+ agg_freemem(pointer(m_data ) ,m_dt_sz );
+
+ m_dt_sz:=(m_width + m_dilation * 2 ) * (m_height + m_dilation * 2 ) * sizeof(rgba8 );
+
+ agg_getmem(pointer(m_data ) ,m_dt_sz );
+
+ m_buf.attach(
+ int8u_ptr(m_data ) ,
+ m_width + m_dilation * 2 ,
+ m_height + m_dilation * 2 ,
+ (m_width + m_dilation * 2 ) * sizeof(rgba8 ) );
+
+ if m_height > 0 then
+ for y:=0 to m_height - 1 do
+ begin
+ d1:=rgba8_ptr(ptrcomp(m_buf.row(y + m_dilation ) ) + m_dilation * sizeof(rgba8 ) );
+
+ for x:=0 to m_width - 1 do
+ begin
+ d1^:=src.pixel(x ,y );
+
+ inc(ptrcomp(d1 ) ,sizeof(rgba8 ) );
+
+ end;
+
+ end;
+
+ for y:=0 to m_dilation - 1 do
+ begin
+ d1:=rgba8_ptr(ptrcomp(m_buf.row(m_dilation + m_height + y ) ) + m_dilation * sizeof(rgba8 ) );
+ d2:=rgba8_ptr(ptrcomp(m_buf.row(m_dilation - y - 1 ) ) + m_dilation * sizeof(rgba8 ) );
+
+ for x:=0 to m_width - 1 do
+ begin
+ d1^.no_color;
+ d2^.no_color;
+
+ inc(ptrcomp(d1 ) ,sizeof(rgba8 ) );
+ inc(ptrcomp(d2 ) ,sizeof(rgba8 ) );
+
+ end;
+
+ end;
+
+ h:=m_height + m_dilation * 2;
+
+ for y:=0 to h - 1 do
+ begin
+ s1:=rgba8_ptr(ptrcomp(m_buf.row(y ) ) + m_dilation * sizeof(rgba8 ) );
+ s2:=rgba8_ptr(ptrcomp(m_buf.row(y ) ) + (m_dilation + m_width ) * sizeof(rgba8 ) );
+ d1:=rgba8_ptr(ptrcomp(m_buf.row(y ) ) + (m_dilation + m_width ) * sizeof(rgba8 ) );
+ d2:=rgba8_ptr(ptrcomp(m_buf.row(y ) ) + m_dilation * sizeof(rgba8 ) );
+
+ for x:=0 to m_dilation - 1 do
+ begin
+ d1^:=s1^;
+
+ inc(ptrcomp(d1 ) ,sizeof(rgba8 ) );
+ inc(ptrcomp(s1 ) ,sizeof(rgba8 ) );
+ dec(ptrcomp(d2 ) ,sizeof(rgba8 ) );
+ dec(ptrcomp(s2 ) ,sizeof(rgba8 ) );
+
+ d2^:=s2^;
+
+ end;
+
+ end;
+
+end;
+
+{ PATTERN_WIDTH }
+function line_image_pattern.pattern_width;
+begin
+ result:=m_width_hr;
+
+end;
+
+{ LINE_WIDTH }
+function line_image_pattern.line_width;
+begin
+ result:=m_half_height_hr;
+
+end;
+
+{ PIXEL }
+procedure line_image_pattern.pixel;
+begin
+ m_filter.pixel_high_res(
+ m_buf.rows ,
+ p ,
+ x mod m_width_hr + m_dilation_hr ,
+ y + m_offset_y_hr );
+
+end;
+
+{ FILTER }
+procedure line_image_pattern.filter(filter_ : pattern_filter_ptr );
+begin
+ m_filter:=filter_;
+
+end;
+
+{ FILTER }
+function line_image_pattern.filter : pattern_filter_ptr;
+begin
+ result:=m_filter;
+
+end;
+
+{ CONSTRUCT }
+constructor line_image_pattern_pow2.Construct(filter_ : pattern_filter_ptr );
+begin
+ inherited Construct(filter_ );
+
+ m_mask:=0;
+
+end;
+
+{ CONSTRUCT }
+constructor line_image_pattern_pow2.Construct(filter_ : pattern_filter_ptr; src : pixel_source_ptr );
+begin
+ inherited Construct(filter_ ,src );
+
+ create(src );
+
+end;
+
+{ CREATE }
+procedure line_image_pattern_pow2.create;
+begin
+ inherited create(src );
+
+ m_mask:=1;
+
+ while m_mask < m_width do
+ begin
+ m_mask:=m_mask shl 1;
+ m_mask:=m_mask or 1;
+
+ end;
+
+ m_mask:=m_mask shl (line_subpixel_shift - 1 );
+ m_mask:=m_mask or line_subpixel_mask;
+
+ m_width_hr:=m_mask + 1;
+
+end;
+
+{ PIXEL }
+procedure line_image_pattern_pow2.pixel;
+begin
+ m_filter.pixel_high_res(
+ m_buf.rows ,
+ p ,
+ (x and m_mask ) + m_dilation_hr ,
+ y + m_offset_y_hr );
+
+end;
+
+{ CONSTRUCT }
+constructor distance_interpolator4.Construct;
+begin
+end;
+
+{ CONSTRUCT }
+constructor distance_interpolator4.Construct(x1 ,y1 ,x2 ,y2 ,sx ,sy ,ex ,ey ,len_ : int; scale : double; x ,y : int );
+var
+ d : double;
+
+ dx_ ,dy_ : int;
+
+begin
+ m_dx:=x2 - x1;
+ m_dy:=y2 - y1;
+
+ m_dx_start:=line_mr(sx ) - line_mr(x1 );
+ m_dy_start:=line_mr(sy ) - line_mr(y1 );
+ m_dx_end :=line_mr(ex ) - line_mr(x2 );
+ m_dy_end :=line_mr(ey ) - line_mr(y2 );
+
+ m_dist:=
+ trunc(
+ (x + line_subpixel_size / 2 - x2 ) * m_dy -
+ (y + line_subpixel_size / 2 - y2 ) * m_dx );
+
+ m_dist_start:=
+ (line_mr(x + line_subpixel_size div 2 ) - line_mr(sx ) ) * m_dy_start -
+ (line_mr(y + line_subpixel_size div 2 ) - line_mr(sy ) ) * m_dx_start;
+
+ m_dist_end:=
+ (line_mr(x + line_subpixel_size div 2) - line_mr(ex ) ) * m_dy_end -
+ (line_mr(y + line_subpixel_size div 2) - line_mr(ey ) ) * m_dx_end;
+
+ if scale <> 0 then
+ m_len:=trunc(len_ / scale )
+ else
+ m_len:=0;
+
+ d:=len_ * scale;
+
+ if d <> 0 then
+ begin
+ dx_:=trunc(((x2 - x1 ) shl line_subpixel_shift ) / d );
+ dy_:=trunc(((y2 - y1 ) shl line_subpixel_shift ) / d );
+
+ end
+ else
+ begin
+ dx_:=0;
+ dy_:=0;
+
+ end;
+
+ m_dx_pict:=-dy_;
+ m_dy_pict:=dx_;
+
+ m_dist_pict:=
+ shr_int32(
+ (x + line_subpixel_size div 2 - (x1 - dy_ ) ) * m_dy_pict -
+ (y + line_subpixel_size div 2 - (y1 + dx_ ) ) * m_dx_pict ,line_subpixel_shift );
+
+ m_dx :=m_dx shl line_subpixel_shift;
+ m_dy :=m_dy shl line_subpixel_shift;
+ m_dx_start:=m_dx_start shl line_mr_subpixel_shift;
+ m_dy_start:=m_dy_start shl line_mr_subpixel_shift;
+ m_dx_end :=m_dx_end shl line_mr_subpixel_shift;
+ m_dy_end :=m_dy_end shl line_mr_subpixel_shift;
+
+end;
+
+{ INC_X_ }
+procedure distance_interpolator4.inc_x_;
+begin
+ inc(m_dist ,m_dy );
+ inc(m_dist_start ,m_dy_start );
+ inc(m_dist_pict ,m_dy_pict );
+ inc(m_dist_end ,m_dy_end );
+
+end;
+
+{ DEC_X_ }
+procedure distance_interpolator4.dec_x_;
+begin
+ dec(m_dist ,m_dy );
+ dec(m_dist_start ,m_dy_start );
+ dec(m_dist_pict ,m_dy_pict );
+ dec(m_dist_end ,m_dy_end );
+
+end;
+
+{ INC_Y_ }
+procedure distance_interpolator4.inc_y_;
+begin
+ dec(m_dist ,m_dx );
+ dec(m_dist_start ,m_dx_start );
+ dec(m_dist_pict ,m_dx_pict );
+ dec(m_dist_end ,m_dx_end );
+
+end;
+
+{ DEC_Y_ }
+procedure distance_interpolator4.dec_y_;
+begin
+ inc(m_dist ,m_dx );
+ inc(m_dist_start ,m_dx_start );
+ inc(m_dist_pict ,m_dx_pict );
+ inc(m_dist_end ,m_dx_end );
+
+end;
+
+{ INC_X }
+procedure distance_interpolator4.inc_x;
+begin
+ inc(m_dist ,m_dy );
+ inc(m_dist_start ,m_dy_start );
+ inc(m_dist_pict ,m_dy_pict );
+ inc(m_dist_end ,m_dy_end );
+
+ if dy_ > 0 then
+ begin
+ dec(m_dist ,m_dx );
+ dec(m_dist_start ,m_dx_start );
+ dec(m_dist_pict ,m_dx_pict );
+ dec(m_dist_end ,m_dx_end );
+
+ end;
+
+ if dy_ < 0 then
+ begin
+ inc(m_dist ,m_dx );
+ inc(m_dist_start ,m_dx_start );
+ inc(m_dist_pict ,m_dx_pict );
+ inc(m_dist_end ,m_dx_end );
+
+ end;
+
+end;
+
+{ DEC_X }
+procedure distance_interpolator4.dec_x;
+begin
+ dec(m_dist ,m_dy );
+ dec(m_dist_start ,m_dy_start );
+ dec(m_dist_pict ,m_dy_pict );
+ dec(m_dist_end ,m_dy_end );
+
+ if dy_ > 0 then
+ begin
+ dec(m_dist ,m_dx );
+ dec(m_dist_start ,m_dx_start );
+ dec(m_dist_pict ,m_dx_pict );
+ dec(m_dist_end ,m_dx_end );
+
+ end;
+
+ if dy_ < 0 then
+ begin
+ inc(m_dist ,m_dx );
+ inc(m_dist_start ,m_dx_start );
+ inc(m_dist_pict ,m_dx_pict );
+ inc(m_dist_end ,m_dx_end );
+
+ end;
+
+end;
+
+{ INC_Y }
+procedure distance_interpolator4.inc_y;
+begin
+ dec(m_dist ,m_dx );
+ dec(m_dist_start ,m_dx_start );
+ dec(m_dist_pict ,m_dx_pict );
+ dec(m_dist_end ,m_dx_end );
+
+ if dx_ > 0 then
+ begin
+ inc(m_dist ,m_dy );
+ inc(m_dist_start ,m_dy_start );
+ inc(m_dist_pict ,m_dy_pict );
+ inc(m_dist_end ,m_dy_end );
+
+ end;
+
+ if dx_ < 0 then
+ begin
+ dec(m_dist ,m_dy );
+ dec(m_dist_start ,m_dy_start );
+ dec(m_dist_pict ,m_dy_pict );
+ dec(m_dist_end ,m_dy_end );
+
+ end;
+
+end;
+
+{ DEC_Y }
+procedure distance_interpolator4.dec_y;
+begin
+ inc(m_dist ,m_dx );
+ inc(m_dist_start ,m_dx_start );
+ inc(m_dist_pict ,m_dx_pict );
+ inc(m_dist_end ,m_dx_end );
+
+ if dx_ > 0 then
+ begin
+ inc(m_dist ,m_dy );
+ inc(m_dist_start ,m_dy_start );
+ inc(m_dist_pict ,m_dy_pict );
+ inc(m_dist_end ,m_dy_end );
+
+ end;
+
+ if dx_ < 0 then
+ begin
+ dec(m_dist ,m_dy );
+ dec(m_dist_start ,m_dy_start );
+ dec(m_dist_pict ,m_dy_pict );
+ dec(m_dist_end ,m_dy_end );
+
+ end;
+
+end;
+
+{ DIST }
+function distance_interpolator4.dist;
+begin
+ result:=m_dist;
+
+end;
+
+{ DIST_START }
+function distance_interpolator4.dist_start;
+begin
+ result:=m_dist_start;
+
+end;
+
+{ DIST_PICT }
+function distance_interpolator4.dist_pict;
+begin
+ result:=m_dist_pict;
+
+end;
+
+{ DIST_END }
+function distance_interpolator4.dist_end;
+begin
+ result:=m_dist_end;
+
+end;
+
+{ DX }
+function distance_interpolator4.dx;
+begin
+ result:=m_dx;
+
+end;
+
+{ DY }
+function distance_interpolator4.dy;
+begin
+ result:=m_dy;
+
+end;
+
+{ DX_START }
+function distance_interpolator4.dx_start;
+begin
+ result:=m_dx_start;
+
+end;
+
+{ DY_START }
+function distance_interpolator4.dy_start;
+begin
+ result:=m_dy_start;
+
+end;
+
+{ DX_PICT }
+function distance_interpolator4.dx_pict;
+begin
+ result:=m_dx_pict;
+
+end;
+
+{ DY_PICT }
+function distance_interpolator4.dy_pict;
+begin
+ result:=m_dy_pict;
+
+end;
+
+{ DX_END }
+function distance_interpolator4.dx_end;
+begin
+ result:=m_dx_end;
+
+end;
+
+{ DY_END }
+function distance_interpolator4.dy_end;
+begin
+ result:=m_dy_end;
+
+end;
+
+{ LEN }
+function distance_interpolator4.len;
+begin
+ result:=m_len;
+
+end;
+
+{ CONSTRUCT }
+constructor line_interpolator_image.Construct;
+var
+ i : unsigned;
+
+ stop ,dist1_start ,dist2_start ,npix ,dx ,dy : int;
+
+ li : dda2_line_interpolator;
+
+begin
+ m_lp:=lp;
+
+ if lp.vertical then
+ m_li.Construct(line_dbl_hr(lp.x2 - lp.x1 ) ,Abs(lp.y2 - lp.y1 ) )
+ else
+ m_li.Construct(line_dbl_hr(lp.y2 - lp.y1 ) ,Abs(lp.x2 - lp.x1 ) + 1 );
+
+ m_di.Construct(
+ lp.x1 ,lp.y1 ,lp.x2 ,lp.y2 ,sx ,sy ,ex ,ey ,lp.len ,scale_x ,
+ lp.x1 and not line_subpixel_mask ,
+ lp.y1 and not line_subpixel_mask );
+
+ m_ren:=ren;
+
+ m_x:=shr_int32(lp.x1 ,line_subpixel_shift );
+ m_y:=shr_int32(lp.y1 ,line_subpixel_shift );
+
+ m_old_x:=m_x;
+ m_old_y:=m_y;
+
+ if lp.vertical then
+ m_count:=Abs(shr_int32(lp.y2 ,line_subpixel_shift ) - m_y )
+ else
+ m_count:=Abs(shr_int32(lp.x2 ,line_subpixel_shift ) - m_x );
+
+ m_width :=ren.subpixel_width;
+ m_max_extent:=shr_int32(m_width ,line_subpixel_shift - 2 );
+
+try
+ m_start:=pattern_start + (m_max_extent + 2 ) * ren._pattern_width;
+except
+ m_start:=0 + (m_max_extent + 2 ) * ren._pattern_width;
+
+end;
+
+ m_step :=0;
+
+ if lp.vertical then
+ li.Construct(0 ,lp.dy shl line_subpixel_shift ,lp.len )
+ else
+ li.Construct(0 ,lp.dx shl line_subpixel_shift ,lp.len );
+
+ stop:=m_width + line_subpixel_size * 2;
+ i :=0;
+
+ while i < max_half_width do
+ begin
+ m_dist_pos[i ]:=li._y;
+
+ if m_dist_pos[i ] >= stop then
+ break;
+
+ li.plus_operator;
+
+ inc(i );
+
+ end;
+
+ m_dist_pos[i ]:=$7FFF0000;
+
+ npix:=1;
+
+ if lp.vertical then
+ repeat
+ m_li.minus_operator;
+
+ dec(m_y ,lp.inc_ );
+
+ m_x:=shr_int32(m_lp.x1 + m_li._y ,line_subpixel_shift );
+
+ if lp.inc_ > 0 then
+ m_di.dec_y(m_x - m_old_x )
+ else
+ m_di.inc_y(m_x - m_old_x );
+
+ m_old_x:=m_x;
+
+ dist1_start:=m_di.dist_start;
+ dist2_start:=dist1_start;
+
+ dx:=0;
+
+ if dist1_start < 0 then
+ inc(npix );
+
+ repeat
+ inc(dist1_start ,m_di.dy_start );
+ dec(dist2_start ,m_di.dy_start );
+
+ if dist1_start < 0 then
+ inc(npix );
+
+ if dist2_start < 0 then
+ inc(npix );
+
+ inc(dx );
+
+ until m_dist_pos[dx ] > m_width;
+
+ if npix = 0 then
+ break;
+
+ npix:=0;
+
+ dec(m_step );
+
+ until m_step < -m_max_extent
+ else
+ repeat
+ m_li.minus_operator;
+
+ dec(m_x ,lp.inc_ );
+
+ m_y:=shr_int32(m_lp.y1 + m_li._y ,line_subpixel_shift );
+
+ if lp.inc_ > 0 then
+ m_di.dec_x(m_y - m_old_y )
+ else
+ m_di.inc_x(m_y - m_old_y );
+
+ m_old_y:=m_y;
+
+ dist1_start:=m_di.dist_start;
+ dist2_start:=dist1_start;
+
+ dy:=0;
+
+ if dist1_start < 0 then
+ inc(npix );
+
+ repeat
+ dec(dist1_start ,m_di.dx_start );
+ inc(dist2_start ,m_di.dx_start );
+
+ if dist1_start < 0 then
+ inc(npix );
+
+ if dist2_start < 0 then
+ inc(npix );
+
+ inc(dy );
+
+ until m_dist_pos[dy ] > m_width;
+
+ if npix = 0 then
+ break;
+
+ npix:=0;
+
+ dec(m_step );
+
+ until m_step < -m_max_extent;
+
+ m_li.adjust_forward;
+
+ dec(m_step ,m_max_extent );
+
+end;
+
+{ STEP_HOR }
+function line_interpolator_image.step_hor;
+var
+ s1 ,s2 ,dist_start ,dist_pict ,dist_end ,dy ,dist ,npix : int;
+
+ p0 ,p1 : aggclr_ptr;
+
+begin
+ m_li.plus_operator;
+
+ inc(m_x ,m_lp.inc_ );
+
+ m_y:=shr_int32(m_lp.y1 + m_li._y ,line_subpixel_shift );
+
+ if m_lp.inc_ > 0 then
+ m_di.inc_x(m_y - m_old_y )
+ else
+ m_di.dec_x(m_y - m_old_y );
+
+ m_old_y:=m_y;
+
+ s1:=m_di.dist div m_lp.len;
+ s2:=-s1;
+
+ if m_lp.inc_ < 0 then
+ s1:=-s1;
+
+ dist_start:=m_di.dist_start;
+ dist_pict :=m_di.dist_pict + m_start;
+ dist_end :=m_di.dist_end;
+
+ p0:=aggclr_ptr(ptrcomp(@m_colors[0 ] ) + (max_half_width + 2 ) * sizeof(aggclr ) );
+ p1:=p0;
+
+ npix:=0;
+
+ p1.clear;
+
+ if dist_end > 0 then
+ begin
+ if dist_start <= 0 then
+ m_ren.pixel(p1 ,dist_pict ,s2 );
+
+ inc(npix );
+
+ end;
+
+ inc(ptrcomp(p1 ) ,sizeof(aggclr ) );
+
+ dy :=1;
+ dist:=m_dist_pos[dy ];
+
+ while dist - s1 <= m_width do
+ begin
+ dec(dist_start ,m_di.dx_start );
+ dec(dist_pict ,m_di.dx_pict );
+ dec(dist_end ,m_di.dx_end );
+
+ p1.clear();
+
+ if (dist_end > 0 ) and
+ (dist_start <= 0 ) then
+ begin
+ if m_lp.inc_ > 0 then
+ dist:=-dist;
+
+ m_ren.pixel(p1 ,dist_pict ,s2 - dist );
+
+ inc(npix );
+
+ end;
+
+ inc(ptrcomp(p1 ) ,sizeof(aggclr ) );
+ inc(dy );
+
+ dist:=m_dist_pos[dy ];
+
+ end;
+
+ dy:=1;
+
+ dist_start:=m_di.dist_start;
+ dist_pict :=m_di.dist_pict + m_start;
+ dist_end :=m_di.dist_end;
+
+ dist:=m_dist_pos[dy ];
+
+ while dist + s1 <= m_width do
+ begin
+ inc(dist_start ,m_di.dx_start );
+ inc(dist_pict ,m_di.dx_pict );
+ inc(dist_end ,m_di.dx_end );
+
+ dec(ptrcomp(p0 ) ,sizeof(aggclr ) );
+
+ p0.clear;
+
+ if (dist_end > 0 ) and
+ (dist_start <= 0 ) then
+ begin
+ if m_lp.inc_ > 0 then
+ dist:=-dist;
+
+ m_ren.pixel(p0 ,dist_pict ,s2 + dist );
+
+ inc(npix );
+
+ end;
+
+ inc(dy );
+
+ dist:=m_dist_pos[dy ];
+
+ end;
+
+ m_ren.blend_color_vspan(
+ m_x ,m_y - dy + 1 ,
+ unsigned((ptrcomp(p1 ) - ptrcomp(p0 ) ) div sizeof(aggclr ) ) ,
+ p0 );
+
+ inc(m_step );
+
+ result:=
+ (npix <> 0 ) and
+ (m_step < m_count );
+
+end;
+
+{ STEP_VER }
+function line_interpolator_image.step_ver;
+var
+ s1 ,s2 ,dist_start ,dist_pict ,dist_end ,dx ,dist ,npix : int;
+
+ p0 ,p1 : aggclr_ptr;
+
+begin
+ m_li.plus_operator;
+
+ inc(m_y ,m_lp.inc_ );
+
+ m_x:=shr_int32(m_lp.x1 + m_li._y ,line_subpixel_shift );
+
+ if m_lp.inc_ > 0 then
+ m_di.inc_y(m_x - m_old_x )
+ else
+ m_di.dec_y(m_x - m_old_x );
+
+ m_old_x:=m_x;
+
+ s1:=m_di.dist div m_lp.len;
+ s2:=-s1;
+
+ if m_lp.inc_ > 0 then
+ s1:=-s1;
+
+ dist_start:=m_di.dist_start;
+ dist_pict :=m_di.dist_pict + m_start;
+ dist_end :=m_di.dist_end;
+
+ p0:=aggclr_ptr(ptrcomp(@m_colors[0 ] ) + (max_half_width + 2 ) * sizeof(aggclr ) );
+ p1:=p0;
+
+ npix:=0;
+
+ p1.clear;
+
+ if dist_end > 0 then
+ begin
+ if dist_start <= 0 then
+ m_ren.pixel(p1 ,dist_pict ,s2 );
+
+ inc(npix );
+
+ end;
+
+ inc(ptrcomp(p1 ) ,sizeof(aggclr ) );
+
+ dx :=1;
+ dist:=m_dist_pos[dx ];
+
+ while dist - s1 <= m_width do
+ begin
+ inc(dist_start ,m_di.dy_start );
+ inc(dist_pict ,m_di.dy_pict );
+ inc(dist_end ,m_di.dy_end );
+
+ p1.clear;
+
+ if (dist_end > 0 ) and
+ (dist_start <= 0 ) then
+ begin
+ if m_lp.inc_ > 0 then
+ dist:=-dist;
+
+ m_ren.pixel(p1 ,dist_pict ,s2 + dist );
+
+ inc(npix );
+
+ end;
+
+ inc(ptrcomp(p1 ) ,sizeof(aggclr ) );
+ inc(dx );
+
+ dist:=m_dist_pos[dx ];
+
+ end;
+
+ dx:=1;
+
+ dist_start:=m_di.dist_start;
+ dist_pict :=m_di.dist_pict + m_start;
+ dist_end :=m_di.dist_end;
+
+ dist:=m_dist_pos[dx ];
+
+ while dist + s1 <= m_width do
+ begin
+ dec(dist_start ,m_di.dy_start );
+ dec(dist_pict ,m_di.dy_pict );
+ dec(dist_end ,m_di.dy_end );
+
+ dec(ptrcomp(p0 ) ,sizeof(aggclr ) );
+
+ p0.clear;
+
+ if (dist_end > 0 ) and
+ (dist_start <= 0 ) then
+ begin
+ if m_lp.inc_ > 0 then
+ dist:=-dist;
+
+ m_ren.pixel(p0 ,dist_pict ,s2 - dist );
+
+ inc(npix );
+
+ end;
+
+ inc(dx );
+
+ dist:=m_dist_pos[dx ];
+
+ end;
+
+ m_ren.blend_color_hspan(
+ m_x - dx + 1 ,m_y ,
+ unsigned((ptrcomp(p1 ) - ptrcomp(p0 ) ) div sizeof(aggclr ) ) ,
+ p0 );
+
+ inc(m_step );
+
+ result:=
+ (npix <> 0 ) and
+ (m_step < m_count );
+
+end;
+
+{ PATTERN_END }
+function line_interpolator_image.pattern_end;
+begin
+ result:=m_start + m_di.len;
+
+end;
+
+{ VERTICAL }
+function line_interpolator_image.vertical;
+begin
+ result:=m_lp.vertical;
+
+end;
+
+{ WIDTH }
+function line_interpolator_image.width;
+begin
+ result:=m_width;
+
+end;
+
+{ COUNT }
+function line_interpolator_image.count;
+begin
+ result:=m_count;
+
+end;
+
+{ CONSTRUCT }
+constructor renderer_outline_image.Construct;
+begin
+ m_ren :=ren;
+ m_pattern:=patt;
+ m_start :=0;
+ m_scale_x:=1.0;
+
+end;
+
+{ PATTERN_ }
+procedure renderer_outline_image.pattern_;
+begin
+ m_pattern:=p;
+
+end;
+
+{ _PATTERN }
+function renderer_outline_image._pattern;
+begin
+ result:=m_pattern;
+
+end;
+
+{ SCALE_X_ }
+procedure renderer_outline_image.scale_x_;
+begin
+ m_scale_x:=s;
+
+end;
+
+{ _SCALE_X }
+function renderer_outline_image._scale_x;
+begin
+ result:=m_scale_x;
+
+end;
+
+{ START_X_ }
+procedure renderer_outline_image.start_x_;
+begin
+ m_start:=trunc(s * line_subpixel_size );
+
+end;
+
+{ _START_X }
+function renderer_outline_image._start_x;
+begin
+ result:=m_start / line_subpixel_size;
+
+end;
+
+{ SUBPIXEL_WIDTH }
+function renderer_outline_image.subpixel_width;
+begin
+ result:=m_pattern.line_width;
+
+end;
+
+{ _PATTERN_WIDTH }
+function renderer_outline_image._pattern_width;
+begin
+ result:=m_pattern.pattern_width;
+
+end;
+
+{ PIXEL }
+procedure renderer_outline_image.pixel;
+begin
+ m_pattern.pixel(p ,x ,y );
+
+end;
+
+{ BLEND_COLOR_HSPAN }
+procedure renderer_outline_image.blend_color_hspan;
+begin
+ m_ren.blend_color_hspan(x ,y ,len ,colors ,NIL );
+
+end;
+
+{ BLEND_COLOR_VSPAN }
+procedure renderer_outline_image.blend_color_vspan;
+begin
+ m_ren.blend_color_vspan(x ,y ,len ,colors ,NIL );
+
+end;
+
+{ ACCURATE_JOIN_ONLY }
+function renderer_outline_image.accurate_join_only;
+begin
+ result:=true;
+
+end;
+
+{ SEMIDOT }
+procedure renderer_outline_image.semidot;
+begin
+end;
+
+{ LINE0 }
+procedure renderer_outline_image.line0;
+begin
+end;
+
+{ LINE1 }
+procedure renderer_outline_image.line1;
+begin
+end;
+
+{ LINE2 }
+procedure renderer_outline_image.line2;
+begin
+end;
+
+{ LINE3 }
+procedure renderer_outline_image.line3;
+var
+ li : line_interpolator_image;
+
+begin
+ fix_degenerate_bisectrix_start(lp ,@sx ,@sy );
+ fix_degenerate_bisectrix_end (lp ,@ex ,@ey );
+
+ li.Construct(@self ,lp ,sx ,sy ,ex ,ey ,m_start ,m_scale_x );
+
+ if li.vertical then
+ while li.step_ver do
+ else
+ while li.step_hor do;
+
+ m_start:=li.pattern_end;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_renderer_primitives.pas b/src/corelib/render/software/agg_renderer_primitives.pas
new file mode 100644
index 00000000..77a43821
--- /dev/null
+++ b/src/corelib/render/software/agg_renderer_primitives.pas
@@ -0,0 +1,333 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// class renderer_primitives
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 15.01.2006-Milano: Unit port establishment
+//
+{ agg_renderer_primitives.pas }
+unit
+ agg_renderer_primitives ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_renderer_base ,
+ agg_color ,
+ agg_dda_line ,
+ agg_ellipse_bresenham ;
+
+{ TYPES DEFINITION }
+type
+ renderer_primitives_ptr = ^renderer_primitives;
+ renderer_primitives = object
+ m_ren : renderer_base_ptr;
+
+ m_fill_color ,
+ m_line_color : aggclr;
+
+ m_curr_x ,
+ m_curr_y : int;
+
+ constructor Construct(ren_ : renderer_base_ptr );
+
+ function coord(c : double ) : int;
+
+ procedure fill_color_(c : aggclr_ptr );
+ procedure line_color_(c : aggclr_ptr );
+
+ function _fill_color : aggclr_ptr;
+ function _line_color : aggclr_ptr;
+
+ procedure rectangle (x1 ,y1 ,x2 ,y2 : int );
+ procedure solid_rectangle (x1 ,y1 ,x2 ,y2 : int );
+ procedure outlined_rectangle(x1 ,y1 ,x2 ,y2 : int );
+
+ procedure ellipse (x ,y ,rx ,ry : int );
+ procedure solid_ellipse (x ,y ,rx ,ry : int );
+ procedure outlined_ellipse(x ,y ,rx ,ry : int );
+
+ procedure line(x1 ,y1 ,x2 ,y2 : int; last : boolean = false );
+
+ procedure move_to(x ,y : int );
+ procedure line_to(x ,y : int; last : boolean = false );
+
+ function ren : renderer_base_ptr;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor renderer_primitives.Construct;
+begin
+ m_fill_color.Construct;
+ m_line_color.Construct;
+
+ m_ren:=ren_;
+
+ m_curr_x:=0;
+ m_curr_y:=0;
+
+end;
+
+{ COORD }
+function renderer_primitives.coord;
+begin
+ result:=trunc(c * subpixel_size );
+
+end;
+
+{ FILL_COLOR_ }
+procedure renderer_primitives.fill_color_;
+begin
+ m_fill_color:=c^;
+
+end;
+
+{ LINE_COLOR_ }
+procedure renderer_primitives.line_color_;
+begin
+ m_line_color:=c^;
+
+end;
+
+{ _FILL_COLOR }
+function renderer_primitives._fill_color;
+begin
+ result:=@m_fill_color;
+
+end;
+
+{ _LINE_COLOR }
+function renderer_primitives._line_color;
+begin
+ result:=@m_line_color;
+
+end;
+
+{ RECTANGLE }
+procedure renderer_primitives.rectangle;
+begin
+ m_ren.blend_hline(x1 ,y1 ,x2 - 1 ,@m_line_color ,cover_full );
+ m_ren.blend_vline(x2 ,y1 ,y2 - 1 ,@m_line_color ,cover_full );
+ m_ren.blend_hline(x1 + 1 ,y2 ,x2 ,@m_line_color ,cover_full );
+ m_ren.blend_vline(x1 ,y1 + 1 ,y2 ,@m_line_color ,cover_full );
+
+end;
+
+{ SOLID_RECTANGLE }
+procedure renderer_primitives.solid_rectangle;
+begin
+ m_ren.blend_bar(x1 ,y1 ,x2 ,y2 ,@m_fill_color ,cover_full );
+
+end;
+
+{ OUTLINED_RECTANGLE }
+procedure renderer_primitives.outlined_rectangle;
+begin
+ rectangle (x1 ,y1 ,x2 ,y2 );
+ m_ren.blend_bar(x1 + 1 ,y1 + 1 ,x2 - 1 ,y2 - 1 ,@m_fill_color ,cover_full );
+
+end;
+
+{ ELLIPSE }
+procedure renderer_primitives.ellipse;
+var
+ ei : ellipse_bresenham_interpolator;
+ dx ,
+ dy : int;
+
+begin
+ ei.Construct(rx ,ry );
+
+ dx:=0;
+ dy:=-ry;
+
+ repeat
+ inc(dx ,ei._dx );
+ inc(dy ,ei._dy );
+
+ m_ren.blend_pixel(x + dx ,y + dy ,@m_line_color ,cover_full );
+ m_ren.blend_pixel(x + dx ,y - dy ,@m_line_color ,cover_full );
+ m_ren.blend_pixel(x - dx ,y - dy ,@m_line_color ,cover_full );
+ m_ren.blend_pixel(x - dx ,y + dy ,@m_line_color ,cover_full );
+
+ ei.inc_operator;
+
+ until dy >= 0;
+
+end;
+
+{ SOLID_ELLIPSE }
+procedure renderer_primitives.solid_ellipse;
+var
+ ei : ellipse_bresenham_interpolator;
+
+ dx ,dy ,dx0 ,dy0 : int;
+
+begin
+ ei.Construct(rx ,ry );
+
+ dx :=0;
+ dy :=-ry;
+ dy0:=dy;
+ dx0:=dx;
+
+ repeat
+ inc(dx ,ei._dx );
+ inc(dy ,ei._dy );
+
+ if dy <> dy0 then
+ begin
+ m_ren.blend_hline(x - dx0 ,y + dy0 ,x + dx0 ,@m_fill_color ,cover_full );
+ m_ren.blend_hline(x - dx0 ,y - dy0 ,x + dx0 ,@m_fill_color ,cover_full );
+
+ end;
+
+ dx0:=dx;
+ dy0:=dy;
+
+ ei.inc_operator;
+
+ until dy >= 0;
+
+ m_ren.blend_hline(x - dx0 ,y + dy0 ,x + dx0 ,@m_fill_color ,cover_full );
+
+end;
+
+{ OUTLINED_ELLIPSE }
+procedure renderer_primitives.outlined_ellipse;
+var
+ ei : ellipse_bresenham_interpolator;
+ dx ,
+ dy : int;
+
+begin
+ ei.Construct(rx ,ry );
+
+ dx:=0;
+ dy:=-ry;
+
+ repeat
+ inc(dx ,ei._dx );
+ inc(dy ,ei._dy );
+
+ m_ren.blend_pixel(x + dx ,y + dy ,@m_line_color ,cover_full );
+ m_ren.blend_pixel(x + dx ,y - dy ,@m_line_color ,cover_full );
+ m_ren.blend_pixel(x - dx ,y - dy ,@m_line_color ,cover_full );
+ m_ren.blend_pixel(x - dx ,y + dy ,@m_line_color ,cover_full );
+
+ if (ei._dy <> 0 ) and
+ (dx <> 0 ) then
+ begin
+ m_ren.blend_hline(x - dx + 1 ,y + dy ,x + dx - 1 ,@m_fill_color ,cover_full );
+ m_ren.blend_hline(x - dx + 1 ,y - dy ,x + dx - 1 ,@m_fill_color ,cover_full );
+
+ end;
+
+ ei.inc_operator;
+
+ until dy >= 0;
+
+end;
+
+{ LINE }
+procedure renderer_primitives.line;
+var
+ li : line_bresenham_interpolator;
+ len : unsigned;
+
+begin
+ li.Construct(x1 ,y1 ,x2 ,y2 );
+
+ len:=li._len;
+
+ if len = 0 then
+ begin
+ if last then
+ m_ren.blend_pixel(li.line_lr(x1 ) ,li.line_lr(y1 ) ,@m_line_color ,cover_full );
+
+ exit;
+
+ end;
+
+ if last then
+ inc(len );
+
+ if li._is_ver then
+ repeat
+ m_ren.blend_pixel(li._x2 ,li._y1 ,@m_line_color ,cover_full );
+
+ li.vstep;
+
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ m_ren.blend_pixel(li._x1 ,li._y2 ,@m_line_color ,cover_full );
+
+ li.hstep;
+
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ MOVE_TO }
+procedure renderer_primitives.move_to;
+begin
+ m_curr_x:=x;
+ m_curr_y:=y;
+
+end;
+
+{ LINE_TO }
+procedure renderer_primitives.line_to;
+begin
+ line(m_curr_x ,m_curr_y ,x ,y ,last );
+
+ m_curr_x:=x;
+ m_curr_y:=y;
+
+end;
+
+{ REN }
+function renderer_primitives.ren;
+begin
+ result:=m_ren;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_renderer_raster_text.pas b/src/corelib/render/software/agg_renderer_raster_text.pas
new file mode 100644
index 00000000..00a7ca77
--- /dev/null
+++ b/src/corelib/render/software/agg_renderer_raster_text.pas
@@ -0,0 +1,385 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 13.02.2006-Milano: Unit port establishment
+//
+{ agg_renderer_raster_text.pas }
+unit
+ agg_renderer_raster_text ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_color ,
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_scanline ,
+ agg_glyph_raster_bin ;
+
+{ TYPES DEFINITION }
+type
+ renderer_raster_htext_solid = object
+ m_ren : renderer_base_ptr;
+ m_glyph : glyph_raster_bin_ptr;
+ m_color : aggclr;
+
+ constructor Construct(ren : renderer_base_ptr; glyph : glyph_raster_bin_ptr );
+
+ procedure color_(c : aggclr_ptr );
+ function _color : aggclr_ptr;
+
+ procedure render_text(x ,y : double; str : PChar; flip : boolean = false );
+
+ end;
+
+ renderer_raster_vtext_solid = object
+ m_ren : renderer_base_ptr;
+ m_glyph : glyph_raster_bin_ptr;
+ m_color : aggclr;
+
+ constructor Construct(ren : renderer_base_ptr; glyph : glyph_raster_bin_ptr );
+
+ procedure color_(c : aggclr_ptr );
+ function _color : aggclr_ptr;
+
+ procedure render_text(x ,y : double; str : PChar; flip : boolean = false );
+
+ end;
+
+ const_span_ptr = ^const_span;
+ const_span = object
+ x ,
+ len : int16;
+ covers : int8u_ptr;
+
+ constructor Construct(x_ : int; len_ : unsigned; covers_ : int8u_ptr );
+
+ end;
+
+ scanline_single_span = object(scanline )
+ m_y : int;
+ m_span : const_span;
+
+ constructor Construct(x_ ,y_ : int; len_ : unsigned; covers_ : int8u_ptr );
+
+ function y : int; virtual;
+ function num_spans : unsigned; virtual;
+ function begin_ : pointer; virtual;
+
+ function sz_of_span : unsigned; virtual;
+
+ end;
+
+ renderer_raster_htext = object
+ m_ren : renderer_scanline_ptr;
+ m_glyph : glyph_raster_bin_ptr;
+
+ constructor Construct(ren : renderer_scanline_ptr; glyph : glyph_raster_bin_ptr );
+
+ procedure render_text(x ,y : double; str : PChar; flip : boolean = false );
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor renderer_raster_htext_solid.Construct;
+begin
+ m_color.Construct;
+
+ m_ren :=ren;
+ m_glyph:=glyph;
+
+end;
+
+{ COLOR_ }
+procedure renderer_raster_htext_solid.color_;
+begin
+ m_color:=c^;
+
+end;
+
+{ _COLOR }
+function renderer_raster_htext_solid._color;
+begin
+ result:=@m_color;
+
+end;
+
+{ RENDER_TEXT }
+procedure renderer_raster_htext_solid.render_text;
+var
+ r : glyph_rect;
+ i : int;
+
+begin
+ while int8u_ptr(str )^ <> 0 do
+ begin
+ m_glyph.prepare(@r ,x ,y ,int8u_ptr(str )^ ,flip );
+
+ if r.x2 >= r.x1 then
+ if flip then
+ begin
+ i:=r.y1;
+
+ while i <= r.y2 do
+ begin
+ m_ren.blend_solid_hspan(
+ r.x1 ,i ,r.x2 - r.x1 + 1 ,
+ @m_color ,
+ m_glyph.span(r.y2 - i ) );
+
+ inc(i );
+
+ end;
+
+ end
+ else
+ begin
+ i:=r.y1;
+
+ while i <= r.y2 do
+ begin
+ m_ren.blend_solid_hspan(
+ r.x1 ,i ,r.x2 - r.x1 + 1 ,
+ @m_color ,
+ m_glyph.span(i - r.y1 ) );
+
+ inc(i );
+
+ end;
+
+ end;
+
+ x:=x + r.dx;
+ y:=y + r.dy;
+
+ inc(ptrcomp(str ) );
+
+ end;
+
+end;
+
+{ CONSTRUCT }
+constructor renderer_raster_vtext_solid.Construct;
+begin
+ m_color.Construct;
+
+ m_ren :=ren;
+ m_glyph:=glyph;
+
+end;
+
+{ COLOR_ }
+procedure renderer_raster_vtext_solid.color_;
+begin
+ m_color:=c^;
+
+end;
+
+{ _COLOR }
+function renderer_raster_vtext_solid._color;
+begin
+ result:=@m_color;
+
+end;
+
+{ RENDER_TEXT }
+procedure renderer_raster_vtext_solid.render_text;
+var
+ r : glyph_rect;
+ i : int;
+
+begin
+ while int8u_ptr(str )^ <> 0 do
+ begin
+ m_glyph.prepare(@r ,x ,y ,int8u_ptr(str )^ ,flip );
+
+ if r.x2 >= r.x1 then
+ if flip then
+ begin
+ i:=r.y1;
+
+ while i <= r.y2 do
+ begin
+ m_ren.blend_solid_vspan(
+ i ,r.x1 ,r.x2 - r.x1 + 1 ,
+ @m_color ,
+ m_glyph.span(i - r.y1 ) );
+
+ inc(i );
+
+ end;
+
+ end
+ else
+ begin
+ i:=r.y1;
+
+ while i <= r.y2 do
+ begin
+ m_ren.blend_solid_vspan(
+ i ,r.x1 ,r.x2 - r.x1 + 1 ,
+ @m_color ,
+ m_glyph.span(r.y2 - i ) );
+
+ inc(i );
+
+ end;
+
+ end;
+
+ x:=x + r.dx;
+ y:=y + r.dy;
+
+ inc(ptrcomp(str ) );
+
+ end;
+
+end;
+
+{ CONSTRUCT }
+constructor const_span.Construct;
+begin
+ x :=x_;
+ len :=len_;
+ covers:=covers_;
+
+end;
+
+{ CONSTRUCT }
+constructor scanline_single_span.Construct;
+begin
+ m_y:=y_;
+
+ m_span.Construct(x_ ,len_ ,covers_ );
+
+end;
+
+{ Y }
+function scanline_single_span.y;
+begin
+ result:=m_y;
+
+end;
+
+{ NUM_SPANS }
+function scanline_single_span.num_spans;
+begin
+ result:=1;
+
+end;
+
+{ BEGIN_ }
+function scanline_single_span.begin_;
+begin
+ result:=@m_span;
+
+end;
+
+{ SZ_OF_SPAN }
+function scanline_single_span.sz_of_span;
+begin
+ result:=sizeof(const_span );
+
+end;
+
+{ CONSTRUCT }
+constructor renderer_raster_htext.Construct;
+begin
+ m_ren :=ren;
+ m_glyph:=glyph;
+
+end;
+
+{ RENDER_TEXT }
+procedure renderer_raster_htext.render_text;
+var
+ r : glyph_rect;
+ i : int;
+ s : scanline_single_span;
+
+begin
+ while int8u_ptr(str )^ <> 0 do
+ begin
+ m_glyph.prepare(@r ,x ,y ,int8u_ptr(str )^ ,flip );
+
+ if r.x2 >= r.x1 then
+ begin
+ m_ren.prepare(r.x2 - r.x1 + 1 );
+
+ if flip then
+ begin
+ i:=r.y1;
+
+ while i <= r.y2 do
+ begin
+ s.Construct(
+ r.x1 ,i ,r.x2 - r.x1 + 1 ,
+ m_glyph.span(r.y2 - i ) );
+
+ m_ren.render(@s );
+
+ inc(i );
+
+ end;
+
+ end
+ else
+ begin
+ i:=r.y1;
+
+ while i <= r.y2 do
+ begin
+ s.Construct(
+ r.x1 ,i ,(r.x2 - r.x1 + 1 ) ,
+ m_glyph.span(i - r.y1 ) );
+
+ m_ren.render(@s );
+
+ inc(i );
+
+ end;
+
+ end;
+
+ end;
+
+ x:=x + r.dx;
+ y:=y + r.dy;
+
+ inc(ptrcomp(str ) );
+
+ end;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_renderer_scanline.pas b/src/corelib/render/software/agg_renderer_scanline.pas
new file mode 100644
index 00000000..d0dbc442
--- /dev/null
+++ b/src/corelib/render/software/agg_renderer_scanline.pas
@@ -0,0 +1,931 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 18.10.2007-Milano: render_scanlines_compound_layered
+// 17.10.2007-Milano: render_scanlines_compound
+// 23.06.2006-Milano: ptrcomp adjustments
+// 27.01.2006-Milano: renderer_scanline_aa
+// 24.11.2005-Milano: renderer.render
+// 17.11.2005-Milano: Unit port establishment
+//
+{ agg_renderer_scanline.pas }
+unit
+ agg_renderer_scanline ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+{$Q- }
+{$R- }
+uses
+ agg_basics ,
+ agg_renderer_base ,
+ agg_color ,
+ agg_scanline ,
+ agg_scanline_p ,
+ agg_scanline_bin ,
+ agg_span_generator ,
+ agg_span_allocator ,
+ agg_rasterizer_scanline_aa ,
+ agg_rasterizer_compound_aa ;
+
+{ TYPES DEFINITION }
+type
+ renderer_scanline_ptr = ^renderer_scanline;
+ renderer_scanline = object(rasterizer_scanline )
+ procedure color_ (c : aggclr_ptr ); virtual; abstract;
+ procedure prepare(u : unsigned ); virtual; abstract;
+ procedure render (sl : scanline_ptr ); virtual; abstract;
+
+ end;
+
+ renderer_scanline_aa = object(renderer_scanline )
+ m_ren : renderer_base_ptr;
+ m_span_gen : span_generator_ptr;
+
+ constructor Construct; overload;
+ constructor Construct(ren : renderer_base_ptr; span_gen : span_generator_ptr ); overload;
+
+ procedure attach(ren : renderer_base_ptr; span_gen : span_generator_ptr );
+
+ procedure prepare(u : unsigned ); virtual;
+ procedure render (sl : scanline_ptr ); virtual;
+
+ end;
+
+ renderer_scanline_aa_solid_ptr = ^renderer_scanline_aa_solid;
+ renderer_scanline_aa_solid = object(renderer_scanline )
+ m_ren : renderer_base_ptr;
+ m_color : aggclr;
+
+ constructor Construct(ren : renderer_base_ptr );
+
+ procedure color_ (c : aggclr_ptr ); virtual;
+ procedure prepare(u : unsigned ); virtual;
+ procedure render (sl : scanline_ptr ); virtual;
+
+ end;
+
+ renderer_scanline_bin_solid_ptr = ^renderer_scanline_bin_solid;
+ renderer_scanline_bin_solid = object(renderer_scanline )
+ m_ren : renderer_base_ptr;
+ m_color : aggclr;
+
+ constructor Construct(ren : renderer_base_ptr );
+
+ procedure color_ (c : aggclr_ptr ); virtual;
+ procedure prepare(u : unsigned ); virtual;
+ procedure render (sl : scanline_ptr ); virtual;
+
+ end;
+
+ style_handler_ptr = ^style_handler;
+ style_handler = object
+ function is_solid(style : unsigned ) : boolean; virtual; abstract;
+ function color (style : unsigned ) : aggclr_ptr; virtual; abstract;
+
+ procedure generate_span(span : aggclr_ptr; x ,y : int; len ,style : unsigned ); virtual; abstract;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+ procedure render_scanline_aa_solid(
+ sl : scanline_ptr;
+ ren : renderer_base_ptr;
+ color : aggclr_ptr );
+
+ procedure render_scanlines_aa_solid(
+ ras : rasterizer_scanline_ptr;
+ sl : scanline_ptr;
+ ren : renderer_base_ptr;
+ color : aggclr_ptr );
+
+ procedure render_scanlines_compound(
+ ras : rasterizer_compound_aa_ptr;
+ sl_aa ,sl_bin : scanline_ptr;
+ ren : renderer_base_ptr;
+ alloc : span_allocator_ptr;
+ sh : style_handler_ptr );
+
+ procedure render_scanlines_compound_layered(
+ ras : rasterizer_compound_aa_ptr;
+ sl_aa : scanline_ptr;
+ ren : renderer_base_ptr;
+ alloc : span_allocator_ptr;
+ sh : style_handler_ptr );
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor renderer_scanline_aa.Construct;
+begin
+ m_ren :=NIL;
+ m_span_gen:=NIL;
+
+end;
+
+{ CONSTRUCT }
+constructor renderer_scanline_aa.Construct(ren : renderer_base_ptr; span_gen : span_generator_ptr );
+begin
+ m_ren :=ren;
+ m_span_gen:=span_gen;
+
+end;
+
+{ ATTACH }
+procedure renderer_scanline_aa.attach;
+begin
+ m_ren :=ren;
+ m_span_gen:=span_gen;
+
+end;
+
+{ PREPARE }
+procedure renderer_scanline_aa.prepare;
+begin
+ m_span_gen.prepare(u );
+
+end;
+
+{ RENDER }
+procedure renderer_scanline_aa.render;
+var
+ y ,xmin ,xmax ,x ,len : int;
+
+ num_spans ,ss : unsigned;
+
+ span : span_ptr;
+ solid : boolean;
+ covers : int8u_ptr;
+
+begin
+ y:=sl.y;
+
+ m_ren.first_clip_box;
+
+ repeat
+ xmin:=m_ren._xmin;
+ xmax:=m_ren._xmax;
+
+ if (y >= m_ren._ymin ) and
+ (y <= m_ren._ymax ) then
+ begin
+ num_spans:=sl.num_spans;
+
+ span:=sl.begin_;
+ ss :=sl.sz_of_span;
+
+ repeat
+ x :=span.x;
+ len:=span.len;
+
+ solid :=false;
+ covers:=span.covers;
+
+ if len < 0 then
+ begin
+ solid:=true;
+ len :=-len;
+
+ end;
+
+ if x < xmin then
+ begin
+ dec(len ,xmin - x );
+
+ if not solid then
+ inc(ptrcomp(covers ) ,xmin - x );
+
+ x:=xmin;
+
+ end;
+
+ if len > 0 then
+ begin
+ if x + len > xmax then
+ len:=xmax - x + 1;
+
+ if len > 0 then
+ if solid then
+ m_ren.blend_color_hspan_no_clip(
+ x ,y ,len ,m_span_gen.generate(x ,y ,len ) ,NIL ,covers^ )
+ else
+ m_ren.blend_color_hspan_no_clip(
+ x ,y ,len ,m_span_gen.generate(x ,y ,len ) ,covers ,covers^ );
+
+ end;
+
+ dec(num_spans );
+
+ if num_spans = 0 then
+ break;
+
+ inc(ptrcomp(span ) ,ss );
+
+ until false;
+
+ end;
+
+ until not m_ren.next_clip_box;
+
+end;
+
+{ CONSTRUCT }
+constructor renderer_scanline_aa_solid.Construct;
+begin
+ m_ren:=ren;
+
+ m_color.Construct;
+
+end;
+
+{ COLOR_ }
+procedure renderer_scanline_aa_solid.color_;
+begin
+ m_color:=c^;
+
+end;
+
+{ PREPARE }
+procedure renderer_scanline_aa_solid.prepare;
+begin
+end;
+
+{ RENDER }
+procedure renderer_scanline_aa_solid.render;
+var
+ x ,y : int;
+
+ num_spans ,ss : unsigned;
+
+ span_pl : span_ptr;
+ span_obj : span_obj_ptr;
+
+begin
+ y:=sl.y;
+
+ num_spans:=sl.num_spans;
+
+ span_pl :=NIL;
+ span_obj:=NIL;
+
+ if sl.is_plain_span then
+ begin
+ span_pl:=sl.begin_;
+ ss :=sl.sz_of_span;
+
+ end
+ else
+ span_obj:=sl.begin_;
+
+ if span_pl <> NIL then
+ repeat
+ x:=span_pl.x;
+
+ if span_pl.len > 0 then
+ m_ren.blend_solid_hspan(x ,y ,unsigned(span_pl.len ),@m_color ,span_pl.covers )
+ else
+ m_ren.blend_hline(x ,y ,unsigned(x - span_pl.len - 1 ) ,@m_color ,span_pl.covers^ );
+
+ dec(num_spans );
+
+ if num_spans = 0 then
+ break;
+
+ inc(ptrcomp(span_pl ) ,ss );
+
+ until false
+ else
+ repeat
+ x:=span_obj.x;
+
+ if span_obj.len > 0 then
+ m_ren.blend_solid_hspan(x ,y ,unsigned(span_obj.len ),@m_color ,span_obj.covers )
+ else
+ m_ren.blend_hline(x ,y ,unsigned(x - span_obj.len - 1 ) ,@m_color ,span_obj.covers^ );
+
+ dec(num_spans );
+
+ if num_spans = 0 then
+ break;
+
+ span_obj.inc_operator;
+
+ until false;
+
+end;
+
+{ CONSTRUCT }
+constructor renderer_scanline_bin_solid.Construct;
+begin
+ m_ren:=ren;
+
+ m_color.Construct;
+
+end;
+
+{ COLOR_ }
+procedure renderer_scanline_bin_solid.color_;
+begin
+ m_color:=c^;
+
+end;
+
+{ PREPARE }
+procedure renderer_scanline_bin_solid.prepare;
+begin
+end;
+
+{ RENDER }
+procedure renderer_scanline_bin_solid.render;
+var
+ span_pl : span_ptr;
+ span_obj : span_obj_ptr;
+
+ num_spans ,ss : unsigned;
+
+begin
+ num_spans:=sl.num_spans;
+
+ span_pl :=NIL;
+ span_obj:=NIL;
+
+ if sl.is_plain_span then
+ begin
+ span_pl:=sl.begin_;
+ ss :=sl.sz_of_span;
+
+ end
+ else
+ span_obj:=sl.begin_;
+
+ if span_pl <> NIL then
+ repeat
+ if span_pl.len < 0 then
+ m_ren.blend_hline(
+ span_pl.x ,sl.y ,
+ span_pl.x - 1 - span_pl.len ,
+ @m_color ,cover_full )
+ else
+ m_ren.blend_hline(
+ span_pl.x ,sl.y ,
+ span_pl.x - 1 + span_pl.len ,
+ @m_color ,cover_full );
+
+ dec(num_spans );
+
+ if num_spans = 0 then
+ break;
+
+ inc(ptrcomp(span_pl ) ,ss );
+
+ until false
+ else
+ repeat
+ if span_obj.len < 0 then
+ m_ren.blend_hline(
+ span_obj.x ,sl.y ,
+ span_obj.x - 1 - span_obj.len ,
+ @m_color ,cover_full )
+ else
+ m_ren.blend_hline(
+ span_obj.x ,sl.y ,
+ span_obj.x - 1 + span_obj.len ,
+ @m_color ,cover_full );
+
+ dec(num_spans );
+
+ if num_spans = 0 then
+ break;
+
+ span_obj.inc_operator;
+
+ until false;
+
+end;
+
+{ RENDER_SCANLINE_AA_SOLID }
+procedure render_scanline_aa_solid(
+ sl : scanline_ptr;
+ ren : renderer_base_ptr;
+ color : aggclr_ptr );
+var
+ y ,x : int;
+
+ num_spans ,ss : unsigned;
+
+ span : span_ptr;
+
+begin
+ y :=sl.y;
+ num_spans:=sl.num_spans;
+ span :=sl.begin_;
+ ss :=sl.sz_of_span;
+
+ repeat
+ x:=span.x;
+
+ if span.len > 0 then
+ ren.blend_solid_hspan(x ,y ,unsigned(span.len ) ,color ,span.covers )
+ else
+ ren.blend_hline(x ,y ,unsigned(x - span.len - 1 ) ,color ,span.covers^ );
+
+ dec(num_spans );
+
+ if num_spans = 0 then
+ break;
+
+ inc(ptrcomp(span ) ,ss );
+
+ until false;
+
+end;
+
+{ RENDER_SCANLINES_AA_SOLID }
+procedure render_scanlines_aa_solid(
+ ras : rasterizer_scanline_ptr;
+ sl : scanline_ptr;
+ ren : renderer_base_ptr;
+ color : aggclr_ptr );
+var
+ y ,x : int;
+
+ num_spans ,ss : unsigned;
+
+ span : span_ptr;
+
+begin
+ if ras.rewind_scanlines then
+ begin
+ sl.reset(ras._min_x ,ras._max_x );
+
+ while ras.sweep_scanline(sl ) do
+ begin
+ y :=sl.y;
+ num_spans:=sl.num_spans;
+ ss :=sl.sz_of_span;
+ span :=sl.begin_;
+
+ repeat
+ x:=span.x;
+
+ if span.len > 0 then
+ ren.blend_solid_hspan(x ,y ,unsigned(span.len ) ,color ,span.covers )
+ else
+ ren.blend_hline(x ,y ,unsigned(x - span.len - 1 ) ,color ,span.covers^ );
+
+ dec(num_spans );
+
+ if num_spans = 0 then
+ break;
+
+ inc(ptrcomp(span ) ,ss );
+
+ until false;
+
+ end;
+
+ end;
+
+end;
+
+{ RENDER_SCANLINES_COMPOUND }
+procedure render_scanlines_compound(
+ ras : rasterizer_compound_aa_ptr;
+ sl_aa ,sl_bin : scanline_ptr;
+ ren : renderer_base_ptr;
+ alloc : span_allocator_ptr;
+ sh : style_handler_ptr );
+var
+ min_x ,len : int;
+
+ num_spans ,num_styles ,style ,i ,ss_aa ,ss_bin : unsigned;
+
+ color_span ,mix_buffer ,colors ,cspan : aggclr_ptr;
+
+ c : aggclr;
+
+ solid : boolean;
+
+ span_aa : span_ptr;
+ span_bin : span_bin_ptr;
+ covers : int8u_ptr;
+
+begin
+ if ras.rewind_scanlines then
+ begin
+ min_x:=ras.min_x;
+ len :=ras.max_x - min_x + 2;
+
+ sl_aa.reset (min_x ,ras.max_x );
+ sl_bin.reset(min_x ,ras.max_x );
+
+ color_span:=alloc.allocate(len * 2 );
+ mix_buffer:=aggclr_ptr(ptrcomp(color_span ) + len * sizeof(aggclr ) );
+
+ num_styles:=ras.sweep_styles;
+
+ while num_styles > 0 do
+ begin
+ if num_styles = 1 then
+ // Optimization for a single style. Happens often
+ if ras.sweep_scanline(sl_aa ,0 ) then
+ begin
+ style:=ras.style(0 );
+
+ if sh.is_solid(style ) then
+ // Just solid fill
+ render_scanline_aa_solid(sl_aa ,ren ,sh.color(style) )
+
+ else
+ begin
+ // Arbitrary span generator
+ span_aa :=sl_aa.begin_;
+ ss_aa :=sl_aa.sz_of_span;
+ num_spans:=sl_aa.num_spans;
+
+ repeat
+ len:=span_aa.len;
+
+ sh.generate_span (color_span ,span_aa.x ,sl_aa.y ,len ,style );
+ ren.blend_color_hspan(span_aa.x ,sl_aa.y ,span_aa.len ,color_span ,span_aa.covers );
+
+ dec(num_spans );
+
+ if num_spans = 0 then
+ break;
+
+ inc(ptrcomp(span_aa ) ,ss_aa );
+
+ until false;
+
+ end;
+
+ end
+ else
+ else // if num_styles = 1 ... else
+ if ras.sweep_scanline(sl_bin ,-1 ) then
+ begin
+ // Clear the spans of the mix_buffer
+ span_bin :=sl_bin.begin_;
+ ss_bin :=sl_bin.sz_of_span;
+ num_spans:=sl_bin.num_spans;
+
+ repeat
+ FillChar(
+ aggclr_ptr(ptrcomp(mix_buffer ) + (span_bin.x - min_x ) * sizeof(aggclr ) )^ ,
+ span_bin.len * sizeof(aggclr ) ,0 );
+
+ dec(num_spans );
+
+ if num_spans = 0 then
+ break;
+
+ inc(ptrcomp(span_bin ) ,ss_bin );
+
+ until false;
+
+ i:=0;
+
+ while i < num_styles do
+ begin
+ style:=ras.style (i );
+ solid:=sh.is_solid(style );
+
+ if ras.sweep_scanline(sl_aa ,i ) then
+ begin
+ span_aa :=sl_aa.begin_;
+ ss_aa :=sl_aa.sz_of_span;
+ num_spans:=sl_aa.num_spans;
+
+ if solid then
+ // Just solid fill
+ repeat
+ c :=sh.color(style )^;
+ len:=span_aa.len;
+
+ colors:=aggclr_ptr(ptrcomp(mix_buffer ) + (span_aa.x - min_x ) * sizeof(aggclr ) );
+ covers:=span_aa.covers;
+
+ repeat
+ if covers^ = cover_full then
+ colors^:=c
+ else
+ colors.add(@c ,covers^ );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+ dec(len );
+
+ until len = 0;
+
+ dec(num_spans );
+
+ if num_spans = 0 then
+ break;
+
+ inc(ptrcomp(span_aa ) ,ss_aa );
+
+ until false
+ else
+ // Arbitrary span generator
+ repeat
+ len :=span_aa.len;
+ colors:=aggclr_ptr(ptrcomp(mix_buffer ) + (span_aa.x - min_x ) * sizeof(aggclr ) );
+ cspan :=color_span;
+
+ sh.generate_span(cspan ,span_aa.x ,sl_aa.y ,len ,style );
+
+ covers:=span_aa.covers;
+
+ repeat
+ if covers^ = cover_full then
+ colors^:=cspan^
+ else
+ colors.add(cspan ,covers^ );
+
+ inc(ptrcomp(cspan ) ,sizeof(aggclr ) );
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+ dec(len );
+
+ until len = 0;
+
+ dec(num_spans );
+
+ if num_spans = 0 then
+ break;
+
+ inc(ptrcomp(span_aa ) ,ss_aa );
+
+ until false;
+
+ end;
+
+ inc(i );
+
+ end;
+
+ // Emit the blended result as a color hspan
+ span_bin :=sl_bin.begin_;
+ ss_bin :=sl_bin.sz_of_span;
+ num_spans:=sl_bin.num_spans;
+
+ repeat
+ ren.blend_color_hspan(
+ span_bin.x ,sl_bin.y ,span_bin.len ,
+ aggclr_ptr(ptrcomp(mix_buffer ) + (span_bin.x - min_x ) * sizeof(aggclr ) ) ,
+ 0 ,cover_full );
+
+ dec(num_spans );
+
+ if num_spans = 0 then
+ break;
+
+ inc(ptrcomp(span_bin ) ,ss_bin );
+
+ until false;
+
+ end; // if ras.sweep_scanline(sl_bin ,-1 )
+
+ num_styles:=ras.sweep_styles;
+
+ end; // while num_styles > 0
+
+ end; // if ras.rewind_scanlines
+
+end;
+
+{ RENDER_SCANLINES_COMPOUND_LAYERED }
+procedure render_scanlines_compound_layered(
+ ras : rasterizer_compound_aa_ptr;
+ sl_aa : scanline_ptr;
+ ren : renderer_base_ptr;
+ alloc : span_allocator_ptr;
+ sh : style_handler_ptr );
+var
+ min_x ,len ,sl_start ,sl_y : int;
+
+ num_spans ,num_styles ,style ,ss_aa ,sl_len ,i ,cover : unsigned;
+
+ color_span ,mix_buffer ,colors ,cspan : aggclr_ptr;
+
+ solid : boolean;
+
+ c : aggclr;
+
+ cover_buffer ,src_covers ,dst_covers : cover_type_ptr;
+
+ span_aa : span_ptr;
+
+begin
+ if ras.rewind_scanlines then
+ begin
+ min_x:=ras.min_x;
+ len :=ras.max_x - min_x + 2;
+
+ sl_aa.reset(min_x ,ras.max_x );
+
+ color_span :=alloc.allocate(len * 2 );
+ mix_buffer :=aggclr_ptr(ptrcomp(color_span ) + len * sizeof(aggclr ) );
+ cover_buffer:=ras.allocate_cover_buffer(len );
+
+ num_styles:=ras.sweep_styles;
+
+ while num_styles > 0 do
+ begin
+ if num_styles = 1 then
+ // Optimization for a single style. Happens often
+ if ras.sweep_scanline(sl_aa ,0 ) then
+ begin
+ style:=ras.style(0 );
+
+ if sh.is_solid(style ) then
+ // Just solid fill
+ render_scanline_aa_solid(sl_aa ,ren ,sh.color(style ) )
+
+ else
+ begin
+ // Arbitrary span generator
+ span_aa :=sl_aa.begin_;
+ num_spans:=sl_aa.num_spans;
+ ss_aa :=sl_aa.sz_of_span;
+
+ repeat
+ len:=span_aa.len;
+
+ sh.generate_span (color_span ,span_aa.x ,sl_aa.y ,len ,style );
+ ren.blend_color_hspan(span_aa.x ,sl_aa.y ,span_aa.len ,color_span ,span_aa.covers );
+
+ dec(num_spans );
+
+ if num_spans = 0 then
+ break;
+
+ inc(ptrcomp(span_aa ) ,ss_aa );
+
+ until false;
+
+ end;
+
+ end
+ else
+ else
+ begin
+ sl_start:=ras.scanline_start;
+ sl_len :=ras.scanline_length;
+
+ if sl_len <> 0 then
+ begin
+ FillChar(
+ aggclr_ptr(ptrcomp(mix_buffer ) + (sl_start - min_x ) * sizeof(aggclr ) )^ ,
+ sl_len * sizeof(aggclr ) ,0 );
+
+ FillChar(
+ cover_type_ptr(ptrcomp(cover_buffer ) + (sl_start - min_x ) * sizeof(cover_type ) )^ ,
+ sl_len * sizeof(cover_type ) ,0 );
+
+ sl_y:=$7FFFFFFF;
+
+ i:=0;
+
+ while i < num_styles do
+ begin
+ style:=ras.style (i );
+ solid:=sh.is_solid(style );
+
+ if ras.sweep_scanline(sl_aa ,i ) then
+ begin
+ span_aa :=sl_aa.begin_;
+ num_spans:=sl_aa.num_spans;
+ sl_y :=sl_aa.y;
+ ss_aa :=sl_aa.sz_of_span;
+
+ if solid then
+ // Just solid fill
+ repeat
+ c.Construct(sh.color(style ) );
+
+ len :=span_aa.len;
+ colors:=aggclr_ptr(ptrcomp(mix_buffer ) + (span_aa.x - min_x ) * sizeof(aggclr ) );
+
+ src_covers:=cover_type_ptr(span_aa.covers );
+ dst_covers:=cover_type_ptr(ptrcomp(cover_buffer ) + (span_aa.x - min_x ) * sizeof(cover_type ) );
+
+ repeat
+ cover:=src_covers^;
+
+ if dst_covers^ + cover > cover_full then
+ cover:=cover_full - dst_covers^;
+
+ if cover <> 0 then
+ begin
+ colors.add(@c ,cover );
+
+ dst_covers^:=dst_covers^ + cover;
+
+ end;
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(ptrcomp(src_covers ) ,sizeof(cover_type ) );
+ inc(ptrcomp(dst_covers ) ,sizeof(cover_type ) );
+ dec(len );
+
+ until len = 0;
+
+ dec(num_spans );
+
+ if num_spans = 0 then
+ break;
+
+ inc(ptrcomp(span_aa ) ,ss_aa );
+
+ until false
+ else
+ // Arbitrary span generator
+ repeat
+ len :=span_aa.len;
+ colors:=aggclr_ptr(ptrcomp(mix_buffer ) + (span_aa.x - min_x ) * sizeof(aggclr ) );
+ cspan :=color_span;
+
+ sh.generate_span(cspan ,span_aa.x ,sl_aa.y ,len ,style );
+
+ src_covers:=cover_type_ptr(span_aa.covers );
+ dst_covers:=cover_type_ptr(ptrcomp(cover_buffer ) + (span_aa.x - min_x ) * sizeof(cover_type ) );
+
+ repeat
+ cover:=src_covers^;
+
+ if dst_covers^ + cover > cover_full then
+ cover:=cover_full - dst_covers^;
+
+ if cover <> 0 then
+ begin
+ colors.add(cspan ,cover );
+
+ dst_covers^:=dst_covers^ + cover;
+
+ end;
+
+ inc(ptrcomp(cspan ) ,sizeof(aggclr ) );
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(ptrcomp(src_covers ) ,sizeof(cover_type ) );
+ inc(ptrcomp(dst_covers ) ,sizeof(cover_type ) );
+ dec(len );
+
+ until len = 0;
+
+ dec(num_spans );
+
+ if num_spans = 0 then
+ break;
+
+ inc(ptrcomp(span_aa ) ,ss_aa );
+
+ until false;
+
+ end;
+
+ inc(i );
+
+ end;
+
+ ren.blend_color_hspan(
+ sl_start ,sl_y ,sl_len ,
+ aggclr_ptr(ptrcomp(mix_buffer ) + (sl_start - min_x ) * sizeof(aggclr ) ) ,
+ 0 ,cover_full );
+
+ end; // if sl_len <> 0
+
+ end; // if num_styles = 1 ... else
+
+ num_styles:=ras.sweep_styles;
+
+ end; // while num_styles > 0
+
+ end; // if ras.rewind_scanlines
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_rendering_buffer.pas b/src/corelib/render/software/agg_rendering_buffer.pas
new file mode 100644
index 00000000..f7fb8c66
--- /dev/null
+++ b/src/corelib/render/software/agg_rendering_buffer.pas
@@ -0,0 +1,329 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// Class rendering_buffer.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 27.09.2005-Milano: Complete unit port
+//
+{ agg_rendering_buffer.pas }
+unit
+ agg_rendering_buffer ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ;
+
+{ TYPES DEFINITION }
+type
+ row_data_type_ptr = ^row_data_type;
+ row_data_type = object
+ x1 ,x2 : int;
+
+ ptr : int8u_ptr;
+
+ constructor Construct; overload;
+ constructor Construct(x1_ ,x2_ : int; ptr_ : int8u_ptr ); overload;
+
+ end;
+
+ span_data_type = object
+ x : int;
+ len : byte;
+ ptr : int8u_ptr;
+
+ constructor Construct; overload;
+ constructor Construct(x_ : int; len_ : byte; ptr_ : int8u_ptr ); overload;
+
+ end;
+
+{ row_ptr_cache_ptr = ^row_ptr_cache;
+ row_ptr_cache = object(rendering_buffer ){!}
+
+ rendering_buffer_ptr = ^rendering_buffer;
+ rendering_buffer = object
+ m_buf : int8u_ptr; // Pointer to rendering buffer
+ m_rows : ^int8u_ptr; // Pointers to each row of the buffer
+ m_width , // Width in pixels
+ m_height : unsigned; // Height in pixels
+ m_stride : int; // Number of bytes per row. Can be < 0
+
+ m_max_height : unsigned; // The maximal height (currently allocated)
+
+ constructor Construct; overload;
+ constructor Construct(buf_ : int8u_ptr; width_ ,height_ : unsigned; stride_ : int ); overload;
+ destructor Destruct; virtual;
+
+ procedure attach(buf_ : int8u_ptr; width_ ,height_ : unsigned; stride_ : int );
+
+ function _buf : int8u_ptr;
+ function _width : unsigned;
+ function _height : unsigned;
+ function _stride : int;
+
+ function _stride_abs : unsigned;
+
+ function row_xy (x ,y : int; len : unsigned ) : int8u_ptr; virtual;
+ function row (y : unsigned ) : int8u_ptr; virtual;
+ function next_row(p : int8u_ptr ) : int8u_ptr; virtual;
+ function rows : int8u_ptr;
+
+ procedure copy_from(mtx : rendering_buffer_ptr );
+ procedure clear (value : int8u );
+
+ end;
+
+IMPLEMENTATION
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor row_data_type.Construct;
+begin
+ x1:=0;
+ x2:=0;
+
+ ptr:=NIL;
+
+end;
+
+{ CONSTRUCT }
+constructor row_data_type.Construct(x1_ ,x2_ : int; ptr_ : int8u_ptr );
+begin
+ x1:=x1_;
+ x2:=x2_;
+
+ ptr:=ptr_;
+
+end;
+
+{ CONSTRUCT }
+constructor span_data_type.Construct;
+begin
+ x :=0;
+ len:=0;
+ ptr:=NIL;
+
+end;
+
+{ CONSTRUCT }
+constructor span_data_type.Construct(x_ : int; len_ : byte; ptr_ : int8u_ptr );
+begin
+ x :=x_;
+ len:=len_;
+ ptr:=ptr_;
+
+end;
+
+{ CONSTRUCT }
+constructor rendering_buffer.Construct;
+begin
+ m_buf :=NIL;
+ m_rows :=NIL;
+ m_width :=0;
+ m_height:=0;
+ m_stride:=0;
+
+ m_max_height:=0;
+
+end;
+
+{ CONSTRUCT }
+constructor rendering_buffer.Construct(buf_ : int8u_ptr; width_ ,height_ : unsigned; stride_ : int );
+begin
+ Construct;
+ attach(buf_ ,width_ ,height_ ,stride_ );
+
+end;
+
+{ DESTRUCT }
+destructor rendering_buffer.Destruct;
+begin
+ agg_freemem(pointer(m_rows ) ,m_max_height * sizeof(int8u_ptr ) );
+
+end;
+
+{ ATTACH }
+procedure rendering_buffer.attach;
+var
+ _rows : ^int8u_ptr;
+ _row_ptr : int8u_ptr;
+
+begin
+ m_buf :=buf_;
+ m_width :=width_;
+ m_height:=height_;
+ m_stride:=stride_;
+
+ if height_ > m_max_height then
+ begin
+ agg_freemem(pointer(m_rows ) ,m_max_height * sizeof(int8u_ptr ) );
+ agg_getmem (pointer(m_rows ) ,height_ * sizeof(int8u_ptr ) );
+
+ m_max_height:=height_;
+
+ end;
+
+ if stride_ < 0 then
+ if height_ > 0 then
+ _row_ptr:=pointer(ptrcomp(m_buf ) - (height_ - 1 ) * stride_ )
+ else
+ _row_ptr:=NIL
+ else
+ _row_ptr:=m_buf;
+
+ _rows:=pointer(m_rows );
+
+ while height_ > 0 do
+ begin
+ _rows^:=_row_ptr;
+
+ inc(ptrcomp(_row_ptr ) ,stride_ );
+ inc(ptrcomp(_rows ) ,sizeof(int8u_ptr ) );
+
+ dec(height_ );
+
+ end;
+
+end;
+
+{ _BUF }
+function rendering_buffer._buf;
+begin
+ result:=m_buf;
+
+end;
+
+{ _WIDTH }
+function rendering_buffer._width;
+begin
+ result:=m_width;
+
+end;
+
+{ _HEIGHT }
+function rendering_buffer._height;
+begin
+ result:=m_height;
+
+end;
+
+{ _STRIDE }
+function rendering_buffer._stride;
+begin
+ result:=m_stride;
+
+end;
+
+{ _STRIDE_ABS }
+function rendering_buffer._stride_abs;
+begin
+ if m_stride < 0 then
+ result:=-m_stride
+ else
+ result:=m_stride;
+
+end;
+
+{ ROW_XY }
+function rendering_buffer.row_xy(x ,y : int; len : unsigned ) : int8u_ptr;
+begin
+ result:=pointer(pointer(ptrcomp(m_rows ) + y * sizeof(int8u_ptr ) )^ );
+
+end;
+
+{ ROW }
+function rendering_buffer.row;
+begin
+ result:=pointer(pointer(ptrcomp(m_rows ) + y * sizeof(int8u_ptr ) )^ );
+
+end;
+
+{ NEXT_ROW }
+function rendering_buffer.next_row;
+begin
+ result:=pointer(ptrcomp(p ) + m_stride );
+
+end;
+
+{ ROWS }
+function rendering_buffer.rows;
+begin
+ result:=pointer(m_rows );
+
+end;
+
+{ COPY_FROM }
+procedure rendering_buffer.copy_from;
+var
+ h ,l ,y : unsigned;
+
+begin
+ h:=_height;
+
+ if mtx._height < h then
+ h:=mtx._height;
+
+ l:=_stride_abs;
+
+ if mtx._stride_abs < l then
+ l:=mtx._stride_abs;
+
+ l:=l * sizeof(int8u );
+
+ if h > 0 then
+ for y:=0 to h - 1 do
+ move(mtx.row(y )^ ,row(y )^ ,l );
+
+end;
+
+{ CLEAR }
+procedure rendering_buffer.clear;
+var
+ y ,
+ x : unsigned;
+ p : int8u_ptr;
+
+begin
+ if _height > 0 then
+ for y:=0 to _height - 1 do
+ begin
+ p:=row(y );
+
+ if _stride_abs > 0 then
+ for x:=0 to _stride_abs - 1 do
+ begin
+ p^:=value;
+
+ inc(ptrcomp(p ) ,sizeof(int8u ) );
+
+ end;
+
+ end;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_rendering_buffer_dynarow.pas b/src/corelib/render/software/agg_rendering_buffer_dynarow.pas
new file mode 100644
index 00000000..a5d4ec63
--- /dev/null
+++ b/src/corelib/render/software/agg_rendering_buffer_dynarow.pas
@@ -0,0 +1,212 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2007
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// class rendering_buffer_dynarow
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 06.10.2007-Milano: Unit port establishment
+//
+{ agg_rendering_buffer_dynarow.pas }
+unit
+ agg_rendering_buffer_dynarow ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_rendering_buffer ;
+
+{ TYPES DEFINITION }
+type
+//===============================================rendering_buffer_dynarow
+// Rendering buffer class with dynamic allocation of the rows.
+// The rows are allocated as needed when requesting for span_ptr().
+// The class automatically calculates min_x and max_x for each row.
+// Generally it's more efficient to use this class as a temporary buffer
+// for rendering a few lines and then to blend it with another buffer.
+ rendering_buffer_dynarow_ptr = ^rendering_buffer_dynarow;
+ rendering_buffer_dynarow = object(rendering_buffer )
+ private
+ m_buff : row_data_type_ptr; // Pointers to each row of the buffer
+ m_alloc ,
+
+ m_byte_width : unsigned; // Width in bytes
+
+ public
+ constructor Construct(width ,height ,byte_width : unsigned );
+ destructor Destruct; virtual;
+
+ procedure init(width ,height ,byte_width : unsigned );
+
+ function _width : unsigned;
+ function _height : unsigned;
+ function _byte_width : unsigned;
+
+ function row_xy(x ,y : int; len : unsigned ) : int8u_ptr; virtual;
+ function row (y : unsigned ) : int8u_ptr; virtual;
+
+ end;
+
+{ GLOBAL VARIABLES & CONSTANTS }
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+// Allocate and clear the buffer
+constructor rendering_buffer_dynarow.Construct(width ,height ,byte_width : unsigned );
+begin
+ m_alloc:=sizeof(row_data_type ) * height;
+
+ agg_getmem(pointer(m_buff ) ,m_alloc );
+
+ m_width :=width;
+ m_height:=height;
+
+ m_byte_width:=byte_width;
+
+ FillChar(m_buff^ ,m_alloc ,0 );
+
+end;
+
+{ DESTRUCT }
+destructor rendering_buffer_dynarow.Destruct;
+begin
+ init(0 ,0 ,0 );
+
+end;
+
+{ INIT }
+// Allocate and clear the buffer
+procedure rendering_buffer_dynarow.init(width ,height ,byte_width : unsigned );
+var
+ i : unsigned;
+
+begin
+ i:=0;
+
+ while i < m_height do
+ begin
+ agg_freemem(
+ pointer(
+ row_data_type_ptr(ptrcomp(m_buff ) + i * sizeof(row_data_type ) ).ptr ) ,
+ m_byte_width );
+
+ inc(i );
+
+ end;
+
+ agg_freemem(pointer(m_buff ) ,m_alloc );
+
+ m_buff:=NIL;
+
+ if (width <> 0 ) and
+ (height <> 0 ) then
+ begin
+ m_width :=width;
+ m_height:=height;
+
+ m_byte_width:=byte_width;
+
+ m_alloc:=sizeof(row_data_type ) * height;
+
+ agg_getmem(pointer(m_buff ) ,m_alloc );
+ FillChar (m_buff^ ,m_alloc ,0 );
+
+ end;
+
+end;
+
+{ _WIDTH }
+function rendering_buffer_dynarow._width : unsigned;
+begin
+ result:=m_width;
+
+end;
+
+{ _HEIGHT }
+function rendering_buffer_dynarow._height : unsigned;
+begin
+ result:=m_height;
+
+end;
+
+{ _BYTE_WIDTH }
+function rendering_buffer_dynarow._byte_width : unsigned;
+begin
+ result:=m_byte_width;
+
+end;
+
+{ ROW_XY }
+// The main function used for rendering. Returns pointer to the
+// pre-allocated span. Memory for the row is allocated as needed.
+function rendering_buffer_dynarow.row_xy(x ,y : int; len : unsigned ) : int8u_ptr;
+var
+ r : row_data_type_ptr;
+ p : int8u_ptr;
+
+ x2 : int;
+
+begin
+ r :=row_data_type_ptr(ptrcomp(m_buff ) + y * sizeof(row_data_type ) );
+ x2:=x + len - 1;
+
+ if r.ptr <> NIL then
+ begin
+ if x < r.x1 then
+ r.x1:=x;
+
+ if x2 > r.x2 then
+ r.x2:=x2;
+
+ end
+ else
+ begin
+ agg_getmem(pointer(p ) ,m_byte_width );
+
+ r.ptr:=p;
+ r.x1 :=x;
+ r.x2 :=x2;
+
+ FillChar(p^ ,m_byte_width ,0 );
+
+ end;
+
+ result:=r.ptr;
+
+end;
+
+{ ROW }
+function rendering_buffer_dynarow.row(y : unsigned ) : int8u_ptr;
+begin
+ result:=row_xy(0 ,y ,m_width );
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_rounded_rect.pas b/src/corelib/render/software/agg_rounded_rect.pas
new file mode 100644
index 00000000..dd70540c
--- /dev/null
+++ b/src/corelib/render/software/agg_rounded_rect.pas
@@ -0,0 +1,468 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// Rounded rectangle vertex generator
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 17.01.2006-Milano: Unit port establishment
+//
+{ agg_rounded_rect.pas }
+unit
+ agg_rounded_rect ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_vertex_source ,
+ agg_arc ;
+
+type
+ rounded_rect = object(vertex_source )
+ m_x1 ,
+ m_y1 ,
+ m_x2 ,
+ m_y2 ,
+ m_rx1 ,
+ m_ry1 ,
+ m_rx2 ,
+ m_ry2 ,
+ m_rx3 ,
+ m_ry3 ,
+ m_rx4 ,
+ m_ry4 : double;
+
+ m_status : unsigned;
+ m_arc : arc;
+
+ constructor Construct; overload;
+ constructor Construct(x1 ,y1 ,x2 ,y2 ,r : double ); overload;
+
+ procedure rect(x1 ,y1 ,x2 ,y2 : double );
+
+ procedure radius(r : double ); overload;
+ procedure radius(rx ,ry : double ); overload;
+ procedure radius(rx_bottom ,ry_bottom ,rx_top ,ry_top : double ); overload;
+ procedure radius(rx1 ,ry1 ,rx2 ,ry2 ,rx3 ,ry3 ,rx4 ,ry4 : double ); overload;
+
+ procedure normalize_radius;
+
+ procedure approximation_scale_(s : double );
+ function _approximation_scale : double;
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor rounded_rect.Construct;
+begin
+ m_x1 :=0;
+ m_y1 :=0;
+ m_x2 :=0;
+ m_y2 :=0;
+ m_rx1:=0;
+ m_ry1:=0;
+ m_rx2:=0;
+ m_ry2:=0;
+ m_rx3:=0;
+ m_ry3:=0;
+ m_rx4:=0;
+ m_ry4:=0;
+
+ m_status:=0;
+
+ m_arc.Construct;
+
+end;
+
+{ CONSTRUCT }
+constructor rounded_rect.Construct(x1 ,y1 ,x2 ,y2 ,r : double );
+begin
+ Construct;
+
+ m_x1 :=x1;
+ m_y1 :=y1;
+ m_x2 :=x2;
+ m_y2 :=y2;
+ m_rx1:=r;
+ m_ry1:=r;
+ m_rx2:=r;
+ m_ry2:=r;
+ m_rx3:=r;
+ m_ry3:=r;
+ m_rx4:=r;
+ m_ry4:=r;
+
+ if x1 > x2 then
+ begin
+ m_x1:=x2;
+ m_x2:=x1;
+
+ end;
+
+ if y1 > y2 then
+ begin
+ m_y1:=y2;
+ m_y2:=y1;
+
+ end;
+
+end;
+
+{ RECT }
+procedure rounded_rect.rect;
+begin
+ m_x1:=x1;
+ m_y1:=y1;
+ m_x2:=x2;
+ m_y2:=y2;
+
+ if x1 > x2 then
+ begin
+ m_x1:=x2;
+ m_x2:=x1;
+
+ end;
+
+ if y1 > y2 then
+ begin
+ m_y1:=y2;
+ m_y2:=y1;
+
+ end;
+
+end;
+
+{ RADIUS }
+procedure rounded_rect.radius(r : double );
+begin
+ m_rx1:=r;
+ m_ry1:=r;
+ m_rx2:=r;
+ m_ry2:=r;
+ m_rx3:=r;
+ m_ry3:=r;
+ m_rx4:=r;
+ m_ry4:=r;
+
+end;
+
+{ RADIUS }
+procedure rounded_rect.radius(rx ,ry : double );
+begin
+ m_rx1:=rx;
+ m_rx2:=rx;
+ m_rx3:=rx;
+ m_rx4:=rx;
+ m_ry1:=ry;
+ m_ry2:=ry;
+ m_ry3:=ry;
+ m_ry4:=ry;
+
+end;
+
+{ RADIUS }
+procedure rounded_rect.radius(rx_bottom ,ry_bottom ,rx_top ,ry_top : double );
+begin
+ m_rx1:=rx_bottom;
+ m_rx2:=rx_bottom;
+ m_rx3:=rx_top;
+ m_rx4:=rx_top;
+ m_ry1:=ry_bottom;
+ m_ry2:=ry_bottom;
+ m_ry3:=ry_top;
+ m_ry4:=ry_top;
+
+end;
+
+{ RADIUS }
+procedure rounded_rect.radius(rx1 ,ry1 ,rx2 ,ry2 ,rx3 ,ry3 ,rx4 ,ry4 : double );
+begin
+ m_rx1:=rx1;
+ m_ry1:=ry1;
+ m_rx2:=rx2;
+ m_ry2:=ry2;
+ m_rx3:=rx3;
+ m_ry3:=ry3;
+ m_rx4:=rx4;
+ m_ry4:=ry4;
+
+end;
+
+{ NORMALIZE_RADIUS }
+procedure rounded_rect.normalize_radius;
+var
+ dx ,dy ,k ,t : double;
+
+begin
+ dx:=Abs(m_y2 - m_y1 );
+ dy:=Abs(m_x2 - m_x1 );
+
+ k:=1.0;
+
+ try
+ t:=dx / (m_rx1 + m_rx2 );
+
+ if t < k then
+ k:=t;
+
+ except
+ end;
+
+ try
+ t:=dx / (m_rx3 + m_rx4 );
+
+ if t < k then
+ k:=t;
+
+ except
+ end;
+
+ try
+ t:=dy / (m_ry1 + m_ry2 );
+
+ if t < k then
+ k:=t;
+
+ except
+ end;
+
+ try
+ t:=dy / (m_ry3 + m_ry4 );
+
+ if t < k then
+ k:=t;
+
+ except
+ end;
+
+ if k < 1.0 then
+ begin
+ m_rx1:=m_rx1 * k;
+ m_ry1:=m_ry1 * k;
+ m_rx2:=m_rx2 * k;
+ m_ry2:=m_ry2 * k;
+ m_rx3:=m_rx3 * k;
+ m_ry3:=m_ry3 * k;
+ m_rx4:=m_rx4 * k;
+ m_ry4:=m_ry4 * k;
+
+ end;
+
+end;
+
+{ APPROXIMATION_SCALE_ }
+procedure rounded_rect.approximation_scale_;
+begin
+ m_arc.approximation_scale_(s );
+
+end;
+
+{ _APPROXIMATION_SCALE }
+function rounded_rect._approximation_scale;
+begin
+ result:=m_arc._approximation_scale;
+
+end;
+
+{ REWIND }
+procedure rounded_rect.rewind;
+begin
+ m_status:=0;
+
+end;
+
+{ VERTEX }
+function rounded_rect.vertex;
+var
+ cmd : unsigned;
+
+label
+ _1 ,_2 ,_3 ,_4 ,_5 ,_6 ,_7 ,_8 ;
+
+begin
+ cmd:=path_cmd_stop;
+
+ case m_status of
+ 0 :
+ begin
+ m_arc.init (m_x1 + m_rx1 ,m_y1 + m_ry1 ,m_rx1 ,m_ry1 ,pi ,pi + pi * 0.5 );
+ m_arc.rewind(0 );
+
+ inc(m_status );
+
+ goto _1;
+
+ end;
+
+ 1 :
+ _1:
+ begin
+ cmd:=m_arc.vertex(x ,y );
+
+ if is_stop(cmd ) then
+ begin
+ inc(m_status );
+
+ goto _2;
+
+ end
+ else
+ begin
+ result:=cmd;
+
+ exit;
+
+ end;
+
+ end;
+
+ 2 :
+ _2:
+ begin
+ m_arc.init (m_x2 - m_rx2 ,m_y1 + m_ry2 ,m_rx2 ,m_ry2 ,pi + pi * 0.5 ,0.0 );
+ m_arc.rewind(0 );
+
+ inc(m_status );
+
+ goto _3;
+
+ end;
+
+ 3 :
+ _3:
+ begin
+ cmd:=m_arc.vertex(x ,y );
+
+ if is_stop(cmd ) then
+ begin
+ inc(m_status );
+
+ goto _4;
+
+ end
+ else
+ begin
+ result:=path_cmd_line_to;
+
+ exit;
+
+ end;
+
+ end;
+
+ 4 :
+ _4:
+ begin
+ m_arc.init (m_x2 - m_rx3 ,m_y2 - m_ry3 ,m_rx3 ,m_ry3 ,0.0 ,pi * 0.5 );
+ m_arc.rewind(0 );
+
+ inc(m_status );
+
+ goto _5;
+
+ end;
+
+ 5 :
+ _5:
+ begin
+ cmd:=m_arc.vertex(x ,y );
+
+ if is_stop(cmd ) then
+ begin
+ inc(m_status );
+
+ goto _6;
+
+ end
+ else
+ begin
+ result:=path_cmd_line_to;
+
+ exit;
+
+ end;
+
+ end;
+
+ 6 :
+ _6:
+ begin
+ m_arc.init (m_x1 + m_rx4 ,m_y2 - m_ry4 ,m_rx4 ,m_ry4 ,pi * 0.5 ,pi );
+ m_arc.rewind(0 );
+
+ inc(m_status );
+
+ goto _7;
+
+ end;
+
+ 7 :
+ _7:
+ begin
+ cmd:=m_arc.vertex(x ,y );
+
+ if is_stop(cmd ) then
+ begin
+ inc(m_status );
+
+ goto _8;
+
+ end
+ else
+ begin
+ result:=path_cmd_line_to;
+
+ exit;
+
+ end;
+
+ end;
+
+ 8 :
+ _8:
+ begin
+ cmd:=path_cmd_end_poly or path_flags_close or path_flags_ccw;
+
+ inc(m_status );
+
+ end;
+
+ end;
+
+ result:=cmd;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_scanline.pas b/src/corelib/render/software/agg_scanline.pas
new file mode 100644
index 00000000..2e07eac7
--- /dev/null
+++ b/src/corelib/render/software/agg_scanline.pas
@@ -0,0 +1,127 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 15.01.2006-Milano: Unit port establishment
+//
+{ agg_scanline.pas }
+unit
+ agg_scanline ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ;
+
+{ TYPES DEFINITION }
+type
+ span_ptr = ^span;
+ span = record
+ x ,
+ len : int16;
+
+ covers : int8u_ptr;
+
+ end;
+
+ span_obj_ptr = ^span_obj;
+ span_obj = object
+ function x : int; virtual;
+ function len : int; virtual;
+ function covers : int8u_ptr; virtual;
+
+ procedure inc_operator; virtual;
+
+ end;
+
+ scanline_ptr = ^scanline;
+ scanline = object
+ procedure reset(min_x ,max_x : int ); virtual; abstract;
+ procedure reset_spans; virtual; abstract;
+
+ procedure finalize (y_ : int ); virtual; abstract;
+ procedure add_cell (x : int; cover : unsigned ); virtual; abstract;
+ procedure add_cells(x : int; len : unsigned; covers : int8u_ptr ); virtual; abstract;
+ procedure add_span (x : int; len ,cover : unsigned ); virtual; abstract;
+
+ function y : int; virtual; abstract;
+ function num_spans : unsigned; virtual; abstract;
+ function begin_ : pointer; virtual; abstract;
+
+ function sz_of_span : unsigned; virtual; abstract;
+ function is_plain_span : boolean; virtual;
+ function is_embedded : boolean; virtual;
+
+ procedure init (ptr : int8u_ptr; dx ,dy : int ); virtual; abstract;
+ procedure setup(scanline_idx : unsigned ); virtual; abstract;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ X }
+function span_obj.x;
+begin
+ result:=0;
+
+end;
+
+{ LEN }
+function span_obj.len;
+begin
+ result:=0;
+
+end;
+
+{ COVERS }
+function span_obj.covers;
+begin
+ result:=NIL;
+
+end;
+
+{ INC_OPERATOR }
+procedure span_obj.inc_operator;
+begin
+end;
+
+{ IS_PLAIN_SPAN }
+function scanline.is_plain_span;
+begin
+ result:=true;
+
+end;
+
+{ IS_EMBEDDED }
+function scanline.is_embedded;
+begin
+ result:=false;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_scanline_bin.pas b/src/corelib/render/software/agg_scanline_bin.pas
new file mode 100644
index 00000000..cdf8be45
--- /dev/null
+++ b/src/corelib/render/software/agg_scanline_bin.pas
@@ -0,0 +1,220 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// Class scanline_bin - binary scanline.
+//
+//----------------------------------------------------------------------------
+//
+// Adaptation for 32-bit screen coordinates (scanline32_bin) has been sponsored by
+// Liberty Technology Systems, Inc., visit http://lib-sys.com
+//
+// Liberty Technology Systems, Inc. is the provider of
+// PostScript and PDF technology for software developers.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 15.01.2006-Milano: Unit port establishment
+//
+{ agg_scanline_bin.pas }
+unit
+ agg_scanline_bin ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_scanline ;
+
+{ TYPES DEFINITION }
+type
+ span_bin_ptr = ^span_bin;
+ span_bin = record
+ x ,
+ len : int16;
+
+ end;
+
+//=============================================================scanline_bin
+//
+// This is binary scaline container which supports the interface
+// used in the rasterizer::render(). See description of agg_scanline_u8
+// for details.
+//
+//------------------------------------------------------------------------
+ scanline_bin = object(scanline )
+ m_max_len : unsigned;
+ m_last_x ,
+ m_y : int;
+
+ m_spans ,
+ m_cur_span : span_bin_ptr;
+
+ constructor Construct;
+ destructor Destruct;
+
+ procedure reset(min_x ,max_x : int ); virtual;
+ procedure reset_spans; virtual;
+
+ procedure finalize(y_ : int ); virtual;
+ procedure add_cell(x : int; cover : unsigned ); virtual;
+ procedure add_span(x : int; len ,cover : unsigned ); virtual;
+
+ function y : int; virtual;
+ function num_spans : unsigned; virtual;
+ function begin_ : pointer; virtual;
+
+ function sz_of_span : unsigned; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor scanline_bin.Construct;
+begin
+ m_max_len:=0;
+ m_last_x :=$7FFFFFF0;
+
+ m_spans :=NIL;
+ m_cur_span:=NIL;
+
+end;
+
+{ DESTRUCT }
+destructor scanline_bin.Destruct;
+begin
+ agg_freemem(pointer(m_spans ) ,m_max_len * sizeof(span_bin ) );
+
+end;
+
+{ RESET }
+procedure scanline_bin.reset;
+var
+ max_len : unsigned;
+
+begin
+ max_len:=max_x - min_x + 3;
+
+ if max_len > m_max_len then
+ begin
+ agg_freemem(pointer(m_spans ) ,m_max_len * sizeof(span_bin ) );
+ agg_getmem (pointer(m_spans ) ,max_len * sizeof(span_bin ) );
+
+ m_max_len:=max_len;
+
+ end;
+
+ m_last_x :=$7FFFFFF0;
+ m_cur_span:=m_spans;
+
+end;
+
+{ RESET_SPANS }
+procedure scanline_bin.reset_spans;
+begin
+ m_last_x :=$7FFFFFF0;
+ m_cur_span:=m_spans;
+
+end;
+
+{ FINALIZE }
+procedure scanline_bin.finalize;
+begin
+ m_y:=y_;
+
+end;
+
+{ ADD_CELL }
+procedure scanline_bin.add_cell;
+begin
+ if x = m_last_x + 1 then
+ inc(m_cur_span.len )
+
+ else
+ begin
+ inc(ptrcomp(m_cur_span ) ,sizeof(span_bin ) );
+
+ m_cur_span.x :=int16(x );
+ m_cur_span.len:=1;
+
+ end;
+
+ m_last_x:=x;
+
+end;
+
+{ ADD_SPAN }
+procedure scanline_bin.add_span;
+begin
+ if x = m_last_x + 1 then
+ m_cur_span.len:=int16(m_cur_span.len + len )
+
+ else
+ begin
+ inc(ptrcomp(m_cur_span ) ,sizeof(span_bin ) );
+
+ m_cur_span.x :=int16(x );
+ m_cur_span.len:=int16(len );
+
+ end;
+
+ m_last_x:=x + len - 1;
+
+end;
+
+{ Y }
+function scanline_bin.y;
+begin
+ result:=m_y
+
+end;
+
+{ NUM_SPANS }
+function scanline_bin.num_spans;
+begin
+ result:=(ptrcomp(m_cur_span ) - ptrcomp(m_spans ) ) div sizeof(span_bin );
+
+end;
+
+{ BEGIN_ }
+function scanline_bin.begin_;
+begin
+ result:=span_bin_ptr(ptrcomp(m_spans ) + sizeof(span_bin ) );
+
+end;
+
+{ SZ_OF_SPAN }
+function scanline_bin.sz_of_span;
+begin
+ result:=sizeof(span_bin );
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_scanline_boolean_algebra.pas b/src/corelib/render/software/agg_scanline_boolean_algebra.pas
new file mode 100644
index 00000000..d074a959
--- /dev/null
+++ b/src/corelib/render/software/agg_scanline_boolean_algebra.pas
@@ -0,0 +1,1663 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 22.02.2006-Milano: sbool_ ... _bin
+// 23.01.2006-Milano: sbool_intersect_shapes
+// 20.01.2006-Milano: Unit port establishment
+//
+{ agg_scanline_boolean_algebra.pas }
+unit
+ agg_scanline_boolean_algebra ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+{$Q- }
+{$R- }
+uses
+ agg_basics ,
+ agg_rasterizer_scanline_aa ,
+ agg_scanline ,
+ agg_renderer_scanline ;
+
+{ TYPES DEFINITION }
+type
+ sbool_op_e = (
+ sbool_or , //----sbool_or
+ sbool_and , //----sbool_and
+ sbool_xor , //----sbool_xor
+ sbool_xor_saddle , //----sbool_xor_saddle
+ sbool_xor_abs_diff , //----sbool_xor_abs_diff
+ sbool_a_minus_b , //----sbool_a_minus_b
+ sbool_b_minus_a ); //----sbool_b_minus_a
+
+ sbool_functor_ptr = ^sbool_functor;
+
+ sbool_functor1 = procedure(this : sbool_functor_ptr; span : span_ptr; x : int; len : unsigned; sl : scanline_ptr );
+ sbool_functor2 = procedure(this : sbool_functor_ptr; span1 ,span2 : span_ptr; x : int; len : unsigned; sl : scanline_ptr );
+ sbool_formula = function (this : sbool_functor_ptr; a ,b : unsigned ) : unsigned;
+
+ sbool_functor = object
+ cover_shift ,
+ cover_size ,
+ cover_mask ,
+ cover_full : unsigned;
+
+ functor1 : sbool_functor1;
+ functor2 : sbool_functor2;
+ formula : sbool_formula;
+
+ constructor Construct1(f1 : sbool_functor1; CoverShift : unsigned = agg_basics.cover_shift );
+ constructor Construct2(f2 : sbool_functor2; CoverShift : unsigned = agg_basics.cover_shift );
+
+ end;
+
+{ GLOBAL PROCEDURES }
+ procedure sbool_subtract_shapes_aa(
+ sg1 ,
+ sg2 : rasterizer_scanline_ptr;
+ sl1 ,
+ sl2 ,
+ sl : scanline_ptr;
+ ren : renderer_scanline_ptr );
+
+ procedure sbool_xor_shapes_abs_diff_aa(
+ sg1 ,
+ sg2 : rasterizer_scanline_ptr;
+ sl1 ,
+ sl2 ,
+ sl : scanline_ptr;
+ ren : renderer_scanline_ptr );
+
+ procedure sbool_xor_shapes_saddle_aa(
+ sg1 ,
+ sg2 : rasterizer_scanline_ptr;
+ sl1 ,
+ sl2 ,
+ sl : scanline_ptr;
+ ren : renderer_scanline_ptr );
+
+ procedure sbool_xor_shapes_aa(
+ sg1 ,
+ sg2 : rasterizer_scanline_ptr;
+ sl1 ,
+ sl2 ,
+ sl : scanline_ptr;
+ ren : renderer_scanline_ptr );
+
+ procedure sbool_intersect_shapes_aa(
+ sg1 ,
+ sg2 : rasterizer_scanline_ptr;
+ sl1 ,
+ sl2 ,
+ sl : scanline_ptr;
+ ren : renderer_scanline_ptr );
+
+ procedure sbool_unite_shapes_aa(
+ sg1 ,
+ sg2 : rasterizer_scanline_ptr;
+ sl1 ,
+ sl2 ,
+ sl : scanline_ptr;
+ ren : renderer_scanline_ptr );
+
+ procedure sbool_combine_shapes_aa(
+ op : sbool_op_e;
+ sg1 ,
+ sg2 : rasterizer_scanline_ptr;
+ sl1 ,
+ sl2 ,
+ sl : scanline_ptr;
+ ren : renderer_scanline_ptr );
+
+ procedure sbool_subtract_shapes_bin(
+ sg1 ,
+ sg2 : rasterizer_scanline_ptr;
+ sl1 ,
+ sl2 ,
+ sl : scanline_ptr;
+ ren : renderer_scanline_ptr );
+
+ procedure sbool_xor_shapes_bin(
+ sg1 ,
+ sg2 : rasterizer_scanline_ptr;
+ sl1 ,
+ sl2 ,
+ sl : scanline_ptr;
+ ren : renderer_scanline_ptr );
+
+ procedure sbool_intersect_shapes_bin(
+ sg1 ,
+ sg2 : rasterizer_scanline_ptr;
+ sl1 ,
+ sl2 ,
+ sl : scanline_ptr;
+ ren : renderer_scanline_ptr );
+
+ procedure sbool_unite_shapes_bin(
+ sg1 ,
+ sg2 : rasterizer_scanline_ptr;
+ sl1 ,
+ sl2 ,
+ sl : scanline_ptr;
+ ren : renderer_scanline_ptr );
+
+ procedure sbool_combine_shapes_bin(
+ op : sbool_op_e;
+ sg1 ,
+ sg2 : rasterizer_scanline_ptr;
+ sl1 ,
+ sl2 ,
+ sl : scanline_ptr;
+ ren : renderer_scanline_ptr );
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT1 }
+constructor sbool_functor.Construct1;
+begin
+ cover_shift:=CoverShift;
+ cover_size :=1 shl cover_shift;
+ cover_mask :=cover_size - 1;
+ cover_full :=cover_mask;
+
+ functor1:=f1;
+ functor2:=NIL;
+ formula :=NIL;
+
+end;
+
+{ CONSTRUCT2 }
+constructor sbool_functor.Construct2;
+begin
+ cover_shift:=CoverShift;
+ cover_size :=1 shl cover_shift;
+ cover_mask :=cover_size - 1;
+ cover_full :=cover_mask;
+
+ functor1:=NIL;
+ functor2:=f2;
+ formula :=NIL;
+
+end;
+
+{ sbool_add_span_empty }
+// Functor.
+// Add nothing. Used in conbine_shapes_sub
+procedure sbool_add_span_empty(this : sbool_functor_ptr; span : span_ptr; x : int; len : unsigned; sl : scanline_ptr );
+begin
+end;
+
+{ sbool_combine_spans_empty }
+// Functor.
+// Combine two spans as empty ones. The functor does nothing
+// and is used to XOR binary spans.
+procedure sbool_combine_spans_empty(this : sbool_functor_ptr; span1 ,span2 : span_ptr; x : int; len : unsigned; sl : scanline_ptr );
+begin
+end;
+
+{ sbool_add_span_aa }
+// Functor.
+// Add an anti-aliased span
+// anti-aliasing information, but only X and Length. The function
+// is compatible with any type of scanlines.
+procedure sbool_add_span_aa(this : sbool_functor_ptr; span : span_ptr; x : int; len : unsigned; sl : scanline_ptr );
+var
+ covers : int8u_ptr;
+
+begin
+ if span.len < 0 then
+ sl.add_span(x ,len ,span.covers^ )
+ else
+ if span.len > 0 then
+ begin
+ covers:=span.covers;
+
+ if span.x < x then
+ inc(ptrcomp(covers ) ,x - span.x );
+
+ sl.add_cells(x ,len ,covers );
+
+ end;
+
+end;
+
+{ sbool_unite_spans_aa }
+// Functor.
+// Unite two spans preserving the anti-aliasing information.
+// The result is added to the "sl" scanline.
+procedure sbool_unite_spans_aa(this : sbool_functor_ptr; span1 ,span2 : span_ptr; x : int; len : unsigned; sl : scanline_ptr );
+var
+ cover : unsigned;
+ covers1 ,
+ covers2 : int8u_ptr;
+
+begin
+// Calculate the operation code and choose the
+// proper combination algorithm.
+// 0 = Both spans are of AA type
+// 1 = span1 is solid, span2 is AA
+// 2 = span1 is AA, span2 is solid
+// 3 = Both spans are of solid type
+ case unsigned(span1.len < 0 ) or (unsigned(span2.len < 0 ) shl 1 ) of
+ 0 : // Both are AA spans
+ begin
+ covers1:=span1.covers;
+ covers2:=span2.covers;
+
+ if span1.x < x then
+ inc(ptrcomp(covers1 ) ,(x - span1.x ) * sizeof(int8u ) );
+
+ if span2.x < x then
+ inc(ptrcomp(covers2 ) ,(x - span2.x ) * sizeof(int8u ) );
+
+ repeat
+ cover:=
+ this.cover_mask * this.cover_mask -
+ (this.cover_mask - covers1^ ) *
+ (this.cover_mask - covers2^ );
+
+ inc(ptrcomp(covers1 ) ,sizeof(int8u ) );
+ inc(ptrcomp(covers2 ) ,sizeof(int8u ) );
+
+ if cover = this.cover_full * this.cover_full then
+ sl.add_cell(x ,this.cover_full )
+ else
+ sl.add_cell(x ,cover shr this.cover_shift );
+
+ inc(x );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+ 1 : // span1 is solid, span2 is AA
+ begin
+ covers2:=span2.covers;
+
+ if span2.x < x then
+ inc(ptrcomp(covers2 ) ,(x - span2.x ) * sizeof(int8u ) );
+
+ if span1.covers^ = this.cover_full then
+ sl.add_span(x ,len ,this.cover_full )
+ else
+ repeat
+ cover:=
+ this.cover_mask * this.cover_mask -
+ (this.cover_mask - span1.covers^ ) *
+ (this.cover_mask - covers2^ );
+
+ inc(ptrcomp(covers2 ) ,sizeof(int8u ) );
+
+ if cover = this.cover_full * this.cover_full then
+ sl.add_cell(x ,this.cover_full )
+ else
+ sl.add_cell(x ,cover shr this.cover_shift );
+
+ inc(x );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+ 2 : // span1 is AA, span2 is solid
+ begin
+ covers1:=span1.covers;
+
+ if span1.x < x then
+ inc(ptrcomp(covers1 ) ,(x - span1.x ) * sizeof(int8u ) );
+
+ if span2.covers^ = this.cover_full then
+ sl.add_span(x ,len ,this.cover_full )
+ else
+ repeat
+ cover:=
+ this.cover_mask * this.cover_mask -
+ (this.cover_mask - covers1^ ) *
+ (this.cover_mask - span2.covers^ );
+
+ inc(ptrcomp(covers1 ) ,sizeof(int8u ) );
+
+ if cover = this.cover_full * this.cover_full then
+ sl.add_cell(x ,this.cover_full )
+ else
+ sl.add_cell(x ,cover shr this.cover_shift );
+
+ inc(x );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+ 3 : // Both are solid spans
+ begin
+ cover:=
+ this.cover_mask * this.cover_mask -
+ (this.cover_mask - span1.covers^ ) *
+ (this.cover_mask - span2.covers^ );
+
+ if cover = this.cover_full * this.cover_full then
+ sl.add_span(x ,len ,this.cover_full )
+ else
+ sl.add_span(x ,len ,cover shr this.cover_shift );
+
+ end;
+
+ end;
+
+end;
+
+{ sbool_combine_spans_bin }
+// Functor.
+// Combine two binary encoded spans, i.e., when we don't have any
+// anti-aliasing information, but only X and Length. The function
+// is compatible with any type of scanlines.
+procedure sbool_combine_spans_bin(this : sbool_functor_ptr; span1 ,span2 : span_ptr; x : int; len : unsigned; sl : scanline_ptr );
+begin
+ sl.add_span(x ,len ,this.cover_full );
+
+end;
+
+{ sbool_add_span_bin }
+// Functor.
+// Add a binary span
+procedure sbool_add_span_bin(this : sbool_functor_ptr; span : span_ptr; x : int; len : unsigned; sl : scanline_ptr );
+begin
+ sl.add_span(x ,len ,this.cover_full );
+
+end;
+
+{ sbool_intersect_spans_aa }
+// Functor.
+// Intersect two spans preserving the anti-aliasing information.
+// The result is added to the "sl" scanline.
+procedure sbool_intersect_spans_aa(this : sbool_functor_ptr; span1 ,span2 : span_ptr; x : int; len : unsigned; sl : scanline_ptr );
+var
+ cover : unsigned;
+ covers1 ,
+ covers2 : int8u_ptr;
+
+begin
+// Calculate the operation code and choose the
+// proper combination algorithm.
+// 0 = Both spans are of AA type
+// 1 = span1 is solid, span2 is AA
+// 2 = span1 is AA, span2 is solid
+// 3 = Both spans are of solid type
+ case unsigned(span1.len < 0 ) or (unsigned(span2.len < 0 ) shl 1 ) of
+ 0 : // Both are AA spans
+ begin
+ covers1:=span1.covers;
+ covers2:=span2.covers;
+
+ if span1.x < x then
+ inc(ptrcomp(covers1 ) ,(x - span1.x ) * sizeof(int8u ) );
+
+ if span2.x < x then
+ inc(ptrcomp(covers2 ) ,(x - span2.x ) * sizeof(int8u ) );
+
+ repeat
+ cover:=covers1^ * covers2^;
+
+ inc(ptrcomp(covers1 ) ,sizeof(int8u ) );
+ inc(ptrcomp(covers2 ) ,sizeof(int8u ) );
+
+ if cover = this.cover_full * this.cover_full then
+ sl.add_cell(x ,this.cover_full )
+ else
+ sl.add_cell(x ,cover shr this.cover_shift );
+
+ inc(x );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+ 1 : // span1 is solid, span2 is AA
+ begin
+ covers2:=span2.covers;
+
+ if span2.x < x then
+ inc(ptrcomp(covers2 ) ,(x - span2.x ) );
+
+ if span1.covers^ = this.cover_full then
+ sl.add_cells(x ,len ,covers2 )
+ else
+ repeat
+ cover:=span1.covers^ * covers2^;
+
+ inc(ptrcomp(covers2 ) ,sizeof(int8u ) );
+
+ if cover = this.cover_full * this.cover_full then
+ sl.add_cell(x ,this.cover_full )
+ else
+ sl.add_cell(x ,cover shr this.cover_shift );
+
+ inc(x );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+ 2 : // span1 is AA, span2 is solid
+ begin
+ covers1:=span1.covers;
+
+ if span1.x < x then
+ inc(ptrcomp(covers1 ) ,(x - span1.x ) * sizeof(int8u ) );
+
+ if span2.covers^ = this.cover_full then
+ sl.add_cells(x ,len ,covers1 )
+ else
+ repeat
+ cover:=covers1^ * span2.covers^;
+
+ inc(ptrcomp(covers1 ) ,sizeof(int8u ) );
+
+ if cover = this.cover_full * this.cover_full then
+ sl.add_cell(x ,this.cover_full )
+ else
+ sl.add_cell(x ,cover shr this.cover_shift );
+
+ inc(x );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+ 3 : // Both are solid spans
+ begin
+ cover:=span1.covers^ * span2.covers^;
+
+ if cover = this.cover_full * this.cover_full then
+ sl.add_span(x ,len ,this.cover_full )
+ else
+ sl.add_span(x ,len ,cover shr this.cover_shift );
+
+ end;
+
+ end;
+
+end;
+
+{ sbool_xor_spans_aa }
+// Functor.
+// XOR two spans preserving the anti-aliasing information.
+// The result is added to the "sl" scanline.
+procedure sbool_xor_spans_aa(this : sbool_functor_ptr; span1 ,span2 : span_ptr; x : int; len : unsigned; sl : scanline_ptr );
+var
+ cover : unsigned;
+ covers1 ,
+ covers2 : int8u_ptr;
+
+begin
+// Calculate the operation code and choose the
+// proper combination algorithm.
+// 0 = Both spans are of AA type
+// 1 = span1 is solid, span2 is AA
+// 2 = span1 is AA, span2 is solid
+// 3 = Both spans are of solid type
+ case unsigned(span1.len < 0 ) or (unsigned(span2.len < 0 ) shl 1 ) of
+ 0 : // Both are AA spans
+ begin
+ covers1:=span1.covers;
+ covers2:=span2.covers;
+
+ if span1.x < x then
+ inc(ptrcomp(covers1 ) ,(x - span1.x ) * sizeof(int8u ) );
+
+ if span2.x < x then
+ inc(ptrcomp(covers2 ) ,(x - span2.x ) * sizeof(int8u ) );
+
+ repeat
+ cover:=this.formula(this ,covers1^ ,covers2^ );
+
+ inc(ptrcomp(covers1 ) ,sizeof(int8u ) );
+ inc(ptrcomp(covers2 ) ,sizeof(int8u ) );
+
+ if cover <> 0 then
+ sl.add_cell(x ,cover );
+
+ inc(x );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+ 1 : // span1 is solid, span2 is AA
+ begin
+ covers2:=span2.covers;
+
+ if span2.x < x then
+ inc(ptrcomp(covers2 ) ,(x - span2.x ) * sizeof(int8u ) );
+
+ repeat
+ cover:=this.formula(this ,span1.covers^ ,covers2^ );
+
+ inc(ptrcomp(covers2 ) ,sizeof(int8u ) );
+
+ if cover <> 0 then
+ sl.add_cell(x ,cover );
+
+ inc(x );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+ 2 : // span1 is AA, span2 is solid
+ begin
+ covers1:=span1.covers;
+
+ if span1.x < x then
+ inc(ptrcomp(covers1 ) ,(x - span1.x ) * sizeof(int8u ) );
+
+ repeat
+ cover:=this.formula(this ,covers1^ ,span2.covers^ );
+
+ inc(ptrcomp(covers1 ) ,sizeof(int8u ) );
+
+ if cover <> 0 then
+ sl.add_cell(x ,cover );
+
+ inc(x );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+ 3 : // Both are solid spans
+ begin
+ cover:=this.formula(this ,span1.covers^ ,span2.covers^ );
+
+ if cover <> 0 then
+ sl.add_span(x ,len ,cover );
+
+ end;
+
+ end;
+
+end;
+
+{ sbool_subtract_spans_aa }
+// Functor.
+// Unite two spans preserving the anti-aliasing information.
+// The result is added to the "sl" scanline.
+procedure sbool_subtract_spans_aa(this : sbool_functor_ptr; span1 ,span2 : span_ptr; x : int; len : unsigned; sl : scanline_ptr );
+var
+ cover : unsigned;
+ covers1 ,
+ covers2 : int8u_ptr;
+
+begin
+// Calculate the operation code and choose the
+// proper combination algorithm.
+// 0 = Both spans are of AA type
+// 1 = span1 is solid, span2 is AA
+// 2 = span1 is AA, span2 is solid
+// 3 = Both spans are of solid type
+ case unsigned(span1.len < 0 ) or (unsigned(span2.len < 0 ) shl 1 ) of
+ 0 : // Both are AA spans
+ begin
+ covers1:=span1.covers;
+ covers2:=span2.covers;
+
+ if span1.x < x then
+ inc(ptrcomp(covers1 ) ,(x - span1.x ) * sizeof(int8u ) );
+
+ if span2.x < x then
+ inc(ptrcomp(covers2 ) ,(x - span2.x ) * sizeof(int8u ) );
+
+ repeat
+ cover:=covers1^ * (this.cover_mask - covers2^ );
+
+ inc(ptrcomp(covers1 ) ,sizeof(int8u ) );
+ inc(ptrcomp(covers2 ) ,sizeof(int8u ) );
+
+ if cover <> 0 then
+ if cover = this.cover_full * this.cover_full then
+ sl.add_cell(x ,this.cover_full )
+ else
+ sl.add_cell(x ,cover shr this.cover_shift );
+
+ inc(x );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+ 1 : // span1 is solid, span2 is AA
+ begin
+ covers2:=span2.covers;
+
+ if span2.x < x then
+ inc(ptrcomp(covers2 ) ,(x - span2.x ) * sizeof(int8u ) );
+
+ repeat
+ cover:=span1.covers^ * (this.cover_mask - covers2^ );
+
+ inc(ptrcomp(covers2 ) ,sizeof(int8u ) );
+
+ if cover <> 0 then
+ if cover = this.cover_full * this.cover_full then
+ sl.add_cell(x ,this.cover_full )
+ else
+ sl.add_cell(x ,cover shr this.cover_shift );
+
+ inc(x );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+ 2 : // span1 is AA, span2 is solid
+ begin
+ covers1:=span1.covers;
+
+ if span1.x < x then
+ inc(ptrcomp(covers1 ) ,(x - span1.x ) * sizeof(int8u ) );
+
+ if span2.covers^ <> this.cover_full then
+ repeat
+ cover:=covers1^ * (this.cover_mask - span2.covers^ );
+
+ inc(ptrcomp(covers1 ) ,sizeof(int8u ) );
+
+ if cover <> 0 then
+ if cover = this.cover_full * this.cover_full then
+ sl.add_cell(x ,this.cover_full )
+ else
+ sl.add_cell(x ,cover shr this.cover_shift );
+
+ inc(x );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+ 3 : // Both are solid spans
+ begin
+ cover:=span1.covers^ * (this.cover_mask - span2.covers^ );
+
+ if cover <> 0 then
+ if cover = this.cover_full * this.cover_full then
+ sl.add_span(x ,len ,this.cover_full )
+ else
+ sl.add_span(x ,len ,cover shr this.cover_shift );
+
+ end;
+
+ end;
+
+end;
+
+{ sbool_xor_formula_linear }
+function sbool_xor_formula_linear(this : sbool_functor_ptr; a ,b : unsigned ) : unsigned;
+var
+ cover : unsigned;
+
+begin
+ cover:=a + b;
+
+ if cover > this.cover_mask then
+ cover:=this.cover_mask + this.cover_mask - cover;
+
+ result:=cover;
+
+end;
+
+{ sbool_xor_formula_saddle }
+function sbool_xor_formula_saddle(this : sbool_functor_ptr; a ,b : int ) : unsigned;
+var
+ k : unsigned;
+
+begin
+ k:=a * b;
+
+ if k = this.cover_mask * this.cover_mask then
+ result:=0
+ else
+ begin
+ a:=(this.cover_mask * this.cover_mask - (a shl this.cover_shift ) + k ) shr this.cover_shift;
+ b:=(this.cover_mask * this.cover_mask - (b shl this.cover_shift ) + k ) shr this.cover_shift;
+
+ result:=this.cover_mask - ((a * b ) shr this.cover_shift);
+
+ end;
+
+end;
+
+{ sbool_xor_formula_abs_diff }
+function sbool_xor_formula_abs_diff(this : sbool_functor_ptr; a ,b : int ) : unsigned;
+begin
+ result:=Abs(a - b );
+
+end;
+
+{ sbool_add_spans_and_render }
+procedure sbool_add_spans_and_render(
+ sl1 ,
+ sl : scanline_ptr;
+ ren : renderer_scanline_ptr;
+ add_span : sbool_functor_ptr );
+
+var
+ ss ,num_spans : unsigned;
+
+ span : span_ptr;
+
+begin
+ sl.reset_spans;
+
+ ss :=sl1.sz_of_span;
+ span :=sl1.begin_;
+ num_spans:=sl1.num_spans;
+
+ repeat
+ add_span.functor1(add_span ,span ,span.x ,Abs(span.len ) ,sl );
+
+ dec(num_spans );
+
+ if num_spans = 0 then
+ break;
+
+ inc(ptrcomp(span ) ,ss );
+
+ until false;
+
+ sl.finalize(sl1.y );
+ ren.render (sl );
+
+end;
+
+{ sbool_unite_scanlines }
+// Unite two scanlines, "sl1" and "sl2" and generate a new "sl" one.
+// The combine_spans functor can be of type sbool_combine_spans_bin or
+// sbool_intersect_spans_aa. First is a general functor to combine
+// two spans without Anti-Aliasing, the second preserves the AA
+// information, but works slower
+procedure sbool_unite_scanlines(
+ sl1 ,
+ sl2 ,
+ sl : scanline_ptr;
+ add_span1 ,
+ add_span2 ,
+ combine_spans : sbool_functor_ptr );
+const
+ invalid_b = $FFFFFFF;
+ invalid_e = invalid_b - 1;
+
+var
+ num1 ,num2 ,ss1 ,ss2 : unsigned;
+
+ xb1 ,xb2 ,xe1 ,xe2 ,xb ,xe ,len : int;
+
+ span1 ,span2 : span_ptr;
+
+begin
+ sl.reset_spans;
+
+ num1:=sl1.num_spans;
+ num2:=sl2.num_spans;
+
+// Initialize the spans as invalid
+ xb1:=invalid_b;
+ xb2:=invalid_b;
+ xe1:=invalid_e;
+ xe2:=invalid_e;
+
+// Initialize span1 if there are spans
+ if num1 <> 0 then
+ begin
+ span1:=sl1.begin_;
+ ss1 :=sl1.sz_of_span;
+ xb1 :=span1.x;
+ xe1 :=xb1 + Abs(span1.len ) - 1;
+
+ dec(num1 );
+
+ end;
+
+// Initialize span2 if there are spans
+ if num2 <> 0 then
+ begin
+ span2:=sl2.begin_;
+ ss2 :=sl2.sz_of_span;
+ xb2 :=span2.x;
+ xe2 :=xb2 + Abs(span2.len ) - 1;
+
+ dec(num2 );
+
+ end;
+
+ repeat
+ // Retrieve a new span1 if it's invalid
+ if (num1 <> 0 ) and
+ (xb1 > xe1 ) then
+ begin
+ dec(num1 );
+ inc(ptrcomp(span1 ) ,ss1 );
+
+ xb1:=span1.x;
+ xe1:=xb1 + abs(span1.len ) - 1;
+
+ end;
+
+ // Retrieve a new span2 if it's invalid
+ if (num2 <> 0 ) and
+ (xb2 > xe2 ) then
+ begin
+ dec(num2 );
+ inc(ptrcomp(span2 ) ,ss2 );
+
+ xb2:=span2.x;
+ xe2:=xb2 + Abs(span2.len ) - 1;
+
+ end;
+
+ if (xb1 > xe1 ) and (xb2 > xe2 ) then
+ break;
+
+ // Calculate the intersection
+ xb:=xb1;
+ xe:=xe1;
+
+ if xb < xb2 then
+ xb:=xb2;
+
+ if xe > xe2 then
+ xe:=xe2;
+
+ len:=xe - xb + 1; // The length of the intersection
+
+ if len > 0 then
+ begin
+ // The spans intersect,
+ // add the beginning of the span
+ if xb1 < xb2 then
+ begin
+ add_span1.functor1(add_span1 ,span1 ,xb1 ,xb2 - xb1 ,sl );
+
+ xb1:=xb2;
+
+ end
+ else
+ if xb2 < xb1 then
+ begin
+ add_span2.functor1(add_span2 ,span2 ,xb2 ,xb1 - xb2 ,sl );
+
+ xb2:=xb1;
+
+ end;
+
+ // Add the combination part of the spans
+ combine_spans.functor2(combine_spans ,span1 ,span2 ,xb ,len ,sl );
+
+ // Invalidate the fully processed span or both
+ if xe1 < xe2 then
+ begin
+ // Invalidate span1 and eat
+ // the processed part of span2
+ xb1:=invalid_b;
+ xe1:=invalid_e;
+
+ inc(xb2 ,len );
+
+ end
+ else
+ if xe2 < xe1 then
+ begin
+ // Invalidate span2 and eat
+ // the processed part of span1
+ xb2:=invalid_b;
+ xe2:=invalid_e;
+
+ inc(xb1 ,len );
+
+ end
+ else
+ begin
+ xb1:=invalid_b; // Invalidate both
+ xb2:=invalid_b;
+ xe1:=invalid_e;
+ xe2:=invalid_e;
+
+ end;
+
+ end
+ else
+ // The spans do not intersect
+ if xb1 < xb2 then
+ begin
+ // Advance span1
+ if xb1 <= xe1 then
+ add_span1.functor1(add_span1 ,span1 ,xb1 ,xe1 - xb1 + 1 ,sl );
+
+ xb1:=invalid_b; // Invalidate
+ xe1:=invalid_e;
+
+ end
+ else
+ begin
+ // Advance span2
+ if xb2 <= xe2 then
+ add_span2.functor1(add_span2 ,span2 ,xb2 ,xe2 - xb2 + 1 ,sl );
+
+ xb2:=invalid_b; // Invalidate
+ xe2:=invalid_e;
+
+ end;
+
+ until false;
+
+end;
+
+{ sbool_unite_shapes }
+// Unite the scanline shapes. Here the "Scanline Generator"
+// abstraction is used. ScanlineGen1 and ScanlineGen2 are
+// the generators, and can be of type rasterizer_scanline_aa<>.
+// There function requires three scanline containers that can be
+// of different type.
+// "sl1" and "sl2" are used to retrieve scanlines from the generators,
+// "sl" is ised as the resulting scanline to render it.
+// The external "sl1" and "sl2" are used only for the sake of
+// optimization and reusing of the scanline objects.
+// the function calls sbool_unite_scanlines with CombineSpansFunctor
+// as the last argument. See sbool_unite_scanlines for details.
+procedure sbool_unite_shapes(
+ sg1 ,
+ sg2 : rasterizer_scanline_ptr;
+ sl1 ,
+ sl2 ,
+ sl : scanline_ptr;
+ ren : renderer_scanline_ptr;
+ add_span1 ,
+ add_span2 ,
+ combine_spans : sbool_functor_ptr );
+var
+ flag1 ,flag2 : boolean;
+
+ r1 ,r2 ,ur : rect;
+
+begin
+// Prepare the scanline generators.
+// If anyone of them doesn't contain
+// any scanlines, then return.
+ flag1:=sg1.rewind_scanlines;
+ flag2:=sg2.rewind_scanlines;
+
+ if not flag1 and not flag2 then
+ exit;
+
+// Get the bounding boxes
+ r1.Construct(sg1._min_x ,sg1._min_y ,sg1._max_x ,sg1._max_y );
+ r2.Construct(sg2._min_x ,sg2._min_y ,sg2._max_x ,sg2._max_y );
+
+// Calculate the union of the bounding boxes
+ ur:=unite_rectangles(@r1 ,@r2 );
+
+ if not ur.is_valid then
+ exit;
+
+ ren.prepare(unsigned(ur.x2 - ur.x2 + 2 ) );
+
+// Reset the scanlines and get two first ones
+ sl.reset(ur.x1 ,ur.x2 );
+
+ if flag1 then
+ begin
+ sl1.reset(sg1._min_x ,sg1._max_x );
+
+ flag1:=sg1.sweep_scanline(sl1 );
+
+ end;
+
+ if flag2 then
+ begin
+ sl2.reset(sg2._min_x ,sg2._max_x );
+
+ flag2:=sg2.sweep_scanline(sl2 );
+
+ end;
+
+// The main loop
+// Here we synchronize the scanlines with
+// the same Y coordinate.
+ while flag1 or flag2 do
+ if flag1 and flag2 then
+ if sl1.y = sl2.y then
+ begin
+ // The Y coordinates are the same.
+ // Combine the scanlines, render if they contain any spans,
+ // and advance both generators to the next scanlines
+ sbool_unite_scanlines(
+ sl1 ,sl2 ,sl ,
+ add_span1 ,add_span2 ,combine_spans );
+
+ if sl.num_spans <> 0 then
+ begin
+ sl.finalize(sl1.y );
+ ren.render (sl );
+
+ end;
+
+ flag1:=sg1.sweep_scanline(sl1 );
+ flag2:=sg2.sweep_scanline(sl2 );
+
+ end
+ else
+ if sl1.y < sl2.y then
+ begin
+ sbool_add_spans_and_render(sl1 ,sl ,ren ,add_span1 );
+
+ flag1:=sg1.sweep_scanline(sl1 );
+
+ end
+ else
+ begin
+ sbool_add_spans_and_render(sl2 ,sl ,ren ,add_span2 );
+
+ flag2:=sg2.sweep_scanline(sl2 );
+
+ end
+ else
+ begin
+ if flag1 then
+ begin
+ sbool_add_spans_and_render(sl1 ,sl ,ren ,add_span1 );
+
+ flag1:=sg1.sweep_scanline(sl1 );
+
+ end;
+
+ if flag2 then
+ begin
+ sbool_add_spans_and_render(sl2 ,sl ,ren ,add_span2 );
+
+ flag2:=sg2.sweep_scanline(sl2 );
+
+ end;
+
+ end;
+
+end;
+
+{ sbool_intersect_scanlines }
+// Intersect two scanlines, "sl1" and "sl2" and generate a new "sl" one.
+// The combine_spans functor can be of type sbool_combine_spans_bin or
+// sbool_intersect_spans_aa. First is a general functor to combine
+// two spans without Anti-Aliasing, the second preserves the AA
+// information, but works slower
+procedure sbool_intersect_scanlines(
+ sl1 ,
+ sl2 ,
+ sl : scanline_ptr;
+ combine_spans : sbool_functor_ptr );
+var
+ num1 ,num2 : unsigned;
+ span1 ,span2 : span_ptr;
+
+ xb1 ,xb2 ,xe1 ,xe2 ,ss1 ,ss2 : int;
+
+ advance_span1 ,advance_both : boolean;
+
+begin
+ sl.reset_spans;
+
+ num1:=sl1.num_spans;
+
+ if num1 = 0 then
+ exit;
+
+ num2:=sl2.num_spans;
+
+ if num2 = 0 then
+ exit;
+
+ span1:=sl1.begin_;
+ ss1 :=sl1.sz_of_span;
+ span2:=sl2.begin_;
+ ss2 :=sl2.sz_of_span;
+
+ while(num1 <> 0 ) and
+ (num2 <> 0 ) do
+ begin
+ xb1:=span1.x;
+ xb2:=span2.x;
+ xe1:=xb1 + Abs(span1.len ) - 1;
+ xe2:=xb2 + Abs(span2.len ) - 1;
+
+ // Determine what spans we should advance in the next step
+ // The span with the least ending X should be advanced
+ // advance_both is just an optimization when we ending
+ // coordinates are the same and we can advance both
+ advance_span1:= xe1 < xe2;
+ advance_both := xe1 = xe2;
+
+ // Find the intersection of the spans
+ // and check if they intersect
+ if xb1 < xb2 then
+ xb1:=xb2;
+
+ if xe1 > xe2 then
+ xe1:=xe2;
+
+ if xb1 <= xe1 then
+ combine_spans.functor2(combine_spans ,span1 ,span2 ,xb1 ,xe1 - xb1 + 1 ,sl );
+
+ // Advance the spans
+ if advance_both then
+ begin
+ dec(num1 );
+ dec(num2 );
+
+ if num1 <> 0 then
+ inc(ptrcomp(span1 ) ,ss1 );
+
+ if num2 <> 0 then
+ inc(ptrcomp(span2 ) ,ss2 );
+
+ end
+ else
+ if advance_span1 then
+ begin
+ dec(num1 );
+
+ if num1 <> 0 then
+ inc(ptrcomp(span1 ) ,ss1 );
+
+ end
+ else
+ begin
+ dec(num2 );
+
+ if num2 <> 0 then
+ inc(ptrcomp(span2 ) ,ss2 );
+
+ end;
+
+ end;
+
+end;
+
+{ sbool_intersect_shapes }
+// Intersect the scanline shapes. Here the "Scanline Generator"
+// abstraction is used. ScanlineGen1 and ScanlineGen2 are
+// the generators, and can be of type rasterizer_scanline_aa<>.
+// There function requires three scanline containers that can be of
+// different types.
+// "sl1" and "sl2" are used to retrieve scanlines from the generators,
+// "sl" is ised as the resulting scanline to render it.
+// The external "sl1" and "sl2" are used only for the sake of
+// optimization and reusing of the scanline objects.
+// the function calls sbool_intersect_scanlines with CombineSpansFunctor
+// as the last argument. See sbool_intersect_scanlines for details.
+procedure sbool_intersect_shapes(
+ sg1 ,
+ sg2 : rasterizer_scanline_ptr;
+ sl1 ,
+ sl2 ,
+ sl : scanline_ptr;
+ ren : renderer_scanline_ptr;
+ combine_spans : sbool_functor_ptr );
+var
+ r1 ,r2 ,ir : rect;
+
+begin
+// Prepare the scanline generators.
+// If anyone of them doesn't contain
+// any scanlines, then return.
+ if not sg1.rewind_scanlines then
+ exit;
+
+ if not sg2.rewind_scanlines then
+ exit;
+
+// Get the bounding boxes
+ r1.Construct(sg1._min_x ,sg1._min_y ,sg1._max_x ,sg1._max_y );
+ r2.Construct(sg2._min_x ,sg2._min_y ,sg2._max_x ,sg2._max_y );
+
+// Calculate the intersection of the bounding
+// boxes and return if they don't intersect.
+ ir:=intersect_rectangles(@r1 ,@r2 );
+
+ if not ir.is_valid then
+ exit;
+
+// Reset the scanlines and get two first ones
+ sl.reset (ir.x1 ,ir.x2 );
+ sl1.reset(sg1._min_x ,sg1._max_x );
+ sl2.reset(sg2._min_x ,sg2._max_x );
+
+ if not sg1.sweep_scanline(sl1 ) then
+ exit;
+
+ if not sg2.sweep_scanline(sl2 ) then
+ exit;
+
+ ren.prepare(unsigned(ir.x2 - ir.x1 + 2 ) );
+
+// The main loop
+// Here we synchronize the scanlines with
+// the same Y coordinate, ignoring all other ones.
+// Only scanlines having the same Y-coordinate
+// are to be combined.
+ repeat
+ while sl1.y < sl2.y do
+ if not sg1.sweep_scanline(sl1 ) then
+ exit;
+
+ while sl2.y < sl1.y do
+ if not sg2.sweep_scanline(sl2 ) then
+ exit;
+
+ if sl1.y = sl2.y then
+ begin
+ // The Y coordinates are the same.
+ // Combine the scanlines, render if they contain any spans,
+ // and advance both generators to the next scanlines
+ sbool_intersect_scanlines(sl1 ,sl2 ,sl ,combine_spans );
+
+ if sl.num_spans <> 0 then
+ begin
+ sl.finalize(sl1.y );
+ ren.render (sl );
+
+ end;
+
+ if not sg1.sweep_scanline(sl1 ) then
+ exit;
+
+ if not sg2.sweep_scanline(sl2 ) then
+ exit;
+
+ end;
+
+ until false;
+
+end;
+
+{ sbool_subtract_shapes }
+// Subtract the scanline shapes, "sg1-sg2". Here the "Scanline Generator"
+// abstraction is used. ScanlineGen1 and ScanlineGen2 are
+// the generators, and can be of type rasterizer_scanline_aa<>.
+// There function requires three scanline containers that can be of
+// different types.
+// "sl1" and "sl2" are used to retrieve scanlines from the generators,
+// "sl" is ised as the resulting scanline to render it.
+// The external "sl1" and "sl2" are used only for the sake of
+// optimization and reusing of the scanline objects.
+// the function calls sbool_intersect_scanlines with CombineSpansFunctor
+// as the last argument. See combine_scanlines_sub for details.
+procedure sbool_subtract_shapes(
+ sg1 ,
+ sg2 : rasterizer_scanline_ptr;
+ sl1 ,
+ sl2 ,
+ sl : scanline_ptr;
+ ren : renderer_scanline_ptr;
+ add_span1 ,
+ combine_spans : sbool_functor_ptr );
+var
+ r1 : rect;
+
+ flag1 ,flag2 : boolean;
+
+ add_span2 : sbool_functor;
+
+begin
+// Prepare the scanline generators.
+// Here "sg1" is master, "sg2" is slave.
+ if not sg1.rewind_scanlines then
+ exit;
+
+ flag2:=sg2.rewind_scanlines;
+
+// Get the bounding box
+ r1.Construct(sg1._min_x ,sg1._min_y ,sg1._max_x ,sg1._max_y );
+
+// Reset the scanlines and get two first ones
+ sl.reset (sg1._min_x ,sg1._max_x );
+ sl1.reset(sg1._min_x ,sg1._max_x );
+ sl2.reset(sg2._min_x ,sg2._max_x );
+
+ if not sg1.sweep_scanline(sl1 ) then
+ exit;
+
+ if flag2 then
+ flag2:=sg2.sweep_scanline(sl2 );
+
+ ren.prepare(unsigned(sg1._max_x - sg1._min_x + 2 ) );
+
+// A fake span2 processor
+ add_span2.Construct1(@sbool_add_span_empty );
+
+// The main loop
+// Here we synchronize the scanlines with
+// the same Y coordinate, ignoring all other ones.
+// Only scanlines having the same Y-coordinate
+// are to be combined.
+ flag1:=true;
+
+ repeat
+ // Synchronize "slave" with "master"
+ while flag2 and
+ (sl2.y < sl1.y ) do
+ flag2:=sg2.sweep_scanline(sl2 );
+
+ if flag2 and
+ (sl2.y = sl1.y ) then
+ begin
+ // The Y coordinates are the same.
+ // Combine the scanlines and render if they contain any spans.
+ sbool_unite_scanlines(sl1 ,sl2 ,sl ,add_span1 ,@add_span2 ,combine_spans );
+
+ if sl.num_spans <> 0 then
+ begin
+ sl.finalize(sl1.y );
+ ren.render (sl );
+
+ end;
+
+ end
+ else
+ sbool_add_spans_and_render(sl1 ,sl ,ren ,add_span1 );
+
+ // Advance the "master"
+ flag1:=sg1.sweep_scanline(sl1 );
+
+ until not flag1;
+
+end;
+
+{ SBOOL_SUBSTRACT_SHAPES_AA }
+// Subtract shapes "sg1-sg2" with anti-aliasing
+// See intersect_shapes_aa for more comments
+procedure sbool_subtract_shapes_aa;
+var
+ add_functor ,
+ combine_functor : sbool_functor;
+
+begin
+ add_functor.Construct1 (@sbool_add_span_aa );
+ combine_functor.Construct2(@sbool_subtract_spans_aa );
+
+ sbool_subtract_shapes(
+ sg1 ,sg2 ,sl1 ,sl2 ,sl ,ren ,
+ @add_functor ,
+ @combine_functor );
+
+end;
+
+{ SBOOL_XOR_SHAPES_ABS_DIFF_AA }
+// Apply eXclusive OR to two anti-aliased scanline shapes.
+// There's the absolute difference used to calculate
+// Anti-Aliasing values, that is:
+// a XOR b : abs(a-b)
+// See intersect_shapes_aa for more comments
+procedure sbool_xor_shapes_abs_diff_aa;
+var
+ add_functor ,
+ combine_functor : sbool_functor;
+
+begin
+ add_functor.Construct1 (@sbool_add_span_aa );
+ combine_functor.Construct2(@sbool_xor_spans_aa );
+
+ combine_functor.formula:=@sbool_xor_formula_abs_diff;
+
+ sbool_unite_shapes(
+ sg1 ,sg2 ,sl1 ,sl2 ,sl ,ren ,
+ @add_functor ,
+ @add_functor ,
+ @combine_functor );
+
+end;
+
+{ SBOOL_XOR_SHAPES_SADDLE_AA }
+// Apply eXclusive OR to two anti-aliased scanline shapes.
+// There's the classical "Saddle" used to calculate the
+// Anti-Aliasing values, that is:
+// a XOR b : 1-((1-a+a*b)*(1-b+a*b))
+// See intersect_shapes_aa for more comments
+procedure sbool_xor_shapes_saddle_aa;
+var
+ add_functor ,
+ combine_functor : sbool_functor;
+
+begin
+ add_functor.Construct1 (@sbool_add_span_aa );
+ combine_functor.Construct2(@sbool_xor_spans_aa );
+
+ combine_functor.formula:=@sbool_xor_formula_saddle;
+
+ sbool_unite_shapes(
+ sg1 ,sg2 ,sl1 ,sl2 ,sl ,ren ,
+ @add_functor ,
+ @add_functor ,
+ @combine_functor );
+
+end;
+
+{ SBOOL_XOR_SHAPES_AA }
+// Apply eXclusive OR to two anti-aliased scanline shapes. There's
+// a modified "Linear" XOR used instead of classical "Saddle" one.
+// The reason is to have the result absolutely conststent with what
+// the scanline rasterizer produces.
+// See intersect_shapes_aa for more comments
+procedure sbool_xor_shapes_aa;
+var
+ add_functor ,
+ combine_functor : sbool_functor;
+
+begin
+ add_functor.Construct1 (@sbool_add_span_aa );
+ combine_functor.Construct2(@sbool_xor_spans_aa );
+
+ combine_functor.formula:=@sbool_xor_formula_linear;
+
+ sbool_unite_shapes(
+ sg1 ,sg2 ,sl1 ,sl2 ,sl ,ren ,
+ @add_functor ,
+ @add_functor ,
+ @combine_functor );
+
+end;
+
+{ SBOOL_INTERSECT_SHAPES_AA }
+// Intersect two anti-aliased scanline shapes.
+// Here the "Scanline Generator" abstraction is used.
+// ScanlineGen1 and ScanlineGen2 are the generators, and can be of
+// type rasterizer_scanline_aa<>. There function requires three
+// scanline containers that can be of different types.
+// "sl1" and "sl2" are used to retrieve scanlines from the generators,
+// "sl" is ised as the resulting scanline to render it.
+// The external "sl1" and "sl2" are used only for the sake of
+// optimization and reusing of the scanline objects.
+procedure sbool_intersect_shapes_aa;
+var
+ combine_functor : sbool_functor;
+
+begin
+ combine_functor.Construct2(@sbool_intersect_spans_aa );
+
+ sbool_intersect_shapes(
+ sg1 ,sg2 ,sl1 ,sl2 ,sl ,ren ,
+ @combine_functor );
+
+end;
+
+{ SBOOL_UNITE_SHAPES_AA }
+// Unite two anti-aliased scanline shapes
+// See intersect_shapes_aa for more comments
+procedure sbool_unite_shapes_aa;
+var
+ add_functor ,
+ combine_functor : sbool_functor;
+
+begin
+ add_functor.Construct1 (@sbool_add_span_aa );
+ combine_functor.Construct2(@sbool_unite_spans_aa );
+
+ sbool_unite_shapes(
+ sg1 ,sg2 ,sl1 ,sl2 ,sl ,ren ,
+ @add_functor ,
+ @add_functor ,
+ @combine_functor );
+
+end;
+
+{ SBOOL_COMBINE_SHAPES_AA }
+procedure sbool_combine_shapes_aa;
+begin
+ case op of
+ sbool_or :
+ sbool_unite_shapes_aa(sg1 ,sg2 ,sl1 ,sl2 ,sl ,ren );
+
+ sbool_and :
+ sbool_intersect_shapes_aa(sg1 ,sg2 ,sl1 ,sl2 ,sl ,ren );
+
+ sbool_xor :
+ sbool_xor_shapes_aa(sg1 ,sg2 ,sl1 ,sl2 ,sl ,ren );
+
+ sbool_xor_saddle :
+ sbool_xor_shapes_saddle_aa(sg1 ,sg2 ,sl1 ,sl2 ,sl ,ren );
+
+ sbool_xor_abs_diff :
+ sbool_xor_shapes_abs_diff_aa(sg1 ,sg2 ,sl1 ,sl2 ,sl ,ren );
+
+ sbool_a_minus_b :
+ sbool_subtract_shapes_aa(sg1 ,sg2 ,sl1 ,sl2 ,sl ,ren );
+
+ sbool_b_minus_a :
+ sbool_subtract_shapes_aa(sg2 ,sg1 ,sl2 ,sl1 ,sl ,ren );
+
+ end;
+
+end;
+
+{ SBOOL_SUBTRACT_SHAPES_BIN }
+procedure sbool_subtract_shapes_bin;
+var
+ add_functor ,
+ combine_functor : sbool_functor;
+
+begin
+ add_functor.Construct1 (@sbool_add_span_bin );
+ combine_functor.Construct2(@sbool_combine_spans_empty );
+
+ sbool_subtract_shapes(
+ sg1 ,sg2 ,sl1 ,sl2 ,sl ,ren ,
+ @add_functor ,
+ @combine_functor );
+
+end;
+
+{ SBOOL_XOR_SHAPES_BIN }
+procedure sbool_xor_shapes_bin;
+var
+ add_functor ,
+ combine_functor : sbool_functor;
+
+begin
+ add_functor.Construct1 (@sbool_add_span_bin );
+ combine_functor.Construct2(@sbool_combine_spans_empty );
+
+ sbool_unite_shapes(
+ sg1 ,sg2 ,sl1 ,sl2 ,sl ,ren ,
+ @add_functor ,
+ @add_functor ,
+ @combine_functor );
+
+end;
+
+{ SBOOL_INTERSECT_SHAPES_BIN }
+procedure sbool_intersect_shapes_bin;
+var
+ combine_functor : sbool_functor;
+
+begin
+ combine_functor.Construct2(@sbool_combine_spans_bin );
+
+ sbool_intersect_shapes(
+ sg1 ,sg2 ,sl1 ,sl2 ,sl ,ren ,
+ @combine_functor );
+
+end;
+
+{ SBOOL_UNITE_SHAPES_BIN }
+procedure sbool_unite_shapes_bin;
+var
+ add_functor ,
+ combine_functor : sbool_functor;
+
+begin
+ add_functor.Construct1 (@sbool_add_span_bin );
+ combine_functor.Construct2(@sbool_combine_spans_bin );
+
+ sbool_unite_shapes(
+ sg1 ,sg2 ,sl1 ,sl2 ,sl ,ren ,
+ @add_functor ,
+ @add_functor ,
+ @combine_functor );
+
+end;
+
+{ SBOOL_COMBINE_SHAPES_BIN }
+procedure sbool_combine_shapes_bin;
+begin
+ case op of
+ sbool_or :
+ sbool_unite_shapes_bin(sg1 ,sg2 ,sl1 ,sl2 ,sl ,ren );
+
+ sbool_and :
+ sbool_intersect_shapes_bin(sg1 ,sg2 ,sl1 ,sl2 ,sl ,ren );
+
+ sbool_xor ,sbool_xor_saddle ,sbool_xor_abs_diff :
+ sbool_xor_shapes_bin(sg1 ,sg2 ,sl1 ,sl2 ,sl ,ren );
+
+ sbool_a_minus_b :
+ sbool_subtract_shapes_bin(sg1 ,sg2 ,sl1 ,sl2 ,sl ,ren );
+
+ sbool_b_minus_a :
+ sbool_subtract_shapes_bin(sg2 ,sg1 ,sl2 ,sl1 ,sl ,ren );
+
+ end;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_scanline_p.pas b/src/corelib/render/software/agg_scanline_p.pas
new file mode 100644
index 00000000..c53b4ef1
--- /dev/null
+++ b/src/corelib/render/software/agg_scanline_p.pas
@@ -0,0 +1,278 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// Class scanline_p - a general purpose scanline container with packed spans.
+//
+//----------------------------------------------------------------------------
+//
+// Adaptation for 32-bit screen coordinates (scanline32_p) has been sponsored by
+// Liberty Technology Systems, Inc., visit http://lib-sys.com
+//
+// Liberty Technology Systems, Inc. is the provider of
+// PostScript and PDF technology for software developers.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 23.11.2005-Milano: ...
+// 18.11.2005-Milano: Unit port establishment
+//
+{ agg_scanline_p.pas }
+unit
+ agg_scanline_p ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_scanline ;
+
+{ TYPES DEFINITION }
+type
+ span_p8_ptr = ^span_p8;
+ span_p8 = record
+ x ,
+ len : int16; // If negative, it's a solid span, covers is valid
+
+ covers : int8u_ptr;
+
+ end;
+
+ scanline_p8_ptr = ^scanline_p8;
+ scanline_p8 = object(scanline )
+ m_max_len : unsigned;
+ m_last_x ,
+ m_y : int;
+
+ m_covers ,
+ m_cover_ptr : int8u_ptr;
+
+ m_spans ,
+ m_cur_span : span_p8_ptr;
+
+ constructor Construct;
+ destructor Destruct;
+
+ procedure reset(min_x ,max_x : int ); virtual;
+ procedure reset_spans; virtual;
+
+ procedure finalize (y_ : int ); virtual;
+ procedure add_cell (x : int; cover : unsigned ); virtual;
+ procedure add_cells(x : int; len : unsigned; covers : int8u_ptr ); virtual;
+ procedure add_span (x : int; len ,cover : unsigned ); virtual;
+
+ function y : int; virtual;
+ function num_spans : unsigned; virtual;
+ function begin_ : pointer; virtual;
+
+ function sz_of_span : unsigned; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor scanline_p8.Construct;
+begin
+ m_max_len:=0;
+ m_last_x :=$7FFFFFF0;
+
+ m_y:=0;
+
+ m_covers :=NIL;
+ m_cover_ptr:=NIL;
+
+ m_spans :=NIL;
+ m_cur_span:=NIL;
+
+end;
+
+{ DESTRUCT }
+destructor scanline_p8.Destruct;
+begin
+ agg_freemem(pointer(m_spans ) ,m_max_len * sizeof(span_p8 ) );
+ agg_freemem(pointer(m_covers ) ,m_max_len * sizeof(int8u ) );
+
+end;
+
+{ RESET }
+procedure scanline_p8.reset;
+var
+ max_len : unsigned;
+
+begin
+ max_len:=max_x - min_x + 3;
+
+ if max_len > m_max_len then
+ begin
+ agg_freemem(pointer(m_covers ) ,m_max_len * sizeof(int8u ) );
+ agg_freemem(pointer(m_spans ) ,m_max_len * sizeof(span_p8 ) );
+
+ agg_getmem(pointer(m_covers ) ,max_len * sizeof(int8u ) );
+ agg_getmem(pointer(m_spans ) ,max_len * sizeof(span_p8 ) );
+
+ m_max_len:=max_len;
+
+ end;
+
+ m_last_x:=$7FFFFFF0;
+
+ m_cover_ptr:=m_covers;
+ m_cur_span :=m_spans;
+
+ m_cur_span.len:=0;
+
+end;
+
+{ RESET_SPANS }
+procedure scanline_p8.reset_spans;
+begin
+ m_last_x:=$7FFFFFF0;
+
+ m_cover_ptr:=m_covers;
+ m_cur_span :=m_spans;
+
+ m_cur_span.len:=0;
+
+end;
+
+{ FINALIZE }
+procedure scanline_p8.finalize;
+begin
+ m_y:=y_;
+
+end;
+
+{ ADD_CELL }
+procedure scanline_p8.add_cell;
+begin
+ m_cover_ptr^:=int8u(cover );
+
+ if (x = m_last_x + 1 ) and
+ (m_cur_span.len > 0 ) then
+ inc(m_cur_span.len )
+
+ else
+ begin
+ inc(ptrcomp(m_cur_span ) ,sizeof(span_p8 ) );
+
+ m_cur_span.covers:=m_cover_ptr;
+
+ m_cur_span.x :=int16(x );
+ m_cur_span.len:=1;
+
+ end;
+
+ m_last_x:=x;
+
+ inc(ptrcomp(m_cover_ptr ) ,sizeof(int8u ) );
+
+end;
+
+{ ADD_CELLS }
+procedure scanline_p8.add_cells;
+begin
+ move(covers^ ,m_cover_ptr^ ,len * sizeof(int8u ) );
+
+ if (x = m_last_x + 1 ) and
+ (m_cur_span.len > 0 ) then
+ inc(m_cur_span.len ,int16(len ) )
+
+ else
+ begin
+ inc(ptrcomp(m_cur_span ) ,sizeof(span_p8 ) );
+
+ m_cur_span.covers:=m_cover_ptr;
+ m_cur_span.x :=int16(x );
+ m_cur_span.len :=int16(len );
+
+ end;
+
+ inc(ptrcomp(m_cover_ptr ) ,len * sizeof(int8u ) );
+
+ m_last_x:=x + len - 1;
+
+end;
+
+{ ADD_SPAN }
+procedure scanline_p8.add_span;
+begin
+ if (x = m_last_x + 1 ) and
+ (m_cur_span.len < 0 ) and
+ (cover = m_cur_span.covers^ ) then
+ dec(m_cur_span.len ,int16(len ) )
+
+ else
+ begin
+ m_cover_ptr^:=int8u(cover );
+
+ inc(ptrcomp(m_cur_span ) ,sizeof(span_p8 ) );
+
+ m_cur_span.covers:=m_cover_ptr;
+ m_cur_span.x :=int16(x );
+ m_cur_span.len :=int16(len );
+ m_cur_span.len :=-m_cur_span.len;
+
+ inc(ptrcomp(m_cover_ptr ) ,sizeof(int8u ) );
+
+ end;
+
+ m_last_x:=x + len - 1;
+
+end;
+
+{ Y }
+function scanline_p8.y;
+begin
+ result:=m_y;
+
+end;
+
+{ NUM_SPANS }
+function scanline_p8.num_spans;
+begin
+ result:=(ptrcomp(m_cur_span ) - ptrcomp(m_spans ) ) div sizeof(span_p8 );
+
+end;
+
+{ BEGIN_ }
+function scanline_p8.begin_;
+begin
+ result:=span_p8_ptr(ptrcomp(m_spans ) + sizeof(span_p8 ) );
+
+end;
+
+{ SZ_OF_SPAN }
+function scanline_p8.sz_of_span;
+begin
+ result:=sizeof(span_p8 );
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_scanline_storage_aa.pas b/src/corelib/render/software/agg_scanline_storage_aa.pas
new file mode 100644
index 00000000..146fff3b
--- /dev/null
+++ b/src/corelib/render/software/agg_scanline_storage_aa.pas
@@ -0,0 +1,1857 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 15.02.2006-Milano: Unit port establishment
+//
+{ agg_scanline_storage_aa.pas }
+unit
+ agg_scanline_storage_aa ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+{$Q- }
+{$R- }
+uses
+ agg_basics ,
+ agg_array ,
+ agg_scanline ,
+ agg_renderer_scanline ,
+ agg_render_scanlines ,
+ agg_rasterizer_scanline_aa ;
+
+{ TYPES DEFINITION }
+type
+//----------------------------------------------scanline_cell_storage
+ extra_span_ptr = ^extra_span;
+ extra_span = record
+ len : unsigned;
+ ptr : pointer;
+
+ end;
+
+ scanline_cell_storage_ptr = ^scanline_cell_storage;
+ scanline_cell_storage = object
+ m_cells ,
+ m_extra_storage : pod_deque;
+
+ constructor Construct(entry_sz : unsigned ); overload;
+ constructor Construct(v : scanline_cell_storage_ptr ); overload;
+ destructor Destruct;
+
+ procedure remove_all;
+ function add_cells(cells : pointer; num_cells : unsigned ) : int;
+
+ function assign_operator(v : scanline_cell_storage_ptr ) : scanline_cell_storage_ptr;
+ function array_operator (idx : int ) : pointer;
+
+ procedure copy_extra_storage(v : scanline_cell_storage_ptr );
+
+ end;
+
+//-----------------------------------------------scanline_storage_aa
+ span_data_ss_ptr = ^span_data_ss;
+ span_data_ss = record
+ x ,
+ len : int32; // If negative, it's a solid span, covers is valid
+ covers_id : int; // The index of the cells in the scanline_cell_storage
+
+ end;
+
+ scanline_data_ss_ptr = ^scanline_data_ss;
+ scanline_data_ss = record
+ y : int;
+ num_spans ,
+ start_span : unsigned;
+
+ end;
+
+ span_ss_ptr = ^span_ss;
+ span_ss = record
+ x ,
+ len : int32; // If negative, it's a solid span, covers is valid
+
+ covers : pointer;
+
+ end;
+
+ scanline_storage_aa_ptr = ^scanline_storage_aa;
+
+ embedded_scanline_ss_ptr = ^embedded_scanline_ss;
+
+ const_iterator_ss = object(span_obj )
+ m_storage : scanline_storage_aa_ptr;
+ m_span_idx : unsigned;
+ m_span : span_ss;
+
+ constructor Construct(sl : embedded_scanline_ss_ptr );
+
+ function x : int; virtual;
+ function len : int; virtual;
+ function covers : int8u_ptr; virtual;
+
+ procedure inc_operator; virtual;
+ procedure init_span;
+
+ end;
+
+ embedded_scanline_ss = object(scanline )
+ m_storage : scanline_storage_aa_ptr;
+ m_scanline : scanline_data_ss;
+ m_scanline_idx : unsigned;
+
+ m_result : const_iterator_ss;
+
+ constructor Construct(storage : scanline_storage_aa_ptr );
+
+ procedure reset(min_x ,max_x : int ); virtual;
+
+ function y : int; virtual;
+ function num_spans : unsigned; virtual;
+ function begin_ : pointer; virtual;
+
+ function sz_of_span : unsigned; virtual;
+ function is_plain_span : boolean; virtual;
+ function is_embedded : boolean; virtual;
+
+ procedure setup(scanline_idx : unsigned ); virtual;
+
+ end;
+
+ scanline_storage_aa = object(renderer_scanline )
+ m_covers : scanline_cell_storage;
+ m_spans ,
+ m_scanlines : pod_deque;
+
+ m_fake_span : span_data_ss;
+ m_fake_scanline : scanline_data_ss;
+
+ m_min_x ,
+ m_min_y ,
+ m_max_x ,
+ m_max_y : int;
+
+ m_cur_scanline : unsigned;
+
+ constructor Construct;
+ destructor Destruct;
+
+ // Renderer Interface
+ procedure prepare(u : unsigned ); virtual;
+ procedure render (sl : scanline_ptr ); virtual;
+
+ // Iterate scanlines interface
+ function _min_x : int; virtual;
+ function _min_y : int; virtual;
+ function _max_x : int; virtual;
+ function _max_y : int; virtual;
+
+ function rewind_scanlines : boolean; virtual;
+ function sweep_scanline(sl : scanline_ptr ) : boolean; virtual;
+
+ // Specialization for embedded_scanline
+ function sweep_scanline_em(sl : scanline_ptr ) : boolean; virtual;
+
+ function byte_size : unsigned; virtual;
+ procedure write_int32(dst : int8u_ptr; val : int32 );
+ procedure serialize (data : int8u_ptr ); virtual;
+
+ function scanline_by_index(i : unsigned ) : scanline_data_ss_ptr;
+ function span_by_index (i : unsigned ) : span_data_ss_ptr;
+ function covers_by_index (i : int ) : pointer;
+
+ end;
+
+ scanline_storage_aa8 = object(scanline_storage_aa )
+ end;
+
+ scanline_storage_aa16 = object(scanline_storage_aa )
+ constructor Construct;
+
+ function sweep_scanline(sl : scanline_ptr ) : boolean; virtual;
+
+ function byte_size : unsigned; virtual;
+ procedure serialize(data : int8u_ptr ); virtual;
+
+ end;
+
+ scanline_storage_aa32 = object(scanline_storage_aa )
+ constructor Construct;
+
+ function sweep_scanline(sl : scanline_ptr ) : boolean; virtual;
+
+ function byte_size : unsigned; virtual;
+ procedure serialize(data : int8u_ptr ); virtual;
+
+ end;
+
+//------------------------------------------serialized_scanlines_adaptor_aa
+ embedded_scanline_sa_ptr = ^embedded_scanline_sa;
+
+ const_iterator_sa = object(span_obj )
+ m_ptr : int8u_ptr;
+ m_span : span_ss;
+
+ m_dx : int;
+ m_sz : unsigned;
+
+ constructor Construct(sl : embedded_scanline_sa_ptr; sz : unsigned );
+
+ function x : int; virtual;
+ function len : int; virtual;
+ function covers : int8u_ptr; virtual;
+
+ procedure inc_operator; virtual;
+ procedure init_span;
+
+ function read_int32 : int;
+
+ end;
+
+ embedded_scanline_sa = object(scanline )
+ m_ptr : int8u_ptr;
+ m_y : int;
+
+ m_num_spans : unsigned;
+
+ m_dx : int;
+ m_sz : unsigned;
+
+ m_result : const_iterator_sa;
+
+ constructor Construct(sz : unsigned );
+
+ procedure reset(min_x ,max_x : int ); virtual;
+
+ function y : int; virtual;
+ function num_spans : unsigned; virtual;
+ function begin_ : pointer; virtual;
+
+ function sz_of_span : unsigned; virtual;
+ function is_plain_span : boolean; virtual;
+ function is_embedded : boolean; virtual;
+
+ procedure init(ptr : int8u_ptr; dx ,dy : int ); virtual;
+
+ function read_int32 : int;
+
+ end;
+
+ serialized_scanlines_adaptor_aa = object(rasterizer_scanline )
+ m_data ,
+ m_end ,
+ m_ptr : int8u_ptr;
+
+ m_dx ,
+ m_dy ,
+
+ m_min_x ,
+ m_min_y ,
+ m_max_x ,
+ m_max_y : int;
+
+ m_sz : unsigned;
+
+ constructor Construct(sz : unsigned ); overload;
+ constructor Construct(sz : unsigned; data : int8u_ptr; size : unsigned; dx ,dy : double ); overload;
+
+ procedure init(data : int8u_ptr; size : unsigned; dx ,dy : double );
+
+ function read_int32 : int;
+ function read_int32u : unsigned;
+
+ // Iterate scanlines interface
+ function rewind_scanlines : boolean; virtual;
+
+ function _min_x : int; virtual;
+ function _min_y : int; virtual;
+ function _max_x : int; virtual;
+ function _max_y : int; virtual;
+
+ function sweep_scanline(sl : scanline_ptr ) : boolean; virtual;
+
+ // Specialization for embedded_scanline
+ function sweep_scanline_em(sl : scanline_ptr ) : boolean; virtual;
+
+ end;
+
+ serialized_scanlines_adaptor_aa8 = object(serialized_scanlines_adaptor_aa )
+ constructor Construct; overload;
+ constructor Construct(data : int8u_ptr; size : unsigned; dx ,dy : double ); overload;
+
+ end;
+
+ serialized_scanlines_adaptor_aa16 = object(serialized_scanlines_adaptor_aa )
+ constructor Construct; overload;
+ constructor Construct(data : int8u_ptr; size : unsigned; dx ,dy : double ); overload;
+
+ end;
+
+ serialized_scanlines_adaptor_aa32 = object(serialized_scanlines_adaptor_aa )
+ constructor Construct; overload;
+ constructor Construct(data : int8u_ptr; size : unsigned; dx ,dy : double ); overload;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor scanline_cell_storage.Construct(entry_sz : unsigned );
+begin
+ m_cells.Construct (128 - 2 ,entry_sz ,12 );
+ m_extra_storage.Construct(sizeof(extra_span ) ,6 );
+
+end;
+
+{ CONSTRUCT }
+constructor scanline_cell_storage.Construct(v : scanline_cell_storage_ptr );
+begin
+ m_cells.Construct (v.m_cells.m_entry_sz );
+ m_extra_storage.Construct(sizeof(extra_span ) ,6 );
+
+ assign_operator (v );
+ copy_extra_storage(v );
+
+end;
+
+{ DESTRUCT }
+destructor scanline_cell_storage.Destruct;
+begin
+ remove_all;
+
+ m_cells.Destruct;
+ m_extra_storage.Destruct;
+
+end;
+
+{ REMOVE_ALL }
+procedure scanline_cell_storage.remove_all;
+var
+ i : int;
+ s : extra_span_ptr;
+
+begin
+ i:=m_extra_storage.size; dec(i );
+
+ while i >= 0 do
+ begin
+ s:=m_extra_storage.array_operator(i );
+
+ agg_freemem(s.ptr ,s.len * m_cells.m_entry_sz );
+
+ dec(i );
+
+ end;
+
+ m_extra_storage.remove_all;
+ m_cells.remove_all;
+
+end;
+
+{ ADD_CELLS }
+function scanline_cell_storage.add_cells;
+var
+ idx : int;
+ ptr : pointer;
+
+ s : extra_span;
+
+begin
+ idx:=m_cells.allocate_continuous_block(num_cells );
+
+ if idx >= 0 then
+ begin
+ ptr:=m_cells.array_operator(idx );
+
+ move(cells^ ,ptr^ ,m_cells.m_entry_sz * num_cells );
+
+ result:=idx;
+
+ exit;
+
+ end;
+
+ s.len:=num_cells;
+
+ agg_getmem(s.ptr ,s.len * m_cells.m_entry_sz );
+
+ move(cells^ ,s.ptr^ ,s.len * m_cells.m_entry_sz );
+
+ m_extra_storage.add(@s );
+
+ result:=-int(m_extra_storage.size );
+
+end;
+
+{ ASSIGN_OPERATOR }
+function scanline_cell_storage.assign_operator;
+begin
+ remove_all;
+
+ m_cells.assign_operator(@v.m_cells );
+ copy_extra_storage (v );
+
+ result:=@self;
+
+end;
+
+{ ARRAY_OPERATOR }
+function scanline_cell_storage.array_operator;
+var
+ i : unsigned;
+
+begin
+ if idx >= 0 then
+ begin
+ if idx >= m_cells.size then
+ begin
+ result:=NIL;
+
+ exit;
+
+ end;
+
+ result:=m_cells.array_operator(idx );
+
+ exit;
+
+ end;
+
+ i:=unsigned(-idx - 1 );
+
+ if i >= m_extra_storage.size then
+ begin
+ result:=0;
+
+ exit;
+
+ end;
+
+ result:=extra_span_ptr(m_extra_storage.array_operator(i ) ).ptr;
+
+end;
+
+{ COPY_EXTRA_STORAGE }
+procedure scanline_cell_storage.copy_extra_storage;
+var
+ i : unsigned;
+
+ src : extra_span_ptr;
+ dst : extra_span;
+
+begin
+ i:=0;
+
+ while i < v.m_extra_storage.size do
+ begin
+ src:=v.m_extra_storage.array_operator(i );
+
+ dst.len:=src.len;
+
+ agg_getmem(dst.ptr ,dst.len * v.m_cells.m_entry_sz );
+
+ move(src.ptr^ ,dst.ptr^ ,dst.len * v.m_cells.m_entry_sz );
+
+ m_extra_storage.add(@dst );
+
+ inc(i );
+
+ end;
+
+end;
+
+{ CONSTRUCT }
+constructor const_iterator_ss.Construct;
+begin
+ m_storage :=sl.m_storage;
+ m_span_idx:=sl.m_scanline.start_span;
+
+ init_span;
+
+end;
+
+{ X }
+function const_iterator_ss.x;
+begin
+ result:=m_span.x;
+
+end;
+
+{ LEN }
+function const_iterator_ss.len;
+begin
+ result:=m_span.len;
+
+end;
+
+{ COVERS }
+function const_iterator_ss.covers;
+begin
+ result:=m_span.covers;
+
+end;
+
+{ INC_OPERATOR }
+procedure const_iterator_ss.inc_operator;
+begin
+ inc(m_span_idx );
+
+ init_span;
+
+end;
+
+{ INIT_SPAN }
+procedure const_iterator_ss.init_span;
+var
+ s : span_data_ss_ptr;
+
+begin
+ s:=m_storage.span_by_index(m_span_idx );
+
+ m_span.x :=s.x;
+ m_span.len :=s.len;
+ m_span.covers:=m_storage.covers_by_index(s.covers_id );
+
+end;
+
+{ CONSTRUCT }
+constructor embedded_scanline_ss.Construct;
+begin
+ m_storage:=storage;
+
+ setup(0 );
+
+end;
+
+{ RESET }
+procedure embedded_scanline_ss.reset;
+begin
+end;
+
+{ Y }
+function embedded_scanline_ss.y;
+begin
+ result:=m_scanline.y;
+
+end;
+
+{ NUM_SPANS }
+function embedded_scanline_ss.num_spans;
+begin
+ result:=m_scanline.num_spans;
+
+end;
+
+{ BEGIN_ }
+function embedded_scanline_ss.begin_;
+begin
+ m_result.Construct(@self );
+
+ result:=@m_result;
+
+end;
+
+{ SZ_OF_SPAN }
+function embedded_scanline_ss.sz_of_span;
+begin
+ result:=sizeof(span_ss );
+
+end;
+
+{ IS_PLAIN_SPAN }
+function embedded_scanline_ss.is_plain_span;
+begin
+ result:=false;
+
+end;
+
+{ IS_EMBEDDED }
+function embedded_scanline_ss.is_embedded;
+begin
+ result:=true;
+
+end;
+
+{ SETUP }
+procedure embedded_scanline_ss.setup;
+begin
+ m_scanline_idx:=scanline_idx;
+ m_scanline :=m_storage.scanline_by_index(m_scanline_idx )^;
+
+end;
+
+{ CONSTRUCT }
+constructor scanline_storage_aa.Construct;
+begin
+ m_covers.Construct (sizeof(int8u ) );
+ m_spans.Construct (256 - 2 ,sizeof(span_data_ss ) ,10 ); // Block increment size
+ m_scanlines.Construct(sizeof(scanline_data_ss ) ,8 );
+
+ m_min_x:=$7FFFFFFF;
+ m_min_y:=$7FFFFFFF;
+ m_max_x:=-$7FFFFFFF;
+ m_max_y:=-$7FFFFFFF;
+
+ m_cur_scanline:=0;
+
+ m_fake_scanline.y :=0;
+ m_fake_scanline.num_spans :=0;
+ m_fake_scanline.start_span:=0;
+
+ m_fake_span.x :=0;
+ m_fake_span.len :=0;
+ m_fake_span.covers_id:=0;
+
+end;
+
+{ DESTRUCT }
+destructor scanline_storage_aa.Destruct;
+begin
+ m_covers.Destruct;
+ m_spans.Destruct;
+ m_scanlines.Destruct;
+
+end;
+
+{ PREPARE }
+procedure scanline_storage_aa.prepare;
+begin
+ m_covers.remove_all;
+ m_scanlines.remove_all;
+ m_spans.remove_all;
+
+ m_min_x:=$7FFFFFFF;
+ m_min_y:=$7FFFFFFF;
+ m_max_x:=-$7FFFFFFF;
+ m_max_y:=-$7FFFFFFF;
+
+ m_cur_scanline:=0;
+
+end;
+
+{ RENDER }
+procedure scanline_storage_aa.render;
+var
+ sl_this : scanline_data_ss;
+
+ y ,x1 ,x2 ,len : int;
+
+ num_spans ,ss : unsigned;
+
+ span_pl : span_ptr;
+ span_obj : span_obj_ptr;
+
+ sp : span_data_ss;
+
+begin
+ y:=sl.y;
+
+ if y < m_min_y then
+ m_min_y:=y;
+
+ if y > m_max_y then
+ m_max_y:=y;
+
+ sl_this.y :=y;
+ sl_this.num_spans :=sl.num_spans;
+ sl_this.start_span:=m_spans.size;
+
+ num_spans:=sl_this.num_spans;
+
+ span_pl :=NIL;
+ span_obj:=NIL;
+
+ if sl.is_plain_span then
+ begin
+ span_pl:=sl.begin_;
+
+ ss:=sl.sz_of_span;
+
+ end
+ else
+ span_obj:=sl.begin_;
+
+ repeat
+ if span_pl <> NIL then
+ begin
+ sp.x :=span_pl.x;
+ sp.len:=span_pl.len;
+
+ end
+ else
+ begin
+ sp.x :=span_obj.x;
+ sp.len:=span_obj.len;
+
+ end;
+
+ len:=Abs(sp.len );
+
+ if span_pl <> NIL then
+ sp.covers_id:=m_covers.add_cells(span_pl.covers ,unsigned(len ) )
+ else
+ sp.covers_id:=m_covers.add_cells(span_obj.covers ,unsigned(len ) );
+
+ m_spans.add(@sp );
+
+ x1:=sp.x;
+ x2:=sp.x + len - 1;
+
+ if x1 < m_min_x then
+ m_min_x:=x1;
+
+ if x2 > m_max_x then
+ m_max_x:=x2;
+
+ dec(num_spans );
+
+ if num_spans = 0 then
+ break;
+
+ if span_pl <> NIL then
+ inc(ptrcomp(span_pl ) ,ss )
+ else
+ span_obj.inc_operator;
+
+ until false;
+
+ m_scanlines.add(@sl_this );
+
+end;
+
+{ _MIN_X }
+function scanline_storage_aa._min_x;
+begin
+ result:=m_min_x;
+
+end;
+
+{ _MIN_Y }
+function scanline_storage_aa._min_y;
+begin
+ result:=m_min_y;
+
+end;
+
+{ _MAX_X }
+function scanline_storage_aa._max_x;
+begin
+ result:=m_max_x;
+
+end;
+
+{ _MAX_Y }
+function scanline_storage_aa._max_y;
+begin
+ result:=m_max_y;
+
+end;
+
+{ REWIND_SCANLINES }
+function scanline_storage_aa.rewind_scanlines;
+begin
+ m_cur_scanline:=0;
+
+ result:=m_scanlines.size > 0;
+
+end;
+
+{ SWEEP_SCANLINE }
+function scanline_storage_aa.sweep_scanline;
+var
+ sl_this : scanline_data_ss_ptr;
+
+ num_spans ,span_idx : unsigned;
+
+ sp : span_data_ss_ptr;
+
+ covers : int8u_ptr;
+
+begin
+ sl.reset_spans;
+
+ repeat
+ if m_cur_scanline >= m_scanlines.size then
+ begin
+ result:=false;
+
+ exit;
+
+ end;
+
+ sl_this:=m_scanlines.array_operator(m_cur_scanline );
+
+ num_spans:=sl_this.num_spans;
+ span_idx :=sl_this.start_span;
+
+ repeat
+ sp:=m_spans.array_operator(span_idx );
+
+ inc(span_idx );
+
+ covers:=covers_by_index(sp.covers_id );
+
+ if sp.len < 0 then
+ sl.add_span(sp.x ,unsigned(-sp.len ) ,covers^ )
+ else
+ sl.add_cells(sp.x ,sp.len ,covers );
+
+ dec(num_spans );
+
+ until num_spans = 0;
+
+ inc(m_cur_scanline );
+
+ if sl.num_spans <> 0 then
+ begin
+ sl.finalize(sl_this.y );
+
+ break;
+
+ end;
+
+ until false;
+
+ result:=true;
+
+end;
+
+{ SWEEP_SCANLINE }
+function scanline_storage_aa.sweep_scanline_em;
+begin
+ repeat
+ if m_cur_scanline >= m_scanlines.size then
+ begin
+ result:=false;
+
+ exit;
+
+ end;
+
+ sl.setup(m_cur_scanline );
+
+ inc(m_cur_scanline );
+
+ until sl.num_spans <> 0;
+
+ result:=true;
+
+end;
+
+{ BYTE_SIZE }
+function scanline_storage_aa.byte_size;
+var
+ i ,size ,num_spans ,span_idx : unsigned;
+
+ sl_this : scanline_data_ss_ptr;
+
+ sp : span_data_ss_ptr;
+
+begin
+ size:=sizeof(int32 ) * 4; // min_x, min_y, max_x, max_y
+
+ i:=0;
+
+ while i < m_scanlines.size do
+ begin
+ inc(size ,sizeof(int32 ) * 3 ); // scanline size in bytes, Y, num_spans
+
+ sl_this:=m_scanlines.array_operator(i );
+
+ num_spans:=sl_this.num_spans;
+ span_idx :=sl_this.start_span;
+
+ repeat
+ sp:=m_spans.array_operator(span_idx );
+
+ inc(span_idx );
+ inc(size ,sizeof(int32 ) * 2 ); // X, span_len
+
+ if sp.len < 0 then
+ inc(size ,sizeof(int8u ) ) // cover
+ else
+ inc(size ,sizeof(int8u ) * unsigned(sp.len ) ); // covers
+
+ dec(num_spans );
+
+ until num_spans = 0;
+
+ inc(i );
+
+ end;
+
+ result:=size;
+
+end;
+
+{ WRITE_INT32 }
+procedure scanline_storage_aa.write_int32;
+begin
+ int8u_ptr(ptrcomp(dst ) + 0 * sizeof(int8u ) )^:=int32_int8u(val )._0;
+ int8u_ptr(ptrcomp(dst ) + 1 * sizeof(int8u ) )^:=int32_int8u(val )._1;
+ int8u_ptr(ptrcomp(dst ) + 2 * sizeof(int8u ) )^:=int32_int8u(val )._2;
+ int8u_ptr(ptrcomp(dst ) + 3 * sizeof(int8u ) )^:=int32_int8u(val )._3;
+
+end;
+
+{ SERIALIZE }
+procedure scanline_storage_aa.serialize;
+var
+ i ,num_spans ,span_idx : unsigned;
+
+ sl_this : scanline_data_ss_ptr;
+
+ sp : span_data_ss_ptr;
+
+ covers : int8u_ptr;
+
+ size_ptr : int8u_ptr;
+
+begin
+ write_int32(data ,_min_x ); // min_x
+ inc(ptrcomp(data ) ,sizeof(int32 ) );
+
+ write_int32(data ,_min_y ); // min_y
+ inc(ptrcomp(data ) ,sizeof(int32 ) );
+
+ write_int32(data ,_max_x ); // max_x
+ inc(ptrcomp(data ) ,sizeof(int32 ) );
+
+ write_int32(data ,_max_y ); // max_y
+ inc(ptrcomp(data ) ,sizeof(int32 ) );
+
+ i:=0;
+
+ while i < m_scanlines.size do
+ begin
+ sl_this :=m_scanlines.array_operator(i );
+ size_ptr:=data;
+
+ inc(ptrcomp(data ) ,sizeof(int32 ) ); // Reserve space for scanline size in bytes
+
+ write_int32(data ,sl_this.y ); // Y
+ inc(ptrcomp(data ) ,sizeof(int32 ) );
+
+ write_int32(data ,sl_this.num_spans ); // num_spans
+ inc(ptrcomp(data ) ,sizeof(int32 ) );
+
+ num_spans:=sl_this.num_spans;
+ span_idx :=sl_this.start_span;
+
+ repeat
+ sp:=m_spans.array_operator(span_idx );
+
+ inc(span_idx );
+
+ covers:=covers_by_index(sp.covers_id );
+
+ write_int32(data ,sp.x ); // X
+ inc(ptrcomp(data ) ,sizeof(int32 ) );
+
+ write_int32(data ,sp.len ); // span_len
+ inc(ptrcomp(data ) ,sizeof(int32 ) );
+
+ if sp.len < 0 then
+ begin
+ move(covers^ ,data^ ,sizeof(int8u ) );
+ inc (ptrcomp(data ) ,sizeof(int8u ) );
+
+ end
+ else
+ begin
+ move(covers^ ,data^ ,unsigned(sp.len ) * sizeof(int8u ) );
+ inc (ptrcomp(data ) ,sizeof(int8u ) * unsigned(sp.len ) );
+
+ end;
+
+ dec(num_spans );
+
+ until num_spans = 0;
+
+ write_int32(size_ptr ,ptrcomp(data ) - ptrcomp(size_ptr ) );
+
+ inc(i );
+
+ end;
+
+end;
+
+{ SCANLINE_BY_INDEX }
+function scanline_storage_aa.scanline_by_index;
+begin
+ if i < m_scanlines.size then
+ result:=m_scanlines.array_operator(i )
+ else
+ result:=@m_fake_scanline;
+
+end;
+
+{ SPAN_BY_INDEX }
+function scanline_storage_aa.span_by_index;
+begin
+ if i < m_spans.size then
+ result:=m_spans.array_operator(i )
+ else
+ result:=@m_fake_span;
+
+end;
+
+{ COVERS_BY_INDEX }
+function scanline_storage_aa.covers_by_index;
+begin
+ result:=m_covers.array_operator(i );
+
+end;
+
+{ CONSTRUCT }
+constructor scanline_storage_aa16.Construct;
+begin
+ m_covers.Construct (sizeof(int16u ) );
+ m_spans.Construct (256 - 2 ,sizeof(span_data_ss ) ,10 ); // Block increment size
+ m_scanlines.Construct(sizeof(scanline_data_ss ) ,8 );
+
+ m_min_x:=$7FFFFFFF;
+ m_min_y:=$7FFFFFFF;
+ m_max_x:=-$7FFFFFFF;
+ m_max_y:=-$7FFFFFFF;
+
+ m_cur_scanline:=0;
+
+ m_fake_scanline.y :=0;
+ m_fake_scanline.num_spans :=0;
+ m_fake_scanline.start_span:=0;
+
+ m_fake_span.x :=0;
+ m_fake_span.len :=0;
+ m_fake_span.covers_id:=0;
+
+end;
+
+{ SWEEP_SCANLINE }
+function scanline_storage_aa16.sweep_scanline;
+var
+ sl_this : scanline_data_ss_ptr;
+
+ num_spans ,span_idx : unsigned;
+
+ sp : span_data_ss_ptr;
+
+ covers : int16u_ptr;
+
+begin
+ sl.reset_spans;
+
+ repeat
+ if m_cur_scanline >= m_scanlines.size then
+ begin
+ result:=false;
+
+ exit;
+
+ end;
+
+ sl_this:=m_scanlines.array_operator(m_cur_scanline );
+
+ num_spans:=sl_this.num_spans;
+ span_idx :=sl_this.start_span;
+
+ repeat
+ sp:=m_spans.array_operator(span_idx );
+
+ inc(span_idx );
+
+ covers:=covers_by_index(sp.covers_id );
+
+ if sp.len < 0 then
+ sl.add_span(sp.x ,unsigned(-sp.len ) ,covers^ )
+ else
+ sl.add_cells(sp.x ,sp.len ,int8u_ptr(covers ) );
+
+ dec(num_spans );
+
+ until num_spans = 0;
+
+ inc(m_cur_scanline );
+
+ if sl.num_spans <> 0 then
+ begin
+ sl.finalize(sl_this.y );
+
+ break;
+
+ end;
+
+ until false;
+
+ result:=true;
+
+end;
+
+{ BYTE_SIZE }
+function scanline_storage_aa16.byte_size;
+var
+ i ,size ,num_spans ,span_idx : unsigned;
+
+ sl_this : scanline_data_ss_ptr;
+
+ sp : span_data_ss_ptr;
+
+begin
+ size:=sizeof(int32 ) * 4; // min_x, min_y, max_x, max_y
+
+ i:=0;
+
+ while i < m_scanlines.size do
+ begin
+ inc(size ,sizeof(int32 ) * 3 ); // scanline size in bytes, Y, num_spans
+
+ sl_this:=m_scanlines.array_operator(i );
+
+ num_spans:=sl_this.num_spans;
+ span_idx :=sl_this.start_span;
+
+ repeat
+ sp:=m_spans.array_operator(span_idx );
+
+ inc(span_idx );
+ inc(size ,sizeof(int32 ) * 2 ); // X, span_len
+
+ if sp.len < 0 then
+ inc(size ,sizeof(int16u ) ) // cover
+ else
+ inc(size ,sizeof(int16u ) * unsigned(sp.len ) ); // covers
+
+ dec(num_spans );
+
+ until num_spans = 0;
+
+ inc(i );
+
+ end;
+
+ result:=size;
+
+end;
+
+{ SERIALIZE }
+procedure scanline_storage_aa16.serialize;
+var
+ i ,num_spans ,span_idx : unsigned;
+
+ sl_this : scanline_data_ss_ptr;
+
+ sp : span_data_ss_ptr;
+
+ covers : int16u_ptr;
+
+ size_ptr : int8u_ptr;
+
+begin
+ write_int32(data ,_min_x ); // min_x
+ inc(ptrcomp(data ) ,sizeof(int32 ) );
+
+ write_int32(data ,_min_y ); // min_y
+ inc(ptrcomp(data ) ,sizeof(int32 ) );
+
+ write_int32(data ,_max_x ); // max_x
+ inc(ptrcomp(data ) ,sizeof(int32 ) );
+
+ write_int32(data ,_max_y ); // max_y
+ inc(ptrcomp(data ) ,sizeof(int32 ) );
+
+ i:=0;
+
+ while i < m_scanlines.size do
+ begin
+ sl_this :=m_scanlines.array_operator(i );
+ size_ptr:=data;
+
+ inc(ptrcomp(data ) ,sizeof(int32 ) ); // Reserve space for scanline size in bytes
+
+ write_int32(data ,sl_this.y ); // Y
+ inc(ptrcomp(data ) ,sizeof(int32 ) );
+
+ write_int32(data ,sl_this.num_spans ); // num_spans
+ inc(ptrcomp(data ) ,sizeof(int32 ) );
+
+ num_spans:=sl_this.num_spans;
+ span_idx :=sl_this.start_span;
+
+ repeat
+ sp:=m_spans.array_operator(span_idx );
+
+ inc(span_idx );
+
+ covers:=covers_by_index(sp.covers_id );
+
+ write_int32(data ,sp.x ); // X
+ inc(ptrcomp(data ) ,sizeof(int32 ) );
+
+ write_int32(data ,sp.len ); // span_len
+ inc(ptrcomp(data ) ,sizeof(int32 ) );
+
+ if sp.len < 0 then
+ begin
+ move(covers^ ,data^ ,sizeof(int16u ) );
+ inc (ptrcomp(data ) ,sizeof(int16u ) );
+
+ end
+ else
+ begin
+ move(covers^ ,data^ ,unsigned(sp.len ) * sizeof(int16u ) );
+ inc (ptrcomp(data ) ,sizeof(int16u ) * unsigned(sp.len ) );
+
+ end;
+
+ dec(num_spans );
+
+ until num_spans = 0;
+
+ write_int32(size_ptr ,ptrcomp(data ) - ptrcomp(size_ptr ) );
+
+ inc(i );
+
+ end;
+
+end;
+
+{ CONSTRUCT }
+constructor scanline_storage_aa32.Construct;
+begin
+ m_covers.Construct (sizeof(int32u ) );
+ m_spans.Construct (256 - 2 ,sizeof(span_data_ss ) ,10 ); // Block increment size
+ m_scanlines.Construct(sizeof(scanline_data_ss ) ,8 );
+
+ m_min_x:=$7FFFFFFF;
+ m_min_y:=$7FFFFFFF;
+ m_max_x:=-$7FFFFFFF;
+ m_max_y:=-$7FFFFFFF;
+
+ m_cur_scanline:=0;
+
+ m_fake_scanline.y :=0;
+ m_fake_scanline.num_spans :=0;
+ m_fake_scanline.start_span:=0;
+
+ m_fake_span.x :=0;
+ m_fake_span.len :=0;
+ m_fake_span.covers_id:=0;
+
+end;
+
+{ SWEEP_SCANLINE }
+function scanline_storage_aa32.sweep_scanline;
+var
+ sl_this : scanline_data_ss_ptr;
+
+ num_spans ,span_idx : unsigned;
+
+ sp : span_data_ss_ptr;
+
+ covers : int32u_ptr;
+
+begin
+ sl.reset_spans;
+
+ repeat
+ if m_cur_scanline >= m_scanlines.size then
+ begin
+ result:=false;
+
+ exit;
+
+ end;
+
+ sl_this:=m_scanlines.array_operator(m_cur_scanline );
+
+ num_spans:=sl_this.num_spans;
+ span_idx :=sl_this.start_span;
+
+ repeat
+ sp:=m_spans.array_operator(span_idx );
+
+ inc(span_idx );
+
+ covers:=covers_by_index(sp.covers_id );
+
+ if sp.len < 0 then
+ sl.add_span(sp.x ,unsigned(-sp.len ) ,covers^ )
+ else
+ sl.add_cells(sp.x ,sp.len ,int8u_ptr(covers ) );
+
+ dec(num_spans );
+
+ until num_spans = 0;
+
+ inc(m_cur_scanline );
+
+ if sl.num_spans <> 0 then
+ begin
+ sl.finalize(sl_this.y );
+
+ break;
+
+ end;
+
+ until false;
+
+ result:=true;
+
+end;
+
+{ BYTE_SIZE }
+function scanline_storage_aa32.byte_size;
+var
+ i ,size ,num_spans ,span_idx : unsigned;
+
+ sl_this : scanline_data_ss_ptr;
+
+ sp : span_data_ss_ptr;
+
+begin
+ size:=sizeof(int32 ) * 4; // min_x, min_y, max_x, max_y
+
+ i:=0;
+
+ while i < m_scanlines.size do
+ begin
+ inc(size ,sizeof(int32 ) * 3 ); // scanline size in bytes, Y, num_spans
+
+ sl_this:=m_scanlines.array_operator(i );
+
+ num_spans:=sl_this.num_spans;
+ span_idx :=sl_this.start_span;
+
+ repeat
+ sp:=m_spans.array_operator(span_idx );
+
+ inc(span_idx );
+ inc(size ,sizeof(int32 ) * 2 ); // X, span_len
+
+ if sp.len < 0 then
+ inc(size ,sizeof(int32u ) ) // cover
+ else
+ inc(size ,sizeof(int32u ) * unsigned(sp.len ) ); // covers
+
+ dec(num_spans );
+
+ until num_spans = 0;
+
+ inc(i );
+
+ end;
+
+ result:=size;
+
+end;
+
+{ SERIALIZE }
+procedure scanline_storage_aa32.serialize;
+var
+ i ,num_spans ,span_idx : unsigned;
+
+ sl_this : scanline_data_ss_ptr;
+
+ sp : span_data_ss_ptr;
+
+ covers : int32u_ptr;
+
+ size_ptr : int8u_ptr;
+
+begin
+ write_int32(data ,_min_x ); // min_x
+ inc(ptrcomp(data ) ,sizeof(int32 ) );
+
+ write_int32(data ,_min_y ); // min_y
+ inc(ptrcomp(data ) ,sizeof(int32 ) );
+
+ write_int32(data ,_max_x ); // max_x
+ inc(ptrcomp(data ) ,sizeof(int32 ) );
+
+ write_int32(data ,_max_y ); // max_y
+ inc(ptrcomp(data ) ,sizeof(int32 ) );
+
+ i:=0;
+
+ while i < m_scanlines.size do
+ begin
+ sl_this :=m_scanlines.array_operator(i );
+ size_ptr:=data;
+
+ inc(ptrcomp(data ) ,sizeof(int32 ) ); // Reserve space for scanline size in bytes
+
+ write_int32(data ,sl_this.y ); // Y
+ inc(ptrcomp(data ) ,sizeof(int32 ) );
+
+ write_int32(data ,sl_this.num_spans ); // num_spans
+ inc(ptrcomp(data ) ,sizeof(int32 ) );
+
+ num_spans:=sl_this.num_spans;
+ span_idx :=sl_this.start_span;
+
+ repeat
+ sp:=m_spans.array_operator(span_idx );
+
+ inc(span_idx );
+
+ covers:=covers_by_index(sp.covers_id );
+
+ write_int32(data ,sp.x ); // X
+ inc(ptrcomp(data ) ,sizeof(int32 ) );
+
+ write_int32(data ,sp.len ); // span_len
+ inc(ptrcomp(data ) ,sizeof(int32 ) );
+
+ if sp.len < 0 then
+ begin
+ move(covers^ ,data^ ,sizeof(int32u ) );
+ inc (ptrcomp(data ) ,sizeof(int32u ) );
+
+ end
+ else
+ begin
+ move(covers^ ,data^ ,unsigned(sp.len ) * sizeof(int32u ) );
+ inc (ptrcomp(data ) ,sizeof(int32u ) * unsigned(sp.len ) );
+
+ end;
+
+ dec(num_spans );
+
+ until num_spans = 0;
+
+ write_int32(size_ptr ,ptrcomp(data ) - ptrcomp(size_ptr ) );
+
+ inc(i );
+
+ end;
+
+end;
+
+{ CONSTRUCT }
+constructor const_iterator_sa.Construct;
+begin
+ m_ptr:=sl.m_ptr;
+ m_dx :=sl.m_dx;
+ m_sz :=sz;
+
+ init_span;
+
+end;
+
+{ X }
+function const_iterator_sa.x;
+begin
+ result:=m_span.x;
+
+end;
+
+{ LEN }
+function const_iterator_sa.len;
+begin
+ result:=m_span.len;
+
+end;
+
+{ COVERS }
+function const_iterator_sa.covers;
+begin
+ result:=m_span.covers;
+
+end;
+
+{ INC_OPERATOR }
+procedure const_iterator_sa.inc_operator;
+begin
+ if m_span.len < 0 then
+ inc(ptrcomp(m_ptr ) ,m_sz )
+ else
+ inc(ptrcomp(m_ptr ) ,m_span.len * m_sz );
+
+ init_span;
+
+end;
+
+{ INIT_SPAN }
+procedure const_iterator_sa.init_span;
+begin
+ m_span.x :=read_int32 + m_dx;
+ m_span.len :=read_int32;
+ m_span.covers:=m_ptr;
+
+end;
+
+{ READ_INT32 }
+function const_iterator_sa.read_int32;
+begin
+ int32_int8u(result )._0:=m_ptr^; inc(ptrcomp(m_ptr ) ,sizeof(int8u ) );
+ int32_int8u(result )._1:=m_ptr^; inc(ptrcomp(m_ptr ) ,sizeof(int8u ) );
+ int32_int8u(result )._2:=m_ptr^; inc(ptrcomp(m_ptr ) ,sizeof(int8u ) );
+ int32_int8u(result )._3:=m_ptr^; inc(ptrcomp(m_ptr ) ,sizeof(int8u ) );
+
+end;
+
+{ CONSTRUCT }
+constructor embedded_scanline_sa.Construct;
+begin
+ m_ptr:=NIL;
+ m_y :=0;
+ m_sz :=sz;
+
+ m_num_spans:=0;
+
+end;
+
+{ RESET }
+procedure embedded_scanline_sa.reset;
+begin
+end;
+
+{ Y }
+function embedded_scanline_sa.y;
+begin
+ result:=m_y;
+
+end;
+
+{ NUM_SPANS }
+function embedded_scanline_sa.num_spans;
+begin
+ result:=m_num_spans;
+
+end;
+
+{ BEGIN_ }
+function embedded_scanline_sa.begin_;
+begin
+ m_result.Construct(@self ,m_sz );
+
+ result:=@m_result;
+
+end;
+
+{ SZ_OF_SPAN }
+function embedded_scanline_sa.sz_of_span;
+begin
+ result:=sizeof(span_ss );
+
+end;
+
+{ IS_PLAIN_SPAN }
+function embedded_scanline_sa.is_plain_span;
+begin
+ result:=false;
+
+end;
+
+{ IS_EMBEDDED }
+function embedded_scanline_sa.is_embedded;
+begin
+ result:=true;
+
+end;
+
+{ INIT }
+procedure embedded_scanline_sa.init;
+begin
+ m_ptr :=ptr;
+ m_y :=read_int32 + dy;
+ m_num_spans:=unsigned(read_int32 );
+ m_dx :=dx;
+
+end;
+
+{ READ_INT32 }
+function embedded_scanline_sa.read_int32;
+begin
+ int32_int8u(result )._0:=m_ptr^; inc(ptrcomp(m_ptr ) ,sizeof(int8u ) );
+ int32_int8u(result )._1:=m_ptr^; inc(ptrcomp(m_ptr ) ,sizeof(int8u ) );
+ int32_int8u(result )._2:=m_ptr^; inc(ptrcomp(m_ptr ) ,sizeof(int8u ) );
+ int32_int8u(result )._3:=m_ptr^; inc(ptrcomp(m_ptr ) ,sizeof(int8u ) );
+
+end;
+
+{ CONSTRUCT }
+constructor serialized_scanlines_adaptor_aa.Construct(sz : unsigned );
+begin
+ m_data:=NIL;
+ m_end :=NIL;
+ m_ptr :=NIL;
+
+ m_dx:=0;
+ m_dy:=0;
+
+ m_min_x:=$7FFFFFFF;
+ m_min_y:=$7FFFFFFF;
+ m_max_x:=-$7FFFFFFF;
+ m_max_y:=-$7FFFFFFF;
+
+ m_sz:=sz;
+
+end;
+
+{ CONSTRUCT }
+constructor serialized_scanlines_adaptor_aa.Construct(sz : unsigned; data : int8u_ptr; size : unsigned; dx ,dy : double );
+begin
+ m_data:=data;
+ m_end :=int8u_ptr(ptrcomp(data ) + size );
+ m_ptr :=data;
+
+ m_dx:=trunc(dx + 0.5 );
+ m_dy:=trunc(dy + 0.5 );
+
+ m_min_x:=$7FFFFFFF;
+ m_min_y:=$7FFFFFFF;
+ m_max_x:=-$7FFFFFFF;
+ m_max_y:=-$7FFFFFFF;
+
+ m_sz:=sz;
+
+end;
+
+{ INIT }
+procedure serialized_scanlines_adaptor_aa.init;
+begin
+ m_data:=data;
+ m_end :=int8u_ptr(ptrcomp(data ) + size );
+ m_ptr :=data;
+
+ m_dx:=trunc(dx + 0.5 );
+ m_dy:=trunc(dy + 0.5 );
+
+ m_min_x:=$7FFFFFFF;
+ m_min_y:=$7FFFFFFF;
+ m_max_x:=-$7FFFFFFF;
+ m_max_y:=-$7FFFFFFF;
+
+end;
+
+{ READ_INT32 }
+function serialized_scanlines_adaptor_aa.read_int32;
+begin
+ int32_int8u(result )._0:=m_ptr^; inc(ptrcomp(m_ptr ) ,sizeof(int8u ) );
+ int32_int8u(result )._1:=m_ptr^; inc(ptrcomp(m_ptr ) ,sizeof(int8u ) );
+ int32_int8u(result )._2:=m_ptr^; inc(ptrcomp(m_ptr ) ,sizeof(int8u ) );
+ int32_int8u(result )._3:=m_ptr^; inc(ptrcomp(m_ptr ) ,sizeof(int8u ) );
+
+end;
+
+{ READ_INT32U }
+function serialized_scanlines_adaptor_aa.read_int32u;
+begin
+ int32_int8u(result )._0:=m_ptr^; inc(ptrcomp(m_ptr ) ,sizeof(int8u ) );
+ int32_int8u(result )._1:=m_ptr^; inc(ptrcomp(m_ptr ) ,sizeof(int8u ) );
+ int32_int8u(result )._2:=m_ptr^; inc(ptrcomp(m_ptr ) ,sizeof(int8u ) );
+ int32_int8u(result )._3:=m_ptr^; inc(ptrcomp(m_ptr ) ,sizeof(int8u ) );
+
+end;
+
+{ REWIND_SCANLINES }
+function serialized_scanlines_adaptor_aa.rewind_scanlines;
+var
+ x : int;
+
+begin
+ m_ptr:=m_data;
+
+ if ptrcomp(m_ptr ) < ptrcomp(m_end ) then
+ begin
+ m_min_x:=read_int32 + m_dx;
+ m_min_y:=read_int32 + m_dy;
+ m_max_x:=read_int32 + m_dx;
+ m_max_y:=read_int32 + m_dy;
+
+ result:=true;
+
+ exit;
+
+ end;
+
+ result:=false;
+
+end;
+
+{ _MIN_X }
+function serialized_scanlines_adaptor_aa._min_x;
+begin
+ result:=m_min_x;
+
+end;
+
+{ _MIN_Y }
+function serialized_scanlines_adaptor_aa._min_y;
+begin
+ result:=m_min_y;
+
+end;
+
+{ _MAX_X }
+function serialized_scanlines_adaptor_aa._max_x;
+begin
+ result:=m_max_x;
+
+end;
+
+{ _MAX_Y }
+function serialized_scanlines_adaptor_aa._max_y;
+begin
+ result:=m_max_y;
+
+end;
+
+{ SWEEP_SCANLINE }
+function serialized_scanlines_adaptor_aa.sweep_scanline;
+var
+ y ,x ,len : int;
+
+ num_spans : unsigned;
+
+begin
+ sl.reset_spans;
+
+ repeat
+ if ptrcomp(m_ptr ) >= ptrcomp(m_end ) then
+ begin
+ result:=false;
+
+ exit;
+
+ end;
+
+ read_int32; // Skip scanline size in bytes
+
+ y :=read_int32 + m_dy;
+ num_spans:=read_int32;
+
+ repeat
+ x :=read_int32 + m_dx;
+ len:=read_int32;
+
+ if len < 0 then
+ begin
+ sl.add_span(x ,unsigned(-len ) ,m_ptr^ );
+
+ inc(ptrcomp(m_ptr ) ,m_sz );
+
+ end
+ else
+ begin
+ sl.add_cells(x ,len ,m_ptr );
+
+ inc(ptrcomp(m_ptr ) ,len * m_sz );
+
+ end;
+
+ dec(num_spans );
+
+ until num_spans = 0;
+
+ if sl.num_spans <> 0 then
+ begin
+ sl.finalize(y );
+
+ break;
+
+ end;
+
+ until false;
+
+ result:=true;
+
+end;
+
+{ SWEEP_SCANLINE }
+function serialized_scanlines_adaptor_aa.sweep_scanline_em;
+var
+ byte_size : unsigned;
+
+begin
+ repeat
+ if ptrcomp(m_ptr ) >= ptrcomp(m_end ) then
+ begin
+ result:=false;
+
+ exit;
+
+ end;
+
+ byte_size:=read_int32u;
+
+ sl.init(m_ptr ,m_dx ,m_dy );
+
+ inc(ptrcomp(m_ptr ) ,byte_size - sizeof(int32 ) );
+
+ until sl.num_spans <> 0;
+
+ result:=true;
+
+end;
+
+{ CONSTRUCT }
+constructor serialized_scanlines_adaptor_aa8.Construct;
+begin
+ inherited Construct(sizeof(int8u ) );
+
+end;
+
+{ CONSTRUCT }
+constructor serialized_scanlines_adaptor_aa8.Construct(data : int8u_ptr; size : unsigned; dx ,dy : double );
+begin
+ inherited Construct(sizeof(int8u ) ,data ,size ,dx ,dy );
+
+end;
+
+{ CONSTRUCT }
+constructor serialized_scanlines_adaptor_aa16.Construct;
+begin
+ inherited Construct(sizeof(int16u ) );
+
+end;
+
+{ CONSTRUCT }
+constructor serialized_scanlines_adaptor_aa16.Construct(data : int8u_ptr; size : unsigned; dx ,dy : double );
+begin
+ inherited Construct(sizeof(int8u ) ,data ,size ,dx ,dy );
+
+end;
+
+{ CONSTRUCT }
+constructor serialized_scanlines_adaptor_aa32.Construct;
+begin
+ inherited Construct(sizeof(int32u ) );
+
+end;
+
+{ CONSTRUCT }
+constructor serialized_scanlines_adaptor_aa32.Construct(data : int8u_ptr; size : unsigned; dx ,dy : double );
+begin
+ inherited Construct(sizeof(int8u ) ,data ,size ,dx ,dy );
+
+end;
+
+END.
+
+
diff --git a/src/corelib/render/software/agg_scanline_storage_bin.pas b/src/corelib/render/software/agg_scanline_storage_bin.pas
new file mode 100644
index 00000000..037966af
--- /dev/null
+++ b/src/corelib/render/software/agg_scanline_storage_bin.pas
@@ -0,0 +1,1009 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// Adaptation for 32-bit screen coordinates has been sponsored by
+// Liberty Technology Systems, Inc., visit http://lib-sys.com
+//
+// Liberty Technology Systems, Inc. is the provider of
+// PostScript and PDF technology for software developers.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 14.02.2006-Milano: Unit port establishment
+//
+{ agg_scanline_storage_bin.pas }
+unit
+ agg_scanline_storage_bin ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+{$Q- }
+{$R- }
+uses
+ agg_basics ,
+ agg_array ,
+ agg_scanline ,
+ agg_renderer_scanline ,
+ agg_render_scanlines ,
+ agg_rasterizer_scanline_aa ;
+
+{ TYPES DEFINITION }
+type
+//-----------------------------------------------scanline_storage_bin
+ span_data_ptr = ^span_data;
+ span_data = record
+ x ,len : int32;
+
+ end;
+
+ scanline_data_ptr = ^scanline_data;
+ scanline_data = record
+ y : int;
+
+ num_spans ,start_span : unsigned;
+
+ end;
+
+ scanline_storage_bin_ptr = ^scanline_storage_bin;
+
+ embedded_scanline_b_ptr = ^embedded_scanline_b;
+
+ const_iterator_b_ptr = ^const_iterator_b;
+ const_iterator_b = object(span_obj )
+ m_storage : scanline_storage_bin_ptr;
+ m_span_idx : unsigned;
+ m_span : span_data;
+
+ constructor Construct(sl : embedded_scanline_b_ptr );
+
+ function x : int; virtual;
+ function len : int; virtual;
+
+ procedure inc_operator; virtual;
+
+ end;
+
+ embedded_scanline_b = object(scanline )
+ m_storage : scanline_storage_bin_ptr;
+ m_scanline : scanline_data;
+
+ m_scanline_idx : unsigned;
+
+ m_result : const_iterator_b;
+
+ constructor Construct(storage : scanline_storage_bin_ptr );
+
+ procedure reset(min_x ,max_x : int ); virtual;
+
+ function y : int; virtual;
+ function num_spans : unsigned; virtual;
+ function begin_ : pointer; virtual;
+
+ function sz_of_span : unsigned; virtual;
+ function is_plain_span : boolean; virtual;
+ function is_embedded : boolean; virtual;
+
+ procedure setup(scanline_idx : unsigned ); virtual;
+
+ end;
+
+ scanline_storage_bin = object(renderer_scanline )
+ m_spans ,
+ m_scanlines : pod_deque;
+
+ m_fake_span : span_data;
+ m_fake_scanline : scanline_data;
+
+ m_min_x ,
+ m_min_y ,
+ m_max_x ,
+ m_max_y : int;
+
+ m_cur_scanline : unsigned;
+
+ constructor Construct;
+ destructor Destruct;
+
+ // Renderer Interface
+ procedure prepare(u : unsigned ); virtual;
+ procedure render (sl : scanline_ptr ); virtual;
+
+ // Iterate scanlines interface
+ function _min_x : int; virtual;
+ function _min_y : int; virtual;
+ function _max_x : int; virtual;
+ function _max_y : int; virtual;
+
+ function rewind_scanlines : boolean; virtual;
+ function sweep_scanline(sl : scanline_ptr ) : boolean; virtual;
+
+ // Specialization for embedded_scanline
+ function sweep_scanline_em(sl : scanline_ptr ) : boolean; virtual;
+
+ function byte_size : unsigned;
+ procedure write_int32(dst : int8u_ptr; val : int32 );
+ procedure serialize (data : int8u_ptr );
+
+ function scanline_by_index(i : unsigned ) : scanline_data_ptr;
+ function span_by_index (i : unsigned ) : span_data_ptr;
+
+ end;
+
+//---------------------------------------serialized_scanlines_adaptor_bin
+ span_a_ptr = ^span_a;
+ span_a = record
+ x ,len : int32;
+
+ end;
+
+ embedded_scanline_a_ptr = ^embedded_scanline_a;
+
+ const_iterator_a_ptr = ^const_iterator_a;
+ const_iterator_a = object(span_obj )
+ m_ptr : int8u_ptr;
+ m_span : span_a;
+ m_dx : int;
+
+ constructor Construct(sl : embedded_scanline_a_ptr );
+
+ function x : int; virtual;
+ function len : int; virtual;
+
+ procedure inc_operator; virtual;
+
+ function read_int32 : int;
+
+ end;
+
+ embedded_scanline_a = object(scanline )
+ m_ptr : int8u_ptr;
+ m_y : int;
+
+ m_num_spans : unsigned;
+
+ m_dx : int;
+
+ m_result : const_iterator_a;
+
+ constructor Construct;
+
+ procedure reset(min_x ,max_x : int ); virtual;
+
+ function y : int; virtual;
+ function num_spans : unsigned; virtual;
+ function begin_ : pointer; virtual;
+
+ function sz_of_span : unsigned; virtual;
+ function is_plain_span : boolean; virtual;
+ function is_embedded : boolean; virtual;
+
+ function read_int32 : int;
+ procedure init(ptr : int8u_ptr; dx ,dy : int ); virtual;
+
+ end;
+
+ serialized_scanlines_adaptor_bin = object(rasterizer_scanline )
+ m_data ,
+ m_end ,
+ m_ptr : int8u_ptr;
+
+ m_dx ,
+ m_dy ,
+
+ m_min_x ,
+ m_min_y ,
+ m_max_x ,
+ m_max_y : int;
+
+ constructor Construct; overload;
+ constructor Construct(data : int8u_ptr; size : unsigned; dx ,dy : double ); overload;
+
+ procedure init(data : int8u_ptr; size : unsigned; dx ,dy : double );
+ function read_int32 : int;
+
+ // Iterate scanlines interface
+ function rewind_scanlines : boolean; virtual;
+
+ function _min_x : int; virtual;
+ function _min_y : int; virtual;
+ function _max_x : int; virtual;
+ function _max_y : int; virtual;
+
+ function sweep_scanline(sl : scanline_ptr ) : boolean; virtual;
+
+ // Specialization for embedded_scanline
+ function sweep_scanline_em(sl : scanline_ptr ) : boolean; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor const_iterator_b.Construct;
+begin
+ m_storage :=sl.m_storage;
+ m_span_idx:=sl.m_scanline.start_span;
+
+ m_span:=m_storage.span_by_index(m_span_idx )^;
+
+end;
+
+{ X }
+function const_iterator_b.x;
+begin
+ result:=m_span.x;
+
+end;
+
+{ LEN }
+function const_iterator_b.len;
+begin
+ result:=m_span.len;
+
+end;
+
+{ INC_OPERATOR }
+procedure const_iterator_b.inc_operator;
+begin
+ inc(m_span_idx );
+
+ m_span:=m_storage.span_by_index(m_span_idx )^;
+
+end;
+
+{ CONSTRUCT }
+constructor embedded_scanline_b.Construct;
+begin
+ m_storage:=storage;
+
+ setup(0 );
+
+end;
+
+{ RESET }
+procedure embedded_scanline_b.reset;
+begin
+end;
+
+{ Y }
+function embedded_scanline_b.y;
+begin
+ result:=m_scanline.y;
+
+end;
+
+{ NUM_SPANS }
+function embedded_scanline_b.num_spans;
+begin
+ result:=m_scanline.num_spans;
+
+end;
+
+{ BEGIN_ }
+function embedded_scanline_b.begin_;
+begin
+ m_result.Construct(@self );
+
+ result:=@m_result;
+
+end;
+
+{ SZ_OF_SPAN }
+function embedded_scanline_b.sz_of_span;
+begin
+ result:=sizeof(span_data );
+
+end;
+
+{ IS_PLAIN_SPAN }
+function embedded_scanline_b.is_plain_span;
+begin
+ result:=false;
+
+end;
+
+{ IS_EMBEDDED }
+function embedded_scanline_b.is_embedded;
+begin
+ result:=true;
+
+end;
+
+{ SETUP }
+procedure embedded_scanline_b.setup;
+begin
+ m_scanline_idx:=scanline_idx;
+ m_scanline :=m_storage.scanline_by_index(m_scanline_idx )^;
+
+end;
+
+{ CONSTRUCT }
+constructor scanline_storage_bin.Construct;
+begin
+ m_spans.Construct (256 - 2 ,sizeof(span_data ) ,10 ); // Block increment size
+ m_scanlines.Construct(sizeof(scanline_data ) ,8 );
+
+ m_min_x:=$7FFFFFFF;
+ m_min_y:=$7FFFFFFF;
+ m_max_x:=-$7FFFFFFF;
+ m_max_y:=-$7FFFFFFF;
+
+ m_cur_scanline :=0;
+ m_fake_scanline.y:=0;
+
+ m_fake_scanline.num_spans :=0;
+ m_fake_scanline.start_span:=0;
+
+ m_fake_span.x :=0;
+ m_fake_span.len:=0;
+
+end;
+
+{ DESTRUCT }
+destructor scanline_storage_bin.Destruct;
+begin
+ m_spans.Destruct;
+ m_scanlines.Destruct;
+
+end;
+
+{ PREPARE }
+procedure scanline_storage_bin.prepare;
+begin
+ m_scanlines.remove_all;
+ m_spans.remove_all;
+
+ m_min_x:=$7FFFFFFF;
+ m_min_y:=$7FFFFFFF;
+ m_max_x:=-$7FFFFFFF;
+ m_max_y:=-$7FFFFFFF;
+
+ m_cur_scanline:=0;
+
+end;
+
+{ RENDER }
+procedure scanline_storage_bin.render;
+var
+ y ,x1 ,x2 : int;
+
+ sl_this : scanline_data;
+ num_spans : unsigned;
+
+ span_pl : span_ptr;
+ span_obj : span_obj_ptr;
+
+ ss : unsigned;
+ sp : span_data;
+
+begin
+ y:=sl.y;
+
+ if y < m_min_y then
+ m_min_y:=y;
+
+ if y > m_max_y then
+ m_max_y:=y;
+
+ sl_this.y :=y;
+ sl_this.num_spans :=sl.num_spans;
+ sl_this.start_span:=m_spans.size;
+
+ num_spans:=sl_this.num_spans;
+
+ span_pl :=NIL;
+ span_obj:=NIL;
+
+ if sl.is_plain_span then
+ begin
+ span_pl:=sl.begin_;
+
+ ss:=sl.sz_of_span;
+
+ end
+ else
+ span_obj:=sl.begin_;
+
+ repeat
+ if span_pl <> NIL then
+ begin
+ sp.x :=span_pl.x;
+ sp.len:=span_pl.len;
+
+ end
+ else
+ begin
+ sp.x :=span_obj.x;
+ sp.len:=span_obj.len;
+
+ end;
+
+ m_spans.add(@sp );
+
+ x1:=sp.x;
+ x2:=sp.x + sp.len - 1;
+
+ if x1 < m_min_x then
+ m_min_x:=x1;
+
+ if x2 > m_max_x then
+ m_max_x:=x2;
+
+ dec(num_spans );
+
+ if num_spans = 0 then
+ break;
+
+ if span_pl <> NIL then
+ inc(ptrcomp(span_pl ) ,ss )
+ else
+ span_obj.inc_operator;
+
+ until false;
+
+ m_scanlines.add(@sl_this );
+
+end;
+
+{ _MIN_X }
+function scanline_storage_bin._min_x;
+begin
+ result:=m_min_x;
+
+end;
+
+{ _MIN_Y }
+function scanline_storage_bin._min_y;
+begin
+ result:=m_min_y;
+
+end;
+
+{ _MAX_X }
+function scanline_storage_bin._max_x;
+begin
+ result:=m_max_x;
+
+end;
+
+{ _MAX_Y }
+function scanline_storage_bin._max_y;
+begin
+ result:=m_max_y;
+
+end;
+
+{ REWIND_SCANLINES }
+function scanline_storage_bin.rewind_scanlines;
+begin
+ m_cur_scanline:=0;
+
+ result:=m_scanlines.size > 0;
+
+end;
+
+{ SWEEP_SCANLINE }
+function scanline_storage_bin.sweep_scanline;
+var
+ sl_this : scanline_data_ptr;
+
+ num_spans ,span_idx : unsigned;
+
+ sp : span_data_ptr;
+
+begin
+ sl.reset_spans;
+
+ repeat
+ if m_cur_scanline >= m_scanlines.size then
+ begin
+ result:=false;
+
+ exit;
+
+ end;
+
+ sl_this:=m_scanlines.array_operator(m_cur_scanline );
+
+ num_spans:=sl_this.num_spans;
+ span_idx :=sl_this.start_span;
+
+ repeat
+ sp:=m_spans.array_operator(span_idx );
+
+ inc(span_idx );
+
+ sl.add_span(sp.x ,sp.len ,cover_full );
+
+ dec(num_spans );
+
+ until num_spans = 0;
+
+ inc(m_cur_scanline );
+
+ if sl.num_spans <> 0 then
+ begin
+ sl.finalize(sl_this.y );
+
+ break;
+
+ end;
+
+ until false;
+
+ result:=true;
+
+end;
+
+{ SWEEP_SCANLINE }
+function scanline_storage_bin.sweep_scanline_em;
+begin
+ repeat
+ if m_cur_scanline >= m_scanlines.size then
+ begin
+ result:=false;
+
+ exit;
+
+ end;
+
+ sl.setup(m_cur_scanline );
+
+ inc(m_cur_scanline );
+
+ until sl.num_spans <> 0;
+
+ result:=true;
+
+end;
+
+{ BYTE_SIZE }
+function scanline_storage_bin.byte_size;
+var
+ i ,size : unsigned;
+
+begin
+ size:=sizeof(int32 ) * 4; // min_x, min_y, max_x, max_y
+
+ i:=0;
+
+ while i < m_scanlines.size do
+ begin
+ size:=
+ size +
+ sizeof(int32 ) * 2 + // Y, num_spans
+ unsigned(scanline_data_ptr(m_scanlines.array_operator(i ) ).num_spans ) * sizeof(int32 ) * 2; // X, span_len
+
+ inc(i );
+
+ end;
+
+ result:=size;
+
+end;
+
+{ WRITE_INT32 }
+procedure scanline_storage_bin.write_int32;
+begin
+ int8u_ptr(ptrcomp(dst ) + 0 * sizeof(int8u ) )^:=int32_int8u(val )._0;
+ int8u_ptr(ptrcomp(dst ) + 1 * sizeof(int8u ) )^:=int32_int8u(val )._1;
+ int8u_ptr(ptrcomp(dst ) + 2 * sizeof(int8u ) )^:=int32_int8u(val )._2;
+ int8u_ptr(ptrcomp(dst ) + 3 * sizeof(int8u ) )^:=int32_int8u(val )._3;
+
+end;
+
+{ SERIALIZE }
+procedure scanline_storage_bin.serialize;
+var
+ i ,num_spans ,span_idx : unsigned;
+
+ sl_this : scanline_data_ptr;
+
+ sp : span_data_ptr;
+
+begin
+ write_int32(data ,_min_x ); // min_x
+ inc(ptrcomp(data ) ,sizeof(int32 ) );
+
+ write_int32(data ,_min_y ); // min_y
+ inc(ptrcomp(data ) ,sizeof(int32 ) );
+
+ write_int32(data ,_max_x ); // max_x
+ inc(ptrcomp(data ) ,sizeof(int32 ) );
+
+ write_int32(data ,_max_y ); // max_y
+ inc(ptrcomp(data ) ,sizeof(int32 ) );
+
+ i:=0;
+
+ while i < m_scanlines.size do
+ begin
+ sl_this:=m_scanlines.array_operator(i );
+
+ write_int32(data ,sl_this.y ); // Y
+ inc(ptrcomp(data ) ,sizeof(int32 ) );
+
+ write_int32(data ,sl_this.num_spans ); // num_spans
+ inc(ptrcomp(data ) ,sizeof(int32 ) );
+
+ num_spans:=sl_this.num_spans;
+ span_idx :=sl_this.start_span;
+
+ repeat
+ sp:=m_spans.array_operator(span_idx );
+
+ inc(span_idx );
+
+ write_int32(data ,sp.x ); // X
+ inc(ptrcomp(data ) ,sizeof(int32 ) );
+
+ write_int32(data ,sp.len ); // len
+ inc(ptrcomp(data ) ,sizeof(int32 ) );
+
+ dec(num_spans );
+
+ until num_spans = 0;
+
+ inc(i );
+
+ end;
+
+end;
+
+{ SCANLINE_BY_INDEX }
+function scanline_storage_bin.scanline_by_index;
+begin
+ if i < m_scanlines.size then
+ result:=m_scanlines.array_operator(i )
+ else
+ result:=@m_fake_scanline;
+
+end;
+
+{ SPAN_BY_INDEX }
+function scanline_storage_bin.span_by_index;
+begin
+ if i < m_spans.size then
+ result:=m_spans.array_operator(i )
+ else
+ result:=@m_fake_span;
+
+end;
+
+{ CONSTRUCT }
+constructor const_iterator_a.Construct;
+begin
+ m_ptr:=sl.m_ptr;
+ m_dx :=sl.m_dx;
+
+ m_span.x :=read_int32 + m_dx;
+ m_span.len:=read_int32;
+
+end;
+
+{ X }
+function const_iterator_a.x;
+begin
+ result:=m_span.x;
+
+end;
+
+{ LEN }
+function const_iterator_a.len;
+begin
+ result:=m_span.len;
+
+end;
+
+{ INC_OPERATOR }
+procedure const_iterator_a.inc_operator;
+begin
+ m_span.x :=read_int32 + m_dx;
+ m_span.len:=read_int32;
+
+end;
+
+{ READ_INT32 }
+function const_iterator_a.read_int32;
+begin
+ int32_int8u(result )._0:=m_ptr^; inc(ptrcomp(m_ptr ) ,sizeof(int8u ) );
+ int32_int8u(result )._1:=m_ptr^; inc(ptrcomp(m_ptr ) ,sizeof(int8u ) );
+ int32_int8u(result )._2:=m_ptr^; inc(ptrcomp(m_ptr ) ,sizeof(int8u ) );
+ int32_int8u(result )._3:=m_ptr^; inc(ptrcomp(m_ptr ) ,sizeof(int8u ) );
+
+end;
+
+{ CONSTRUCT }
+constructor embedded_scanline_a.Construct;
+begin
+ m_ptr:=NIL;
+ m_y :=0;
+
+ m_num_spans:=0;
+
+end;
+
+{ RESET }
+procedure embedded_scanline_a.reset;
+begin
+end;
+
+{ Y }
+function embedded_scanline_a.y;
+begin
+ result:=m_y;
+
+end;
+
+{ NUM_SPANS }
+function embedded_scanline_a.num_spans;
+begin
+ result:=m_num_spans;
+
+end;
+
+{ BEGIN_ }
+function embedded_scanline_a.begin_;
+begin
+ m_result.Construct(@self );
+
+ result:=@m_result;
+
+end;
+
+{ SZ_OF_SPAN }
+function embedded_scanline_a.sz_of_span;
+begin
+ result:=sizeof(span_a );
+
+end;
+
+{ IS_PLAIN_SPAN }
+function embedded_scanline_a.is_plain_span;
+begin
+ result:=false;
+
+end;
+
+{ IS_EMBEDDED }
+function embedded_scanline_a.is_embedded;
+begin
+ result:=true;
+
+end;
+
+{ READ_INT32 }
+function embedded_scanline_a.read_int32;
+begin
+ int32_int8u(result )._0:=m_ptr^; inc(ptrcomp(m_ptr ) ,sizeof(int8u ) );
+ int32_int8u(result )._1:=m_ptr^; inc(ptrcomp(m_ptr ) ,sizeof(int8u ) );
+ int32_int8u(result )._2:=m_ptr^; inc(ptrcomp(m_ptr ) ,sizeof(int8u ) );
+ int32_int8u(result )._3:=m_ptr^; inc(ptrcomp(m_ptr ) ,sizeof(int8u ) );
+
+end;
+
+{ INIT }
+procedure embedded_scanline_a.init;
+begin
+ m_ptr :=ptr;
+ m_y :=read_int32 + dy;
+ m_num_spans:=unsigned(read_int32 );
+ m_dx :=dx;
+
+end;
+
+{ CONSTRUCT }
+constructor serialized_scanlines_adaptor_bin.Construct;
+begin
+ m_data:=NIL;
+ m_end :=NIL;
+ m_ptr :=NIL;
+
+ m_dx:=0;
+ m_dy:=0;
+
+ m_min_x:=$7FFFFFFF;
+ m_min_y:=$7FFFFFFF;
+ m_max_x:=-$7FFFFFFF;
+ m_max_y:=-$7FFFFFFF;
+
+end;
+
+{ CONSTRUCT }
+constructor serialized_scanlines_adaptor_bin.Construct(data : int8u_ptr; size : unsigned; dx ,dy : double );
+begin
+ m_data:=data;
+ m_end :=int8u_ptr(ptrcomp(data ) + size );
+ m_ptr :=data;
+
+ m_dx:=trunc(dx + 0.5 );
+ m_dy:=trunc(dy + 0.5 );
+
+ m_min_x:=$7FFFFFFF;
+ m_min_y:=$7FFFFFFF;
+ m_max_x:=-$7FFFFFFF;
+ m_max_y:=-$7FFFFFFF;
+
+end;
+
+{ INIT }
+procedure serialized_scanlines_adaptor_bin.init;
+begin
+ m_data:=data;
+ m_end :=int8u_ptr(ptrcomp(data ) + size );
+ m_ptr :=data;
+
+ m_dx:=trunc(dx + 0.5 );
+ m_dy:=trunc(dy + 0.5 );
+
+ m_min_x:=$7FFFFFFF;
+ m_min_y:=$7FFFFFFF;
+ m_max_x:=-$7FFFFFFF;
+ m_max_y:=-$7FFFFFFF;
+
+end;
+
+{ READ_INT32 }
+function serialized_scanlines_adaptor_bin.read_int32;
+begin
+ int32_int8u(result )._0:=m_ptr^; inc(ptrcomp(m_ptr ) ,sizeof(int8u ) );
+ int32_int8u(result )._1:=m_ptr^; inc(ptrcomp(m_ptr ) ,sizeof(int8u ) );
+ int32_int8u(result )._2:=m_ptr^; inc(ptrcomp(m_ptr ) ,sizeof(int8u ) );
+ int32_int8u(result )._3:=m_ptr^; inc(ptrcomp(m_ptr ) ,sizeof(int8u ) );
+
+end;
+
+{ REWIND_SCANLINES }
+function serialized_scanlines_adaptor_bin.rewind_scanlines;
+begin
+ m_ptr:=m_data;
+
+ if ptrcomp(m_ptr ) < ptrcomp(m_end ) then
+ begin
+ m_min_x:=read_int32 + m_dx;
+ m_min_y:=read_int32 + m_dy;
+ m_max_x:=read_int32 + m_dx;
+ m_max_y:=read_int32 + m_dy;
+
+ result:=true;
+
+ end
+ else
+ result:=false;
+
+end;
+
+{ _MIN_X }
+function serialized_scanlines_adaptor_bin._min_x;
+begin
+ result:=m_min_x;
+
+end;
+
+{ _MIN_Y }
+function serialized_scanlines_adaptor_bin._min_y;
+begin
+ result:=m_min_y;
+
+end;
+
+{ _MAX_X }
+function serialized_scanlines_adaptor_bin._max_x;
+begin
+ result:=m_max_x;
+
+end;
+
+{ _MAX_Y }
+function serialized_scanlines_adaptor_bin._max_y;
+begin
+ result:=m_max_y;
+
+end;
+
+{ SWEEP_SCANLINE }
+function serialized_scanlines_adaptor_bin.sweep_scanline;
+var
+ y ,x ,len : int;
+
+ num_spans : unsigned;
+
+begin
+ sl.reset_spans;
+
+ repeat
+ if ptrcomp(m_ptr ) >= ptrcomp(m_end ) then
+ begin
+ result:=false;
+
+ exit;
+
+ end;
+
+ y :=read_int32 + m_dy;
+ num_spans:=read_int32;
+
+ repeat
+ x :=read_int32 + m_dx;
+ len:=read_int32;
+
+ if len < 0 then
+ len:=-len;
+
+ sl.add_span(x ,unsigned(len ) ,cover_full );
+
+ inc(num_spans );
+
+ until num_spans = 0;
+
+ if sl.num_spans <> 0 then
+ begin
+ sl.finalize(y );
+
+ break;
+
+ end;
+
+ until false;
+
+ result:=true;
+
+end;
+
+{ SWEEP_SCANLINE }
+function serialized_scanlines_adaptor_bin.sweep_scanline_em;
+var
+ num_spans : int;
+
+begin
+ repeat
+ if ptrcomp(m_ptr ) >= ptrcomp(m_end ) then
+ begin
+ result:=false;
+
+ exit;
+
+ end;
+
+ sl.init(m_ptr ,m_dx ,m_dy );
+
+ // Jump to the next scanline
+ read_int32; // Y
+
+ num_spans:=read_int32; // num_spans
+
+ inc(ptrcomp(m_ptr ) ,num_spans * sizeof(int32 ) * 2 );
+
+ until sl.num_spans <> 0;
+
+ result:=true;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_scanline_u.pas b/src/corelib/render/software/agg_scanline_u.pas
new file mode 100644
index 00000000..3098fac9
--- /dev/null
+++ b/src/corelib/render/software/agg_scanline_u.pas
@@ -0,0 +1,393 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 4 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// Adaptation for 32-bit screen coordinates (scanline32_u) has been sponsored by
+// Liberty Technology Systems, Inc., visit http://lib-sys.com
+//
+// Liberty Technology Systems, Inc. is the provider of
+// PostScript and PDF technology for software developers.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 17.01.2006-Milano: Unit port establishment
+//
+{ agg_scanline_u.pas }
+unit
+ agg_scanline_u ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_scanline ,
+ agg_alpha_mask_u8 ;
+
+{ TYPES DEFINITION }
+type
+//==============================================================scanline_u
+//
+// Unpacked scanline container class
+//
+// This class is used to transfer data from a scanline rasterizer
+// to the rendering buffer. It's organized very simple. The class stores
+// information of horizontal spans to render it into a pixel-map buffer.
+// Each span has staring X, length, and an array of bytes that determine the
+// cover-values for each pixel.
+// Before using this class you should know the minimal and maximal pixel
+// coordinates of your scanline. The protocol of using is:
+// 1. reset(min_x, max_x)
+// 2. add_cell() / add_span() - accumulate scanline.
+// When forming one scanline the next X coordinate must be always greater
+// than the last stored one, i.e. it works only with ordered coordinates.
+// 3. Call finalize(y) and render the scanline.
+// 3. Call reset_spans() to prepare for the new scanline.
+//
+// 4. Rendering:
+//
+// Scanline provides an iterator class that allows you to extract
+// the spans and the cover values for each pixel. Be aware that clipping
+// has not been done yet, so you should perform it yourself.
+// Use scanline_u8::iterator to render spans:
+//-------------------------------------------------------------------------
+//
+// int y = sl.y(); // Y-coordinate of the scanline
+//
+// ************************************
+// ...Perform vertical clipping here...
+// ************************************
+//
+// scanline_u8::const_iterator span = sl.begin();
+//
+// unsigned char* row = m_rbuf->row(y); // The the address of the beginning
+// // of the current row
+//
+// unsigned num_spans = sl.num_spans(); // Number of spans. It's guaranteed that
+// // num_spans is always greater than 0.
+//
+// do
+// {
+// const scanline_u8::cover_type* covers =
+// span->covers; // The array of the cover values
+//
+// int num_pix = span->len; // Number of pixels of the span.
+// // Always greater than 0, still it's
+// // better to use "int" instead of
+// // "unsigned" because it's more
+// // convenient for clipping
+// int x = span->x;
+//
+// **************************************
+// ...Perform horizontal clipping here...
+// ...you have x, covers, and pix_count..
+// **************************************
+//
+// unsigned char* dst = row + x; // Calculate the start address of the row.
+// // In this case we assume a simple
+// // grayscale image 1-byte per pixel.
+// do
+// {
+// *dst++ = *covers++; // Hypotetical rendering.
+// }
+// while(--num_pix);
+//
+// ++span;
+// }
+// while(--num_spans); // num_spans cannot be 0, so this loop is quite safe
+//------------------------------------------------------------------------
+//
+// The question is: why should we accumulate the whole scanline when we
+// could render just separate spans when they're ready?
+// That's because using the scanline is generally faster. When is consists
+// of more than one span the conditions for the processor cash system
+// are better, because switching between two different areas of memory
+// (that can be very large) occurs less frequently.
+//------------------------------------------------------------------------
+ span_u8_ptr = ^span_u8;
+ span_u8 = record
+ x ,
+ len : int16;
+
+ covers : int8u_ptr;
+
+ end;
+
+ scanline_u8 = object(scanline )
+ m_min_x : int;
+ m_max_len : unsigned;
+ m_last_x ,
+ m_y : int;
+
+ m_covers : int8u_ptr;
+ m_spans ,
+ m_cur_span : span_u8_ptr;
+
+ constructor Construct;
+ destructor Destruct;
+
+ procedure reset(min_x ,max_x : int ); virtual;
+ procedure reset_spans; virtual;
+
+ procedure finalize (y_ : int ); virtual;
+ procedure add_cell (x : int; cover : unsigned ); virtual;
+ procedure add_cells(x : int; len : unsigned; covers : int8u_ptr ); virtual;
+ procedure add_span (x : int; len ,cover : unsigned ); virtual;
+
+ function y : int; virtual;
+ function num_spans : unsigned; virtual;
+ function begin_ : pointer; virtual;
+
+ function sz_of_span : unsigned; virtual;
+
+ end;
+
+ scanline_u8_am = object(scanline_u8 )
+ m_alpha_mask : alpha_mask_ptr;
+
+ constructor Construct; overload;
+ constructor Construct(am : alpha_mask_ptr ); overload;
+
+ procedure finalize(y_ : int ); virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor scanline_u8.Construct;
+begin
+ m_min_x :=0;
+ m_max_len:=0;
+ m_last_x :=$7FFFFFF0;
+
+ m_covers :=NIL;
+ m_spans :=NIL;
+ m_cur_span:=NIL;
+
+end;
+
+{ DESTRUCT }
+destructor scanline_u8.Destruct;
+begin
+ agg_freemem(pointer(m_spans ) ,m_max_len * sizeof(span_u8 ) );
+ agg_freemem(pointer(m_covers ) ,m_max_len * sizeof(int8u ) );
+
+end;
+
+{ RESET }
+procedure scanline_u8.reset;
+var
+ max_len : unsigned;
+
+begin
+ max_len:=max_x - min_x + 2;
+
+ if max_len > m_max_len then
+ begin
+ agg_freemem(pointer(m_spans ) ,m_max_len * sizeof(span_u8 ) );
+ agg_freemem(pointer(m_covers ) ,m_max_len * sizeof(int8u ) );
+
+ agg_getmem(pointer(m_covers ) ,max_len * sizeof(int8u ) );
+ agg_getmem(pointer(m_spans ) ,max_len * sizeof(span_u8 ) );
+
+ m_max_len:=max_len;
+
+ end;
+
+ m_last_x :=$7FFFFFF0;
+ m_min_x :=min_x;
+ m_cur_span:=m_spans;
+
+end;
+
+{ RESET_SPANS }
+procedure scanline_u8.reset_spans;
+begin
+ m_last_x :=$7FFFFFF0;
+ m_cur_span:=m_spans;
+
+end;
+
+{ FINALIZE }
+procedure scanline_u8.finalize;
+begin
+ m_y:=y_;
+
+end;
+
+{ ADD_CELL }
+procedure scanline_u8.add_cell;
+begin
+ dec(x ,m_min_x );
+
+ int8u_ptr(ptrcomp(m_covers ) + x * sizeof(int8u ) )^:=int8u(cover );
+
+ if x = m_last_x + 1 then
+ inc(m_cur_span.len )
+
+ else
+ begin
+ inc(ptrcomp(m_cur_span ) ,sizeof(span_u8 ) );
+
+ m_cur_span.x :=int16(x + m_min_x );
+ m_cur_span.len:=1;
+
+ m_cur_span.covers:=int8u_ptr(ptrcomp(m_covers ) + x * sizeof(int8u ) );
+
+ end;
+
+ m_last_x:=x;
+
+end;
+
+{ ADD_CELLS }
+procedure scanline_u8.add_cells;
+begin
+ dec (x ,m_min_x );
+ move(
+ covers^ ,
+ int8u_ptr(ptrcomp(m_covers ) + x )^ ,
+ len * sizeof(int8u ) );
+
+ if x = m_last_x + 1 then
+ inc(m_cur_span.len ,int16(len ) )
+
+ else
+ begin
+ inc(ptrcomp(m_cur_span ) ,sizeof(span_u8 ) );
+
+ m_cur_span.x :=int16(x + m_min_x );
+ m_cur_span.len :=int16(len );
+ m_cur_span.covers:=int8u_ptr(ptrcomp(m_covers ) + x * sizeof(int8u ) );
+
+ end;
+
+ m_last_x:=x + len - 1;
+
+end;
+
+{ ADD_SPAN }
+procedure scanline_u8.add_span;
+begin
+ dec(x ,m_min_x );
+
+ fillchar(int8u_ptr(ptrcomp(m_covers ) + x * sizeof(int8u ) )^ ,len ,cover );
+
+ if x = m_last_x + 1 then
+ inc(m_cur_span.len ,int16(len ) )
+
+ else
+ begin
+ inc(ptrcomp(m_cur_span ) ,sizeof(span_u8 ) );
+
+ m_cur_span.x :=int16(x + m_min_x );
+ m_cur_span.len :=int16(len );
+ m_cur_span.covers:=int8u_ptr(ptrcomp(m_covers ) + x * sizeof(int8u ) );
+
+ end;
+
+ m_last_x:=x + len - 1;
+
+end;
+
+{ Y }
+function scanline_u8.y;
+begin
+ result:=m_y;
+
+end;
+
+{ NUM_SPANS }
+function scanline_u8.num_spans;
+begin
+ result:=(ptrcomp(m_cur_span ) - ptrcomp(m_spans ) ) div sizeof(span_u8 );
+
+end;
+
+{ BEGIN_ }
+function scanline_u8.begin_;
+begin
+ result:=span_u8_ptr(ptrcomp(m_spans ) + sizeof(span_u8 ) );
+
+end;
+
+{ SZ_OF_SPAN }
+function scanline_u8.sz_of_span;
+begin
+ result:=sizeof(span_u8 );
+
+end;
+
+{ CONSTRUCT }
+constructor scanline_u8_am.Construct;
+begin
+ inherited Construct;
+
+ m_alpha_mask:=NIL;
+
+end;
+
+{ CONSTRUCT }
+constructor scanline_u8_am.Construct(am : alpha_mask_ptr );
+begin
+ inherited Construct;
+
+ m_alpha_mask:=am;
+
+end;
+
+{ FINALIZE }
+procedure scanline_u8_am.finalize;
+var
+ span : span_u8_ptr;
+
+ ss ,count : unsigned;
+
+begin
+ inherited finalize(y_ );
+
+ if m_alpha_mask <> NIL then
+ begin
+ span :=begin_;
+ ss :=sz_of_span;
+ count:=num_spans;
+
+ repeat
+ m_alpha_mask.combine_hspan(span.x ,y ,span.covers ,span.len );
+
+ inc(ptrcomp(span ) ,ss );
+ dec(count );
+
+ until count = 0;
+
+ end;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_shorten_path.pas b/src/corelib/render/software/agg_shorten_path.pas
new file mode 100644
index 00000000..7abeb71c
--- /dev/null
+++ b/src/corelib/render/software/agg_shorten_path.pas
@@ -0,0 +1,103 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 20.12.2005-Milano: Unit port establishment
+//
+{ agg_shorten_path.pas }
+unit
+ agg_shorten_path ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_vertex_sequence ;
+
+{ GLOBAL PROCEDURES }
+ procedure shorten_path(vs : vertex_sequence_ptr; s : double; closed : unsigned = 0 );
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ SHORTEN_PATH }
+procedure shorten_path;
+var
+ n : int;
+
+ d ,x ,y : double;
+
+ prev ,last : vertex_dist_ptr;
+
+begin
+ if (s > 0.0 ) and
+ (vs.size > 1 ) then
+ begin
+ n:=vs.size - 2;
+
+ while n <> 0 do
+ begin
+ d:=vertex_dist_ptr(vs.array_operator(n ) )^.dist;
+
+ if d > s then
+ break;
+
+ vs.remove_last;
+
+ s:=s - d;
+
+ dec(n );
+
+ end;
+
+ if vs.size < 2 then
+ vs.remove_all
+
+ else
+ begin
+ n:=vs.size - 1;
+
+ prev:=vs.array_operator(n - 1 );
+ last:=vs.array_operator(n );
+
+ d:=(prev.dist - s ) / prev.dist;
+
+ x:=prev.x + (last.x - prev.x ) * d;
+ y:=prev.y + (last.y - prev.y ) * d;
+ last.x:=x;
+ last.y:=y;
+
+ if not vs.func_operator_vertex_sequence(prev ,last ) then
+ vs.remove_last;
+
+ vs.close(boolean(closed <> 0 ) );
+
+ end;
+
+ end;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_simul_eq.pas b/src/corelib/render/software/agg_simul_eq.pas
new file mode 100644
index 00000000..7ab4c64c
--- /dev/null
+++ b/src/corelib/render/software/agg_simul_eq.pas
@@ -0,0 +1,240 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 06.02.2006-Milano: Unit port establishment
+//
+{ agg_simul_eq.pas }
+unit
+ agg_simul_eq ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ;
+
+{ GLOBAL PROCEDURES }
+ procedure swap_arrays (a1 ,a2 : double_ptr; n : unsigned );
+ function matrix_pivot (m : double_ptr; row ,Rows ,Cols : unsigned ) : int;
+ function simul_eq_solve(left ,right ,result_ : double_ptr; Size ,RightCols : unsigned ) : boolean;
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ SWAP_ARRAYS }
+procedure swap_arrays;
+var
+ i : unsigned;
+ tmp : double;
+
+begin
+ i:=0;
+
+ while i < n do
+ begin
+ tmp:=a1^;
+ a1^:=a2^;
+ a2^:=tmp;
+
+ inc(ptrcomp(a1 ) ,sizeof(double ) );
+ inc(ptrcomp(a2 ) ,sizeof(double ) );
+ inc(i );
+
+ end;
+
+end;
+
+{ MATRIX_PIVOT }
+function matrix_pivot;
+var
+ i : unsigned;
+ k : int;
+
+ max_val ,tmp : double;
+
+begin
+ k:=row;
+
+ max_val:=-1.0;
+
+ i:=row;
+
+ while i < Rows do
+ begin
+ tmp:=Abs(double_ptr(ptrcomp(m ) + (i * Cols + row ) * sizeof(double ) )^ );
+
+ if (tmp > max_val ) and
+ (tmp <> 0.0 ) then
+ begin
+ max_val:=tmp;
+
+ k:=i;
+
+ end;
+
+ inc(i );
+
+ end;
+
+ if double_ptr(ptrcomp(m ) + (k * Cols + row ) * sizeof(double ) )^ = 0.0 then
+ begin
+ result:=-1;
+
+ exit;
+
+ end;
+
+ if k <> row then
+ begin
+ swap_arrays(
+ double_ptr(ptrcomp(m ) + k * Cols * sizeof(double ) ) ,
+ double_ptr(ptrcomp(m ) + row * Cols * sizeof(double ) ) ,
+ Cols );
+
+ result:=k;
+
+ exit;
+
+ end;
+
+ result:=0;
+
+end;
+
+{ SIMUL_EQ_SOLVE }
+function simul_eq_solve;
+var
+ m : int;
+
+ i , j , k ,adx : unsigned;
+
+ a1 : double;
+ tmp : double_ptr;
+
+label
+ return_false ,free ;
+
+begin
+// Alloc
+ adx:=Size + RightCols;
+
+ agg_getmem(pointer(tmp ) ,Size * adx * sizeof(double ) );
+
+ for i:=0 to Size - 1 do
+ begin
+ for j:=0 to Size - 1 do
+ double_ptr(ptrcomp(tmp ) + (i * adx + j ) * sizeof(double ) )^:=
+ double_ptr(ptrcomp(left ) + (i * Size + j ) * sizeof(double ) )^;
+
+ for j:=0 to RightCols - 1 do
+ double_ptr(ptrcomp(tmp ) + (i * adx + Size + j ) * sizeof(double ) )^:=
+ double_ptr(ptrcomp(right ) + (i * RightCols + j ) * sizeof(double ) )^;
+
+ end;
+
+ for k:=0 to Size - 1 do
+ begin
+ if matrix_pivot(tmp ,k ,Size ,Size + RightCols ) < 0 then
+ goto return_false; // Singularity....
+
+ a1:=double_ptr(ptrcomp(tmp ) + (k * adx + k ) * sizeof(double ) )^;
+ j :=k;
+
+ while j < Size + RightCols do
+ begin
+ double_ptr(ptrcomp(tmp ) + (k * adx + j ) * sizeof(double ) )^:=
+ double_ptr(ptrcomp(tmp ) + (k * adx + j ) * sizeof(double ) )^ / a1;
+
+ inc(j );
+
+ end;
+
+ i:=k + 1;
+
+ while i < Size do
+ begin
+ a1:=double_ptr(ptrcomp(tmp ) + (i * adx + k ) * sizeof(double ) )^;
+ j :=k;
+
+ while j < Size + RightCols do
+ begin
+ double_ptr(ptrcomp(tmp ) + (i * adx + j ) * sizeof(double ) )^:=
+ double_ptr(ptrcomp(tmp ) + (i * adx + j ) * sizeof(double ) )^ -
+ a1 * double_ptr(ptrcomp(tmp ) + (k * adx + j ) * sizeof(double ) )^;
+
+ inc(j );
+
+ end;
+
+ inc(i );
+
+ end;
+
+ end;
+
+ for k:=0 to RightCols - 1 do
+ begin
+ m:=int(Size - 1 );
+
+ while m >= 0 do
+ begin
+ double_ptr(ptrcomp(result_ ) + (m * RightCols + k ) * sizeof(double ) )^:=
+ double_ptr(ptrcomp(tmp ) + (m * adx + Size + k ) * sizeof(double ) )^;
+
+ j:=m + 1;
+
+ while j < Size do
+ begin
+ double_ptr(ptrcomp(result_ ) + (m * RightCols + k ) * sizeof(double ) )^:=
+ double_ptr(ptrcomp(result_ ) + (m * RightCols + k ) * sizeof(double ) )^ -
+ (double_ptr(ptrcomp(tmp ) + (m * adx + j ) * sizeof(double ) )^ *
+ double_ptr(ptrcomp(result_ ) + (j * RightCols + k ) * sizeof(double ) )^ );
+
+ inc(j );
+
+ end;
+
+ dec(m );
+
+ end;
+
+ end;
+
+// Done
+ result:=true;
+
+ goto free;
+
+return_false:
+ result:=false;
+
+// Free
+free:
+ agg_freemem(pointer(tmp ) ,Size * adx * sizeof(double ) );
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_span_allocator.pas b/src/corelib/render/software/agg_span_allocator.pas
new file mode 100644
index 00000000..0f3b6083
--- /dev/null
+++ b/src/corelib/render/software/agg_span_allocator.pas
@@ -0,0 +1,105 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 27.01.2006-Milano: Unit port establishment
+//
+{ agg_span_allocator.pas }
+unit
+ agg_span_allocator ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_color ;
+
+{ TYPES DEFINITION }
+type
+ span_allocator_ptr = ^span_allocator;
+ span_allocator = object
+ m_max_span_len : unsigned;
+
+ m_span : aggclr_ptr;
+
+ constructor Construct;
+ destructor Destruct;
+
+ function allocate(max_span_len : unsigned ) : aggclr_ptr;
+ function span : aggclr_ptr;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor span_allocator.Construct;
+begin
+ m_max_span_len:=0;
+
+ m_span:=NIL;
+
+end;
+
+{ DESTRUCT }
+destructor span_allocator.Destruct;
+begin
+ agg_freemem(pointer(m_span ) ,m_max_span_len * sizeof(aggclr ) );
+
+end;
+
+{ ALLOCATE }
+function span_allocator.allocate;
+begin
+ if max_span_len > m_max_span_len then
+ begin
+ agg_freemem(pointer(m_span ) ,m_max_span_len * sizeof(aggclr ) );
+
+ // To reduce the number of reallocs we align the
+ // span_len to 256 color elements.
+ // Well, I just like this number and it looks reasonable.
+ max_span_len:=((max_span_len + 255 ) shr 8 ) shl 8;
+
+ agg_getmem(pointer(m_span ) ,max_span_len * sizeof(aggclr ) );
+
+ m_max_span_len:=max_span_len;
+
+ end;
+
+ result:=m_span;
+
+end;
+
+{ SPAN }
+function span_allocator.span;
+begin
+ result:=m_span;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_span_converter.pas b/src/corelib/render/software/agg_span_converter.pas
new file mode 100644
index 00000000..1424c0f0
--- /dev/null
+++ b/src/corelib/render/software/agg_span_converter.pas
@@ -0,0 +1,93 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.02.2006-Milano: Unit port establishment
+//
+{ agg_span_converter.pas }
+unit
+ agg_span_converter ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_color ,
+ agg_span_generator ;
+
+{ TYPES DEFINITION }
+type
+ span_convertor_ptr = ^span_convertor;
+ span_convertor = object
+ procedure convert(span : aggclr_ptr; x ,y : int; len : unsigned ); virtual; abstract;
+
+ end;
+
+ span_converter = object(span_generator )
+ m_span_gen : span_generator_ptr;
+ m_conv : span_convertor_ptr;
+
+ constructor Construct(span_gen : span_generator_ptr; conv : span_convertor_ptr );
+
+ procedure prepare (max_span_len : unsigned ); virtual;
+ function generate(x ,y : int; len : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor span_converter.Construct;
+begin
+ m_span_gen:=span_gen;
+ m_conv :=conv;
+
+end;
+
+{ PREPARE }
+procedure span_converter.prepare;
+begin
+ m_span_gen.prepare(max_span_len );
+
+end;
+
+{ GENERATE }
+function span_converter.generate;
+var
+ span : aggclr_ptr;
+
+begin
+ span:=m_span_gen.generate(x ,y ,len );
+
+ m_conv.convert(span ,x ,y ,len );
+
+ result:=span;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_span_generator.pas b/src/corelib/render/software/agg_span_generator.pas
new file mode 100644
index 00000000..d4bc54af
--- /dev/null
+++ b/src/corelib/render/software/agg_span_generator.pas
@@ -0,0 +1,90 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 27.01.2006-Milano: Unit port establishment
+//
+{ agg_span_generator.pas }
+unit
+ agg_span_generator ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_span_allocator ,
+ agg_vertex_source ,
+ agg_color ;
+
+{ TYPES DEFINITION }
+type
+ span_generator_ptr = ^span_generator;
+ span_generator = object(vertex_source )
+ m_alloc : span_allocator_ptr;
+
+ constructor Construct(alloc : span_allocator_ptr );
+
+ procedure allocator_(alloc : span_allocator_ptr );
+ function _allocator : span_allocator_ptr;
+
+ procedure prepare (max_span_len : unsigned ); virtual;
+ function generate(x ,y : int; len : unsigned ) : aggclr_ptr; virtual; abstract;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor span_generator.Construct;
+begin
+ m_alloc:=alloc;
+
+end;
+
+{ ALLOCATOR_ }
+procedure span_generator.allocator_;
+begin
+ m_alloc:=alloc;
+
+end;
+
+{ _ALLOCATOR }
+function span_generator._allocator;
+begin
+ result:=m_alloc;
+
+end;
+
+{ PREPARE }
+procedure span_generator.prepare;
+begin
+ m_alloc.allocate(max_span_len );
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_span_gouraud.pas b/src/corelib/render/software/agg_span_gouraud.pas
new file mode 100644
index 00000000..9c624893
--- /dev/null
+++ b/src/corelib/render/software/agg_span_gouraud.pas
@@ -0,0 +1,235 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 27.01.2006-Milano: Unit port establishment
+//
+{ agg_span_gouraud.pas }
+unit
+ agg_span_gouraud ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_math ,
+ agg_span_allocator ,
+ agg_span_generator ,
+ agg_color ,
+ agg_vertex_source ;
+
+{ TYPES DEFINITION }
+type
+ coord_type_ptr = ^coord_type;
+ coord_type = record
+ x ,y : double;
+ color : aggclr;
+
+ end;
+
+ span_gouraud = object(span_generator )
+ m_coord : array[0..2 ] of coord_type;
+ m_x ,
+ m_y : array[0..7 ] of double;
+ m_cmd : array[0..7 ] of unsigned;
+ m_vertex : unsigned;
+
+ constructor Construct(alloc : span_allocator_ptr ); overload;
+ constructor Construct(
+ alloc : span_allocator_ptr;
+ c1 ,c2 ,c3 : aggclr_ptr;
+ x1 ,y1 ,x2 ,y2 ,x3 ,y3 ,d : double ); overload;
+
+ procedure colors_ (c1 ,c2 ,c3 : aggclr_ptr );
+ procedure triangle(x1 ,y1 ,x2 ,y2 ,x3 ,y3 ,d : double );
+
+ // Vertex Source Interface to feed the coordinates to the rasterizer
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ // Private
+ procedure arrange_vertices(coord : coord_type_ptr );
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor span_gouraud.Construct(alloc : span_allocator_ptr );
+begin
+ inherited Construct(alloc );
+
+ m_cmd[0 ]:=path_cmd_stop;
+
+end;
+
+{ CONSTRUCT }
+constructor span_gouraud.Construct(
+ alloc : span_allocator_ptr;
+ c1 ,c2 ,c3 : aggclr_ptr;
+ x1 ,y1 ,x2 ,y2 ,x3 ,y3 ,d : double );
+begin
+ inherited Construct(alloc );
+
+ colors_ (c1 ,c2 ,c3 );
+ triangle(x1 ,y1 ,x2 ,y2 ,x3 ,y3 ,d );
+
+end;
+
+{ COLORS_ }
+procedure span_gouraud.colors_;
+begin
+ m_coord[0 ].color:=c1^;
+ m_coord[1 ].color:=c2^;
+ m_coord[2 ].color:=c3^;
+
+end;
+
+{ TRIANGLE }
+// Sets the triangle and dilates it if needed.
+// The trick here is to calculate beveled joins in the vertices of the
+// triangle and render it as a 6-vertex polygon.
+// It's necessary to achieve numerical stability.
+// However, the coordinates to interpolate colors are calculated
+// as miter joins (calc_intersection).
+procedure span_gouraud.triangle;
+begin
+ m_coord[0 ].x:=x1;
+ m_x[0 ] :=x1;
+ m_coord[0 ].y:=y1;
+ m_y[0 ] :=y1;
+ m_coord[1 ].x:=x2;
+ m_x[1 ] :=x2;
+ m_coord[1 ].y:=y2;
+ m_y[1 ] :=y2;
+ m_coord[2 ].x:=x3;
+ m_x[2 ] :=x3;
+ m_coord[2 ].y:=y3;
+ m_y[2 ] :=y3;
+
+ m_cmd[0 ]:=path_cmd_move_to;
+ m_cmd[1 ]:=path_cmd_line_to;
+ m_cmd[2 ]:=path_cmd_line_to;
+ m_cmd[3 ]:=path_cmd_stop;
+
+ if d <> 0.0 then
+ begin
+ dilate_triangle(
+ m_coord[0 ].x ,m_coord[0 ].y ,
+ m_coord[1 ].x ,m_coord[1 ].y ,
+ m_coord[2 ].x ,m_coord[2 ].y ,
+ @m_x ,@m_y ,d );
+
+ calc_intersection(
+ m_x[4 ] ,m_y[4 ] ,m_x[5 ] ,m_y[5 ] ,
+ m_x[0 ] ,m_y[0 ] ,m_x[1 ] ,m_y[1 ] ,
+ @m_coord[0 ].x ,@m_coord[0 ].y );
+
+ calc_intersection(
+ m_x[0 ] ,m_y[0 ] ,m_x[1 ] ,m_y[1 ] ,
+ m_x[2 ] ,m_y[2 ] ,m_x[3 ] ,m_y[3 ] ,
+ @m_coord[1 ].x ,@m_coord[1 ].y );
+
+ calc_intersection(
+ m_x[2 ] ,m_y[2 ] ,m_x[3 ] ,m_y[3 ] ,
+ m_x[4 ] ,m_y[4 ] ,m_x[5 ] ,m_y[5 ] ,
+ @m_coord[2 ].x ,@m_coord[2 ].y );
+
+ m_cmd[3 ]:=path_cmd_line_to;
+ m_cmd[4 ]:=path_cmd_line_to;
+ m_cmd[5 ]:=path_cmd_line_to;
+ m_cmd[6 ]:=path_cmd_stop;
+
+ end;
+
+end;
+
+{ REWIND }
+procedure span_gouraud.rewind;
+begin
+ m_vertex:=0;
+
+end;
+
+{ VERTEX }
+function span_gouraud.vertex;
+begin
+ x^:=m_x[m_vertex ];
+ y^:=m_y[m_vertex ];
+
+ result:=m_cmd[m_vertex ];
+
+ inc(m_vertex );
+
+end;
+
+{ ARRANGE_VERTICES }
+procedure span_gouraud.arrange_vertices;
+var
+ tmp : coord_type;
+
+begin
+ coord_type_ptr(ptrcomp(coord ) + 0 * sizeof(coord_type ) )^:=m_coord[0 ];
+ coord_type_ptr(ptrcomp(coord ) + 1 * sizeof(coord_type ) )^:=m_coord[1 ];
+ coord_type_ptr(ptrcomp(coord ) + 2 * sizeof(coord_type ) )^:=m_coord[2 ];
+
+ if m_coord[0 ].y > m_coord[2 ].y then
+ begin
+ coord_type_ptr(ptrcomp(coord ) + 0 * sizeof(coord_type ) )^:=m_coord[2 ];
+ coord_type_ptr(ptrcomp(coord ) + 2 * sizeof(coord_type ) )^:=m_coord[0 ];
+
+ end;
+
+ if coord_type_ptr(ptrcomp(coord ) + 0 * sizeof(coord_type ) ).y >
+ coord_type_ptr(ptrcomp(coord ) + 1 * sizeof(coord_type ) ).y then
+ begin
+ tmp:=coord_type_ptr(ptrcomp(coord ) + 1 * sizeof(coord_type ) )^;
+
+ coord_type_ptr(ptrcomp(coord ) + 1 * sizeof(coord_type ) )^:=
+ coord_type_ptr(ptrcomp(coord ) + 0 * sizeof(coord_type ) )^;
+
+ coord_type_ptr(ptrcomp(coord ) + 0 * sizeof(coord_type ) )^:=tmp;
+
+ end;
+
+ if coord_type_ptr(ptrcomp(coord ) + 1 * sizeof(coord_type ) ).y >
+ coord_type_ptr(ptrcomp(coord ) + 2 * sizeof(coord_type ) ).y then
+ begin
+ tmp:=coord_type_ptr(ptrcomp(coord ) + 2 * sizeof(coord_type ) )^;
+
+ coord_type_ptr(ptrcomp(coord ) + 2 * sizeof(coord_type ) )^:=
+ coord_type_ptr(ptrcomp(coord ) + 1 * sizeof(coord_type ) )^;
+
+ coord_type_ptr(ptrcomp(coord ) + 1 * sizeof(coord_type ) )^:=tmp;
+
+ end;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_span_gouraud_gray.pas b/src/corelib/render/software/agg_span_gouraud_gray.pas
new file mode 100644
index 00000000..ca72c23b
--- /dev/null
+++ b/src/corelib/render/software/agg_span_gouraud_gray.pas
@@ -0,0 +1,336 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 31.01.2006-Milano: Unit port establishment
+//
+{ agg_span_gouraud_gray.pas }
+unit
+ agg_span_gouraud_gray ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_color ,
+ agg_dda_line ,
+ agg_span_gouraud ,
+ agg_span_allocator ,
+ agg_math ;
+
+{ TYPES DEFINITION }
+const
+ subpixel_shift = 4;
+ subpixel_size = 1 shl subpixel_shift;
+
+type
+ gray_calc_ptr = ^gray_calc;
+ gray_calc = object
+ m_x1 ,m_y1 ,m_dx ,m_1dy : double;
+
+ m_v1 ,m_a1 ,
+ m_dv ,m_da ,
+ m_v ,m_a ,m_x : int;
+
+ function round(v : double ) : int;
+ procedure init (c1 ,c2 : coord_type_ptr );
+ procedure calc (y : double );
+
+ end;
+
+ span_gouraud_gray = object(span_gouraud )
+ m_swap : boolean;
+ m_y2 : int;
+
+ m_c1 ,
+ m_c2 ,
+ m_c3 : gray_calc;
+
+ constructor Construct(alloc : span_allocator_ptr ); overload;
+ constructor Construct(
+ alloc : span_allocator_ptr;
+ c1 ,c2 ,c3 : aggclr_ptr;
+ x1 ,y1 ,x2 ,y2 ,x3 ,y3 ,d : double ); overload;
+
+ procedure prepare (max_span_len : unsigned ); virtual;
+ function generate(x ,y : int; len : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ ROUND }
+function gray_calc.round;
+begin
+ if v < 0.0 then
+ result:=trunc(v - 0.5 )
+ else
+ result:=trunc(v + 0.5 );
+
+end;
+
+{ INIT }
+procedure gray_calc.init;
+var
+ dy : double;
+
+begin
+ m_x1:=c1.x - 0.5;
+ m_y1:=c1.y - 0.5;
+ m_dx:=c2.x - c1.x;
+
+ dy:=c2.y - c1.y;
+
+ if Abs(dy ) < 1e-10 then
+ m_1dy:=1e10
+ else
+ m_1dy:=1.0 / dy;
+
+ m_v1:=c1.color.v;
+ m_a1:=c1.color.a;
+ m_dv:=c2.color.v - m_v1;
+ m_da:=c2.color.a - m_a1;
+
+end;
+
+{ CALC }
+procedure gray_calc.calc;
+var
+ k : double;
+
+begin
+ k:=(y - m_y1 ) * m_1dy;
+
+ if k < 0.0 then
+ k:=0.0;
+
+ if k > 1.0 then
+ k:=1.0;
+
+ m_v:=m_v1 + self.round(m_dv * k );
+ m_a:=m_a1 + self.round(m_da * k );
+ m_x:=self.round((m_x1 + m_dx * k ) * subpixel_size );
+
+end;
+
+{ CONSTRUCT }
+constructor span_gouraud_gray.Construct(alloc : span_allocator_ptr );
+begin
+ inherited Construct(alloc );
+
+end;
+
+{ CONSTRUCT }
+constructor span_gouraud_gray.Construct(
+ alloc : span_allocator_ptr;
+ c1 ,c2 ,c3 : aggclr_ptr;
+ x1 ,y1 ,x2 ,y2 ,x3 ,y3 ,d : double );
+begin
+ inherited Construct(alloc ,c1 ,c2 ,c3 ,x1 ,y1 ,x2 ,y2 ,x3 ,y3 ,d );
+
+end;
+
+{ PREPARE }
+procedure span_gouraud_gray.prepare;
+var
+ coord : array[0..2 ] of coord_type;
+
+begin
+ inherited prepare(max_span_len );
+
+ arrange_vertices(@coord );
+
+ m_y2:=trunc(coord[1 ].y );
+
+ m_swap:=
+ calc_point_location(
+ coord[0 ].x ,coord[0 ].y,
+ coord[2 ].x ,coord[2 ].y,
+ coord[1 ].x ,coord[1 ].y ) < 0.0;
+
+ m_c1.init(@coord[0 ] ,@coord[2 ] );
+ m_c2.init(@coord[0 ] ,@coord[1 ] );
+ m_c3.init(@coord[1 ] ,@coord[2 ] );
+
+end;
+
+{ GENERATE }
+function span_gouraud_gray.generate;
+const
+ lim = agg_color.base_mask;
+
+var
+ pc1 ,pc2 ,t : gray_calc_ptr;
+
+ nlen ,start ,vv ,va : int;
+
+ v ,a : dda_line_interpolator;
+ span : aggclr_ptr;
+
+begin
+ m_c1.calc(y );
+
+ pc1:=@m_c1;
+ pc2:=@m_c2;
+
+ if y < m_y2 then
+ // Bottom part of the triangle (first subtriangle)
+ m_c2.calc(y + m_c2.m_1dy )
+ else
+ begin
+ // Upper part (second subtriangle)
+ m_c3.calc(y - m_c3.m_1dy );
+
+ pc2:=@m_c3;
+
+ end;
+
+// It means that the triangle is oriented clockwise,
+// so that we need to swap the controlling structures
+ if m_swap then
+ begin
+ t :=pc2;
+ pc2:=pc1;
+ pc1:=t;
+
+ end;
+
+// Get the horizontal length with subpixel accuracy
+// and protect it from division by zero
+ nlen:=Abs(pc2.m_x - pc1.m_x );
+
+ if nlen <= 0 then
+ nlen:=1;
+
+ v.Construct(pc1.m_v ,pc2.m_v ,nlen ,14 );
+ a.Construct(pc1.m_a ,pc2.m_a ,nlen ,14 );
+
+// Calculate the starting point of the gradient with subpixel
+// accuracy and correct (roll back) the interpolators.
+// This operation will also clip the beginning of the span
+// if necessary.
+ start:=pc1.m_x - (x shl subpixel_shift );
+
+ v.dec_operator(start );
+ a.dec_operator(start );
+
+ inc(nlen ,start );
+
+ span:=_allocator.span;
+
+// Beginning part of the span. Since we rolled back the
+// interpolators, the color values may have overflow.
+// So that, we render the beginning part with checking
+// for overflow. It lasts until "start" is positive;
+// typically it's 1-2 pixels, but may be more in some cases.
+ while (len <> 0 ) and
+ (start > 0 ) do
+ begin
+ vv:=v._y;
+ va:=a._y;
+
+ if vv < 0 then
+ vv:=0;
+
+ if vv > lim then
+ vv:=lim;
+
+ if va < 0 then
+ va:=0;
+
+ if va > lim then
+ va:=lim;
+
+ span.v:=int8u(vv );
+ span.a:=int8u(va );
+
+ v.inc_operator(subpixel_size );
+ a.inc_operator(subpixel_size );
+
+ dec(nlen ,subpixel_size );
+ dec(start ,subpixel_size );
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+ dec(len );
+
+ end;
+
+// Middle part, no checking for overflow.
+// Actual spans can be longer than the calculated length
+// because of anti-aliasing, thus, the interpolators can
+// overflow. But while "nlen" is positive we are safe.
+ while (len <> 0 ) and
+ (nlen > 0 ) do
+ begin
+ span.v:=int8u(v._y );
+ span.a:=int8u(a._y );
+
+ v.inc_operator(subpixel_size );
+ a.inc_operator(subpixel_size );
+
+ dec(nlen ,subpixel_size );
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+ dec(len );
+
+ end;
+
+// Ending part; checking for overflow.
+// Typically it's 1-2 pixels, but may be more in some cases.
+ while len <> 0 do
+ begin
+ vv:=v._y;
+ va:=a._y;
+
+ if vv < 0 then
+ vv:=0;
+
+ if vv > lim then
+ vv:=lim;
+
+ if va < 0 then
+ va:=0;
+
+ if va > lim then
+ va:=lim;
+
+ span.v:=int8u(vv );
+ span.a:=int8u(va );
+
+ v.inc_operator(subpixel_size );
+ a.inc_operator(subpixel_size );
+
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+ dec(len );
+
+ end;
+
+ result:=_allocator.span;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_span_gouraud_rgba.pas b/src/corelib/render/software/agg_span_gouraud_rgba.pas
new file mode 100644
index 00000000..f7b98857
--- /dev/null
+++ b/src/corelib/render/software/agg_span_gouraud_rgba.pas
@@ -0,0 +1,629 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// Adaptation for high precision colors has been sponsored by
+// Liberty Technology Systems, Inc., visit http://lib-sys.com
+//
+// Liberty Technology Systems, Inc. is the provider of
+// PostScript and PDF technology for software developers.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 27.01.2006-Milano: Unit port establishment
+//
+{ agg_span_gouraud_rgba.pas }
+unit
+ agg_span_gouraud_rgba ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_color ,
+ agg_dda_line ,
+ agg_span_gouraud ,
+ agg_span_allocator ,
+ agg_math ;
+
+{ TYPES DEFINITION }
+const
+ subpixel_shift = 4;
+ subpixel_size = 1 shl subpixel_shift;
+
+type
+ rgba_calc_ptr = ^rgba_calc;
+ rgba_calc = object
+ m_x1 ,m_y1 ,m_dx ,m_1dy : double;
+
+ m_r1 ,m_g1 ,m_b1 ,m_a1 ,
+ m_dr ,m_dg ,m_db ,m_da ,
+ m_r ,m_g ,m_b ,m_a ,m_x : int;
+
+ function round(v : double ) : int;
+ procedure init (c1 ,c2 : coord_type_ptr );
+ procedure calc (y : double );
+
+ end;
+
+ span_gouraud_rgba_ptr = ^span_gouraud_rgba;
+ span_gouraud_rgba = object(span_gouraud )
+ m_swap : boolean;
+ m_y2 : int;
+
+ m_rgba1 ,
+ m_rgba2 ,
+ m_rgba3 : rgba_calc;
+
+ constructor Construct(alloc : span_allocator_ptr ); overload;
+ constructor Construct(
+ alloc : span_allocator_ptr;
+ c1 ,c2 ,c3 : aggclr_ptr;
+ x1 ,y1 ,x2 ,y2 ,x3 ,y3 ,d : double ); overload;
+
+ procedure prepare (max_span_len : unsigned ); virtual;
+ function generate(x ,y : int; len : unsigned ) : aggclr_ptr; virtual;
+
+ // Agg 2.4 impl
+ constructor Construct_(
+ c1 ,c2 ,c3 : aggclr_ptr;
+ x1 ,y1 ,x2 ,y2 ,x3 ,y3 : double;
+ d : double = 0 );
+
+ procedure prepare_;
+ procedure generate_(span : aggclr_ptr; x ,y : int; len : unsigned );
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ ROUND }
+function rgba_calc.round;
+begin
+ if v < 0.0 then
+ result:=trunc(v - 0.5 )
+ else
+ result:=trunc(v + 0.5 );
+
+end;
+
+{ INIT }
+procedure rgba_calc.init;
+var
+ dy : double;
+
+begin
+ m_x1:=c1.x - 0.5;
+ m_y1:=c1.y - 0.5;
+ m_dx:=c2.x - c1.x;
+
+ dy:=c2.y - c1.y;
+
+ if dy < 1e-5 then
+ m_1dy:=1e5
+ else
+ m_1dy:=1.0 / dy;
+
+ m_r1:=c1.color.r;
+ m_g1:=c1.color.g;
+ m_b1:=c1.color.b;
+ m_a1:=c1.color.a;
+ m_dr:=c2.color.r - m_r1;
+ m_dg:=c2.color.g - m_g1;
+ m_db:=c2.color.b - m_b1;
+ m_da:=c2.color.a - m_a1;
+
+end;
+
+{ CALC }
+procedure rgba_calc.calc;
+var
+ k : double;
+
+begin
+ k:=(y - m_y1 ) * m_1dy;
+
+ if k < 0.0 then
+ k:=0.0;
+
+ if k > 1.0 then
+ k:=1.0;
+
+ m_r:=m_r1 + self.round(m_dr * k );
+ m_g:=m_g1 + self.round(m_dg * k );
+ m_b:=m_b1 + self.round(m_db * k );
+ m_a:=m_a1 + self.round(m_da * k );
+ m_x:=self.round((m_x1 + m_dx * k ) * subpixel_size );
+
+end;
+
+{ CONSTRUCT }
+constructor span_gouraud_rgba.Construct(alloc : span_allocator_ptr );
+begin
+ inherited Construct(alloc );
+
+end;
+
+{ CONSTRUCT }
+constructor span_gouraud_rgba.Construct(
+ alloc : span_allocator_ptr;
+ c1 ,c2 ,c3 : aggclr_ptr;
+ x1 ,y1 ,x2 ,y2 ,x3 ,y3 ,d : double );
+begin
+ inherited Construct(alloc ,c1 ,c2 ,c3 ,x1 ,y1 ,x2 ,y2 ,x3 ,y3 ,d );
+
+end;
+
+{ PREPARE }
+procedure span_gouraud_rgba.prepare;
+var
+ coord : array[0..2 ] of coord_type;
+
+begin
+ inherited prepare(max_span_len );
+
+ arrange_vertices(@coord );
+
+ m_y2:=trunc(coord[1 ].y );
+
+ m_swap:=
+ calc_point_location(
+ coord[0 ].x ,coord[0 ].y,
+ coord[2 ].x ,coord[2 ].y,
+ coord[1 ].x ,coord[1 ].y ) < 0.0;
+
+ m_rgba1.init(@coord[0 ] ,@coord[2 ] );
+ m_rgba2.init(@coord[0 ] ,@coord[1 ] );
+ m_rgba3.init(@coord[1 ] ,@coord[2 ] );
+
+end;
+
+{ GENERATE }
+function span_gouraud_rgba.generate;
+const
+ lim = agg_color.base_mask;
+
+var
+ pc1 ,pc2 ,t : rgba_calc_ptr;
+
+ nlen ,start ,vr ,vg ,vb ,va : int;
+
+ r ,g ,b ,a : dda_line_interpolator;
+
+ span : aggclr_ptr;
+
+begin
+ m_rgba1.calc(y ); //(m_rgba1.m_1dy > 2) ? m_rgba1.m_y1 : y);
+
+ pc1:=@m_rgba1;
+ pc2:=@m_rgba2;
+
+ if y <= m_y2 then
+ // Bottom part of the triangle (first subtriangle)
+ m_rgba2.calc(y + m_rgba2.m_1dy )
+ else
+ begin
+ // Upper part (second subtriangle)
+ m_rgba3.calc(y - m_rgba3.m_1dy );
+
+ pc2:=@m_rgba3;
+
+ end;
+
+ if m_swap then
+ begin
+ // It means that the triangle is oriented clockwise,
+ // so that we need to swap the controlling structures
+ t :=pc2;
+ pc2:=pc1;
+ pc1:=t;
+
+ end;
+
+// Get the horizontal length with subpixel accuracy
+// and protect it from division by zero
+ nlen:=Abs(pc2.m_x - pc1.m_x );
+
+ if nlen <= 0 then
+ nlen:=1;
+
+ r.Construct(pc1.m_r ,pc2.m_r ,nlen ,14 );
+ g.Construct(pc1.m_g ,pc2.m_g ,nlen ,14 );
+ b.Construct(pc1.m_b ,pc2.m_b ,nlen ,14 );
+ a.Construct(pc1.m_a ,pc2.m_a ,nlen ,14 );
+
+// Calculate the starting point of the gradient with subpixel
+// accuracy and correct (roll back) the interpolators.
+// This operation will also clip the beginning of the span
+// if necessary.
+ start:=pc1.m_x - (x shl subpixel_shift );
+
+ r.dec_operator(start );
+ g.dec_operator(start );
+ b.dec_operator(start );
+ a.dec_operator(start );
+
+ inc(nlen ,start );
+
+ span:=_allocator.span;
+
+// Beginning part of the span. Since we rolled back the
+// interpolators, the color values may have overflow.
+// So that, we render the beginning part with checking
+// for overflow. It lasts until "start" is positive;
+// typically it's 1-2 pixels, but may be more in some cases.
+ while (len <> 0 ) and
+ (start > 0 ) do
+ begin
+ vr:=r._y;
+ vg:=g._y;
+ vb:=b._y;
+ va:=a._y;
+
+ if vr < 0 then
+ vr:=0;
+
+ if vr > lim then
+ vr:=lim;
+
+ if vg < 0 then
+ vg:=0;
+
+ if vg > lim then
+ vg:=lim;
+
+ if vb < 0 then
+ vb:=0;
+
+ if vb > lim then
+ vb:=lim;
+
+ if va < 0 then
+ va:=0;
+
+ if va > lim then
+ va:=lim;
+
+ span.r:=int8u(vr );
+ span.g:=int8u(vg );
+ span.b:=int8u(vb );
+ span.a:=int8u(va );
+
+ r.inc_operator(subpixel_size );
+ g.inc_operator(subpixel_size );
+ b.inc_operator(subpixel_size );
+ a.inc_operator(subpixel_size );
+
+ dec(nlen ,subpixel_size );
+ dec(start ,subpixel_size );
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+ dec(len );
+
+ end;
+
+// Middle part, no checking for overflow.
+// Actual spans can be longer than the calculated length
+// because of anti-aliasing, thus, the interpolators can
+// overflow. But while "nlen" is positive we are safe.
+ while (len <> 0 ) and
+ (nlen > 0 ) do
+ begin
+ span.r:=int8u(r._y );
+ span.g:=int8u(g._y );
+ span.b:=int8u(b._y );
+ span.a:=int8u(a._y );
+
+ r.inc_operator(subpixel_size );
+ g.inc_operator(subpixel_size );
+ b.inc_operator(subpixel_size );
+ a.inc_operator(subpixel_size );
+
+ dec(nlen ,subpixel_size );
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+ dec(len );
+
+ end;
+
+// Ending part; checking for overflow.
+// Typically it's 1-2 pixels, but may be more in some cases.
+ while len <> 0 do
+ begin
+ vr:=r._y;
+ vg:=g._y;
+ vb:=b._y;
+ va:=a._y;
+
+ if vr < 0 then
+ vr:=0;
+
+ if vr > lim then
+ vr:=lim;
+
+ if vg < 0 then
+ vg:=0;
+
+ if vg > lim then
+ vg:=lim;
+
+ if vb < 0 then
+ vb:=0;
+
+ if vb > lim then
+ vb:=lim;
+
+ if va < 0 then
+ va:=0;
+
+ if va > lim then
+ va:=lim;
+
+ span.r:=int8u(vr );
+ span.g:=int8u(vg );
+ span.b:=int8u(vb );
+ span.a:=int8u(va );
+
+ r.inc_operator(subpixel_size );
+ g.inc_operator(subpixel_size );
+ b.inc_operator(subpixel_size );
+ a.inc_operator(subpixel_size );
+
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+ dec(len );
+
+ end;
+
+ result:=_allocator.span;
+
+end;
+
+{ CONSTRUCT_ }
+constructor span_gouraud_rgba.Construct_(
+ c1 ,c2 ,c3 : aggclr_ptr;
+ x1 ,y1 ,x2 ,y2 ,x3 ,y3 : double;
+ d : double = 0 );
+begin
+ inherited Construct(NIL ,c1 ,c2 ,c3 ,x1 ,y1 ,x2 ,y2 ,x3 ,y3 ,d );
+
+end;
+
+{ PREPARE_ }
+procedure span_gouraud_rgba.prepare_;
+var
+ coord : array[0..2 ] of coord_type;
+
+begin
+ arrange_vertices(@coord );
+
+ m_y2:=int(Trunc(coord[1 ].y ) );
+
+ m_swap:=
+ cross_product(
+ coord[0 ].x ,coord[0 ].y,
+ coord[2 ].x ,coord[2 ].y,
+ coord[1 ].x ,coord[1 ].y ) < 0.0;
+
+ m_rgba1.init(@coord[0 ] ,@coord[2 ] );
+ m_rgba2.init(@coord[0 ] ,@coord[1 ] );
+ m_rgba3.init(@coord[1 ] ,@coord[2 ] );
+
+end;
+
+{ GENERATE_ }
+procedure span_gouraud_rgba.generate_(span : aggclr_ptr; x ,y : int; len : unsigned );
+const
+ lim = agg_color.base_mask;
+
+var
+ pc1 ,pc2 ,t : rgba_calc_ptr;
+
+ nlen ,start ,vr ,vg ,vb ,va : int;
+
+ r ,g ,b ,a : dda_line_interpolator;
+
+begin
+ m_rgba1.calc(y ); //(m_rgba1.m_1dy > 2) ? m_rgba1.m_y1 : y);
+
+ pc1:=@m_rgba1;
+ pc2:=@m_rgba2;
+
+ if y <= m_y2 then
+ // Bottom part of the triangle (first subtriangle)
+ m_rgba2.calc(y + m_rgba2.m_1dy )
+ else
+ begin
+ // Upper part (second subtriangle)
+ m_rgba3.calc(y - m_rgba3.m_1dy );
+
+ pc2:=@m_rgba3;
+
+ end;
+
+ if m_swap then
+ begin
+ // It means that the triangle is oriented clockwise,
+ // so that we need to swap the controlling structures
+ t :=pc2;
+ pc2:=pc1;
+ pc1:=t;
+
+ end;
+
+// Get the horizontal length with subpixel accuracy
+// and protect it from division by zero
+ nlen:=Abs(pc2.m_x - pc1.m_x );
+
+ if nlen <= 0 then
+ nlen:=1;
+
+ r.Construct(pc1.m_r ,pc2.m_r ,nlen ,14 );
+ g.Construct(pc1.m_g ,pc2.m_g ,nlen ,14 );
+ b.Construct(pc1.m_b ,pc2.m_b ,nlen ,14 );
+ a.Construct(pc1.m_a ,pc2.m_a ,nlen ,14 );
+
+// Calculate the starting point of the gradient with subpixel
+// accuracy and correct (roll back) the interpolators.
+// This operation will also clip the beginning of the span
+// if necessary.
+ start:=pc1.m_x - (x shl subpixel_shift );
+
+ r.dec_operator(start );
+ g.dec_operator(start );
+ b.dec_operator(start );
+ a.dec_operator(start );
+
+ inc(nlen ,start );
+
+// Beginning part of the span. Since we rolled back the
+// interpolators, the color values may have overflow.
+// So that, we render the beginning part with checking
+// for overflow. It lasts until "start" is positive;
+// typically it's 1-2 pixels, but may be more in some cases.
+ while (len <> 0 ) and
+ (start > 0 ) do
+ begin
+ vr:=r._y;
+ vg:=g._y;
+ vb:=b._y;
+ va:=a._y;
+
+ if vr < 0 then
+ vr:=0;
+
+ if vr > lim then
+ vr:=lim;
+
+ if vg < 0 then
+ vg:=0;
+
+ if vg > lim then
+ vg:=lim;
+
+ if vb < 0 then
+ vb:=0;
+
+ if vb > lim then
+ vb:=lim;
+
+ if va < 0 then
+ va:=0;
+
+ if va > lim then
+ va:=lim;
+
+ span.r:=int8u(vr );
+ span.g:=int8u(vg );
+ span.b:=int8u(vb );
+ span.a:=int8u(va );
+
+ r.inc_operator(subpixel_size );
+ g.inc_operator(subpixel_size );
+ b.inc_operator(subpixel_size );
+ a.inc_operator(subpixel_size );
+
+ dec(nlen ,subpixel_size );
+ dec(start ,subpixel_size );
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+ dec(len );
+
+ end;
+
+// Middle part, no checking for overflow.
+// Actual spans can be longer than the calculated length
+// because of anti-aliasing, thus, the interpolators can
+// overflow. But while "nlen" is positive we are safe.
+ while (len <> 0 ) and
+ (nlen > 0 ) do
+ begin
+ span.r:=int8u(r._y );
+ span.g:=int8u(g._y );
+ span.b:=int8u(b._y );
+ span.a:=int8u(a._y );
+
+ r.inc_operator(subpixel_size );
+ g.inc_operator(subpixel_size );
+ b.inc_operator(subpixel_size );
+ a.inc_operator(subpixel_size );
+
+ dec(nlen ,subpixel_size );
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+ dec(len );
+
+ end;
+
+// Ending part; checking for overflow.
+// Typically it's 1-2 pixels, but may be more in some cases.
+ while len <> 0 do
+ begin
+ vr:=r._y;
+ vg:=g._y;
+ vb:=b._y;
+ va:=a._y;
+
+ if vr < 0 then
+ vr:=0;
+
+ if vr > lim then
+ vr:=lim;
+
+ if vg < 0 then
+ vg:=0;
+
+ if vg > lim then
+ vg:=lim;
+
+ if vb < 0 then
+ vb:=0;
+
+ if vb > lim then
+ vb:=lim;
+
+ if va < 0 then
+ va:=0;
+
+ if va > lim then
+ va:=lim;
+
+ span.r:=int8u(vr );
+ span.g:=int8u(vg );
+ span.b:=int8u(vb );
+ span.a:=int8u(va );
+
+ r.inc_operator(subpixel_size );
+ g.inc_operator(subpixel_size );
+ b.inc_operator(subpixel_size );
+ a.inc_operator(subpixel_size );
+
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+ dec(len );
+
+ end;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_span_gradient.pas b/src/corelib/render/software/agg_span_gradient.pas
new file mode 100644
index 00000000..6caceb51
--- /dev/null
+++ b/src/corelib/render/software/agg_span_gradient.pas
@@ -0,0 +1,805 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 12.10.2007-Milano: gradient_radial_focus_extended
+// 23.06.2006-Milano: ptrcomp adjustments
+// 27.01.2006-Milano: Unit port establishment
+//
+{ agg_span_gradient.pas }
+unit
+ agg_span_gradient ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+{$Q- }
+{$R- }
+uses
+ Math ,
+ agg_basics ,
+ agg_span_allocator ,
+ agg_span_generator ,
+ agg_math ,
+ agg_array ,
+ agg_span_interpolator_linear ,
+ agg_color ;
+
+{ TYPES DEFINITION }
+const
+ gradient_subpixel_shift = 4; //-----gradient_subpixel_shift
+ gradient_subpixel_size = 1 shl gradient_subpixel_shift; //-----gradient_subpixel_size
+ gradient_subpixel_mask = gradient_subpixel_size - 1; //-----gradient_subpixel_mask
+
+type
+ gradient_linear_color_ptr = ^gradient_linear_color;
+
+ gradient_ptr = ^gradient;
+
+ span_gradient = object(span_generator )
+ downscale_shift : int;
+
+ m_interpolator : span_interpolator_ptr;
+ m_gradient_function : gradient_ptr;
+ m_color_function : array_base_ptr;
+
+ m_d1 ,
+ m_d2 : int;
+
+ constructor Construct(alloc : span_allocator_ptr ); overload;
+ constructor Construct(
+ alloc : span_allocator_ptr;
+ inter : span_interpolator_ptr;
+ gradient_function : gradient_ptr;
+ color_function : array_base_ptr;
+ d1 ,d2 : double ); overload;
+
+ function _interpolator : span_interpolator_ptr;
+ function _gradient_function : gradient_ptr;
+ function _color_function : array_base_ptr;
+ function _d1 : double;
+ function _d2 : double;
+
+ procedure interpolator_ (i : span_interpolator_ptr );
+ procedure gradient_function_(gf : gradient_ptr );
+ procedure color_function_ (cf : array_base_ptr );
+
+ procedure d1_(v : double );
+ procedure d2_(v : double );
+
+ function generate(x ,y : int; len : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+ gradient_linear_color = object(pod_auto_array )
+ m_c1 ,
+ m_c2 ,
+ m_res : aggclr;
+
+ constructor Construct(c1 ,c2 : aggclr_ptr; size_ : unsigned = 256 );
+
+ function size : unsigned; virtual;
+ function array_operator(i : unsigned ) : pointer; virtual;
+
+ procedure colors_(c1 ,c2 : aggclr_ptr; size_ : unsigned = 256 );
+
+ end;
+
+ gradient = object
+ constructor Construct;
+
+ function calculate(x ,y ,d : int ) : int; virtual; abstract;
+
+ end;
+
+// Actually the same as radial. Just for compatibility
+ gradient_circle = object(gradient )
+ function calculate(x ,y ,d : int ) : int; virtual;
+
+ end;
+
+ gradient_radial = object(gradient )
+ function calculate(x ,y ,d : int ) : int; virtual;
+
+ end;
+
+ gradient_radial_d = object(gradient )
+ function calculate(x ,y ,d : int ) : int; virtual;
+
+ end;
+
+ gradient_radial_focus = object(gradient )
+ m_radius ,
+ m_focus_x ,
+ m_focus_y : int;
+
+ m_radius2 ,
+ m_trivial : double;
+
+ constructor Construct; overload;
+ constructor Construct(r ,fx ,fy : double ); overload;
+
+ procedure init(r ,fx ,fy : double );
+
+ function radius : double;
+ function focus_x : double;
+ function focus_y : double;
+
+ function calculate(x ,y ,d : int ) : int; virtual;
+
+ procedure update_values;
+
+ end;
+
+ gradient_radial_focus_extended = object(gradient )
+ m_r ,
+ m_fx ,
+ m_fy : int;
+ m_r2 ,
+ m_fx2 ,
+ m_fy2 ,
+ m_mul : double;
+
+ constructor Construct; overload;
+ constructor Construct(r ,fx ,fy : double ); overload;
+
+ procedure init(r ,fx ,fy : double );
+
+ function radius : double;
+ function focus_x : double;
+ function focus_y : double;
+
+ function calculate(x ,y ,d : int ) : int; virtual;
+
+ procedure update_values;
+
+ end;
+
+ gradient_x = object(gradient )
+ function calculate(x ,y ,d : int ) : int; virtual;
+
+ end;
+
+ gradient_y = object(gradient )
+ function calculate(x ,y ,d : int ) : int; virtual;
+
+ end;
+
+ gradient_diamond = object(gradient )
+ function calculate(x ,y ,d : int ) : int; virtual;
+
+ end;
+
+ gradient_xy = object(gradient )
+ function calculate(x ,y ,d : int ) : int; virtual;
+
+ end;
+
+ gradient_sqrt_xy = object(gradient )
+ function calculate(x ,y ,d : int ) : int; virtual;
+
+ end;
+
+ gradient_conic = object(gradient )
+ function calculate(x ,y ,d : int ) : int; virtual;
+
+ end;
+
+ gradient_repeat_adaptor = object(gradient )
+ m_gradient : gradient_ptr;
+
+ constructor Construct(gradient : gradient_ptr );
+
+ function calculate(x ,y ,d : int ) : int; virtual;
+
+ end;
+
+ gradient_reflect_adaptor = object(gradient )
+ m_gradient : gradient_ptr;
+
+ constructor Construct(gradient : gradient_ptr );
+
+ function calculate(x ,y ,d : int ) : int; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor span_gradient.Construct(alloc : span_allocator_ptr );
+begin
+ inherited Construct(alloc );
+
+end;
+
+{ CONSTRUCT }
+constructor span_gradient.Construct(
+ alloc : span_allocator_ptr;
+ inter : span_interpolator_ptr;
+ gradient_function : gradient_ptr;
+ color_function : array_base_ptr;
+ d1 ,d2 : double );
+begin
+ inherited Construct(alloc );
+
+ m_interpolator :=inter;
+ m_gradient_function:=gradient_function;
+ m_color_function :=color_function;
+
+ downscale_shift:=m_interpolator.subpixel_shift - gradient_subpixel_shift;
+
+ m_d1:=trunc(d1 * gradient_subpixel_size );
+ m_d2:=trunc(d2 * gradient_subpixel_size );
+
+end;
+
+{ _INTERPOLATOR }
+function span_gradient._interpolator;
+begin
+ result:=m_interpolator;
+
+end;
+
+{ _GRADIENT_FUNCTION }
+function span_gradient._gradient_function;
+begin
+ result:=m_gradient_function;
+
+end;
+
+{ _COLOR_FUNCTION }
+function span_gradient._color_function;
+begin
+ result:=m_color_function;
+
+end;
+
+{ _D1 }
+function span_gradient._d1;
+begin
+ result:=m_d1 / gradient_subpixel_size;
+
+end;
+
+{ _D2 }
+function span_gradient._d2;
+begin
+ result:=m_d2 / gradient_subpixel_size;
+
+end;
+
+{ INTERPOLATOR_ }
+procedure span_gradient.interpolator_;
+begin
+ m_interpolator:=i;
+
+end;
+
+{ GRADIENT_FUNCTION_ }
+procedure span_gradient.gradient_function_;
+begin
+ m_gradient_function:=gf;
+
+end;
+
+{ COLOR_FUNCTION_ }
+procedure span_gradient.color_function_;
+begin
+ m_color_function:=cf;
+
+end;
+
+{ D1_ }
+procedure span_gradient.d1_;
+begin
+ m_d1:=trunc(v * gradient_subpixel_size );
+
+end;
+
+{ D2_ }
+procedure span_gradient.d2_;
+begin
+ m_d2:=trunc(v * gradient_subpixel_size );
+
+end;
+
+{ GENERATE }
+function span_gradient.generate;
+var
+ span : aggclr_ptr;
+
+ dd ,d : int;
+
+begin
+ span:=_allocator.span;
+
+ dd:=m_d2 - m_d1;
+
+ if dd < 1 then
+ dd:=1;
+
+ m_interpolator.begin_(x + 0.5 ,y + 0.5 ,len );
+
+ repeat
+ m_interpolator.coordinates(@x ,@y );
+
+ d:=
+ m_gradient_function.calculate(
+ shr_int32(x ,downscale_shift ) ,
+ shr_int32(y ,downscale_shift ) ,m_d2 );
+
+ d:=((d - m_d1 ) * m_color_function.size ) div dd;
+
+ if d < 0 then
+ d:=0;
+
+ if d >= m_color_function.size then
+ d:=m_color_function.size - 1;
+
+ span^:=aggclr_ptr(m_color_function.array_operator(d ) )^;
+
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+
+ m_interpolator.inc_operator;
+
+ dec(len );
+
+ until len = 0;
+
+ result:=_allocator.span;
+
+end;
+
+{ CONSTRUCT }
+constructor gradient_linear_color.Construct;
+begin
+ m_c1:=c1^;
+ m_c2:=c2^;
+
+ m_size:=size_;
+
+end;
+
+{ SIZE }
+function gradient_linear_color.size;
+begin
+ result:=m_size;
+
+end;
+
+{ ARRAY_OPERATOR }
+function gradient_linear_color.array_operator;
+begin
+ m_res :=m_c1.gradient(@m_c2 ,i / (m_size - 1 ) );
+ result:=@m_res;
+
+end;
+
+{ COLORS_ }
+procedure gradient_linear_color.colors_;
+begin
+ m_c1:=c1^;
+ m_c2:=c2^;
+
+ m_size:=size;
+
+end;
+
+{ CONSTRUCT }
+constructor gradient.Construct;
+begin
+end;
+
+{ CALCULATE }
+function gradient_circle.calculate;
+begin
+ result:=fast_sqrt(x * x + y * y );
+
+end;
+
+{ CALCULATE }
+function gradient_radial.calculate;
+begin
+ result:=fast_sqrt(x * x + y * y );
+
+end;
+
+{ CALCULATE }
+function gradient_radial_d.calculate;
+begin
+ result:=trunc(Sqrt(x * x + y * y ) );
+
+end;
+
+{ CONSTRUCT }
+constructor gradient_radial_focus.Construct;
+begin
+ m_radius :=100 * gradient_subpixel_size;
+ m_focus_x:=0;
+ m_focus_y:=0;
+
+ update_values;
+
+end;
+
+{ CONSTRUCT }
+constructor gradient_radial_focus.Construct(r ,fx ,fy : double );
+begin
+ m_radius :=trunc(r * gradient_subpixel_size );
+ m_focus_x:=trunc(fx * gradient_subpixel_size );
+ m_focus_y:=trunc(fy * gradient_subpixel_size );
+
+ update_values;
+
+end;
+
+{ INIT }
+procedure gradient_radial_focus.init;
+begin
+ m_radius :=trunc(r * gradient_subpixel_size );
+ m_focus_x:=trunc(fx * gradient_subpixel_size );
+ m_focus_y:=trunc(fy * gradient_subpixel_size );
+
+ update_values;
+
+end;
+
+{ RADIUS }
+function gradient_radial_focus.radius;
+begin
+ result:=m_radius / gradient_subpixel_size;
+
+end;
+
+{ FOCUS_X }
+function gradient_radial_focus.focus_x;
+begin
+ result:=m_focus_x / gradient_subpixel_size;
+
+end;
+
+{ FOCUS_Y }
+function gradient_radial_focus.focus_y;
+begin
+ result:=m_focus_y / gradient_subpixel_size;
+
+end;
+
+{ CALCULATE }
+function gradient_radial_focus.calculate;
+var
+ solution_x ,
+ solution_y ,
+ slope ,yint ,
+ a ,b ,c ,det ,
+ int_to_focus ,
+ cur_to_focus : double;
+
+begin
+// Special case to avoid divide by zero or very near zero
+ if x = m_focus_x then
+ begin
+ solution_x:=m_focus_x;
+ solution_y:=0.0;
+
+ if y > m_focus_y then
+ solution_y:=solution_y + m_trivial
+ else
+ solution_y:=solution_y - m_trivial;
+
+ end
+ else
+ begin
+ // Slope of the focus-current line
+ slope:=(y - m_focus_y ) / (x - m_focus_x );
+
+ // y-intercept of that same line
+ yint:=y - (slope * x );
+
+ // Use the classical quadratic formula to calculate
+ // the intersection point
+ a:=(slope * slope ) + 1;
+ b:=2 * slope * yint;
+ c:=yint * yint - m_radius2;
+
+ det:=Sqrt((b * b ) - (4.0 * a * c ) );
+
+ solution_x:=-b;
+
+ // Choose the positive or negative root depending
+ // on where the X coord lies with respect to the focus.
+ if x < m_focus_x then
+ solution_x:=solution_x - det
+ else
+ solution_x:=solution_x + det;
+
+ solution_x:=solution_x / (2.0 * a );
+
+ // Calculating of Y is trivial
+ solution_y:=(slope * solution_x ) + yint;
+
+ end;
+
+// Calculate the percentage (0...1) of the current point along the
+// focus-circumference line and return the normalized (0...d) value
+ solution_x:=solution_x - m_focus_x;
+ solution_y:=solution_y - m_focus_y;
+
+ int_to_focus:=solution_x * solution_x + solution_y * solution_y;
+ cur_to_focus:=
+ (x - m_focus_x ) * (x - m_focus_x ) +
+ (y - m_focus_y ) * (y - m_focus_y );
+
+ result:=trunc(Sqrt(cur_to_focus / int_to_focus ) * m_radius );
+
+end;
+
+{ UPDATE_VALUES }
+procedure gradient_radial_focus.update_values;
+var
+ dist ,r ,a : double;
+
+begin
+// For use in the quadratic equation
+ m_radius2:=m_radius * m_radius;
+
+ dist:=Sqrt(m_focus_x * m_focus_x + m_focus_y * m_focus_y );
+
+// Test if distance from focus to center is greater than the radius
+// For the sake of assurance factor restrict the point to be
+// no further than 99% of the radius.
+ r:=m_radius * 0.99;
+
+ if dist > r then
+ begin
+ // clamp focus to radius
+ // x = r cos theta, y = r sin theta
+ a:=ArcTan2(m_focus_y ,m_focus_x );
+
+ m_focus_x:=trunc(r * Cos(a ) );
+ m_focus_y:=trunc(r * Sin(a ) );
+
+ end;
+
+// Calculate the solution to be used in the case where x == focus_x
+ m_trivial:=Sqrt(m_radius2 - (m_focus_x * m_focus_x ) );
+
+end;
+
+{ CONSTRUCT }
+constructor gradient_radial_focus_extended.Construct;
+begin
+ m_r :=100 * gradient_subpixel_size;
+ m_fx:=0;
+ m_fy:=0;
+
+ update_values;
+
+end;
+
+{ CONSTRUCT }
+constructor gradient_radial_focus_extended.Construct(r ,fx ,fy : double );
+begin
+ m_r :=iround(r * gradient_subpixel_size );
+ m_fx:=iround(fx * gradient_subpixel_size );
+ m_fy:=iround(fy * gradient_subpixel_size );
+
+ update_values;
+
+end;
+
+{ INIT }
+procedure gradient_radial_focus_extended.init(r ,fx ,fy : double );
+begin
+ m_r :=iround(r * gradient_subpixel_size );
+ m_fx:=iround(fx * gradient_subpixel_size );
+ m_fy:=iround(fy * gradient_subpixel_size );
+
+ update_values;
+
+end;
+
+{ RADIUS }
+function gradient_radial_focus_extended.radius : double;
+begin
+ result:=m_r / gradient_subpixel_size;
+
+end;
+
+{ FOCUS_X }
+function gradient_radial_focus_extended.focus_x : double;
+begin
+ result:=m_fx / gradient_subpixel_size;
+
+end;
+
+{ FOCUS_Y }
+function gradient_radial_focus_extended.focus_y : double;
+begin
+ result:=m_fy / gradient_subpixel_size;
+
+end;
+
+{ CALCULATE }
+function gradient_radial_focus_extended.calculate(x ,y ,d : int ) : int;
+var
+ dx ,dy ,d2 ,d3 : double;
+
+begin
+ dx:=x - m_fx;
+ dy:=y - m_fy;
+ d2:=dx * m_fy - dy * m_fx;
+ d3:=m_r2 * (dx * dx + dy * dy ) - d2 * d2;
+
+ result:=iround((dx * m_fx + dy * m_fy + Sqrt(Abs(d3 ) ) ) * m_mul );
+
+end;
+
+{ UPDATE_VALUES }
+// Calculate the invariant values. In case the focal center
+// lies exactly on the gradient circle the divisor degenerates
+// into zero. In this case we just move the focal center by
+// one subpixel unit possibly in the direction to the origin (0,0)
+// and calculate the values again.
+procedure gradient_radial_focus_extended.update_values;
+var
+ d : double;
+
+begin
+ m_r2 :=m_r * m_r;
+ m_fx2:=m_fx * m_fx;
+ m_fy2:=m_fy * m_fy;
+
+ d:=(m_r2 - (m_fx2 + m_fy2 ) );
+
+ if d = 0 then
+ begin
+ if m_fx <> 0 then
+ if m_fx < 0 then
+ inc(m_fx )
+ else
+ dec(m_fx );
+
+ if m_fy <> 0 then
+ if m_fy < 0 then
+ inc(m_fy )
+ else
+ dec(m_fy );
+
+ m_fx2:=m_fx * m_fx;
+ m_fy2:=m_fy * m_fy;
+
+ d:=(m_r2 - (m_fx2 + m_fy2 ) );
+
+ end;
+
+ m_mul:=m_r / d;
+
+end;
+
+{ CALCULATE }
+function gradient_x.calculate;
+begin
+ result:=x;
+
+end;
+
+{ CALCULATE }
+function gradient_y.calculate;
+begin
+ result:=y;
+
+end;
+
+{ CALCULATE }
+function gradient_diamond.calculate;
+var
+ ax ,ay : int;
+
+begin
+ ax:=Abs(x );
+ ay:=Abs(y );
+
+ if ax > ay then
+ result:=ax
+ else
+ result:=ay;
+
+end;
+
+{ CALCULATE }
+function gradient_xy.calculate;
+begin
+ if d = 0 then
+ result:=0
+ else
+ result:=Abs(x ) * Abs(y ) div d;
+
+end;
+
+{ CALCULATE }
+function gradient_sqrt_xy.calculate;
+begin
+ result:=fast_sqrt(Abs(x ) * Abs(y ) );
+
+end;
+
+{ CALCULATE }
+function gradient_conic.calculate;
+begin
+ result:=trunc(Abs(ArcTan2(y ,x ) ) * d / pi );
+
+end;
+
+{ CONSTRUCT }
+constructor gradient_repeat_adaptor.Construct;
+begin
+ m_gradient:=gradient;
+
+end;
+
+{ CALCULATE }
+function gradient_repeat_adaptor.calculate;
+begin
+ if d = 0 then
+ result:=0
+ else
+ result:=m_gradient.calculate(x ,y ,d ) mod d;
+
+ if result < 0 then
+ inc(result ,d );
+
+end;
+
+{ CONSTRUCT }
+constructor gradient_reflect_adaptor.Construct;
+begin
+ m_gradient:=gradient;
+
+end;
+
+{ CALCULATE }
+function gradient_reflect_adaptor.calculate;
+var
+ d2 : int;
+
+begin
+ d2:=d shl 1;
+
+ if d2 = 0 then
+ result:=0
+ else
+ result:=m_gradient.calculate(x ,y ,d ) mod d2;
+
+ if result < 0 then
+ inc(result ,d2 );
+
+ if result >= d then
+ result:=d2 - result;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_span_gradient_alpha.pas b/src/corelib/render/software/agg_span_gradient_alpha.pas
new file mode 100644
index 00000000..757c9397
--- /dev/null
+++ b/src/corelib/render/software/agg_span_gradient_alpha.pas
@@ -0,0 +1,270 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 23.02.2006-Milano: Unit port establishment
+//
+{ agg_span_gradient_alpha.pas }
+unit
+ agg_span_gradient_alpha ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+{$Q- }
+{$R- }
+uses
+ agg_basics ,
+ agg_color ,
+ agg_array ,
+ agg_span_gradient ,
+ agg_span_interpolator_linear ,
+ agg_span_converter ;
+
+{ TYPES DEFINITION }
+type
+ gradient_alpha_ptr = ^gradient_alpha;
+ gradient_alpha = object(array_base )
+ end;
+
+ span_gradient_alpha = object(span_convertor )
+ downscale_shift : unsigned;
+
+ m_interpolator : span_interpolator_ptr;
+ m_gradient_function : gradient_ptr;
+ m_alpha_function : gradient_alpha_ptr;
+
+ m_d1 ,
+ m_d2 : int;
+
+ constructor Construct; overload;
+ constructor Construct(
+ inter : span_interpolator_ptr;
+ gradient_fnc : gradient_ptr;
+ alpha_fnc : gradient_alpha_ptr;
+ d1 ,d2 : double ); overload;
+
+ function _interpolator : span_interpolator_ptr;
+ function _gradient_function : gradient_ptr;
+ function _alpha_function : gradient_alpha_ptr;
+ function _d1 : double;
+ function _d2 : double;
+
+ procedure interpolator_ (i : span_interpolator_ptr );
+ procedure gradient_function_(gf : gradient_ptr );
+ procedure alpha_function_ (af : gradient_alpha_ptr );
+
+ procedure d1_(v : double );
+ procedure d2_(v : double );
+
+ procedure convert(span : aggclr_ptr; x ,y : int; len : unsigned ); virtual;
+
+ end;
+
+ gradient_alpha_x = object
+ function array_operator(x : aggclr ) : aggclr;
+
+ end;
+
+ gradient_alpha_x_u8 = object
+ function array_operator(x : int ) : int8u;
+
+ end;
+
+ gradient_alpha_one_munus_x_u8 = object
+ function array_operator(x : int ) : int8u;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor span_gradient_alpha.Construct;
+begin
+ m_interpolator :=NIL;
+ m_gradient_function:=NIL;
+ m_alpha_function :=NIL;
+
+ downscale_shift:=0;
+
+ m_d1:=0;
+ m_d2:=0;
+
+end;
+
+{ CONSTRUCT }
+constructor span_gradient_alpha.Construct(
+ inter : span_interpolator_ptr;
+ gradient_fnc : gradient_ptr;
+ alpha_fnc : gradient_alpha_ptr;
+ d1 ,d2 : double );
+begin
+ m_interpolator :=inter;
+ m_gradient_function:=gradient_fnc;
+ m_alpha_function :=alpha_fnc;
+
+ downscale_shift:=m_interpolator.subpixel_shift - gradient_subpixel_shift;
+
+ m_d1:=trunc(d1 * gradient_subpixel_size );
+ m_d2:=trunc(d2 * gradient_subpixel_size );
+
+end;
+
+{ _INTERPOLATOR }
+function span_gradient_alpha._interpolator;
+begin
+ result:=m_interpolator;
+
+end;
+
+{ _GRADIENT_FUNCTION }
+function span_gradient_alpha._gradient_function;
+begin
+ result:=m_gradient_function;
+
+end;
+
+{ _ALPHA_FUNCTION }
+function span_gradient_alpha._alpha_function;
+begin
+ result:=m_alpha_function;
+
+end;
+
+{ _D1 }
+function span_gradient_alpha._d1;
+begin
+ result:=m_d1 / gradient_subpixel_size;
+
+end;
+
+{ _D2 }
+function span_gradient_alpha._d2;
+begin
+ result:=m_d2 / gradient_subpixel_size;
+
+end;
+
+{ INTERPOLATOR_ }
+procedure span_gradient_alpha.interpolator_;
+begin
+ m_interpolator:=i;
+
+end;
+
+{ GRADIENT_FUNCTION_ }
+procedure span_gradient_alpha.gradient_function_;
+begin
+ m_gradient_function:=gf;
+
+end;
+
+{ ALPHA_FUNCTION_ }
+procedure span_gradient_alpha.alpha_function_;
+begin
+ m_alpha_function:=af;
+
+end;
+
+{ D1_ }
+procedure span_gradient_alpha.d1_;
+begin
+ m_d1:=trunc(v * gradient_subpixel_size );
+
+end;
+
+{ D2_ }
+procedure span_gradient_alpha.d2_;
+begin
+ m_d2:=trunc(v * gradient_subpixel_size );
+
+end;
+
+{ CONVERT }
+procedure span_gradient_alpha.convert;
+var
+ dd ,d : int;
+
+begin
+ dd:=m_d2 - m_d1;
+
+ if dd < 1 then
+ dd:=1;
+
+ m_interpolator.begin_(x + 0.5 ,y + 0.5 ,len );
+
+ repeat
+ m_interpolator.coordinates(@x ,@y );
+
+ d:=
+ m_gradient_function.calculate(
+ shr_int32(x ,downscale_shift ) ,
+ shr_int32(y ,downscale_shift ) ,
+ m_d2 );
+
+ d:=((d - m_d1 ) * m_alpha_function.size ) div dd;
+
+ if d < 0 then
+ d:=0;
+
+ if d >= m_alpha_function.size then
+ d:=m_alpha_function.size - 1;
+
+ span.a:=int8u_ptr(m_alpha_function.array_operator(d ) )^;
+
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+
+ m_interpolator.inc_operator;
+
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ ARRAY_OPERATOR }
+function gradient_alpha_x.array_operator;
+begin
+ result:=x;
+
+end;
+
+{ ARRAY_OPERATOR }
+function gradient_alpha_x_u8.array_operator;
+begin
+ result:=int8u(x );
+
+end;
+
+{ ARRAY_OPERATOR }
+function gradient_alpha_one_munus_x_u8.array_operator;
+begin
+ result:=int8u(255 - x );
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_span_gradient_contour.pas b/src/corelib/render/software/agg_span_gradient_contour.pas
new file mode 100644
index 00000000..6550f703
--- /dev/null
+++ b/src/corelib/render/software/agg_span_gradient_contour.pas
@@ -0,0 +1,519 @@
+//----------------------------------------------------------------------------
+// AGG Contribution Pack - Gradients 1 (AGG CP - Gradients 1)
+// http://milan.marusinec.sk/aggcp
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// http://www.aggpas.org
+//
+// Contribution Created By:
+// Milan Marusinec alias Milano
+// milan@marusinec.sk
+// Copyright (c) 2007
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+// [History] -----------------------------------------------------------------
+//
+// 17.11.2007-Milano: Establishment
+//
+{ agg_span_gradient_contour.pas }
+unit
+ agg_span_gradient_contour ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ Math ,
+ agg_basics ,
+ agg_color ,
+ agg_span_gradient ,
+ agg_path_storage ,
+ agg_bounding_rect ,
+ agg_conv_curve ,
+ agg_conv_stroke ,
+ agg_conv_transform ,
+ agg_trans_affine ,
+ agg_rendering_buffer ,
+ agg_renderer_base ,
+ agg_renderer_scanline ,
+ agg_renderer_primitives ,
+ agg_render_scanlines ,
+ agg_rasterizer_outline ,
+ agg_rasterizer_scanline_aa ,
+ agg_scanline ,
+ agg_scanline_u ,
+ agg_pixfmt ,
+ agg_pixfmt_gray ;
+
+{ GLOBAL VARIABLES & CONSTANTS }
+{ TYPES DEFINITION }
+type
+ single_ptr = ^single;
+
+ int_array_ptr = ^int_array;
+ int_array = array[0..65535 ] of int;
+
+ single_array_ptr = ^single_array;
+ single_array = array[0..65535 ] of single;
+
+ gradient_contour = object(gradient )
+ private
+ m_buffer : pointer;
+ m_width ,
+ m_height ,
+ m_frame : int;
+
+ m_d1 ,
+ m_d2 : double;
+
+ public
+ constructor Construct(d_1 : double = 0; d_2 : double = 100 );
+ destructor Destruct;
+
+ function contour_create(ps : path_storage_ptr ) : pointer;
+ function contour_width : int;
+ function contour_height : int;
+
+ procedure d1(d : double );
+ procedure d2(d : double );
+
+ procedure frame(f : int ); overload;
+ function frame : int; overload;
+
+ function calculate(x ,y ,d : int ) : int; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+const
+ infinity = 1e20;
+
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor gradient_contour.Construct(d_1 : double = 0; d_2 : double = 100 );
+begin
+ m_buffer:=NIL;
+ m_width :=0;
+ m_height:=0;
+ m_frame :=10;
+
+ m_d1:=d_1;
+ m_d2:=d_2;
+
+end;
+
+{ DESTRUCT }
+destructor gradient_contour.Destruct;
+begin
+ if m_buffer <> NIL then
+ agg_freemem(m_buffer ,m_width * m_height );
+
+end;
+
+{ SQUARE }
+function square(x : int ) : int;
+begin
+ result:=x * x;
+
+end;
+
+{ DT }
+// DT algorithm by: Pedro Felzenszwalb
+procedure dt(spanf ,spang ,spanr : single_array_ptr; spann : int_array_ptr; length : int );
+var
+ k ,q : int;
+
+ s : single;
+
+begin
+ k:=0;
+
+ spann[0 ]:=0;
+ spang[0 ]:=-infinity;
+ spang[1 ]:=+infinity;
+
+ q:=1;
+
+ while q <= length - 1 do
+ begin
+ s:=((spanf[q ] + square(q ) ) - (spanf[spann[k ] ] + square(spann[k ] ) ) ) / (2 * q - 2 * spann[k ] );
+
+ while s <= spang[k ] do
+ begin
+ dec(k );
+
+ s:=((spanf[q ] + square(q ) ) - (spanf[spann[k ] ] + square(spann[k ] ) ) ) / (2 * q - 2 * spann[k ] );
+
+ end;
+
+ inc(k );
+
+ spann[k ]:=q;
+ spang[k ]:=s;
+
+ spang[k + 1 ]:=+infinity;
+
+ inc(q );
+
+ end;
+
+ k:=0;
+ q:=0;
+
+ while q <= length - 1 do
+ begin
+ while spang[k + 1 ] < q do
+ inc(k );
+
+ spanr[q ]:=square(q - spann[k ] ) + spanf[spann[k ] ];
+
+ inc(q );
+
+ end;
+
+end;
+
+{ CONTOUR_CREATE }
+// DT algorithm by: Pedro Felzenszwalb
+function gradient_contour.contour_create(ps : path_storage_ptr ) : pointer;
+var
+ rb : rendering_buffer;
+ pf : pixel_formats;
+
+ ras : rasterizer_outline;
+ mtx : trans_affine;
+
+ rgba : aggclr;
+ renb : renderer_base;
+ prim : renderer_primitives;
+ conv : conv_curve;
+
+ trans : conv_transform;
+
+ min ,max ,scale : single;
+
+ x1 ,y1 ,x2 ,y2 : double;
+
+ width ,height ,length ,fcx ,fcy : int;
+
+ buffer ,image : pointer;
+
+ src : int8u_ptr;
+
+ dst ,im ,spanf ,spang ,spanr : single_ptr;
+
+ spann : int_ptr;
+
+begin
+ result:=NIL;
+ buffer:=NIL;
+
+ if ps <> NIL then
+ begin
+ { I. Render Black And White NonAA Stroke of the Path }
+ { Path Bounding Box + Some Frame Space Around [configurable] }
+ conv.Construct(ps );
+
+ if bounding_rect_single(@conv ,0 ,@x1 ,@y1 ,@x2 ,@y2 ) then
+ begin
+ { Create BW Rendering Surface }
+ width :=Ceil(x2 - x1 ) + m_frame * 2 + 1;
+ height:=Ceil(y2 - y1 ) + m_frame * 2 + 1;
+
+ if agg_getmem(buffer ,width * height ) then
+ begin
+ FillChar(buffer^ ,width * height ,255 );
+
+ { Setup VG Engine & Render }
+ rb.Construct;
+ rb.attach(buffer ,width ,height ,width );
+
+ pixfmt_gray8(pf ,@rb );
+
+ renb.Construct(@pf );
+
+ prim.Construct(@renb );
+ ras.Construct (@prim );
+
+ mtx.Construct;
+ mtx.Translate(-x1 + m_frame ,-y1 + m_frame );
+
+ trans.Construct(@conv ,@mtx );
+
+ rgba.ConstrInt (0 ,0 ,0 ,255 );
+ prim.line_color_(@rgba );
+ ras.add_path (@trans );
+
+ rb.Destruct;
+
+ { II. Distance Transform }
+ { Create Float Buffer + 0 vs infinity (1e20) assignment }
+ if agg_getmem(image ,width * height * sizeof(single ) ) then
+ begin
+ src:=buffer;
+ dst:=image;
+
+ for fcy:=0 to height - 1 do
+ for fcx:=0 to width - 1 do
+ begin
+ if src^ = 0 then
+ dst^:=0
+ else
+ dst^:=infinity;
+
+ inc(ptrcomp(src ) );
+ inc(ptrcomp(dst ) ,sizeof(single ) );
+
+ end;
+
+ { DT of 2d }
+ { SubBuff<float> max width,height }
+ length:=width;
+
+ if height > length then
+ length:=height;
+
+ spanf:=NIL;
+ spang:=NIL;
+ spanr:=NIL;
+ spann:=NIL;
+
+ if agg_getmem(pointer(spanf ) ,length * sizeof(single ) ) and
+ agg_getmem(pointer(spang ) ,(length + 1 ) * sizeof(single ) ) and
+ agg_getmem(pointer(spanr ) ,length * sizeof(single ) ) and
+ agg_getmem(pointer(spann ) ,length * sizeof(int ) ) then
+ begin
+ { Transform along columns }
+ for fcx:=0 to width - 1 do
+ begin
+ im :=pointer(ptrcomp(image ) + fcx * sizeof(single ) );
+ dst:=spanf;
+
+ for fcy:=0 to height - 1 do
+ begin
+ dst^:=im^;
+
+ inc(ptrcomp(dst ) ,sizeof(single ) );
+ inc(ptrcomp(im ) ,width * sizeof(single ) );
+
+ end;
+
+ { DT of 1d }
+ dt(pointer(spanf ) ,pointer(spang ) ,pointer(spanr ) ,pointer(spann ) ,height );
+
+ im :=pointer(ptrcomp(image ) + fcx * sizeof(single ) );
+ dst:=spanr;
+
+ for fcy:=0 to height - 1 do
+ begin
+ im^:=dst^;
+
+ inc(ptrcomp(dst ) ,sizeof(single ) );
+ inc(ptrcomp(im ) ,width * sizeof(single ) );
+
+ end;
+
+ end;
+
+ { Transform along rows }
+ for fcy:=0 to height - 1 do
+ begin
+ im :=pointer(ptrcomp(image ) + fcy * width * sizeof(single ) );
+ dst:=spanf;
+
+ for fcx:=0 to width - 1 do
+ begin
+ dst^:=im^;
+
+ inc(ptrcomp(dst ) ,sizeof(single ) );
+ inc(ptrcomp(im ) ,sizeof(single ) );
+
+ end;
+
+ { DT of 1d }
+ dt(pointer(spanf ) ,pointer(spang ) ,pointer(spanr ) ,pointer(spann ) ,width );
+
+ im :=pointer(ptrcomp(image ) + fcy * width * sizeof(single ) );
+ dst:=spanr;
+
+ for fcx:=0 to width - 1 do
+ begin
+ im^:=dst^;
+
+ inc(ptrcomp(dst ) ,sizeof(single ) );
+ inc(ptrcomp(im ) ,sizeof(single ) );
+
+ end;
+
+ end;
+
+ { Take Square Roots, Min & Max }
+ dst:=image;
+ min:=Sqrt(dst^ );
+ max:=min;
+
+ for fcy:=0 to height - 1 do
+ for fcx:=0 to width - 1 do
+ begin
+ dst^:=Sqrt(dst^ );
+
+ if min > dst^ then
+ min:=dst^;
+
+ if max < dst^ then
+ max:=dst^;
+
+ inc(ptrcomp(dst ) ,sizeof(single ) );
+
+ end;
+
+ { III. Convert To Grayscale }
+ if min = max then
+ FillChar(buffer^ ,width * height ,0 )
+ else
+ begin
+ scale:=255 / (max - min );
+
+ src:=buffer;
+ dst:=image;
+
+ for fcy:=0 to height - 1 do
+ for fcx:=0 to width - 1 do
+ begin
+ src^:=int8u(Trunc((dst^ - min ) * scale ) );
+
+ inc(ptrcomp(src ) );
+ inc(ptrcomp(dst ) ,sizeof(single ) );
+
+ end;
+
+ end;
+
+ { OK }
+ if m_buffer <> NIL then
+ agg_freemem(m_buffer ,m_width * m_height );
+
+ m_buffer:=buffer;
+ m_width :=width;
+ m_height:=height;
+
+ buffer:=NIL;
+ result:=m_buffer;
+
+ end;
+
+ if spanf <> NIL then
+ agg_freemem(pointer(spanf ) ,length * sizeof(single ) );
+
+ if spang <> NIL then
+ agg_freemem(pointer(spang ) ,(length + 1 ) * sizeof(single ) );
+
+ if spanr <> NIL then
+ agg_freemem(pointer(spanr ) ,length * sizeof(single ) );
+
+ if spann <> NIL then
+ agg_freemem(pointer(spann ) ,length * sizeof(int ) );
+
+ agg_freemem(image ,width * height * sizeof(single ) );
+
+ end;
+
+ end;
+
+ end;
+
+ { Free }
+ conv.Destruct;
+
+ if buffer <> NIL then
+ agg_freemem(buffer ,width * height );
+
+ end;
+
+end;
+
+{ CONTOUR_WIDTH }
+function gradient_contour.contour_width : int;
+begin
+ result:=m_width;
+
+end;
+
+{ CONTOUR_HEIGHT }
+function gradient_contour.contour_height : int;
+begin
+ result:=m_height;
+
+end;
+
+{ D1 }
+procedure gradient_contour.d1(d : double );
+begin
+ m_d1:=d;
+
+end;
+
+{ D2 }
+procedure gradient_contour.d2(d : double );
+begin
+ m_d2:=d;
+
+end;
+
+{ FRAME }
+procedure gradient_contour.frame(f : int );
+begin
+ m_frame:=f;
+
+end;
+
+{ FRAME }
+function gradient_contour.frame : int;
+begin
+ result:=m_frame;
+
+end;
+
+{ CALCULATE }
+function gradient_contour.calculate(x ,y ,d : int ) : int;
+var
+ px ,py : int;
+
+ pixel : int8u_ptr;
+
+begin
+ if m_buffer <> NIL then
+ begin
+ px:=shr_int32(x ,gradient_subpixel_shift );
+ py:=shr_int32(y ,gradient_subpixel_shift );
+
+ px:=px mod m_width;
+
+ if px < 0 then
+ px:=m_width + px;
+
+ py:=py mod m_height;
+
+ if py < 0 then
+ py:=m_height + py;
+
+ pixel :=int8u_ptr(ptrcomp(m_buffer ) + py * m_width + px );
+ result:=Round(pixel^ * (m_d2 / 256 ) + m_d1 ) shl gradient_subpixel_shift;
+
+ end
+ else
+ result:=0;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_span_gradient_image.pas b/src/corelib/render/software/agg_span_gradient_image.pas
new file mode 100644
index 00000000..60964938
--- /dev/null
+++ b/src/corelib/render/software/agg_span_gradient_image.pas
@@ -0,0 +1,315 @@
+//----------------------------------------------------------------------------
+// AGG Contribution Pack - Gradients 1 (AGG CP - Gradients 1)
+// http://milan.marusinec.sk/aggcp
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// http://www.aggpas.org
+//
+// Contribution Created By:
+// Milan Marusinec alias Milano
+// milan@marusinec.sk
+// Copyright (c) 2007
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+// [History] -----------------------------------------------------------------
+//
+// 14.11.2007-Milano: Establishment
+//
+{ agg_span_gradient_image.pas }
+unit
+ agg_span_gradient_image ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_color ,
+ agg_array ,
+ agg_span_gradient ,
+ agg_pixfmt ,
+ agg_pixfmt_rgba ,
+ agg_rendering_buffer ;
+
+{ GLOBAL VARIABLES & CONSTANTS }
+{ TYPES DEFINITION }
+type
+ one_color_function = object(array_base )
+ m_color : aggclr;
+
+ constructor Construct;
+
+ function size : unsigned; virtual;
+ function entry : unsigned; virtual;
+ function array_operator(i : unsigned ) : pointer; virtual;
+
+ end;
+
+ gradient_image = object(gradient )
+ private
+ m_buffer : pointer;
+ m_alocdx ,
+ m_alocdy ,
+ m_width ,
+ m_height : int;
+
+ m_renbuf : rendering_buffer_ptr;
+ m_pixelf : pixel_formats;
+
+ m_color : aggclr_ptr;
+
+ m_color_function : one_color_function;
+
+ public
+ constructor Construct;
+ destructor Destruct;
+
+ function image_create(width ,height : int ) : pointer;
+ function image_buffer : pointer;
+ function image_width : int;
+ function image_height : int;
+ function image_stride : int;
+
+ function calculate(x ,y ,d : int ) : int; virtual;
+
+ function pixel_format : pixel_formats_ptr;
+ function color_function : array_base_ptr;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor one_color_function.Construct;
+begin
+ m_color.Construct;
+
+end;
+
+{ SIZE }
+function one_color_function.size : unsigned;
+begin
+ result:=1;
+
+end;
+
+{ ENTRY }
+function one_color_function.entry : unsigned;
+begin
+ result:=sizeof(aggclr );
+
+end;
+
+{ ARRAY_OPERATOR }
+function one_color_function.array_operator(i : unsigned ) : pointer;
+begin
+ result:=@m_color;
+
+end;
+
+{ CONSTRUCT }
+constructor gradient_image.Construct;
+begin
+ m_color_function.Construct;
+
+ m_buffer:=NIL;
+ m_alocdx:=0;
+ m_alocdy:=0;
+ m_width :=0;
+ m_height:=0;
+
+ m_renbuf:=NIL;
+
+ pixfmt_undefined(m_pixelf );
+
+ m_color:=m_color_function.array_operator(0 );
+
+end;
+
+{ DESTRUCT }
+destructor gradient_image.Destruct;
+begin
+ if m_buffer <> NIL then
+ agg_freemem(m_buffer ,m_alocdx * m_alocdy * 4 );
+
+ if m_renbuf <> NIL then
+ dispose(m_renbuf ,Destruct );
+
+end;
+
+{ IMAGE_CREATE }
+function gradient_image.image_create(width ,height : int ) : pointer;
+var
+ row : pointer;
+ rows : unsigned;
+
+begin
+ result:=NIL;
+
+ if m_renbuf <> NIL then
+ dispose(m_renbuf ,Destruct );
+
+ m_renbuf:=NIL;
+
+ if (width > m_alocdx ) or
+ (height > m_alocdy ) then
+ begin
+ if m_buffer <> NIL then
+ agg_freemem(m_buffer ,m_alocdx * m_alocdy * 4 );
+
+ m_buffer:=NIL;
+
+ if agg_getmem(m_buffer ,width * height * 4 ) then
+ begin
+ m_alocdx:=width;
+ m_alocdy:=height;
+
+ end
+ else
+ begin
+ m_alocdx:=0;
+ m_alocdy:=0;
+
+ end;
+
+ end;
+
+ if m_buffer <> NIL then
+ begin
+ m_width :=width;
+ m_height:=height;
+
+ row :=m_buffer;
+ rows:=height;
+
+ while rows > 0 do
+ begin
+ FillChar(row^ ,m_width * 4 ,0 );
+
+ inc(ptrcomp(row ) ,m_alocdx * 4 );
+ dec(rows );
+
+ end;
+
+ result:=m_buffer;
+
+ end
+ else
+ begin
+ m_width :=0;
+ m_height:=0;
+
+ end;
+
+end;
+
+{ IMAGE_BUFFER }
+function gradient_image.image_buffer : pointer;
+begin
+ result:=m_buffer;
+
+end;
+
+{ IMAGE_WIDTH }
+function gradient_image.image_width : int;
+begin
+ result:=m_width;
+
+end;
+
+{ IMAGE_HEIGHT }
+function gradient_image.image_height : int;
+begin
+ result:=m_height;
+
+end;
+
+{ IMAGE_STRIDE }
+function gradient_image.image_stride : int;
+begin
+ result:=m_alocdx * 4;
+
+end;
+
+{ CALCULATE }
+function gradient_image.calculate(x ,y ,d : int ) : int;
+var
+ px ,py : int;
+
+ pixel : rgba8_ptr;
+
+begin
+ result:=0;
+
+ if m_buffer <> NIL then
+ begin
+ px:=shr_int32(x ,gradient_subpixel_shift );
+ py:=shr_int32(y ,gradient_subpixel_shift );
+
+ px:=px mod m_width;
+
+ if px < 0 then
+ px:=m_width + px;
+
+ py:=py mod m_height;
+
+ if py < 0 then
+ py:=m_height + py;
+
+ pixel:=rgba8_ptr(ptrcomp(m_buffer ) + py * (m_alocdx * 4 ) + px * 4 );
+
+ m_color.r:=pixel.r;
+ m_color.g:=pixel.g;
+ m_color.b:=pixel.b;
+ m_color.a:=pixel.a;
+
+ end
+ else
+ begin
+ m_color.r:=0;
+ m_color.g:=0;
+ m_color.b:=0;
+ m_color.a:=0;
+
+ end;
+
+end;
+
+{ PIXEL_FORMAT }
+function gradient_image.pixel_format : pixel_formats_ptr;
+begin
+ if (m_buffer <> NIL ) and
+ (m_renbuf = NIL ) then
+ begin
+ new(m_renbuf ,Construct );
+
+ m_renbuf.attach(m_buffer ,m_width ,m_height ,m_alocdx * 4 );
+ pixfmt_rgba32 (m_pixelf ,m_renbuf );
+
+ end;
+
+ if m_renbuf = NIL then
+ result:=NIL
+ else
+ result:=@m_pixelf;
+
+end;
+
+{ COLOR_FUNCTION }
+function gradient_image.color_function : array_base_ptr;
+begin
+ result:=@m_color_function;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_span_image_filter.pas b/src/corelib/render/software/agg_span_image_filter.pas
new file mode 100644
index 00000000..793ea92e
--- /dev/null
+++ b/src/corelib/render/software/agg_span_image_filter.pas
@@ -0,0 +1,235 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// Image transformations with filtering. Span generator base class
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 01.03.2006-Milano: Unit port establishment
+//
+{ agg_span_image_filter.pas }
+unit
+ agg_span_image_filter ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_color ,
+ agg_image_filters ,
+ agg_rendering_buffer ,
+ agg_span_generator ,
+ agg_span_allocator ,
+ agg_span_interpolator_linear ;
+
+{ TYPES DEFINITION }
+type
+ span_image_filter_ptr = ^span_image_filter;
+ span_image_filter = object(span_generator )
+ m_src : rendering_buffer_ptr;
+ m_back_color : aggclr;
+ m_interpolator : span_interpolator_ptr;
+ m_filter : image_filter_lut_ptr;
+
+ m_dx_dbl ,
+ m_dy_dbl : double;
+ m_dx_int ,
+ m_dy_int : unsigned;
+
+ constructor Construct(alloc : span_allocator_ptr ); overload;
+ constructor Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ back_color : aggclr_ptr;
+ interpolator : span_interpolator_ptr;
+ filter : image_filter_lut_ptr ); overload;
+
+ function _source_image : rendering_buffer_ptr;
+ function _background_color : aggclr_ptr;
+ function _filter : image_filter_lut_ptr;
+ function _interpolator : span_interpolator_ptr;
+
+ function filter_dx_int : int;
+ function filter_dy_int : int;
+ function filter_dx_dbl : double;
+ function filter_dy_dbl : double;
+
+ procedure source_image_ (v : rendering_buffer_ptr );
+ procedure background_color_(v : aggclr_ptr );
+ procedure interpolator_ (v : span_interpolator_ptr );
+ procedure filter_ (v : image_filter_lut_ptr );
+ procedure filter_offset (dx ,dy : double ); overload;
+ procedure filter_offset (d : double ); overload;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor span_image_filter.Construct(alloc : span_allocator_ptr );
+begin
+ inherited Construct(alloc );
+
+ m_back_color.Construct;
+
+ m_src :=NIL;
+ m_interpolator:=NIL;
+ m_filter :=NIL;
+
+ m_dx_dbl:=0.0;
+ m_dy_dbl:=0.0;
+ m_dx_int:=0;
+ m_dy_int:=0;
+
+end;
+
+{ CONSTRUCT }
+constructor span_image_filter.Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ back_color : aggclr_ptr;
+ interpolator : span_interpolator_ptr;
+ filter : image_filter_lut_ptr );
+begin
+ inherited Construct(alloc );
+
+ m_src :=src;
+ m_back_color :=back_color^;
+ m_interpolator:=interpolator;
+ m_filter :=filter;
+
+ m_dx_dbl:=0.5;
+ m_dy_dbl:=0.5;
+ m_dx_int:=image_subpixel_size div 2;
+ m_dy_int:=image_subpixel_size div 2;
+
+end;
+
+{ _SOURCE_IMAGE }
+function span_image_filter._source_image;
+begin
+ result:=m_src;
+
+end;
+
+{ _BACKGROUND_COLOR }
+function span_image_filter._background_color;
+begin
+ result:=@m_back_color;
+
+end;
+
+{ _FILTER }
+function span_image_filter._filter;
+begin
+ result:=m_filter;
+
+end;
+
+{ _INTERPOLATOR }
+function span_image_filter._interpolator;
+begin
+ result:=m_interpolator;
+
+end;
+
+{ FILTER_DX_INT }
+function span_image_filter.filter_dx_int;
+begin
+ result:=m_dx_int;
+
+end;
+
+{ FILTER_DY_INT }
+function span_image_filter.filter_dy_int;
+begin
+ result:=m_dy_int;
+
+end;
+
+{ FILTER_DX_DBL }
+function span_image_filter.filter_dx_dbl;
+begin
+ result:=m_dx_dbl;
+
+end;
+
+{ FILTER_DY_DBL }
+function span_image_filter.filter_dy_dbl;
+begin
+ result:=m_dy_dbl;
+
+end;
+
+{ SOURCE_IMAGE_ }
+procedure span_image_filter.source_image_;
+begin
+ m_src:=v;
+
+end;
+
+{ BACKGROUND_COLOR_ }
+procedure span_image_filter.background_color_;
+begin
+ m_back_color:=v^;
+
+end;
+
+{ INTERPOLATOR_ }
+procedure span_image_filter.interpolator_;
+begin
+ m_interpolator:=v;
+
+end;
+
+{ FILTER_ }
+procedure span_image_filter.filter_;
+begin
+ m_filter:=v;
+
+end;
+
+{ FILTER_OFFSET }
+procedure span_image_filter.filter_offset(dx ,dy : double );
+begin
+ m_dx_dbl:=dx;
+ m_dy_dbl:=dy;
+ m_dx_int:=trunc(dx * image_subpixel_size );
+ m_dy_int:=trunc(dy * image_subpixel_size );
+
+end;
+
+{ FILTER_OFFSET }
+procedure span_image_filter.filter_offset(d : double );
+begin
+ filter_offset(d ,d );
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_span_image_filter_gray.pas b/src/corelib/render/software/agg_span_image_filter_gray.pas
new file mode 100644
index 00000000..f4960122
--- /dev/null
+++ b/src/corelib/render/software/agg_span_image_filter_gray.pas
@@ -0,0 +1,869 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// Adaptation for high precision colors has been sponsored by
+// Liberty Technology Systems, Inc., visit http://lib-sys.com
+//
+// Liberty Technology Systems, Inc. is the provider of
+// PostScript and PDF technology for software developers.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 01.03.2006-Milano: Unit port establishment
+//
+{ agg_span_image_filter_gray.pas }
+unit
+ agg_span_image_filter_gray ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+{$Q- }
+{$R- }
+uses
+ agg_basics ,
+ agg_color ,
+ agg_image_filters ,
+ agg_span_image_filter ,
+ agg_span_allocator ,
+ agg_span_interpolator_linear ,
+ agg_rendering_buffer ;
+
+{ TYPES DEFINITION }
+const
+ base_shift = agg_color.base_shift;
+ base_mask = agg_color.base_mask;
+
+type
+ span_image_filter_gray_nn_ptr = ^span_image_filter_gray_nn;
+ span_image_filter_gray_nn = object(span_image_filter )
+ constructor Construct(alloc : span_allocator_ptr ); overload;
+ constructor Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ back_color : aggclr_ptr;
+ inter : span_interpolator_ptr ); overload;
+
+ function generate(x ,y : int; len : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+ span_image_filter_gray_bilinear_ptr = ^span_image_filter_gray_bilinear;
+ span_image_filter_gray_bilinear = object(span_image_filter )
+ constructor Construct(alloc : span_allocator_ptr ); overload;
+ constructor Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ back_color : aggclr_ptr;
+ inter : span_interpolator_ptr ); overload;
+
+ function generate(x ,y : int; len : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+ span_image_filter_gray_2x2_ptr = ^span_image_filter_gray_2x2;
+ span_image_filter_gray_2x2 = object(span_image_filter )
+ constructor Construct(alloc : span_allocator_ptr ); overload;
+ constructor Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ back_color : aggclr_ptr;
+ inter : span_interpolator_ptr;
+ filter : image_filter_lut_ptr ); overload;
+
+ function generate(x ,y : int; len : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+ span_image_filter_gray_ptr = ^span_image_filter_gray;
+ span_image_filter_gray = object(span_image_filter )
+ constructor Construct(alloc : span_allocator_ptr ); overload;
+ constructor Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ back_color : aggclr_ptr;
+ inter : span_interpolator_ptr;
+ filter : image_filter_lut_ptr ); overload;
+
+ function generate(x ,y : int; len : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor span_image_filter_gray_nn.Construct(alloc : span_allocator_ptr );
+begin
+ inherited Construct(alloc );
+
+end;
+
+{ CONSTRUCT }
+constructor span_image_filter_gray_nn.Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ back_color : aggclr_ptr;
+ inter : span_interpolator_ptr );
+begin
+ inherited Construct(alloc ,src ,back_color ,inter ,NIL );
+
+end;
+
+{ GENERATE }
+function span_image_filter_gray_nn.generate;
+var
+ maxx ,maxy : int;
+
+ fg ,src_alpha : unsigned;
+
+ span : aggclr_ptr;
+
+begin
+ _interpolator.begin_(x + filter_dx_dbl ,y + filter_dy_dbl, len );
+
+ span:=_allocator.span;
+
+ maxx:=_source_image._width - 1;
+ maxy:=_source_image._height - 1;
+
+ repeat
+ _interpolator.coordinates(@x ,@y );
+
+ x:=shr_int32(x ,image_subpixel_shift );
+ y:=shr_int32(y ,image_subpixel_shift );
+
+ if (x >= 0 ) and
+ (y >= 0 ) and
+ (x <= maxx ) and
+ (y <= maxy ) then
+ begin
+ fg:=int8u_ptr(ptrcomp(_source_image.row(y ) ) + x * sizeof(int8u ) )^;
+
+ src_alpha:=base_mask;
+
+ end
+ else
+ begin
+ fg:=_background_color.v;
+
+ src_alpha:=_background_color.a;
+
+ end;
+
+ span.v:=int8u(fg );
+ span.a:=int8u(src_alpha );
+
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+
+ _interpolator.inc_operator;
+
+ dec(len );
+
+ until len = 0;
+
+ result:=_allocator.span;
+
+end;
+
+{ CONSTRUCT }
+constructor span_image_filter_gray_bilinear.Construct(alloc : span_allocator_ptr );
+begin
+ inherited Construct(alloc );
+
+end;
+
+{ CONSTRUCT }
+constructor span_image_filter_gray_bilinear.Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ back_color : aggclr_ptr;
+ inter : span_interpolator_ptr );
+begin
+ inherited Construct(alloc ,src ,back_color ,inter ,NIL );
+
+end;
+
+{ GENERATE }
+function span_image_filter_gray_bilinear.generate;
+var
+ fg ,src_alpha ,weight : unsigned;
+
+ back_v ,back_a : int8u;
+
+ fg_ptr : int8u_ptr;
+
+ span : aggclr_ptr;
+
+ maxx ,maxy ,x_hr ,y_hr ,x_lr ,y_lr : int;
+
+begin
+ _interpolator.begin_(x + filter_dx_dbl ,y + filter_dy_dbl ,len );
+
+ back_v:=_background_color.v;
+ back_a:=_background_color.a;
+
+ span:=_allocator.span;
+
+ maxx:=_source_image._width - 1;
+ maxy:=_source_image._height - 1;
+
+ repeat
+ _interpolator.coordinates(@x_hr ,@y_hr );
+
+ dec(x_hr ,filter_dx_int );
+ dec(y_hr ,filter_dy_int );
+
+ x_lr:=shr_int32(x_hr ,image_subpixel_shift );
+ y_lr:=shr_int32(y_hr ,image_subpixel_shift );
+
+ if (x_lr >= 0 ) and
+ (y_lr >= 0 ) and
+ (x_lr < maxx ) and
+ (y_lr < maxy ) then
+ begin
+ fg:=image_subpixel_size * image_subpixel_size div 2;
+
+ x_hr:=x_hr and image_subpixel_mask;
+ y_hr:=y_hr and image_subpixel_mask;
+
+ fg_ptr:=int8u_ptr(ptrcomp(_source_image.row(y_lr ) ) + x_lr * sizeof(int8u ) );
+
+ inc(fg ,fg_ptr^ * (image_subpixel_size - x_hr ) * (image_subpixel_size - y_hr ) );
+ inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+
+ inc(fg ,fg_ptr^ * (image_subpixel_size - y_hr ) * x_hr );
+ inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+
+ fg_ptr:=_source_image.next_row(int8u_ptr(ptrcomp(fg_ptr ) - 2 ) );
+
+ inc(fg ,fg_ptr^ * (image_subpixel_size - x_hr ) * y_hr );
+ inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+
+ inc(fg ,fg_ptr^ * x_hr * y_hr );
+ inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+
+ fg:=fg shr (image_subpixel_shift * 2 );
+
+ src_alpha:=base_mask;
+
+ end
+ else
+ begin
+ if (x_lr < -1 ) or
+ (y_lr < -1 ) or
+ (x_lr > maxx ) or
+ (y_lr > maxy ) then
+ begin
+ fg :=back_v;
+ src_alpha:=back_a;
+
+ end
+ else
+ begin
+ fg :=image_subpixel_size * image_subpixel_size div 2;
+ src_alpha:=fg;
+
+ x_hr:=x_hr and image_subpixel_mask;
+ y_hr:=y_hr and image_subpixel_mask;
+
+ weight:=
+ (image_subpixel_size - x_hr ) *
+ (image_subpixel_size - y_hr );
+
+ if (x_lr >= 0 ) and
+ (y_lr >= 0 ) and
+ (x_lr <= maxx ) and
+ (y_lr <= maxy ) then
+ begin
+ inc(fg ,weight * int8u_ptr(ptrcomp(_source_image.row(y_lr ) ) + x_lr * sizeof(int8u ) )^ );
+ inc(src_alpha ,weight * base_mask );
+
+ end
+ else
+ begin
+ inc(fg ,back_v * weight );
+ inc(src_alpha ,back_a * weight );
+
+ end;
+
+ inc(x_lr );
+
+ weight:=x_hr * (image_subpixel_size - y_hr );
+
+ if (x_lr >= 0 ) and
+ (y_lr >= 0 ) and
+ (x_lr <= maxx ) and
+ (y_lr <= maxy ) then
+ begin
+ inc(fg ,weight * int8u_ptr(ptrcomp(_source_image.row(y_lr ) ) + x_lr * sizeof(int8u ) )^ );
+ inc(src_alpha ,weight * base_mask );
+
+ end
+ else
+ begin
+ inc(fg ,back_v * weight );
+ inc(src_alpha ,back_a * weight );
+
+ end;
+
+ dec(x_lr );
+ inc(y_lr );
+
+ weight:=(image_subpixel_size - x_hr ) * y_hr;
+
+ if (x_lr >= 0 ) and
+ (y_lr >= 0 ) and
+ (x_lr <= maxx ) and
+ (y_lr <= maxy ) then
+ begin
+ inc(fg ,weight * int8u_ptr(ptrcomp(_source_image.row(y_lr ) ) + x_lr * sizeof(int8u ) )^ );
+ inc(src_alpha ,weight * base_mask );
+
+ end
+ else
+ begin
+ inc(fg ,back_v * weight );
+ inc(src_alpha ,back_a * weight );
+
+ end;
+
+ inc(x_lr );
+
+ weight:=x_hr * y_hr;
+
+ if (x_lr >= 0 ) and
+ (y_lr >= 0 ) and
+ (x_lr <= maxx ) and
+ (y_lr <= maxy ) then
+ begin
+ inc(fg ,weight * int8u_ptr(ptrcomp(_source_image.row(y_lr ) ) + x_lr * sizeof(int8u ) )^ );
+ inc(src_alpha ,weight * base_mask );
+
+ end
+ else
+ begin
+ inc(fg ,back_v * weight );
+ inc(src_alpha ,back_a * weight );
+
+ end;
+
+ fg :=fg shr (image_subpixel_shift * 2 );
+ src_alpha:=src_alpha shr (image_subpixel_shift * 2 );
+
+ end;
+
+ end;
+
+ span.v:=int8u(fg );
+ span.a:=int8u(src_alpha );
+
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+
+ _interpolator.inc_operator;
+
+ dec(len );
+
+ until len = 0;
+
+ result:=_allocator.span;
+
+end;
+
+{ CONSTRUCT }
+constructor span_image_filter_gray_2x2.Construct(alloc : span_allocator_ptr );
+begin
+ inherited Construct(alloc );
+
+end;
+
+{ CONSTRUCT }
+constructor span_image_filter_gray_2x2.Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ back_color : aggclr_ptr;
+ inter : span_interpolator_ptr;
+ filter : image_filter_lut_ptr );
+begin
+ inherited Construct(alloc ,src ,back_color ,inter ,filter );
+
+end;
+
+{ GENERATE }
+function span_image_filter_gray_2x2.generate;
+var
+ fg ,src_alpha ,weight : unsigned;
+
+ back_v ,back_a : int8u;
+
+ fg_ptr : int8u_ptr;
+
+ span : aggclr_ptr;
+
+ weight_array : int16_ptr;
+
+ maxx ,maxy ,x_hr ,y_hr ,x_lr ,y_lr : int;
+
+begin
+ _interpolator.begin_(x + filter_dx_dbl ,y + filter_dy_dbl ,len );
+
+ back_v:=_background_color.v;
+ back_a:=_background_color.a;
+
+ span:=_allocator.span;
+
+ weight_array:=
+ int16_ptr(
+ ptrcomp(_filter.weight_array ) +
+ ((_filter.diameter div 2 - 1) shl image_subpixel_shift ) * sizeof(int16 ) );
+
+ maxx:=_source_image._width - 1;
+ maxy:=_source_image._height - 1;
+
+ repeat
+ _interpolator.coordinates(@x_hr ,@y_hr );
+
+ dec(x_hr ,filter_dx_int );
+ dec(y_hr ,filter_dy_int );
+
+ x_lr:=shr_int32(x_hr ,image_subpixel_shift );
+ y_lr:=shr_int32(y_hr ,image_subpixel_shift );
+
+ if (x_lr >= 0 ) and
+ (y_lr >= 0 ) and
+ (x_lr < maxx ) and
+ (y_lr < maxy ) then
+ begin
+ fg:=image_filter_size div 2;
+
+ x_hr:=x_hr and image_subpixel_mask;
+ y_hr:=y_hr and image_subpixel_mask;
+
+ fg_ptr:=int8u_ptr(ptrcomp(_source_image.row(y_lr ) ) + x_lr * sizeof(int8u ) );
+
+ inc(fg ,
+ fg_ptr^ *
+ shr_int32(
+ int16_ptr(ptrcomp(weight_array ) + (x_hr + image_subpixel_size ) * sizeof(int16 ) )^ *
+ int16_ptr(ptrcomp(weight_array ) + (y_hr + image_subpixel_size ) * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,image_filter_shift ) );
+
+ inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+
+ inc(fg ,
+ fg_ptr^ *
+ shr_int32(
+ int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ *
+ int16_ptr(ptrcomp(weight_array ) + (y_hr + image_subpixel_size ) * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,image_filter_shift ) );
+
+ inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+
+ fg_ptr:=_source_image.next_row(int8u_ptr(ptrcomp(fg_ptr ) - 2 * sizeof(int8u ) ) );
+
+ inc(fg ,
+ fg_ptr^ *
+ shr_int32(
+ int16_ptr(ptrcomp(weight_array ) + (x_hr + image_subpixel_size ) * sizeof(int16 ) )^ *
+ int16_ptr(ptrcomp(weight_array ) + y_hr * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,image_filter_shift ) );
+
+ inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+
+ inc(fg ,
+ fg_ptr^ *
+ shr_int32(
+ int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ *
+ int16_ptr(ptrcomp(weight_array ) + y_hr * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,image_filter_shift ) );
+
+ inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+
+ fg:=fg shr image_filter_shift;
+
+ if fg > base_mask then
+ fg:=base_mask;
+
+ src_alpha:=base_mask;
+
+ end
+ else
+ begin
+ if (x_lr < -1 ) or
+ (y_lr < -1 ) or
+ (x_lr > maxx ) or
+ (y_lr > maxy ) then
+ begin
+ fg :=back_v;
+ src_alpha:=back_a;
+
+ end
+ else
+ begin
+ fg :=image_filter_size div 2;
+ src_alpha:=fg;
+
+ x_hr:=x_hr and image_subpixel_mask;
+ y_hr:=y_hr and image_subpixel_mask;
+
+ weight:=
+ shr_int32(
+ int16_ptr(ptrcomp(weight_array ) + (x_hr + image_subpixel_size ) * sizeof(int16 ) )^ *
+ int16_ptr(ptrcomp(weight_array ) + (y_hr + image_subpixel_size ) * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,image_filter_shift );
+
+ if (x_lr >= 0 ) and
+ (y_lr >= 0 ) and
+ (x_lr <= maxx ) and
+ (y_lr <= maxy ) then
+ begin
+ inc(fg ,weight * int8u_ptr(ptrcomp(_source_image.row(y_lr ) ) + x_lr * sizeof(int8u ) )^ );
+ inc(src_alpha ,weight * base_mask );
+
+ end
+ else
+ begin
+ inc(fg ,back_v * weight );
+ inc(src_alpha ,back_a * weight );
+
+ end;
+
+ inc(x_lr );
+
+ weight:=
+ shr_int32(
+ int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ *
+ int16_ptr(ptrcomp(weight_array ) + (y_hr + image_subpixel_size ) * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,image_filter_shift );
+
+ if (x_lr >= 0 ) and
+ (y_lr >= 0 ) and
+ (x_lr <= maxx ) and
+ (y_lr <= maxy ) then
+ begin
+ inc(fg ,weight * int8u_ptr(ptrcomp(_source_image.row(y_lr ) ) + x_lr * sizeof(int8u ) )^ );
+ inc(src_alpha ,weight * base_mask );
+
+ end
+ else
+ begin
+ inc(fg ,back_v * weight );
+ inc(src_alpha ,back_a * weight );
+
+ end;
+
+ dec(x_lr );
+ inc(y_lr );
+
+ weight:=
+ shr_int32(
+ int16_ptr(ptrcomp(weight_array ) + (x_hr + image_subpixel_size ) * sizeof(int16 ) )^ *
+ int16_ptr(ptrcomp(weight_array ) + y_hr * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,image_filter_shift );
+
+ if (x_lr >= 0 ) and
+ (y_lr >= 0 ) and
+ (x_lr <= maxx ) and
+ (y_lr <= maxy ) then
+ begin
+ inc(fg ,weight * int8u_ptr(ptrcomp(_source_image.row(y_lr ) ) + x_lr * sizeof(int8u ) )^ );
+ inc(src_alpha ,weight * base_mask );
+
+ end
+ else
+ begin
+ inc(fg ,back_v * weight );
+ inc(src_alpha ,back_a * weight );
+
+ end;
+
+ inc(x_lr );
+
+ weight:=
+ shr_int32(
+ int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ *
+ int16_ptr(ptrcomp(weight_array ) + y_hr * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,image_filter_shift );
+
+ if (x_lr >= 0 ) and
+ (y_lr >= 0 ) and
+ (x_lr <= maxx ) and
+ (y_lr <= maxy ) then
+ begin
+ inc(fg ,weight * int8u_ptr(ptrcomp(_source_image.row(y_lr ) ) + x_lr * sizeof(int8u ) )^ );
+ inc(src_alpha ,weight * base_mask );
+
+ end
+ else
+ begin
+ inc(fg ,back_v * weight );
+ inc(src_alpha ,back_a * weight );
+
+ end;
+
+ fg :=fg shr image_filter_shift;
+ src_alpha:=src_alpha shr image_filter_shift;
+
+ if src_alpha > base_mask then
+ src_alpha:=base_mask;
+
+ if fg > src_alpha then
+ fg:=src_alpha;
+
+ end;
+
+ end;
+
+ span.v:=int8u(fg );
+ span.a:=int8u(src_alpha );
+
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+
+ _interpolator.inc_operator;
+
+ dec(len );
+
+ until len = 0;
+
+ result:=_allocator.span;
+
+end;
+
+{ CONSTRUCT }
+constructor span_image_filter_gray.Construct(alloc : span_allocator_ptr );
+begin
+ inherited Construct(alloc );
+
+end;
+
+{ CONSTRUCT }
+constructor span_image_filter_gray.Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ back_color : aggclr_ptr;
+ inter : span_interpolator_ptr;
+ filter : image_filter_lut_ptr );
+begin
+ inherited Construct(alloc ,src ,back_color ,inter ,filter );
+
+end;
+
+{ GENERATE }
+function span_image_filter_gray.generate;
+var
+ fg ,src_alpha ,start ,start1 ,maxx ,maxy ,maxx2 ,maxy2 ,x_count ,weight_y ,
+ x_hr ,y_hr ,x_lr ,y_lr ,x_fract ,weight : int;
+
+ back_v ,back_a : int8u;
+
+ fg_ptr : int8u_ptr;
+
+ diameter ,y_count : unsigned;
+
+ weight_array : int16_ptr;
+
+ span : aggclr_ptr;
+
+begin
+ _interpolator.begin_(x + filter_dx_dbl ,y + filter_dy_dbl ,len );
+
+ back_v:=_background_color.v;
+ back_a:=_background_color.a;
+
+ diameter :=_filter.diameter;
+ start :=_filter.start;
+ start1 :=start - 1;
+ weight_array:=_filter.weight_array;
+
+ span:=_allocator.span;
+
+ maxx:=_source_image._width + start - 2;
+ maxy:=_source_image._height + start - 2;
+
+ maxx2:=_source_image._width - start - 1;
+ maxy2:=_source_image._height - start - 1;
+
+ repeat
+ _interpolator.coordinates(@x ,@y );
+
+ dec(x ,filter_dx_int );
+ dec(y ,filter_dy_int );
+
+ x_hr:=x;
+ y_hr:=y;
+
+ x_lr:=shr_int32(x_hr ,image_subpixel_shift );
+ y_lr:=shr_int32(y_hr ,image_subpixel_shift );
+
+ fg:=image_filter_size div 2;
+
+ x_fract:=x_hr and image_subpixel_mask;
+ y_count:=diameter;
+
+ if (x_lr >= -start ) and
+ (y_lr >= -start ) and
+ (x_lr <= maxx ) and
+ (y_lr <= maxy ) then
+ begin
+ y_hr :=image_subpixel_mask - (y_hr and image_subpixel_mask );
+ fg_ptr:=int8u_ptr(ptrcomp(_source_image.row(y_lr + start ) ) + (x_lr + start ) * sizeof(int8u ) );
+
+ repeat
+ x_count :=diameter;
+ weight_y:=int16_ptr(ptrcomp(weight_array ) + y_hr * sizeof(int16 ) )^;
+ x_hr :=image_subpixel_mask - x_fract;
+
+ repeat
+ inc(fg ,
+ fg_ptr^ *
+ shr_int32(
+ weight_y *
+ int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,image_filter_shift ) );
+
+ inc(x_hr ,image_subpixel_size );
+ dec(x_count );
+
+ until x_count = 0;
+
+ inc(y_hr ,image_subpixel_size );
+
+ fg_ptr:=_source_image.next_row(int8u_ptr(ptrcomp(fg_ptr ) - diameter ) );
+
+ dec(y_count );
+
+ until y_count = 0;
+
+ fg:=shr_int32(fg ,image_filter_shift );
+
+ if fg < 0 then
+ fg:=0;
+
+ if fg > base_mask then
+ fg:=base_mask;
+
+ src_alpha:=base_mask;
+
+ end
+ else
+ begin
+ if (x_lr < start1 ) or
+ (y_lr < start1 ) or
+ (x_lr > maxx2 ) or
+ (y_lr > maxy2 ) then
+ begin
+ fg :=back_v;
+ src_alpha:=back_a;
+
+ end
+ else
+ begin
+ src_alpha:=image_filter_size div 2;
+
+ y_lr:=shr_int32(y ,image_subpixel_shift ) + start;
+ y_hr:=image_subpixel_mask - (y_hr and image_subpixel_mask );
+
+ repeat
+ x_count :=diameter;
+ weight_y:=int16_ptr(ptrcomp(weight_array ) + y_hr * sizeof(int16 ) )^;
+
+ x_lr:=shr_int32(x ,image_subpixel_shift ) + start;
+ x_hr:=image_subpixel_mask - x_fract;
+
+ repeat
+ weight:=
+ shr_int32(
+ weight_y *
+ int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,image_filter_shift );
+
+ if (x_lr >= 0 ) and
+ (y_lr >= 0 ) and
+ (x_lr < trunc(_source_image._width ) ) and
+ (y_lr < trunc(_source_image._height ) ) then
+ begin
+ fg_ptr:=int8u_ptr(ptrcomp(_source_image.row(y_lr ) ) + x_lr * sizeof(int8u ) );
+
+ inc(fg ,fg_ptr^ * weight );
+ inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(src_alpha ,base_mask * weight );
+
+ end
+ else
+ begin
+ inc(fg ,back_v * weight );
+ inc(src_alpha ,back_a * weight );
+
+ end;
+
+ inc(x_hr ,image_subpixel_size );
+ inc(x_lr );
+ dec(x_count );
+
+ until x_count = 0;
+
+ inc(y_hr ,image_subpixel_size );
+ inc(y_lr );
+ dec(y_count );
+
+ until y_count = 0;
+
+ fg :=shr_int32(fg ,image_filter_shift );
+ src_alpha:=shr_int32(src_alpha ,image_filter_shift );
+
+ if fg < 0 then
+ fg:=0;
+
+ if src_alpha < 0 then
+ src_alpha:=0;
+
+ if src_alpha > base_mask then
+ src_alpha:=base_mask;
+
+ if fg > src_alpha then
+ fg:=src_alpha;
+
+ end;
+
+ end;
+
+ span.v:=int8u(fg );
+ span.a:=int8u(src_alpha );
+
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+
+ _interpolator.inc_operator;
+
+ dec(len );
+
+ until len = 0;
+
+ result:=_allocator.span;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_span_image_filter_rgb.pas b/src/corelib/render/software/agg_span_image_filter_rgb.pas
new file mode 100644
index 00000000..db740793
--- /dev/null
+++ b/src/corelib/render/software/agg_span_image_filter_rgb.pas
@@ -0,0 +1,1081 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// Adaptation for high precision colors has been sponsored by
+// Liberty Technology Systems, Inc., visit http://lib-sys.com
+//
+// Liberty Technology Systems, Inc. is the provider of
+// PostScript and PDF technology for software developers.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 01.03.2006-Milano: Unit port establishment
+//
+{ agg_span_image_filter_rgb.pas }
+unit
+ agg_span_image_filter_rgb ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+{$Q- }
+{$R- }
+uses
+ agg_basics ,
+ agg_color ,
+ agg_image_filters ,
+ agg_span_image_filter ,
+ agg_span_allocator ,
+ agg_span_interpolator_linear ,
+ agg_rendering_buffer ;
+
+{ TYPES DEFINITION }
+const
+ base_shift = agg_color.base_shift;
+ base_mask = agg_color.base_mask;
+
+type
+ span_image_filter_rgb_nn_ptr = ^span_image_filter_rgb_nn;
+ span_image_filter_rgb_nn = object(span_image_filter )
+ m_order : order_type;
+
+ constructor Construct(alloc : span_allocator_ptr; order : order_type ); overload;
+ constructor Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ back_color : aggclr_ptr;
+ inter : span_interpolator_ptr;
+ order : order_type ); overload;
+
+ function generate(x ,y : int; len : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+ span_image_filter_rgb_bilinear_ptr = ^span_image_filter_rgb_bilinear;
+ span_image_filter_rgb_bilinear = object(span_image_filter )
+ m_order : order_type;
+
+ constructor Construct(alloc : span_allocator_ptr; order : order_type ); overload;
+ constructor Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ back_color : aggclr_ptr;
+ inter : span_interpolator_ptr;
+ order : order_type ); overload;
+
+ function generate(x ,y : int; len : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+ span_image_filter_rgb_2x2_ptr = ^span_image_filter_rgb_2x2;
+ span_image_filter_rgb_2x2 = object(span_image_filter )
+ m_order : order_type;
+
+ constructor Construct(alloc : span_allocator_ptr; order : order_type ); overload;
+ constructor Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ back_color : aggclr_ptr;
+ inter : span_interpolator_ptr;
+ filter : image_filter_lut_ptr;
+ order : order_type ); overload;
+
+ function generate(x ,y : int; len : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+ span_image_filter_rgb_ptr = ^span_image_filter_rgb;
+ span_image_filter_rgb = object(span_image_filter )
+ m_order : order_type;
+
+ constructor Construct(alloc : span_allocator_ptr; order : order_type ); overload;
+ constructor Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ back_color : aggclr_ptr;
+ inter : span_interpolator_ptr;
+ filter : image_filter_lut_ptr;
+ order : order_type ); overload;
+
+ function generate(x ,y : int; len : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor span_image_filter_rgb_nn.Construct(alloc : span_allocator_ptr; order : order_type );
+begin
+ inherited Construct(alloc );
+
+ m_order:=order;
+
+end;
+
+{ CONSTRUCT }
+constructor span_image_filter_rgb_nn.Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ back_color : aggclr_ptr;
+ inter : span_interpolator_ptr;
+ order : order_type );
+begin
+ inherited Construct(alloc ,src ,back_color ,inter ,NIL );
+
+ m_order:=order;
+
+end;
+
+{ GENERATE }
+function span_image_filter_rgb_nn.generate;
+var
+ fg : array[0..2 ] of unsigned;
+
+ src_alpha : unsigned;
+
+ fg_ptr : int8u_ptr;
+
+ span : aggclr_ptr;
+
+ maxx ,maxy : int;
+
+begin
+ _interpolator.begin_(x + filter_dx_dbl ,y + filter_dy_dbl ,len );
+
+ span:=_allocator.span;
+
+ maxx:=_source_image._width - 1;
+ maxy:=_source_image._height - 1;
+
+ repeat
+ _interpolator.coordinates(@x ,@y );
+
+ x:=shr_int32(x ,image_subpixel_shift );
+ y:=shr_int32(y ,image_subpixel_shift );
+
+ if (x >= 0 ) and
+ (y >= 0 ) and
+ (x <= maxx ) and
+ (y <= maxy ) then
+ begin
+ fg_ptr:=int8u_ptr(ptrcomp(_source_image.row(y ) ) + (x + x + x ) * sizeof(int8u ) );
+
+ fg[0 ]:=fg_ptr^; inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ fg[1 ]:=fg_ptr^; inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ fg[2 ]:=fg_ptr^; inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+
+ src_alpha:=base_mask;
+
+ end
+ else
+ begin
+ fg[m_order.R ]:=_background_color.r;
+ fg[m_order.G ]:=_background_color.g;
+ fg[m_order.B ]:=_background_color.b;
+ src_alpha :=_background_color.a;
+
+ end;
+
+ span.r:=int8u(fg[m_order.R ] );
+ span.g:=int8u(fg[m_order.G ] );
+ span.b:=int8u(fg[m_order.B ] );
+ span.a:=int8u(src_alpha );
+
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+
+ _interpolator.inc_operator;
+
+ dec(len );
+
+ until len = 0;
+
+ result:=_allocator.span;
+
+end;
+
+{ CONSTRUCT }
+constructor span_image_filter_rgb_bilinear.Construct(alloc : span_allocator_ptr; order : order_type );
+begin
+ inherited Construct(alloc );
+
+ m_order:=order;
+
+end;
+
+{ CONSTRUCT }
+constructor span_image_filter_rgb_bilinear.Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ back_color : aggclr_ptr;
+ inter : span_interpolator_ptr;
+ order : order_type );
+begin
+ inherited Construct(alloc ,src ,back_color ,inter ,NIL );
+
+ m_order:=order;
+
+end;
+
+{ GENERATE }
+function span_image_filter_rgb_bilinear.generate;
+var
+ fg : array[0..2 ] of unsigned;
+
+ src_alpha ,weight : unsigned;
+
+ back_r ,back_g ,back_b ,back_a : int8u;
+
+ fg_ptr : int8u_ptr;
+
+ span : aggclr_ptr;
+
+ maxx ,maxy ,x_hr ,y_hr ,x_lr ,y_lr : int;
+
+begin
+ _interpolator.begin_(x + filter_dx_dbl ,y + filter_dy_dbl ,len );
+
+ back_r:=_background_color.r;
+ back_g:=_background_color.g;
+ back_b:=_background_color.b;
+ back_a:=_background_color.a;
+
+ span:=_allocator.span;
+
+ maxx:=_source_image._width - 1;
+ maxy:=_source_image._height - 1;
+
+ repeat
+ _interpolator.coordinates(@x_hr ,@y_hr );
+
+ dec(x_hr ,filter_dx_int );
+ dec(y_hr ,filter_dy_int );
+
+ x_lr:=shr_int32(x_hr ,image_subpixel_shift );
+ y_lr:=shr_int32(y_hr ,image_subpixel_shift );
+
+ if (x_lr >= 0 ) and
+ (y_lr >= 0 ) and
+ (x_lr < maxx ) and
+ (y_lr < maxy ) then
+ begin
+ fg[0 ]:=image_subpixel_size * image_subpixel_size div 2;
+ fg[1 ]:=fg[0 ];
+ fg[2 ]:=fg[0 ];
+
+ x_hr:=x_hr and image_subpixel_mask;
+ y_hr:=y_hr and image_subpixel_mask;
+
+ fg_ptr:=int8u_ptr(ptrcomp(_source_image.row(y_lr ) ) + (x_lr + x_lr + x_lr ) * sizeof(int8u ) );
+ weight:=(image_subpixel_size - x_hr ) * (image_subpixel_size - y_hr );
+
+ inc(fg[0 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+
+ weight:=x_hr * (image_subpixel_size - y_hr );
+
+ inc(fg[0 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+
+ fg_ptr:=_source_image.next_row(int8u_ptr(ptrcomp(fg_ptr ) - 6 * sizeof(int8u ) ) );
+ weight:=(image_subpixel_size - x_hr ) * y_hr;
+
+ inc(fg[0 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+
+ weight:=x_hr * y_hr;
+
+ inc(fg[0 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+
+ fg[0 ]:=fg[0 ] shr (image_subpixel_shift * 2 );
+ fg[1 ]:=fg[1 ] shr (image_subpixel_shift * 2 );
+ fg[2 ]:=fg[2 ] shr (image_subpixel_shift * 2 );
+
+ src_alpha:=base_mask;
+
+ end
+ else
+ begin
+ if (x_lr < -1 ) or
+ (y_lr < -1 ) or
+ (x_lr > maxx ) or
+ (y_lr > maxy ) then
+ begin
+ fg[m_order.R ]:=back_r;
+ fg[m_order.G ]:=back_g;
+ fg[m_order.B ]:=back_b;
+ src_alpha :=back_a;
+
+ end
+ else
+ begin
+ fg[0 ] :=image_subpixel_size * image_subpixel_size div 2;
+ fg[1 ] :=fg[0 ];
+ fg[2 ] :=fg[0 ];
+ src_alpha:=fg[0 ];
+
+ x_hr:=x_hr and image_subpixel_mask;
+ y_hr:=y_hr and image_subpixel_mask;
+
+ weight:=(image_subpixel_size - x_hr ) * (image_subpixel_size - y_hr );
+
+ if (x_lr >= 0 ) and
+ (y_lr >= 0 ) and
+ (x_lr <= maxx ) and
+ (y_lr <= maxy ) then
+ begin
+ fg_ptr:=int8u_ptr(ptrcomp(_source_image.row(y_lr ) ) + (x_lr + x_lr + x_lr ) * sizeof(int8u ) );
+
+ inc(fg[0 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+
+ inc(src_alpha ,weight * base_mask );
+
+ end
+ else
+ begin
+ inc(fg[m_order.R ] ,back_r * weight );
+ inc(fg[m_order.G ] ,back_g * weight );
+ inc(fg[m_order.B ] ,back_b * weight );
+
+ inc(src_alpha ,back_a * weight );
+
+ end;
+
+ inc(x_lr );
+
+ weight:=x_hr * (image_subpixel_size - y_hr );
+
+ if (x_lr >= 0 ) and
+ (y_lr >= 0 ) and
+ (x_lr <= maxx ) and
+ (y_lr <= maxy ) then
+ begin
+ fg_ptr:=int8u_ptr(ptrcomp(_source_image.row(y_lr ) ) + (x_lr + x_lr + x_lr ) * sizeof(int8u ) );
+
+ inc(fg[0 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+
+ inc(src_alpha ,weight * base_mask );
+
+ end
+ else
+ begin
+ inc(fg[m_order.R ] ,back_r * weight );
+ inc(fg[m_order.G ] ,back_g * weight );
+ inc(fg[m_order.B ] ,back_b * weight );
+
+ inc(src_alpha ,back_a * weight );
+
+ end;
+
+ dec(x_lr );
+ inc(y_lr );
+
+ weight:=(image_subpixel_size - x_hr ) * y_hr;
+
+ if (x_lr >= 0 ) and
+ (y_lr >= 0 ) and
+ (x_lr <= maxx ) and
+ (y_lr <= maxy ) then
+ begin
+ fg_ptr:=int8u_ptr(ptrcomp(_source_image.row(y_lr ) ) + (x_lr + x_lr + x_lr ) * sizeof(int8u ) );
+
+ inc(fg[0 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+
+ inc(src_alpha ,weight * base_mask );
+
+ end
+ else
+ begin
+ inc(fg[m_order.R ] ,back_r * weight );
+ inc(fg[m_order.G ] ,back_g * weight );
+ inc(fg[m_order.B ] ,back_b * weight );
+
+ inc(src_alpha ,back_a * weight );
+
+ end;
+
+ inc(x_lr );
+
+ weight:=x_hr * y_hr;
+
+ if (x_lr >= 0 ) and
+ (y_lr >= 0 ) and
+ (x_lr <= maxx ) and
+ (y_lr <= maxy ) then
+ begin
+ fg_ptr:=int8u_ptr(ptrcomp(_source_image.row(y_lr ) ) + (x_lr + x_lr + x_lr ) * sizeof(int8u ) );
+
+ inc(fg[0 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+
+ inc(src_alpha ,weight * base_mask );
+
+ end
+ else
+ begin
+ inc(fg[m_order.R ] ,back_r * weight );
+ inc(fg[m_order.G ] ,back_g * weight );
+ inc(fg[m_order.B ] ,back_b * weight );
+
+ inc(src_alpha ,back_a * weight );
+
+ end;
+
+ fg[0 ]:=fg[0 ] shr (image_subpixel_shift * 2 );
+ fg[1 ]:=fg[0 ] shr (image_subpixel_shift * 2 );
+ fg[2 ]:=fg[0 ] shr (image_subpixel_shift * 2 );
+
+ src_alpha:=src_alpha shr (image_subpixel_shift * 2 );
+
+ end;
+
+ end;
+
+ span.r:=int8u(fg[m_order.R ] );
+ span.g:=int8u(fg[m_order.G ] );
+ span.b:=int8u(fg[m_order.B ] );
+ span.a:=int8u(src_alpha );
+
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+
+ _interpolator.inc_operator;
+
+ dec(len );
+
+ until len = 0;
+
+ result:=_allocator.span;
+
+end;
+
+{ CONSTRUCT }
+constructor span_image_filter_rgb_2x2.Construct(alloc : span_allocator_ptr; order : order_type );
+begin
+ inherited Construct(alloc );
+
+ m_order:=order;
+
+end;
+
+{ CONSTRUCT }
+constructor span_image_filter_rgb_2x2.Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ back_color : aggclr_ptr;
+ inter : span_interpolator_ptr;
+ filter : image_filter_lut_ptr;
+ order : order_type );
+begin
+ inherited Construct(alloc ,src ,back_color ,inter ,filter );
+
+ m_order:=order;
+
+end;
+
+{ GENERATE }
+function span_image_filter_rgb_2x2.generate;
+var
+ fg : array[0..2 ] of unsigned;
+
+ src_alpha ,weight : unsigned;
+
+ back_r ,back_g ,back_b ,back_a : int8u;
+
+ fg_ptr : int8u_ptr;
+
+ span : aggclr_ptr;
+
+ weight_array : int16_ptr;
+
+ maxx ,maxy ,x_hr ,y_hr ,x_lr ,y_lr : int;
+
+begin
+ _interpolator.begin_(x + filter_dx_dbl ,y + filter_dy_dbl ,len );
+
+ back_r:=_background_color.r;
+ back_g:=_background_color.g;
+ back_b:=_background_color.b;
+ back_a:=_background_color.a;
+
+ span:=_allocator.span;
+
+ weight_array:=
+ int16_ptr(
+ ptrcomp(_filter.weight_array ) +
+ ((_filter.diameter div 2 - 1 ) shl image_subpixel_shift ) * sizeof(int16 ) );
+
+ maxx:=_source_image._width - 1;
+ maxy:=_source_image._height - 1;
+
+ repeat
+ _interpolator.coordinates(@x_hr ,@y_hr );
+
+ dec(x_hr ,filter_dx_int );
+ dec(y_hr ,filter_dy_int );
+
+ x_lr:=shr_int32(x_hr ,image_subpixel_shift );
+ y_lr:=shr_int32(y_hr ,image_subpixel_shift );
+
+ if (x_lr >= 0 ) and
+ (y_lr >= 0 ) and
+ (x_lr < maxx ) and
+ (y_lr < maxy ) then
+ begin
+ fg[0 ]:=image_filter_size div 2;
+ fg[1 ]:=fg[0 ];
+ fg[2 ]:=fg[0 ];
+
+ x_hr:=x_hr and image_subpixel_mask;
+ y_hr:=y_hr and image_subpixel_mask;
+
+ fg_ptr:=int8u_ptr(ptrcomp(_source_image.row(y_lr ) ) + (x_lr + x_lr + x_lr ) * sizeof(int8u ) );
+ weight:=
+ shr_int32(
+ int16_ptr(ptrcomp(weight_array ) + (x_hr + image_subpixel_size ) * sizeof(int16 ) )^ *
+ int16_ptr(ptrcomp(weight_array ) + (y_hr + image_subpixel_size ) * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,image_filter_shift );
+
+ inc(fg[0 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+
+ weight:=
+ shr_int32(
+ int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ *
+ int16_ptr(ptrcomp(weight_array ) + (y_hr + image_subpixel_size ) * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,image_filter_shift );
+
+ inc(fg[0 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+
+ fg_ptr:=_source_image.next_row(int8u_ptr(ptrcomp(fg_ptr ) - 6 * sizeof(int8u ) ) );
+ weight:=
+ shr_int32(
+ int16_ptr(ptrcomp(weight_array ) + (x_hr + image_subpixel_size ) * sizeof(int16 ) )^ *
+ int16_ptr(ptrcomp(weight_array ) + y_hr * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,image_filter_shift );
+
+ inc(fg[0 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+
+ weight:=
+ shr_int32(
+ int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ *
+ int16_ptr(ptrcomp(weight_array ) + y_hr * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,image_filter_shift );
+
+ inc(fg[0 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+
+ fg[0 ]:=fg[0 ] shr image_filter_shift;
+ fg[1 ]:=fg[1 ] shr image_filter_shift;
+ fg[2 ]:=fg[2 ] shr image_filter_shift;
+
+ src_alpha:=base_mask;
+
+ if fg[0 ] > base_mask then
+ fg[0 ]:=base_mask;
+
+ if fg[1 ] > base_mask then
+ fg[1 ]:=base_mask;
+
+ if fg[2 ] > base_mask then
+ fg[2 ]:=base_mask;
+
+ end
+ else
+ begin
+ if (x_lr < -1 ) or
+ (y_lr < -1 ) or
+ (x_lr > maxx ) or
+ (y_lr > maxy ) then
+ begin
+ fg[m_order.R ]:=back_r;
+ fg[m_order.G ]:=back_g;
+ fg[m_order.B ]:=back_b;
+ src_alpha :=back_a;
+
+ end
+ else
+ begin
+ fg[0 ] :=image_filter_size div 2;
+ fg[1 ] :=fg[0 ];
+ fg[2 ] :=fg[0 ];
+ src_alpha:=fg[0 ];
+
+ x_hr:=x_hr and image_subpixel_mask;
+ y_hr:=y_hr and image_subpixel_mask;
+
+ weight:=
+ shr_int32(
+ int16_ptr(ptrcomp(weight_array ) + (x_hr + image_subpixel_size ) * sizeof(int16 ) )^ *
+ int16_ptr(ptrcomp(weight_array ) + (y_hr + image_subpixel_size ) * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,image_filter_shift );
+
+ if (x_lr >= 0 ) and
+ (y_lr >= 0 ) and
+ (x_lr <= maxx ) and
+ (y_lr <= maxy ) then
+ begin
+ fg_ptr:=int8u_ptr(ptrcomp(_source_image.row(y_lr ) ) + (x_lr + x_lr + x_lr ) * sizeof(int8u ) );
+
+ inc(fg[0 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+
+ inc(src_alpha ,weight * base_mask );
+
+ end
+ else
+ begin
+ inc(fg[m_order.R ] ,back_r * weight );
+ inc(fg[m_order.G ] ,back_g * weight );
+ inc(fg[m_order.B ] ,back_b * weight );
+
+ inc(src_alpha ,back_a * weight );
+
+ end;
+
+ inc(x_lr );
+
+ weight:=
+ shr_int32(
+ int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ *
+ int16_ptr(ptrcomp(weight_array ) + (y_hr + image_subpixel_size ) * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,image_filter_shift );
+
+ if (x_lr >= 0 ) and
+ (y_lr >= 0 ) and
+ (x_lr <= maxx ) and
+ (y_lr <= maxy ) then
+ begin
+ fg_ptr:=int8u_ptr(ptrcomp(_source_image.row(y_lr) ) + (x_lr + x_lr + x_lr ) * sizeof(int8u ) );
+
+ inc(fg[0 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+
+ inc(src_alpha ,weight * base_mask );
+
+ end
+ else
+ begin
+ inc(fg[m_order.R ] ,back_r * weight );
+ inc(fg[m_order.G ] ,back_g * weight );
+ inc(fg[m_order.B ] ,back_b * weight );
+
+ inc(src_alpha ,back_a * weight );
+
+ end;
+
+ dec(x_lr );
+ inc(y_lr );
+
+ weight:=
+ shr_int32(
+ int16_ptr(ptrcomp(weight_array ) + (x_hr + image_subpixel_size ) * sizeof(int16 ) )^ *
+ int16_ptr(ptrcomp(weight_array ) + y_hr * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,image_filter_shift );
+
+ if (x_lr >= 0 ) and
+ (y_lr >= 0 ) and
+ (x_lr <= maxx ) and
+ (y_lr <= maxy ) then
+ begin
+ fg_ptr:=int8u_ptr(ptrcomp(_source_image.row(y_lr ) ) + (x_lr + x_lr + x_lr ) * sizeof(int8u ) );
+
+ inc(fg[0 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+
+ inc(src_alpha ,weight * base_mask );
+
+ end
+ else
+ begin
+ inc(fg[m_order.R ] ,back_r * weight );
+ inc(fg[m_order.G ] ,back_g * weight );
+ inc(fg[m_order.B ] ,back_b * weight );
+
+ inc(src_alpha ,back_a * weight );
+
+ end;
+
+ inc(x_lr );
+
+ weight:=
+ shr_int32(
+ int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ *
+ int16_ptr(ptrcomp(weight_array ) + y_hr * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,image_filter_shift );
+
+ if (x_lr >= 0 ) and
+ (y_lr >= 0 ) and
+ (x_lr <= maxx ) and
+ (y_lr <= maxy ) then
+ begin
+ fg_ptr:=int8u_ptr(ptrcomp(_source_image.row(y_lr ) ) + (x_lr + x_lr + x_lr ) * sizeof(int8u ) );
+
+ inc(fg[0 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+
+ inc(src_alpha ,weight * base_mask );
+
+ end
+ else
+ begin
+ inc(fg[m_order.R] ,back_r * weight );
+ inc(fg[m_order.G] ,back_g * weight );
+ inc(fg[m_order.B] ,back_b * weight );
+
+ inc(src_alpha ,back_a * weight );
+
+ end;
+
+ fg[0 ]:=fg[0 ] shr image_filter_shift;
+ fg[1 ]:=fg[0 ] shr image_filter_shift;
+ fg[2 ]:=fg[0 ] shr image_filter_shift;
+
+ src_alpha:=src_alpha shr image_filter_shift;
+
+ if src_alpha > base_mask then
+ src_alpha:=base_mask;
+
+ if fg[0 ] > src_alpha then
+ fg[0 ]:=src_alpha;
+
+ if fg[1 ] > src_alpha then
+ fg[1 ]:=src_alpha;
+
+ if fg[2 ] > src_alpha then
+ fg[2 ]:=src_alpha;
+
+ end;
+
+ end;
+
+ span.r:=int8u(fg[m_order.R ] );
+ span.g:=int8u(fg[m_order.G ] );
+ span.b:=int8u(fg[m_order.B ] );
+ span.a:=int8u(src_alpha );
+
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+
+ _interpolator.inc_operator;
+
+ dec(len );
+
+ until len = 0;
+
+ result:=_allocator.span;
+
+end;
+
+{ CONSTRUCT }
+constructor span_image_filter_rgb.Construct(alloc : span_allocator_ptr; order : order_type );
+begin
+ inherited Construct(alloc );
+
+ m_order:=order;
+
+end;
+
+{ CONSTRUCT }
+constructor span_image_filter_rgb.Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ back_color : aggclr_ptr;
+ inter : span_interpolator_ptr;
+ filter : image_filter_lut_ptr;
+ order : order_type );
+begin
+ inherited Construct(alloc ,src ,back_color ,inter ,filter );
+
+ m_order:=order;
+
+end;
+
+{ GENERATE }
+function span_image_filter_rgb.generate;
+var
+ fg : array[0..2 ] of int;
+
+ src_alpha ,start ,start1 ,maxx ,maxy ,maxx2 ,maxy2 ,x_count ,weight_y ,weight ,
+ x_hr ,y_hr ,x_lr ,y_lr ,x_fract : int;
+
+ back_r ,back_g ,back_b ,back_a : int8u;
+
+ fg_ptr : int8u_ptr;
+
+ diameter ,step_back ,y_count : unsigned;
+
+ weight_array : int16_ptr;
+
+ span : aggclr_ptr;
+
+begin
+ _interpolator.begin_(x + filter_dx_dbl ,y + filter_dy_dbl ,len );
+
+ back_r:=_background_color.r;
+ back_g:=_background_color.g;
+ back_b:=_background_color.b;
+ back_a:=_background_color.a;
+
+ diameter :=_filter.diameter;
+ start :=_filter.start;
+ start1 :=start - 1;
+ weight_array:=_filter.weight_array;
+
+ step_back:=diameter * 3;
+
+ span:=_allocator.span;
+
+ maxx:=_source_image._width + start - 2;
+ maxy:=_source_image._height + start - 2;
+
+ maxx2:=_source_image._width - start - 1;
+ maxy2:=_source_image._height - start - 1;
+
+ repeat
+ _interpolator.coordinates(@x ,@y );
+
+ dec(x ,filter_dx_int );
+ dec(y ,filter_dy_int );
+
+ x_hr:=x;
+ y_hr:=y;
+
+ x_lr:=shr_int32(x_hr ,image_subpixel_shift );
+ y_lr:=shr_int32(y_hr ,image_subpixel_shift );
+
+ fg[0 ]:=image_filter_size div 2;
+ fg[1 ]:=fg[0 ];
+ fg[2 ]:=fg[0 ];
+
+ x_fract:=x_hr and image_subpixel_mask;
+ y_count:=diameter;
+
+ if (x_lr >= -start ) and
+ (y_lr >= -start ) and
+ (x_lr <= maxx ) and
+ (y_lr <= maxy ) then
+ begin
+ y_hr :=image_subpixel_mask - (y_hr and image_subpixel_mask );
+ fg_ptr:=int8u_ptr(ptrcomp(_source_image.row(y_lr + start ) ) + (x_lr + start ) * 3 * sizeof(int8u ) );
+
+ repeat
+ x_count :=diameter;
+ weight_y:=int16_ptr(ptrcomp(weight_array ) + y_hr * sizeof(int16 ) )^;
+ x_hr :=image_subpixel_mask - x_fract;
+
+ repeat
+ weight:=
+ shr_int32(
+ weight_y *
+ int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,image_filter_shift );
+
+ inc(fg[0 ] ,fg_ptr^ * weight ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,fg_ptr^ * weight ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,fg_ptr^ * weight ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+
+ inc(x_hr ,image_subpixel_size );
+ dec(x_count );
+
+ until x_count = 0;
+
+ inc(y_hr ,image_subpixel_size );
+
+ fg_ptr:=_source_image.next_row(int8u_ptr(ptrcomp(fg_ptr ) - step_back * sizeof(int8u ) ) );
+
+ dec(y_count );
+
+ until y_count = 0;
+
+ fg[0 ]:=shr_int32(fg[0 ] ,image_filter_shift );
+ fg[1 ]:=shr_int32(fg[1 ] ,image_filter_shift );
+ fg[2 ]:=shr_int32(fg[2 ] ,image_filter_shift );
+
+ if fg[0 ] < 0 then
+ fg[0 ]:=0;
+
+ if fg[1 ] < 0 then
+ fg[1 ]:=0;
+
+ if fg[2 ] < 0 then
+ fg[2 ]:=0;
+
+ if fg[0 ] > base_mask then
+ fg[0 ]:=base_mask;
+
+ if fg[1 ] > base_mask then
+ fg[1 ]:=base_mask;
+
+ if fg[2 ] > base_mask then
+ fg[2 ]:=base_mask;
+
+ src_alpha:=base_mask;
+
+ end
+ else
+ begin
+ if (x_lr < start1 ) or
+ (y_lr < start1 ) or
+ (x_lr > maxx2 ) or
+ (y_lr > maxy2 ) then
+ begin
+ fg[m_order.R ]:=back_r;
+ fg[m_order.G ]:=back_g;
+ fg[m_order.B ]:=back_b;
+ src_alpha :=back_a;
+
+ end
+ else
+ begin
+ src_alpha:=image_filter_size div 2;
+
+ y_lr:=shr_int32(y ,image_subpixel_shift ) + start;
+ y_hr:=image_subpixel_mask - (y_hr and image_subpixel_mask );
+
+ repeat
+ x_count :=diameter;
+ weight_y:=int16_ptr(ptrcomp(weight_array ) + y_hr * sizeof(int16 ) )^;
+
+ x_lr:=shr_int32(x ,image_subpixel_shift ) + start;
+ x_hr:=image_subpixel_mask - x_fract;
+
+ repeat
+ weight:=
+ shr_int32(
+ weight_y *
+ int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,image_filter_shift );
+
+ if (x_lr >= 0 ) and
+ (y_lr >= 0 ) and
+ (x_lr < trunc(_source_image._width ) ) and
+ (y_lr < trunc(_source_image._height ) ) then
+ begin
+ fg_ptr:=int8u_ptr(ptrcomp(_source_image.row(y_lr ) ) + x_lr * 3 * sizeof(int8u ) );
+
+ inc(fg[0 ] ,fg_ptr^ * weight ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,fg_ptr^ * weight ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,fg_ptr^ * weight ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+
+ inc(src_alpha ,base_mask * weight );
+
+ end
+ else
+ begin
+ inc(fg[m_order.R ] ,back_r * weight );
+ inc(fg[m_order.G ] ,back_g * weight );
+ inc(fg[m_order.B ] ,back_b * weight );
+
+ inc(src_alpha ,back_a * weight );
+
+ end;
+
+ inc(x_hr ,image_subpixel_size );
+ inc(x_lr );
+ dec(x_count );
+
+ until x_count = 0;
+
+ inc(y_hr ,image_subpixel_size );
+ inc(y_lr );
+ dec(y_count );
+
+ until y_count = 0;
+
+ fg[0 ]:=shr_int32(fg[0 ] ,image_filter_shift );
+ fg[1 ]:=shr_int32(fg[1 ] ,image_filter_shift );
+ fg[2 ]:=shr_int32(fg[2 ] ,image_filter_shift );
+
+ src_alpha:=shr_int32(src_alpha ,image_filter_shift );
+
+ if fg[0 ] < 0 then
+ fg[0 ]:=0;
+
+ if fg[1 ] < 0 then
+ fg[1 ]:=0;
+
+ if fg[2 ] < 0 then
+ fg[2 ]:=0;
+
+ if src_alpha < 0 then
+ src_alpha:=0;
+
+ if src_alpha > base_mask then
+ src_alpha:=base_mask;
+
+ if fg[0 ] > src_alpha then
+ fg[0 ]:=src_alpha;
+
+ if fg[1 ] > src_alpha then
+ fg[1 ]:=src_alpha;
+
+ if fg[2 ] > src_alpha then
+ fg[2 ]:=src_alpha;
+
+ end;
+
+ end;
+
+ span.r:=int8u(fg[m_order.R ] );
+ span.g:=int8u(fg[m_order.G ] );
+ span.b:=int8u(fg[m_order.B ] );
+ span.a:=int8u(src_alpha );
+
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+
+ _interpolator.inc_operator;
+
+ dec(len );
+
+ until len = 0;
+
+ result:=_allocator.span;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_span_image_filter_rgba.pas b/src/corelib/render/software/agg_span_image_filter_rgba.pas
new file mode 100644
index 00000000..7c43d72e
--- /dev/null
+++ b/src/corelib/render/software/agg_span_image_filter_rgba.pas
@@ -0,0 +1,1072 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// Adaptation for high precision colors has been sponsored by
+// Liberty Technology Systems, Inc., visit http://lib-sys.com
+//
+// Liberty Technology Systems, Inc. is the provider of
+// PostScript and PDF technology for software developers.
+//
+//----------------------------------------------------------------------------
+//
+// classes span_image_filter_rgba32*
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 01.03.2006-Milano: Unit port establishment
+//
+{ agg_span_image_filter_rgba.pas }
+unit
+ agg_span_image_filter_rgba ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+{$Q- }
+{$R- }
+uses
+ agg_basics ,
+ agg_color ,
+ agg_image_filters ,
+ agg_span_image_filter ,
+ agg_span_allocator ,
+ agg_span_interpolator_linear ,
+ agg_rendering_buffer ;
+
+{ TYPES DEFINITION }
+const
+ base_shift = agg_color.base_shift;
+ base_mask = agg_color.base_mask;
+
+type
+ span_image_filter_rgba_nn_ptr = ^span_image_filter_rgba_nn;
+ span_image_filter_rgba_nn = object(span_image_filter )
+ m_order : order_type;
+
+ constructor Construct(alloc : span_allocator_ptr; order : order_type ); overload;
+ constructor Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ back_color : aggclr_ptr;
+ inter : span_interpolator_ptr;
+ order : order_type ); overload;
+
+ function generate(x ,y : int; len : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+ span_image_filter_rgba_bilinear_ptr = ^span_image_filter_rgba_bilinear;
+ span_image_filter_rgba_bilinear = object(span_image_filter )
+ m_order : order_type;
+
+ constructor Construct(alloc : span_allocator_ptr; order : order_type ); overload;
+ constructor Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ back_color : aggclr_ptr;
+ inter : span_interpolator_ptr;
+ order : order_type ); overload;
+
+ function generate(x ,y : int; len : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+ span_image_filter_rgba_2x2_ptr = ^span_image_filter_rgba_2x2;
+ span_image_filter_rgba_2x2 = object(span_image_filter )
+ m_order : order_type;
+
+ constructor Construct(alloc : span_allocator_ptr; order : order_type ); overload;
+ constructor Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ back_color : aggclr_ptr;
+ inter : span_interpolator_ptr;
+ filter : image_filter_lut_ptr;
+ order : order_type ); overload;
+
+ function generate(x ,y : int; len : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+ span_image_filter_rgba_ptr = ^span_image_filter_rgba;
+ span_image_filter_rgba = object(span_image_filter )
+ m_order : order_type;
+
+ constructor Construct(alloc : span_allocator_ptr; order : order_type ); overload;
+ constructor Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ back_color : aggclr_ptr;
+ inter : span_interpolator_ptr;
+ filter : image_filter_lut_ptr;
+ order : order_type ); overload;
+
+ function generate(x ,y : int; len : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor span_image_filter_rgba_nn.Construct(alloc : span_allocator_ptr; order : order_type );
+begin
+ inherited Construct(alloc );
+
+ m_order:=order;
+
+end;
+
+{ CONSTRUCT }
+constructor span_image_filter_rgba_nn.Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ back_color : aggclr_ptr;
+ inter : span_interpolator_ptr;
+ order : order_type );
+begin
+ inherited Construct(alloc ,src ,back_color ,inter ,NIL );
+
+ m_order:=order;
+
+end;
+
+{ GENERATE }
+function span_image_filter_rgba_nn.generate;
+var
+ fg : array[0..3 ] of unsigned;
+
+ fg_ptr : int8u_ptr;
+
+ span : aggclr_ptr;
+
+ maxx ,maxy : int;
+
+begin
+ _interpolator.begin_(x + filter_dx_dbl ,y + filter_dy_dbl ,len );
+
+ span:=_allocator.span;
+
+ maxx:=_source_image._width - 1;
+ maxy:=_source_image._height - 1;
+
+ repeat
+ _interpolator.coordinates(@x ,@y );
+
+ x:=shr_int32(x ,image_subpixel_shift );
+ y:=shr_int32(y ,image_subpixel_shift );
+
+ if (x >= 0 ) and
+ (y >= 0 ) and
+ (x <= maxx ) and
+ (y <= maxy ) then
+ begin
+ fg_ptr:=int8u_ptr(ptrcomp(_source_image.row(y ) ) + (x shl 2 ) * sizeof(int8u ) );
+
+ fg[0 ]:=fg_ptr^; inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ fg[1 ]:=fg_ptr^; inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ fg[2 ]:=fg_ptr^; inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ fg[3 ]:=fg_ptr^; inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+
+ end
+ else
+ begin
+ fg[m_order.R ]:=_background_color.r;
+ fg[m_order.G ]:=_background_color.g;
+ fg[m_order.B ]:=_background_color.b;
+ fg[m_order.A ]:=_background_color.a;
+
+ end;
+
+ span.r:=fg[m_order.R ];
+ span.g:=fg[m_order.G ];
+ span.b:=fg[m_order.B ];
+ span.a:=fg[m_order.A ];
+
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+
+ _interpolator.inc_operator;
+
+ dec(len );
+
+ until len = 0;
+
+ result:=_allocator.span;
+
+end;
+
+{ CONSTRUCT }
+constructor span_image_filter_rgba_bilinear.Construct(alloc : span_allocator_ptr; order : order_type );
+begin
+ inherited Construct(alloc );
+
+ m_order:=order;
+
+end;
+
+{ CONSTRUCT }
+constructor span_image_filter_rgba_bilinear.Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ back_color : aggclr_ptr;
+ inter : span_interpolator_ptr;
+ order : order_type );
+begin
+ inherited Construct(alloc ,src ,back_color ,inter ,NIL );
+
+ m_order:=order;
+
+end;
+
+{ GENERATE }
+function span_image_filter_rgba_bilinear.generate;
+var
+ fg : array[0..3 ] of unsigned;
+
+ back_r ,back_g ,back_b ,back_a : int8u;
+
+ fg_ptr : int8u_ptr;
+
+ span : aggclr_ptr;
+
+ maxx ,maxy ,x_hr ,y_hr ,x_lr ,y_lr : int;
+
+ weight : unsigned;
+
+begin
+ _interpolator.begin_(x + filter_dx_dbl ,y + filter_dy_dbl ,len );
+
+ back_r:=_background_color.r;
+ back_g:=_background_color.g;
+ back_b:=_background_color.b;
+ back_a:=_background_color.a;
+
+ span:=_allocator.span;
+
+ maxx:=_source_image._width - 1;
+ maxy:=_source_image._height - 1;
+
+ repeat
+ _interpolator.coordinates(@x_hr ,@y_hr );
+
+ dec(x_hr ,filter_dx_int );
+ dec(y_hr ,filter_dy_int );
+
+ x_lr:=shr_int32(x_hr ,image_subpixel_shift );
+ y_lr:=shr_int32(y_hr ,image_subpixel_shift );
+
+ if (x_lr >= 0 ) and
+ (y_lr >= 0 ) and
+ (x_lr < maxx ) and
+ (y_lr < maxy ) then
+ begin
+ fg[0 ]:=image_subpixel_size * image_subpixel_size div 2;
+ fg[1 ]:=fg[0 ];
+ fg[2 ]:=fg[0 ];
+ fg[3 ]:=fg[0 ];
+
+ x_hr:=x_hr and image_subpixel_mask;
+ y_hr:=y_hr and image_subpixel_mask;
+
+ fg_ptr:=int8u_ptr(ptrcomp(_source_image.row(y_lr ) ) + (x_lr shl 2 ) * sizeof(int8u ) );
+ weight:=(image_subpixel_size - x_hr ) * (image_subpixel_size - y_hr );
+
+ inc(fg[0 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[3 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+
+ weight:=x_hr * (image_subpixel_size - y_hr );
+
+ inc(fg[0 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[3 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+
+ fg_ptr:=_source_image.next_row(int8u_ptr(ptrcomp(fg_ptr ) - 8 * sizeof(int8u ) ) );
+ weight:=(image_subpixel_size - x_hr ) * y_hr;
+
+ inc(fg[0 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[3 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+
+ weight:=x_hr * y_hr;
+
+ inc(fg[0 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[3 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+
+ fg[0 ]:=fg[0 ] shr (image_subpixel_shift * 2 );
+ fg[1 ]:=fg[1 ] shr (image_subpixel_shift * 2 );
+ fg[2 ]:=fg[2 ] shr (image_subpixel_shift * 2 );
+ fg[3 ]:=fg[3 ] shr (image_subpixel_shift * 2 );
+
+ end
+ else
+ begin
+ if (x_lr < -1 ) or
+ (y_lr < -1 ) or
+ (x_lr > maxx ) or
+ (y_lr > maxy ) then
+ begin
+ fg[m_order.R ]:=back_r;
+ fg[m_order.G ]:=back_g;
+ fg[m_order.B ]:=back_b;
+ fg[m_order.A ]:=back_a;
+
+ end
+ else
+ begin
+ fg[0 ]:=image_subpixel_size * image_subpixel_size div 2;
+ fg[1 ]:=fg[0 ];
+ fg[2 ]:=fg[0 ];
+ fg[3 ]:=fg[0 ];
+
+ x_hr:=x_hr and image_subpixel_mask;
+ y_hr:=y_hr and image_subpixel_mask;
+
+ weight:=(image_subpixel_size - x_hr ) * (image_subpixel_size - y_hr );
+
+ if (x_lr >= 0 ) and
+ (y_lr >= 0 ) and
+ (x_lr <= maxx ) and
+ (y_lr <= maxy ) then
+ begin
+ fg_ptr:=int8u_ptr(ptrcomp(_source_image.row(y_lr ) ) + (x_lr shl 2 ) * sizeof(int8u ) );
+
+ inc(fg[0 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[3 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+
+ end
+ else
+ begin
+ inc(fg[m_order.R ] ,back_r * weight );
+ inc(fg[m_order.G ] ,back_g * weight );
+ inc(fg[m_order.B ] ,back_b * weight );
+ inc(fg[m_order.A ] ,back_a * weight );
+
+ end;
+
+ inc(x_lr );
+
+ weight:=x_hr * (image_subpixel_size - y_hr );
+
+ if (x_lr >= 0 ) and
+ (y_lr >= 0 ) and
+ (x_lr <= maxx ) and
+ (y_lr <= maxy ) then
+ begin
+ fg_ptr:=int8u_ptr(ptrcomp(_source_image.row(y_lr ) ) + (x_lr shl 2 ) * sizeof(int8u ) );
+
+ inc(fg[0 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[3 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+
+ end
+ else
+ begin
+ inc(fg[m_order.R ] ,back_r * weight );
+ inc(fg[m_order.G ] ,back_g * weight );
+ inc(fg[m_order.B ] ,back_b * weight );
+ inc(fg[m_order.A ] ,back_a * weight );
+
+ end;
+
+ dec(x_lr );
+ inc(y_lr );
+
+ weight:=(image_subpixel_size - x_hr ) * y_hr;
+
+ if (x_lr >= 0 ) and
+ (y_lr >= 0 ) and
+ (x_lr <= maxx ) and
+ (y_lr <= maxy ) then
+ begin
+ fg_ptr:=int8u_ptr(ptrcomp(_source_image.row(y_lr ) ) + (x_lr shl 2 ) * sizeof(int8u ) );
+
+ inc(fg[0 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[3 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+
+ end
+ else
+ begin
+ inc(fg[m_order.R ] ,back_r * weight );
+ inc(fg[m_order.G ] ,back_g * weight );
+ inc(fg[m_order.B ] ,back_b * weight );
+ inc(fg[m_order.A ] ,back_a * weight );
+
+ end;
+
+ inc(x_lr );
+
+ weight:=x_hr * y_hr;
+
+ if (x_lr >= 0 ) and
+ (y_lr >= 0 ) and
+ (x_lr <= maxx ) and
+ (y_lr <= maxy ) then
+ begin
+ fg_ptr:=int8u_ptr(ptrcomp(_source_image.row(y_lr ) ) + (x_lr shl 2 ) * sizeof(int8u ) );
+
+ inc(fg[0 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[3 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+
+ end
+ else
+ begin
+ inc(fg[m_order.R ] ,back_r * weight );
+ inc(fg[m_order.G ] ,back_g * weight );
+ inc(fg[m_order.B ] ,back_b * weight );
+ inc(fg[m_order.A ] ,back_a * weight );
+
+ end;
+
+ fg[0 ]:=fg[0 ] shr (image_subpixel_shift * 2 );
+ fg[1 ]:=fg[1 ] shr (image_subpixel_shift * 2 );
+ fg[2 ]:=fg[2 ] shr (image_subpixel_shift * 2 );
+ fg[3 ]:=fg[3 ] shr (image_subpixel_shift * 2 );
+
+ end;
+
+ end;
+
+ span.r:=int8u(fg[m_order.R ] );
+ span.g:=int8u(fg[m_order.G ] );
+ span.b:=int8u(fg[m_order.B ] );
+ span.a:=int8u(fg[m_order.A ] );
+
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+
+ _interpolator.inc_operator;
+
+ dec(len );
+
+ until len = 0;
+
+ result:=_allocator.span;
+
+end;
+
+{ CONSTRUCT }
+constructor span_image_filter_rgba_2x2.Construct(alloc : span_allocator_ptr; order : order_type );
+begin
+ inherited Construct(alloc );
+
+ m_order:=order;
+
+end;
+
+{ CONSTRUCT }
+constructor span_image_filter_rgba_2x2.Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ back_color : aggclr_ptr;
+ inter : span_interpolator_ptr;
+ filter : image_filter_lut_ptr;
+ order : order_type );
+begin
+ inherited Construct(alloc ,src ,back_color ,inter ,filter );
+
+ m_order:=order;
+
+end;
+
+{ GENERATE }
+function span_image_filter_rgba_2x2.generate;
+var
+ fg : array[0..3 ] of unsigned;
+
+ back_r ,back_g ,back_b ,back_a : int8u;
+
+ fg_ptr : int8u_ptr;
+
+ span : aggclr_ptr;
+
+ weight_array : int16_ptr;
+
+ maxx ,maxy ,x_hr ,y_hr ,x_lr ,y_lr : int;
+
+ weight : unsigned;
+
+begin
+ _interpolator.begin_(x + filter_dx_dbl ,y + filter_dy_dbl ,len );
+
+ back_r:=_background_color.r;
+ back_g:=_background_color.g;
+ back_b:=_background_color.b;
+ back_a:=_background_color.a;
+
+ span:=_allocator.span;
+
+ weight_array:=
+ int16_ptr(
+ ptrcomp(_filter.weight_array ) +
+ ((_filter.diameter div 2 - 1 ) shl image_subpixel_shift ) * sizeof(int16 ) );
+
+ maxx:=_source_image._width - 1;
+ maxy:=_source_image._height - 1;
+
+ repeat
+ _interpolator.coordinates(@x_hr ,@y_hr );
+
+ dec(x_hr ,filter_dx_int );
+ dec(y_hr ,filter_dy_int );
+
+ x_lr:=shr_int32(x_hr ,image_subpixel_shift );
+ y_lr:=shr_int32(y_hr ,image_subpixel_shift );
+
+ fg[0 ]:=image_filter_size div 2;
+ fg[1 ]:=fg[0 ];
+ fg[2 ]:=fg[0 ];
+ fg[3 ]:=fg[0 ];
+
+ if (x_lr >= 0 ) and
+ (y_lr >= 0 ) and
+ (x_lr < maxx ) and
+ (y_lr < maxy ) then
+ begin
+ x_hr:=x_hr and image_subpixel_mask;
+ y_hr:=y_hr and image_subpixel_mask;
+
+ fg_ptr:=int8u_ptr(ptrcomp(_source_image.row(y_lr ) ) + (x_lr shl 2 ) * sizeof(int8u ) );
+ weight:=
+ shr_int32(
+ int16_ptr(ptrcomp(weight_array ) + (x_hr + image_subpixel_size ) * sizeof(int16 ) )^ *
+ int16_ptr(ptrcomp(weight_array ) + (y_hr + image_subpixel_size ) * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,image_filter_shift );
+
+ inc(fg[0 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[3 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+
+ weight:=
+ shr_int32(
+ int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ *
+ int16_ptr(ptrcomp(weight_array ) + (y_hr + image_subpixel_size ) * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,image_filter_shift );
+
+ inc(fg[0 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[3 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+
+ fg_ptr:=_source_image.next_row(int8u_ptr(ptrcomp(fg_ptr ) - 8 * sizeof(int8u ) ) );
+ weight:=
+ shr_int32(
+ int16_ptr(ptrcomp(weight_array ) + (x_hr + image_subpixel_size ) * sizeof(int16 ) )^ *
+ int16_ptr(ptrcomp(weight_array ) + y_hr * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,image_filter_shift );
+
+ inc(fg[0 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[3 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+
+ weight:=
+ shr_int32(
+ int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ *
+ int16_ptr(ptrcomp(weight_array ) + y_hr * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,image_filter_shift );
+
+ inc(fg[0 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[3 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+
+ fg[0 ]:=fg[0 ] shr image_filter_shift;
+ fg[1 ]:=fg[1 ] shr image_filter_shift;
+ fg[2 ]:=fg[2 ] shr image_filter_shift;
+ fg[3 ]:=fg[3 ] shr image_filter_shift;
+
+ if fg[m_order.A ] > base_mask then
+ fg[m_order.A ]:=base_mask;
+
+ if fg[m_order.R ] > fg[m_order.A ] then
+ fg[m_order.R ]:=fg[m_order.A ];
+
+ if fg[m_order.G ] > fg[m_order.A ] then
+ fg[m_order.G ]:=fg[m_order.A ];
+
+ if fg[m_order.B ] > fg[m_order.A ] then
+ fg[m_order.B ]:=fg[m_order.A ];
+
+ end
+ else
+ begin
+ if (x_lr < -1 ) or
+ (y_lr < -1 ) or
+ (x_lr > maxx ) or
+ (y_lr > maxy ) then
+ begin
+ fg[m_order.R ]:=back_r;
+ fg[m_order.G ]:=back_g;
+ fg[m_order.B ]:=back_b;
+ fg[m_order.A ]:=back_a;
+
+ end
+ else
+ begin
+ x_hr:=x_hr and image_subpixel_mask;
+ y_hr:=y_hr and image_subpixel_mask;
+
+ weight:=
+ shr_int32(
+ int16_ptr(ptrcomp(weight_array ) + (x_hr + image_subpixel_size ) * sizeof(int16 ) )^ *
+ int16_ptr(ptrcomp(weight_array ) + (y_hr + image_subpixel_size ) * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,image_filter_shift );
+
+ if (x_lr >= 0 ) and
+ (y_lr >= 0 ) and
+ (x_lr <= maxx ) and
+ (y_lr <= maxy ) then
+ begin
+ fg_ptr:=int8u_ptr(ptrcomp(_source_image.row(y_lr ) ) + (x_lr shl 2 ) * sizeof(int8u ) );
+
+ inc(fg[0 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[3 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+
+ end
+ else
+ begin
+ inc(fg[m_order.R ] ,back_r * weight );
+ inc(fg[m_order.G ] ,back_g * weight );
+ inc(fg[m_order.B ] ,back_b * weight );
+ inc(fg[m_order.A ] ,back_a * weight );
+
+ end;
+
+ inc(x_lr );
+
+ weight:=
+ shr_int32(
+ int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ *
+ int16_ptr(ptrcomp(weight_array ) + (y_hr + image_subpixel_size ) * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,image_filter_shift );
+
+ if (x_lr >= 0 ) and
+ (y_lr >= 0 ) and
+ (x_lr <= maxx ) and
+ (y_lr <= maxy ) then
+ begin
+ fg_ptr:=int8u_ptr(ptrcomp(_source_image.row(y_lr ) ) + (x_lr shl 2 ) * sizeof(int8u ) );
+
+ inc(fg[0 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[3 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+
+ end
+ else
+ begin
+ inc(fg[m_order.R ] ,back_r * weight );
+ inc(fg[m_order.G ] ,back_g * weight );
+ inc(fg[m_order.B ] ,back_b * weight );
+ inc(fg[m_order.A ] ,back_a * weight );
+
+ end;
+
+ dec(x_lr );
+ inc(y_lr );
+
+ weight:=
+ shr_int32(
+ int16_ptr(ptrcomp(weight_array ) + (x_hr + image_subpixel_size ) * sizeof(int16 ) )^ *
+ int16_ptr(ptrcomp(weight_array ) + y_hr * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,image_filter_shift );
+
+ if (x_lr >= 0 ) and
+ (y_lr >= 0 ) and
+ (x_lr <= maxx ) and
+ (y_lr <= maxy ) then
+ begin
+ fg_ptr:=int8u_ptr(ptrcomp(_source_image.row(y_lr ) ) + (x_lr shl 2 ) * sizeof(int8u ) );
+
+ inc(fg[0 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[3 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+
+ end
+ else
+ begin
+ inc(fg[m_order.R ] ,back_r * weight );
+ inc(fg[m_order.G ] ,back_g * weight );
+ inc(fg[m_order.B ] ,back_b * weight );
+ inc(fg[m_order.A ] ,back_a * weight );
+
+ end;
+
+ inc(x_lr );
+
+ weight:=
+ shr_int32(
+ int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ *
+ int16_ptr(ptrcomp(weight_array ) + y_hr * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,image_filter_shift );
+
+ if (x_lr >= 0 ) and
+ (y_lr >= 0 ) and
+ (x_lr <= maxx ) and
+ (y_lr <= maxy ) then
+ begin
+ fg_ptr:=int8u_ptr(ptrcomp(_source_image.row(y_lr ) ) + (x_lr shl 2 ) * sizeof(int8u ) );
+
+ inc(fg[0 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[3 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+
+ end
+ else
+ begin
+ inc(fg[m_order.R ] ,back_r * weight );
+ inc(fg[m_order.G ] ,back_g * weight );
+ inc(fg[m_order.B ] ,back_b * weight );
+ inc(fg[m_order.A ] ,back_a * weight );
+
+ end;
+
+ fg[0 ]:=fg[0 ] shr image_filter_shift;
+ fg[1 ]:=fg[1 ] shr image_filter_shift;
+ fg[2 ]:=fg[2 ] shr image_filter_shift;
+ fg[3 ]:=fg[3 ] shr image_filter_shift;
+
+ if fg[m_order.A ] > base_mask then
+ fg[m_order.A ]:=base_mask;
+
+ if fg[m_order.R ] > fg[m_order.A ] then
+ fg[m_order.R ]:=fg[m_order.A ];
+
+ if fg[m_order.G ] > fg[m_order.A ] then
+ fg[m_order.G ]:=fg[m_order.A ];
+
+ if fg[m_order.B ] > fg[m_order.A ] then
+ fg[m_order.B ]:=fg[m_order.A ];
+
+ end;
+
+ end;
+
+ span.r:=int8u(fg[m_order.R ] );
+ span.g:=int8u(fg[m_order.G ] );
+ span.b:=int8u(fg[m_order.B ] );
+ span.a:=int8u(fg[m_order.A ] );
+
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+
+ _interpolator.inc_operator;
+
+ dec(len );
+
+ until len = 0;
+
+ result:=_allocator.span;
+
+end;
+
+{ CONSTRUCT }
+constructor span_image_filter_rgba.Construct(alloc : span_allocator_ptr; order : order_type );
+begin
+ inherited Construct(alloc );
+
+ m_order:=order;
+
+end;
+
+{ CONSTRUCT }
+constructor span_image_filter_rgba.Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ back_color : aggclr_ptr;
+ inter : span_interpolator_ptr;
+ filter : image_filter_lut_ptr;
+ order : order_type );
+begin
+ inherited Construct(alloc ,src ,back_color ,inter ,filter );
+
+ m_order:=order;
+
+end;
+
+{ GENERATE }
+function span_image_filter_rgba.generate;
+var
+ fg : array[0..3 ] of int;
+
+ back_r ,back_g ,back_b ,back_a : int8u;
+
+ fg_ptr : int8u_ptr;
+
+ diameter ,step_back ,y_count : unsigned;
+
+ start ,start1 ,maxx ,maxy ,maxx2 ,maxy2 ,x_count ,weight_y ,weight ,
+ x_hr ,y_hr ,x_lr ,y_lr ,x_fract : int;
+
+ weight_array : int16_ptr;
+
+ span : aggclr_ptr;
+
+begin
+ _interpolator.begin_(x + filter_dx_dbl ,y + filter_dy_dbl ,len );
+
+ back_r:=_background_color.r;
+ back_g:=_background_color.g;
+ back_b:=_background_color.b;
+ back_a:=_background_color.a;
+
+ diameter :=_filter.diameter;
+ start :=_filter.start;
+ start1 :=start - 1;
+ weight_array:=_filter.weight_array;
+
+ step_back:=diameter shl 2;
+
+ span:=_allocator.span;
+
+ maxx:=_source_image._width + start - 2;
+ maxy:=_source_image._height + start - 2;
+
+ maxx2:=_source_image._width - start - 1;
+ maxy2:=_source_image._height - start - 1;
+
+ repeat
+ _interpolator.coordinates(@x ,@y );
+
+ dec(x ,filter_dx_int );
+ dec(y ,filter_dy_int );
+
+ x_hr:=x;
+ y_hr:=y;
+
+ x_lr:=shr_int32(x_hr ,image_subpixel_shift );
+ y_lr:=shr_int32(y_hr ,image_subpixel_shift );
+
+ fg[0 ]:=image_filter_size div 2;
+ fg[1 ]:=fg[0 ];
+ fg[2 ]:=fg[0 ];
+ fg[3 ]:=fg[0 ];
+
+ x_fract:=x_hr and image_subpixel_mask;
+ y_count:=diameter;
+
+ if (x_lr >= -start ) and
+ (y_lr >= -start ) and
+ (x_lr <= maxx ) and
+ (y_lr <= maxy ) then
+ begin
+ y_hr :=image_subpixel_mask - (y_hr and image_subpixel_mask );
+ fg_ptr:=int8u_ptr(ptrcomp(_source_image.row(y_lr + start ) ) + ((x_lr + start ) shl 2 ) * sizeof(int8u ) );
+
+ repeat
+ x_count :=diameter;
+ weight_y:=int16_ptr(ptrcomp(weight_array ) + y_hr * sizeof(int16 ) )^;
+ x_hr :=image_subpixel_mask - x_fract;
+
+ repeat
+ weight:=
+ shr_int32(
+ weight_y *
+ int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,image_filter_shift );
+
+ inc(fg[0 ] ,fg_ptr^ * weight ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,fg_ptr^ * weight ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,fg_ptr^ * weight ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[3 ] ,fg_ptr^ * weight ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+
+ inc(x_hr ,image_subpixel_size );
+ dec(x_count );
+
+ until x_count = 0;
+
+ inc(y_hr ,image_subpixel_size );
+
+ fg_ptr:=_source_image.next_row(int8u_ptr(ptrcomp(fg_ptr ) - step_back ) );
+
+ dec(y_count );
+
+ until y_count = 0;
+
+ fg[0 ]:=shr_int32(fg[0 ] ,image_filter_shift );
+ fg[1 ]:=shr_int32(fg[1 ] ,image_filter_shift );
+ fg[2 ]:=shr_int32(fg[2 ] ,image_filter_shift );
+ fg[3 ]:=shr_int32(fg[3 ] ,image_filter_shift );
+
+ if fg[0 ] < 0 then
+ fg[0 ]:=0;
+
+ if fg[1 ] < 0 then
+ fg[1 ]:=0;
+
+ if fg[2 ] < 0 then
+ fg[2 ]:=0;
+
+ if fg[3 ] < 0 then
+ fg[3 ]:=0;
+
+ if fg[m_order.A ] > base_mask then
+ fg[m_order.A ]:=base_mask;
+
+ if fg[m_order.R ] > fg[m_order.A ] then
+ fg[m_order.R ]:=fg[m_order.A ];
+
+ if fg[m_order.G ] > fg[m_order.A ] then
+ fg[m_order.G ]:=fg[m_order.A ];
+
+ if fg[m_order.B ] > fg[m_order.A ] then
+ fg[m_order.B ]:=fg[m_order.A ];
+
+ end
+ else
+ begin
+ if (x_lr < start1 ) or
+ (y_lr < start1 ) or
+ (x_lr > maxx2 ) or
+ (y_lr > maxy2 ) then
+ begin
+ fg[m_order.R ]:=back_r;
+ fg[m_order.G ]:=back_g;
+ fg[m_order.B ]:=back_b;
+ fg[m_order.A ]:=back_a;
+
+ end
+ else
+ begin
+ y_lr:=shr_int32(y ,image_subpixel_shift ) + start;
+ y_hr:=image_subpixel_mask - (y_hr and image_subpixel_mask );
+
+ repeat
+ x_count :=diameter;
+ weight_y:=int16_ptr(ptrcomp(weight_array ) + y_hr * sizeof(int16 ) )^;
+
+ x_lr:=shr_int32(x ,image_subpixel_shift ) + start;
+ x_hr:=image_subpixel_mask - x_fract;
+
+ repeat
+ weight:=
+ shr_int32(
+ weight_y *
+ int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,image_filter_shift );
+
+ if (x_lr >= 0 ) and
+ (y_lr >= 0 ) and
+ (x_lr < trunc(_source_image._width ) ) and
+ (y_lr < trunc(_source_image._height ) ) then
+ begin
+ fg_ptr:=int8u_ptr(ptrcomp(_source_image.row(y_lr ) ) + (x_lr shl 2 ) * sizeof(int8u ) );
+
+ inc(fg[0 ] ,fg_ptr^ * weight ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,fg_ptr^ * weight ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,fg_ptr^ * weight ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[3 ] ,fg_ptr^ * weight ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+
+ end
+ else
+ begin
+ inc(fg[m_order.R ] ,back_r * weight );
+ inc(fg[m_order.G ] ,back_g * weight );
+ inc(fg[m_order.B ] ,back_b * weight );
+ inc(fg[m_order.A ] ,back_a * weight );
+
+ end;
+
+ inc(x_hr ,image_subpixel_size );
+ inc(x_lr );
+ dec(x_count );
+
+ until x_count = 0;
+
+ inc(y_hr ,image_subpixel_size );
+ inc(y_lr );
+ dec(y_count );
+
+ until y_count = 0;
+
+ fg[0 ]:=shr_int32(fg[0 ] ,image_filter_shift );
+ fg[1 ]:=shr_int32(fg[1 ] ,image_filter_shift );
+ fg[2 ]:=shr_int32(fg[2 ] ,image_filter_shift );
+ fg[3 ]:=shr_int32(fg[3 ] ,image_filter_shift );
+
+ if fg[0 ] < 0 then
+ fg[0 ]:=0;
+
+ if fg[1 ] < 0 then
+ fg[1 ]:=0;
+
+ if fg[2 ] < 0 then
+ fg[2 ]:=0;
+
+ if fg[3 ] < 0 then
+ fg[3 ]:=0;
+
+ if fg[m_order.A ] > base_mask then
+ fg[m_order.A ]:=base_mask;
+
+ if fg[m_order.R ] > fg[m_order.A ] then
+ fg[m_order.R ]:=fg[m_order.A ];
+
+ if fg[m_order.G ] > fg[m_order.A ] then
+ fg[m_order.G ]:=fg[m_order.A ];
+
+ if fg[m_order.B ] > fg[m_order.A ] then
+ fg[m_order.B ]:=fg[m_order.A ];
+
+ end;
+
+ end;
+
+ span.r:=fg[m_order.R ];
+ span.g:=fg[m_order.G ];
+ span.b:=fg[m_order.B ];
+ span.a:=fg[m_order.A ];
+
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+
+ _interpolator.inc_operator;
+
+ dec(len );
+
+ until len = 0;
+
+ result:=_allocator.span;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_span_image_resample.pas b/src/corelib/render/software/agg_span_image_resample.pas
new file mode 100644
index 00000000..e7116372
--- /dev/null
+++ b/src/corelib/render/software/agg_span_image_resample.pas
@@ -0,0 +1,312 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 05.03.2006-Milano: Unit port establishment
+//
+{ agg_span_image_resample.pas }
+unit
+ agg_span_image_resample ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_color ,
+ agg_span_image_filter ,
+ agg_span_interpolator_linear ,
+ agg_rendering_buffer ,
+ agg_span_allocator ,
+ agg_image_filters ;
+
+{ TYPES DEFINITION }
+type
+ span_image_resample_ptr = ^span_image_resample;
+ span_image_resample = object(span_image_filter )
+ m_scale_limit ,
+ m_blur_x ,
+ m_blur_y : int;
+
+ constructor Construct(alloc : span_allocator_ptr ); overload;
+ constructor Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ back_color : aggclr_ptr;
+ interpolator : span_interpolator_ptr;
+ filter : image_filter_lut_ptr ); overload;
+
+ function _scale_limit : int;
+ procedure scale_limit_(v : int );
+
+ function _blur_x : double;
+ function _blur_y : double;
+ procedure blur_x_(v : double );
+ procedure blur_y_(v : double );
+ procedure blur_ (v : double );
+
+ end;
+
+ span_image_resample_affine = object(span_image_filter )
+ m_rx ,
+ m_ry ,
+ m_rx_inv ,
+ m_ry_inv : int;
+
+ m_scale_limit ,
+ m_blur_x ,
+ m_blur_y : double;
+
+ constructor Construct(alloc : span_allocator_ptr ); overload;
+ constructor Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ back_color : aggclr_ptr;
+ interpolator : span_interpolator_ptr;
+ filter : image_filter_lut_ptr ); overload;
+
+ function _scale_limit : int;
+ procedure scale_limit_(v : int );
+
+ function _blur_x : double;
+ function _blur_y : double;
+ procedure blur_x_(v : double );
+ procedure blur_y_(v : double );
+ procedure blur_ (v : double );
+
+ procedure prepare(max_span_len : unsigned ); virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor span_image_resample.Construct(alloc : span_allocator_ptr );
+begin
+ inherited Construct(alloc );
+
+ m_scale_limit:=20;
+
+ m_blur_x:=image_subpixel_size;
+ m_blur_y:=image_subpixel_size;
+
+end;
+
+{ CONSTRUCT }
+constructor span_image_resample.Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ back_color : aggclr_ptr;
+ interpolator : span_interpolator_ptr;
+ filter : image_filter_lut_ptr );
+begin
+ inherited Construct(alloc ,src ,back_color ,interpolator ,filter );
+
+ m_scale_limit:=20;
+
+ m_blur_x:=image_subpixel_size;
+ m_blur_y:=image_subpixel_size;
+
+end;
+
+{ _SCALE_LIMIT }
+function span_image_resample._scale_limit;
+begin
+ result:=m_scale_limit;
+
+end;
+
+{ SCALE_LIMIT_ }
+procedure span_image_resample.scale_limit_;
+begin
+ m_scale_limit:=v;
+
+end;
+
+{ _BLUR_X }
+function span_image_resample._blur_x;
+begin
+ result:=m_blur_x / image_subpixel_size;
+
+end;
+
+{ _BLUR_Y }
+function span_image_resample._blur_y;
+begin
+ result:=m_blur_y / image_subpixel_size;
+
+end;
+
+{ BLUR_X_ }
+procedure span_image_resample.blur_x_;
+begin
+ m_blur_x:=trunc(v * image_subpixel_size + 0.5 );
+
+end;
+
+{ BLUR_Y_ }
+procedure span_image_resample.blur_y_;
+begin
+ m_blur_y:=trunc(v * image_subpixel_size + 0.5 );
+
+end;
+
+{ BLUR_ }
+procedure span_image_resample.blur_;
+begin
+ m_blur_x:=trunc(v * image_subpixel_size + 0.5 );
+ m_blur_y:=m_blur_x;
+
+end;
+
+{ CONSTRUCT }
+constructor span_image_resample_affine.Construct(alloc : span_allocator_ptr );
+begin
+ inherited Construct(alloc );
+
+ m_scale_limit:=200.0;
+
+ m_blur_x:=1.0;
+ m_blur_y:=1.0;
+
+end;
+
+{ CONSTRUCT }
+constructor span_image_resample_affine.Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ back_color : aggclr_ptr;
+ interpolator : span_interpolator_ptr;
+ filter : image_filter_lut_ptr );
+begin
+ inherited Construct(alloc ,src ,back_color ,interpolator ,filter );
+
+ m_scale_limit:=200.0;
+
+ m_blur_x:=1.0;
+ m_blur_y:=1.0;
+
+end;
+
+{ _SCALE_LIMIT }
+function span_image_resample_affine._scale_limit;
+begin
+ result:=trunc(m_scale_limit );
+
+end;
+
+{ SCALE_LIMIT_ }
+procedure span_image_resample_affine.scale_limit_;
+begin
+ m_scale_limit:=v;
+
+end;
+
+{ _BLUR_X }
+function span_image_resample_affine._blur_x;
+begin
+ result:=m_blur_x;
+
+end;
+
+{ _BLUR_Y }
+function span_image_resample_affine._blur_y;
+begin
+ result:=m_blur_y;
+
+end;
+
+{ BLUR_X_ }
+procedure span_image_resample_affine.blur_x_;
+begin
+ m_blur_x:=v;
+
+end;
+
+{ BLUR_Y_ }
+procedure span_image_resample_affine.blur_y_;
+begin
+ m_blur_y:=v;
+
+end;
+
+{ BLUR_ }
+procedure span_image_resample_affine.blur_;
+begin
+ m_blur_x:=v;
+ m_blur_y:=v;
+
+end;
+
+{ PREPARE }
+procedure span_image_resample_affine.prepare;
+var
+ scale_x ,scale_y : double;
+
+begin
+ inherited prepare(max_span_len );
+
+ _interpolator._transformer.scaling_abs(@scale_x ,@scale_y );
+
+ m_rx :=image_subpixel_size;
+ m_ry :=image_subpixel_size;
+ m_rx_inv:=image_subpixel_size;
+ m_ry_inv:=image_subpixel_size;
+
+ scale_x:=scale_x * m_blur_x;
+ scale_y:=scale_y * m_blur_y;
+
+ if scale_x * scale_y > m_scale_limit then
+ begin
+ scale_x:=scale_x * m_scale_limit / (scale_x * scale_y );
+ scale_y:=scale_y * m_scale_limit / (scale_x * scale_y );
+
+ end;
+
+ if scale_x > 1.0001 then
+ begin
+ if scale_x > m_scale_limit then
+ scale_x:=m_scale_limit;
+
+ m_rx :=trunc(scale_x * image_subpixel_size + 0.5 );
+ m_rx_inv:=trunc(1.0 / scale_x * image_subpixel_size + 0.5);
+
+ end;
+
+ if scale_y > 1.0001 then
+ begin
+ if scale_y > m_scale_limit then
+ scale_y:=m_scale_limit;
+
+ m_ry :=trunc(scale_y * image_subpixel_size + 0.5 );
+ m_ry_inv:=trunc(1.0 / scale_y * image_subpixel_size + 0.5 );
+
+ end;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_span_image_resample_gray.pas b/src/corelib/render/software/agg_span_image_resample_gray.pas
new file mode 100644
index 00000000..a664c1f7
--- /dev/null
+++ b/src/corelib/render/software/agg_span_image_resample_gray.pas
@@ -0,0 +1,445 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 05.03.2006-Milano: Unit port establishment
+//
+{ agg_span_image_resample_gray.pas }
+unit
+ agg_span_image_resample_gray ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_color ,
+ agg_span_image_resample ,
+ agg_span_interpolator_linear ,
+ agg_rendering_buffer ,
+ agg_span_allocator ,
+ agg_image_filters ;
+
+{ TYPES DEFINITION }
+const
+ base_shift = agg_color.base_shift;
+ base_mask = agg_color.base_mask;
+ downscale_shift = image_filter_shift;
+
+type
+ span_image_resample_gray_affine_ptr = ^span_image_resample_gray_affine;
+ span_image_resample_gray_affine = object(span_image_resample_affine )
+ constructor Construct(alloc : span_allocator_ptr ); overload;
+ constructor Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ back_color : aggclr_ptr;
+ interpolator : span_interpolator_ptr;
+ filter : image_filter_lut_ptr ); overload;
+
+ function generate(x ,y : int; len : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+ span_image_resample_gray_ptr = ^span_image_resample_gray;
+ span_image_resample_gray = object(span_image_resample )
+ constructor Construct(alloc : span_allocator_ptr ); overload;
+ constructor Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ back_color : aggclr_ptr;
+ interpolator : span_interpolator_ptr;
+ filter : image_filter_lut_ptr ); overload;
+
+ function generate(x ,y : int; len : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor span_image_resample_gray_affine.Construct(alloc : span_allocator_ptr );
+begin
+ inherited Construct(alloc );
+
+end;
+
+{ CONSTRUCT }
+constructor span_image_resample_gray_affine.Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ back_color : aggclr_ptr;
+ interpolator : span_interpolator_ptr;
+ filter : image_filter_lut_ptr );
+begin
+ inherited Construct(alloc ,src ,back_color ,interpolator ,filter );
+
+end;
+
+{ GENERATE }
+function span_image_resample_gray_affine.generate;
+var
+ fg ,src_alpha ,diameter ,filter_size ,radius_x ,radius_y ,maxx ,maxy ,
+ y_lr ,y_hr ,total_weight ,x_lr_ini ,x_hr_ini ,weight_y ,x_lr ,x_hr ,weight : int;
+
+ back_v ,back_a : int8u;
+
+ span : aggclr_ptr;
+
+ fg_ptr : int8u_ptr;
+
+ weight_array : int16_ptr;
+
+begin
+ _interpolator.begin_(x + filter_dx_dbl ,y + filter_dy_dbl ,len );
+
+ back_v:=_background_color.v;
+ back_a:=_background_color.a;
+
+ span:=_allocator.span;
+
+ diameter :=_filter.diameter;
+ filter_size:=diameter shl image_subpixel_shift;
+
+ radius_x:=shr_int32(diameter * m_rx ,1 );
+ radius_y:=shr_int32(diameter * m_ry ,1 );
+
+ maxx:=_source_image._width - 1;
+ maxy:=_source_image._height - 1;
+
+ weight_array:=_filter.weight_array;
+
+ repeat
+ _interpolator.coordinates(@x ,@y );
+
+ inc(x ,filter_dx_int - radius_x );
+ inc(y ,filter_dy_int - radius_y );
+
+ fg :=image_filter_size div 2;
+ src_alpha:=fg;
+
+ y_lr:=shr_int32(y ,image_subpixel_shift );
+ y_hr:=
+ shr_int32(
+ (image_subpixel_mask - (y and image_subpixel_mask ) ) *
+ m_ry_inv ,image_subpixel_shift );
+
+ total_weight:=0;
+
+ x_lr_ini:=shr_int32(x ,image_subpixel_shift );
+ x_hr_ini:=
+ shr_int32(
+ (image_subpixel_mask - (x and image_subpixel_mask ) ) *
+ m_rx_inv ,image_subpixel_shift );
+
+ repeat
+ weight_y:=int16_ptr(ptrcomp(weight_array ) + y_hr * sizeof(int16 ) )^;
+
+ x_lr:=x_lr_ini;
+ x_hr:=x_hr_ini;
+
+ if (y_lr >= 0 ) and
+ (y_lr <= maxy ) then
+ begin
+ fg_ptr:=int8u_ptr(ptrcomp(_source_image.row(y_lr ) ) + x_lr * sizeof(int8u ) );
+
+ repeat
+ weight:=
+ shr_int32(
+ weight_y *
+ int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,downscale_shift );
+
+ if (x_lr >= 0 ) and
+ (x_lr <= maxx ) then
+ begin
+ inc(fg ,fg_ptr^ * weight );
+ inc(src_alpha ,base_mask * weight );
+
+ end
+ else
+ begin
+ inc(fg ,back_v * weight );
+ inc(src_alpha ,back_a * weight );
+
+ end;
+
+ inc(total_weight ,weight );
+ inc(x_hr ,m_rx_inv );
+ inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(x_lr );
+
+ until x_hr >= filter_size;
+
+ end
+ else
+ repeat
+ weight:=
+ shr_int32(
+ weight_y *
+ int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,downscale_shift );
+
+ inc(total_weight ,weight );
+ inc(fg ,back_v * weight );
+ inc(src_alpha ,back_a * weight );
+ inc(x_hr ,m_rx_inv );
+
+ until x_hr >= filter_size;
+
+ inc(y_hr ,m_ry_inv );
+ inc(y_lr );
+
+ until y_hr >= filter_size;
+
+ fg :=fg div total_weight;
+ src_alpha:=src_alpha div total_weight;
+
+ if fg < 0 then
+ fg:=0;
+
+ if src_alpha < 0 then
+ src_alpha:=0;
+
+ if src_alpha > base_mask then
+ src_alpha:=base_mask;
+
+ if fg > src_alpha then
+ fg:=src_alpha;
+
+ span.v:=int8u(fg );
+ span.a:=int8u(src_alpha );
+
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+
+ _interpolator.inc_operator;
+
+ dec(len );
+
+ until len = 0;
+
+ result:=_allocator.span;
+
+end;
+
+{ CONSTRUCT }
+constructor span_image_resample_gray.Construct(alloc : span_allocator_ptr );
+begin
+ inherited Construct(alloc );
+
+end;
+
+{ CONSTRUCT }
+constructor span_image_resample_gray.Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ back_color : aggclr_ptr;
+ interpolator : span_interpolator_ptr;
+ filter : image_filter_lut_ptr );
+begin
+ inherited Construct(alloc ,src ,back_color ,interpolator ,filter );
+
+end;
+
+{ GENERATE }
+function span_image_resample_gray.generate;
+var
+ span : aggclr_ptr;
+
+ fg ,src_alpha ,diameter ,filter_size ,rx ,ry ,rx_inv ,ry_inv ,
+ radius_x ,radius_y ,maxx ,maxy ,y_lr ,y_hr ,total_weight ,
+ x_lr_ini ,x_hr_ini ,weight_y ,x_lr ,x_hr ,weight : int;
+
+ back_v ,back_a : int8u;
+
+ weight_array : int16_ptr;
+
+ fg_ptr : int8u_ptr;
+
+begin
+ span:=_allocator.span;
+
+ _interpolator.begin_(x + filter_dx_dbl ,y + filter_dy_dbl ,len );
+
+ back_v:=_background_color.v;
+ back_a:=_background_color.a;
+
+ diameter :=_filter.diameter;
+ filter_size:=diameter shl image_subpixel_shift;
+
+ weight_array:=_filter.weight_array;
+
+ repeat
+ rx_inv:=image_subpixel_size;
+ ry_inv:=image_subpixel_size;
+
+ _interpolator.coordinates(@x ,@y );
+ _interpolator.local_scale(@rx ,@ry );
+
+ rx:=shr_int32(rx * m_blur_x ,image_subpixel_shift );
+ ry:=shr_int32(ry * m_blur_y ,image_subpixel_shift );
+
+ if rx < image_subpixel_size then
+ rx:=image_subpixel_size
+ else
+ begin
+ if rx > image_subpixel_size * m_scale_limit then
+ rx:=image_subpixel_size * m_scale_limit;
+
+ rx_inv:=image_subpixel_size * image_subpixel_size div rx;
+
+ end;
+
+ if ry < image_subpixel_size then
+ ry:=image_subpixel_size
+ else
+ begin
+ if ry > image_subpixel_size * m_scale_limit then
+ ry:=image_subpixel_size * m_scale_limit;
+
+ ry_inv:=image_subpixel_size * image_subpixel_size div ry;
+
+ end;
+
+ radius_x:=shr_int32(diameter * rx ,1 );
+ radius_y:=shr_int32(diameter * ry ,1 );
+
+ maxx:=_source_image._width - 1;
+ maxy:=_source_image._height - 1;
+
+ inc(x ,filter_dx_int - radius_x );
+ inc(y ,filter_dy_int - radius_y );
+
+ fg :=image_filter_size div 2;
+ src_alpha:=fg;
+
+ y_lr:=shr_int32(y ,image_subpixel_shift );
+ y_hr:=
+ shr_int32(
+ (image_subpixel_mask - (y and image_subpixel_mask ) ) *
+ ry_inv ,image_subpixel_shift );
+
+ total_weight:=0;
+
+ x_lr_ini:=shr_int32(x ,image_subpixel_shift );
+ x_hr_ini:=
+ shr_int32(
+ (image_subpixel_mask - (x and image_subpixel_mask ) ) *
+ rx_inv ,image_subpixel_shift );
+
+ repeat
+ weight_y:=int16_ptr(ptrcomp(weight_array ) + y_hr * sizeof(int16 ) )^;
+
+ x_lr:=x_lr_ini;
+ x_hr:=x_hr_ini;
+
+ if (y_lr >= 0 ) and
+ (y_lr <= maxy ) then
+ begin
+ fg_ptr:=int8u_ptr(ptrcomp(_source_image.row(y_lr ) ) + x_lr * sizeof(int8u ) );
+
+ repeat
+ weight:=
+ shr_int32(
+ weight_y *
+ int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,downscale_shift );
+
+ if (x_lr >= 0 ) and
+ (x_lr <= maxx ) then
+ begin
+ inc(fg ,fg_ptr^ * weight );
+ inc(src_alpha ,base_mask * weight );
+
+ end
+ else
+ begin
+ inc(fg ,back_v * weight );
+ inc(src_alpha ,back_a * weight );
+
+ end;
+
+ inc(total_weight ,weight );
+ inc(x_hr ,rx_inv );
+ inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(x_lr );
+
+ until x_hr >= filter_size;
+
+ end
+ else
+ repeat
+ weight:=
+ shr_int32(
+ weight_y *
+ int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,downscale_shift );
+
+ inc(total_weight ,weight );
+ inc(fg ,back_v * weight );
+ inc(src_alpha ,back_a * weight );
+ inc(x_hr ,rx_inv );
+
+ until x_hr >= filter_size;
+
+ inc(y_hr ,ry_inv );
+ inc(y_lr );
+
+ until y_hr >= filter_size;
+
+ fg :=fg div total_weight;
+ src_alpha:=src_alpha div total_weight;
+
+ if fg < 0 then
+ fg:=0;
+
+ if src_alpha < 0 then
+ src_alpha:=0;
+
+ if src_alpha > base_mask then
+ src_alpha:=base_mask;
+
+ if fg > src_alpha then
+ fg:=src_alpha;
+
+ span.v:=int8u(fg );
+ span.a:=int8u(src_alpha );
+
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+
+ _interpolator.inc_operator;
+
+ dec(len );
+
+ until len = 0;
+
+ result:=_allocator.span;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_span_image_resample_rgb.pas b/src/corelib/render/software/agg_span_image_resample_rgb.pas
new file mode 100644
index 00000000..a2a99ea7
--- /dev/null
+++ b/src/corelib/render/software/agg_span_image_resample_rgb.pas
@@ -0,0 +1,519 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 05.03.2006-Milano: Unit port establishment
+//
+{ agg_span_image_resample_rgb.pas }
+unit
+ agg_span_image_resample_rgb ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_color ,
+ agg_span_image_resample ,
+ agg_span_interpolator_linear ,
+ agg_rendering_buffer ,
+ agg_span_allocator ,
+ agg_image_filters ;
+
+{ TYPES DEFINITION }
+const
+ base_shift = agg_color.base_shift;
+ base_mask = agg_color.base_mask;
+ downscale_shift = image_filter_shift;
+
+type
+ span_image_resample_rgb_affine_ptr = ^span_image_resample_rgb_affine;
+ span_image_resample_rgb_affine = object(span_image_resample_affine )
+ m_order : order_type;
+
+ constructor Construct(alloc : span_allocator_ptr; order : order_type ); overload;
+ constructor Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ back_color : aggclr_ptr;
+ interpolator : span_interpolator_ptr;
+ filter : image_filter_lut_ptr;
+ order : order_type ); overload;
+
+ function generate(x ,y : int; len : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+ span_image_resample_rgb_ptr = ^span_image_resample_rgb;
+ span_image_resample_rgb = object(span_image_resample )
+ m_order : order_type;
+
+ constructor Construct(alloc : span_allocator_ptr; order : order_type ); overload;
+ constructor Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ back_color : aggclr_ptr;
+ interpolator : span_interpolator_ptr;
+ filter : image_filter_lut_ptr;
+ order : order_type ); overload;
+
+ function generate(x ,y : int; len : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor span_image_resample_rgb_affine.Construct(alloc : span_allocator_ptr; order : order_type );
+begin
+ inherited Construct(alloc );
+
+ m_order:=order;
+
+end;
+
+{ CONSTRUCT }
+constructor span_image_resample_rgb_affine.Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ back_color : aggclr_ptr;
+ interpolator : span_interpolator_ptr;
+ filter : image_filter_lut_ptr;
+ order : order_type );
+begin
+ inherited Construct(alloc ,src ,back_color ,interpolator ,filter );
+
+ m_order:=order;
+
+end;
+
+{ GENERATE }
+function span_image_resample_rgb_affine.generate;
+var
+ fg : array[0..3 ] of int;
+
+ back_r ,back_g ,back_b ,back_a : int8u;
+
+ span : aggclr_ptr;
+
+ diameter ,filter_size ,radius_x ,radius_y ,maxx ,maxy ,y_lr ,y_hr ,
+ total_weight ,x_lr_ini ,x_hr_ini ,weight_y ,x_lr ,x_hr ,weight : int;
+
+ fg_ptr : int8u_ptr;
+
+ weight_array : int16_ptr;
+
+begin
+ _interpolator.begin_(x + filter_dx_dbl ,y + filter_dy_dbl ,len );
+
+ back_r:=_background_color.r;
+ back_g:=_background_color.g;
+ back_b:=_background_color.b;
+ back_a:=_background_color.a;
+
+ span:=_allocator.span;
+
+ diameter :=_filter.diameter;
+ filter_size:=diameter shl image_subpixel_shift;
+
+ radius_x:=shr_int32(diameter * m_rx ,1 );
+ radius_y:=shr_int32(diameter * m_ry ,1 );
+
+ maxx:=_source_image._width - 1;
+ maxy:=_source_image._height - 1;
+
+ weight_array:=_filter.weight_array;
+
+ repeat
+ _interpolator.coordinates(@x ,@y );
+
+ inc(x ,filter_dx_int - radius_x );
+ inc(y ,filter_dy_int - radius_y );
+
+ fg[0 ]:=image_filter_size div 2;
+ fg[1 ]:=fg[0 ];
+ fg[2 ]:=fg[0 ];
+ fg[3 ]:=fg[0 ];
+
+ y_lr:=shr_int32(y ,image_subpixel_shift );
+ y_hr:=
+ shr_int32(
+ (image_subpixel_mask - (y and image_subpixel_mask ) ) *
+ m_ry_inv ,image_subpixel_shift );
+
+ total_weight:=0;
+
+ x_lr_ini:=shr_int32(x ,image_subpixel_shift );
+ x_hr_ini:=
+ shr_int32(
+ (image_subpixel_mask - (x and image_subpixel_mask ) ) *
+ m_rx_inv ,image_subpixel_shift );
+
+ repeat
+ weight_y:=int16_ptr(ptrcomp(weight_array ) + y_hr * sizeof(int16 ) )^;
+
+ x_lr:=x_lr_ini;
+ x_hr:=x_hr_ini;
+
+ if (y_lr >= 0 ) and
+ (y_lr <= maxy ) then
+ begin
+ fg_ptr:=int8u_ptr(ptrcomp(_source_image.row(y_lr ) ) + x_lr * 3 * sizeof(int8u ) );
+
+ repeat
+ weight:=
+ shr_int32(
+ weight_y *
+ int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,downscale_shift );
+
+ if (x_lr >= 0 ) and
+ (x_lr <= maxx ) then
+ begin
+ inc(fg[0 ] ,fg_ptr^ * weight ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,fg_ptr^ * weight ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,fg_ptr^ * weight ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[3 ] ,base_mask * weight );
+
+ end
+ else
+ begin
+ inc(fg[m_order.R ] ,back_r * weight );
+ inc(fg[m_order.G ] ,back_g * weight );
+ inc(fg[m_order.B ] ,back_b * weight );
+ inc(fg[3 ] ,back_a * weight );
+
+ inc(ptrcomp(fg_ptr ) ,3 * sizeof(int8u ) );
+
+ end;
+
+ inc(total_weight ,weight );
+ inc(x_hr ,m_rx_inv );
+ inc(x_lr );
+
+ until x_hr >= filter_size;
+
+ end
+ else
+ repeat
+ weight:=
+ shr_int32(
+ weight_y *
+ int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,downscale_shift );
+
+ inc(total_weight ,weight );
+ inc(fg[m_order.R ] ,back_r * weight );
+ inc(fg[m_order.G ] ,back_g * weight );
+ inc(fg[m_order.B ] ,back_b * weight );
+ inc(fg[3 ] ,back_a * weight );
+ inc(x_hr ,m_rx_inv );
+
+ until x_hr >= filter_size;
+
+ inc(y_hr ,m_ry_inv );
+ inc(y_lr );
+
+ until y_hr >= filter_size;
+
+ fg[0 ]:=fg[0 ] div total_weight;
+ fg[1 ]:=fg[1 ] div total_weight;
+ fg[2 ]:=fg[2 ] div total_weight;
+ fg[3 ]:=fg[3 ] div total_weight;
+
+ if fg[0 ] < 0 then
+ fg[0 ]:=0;
+
+ if fg[1 ] < 0 then
+ fg[1 ]:=0;
+
+ if fg[2 ] < 0 then
+ fg[2 ]:=0;
+
+ if fg[3 ] < 0 then
+ fg[3 ]:=0;
+
+ if fg[3 ] > base_mask then
+ fg[3 ]:=base_mask;
+
+ if fg[0 ] > fg[3 ] then
+ fg[0 ]:=fg[3 ];
+
+ if fg[1 ] > fg[3 ] then
+ fg[1 ]:=fg[3 ];
+
+ if fg[2 ] > fg[3 ] then
+ fg[2 ]:=fg[3 ];
+
+ span.r:=int8u(fg[m_order.R ] );
+ span.g:=int8u(fg[m_order.G ] );
+ span.b:=int8u(fg[m_order.B ] );
+ span.a:=int8u(fg[3 ] );
+
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+
+ _interpolator.inc_operator;
+
+ dec(len );
+
+ until len = 0;
+
+ result:=_allocator.span;
+
+end;
+
+{ CONSTRUCT }
+constructor span_image_resample_rgb.Construct(alloc : span_allocator_ptr; order : order_type );
+begin
+ inherited Construct(alloc );
+
+ m_order:=order;
+
+end;
+
+{ CONSTRUCT }
+constructor span_image_resample_rgb.Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ back_color : aggclr_ptr;
+ interpolator : span_interpolator_ptr;
+ filter : image_filter_lut_ptr;
+ order : order_type );
+begin
+ inherited Construct(alloc ,src ,back_color ,interpolator ,filter );
+
+ m_order:=order;
+
+end;
+
+{ GENERATE }
+function span_image_resample_rgb.generate;
+var
+ span : aggclr_ptr;
+
+ fg : array[0..3 ] of int;
+
+ back_r ,back_g ,back_b ,back_a : int8u;
+
+ diameter ,filter_size ,rx ,ry ,rx_inv ,ry_inv ,radius_x ,radius_y ,
+ maxx ,maxy ,y_lr ,y_hr ,total_weight ,x_lr_ini ,x_hr_ini ,weight_y ,
+ x_lr ,x_hr ,weight : int;
+
+ weight_array : int16_ptr;
+
+ fg_ptr : int8u_ptr;
+
+begin
+ span:=_allocator.span;
+
+ _interpolator.begin_(x + filter_dx_dbl ,y + filter_dy_dbl ,len );
+
+ back_r:=_background_color.r;
+ back_g:=_background_color.g;
+ back_b:=_background_color.b;
+ back_a:=_background_color.a;
+
+ diameter :=_filter.diameter;
+ filter_size:=diameter shl image_subpixel_shift;
+
+ weight_array:=_filter.weight_array;
+
+ repeat
+ rx_inv:=image_subpixel_size;
+ ry_inv:=image_subpixel_size;
+
+ _interpolator.coordinates(@x ,@y );
+ _interpolator.local_scale(@rx ,@ry );
+
+ rx:=shr_int32(rx * m_blur_x ,image_subpixel_shift );
+ ry:=shr_int32(ry * m_blur_y ,image_subpixel_shift );
+
+ if rx < image_subpixel_size then
+ rx:=image_subpixel_size
+ else
+ begin
+ if rx > image_subpixel_size * m_scale_limit then
+ rx:=image_subpixel_size * m_scale_limit;
+
+ rx_inv:=image_subpixel_size * image_subpixel_size div rx;
+
+ end;
+
+ if ry < image_subpixel_size then
+ ry:=image_subpixel_size
+ else
+ begin
+ if ry > image_subpixel_size * m_scale_limit then
+ ry:=image_subpixel_size * m_scale_limit;
+
+ ry_inv:=image_subpixel_size * image_subpixel_size div ry;
+
+ end;
+
+ radius_x:=shr_int32(diameter * rx ,1 );
+ radius_y:=shr_int32(diameter * ry ,1 );
+
+ maxx:=_source_image._width - 1;
+ maxy:=_source_image._height - 1;
+
+ inc(x ,filter_dx_int - radius_x );
+ inc(y ,filter_dy_int - radius_y );
+
+ fg[0 ]:=image_filter_size div 2;
+ fg[1 ]:=fg[0 ];
+ fg[2 ]:=fg[0 ];
+ fg[3 ]:=fg[0 ];
+
+ y_lr:=shr_int32(y ,image_subpixel_shift );
+ y_hr:=
+ shr_int32(
+ (image_subpixel_mask - (y and image_subpixel_mask ) ) *
+ ry_inv ,image_subpixel_shift );
+
+ total_weight:=0;
+
+ x_lr_ini:=shr_int32(x ,image_subpixel_shift );
+ x_hr_ini:=
+ shr_int32(
+ (image_subpixel_mask - (x and image_subpixel_mask ) ) *
+ rx_inv ,image_subpixel_shift );
+
+ repeat
+ weight_y:=int16_ptr(ptrcomp(weight_array ) + y_hr * sizeof(int16 ) )^;
+
+ x_lr:=x_lr_ini;
+ x_hr:=x_hr_ini;
+
+ if (y_lr >= 0 ) and
+ (y_lr <= maxy ) then
+ begin
+ fg_ptr:=int8u_ptr(ptrcomp(_source_image.row(y_lr ) ) + x_lr * 3 * sizeof(int8 ) );
+
+ repeat
+ weight:=
+ shr_int32(
+ weight_y *
+ int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,downscale_shift );
+
+ if (x_lr >= 0 ) and
+ (x_lr <= maxx ) then
+ begin
+ inc(fg[0 ] ,fg_ptr^ * weight ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,fg_ptr^ * weight ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,fg_ptr^ * weight ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[3 ] ,base_mask * weight );
+
+ end
+ else
+ begin
+ inc(fg[m_order.R ] ,back_r * weight );
+ inc(fg[m_order.G ] ,back_g * weight );
+ inc(fg[m_order.B ] ,back_b * weight );
+ inc(fg[3 ] ,back_a * weight );
+
+ inc(ptrcomp(fg_ptr ) ,3 * sizeof(int8u ) );
+
+ end;
+
+ inc(total_weight ,weight );
+ inc(x_hr ,rx_inv );
+ inc(x_lr );
+
+ until x_hr >= filter_size;
+
+ end
+ else
+ repeat
+ weight:=
+ shr_int32(
+ weight_y *
+ int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,downscale_shift );
+
+ inc(total_weight ,weight );
+ inc(fg[m_order.R ] ,back_r * weight );
+ inc(fg[m_order.G ] ,back_g * weight );
+ inc(fg[m_order.B ] ,back_b * weight );
+ inc(fg[3 ] ,back_a * weight );
+ inc(x_hr ,rx_inv );
+
+ until x_hr >= filter_size;
+
+ inc(y_hr ,ry_inv );
+ inc(y_lr );
+
+ until y_hr >= filter_size;
+
+ fg[0 ]:=fg[0 ] div total_weight;
+ fg[1 ]:=fg[1 ] div total_weight;
+ fg[2 ]:=fg[2 ] div total_weight;
+ fg[3 ]:=fg[3 ] div total_weight;
+
+ if fg[0 ] < 0 then
+ fg[0 ]:=0;
+
+ if fg[1 ] < 0 then
+ fg[1 ]:=0;
+
+ if fg[2 ] < 0 then
+ fg[2 ]:=0;
+
+ if fg[3 ] < 0 then
+ fg[3 ]:=0;
+
+ if fg[3 ] > base_mask then
+ fg[3 ]:=base_mask;
+
+ if fg[0 ] > fg[3 ] then
+ fg[0 ]:=fg[3 ];
+
+ if fg[1 ] > fg[3 ] then
+ fg[1 ]:=fg[3 ];
+
+ if fg[2 ] > fg[3 ] then
+ fg[2 ]:=fg[3 ];
+
+ span.r:=int8u(fg[m_order.R ] );
+ span.g:=int8u(fg[m_order.G ] );
+ span.b:=int8u(fg[m_order.B ] );
+ span.a:=int8u(fg[3 ] );
+
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+
+ _interpolator.inc_operator;
+
+ dec(len );
+
+ until len = 0;
+
+ result:=_allocator.span;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_span_image_resample_rgba.pas b/src/corelib/render/software/agg_span_image_resample_rgba.pas
new file mode 100644
index 00000000..fc8e6870
--- /dev/null
+++ b/src/corelib/render/software/agg_span_image_resample_rgba.pas
@@ -0,0 +1,519 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 05.03.2006-Milano: Unit port establishment
+//
+{ agg_span_image_resample_rgba.pas }
+unit
+ agg_span_image_resample_rgba ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_color ,
+ agg_span_image_resample ,
+ agg_span_interpolator_linear ,
+ agg_rendering_buffer ,
+ agg_span_allocator ,
+ agg_image_filters ;
+
+{ TYPES DEFINITION }
+const
+ base_shift = agg_color.base_shift;
+ base_mask = agg_color.base_mask;
+ downscale_shift = image_filter_shift;
+
+type
+ span_image_resample_rgba_affine_ptr = ^span_image_resample_rgba_affine;
+ span_image_resample_rgba_affine = object(span_image_resample_affine )
+ m_order : order_type;
+
+ constructor Construct(alloc : span_allocator_ptr; order : order_type ); overload;
+ constructor Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ back_color : aggclr_ptr;
+ interpolator : span_interpolator_ptr;
+ filter : image_filter_lut_ptr;
+ order : order_type ); overload;
+
+ function generate(x ,y : int; len : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+ span_image_resample_rgba_ptr = ^span_image_resample_rgba;
+ span_image_resample_rgba = object(span_image_resample )
+ m_order : order_type;
+
+ constructor Construct(alloc : span_allocator_ptr; order : order_type ); overload;
+ constructor Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ back_color : aggclr_ptr;
+ interpolator : span_interpolator_ptr;
+ filter : image_filter_lut_ptr;
+ order : order_type ); overload;
+
+ function generate(x ,y : int; len : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor span_image_resample_rgba_affine.Construct(alloc : span_allocator_ptr; order : order_type );
+begin
+ inherited Construct(alloc );
+
+ m_order:=order;
+
+end;
+
+{ CONSTRUCT }
+constructor span_image_resample_rgba_affine.Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ back_color : aggclr_ptr;
+ interpolator : span_interpolator_ptr;
+ filter : image_filter_lut_ptr;
+ order : order_type );
+begin
+ inherited Construct(alloc ,src ,back_color ,interpolator ,filter );
+
+ m_order:=order;
+
+end;
+
+{ GENERATE }
+function span_image_resample_rgba_affine.generate;
+var
+ fg : array[0..3 ] of int;
+
+ back_r ,back_g ,back_b ,back_a : int8u;
+
+ span : aggclr_ptr;
+
+ diameter ,filter_size ,radius_x ,radius_y ,maxx ,maxy ,y_lr ,y_hr ,
+ total_weight ,x_lr_ini ,x_hr_ini ,weight_y ,x_lr ,x_hr ,weight : int;
+
+ fg_ptr : int8u_ptr;
+
+ weight_array : int16_ptr;
+
+begin
+ _interpolator.begin_(x + filter_dx_dbl ,y + filter_dy_dbl ,len );
+
+ back_r:=_background_color.r;
+ back_g:=_background_color.g;
+ back_b:=_background_color.b;
+ back_a:=_background_color.a;
+
+ span:=_allocator.span;
+
+ diameter :=_filter.diameter;
+ filter_size:=diameter shl image_subpixel_shift;
+
+ radius_x:=shr_int32(diameter * m_rx ,1 );
+ radius_y:=shr_int32(diameter * m_ry ,1 );
+
+ maxx:=_source_image._width - 1;
+ maxy:=_source_image._height - 1;
+
+ weight_array:=_filter.weight_array;
+
+ repeat
+ _interpolator.coordinates(@x ,@y );
+
+ inc(x ,filter_dx_int - radius_x );
+ inc(y ,filter_dy_int - radius_y );
+
+ fg[0 ]:=image_filter_size div 2;
+ fg[1 ]:=fg[0 ];
+ fg[2 ]:=fg[0 ];
+ fg[3 ]:=fg[0 ];
+
+ y_lr:=shr_int32(y ,image_subpixel_shift );
+ y_hr:=
+ shr_int32(
+ (image_subpixel_mask - (y and image_subpixel_mask ) ) *
+ m_ry_inv ,image_subpixel_shift );
+
+ total_weight:=0;
+
+ x_lr_ini:=shr_int32(x ,image_subpixel_shift );
+ x_hr_ini:=
+ shr_int32(
+ (image_subpixel_mask - (x and image_subpixel_mask ) ) *
+ m_rx_inv ,image_subpixel_shift );
+
+ repeat
+ weight_y:=int16_ptr(ptrcomp(weight_array ) + y_hr * sizeof(int16 ) )^;
+
+ x_lr:=x_lr_ini;
+ x_hr:=x_hr_ini;
+
+ if (y_lr >= 0 ) and
+ (y_lr <= maxy ) then
+ begin
+ fg_ptr:=int8u_ptr(ptrcomp(_source_image.row(y_lr ) ) + (x_lr shl 2 ) * sizeof(int8u ) );
+
+ repeat
+ weight:=
+ shr_int32(
+ weight_y *
+ int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,downscale_shift );
+
+ if (x_lr >= 0 ) and
+ (x_lr <= maxx ) then
+ begin
+ inc(fg[0 ] ,fg_ptr^ * weight ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,fg_ptr^ * weight ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,fg_ptr^ * weight ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[3 ] ,fg_ptr^ * weight ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+
+ end
+ else
+ begin
+ inc(fg[m_order.R ] ,back_r * weight );
+ inc(fg[m_order.G ] ,back_g * weight );
+ inc(fg[m_order.B ] ,back_b * weight );
+ inc(fg[m_order.A ] ,back_a * weight );
+
+ inc(ptrcomp(fg_ptr ) ,4 * sizeof(int8u ) );
+
+ end;
+
+ inc(total_weight ,weight );
+ inc(x_hr ,m_rx_inv );
+ inc(x_lr );
+
+ until x_hr >= filter_size;
+
+ end
+ else
+ repeat
+ weight:=
+ shr_int32(
+ weight_y *
+ int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,downscale_shift );
+
+ inc(total_weight ,weight );
+ inc(fg[m_order.R ] ,back_r * weight );
+ inc(fg[m_order.G ] ,back_g * weight );
+ inc(fg[m_order.B ] ,back_b * weight );
+ inc(fg[m_order.A ] ,back_a * weight );
+ inc(x_hr ,m_rx_inv );
+
+ until x_hr >= filter_size;
+
+ inc(y_hr ,m_ry_inv );
+ inc(y_lr );
+
+ until y_hr >= filter_size;
+
+ fg[0 ]:=fg[0 ] div total_weight;
+ fg[1 ]:=fg[1 ] div total_weight;
+ fg[2 ]:=fg[2 ] div total_weight;
+ fg[3 ]:=fg[3 ] div total_weight;
+
+ if fg[0 ] < 0 then
+ fg[0 ]:=0;
+
+ if fg[1 ] < 0 then
+ fg[1 ]:=0;
+
+ if fg[2 ] < 0 then
+ fg[2 ]:=0;
+
+ if fg[3 ] < 0 then
+ fg[3 ]:=0;
+
+ if fg[m_order.A ] > base_mask then
+ fg[m_order.A ]:=base_mask;
+
+ if fg[m_order.R ] > fg[m_order.A ] then
+ fg[m_order.R ]:=fg[m_order.A ];
+
+ if fg[m_order.G ] > fg[m_order.A ] then
+ fg[m_order.G ]:=fg[m_order.A ];
+
+ if fg[m_order.B ] > fg[m_order.A ] then
+ fg[m_order.B ]:=fg[m_order.A ];
+
+ span.r:=int8u(fg[m_order.R ] );
+ span.g:=int8u(fg[m_order.G ] );
+ span.b:=int8u(fg[m_order.B ] );
+ span.a:=int8u(fg[m_order.A ] );
+
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+
+ _interpolator.inc_operator;
+
+ dec(len );
+
+ until len = 0;
+
+ result:=_allocator.span;
+
+end;
+
+{ CONSTRUCT }
+constructor span_image_resample_rgba.Construct(alloc : span_allocator_ptr; order : order_type );
+begin
+ inherited Construct(alloc );
+
+ m_order:=order;
+
+end;
+
+{ CONSTRUCT }
+constructor span_image_resample_rgba.Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ back_color : aggclr_ptr;
+ interpolator : span_interpolator_ptr;
+ filter : image_filter_lut_ptr;
+ order : order_type );
+begin
+ inherited Construct(alloc ,src ,back_color ,interpolator ,filter );
+
+ m_order:=order;
+
+end;
+
+{ GENERATE }
+function span_image_resample_rgba.generate;
+var
+ span : aggclr_ptr;
+
+ fg : array[0..3 ] of int;
+
+ back_r ,back_g ,back_b ,back_a : int8u;
+
+ diameter ,filter_size ,rx ,ry ,rx_inv ,ry_inv ,radius_x ,radius_y ,
+ maxx ,maxy ,y_lr ,y_hr ,total_weight ,x_lr_ini ,x_hr_ini ,weight_y ,
+ x_lr ,x_hr ,weight : int;
+
+ fg_ptr : int8u_ptr;
+
+ weight_array : int16_ptr;
+
+begin
+ span:=_allocator.span;
+
+ _interpolator.begin_(x + filter_dx_dbl ,y + filter_dy_dbl ,len );
+
+ back_r:=_background_color.r;
+ back_g:=_background_color.g;
+ back_b:=_background_color.b;
+ back_a:=_background_color.a;
+
+ diameter :=_filter.diameter;
+ filter_size:=diameter shl image_subpixel_shift;
+
+ weight_array:=_filter.weight_array;
+
+ repeat
+ rx_inv:=image_subpixel_size;
+ ry_inv:=image_subpixel_size;
+
+ _interpolator.coordinates(@x ,@y );
+ _interpolator.local_scale(@rx ,@ry );
+
+ rx:=shr_int32(rx * m_blur_x ,image_subpixel_shift );
+ ry:=shr_int32(ry * m_blur_y ,image_subpixel_shift );
+
+ if rx < image_subpixel_size then
+ rx:=image_subpixel_size
+ else
+ begin
+ if rx > image_subpixel_size * m_scale_limit then
+ rx:=image_subpixel_size * m_scale_limit;
+
+ rx_inv:=image_subpixel_size * image_subpixel_size div rx;
+
+ end;
+
+ if ry < image_subpixel_size then
+ ry:=image_subpixel_size
+ else
+ begin
+ if ry > image_subpixel_size * m_scale_limit then
+ ry:=image_subpixel_size * m_scale_limit;
+
+ ry_inv:=image_subpixel_size * image_subpixel_size div ry;
+
+ end;
+
+ radius_x:=shr_int32(diameter * rx ,1 );
+ radius_y:=shr_int32(diameter * ry ,1 );
+
+ maxx:=_source_image._width - 1;
+ maxy:=_source_image._height - 1;
+
+ inc(x ,filter_dx_int - radius_x );
+ inc(y ,filter_dy_int - radius_y );
+
+ fg[0 ]:=image_filter_size div 2;
+ fg[1 ]:=fg[0 ];
+ fg[2 ]:=fg[0 ];
+ fg[3 ]:=fg[0 ];
+
+ y_lr:=shr_int32(y ,image_subpixel_shift );
+ y_hr:=
+ shr_int32(
+ (image_subpixel_mask - (y and image_subpixel_mask ) ) *
+ ry_inv ,image_subpixel_shift );
+
+ total_weight:=0;
+
+ x_lr_ini:=shr_int32(x ,image_subpixel_shift );
+ x_hr_ini:=
+ shr_int32(
+ (image_subpixel_mask - (x and image_subpixel_mask ) ) *
+ rx_inv ,image_subpixel_shift );
+
+ repeat
+ weight_y:=int16_ptr(ptrcomp(weight_array ) + y_hr * sizeof(int16 ) )^;
+
+ x_lr:=x_lr_ini;
+ x_hr:=x_hr_ini;
+
+ if (y_lr >= 0 ) and
+ (y_lr <= maxy ) then
+ begin
+ fg_ptr:=int8u_ptr(ptrcomp(_source_image.row(y_lr ) ) + (x_lr shl 2 ) * sizeof(int8u ) );
+
+ repeat
+ weight:=
+ shr_int32(
+ weight_y *
+ int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,downscale_shift );
+
+ if (x_lr >= 0 ) and
+ (x_lr <= maxx ) then
+ begin
+ inc(fg[0 ] ,fg_ptr^ * weight ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,fg_ptr^ * weight ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,fg_ptr^ * weight ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[3 ] ,fg_ptr^ * weight ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+
+ end
+ else
+ begin
+ inc(fg[m_order.R ] ,back_r * weight );
+ inc(fg[m_order.G ] ,back_g * weight );
+ inc(fg[m_order.B ] ,back_b * weight );
+ inc(fg[m_order.A ] ,back_a * weight );
+
+ inc(ptrcomp(fg_ptr ) ,4 * sizeof(int8u ) );
+
+ end;
+
+ inc(total_weight ,weight );
+ inc(x_hr ,rx_inv );
+ inc(x_lr );
+
+ until x_hr >= filter_size;
+
+ end
+ else
+ repeat
+ weight:=
+ shr_int32(
+ weight_y *
+ int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,downscale_shift );
+
+ inc(total_weight ,weight );
+ inc(fg[m_order.R ] ,back_r * weight );
+ inc(fg[m_order.G ] ,back_g * weight );
+ inc(fg[m_order.B ] ,back_b * weight );
+ inc(fg[m_order.A ] ,back_a * weight );
+ inc(x_hr ,rx_inv );
+
+ until x_hr >= filter_size;
+
+ inc(y_hr ,ry_inv );
+ inc(y_lr );
+
+ until y_hr >= filter_size;
+
+ fg[0 ]:=fg[0 ] div total_weight;
+ fg[1 ]:=fg[1 ] div total_weight;
+ fg[2 ]:=fg[2 ] div total_weight;
+ fg[3 ]:=fg[3 ] div total_weight;
+
+ if fg[0 ] < 0 then
+ fg[0 ]:=0;
+
+ if fg[1 ] < 0 then
+ fg[1 ]:=0;
+
+ if fg[2 ] < 0 then
+ fg[2 ]:=0;
+
+ if fg[3 ] < 0 then
+ fg[3 ]:=0;
+
+ if fg[m_order.A ] > base_mask then
+ fg[m_order.A ]:=base_mask;
+
+ if fg[m_order.R ] > fg[m_order.A ] then
+ fg[m_order.R ]:=fg[m_order.A ];
+
+ if fg[m_order.G ] > fg[m_order.A ] then
+ fg[m_order.G ]:=fg[m_order.A ];
+
+ if fg[m_order.B ] > fg[m_order.A ] then
+ fg[m_order.B ]:=fg[m_order.A ];
+
+ span.r:=int8u(fg[m_order.R ] );
+ span.g:=int8u(fg[m_order.G ] );
+ span.b:=int8u(fg[m_order.B ] );
+ span.a:=int8u(fg[m_order.A ] );
+
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+
+ _interpolator.inc_operator;
+
+ dec(len );
+
+ until len = 0;
+
+ result:=_allocator.span;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_span_interpolator_adaptor.pas b/src/corelib/render/software/agg_span_interpolator_adaptor.pas
new file mode 100644
index 00000000..48154aa9
--- /dev/null
+++ b/src/corelib/render/software/agg_span_interpolator_adaptor.pas
@@ -0,0 +1,123 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 07.03.2006-Milano: Unit port establishment
+//
+{ agg_span_interpolator_adaptor.pas }
+unit
+ agg_span_interpolator_adaptor ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_span_interpolator_linear ,
+ agg_trans_affine ;
+
+{ TYPES DEFINITION }
+type
+ distortion_ptr = ^distortion;
+ distortion = object
+ procedure calculate(x ,y : int_ptr ); virtual; abstract;
+
+ end;
+
+ span_interpolator_adaptor = object(span_interpolator_linear )
+ m_distortion : distortion_ptr;
+
+ constructor Construct; overload;
+ constructor Construct(trans : trans_affine_ptr; dist : distortion_ptr ); overload;
+ constructor Construct(
+ trans : trans_affine_ptr;
+ dist : distortion_ptr;
+ x ,y : double; len : unsigned ); overload;
+
+ function _distortion : distortion_ptr;
+ procedure distortion_(dist : distortion_ptr );
+
+ procedure coordinates(x ,y : int_ptr ); virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor span_interpolator_adaptor.Construct;
+begin
+ inherited Construct;
+
+ m_distortion:=NIL;
+
+end;
+
+{ CONSTRUCT }
+constructor span_interpolator_adaptor.Construct(trans : trans_affine_ptr; dist : distortion_ptr );
+begin
+ inherited Construct(trans );
+
+ m_distortion:=dist;
+
+end;
+
+{ CONSTRUCT }
+constructor span_interpolator_adaptor.Construct(
+ trans : trans_affine_ptr;
+ dist : distortion_ptr;
+ x ,y : double; len : unsigned );
+begin
+ inherited Construct(trans ,x ,y ,len );
+
+ m_distortion:=dist;
+
+end;
+
+{ _DISTORTION }
+function span_interpolator_adaptor._distortion;
+begin
+ result:=m_distortion;
+
+end;
+
+{ DISTORTION_ }
+procedure span_interpolator_adaptor.distortion_;
+begin
+ m_distortion:=dist;
+
+end;
+
+{ COORDINATES }
+procedure span_interpolator_adaptor.coordinates;
+begin
+ inherited coordinates(x ,y );
+
+ m_distortion.calculate(x ,y );
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_span_interpolator_linear.pas b/src/corelib/render/software/agg_span_interpolator_linear.pas
new file mode 100644
index 00000000..e84969e6
--- /dev/null
+++ b/src/corelib/render/software/agg_span_interpolator_linear.pas
@@ -0,0 +1,371 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 27.01.2006-Milano: Unit port establishment
+//
+{ agg_span_interpolator_linear.pas }
+unit
+ agg_span_interpolator_linear ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+{$Q- }
+{$R- }
+uses
+ agg_basics ,
+ agg_dda_line ,
+ agg_trans_affine ;
+
+{ TYPES DEFINITION }
+type
+ span_interpolator_ptr = ^span_interpolator;
+ span_interpolator = object
+ subpixel_shift ,
+ subpixel_size : unsigned;
+
+ constructor Construct(SS : unsigned = 8 );
+
+ function _transformer : trans_affine_ptr; virtual; abstract;
+ procedure transformer_(trans : trans_affine_ptr ); virtual; abstract;
+
+ procedure begin_(x ,y : double; len : unsigned ); virtual; abstract;
+
+ procedure resynchronize(xe ,ye : double; len : unsigned ); virtual; abstract;
+
+ procedure inc_operator; virtual; abstract;
+ procedure coordinates(x ,y : int_ptr ); virtual; abstract;
+
+ procedure local_scale(x ,y : int_ptr ); virtual;
+
+ end;
+
+//================================================span_interpolator_linear
+ span_interpolator_linear_ptr = ^span_interpolator_linear;
+ span_interpolator_linear = object(span_interpolator )
+ m_trans : trans_affine_ptr;
+ m_li_x ,
+ m_li_y : dda2_line_interpolator;
+
+ constructor Construct(SS : unsigned = 8 ); overload;
+ constructor Construct(trans : trans_affine_ptr; SS : unsigned = 8 ); overload;
+ constructor Construct(trans : trans_affine_ptr; x ,y : double; len : unsigned; SS : unsigned = 8 ); overload;
+
+ function _transformer : trans_affine_ptr; virtual;
+ procedure transformer_(trans : trans_affine_ptr ); virtual;
+
+ procedure begin_(x ,y : double; len : unsigned ); virtual;
+
+ procedure resynchronize(xe ,ye : double; len : unsigned ); virtual;
+
+ procedure inc_operator; virtual;
+ procedure coordinates(x ,y : int_ptr ); virtual;
+
+ end;
+
+//=====================================span_interpolator_linear_subdiv
+ span_interpolator_linear_subdiv = object(span_interpolator )
+ m_subdiv_shift ,
+ m_subdiv_size ,
+ m_subdiv_mask : unsigned;
+
+ m_trans : trans_affine_ptr;
+ m_li_x ,
+ m_li_y : dda2_line_interpolator;
+
+ m_src_x : int;
+ m_src_y : double;
+ m_pos ,
+ m_len : unsigned;
+
+ constructor Construct(SS : unsigned = 8 ); overload;
+ constructor Construct(trans : trans_affine_ptr; subdiv_shift : unsigned = 4; SS : unsigned = 8 ); overload;
+ constructor Construct(trans : trans_affine_ptr; x ,y : double; len : unsigned; subdiv_shift : unsigned = 4; SS : unsigned = 8 ); overload;
+
+ function _transformer : trans_affine_ptr; virtual;
+ procedure transformer_(trans : trans_affine_ptr ); virtual;
+
+ function _subdiv_shift : unsigned;
+ procedure subdiv_shift_(shift : unsigned );
+
+ procedure begin_(x ,y : double; len : unsigned ); virtual;
+
+ procedure inc_operator; virtual;
+ procedure coordinates(x ,y : int_ptr ); virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor span_interpolator.Construct;
+begin
+ subpixel_shift:=SS;
+ subpixel_size :=1 shl subpixel_shift;
+
+end;
+
+{ LOCAL_SCALE }
+procedure span_interpolator.local_scale;
+begin
+end;
+
+{ CONSTRUCT }
+constructor span_interpolator_linear.Construct(SS : unsigned = 8 );
+begin
+ inherited Construct(SS );
+
+end;
+
+{ CONSTRUCT }
+constructor span_interpolator_linear.Construct(trans : trans_affine_ptr; SS : unsigned = 8 );
+begin
+ Construct(SS );
+
+ m_trans:=trans;
+
+end;
+
+{ CONSTRUCT }
+constructor span_interpolator_linear.Construct(trans : trans_affine_ptr; x ,y : double; len : unsigned; SS : unsigned = 8 );
+begin
+ Construct(trans ,SS );
+
+ begin_(x ,y ,len );
+
+end;
+
+{ _TRANSFORMER }
+function span_interpolator_linear._transformer;
+begin
+ result:=m_trans;
+
+end;
+
+{ TRANSFORMER_ }
+procedure span_interpolator_linear.transformer_;
+begin
+ m_trans:=trans;
+
+end;
+
+{ BEGIN_ }
+procedure span_interpolator_linear.begin_;
+var
+ tx ,ty : double;
+
+ x1 ,y1 ,x2 ,y2 : int;
+
+begin
+ tx:=x;
+ ty:=y;
+
+ m_trans.transform(m_trans ,@tx ,@ty );
+
+ x1:=trunc(tx * subpixel_size );
+ y1:=trunc(ty * subpixel_size );
+
+ tx:=x + len;
+ ty:=y;
+
+ m_trans.transform(m_trans ,@tx ,@ty );
+
+ x2:=trunc(tx * subpixel_size );
+ y2:=trunc(ty * subpixel_size );
+
+ m_li_x.Construct(x1 ,x2 ,len );
+ m_li_y.Construct(y1 ,y2 ,len );
+
+end;
+
+{ RESYNCHRONIZE }
+procedure span_interpolator_linear.resynchronize;
+begin
+ m_trans.transform(m_trans ,@xe ,@ye );
+
+ m_li_x.Construct(m_li_x._y ,trunc(xe * subpixel_size ) ,len );
+ m_li_y.Construct(m_li_y._y ,trunc(ye * subpixel_size ) ,len );
+
+end;
+
+{ INC_OPERATOR }
+procedure span_interpolator_linear.inc_operator;
+begin
+ m_li_x.plus_operator;
+ m_li_y.plus_operator;
+
+end;
+
+{ COORDINATES }
+procedure span_interpolator_linear.coordinates;
+begin
+ x^:=m_li_x._y;
+ y^:=m_li_y._y;
+
+end;
+
+{ CONSTRUCT }
+constructor span_interpolator_linear_subdiv.Construct(SS : unsigned = 8 );
+begin
+ inherited Construct(SS );
+
+ m_subdiv_shift:=4;
+ m_subdiv_size :=1 shl m_subdiv_shift;
+ m_subdiv_mask :=m_subdiv_size - 1;
+
+end;
+
+{ CONSTRUCT }
+constructor span_interpolator_linear_subdiv.Construct(trans : trans_affine_ptr; subdiv_shift : unsigned = 4; SS : unsigned = 8 );
+begin
+ inherited Construct(SS );
+
+ m_subdiv_shift:=subdiv_shift;
+ m_subdiv_size :=1 shl m_subdiv_shift;
+ m_subdiv_mask :=m_subdiv_size - 1;
+
+ m_trans:=trans;
+
+end;
+
+{ CONSTRUCT }
+constructor span_interpolator_linear_subdiv.Construct(trans : trans_affine_ptr; x ,y : double; len : unsigned; subdiv_shift : unsigned = 4; SS : unsigned = 8 );
+begin
+ Construct(trans ,subdiv_shift ,SS );
+
+ begin_(x ,y ,len );
+
+end;
+
+{ _TRANSFORMER }
+function span_interpolator_linear_subdiv._transformer;
+begin
+ result:=m_trans;
+
+end;
+
+{ TRANSFORMER_ }
+procedure span_interpolator_linear_subdiv.transformer_;
+begin
+ m_trans:=trans;
+
+end;
+
+{ _SUBDIV_SHIFT }
+function span_interpolator_linear_subdiv._subdiv_shift;
+begin
+ result:=m_subdiv_shift;
+
+end;
+
+{ SUBDIV_SHIFT_ }
+procedure span_interpolator_linear_subdiv.subdiv_shift_;
+begin
+ m_subdiv_shift:=shift;
+ m_subdiv_size :=1 shl m_subdiv_shift;
+ m_subdiv_mask :=m_subdiv_size - 1;
+
+end;
+
+{ BEGIN_ }
+procedure span_interpolator_linear_subdiv.begin_;
+var
+ tx ,ty : double;
+ x1 ,y1 : int;
+
+begin
+ m_pos :=1;
+ m_src_x:=trunc(x * subpixel_size ) + subpixel_size;
+ m_src_y:=y;
+ m_len :=len;
+
+ if len > m_subdiv_size then
+ len:=m_subdiv_size;
+
+ tx:=x;
+ ty:=y;
+
+ m_trans.transform(m_trans ,@tx ,@ty );
+
+ x1:=trunc(tx * subpixel_size );
+ y1:=trunc(ty * subpixel_size );
+
+ tx:=x + len;
+ ty:=y;
+
+ m_trans.transform(m_trans ,@tx ,@ty );
+
+ m_li_x.Construct(x1 ,trunc(tx * subpixel_size ) ,len );
+ m_li_y.Construct(y1 ,trunc(ty * subpixel_size ) ,len );
+
+end;
+
+{ INC_OPERATOR }
+procedure span_interpolator_linear_subdiv.inc_operator;
+var
+ tx ,ty : double;
+
+ len : unsigned;
+
+begin
+ m_li_x.plus_operator;
+ m_li_y.plus_operator;
+
+ if m_pos >= m_subdiv_size then
+ begin
+ len:=m_len;
+
+ if len > m_subdiv_size then
+ len:=m_subdiv_size;
+
+ tx:=m_src_x / subpixel_size + len;
+ ty:=m_src_y;
+
+ m_trans.transform(m_trans ,@tx ,@ty );
+
+ m_li_x.Construct(m_li_x._y ,trunc(tx * subpixel_size ) ,len );
+ m_li_y.Construct(m_li_y._y ,trunc(ty * subpixel_size ) ,len );
+
+ m_pos:=0;
+
+ end;
+
+ inc(m_src_x ,subpixel_size );
+ inc(m_pos );
+ dec(m_len );
+
+end;
+
+{ COORDINATES }
+procedure span_interpolator_linear_subdiv.coordinates;
+begin
+ x^:=m_li_x._y;
+ y^:=m_li_y._y;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_span_interpolator_persp.pas b/src/corelib/render/software/agg_span_interpolator_persp.pas
new file mode 100644
index 00000000..f3cf5631
--- /dev/null
+++ b/src/corelib/render/software/agg_span_interpolator_persp.pas
@@ -0,0 +1,642 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 05.03.2006-Milano: Unit port establishment
+//
+{ agg_span_interpolator_persp.pas }
+unit
+ agg_span_interpolator_persp ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+{$Q- }
+{$R- }
+uses
+ agg_basics ,
+ agg_trans_perspective ,
+ agg_span_interpolator_linear ,
+ agg_dda_line ;
+
+{ TYPES DEFINITION }
+type
+ span_interpolator_persp_exact = object(span_interpolator )
+ m_trans_dir ,
+ m_trans_inv : trans_perspective23;
+ m_iterator : agg_trans_perspective.iterator_x23;
+ m_scale_x ,
+ m_scale_y : dda2_line_interpolator;
+
+ constructor Construct(SS : unsigned = 8 ); overload;
+
+ // Arbitrary quadrangle transformations
+ constructor Construct(src ,dst : double_ptr; SS : unsigned = 8 ); overload;
+
+ // Direct transformations
+ constructor Construct(x1 ,y1 ,x2 ,y2 : double; quad : double_ptr; SS : unsigned = 8 ); overload;
+
+ // Reverse transformations
+ constructor Construct(quad : double_ptr; x1 ,y1 ,x2 ,y2 : double; SS : unsigned = 8 ); overload;
+
+ // Set the transformations using two arbitrary quadrangles.
+ procedure quad_to_quad(src ,dst : double_ptr );
+
+ // Set the direct transformations, i.e., rectangle -> quadrangle
+ procedure rect_to_quad(x1 ,y1 ,x2 ,y2 : double; quad : double_ptr );
+
+ // Set the reverse transformations, i.e., quadrangle -> rectangle
+ procedure quad_to_rect(quad : double_ptr; x1 ,y1 ,x2 ,y2 : double );
+
+ // Check if the equations were solved successfully
+ function is_valid : boolean;
+
+ // Span interpolator interface
+ procedure begin_(x ,y : double; len : unsigned ); virtual;
+
+ procedure resynchronize(xe ,ye : double; len : unsigned ); virtual;
+
+ procedure inc_operator; virtual;
+ procedure coordinates(x ,y : int_ptr ); virtual;
+
+ procedure local_scale(x ,y : int_ptr ); virtual;
+
+ procedure transform(x ,y : double_ptr );
+
+ end;
+
+ span_interpolator_persp_lerp = object(span_interpolator )
+ m_trans_dir ,
+ m_trans_inv : trans_perspective23;
+
+ m_coord_x ,
+ m_coord_y ,
+ m_scale_x ,
+ m_scale_y : dda2_line_interpolator;
+
+ constructor Construct(SS : unsigned = 8 ); overload;
+
+ // Arbitrary quadrangle transformations
+ constructor Construct(src ,dst : double_ptr; SS : unsigned = 8 ); overload;
+
+ // Direct transformations
+ constructor Construct(x1 ,y1 ,x2 ,y2 : double; quad : double_ptr; SS : unsigned = 8 ); overload;
+
+ // Reverse transformations
+ constructor Construct(quad : double_ptr; x1 ,y1 ,x2 ,y2 : double; SS : unsigned = 8 ); overload;
+
+ // Set the transformations using two arbitrary quadrangles.
+ procedure quad_to_quad(src ,dst : double_ptr );
+
+ // Set the direct transformations, i.e., rectangle -> quadrangle
+ procedure rect_to_quad(x1 ,y1 ,x2 ,y2 : double; quad : double_ptr );
+
+ // Set the reverse transformations, i.e., quadrangle -> rectangle
+ procedure quad_to_rect(quad : double_ptr; x1 ,y1 ,x2 ,y2 : double );
+
+ // Check if the equations were solved successfully
+ function is_valid : boolean;
+
+ // Span interpolator interface
+ procedure begin_(x ,y : double; len : unsigned ); virtual;
+
+ procedure resynchronize(xe ,ye : double; len : unsigned ); virtual;
+
+ procedure inc_operator; virtual;
+ procedure coordinates(x ,y : int_ptr ); virtual;
+
+ procedure local_scale(x ,y : int_ptr ); virtual;
+
+ procedure transform(x ,y : double_ptr );
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor span_interpolator_persp_exact.Construct(SS : unsigned = 8 );
+begin
+ inherited Construct(SS );
+
+ m_trans_dir.Construct;
+ m_trans_inv.Construct;
+ m_iterator.Construct;
+
+end;
+
+{ CONSTRUCT }
+constructor span_interpolator_persp_exact.Construct(src ,dst : double_ptr; SS : unsigned = 8 );
+begin
+ inherited Construct(SS );
+
+ m_trans_dir.Construct;
+ m_trans_inv.Construct;
+ m_iterator.Construct;
+
+ quad_to_quad(src ,dst );
+
+end;
+
+{ CONSTRUCT }
+constructor span_interpolator_persp_exact.Construct(x1 ,y1 ,x2 ,y2 : double; quad : double_ptr; SS : unsigned = 8 );
+begin
+ inherited Construct(SS );
+
+ m_trans_dir.Construct;
+ m_trans_inv.Construct;
+ m_iterator.Construct;
+
+ rect_to_quad(x1 ,y1 ,x2 ,y2 ,quad );
+
+end;
+
+{ CONSTRUCT }
+constructor span_interpolator_persp_exact.Construct(quad : double_ptr; x1 ,y1 ,x2 ,y2 : double; SS : unsigned = 8 );
+begin
+ inherited Construct(SS );
+
+ m_trans_dir.Construct;
+ m_trans_inv.Construct;
+ m_iterator.Construct;
+
+ quad_to_rect(quad ,x1 ,y1 ,x2 ,y2 );
+
+end;
+
+{ QUAD_TO_QUAD }
+procedure span_interpolator_persp_exact.quad_to_quad;
+begin
+ m_trans_dir.quad_to_quad(src ,dst );
+ m_trans_inv.quad_to_quad(dst ,src );
+
+end;
+
+{ RECT_TO_QUAD }
+procedure span_interpolator_persp_exact.rect_to_quad;
+var
+ src : array[0..7 ] of double;
+
+begin
+ src[0 ]:=x1;
+ src[6 ]:=x1;
+ src[2 ]:=x2;
+ src[4 ]:=x2;
+ src[1 ]:=y1;
+ src[3 ]:=y1;
+ src[5 ]:=y2;
+ src[7 ]:=y2;
+
+ quad_to_quad(@src ,quad );
+
+end;
+
+{ QUAD_TO_RECT }
+procedure span_interpolator_persp_exact.quad_to_rect;
+var
+ dst : array[0..7 ] of double;
+
+begin
+ dst[0 ]:=x1;
+ dst[6 ]:=x1;
+ dst[2 ]:=x2;
+ dst[4 ]:=x2;
+ dst[1 ]:=y1;
+ dst[3 ]:=y1;
+ dst[5 ]:=y2;
+ dst[7 ]:=y2;
+
+ quad_to_quad(quad ,@dst );
+
+end;
+
+{ IS_VALID }
+function span_interpolator_persp_exact.is_valid;
+begin
+ result:=m_trans_dir.is_valid;
+
+end;
+
+{ BEGIN_ }
+procedure span_interpolator_persp_exact.begin_;
+var
+ xt ,yt ,dx ,dy ,delta : double;
+
+ sx1 ,sy1 ,sx2 ,sy2 : int;
+
+begin
+ m_iterator:=m_trans_dir.begin_(x ,y ,1.0 );
+
+ xt:=m_iterator.x;
+ yt:=m_iterator.y;
+
+ delta:=1 / subpixel_size;
+
+ dx:=xt + delta;
+ dy:=yt;
+
+ m_trans_inv.transform(@m_trans_inv ,@dx ,@dy );
+
+ dx :=dx - x;
+ dy :=dy - y;
+ sx1:=shr_int32(trunc(subpixel_size / Sqrt(dx * dx + dy * dy ) ) ,subpixel_shift );
+ dx :=xt;
+ dy :=yt + delta;
+
+ m_trans_inv.transform(@m_trans_inv ,@dx ,@dy );
+
+ dx :=dx - x;
+ dy :=dy - y;
+ sy1:=shr_int32(trunc(subpixel_size / Sqrt(dx * dx + dy * dy ) ) ,subpixel_shift );
+
+ x :=x + len;
+ xt:=x;
+ yt:=y;
+
+ m_trans_dir.transform(@m_trans_dir ,@xt ,@yt );
+
+ dx:=xt + delta;
+ dy:=yt;
+
+ m_trans_inv.transform(@m_trans_inv ,@dx ,@dy );
+
+ dx :=dx- x;
+ dy :=dy - y;
+ sx2:=shr_int32(trunc(subpixel_size / Sqrt(dx * dx + dy * dy ) ) ,subpixel_shift );
+ dx :=xt;
+ dy :=yt + delta;
+
+ m_trans_inv.transform(@m_trans_inv ,@dx ,@dy );
+
+ dx :=dx - x;
+ dy :=dy - y;
+ sy2:=shr_int32(trunc(subpixel_size / Sqrt(dx * dx + dy * dy ) ) ,subpixel_shift );
+
+ m_scale_x.Construct(sx1 ,sx2 ,len );
+ m_scale_y.Construct(sy1 ,sy2 ,len );
+
+end;
+
+{ RESYNCHRONIZE }
+procedure span_interpolator_persp_exact.resynchronize;
+var
+ sx1 ,sy1 ,sx2 ,sy2 : int;
+
+ xt ,yt ,delta ,dx ,dy : double;
+
+begin
+// Assume x1,y1 are equal to the ones at the previous end point
+ sx1:=m_scale_x._y;
+ sy1:=m_scale_y._y;
+
+// Calculate transformed coordinates at x2,y2
+ xt:=xe;
+ yt:=ye;
+
+ m_trans_dir.transform(@m_trans_dir ,@xt ,@yt );
+
+ delta:=1 / subpixel_size;
+
+// Calculate scale by X at x2,y2
+ dx:=xt + delta;
+ dy:=yt;
+
+ m_trans_inv.transform(@m_trans_inv ,@dx ,@dy );
+
+ dx :=dx - xe;
+ dy :=dy - ye;
+ sx2:=shr_int32(trunc(subpixel_size / Sqrt(dx * dx + dy * dy ) ) ,subpixel_shift );
+
+// Calculate scale by Y at x2,y2
+ dx:=xt;
+ dy:=yt + delta;
+
+ m_trans_inv.transform(@m_trans_inv ,@dx ,@dy );
+
+ dx :=dx - xe;
+ dy :=dy - ye;
+ sy2:=shr_int32(trunc(subpixel_size / Sqrt(dx * dx + dy * dy ) ) ,subpixel_shift );
+
+// Initialize the interpolators
+ m_scale_x.Construct(sx1 ,sx2 ,len );
+ m_scale_y.Construct(sy1 ,sy2 ,len );
+
+end;
+
+{ INC_OPERATOR }
+procedure span_interpolator_persp_exact.inc_operator;
+begin
+ m_iterator.inc_operator;
+ m_scale_x.plus_operator;
+ m_scale_y.plus_operator;
+
+end;
+
+{ COORDINATES }
+procedure span_interpolator_persp_exact.coordinates;
+begin
+ x^:=trunc(m_iterator.x * subpixel_size + 0.5 );
+ y^:=trunc(m_iterator.y * subpixel_size + 0.5 );
+
+end;
+
+{ LOCAL_SCALE }
+procedure span_interpolator_persp_exact.local_scale;
+begin
+ x^:= m_scale_x._y;
+ y^:= m_scale_y._y;
+
+end;
+
+{ TRANSFORM }
+procedure span_interpolator_persp_exact.transform;
+begin
+ m_trans_dir.transform(@m_trans_dir ,x ,y );
+
+end;
+
+{ CONSTRUCT }
+constructor span_interpolator_persp_lerp.Construct(SS : unsigned = 8 );
+begin
+ inherited Construct(SS );
+
+ m_trans_dir.Construct;
+ m_trans_inv.Construct;
+
+end;
+
+{ CONSTRUCT }
+constructor span_interpolator_persp_lerp.Construct(src ,dst : double_ptr; SS : unsigned = 8 );
+begin
+ inherited Construct(SS );
+
+ m_trans_dir.Construct;
+ m_trans_inv.Construct;
+
+ quad_to_quad(src ,dst );
+
+end;
+
+{ CONSTRUCT }
+constructor span_interpolator_persp_lerp.Construct(x1 ,y1 ,x2 ,y2 : double; quad : double_ptr; SS : unsigned = 8 );
+begin
+ inherited Construct(SS );
+
+ m_trans_dir.Construct;
+ m_trans_inv.Construct;
+
+ rect_to_quad(x1 ,y1 ,x2 ,y2 ,quad );
+
+end;
+
+{ CONSTRUCT }
+constructor span_interpolator_persp_lerp.Construct(quad : double_ptr; x1 ,y1 ,x2 ,y2 : double; SS : unsigned = 8 );
+begin
+ inherited Construct(SS );
+
+ m_trans_dir.Construct;
+ m_trans_inv.Construct;
+
+ quad_to_rect(quad ,x1 ,y1 ,x2 ,y2 );
+
+end;
+
+{ QUAD_TO_QUAD }
+procedure span_interpolator_persp_lerp.quad_to_quad;
+begin
+ m_trans_dir.quad_to_quad(src ,dst );
+ m_trans_inv.quad_to_quad(dst ,src );
+
+end;
+
+{ RECT_TO_QUAD }
+procedure span_interpolator_persp_lerp.rect_to_quad;
+var
+ src : array[0..7 ] of double;
+
+begin
+ src[0 ]:=x1;
+ src[6 ]:=x1;
+ src[2 ]:=x2;
+ src[4 ]:=x2;
+ src[1 ]:=y1;
+ src[3 ]:=y1;
+ src[5 ]:=y2;
+ src[7 ]:=y2;
+
+ quad_to_quad(@src ,quad );
+
+end;
+
+{ QUAD_TO_RECT }
+procedure span_interpolator_persp_lerp.quad_to_rect;
+var
+ dst : array[0..7 ] of double;
+
+begin
+ dst[0 ]:=x1;
+ dst[6 ]:=x1;
+ dst[2 ]:=x2;
+ dst[4 ]:=x2;
+ dst[1 ]:=y1;
+ dst[3 ]:=y1;
+ dst[5 ]:=y2;
+ dst[7 ]:=y2;
+
+ quad_to_quad(quad ,@dst );
+
+end;
+
+{ IS_VALID }
+function span_interpolator_persp_lerp.is_valid;
+begin
+ result:=m_trans_dir.is_valid;
+
+end;
+
+{ BEGIN_ }
+procedure span_interpolator_persp_lerp.begin_;
+var
+ xt ,yt ,dx ,dy ,delta : double;
+
+ x1 ,y1 ,sx1 ,sy1 ,x2 ,y2 ,sx2 ,sy2 : int;
+
+begin
+// Calculate transformed coordinates at x1,y1
+ xt:=x;
+ yt:=y;
+
+ m_trans_dir.transform(@m_trans_dir ,@xt ,@yt );
+
+ x1:=trunc(xt * subpixel_size );
+ y1:=trunc(yt * subpixel_size );
+
+ delta:=1 / subpixel_size;
+
+// Calculate scale by X at x1,y1
+ dx:=xt + delta;
+ dy:=yt;
+
+ m_trans_inv.transform(@m_trans_inv ,@dx ,@dy );
+
+ dx :=dx - x;
+ dy :=dy - y;
+ sx1:=shr_int32(trunc(subpixel_size / Sqrt(dx * dx + dy * dy ) ) ,subpixel_shift );
+
+// Calculate scale by Y at x1,y1
+ dx:=xt;
+ dy:=yt + delta;
+
+ m_trans_inv.transform(@m_trans_inv ,@dx ,@dy );
+
+ dx :=dx - x;
+ dy :=dy - y;
+ sy1:=shr_int32(trunc(subpixel_size / Sqrt(dx * dx + dy * dy ) ) ,subpixel_shift );
+
+// Calculate transformed coordinates at x2,y2
+ x :=x + len;
+ xt:=x;
+ yt:=y;
+
+ m_trans_dir.transform(@m_trans_dir ,@xt ,@yt );
+
+ x2:=trunc(xt * subpixel_size );
+ y2:=trunc(yt * subpixel_size );
+
+// Calculate scale by X at x2,y2
+ dx:=xt + delta;
+ dy:=yt;
+
+ m_trans_inv.transform(@m_trans_inv ,@dx ,@dy );
+
+ dx :=dx - x;
+ dy :=dy - y;
+ sx2:=shr_int32(trunc(subpixel_size / Sqrt(dx * dx + dy * dy ) ) ,subpixel_shift );
+
+// Calculate scale by Y at x2,y2
+ dx:=xt;
+ dy:=yt + delta;
+
+ m_trans_inv.transform(@m_trans_inv ,@dx ,@dy );
+
+ dx :=dx - x;
+ dy :=dy - y;
+ sy2:=shr_int32(trunc(subpixel_size / Sqrt(dx * dx + dy * dy ) ) ,subpixel_shift );
+
+// Initialize the interpolators
+ m_coord_x.Construct(x1 ,x2 ,len );
+ m_coord_y.Construct(y1 ,y2 ,len );
+ m_scale_x.Construct(sx1 ,sx2 ,len );
+ m_scale_y.Construct(sy1 ,sy2 ,len );
+
+end;
+
+{ RESYNCHRONIZE }
+procedure span_interpolator_persp_lerp.resynchronize;
+var
+ x1 ,y1 ,sx1 ,sy1 ,x2 ,y2 ,sx2 ,sy2 : int;
+
+ xt ,yt ,delta ,dx ,dy : double;
+
+begin
+// Assume x1,y1 are equal to the ones at the previous end point
+ x1 :=m_coord_x._y;
+ y1 :=m_coord_y._y;
+ sx1:=m_scale_x._y;
+ sy1:=m_scale_y._y;
+
+// Calculate transformed coordinates at x2,y2
+ xt:=xe;
+ yt:=ye;
+
+ m_trans_dir.transform(@m_trans_dir ,@xt ,@yt );
+
+ x2:=trunc(xt * subpixel_size );
+ y2:=trunc(yt * subpixel_size );
+
+ delta:=1 / subpixel_size;
+
+// Calculate scale by X at x2,y2
+ dx:=xt + delta;
+ dy:=yt;
+
+ m_trans_inv.transform(@m_trans_inv ,@dx ,@dy );
+
+ dx :=dx - xe;
+ dy :=dy - ye;
+ sx2:=shr_int32(trunc(subpixel_size / Sqrt(dx * dx + dy * dy ) ) ,subpixel_shift );
+
+// Calculate scale by Y at x2,y2
+ dx:=xt;
+ dy:=yt + delta;
+
+ m_trans_inv.transform(@m_trans_inv ,@dx ,@dy );
+
+ dx :=dx - xe;
+ dy :=dy - ye;
+ sy2:=shr_int32(trunc(subpixel_size / Sqrt(dx * dx + dy * dy ) ) ,subpixel_shift );
+
+// Initialize the interpolators
+ m_coord_x.Construct(x1 ,x2 ,len );
+ m_coord_y.Construct(y1 ,y2 ,len );
+ m_scale_x.Construct(sx1 ,sx2 ,len );
+ m_scale_y.Construct(sy1 ,sy2 ,len );
+
+end;
+
+{ INC_OPERATOR }
+procedure span_interpolator_persp_lerp.inc_operator;
+begin
+ m_coord_x.plus_operator;
+ m_coord_y.plus_operator;
+ m_scale_x.plus_operator;
+ m_scale_y.plus_operator;
+
+end;
+
+{ COORDINATES }
+procedure span_interpolator_persp_lerp.coordinates;
+begin
+ x^:=m_coord_x._y;
+ y^:=m_coord_y._y;
+
+end;
+
+{ LOCAL_SCALE }
+procedure span_interpolator_persp_lerp.local_scale;
+begin
+ x^:=m_scale_x._y;
+ y^:=m_scale_y._y;
+
+end;
+
+{ TRANSFORM }
+procedure span_interpolator_persp_lerp.transform;
+begin
+ m_trans_dir.transform(@m_trans_dir ,x ,y );
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_span_interpolator_trans.pas b/src/corelib/render/software/agg_span_interpolator_trans.pas
new file mode 100644
index 00000000..c6ddb84b
--- /dev/null
+++ b/src/corelib/render/software/agg_span_interpolator_trans.pas
@@ -0,0 +1,157 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// Horizontal span interpolator for use with an arbitrary transformer
+// The efficiency highly depends on the operations done in the transformer
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 05.03.2006-Milano: Unit port establishment
+//
+{ agg_span_interpolator_trans.pas }
+unit
+ agg_span_interpolator_trans ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+{$Q- }
+{$R- }
+uses
+ agg_basics ,
+ agg_trans_affine ,
+ agg_span_interpolator_linear ;
+
+{ TYPES DEFINITION }
+type
+ span_interpolator_trans = object(span_interpolator )
+ m_trans : trans_affine_ptr;
+
+ m_x ,
+ m_y : double;
+ m_ix ,
+ m_iy : int;
+
+ constructor Construct(SS : unsigned = 8 ); overload;
+ constructor Construct(trans : trans_affine_ptr; SS : unsigned = 8 ); overload;
+ constructor Construct(trans : trans_affine_ptr; x ,y ,z : unsigned; SS : unsigned = 8 ); overload;
+
+ function _transformer : trans_affine_ptr; virtual;
+ procedure transformer_(trans : trans_affine_ptr ); virtual;
+
+ procedure begin_(x ,y : double; len : unsigned ); virtual;
+
+ procedure inc_operator; virtual;
+ procedure coordinates(x ,y : int_ptr ); virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor span_interpolator_trans.Construct(SS : unsigned = 8 );
+begin
+ inherited Construct(SS );
+
+ m_trans:=NIL;
+
+end;
+
+{ CONSTRUCT }
+constructor span_interpolator_trans.Construct(trans : trans_affine_ptr; SS : unsigned = 8 );
+begin
+ inherited Construct(SS );
+
+ m_trans:=trans;
+
+end;
+
+{ CONSTRUCT }
+constructor span_interpolator_trans.Construct(trans : trans_affine_ptr; x ,y ,z : unsigned; SS : unsigned = 8 );
+begin
+ inherited Construct(SS );
+
+ m_trans:=trans;
+
+ begin_(x ,y ,0 );
+
+end;
+
+{ _TRANSFORMER }
+function span_interpolator_trans._transformer;
+begin
+ result:=m_trans;
+
+end;
+
+{ TRANSFORMER_ }
+procedure span_interpolator_trans.transformer_;
+begin
+ m_trans:=trans;
+
+end;
+
+{ BEGIN_ }
+procedure span_interpolator_trans.begin_;
+begin
+ m_x:=x;
+ m_y:=y;
+
+ m_trans.transform(m_trans ,@x ,@y );
+
+ m_ix:=iround(x * subpixel_size );
+ m_iy:=iround(y * subpixel_size );
+
+end;
+
+{ INC_OPERATOR }
+procedure span_interpolator_trans.inc_operator;
+var
+ x ,y : double;
+
+begin
+ m_x:=m_x + 1.0;
+
+ x:=m_x;
+ y:=m_y;
+
+ m_trans.transform(m_trans ,@x ,@y );
+
+ m_ix:=iround(x * subpixel_size );
+ m_iy:=iround(y * subpixel_size );
+
+end;
+
+{ COORDINATES }
+procedure span_interpolator_trans.coordinates;
+begin
+ x^:=m_ix;
+ y^:=m_iy;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_span_pattern.pas b/src/corelib/render/software/agg_span_pattern.pas
new file mode 100644
index 00000000..194a51dc
--- /dev/null
+++ b/src/corelib/render/software/agg_span_pattern.pas
@@ -0,0 +1,501 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// Adaptation for high precision colors has been sponsored by
+// Liberty Technology Systems, Inc., visit http://lib-sys.com
+//
+// Liberty Technology Systems, Inc. is the provider of
+// PostScript and PDF technology for software developers.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 28.02.2006-Milano: Unit port establishment
+//
+{ agg_span_pattern.pas }
+unit
+ agg_span_pattern ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+{$Q- }
+{$R- }
+
+uses
+ agg_basics ,
+ agg_color ,
+ agg_rendering_buffer ,
+ agg_span_generator ,
+ agg_span_allocator ;
+
+{ TYPES DEFINITION }
+const
+ base_mask = agg_color.base_mask;
+
+type
+ span_pattern_base = object(span_generator )
+ m_src : rendering_buffer_ptr;
+ m_offset_x ,
+ m_offset_y : unsigned;
+ m_alpha : int8u;
+
+ constructor Construct(alloc : span_allocator_ptr ); overload;
+ constructor Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ offset_x ,offset_y : unsigned;
+ alpha : double ); overload;
+
+ function _source_image : rendering_buffer_ptr;
+ function _offset_x : unsigned;
+ function _offset_y : unsigned;
+ function _alpha : double;
+ function _alpha_int : int8u;
+
+ procedure source_image_(v : rendering_buffer_ptr );
+
+ procedure offset_x_(v : unsigned );
+ procedure offset_y_(v : unsigned );
+ procedure alpha_ (v : double );
+
+ end;
+
+ wrap_mode_ptr = ^wrap_mode;
+ wrap_mode = object
+ constructor Construct;
+
+ procedure init(size : unsigned ); virtual; abstract;
+
+ function func_operator(v : int ) : unsigned; virtual; abstract;
+ function inc_operator : unsigned; virtual; abstract;
+
+ end;
+
+ wrap_mode_repeat = object(wrap_mode )
+ m_size ,
+ m_add ,
+ m_value : unsigned;
+
+ procedure init(size : unsigned ); virtual;
+
+ function func_operator(v : int ) : unsigned; virtual;
+ function inc_operator : unsigned; virtual;
+
+ end;
+
+ wrap_mode_repeat_pow2 = object(wrap_mode )
+ m_mask ,
+ m_value : unsigned;
+
+ procedure init(size : unsigned ); virtual;
+
+ function func_operator(v : int ) : unsigned; virtual;
+ function inc_operator : unsigned; virtual;
+
+ end;
+
+ wrap_mode_repeat_auto_pow2 = object(wrap_mode )
+ m_size ,
+ m_add ,
+ m_mask ,
+ m_value : unsigned;
+
+ procedure init(size : unsigned ); virtual;
+
+ function func_operator(v : int ) : unsigned; virtual;
+ function inc_operator : unsigned; virtual;
+
+ end;
+
+ wrap_mode_reflect = object(wrap_mode )
+ m_size ,
+ m_size2 ,
+ m_add ,
+ m_value : unsigned;
+
+ procedure init(size : unsigned ); virtual;
+
+ function func_operator(v : int ) : unsigned; virtual;
+ function inc_operator : unsigned; virtual;
+
+ end;
+
+ wrap_mode_reflect_pow2 = object(wrap_mode )
+ m_size ,
+ m_mask ,
+ m_value : unsigned;
+
+ procedure init(size : unsigned ); virtual;
+
+ function func_operator(v : int ) : unsigned; virtual;
+ function inc_operator : unsigned; virtual;
+
+ end;
+
+ wrap_mode_reflect_auto_pow2 = object(wrap_mode )
+ m_size ,
+ m_size2 ,
+ m_add ,
+ m_mask ,
+ m_value : unsigned;
+
+ procedure init(size : unsigned ); virtual;
+
+ function func_operator(v : int ) : unsigned; virtual;
+ function inc_operator : unsigned; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor span_pattern_base.Construct(alloc : span_allocator_ptr );
+begin
+ inherited Construct(alloc );
+
+ m_src :=NIL;
+ m_offset_x:=0;
+ m_offset_y:=0;
+ m_alpha :=0;
+
+end;
+
+{ CONSTRUCT }
+constructor span_pattern_base.Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ offset_x ,offset_y : unsigned;
+ alpha : double );
+begin
+ inherited Construct(alloc );
+
+ m_src :=src;
+ m_offset_x:=offset_x;
+ m_offset_y:=offset_y;
+ m_alpha :=int8u(trunc(alpha * base_mask ) );
+
+end;
+
+{ _SOURCE_IMAGE }
+function span_pattern_base._source_image;
+begin
+ result:=m_src;
+
+end;
+
+{ _OFFSET_X }
+function span_pattern_base._offset_x;
+begin
+ result:=m_offset_x;
+
+end;
+
+{ _OFFSET_Y }
+function span_pattern_base._offset_y;
+begin
+ result:=m_offset_y;
+
+end;
+
+{ _ALPHA }
+function span_pattern_base._alpha;
+begin
+ result:=m_alpha / base_mask;
+
+end;
+
+{ _ALPHA_INT }
+function span_pattern_base._alpha_int;
+begin
+ result:=m_alpha;
+
+end;
+
+{ SOURCE_IMAGE_ }
+procedure span_pattern_base.source_image_;
+begin
+ m_src:=v;
+
+end;
+
+{ OFFSET_X_ }
+procedure span_pattern_base.offset_x_;
+begin
+ m_offset_x:=v;
+
+end;
+
+{ OFFSET_Y_ }
+procedure span_pattern_base.offset_y_;
+begin
+ m_offset_y:=v;
+
+end;
+
+{ ALPHA_ }
+procedure span_pattern_base.alpha_;
+begin
+ m_alpha:=int8u(trunc(v * base_mask ) );
+
+end;
+
+{ CONSTRUCT }
+constructor wrap_mode.Construct;
+begin
+end;
+
+{ INIT }
+procedure wrap_mode_repeat.init;
+begin
+ m_size :=size;
+ m_add :=size * ($3FFFFFFF div size );
+ m_value:=0;
+
+end;
+
+{ FUNC_OPERATOR }
+function wrap_mode_repeat.func_operator;
+begin
+ m_value:=(unsigned(v ) + m_add ) mod m_size;
+ result :=m_value;
+
+end;
+
+{ INC_OPERATOR }
+function wrap_mode_repeat.inc_operator;
+begin
+ inc(m_value );
+
+ if m_value >= m_size then
+ m_value:=0;
+
+ result:=m_value;
+
+end;
+
+{ INIT }
+procedure wrap_mode_repeat_pow2.init;
+begin
+ m_mask:=1;
+
+ while m_mask < size do
+ m_mask:=(m_mask shl 1 ) or 1;
+
+ m_mask:=m_mask shr 1;
+
+end;
+
+{ FUNC_OPERATOR }
+function wrap_mode_repeat_pow2.func_operator;
+begin
+ m_value:=unsigned(v ) and m_mask;
+ result :=m_value;
+
+end;
+
+{ INC_OPERATOR }
+function wrap_mode_repeat_pow2.inc_operator;
+begin
+ inc(m_value );
+
+ if m_value > m_mask then
+ m_value:=0;
+
+ result:=m_value;
+
+end;
+
+{ INIT }
+procedure wrap_mode_repeat_auto_pow2.init;
+begin
+ m_size:=size;
+ m_add :=size * ($3FFFFFFF div size );
+
+ if m_size and (m_size - 1 ) <> 0 then
+ m_mask:=0
+ else
+ m_mask:=m_size - 1;
+
+ m_value:=0;
+
+end;
+
+{ FUNC_OPERATOR }
+function wrap_mode_repeat_auto_pow2.func_operator;
+begin
+ if m_mask <> 0 then
+ begin
+ m_value:=unsigned(unsigned(v ) and m_mask );
+ result :=m_value;
+
+ end
+ else
+ begin
+ m_value:=unsigned((unsigned(v ) + m_add ) mod m_size );
+ result :=m_value;
+
+ end;
+
+end;
+
+{ INC_OPERATOR }
+function wrap_mode_repeat_auto_pow2.inc_operator;
+begin
+ inc(m_value );
+
+ if m_value >= m_size then
+ m_value:=0;
+
+ result:=m_value;
+
+end;
+
+{ INIT }
+procedure wrap_mode_reflect.init;
+begin
+ m_size :=size;
+ m_size2:=size * 2;
+ m_add :=m_size2 * ($3FFFFFFF div m_size2 );
+ m_value:=0;
+
+end;
+
+{ FUNC_OPERATOR }
+function wrap_mode_reflect.func_operator;
+begin
+ m_value:=(unsigned(v ) + m_add ) mod m_size2;
+
+ if m_value >= m_size then
+ result:=m_size2 - m_value - 1
+ else
+ result:=m_value;
+
+end;
+
+{ INC_OPERATOR }
+function wrap_mode_reflect.inc_operator;
+begin
+ inc(m_value );
+
+ if m_value >= m_size2 then
+ m_value:=0;
+
+ if m_value >= m_size then
+ result:=m_size2 - m_value - 1
+ else
+ result:=m_value;
+
+end;
+
+{ INIT }
+procedure wrap_mode_reflect_pow2.init;
+begin
+ m_mask:=1;
+ m_size:=1;
+
+ while m_mask < size do
+ begin
+ m_mask:=(m_mask shl 1 ) or 1;
+ m_size:=m_size shl 1;
+
+ end;
+
+end;
+
+{ FUNC_OPERATOR }
+function wrap_mode_reflect_pow2.func_operator;
+begin
+ m_value:=unsigned(v ) and m_mask;
+
+ if m_value >= m_size then
+ result:=m_mask - m_value
+ else
+ result:=m_value;
+
+end;
+
+{ INC_OPERATOR }
+function wrap_mode_reflect_pow2.inc_operator;
+begin
+ inc(m_value );
+
+ m_value:=m_value and m_mask;
+
+ if m_value >= m_size then
+ result:=m_mask - m_value
+ else
+ result:=m_value;
+
+end;
+
+{ INIT }
+procedure wrap_mode_reflect_auto_pow2.init;
+begin
+ m_size :=size;
+ m_size2:=size * 2;
+ m_add :=m_size2 * ($3FFFFFFF div m_size2 );
+
+ if m_size2 and (m_size2 - 1 ) <> 0 then
+ m_mask:=0
+ else
+ m_mask:=m_size2 - 1;
+
+ m_value:=0;
+
+end;
+
+{ FUNC_OPERATOR }
+function wrap_mode_reflect_auto_pow2.func_operator;
+begin
+ if m_mask <> 0 then
+ m_value:=unsigned(v ) and m_mask
+ else
+ m_value:=(unsigned(v ) + m_add ) mod m_size2;
+
+ if m_value >= m_size then
+ result:=m_size2 - m_value - 1
+ else
+ result:=m_value;
+
+end;
+
+{ INC_OPERATOR }
+function wrap_mode_reflect_auto_pow2.inc_operator;
+begin
+ inc(m_value );
+
+ if m_value >= m_size2 then
+ m_value:=0;
+
+ if m_value >= m_size then
+ result:=m_size2 - m_value - 1
+ else
+ result:=m_value;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_span_pattern_filter_gray.pas b/src/corelib/render/software/agg_span_pattern_filter_gray.pas
new file mode 100644
index 00000000..645153b8
--- /dev/null
+++ b/src/corelib/render/software/agg_span_pattern_filter_gray.pas
@@ -0,0 +1,599 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// classes span_pattern_filter_gray*
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 06.03.2006-Milano: Unit port establishment
+//
+{ agg_span_pattern_filter_gray.pas {untested}
+unit
+ agg_span_pattern_filter_gray ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+{$Q- }
+{$R- }
+uses
+ agg_basics ,
+ agg_color ,
+ agg_span_pattern ,
+ agg_span_image_filter ,
+ agg_span_interpolator_linear ,
+ agg_rendering_buffer ,
+ agg_span_allocator ,
+ agg_image_filters ;
+
+{ TYPES DEFINITION }
+const
+ base_shift = agg_color.base_shift;
+ base_mask = agg_color.base_mask;
+
+type
+ span_pattern_filter_gray_nn_ptr = ^span_pattern_filter_gray_nn;
+ span_pattern_filter_gray_nn = object(span_image_filter )
+ m_wrap_mode_x ,
+ m_wrap_mode_y : wrap_mode_ptr;
+
+ constructor Construct(alloc : span_allocator_ptr; WX ,WY : wrap_mode_ptr ); overload;
+ constructor Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ interpolator : span_interpolator_ptr;
+ WX ,WY : wrap_mode_ptr ); overload;
+
+ procedure source_image_(src : rendering_buffer_ptr );
+
+ function generate(x ,y : int; len : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+ span_pattern_filter_gray_bilinear_ptr = ^span_pattern_filter_gray_bilinear;
+ span_pattern_filter_gray_bilinear = object(span_image_filter )
+ m_wrap_mode_x ,
+ m_wrap_mode_y : wrap_mode_ptr;
+
+ constructor Construct(alloc : span_allocator_ptr; WX ,WY : wrap_mode_ptr ); overload;
+ constructor Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ interpolator : span_interpolator_ptr;
+ WX ,WY : wrap_mode_ptr ); overload;
+
+ procedure source_image_(src : rendering_buffer_ptr );
+
+ function generate(x ,y : int; len : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+ span_pattern_filter_gray_2x2_ptr = ^span_pattern_filter_gray_2x2;
+ span_pattern_filter_gray_2x2 = object(span_image_filter )
+ m_wrap_mode_x ,
+ m_wrap_mode_y : wrap_mode_ptr;
+
+ constructor Construct(alloc : span_allocator_ptr; WX ,WY : wrap_mode_ptr ); overload;
+ constructor Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ interpolator : span_interpolator_ptr;
+ filter : image_filter_lut_ptr;
+ WX ,WY : wrap_mode_ptr ); overload;
+
+ procedure source_image_(src : rendering_buffer_ptr );
+
+ function generate(x ,y : int; len : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+ span_pattern_filter_gray_ptr = ^span_pattern_filter_gray;
+ span_pattern_filter_gray = object(span_image_filter )
+ m_wrap_mode_x ,
+ m_wrap_mode_y : wrap_mode_ptr;
+
+ constructor Construct(alloc : span_allocator_ptr; WX ,WY : wrap_mode_ptr ); overload;
+ constructor Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ interpolator : span_interpolator_ptr;
+ filter : image_filter_lut_ptr;
+ WX ,WY : wrap_mode_ptr ); overload;
+
+ procedure source_image_(src : rendering_buffer_ptr );
+
+ function generate(x ,y : int; len : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor span_pattern_filter_gray_nn.Construct(alloc : span_allocator_ptr; WX ,WY : wrap_mode_ptr );
+begin
+ inherited Construct(alloc );
+
+ m_wrap_mode_x:=WX;
+ m_wrap_mode_y:=WY;
+
+ m_wrap_mode_x.init(1 );
+ m_wrap_mode_y.init(1 );
+
+end;
+
+{ CONSTRUCT }
+constructor span_pattern_filter_gray_nn.Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ interpolator : span_interpolator_ptr;
+ WX ,WY : wrap_mode_ptr );
+var
+ rgba : aggclr;
+
+begin
+ rgba.ConstrInt(0 ,0 );
+
+ inherited Construct(alloc ,src ,@rgba ,interpolator ,NIL );
+
+ m_wrap_mode_x:=WX;
+ m_wrap_mode_y:=WY;
+
+ m_wrap_mode_x.init(src._width );
+ m_wrap_mode_y.init(src._height );
+
+end;
+
+{ SOURCE_IMAGE_ }
+procedure span_pattern_filter_gray_nn.source_image_;
+begin
+ inherited source_image_(src );
+
+ m_wrap_mode_x.init(src._width );
+ m_wrap_mode_y.init(src._height );
+
+end;
+
+{ GENERATE }
+function span_pattern_filter_gray_nn.generate;
+var
+ span : aggclr_ptr;
+
+begin
+ _interpolator.begin_(x + filter_dx_dbl ,y + filter_dy_dbl ,len );
+
+ span:=_allocator.span;
+
+ repeat
+ _interpolator.coordinates(@x ,@y );
+
+ x:=m_wrap_mode_x.func_operator(shr_int32(x ,image_subpixel_shift ) );
+ y:=m_wrap_mode_y.func_operator(shr_int32(y ,image_subpixel_shift ) );
+
+ span.v:=int8u_ptr(ptrcomp(_source_image.row(y ) ) + x * sizeof(int8u ) )^;
+ span.a:=base_mask;
+
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+
+ _interpolator.inc_operator;
+
+ dec(len );
+
+ until len = 0;
+
+ result:=_allocator.span;
+
+end;
+
+{ CONSTRUCT }
+constructor span_pattern_filter_gray_bilinear.Construct(alloc : span_allocator_ptr; WX ,WY : wrap_mode_ptr );
+begin
+ inherited Construct(alloc );
+
+ m_wrap_mode_x:=WX;
+ m_wrap_mode_y:=WY;
+
+ m_wrap_mode_x.init(1 );
+ m_wrap_mode_y.init(1 );
+
+end;
+
+{ CONSTRUCT }
+constructor span_pattern_filter_gray_bilinear.Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ interpolator : span_interpolator_ptr;
+ WX ,WY : wrap_mode_ptr );
+var
+ rgba : aggclr;
+
+begin
+ rgba.ConstrInt(0 ,0 );
+
+ inherited Construct(alloc ,src ,@rgba ,interpolator ,NIL );
+
+ m_wrap_mode_x:=WX;
+ m_wrap_mode_y:=WY;
+
+ m_wrap_mode_x.init(src._width );
+ m_wrap_mode_y.init(src._height );
+
+end;
+
+{ SOURCE_IMAGE_ }
+procedure span_pattern_filter_gray_bilinear.source_image_;
+begin
+ inherited source_image_(src );
+
+ m_wrap_mode_x.init(src._width );
+ m_wrap_mode_y.init(src._height );
+
+end;
+
+{ GENERATE }
+function span_pattern_filter_gray_bilinear.generate;
+var
+ fg ,x1 ,x2 ,y1 ,y2 : unsigned;
+
+ x_hr ,y_hr ,x_lr ,y_lr : int;
+
+ span : aggclr_ptr;
+
+ ptr1 ,ptr2 : int8u_ptr;
+
+begin
+ _interpolator.begin_(x + filter_dx_dbl ,y + filter_dy_dbl ,len );
+
+ span:=_allocator.span;
+
+ repeat
+ _interpolator.coordinates(@x_hr ,@y_hr );
+
+ dec(x_hr ,filter_dx_int );
+ dec(y_hr ,filter_dy_int );
+
+ x_lr:=shr_int32(x_hr ,image_subpixel_shift );
+ y_lr:=shr_int32(y_hr ,image_subpixel_shift );
+
+ x1:=m_wrap_mode_x.func_operator(x_lr );
+ x2:=m_wrap_mode_x.inc_operator;
+
+ y1:=m_wrap_mode_y.func_operator(y_lr );
+ y2:=m_wrap_mode_y.inc_operator;
+
+ ptr1:=_source_image.row(y1 );
+ ptr2:=_source_image.row(y2 );
+
+ fg:=image_subpixel_size * image_subpixel_size div 2;
+
+ x_hr:=x_hr and image_subpixel_mask;
+ y_hr:=y_hr and image_subpixel_mask;
+
+ inc(fg ,int8u_ptr(ptrcomp(ptr1 ) + x1 * sizeof(int8u ) )^ * (image_subpixel_size - x_hr ) * (image_subpixel_size - y_hr ) );
+ inc(fg ,int8u_ptr(ptrcomp(ptr1 ) + x2 * sizeof(int8u ) )^ * x_hr * (image_subpixel_size - y_hr ) );
+ inc(fg ,int8u_ptr(ptrcomp(ptr2 ) + x1 * sizeof(int8u ) )^ * (image_subpixel_size - x_hr ) * y_hr );
+ inc(fg ,int8u_ptr(ptrcomp(ptr2 ) + x2 * sizeof(int8u ) )^ * x_hr * y_hr );
+
+ span.v:=int8u(fg shr (image_subpixel_shift * 2 ) );
+ span.a:=base_mask;
+
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+
+ _interpolator.inc_operator;
+
+ dec(len );
+
+ until len = 0;
+
+ result:=_allocator.span;
+
+end;
+
+{ CONSTRUCT }
+constructor span_pattern_filter_gray_2x2.Construct(alloc : span_allocator_ptr; WX ,WY : wrap_mode_ptr );
+begin
+ inherited Construct(alloc );
+
+ m_wrap_mode_x:=WX;
+ m_wrap_mode_y:=WY;
+
+ m_wrap_mode_x.init(1 );
+ m_wrap_mode_y.init(1 );
+
+end;
+
+{ CONSTRUCT }
+constructor span_pattern_filter_gray_2x2.Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ interpolator : span_interpolator_ptr;
+ filter : image_filter_lut_ptr;
+ WX ,WY : wrap_mode_ptr );
+var
+ rgba : aggclr;
+
+begin
+ rgba.ConstrInt(0 ,0 );
+
+ inherited Construct(alloc ,src ,@rgba ,interpolator ,filter );
+
+ m_wrap_mode_x:=WX;
+ m_wrap_mode_y:=WY;
+
+ m_wrap_mode_x.init(src._width );
+ m_wrap_mode_y.init(src._height );
+
+end;
+
+{ SOURCE_IMAGE_ }
+procedure span_pattern_filter_gray_2x2.source_image_;
+begin
+ inherited source_image_(src );
+
+ m_wrap_mode_x.init(src._width );
+ m_wrap_mode_y.init(src._height );
+
+end;
+
+{ GENERATE }
+function span_pattern_filter_gray_2x2.generate;
+var
+ fg ,x1 ,x2 ,y1 ,y2 : unsigned;
+
+ x_hr ,y_hr ,x_lr ,y_lr : int;
+
+ ptr1 ,ptr2 : int8u_ptr;
+
+ span : aggclr_ptr;
+
+ weight_array : int16_ptr;
+
+begin
+ _interpolator.begin_(x + filter_dx_dbl ,y + filter_dy_dbl ,len );
+
+ span:=_allocator.span;
+
+ weight_array:=
+ int16_ptr(
+ ptrcomp(_filter.weight_array ) +
+ shr_int32(_filter.diameter div 2 - 1 ,image_subpixel_shift ) );
+
+ repeat
+ _interpolator.coordinates(@x_hr ,@y_hr );
+
+ inc(x_hr ,filter_dx_int );
+ inc(y_hr ,filter_dy_int );
+
+ x_lr:=shr_int32(x_hr ,image_subpixel_shift );
+ y_lr:=shr_int32(y_hr ,image_subpixel_shift );
+
+ x1:=m_wrap_mode_x.func_operator(x_lr );
+ x2:=m_wrap_mode_x.inc_operator;
+
+ y1:=m_wrap_mode_y.func_operator(y_lr );
+ y2:=m_wrap_mode_y.inc_operator;
+
+ ptr1:=_source_image.row(y1 );
+ ptr2:=_source_image.row(y2 );
+
+ fg:=image_filter_size div 2;
+
+ x_hr:=x_hr and image_subpixel_mask;
+ y_hr:=y_hr and image_subpixel_mask;
+
+ inc(fg ,
+ int8u_ptr(ptrcomp(ptr1 ) + x1 * sizeof(int8u ) )^ *
+ shr_int32(
+ int16_ptr(ptrcomp(weight_array ) + (x_hr + image_subpixel_size ) * sizeof(int16 ) )^ *
+ int16_ptr(ptrcomp(weight_array ) + (y_hr + image_subpixel_size ) * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,image_filter_shift ) );
+
+ inc(fg ,
+ int8u_ptr(ptrcomp(ptr1 ) + x2 * sizeof(int8u ) )^ *
+ shr_int32(
+ int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ *
+ int16_ptr(ptrcomp(weight_array ) + (y_hr + image_subpixel_size ) * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,image_filter_shift ) );
+
+ inc(fg ,
+ int8u_ptr(ptrcomp(ptr2 ) + x1 * sizeof(int8u ) )^ *
+ shr_int32(
+ int16_ptr(ptrcomp(weight_array ) + (x_hr + image_subpixel_size ) * sizeof(int16 ) )^ *
+ int16_ptr(ptrcomp(weight_array ) + y_hr * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,image_filter_shift ) );
+
+ inc(fg ,
+ int8u_ptr(ptrcomp(ptr2 ) + x2 * sizeof(int8u ) )^ *
+ shr_int32(
+ int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ *
+ int16_ptr(ptrcomp(weight_array ) + y_hr * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,image_filter_shift ) );
+
+ fg:=fg shr image_filter_shift;
+
+ if fg > base_mask then
+ fg:=base_mask;
+
+ span.v:=int8u(fg );
+ span.a:=base_mask;
+
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+
+ _interpolator.inc_operator;
+
+ dec(len );
+
+ until len = 0;
+
+ result:=_allocator.span;
+
+end;
+
+{ CONSTRUCT }
+constructor span_pattern_filter_gray.Construct(alloc : span_allocator_ptr; WX ,WY : wrap_mode_ptr );
+begin
+ inherited Construct(alloc );
+
+ m_wrap_mode_x:=WX;
+ m_wrap_mode_y:=WY;
+
+ m_wrap_mode_x.init(1 );
+ m_wrap_mode_y.init(1 );
+
+end;
+
+{ CONSTRUCT }
+constructor span_pattern_filter_gray.Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ interpolator : span_interpolator_ptr;
+ filter : image_filter_lut_ptr;
+ WX ,WY : wrap_mode_ptr );
+var
+ rgba : aggclr;
+
+begin
+ rgba.ConstrInt(0 ,0 );
+
+ inherited Construct(alloc ,src ,@rgba ,interpolator ,filter );
+
+ m_wrap_mode_x:=WX;
+ m_wrap_mode_y:=WY;
+
+ m_wrap_mode_x.init(src._width );
+ m_wrap_mode_y.init(src._height );
+
+end;
+
+{ SOURCE_IMAGE_ }
+procedure span_pattern_filter_gray.source_image_;
+begin
+ inherited source_image_(src );
+
+ m_wrap_mode_x.init(src._width );
+ m_wrap_mode_y.init(src._height );
+
+end;
+
+{ GENERATE }
+function span_pattern_filter_gray.generate;
+var
+ fg ,start ,x_count ,weight_y ,x_hr ,y_hr ,x_fract ,y_lr ,x_int ,x_lr : int;
+
+ diameter ,y_count : unsigned;
+
+ row_ptr : int8u_ptr;
+
+ weight_array : int16_ptr;
+
+ span : aggclr_ptr;
+
+begin
+ _interpolator.begin_(x + filter_dx_dbl ,y + filter_dy_dbl ,len );
+
+ diameter:=_filter.diameter;
+ start :=_filter.start;
+
+ weight_array:=_filter.weight_array;
+
+ span:=_allocator.span;
+
+ repeat
+ _interpolator.coordinates(@x ,@y );
+
+ dec(x ,filter_dx_int );
+ dec(y ,filter_dy_int );
+
+ x_hr:=x;
+ y_hr:=y;
+
+ x_fract:=x_hr and image_subpixel_mask;
+ y_count:=diameter;
+
+ y_lr :=m_wrap_mode_y.func_operator(shr_int32(y ,image_subpixel_shift ) + start );
+ x_int:=shr_int32(x ,image_subpixel_shift ) + start;
+
+ y_hr:=image_subpixel_mask - (y_hr and image_subpixel_mask );
+ fg :=image_filter_size div 2;
+
+ repeat
+ x_count :=diameter;
+ weight_y:=int16_ptr(ptrcomp(weight_array ) + y_hr * sizeof(int16 ) )^;
+
+ x_hr:=image_subpixel_mask - x_fract;
+ x_lr:=m_wrap_mode_x.func_operator(x_int );
+
+ row_ptr:=_source_image.row(y_lr );
+
+ repeat
+ inc(fg ,
+ int8u_ptr(ptrcomp(row_ptr ) + x_lr * sizeof(int8u ) )^ *
+ shr_int32(
+ weight_y *
+ int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,image_filter_shift ) );
+
+ inc(x_hr ,image_subpixel_size );
+
+ x_lr:=m_wrap_mode_x.inc_operator;
+
+ dec(x_count );
+
+ until x_count = 0;
+
+ inc(y_hr ,image_subpixel_size );
+
+ y_lr:=m_wrap_mode_y.inc_operator;
+
+ dec(y_count );
+
+ until y_count = 0;
+
+ fg:=shr_int32(fg ,image_filter_shift );
+
+ if fg < 0 then
+ fg:=0;
+
+ if fg > base_mask then
+ fg:=base_mask;
+
+ span.v:=int8u(fg );
+ span.a:=base_mask;
+
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+
+ _interpolator.inc_operator;
+
+ dec(len );
+
+ until len = 0;
+
+ result:=_allocator.span;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_span_pattern_filter_rgb.pas b/src/corelib/render/software/agg_span_pattern_filter_rgb.pas
new file mode 100644
index 00000000..9f3fc6e3
--- /dev/null
+++ b/src/corelib/render/software/agg_span_pattern_filter_rgb.pas
@@ -0,0 +1,740 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// Adaptation for high precision colors has been sponsored by
+// Liberty Technology Systems, Inc., visit http://lib-sys.com
+//
+// Liberty Technology Systems, Inc. is the provider of
+// PostScript and PDF technology for software developers.
+//
+//----------------------------------------------------------------------------
+//
+// classes span_pattern_filter_rgb*
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 06.03.2006-Milano: Unit port establishment
+//
+{ agg_span_pattern_filter_rgb.pas }
+unit
+ agg_span_pattern_filter_rgb ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+{$Q- }
+{$R- }
+uses
+ agg_basics ,
+ agg_color ,
+ agg_span_pattern ,
+ agg_span_image_filter ,
+ agg_span_interpolator_linear ,
+ agg_rendering_buffer ,
+ agg_span_allocator ,
+ agg_image_filters ;
+
+{ TYPES DEFINITION }
+const
+ base_shift = agg_color.base_shift;
+ base_mask = agg_color.base_mask;
+
+type
+ span_pattern_filter_rgb_nn_ptr = ^span_pattern_filter_rgb_nn;
+ span_pattern_filter_rgb_nn = object(span_image_filter )
+ m_wrap_mode_x ,
+ m_wrap_mode_y : wrap_mode_ptr;
+
+ m_order : order_type;
+
+ constructor Construct(alloc : span_allocator_ptr; WX ,WY : wrap_mode_ptr; order : order_type ); overload;
+ constructor Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ interpolator : span_interpolator_ptr;
+ WX ,WY : wrap_mode_ptr;
+ order : order_type ); overload;
+
+ procedure source_image_(src : rendering_buffer_ptr );
+
+ function generate(x ,y : int; len : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+ span_pattern_filter_rgb_bilinear_ptr = ^span_pattern_filter_rgb_bilinear;
+ span_pattern_filter_rgb_bilinear = object(span_image_filter )
+ m_wrap_mode_x ,
+ m_wrap_mode_y : wrap_mode_ptr;
+
+ m_order : order_type;
+
+ constructor Construct(alloc : span_allocator_ptr; WX ,WY : wrap_mode_ptr; order : order_type ); overload;
+ constructor Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ interpolator : span_interpolator_ptr;
+ WX ,WY : wrap_mode_ptr;
+ order : order_type ); overload;
+
+ procedure source_image_(src : rendering_buffer_ptr );
+
+ function generate(x ,y : int; len : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+ span_pattern_filter_rgb_2x2_ptr = ^span_pattern_filter_rgb_2x2;
+ span_pattern_filter_rgb_2x2 = object(span_image_filter )
+ m_wrap_mode_x ,
+ m_wrap_mode_y : wrap_mode_ptr;
+
+ m_order : order_type;
+
+ constructor Construct(alloc : span_allocator_ptr; WX ,WY : wrap_mode_ptr; order : order_type ); overload;
+ constructor Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ interpolator : span_interpolator_ptr;
+ filter : image_filter_lut_ptr;
+ WX ,WY : wrap_mode_ptr;
+ order : order_type ); overload;
+
+ procedure source_image_(src : rendering_buffer_ptr );
+
+ function generate(x ,y : int; len : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+ span_pattern_filter_rgb_ptr = ^span_pattern_filter_rgb;
+ span_pattern_filter_rgb = object(span_image_filter )
+ m_wrap_mode_x ,
+ m_wrap_mode_y : wrap_mode_ptr;
+
+ m_order : order_type;
+
+ constructor Construct(alloc : span_allocator_ptr; WX ,WY : wrap_mode_ptr; order : order_type ); overload;
+ constructor Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ interpolator : span_interpolator_ptr;
+ filter : image_filter_lut_ptr;
+ WX ,WY : wrap_mode_ptr;
+ order : order_type ); overload;
+
+ procedure source_image_(src : rendering_buffer_ptr );
+
+ function generate(x ,y : int; len : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor span_pattern_filter_rgb_nn.Construct(alloc : span_allocator_ptr; WX ,WY : wrap_mode_ptr; order : order_type );
+begin
+ inherited Construct(alloc );
+
+ m_order:=order;
+
+ m_wrap_mode_x:=WX;
+ m_wrap_mode_y:=WY;
+
+ m_wrap_mode_x.init(1 );
+ m_wrap_mode_y.init(1 );
+
+end;
+
+{ CONSTRUCT }
+constructor span_pattern_filter_rgb_nn.Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ interpolator : span_interpolator_ptr;
+ WX ,WY : wrap_mode_ptr;
+ order : order_type );
+var
+ rgba : aggclr;
+
+begin
+ rgba.ConstrInt(0 ,0 ,0 ,0 );
+
+ inherited Construct(alloc ,src ,@rgba ,interpolator ,NIL );
+
+ m_order:=order;
+
+ m_wrap_mode_x:=WX;
+ m_wrap_mode_y:=WY;
+
+ m_wrap_mode_x.init(src._width );
+ m_wrap_mode_y.init(src._height );
+
+end;
+
+{ SOURCE_IMAGE_ }
+procedure span_pattern_filter_rgb_nn.source_image_;
+begin
+ inherited source_image_(src );
+
+ m_wrap_mode_x.init(src._width );
+ m_wrap_mode_y.init(src._height );
+
+end;
+
+{ GENERATE }
+function span_pattern_filter_rgb_nn.generate;
+var
+ span : aggclr_ptr;
+ intr : span_interpolator_ptr;
+
+ fg_ptr : int8u_ptr;
+
+begin
+ span:=_allocator.span;
+ intr:=_interpolator;
+
+ intr.begin_(x + filter_dx_dbl ,y + filter_dy_dbl ,len );
+
+ repeat
+ intr.coordinates(@x ,@y );
+
+ x:=m_wrap_mode_x.func_operator(shr_int32(x ,image_subpixel_shift ) );
+ y:=m_wrap_mode_y.func_operator(shr_int32(y ,image_subpixel_shift ) );
+
+ fg_ptr:=int8u_ptr(ptrcomp(_source_image.row(y ) ) + x * 3 * sizeof(int8u ) );
+
+ span.r:=int8u_ptr(ptrcomp(fg_ptr ) + m_order.R * sizeof(int8u ) )^;
+ span.g:=int8u_ptr(ptrcomp(fg_ptr ) + m_order.G * sizeof(int8u ) )^;
+ span.b:=int8u_ptr(ptrcomp(fg_ptr ) + m_order.B * sizeof(int8u ) )^;
+ span.a:=base_mask;
+
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+
+ intr.inc_operator;
+
+ dec(len );
+
+ until len = 0;
+
+ result:=_allocator.span;
+
+end;
+
+{ CONSTRUCT }
+constructor span_pattern_filter_rgb_bilinear.Construct(alloc : span_allocator_ptr; WX ,WY : wrap_mode_ptr; order : order_type );
+begin
+ inherited Construct(alloc );
+
+ m_order:=order;
+
+ m_wrap_mode_x:=WX;
+ m_wrap_mode_y:=WY;
+
+ m_wrap_mode_x.init(1 );
+ m_wrap_mode_y.init(1 );
+
+end;
+
+{ CONSTRUCT }
+constructor span_pattern_filter_rgb_bilinear.Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ interpolator : span_interpolator_ptr;
+ WX ,WY : wrap_mode_ptr;
+ order : order_type );
+var
+ rgba : aggclr;
+
+begin
+ rgba.ConstrInt(0 ,0 ,0 ,0 );
+
+ inherited Construct(alloc ,src ,@rgba ,interpolator ,NIL );
+
+ m_order:=order;
+
+ m_wrap_mode_x:=WX;
+ m_wrap_mode_y:=WY;
+
+ m_wrap_mode_x.init(src._width );
+ m_wrap_mode_y.init(src._height );
+
+end;
+
+{ SOURCE_IMAGE_ }
+procedure span_pattern_filter_rgb_bilinear.source_image_;
+begin
+ inherited source_image_(src );
+
+ m_wrap_mode_x.init(src._width );
+ m_wrap_mode_y.init(src._height );
+
+end;
+
+{ GENERATE }
+function span_pattern_filter_rgb_bilinear.generate;
+var
+ span : aggclr_ptr;
+ intr : span_interpolator_ptr;
+
+ fg : array[0..2 ] of unsigned;
+
+ fg_ptr ,ptr1 ,ptr2 : int8u_ptr;
+
+ x_hr ,y_hr ,x_lr ,y_lr ,weight : int;
+
+ x1 ,x2 ,y1 ,y2 : unsigned;
+
+begin
+ span:=_allocator.span;
+ intr:=_interpolator;
+
+ intr.begin_(x + filter_dx_dbl ,y + filter_dy_dbl ,len );
+
+ repeat
+ intr.coordinates(@x_hr ,@y_hr );
+
+ dec(x_hr ,filter_dx_int );
+ dec(y_hr ,filter_dy_int );
+
+ x_lr:=shr_int32(x_hr ,image_subpixel_shift );
+ y_lr:=shr_int32(y_hr ,image_subpixel_shift );
+
+ x1:=m_wrap_mode_x.func_operator(x_lr);
+ x2:=m_wrap_mode_x.inc_operator;
+
+ x1:=x1 * 3;
+ x2:=x2 * 3;
+
+ y1:=m_wrap_mode_y.func_operator(y_lr );
+ y2:=m_wrap_mode_y.inc_operator;
+
+ ptr1:=_source_image.row(y1 );
+ ptr2:=_source_image.row(y2 );
+
+ fg[0 ]:=image_subpixel_size * image_subpixel_size div 2;
+ fg[1 ]:=fg[0 ];
+ fg[2 ]:=fg[0 ];
+
+ x_hr:=x_hr and image_subpixel_mask;
+ y_hr:=y_hr and image_subpixel_mask;
+
+ fg_ptr:=int8u_ptr(ptrcomp(ptr1 ) + x1 * sizeof(int8u ) );
+ weight:=(image_subpixel_size - x_hr ) * (image_subpixel_size - y_hr );
+
+ inc(fg[0 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,weight * fg_ptr^ );
+
+ fg_ptr:=int8u_ptr(ptrcomp(ptr1 ) + x2 * sizeof(int8u ) );
+ weight:=x_hr * (image_subpixel_size - y_hr );
+
+ inc(fg[0 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,weight * fg_ptr^ );
+
+ fg_ptr:=int8u_ptr(ptrcomp(ptr2 ) + x1 * sizeof(int8u ) );
+ weight:=(image_subpixel_size - x_hr ) * y_hr;
+
+ inc(fg[0 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,weight * fg_ptr^ );
+
+ fg_ptr:=int8u_ptr(ptrcomp(ptr2 ) + x2 * sizeof(int8u ) );
+ weight:=x_hr * y_hr;
+
+ inc(fg[0 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,weight * fg_ptr^ );
+
+ span.r:=int8u(fg[m_order.R ] shr (image_subpixel_shift * 2 ) );
+ span.g:=int8u(fg[m_order.G ] shr (image_subpixel_shift * 2 ) );
+ span.b:=int8u(fg[m_order.B ] shr (image_subpixel_shift * 2 ) );
+ span.a:=base_mask;
+
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+
+ intr.inc_operator;
+
+ dec(len );
+
+ until len = 0;
+
+ result:=_allocator.span;
+
+end;
+
+{ CONSTRUCT }
+constructor span_pattern_filter_rgb_2x2.Construct(alloc : span_allocator_ptr; WX ,WY : wrap_mode_ptr; order : order_type );
+begin
+ inherited Construct(alloc );
+
+ m_order:=order;
+
+ m_wrap_mode_x:=WX;
+ m_wrap_mode_y:=WY;
+
+ m_wrap_mode_x.init(1 );
+ m_wrap_mode_y.init(1 );
+
+end;
+
+{ CONSTRUCT }
+constructor span_pattern_filter_rgb_2x2.Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ interpolator : span_interpolator_ptr;
+ filter : image_filter_lut_ptr;
+ WX ,WY : wrap_mode_ptr;
+ order : order_type );
+var
+ rgba : aggclr;
+
+begin
+ rgba.ConstrInt(0 ,0 ,0 ,0 );
+
+ inherited Construct(alloc ,src ,@rgba ,interpolator ,filter );
+
+ m_order:=order;
+
+ m_wrap_mode_x:=WX;
+ m_wrap_mode_y:=WY;
+
+ m_wrap_mode_x.init(src._width );
+ m_wrap_mode_y.init(src._height );
+
+end;
+
+{ SOURCE_IMAGE_ }
+procedure span_pattern_filter_rgb_2x2.source_image_;
+begin
+ inherited source_image_(src );
+
+ m_wrap_mode_x.init(src._width );
+ m_wrap_mode_y.init(src._height );
+
+end;
+
+{ GENERATE }
+function span_pattern_filter_rgb_2x2.generate;
+var
+ span : aggclr_ptr;
+ intr : span_interpolator_ptr;
+
+ x_hr ,y_hr ,x_lr ,y_lr ,weight : int;
+
+ x1 ,x2 ,y1 ,y2 : unsigned;
+
+ fg : array[0..2 ] of unsigned;
+
+ fg_ptr ,ptr1 ,ptr2 : int8u_ptr;
+
+ weight_array : int16_ptr;
+
+begin
+ span:=_allocator.span;
+ intr:=_interpolator;
+
+ intr.begin_(x + filter_dx_dbl ,y + filter_dy_dbl ,len );
+
+ weight_array:=
+ int16_ptr(
+ ptrcomp(_filter.weight_array ) +
+ shr_int32(_filter.diameter div 2 - 1 ,image_subpixel_shift ) );
+
+ repeat
+ intr.coordinates(@x_hr ,@y_hr );
+
+ dec(x_hr ,filter_dx_int );
+ dec(y_hr ,filter_dy_int );
+
+ x_lr:=shr_int32(x_hr ,image_subpixel_shift );
+ y_lr:=shr_int32(y_hr ,image_subpixel_shift );
+
+ x1:=m_wrap_mode_x.func_operator(x_lr );
+ x2:=m_wrap_mode_x.inc_operator;
+
+ x1:=x1 * 3;
+ x2:=x2 * 3;
+
+ y1:=m_wrap_mode_y.func_operator(y_lr );
+ y2:=m_wrap_mode_y.inc_operator;
+
+ ptr1:=_source_image.row(y1 );
+ ptr2:=_source_image.row(y2 );
+
+ fg[0 ]:=image_filter_size div 2;
+ fg[1 ]:=fg[0 ];
+ fg[2 ]:=fg[0 ];
+
+ x_hr:=x_hr and image_subpixel_mask;
+ y_hr:=y_hr and image_subpixel_mask;
+
+ fg_ptr:=int8u_ptr(ptrcomp(ptr1 ) + x1 * sizeof(int8u ) );
+ weight:=
+ shr_int32(
+ int16_ptr(ptrcomp(weight_array ) + (x_hr + image_subpixel_size ) * sizeof(int16 ) )^ *
+ int16_ptr(ptrcomp(weight_array ) + (y_hr + image_subpixel_size ) * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,image_filter_shift );
+
+ inc(fg[0 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,weight * fg_ptr^ );
+
+ fg_ptr:=int8u_ptr(ptrcomp(ptr1 ) + x2 * sizeof(int8u ) );
+ weight:=
+ shr_int32(
+ int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ *
+ int16_ptr(ptrcomp(weight_array ) + (y_hr + image_subpixel_size ) * sizeof(int16 ) )^ +
+ image_filter_size div 2,image_filter_shift );
+
+ inc(fg[0 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,weight * fg_ptr^ );
+
+ fg_ptr:=int8u_ptr(ptrcomp(ptr2 ) + x1 * sizeof(int8u ) );
+ weight:=
+ shr_int32(
+ int16_ptr(ptrcomp(weight_array ) + (x_hr + image_subpixel_size ) * sizeof(int16 ) )^ *
+ int16_ptr(ptrcomp(weight_array ) + y_hr * sizeof(int16 ) )^ +
+ image_filter_size div 2,image_filter_shift );
+
+ inc(fg[0 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,weight * fg_ptr^ );
+
+ fg_ptr:=int8u_ptr(ptrcomp(ptr2 ) + x2 * sizeof(int8u ) );
+ weight:=
+ shr_int32(
+ int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ *
+ int16_ptr(ptrcomp(weight_array ) + y_hr * sizeof(int16 ) )^ +
+ image_filter_size div 2,image_filter_shift );
+
+ inc(fg[0 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,weight * fg_ptr^ );
+
+ fg[0 ]:=fg[0 ] shr image_filter_shift;
+ fg[1 ]:=fg[1 ] shr image_filter_shift;
+ fg[2 ]:=fg[2 ] shr image_filter_shift;
+
+ if fg[0 ] > base_mask then
+ fg[0 ]:=base_mask;
+
+ if fg[1 ] > base_mask then
+ fg[1 ]:=base_mask;
+
+ if fg[2 ] > base_mask then
+ fg[2 ]:=base_mask;
+
+ span.r:=int8u(fg[m_order.R ] );
+ span.g:=int8u(fg[m_order.G ] );
+ span.b:=int8u(fg[m_order.B ] );
+ span.a:=base_mask;
+
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+
+ intr.inc_operator;
+
+ dec(len );
+
+ until len = 0;
+
+ result:=_allocator.span;
+
+end;
+
+{ CONSTRUCT }
+constructor span_pattern_filter_rgb.Construct(alloc : span_allocator_ptr; WX ,WY : wrap_mode_ptr; order : order_type );
+begin
+ inherited Construct(alloc );
+
+ m_order:=order;
+
+ m_wrap_mode_x:=WX;
+ m_wrap_mode_y:=WY;
+
+ m_wrap_mode_x.init(1 );
+ m_wrap_mode_y.init(1 );
+
+end;
+
+{ CONSTRUCT }
+constructor span_pattern_filter_rgb.Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ interpolator : span_interpolator_ptr;
+ filter : image_filter_lut_ptr;
+ WX ,WY : wrap_mode_ptr;
+ order : order_type );
+var
+ rgba : aggclr;
+
+begin
+ rgba.ConstrInt(0 ,0 ,0 ,0 );
+
+ inherited Construct(alloc ,src ,@rgba ,interpolator ,filter );
+
+ m_order:=order;
+
+ m_wrap_mode_x:=WX;
+ m_wrap_mode_y:=WY;
+
+ m_wrap_mode_x.init(src._width );
+ m_wrap_mode_y.init(src._height );
+
+end;
+
+{ SOURCE_IMAGE_ }
+procedure span_pattern_filter_rgb.source_image_;
+begin
+ inherited source_image_(src );
+
+ m_wrap_mode_x.init(src._width );
+ m_wrap_mode_y.init(src._height );
+
+end;
+
+{ GENERATE }
+function span_pattern_filter_rgb.generate;
+var
+ span : aggclr_ptr;
+ intr : span_interpolator_ptr;
+
+ fg : array[0..2 ] of int;
+
+ diameter ,y_count : unsigned;
+
+ start ,x_count ,weight_y ,x_hr ,y_hr ,x_fract ,y_lr ,x_int ,x_lr ,weight : int;
+
+ row_ptr ,fg_ptr : int8u_ptr;
+
+ weight_array : int16_ptr;
+
+begin
+ span:=_allocator.span;
+ intr:=_interpolator;
+
+ intr.begin_(x + filter_dx_dbl ,y + filter_dy_dbl ,len );
+
+ diameter :=_filter.diameter;
+ start :=_filter.start;
+ weight_array:=_filter.weight_array;
+
+ repeat
+ intr.coordinates(@x ,@y );
+
+ dec(x ,filter_dx_int );
+ dec(y ,filter_dy_int );
+
+ x_hr:=x;
+ y_hr:=y;
+
+ x_fract:=x_hr and image_subpixel_mask;
+ y_count:=diameter;
+
+ y_lr :=m_wrap_mode_y.func_operator(shr_int32(y ,image_subpixel_shift ) + start );
+ x_int:=shr_int32(x ,image_subpixel_shift ) + start;
+ y_hr :=image_subpixel_mask - (y_hr and image_subpixel_mask );
+
+ fg[0 ]:=image_filter_size div 2;
+ fg[1 ]:=fg[0 ];
+ fg[2 ]:=fg[0 ];
+
+ repeat
+ x_count :=diameter;
+ weight_y:=int16_ptr(ptrcomp(weight_array ) + y_hr * sizeof(int16 ) )^;
+
+ x_hr:=image_subpixel_mask - x_fract;
+ x_lr:=m_wrap_mode_x.func_operator(x_int );
+
+ row_ptr:=_source_image.row(y_lr );
+
+ repeat
+ fg_ptr:=int8u_ptr(ptrcomp(row_ptr ) + x_lr * 3 * sizeof(int8u ) );
+ weight:=
+ shr_int32(
+ weight_y *
+ int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,image_filter_shift );
+
+ inc(fg[0 ] ,fg_ptr^ * weight ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,fg_ptr^ * weight ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,fg_ptr^ * weight );
+ inc(x_hr ,image_subpixel_size );
+
+ x_lr:=m_wrap_mode_x.inc_operator;
+
+ dec(x_count );
+
+ until x_count = 0;
+
+ inc(y_hr ,image_subpixel_size );
+
+ y_lr:=m_wrap_mode_y.inc_operator;
+
+ dec(y_count );
+
+ until y_count = 0;
+
+ fg[0 ]:=shr_int32(fg[0 ] ,image_filter_shift );
+ fg[1 ]:=shr_int32(fg[1 ] ,image_filter_shift );
+ fg[2 ]:=shr_int32(fg[2 ] ,image_filter_shift );
+
+ if fg[0 ] < 0 then
+ fg[0 ]:=0;
+
+ if fg[1 ] < 0 then
+ fg[1 ]:=0;
+
+ if fg[2 ] < 0 then
+ fg[2 ]:=0;
+
+ if fg[0 ] > base_mask then
+ fg[0 ]:=base_mask;
+
+ if fg[1 ] > base_mask then
+ fg[1 ]:=base_mask;
+
+ if fg[2 ] > base_mask then
+ fg[2 ]:=base_mask;
+
+ span.r:=int8u(fg[m_order.R ] );
+ span.g:=int8u(fg[m_order.G ] );
+ span.b:=int8u(fg[m_order.B ] );
+ span.a:=base_mask;
+
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+
+ intr.inc_operator;
+
+ dec(len );
+
+ until len = 0;
+
+ result:=_allocator.span;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_span_pattern_filter_rgba.pas b/src/corelib/render/software/agg_span_pattern_filter_rgba.pas
new file mode 100644
index 00000000..8dc6497e
--- /dev/null
+++ b/src/corelib/render/software/agg_span_pattern_filter_rgba.pas
@@ -0,0 +1,755 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// Adaptation for high precision colors has been sponsored by
+// Liberty Technology Systems, Inc., visit http://lib-sys.com
+//
+// Liberty Technology Systems, Inc. is the provider of
+// PostScript and PDF technology for software developers.
+//
+//----------------------------------------------------------------------------
+//
+// classes span_pattern_filter_rgba*
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 06.03.2006-Milano: Unit port establishment
+//
+{ agg_span_pattern_filter_rgba.pas {untested}
+unit
+ agg_span_pattern_filter_rgba ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+{$Q- }
+{$R- }
+uses
+ agg_basics ,
+ agg_color ,
+ agg_span_pattern ,
+ agg_span_image_filter ,
+ agg_span_interpolator_linear ,
+ agg_rendering_buffer ,
+ agg_span_allocator ,
+ agg_image_filters ;
+
+{ TYPES DEFINITION }
+const
+ base_shift = agg_color.base_shift;
+ base_mask = agg_color.base_mask;
+
+type
+ span_pattern_filter_rgba_nn_ptr = ^span_pattern_filter_rgba_nn;
+ span_pattern_filter_rgba_nn = object(span_image_filter )
+ m_wrap_mode_x ,
+ m_wrap_mode_y : wrap_mode_ptr;
+
+ m_order : order_type;
+
+ constructor Construct(alloc : span_allocator_ptr; WX ,WY : wrap_mode_ptr; order : order_type ); overload;
+ constructor Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ interpolator : span_interpolator_ptr;
+ WX ,WY : wrap_mode_ptr;
+ order : order_type ); overload;
+
+ procedure source_image_(src : rendering_buffer_ptr );
+
+ function generate(x ,y : int; len : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+ span_pattern_filter_rgba_bilinear_ptr = ^span_pattern_filter_rgba_bilinear;
+ span_pattern_filter_rgba_bilinear = object(span_image_filter )
+ m_wrap_mode_x ,
+ m_wrap_mode_y : wrap_mode_ptr;
+
+ m_order : order_type;
+
+ constructor Construct(alloc : span_allocator_ptr; WX ,WY : wrap_mode_ptr; order : order_type ); overload;
+ constructor Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ interpolator : span_interpolator_ptr;
+ WX ,WY : wrap_mode_ptr;
+ order : order_type ); overload;
+
+ procedure source_image_(src : rendering_buffer_ptr );
+
+ function generate(x ,y : int; len : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+ span_pattern_filter_rgba_2x2_ptr = ^span_pattern_filter_rgba_2x2;
+ span_pattern_filter_rgba_2x2 = object(span_image_filter )
+ m_wrap_mode_x ,
+ m_wrap_mode_y : wrap_mode_ptr;
+
+ m_order : order_type;
+
+ constructor Construct(alloc : span_allocator_ptr; WX ,WY : wrap_mode_ptr; order : order_type ); overload;
+ constructor Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ interpolator : span_interpolator_ptr;
+ filter : image_filter_lut_ptr;
+ WX ,WY : wrap_mode_ptr;
+ order : order_type ); overload;
+
+ procedure source_image_(src : rendering_buffer_ptr );
+
+ function generate(x ,y : int; len : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+ span_pattern_filter_rgba_ptr = ^span_pattern_filter_rgba;
+ span_pattern_filter_rgba = object(span_image_filter )
+ m_wrap_mode_x ,
+ m_wrap_mode_y : wrap_mode_ptr;
+
+ m_order : order_type;
+
+ constructor Construct(alloc : span_allocator_ptr; WX ,WY : wrap_mode_ptr; order : order_type ); overload;
+ constructor Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ interpolator : span_interpolator_ptr;
+ filter : image_filter_lut_ptr;
+ WX ,WY : wrap_mode_ptr;
+ order : order_type ); overload;
+
+ procedure source_image_(src : rendering_buffer_ptr );
+
+ function generate(x ,y : int; len : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor span_pattern_filter_rgba_nn.Construct(alloc : span_allocator_ptr; WX ,WY : wrap_mode_ptr; order : order_type );
+begin
+ inherited Construct(alloc );
+
+ m_order:=order;
+
+ m_wrap_mode_x:=WX;
+ m_wrap_mode_y:=WY;
+
+ m_wrap_mode_x.init(1 );
+ m_wrap_mode_y.init(1 );
+
+end;
+
+{ CONSTRUCT }
+constructor span_pattern_filter_rgba_nn.Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ interpolator : span_interpolator_ptr;
+ WX ,WY : wrap_mode_ptr;
+ order : order_type );
+var
+ rgba : aggclr;
+
+begin
+ rgba.ConstrInt(0 ,0 ,0 ,0 );
+
+ inherited Construct(alloc ,src ,@rgba ,interpolator ,NIL );
+
+ m_order:=order;
+
+ m_wrap_mode_x:=WX;
+ m_wrap_mode_y:=WY;
+
+ m_wrap_mode_x.init(src._width );
+ m_wrap_mode_y.init(src._height );
+
+end;
+
+{ SOURCE_IMAGE_ }
+procedure span_pattern_filter_rgba_nn.source_image_;
+begin
+ inherited source_image_(src );
+
+ m_wrap_mode_x.init(src._width );
+ m_wrap_mode_y.init(src._height );
+
+end;
+
+{ GENERATE }
+function span_pattern_filter_rgba_nn.generate;
+var
+ fg_ptr : int8u_ptr;
+
+ span : aggclr_ptr;
+
+begin
+ _interpolator.begin_(x + filter_dx_dbl ,y + filter_dy_dbl ,len );
+
+ span:=_allocator.span;
+
+ repeat
+ _interpolator.coordinates(@x ,@y );
+
+ x:=m_wrap_mode_x.func_operator(shr_int32(x ,image_subpixel_shift ) );
+ y:=m_wrap_mode_y.func_operator(shr_int32(y ,image_subpixel_shift ) );
+
+ fg_ptr:=int8u_ptr(ptrcomp(_source_image.row(y ) ) + (x shl 2 ) * sizeof(int8u ) );
+
+ span.r:=int8u_ptr(ptrcomp(fg_ptr ) + m_order.R * sizeof(int8u ) )^;
+ span.g:=int8u_ptr(ptrcomp(fg_ptr ) + m_order.G * sizeof(int8u ) )^;
+ span.b:=int8u_ptr(ptrcomp(fg_ptr ) + m_order.B * sizeof(int8u ) )^;
+ span.a:=int8u_ptr(ptrcomp(fg_ptr ) + m_order.A * sizeof(int8u ) )^;
+
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+
+ _interpolator.inc_operator;
+
+ dec(len );
+
+ until len = 0;
+
+ result:=_allocator.span;
+
+end;
+
+{ CONSTRUCT }
+constructor span_pattern_filter_rgba_bilinear.Construct(alloc : span_allocator_ptr; WX ,WY : wrap_mode_ptr; order : order_type );
+begin
+ inherited Construct(alloc );
+
+ m_order:=order;
+
+ m_wrap_mode_x:=WX;
+ m_wrap_mode_y:=WY;
+
+ m_wrap_mode_x.init(1 );
+ m_wrap_mode_y.init(1 );
+
+end;
+
+{ CONSTRUCT }
+constructor span_pattern_filter_rgba_bilinear.Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ interpolator : span_interpolator_ptr;
+ WX ,WY : wrap_mode_ptr;
+ order : order_type );
+var
+ rgba : aggclr;
+
+begin
+ rgba.ConstrInt(0 ,0 ,0 ,0 );
+
+ inherited Construct(alloc ,src ,@rgba ,interpolator ,NIL );
+
+ m_order:=order;
+
+ m_wrap_mode_x:=WX;
+ m_wrap_mode_y:=WY;
+
+ m_wrap_mode_x.init(src._width );
+ m_wrap_mode_y.init(src._height );
+
+end;
+
+{ SOURCE_IMAGE_ }
+procedure span_pattern_filter_rgba_bilinear.source_image_;
+begin
+ inherited source_image_(src );
+
+ m_wrap_mode_x.init(src._width );
+ m_wrap_mode_y.init(src._height );
+
+end;
+
+{ GENERATE }
+function span_pattern_filter_rgba_bilinear.generate;
+var
+ fg : array[0..3 ] of unsigned;
+
+ x_hr ,y_hr ,x_lr ,y_lr ,weight : int;
+
+ x1 ,x2 ,y1 ,y2 : unsigned;
+
+ fg_ptr ,ptr1 ,ptr2 : int8u_ptr;
+
+ span : aggclr_ptr;
+
+begin
+ _interpolator.begin_(x + filter_dx_dbl ,y + filter_dy_dbl ,len );
+
+ span:=_allocator.span;
+
+ repeat
+ _interpolator.coordinates(@x_hr ,@y_hr );
+
+ dec(x_hr ,filter_dx_int );
+ dec(y_hr ,filter_dy_int );
+
+ x_lr:=shr_int32(x_hr ,image_subpixel_shift );
+ y_lr:=shr_int32(y_hr ,image_subpixel_shift );
+
+ x1:=m_wrap_mode_x.func_operator(x_lr );
+ x2:=m_wrap_mode_x.inc_operator;
+
+ x1:=x1 shl 2;
+ x2:=x2 shl 2;
+
+ y1:=m_wrap_mode_y.func_operator(y_lr );
+ y2:=m_wrap_mode_y.inc_operator;
+
+ ptr1:=_source_image.row(y1 );
+ ptr2:=_source_image.row(y2 );
+
+ fg[0 ]:=image_subpixel_size * image_subpixel_size div 2;
+ fg[1 ]:=fg[0 ];
+ fg[2 ]:=fg[0 ];
+ fg[3 ]:=fg[0 ];
+
+ x_hr:=x_hr and image_subpixel_mask;
+ y_hr:=y_hr and image_subpixel_mask;
+
+ fg_ptr:=int8u_ptr(ptrcomp(ptr1 ) + x1 * sizeof(int8u ) );
+ weight:=(image_subpixel_size - x_hr ) * (image_subpixel_size - y_hr );
+
+ inc(fg[0 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr) ,sizeof(int8u ) );
+ inc(fg[1 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr) ,sizeof(int8u ) );
+ inc(fg[2 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr) ,sizeof(int8u ) );
+ inc(fg[3 ] ,weight * fg_ptr^ );
+
+ fg_ptr:=int8u_ptr(ptrcomp(ptr1 ) + x2 * sizeof(int8u ) );
+ weight:=x_hr * (image_subpixel_size - y_hr );
+
+ inc(fg[0 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr) ,sizeof(int8u ) );
+ inc(fg[1 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr) ,sizeof(int8u ) );
+ inc(fg[2 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr) ,sizeof(int8u ) );
+ inc(fg[3 ] ,weight * fg_ptr^ );
+
+ fg_ptr:=int8u_ptr(ptrcomp(ptr2 ) + x1 * sizeof(int8u ) );
+ weight:=(image_subpixel_size - x_hr ) * y_hr;
+
+ inc(fg[0 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr) ,sizeof(int8u ) );
+ inc(fg[1 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr) ,sizeof(int8u ) );
+ inc(fg[2 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr) ,sizeof(int8u ) );
+ inc(fg[3 ] ,weight * fg_ptr^ );
+
+ fg_ptr:=int8u_ptr(ptrcomp(ptr2 ) + x2 * sizeof(int8u ) );
+ weight:=x_hr * y_hr;
+
+ inc(fg[0 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr) ,sizeof(int8u ) );
+ inc(fg[1 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr) ,sizeof(int8u ) );
+ inc(fg[2 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr) ,sizeof(int8u ) );
+ inc(fg[3 ] ,weight * fg_ptr^ );
+
+ span.r:=int8u(fg[m_order.R ] shr (image_subpixel_shift * 2 ) );
+ span.g:=int8u(fg[m_order.G ] shr (image_subpixel_shift * 2 ) );
+ span.b:=int8u(fg[m_order.B ] shr (image_subpixel_shift * 2 ) );
+ span.a:=int8u(fg[m_order.A ] shr (image_subpixel_shift * 2 ) );
+
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+
+ _interpolator.inc_operator;
+
+ dec(len );
+
+ until len = 0;
+
+ result:=_allocator.span;
+
+end;
+
+{ CONSTRUCT }
+constructor span_pattern_filter_rgba_2x2.Construct(alloc : span_allocator_ptr; WX ,WY : wrap_mode_ptr; order : order_type );
+begin
+ inherited Construct(alloc );
+
+ m_order:=order;
+
+ m_wrap_mode_x:=WX;
+ m_wrap_mode_y:=WY;
+
+ m_wrap_mode_x.init(1 );
+ m_wrap_mode_y.init(1 );
+
+end;
+
+{ CONSTRUCT }
+constructor span_pattern_filter_rgba_2x2.Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ interpolator : span_interpolator_ptr;
+ filter : image_filter_lut_ptr;
+ WX ,WY : wrap_mode_ptr;
+ order : order_type );
+var
+ rgba : aggclr;
+
+begin
+ rgba.ConstrInt(0 ,0 ,0 ,0 );
+
+ inherited Construct(alloc ,src ,@rgba ,interpolator ,filter );
+
+ m_order:=order;
+
+ m_wrap_mode_x:=WX;
+ m_wrap_mode_y:=WY;
+
+ m_wrap_mode_x.init(src._width );
+ m_wrap_mode_y.init(src._height );
+
+end;
+
+{ SOURCE_IMAGE_ }
+procedure span_pattern_filter_rgba_2x2.source_image_;
+begin
+ inherited source_image_(src );
+
+ m_wrap_mode_x.init(src._width );
+ m_wrap_mode_y.init(src._height );
+
+end;
+
+{ GENERATE }
+function span_pattern_filter_rgba_2x2.generate;
+var
+ fg : array[0..3 ] of unsigned;
+
+ x_hr ,y_hr ,x_lr ,y_lr ,weight : int;
+
+ x1 ,x2 ,y1 ,y2 : unsigned;
+
+ fg_ptr ,ptr1 ,ptr2 : int8u_ptr;
+
+ span : aggclr_ptr;
+
+ weight_array : int16_ptr;
+
+begin
+ _interpolator.begin_(x + filter_dx_dbl ,y + filter_dy_dbl ,len );
+
+ span:=_allocator.span;
+
+ weight_array:=
+ int16_ptr(
+ ptrcomp(_filter.weight_array ) +
+ shr_int32(_filter.diameter div 2 - 1 ,image_subpixel_shift ) );
+
+ repeat
+ _interpolator.coordinates(@x_hr ,@y_hr );
+
+ dec(x_hr ,filter_dx_int );
+ dec(y_hr ,filter_dy_int );
+
+ x_lr:=shr_int32(x_hr ,image_subpixel_shift );
+ y_lr:=shr_int32(y_hr ,image_subpixel_shift );
+
+ x1:=m_wrap_mode_x.func_operator(x_lr );
+ x2:=m_wrap_mode_x.inc_operator;
+
+ x1:=x1 shl 2;
+ x2:=x2 shl 2;
+
+ y1:=m_wrap_mode_y.func_operator(y_lr );
+ y2:=m_wrap_mode_y.inc_operator;
+
+ ptr1:=_source_image.row(y1 );
+ ptr2:=_source_image.row(y2 );
+
+ fg[0 ]:=image_filter_size div 2;
+ fg[1 ]:=fg[0 ];
+ fg[2 ]:=fg[0 ];
+ fg[3 ]:=fg[0 ];
+
+ x_hr:=x_hr and image_subpixel_mask;
+ y_hr:=y_hr and image_subpixel_mask;
+
+ fg_ptr:=int8u_ptr(ptrcomp(ptr1 ) + x1 * sizeof(int8u ) );
+ weight:=
+ shr_int32(
+ int16_ptr(ptrcomp(weight_array ) + (x_hr + image_subpixel_size ) * sizeof(int16 ) )^ *
+ int16_ptr(ptrcomp(weight_array ) + (y_hr + image_subpixel_size ) * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,image_filter_shift );
+
+ inc(fg[0 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[3 ] ,weight * fg_ptr^ );
+
+ fg_ptr:=int8u_ptr(ptrcomp(ptr1 ) + x2 * sizeof(int8u ) );
+ weight:=
+ shr_int32(
+ int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ *
+ int16_ptr(ptrcomp(weight_array ) + (y_hr + image_subpixel_size ) * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,image_filter_shift );
+
+ inc(fg[0 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[3 ] ,weight * fg_ptr^ );
+
+ fg_ptr:=int8u_ptr(ptrcomp(ptr2 ) + x1 * sizeof(int8u ) );
+ weight:=
+ shr_int32(
+ int16_ptr(ptrcomp(weight_array ) + (x_hr + image_subpixel_size ) * sizeof(int16 ) )^ *
+ int16_ptr(ptrcomp(weight_array ) + y_hr * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,image_filter_shift );
+
+ inc(fg[0 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[3 ] ,weight * fg_ptr^ );
+
+ fg_ptr:=int8u_ptr(ptrcomp(ptr2 ) + x2 * sizeof(int8u ) );
+ weight:=
+ shr_int32(
+ int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ *
+ int16_ptr(ptrcomp(weight_array ) + y_hr * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,image_filter_shift );
+
+ inc(fg[0 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,weight * fg_ptr^ ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[3 ] ,weight * fg_ptr^ );
+
+ fg[0 ]:=fg[0 ] shr image_filter_shift;
+ fg[1 ]:=fg[1 ] shr image_filter_shift;
+ fg[2 ]:=fg[2 ] shr image_filter_shift;
+ fg[3 ]:=fg[3 ] shr image_filter_shift;
+
+ if fg[m_order.A ] > base_mask then
+ fg[m_order.A ]:=base_mask;
+
+ if fg[m_order.R ] > fg[m_order.A ] then
+ fg[m_order.R ]:=fg[m_order.A ];
+
+ if fg[m_order.G ] > fg[m_order.A ] then
+ fg[m_order.G ]:=fg[m_order.A ];
+
+ if fg[m_order.B ] > fg[m_order.A ] then
+ fg[m_order.B ]:=fg[m_order.A ];
+
+ span.r:=int8u(fg[m_order.R ] );
+ span.g:=int8u(fg[m_order.G ] );
+ span.b:=int8u(fg[m_order.B ] );
+ span.a:=int8u(fg[m_order.A ] );
+
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+
+ _interpolator.inc_operator;
+
+ dec(len );
+
+ until len = 0;
+
+ result:=_allocator.span;
+
+end;
+
+{ CONSTRUCT }
+constructor span_pattern_filter_rgba.Construct(alloc : span_allocator_ptr; WX ,WY : wrap_mode_ptr; order : order_type );
+begin
+ inherited Construct(alloc );
+
+ m_order:=order;
+
+ m_wrap_mode_x:=WX;
+ m_wrap_mode_y:=WY;
+
+ m_wrap_mode_x.init(1 );
+ m_wrap_mode_y.init(1 );
+
+end;
+
+{ CONSTRUCT }
+constructor span_pattern_filter_rgba.Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ interpolator : span_interpolator_ptr;
+ filter : image_filter_lut_ptr;
+ WX ,WY : wrap_mode_ptr;
+ order : order_type );
+var
+ rgba : aggclr;
+
+begin
+ rgba.ConstrInt(0 ,0 ,0 ,0 );
+
+ inherited Construct(alloc ,src ,@rgba ,interpolator ,filter );
+
+ m_order:=order;
+
+ m_wrap_mode_x:=WX;
+ m_wrap_mode_y:=WY;
+
+ m_wrap_mode_x.init(src._width );
+ m_wrap_mode_y.init(src._height );
+
+end;
+
+{ SOURCE_IMAGE_ }
+procedure span_pattern_filter_rgba.source_image_;
+begin
+ inherited source_image_(src );
+
+ m_wrap_mode_x.init(src._width );
+ m_wrap_mode_y.init(src._height );
+
+end;
+
+{ GENERATE }
+function span_pattern_filter_rgba.generate;
+var
+ fg : array[0..3 ] of int;
+
+ diameter ,y_count : unsigned;
+
+ start ,x_count ,weight_y ,x_hr ,y_hr ,x_fract ,y_lr ,x_int ,x_lr ,weight : int;
+
+ row_ptr ,fg_ptr : int8u_ptr;
+
+ weight_array : int16_ptr;
+
+ span : aggclr_ptr;
+
+begin
+ _interpolator.begin_(x + filter_dx_dbl ,y + filter_dy_dbl ,len );
+
+ diameter :=_filter.diameter;
+ start :=_filter.start;
+ weight_array:=_filter.weight_array;
+
+ span:=_allocator.span;
+
+ repeat
+ _interpolator.coordinates(@x ,@y );
+
+ dec(x ,filter_dx_int );
+ dec(y ,filter_dy_int );
+
+ x_hr:=x;
+ x_hr:=y;
+
+ x_fract:=x_hr and image_subpixel_mask;
+ y_count:=diameter;
+
+ y_lr :=m_wrap_mode_y.func_operator(shr_int32(y ,image_subpixel_shift ) + start );
+ x_int:=shr_int32(x ,image_subpixel_shift ) + start;
+ y_hr :=image_subpixel_mask - (y_hr and image_subpixel_mask );
+
+ fg[0 ]:=image_filter_size div 2;
+ fg[1 ]:=fg[0 ];
+ fg[2 ]:=fg[0 ];
+ fg[3 ]:=fg[0 ];
+
+ repeat
+ x_count :=diameter;
+ weight_y:=int16_ptr(ptrcomp(weight_array ) + y_hr * sizeof(int16 ) )^;
+
+ x_hr:=image_subpixel_mask - x_fract;
+ x_lr:=m_wrap_mode_x.func_operator(x_int );
+
+ row_ptr:=_source_image.row(y_lr );
+
+ repeat
+ fg_ptr:=int8u_ptr(ptrcomp(row_ptr ) + (x_lr shl 2 ) * sizeof(int8u ) );
+ weight:=
+ shr_int32(
+ weight_y *
+ int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,image_filter_shift );
+
+ inc(fg[0 ] ,fg_ptr^ * weight ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,fg_ptr^ * weight ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,fg_ptr^ * weight ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[3 ] ,fg_ptr^ * weight );
+ inc(x_hr ,image_subpixel_size );
+
+ x_lr:=m_wrap_mode_x.inc_operator;
+
+ dec(x_count );
+
+ until x_count = 0;
+
+ inc(y_hr ,image_subpixel_size );
+
+ y_lr:=m_wrap_mode_y.inc_operator;
+
+ dec(y_count );
+
+ until y_count = 0;
+
+ fg[0 ]:=shr_int32(fg[0 ] ,image_filter_shift );
+ fg[1 ]:=shr_int32(fg[1 ] ,image_filter_shift );
+ fg[2 ]:=shr_int32(fg[2 ] ,image_filter_shift );
+ fg[3 ]:=shr_int32(fg[3 ] ,image_filter_shift );
+
+ if fg[0 ] < 0 then
+ fg[0 ]:=0;
+
+ if fg[1 ] < 0 then
+ fg[1 ]:=0;
+
+ if fg[2 ] < 0 then
+ fg[2 ]:=0;
+
+ if fg[3 ] < 0 then
+ fg[3 ]:=0;
+
+ if fg[m_order.A ] > base_mask then
+ fg[m_order.A ]:=base_mask;
+
+ if fg[m_order.R ] > fg[m_order.A ] then
+ fg[m_order.R ]:=fg[m_order.A ];
+
+ if fg[m_order.G ] > fg[m_order.A ] then
+ fg[m_order.G ]:=fg[m_order.A ];
+
+ if fg[m_order.B ] > fg[m_order.A ] then
+ fg[m_order.B ]:=fg[m_order.A ];
+
+ span.r:=int8u(fg[m_order.R ] );
+ span.g:=int8u(fg[m_order.G ] );
+ span.b:=int8u(fg[m_order.B ] );
+ span.a:=int8u(fg[m_order.A ] );
+
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+
+ _interpolator.inc_operator;
+
+ dec(len );
+
+ until len = 0;
+
+ result:=_allocator.span;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_span_pattern_resample_gray.pas b/src/corelib/render/software/agg_span_pattern_resample_gray.pas
new file mode 100644
index 00000000..3b2c0db0
--- /dev/null
+++ b/src/corelib/render/software/agg_span_pattern_resample_gray.pas
@@ -0,0 +1,428 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 06.03.2006-Milano: Unit port establishment
+//
+{ agg_span_pattern_resample_gray.pas {untested}
+unit
+ agg_span_pattern_resample_gray ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+{$Q- }
+{$R- }
+uses
+ agg_basics ,
+ agg_color ,
+ agg_span_pattern ,
+ agg_span_image_resample ,
+ agg_span_interpolator_linear ,
+ agg_rendering_buffer ,
+ agg_span_allocator ,
+ agg_image_filters ;
+
+{ TYPES DEFINITION }
+const
+ base_shift = agg_color.base_shift;
+ base_mask = agg_color.base_mask;
+ downscale_shift = image_filter_shift;
+
+type
+ span_pattern_resample_gray_affine_ptr = ^span_pattern_resample_gray_affine;
+ span_pattern_resample_gray_affine = object(span_image_resample_affine )
+ m_wrap_mode_x ,
+ m_wrap_mode_y : wrap_mode_ptr;
+
+ constructor Construct(alloc : span_allocator_ptr; WX ,WY : wrap_mode_ptr ); overload;
+ constructor Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ interpolator : span_interpolator_ptr;
+ filter : image_filter_lut_ptr;
+ WX ,WY : wrap_mode_ptr ); overload;
+
+ procedure source_image_(src : rendering_buffer_ptr );
+
+ function generate(x ,y : int; len : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+ span_pattern_resample_gray_ptr = ^span_pattern_resample_gray;
+ span_pattern_resample_gray = object(span_image_resample )
+ m_wrap_mode_x ,
+ m_wrap_mode_y : wrap_mode_ptr;
+
+ constructor Construct(alloc : span_allocator_ptr; WX ,WY : wrap_mode_ptr ); overload;
+ constructor Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ interpolator : span_interpolator_ptr;
+ filter : image_filter_lut_ptr;
+ WX ,WY : wrap_mode_ptr ); overload;
+
+ procedure source_image_(src : rendering_buffer_ptr );
+
+ function generate(x ,y : int; len : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor span_pattern_resample_gray_affine.Construct(alloc : span_allocator_ptr; WX ,WY : wrap_mode_ptr );
+begin
+ inherited Construct(alloc );
+
+ m_wrap_mode_x:=WX;
+ m_wrap_mode_y:=WY;
+
+ m_wrap_mode_x.init(1 );
+ m_wrap_mode_y.init(1 );
+
+end;
+
+{ CONSTRUCT }
+constructor span_pattern_resample_gray_affine.Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ interpolator : span_interpolator_ptr;
+ filter : image_filter_lut_ptr;
+ WX ,WY : wrap_mode_ptr );
+var
+ rgba : aggclr;
+
+begin
+ rgba.ConstrInt(0 ,0 );
+
+ inherited Construct(alloc ,src ,@rgba ,interpolator ,filter );
+
+ m_wrap_mode_x:=WX;
+ m_wrap_mode_y:=WY;
+
+ m_wrap_mode_x.init(src._width );
+ m_wrap_mode_y.init(src._height );
+
+end;
+
+{ SOURCE_IMAGE_ }
+procedure span_pattern_resample_gray_affine.source_image_;
+begin
+ inherited source_image_(src );
+
+ m_wrap_mode_x.init(src._width );
+ m_wrap_mode_y.init(src._height );
+
+end;
+
+{ GENERATE }
+function span_pattern_resample_gray_affine.generate;
+var
+ span : aggclr_ptr;
+ intr : span_interpolator_ptr;
+
+ fg ,diameter ,filter_size ,radius_x ,radius_y ,maxx ,maxy ,y_lr ,y_hr ,
+ total_weight ,x_lr_ini ,x_hr_ini ,weight_y ,x_lr ,x_hr ,weight : int;
+
+ row_ptr ,fg_ptr : int8u_ptr;
+
+ weight_array : int16_ptr;
+
+begin
+ span:=_allocator.span;
+ intr:=_interpolator;
+
+ intr.begin_(x + filter_dx_dbl ,y + filter_dy_dbl ,len );
+
+ diameter :=_filter.diameter;
+ filter_size:=diameter shl image_subpixel_shift;
+
+ radius_x:=shr_int32(diameter * m_rx ,1 );
+ radius_y:=shr_int32(diameter * m_ry ,1 );
+
+ maxx:=_source_image._width - 1;
+ maxy:=_source_image._height - 1;
+
+ weight_array:=_filter.weight_array;
+
+ repeat
+ intr.coordinates(@x ,@y );
+
+ inc(x ,filter_dx_int - radius_x );
+ inc(y ,filter_dy_int - radius_y );
+
+ fg:=image_filter_size div 2;
+
+ y_lr:=m_wrap_mode_y.func_operator(shr_int32(y ,image_subpixel_shift ) );
+ y_hr:=
+ shr_int32(
+ (image_subpixel_mask - (y and image_subpixel_mask ) ) *
+ m_ry_inv ,image_subpixel_shift );
+
+ total_weight:=0;
+
+ x_lr_ini:=shr_int32(x ,image_subpixel_shift );
+ x_hr_ini:=
+ shr_int32(
+ (image_subpixel_mask - (x and image_subpixel_mask ) ) *
+ m_rx_inv ,image_subpixel_shift );
+
+ repeat
+ weight_y:=int16_ptr(ptrcomp(weight_array ) + y_hr * sizeof(int16 ) )^;
+
+ x_lr:=m_wrap_mode_x.func_operator(x_lr_ini );
+ x_hr:=x_hr_ini;
+
+ row_ptr:=_source_image.row(y_lr );
+
+ repeat
+ fg_ptr:=int8u_ptr(ptrcomp(row_ptr ) + x_lr * sizeof(int8u ) );
+ weight:=
+ shr_int32(
+ weight_y *
+ int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,downscale_shift );
+
+ inc(fg ,fg_ptr^ * weight );
+ inc(total_weight ,weight );
+ inc(x_hr ,m_rx_inv );
+
+ x_lr:=m_wrap_mode_x.inc_operator;
+
+ until x_hr >= filter_size;
+
+ inc(y_hr ,m_ry_inv );
+
+ y_lr:=m_wrap_mode_y.inc_operator;
+
+ until y_hr >= filter_size;
+
+ fg:=fg div total_weight;
+
+ if fg < 0 then
+ fg:=0;
+
+ if fg > base_mask then
+ fg:=base_mask;
+
+ span.v:=int8u(fg );
+ span.a:=int8u(base_mask );
+
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+
+ intr.inc_operator;
+
+ dec(len );
+
+ until len = 0;
+
+ result:=_allocator.span;
+
+end;
+
+{ CONSTRUCT }
+constructor span_pattern_resample_gray.Construct(alloc : span_allocator_ptr; WX ,WY : wrap_mode_ptr );
+begin
+ inherited Construct(alloc );
+
+ m_wrap_mode_x:=WX;
+ m_wrap_mode_y:=WY;
+
+ m_wrap_mode_x.init(1 );
+ m_wrap_mode_y.init(1 );
+
+end;
+
+{ CONSTRUCT }
+constructor span_pattern_resample_gray.Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ interpolator : span_interpolator_ptr;
+ filter : image_filter_lut_ptr;
+ WX ,WY : wrap_mode_ptr );
+var
+ rgba : aggclr;
+
+begin
+ rgba.ConstrInt(0 ,0 );
+
+ inherited Construct(alloc ,src ,@rgba ,interpolator ,filter );
+
+ m_wrap_mode_x:=WX;
+ m_wrap_mode_y:=WY;
+
+ m_wrap_mode_x.init(src._width );
+ m_wrap_mode_y.init(src._height );
+
+end;
+
+{ SOURCE_IMAGE_ }
+procedure span_pattern_resample_gray.source_image_;
+begin
+ inherited source_image_(src );
+
+ m_wrap_mode_x.init(src._width );
+ m_wrap_mode_y.init(src._height );
+
+end;
+
+{ GENERATE }
+function span_pattern_resample_gray.generate;
+var
+ span : aggclr_ptr;
+ intr : span_interpolator_ptr;
+
+ fg ,diameter ,filter_size ,rx ,ry ,rx_inv ,ry_inv ,radius_x ,radius_y ,
+ maxx ,maxy ,y_lr ,y_hr ,total_weight ,x_lr_ini ,x_hr_ini ,weight_y ,
+ x_lr ,x_hr ,weight : int;
+
+ row_ptr ,fg_ptr : int8u_ptr;
+
+ weight_array : int16_ptr;
+
+begin
+ span:=_allocator.span;
+ intr:=_interpolator;
+
+ intr.begin_(x + filter_dx_dbl ,y + filter_dy_dbl ,len );
+
+ diameter :=_filter.diameter;
+ filter_size :=diameter shl image_subpixel_shift;
+ weight_array:=_filter.weight_array;
+
+ repeat
+ rx_inv:=image_subpixel_size;
+ ry_inv:=image_subpixel_size;
+
+ intr.coordinates(@x ,@y );
+ intr.local_scale(@rx ,@ry );
+
+ rx:=shr_int32(rx * m_blur_x ,image_subpixel_shift );
+ ry:=shr_int32(ry * m_blur_y ,image_subpixel_shift );
+
+ if rx < image_subpixel_size then
+ rx:=image_subpixel_size
+ else
+ begin
+ if rx > image_subpixel_size * m_scale_limit then
+ rx:=image_subpixel_size * m_scale_limit;
+
+ rx_inv:=image_subpixel_size * image_subpixel_size div rx;
+
+ end;
+
+ if ry < image_subpixel_size then
+ ry:=image_subpixel_size
+ else
+ begin
+ if ry > image_subpixel_size * m_scale_limit then
+ ry:=image_subpixel_size * m_scale_limit;
+
+ ry_inv:=image_subpixel_size * image_subpixel_size div ry;
+
+ end;
+
+ radius_x:=shr_int32(diameter * rx ,1 );
+ radius_y:=shr_int32(diameter * ry ,1 );
+
+ maxx:=_source_image._width - 1;
+ maxy:=_source_image._height - 1;
+
+ inc(x ,filter_dx_int - radius_x );
+ inc(y ,filter_dy_int - radius_y );
+
+ fg:=image_filter_size div 2;
+
+ y_lr:=m_wrap_mode_y.func_operator(shr_int32(y ,image_subpixel_shift ) );
+ y_hr:=
+ shr_int32(
+ (image_subpixel_mask - (y and image_subpixel_mask ) ) *
+ ry_inv ,image_subpixel_shift );
+
+ total_weight:=0;
+
+ x_lr_ini:=shr_int32(x ,image_subpixel_shift );
+ x_hr_ini:=
+ shr_int32(
+ (image_subpixel_mask - (x and image_subpixel_mask ) ) *
+ rx_inv ,image_subpixel_shift );
+
+ repeat
+ weight_y:=int16_ptr(ptrcomp(weight_array ) + y_hr * sizeof(int16 ) )^;
+
+ x_lr:=m_wrap_mode_x.func_operator(x_lr_ini );
+ x_hr:=x_hr_ini;
+
+ row_ptr:=_source_image.row(y_lr );
+
+ repeat
+ fg_ptr:=int8u_ptr(ptrcomp(row_ptr ) + x_lr * sizeof(int8u ) );
+ weight:=
+ shr_int32(
+ weight_y *
+ int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,downscale_shift );
+
+ inc(fg ,fg_ptr^ * weight );
+ inc(total_weight ,weight );
+ inc(x_hr ,rx_inv );
+
+ x_lr:=m_wrap_mode_x.inc_operator;
+
+ until x_hr > filter_size;
+
+ inc(y_hr ,ry_inv );
+
+ y_lr:=m_wrap_mode_y.inc_operator;
+
+ until y_hr >= filter_size;
+
+ fg:=fg div total_weight;
+
+ if fg < 0 then
+ fg:=0;
+
+ if fg > base_mask then
+ fg:=base_mask;
+
+ span.v:=int8u(fg );
+ span.a:=int8u(base_mask );
+
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+
+ intr.inc_operator;
+
+ dec(len );
+
+ until len = 0;
+
+ result:=_allocator.span;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_span_pattern_resample_rgb.pas b/src/corelib/render/software/agg_span_pattern_resample_rgb.pas
new file mode 100644
index 00000000..f55f11de
--- /dev/null
+++ b/src/corelib/render/software/agg_span_pattern_resample_rgb.pas
@@ -0,0 +1,488 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 06.03.2006-Milano: Unit port establishment
+//
+{ agg_span_pattern_resample_rgb.pas {untested}
+unit
+ agg_span_pattern_resample_rgb ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+{$Q- }
+{$R- }
+uses
+ agg_basics ,
+ agg_color ,
+ agg_span_pattern ,
+ agg_span_image_resample ,
+ agg_span_interpolator_linear ,
+ agg_rendering_buffer ,
+ agg_span_allocator ,
+ agg_image_filters ;
+
+{ TYPES DEFINITION }
+const
+ base_shift = agg_color.base_shift;
+ base_mask = agg_color.base_mask;
+ downscale_shift = image_filter_shift;
+
+type
+ span_pattern_resample_rgb_affine_ptr = ^span_pattern_resample_rgb_affine;
+ span_pattern_resample_rgb_affine = object(span_image_resample_affine )
+ m_wrap_mode_x ,
+ m_wrap_mode_y : wrap_mode_ptr;
+
+ m_order : order_type;
+
+ constructor Construct(alloc : span_allocator_ptr; WX ,WY : wrap_mode_ptr; order : order_type ); overload;
+ constructor Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ interpolator : span_interpolator_ptr;
+ filter : image_filter_lut_ptr;
+ WX ,WY : wrap_mode_ptr;
+ order : order_type ); overload;
+
+ procedure source_image_(src : rendering_buffer_ptr );
+
+ function generate(x ,y : int; len : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+ span_pattern_resample_rgb_ptr = ^span_pattern_resample_rgb;
+ span_pattern_resample_rgb = object(span_image_resample )
+ m_wrap_mode_x ,
+ m_wrap_mode_y : wrap_mode_ptr;
+
+ m_order : order_type;
+
+ constructor Construct(alloc : span_allocator_ptr; WX ,WY : wrap_mode_ptr; order : order_type ); overload;
+ constructor Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ interpolator : span_interpolator_ptr;
+ filter : image_filter_lut_ptr;
+ WX ,WY : wrap_mode_ptr;
+ order : order_type ); overload;
+
+ procedure source_image_(src : rendering_buffer_ptr );
+
+ function generate(x ,y : int; len : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor span_pattern_resample_rgb_affine.Construct(alloc : span_allocator_ptr; WX ,WY : wrap_mode_ptr; order : order_type );
+begin
+ inherited Construct(alloc );
+
+ m_order:=order;
+
+ m_wrap_mode_x:=WX;
+ m_wrap_mode_y:=WY;
+
+ m_wrap_mode_x.init(1 );
+ m_wrap_mode_y.init(1 );
+
+end;
+
+{ CONSTRUCT }
+constructor span_pattern_resample_rgb_affine.Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ interpolator : span_interpolator_ptr;
+ filter : image_filter_lut_ptr;
+ WX ,WY : wrap_mode_ptr;
+ order : order_type );
+var
+ rgba : aggclr;
+
+begin
+ rgba.ConstrInt(0 ,0 ,0 ,0 );
+
+ inherited Construct(alloc ,src ,@rgba ,interpolator ,filter );
+
+ m_order:=order;
+
+ m_wrap_mode_x:=WX;
+ m_wrap_mode_y:=WY;
+
+ m_wrap_mode_x.init(src._width );
+ m_wrap_mode_y.init(src._height );
+
+end;
+
+{ SOURCE_IMAGE_ }
+procedure span_pattern_resample_rgb_affine.source_image_;
+begin
+ inherited source_image_(src );
+
+ m_wrap_mode_x.init(src._width );
+ m_wrap_mode_y.init(src._height );
+
+end;
+
+{ GENERATE }
+function span_pattern_resample_rgb_affine.generate;
+var
+ span : aggclr_ptr;
+ intr : span_interpolator_ptr;
+
+ fg : array[0..2 ] of int;
+
+ diameter ,filter_size ,radius_x ,radius_y ,maxx ,maxy ,y_lr ,y_hr ,
+ total_weight ,x_lr_ini ,x_hr_ini ,weight_y ,x_lr ,x_hr ,weight : int;
+
+ row_ptr ,fg_ptr : int8u_ptr;
+
+ weight_array : int16_ptr;
+
+begin
+ span:=_allocator.span;
+ intr:=_interpolator;
+
+ intr.begin_(x + filter_dx_dbl ,y + filter_dy_dbl ,len );
+
+ diameter :=_filter.diameter;
+ filter_size:=diameter shl image_subpixel_shift;
+
+ radius_x:=shr_int32(diameter * m_rx ,1 );
+ radius_y:=shr_int32(diameter * m_ry ,1 );
+
+ maxx:=_source_image._width - 1;
+ maxy:=_source_image._height - 1;
+
+ weight_array:=_filter.weight_array;
+
+ repeat
+ intr.coordinates(@x ,@y );
+
+ inc(x ,filter_dx_int - radius_x );
+ inc(y ,filter_dy_int - radius_y );
+
+ fg[0 ]:=image_filter_size div 2;
+ fg[1 ]:=fg[0 ];
+ fg[2 ]:=fg[0 ];
+
+ y_lr:=m_wrap_mode_y.func_operator(shr_int32(y ,image_subpixel_shift ) );
+ y_hr:=
+ shr_int32(
+ (image_subpixel_mask - (y and image_subpixel_mask ) ) *
+ m_ry_inv ,image_subpixel_shift );
+
+ total_weight:=0;
+
+ x_lr_ini:=shr_int32(x ,image_subpixel_shift );
+ x_hr_ini:=
+ shr_int32(
+ (image_subpixel_mask - (x and image_subpixel_mask ) ) *
+ m_rx_inv ,image_subpixel_shift );
+
+ repeat
+ weight_y:=int16_ptr(ptrcomp(weight_array ) + y_hr * sizeof(int16 ) )^;
+
+ x_lr:=m_wrap_mode_x.func_operator(x_lr_ini );
+ x_hr:=x_hr_ini;
+
+ row_ptr:=_source_image.row(y_lr );
+
+ repeat
+ fg_ptr:=int8u_ptr(ptrcomp(row_ptr ) + x_lr * 3 * sizeof(int8u ) );
+ weight:=
+ shr_int32(
+ weight_y *
+ int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,downscale_shift );
+
+ inc(fg[0] ,fg_ptr^ * weight ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1] ,fg_ptr^ * weight ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2] ,fg_ptr^ * weight );
+ inc(total_weight ,weight );
+ inc(x_hr ,m_rx_inv );
+
+ x_lr:=m_wrap_mode_x.inc_operator;
+
+ until x_hr >= filter_size;
+
+ inc(y_hr ,m_ry_inv );
+
+ y_lr:=m_wrap_mode_y.inc_operator;
+
+ until y_hr >= filter_size;
+
+ fg[0 ]:=fg[0 ] div total_weight;
+ fg[1 ]:=fg[0 ] div total_weight;
+ fg[2 ]:=fg[0 ] div total_weight;
+
+ if fg[0 ] < 0 then
+ fg[0 ]:=0;
+
+ if fg[1 ] < 0 then
+ fg[1 ]:=0;
+
+ if fg[2 ] < 0 then
+ fg[2 ]:=0;
+
+ if fg[0 ] > base_mask then
+ fg[0 ]:=base_mask;
+
+ if fg[1 ] > base_mask then
+ fg[1 ]:=base_mask;
+
+ if fg[2 ] > base_mask then
+ fg[2 ]:=base_mask;
+
+ span.r:=int8u(fg[m_order.R ] );
+ span.g:=int8u(fg[m_order.G ] );
+ span.b:=int8u(fg[m_order.B ] );
+ span.a:=int8u(base_mask );
+
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+
+ intr.inc_operator;
+
+ dec(len );
+
+ until len = 0;
+
+ result:=_allocator.span;
+
+end;
+
+{ CONSTRUCT }
+constructor span_pattern_resample_rgb.Construct(alloc : span_allocator_ptr; WX ,WY : wrap_mode_ptr; order : order_type );
+begin
+ inherited Construct(alloc );
+
+ m_order:=order;
+
+ m_wrap_mode_x:=WX;
+ m_wrap_mode_y:=WY;
+
+ m_wrap_mode_x.init(1 );
+ m_wrap_mode_y.init(1 );
+
+end;
+
+{ CONSTRUCT }
+constructor span_pattern_resample_rgb.Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ interpolator : span_interpolator_ptr;
+ filter : image_filter_lut_ptr;
+ WX ,WY : wrap_mode_ptr;
+ order : order_type );
+var
+ rgba : aggclr;
+
+begin
+ rgba.ConstrInt(0 ,0 ,0 ,0 );
+
+ inherited Construct(alloc ,src ,@rgba ,interpolator ,filter );
+
+ m_order:=order;
+
+ m_wrap_mode_x:=WX;
+ m_wrap_mode_y:=WY;
+
+ m_wrap_mode_x.init(src._width );
+ m_wrap_mode_y.init(src._height );
+
+end;
+
+{ SOURCE_IMAGE_ }
+procedure span_pattern_resample_rgb.source_image_;
+begin
+ inherited source_image_(src );
+
+ m_wrap_mode_x.init(src._width );
+ m_wrap_mode_y.init(src._height );
+
+end;
+
+{ GENERATE }
+function span_pattern_resample_rgb.generate;
+var
+ span : aggclr_ptr;
+ intr : span_interpolator_ptr;
+
+ fg : array[0..2 ] of int;
+
+ diameter ,filter_size ,rx ,ry ,rx_inv ,ry_inv ,radius_x ,radius_y ,
+ maxx ,maxy ,y_lr ,y_hr ,total_weight ,x_lr_ini ,x_hr_ini ,weight_y ,
+ x_lr ,x_hr ,weight : int;
+
+ row_ptr ,fg_ptr : int8u_ptr;
+
+ weight_array : int16_ptr;
+
+begin
+ span:=_allocator.span;
+ intr:=_interpolator;
+
+ intr.begin_(x + filter_dx_dbl ,y + filter_dy_dbl ,len );
+
+ diameter :=_filter.diameter;
+ filter_size :=diameter shl image_subpixel_shift;
+ weight_array:=_filter.weight_array;
+
+ repeat
+ rx_inv:=image_subpixel_size;
+ ry_inv:=image_subpixel_size;
+
+ intr.coordinates(@x ,@y );
+ intr.local_scale(@rx ,@ry );
+
+ rx:=shr_int32(rx * m_blur_x ,image_subpixel_shift );
+ ry:=shr_int32(ry * m_blur_y ,image_subpixel_shift );
+
+ if rx < image_subpixel_size then
+ rx:=image_subpixel_size
+ else
+ begin
+ if rx > image_subpixel_size * m_scale_limit then
+ rx:=image_subpixel_size * m_scale_limit;
+
+ rx_inv:=image_subpixel_size * image_subpixel_size div rx;
+
+ end;
+
+ if ry < image_subpixel_size then
+ ry:=image_subpixel_size
+ else
+ begin
+ if ry > image_subpixel_size * m_scale_limit then
+ ry:=image_subpixel_size * m_scale_limit;
+
+ ry_inv:=image_subpixel_size * image_subpixel_size div ry;
+
+ end;
+
+ radius_x:=shr_int32(diameter * rx ,1 );
+ radius_y:=shr_int32(diameter * ry ,1 );
+
+ maxx:=_source_image._width - 1;
+ maxy:=_source_image._height - 1;
+
+ inc(x ,filter_dx_int - radius_x );
+ inc(y ,filter_dy_int - radius_y );
+
+ fg[0 ]:=image_filter_size div 2;
+ fg[1 ]:=fg[0 ];
+ fg[2 ]:=fg[0 ];
+
+ y_lr:=m_wrap_mode_y.func_operator(shr_int32(y ,image_subpixel_shift ) );
+ y_hr:=
+ shr_int32(
+ (image_subpixel_mask - (y and image_subpixel_mask ) ) *
+ ry_inv ,image_subpixel_shift );
+
+ total_weight:=0;
+
+ x_lr_ini:=shr_int32(x ,image_subpixel_shift );
+ x_hr_ini:=
+ shr_int32(
+ (image_subpixel_mask - (x and image_subpixel_mask ) ) *
+ rx_inv ,image_subpixel_shift );
+
+ repeat
+ weight_y:=int16_ptr(ptrcomp(weight_array ) + y_hr * sizeof(int16 ) )^;
+
+ x_lr:=m_wrap_mode_x.func_operator(x_lr_ini );
+ x_hr:=x_hr_ini;
+
+ row_ptr:=_source_image.row(y_lr );
+
+ repeat
+ fg_ptr:=int8u_ptr(ptrcomp(row_ptr ) + x_lr * 3 * sizeof(int8u ) );
+ weight:=
+ shr_int32(
+ weight_y *
+ int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,downscale_shift );
+
+ inc(fg[0 ] ,fg_ptr^ * weight ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,fg_ptr^ * weight ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,fg_ptr^ * weight );
+ inc(total_weight ,weight );
+ inc(x_hr ,rx_inv );
+
+ x_lr:=m_wrap_mode_x.inc_operator;
+
+ until x_hr >= filter_size;
+
+ inc(y_hr ,ry_inv );
+
+ y_lr:=m_wrap_mode_y.inc_operator;
+
+ until y_hr >= filter_size;
+
+ fg[0 ]:=fg[0 ] div total_weight;
+ fg[1 ]:=fg[1 ] div total_weight;
+ fg[2 ]:=fg[2 ] div total_weight;
+
+ if fg[0 ] < 0 then
+ fg[0 ]:=0;
+
+ if fg[1 ] < 0 then
+ fg[1 ]:=0;
+
+ if fg[2 ] < 0 then
+ fg[2 ]:=0;
+
+ if fg[0 ] > base_mask then
+ fg[0 ]:=base_mask;
+
+ if fg[1 ] > base_mask then
+ fg[1 ]:=base_mask;
+
+ if fg[2 ] > base_mask then
+ fg[2 ]:=base_mask;
+
+ span.r:=int8u(fg[m_order.R] );
+ span.g:=int8u(fg[m_order.G] );
+ span.b:=int8u(fg[m_order.B] );
+ span.a:=int8u(base_mask );
+
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+
+ intr.inc_operator;
+
+ dec(len );
+
+ until len = 0;
+
+ result:=_allocator.span;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_span_pattern_resample_rgba.pas b/src/corelib/render/software/agg_span_pattern_resample_rgba.pas
new file mode 100644
index 00000000..368af182
--- /dev/null
+++ b/src/corelib/render/software/agg_span_pattern_resample_rgba.pas
@@ -0,0 +1,506 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 06.03.2006-Milano: Unit port establishment
+//
+{ agg_span_pattern_resample_rgba.pas {untested}
+unit
+ agg_span_pattern_resample_rgba ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+{$Q- }
+{$R- }
+uses
+ agg_basics ,
+ agg_color ,
+ agg_span_pattern ,
+ agg_span_image_resample ,
+ agg_span_interpolator_linear ,
+ agg_rendering_buffer ,
+ agg_span_allocator ,
+ agg_image_filters ;
+
+{ TYPES DEFINITION }
+const
+ base_shift = agg_color.base_shift;
+ base_mask = agg_color.base_mask;
+ downscale_shift = image_filter_shift;
+
+type
+ span_pattern_resample_rgba_affine_ptr = ^span_pattern_resample_rgba_affine;
+ span_pattern_resample_rgba_affine = object(span_image_resample_affine )
+ m_wrap_mode_x ,
+ m_wrap_mode_y : wrap_mode_ptr;
+
+ m_order : order_type;
+
+ constructor Construct(alloc : span_allocator_ptr; WX ,WY : wrap_mode_ptr; order : order_type ); overload;
+ constructor Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ interpolator : span_interpolator_ptr;
+ filter : image_filter_lut_ptr;
+ WX ,WY : wrap_mode_ptr;
+ order : order_type ); overload;
+
+ procedure source_image_(src : rendering_buffer_ptr );
+
+ function generate(x ,y : int; len : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+ span_pattern_resample_rgba_ptr = ^span_pattern_resample_rgba;
+ span_pattern_resample_rgba = object(span_image_resample )
+ m_wrap_mode_x ,
+ m_wrap_mode_y : wrap_mode_ptr;
+
+ m_order : order_type;
+
+ constructor Construct(alloc : span_allocator_ptr; WX ,WY : wrap_mode_ptr; order : order_type ); overload;
+ constructor Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ interpolator : span_interpolator_ptr;
+ filter : image_filter_lut_ptr;
+ WX ,WY : wrap_mode_ptr;
+ order : order_type ); overload;
+
+ procedure source_image_(src : rendering_buffer_ptr );
+
+ function generate(x ,y : int; len : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor span_pattern_resample_rgba_affine.Construct(alloc : span_allocator_ptr; WX ,WY : wrap_mode_ptr; order : order_type );
+begin
+ inherited Construct(alloc );
+
+ m_order:=order;
+
+ m_wrap_mode_x:=WX;
+ m_wrap_mode_y:=WY;
+
+ m_wrap_mode_x.init(1 );
+ m_wrap_mode_y.init(1 );
+
+end;
+
+{ CONSTRUCT }
+constructor span_pattern_resample_rgba_affine.Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ interpolator : span_interpolator_ptr;
+ filter : image_filter_lut_ptr;
+ WX ,WY : wrap_mode_ptr;
+ order : order_type );
+var
+ rgba : aggclr;
+
+begin
+ rgba.ConstrInt(0 ,0 ,0 ,0 );
+
+ inherited Construct(alloc ,src ,@rgba ,interpolator ,filter );
+
+ m_order:=order;
+
+ m_wrap_mode_x:=WX;
+ m_wrap_mode_y:=WY;
+
+ m_wrap_mode_x.init(src._width );
+ m_wrap_mode_y.init(src._height );
+
+end;
+
+{ SOURCE_IMAGE_ }
+procedure span_pattern_resample_rgba_affine.source_image_;
+begin
+ inherited source_image_(src );
+
+ m_wrap_mode_x.init(src._width );
+ m_wrap_mode_y.init(src._height );
+
+end;
+
+{ GENERATE }
+function span_pattern_resample_rgba_affine.generate;
+var
+ span : aggclr_ptr;
+ intr : span_interpolator_ptr;
+
+ fg : array[0..3 ] of int;
+
+ diameter ,filter_size ,radius_x ,radius_y ,maxx ,maxy ,y_lr ,y_hr ,
+ total_weight ,x_lr_ini ,x_hr_ini ,weight_y ,x_lr ,x_hr ,weight : int;
+
+ row_ptr ,fg_ptr : int8u_ptr;
+
+ weight_array : int16_ptr;
+
+begin
+ span:=_allocator.span;
+ intr:=_interpolator;
+
+ intr.begin_(x + filter_dx_dbl ,y + filter_dy_dbl ,len );
+
+ diameter :=_filter.diameter;
+ filter_size:=diameter shl image_subpixel_shift;
+
+ radius_x:=shr_int32(diameter * m_rx ,1 );
+ radius_y:=shr_int32(diameter * m_ry ,1 );
+
+ maxx:=_source_image._width - 1;
+ maxy:=_source_image._height - 1;
+
+ weight_array:=_filter.weight_array;
+
+ repeat
+ intr.coordinates(@x ,@y );
+
+ inc(x ,filter_dx_int - radius_x );
+ inc(y ,filter_dy_int - radius_y );
+
+ fg[0 ]:=image_filter_size div 2;
+ fg[1 ]:=fg[0 ];
+ fg[2 ]:=fg[0 ];
+ fg[3 ]:=fg[0 ];
+
+ y_lr:=m_wrap_mode_y.func_operator(shr_int32(y ,image_subpixel_shift ) );
+ y_hr:=
+ shr_int32(
+ (image_subpixel_mask - (y and image_subpixel_mask ) ) *
+ m_ry_inv ,image_subpixel_shift );
+
+ total_weight:=0;
+
+ x_lr_ini:=shr_int32(x ,image_subpixel_shift );
+ x_hr_ini:=
+ shr_int32(
+ (image_subpixel_mask - (x and image_subpixel_mask ) ) *
+ m_rx_inv ,image_subpixel_shift );
+
+ repeat
+ weight_y:=int16_ptr(ptrcomp(weight_array ) + y_hr * sizeof(int16 ) )^;
+
+ x_lr:=m_wrap_mode_x.func_operator(x_lr_ini );
+ x_hr:=x_hr_ini;
+
+ row_ptr:=_source_image.row(y_lr );
+
+ repeat
+ fg_ptr:=int8u_ptr(ptrcomp(row_ptr ) + (x_lr shl 2 ) * sizeof(int8u ) );
+ weight:=
+ shr_int32(
+ weight_y *
+ int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,downscale_shift );
+
+ inc(fg[0 ] ,fg_ptr^ * weight ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,fg_ptr^ * weight ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,fg_ptr^ * weight ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[3 ] ,fg_ptr^ * weight );
+ inc(total_weight ,weight );
+ inc(x_hr ,m_rx_inv );
+
+ x_lr:=m_wrap_mode_x.inc_operator;
+
+ until x_hr >= filter_size;
+
+ inc(y_hr ,m_ry_inv );
+
+ y_lr:=m_wrap_mode_y.inc_operator;
+
+ until y_hr >= filter_size;
+
+ fg[0 ]:=fg[0 ] div total_weight;
+ fg[1 ]:=fg[1 ] div total_weight;
+ fg[2 ]:=fg[2 ] div total_weight;
+ fg[3 ]:=fg[3 ] div total_weight;
+
+ if fg[0 ] < 0 then
+ fg[0 ]:=0;
+
+ if fg[1 ] < 0 then
+ fg[1 ]:=0;
+
+ if fg[2 ] < 0 then
+ fg[2 ]:=0;
+
+ if fg[3 ] < 0 then
+ fg[3 ]:=0;
+
+ if fg[m_order.A ] > base_mask then
+ fg[m_order.A ]:=base_mask;
+
+ if fg[m_order.R ] > fg[m_order.A ] then
+ fg[m_order.R ]:=fg[m_order.A ];
+
+ if fg[m_order.G ] > fg[m_order.A ] then
+ fg[m_order.G ]:=fg[m_order.A ];
+
+ if fg[m_order.B ] > fg[m_order.A ] then
+ fg[m_order.B ]:=fg[m_order.A ];
+
+ span.r:=int8u(fg[m_order.R ] );
+ span.g:=int8u(fg[m_order.G ] );
+ span.b:=int8u(fg[m_order.B ] );
+ span.a:=int8u(fg[m_order.A ] );
+
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+
+ intr.inc_operator;
+
+ dec(len );
+
+ until len = 0;
+
+ result:=_allocator.span;
+
+end;
+
+{ CONSTRUCT }
+constructor span_pattern_resample_rgba.Construct(alloc : span_allocator_ptr; WX ,WY : wrap_mode_ptr; order : order_type );
+begin
+ inherited Construct(alloc );
+
+ m_order:=order;
+
+ m_wrap_mode_x:=WX;
+ m_wrap_mode_y:=WY;
+
+ m_wrap_mode_x.init(1 );
+ m_wrap_mode_y.init(1 );
+
+end;
+
+{ CONSTRUCT }
+constructor span_pattern_resample_rgba.Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ interpolator : span_interpolator_ptr;
+ filter : image_filter_lut_ptr;
+ WX ,WY : wrap_mode_ptr;
+ order : order_type );
+var
+ rgba : aggclr;
+
+begin
+ rgba.ConstrInt(0 ,0 ,0 ,0 );
+
+ inherited Construct(alloc ,src ,@rgba ,interpolator ,filter );
+
+ m_order:=order;
+
+ m_wrap_mode_x:=WX;
+ m_wrap_mode_y:=WY;
+
+ m_wrap_mode_x.init(src._width );
+ m_wrap_mode_y.init(src._height );
+
+end;
+
+{ SOURCE_IMAGE_ }
+procedure span_pattern_resample_rgba.source_image_;
+begin
+ inherited source_image_(src );
+
+ m_wrap_mode_x.init(src._width );
+ m_wrap_mode_y.init(src._height );
+
+end;
+
+{ GENERATE }
+function span_pattern_resample_rgba.generate;
+var
+ span : aggclr_ptr;
+ intr : span_interpolator_ptr;
+
+ fg : array[0..3 ] of int;
+
+ diameter ,filter_size ,rx ,ry ,rx_inv ,ry_inv ,radius_x ,radius_y ,maxx ,maxy ,
+ y_lr ,y_hr ,total_weight ,x_lr_ini ,x_hr_ini ,weight_y ,x_lr ,x_hr ,weight : int;
+
+ row_ptr ,fg_ptr : int8u_ptr;
+
+ weight_array : int16_ptr;
+
+begin
+ span:=_allocator.span;
+ intr:=_interpolator;
+
+ intr.begin_(x + filter_dx_dbl ,y + filter_dy_dbl ,len );
+
+ diameter :=_filter.diameter;
+ filter_size:=diameter shl image_subpixel_shift;
+
+ weight_array:=_filter.weight_array;
+
+ repeat
+ rx_inv:=image_subpixel_size;
+ ry_inv:=image_subpixel_size;
+
+ intr.coordinates(@x ,@y );
+ intr.local_scale(@rx ,@ry );
+
+ rx:=shr_int32(rx * m_blur_x ,image_subpixel_shift );
+ ry:=shr_int32(ry * m_blur_y ,image_subpixel_shift );
+
+ if rx < image_subpixel_size then
+ rx:=image_subpixel_size
+ else
+ begin
+ if rx > image_subpixel_size * m_scale_limit then
+ rx:=image_subpixel_size * m_scale_limit;
+
+ rx_inv:=image_subpixel_size * image_subpixel_size div rx;
+
+ end;
+
+ if ry < image_subpixel_size then
+ ry:=image_subpixel_size
+ else
+ begin
+ if ry > image_subpixel_size * m_scale_limit then
+ ry:=image_subpixel_size * m_scale_limit;
+
+ ry_inv:=image_subpixel_size * image_subpixel_size div ry;
+
+ end;
+
+ radius_x:=shr_int32(diameter * rx ,1 );
+ radius_y:=shr_int32(diameter * ry ,1 );
+
+ maxx:=_source_image._width - 1;
+ maxy:=_source_image._height - 1;
+
+ inc(x ,filter_dx_int - radius_x );
+ inc(y ,filter_dy_int - radius_y );
+
+ fg[0 ]:=image_filter_size div 2;
+ fg[1 ]:=fg[0 ];
+ fg[2 ]:=fg[0 ];
+ fg[3 ]:=fg[0 ];
+
+ y_lr:=m_wrap_mode_y.func_operator(shr_int32(y ,image_subpixel_shift ) );
+ y_hr:=
+ shr_int32(
+ (image_subpixel_mask - (y and image_subpixel_mask ) ) *
+ ry_inv ,image_subpixel_shift );
+
+ total_weight:=0;
+
+ x_lr_ini:=shr_int32(x ,image_subpixel_shift );
+ x_hr_ini:=
+ shr_int32(
+ (image_subpixel_mask - (x and image_subpixel_mask ) ) *
+ rx_inv ,image_subpixel_shift );
+
+ repeat
+ weight_y:=int16_ptr(ptrcomp(weight_array ) + y_hr * sizeof(int16 ) )^;
+
+ x_lr:=m_wrap_mode_x.func_operator(x_lr_ini );
+ x_hr:=x_hr_ini;
+
+ row_ptr:=_source_image.row(y_lr );
+
+ repeat
+ fg_ptr:=int8u_ptr(ptrcomp(row_ptr ) + (x_lr shl 2 ) * sizeof(int8u ) );
+ weight:=
+ shr_int32(
+ weight_y *
+ int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ +
+ image_filter_size div 2 ,downscale_shift );
+
+ inc(fg[0 ] ,fg_ptr^ * weight ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[1 ] ,fg_ptr^ * weight ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[2 ] ,fg_ptr^ * weight ); inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
+ inc(fg[3 ] ,fg_ptr^ * weight );
+ inc(total_weight ,weight );
+ inc(x_hr ,rx_inv );
+
+ x_lr:=m_wrap_mode_x.inc_operator;
+
+ until x_hr >= filter_size;
+
+ inc(y_hr ,ry_inv );
+
+ y_lr:=m_wrap_mode_y.inc_operator;
+
+ until y_hr >= filter_size;
+
+ fg[0 ]:=fg[0 ] div total_weight;
+ fg[1 ]:=fg[1 ] div total_weight;
+ fg[2 ]:=fg[2 ] div total_weight;
+ fg[3 ]:=fg[3 ] div total_weight;
+
+ if fg[0 ] < 0 then
+ fg[0 ]:=0;
+
+ if fg[1 ] < 0 then
+ fg[1 ]:=0;
+
+ if fg[2 ] < 0 then
+ fg[2 ]:=0;
+
+ if fg[3 ] < 0 then
+ fg[3 ]:=0;
+
+ if fg[m_order.A ] > base_mask then
+ fg[m_order.A ]:=base_mask;
+
+ if fg[m_order.R ] > fg[m_order.A ] then
+ fg[m_order.R ]:=fg[m_order.A ];
+
+ if fg[m_order.G ] > fg[m_order.A ] then
+ fg[m_order.G ]:=fg[m_order.A ];
+
+ if fg[m_order.B ] > fg[m_order.A ] then
+ fg[m_order.B ]:=fg[m_order.A ];
+
+ span.r:=int8u(fg[m_order.R ] );
+ span.g:=int8u(fg[m_order.G ] );
+ span.b:=int8u(fg[m_order.B ] );
+ span.a:=int8u(fg[m_order.A ] );
+
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+
+ intr.inc_operator;
+
+ dec(len );
+
+ until len = 0;
+
+ result:=_allocator.span;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_span_pattern_rgb.pas b/src/corelib/render/software/agg_span_pattern_rgb.pas
new file mode 100644
index 00000000..3ead2d05
--- /dev/null
+++ b/src/corelib/render/software/agg_span_pattern_rgb.pas
@@ -0,0 +1,167 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// Adaptation for high precision colors has been sponsored by
+// Liberty Technology Systems, Inc., visit http://lib-sys.com
+//
+// Liberty Technology Systems, Inc. is the provider of
+// PostScript and PDF technology for software developers.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 06.03.2006-Milano: Unit port establishment
+//
+{ agg_span_pattern_rgb.pas {untested}
+unit
+ agg_span_pattern_rgb ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+{$Q- }
+{$R- }
+uses
+ agg_basics ,
+ agg_color ,
+ agg_pixfmt ,
+ agg_pixfmt_rgb ,
+ agg_span_pattern ,
+ agg_span_allocator ,
+ agg_rendering_buffer ;
+
+{ TYPES DEFINITION }
+const
+ base_shift = agg_color.base_shift;
+ base_mask = agg_color.base_mask;
+
+type
+ span_pattern_rgb_ptr = ^span_pattern_rgb;
+ span_pattern_rgb = object(span_pattern_base )
+ m_wrap_mode_x ,
+ m_wrap_mode_y : wrap_mode_ptr;
+
+ m_order : order_type;
+
+ constructor Construct(alloc : span_allocator_ptr; WX ,WY : wrap_mode_ptr; order : order_type ); overload;
+ constructor Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ offset_x ,offset_y : unsigned;
+ WX ,WY : wrap_mode_ptr;
+ order : order_type;
+ alpha : int8u = base_mask ); overload;
+
+ procedure source_image_(src : rendering_buffer_ptr );
+
+ function generate(x ,y : int; len : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor span_pattern_rgb.Construct(alloc : span_allocator_ptr; WX ,WY : wrap_mode_ptr; order : order_type );
+begin
+ inherited Construct(alloc );
+
+ m_order:=order;
+
+ m_wrap_mode_x:=WX;
+ m_wrap_mode_y:=WY;
+
+ m_wrap_mode_x.init(1 );
+ m_wrap_mode_y.init(1 );
+
+end;
+
+{ CONSTRUCT }
+constructor span_pattern_rgb.Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ offset_x ,offset_y : unsigned;
+ WX ,WY : wrap_mode_ptr;
+ order : order_type;
+ alpha : int8u = base_mask );
+begin
+ inherited Construct(alloc ,src ,offset_x ,offset_y ,alpha );
+
+ m_order:=order;
+
+ m_wrap_mode_x:=WX;
+ m_wrap_mode_y:=WY;
+
+ m_wrap_mode_x.init(src._width );
+ m_wrap_mode_y.init(src._height );
+
+end;
+
+{ SOURCE_IMAGE_ }
+procedure span_pattern_rgb.source_image_;
+begin
+ inherited source_image_(src );
+
+ m_wrap_mode_x.init(src._width );
+ m_wrap_mode_y.init(src._height );
+
+end;
+
+{ GENERATE }
+function span_pattern_rgb.generate;
+var
+ span : aggclr_ptr;
+
+ sx : unsigned;
+
+ row_ptr ,p : int8u_ptr;
+
+begin
+ span:=_allocator.span;
+ sx :=m_wrap_mode_x.func_operator(_offset_x + x );
+
+ row_ptr:=_source_image.row(m_wrap_mode_y.func_operator(_offset_y + y ) );
+
+ repeat
+ p:=int8u_ptr(ptrcomp(row_ptr ) + (sx + sx + sx ) * sizeof(int8u ) );
+
+ span.r:=int8u_ptr(ptrcomp(p ) + m_order.R * sizeof(int8u ) )^;
+ span.g:=int8u_ptr(ptrcomp(p ) + m_order.G * sizeof(int8u ) )^;
+ span.b:=int8u_ptr(ptrcomp(p ) + m_order.B * sizeof(int8u ) )^;
+ span.a:=_alpha_int;
+
+ sx:=m_wrap_mode_x.inc_operator;
+
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+ result:=_allocator.span;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_span_pattern_rgba.pas b/src/corelib/render/software/agg_span_pattern_rgba.pas
new file mode 100644
index 00000000..b2b7e91d
--- /dev/null
+++ b/src/corelib/render/software/agg_span_pattern_rgba.pas
@@ -0,0 +1,165 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// Adaptation for high precision colors has been sponsored by
+// Liberty Technology Systems, Inc., visit http://lib-sys.com
+//
+// Liberty Technology Systems, Inc. is the provider of
+// PostScript and PDF technology for software developers.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 28.02.2006-Milano: Unit port establishment
+//
+{ agg_span_pattern_rgba.pas }
+unit
+ agg_span_pattern_rgba ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+{$Q- }
+{$R- }
+uses
+ agg_basics ,
+ agg_color ,
+ agg_pixfmt ,
+ agg_pixfmt_rgba ,
+ agg_span_pattern ,
+ agg_span_allocator ,
+ agg_rendering_buffer ;
+
+{ TYPES DEFINITION }
+const
+ base_shift = agg_color.base_shift;
+ base_mask = agg_color.base_mask;
+
+type
+ span_pattern_rgba_ptr = ^span_pattern_rgba;
+ span_pattern_rgba = object(span_pattern_base )
+ m_wrap_mode_x ,
+ m_wrap_mode_y : wrap_mode_ptr;
+
+ m_order : order_type;
+
+ constructor Construct(alloc : span_allocator_ptr; WX ,WY : wrap_mode_ptr; order : order_type ); overload;
+ constructor Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ offset_x ,offset_y : unsigned;
+ WX ,WY : wrap_mode_ptr;
+ order : order_type ); overload;
+
+ procedure source_image_(src : rendering_buffer_ptr );
+
+ function generate(x ,y : int; len : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor span_pattern_rgba.Construct(alloc : span_allocator_ptr; WX ,WY : wrap_mode_ptr; order : order_type );
+begin
+ inherited Construct(alloc );
+
+ m_order:=order;
+
+ m_wrap_mode_x:=WX;
+ m_wrap_mode_y:=WY;
+
+ m_wrap_mode_x.init(1 );
+ m_wrap_mode_y.init(1 );
+
+end;
+
+{ CONSTRUCT }
+constructor span_pattern_rgba.Construct(
+ alloc : span_allocator_ptr;
+ src : rendering_buffer_ptr;
+ offset_x ,offset_y : unsigned;
+ WX ,WY : wrap_mode_ptr;
+ order : order_type );
+begin
+ inherited Construct(alloc ,src ,offset_x ,offset_y ,0 );
+
+ m_order:=order;
+
+ m_wrap_mode_x:=WX;
+ m_wrap_mode_y:=WY;
+
+ m_wrap_mode_x.init(src._width );
+ m_wrap_mode_y.init(src._height );
+
+end;
+
+{ SOURCE_IMAGE_ }
+procedure span_pattern_rgba.source_image_;
+begin
+ inherited source_image_(src );
+
+ m_wrap_mode_x.init(src._width );
+ m_wrap_mode_y.init(src._height );
+
+end;
+
+{ GENERATE }
+function span_pattern_rgba.generate;
+var
+ span : aggclr_ptr;
+
+ row_ptr ,p : int8u_ptr;
+
+ sx : unsigned;
+
+begin
+ span:=_allocator.span;
+ sx :=m_wrap_mode_x.func_operator(_offset_x + x );
+
+ row_ptr:=_source_image.row(m_wrap_mode_y.func_operator(_offset_y + y ) );
+
+ repeat
+ p:=int8u_ptr(ptrcomp(row_ptr ) + (sx shl 2 ) * sizeof(int8u ) );
+
+ span.r:=int8u_ptr(ptrcomp(p ) + m_order.R * sizeof(int8u ) )^;
+ span.g:=int8u_ptr(ptrcomp(p ) + m_order.G * sizeof(int8u ) )^;
+ span.b:=int8u_ptr(ptrcomp(p ) + m_order.B * sizeof(int8u ) )^;
+ span.a:=int8u_ptr(ptrcomp(p ) + m_order.A * sizeof(int8u ) )^;
+
+ sx:=m_wrap_mode_x.inc_operator;
+
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+ result:=_allocator.span;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_span_solid.pas b/src/corelib/render/software/agg_span_solid.pas
new file mode 100644
index 00000000..a4cec6d8
--- /dev/null
+++ b/src/corelib/render/software/agg_span_solid.pas
@@ -0,0 +1,109 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// span_solid_rgba8
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 30.01.2006-Milano: Unit port establishment
+//
+{ agg_span_solid.pas }
+unit
+ agg_span_solid ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_span_allocator ,
+ agg_span_generator ,
+ agg_color ;
+
+{ TYPES DEFINITION }
+type
+ span_solid_ptr = ^span_solid;
+ span_solid = object(span_generator )
+ m_color : aggclr;
+
+ constructor Construct(alloc : span_allocator_ptr );
+
+ procedure color_(c : aggclr_ptr );
+ function _color : aggclr_ptr;
+
+ function generate(x ,y : int; len : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor span_solid.Construct;
+begin
+ inherited Construct(alloc );
+
+ m_color.Construct;
+
+end;
+
+{ COLOR_ }
+procedure span_solid.color_;
+begin
+ m_color:=c^;
+
+end;
+
+{ _COLOR }
+function span_solid._color;
+begin
+ result:=@m_color;
+
+end;
+
+{ GENERATE }
+function span_solid.generate;
+var
+ span : aggclr_ptr;
+
+begin
+ span:=_allocator.span;
+
+ repeat
+ span^:=m_color;
+
+ inc(ptrcomp(span ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+ result:=_allocator.span;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_span_subdiv_adaptor.pas b/src/corelib/render/software/agg_span_subdiv_adaptor.pas
new file mode 100644
index 00000000..583d6848
--- /dev/null
+++ b/src/corelib/render/software/agg_span_subdiv_adaptor.pas
@@ -0,0 +1,233 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 04.03.2006-Milano: Unit port establishment
+//
+{ agg_span_subdiv_adaptor.pas }
+unit
+ agg_span_subdiv_adaptor ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_span_interpolator_linear ,
+ agg_trans_affine ;
+
+{ TYPES DEFINITION }
+type
+ span_subdiv_adaptor = object(span_interpolator )
+ m_subdiv_shift ,
+ m_subdiv_size ,
+ m_subdiv_mask : unsigned;
+
+ m_interpolator : span_interpolator_ptr;
+
+ m_src_x : int;
+ m_src_y : double;
+ m_pos ,
+ m_len : unsigned;
+
+ constructor Construct(SS : unsigned = 8 ); overload;
+ constructor Construct(interpolator : span_interpolator_ptr; subdiv_shift : unsigned = 4; SS : unsigned = 8 ); overload;
+ constructor Construct(
+ interpolator : span_interpolator_ptr;
+ x ,y : double; len : unsigned;
+ subdiv_shift : unsigned = 4;
+ SS : unsigned = 8 ); overload;
+
+ function _interpolator : span_interpolator_ptr;
+ procedure interpolator_(intr : span_interpolator_ptr );
+
+ function _transformer : trans_affine_ptr; virtual;
+ procedure transformer_(trans : trans_affine_ptr ); virtual;
+
+ function _subdiv_shift : unsigned;
+ procedure subdiv_shift_(shift : unsigned );
+
+ procedure begin_(x ,y : double; len : unsigned ); virtual;
+
+ procedure inc_operator; virtual;
+ procedure coordinates(x ,y : int_ptr ); virtual;
+
+ procedure local_scale(x ,y : int_ptr ); virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor span_subdiv_adaptor.Construct(SS : unsigned = 8 );
+begin
+ subpixel_shift:=SS;
+ subpixel_size :=1 shl subpixel_shift;
+
+ m_subdiv_shift:=4;
+ m_subdiv_size :=1 shl m_subdiv_shift;
+ m_subdiv_mask :=m_subdiv_size - 1;
+
+ m_interpolator:=NIL;
+
+end;
+
+{ CONSTRUCT }
+constructor span_subdiv_adaptor.Construct(interpolator : span_interpolator_ptr; subdiv_shift : unsigned = 4; SS : unsigned = 8 );
+begin
+ subpixel_shift:=SS;
+ subpixel_size :=1 shl subpixel_shift;
+
+ m_subdiv_shift:=subdiv_shift;
+ m_subdiv_size :=1 shl m_subdiv_shift;
+ m_subdiv_mask :=m_subdiv_size - 1;
+
+ m_interpolator:=interpolator;
+
+end;
+
+{ CONSTRUCT }
+constructor span_subdiv_adaptor.Construct(
+ interpolator : span_interpolator_ptr;
+ x ,y : double; len : unsigned;
+ subdiv_shift : unsigned = 4;
+ SS : unsigned = 8 );
+begin
+ subpixel_shift:=SS;
+ subpixel_size :=1 shl subpixel_shift;
+
+ m_subdiv_shift:=subdiv_shift;
+ m_subdiv_size :=1 shl m_subdiv_shift;
+ m_subdiv_mask :=m_subdiv_size - 1;
+
+ m_interpolator:=interpolator;
+
+ begin_(x ,y ,len );
+
+end;
+
+{ _INTERPOLATOR }
+function span_subdiv_adaptor._interpolator;
+begin
+ result:=m_interpolator;
+
+end;
+
+{ INTERPOLATOR_ }
+procedure span_subdiv_adaptor.interpolator_;
+begin
+ m_interpolator:=intr;
+
+end;
+
+{ _TRANSFORMER }
+function span_subdiv_adaptor._transformer;
+begin
+ result:=m_interpolator._transformer;
+
+end;
+
+{ TRANSFORMER_ }
+procedure span_subdiv_adaptor.transformer_;
+begin
+ m_interpolator.transformer_(trans );
+
+end;
+
+{ _SUBDIV_SHIFT }
+function span_subdiv_adaptor._subdiv_shift;
+begin
+ result:=m_subdiv_shift;
+
+end;
+
+{ SUBDIV_SHIFT_ }
+procedure span_subdiv_adaptor.subdiv_shift_;
+begin
+ m_subdiv_shift:=shift;
+ m_subdiv_size :=1 shl m_subdiv_shift;
+ m_subdiv_mask :=m_subdiv_size - 1;
+
+end;
+
+{ BEGIN_ }
+procedure span_subdiv_adaptor.begin_;
+begin
+ m_pos :=1;
+ m_src_x:=trunc(x * subpixel_size ) + subpixel_size;
+ m_src_y:=y;
+ m_len :=len;
+
+ if len > m_subdiv_size then
+ len:=m_subdiv_size;
+
+ m_interpolator.begin_(x ,y ,len );
+
+end;
+
+{ INC_OPERATOR }
+procedure span_subdiv_adaptor.inc_operator;
+var
+ len : unsigned;
+
+begin
+ m_interpolator.inc_operator;
+
+ if m_pos >= m_subdiv_size then
+ begin
+ len:=m_len;
+
+ if len > m_subdiv_size then
+ len:=m_subdiv_size;
+
+ m_interpolator.resynchronize(m_src_x / subpixel_size + len ,m_src_y ,len );
+
+ m_pos:=0;
+
+ end;
+
+ inc(m_src_x ,subpixel_size );
+ inc(m_pos );
+ dec(m_len );
+
+end;
+
+{ COORDINATES }
+procedure span_subdiv_adaptor.coordinates;
+begin
+ m_interpolator.coordinates(x ,y );
+
+end;
+
+{ LOCAL_SCALE }
+procedure span_subdiv_adaptor.local_scale;
+begin
+ m_interpolator.local_scale(x ,y );
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_trans_affine.pas b/src/corelib/render/software/agg_trans_affine.pas
new file mode 100644
index 00000000..b4bdeb38
--- /dev/null
+++ b/src/corelib/render/software/agg_trans_affine.pas
@@ -0,0 +1,926 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// Affine transformation classes.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 26.10.2007-Milano: Reflection Transformations
+// 27.09.2005-Milano: Complete unit port
+//
+//----------------------------------------------------------------------------
+//
+// Affine transformation are linear transformations in Cartesian coordinates
+// (strictly speaking not only in Cartesian, but for the beginning we will
+// think so). They are rotation, scaling, translation and skewing.
+// After any affine transformation a line segment remains a line segment
+// and it will never become a curve.
+//
+// There will be no math about matrix calculations, since it has been
+// described many times. Ask yourself a very simple question:
+// "why do we need to understand and use some matrix stuff instead of just
+// rotating, scaling and so on". The answers are:
+//
+// 1. Any combination of transformations can be done by only 4 multiplications
+// and 4 additions in floating point.
+// 2. One matrix transformation is equivalent to the number of consecutive
+// discrete transformations, i.e. the matrix "accumulates" all transformations
+// in the order of their settings. Suppose we have 4 transformations:
+// * rotate by 30 degrees,
+// * scale X to 2.0,
+// * scale Y to 1.5,
+// * move to (100, 100).
+// The result will depend on the order of these transformations,
+// and the advantage of matrix is that the sequence of discret calls:
+// rotate(30), scaleX(2.0), scaleY(1.5), move(100,100)
+// will have exactly the same result as the following matrix transformations:
+//
+// affine_matrix m;
+// m *= rotate_matrix(30);
+// m *= scaleX_matrix(2.0);
+// m *= scaleY_matrix(1.5);
+// m *= move_matrix(100,100);
+//
+// m.transform_my_point_at_last(x, y);
+//
+// What is the good of it? In real life we will set-up the matrix only once
+// and then transform many points, let alone the convenience to set any
+// combination of transformations.
+//
+// So, how to use it? Very easy - literally as it's shown above. Not quite,
+// let us write a correct example:
+//
+// agg::trans_affine m;
+// m *= agg::trans_affine_rotation(30.0 * 3.1415926 / 180.0);
+// m *= agg::trans_affine_scaling(2.0, 1.5);
+// m *= agg::trans_affine_translation(100.0, 100.0);
+// m.transform(&x, &y);
+//
+// The affine matrix is all you need to perform any linear transformation,
+// but all transformations have origin point (0,0). It means that we need to
+// use 2 translations if we want to rotate someting around (100,100):
+//
+// m *= agg::trans_affine_translation(-100.0, -100.0); // move to (0,0)
+// m *= agg::trans_affine_rotation(30.0 * 3.1415926 / 180.0); // rotate
+// m *= agg::trans_affine_translation(100.0, 100.0); // move back to (100,100)
+//
+{ agg_trans_affine.pas }
+unit
+ agg_trans_affine ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ Math ,
+ agg_basics ;
+
+{ TYPES DEFINITION }
+const
+ affine_epsilon = 1e-14; // About of precision of doubles
+
+type
+ trans_affine_ptr = ^trans_affine;
+
+ proc_transform = procedure(this : trans_affine_ptr; x ,y : double_ptr );
+
+ parallelo_ptr = ^parallelogram;
+ parallelogram = array[0..5 ] of double;
+
+ trans_affine = object
+ { sx ,shy ,shx ,sy ,tx ,ty }
+ m0 ,m1 ,m2 ,m3 ,m4 ,m5 : double;
+
+ transform ,
+ transform_2x2 ,
+ inverse_transform : proc_transform;
+
+ // Construct an identity matrix - it does not transform anything
+ constructor Construct; overload;
+
+ // Construct a custom matrix. Usually used in derived classes
+ constructor Construct(v0 ,v1 ,v2 ,v3 ,v4 ,v5 : double ); overload;
+
+ // Construct a matrix to transform a parallelogram to another one
+ constructor Construct(rect, parl : parallelo_ptr ); overload;
+
+ // Construct a matrix to transform a rectangle to a parallelogram
+ constructor Construct(x1 ,y1 ,x2 ,y2 : double; parl : parallelo_ptr ); overload;
+
+ // Construct a matrix to transform a parallelogram to a rectangle
+ constructor Construct(parl : parallelo_ptr; x1 ,y1 ,x2 ,y2 : double ); overload;
+
+ // Construct a matrix with different transform function
+ constructor Construct(tr : proc_transform ); overload;
+
+ //---------------------------------- Parallelogram transformations
+ // Calculate a matrix to transform a parallelogram to another one.
+ // src and dst are pointers to arrays of three points
+ // (double[6], x,y,...) that identify three corners of the
+ // parallelograms assuming implicit fourth points.
+ // There are also transformations rectangtle to parallelogram and
+ // parellelogram to rectangle
+ procedure parl_to_parl(src ,dst : parallelo_ptr );
+ procedure rect_to_parl(x1 ,y1 ,x2 ,y2 : double; parl : parallelo_ptr );
+ procedure parl_to_rect(parl : parallelo_ptr; x1 ,y1 ,x2 ,y2 : double );
+
+ //------------------------------------------ Operations
+ // Reset - actually load an identity matrix
+ procedure reset; virtual;
+
+ // Multiply matrix to another one
+ procedure multiply(m : trans_affine_ptr );
+
+ // Multiply "m" to "this" and assign the result to "this"
+ procedure premultiply(m : trans_affine_ptr );
+
+ // Multiply matrix to inverse of another one
+ procedure multiply_inv(m : trans_affine_ptr );
+
+ // Multiply inverse of "m" to "this" and assign the result to "this"
+ procedure premultiply_inv(m : trans_affine_ptr );
+
+ // Invert matrix. Do not try to invert degenerate matrices,
+ // there's no check for validity. If you set scale to 0 and
+ // then try to invert matrix, expect unpredictable result.
+ procedure invert;
+
+ // Mirroring around X
+ procedure flip_x;
+
+ // Mirroring around Y
+ procedure flip_y;
+
+ //------------------------------------------- Load/Store
+ // Store matrix to an array [6] of double
+ procedure store_to(m : parallelo_ptr );
+
+ // Load matrix from an array [6] of double
+ procedure load_from(m : parallelo_ptr );
+
+ //-------------------------------------------- Transformations
+ // Direct transformation x and y
+ // see: transform : proc_transform; above
+
+ // Direct transformation x and y, 2x2 matrix only, no translation
+ // procedure transform_2x2(x ,y : double_ptr );
+
+ // Inverse transformation x and y. It works slower than the
+ // direct transformation, so if the performance is critical
+ // it's better to invert() the matrix and then use transform()
+ // procedure inverse_transform(x ,y : double_ptr );
+
+ //-------------------------------------------- Auxiliary
+ // Calculate the determinant of matrix
+ function determinant : double;
+
+ // Get the average scale (by X and Y).
+ // Basically used to calculate the approximation_scale when
+ // decomposinting curves into line segments.
+ function scale : double; overload;
+
+ // Check to see if it's an identity matrix
+ function is_identity(epsilon : double = affine_epsilon ) : boolean;
+
+ // Check to see if two matrices are equal
+ function is_equal(m : trans_affine; epsilon : double = affine_epsilon ) : boolean;
+
+ // Determine the major parameters. Use carefully considering degenerate matrices
+ function rotation : double;
+ procedure translation(dx ,dy : double_ptr );
+ procedure scaling (sx ,sy : double_ptr );
+ procedure scaling_abs(sx ,sy : double_ptr );
+
+ // Trans Affine Assignations
+ procedure assign (from : trans_affine_ptr );
+ procedure assign_all(from : trans_affine_ptr );
+
+ // Direct transformations operations
+ function translate(x ,y : double ) : trans_affine_ptr;
+ function rotate (a : double ) : trans_affine_ptr;
+ function scale (s : double ) : trans_affine_ptr; overload;
+ function scale (x ,y : double ) : trans_affine_ptr; overload;
+
+ end;
+
+//====================================================trans_affine_rotation
+// Rotation matrix. sin() and cos() are calculated twice for the same angle.
+// There's no harm because the performance of sin()/cos() is very good on all
+// modern processors. Besides, this operation is not going to be invoked too
+// often.
+ trans_affine_rotation = object(trans_affine )
+ constructor Construct(a : double );
+
+ end;
+
+//====================================================trans_affine_scaling
+// Scaling matrix. sx, sy - scale coefficients by X and Y respectively
+ trans_affine_scaling = object(trans_affine )
+ constructor Construct(sx ,sy : double ); overload;
+ constructor Construct(s : double ); overload;
+
+ end;
+
+//================================================trans_affine_translation
+// Translation matrix
+ trans_affine_translation = object(trans_affine )
+ constructor Construct(tx ,ty : double );
+
+ end;
+
+//====================================================trans_affine_skewing
+// Sckewing (shear) matrix
+ trans_affine_skewing = object(trans_affine )
+ constructor Construct(sx ,sy : double );
+
+ end;
+
+//===============================================trans_affine_line_segment
+// Rotate, Scale and Translate, associating 0...dist with line segment
+// x1,y1,x2,y2
+ trans_affine_line_segment = object(trans_affine )
+ constructor Construct(x1 ,y1 ,x2 ,y2 ,dist : double );
+
+ end;
+
+//============================================trans_affine_reflection_unit
+// Reflection matrix. Reflect coordinates across the line through
+// the origin containing the unit vector (ux, uy).
+// Contributed by John Horigan
+ trans_affine_reflection_unit = object(trans_affine )
+ constructor Construct(ux ,uy : double );
+
+ end;
+
+//=================================================trans_affine_reflection
+// Reflection matrix. Reflect coordinates across the line through
+// the origin at the angle a or containing the non-unit vector (x, y).
+// Contributed by John Horigan
+ trans_affine_reflection = object(trans_affine_reflection_unit )
+ constructor Construct(a : double ); overload;
+ constructor Construct(x ,y : double ); overload;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+ function is_equal_eps(v1 ,v2 ,epsilon : double ) : boolean;
+
+
+IMPLEMENTATION
+{ UNIT IMPLEMENTATION }
+{ is_equal_eps }
+function is_equal_eps;
+begin
+ result:=Abs(v1 - v2 ) < epsilon;
+
+end;
+
+{ trans_affine_transform }
+procedure trans_affine_transform(this : trans_affine_ptr; x ,y : double_ptr );
+var
+ tx : double;
+
+begin
+ tx:=x^;
+ x^:=tx * this.m0 + y^ * this.m2 + this.m4;
+ y^:=tx * this.m1 + y^ * this.m3 + this.m5;
+
+end;
+
+{ trans_affine_transform_2x2 }
+procedure trans_affine_transform_2x2(this : trans_affine_ptr; x ,y : double_ptr );
+var
+ tx : double;
+
+begin
+ tx:=x^;
+ x^:=tx * this.m0 + y^ * this.m2;
+ y^:=tx * this.m1 + y^ * this.m3;
+
+end;
+
+{ trans_affine_inverse_transform }
+procedure trans_affine_inverse_transform(this : trans_affine_ptr; x ,y : double_ptr );
+var
+ d ,a ,b : double;
+
+begin
+ d:=this.determinant;
+ a:=(x^ - this.m4 ) * d;
+ b:=(y^ - this.m5 ) * d;
+
+ x^:=a * this.m3 - b * this.m2;
+ y^:=b * this.m0 - a * this.m1;
+
+end;
+
+{ CONSTRUCT }
+constructor trans_affine.Construct;
+begin
+ m0:=1;
+ m1:=0;
+ m2:=0;
+ m3:=1;
+ m4:=0;
+ m5:=0;
+
+ transform :=@trans_affine_transform;
+ transform_2x2 :=@trans_affine_transform_2x2;
+ inverse_transform:=@trans_affine_inverse_transform;
+
+end;
+
+{ CONSTRUCT }
+constructor trans_affine.Construct(v0 ,v1 ,v2 ,v3 ,v4 ,v5 : double );
+begin
+ m0:=v0;
+ m1:=v1;
+ m2:=v2;
+ m3:=v3;
+ m4:=v4;
+ m5:=v5;
+
+ transform :=@trans_affine_transform;
+ transform_2x2 :=@trans_affine_transform_2x2;
+ inverse_transform:=@trans_affine_inverse_transform;
+
+end;
+
+{ CONSTRUCT }
+constructor trans_affine.Construct(rect, parl : parallelo_ptr );
+begin
+ parl_to_parl(rect ,parl );
+
+ transform :=@trans_affine_transform;
+ transform_2x2 :=@trans_affine_transform_2x2;
+ inverse_transform:=@trans_affine_inverse_transform;
+
+end;
+
+{ CONSTRUCT }
+constructor trans_affine.Construct(x1 ,y1 ,x2 ,y2 : double; parl : parallelo_ptr );
+begin
+ rect_to_parl(x1 ,y1 ,x2 ,y2 ,parl );
+
+ transform :=@trans_affine_transform;
+ transform_2x2 :=@trans_affine_transform_2x2;
+ inverse_transform:=@trans_affine_inverse_transform;
+
+end;
+
+{ CONSTRUCT }
+constructor trans_affine.Construct(parl : parallelo_ptr; x1 ,y1 ,x2 ,y2 : double );
+begin
+ parl_to_rect(parl ,x1 ,y1 ,x2 ,y2 );
+
+ transform :=@trans_affine_transform;
+ transform_2x2 :=@trans_affine_transform_2x2;
+ inverse_transform:=@trans_affine_inverse_transform;
+
+end;
+
+{ CONSTRUCT }
+constructor trans_affine.Construct(tr : proc_transform );
+begin
+ m0:=1;
+ m1:=0;
+ m2:=0;
+ m3:=1;
+ m4:=0;
+ m5:=0;
+
+ transform :=tr;
+ transform_2x2 :=@trans_affine_transform_2x2;
+ inverse_transform:=@trans_affine_inverse_transform;
+
+end;
+
+{ parl_to_parl }
+procedure trans_affine.parl_to_parl;
+var
+ m : trans_affine;
+
+begin
+ m0:=src[2 ] - src[0 ];
+ m1:=src[3 ] - src[1 ];
+ m2:=src[4 ] - src[0 ];
+ m3:=src[5 ] - src[1 ];
+ m4:=src[0 ];
+ m5:=src[1 ];
+
+ invert;
+
+ m.Construct(
+ dst[2 ] - dst[0 ] ,
+ dst[3 ] - dst[1 ] ,
+ dst[4 ] - dst[0 ] ,
+ dst[5 ] - dst[1 ] ,
+ dst[0 ] ,
+ dst[1 ] );
+
+ multiply(@m );
+
+end;
+
+{ rect_to_parl }
+procedure trans_affine.rect_to_parl;
+var
+ src : parallelogram;
+
+begin
+ src[0 ]:=x1;
+ src[1 ]:=y1;
+ src[2 ]:=x2;
+ src[3 ]:=y1;
+ src[4 ]:=x2;
+ src[5 ]:=y2;
+
+ parl_to_parl(@src ,parl );
+
+end;
+
+{ parl_to_rect }
+procedure trans_affine.parl_to_rect;
+var
+ dst : parallelogram;
+
+begin
+ dst[0 ]:=x1;
+ dst[1 ]:=y1;
+ dst[2 ]:=x2;
+ dst[3 ]:=y1;
+ dst[4 ]:=x2;
+ dst[5 ]:=y2;
+
+ parl_to_parl(parl ,@dst );
+
+end;
+
+{ reset }
+procedure trans_affine.reset;
+begin
+ m0:=1;
+ m1:=0;
+ m2:=0;
+ m3:=1;
+ m4:=0;
+ m5:=0;
+
+end;
+
+{ multiply }
+procedure trans_affine.multiply;
+var
+ t0 ,t2 ,t4 : double;
+
+begin
+ t0:=m0 * m.m0 + m1 * m.m2;
+ t2:=m2 * m.m0 + m3 * m.m2;
+ t4:=m4 * m.m0 + m5 * m.m2 + m.m4;
+ m1:=m0 * m.m1 + m1 * m.m3;
+ m3:=m2 * m.m1 + m3 * m.m3;
+ m5:=m4 * m.m1 + m5 * m.m3 + m.m5;
+ m0:=t0;
+ m2:=t2;
+ m4:=t4;
+
+end;
+
+{ premultiply }
+procedure trans_affine.premultiply;
+var
+ t : trans_affine;
+
+begin
+ t.assign_all(m );
+
+ t.multiply(@self );
+
+ assign(@t );
+
+end;
+
+{ multiply_inv }
+procedure trans_affine.multiply_inv;
+var
+ t : trans_affine;
+
+begin
+ t.assign_all(m );
+ t.invert;
+
+ multiply(@t );
+
+end;
+
+{ premultiply_inv }
+procedure trans_affine.premultiply_inv;
+var
+ t : trans_affine;
+
+begin
+ t.assign_all(m );
+
+ t.invert;
+ t.multiply(@self );
+
+ assign(@t );
+
+end;
+
+{ invert }
+procedure trans_affine.invert;
+var
+ d ,t0 ,t4 : double;
+
+begin
+ d:=determinant;
+
+ t0:= m3 * d;
+ m3:= m0 * d;
+ m1:=-m1 * d;
+ m2:=-m2 * d;
+
+ t4:=-m4 * t0 - m5 * m2;
+ m5:=-m4 * m1 - m5 * m3;
+
+ m0:=t0;
+ m4:=t4;
+
+end;
+
+{ flip_x }
+procedure trans_affine.flip_x;
+begin
+ m0:=-m0;
+ m1:=-m1;
+ m4:=-m4;
+
+end;
+
+{ flip_y }
+procedure trans_affine.flip_y;
+begin
+ m2:=-m2;
+ m3:=-m3;
+ m5:=-m5;
+
+end;
+
+{ store_to }
+procedure trans_affine.store_to;
+begin
+ m[0 ]:=m0;
+ m[1 ]:=m1;
+ m[2 ]:=m2;
+ m[3 ]:=m3;
+ m[4 ]:=m4;
+ m[5 ]:=m5;
+
+end;
+
+{ load_from }
+procedure trans_affine.load_from;
+begin
+ m0:=m[0 ];
+ m1:=m[1 ];
+ m2:=m[2 ];
+ m3:=m[3 ];
+ m4:=m[4 ];
+ m5:=m[5 ];
+
+end;
+
+{ determinant }
+function trans_affine.determinant;
+begin
+ try
+ result:=1 / (m0 * m3 - m1 * m2 );
+
+ except
+ result:=0;
+
+ end;
+
+end;
+
+{ scale }
+function trans_affine.scale : double;
+var
+ x ,y : double;
+
+begin
+ x:=0.707106781 * m0 + 0.707106781 * m2;
+ y:=0.707106781 * m1 + 0.707106781 * m3;
+
+ result:=Sqrt(x * x + y * y );
+
+end;
+
+{ is_identity }
+function trans_affine.is_identity;
+begin
+ result:=
+ is_equal_eps(m0 ,1 ,epsilon ) and
+ is_equal_eps(m1 ,0 ,epsilon ) and
+ is_equal_eps(m2 ,0 ,epsilon ) and
+ is_equal_eps(m3 ,1 ,epsilon ) and
+ is_equal_eps(m4 ,0 ,epsilon ) and
+ is_equal_eps(m5 ,0 ,epsilon );
+
+end;
+
+{ is_equal }
+function trans_affine.is_equal;
+begin
+ result:=
+ is_equal_eps(m0 ,m.m0 ,epsilon ) and
+ is_equal_eps(m1 ,m.m1 ,epsilon ) and
+ is_equal_eps(m2 ,m.m2 ,epsilon ) and
+ is_equal_eps(m3 ,m.m3 ,epsilon ) and
+ is_equal_eps(m4 ,m.m4 ,epsilon ) and
+ is_equal_eps(m5 ,m.m5 ,epsilon );
+
+end;
+
+{ rotation }
+function trans_affine.rotation;
+var
+ x1 ,y1 ,x2 ,y2 : double;
+
+begin
+ x1:=0;
+ y1:=0;
+ x2:=1;
+ y2:=0;
+
+ transform(@self ,@x1 ,@y1 );
+ transform(@self ,@x2 ,@y2 );
+
+ result:=ArcTan2(y2 - y1 ,x2 - x1 );
+
+end;
+
+{ translation }
+procedure trans_affine.translation;
+begin
+ dx:=0;
+ dy:=0;
+
+ transform(@self ,@dx ,@dy );
+
+end;
+
+{ scaling }
+procedure trans_affine.scaling;
+var
+ t : trans_affine_rotation;
+
+ x1 ,y1 ,x2 ,y2 : double;
+
+begin
+ x1:=0;
+ y1:=0;
+ x2:=1;
+ y2:=1;
+
+ trans_affine(t ):=self;
+
+ t.Construct(-rotation );
+
+ t.transform(@self ,@x1 ,@y1 );
+ t.transform(@self ,@x2 ,@y2 );
+
+ sx^:=x2 - x1;
+ sy^:=y2 - y1;
+
+end;
+
+{ scaling_abs }
+procedure trans_affine.scaling_abs;
+begin
+ sx^:=Sqrt(m0 * m0 + m2 * m2 );
+ sy^:=Sqrt(m1 * m1 + m3 * m3 );
+
+end;
+
+{ ASSIGN }
+procedure trans_affine.assign;
+begin
+ m0:=from.m0;
+ m1:=from.m1;
+ m2:=from.m2;
+ m3:=from.m3;
+ m4:=from.m4;
+ m5:=from.m5;
+
+end;
+
+{ ASSIGN_ALL }
+procedure trans_affine.assign_all;
+begin
+ m0:=from.m0;
+ m1:=from.m1;
+ m2:=from.m2;
+ m3:=from.m3;
+ m4:=from.m4;
+ m5:=from.m5;
+
+ transform :=@from.transform;
+ transform_2x2 :=@from.transform_2x2;
+ inverse_transform:=@from.inverse_transform;
+
+end;
+
+{ TRANSLATE }
+function trans_affine.translate(x ,y : double ) : trans_affine_ptr;
+begin
+ m4:=m4 + x;
+ m5:=m5 + y;
+
+ result:=@self;
+
+end;
+
+{ ROTATE }
+function trans_affine.rotate(a : double ) : trans_affine_ptr;
+var
+ ca ,sa ,t0 ,t2 ,t4 : double;
+
+begin
+ ca:=Cos(a);
+ sa:=Sin(a);
+ t0:=m0 * ca - m1 * sa;
+ t2:=m2 * ca - m3 * sa;
+ t4:=m4 * ca - m5 * sa;
+
+ m1:=m0 * sa + m1 * ca;
+ m3:=m2 * sa + m3 * ca;
+ m5:=m4 * sa + m5 * ca;
+ m0:=t0;
+ m2:=t2;
+ m4:=t4;
+
+ result:=@self;
+
+end;
+
+{ SCALE }
+function trans_affine.scale(s : double ) : trans_affine_ptr;
+begin
+ m0:=m0 * s;
+ m1:=m1 * s;
+ m2:=m2 * s;
+ m3:=m3 * s;
+ m4:=m4 * s;
+ m5:=m5 * s;
+
+ result:=@self;
+
+end;
+
+{ SCALE }
+function trans_affine.scale(x ,y : double ) : trans_affine_ptr;
+begin
+ m0:=m0 * x;
+ m2:=m2 * x;
+ m4:=m4 * x;
+ m1:=m1 * y;
+ m3:=m3 * y;
+ m5:=m5 * y;
+
+ result:=@self;
+
+end;
+
+{ CONSTRUCT }
+constructor trans_affine_rotation.Construct;
+begin
+ inherited Construct(Cos(a ) ,Sin(a ) ,-Sin(a ) ,Cos(a ) ,0 ,0 );
+
+end;
+
+{ CONSTRUCT }
+constructor trans_affine_scaling.Construct(sx ,sy : double );
+begin
+ inherited Construct(sx ,0 ,0 ,sy ,0 ,0 );
+
+end;
+
+{ CONSTRUCT }
+constructor trans_affine_scaling.Construct(s : double );
+begin
+ inherited Construct(s ,0 ,0 ,s ,0 ,0 );
+
+end;
+
+{ CONSTRUCT }
+constructor trans_affine_translation.Construct;
+begin
+ inherited Construct(1 ,0 ,0 ,1 ,tx ,ty );
+
+end;
+
+{ CONSTRUCT }
+constructor trans_affine_skewing.Construct;
+begin
+ inherited Construct(1 ,Tan(sy ) ,Tan(sx ) ,1 ,0 ,0 );
+
+end;
+
+{ CONSTRUCT }
+constructor trans_affine_line_segment.Construct;
+var
+ dx ,dy : double;
+
+ s : trans_affine_scaling;
+ r : trans_affine_rotation;
+ t : trans_affine_translation;
+
+begin
+ dx:=x2 - x1;
+ dy:=y2 - y1;
+
+ if dist > 0 then
+ begin
+ s.Construct(Sqrt(dx * dx + dy * dy ) / dist );
+
+ multiply(@s );
+
+ end;
+
+ r.Construct(ArcTan2(dy ,dx ) );
+
+ multiply(@r );
+
+ t.Construct(x1 ,y1 );
+
+ multiply(@t );
+
+end;
+
+{ CONSTRUCT }
+constructor trans_affine_reflection_unit.Construct(ux ,uy : double );
+begin
+ inherited Construct(
+ 2.0 * ux * ux - 1.0 ,
+ 2.0 * ux * uy ,
+ 2.0 * ux * uy ,
+ 2.0 * uy * uy - 1.0 ,
+ 0.0 ,0.0 );
+
+end;
+
+{ CONSTRUCT }
+constructor trans_affine_reflection.Construct(a : double );
+begin
+ inherited Construct(Cos(a ) ,Sin(a ) );
+
+end;
+
+{ CONSTRUCT }
+constructor trans_affine_reflection.Construct(x ,y : double );
+var
+ nx ,ny : double;
+
+begin
+ if (x = 0 ) and
+ (y = 0 ) then
+ begin
+ x:=0;
+ y:=0;
+
+ end
+ else
+ begin
+ nx:=x / Sqrt(x * x + y * y );
+ ny:=y / Sqrt(x * x + y * y );
+
+ end;
+
+ inherited Construct(nx ,ny );
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_trans_bilinear.pas b/src/corelib/render/software/agg_trans_bilinear.pas
new file mode 100644
index 00000000..a083dee4
--- /dev/null
+++ b/src/corelib/render/software/agg_trans_bilinear.pas
@@ -0,0 +1,257 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// Bilinear 2D transformations
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 07.02.2006-Milano: Unit port establishment
+//
+{ agg_trans_bilinear.pas }
+unit
+ agg_trans_bilinear ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_trans_affine ,
+ agg_simul_eq ;
+
+{ TYPES DEFINITION }
+type
+ iterator_x = object
+ inc_x ,inc_y ,x ,y : double;
+
+ constructor Construct; overload;
+ constructor Construct(tx ,ty ,step : double; m : double_42_ptr ); overload;
+
+ procedure inc_operator;
+
+ end;
+
+ trans_bilinear_ptr = ^trans_bilinear;
+ trans_bilinear = object(trans_affine )
+ m_valid : boolean;
+ m_mtx : array[0..3 ,0..1 ] of double;
+
+ constructor Construct; overload;
+
+ // Arbitrary quadrangle transformations
+ constructor Construct(src ,dst : double_ptr ); overload;
+
+ // Direct transformations
+ constructor Construct(x1 ,y1 ,x2 ,y2 : double; quad : double_ptr ); overload;
+
+ // Reverse transformations
+ constructor Construct(quad : double_ptr; x1 ,y1 ,x2 ,y2 : double ); overload;
+
+ // Set the transformations using two arbitrary quadrangles.
+ procedure quad_to_quad(src ,dst : double_ptr );
+
+ // Set the direct transformations, i.e., rectangle -> quadrangle
+ procedure rect_to_quad(x1 ,y1 ,x2 ,y2 : double; quad : double_ptr );
+
+ // Set the reverse transformations, i.e., quadrangle -> rectangle
+ procedure quad_to_rect(quad : double_ptr; x1 ,y1 ,x2 ,y2 : double );
+
+ // Check if the equations were solved successfully
+ function is_valid : boolean;
+
+ function begin_(x ,y ,step : double ) : iterator_x;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor iterator_x.Construct;
+begin
+end;
+
+{ CONSTRUCT }
+constructor iterator_x.Construct(tx ,ty ,step : double; m : double_42_ptr );
+begin
+ inc_x:=m^[1 ,0 ] * step * ty + m^[2 ,0 ] * step;
+ inc_y:=m^[1 ,1 ] * step * ty + m^[2 ,1 ] * step;
+
+ x:=m^[0 ,0 ] + m^[1 ,0 ] * tx * ty + m^[2 ,0 ] * tx + m^[3 ,0 ] * ty;
+ y:=m^[0 ,1 ] + m^[1 ,1 ] * tx * ty + m^[2 ,1 ] * tx + m^[3 ,1 ] * ty;
+
+end;
+
+{ INC_OPERATOR }
+procedure iterator_x.inc_operator;
+begin
+ x:=x + inc_x;
+ y:=y + inc_y;
+
+end;
+
+{ _transform }
+procedure _transform(this : trans_bilinear_ptr; x ,y : double_ptr );
+var
+ tx ,ty ,xy : double;
+
+begin
+ tx:=x^;
+ ty:=y^;
+ xy:=tx * ty;
+
+ x^:=this.m_mtx[0 ,0 ] + this.m_mtx[1 ,0 ] * xy + this.m_mtx[2 ,0 ] * tx + this.m_mtx[3 ,0 ] * ty;
+ y^:=this.m_mtx[0 ,1 ] + this.m_mtx[1 ,1 ] * xy + this.m_mtx[2 ,1 ] * tx + this.m_mtx[3 ,1 ] * ty;
+
+end;
+
+{ CONSTRUCT }
+constructor trans_bilinear.Construct;
+begin
+ inherited Construct;
+
+ m_valid:=false;
+
+ transform:=@_transform;
+
+end;
+
+{ CONSTRUCT }
+constructor trans_bilinear.Construct(src ,dst : double_ptr );
+begin
+ inherited Construct;
+
+ quad_to_quad(src ,dst );
+
+ transform:=@_transform;
+
+end;
+
+{ CONSTRUCT }
+constructor trans_bilinear.Construct(x1 ,y1 ,x2 ,y2 : double; quad : double_ptr );
+begin
+ inherited Construct;
+
+ rect_to_quad(x1 ,y1 ,x2 ,y2 ,quad );
+
+ transform:=@_transform;
+
+end;
+
+{ CONSTRUCT }
+constructor trans_bilinear.Construct(quad : double_ptr; x1 ,y1 ,x2 ,y2 : double );
+begin
+ inherited Construct;
+
+ quad_to_rect(quad ,x1 ,y1 ,x2 ,y2 );
+
+ transform:=@_transform;
+
+end;
+
+{ QUAD_TO_QUAD }
+procedure trans_bilinear.quad_to_quad;
+var
+ left : double_44;
+ right : double_42;
+
+ i ,ix ,iy : unsigned;
+
+begin
+ for i:=0 to 3 do
+ begin
+ ix:=i * 2;
+ iy:=ix + 1;
+
+ left[i ,0 ]:=1.0;
+ left[i ,1 ]:=double_ptr(ptrcomp(src ) + ix * sizeof(double ) )^ * double_ptr(ptrcomp(src ) + iy * sizeof(double ) )^;
+ left[i ,2 ]:=double_ptr(ptrcomp(src ) + ix * sizeof(double ) )^;
+ left[i ,3 ]:=double_ptr(ptrcomp(src ) + iy * sizeof(double ) )^;
+
+ right[i ,0 ]:=double_ptr(ptrcomp(dst ) + ix * sizeof(double ) )^;
+ right[i ,1 ]:=double_ptr(ptrcomp(dst ) + iy * sizeof(double ) )^;
+
+ end;
+
+ m_valid:=simul_eq_solve(@left ,@right ,@m_mtx ,4 ,2 );
+
+end;
+
+{ RECT_TO_QUAD }
+procedure trans_bilinear.rect_to_quad;
+var
+ src : double_8;
+
+begin
+ src[0 ]:=x1;
+ src[6 ]:=x1;
+ src[2 ]:=x2;
+ src[4 ]:=x2;
+ src[1 ]:=y1;
+ src[3 ]:=y1;
+ src[5 ]:=y2;
+ src[7 ]:=y2;
+
+ quad_to_quad(@src ,quad );
+
+end;
+
+{ QUAD_TO_RECT }
+procedure trans_bilinear.quad_to_rect;
+var
+ dst : double_8;
+
+begin
+ dst[0 ]:=x1;
+ dst[6 ]:=x1;
+ dst[2 ]:=x2;
+ dst[4 ]:=x2;
+ dst[1 ]:=y1;
+ dst[3 ]:=y1;
+ dst[5 ]:=y2;
+ dst[7 ]:=y2;
+
+ quad_to_quad(quad ,@dst );
+
+end;
+
+{ IS_VALID }
+function trans_bilinear.is_valid;
+begin
+ result:=m_valid;
+
+end;
+
+{ BEGIN_ }
+function trans_bilinear.begin_;
+begin
+ result.Construct(x ,y ,step ,@m_mtx );
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_trans_double_path.pas b/src/corelib/render/software/agg_trans_double_path.pas
new file mode 100644
index 00000000..54e053f0
--- /dev/null
+++ b/src/corelib/render/software/agg_trans_double_path.pas
@@ -0,0 +1,521 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 20.02.2006-Milano: Unit port establishment
+//
+{ agg_trans_double_path.pas }
+unit
+ agg_trans_double_path ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_vertex_source ,
+ agg_vertex_sequence ,
+ agg_trans_affine ;
+
+
+{ TYPES DEFINITION }
+type
+ status_e = (initial ,making_path ,ready );
+
+ trans_double_path_ptr = ^trans_double_path;
+ trans_double_path = object(trans_affine )
+ m_src_vertices1 ,
+ m_src_vertices2 : vertex_sequence;
+
+ m_base_length ,
+ m_base_height ,
+ m_kindex1 ,
+ m_kindex2 : double;
+
+ m_status1 ,
+ m_status2 : status_e;
+
+ m_preserve_x_scale : boolean;
+
+ constructor Construct;
+ destructor Destruct;
+
+ procedure base_length_(v : double );
+ function _base_length : double;
+
+ procedure base_height_(v : double );
+ function _base_height : double;
+
+ procedure preserve_x_scale_(f : boolean );
+ function _preserve_x_scale : boolean;
+
+ procedure reset; virtual;
+
+ procedure move_to1(x ,y : double );
+ procedure line_to1(x ,y : double );
+ procedure move_to2(x ,y : double );
+ procedure line_to2(x ,y : double );
+ procedure finalize_paths;
+
+ procedure add_paths(vs1 ,vs2 : vertex_source_ptr; path1_id : unsigned = 0; path2_id : unsigned = 0 );
+
+ function total_length1 : double;
+ function total_length2 : double;
+
+ function finalize_path(vertices : vertex_sequence_ptr ) : double;
+
+ procedure transform1(vertices : vertex_sequence_ptr; kindex ,kx : double; x ,y : double_ptr );
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ _transform }
+procedure _transform(this : trans_double_path_ptr; x ,y : double_ptr );
+var
+ x1 ,y1 ,x2 ,y2 ,dd : double;
+
+begin
+ if (this.m_status1 = ready ) and
+ (this.m_status2 = ready ) then
+ begin
+ if this.m_base_length > 1e-10 then
+ x^:=
+ x^ *
+ (vertex_dist_ptr(this.m_src_vertices1.array_operator(this.m_src_vertices1.size - 1 ) ).dist /
+ this.m_base_length );
+
+ x1:=x^;
+ y1:=y^;
+ x2:=x^;
+ y2:=y^;
+ dd:=
+ vertex_dist_ptr(this.m_src_vertices2.array_operator(this.m_src_vertices2.size - 1 ) ).dist /
+ vertex_dist_ptr(this.m_src_vertices1.array_operator(this.m_src_vertices1.size - 1 ) ).dist;
+
+ this.transform1(@this.m_src_vertices1 ,this.m_kindex1 ,1.0 ,@x1 ,@y1 );
+ this.transform1(@this.m_src_vertices2 ,this.m_kindex2 ,dd ,@x2 ,@y2 );
+
+ x^:=x1 + y^ * (x2 - x1 ) / this.m_base_height;
+ y^:=y1 + y^ * (y2 - y1 ) / this.m_base_height;
+
+ end;
+
+end;
+
+{ CONSTRUCT }
+constructor trans_double_path.Construct;
+begin
+ inherited Construct;
+
+ transform:=@_transform;
+
+ m_src_vertices1.Construct(sizeof(vertex_dist ) );
+ m_src_vertices2.Construct(sizeof(vertex_dist ) );
+
+ m_kindex1:=0.0;
+ m_kindex2:=0.0;
+
+ m_base_length:=0.0;
+ m_base_height:=1.0;
+
+ m_status1:=initial;
+ m_status2:=initial;
+
+ m_preserve_x_scale:=true;
+
+end;
+
+{ DESTRUCT }
+destructor trans_double_path.Destruct;
+begin
+ m_src_vertices1.Destruct;
+ m_src_vertices2.Destruct;
+
+end;
+
+{ BASE_LENGTH_ }
+procedure trans_double_path.base_length_;
+begin
+ m_base_length:=v;
+
+end;
+
+{ _BASE_LENGTH }
+function trans_double_path._base_length;
+begin
+ result:=m_base_length;
+
+end;
+
+{ BASE_HEIGHT_ }
+procedure trans_double_path.base_height_;
+begin
+ m_base_height:=v;
+
+end;
+
+{ _BASE_HEIGHT }
+function trans_double_path._base_height;
+begin
+ result:=m_base_height;
+
+end;
+
+{ PRESERVE_X_SCALE_ }
+procedure trans_double_path.preserve_x_scale_;
+begin
+ m_preserve_x_scale:=f;
+
+end;
+
+{ _PRESERVE_X_SCALE }
+function trans_double_path._preserve_x_scale;
+begin
+ result:=m_preserve_x_scale;
+
+end;
+
+{ RESET }
+procedure trans_double_path.reset;
+begin
+ m_src_vertices1.remove_all;
+ m_src_vertices2.remove_all;
+
+ m_kindex1:=0.0;
+ m_kindex1:=0.0;
+ m_status1:=initial;
+ m_status2:=initial;
+
+end;
+
+{ MOVE_TO1 }
+procedure trans_double_path.move_to1;
+var
+ vd : vertex_dist;
+
+begin
+ if m_status1 = initial then
+ begin
+ vd.x:=x;
+ vd.y:=y;
+
+ vd.dist:=0;
+
+ m_src_vertices1.modify_last(@vd );
+
+ m_status1:=making_path;
+
+ end
+ else
+ line_to1(x ,y );
+
+end;
+
+{ LINE_TO1 }
+procedure trans_double_path.line_to1;
+var
+ vd : vertex_dist;
+
+begin
+ if m_status1 = making_path then
+ begin
+ vd.x:=x;
+ vd.y:=y;
+
+ vd.dist:=0;
+
+ m_src_vertices1.add(@vd );
+
+ end;
+
+end;
+
+{ MOVE_TO2 }
+procedure trans_double_path.move_to2;
+var
+ vd : vertex_dist;
+
+begin
+ if m_status2 = initial then
+ begin
+ vd.x:=x;
+ vd.y:=y;
+
+ vd.dist:=0;
+
+ m_src_vertices2.modify_last(@vd );
+
+ m_status2:=making_path;
+
+ end
+ else
+ line_to2(x ,y );
+
+end;
+
+{ LINE_TO2 }
+procedure trans_double_path.line_to2;
+var
+ vd : vertex_dist;
+
+begin
+ if m_status2 = making_path then
+ begin
+ vd.x:=x;
+ vd.y:=y;
+
+ vd.dist:=0;
+
+ m_src_vertices2.add(@vd );
+
+ end;
+
+end;
+
+{ FINALIZE_PATHS }
+procedure trans_double_path.finalize_paths;
+begin
+ if (m_status1 = making_path ) and
+ (m_src_vertices1.size > 1 ) and
+ (m_status2 = making_path ) and
+ (m_src_vertices2.size > 1 ) then
+ begin
+ m_kindex1:=finalize_path(@m_src_vertices1 );
+ m_kindex2:=finalize_path(@m_src_vertices2 );
+ m_status1:=ready;
+ m_status2:=ready;
+
+ end;
+
+end;
+
+{ ADD_PATHS }
+procedure trans_double_path.add_paths;
+var
+ x ,y : double;
+ cmd : unsigned;
+
+begin
+ vs1.rewind(path1_id );
+
+ cmd:=vs1.vertex(@x ,@y );
+
+ while not is_stop(cmd ) do
+ begin
+ if is_move_to(cmd ) then
+ move_to1(x ,y )
+ else
+ if is_vertex(cmd ) then
+ line_to1(x ,y );
+
+ cmd:=vs1.vertex(@x ,@y );
+
+ end;
+
+ vs2.rewind(path2_id );
+
+ cmd:=vs2.vertex(@x ,@y );
+
+ while not is_stop(cmd ) do
+ begin
+ if is_move_to(cmd ) then
+ move_to2(x ,y )
+ else
+ if is_vertex(cmd ) then
+ line_to2(x ,y );
+
+ cmd:=vs2.vertex(@x ,@y );
+
+ end;
+
+ finalize_paths;
+
+end;
+
+{ TOTAL_LENGTH1 }
+function trans_double_path.total_length1;
+begin
+ if m_base_length >= 1e-10 then
+ result:=m_base_length
+ else
+ if m_status1 = ready then
+ result:=vertex_dist_ptr(m_src_vertices1.array_operator(m_src_vertices1.size - 1 ) ).dist
+ else
+ result:=0.0;
+
+end;
+
+{ TOTAL_LENGTH2 }
+function trans_double_path.total_length2;
+begin
+ if m_base_length >= 1e-10 then
+ result:=m_base_length
+ else
+ if m_status2 = ready then
+ result:=vertex_dist_ptr(m_src_vertices2.array_operator(m_src_vertices2.size - 1 ) ).dist
+ else
+ result:=0.0;
+
+end;
+
+{ FINALIZE_PATH }
+function trans_double_path.finalize_path;
+var
+ i : unsigned;
+ v : vertex_dist_ptr;
+
+ d ,dist : double;
+
+begin
+ vertices.close(false );
+
+ if vertices.size > 2 then
+ if vertex_dist_ptr(vertices.array_operator(vertices.size - 2 ) ).dist * 10.0 <
+ vertex_dist_ptr(vertices.array_operator(vertices.size - 3 ) ).dist then
+ begin
+ d:=
+ vertex_dist_ptr(vertices.array_operator(vertices.size - 3 ) ).dist +
+ vertex_dist_ptr(vertices.array_operator(vertices.size - 2 ) ).dist;
+
+ move(
+ vertices.array_operator(vertices.size - 1 )^ ,
+ vertices.array_operator(vertices.size - 2 )^ ,
+ sizeof(vertex_dist ) );
+
+ vertices.remove_last;
+
+ vertex_dist_ptr(vertices.array_operator(vertices.size - 2 ) ).dist:=d;
+
+ end;
+
+ dist:=0;
+
+ for i:=0 to vertices.size - 1 do
+ begin
+ v:=vertices.array_operator(i );
+ d:=v.dist;
+
+ v.dist:=dist;
+ dist :=dist + d;
+
+ end;
+
+ result:=(vertices.size - 1 ) / dist;
+
+end;
+
+{ TRANSFORM1 }
+procedure trans_double_path.transform1;
+var
+ x1 ,y1 ,dx ,dy ,d ,dd : double;
+
+ i ,j ,k : unsigned;
+
+begin
+ x1:=0.0;
+ y1:=0.0;
+ dx:=1.0;
+ dy:=1.0;
+ d :=0.0;
+ dd:=1.0;
+
+ x^:=x^ * kx;
+
+ if x^ < 0.0 then
+ begin
+ // Extrapolation on the left
+ x1:=vertex_dist_ptr(vertices.array_operator(0 ) ).x;
+ y1:=vertex_dist_ptr(vertices.array_operator(0 ) ).y;
+ dx:=vertex_dist_ptr(vertices.array_operator(1 ) ).x - x1;
+ dy:=vertex_dist_ptr(vertices.array_operator(1 ) ).y - y1;
+ dd:=vertex_dist_ptr(vertices.array_operator(1 ) ).dist - vertex_dist_ptr(vertices.array_operator(0 ) ).dist;
+ d :=x^;
+
+ end
+ else
+ if x^ > vertex_dist_ptr(vertices.array_operator(vertices.size - 1 ) ).dist then
+ begin
+ i:=vertices.size - 2;
+ j:=vertices.size - 1;
+
+ x1:=vertex_dist_ptr(vertices.array_operator(j ) ).x;
+ y1:=vertex_dist_ptr(vertices.array_operator(j ) ).y;
+ dx:=x1 - vertex_dist_ptr(vertices.array_operator(i ) ).x;
+ dy:=y1 - vertex_dist_ptr(vertices.array_operator(i ) ).y;
+ dd:=vertex_dist_ptr(vertices.array_operator(j ) ).dist - vertex_dist_ptr(vertices.array_operator(i ) ).dist;
+ d :=x^ - vertex_dist_ptr(vertices.array_operator(j ) ).dist;
+
+ end
+ else
+ begin
+ // Interpolation
+ i:=0;
+ j:=vertices.size - 1;
+
+ if m_preserve_x_scale then
+ begin
+ i:=0;
+
+ while j - i > 1 do
+ begin
+ k:=(i + j ) shr 1;
+
+ if x^ < vertex_dist_ptr(vertices.array_operator(k ) ).dist then
+ j:=k
+ else
+ i:=k;
+
+ end;
+
+ d :=vertex_dist_ptr(vertices.array_operator(i ) ).dist;
+ dd:=vertex_dist_ptr(vertices.array_operator(j ) ).dist - d;
+ d :=x^ - d;
+
+ end
+ else
+ begin
+ i :=trunc(x^ * kindex );
+ j :=i + 1;
+ dd:=vertex_dist_ptr(vertices.array_operator(j ) ).dist - vertex_dist_ptr(vertices.array_operator(i ) ).dist;
+ d :=((x^ * kindex ) - i ) * dd;
+
+ end;
+
+ x1:=vertex_dist_ptr(vertices.array_operator(i ) ).x;
+ y1:=vertex_dist_ptr(vertices.array_operator(i ) ).y;
+ dx:=vertex_dist_ptr(vertices.array_operator(j ) ).x - x1;
+ dy:=vertex_dist_ptr(vertices.array_operator(j ) ).y - y1;
+
+ end;
+
+ x^:=x1 + dx * d / dd;
+ y^:=y1 + dy * d / dd;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_trans_perspective.pas b/src/corelib/render/software/agg_trans_perspective.pas
new file mode 100644
index 00000000..87409e83
--- /dev/null
+++ b/src/corelib/render/software/agg_trans_perspective.pas
@@ -0,0 +1,1276 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// Perspective 2D transformations
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 13.11.2007-Milano: trans_perspective v 2.4
+// 23.06.2006-Milano: ptrcomp adjustments
+// 06.02.2006-Milano: Unit port establishment
+//
+{ agg_trans_perspective.pas }
+unit
+ agg_trans_perspective ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ Math ,
+ agg_basics ,
+ agg_simul_eq ,
+ agg_trans_affine ;
+
+{ TYPES DEFINITION }
+type
+ iterator_x23 = object
+ den ,den_step ,
+ nom_x ,nom_x_step ,
+ nom_y ,nom_y_step : double;
+
+ x ,y : double;
+
+ constructor Construct; overload;
+ constructor Construct(tx ,ty ,step : double; m : double_ptr ); overload;
+
+ procedure inc_operator;
+
+ end;
+
+ trans_perspective23_ptr = ^trans_perspective23;
+ trans_perspective23 = object(trans_affine )
+ m_valid : boolean;
+ m_mtx : array[0..7 ] of double;
+
+ constructor Construct; overload;
+
+ // Arbitrary quadrangle transformations
+ constructor Construct(src ,dst : double_ptr ); overload;
+
+ // Direct transformations
+ constructor Construct(x1 ,y1 ,x2 ,y2 : double; quad : double_ptr ); overload;
+
+ // Reverse transformations
+ constructor Construct(quad : double_ptr; x1 ,y1 ,x2 ,y2 : double ); overload;
+
+ // Set the transformations using two arbitrary quadrangles.
+ procedure quad_to_quad(src ,dst : double_ptr );
+
+ // Set the direct transformations, i.e., rectangle -> quadrangle
+ procedure rect_to_quad(x1 ,y1 ,x2 ,y2 : double; quad : double_ptr );
+
+ // Set the reverse transformations, i.e., quadrangle -> rectangle
+ procedure quad_to_rect(quad : double_ptr; x1 ,y1 ,x2 ,y2 : double );
+
+ // Check if the equations were solved successfully
+ function is_valid : boolean;
+
+ function begin_(x ,y ,step : double ) : iterator_x23;
+
+ end;
+
+ quadrilateral_ptr = ^quadrilateral;
+ quadrilateral = array[0..8 ] of double;
+
+ trans_perspective_ptr = ^trans_perspective;
+
+ iterator_x = object
+ den ,den_step ,
+ nom_x ,nom_x_step ,
+ nom_y ,nom_y_step : double;
+
+ x ,y : double;
+
+ constructor Construct; overload;
+ constructor Construct(px ,py ,step : double; m : trans_perspective_ptr ); overload;
+
+ procedure operator_inc;
+
+ end;
+
+ trans_perspective = object(trans_affine )
+ sx ,shy ,w0 ,shx ,sy ,w1 ,tx ,ty ,w2 : double;
+
+ transform_affine : proc_transform;
+
+ //------------------------------------------------------- Construction
+ // Identity matrix
+ constructor Construct; overload;
+
+ // Custom matrix
+ constructor Construct(v0 ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 : double ); overload;
+
+ // Custom matrix from m[9]
+ constructor Construct(m : quadrilateral_ptr ); overload;
+
+ // From affine
+ constructor Construct_af(a : trans_affine_ptr );
+
+ // From affine
+ constructor Construct(p : trans_perspective_ptr ); overload;
+
+ // Rectangle to quadrilateral
+ constructor Construct(x1 ,y1 ,x2 ,y2 : double; quad : quadrilateral_ptr ); overload;
+
+ // Quadrilateral to rectangle
+ constructor Construct(quad : quadrilateral_ptr; x1 ,y1 ,x2 ,y2 : double ); overload;
+
+ // Arbitrary quadrilateral transformations
+ constructor Construct(src ,dst : quadrilateral_ptr ); overload;
+
+ //-------------------------------------- Quadrilateral transformations
+ // The arguments are double[8] that are mapped to quadrilaterals:
+ // x1,y1, x2,y2, x3,y3, x4,y4
+ function quad_to_quad(qs ,qd : quadrilateral_ptr ) : boolean;
+ function rect_to_quad(x1 ,y1 ,x2 ,y2 : double; q : quadrilateral_ptr ) : boolean;
+ function quad_to_rect(q : quadrilateral_ptr; x1 ,y1 ,x2 ,y2 : double ) : boolean;
+
+ // Map square (0,0,1,1) to the quadrilateral and vice versa
+ function square_to_quad(q : quadrilateral_ptr ) : boolean;
+ function quad_to_square(q : quadrilateral_ptr ) : boolean;
+
+ //--------------------------------------------------------- Operations
+ // Reset - load an identity matrix
+ function reset_ : trans_perspective_ptr;
+
+ // Invert matrix. Returns false in degenerate case
+ function invert : boolean;
+
+ // Direct transformations operations
+ function translate(x ,y : double ) : trans_perspective_ptr;
+ function rotate (a : double ) : trans_perspective_ptr;
+ function scale (s : double ) : trans_perspective_ptr; overload;
+ function scale (x ,y : double ) : trans_perspective_ptr; overload;
+
+ // Multiply the matrix by another one
+ function multiply(a : trans_perspective_ptr ) : trans_perspective_ptr;
+
+ // Multiply "m" by "this" and assign the result to "this"
+ function premultiply(b : trans_perspective_ptr ) : trans_perspective_ptr;
+
+ // Multiply matrix to inverse of another one
+ function multiply_inv(m : trans_perspective_ptr ) : trans_perspective_ptr;
+
+ // Multiply inverse of "m" by "this" and assign the result to "this"
+ function premultiply_inv(m : trans_perspective_ptr ) : trans_perspective_ptr;
+
+ // Multiply the matrix by another one
+ function multiply_af(a : trans_affine_ptr ) : trans_perspective_ptr;
+
+ // Multiply "m" by "this" and assign the result to "this"
+ function premultiply_af(b : trans_affine_ptr ) : trans_perspective_ptr;
+
+ // Multiply the matrix by inverse of another one
+ function multiply_inv_af(m : trans_affine_ptr ) : trans_perspective_ptr;
+
+ // Multiply inverse of "m" by "this" and assign the result to "this"
+ function premultiply_inv_af(m : trans_affine_ptr ) : trans_perspective_ptr;
+
+ //--------------------------------------------------------- Load/Store
+ procedure store_to (m : quadrilateral_ptr );
+ function load_from(m : quadrilateral_ptr ) : trans_perspective_ptr;
+
+ //---------------------------------------------------------- Auxiliary
+ function from_affine(a : trans_affine_ptr ) : trans_perspective_ptr;
+
+ function determinant : double;
+ function determinant_reciprocal : double;
+
+ function is_valid (epsilon : double = affine_epsilon ) : boolean;
+ function is_identity(epsilon : double = affine_epsilon ) : boolean;
+ function is_equal (m : trans_perspective_ptr; epsilon : double = affine_epsilon ) : boolean;
+
+ // Determine the major affine parameters. Use with caution
+ // considering possible degenerate cases.
+ function scale : double; overload;
+ function rotation : double;
+
+ procedure translation(dx ,dy : double_ptr );
+ procedure scaling (x ,y : double_ptr );
+ procedure scaling_abs(x ,y : double_ptr );
+
+ // private
+ function begin_(x ,y ,step : double ) : iterator_x;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor iterator_x23.Construct;
+begin
+end;
+
+{ CONSTRUCT }
+constructor iterator_x23.Construct(tx ,ty ,step : double; m : double_ptr );
+begin
+ den :=double_ptr(ptrcomp(m ) + 6 * sizeof(double ) )^ * tx + double_ptr(ptrcomp(m ) + 7 * sizeof(double ) )^ * ty + 1.0;
+ den_step:=double_ptr(ptrcomp(m ) + 6 * sizeof(double ) )^ * step;
+
+ nom_x :=double_ptr(ptrcomp(m ) + 0 * sizeof(double ) )^ + double_ptr(ptrcomp(m ) + 1 * sizeof(double ) )^ * tx + double_ptr(ptrcomp(m ) + 2 * sizeof(double ) )^ * ty;
+ nom_x_step:=double_ptr(ptrcomp(m ) + 1 * sizeof(double ) )^ * step;
+
+ nom_y :=double_ptr(ptrcomp(m ) + 3 * sizeof(double ) )^ + double_ptr(ptrcomp(m ) + 4 * sizeof(double ) )^ * tx + double_ptr(ptrcomp(m ) + 5 * sizeof(double ) )^ * ty;
+ nom_y_step:=double_ptr(ptrcomp(m ) + 4 * sizeof(double ) )^ * step;
+
+ x:=nom_x / den;
+ y:=nom_y / den;
+
+end;
+
+{ INC_OPERATOR }
+procedure iterator_x23.inc_operator;
+var
+ d : double;
+
+begin
+ den :=den + den_step;
+ nom_x:=nom_x + nom_x_step;
+ nom_y:=nom_y + nom_y_step;
+
+ d:=1.0 / den;
+ x:=nom_x * d;
+ y:=nom_y * d;
+
+end;
+
+{ _transform23 }
+procedure _transform23(this : trans_perspective23_ptr; x ,y : double_ptr );
+var
+ tx ,ty ,d : double;
+
+begin
+ tx:=x^;
+ ty:=y^;
+ d :=1.0 / (this.m_mtx[6 ] * tx + this.m_mtx[7 ] * ty + 1.0 );
+
+ x^:=(this.m_mtx[0 ] + this.m_mtx[1 ] * tx + this.m_mtx[2 ] * ty ) * d;
+ y^:=(this.m_mtx[3 ] + this.m_mtx[4 ] * tx + this.m_mtx[5 ] * ty ) * d;
+
+end;
+
+{ CONSTRUCT }
+constructor trans_perspective23.Construct;
+begin
+ inherited Construct;
+
+ m_valid:=false;
+
+ transform:=@_transform23;
+
+end;
+
+{ CONSTRUCT }
+constructor trans_perspective23.Construct(src ,dst : double_ptr );
+begin
+ inherited Construct;
+
+ quad_to_quad(src ,dst );
+
+ transform:=@_transform23;
+
+end;
+
+{ CONSTRUCT }
+constructor trans_perspective23.Construct(x1 ,y1 ,x2 ,y2 : double; quad : double_ptr );
+begin
+ inherited Construct;
+
+ rect_to_quad(x1 ,y1 ,x2 ,y2 ,quad );
+
+ transform:=@_transform23;
+
+end;
+
+{ CONSTRUCT }
+constructor trans_perspective23.Construct(quad : double_ptr; x1 ,y1 ,x2 ,y2 : double );
+begin
+ inherited Construct;
+
+ quad_to_rect(quad ,x1 ,y1 ,x2 ,y2 );
+
+ transform:=@_transform23;
+
+end;
+
+{ QUAD_TO_QUAD }
+procedure trans_perspective23.quad_to_quad;
+var
+ left : double_88;
+ right : double_81;
+
+ i ,ix ,iy : unsigned;
+
+begin
+ for i:=0 to 3 do
+ begin
+ ix:=i * 2;
+ iy:=ix + 1;
+
+ left [ix ][0 ]:=1.0;
+ left [ix ][1 ]:=double_ptr(ptrcomp(src ) + ix * sizeof(double ) )^;
+ left [ix ][2 ]:=double_ptr(ptrcomp(src ) + iy * sizeof(double ) )^;
+ left [ix ][3 ]:=0.0;
+ left [ix ][4 ]:=0.0;
+ left [ix ][5 ]:=0.0;
+ left [ix ][6 ]:=-double_ptr(ptrcomp(src ) + ix * sizeof(double ) )^ * double_ptr(ptrcomp(dst ) + ix * sizeof(double ) )^;
+ left [ix ][7 ]:=-double_ptr(ptrcomp(src ) + iy * sizeof(double ) )^ * double_ptr(ptrcomp(dst ) + ix * sizeof(double ) )^;
+ right[ix ][0 ]:=double_ptr(ptrcomp(dst ) + ix * sizeof(double ) )^;
+
+ left [iy ][0 ]:=0.0;
+ left [iy ][1 ]:=0.0;
+ left [iy ][2 ]:=0.0;
+ left [iy ][3 ]:=1.0;
+ left [iy ][4 ]:=double_ptr(ptrcomp(src ) + ix * sizeof(double ) )^;
+ left [iy ][5 ]:=double_ptr(ptrcomp(src ) + iy * sizeof(double ) )^;
+ left [iy ][6 ]:=-double_ptr(ptrcomp(src ) + ix * sizeof(double ) )^ * double_ptr(ptrcomp(dst ) + iy * sizeof(double ) )^;
+ left [iy ][7 ]:=-double_ptr(ptrcomp(src ) + iy * sizeof(double ) )^ * double_ptr(ptrcomp(dst ) + iy * sizeof(double ) )^;
+ right[iy ][0 ]:=double_ptr(ptrcomp(dst ) + iy * sizeof(double ) )^;
+
+ end;
+
+ m_valid:=simul_eq_solve(@left ,@right ,@m_mtx ,8 ,1 );
+
+end;
+
+{ RECT_TO_QUAD }
+procedure trans_perspective23.rect_to_quad;
+var
+ src : double_8;
+
+begin
+ src[0 ]:=x1;
+ src[6 ]:=x1;
+ src[2 ]:=x2;
+ src[4 ]:=x2;
+ src[1 ]:=y1;
+ src[3 ]:=y1;
+ src[5 ]:=y2;
+ src[7 ]:=y2;
+
+ quad_to_quad(@src ,quad );
+
+end;
+
+{ QUAD_TO_RECT }
+procedure trans_perspective23.quad_to_rect;
+var
+ dst : double_8;
+
+begin
+ dst[0 ]:=x1;
+ dst[6 ]:=x1;
+ dst[2 ]:=x2;
+ dst[4 ]:=x2;
+ dst[1 ]:=y1;
+ dst[3 ]:=y1;
+ dst[5 ]:=y2;
+ dst[7 ]:=y2;
+
+ quad_to_quad(quad ,@dst );
+
+end;
+
+{ IS_VALID }
+function trans_perspective23.is_valid;
+begin
+ result:=m_valid;
+
+end;
+
+{ BEGIN_ }
+function trans_perspective23.begin_;
+begin
+ result.Construct(x ,y ,step ,@m_mtx );
+
+end;
+
+{ CONSTRUCT }
+constructor iterator_x.Construct;
+begin
+end;
+
+{ CONSTRUCT }
+constructor iterator_x.Construct(px ,py ,step : double; m : trans_perspective_ptr );
+begin
+ den :=px * m.w0 + py * m.w1 + m.w2;
+ den_step:=m.w0 * step;
+
+ nom_x :=px * m.sx + py * m.shx + m.tx;
+ nom_x_step:=step * m.sx;
+ nom_y :=px * m.shy + py * m.sy + m.ty;
+ nom_y_step:=step * m.shy;
+
+ x:=nom_x / den;
+ y:=nom_y / den;
+
+end;
+
+{ OPERATOR_INC }
+procedure iterator_x.operator_inc;
+var
+ d : double;
+
+begin
+ den:=den + den_step;
+
+ nom_x:=nom_x + nom_x_step;
+ nom_y:=nom_y + nom_y_step;
+
+ d:=1.0 / den;
+ x:=nom_x * d;
+ y:=nom_y * d;
+
+end;
+
+{ _transform }
+// Direct transformation of x and y
+procedure _transform(this : trans_perspective_ptr; px ,py : double_ptr );
+var
+ x ,y ,m : double;
+
+begin
+ x:=px^;
+ y:=py^;
+
+ try
+ m:=1.0 / (x * this.w0 + y * this.w1 + this.w2 );
+
+ except
+ m:=0;
+
+ end;
+
+ px^:=m * (x * this.sx + y * this.shx + this.tx );
+ py^:=m * (x * this.shy + y * this.sy + this.ty );
+
+end;
+
+{ _transform_affine }
+// Direct transformation of x and y, affine part only
+procedure _transform_affine(this : trans_perspective_ptr; x ,y : double_ptr );
+var
+ tmp : double;
+
+begin
+ tmp:=x^;
+
+ x^:=tmp * this.sx + y^ * this.shx + this.tx;
+ y^:=tmp * this.shy + y^ * this.sy + this.ty;
+
+end;
+
+{ _transform_2x2 }
+// Direct transformation of x and y, 2x2 matrix only, no translation
+procedure _transform_2x2(this : trans_perspective_ptr; x ,y : double_ptr );
+var
+ tmp : double;
+
+begin
+ tmp:=x^;
+
+ x^:=tmp * this.sx + y^ * this.shx;
+ y^:=tmp * this.shy + y^ * this.sy;
+
+end;
+
+{ _inverse_transform }
+// Inverse transformation of x and y. It works slow because
+// it explicitly inverts the matrix on every call. For massive
+// operations it's better to invert() the matrix and then use
+// direct transformations.
+procedure _inverse_transform(this : trans_perspective_ptr; x ,y : double_ptr );
+var
+ t : trans_perspective;
+
+begin
+ t.Construct(this );
+
+ if t.invert then
+ t.transform(@t ,x ,y );
+
+end;
+
+{ CONSTRUCT }
+constructor trans_perspective.Construct;
+begin
+ inherited Construct;
+
+ sx :=1;
+ shy:=0;
+ w0 :=0;
+ shx:=0;
+ sy :=1;
+ w1 :=0;
+ tx :=0;
+ ty :=0;
+ w2 :=1;
+
+ transform :=@_transform;
+ transform_2x2 :=@_transform_2x2;
+ inverse_transform:=@_inverse_transform;
+ transform_affine :=@_transform_affine;
+
+end;
+
+{ CONSTRUCT }
+constructor trans_perspective.Construct(v0 ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 : double );
+begin
+ inherited Construct;
+
+ sx :=v0;
+ shy:=v1;
+ w0 :=v2;
+ shx:=v3;
+ sy :=v4;
+ w1 :=v5;
+ tx :=v6;
+ ty :=v7;
+ w2 :=v8;
+
+ transform :=@_transform;
+ transform_2x2 :=@_transform_2x2;
+ inverse_transform:=@_inverse_transform;
+ transform_affine :=@_transform_affine;
+
+end;
+
+{ CONSTRUCT }
+constructor trans_perspective.Construct(m : quadrilateral_ptr );
+begin
+ inherited Construct;
+
+ sx :=m[0 ];
+ shy:=m[1 ];
+ w0 :=m[2 ];
+ shx:=m[3 ];
+ sy :=m[4 ];
+ w1 :=m[5 ];
+ tx :=m[6 ];
+ ty :=m[7 ];
+ w2 :=m[8 ];
+
+ transform :=@_transform;
+ transform_2x2 :=@_transform_2x2;
+ inverse_transform:=@_inverse_transform;
+ transform_affine :=@_transform_affine;
+
+end;
+
+{ CONSTRUCT }
+constructor trans_perspective.Construct_af(a : trans_affine_ptr );
+begin
+ inherited Construct;
+
+ sx :=a.m0;
+ shy:=a.m1;
+ w0 :=0;
+ shx:=a.m2;
+ sy :=a.m3;
+ w1 :=0;
+ tx :=a.m4;
+ ty :=a.m5;
+ w2 :=1;
+
+ transform :=@_transform;
+ transform_2x2 :=@_transform_2x2;
+ inverse_transform:=@_inverse_transform;
+ transform_affine :=@_transform_affine;
+
+end;
+
+{ CONSTRUCT }
+constructor trans_perspective.Construct(p : trans_perspective_ptr );
+begin
+ inherited Construct;
+
+ sx :=p.sx;
+ shy:=p.shy;
+ w0 :=p.w0;
+ shx:=p.shx;
+ sy :=p.sy;
+ w1 :=p.w1;
+ tx :=p.tx;
+ ty :=p.ty;
+ w2 :=p.w2;
+
+ transform :=@_transform;
+ transform_2x2 :=@_transform_2x2;
+ inverse_transform:=@_inverse_transform;
+ transform_affine :=@_transform_affine;
+
+end;
+
+{ CONSTRUCT }
+constructor trans_perspective.Construct(x1 ,y1 ,x2 ,y2 : double; quad : quadrilateral_ptr );
+begin
+ inherited Construct;
+
+ rect_to_quad(x1 ,y1 ,x2 ,y2 ,quad );
+
+ transform :=@_transform;
+ transform_2x2 :=@_transform_2x2;
+ inverse_transform:=@_inverse_transform;
+ transform_affine :=@_transform_affine;
+
+end;
+
+{ CONSTRUCT }
+constructor trans_perspective.Construct(quad : quadrilateral_ptr; x1 ,y1 ,x2 ,y2 : double );
+begin
+ inherited Construct;
+
+ quad_to_rect(quad ,x1 ,y1 ,x2 ,y2 );
+
+ transform :=@_transform;
+ transform_2x2 :=@_transform_2x2;
+ inverse_transform:=@_inverse_transform;
+ transform_affine :=@_transform_affine;
+
+end;
+
+{ CONSTRUCT }
+constructor trans_perspective.Construct(src ,dst : quadrilateral_ptr );
+begin
+ inherited Construct;
+
+ quad_to_quad(src ,dst );
+
+ transform :=@_transform;
+ transform_2x2 :=@_transform_2x2;
+ inverse_transform:=@_inverse_transform;
+ transform_affine :=@_transform_affine;
+
+end;
+
+{ QUAD_TO_QUAD }
+function trans_perspective.quad_to_quad(qs ,qd : quadrilateral_ptr ) : boolean;
+var
+ p : trans_perspective;
+
+begin
+ p.Construct;
+
+ if not quad_to_square(qs ) then
+ begin
+ result:=false;
+
+ exit;
+
+ end;
+
+ if not p.square_to_quad(qd ) then
+ begin
+ result:=false;
+
+ exit;
+
+ end;
+
+ multiply(@p );
+
+ result:=true;
+
+end;
+
+{ RECT_TO_QUAD }
+function trans_perspective.rect_to_quad(x1 ,y1 ,x2 ,y2 : double; q : quadrilateral_ptr ) : boolean;
+var
+ r : array[0..7 ] of double;
+
+begin
+ r[0 ]:=x1;
+ r[6 ]:=x1;
+ r[2 ]:=x2;
+ r[4 ]:=x2;
+ r[1 ]:=y1;
+ r[3 ]:=y1;
+ r[5 ]:=y2;
+ r[7 ]:=y2;
+
+ result:=quad_to_quad(@r[0 ] ,q );
+
+end;
+
+{ QUAD_TO_RECT }
+function trans_perspective.quad_to_rect(q : quadrilateral_ptr; x1 ,y1 ,x2 ,y2 : double ) : boolean;
+var
+ r : array[0..7 ] of double;
+
+begin
+ r[0 ]:=x1;
+ r[6 ]:=x1;
+ r[2 ]:=x2;
+ r[4 ]:=x2;
+ r[1 ]:=y1;
+ r[3 ]:=y1;
+ r[5 ]:=y2;
+ r[7 ]:=y2;
+
+ result:=quad_to_quad(q ,@r[0 ] );
+
+end;
+
+{ SQUARE_TO_QUAD }
+function trans_perspective.square_to_quad(q : quadrilateral_ptr ) : boolean;
+var
+ dx ,dy ,dx1 ,dy1 ,dx2 ,dy2 ,den ,u ,v : double;
+
+begin
+ dx:=q[0 ] - q[2 ] + q[4 ] - q[6 ];
+ dy:=q[1 ] - q[3 ] + q[5 ] - q[7 ];
+
+ if (dx = 0.0 ) and
+ (dy = 0.0 ) then
+ begin
+ // Affine case (parallelogram)
+ sx :=q[2 ] - q[0 ];
+ shy:=q[3 ] - q[1 ];
+ w0 :=0.0;
+ shx:=q[4 ] - q[2 ];
+ sy :=q[5 ] - q[3 ];
+ w1 :=0.0;
+ tx :=q[0 ];
+ ty :=q[1 ];
+ w2 :=1.0;
+
+ end
+ else
+ begin
+ dx1:=q[2 ] - q[4 ];
+ dy1:=q[3 ] - q[5 ];
+ dx2:=q[6 ] - q[4 ];
+ dy2:=q[7 ] - q[5 ];
+ den:=dx1 * dy2 - dx2 * dy1;
+
+ if den = 0.0 then
+ begin
+ // Singular case
+ sx :=0.0;
+ shy:=0.0;
+ w0 :=0.0;
+ shx:=0.0;
+ sy :=0.0;
+ w1 :=0.0;
+ tx :=0.0;
+ ty :=0.0;
+ w2 :=0.0;
+
+ result:=false;
+
+ exit;
+
+ end;
+
+ // General case
+ u:=(dx * dy2 - dy * dx2 ) / den;
+ v:=(dy * dx1 - dx * dy1 ) / den;
+
+ sx :=q[2 ] - q[0 ] + u * q[2 ];
+ shy:=q[3 ] - q[1 ] + u * q[3 ];
+ w0 :=u;
+ shx:=q[6 ] - q[0 ] + v * q[6 ];
+ sy :=q[7 ] - q[1 ] + v * q[7 ];
+ w1 :=v;
+ tx :=q[0 ];
+ ty :=q[1 ];
+ w2 :=1.0;
+
+ end;
+
+ result:=true;
+
+end;
+
+{ QUAD_TO_SQUARE }
+function trans_perspective.quad_to_square(q : quadrilateral_ptr ) : boolean;
+begin
+ if not square_to_quad(q ) then
+ result:=false
+ else
+ begin
+ invert;
+
+ result:=true;
+
+ end;
+
+end;
+
+{ RESET_ }
+function trans_perspective.reset_ : trans_perspective_ptr;
+begin
+ sx :=1;
+ shy:=0;
+ w0 :=0;
+ shx:=0;
+ sy :=1;
+ w1 :=0;
+ tx :=0;
+ ty :=0;
+ w2 :=1;
+
+ result:=@self;
+
+end;
+
+{ INVERT }
+function trans_perspective.invert : boolean;
+var
+ d0 ,d1 ,d2 ,d : double;
+
+ a : trans_perspective;
+
+begin
+ d0:=sy * w2 - w1 * ty;
+ d1:=w0 * ty - shy * w2;
+ d2:=shy * w1 - w0 * sy;
+ d :=sx * d0 + shx * d1 + tx * d2;
+
+ if d = 0.0 then
+ begin
+ sx :=0.0;
+ shy:=0.0;
+ w0 :=0.0;
+ shx:=0.0;
+ sy :=0.0;
+ w1 :=0.0;
+ tx :=0.0;
+ ty :=0.0;
+ w2 :=0.0;
+
+ result:=false;
+
+ exit;
+
+ end;
+
+ d:=1.0 / d;
+
+ a.Construct(trans_perspective_ptr(@self ) );
+
+ sx :=d * d0;
+ shy:=d * d1;
+ w0 :=d * d2;
+ shx:=d * (a.w1 * a.tx - a.shx * a.w2 );
+ sy :=d * (a.sx * a.w2 - a.w0 * a.tx );
+ w1 :=d * (a.w0 * a.shx - a.sx * a.w1 );
+ tx :=d * (a.shx * a.ty - a.sy * a.tx );
+ ty :=d * (a.shy * a.tx - a.sx * a.ty );
+ w2 :=d * (a.sx * a.sy - a.shy * a.shx );
+
+ result:=true;
+
+end;
+
+{ TRANSLATE }
+function trans_perspective.translate(x ,y : double ) : trans_perspective_ptr;
+begin
+ tx:=tx + x;
+ ty:=ty + y;
+
+ result:=@self;
+
+end;
+
+{ ROTATE }
+function trans_perspective.rotate(a : double ) : trans_perspective_ptr;
+var
+ tar : trans_affine_rotation;
+
+begin
+ tar.Construct(a );
+
+ multiply_af(@tar );
+
+ result:=@self;
+
+end;
+
+{ SCALE }
+function trans_perspective.scale(s : double ) : trans_perspective_ptr;
+var
+ tas : trans_affine_scaling;
+
+begin
+ tas.Construct(s );
+
+ multiply_af(@tas );
+
+ result:=@self;
+
+end;
+
+{ SCALE }
+function trans_perspective.scale(x ,y : double ) : trans_perspective_ptr;
+var
+ tas : trans_affine_scaling;
+
+begin
+ tas.Construct(x ,y );
+
+ multiply_af(@tas );
+
+ result:=@self;
+
+end;
+
+{ MULTIPLY }
+function trans_perspective.multiply(a : trans_perspective_ptr ) : trans_perspective_ptr;
+var
+ b : trans_perspective;
+
+begin
+ b.Construct(trans_perspective_ptr(@self ) );
+
+ sx :=a.sx * b.sx + a.shx * b.shy + a.tx * b.w0;
+ shx:=a.sx * b.shx + a.shx * b.sy + a.tx * b.w1;
+ tx :=a.sx * b.tx + a.shx * b.ty + a.tx * b.w2;
+ shy:=a.shy * b.sx + a.sy * b.shy + a.ty * b.w0;
+ sy :=a.shy * b.shx + a.sy * b.sy + a.ty * b.w1;
+ ty :=a.shy * b.tx + a.sy * b.ty + a.ty * b.w2;
+ w0 :=a.w0 * b.sx + a.w1 * b.shy + a.w2 * b.w0;
+ w1 :=a.w0 * b.shx + a.w1 * b.sy + a.w2 * b.w1;
+ w2 :=a.w0 * b.tx + a.w1 * b.ty + a.w2 * b.w2;
+
+ result:=@self;
+
+end;
+
+{ PREMULTIPLY }
+function trans_perspective.premultiply(b : trans_perspective_ptr ) : trans_perspective_ptr;
+var
+ a : trans_perspective;
+
+begin
+ a.Construct(trans_perspective_ptr(@self ) );
+
+ sx :=a.sx * b.sx + a.shx * b.shy + a.tx * b.w0;
+ shx:=a.sx * b.shx + a.shx * b.sy + a.tx * b.w1;
+ tx :=a.sx * b.tx + a.shx * b.ty + a.tx * b.w2;
+ shy:=a.shy * b.sx + a.sy * b.shy + a.ty * b.w0;
+ sy :=a.shy * b.shx + a.sy * b.sy + a.ty * b.w1;
+ ty :=a.shy * b.tx + a.sy * b.ty + a.ty * b.w2;
+ w0 :=a.w0 * b.sx + a.w1 * b.shy + a.w2 * b.w0;
+ w1 :=a.w0 * b.shx + a.w1 * b.sy + a.w2 * b.w1;
+ w2 :=a.w0 * b.tx + a.w1 * b.ty + a.w2 * b.w2;
+
+ result:=@self;
+
+end;
+
+{ MULTIPLY_INV }
+function trans_perspective.multiply_inv(m : trans_perspective_ptr ) : trans_perspective_ptr;
+var
+ t : trans_perspective;
+
+begin
+ t.Construct(m );
+ t.invert;
+
+ result:=multiply(@t )
+
+end;
+
+{ PREMULTIPLY_INV }
+function trans_perspective.premultiply_inv(m : trans_perspective_ptr ) : trans_perspective_ptr;
+var
+ t : trans_perspective;
+
+begin
+ t.Construct(m );
+ t.invert;
+
+ t.multiply(@self );
+
+ Construct(trans_perspective_ptr(@self ) );
+
+ result:=@self;
+
+end;
+
+{ MULIPLY_AF }
+function trans_perspective.multiply_af(a : trans_affine_ptr ) : trans_perspective_ptr;
+var
+ b : trans_perspective;
+
+begin
+ b.Construct(trans_perspective_ptr(@self ) );
+
+ sx :=a.m0 * b.sx + a.m2 * b.shy + a.m4 * b.w0;
+ shx:=a.m0 * b.shx + a.m2 * b.sy + a.m4 * b.w1;
+ tx :=a.m0 * b.tx + a.m2 * b.ty + a.m4 * b.w2;
+ shy:=a.m1 * b.sx + a.m3 * b.shy + a.m5 * b.w0;
+ sy :=a.m1 * b.shx + a.m3 * b.sy + a.m5 * b.w1;
+ ty :=a.m1 * b.tx + a.m3 * b.ty + a.m5 * b.w2;
+
+ result:=@self;
+
+end;
+
+{ PREMULTIPLY_AF }
+function trans_perspective.premultiply_af(b : trans_affine_ptr ) : trans_perspective_ptr;
+var
+ a : trans_perspective;
+
+begin
+ a.Construct(trans_perspective_ptr(@self ) );
+
+ sx :=a.sx * b.m0 + a.shx * b.m1;
+ shx:=a.sx * b.m2 + a.shx * b.m3;
+ tx :=a.sx * b.m4 + a.shx * b.m5 + a.tx;
+ shy:=a.shy * b.m0 + a.sy * b.m1;
+ sy :=a.shy * b.m2 + a.sy * b.m3;
+ ty :=a.shy * b.m4 + a.sy * b.m5 + a.ty;
+ w0 :=a.w0 * b.m0 + a.w1 * b.m1;
+ w1 :=a.w0 * b.m2 + a.w1 * b.m3;
+ w2 :=a.w0 * b.m4 + a.w1 * b.m5 + a.w2;
+
+ result:=@self;
+
+end;
+
+{ MULTIPLY_INV_AF }
+function trans_perspective.multiply_inv_af(m : trans_affine_ptr ) : trans_perspective_ptr;
+var
+ t : trans_affine;
+
+begin
+ t.Construct(m.m0 ,m.m1 ,m.m2 ,m.m3 ,m.m4 ,m.m5 );
+ t.invert;
+
+ result:=multiply_af(@t );
+
+end;
+
+{ PREMULTIPLY_INV_AF }
+function trans_perspective.premultiply_inv_af(m : trans_affine_ptr ) : trans_perspective_ptr;
+var
+ t : trans_perspective;
+
+begin
+ t.Construct_af(m );
+ t.invert;
+
+ t.multiply(@self );
+
+ Construct(trans_perspective_ptr(@t ) );
+
+ result:=@self;
+
+end;
+
+{ STORE_TO }
+procedure trans_perspective.store_to(m : quadrilateral_ptr );
+begin
+ m[0 ]:=sx;
+ m[1 ]:=shy;
+ m[2 ]:=w0;
+ m[3 ]:=shx;
+ m[4 ]:=sy;
+ m[5 ]:=w1;
+ m[6 ]:=tx;
+ m[7 ]:=ty;
+ m[8 ]:=w2;
+
+end;
+
+{ LOAD_FROM }
+function trans_perspective.load_from(m : quadrilateral_ptr ) : trans_perspective_ptr;
+begin
+ sx :=m[0 ];
+ shy:=m[1 ];
+ w0 :=m[2 ];
+ shx:=m[3 ];
+ sy :=m[4 ];
+ w1 :=m[5 ];
+ tx :=m[6 ];
+ ty :=m[7 ];
+ w2 :=m[8 ];
+
+end;
+
+{ FROM_AFFINE }
+function trans_perspective.from_affine(a : trans_affine_ptr ) : trans_perspective_ptr;
+begin
+ sx :=a.m0;
+ shy:=a.m1;
+ w0 :=0;
+ shx:=a.m2;
+ sy :=a.m3;
+ w1 :=0;
+ tx :=a.m4;
+ ty :=a.m5;
+ w2 :=1;
+
+ result:=@self;
+
+end;
+
+{ DETERMINANT }
+function trans_perspective.determinant : double;
+begin
+ result:=
+ sx * (sy * w2 - ty * w1 ) +
+ shx * (ty * w0 - shy * w2 ) +
+ tx * (shy * w1 - sy * w0 );
+
+end;
+
+{ DETERMINANT_RECIPROCAL }
+function trans_perspective.determinant_reciprocal : double;
+begin
+ result:=1.0 / determinant;
+
+end;
+
+{ IS_VALID }
+function trans_perspective.is_valid(epsilon : double = affine_epsilon ) : boolean;
+begin
+ result:=
+ (Abs(sx ) > epsilon ) and
+ (Abs(sy ) > epsilon ) and
+ (Abs(w2 ) > epsilon );
+
+end;
+
+{ IS_IDENTITY }
+function trans_perspective.is_identity(epsilon : double = affine_epsilon ) : boolean;
+begin
+ result:=
+ is_equal_eps(sx ,1.0 ,epsilon ) and
+ is_equal_eps(shy ,0.0 ,epsilon ) and
+ is_equal_eps(w0 ,0.0 ,epsilon ) and
+ is_equal_eps(shx ,0.0 ,epsilon ) and
+ is_equal_eps(sy ,1.0 ,epsilon ) and
+ is_equal_eps(w1 ,0.0 ,epsilon ) and
+ is_equal_eps(tx ,0.0 ,epsilon ) and
+ is_equal_eps(ty ,0.0 ,epsilon ) and
+ is_equal_eps(w2 ,1.0 ,epsilon );
+
+end;
+
+{ IS_EQUAL }
+function trans_perspective.is_equal(m : trans_perspective_ptr; epsilon : double = affine_epsilon ) : boolean;
+begin
+ result:=
+ is_equal_eps(sx ,m.sx ,epsilon ) and
+ is_equal_eps(shy ,m.shy ,epsilon ) and
+ is_equal_eps(w0 ,m.w0 ,epsilon ) and
+ is_equal_eps(shx ,m.shx ,epsilon ) and
+ is_equal_eps(sy ,m.sy ,epsilon ) and
+ is_equal_eps(w1 ,m.w1 ,epsilon ) and
+ is_equal_eps(tx ,m.tx ,epsilon ) and
+ is_equal_eps(ty ,m.ty ,epsilon ) and
+ is_equal_eps(w2 ,m.w2 ,epsilon );
+
+end;
+
+{ SCALE }
+function trans_perspective.scale : double;
+var
+ x ,y : double;
+
+begin
+ x:=0.707106781 * sx + 0.707106781 * shx;
+ y:=0.707106781 * shy + 0.707106781 * sy;
+
+ result:=Sqrt(x * x + y * y );
+
+end;
+
+{ ROTATION }
+function trans_perspective.rotation : double;
+var
+ x1 ,y1 ,x2 ,y2 : double;
+
+begin
+ x1:=0.0;
+ y1:=0.0;
+ x2:=1.0;
+ y2:=0.0;
+
+ _transform(@self ,@x1 ,@y1 );
+ _transform(@self ,@x2 ,@y2 );
+
+ result:=ArcTan2(y2 - y1 ,x2 - x1 );
+
+end;
+
+{ TRANSLATION }
+procedure trans_perspective.translation(dx ,dy : double_ptr );
+begin
+ dx^:=tx;
+ dy^:=ty;
+
+end;
+
+{ SCALING }
+procedure trans_perspective.scaling(x ,y : double_ptr );
+var
+ x1 ,y1 ,x2 ,y2 : double;
+
+ t : trans_perspective;
+
+ tar : trans_affine_rotation;
+
+begin
+ x1:= 0.0;
+ y1:= 0.0;
+ x2:= 1.0;
+ y2:= 1.0;
+
+ t.Construct (trans_perspective_ptr(@self ) );
+ tar.Construct(-rotation );
+ t.multiply_af(@tar );
+
+ t.transform(@t ,@x1 ,@y1 );
+ t.transform(@t ,@x2 ,@y2 );
+
+ x^:=x2 - x1;
+ y^:=y2 - y1;
+
+end;
+
+{ SCALING_ABS }
+procedure trans_perspective.scaling_abs(x ,y : double_ptr );
+begin
+ x^:=Sqrt(sx * sx + shx * shx );
+ y^:=Sqrt(shy * shy + sy * sy );
+
+end;
+
+{ BEGIN_ }
+function trans_perspective.begin_(x ,y ,step : double ) : iterator_x;
+begin
+ result.Construct(x ,y ,step ,@self );
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_trans_single_path.pas b/src/corelib/render/software/agg_trans_single_path.pas
new file mode 100644
index 00000000..1a5845f5
--- /dev/null
+++ b/src/corelib/render/software/agg_trans_single_path.pas
@@ -0,0 +1,395 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 13.02.2006-Milano: Unit port establishment
+//
+{ agg_trans_single_path.pas }
+unit
+ agg_trans_single_path ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_vertex_source ,
+ agg_vertex_sequence ,
+ agg_trans_affine ;
+
+{ TYPES DEFINITION }
+type
+ status_e = (initial ,making_path ,ready );
+
+ trans_single_path_ptr = ^trans_single_path;
+ trans_single_path = object(trans_affine )
+ m_src_vertices : vertex_sequence;
+ m_base_length ,
+ m_kindex : double;
+
+ m_status : status_e;
+
+ m_preserve_x_scale : boolean;
+
+ constructor Construct;
+ destructor Destruct;
+
+ procedure base_length_(v : double );
+ function _base_length : double;
+
+ procedure preserve_x_scale_(f : boolean );
+ function _preserve_x_scale : boolean;
+
+ procedure reset; virtual;
+
+ procedure move_to(x ,y : double );
+ procedure line_to(x ,y : double );
+ procedure finalize_path;
+
+ procedure add_path(vs : vertex_source_ptr; path_id : unsigned = 0 );
+
+ function total_length : double;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ _transform }
+procedure _transform(this : trans_single_path_ptr; x ,y : double_ptr );
+var
+ x1 ,y1 ,dx ,dy ,d ,dd ,x2 ,y2 : double;
+
+ i ,j ,k : unsigned;
+
+begin
+ if this.m_status = ready then
+ begin
+ if this.m_base_length > 1e-10 then
+ x^:=
+ x^ *
+ (vertex_dist_ptr(this.m_src_vertices.array_operator(this.m_src_vertices.size - 1 ) ).dist /
+ this.m_base_length );
+
+ x1:=0.0;
+ y1:=0.0;
+ dx:=1.0;
+ dy:=1.0;
+ d :=0.0;
+ dd:=1.0;
+
+ if x^ < 0.0 then
+ begin
+ // Extrapolation on the left
+ x1:=vertex_dist_ptr(this.m_src_vertices.array_operator(0 ) ).x;
+ y1:=vertex_dist_ptr(this.m_src_vertices.array_operator(0 ) ).y;
+ dx:=vertex_dist_ptr(this.m_src_vertices.array_operator(1 ) ).x - x1;
+ dy:=vertex_dist_ptr(this.m_src_vertices.array_operator(1 ) ).y - y1;
+
+ dd:=
+ vertex_dist_ptr(this.m_src_vertices.array_operator(1 ) ).dist -
+ vertex_dist_ptr(this.m_src_vertices.array_operator(0 ) ).dist;
+
+ d:=x^;
+
+ end
+ else
+ if x^ > vertex_dist_ptr(this.m_src_vertices.array_operator(this.m_src_vertices.size - 1 ) ).dist then
+ begin
+ // Extrapolation on the right
+ i:=this.m_src_vertices.size - 2;
+ j:=this.m_src_vertices.size - 1;
+
+ x1:=vertex_dist_ptr(this.m_src_vertices.array_operator(j ) ).x;
+ y1:=vertex_dist_ptr(this.m_src_vertices.array_operator(j ) ).y;
+ dx:=x1 - vertex_dist_ptr(this.m_src_vertices.array_operator(i ) ).x;
+ dy:=y1 - vertex_dist_ptr(this.m_src_vertices.array_operator(i ) ).y;
+
+ dd:=
+ vertex_dist_ptr(this.m_src_vertices.array_operator(j ) ).dist -
+ vertex_dist_ptr(this.m_src_vertices.array_operator(i ) ).dist;
+
+ d:=x^ - vertex_dist_ptr(this.m_src_vertices.array_operator(j ) ).dist;
+
+ end
+ else
+ begin
+ // Interpolation
+ i:=0;
+ j:=this.m_src_vertices.size - 1;
+
+ if this.m_preserve_x_scale then
+ begin
+ i:=0;
+
+ while j - i > 1 do
+ begin
+ k:=(i + j ) shr 1;
+
+ if x^ < vertex_dist_ptr(this.m_src_vertices.array_operator(k ) ).dist then
+ j:=k
+ else
+ i:=k;
+
+ end;
+
+ d :=vertex_dist_ptr(this.m_src_vertices.array_operator(i ) ).dist;
+ dd:=vertex_dist_ptr(this.m_src_vertices.array_operator(j ) ).dist - d;
+ d :=x^ - d;
+
+ end
+ else
+ begin
+ i:=trunc(x^ * this.m_kindex );
+ j:=i + 1;
+
+ dd:=
+ vertex_dist_ptr(this.m_src_vertices.array_operator(j ) ).dist -
+ vertex_dist_ptr(this.m_src_vertices.array_operator(i ) ).dist;
+
+ d:=((x^ * this.m_kindex ) - i ) * dd;
+
+ end;
+
+ x1:=vertex_dist_ptr(this.m_src_vertices.array_operator(i ) ).x;
+ y1:=vertex_dist_ptr(this.m_src_vertices.array_operator(i ) ).y;
+ dx:=vertex_dist_ptr(this.m_src_vertices.array_operator(j ) ).x - x1;
+ dy:=vertex_dist_ptr(this.m_src_vertices.array_operator(j ) ).y - y1;
+
+ end;
+
+ x2:=x1 + dx * d / dd;
+ y2:=y1 + dy * d / dd;
+ x^:=x2 - y^ * dy / dd;
+ y^:=y2 + y^ * dx / dd;
+
+ end;
+
+end;
+
+{ CONSTRUCT }
+constructor trans_single_path.Construct;
+begin
+ inherited Construct;
+
+ transform:=@_transform;
+
+ m_src_vertices.Construct(sizeof(vertex_dist ) );
+
+ m_base_length:=0.0;
+ m_kindex :=0.0;
+
+ m_status:=initial;
+
+ m_preserve_x_scale:=true;
+
+end;
+
+{ DESTRUCT }
+destructor trans_single_path.Destruct;
+begin
+ m_src_vertices.Destruct;
+
+end;
+
+{ BASE_LENGTH_ }
+procedure trans_single_path.base_length_;
+begin
+ m_base_length:=v;
+
+end;
+
+{ _BASE_LENGTH }
+function trans_single_path._base_length;
+begin
+ result:=m_base_length;
+
+end;
+
+{ PRESERVE_X_SCALE_ }
+procedure trans_single_path.preserve_x_scale_;
+begin
+ m_preserve_x_scale:=f;
+
+end;
+
+{ _PRESERVE_X_SCALE }
+function trans_single_path._preserve_x_scale;
+begin
+ result:=m_preserve_x_scale;
+
+end;
+
+{ RESET }
+procedure trans_single_path.reset;
+begin
+ m_src_vertices.remove_all;
+
+ m_kindex:=0.0;
+ m_status:=initial;
+
+end;
+
+{ MOVE_TO }
+procedure trans_single_path.move_to;
+var
+ vd : vertex_dist;
+
+begin
+ if m_status = initial then
+ begin
+ vd.x:=x;
+ vd.y:=y;
+
+ vd.dist:=0;
+
+ m_src_vertices.modify_last(@vd );
+
+ m_status:=making_path;
+
+ end
+ else
+ line_to(x ,y );
+
+end;
+
+{ LINE_TO }
+procedure trans_single_path.line_to;
+var
+ vd : vertex_dist;
+
+begin
+ if m_status = making_path then
+ begin
+ vd.x:=x;
+ vd.y:=y;
+
+ vd.dist:=0;
+
+ m_src_vertices.add(@vd );
+
+ end;
+
+end;
+
+{ FINALIZE_PATH }
+procedure trans_single_path.finalize_path;
+var
+ i : unsigned;
+ v : vertex_dist_ptr;
+
+ dist ,d : double;
+
+begin
+ if (m_status = making_path ) and
+ (m_src_vertices.size > 1 ) then
+ begin
+ m_src_vertices.close(false );
+
+ if m_src_vertices.size > 2 then
+ if vertex_dist_ptr(m_src_vertices.array_operator(m_src_vertices.size - 2 ) ).dist * 10.0 <
+ vertex_dist_ptr(m_src_vertices.array_operator(m_src_vertices.size - 3 ) ).dist then
+ begin
+ d:=
+ vertex_dist_ptr(m_src_vertices.array_operator(m_src_vertices.size - 3 ) ).dist +
+ vertex_dist_ptr(m_src_vertices.array_operator(m_src_vertices.size - 2 ) ).dist;
+
+ move(
+ m_src_vertices.array_operator(m_src_vertices.size - 1 )^ ,
+ m_src_vertices.array_operator(m_src_vertices.size - 2 )^ ,
+ sizeof(vertex_dist ) );
+
+ m_src_vertices.remove_last;
+
+ vertex_dist_ptr(m_src_vertices.array_operator(m_src_vertices.size - 2 ) ).dist:=d;
+
+ end;
+
+ dist:=0.0;
+
+ for i:=0 to m_src_vertices.size - 1 do
+ begin
+ v:=m_src_vertices.array_operator(i );
+ d:=v.dist;
+
+ v.dist:=dist;
+ dist :=dist + d;
+
+ end;
+
+ m_kindex:=(m_src_vertices.size - 1 ) / dist;
+ m_status:=ready;
+
+ end;
+
+end;
+
+{ ADD_PATH }
+procedure trans_single_path.add_path;
+var
+ x ,y : double;
+ cmd : unsigned;
+
+begin
+ vs.rewind(path_id );
+
+ cmd:=vs.vertex(@x ,@y );
+
+ while not is_stop(cmd ) do
+ begin
+ if is_move_to(cmd ) then
+ move_to(x ,y )
+ else
+ if is_vertex(cmd ) then
+ line_to(x ,y );
+
+ cmd:=vs.vertex(@x ,@y );
+
+ end;
+
+ finalize_path;
+
+end;
+
+{ TOTAL_LENGTH }
+function trans_single_path.total_length;
+begin
+ if m_base_length >= 1e-10 then
+ begin
+ result:=m_base_length;
+
+ exit;
+
+ end;
+
+ if m_status = ready then
+ result:=vertex_dist_ptr(m_src_vertices.array_operator(m_src_vertices.size - 1 ) ).dist
+ else
+ result:=0.0
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_trans_viewport.pas b/src/corelib/render/software/agg_trans_viewport.pas
new file mode 100644
index 00000000..06244337
--- /dev/null
+++ b/src/corelib/render/software/agg_trans_viewport.pas
@@ -0,0 +1,443 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// Viewport transformer - simple orthogonal conversions from world coordinates
+// to screen (device) ones
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 27.09.2005-Milano: Complete unit port
+//
+{ agg_trans_viewport.pas }
+unit
+ agg_trans_viewport ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_trans_affine ;
+
+{ TYPES DEFINITION }
+type
+ aspect_ratio_e = (aspect_ratio_stretch ,aspect_ratio_meet ,aspect_ratio_slice );
+
+//----------------------------------------------------------trans_viewport
+ trans_viewport_ptr = ^trans_viewport;
+ trans_viewport = object(trans_affine )
+ m_world_x1 ,
+ m_world_y1 ,
+ m_world_x2 ,
+ m_world_y2 ,
+
+ m_device_x1 ,
+ m_device_y1 ,
+ m_device_x2 ,
+ m_device_y2 : double;
+
+ m_aspect : aspect_ratio_e;
+ m_is_valid : boolean;
+
+ m_align_x ,
+ m_align_y ,
+
+ m_wx1 ,
+ m_wy1 ,
+ m_wx2 ,
+ m_wy2 ,
+ m_dx1 ,
+ m_dy1 ,
+
+ m_kx ,
+ m_ky : double;
+
+ constructor Construct;
+
+ procedure preserve_aspect_ratio(alignx ,aligny : double; aspect : aspect_ratio_e );
+
+ procedure device_viewport (x1 ,y1 ,x2 ,y2 : double );
+ procedure device_viewport_ex(var x1 ,y1 ,x2 ,y2 : double );
+
+ procedure world_viewport (x1 ,y1 ,x2 ,y2 : double );
+ procedure world_viewport_ex(var x1 ,y1 ,x2 ,y2 : double );
+
+ procedure world_viewport_actual(var x1 ,y1 ,x2 ,y2 : double );
+
+ function is_valid : boolean;
+ function align_x : double;
+ function align_y : double;
+ function aspect_ratio : aspect_ratio_e;
+
+ procedure inverse_transform_scale_only(x ,y : double_ptr );
+
+ function device_dx : double;
+ function device_dy : double;
+ function scale_x : double;
+ function scale_y : double;
+ function scale : double;
+
+ procedure to_affine (mtx : trans_affine_ptr );
+ procedure to_affine_scale_only(mtx : trans_affine_ptr );
+
+ function byte_size : unsigned;
+ procedure serialize (ptr : int8u_ptr );
+ procedure deserialize(ptr : int8u_ptr);
+
+ procedure update;
+
+ end;
+
+{ GLOBAL VARIABLES & CONSTANTS }
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ UNIT IMPLEMENTATION }
+{ _transform }
+procedure _transform(this : trans_viewport_ptr; x ,y : double_ptr );
+begin
+ x^:=x^ * this.m_kx;
+ y^:=y^ * this.m_ky;
+
+end;
+
+{ _inverse_transform }
+procedure _inverse_transform(this : trans_viewport_ptr; x ,y : double_ptr );
+begin
+ x^:=(x^ - this.m_dx1 ) / this.m_kx + this.m_wx1;
+ y^:=(y^ - this.m_dy1 ) / this.m_ky + this.m_wy1;
+
+end;
+
+{ CONSTRUCT }
+constructor trans_viewport.Construct;
+begin
+ inherited Construct;
+
+ transform :=@_transform;
+ inverse_transform:=@_inverse_transform;
+
+ m_world_x1:=0;
+ m_world_y1:=0;
+ m_world_x2:=1;
+ m_world_y2:=1;
+
+ m_device_x1:=0;
+ m_device_y1:=0;
+ m_device_x2:=1;
+ m_device_y2:=1;
+
+ m_aspect :=aspect_ratio_stretch;
+ m_is_valid:=true;
+
+ m_align_x:=0.5;
+ m_align_y:=0.5;
+
+ m_wx1:=0;
+ m_wy1:=0;
+ m_wx2:=1;
+ m_wy2:=1;
+ m_dx1:=0;
+ m_dy1:=0;
+
+ m_kx:=1;
+ m_ky:=1;
+
+end;
+
+{ preserve_aspect_ratio }
+procedure trans_viewport.preserve_aspect_ratio;
+begin
+ m_align_x:=alignx;
+ m_align_y:=aligny;
+ m_aspect :=aspect;
+
+ update;
+
+end;
+
+{ device_viewport }
+procedure trans_viewport.device_viewport;
+begin
+ m_device_x1:=x1;
+ m_device_y1:=y1;
+ m_device_x2:=x2;
+ m_device_y2:=y2;
+
+ update;
+
+end;
+
+{ device_viewport_ex }
+procedure trans_viewport.device_viewport_ex;
+begin
+ x1:=m_device_x1;
+ y1:=m_device_y1;
+ x2:=m_device_x2;
+ y2:=m_device_y2;
+
+end;
+
+{ world_viewport }
+procedure trans_viewport.world_viewport;
+begin
+ m_world_x1:=x1;
+ m_world_y1:=y1;
+ m_world_x2:=x2;
+ m_world_y2:=y2;
+
+ update;
+
+end;
+
+{ world_viewport_ex }
+procedure trans_viewport.world_viewport_ex;
+begin
+ x1:=m_world_x1;
+ y1:=m_world_y1;
+ x2:=m_world_x2;
+ y2:=m_world_y2;
+
+end;
+
+{ world_viewport_actual }
+procedure trans_viewport.world_viewport_actual;
+begin
+ x1:=m_wx1;
+ y1:=m_wy1;
+ x2:=m_wx2;
+ y2:=m_wy2;
+
+end;
+
+{ is_valid }
+function trans_viewport.is_valid;
+begin
+ result:=m_is_valid;
+
+end;
+
+{ align_x }
+function trans_viewport.align_x;
+begin
+ result:=m_align_x;
+
+end;
+
+{ align_y }
+function trans_viewport.align_y;
+begin
+ result:=m_align_y;
+
+end;
+
+{ aspect_ratio }
+function trans_viewport.aspect_ratio;
+begin
+ result:=m_aspect;
+
+end;
+
+{ inverse_transform_scale_only }
+procedure trans_viewport.inverse_transform_scale_only;
+begin
+ x^:=x^ / m_kx;
+ y^:=y^ / m_ky;
+
+end;
+
+{ device_dx }
+function trans_viewport.device_dx;
+begin
+ result:=m_dx1 - m_wx1 * m_kx;
+
+end;
+
+{ device_dy }
+function trans_viewport.device_dy;
+begin
+ result:=m_dy1 - m_wy1 * m_ky;
+
+end;
+
+{ scale_x }
+function trans_viewport.scale_x;
+begin
+ result:=m_kx;
+
+end;
+
+{ scale_y }
+function trans_viewport.scale_y;
+begin
+ result:=m_ky;
+
+end;
+
+{ scale }
+function trans_viewport.scale;
+begin
+ result:=(m_kx + m_ky ) * 0.5;
+
+end;
+
+{ to_affine }
+procedure trans_viewport.to_affine;
+var
+ m ,
+ t : trans_affine_translation;
+ s : trans_affine_scaling;
+
+begin
+ m.Construct(-m_wx1 ,-m_wy1 );
+ s.Construct(m_kx ,m_ky );
+ m.multiply (@s );
+ t.Construct(m_dx1 ,m_dy1 );
+ m.multiply (@t );
+
+ mtx.assign(@m );
+
+end;
+
+{ to_affine_scale_only }
+procedure trans_viewport.to_affine_scale_only;
+var
+ s : trans_affine_scaling;
+
+begin
+ s.Construct(m_kx ,m_ky );
+
+ mtx.assign(@s );
+
+end;
+
+{ byte_size }
+function trans_viewport.byte_size;
+begin
+ result:=sizeof(self );
+
+end;
+
+{ serialize }
+procedure trans_viewport.serialize;
+begin
+ move(self ,ptr^ ,sizeof(self ) );
+
+end;
+
+{ deserialize }
+procedure trans_viewport.deserialize;
+begin
+ move(ptr^ ,self ,sizeof(self ) );
+
+end;
+
+{ update }
+procedure trans_viewport.update;
+const
+ epsilon : double = 1e-30;
+
+var
+ d ,
+
+ world_x1 ,
+ world_y1 ,
+ world_x2 ,
+ world_y2 ,
+
+ device_x1 ,
+ device_y1 ,
+ device_x2 ,
+ device_y2 : double;
+
+begin
+ if (Abs(m_world_x1 - m_world_x2 ) < epsilon ) or
+ (Abs(m_world_y1 - m_world_y2 ) < epsilon ) or
+ (Abs(m_device_x1 - m_device_x2 ) < epsilon ) or
+ (Abs(m_device_y1 - m_device_y2 ) < epsilon ) then
+ begin
+ m_wx1:=m_world_x1;
+ m_wy1:=m_world_y1;
+ m_wx2:=m_world_x1 + 1;
+ m_wy2:=m_world_y2 + 1;
+ m_dx1:=m_device_x1;
+ m_dy1:=m_device_y1;
+ m_kx :=1;
+ m_ky :=1;
+
+ m_is_valid:=false;
+
+ end
+ else
+ begin
+ world_x1 :=m_world_x1;
+ world_y1 :=m_world_y1;
+ world_x2 :=m_world_x2;
+ world_y2 :=m_world_y2;
+ device_x1:=m_device_x1;
+ device_y1:=m_device_y1;
+ device_x2:=m_device_x2;
+ device_y2:=m_device_y2;
+
+ if not (m_aspect = aspect_ratio_stretch ) then
+ begin
+ m_kx:=(device_x2 - device_x1 ) / (world_x2 - world_x1 );
+ m_ky:=(device_y2 - device_y1 ) / (world_y2 - world_y1 );
+
+ if (m_aspect = aspect_ratio_meet ) = (m_kx < m_ky ) then
+ begin
+ d:=(world_y2 - world_y1 ) * m_ky / m_kx;
+
+ world_y1:=world_y1 + ((world_y2 - world_y1 - d ) * m_align_y );
+ world_y2:=world_y1 + d;
+
+ end
+ else
+ begin
+ d:=(world_x2 - world_x1 ) * m_kx / m_ky;
+
+ world_x1:=world_x1 + ((world_x2 - world_x1 - d ) * m_align_x );
+ world_x2:=world_x1 + d;
+
+ end;
+
+ end;
+
+ m_wx1:=world_x1;
+ m_wy1:=world_y1;
+ m_wx2:=world_x2;
+ m_wy2:=world_y2;
+ m_dx1:=device_x1;
+ m_dy1:=device_y1;
+ m_kx :=(device_x2 - device_x1 ) / (world_x2 - world_x1 );
+ m_ky :=(device_y2 - device_y1 ) / (world_y2 - world_y1 );
+
+ m_is_valid:=true;
+
+ end;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_trans_warp_magnifier.pas b/src/corelib/render/software/agg_trans_warp_magnifier.pas
new file mode 100644
index 00000000..447d8b92
--- /dev/null
+++ b/src/corelib/render/software/agg_trans_warp_magnifier.pas
@@ -0,0 +1,142 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 06.20.2006-Milano: Unit port establishment
+//
+{ agg_trans_warp_magnifier.pas }
+unit
+ agg_trans_warp_magnifier ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_trans_affine ;
+
+{ TYPES DEFINITION }
+type
+ trans_warp_magnifier_ptr = ^trans_warp_magnifier;
+ trans_warp_magnifier = object(trans_affine )
+ m_xc ,
+ m_yc ,
+
+ m_magn ,
+ m_radius : double;
+
+ constructor Construct;
+
+ procedure center (x ,y : double );
+ procedure magnification(m : double );
+ procedure radius (r : double );
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ _transform }
+procedure _transform(this : trans_warp_magnifier_ptr; x ,y : double_ptr );
+var
+ dx ,dy ,r ,m : double;
+
+begin
+ dx:=x^ - this.m_xc;
+ dy:=y^ - this.m_yc;
+ r :=Sqrt(dx * dx + dy * dy );
+
+ if r < this.m_radius then
+ begin
+ x^:=this.m_xc + dx * this.m_magn;
+ y^:=this.m_yc + dy * this.m_magn;
+
+ exit;
+
+ end;
+
+ m:=(r + this.m_radius * (this.m_magn - 1.0 ) ) / r;
+
+ x^:=this.m_xc + dx * m;
+ y^:=this.m_yc + dy * m;
+
+end;
+
+{ _inverse_transform }
+procedure _inverse_transform(this : trans_warp_magnifier_ptr; x ,y : double_ptr );
+var
+ t : trans_warp_magnifier;
+
+begin
+ t.Construct;
+
+ t:=this^;
+
+ t.magnification(1.0 / this.m_magn );
+ t.radius (this.m_radius * this.m_magn );
+ t.transform (@t ,x ,y );
+
+end;
+
+{ CONSTRUCT }
+constructor trans_warp_magnifier.Construct;
+begin
+ inherited Construct;
+
+ m_xc:=0.0;
+ m_yc:=0.0;
+
+ m_magn :=1.0;
+ m_radius:=1.0;
+
+ transform :=@_transform;
+ inverse_transform:=@_inverse_transform;
+
+end;
+
+{ CENTER }
+procedure trans_warp_magnifier.center;
+begin
+ m_xc:=x;
+ m_yc:=y;
+
+end;
+
+{ MAGNIFICATION }
+procedure trans_warp_magnifier.magnification;
+begin
+ m_magn:=m;
+
+end;
+
+{ RADIUS }
+procedure trans_warp_magnifier.radius;
+begin
+ m_radius:=r;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_vcgen_bspline.pas b/src/corelib/render/software/agg_vcgen_bspline.pas
new file mode 100644
index 00000000..d07530e0
--- /dev/null
+++ b/src/corelib/render/software/agg_vcgen_bspline.pas
@@ -0,0 +1,403 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 19.01.2006-Milano: Complete Unit Port
+// 18.01.2006-Milano: Unit port establishment
+//
+{ agg_vcgen_bspline.pas }
+unit
+ agg_vcgen_bspline ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_bspline ,
+ agg_array ,
+ agg_vertex_source ;
+
+{ TYPES DEFINITION }
+type
+ status_e = (initial ,ready ,polygon ,end_poly ,stop );
+
+ vcgen_bspline_ptr = ^vcgen_bspline;
+ vcgen_bspline = object(vertex_source )
+ m_src_vertices : pod_deque;
+
+ m_spline_x ,
+ m_spline_y : bspline;
+
+ m_interpolation_step : double;
+
+ m_closed : unsigned;
+ m_status : status_e;
+
+ m_src_vertex : unsigned;
+
+ m_cur_abscissa ,
+ m_max_abscissa : double;
+
+ constructor Construct;
+ destructor Destruct; virtual;
+
+ procedure interpolation_step_(v : double );
+ function _interpolation_step : double;
+
+ // Vertex Generator Interface
+ procedure remove_all; virtual;
+ procedure add_vertex(x ,y : double; cmd : unsigned ); virtual;
+
+ // Vertex Source Interface
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor vcgen_bspline.Construct;
+begin
+ inherited Construct;
+
+ m_src_vertices.Construct(sizeof(point_type ) ,6 );
+ m_spline_x.Construct;
+ m_spline_y.Construct;
+
+ m_interpolation_step:=1.0 / 50.0;
+
+ m_closed:=0;
+ m_status:=initial;
+
+ m_src_vertex:=0;
+
+end;
+
+{ DESTRUCT }
+destructor vcgen_bspline.Destruct;
+begin
+ inherited Destruct;
+
+ m_src_vertices.Destruct;
+ m_spline_x.Destruct;
+ m_spline_y.Destruct;
+
+end;
+
+{ INTERPOLATION_STEP_ }
+procedure vcgen_bspline.interpolation_step_;
+begin
+ m_interpolation_step:=v;
+
+end;
+
+{ _INTERPOLATION_STEP }
+function vcgen_bspline._interpolation_step;
+begin
+ result:=m_interpolation_step;
+
+end;
+
+{ REMOVE_ALL }
+procedure vcgen_bspline.remove_all;
+begin
+ m_src_vertices.remove_all;
+
+ m_closed:=0;
+ m_status:=initial;
+
+ m_src_vertex:=0;
+
+end;
+
+{ ADD_VERTEX }
+procedure vcgen_bspline.add_vertex;
+var
+ pt : point_type;
+
+begin
+ m_status:=initial;
+
+ if is_move_to(cmd ) then
+ begin
+ pt.x:=x;
+ pt.y:=y;
+
+ m_src_vertices.modify_last(@pt );
+
+ end
+ else
+ if is_vertex(cmd ) then
+ begin
+ pt.x:=x;
+ pt.y:=y;
+
+ m_src_vertices.add(@pt );
+
+ end
+ else
+ m_closed:=get_close_flag(cmd );
+
+end;
+
+{ REWIND }
+procedure vcgen_bspline.rewind;
+var
+ i : unsigned;
+ x : double;
+
+begin
+ m_cur_abscissa:=0.0;
+ m_max_abscissa:=0.0;
+
+ m_src_vertex:=0;
+
+ if (m_status = initial ) and
+ (m_src_vertices.size > 2 ) then
+ begin
+ if m_closed <> 0 then
+ begin
+ m_spline_x.init(m_src_vertices.size + 8 );
+ m_spline_y.init(m_src_vertices.size + 8 );
+
+ m_spline_x.add_point(0.0 ,point_type_ptr(m_src_vertices.prev(m_src_vertices.size - 3 ) )^.x );
+ m_spline_y.add_point(0.0 ,point_type_ptr(m_src_vertices.prev(m_src_vertices.size - 3 ) )^.y );
+ m_spline_x.add_point(1.0 ,point_type_ptr(m_src_vertices.array_operator(m_src_vertices.size - 3 ) )^.x );
+ m_spline_y.add_point(1.0 ,point_type_ptr(m_src_vertices.array_operator(m_src_vertices.size - 3 ) )^.y );
+ m_spline_x.add_point(2.0 ,point_type_ptr(m_src_vertices.array_operator(m_src_vertices.size - 2 ) )^.x );
+ m_spline_y.add_point(2.0 ,point_type_ptr(m_src_vertices.array_operator(m_src_vertices.size - 2 ) )^.y );
+ m_spline_x.add_point(3.0 ,point_type_ptr(m_src_vertices.array_operator(m_src_vertices.size - 1 ) )^.x );
+ m_spline_y.add_point(3.0 ,point_type_ptr(m_src_vertices.array_operator(m_src_vertices.size - 1 ) )^.y );
+
+ end
+ else
+ begin
+ m_spline_x.init(m_src_vertices.size );
+ m_spline_y.init(m_src_vertices.size );
+
+ end;
+
+ for i:=0 to m_src_vertices.size - 1 do
+ begin
+ if m_closed <> 0 then
+ x:=i + 4
+ else
+ x:=i;
+
+ m_spline_x.add_point(x ,point_type_ptr(m_src_vertices.array_operator(i ) )^.x );
+ m_spline_y.add_point(x ,point_type_ptr(m_src_vertices.array_operator(i ) )^.y );
+
+ end;
+
+ m_cur_abscissa:=0.0;
+ m_max_abscissa:=m_src_vertices.size - 1;
+
+ if m_closed <> 0 then
+ begin
+ m_cur_abscissa:=4.0;
+ m_max_abscissa:=m_max_abscissa + 5.0;
+
+ m_spline_x.add_point(
+ m_src_vertices.size + 4 ,
+ point_type_ptr(m_src_vertices.array_operator(0 ) )^.x );
+
+ m_spline_y.add_point(
+ m_src_vertices.size + 4 ,
+ point_type_ptr(m_src_vertices.array_operator(0 ) )^.y );
+
+ m_spline_x.add_point(
+ m_src_vertices.size + 5 ,
+ point_type_ptr(m_src_vertices.array_operator(1 ) )^.x );
+
+ m_spline_y.add_point(
+ m_src_vertices.size + 5 ,
+ point_type_ptr(m_src_vertices.array_operator(1 ) )^.y );
+
+ m_spline_x.add_point(
+ m_src_vertices.size + 6 ,
+ point_type_ptr(m_src_vertices.array_operator(2 ) )^.x );
+
+ m_spline_y.add_point(
+ m_src_vertices.size + 6 ,
+ point_type_ptr(m_src_vertices.array_operator(2 ) )^.y );
+
+ m_spline_x.add_point(
+ m_src_vertices.size + 7 ,
+ point_type_ptr(m_src_vertices.next(2 ) )^.x );
+
+ m_spline_y.add_point(
+ m_src_vertices.size + 7 ,
+ point_type_ptr(m_src_vertices.next(2 ) )^.y );
+
+ end;
+
+ m_spline_x.prepare;
+ m_spline_y.prepare;
+
+ end;
+
+ m_status:=ready;
+
+end;
+
+{ VERTEX }
+function vcgen_bspline.vertex;
+var
+ cmd : unsigned;
+
+label
+ _next ,_ready ,_polygon ;
+
+begin
+ cmd:=path_cmd_line_to;
+
+_next:
+ while not is_stop(cmd ) do
+ case m_status of
+ initial :
+ begin
+ rewind(0 );
+
+ goto _ready;
+
+ end;
+
+ ready :
+ _ready:
+ begin
+ if m_src_vertices.size < 2 then
+ begin
+ cmd:=path_cmd_stop;
+
+ goto _next;
+
+ end;
+
+ if m_src_vertices.size = 2 then
+ begin
+ x^:=point_type_ptr(m_src_vertices.array_operator(m_src_vertex ) )^.x;
+ y^:=point_type_ptr(m_src_vertices.array_operator(m_src_vertex ) )^.y;
+
+ inc(m_src_vertex );
+
+ if m_src_vertex = 1 then
+ begin
+ result:=path_cmd_move_to;
+
+ exit;
+
+ end;
+
+ if m_src_vertex = 2 then
+ begin
+ result:=path_cmd_line_to;
+
+ exit;
+
+ end;
+
+ cmd:=path_cmd_stop;
+
+ goto _next;
+
+ end;
+
+ cmd:=path_cmd_move_to;
+
+ m_status:=polygon;
+
+ m_src_vertex:=0;
+
+ goto _polygon;
+
+ end;
+
+ polygon :
+ _polygon:
+ begin
+ if m_cur_abscissa >= m_max_abscissa then
+ if m_closed <> 0 then
+ begin
+ m_status:=end_poly;
+
+ goto _next;
+
+ end
+ else
+ begin
+ x^:=point_type_ptr(m_src_vertices.array_operator(m_src_vertices.size - 1 ) )^.x;
+ y^:=point_type_ptr(m_src_vertices.array_operator(m_src_vertices.size - 1 ) )^.y;
+
+ m_status:=end_poly;
+ result :=path_cmd_line_to;
+
+ exit;
+
+ end;
+
+ x^:=m_spline_x.get_stateful(m_cur_abscissa );
+ y^:=m_spline_y.get_stateful(m_cur_abscissa );
+
+ inc(m_src_vertex );
+
+ m_cur_abscissa:=m_cur_abscissa + m_interpolation_step;
+
+ if m_src_vertex = 1 then
+ result:=path_cmd_move_to
+ else
+ result:=path_cmd_line_to;
+
+ exit;
+
+ end;
+
+ end_poly :
+ begin
+ m_status:=stop;
+ result :=path_cmd_end_poly or m_closed;
+
+ exit;
+
+ end;
+
+ stop :
+ begin
+ result:=path_cmd_stop;
+
+ exit;
+
+ end;
+
+ end;
+
+ result:=cmd;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_vcgen_contour.pas b/src/corelib/render/software/agg_vcgen_contour.pas
new file mode 100644
index 00000000..f8d11207
--- /dev/null
+++ b/src/corelib/render/software/agg_vcgen_contour.pas
@@ -0,0 +1,453 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// Contour generator
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 12.02.2006-Milano: Unit port establishment
+//
+{ agg_vcgen_contour.pas }
+unit
+ agg_vcgen_contour ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_array ,
+ agg_math ,
+ agg_math_stroke ,
+ agg_vertex_source ,
+ agg_vertex_sequence ;
+
+{ TYPES DEFINITION }
+type
+ status_e = (initial ,ready ,outline ,out_vertices ,end_poly ,stop );
+
+ vcgen_contour_ptr = ^vcgen_contour;
+ vcgen_contour = object(vertex_source )
+ m_src_vertices : vertex_sequence;
+ m_out_vertices : pod_deque;
+
+ m_width : double;
+
+ m_line_join ,
+ m_inner_join : unsigned;
+ m_approx_scale ,
+ m_abs_width ,
+ m_signed_width ,
+ m_miter_limit ,
+
+ m_inner_miter_limit : double;
+
+ m_status : status_e;
+
+ m_src_vertex ,
+ m_out_vertex ,
+ m_closed ,
+ m_orientation : unsigned;
+ m_auto_detect : boolean;
+
+ constructor Construct;
+ destructor Destruct; virtual;
+
+ procedure line_join_ (lj : unsigned );
+ procedure inner_join_(ij : unsigned );
+
+ procedure width_(w : double );
+
+ procedure miter_limit_ (ml : double );
+ procedure miter_limit_theta_ (t : double );
+ procedure inner_miter_limit_ (ml : double );
+ procedure approximation_scale_(_as_ : double );
+
+ procedure auto_detect_orientation_(v : boolean );
+
+ function _line_join : unsigned;
+ function _inner_join : unsigned;
+ function _width : double;
+ function _miter_limit : double;
+ function _inner_miter_limit : double;
+ function _approximation_scale : double;
+ function _auto_detect_orientation : boolean;
+
+ // Generator interface
+ procedure remove_all; virtual;
+ procedure add_vertex(x ,y : double; cmd : unsigned ); virtual;
+
+ // Vertex Source Interface
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor vcgen_contour.Construct;
+begin
+ m_src_vertices.Construct(sizeof(vertex_dist ) );
+ m_out_vertices.Construct(sizeof(point_type ) );
+
+ m_width:=1.0;
+
+ m_line_join :=bevel_join;
+ m_inner_join :=inner_miter;
+ m_approx_scale:=1.0;
+ m_abs_width :=1.0;
+ m_signed_width:=1.0;
+ m_miter_limit :=4.0;
+
+ m_inner_miter_limit:=1.0 + 1.0 / 64.0;
+
+ m_status :=initial;
+ m_src_vertex :=0;
+ m_closed :=0;
+ m_orientation:=0;
+ m_auto_detect:=false;
+
+end;
+
+{ DESTRUCT }
+destructor vcgen_contour.Destruct;
+begin
+ m_src_vertices.Destruct;
+ m_out_vertices.Destruct;
+
+end;
+
+{ LINE_JOIN_ }
+procedure vcgen_contour.line_join_;
+begin
+ m_line_join:=lj;
+
+end;
+
+{ INNER_JOIN_ }
+procedure vcgen_contour.inner_join_;
+begin
+ m_inner_join:=ij;
+
+end;
+
+{ WIDTH_ }
+procedure vcgen_contour.width_;
+begin
+ m_width:=w * 0.5;
+
+end;
+
+{ MITER_LIMIT_ }
+procedure vcgen_contour.miter_limit_;
+begin
+ m_miter_limit:=ml;
+
+end;
+
+{ MITER_LIMIT_THETA_ }
+procedure vcgen_contour.miter_limit_theta_;
+begin
+ m_miter_limit:=1.0 / Sin(t * 0.5 );
+
+end;
+
+{ INNER_MITER_LIMIT_ }
+procedure vcgen_contour.inner_miter_limit_;
+begin
+ m_inner_miter_limit:=ml;
+
+end;
+
+{ APPROXIMATION_SCALE_ }
+procedure vcgen_contour.approximation_scale_;
+begin
+ m_approx_scale:=_as_;
+
+end;
+
+{ AUTO_DETECT_ORIENTATION_ }
+procedure vcgen_contour.auto_detect_orientation_;
+begin
+ m_auto_detect:=v;
+
+end;
+
+{ _LINE_JOIN }
+function vcgen_contour._line_join;
+begin
+ result:=m_line_join;
+
+end;
+
+{ _INNER_JOIN }
+function vcgen_contour._inner_join;
+begin
+ result:=m_inner_join;
+
+end;
+
+{ _WIDTH }
+function vcgen_contour._width;
+begin
+ result:=m_width * 2.0;
+
+end;
+
+{ _MITER_LIMIT }
+function vcgen_contour._miter_limit;
+begin
+ result:=m_miter_limit;
+
+end;
+
+{ _INNER_MITER_LIMIT }
+function vcgen_contour._inner_miter_limit;
+begin
+ result:=m_inner_miter_limit;
+
+end;
+
+{ _APPROXIMATION_SCALE }
+function vcgen_contour._approximation_scale;
+begin
+ result:=m_approx_scale;
+
+end;
+
+{ _AUTO_DETECT_ORIENTATION }
+function vcgen_contour._auto_detect_orientation;
+begin
+ result:=m_auto_detect;
+
+end;
+
+{ REMOVE_ALL }
+procedure vcgen_contour.remove_all;
+begin
+ m_src_vertices.remove_all;
+
+ m_closed :=0;
+ m_orientation :=0;
+ m_abs_width :=Abs(m_width );
+ m_signed_width:=m_width;
+ m_status :=initial;
+
+end;
+
+{ ADD_VERTEX }
+procedure vcgen_contour.add_vertex;
+var
+ vd : vertex_dist;
+
+begin
+ m_status:=initial;
+
+ vd.x:=x;
+ vd.y:=y;
+
+ vd.dist:=0;
+
+ if is_move_to(cmd ) then
+ m_src_vertices.modify_last(@vd )
+ else
+ if is_vertex(cmd ) then
+ m_src_vertices.add(@vd )
+ else
+ if is_end_poly(cmd ) then
+ begin
+ m_closed:=get_close_flag(cmd );
+
+ if m_orientation = path_flags_none then
+ m_orientation:=get_orientation(cmd );
+
+ end;
+
+end;
+
+{ REWIND }
+procedure vcgen_contour.rewind;
+begin
+ if m_status = initial then
+ begin
+ m_src_vertices.close(true );
+
+ m_signed_width:=m_width;
+
+ if m_auto_detect then
+ if not is_oriented(m_orientation ) then
+ if calc_polygon_area_vs(@m_src_vertices ) > 0.0 then
+ m_orientation:=path_flags_ccw
+ else
+ m_orientation:=path_flags_cw;
+
+ if is_oriented(m_orientation ) then
+ if is_ccw(m_orientation ) then
+ m_signed_width:=m_width
+ else
+ m_signed_width:=-m_width;
+
+ end;
+
+ m_status :=ready;
+ m_src_vertex:=0;
+
+end;
+
+{ VERTEX }
+function vcgen_contour.vertex;
+var
+ cmd : unsigned;
+
+ c : point_type_ptr;
+
+label
+ _next ,_ready ,_outline ,_out_vertices ;
+
+begin
+ cmd:=path_cmd_line_to;
+
+_next:
+ while not is_stop(cmd ) do
+ case m_status of
+ initial :
+ begin
+ rewind(0 );
+
+ goto _ready;
+
+ end;
+
+ ready :
+ _ready:
+ begin
+ if m_src_vertices.size < 2 + unsigned(m_closed <> 0 ) then
+ begin
+ cmd:=path_cmd_stop;
+
+ goto _next;
+
+ end;
+
+ m_status:=outline;
+
+ cmd:=path_cmd_move_to;
+
+ m_src_vertex:=0;
+ m_out_vertex:=0;
+
+ goto _outline;
+
+ end;
+
+ outline :
+ _outline:
+ begin
+ if m_src_vertex >= m_src_vertices.size then
+ begin
+ m_status:=end_poly;
+
+ goto _next;
+
+ end;
+
+ stroke_calc_join(
+ @m_out_vertices ,
+ m_src_vertices.prev(m_src_vertex ) ,
+ m_src_vertices.curr(m_src_vertex ) ,
+ m_src_vertices.next(m_src_vertex ) ,
+ vertex_dist_ptr(m_src_vertices.prev(m_src_vertex ) ).dist ,
+ vertex_dist_ptr(m_src_vertices.curr(m_src_vertex ) ).dist ,
+ m_signed_width ,
+ m_line_join ,
+ m_inner_join ,
+ m_miter_limit ,
+ m_inner_miter_limit ,
+ m_approx_scale );
+
+ inc(m_src_vertex );
+
+ m_status :=out_vertices;
+ m_out_vertex:=0;
+
+ goto _out_vertices;
+
+ end;
+
+ out_vertices :
+ _out_vertices:
+ if m_out_vertex >= m_out_vertices.size then
+ m_status:=outline
+ else
+ begin
+ c:=m_out_vertices.array_operator(m_out_vertex );
+
+ inc(m_out_vertex );
+
+ x^:=c.x;
+ y^:=c.y;
+
+ result:=cmd;
+
+ exit;
+
+ end;
+
+ end_poly :
+ begin
+ if m_closed = 0 then
+ begin
+ result:=path_cmd_stop;
+
+ exit;
+
+ end;
+
+ m_status:=stop;
+ result :=path_cmd_end_poly or path_flags_close or path_flags_ccw;
+
+ exit;
+
+ end;
+
+ stop :
+ begin
+ result:=path_cmd_stop;
+
+ exit;
+
+ end;
+
+ end;
+
+ result:=cmd;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_vcgen_dash.pas b/src/corelib/render/software/agg_vcgen_dash.pas
new file mode 100644
index 00000000..fb5987a0
--- /dev/null
+++ b/src/corelib/render/software/agg_vcgen_dash.pas
@@ -0,0 +1,382 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// Line dash generator
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 26.01.2006-Milano: Unit port establishment
+//
+{ agg_vcgen_dash.pas }
+unit
+ agg_vcgen_dash ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_vertex_source ,
+ agg_vertex_sequence ,
+ agg_shorten_path ;
+
+{ TYPES DEFINITION }
+const
+ max_dashes = 32;
+
+type
+ status_e = (initial ,ready ,polyline ,stop );
+
+ vcgen_dash_ptr = ^vcgen_dash;
+ vcgen_dash = object(vertex_source )
+ m_dashes : array[0..max_dashes - 1 ] of double;
+
+ m_total_dash_len : double;
+ m_num_dashes : unsigned;
+ m_dash_start ,
+ m_shorten ,
+ m_curr_dash_start : double;
+
+ m_curr_dash : unsigned;
+ m_curr_rest : double;
+
+ m_v1 ,
+ m_v2 : vertex_dist_ptr;
+
+ m_src_vertices : vertex_sequence;
+
+ m_closed : unsigned;
+ m_status : status_e;
+
+ m_src_vertex : unsigned;
+
+ constructor Construct;
+ destructor Destruct; virtual;
+
+ procedure remove_all_dashes;
+ procedure add_dash (dash_len ,gap_len : double );
+ procedure dash_start(ds : double );
+
+ procedure shorten_(s : double );
+ function _shorten : double;
+
+ // Vertex Generator Interface
+ procedure remove_all; virtual;
+ procedure add_vertex(x ,y : double; cmd : unsigned ); virtual;
+
+ // Vertex Source Interface
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ // Private
+ procedure calc_dash_start(ds : double );
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor vcgen_dash.Construct;
+begin
+ m_src_vertices.Construct(sizeof(vertex_dist ) );
+
+ m_total_dash_len :=0.0;
+ m_num_dashes :=0;
+ m_dash_start :=0.0;
+ m_shorten :=0.0;
+ m_curr_dash_start:=0.0;
+ m_curr_dash :=0;
+
+ m_closed :=0;
+ m_status :=initial;
+ m_src_vertex:=0;
+
+end;
+
+{ DESTRUCT }
+destructor vcgen_dash.Destruct;
+begin
+ m_src_vertices.Destruct;
+
+end;
+
+{ REMOVE_ALL_DASHES }
+procedure vcgen_dash.remove_all_dashes;
+begin
+ m_total_dash_len :=0.0;
+ m_num_dashes :=0;
+ m_curr_dash_start:=0.0;
+ m_curr_dash :=0;
+
+end;
+
+{ ADD_DASH }
+procedure vcgen_dash.add_dash;
+begin
+ if m_num_dashes < max_dashes then
+ begin
+ m_total_dash_len:=m_total_dash_len + dash_len + gap_len;
+
+ m_dashes[m_num_dashes ]:=dash_len;
+
+ inc(m_num_dashes );
+
+ m_dashes[m_num_dashes ]:=gap_len;
+
+ inc(m_num_dashes );
+
+ end;
+
+end;
+
+{ DASH_START }
+procedure vcgen_dash.dash_start;
+begin
+ m_dash_start:=ds;
+
+ calc_dash_start(Abs(ds ) );
+
+end;
+
+{ SHORTEN_ }
+procedure vcgen_dash.shorten_;
+begin
+ m_shorten:=s;
+
+end;
+
+{ _SHORTEN }
+function vcgen_dash._shorten;
+begin
+ result:=m_shorten;
+
+end;
+
+{ REMOVE_ALL }
+procedure vcgen_dash.remove_all;
+begin
+ m_status:=initial;
+
+ m_src_vertices.remove_all;
+
+ m_closed:=0;
+
+end;
+
+{ ADD_VERTEX }
+procedure vcgen_dash.add_vertex;
+var
+ vd : vertex_dist;
+
+begin
+ m_status:=initial;
+
+ vd.x :=x;
+ vd.y :=y;
+ vd.dist:=0;
+
+ if is_move_to(cmd ) then
+ m_src_vertices.modify_last(@vd )
+ else
+ if is_vertex(cmd ) then
+ m_src_vertices.add(@vd )
+ else
+ m_closed:=get_close_flag(cmd );
+
+end;
+
+{ REWIND }
+procedure vcgen_dash.rewind;
+begin
+ if m_status = initial then
+ begin
+ m_src_vertices.close(boolean(m_closed <> 0 ) );
+
+ shorten_path(@m_src_vertices ,m_shorten ,m_closed );
+
+ end;
+
+ m_status :=ready;
+ m_src_vertex:=0;
+
+end;
+
+{ VERTEX }
+function vcgen_dash.vertex;
+var
+ cmd : unsigned;
+
+ dash_rest : double;
+
+label
+ _next ,_ready ;
+
+begin
+ cmd:=path_cmd_move_to;
+
+_next:
+ while not is_stop(cmd ) do
+ case m_status of
+ initial:
+ begin
+ rewind(0 );
+
+ goto _ready;
+
+ end;
+
+ ready :
+ _ready:
+ begin
+ if (m_num_dashes < 2 ) or
+ (m_src_vertices.size < 2 ) then
+ begin
+ cmd:=path_cmd_stop;
+
+ goto _next;
+
+ end;
+
+ m_status :=polyline;
+ m_src_vertex:=1;
+
+ m_v1:=m_src_vertices.array_operator(0 );
+ m_v2:=m_src_vertices.array_operator(1 );
+
+ m_curr_rest:=m_v1.dist;
+
+ x^:=m_v1.x;
+ y^:=m_v1.y;
+
+ if m_dash_start >= 0.0 then
+ calc_dash_start(m_dash_start );
+
+ result:=path_cmd_move_to;
+
+ exit;
+
+ end;
+
+ polyline :
+ begin
+ dash_rest:=m_dashes[m_curr_dash ] - m_curr_dash_start;
+
+ if m_curr_dash and 1 <> 0 then
+ cmd:=path_cmd_move_to
+ else
+ cmd:=path_cmd_line_to;
+
+ if m_curr_rest > dash_rest then
+ begin
+ m_curr_rest:=m_curr_rest - dash_rest;
+
+ inc(m_curr_dash );
+
+ if m_curr_dash >= m_num_dashes then
+ m_curr_dash:=0;
+
+ m_curr_dash_start:=0.0;
+
+ x^:=m_v2.x - (m_v2.x - m_v1.x ) * m_curr_rest / m_v1.dist;
+ y^:=m_v2.y - (m_v2.y - m_v1.y ) * m_curr_rest / m_v1.dist;
+
+ end
+ else
+ begin
+ m_curr_dash_start:=m_curr_dash_start + m_curr_rest;
+
+ x^:=m_v2.x;
+ y^:=m_v2.y;
+
+ inc(m_src_vertex );
+
+ m_v1:=m_v2;
+
+ m_curr_rest:=m_v1.dist;
+
+ if m_closed <> 0 then
+ if m_src_vertex > m_src_vertices.size then
+ m_status:=stop
+ else
+ if m_src_vertex >= m_src_vertices.size then
+ m_v2:=m_src_vertices.array_operator(0 )
+ else
+ m_v2:=m_src_vertices.array_operator(m_src_vertex )
+ else
+ if m_src_vertex >= m_src_vertices.size then
+ m_status:=stop
+ else
+ m_v2:=m_src_vertices.array_operator(m_src_vertex );
+
+ end;
+
+ result:=cmd;
+
+ exit;
+
+ end;
+
+ stop :
+ cmd:=path_cmd_stop;
+
+ end;
+
+ result:=path_cmd_stop;
+
+end;
+
+{ CALC_DASH_START }
+procedure vcgen_dash.calc_dash_start;
+begin
+ m_curr_dash :=0;
+ m_curr_dash_start:=0.0;
+
+ while ds > 0.0 do
+ if ds > m_dashes[m_curr_dash ] then
+ begin
+ ds:=ds - m_dashes[m_curr_dash ];
+
+ inc(m_curr_dash );
+
+ m_curr_dash_start:=0.0;
+
+ if m_curr_dash >= m_num_dashes then
+ m_curr_dash:=0;
+
+ end
+ else
+ begin
+ m_curr_dash_start:=ds;
+
+ ds:=0.0;
+
+ end;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_vcgen_markers_term.pas b/src/corelib/render/software/agg_vcgen_markers_term.pas
new file mode 100644
index 00000000..5d9313e6
--- /dev/null
+++ b/src/corelib/render/software/agg_vcgen_markers_term.pas
@@ -0,0 +1,217 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// Terminal markers generator (arrowhead/arrowtail)
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 24.02.2006-Milano: Unit port establishment
+//
+{ agg_vcgen_markers_term.pas }
+unit
+ agg_vcgen_markers_term ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_array ,
+ agg_vertex_source ,
+ agg_vertex_sequence ;
+
+{ TYPES DEFINITION }
+type
+ coord_type_ptr = ^coord_type;
+ coord_type = object
+ x ,y : double;
+
+ constructor Construct; overload;
+ constructor Construct(x_ ,y_ : double ); overload;
+
+ end;
+
+ vcgen_markers_term = object(vertex_source )
+ m_markers : pod_deque;
+ m_curr_id ,
+ m_curr_idx : unsigned;
+
+ constructor Construct;
+ destructor Destruct; virtual;
+
+ // Vertex Generator Interface
+ procedure remove_all; virtual;
+ procedure add_vertex(x ,y : double; cmd : unsigned ); virtual;
+
+ // Vertex Source Interface
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor coord_type.Construct;
+begin
+ x:=0;
+ y:=0;
+
+end;
+
+{ CONSTRUCT }
+constructor coord_type.Construct(x_ ,y_ : double );
+begin
+ x:=x_;
+ y:=y_;
+
+end;
+
+{ CONSTRUCT }
+constructor vcgen_markers_term.Construct;
+begin
+ m_markers.Construct(sizeof(coord_type ) ,6 );
+
+ m_curr_id :=0;
+ m_curr_idx:=0;
+
+end;
+
+{ DESTRUCT }
+destructor vcgen_markers_term.Destruct;
+begin
+ m_markers.Destruct;
+
+end;
+
+{ REMOVE_ALL }
+procedure vcgen_markers_term.remove_all;
+begin
+ m_markers.remove_all;
+
+end;
+
+{ ADD_VERTEX }
+procedure vcgen_markers_term.add_vertex;
+var
+ ct : coord_type;
+
+begin
+ if is_move_to(cmd ) then
+ if m_markers.size and 1 <> 0 then
+ begin
+ // Initial state, the first coordinate was added.
+ // If two of more calls of start_vertex() occures
+ // we just modify the last one.
+ ct.Construct (x ,y );
+ m_markers.modify_last(@ct );
+
+ end
+ else
+ begin
+ ct.Construct (x ,y );
+ m_markers.add(@ct );
+
+ end
+ else
+ if is_vertex(cmd ) then
+ if m_markers.size and 1 <> 0 then
+ begin
+ // Initial state, the first coordinate was added.
+ // Add three more points, 0,1,1,0
+ ct.Construct (x ,y );
+ m_markers.add(@ct );
+ m_markers.add(m_markers.array_operator(m_markers.size - 1 ) );
+ m_markers.add(m_markers.array_operator(m_markers.size - 3 ) );
+
+ end
+ else
+ if m_markers.size <> 0 then
+ begin
+ // Replace two last points: 0,1,1,0 -> 0,1,2,1
+ ct.Construct(x ,y );
+
+ move(
+ m_markers.array_operator(m_markers.size - 2 )^ ,
+ m_markers.array_operator(m_markers.size - 1 )^ ,
+ sizeof(coord_type ) );
+
+ move(
+ ct ,
+ m_markers.array_operator(m_markers.size - 2 )^ ,
+ sizeof(coord_type ) );
+
+ end;
+
+end;
+
+{ REWIND }
+procedure vcgen_markers_term.rewind;
+begin
+ m_curr_id :=path_id * 2;
+ m_curr_idx:=m_curr_id;
+
+end;
+
+{ VERTEX }
+function vcgen_markers_term.vertex;
+var
+ c : coord_type_ptr;
+
+begin
+ if (m_curr_id > 2 ) or
+ (m_curr_idx >= m_markers.size ) then
+ begin
+ result:=path_cmd_stop;
+
+ exit;
+
+ end;
+
+ c:=m_markers.array_operator(m_curr_idx );
+
+ x^:=c.x;
+ y^:=c.y;
+
+ if m_curr_idx and 1 <> 0 then
+ begin
+ inc(m_curr_idx ,3 );
+
+ result:=path_cmd_line_to;
+
+ exit;
+
+ end;
+
+ inc(m_curr_idx );
+
+ result:=path_cmd_move_to;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_vcgen_smooth_poly1.pas b/src/corelib/render/software/agg_vcgen_smooth_poly1.pas
new file mode 100644
index 00000000..f3d34f41
--- /dev/null
+++ b/src/corelib/render/software/agg_vcgen_smooth_poly1.pas
@@ -0,0 +1,431 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// Smooth polygon generator
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 24.02.2006-Milano: Unit port establishment
+//
+{ agg_vcgen_smooth_poly1.pas }
+unit
+ agg_vcgen_smooth_poly1 ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_vertex_source ,
+ agg_vertex_sequence ;
+
+{ TYPES DEFINITION }
+type
+ status_e = (
+ initial ,
+ ready ,
+ polygon ,
+ ctrl_b ,
+ ctrl_e ,
+ ctrl1 ,
+ ctrl2 ,
+ end_poly ,
+ stop );
+
+ vcgen_smooth_poly1_ptr = ^vcgen_smooth_poly1;
+ vcgen_smooth_poly1 = object(vertex_source )
+ m_src_vertices : vertex_sequence;
+ m_smooth_value : double;
+
+ m_closed : unsigned;
+ m_status : status_e;
+
+ m_src_vertex : unsigned;
+
+ m_ctrl1_x ,
+ m_ctrl1_y ,
+ m_ctrl2_x ,
+ m_ctrl2_y : double;
+
+ constructor Construct;
+ destructor Destruct; virtual;
+
+ procedure smooth_value_(v : double );
+ function _smooth_value : double;
+
+ // Vertex Generator Interface
+ procedure remove_all; virtual;
+ procedure add_vertex(x ,y : double; cmd : unsigned ); virtual;
+
+ // Vertex Source Interface
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ // Private
+ procedure calculate(v0 ,v1 ,v2 ,v3 : vertex_dist_ptr );
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor vcgen_smooth_poly1.Construct;
+begin
+ m_src_vertices.Construct(sizeof(vertex_dist ) ,6 );
+
+ m_smooth_value:=0.5;
+
+ m_closed:=0;
+ m_status:=initial;
+
+ m_src_vertex:=0;
+
+end;
+
+{ DESTRUCT }
+destructor vcgen_smooth_poly1.Destruct;
+begin
+ m_src_vertices.Destruct;
+
+end;
+
+{ SMOOTH_VALUE_ }
+procedure vcgen_smooth_poly1.smooth_value_;
+begin
+ m_smooth_value:=v * 0.5;
+
+end;
+
+{ _SMOOTH_VALUE }
+function vcgen_smooth_poly1._smooth_value;
+begin
+ result:=m_smooth_value * 2.0;
+
+end;
+
+{ REMOVE_ALL }
+procedure vcgen_smooth_poly1.remove_all;
+begin
+ m_src_vertices.remove_all;
+
+ m_closed:=0;
+ m_status:=initial;
+
+end;
+
+{ ADD_VERTEX }
+procedure vcgen_smooth_poly1.add_vertex;
+var
+ vd : vertex_dist;
+
+begin
+ m_status:=initial;
+
+ if is_move_to(cmd ) then
+ begin
+ vd.x:=x;
+ vd.y:=y;
+
+ vd.dist:=0;
+
+ m_src_vertices.modify_last(@vd );
+
+ end
+ else
+ if is_vertex(cmd ) then
+ begin
+ vd.x:=x;
+ vd.y:=y;
+
+ vd.dist:=0;
+
+ m_src_vertices.add(@vd );
+
+ end
+ else
+ m_closed:=get_close_flag(cmd );
+
+end;
+
+{ REWIND }
+procedure vcgen_smooth_poly1.rewind;
+begin
+ if m_status = initial then
+ m_src_vertices.close(boolean(m_closed <> 0 ) );
+
+ m_status :=ready;
+ m_src_vertex:=0;
+
+end;
+
+{ VERTEX }
+function vcgen_smooth_poly1.vertex;
+var
+ cmd : unsigned;
+
+label
+ _next ,_ready ,_polygon ;
+
+begin
+ cmd:=path_cmd_line_to;
+
+_next:
+ while not is_stop(cmd ) do
+ case m_status of
+ initial :
+ begin
+ rewind(0 );
+
+ goto _ready;
+
+ end;
+
+ ready :
+ _ready:
+ begin
+ if m_src_vertices.size < 2 then
+ begin
+ cmd:=path_cmd_stop;
+
+ goto _next;
+
+ end;
+
+ if m_src_vertices.size = 2 then
+ begin
+ x^:=vertex_dist_ptr(m_src_vertices.array_operator(m_src_vertex ) ).x;
+ y^:=vertex_dist_ptr(m_src_vertices.array_operator(m_src_vertex ) ).y;
+
+ inc(m_src_vertex );
+
+ if m_src_vertex = 1 then
+ begin
+ result:=path_cmd_move_to;
+
+ exit;
+
+ end;
+
+ if m_src_vertex = 2 then
+ begin
+ result:=path_cmd_line_to;
+
+ exit;
+
+ end;
+
+ cmd:=path_cmd_stop;
+
+ goto _next;
+
+ end;
+
+ cmd:=path_cmd_move_to;
+
+ m_status:=polygon;
+
+ m_src_vertex:=0;
+
+ goto _polygon;
+
+ end;
+
+ polygon :
+ _polygon:
+ begin
+ if m_closed <> 0 then
+ if m_src_vertex >= m_src_vertices.size then
+ begin
+ x^:=vertex_dist_ptr(m_src_vertices.array_operator(0 ) ).x;
+ y^:=vertex_dist_ptr(m_src_vertices.array_operator(0 ) ).y;
+
+ m_status:=end_poly;
+ result :=path_cmd_curve4;
+
+ exit;
+
+ end
+ else
+ else
+ if m_src_vertex >= m_src_vertices.size - 1 then
+ begin
+ x^:=vertex_dist_ptr(m_src_vertices.array_operator(m_src_vertices.size - 1 ) ).x;
+ y^:=vertex_dist_ptr(m_src_vertices.array_operator(m_src_vertices.size - 1 ) ).y;
+
+ m_status:=end_poly;
+ result :=path_cmd_curve3;
+
+ exit;
+
+ end;
+
+ calculate(
+ m_src_vertices.prev(m_src_vertex ) ,
+ m_src_vertices.curr(m_src_vertex ) ,
+ m_src_vertices.next(m_src_vertex ) ,
+ m_src_vertices.next(m_src_vertex + 1 ) );
+
+ x^:=vertex_dist_ptr(m_src_vertices.array_operator(m_src_vertex ) ).x;
+ y^:=vertex_dist_ptr(m_src_vertices.array_operator(m_src_vertex ) ).y;
+
+ inc(m_src_vertex );
+
+ if m_closed <> 0 then
+ begin
+ m_status:=ctrl1;
+
+ if m_src_vertex = 1 then
+ result:=path_cmd_move_to
+ else
+ result:=path_cmd_curve4;
+
+ exit;
+
+ end
+ else
+ begin
+ if m_src_vertex = 1 then
+ begin
+ m_status:=ctrl_b;
+ result :=path_cmd_move_to;
+
+ exit;
+
+ end;
+
+ if m_src_vertex >= m_src_vertices.size - 1 then
+ begin
+ m_status:=ctrl_e;
+ result :=path_cmd_curve3;
+
+ exit;
+
+ end;
+
+ m_status:=ctrl1;
+ result :=path_cmd_curve4;
+
+ exit;
+
+ end;
+
+ end;
+
+ ctrl_b :
+ begin
+ x^:=m_ctrl2_x;
+ y^:=m_ctrl2_y;
+
+ m_status:=polygon;
+ result :=path_cmd_curve3;
+
+ exit;
+
+ end;
+
+ ctrl_e :
+ begin
+ x^:=m_ctrl1_x;
+ y^:=m_ctrl1_y;
+
+ m_status:=polygon;
+ result :=path_cmd_curve3;
+
+ exit;
+
+ end;
+
+ ctrl1 :
+ begin
+ x^:=m_ctrl1_x;
+ y^:=m_ctrl1_y;
+
+ m_status:=ctrl2;
+ result :=path_cmd_curve4;
+
+ exit;
+
+ end;
+
+ ctrl2 :
+ begin
+ x^:=m_ctrl2_x;
+ y^:=m_ctrl2_y;
+
+ m_status:=polygon;
+ result :=path_cmd_curve4;
+
+ exit;
+
+ end;
+
+ end_poly :
+ begin
+ m_status:=stop;
+ result :=path_cmd_end_poly or m_closed;
+
+ exit;
+
+ end;
+
+ stop :
+ begin
+ result:=path_cmd_stop;
+
+ exit;
+
+ end;
+
+ end;
+
+ result:=cmd;
+
+end;
+
+{ CALCULATE }
+procedure vcgen_smooth_poly1.calculate;
+var
+ k1 ,k2 ,xm1 ,ym1 ,xm2 ,ym2 : double;
+
+begin
+ k1:=v0.dist / (v0.dist + v1.dist );
+ k2:=v1.dist / (v1.dist + v2.dist );
+
+ xm1:=v0.x + (v2.x - v0.x ) * k1;
+ ym1:=v0.y + (v2.y - v0.y ) * k1;
+ xm2:=v1.x + (v3.x - v1.x ) * k2;
+ ym2:=v1.y + (v3.y - v1.y ) * k2;
+
+ m_ctrl1_x:=v1.x + m_smooth_value * (v2.x - xm1 );
+ m_ctrl1_y:=v1.y + m_smooth_value * (v2.y - ym1 );
+ m_ctrl2_x:=v2.x + m_smooth_value * (v1.x - xm2 );
+ m_ctrl2_y:=v2.y + m_smooth_value * (v1.y - ym2 );
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_vcgen_stroke.pas b/src/corelib/render/software/agg_vcgen_stroke.pas
new file mode 100644
index 00000000..b6f7dbce
--- /dev/null
+++ b/src/corelib/render/software/agg_vcgen_stroke.pas
@@ -0,0 +1,1008 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// Stroke generator
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 18.10.2007-Milano: vcgen_stroke_math
+// 21.12.2005-Milano: Unit port establishment
+//
+{ agg_vcgen_stroke.pas }
+unit
+ agg_vcgen_stroke ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_array ,
+ agg_vertex_source ,
+ agg_vertex_sequence ,
+ agg_math_stroke ,
+ agg_shorten_path ;
+
+{ TYPES DEFINITION }
+type
+ status_e = (
+ initial ,
+ ready ,
+ cap1 ,
+ cap2 ,
+ outline1 ,
+ close_first ,
+ outline2 ,
+ out_vertices ,
+ end_poly1 ,
+ end_poly2 ,
+ stop );
+
+ vcgen_stroke_ptr = ^vcgen_stroke;
+ vcgen_stroke = object(vertex_source )
+ m_src_vertices : vertex_sequence;
+ m_out_vertices : pod_deque;
+ m_width ,
+ m_miter_limit ,
+ m_inner_miter_limit ,
+ m_approx_scale ,
+ m_shorten : double;
+ m_line_cap ,
+ m_line_join ,
+ m_inner_join ,
+ m_closed : unsigned;
+ m_status ,
+ m_prev_status : status_e;
+ m_src_vertex ,
+ m_out_vertex : unsigned;
+
+ constructor Construct;
+ destructor Destruct; virtual;
+
+ procedure line_cap_ (lc : unsigned );
+ procedure line_join_ (lj : unsigned );
+ procedure inner_join_(ij : unsigned );
+
+ function _line_cap : unsigned;
+ function _line_join : unsigned;
+ function _inner_join : unsigned;
+
+ procedure width_ (w : double );
+ procedure miter_limit_ (ml : double );
+ procedure miter_limit_theta_ (t : double );
+ procedure inner_miter_limit_ (ml : double );
+ procedure approximation_scale_(as_ : double );
+
+ function _width : double;
+ function _miter_limit : double;
+ function _inner_miter_limit : double;
+ function _approximation_scale : double;
+
+ procedure shorten_(s : double );
+ function _shorten : double;
+
+ // Vertex Generator Interface
+ procedure remove_all; virtual;
+ procedure add_vertex(x ,y : double; cmd : unsigned ); virtual;
+
+ // Vertex Source Interface
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ end;
+
+ vcgen_stroke_math_ptr = ^vcgen_stroke_math;
+ vcgen_stroke_math = object(vertex_source )
+ m_stroker : math_stroke;
+ m_src_vertices : vertex_sequence;
+ m_out_vertices : pod_deque;
+
+ m_shorten : double;
+ m_closed : unsigned;
+
+ m_status ,
+ m_prev_status : status_e;
+
+ m_src_vertex ,
+ m_out_vertex : unsigned;
+
+ constructor Construct;
+ destructor Destruct; virtual;
+
+ procedure line_cap_ (lc : unsigned );
+ procedure line_join_ (lj : unsigned );
+ procedure inner_join_(ij : unsigned );
+
+ function _line_cap : unsigned;
+ function _line_join : unsigned;
+ function _inner_join : unsigned;
+
+ procedure width_ (w : double );
+ procedure miter_limit_ (ml : double );
+ procedure miter_limit_theta_ (t : double );
+ procedure inner_miter_limit_ (ml : double );
+ procedure approximation_scale_(as_ : double );
+
+ function _width : double;
+ function _miter_limit : double;
+ function _inner_miter_limit : double;
+ function _approximation_scale : double;
+
+ procedure shorten_(s : double );
+ function _shorten : double;
+
+ // Vertex Generator Interface
+ procedure remove_all; virtual;
+ procedure add_vertex(x ,y : double; cmd : unsigned ); virtual;
+
+ // Vertex Source Interface
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor vcgen_stroke.Construct;
+begin
+ m_src_vertices.Construct(sizeof(vertex_dist ) );
+ m_out_vertices.Construct(sizeof(point_type ) );
+
+ m_width :=0.5;
+ m_miter_limit :=4.0;
+ m_inner_miter_limit:=1.01;
+ m_approx_scale :=1.0;
+ m_shorten :=0.0;
+ m_line_cap :=butt_cap;
+ m_line_join :=miter_join;
+ m_inner_join :=inner_miter;
+ m_closed :=0;
+ m_status :=initial;
+ m_src_vertex :=0;
+ m_out_vertex :=0;
+
+end;
+
+{ DESTRUCT }
+destructor vcgen_stroke.Destruct;
+begin
+ m_src_vertices.Destruct;
+ m_out_vertices.Destruct;
+
+end;
+
+{ LINE_CAP_ }
+procedure vcgen_stroke.line_cap_;
+begin
+ m_line_cap:=lc;
+
+end;
+
+{ LINE_JOIN_ }
+procedure vcgen_stroke.line_join_;
+begin
+ m_line_join:=lj;
+
+end;
+
+{ INNER_JOIN_ }
+procedure vcgen_stroke.inner_join_;
+begin
+ m_inner_join:=ij;
+
+end;
+
+{ _LINE_CAP }
+function vcgen_stroke._line_cap;
+begin
+ result:=m_line_cap;
+
+end;
+
+{ _LINE_JOIN }
+function vcgen_stroke._line_join;
+begin
+ result:=m_line_join;
+
+end;
+
+{ _INNER_JOIN }
+function vcgen_stroke._inner_join;
+begin
+ result:=m_inner_join;
+
+end;
+
+{ WIDHT_ }
+procedure vcgen_stroke.width_;
+begin
+ m_width:=w * 0.5;
+
+end;
+
+{ MITER_LIMIT_ }
+procedure vcgen_stroke.miter_limit_;
+begin
+ m_miter_limit:=ml;
+
+end;
+
+{ MITER_LIMIT_THETA_ }
+procedure vcgen_stroke.miter_limit_theta_;
+begin
+ m_miter_limit:=1.0 / Sin(t * 0.5 );
+
+end;
+
+{ INNER_MITER_LIMIT_ }
+procedure vcgen_stroke.inner_miter_limit_;
+begin
+ m_inner_miter_limit:=ml;
+
+end;
+
+{ APPROXIMATION_SCALE_ }
+procedure vcgen_stroke.approximation_scale_;
+begin
+ m_approx_scale:=as_;
+
+end;
+
+{ _WIDTH }
+function vcgen_stroke._width;
+begin
+ result:=m_width * 2.0;
+
+end;
+
+{ _MITER_LIMIT }
+function vcgen_stroke._miter_limit;
+begin
+ result:=m_miter_limit;
+
+end;
+
+{ _INNER_MITER_LIMIT }
+function vcgen_stroke._inner_miter_limit;
+begin
+ result:=m_inner_miter_limit;
+
+end;
+
+{ _APPROXIMATION_SCALE }
+function vcgen_stroke._approximation_scale;
+begin
+ result:=m_approx_scale;
+
+end;
+
+{ SHORTEN_ }
+procedure vcgen_stroke.shorten_;
+begin
+ m_shorten:=s;
+
+end;
+
+{ _SHORTEN }
+function vcgen_stroke._shorten;
+begin
+ result:=m_shorten;
+
+end;
+
+{ REMOVE_ALL }
+procedure vcgen_stroke.remove_all;
+begin
+ m_src_vertices.remove_all;
+
+ m_closed:=0;
+ m_status:=initial;
+
+end;
+
+{ ADD_VERTEX }
+procedure vcgen_stroke.add_vertex;
+var
+ vd : vertex_dist;
+
+begin
+ m_status:=initial;
+
+ vd.x:=x;
+ vd.y:=y;
+
+ vd.dist:=0;
+
+ if is_move_to(cmd ) then
+ m_src_vertices.modify_last(@vd )
+ else
+ if is_vertex(cmd ) then
+ m_src_vertices.add(@vd )
+ else
+ m_closed:=get_close_flag(cmd );
+
+end;
+
+{ calc_butt_cap }
+procedure calc_butt_cap(cap : double_00_ptr; v0 ,v1 : vertex_dist_ptr; len ,width : double );
+var
+ dx ,dy : double;
+
+begin
+ dx:=(v1.y - v0.y ) * width / len;
+ dy:=(v1.x - v0.x ) * width / len;
+
+ cap^[0 ]:=v0.x - dx;
+ cap^[1 ]:=v0.y + dy;
+ cap^[2 ]:=v0.x + dx;
+ cap^[3 ]:=v0.y - dy;
+
+end;
+
+{ REWIND }
+procedure vcgen_stroke.rewind;
+begin
+ if m_status = initial then
+ begin
+ m_src_vertices.close(boolean(m_closed <> 0 ) );
+
+ shorten_path(@m_src_vertices ,m_shorten ,m_closed );
+
+ if m_src_vertices.size < 3 then
+ m_closed:=0;
+
+ end;
+
+ m_status:=ready;
+
+ m_src_vertex:=0;
+ m_out_vertex:=0;
+
+end;
+
+{ VERTEX }
+function vcgen_stroke.vertex;
+var
+ c : point_type_ptr;
+
+ cmd : unsigned;
+
+label
+ _rdy ,_out2 ,_end ;
+
+begin
+ cmd:=path_cmd_line_to;
+
+ while not is_stop(cmd ) do
+ begin
+ case m_status of
+ initial :
+ begin
+ rewind(0 );
+
+ goto _rdy;
+
+ end;
+
+ ready :
+ begin
+ _rdy:
+ if m_src_vertices.size < 2 + unsigned(m_closed <> 0 ) then
+ begin
+ cmd:=path_cmd_stop;
+
+ goto _end;
+
+ end;
+
+ if (m_closed <> 0 ) then
+ m_status:=outline1
+ else
+ m_status:=cap1;
+
+ cmd:=path_cmd_move_to;
+
+ m_src_vertex:=0;
+ m_out_vertex:=0;
+
+ end;
+
+ cap1 :
+ begin
+ stroke_calc_cap(
+ @m_out_vertices ,
+ m_src_vertices.array_operator(0 ) ,
+ m_src_vertices.array_operator(1 ) ,
+ vertex_dist_ptr(m_src_vertices.array_operator(0 ) )^.dist ,
+ m_line_cap ,
+ m_width ,
+ m_approx_scale );
+
+ m_src_vertex :=1;
+ m_prev_status:=outline1;
+ m_status :=out_vertices;
+ m_out_vertex :=0;
+
+ end;
+
+ cap2 :
+ begin
+ stroke_calc_cap(
+ @m_out_vertices ,
+ m_src_vertices.array_operator(m_src_vertices.size - 1 ) ,
+ m_src_vertices.array_operator(m_src_vertices.size - 2 ) ,
+ vertex_dist_ptr(m_src_vertices.array_operator(m_src_vertices.size - 2 ) )^.dist ,
+ m_line_cap ,
+ m_width ,
+ m_approx_scale );
+
+ m_prev_status:=outline2;
+ m_status :=out_vertices;
+ m_out_vertex :=0;
+
+ end;
+
+ outline1 :
+ begin
+ if m_closed <> 0 then
+ if m_src_vertex >= m_src_vertices.size then
+ begin
+ m_prev_status:=close_first;
+ m_status :=end_poly1;
+
+ goto _end;
+
+ end
+ else
+ else
+ if m_src_vertex >= m_src_vertices.size - 1 then
+ begin
+ m_status:=cap2;
+
+ goto _end;
+
+ end;
+
+ stroke_calc_join(
+ @m_out_vertices ,
+ m_src_vertices.prev(m_src_vertex ) ,
+ m_src_vertices.curr(m_src_vertex ) ,
+ m_src_vertices.next(m_src_vertex ) ,
+ vertex_dist_ptr(m_src_vertices.prev(m_src_vertex ) )^.dist ,
+ vertex_dist_ptr(m_src_vertices.curr(m_src_vertex ) )^.dist ,
+ m_width ,
+ m_line_join ,
+ m_inner_join ,
+ m_miter_limit ,
+ m_inner_miter_limit ,
+ m_approx_scale );
+
+ inc(m_src_vertex );
+
+ m_prev_status:=m_status;
+ m_status :=out_vertices;
+ m_out_vertex :=0;
+
+ end;
+
+ close_first :
+ begin
+ m_status:=outline2;
+
+ cmd:=path_cmd_move_to;
+
+ goto _out2;
+
+ end;
+
+ outline2 :
+ begin
+ _out2:
+ if m_src_vertex <= unsigned(m_closed = 0 ) then
+ begin
+ m_status :=end_poly2;
+ m_prev_status:=stop;
+
+ goto _end;
+
+ end;
+
+ dec(m_src_vertex );
+
+ stroke_calc_join(
+ @m_out_vertices ,
+ m_src_vertices.next(m_src_vertex ) ,
+ m_src_vertices.curr(m_src_vertex ) ,
+ m_src_vertices.prev(m_src_vertex ) ,
+ vertex_dist_ptr(m_src_vertices.curr(m_src_vertex ) )^.dist ,
+ vertex_dist_ptr(m_src_vertices.prev(m_src_vertex ) )^.dist ,
+ m_width ,
+ m_line_join ,
+ m_inner_join ,
+ m_miter_limit ,
+ m_inner_miter_limit ,
+ m_approx_scale );
+
+ m_prev_status:=m_status;
+ m_status :=out_vertices;
+ m_out_vertex :=0;
+
+ end;
+
+ out_vertices :
+ if m_out_vertex >= m_out_vertices.size then
+ m_status:=m_prev_status
+
+ else
+ begin
+ c:=m_out_vertices.array_operator(m_out_vertex );
+
+ inc(m_out_vertex );
+
+ x^:=c.x;
+ y^:=c.y;
+
+ result:=cmd;
+
+ exit;
+
+ end;
+
+ end_poly1 :
+ begin
+ m_status:=m_prev_status;
+
+ result:=path_cmd_end_poly or path_flags_close or path_flags_ccw;
+
+ exit;
+
+ end;
+
+ end_poly2 :
+ begin
+ m_status:=m_prev_status;
+
+ result:=path_cmd_end_poly or path_flags_close or path_flags_cw;
+
+ exit;
+
+ end;
+
+ stop :
+ cmd:=path_cmd_stop;
+
+ end;
+
+ _end:
+ end;
+
+ result:=cmd;
+
+end;
+
+{ CONSTRUCT }
+constructor vcgen_stroke_math.Construct;
+begin
+ m_stroker.Construct;
+ m_src_vertices.Construct(sizeof(vertex_dist ) );
+ m_out_vertices.Construct(sizeof(point_type ) );
+
+ m_shorten:=0.0;
+ m_closed :=0;
+ m_status :=initial;
+
+ m_src_vertex:=0;
+ m_out_vertex:=0;
+
+end;
+
+{ DESTRUCT }
+destructor vcgen_stroke_math.Destruct;
+begin
+ m_src_vertices.Destruct;
+ m_out_vertices.Destruct;
+
+end;
+
+{ LINE_CAP_ }
+procedure vcgen_stroke_math.line_cap_(lc : unsigned );
+begin
+ m_stroker.line_cap_(lc );
+
+end;
+
+{ LINE_JOIN_ }
+procedure vcgen_stroke_math.line_join_(lj : unsigned );
+begin
+ m_stroker.line_join_(lj );
+
+end;
+
+{ INNER_JOIN_ }
+procedure vcgen_stroke_math.inner_join_(ij : unsigned );
+begin
+ m_stroker.inner_join_(ij );
+
+end;
+
+{ _LINE_CAP }
+function vcgen_stroke_math._line_cap : unsigned;
+begin
+ result:=m_stroker._line_cap;
+
+end;
+
+{ _LINE_JOIN }
+function vcgen_stroke_math._line_join : unsigned;
+begin
+ result:=m_stroker._line_join;
+
+end;
+
+{ _INNER_JOIN }
+function vcgen_stroke_math._inner_join : unsigned;
+begin
+ result:=m_stroker._inner_join;
+
+end;
+
+{ WIDTH_ }
+procedure vcgen_stroke_math.width_(w : double );
+begin
+ m_stroker.width_(w );
+
+end;
+
+{ MITER_LIMIT_ }
+procedure vcgen_stroke_math.miter_limit_(ml : double );
+begin
+ m_stroker.miter_limit_(ml );
+
+end;
+
+{ MITER_LIMIT_THETA_ }
+procedure vcgen_stroke_math.miter_limit_theta_(t : double );
+begin
+ m_stroker.miter_limit_theta_(t );
+
+end;
+
+{ INNER_MITER_LIMIT_ }
+procedure vcgen_stroke_math.inner_miter_limit_(ml : double );
+begin
+ m_stroker.inner_miter_limit_(ml );
+
+end;
+
+{ APPROXIMATION_SCALE_ }
+procedure vcgen_stroke_math.approximation_scale_(as_ : double );
+begin
+ m_stroker.approximation_scale_(as_ );
+
+end;
+
+{ _WIDTH }
+function vcgen_stroke_math._width : double;
+begin
+ result:=m_stroker._width;
+
+end;
+
+{ _MITER_LIMIT }
+function vcgen_stroke_math._miter_limit : double;
+begin
+ result:=m_stroker._miter_limit;
+
+end;
+
+{ _INNER_MITER_LIMIT }
+function vcgen_stroke_math._inner_miter_limit : double;
+begin
+ result:=m_stroker._inner_miter_limit;
+
+end;
+
+{ _APPROXIMATION_SCALE }
+function vcgen_stroke_math._approximation_scale : double;
+begin
+ result:=m_stroker._approximation_scale;
+
+end;
+
+{ SHORTEN_ }
+procedure vcgen_stroke_math.shorten_(s : double );
+begin
+ m_shorten:=s;
+
+end;
+
+{ _SHORTEN }
+function vcgen_stroke_math._shorten : double;
+begin
+ result:=m_shorten;
+
+end;
+
+{ REMOVE_ALL }
+procedure vcgen_stroke_math.remove_all;
+begin
+ m_src_vertices.remove_all;
+
+ m_closed:=0;
+ m_status:=initial;
+
+end;
+
+{ ADD_VERTEX }
+procedure vcgen_stroke_math.add_vertex(x ,y : double; cmd : unsigned );
+var
+ vd : vertex_dist;
+
+begin
+ m_status:=initial;
+
+ vd.x:=x;
+ vd.y:=y;
+
+ vd.dist:=0;
+
+ if is_move_to(cmd ) then
+ m_src_vertices.modify_last(@vd )
+ else
+ if is_vertex(cmd ) then
+ m_src_vertices.add(@vd )
+ else
+ m_closed:=get_close_flag(cmd );
+
+end;
+
+{ REWIND }
+procedure vcgen_stroke_math.rewind(path_id : unsigned );
+begin
+ if m_status = initial then
+ begin
+ m_src_vertices.close(boolean(m_closed <> 0 ) );
+
+ shorten_path(@m_src_vertices ,m_shorten ,m_closed );
+
+ if m_src_vertices.size < 3 then
+ m_closed:=0;
+
+ end;
+
+ m_status:=ready;
+
+ m_src_vertex:=0;
+ m_out_vertex:=0;
+
+end;
+
+{ VERTEX }
+function vcgen_stroke_math.vertex(x ,y : double_ptr ) : unsigned;
+var
+ cmd : unsigned;
+
+ c : point_type_ptr;
+
+label
+ _rdy ,_out2 ,_end ;
+
+begin
+ cmd:=path_cmd_line_to;
+
+ while not is_stop(cmd ) do
+ begin
+ case m_status of
+ initial :
+ begin
+ rewind(0 );
+
+ goto _rdy;
+
+ end;
+
+ ready :
+ begin
+ _rdy:
+ if m_src_vertices.size < 2 + unsigned(m_closed <> 0 ) then
+ begin
+ cmd:=path_cmd_stop;
+
+ goto _end;
+
+ end;
+
+ if (m_closed <> 0 ) then
+ m_status:=outline1
+ else
+ m_status:=cap1;
+
+ cmd:=path_cmd_move_to;
+
+ m_src_vertex:=0;
+ m_out_vertex:=0;
+
+ end;
+
+ cap1 :
+ begin
+ m_stroker.calc_cap(
+ @m_out_vertices ,
+ m_src_vertices.array_operator(0 ) ,
+ m_src_vertices.array_operator(1 ) ,
+ vertex_dist_ptr(m_src_vertices.array_operator(0 ) )^.dist );
+
+ m_src_vertex :=1;
+ m_prev_status:=outline1;
+ m_status :=out_vertices;
+ m_out_vertex :=0;
+
+ end;
+
+ cap2 :
+ begin
+ m_stroker.calc_cap(
+ @m_out_vertices ,
+ m_src_vertices.array_operator(m_src_vertices.size - 1 ) ,
+ m_src_vertices.array_operator(m_src_vertices.size - 2 ) ,
+ vertex_dist_ptr(m_src_vertices.array_operator(m_src_vertices.size - 2 ) )^.dist );
+
+ m_prev_status:=outline2;
+ m_status :=out_vertices;
+ m_out_vertex :=0;
+
+ end;
+
+ outline1 :
+ begin
+ if m_closed <> 0 then
+ if m_src_vertex >= m_src_vertices.size then
+ begin
+ m_prev_status:=close_first;
+ m_status :=end_poly1;
+
+ goto _end;
+
+ end
+ else
+ else
+ if m_src_vertex >= m_src_vertices.size - 1 then
+ begin
+ m_status:=cap2;
+
+ goto _end;
+
+ end;
+
+ m_stroker.calc_join(
+ @m_out_vertices ,
+ m_src_vertices.prev(m_src_vertex ) ,
+ m_src_vertices.curr(m_src_vertex ) ,
+ m_src_vertices.next(m_src_vertex ) ,
+ vertex_dist_ptr(m_src_vertices.prev(m_src_vertex ) )^.dist ,
+ vertex_dist_ptr(m_src_vertices.curr(m_src_vertex ) )^.dist );
+
+ inc(m_src_vertex );
+
+ m_prev_status:=m_status;
+ m_status :=out_vertices;
+ m_out_vertex :=0;
+
+ end;
+
+ close_first :
+ begin
+ m_status:=outline2;
+
+ cmd:=path_cmd_move_to;
+
+ goto _out2;
+
+ end;
+
+ outline2 :
+ begin
+ _out2:
+ if m_src_vertex <= unsigned(m_closed = 0 ) then
+ begin
+ m_status :=end_poly2;
+ m_prev_status:=stop;
+
+ goto _end;
+
+ end;
+
+ dec(m_src_vertex );
+
+ m_stroker.calc_join(
+ @m_out_vertices ,
+ m_src_vertices.next(m_src_vertex ) ,
+ m_src_vertices.curr(m_src_vertex ) ,
+ m_src_vertices.prev(m_src_vertex ) ,
+ vertex_dist_ptr(m_src_vertices.curr(m_src_vertex ) )^.dist ,
+ vertex_dist_ptr(m_src_vertices.prev(m_src_vertex ) )^.dist );
+
+ m_prev_status:=m_status;
+ m_status :=out_vertices;
+ m_out_vertex :=0;
+
+ end;
+
+ out_vertices :
+ if m_out_vertex >= m_out_vertices.size then
+ m_status:=m_prev_status
+
+ else
+ begin
+ c:=m_out_vertices.array_operator(m_out_vertex );
+
+ inc(m_out_vertex );
+
+ x^:=c.x;
+ y^:=c.y;
+
+ result:=cmd;
+
+ exit;
+
+ end;
+
+ end_poly1 :
+ begin
+ m_status:=m_prev_status;
+
+ result:=path_cmd_end_poly or path_flags_close or path_flags_ccw;
+
+ exit;
+
+ end;
+
+ end_poly2 :
+ begin
+ m_status:=m_prev_status;
+
+ result:=path_cmd_end_poly or path_flags_close or path_flags_cw;
+
+ exit;
+
+ end;
+
+ stop :
+ cmd:=path_cmd_stop;
+
+ end;
+
+ _end:
+ end;
+
+ result:=cmd;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_vcgen_vertex_sequence.pas b/src/corelib/render/software/agg_vcgen_vertex_sequence.pas
new file mode 100644
index 00000000..2104ff32
--- /dev/null
+++ b/src/corelib/render/software/agg_vcgen_vertex_sequence.pas
@@ -0,0 +1,196 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 26.02.2006-Milano: Unit port establishment
+//
+{ agg_vcgen_vertex_sequence.pas }
+unit
+ agg_vcgen_vertex_sequence ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_vertex_sequence ,
+ agg_shorten_path ,
+ agg_vertex_source ;
+
+{ TYPES DEFINITION }
+type
+ vcgen_vertex_sequence_ptr = ^vcgen_vertex_sequence;
+ vcgen_vertex_sequence = object(vertex_source )
+ m_src_vertices : vertex_sequence;
+ m_flags ,
+ m_cur_vertex : unsigned;
+
+ m_shorten : double;
+ m_ready : boolean;
+
+ constructor Construct;
+ destructor Destruct; virtual;
+
+ procedure shorten_(s : double );
+ function _shorten : double;
+
+ // Vertex Generator Interface
+ procedure remove_all; virtual;
+ procedure add_vertex(x ,y : double; cmd : unsigned ); virtual;
+
+ // Vertex Source Interface
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor vcgen_vertex_sequence.Construct;
+begin
+ m_src_vertices.Construct(sizeof(vertex_dist_cmd ) ,6 );
+
+ m_flags :=0;
+ m_cur_vertex:=0;
+ m_shorten :=0.0;
+ m_ready :=false;
+
+end;
+
+{ DESTRUCT }
+destructor vcgen_vertex_sequence.Destruct;
+begin
+ m_src_vertices.Destruct;
+
+end;
+
+{ SHORTEN_ }
+procedure vcgen_vertex_sequence.shorten_;
+begin
+ m_shorten:=s;
+
+end;
+
+{ _SHORTEN }
+function vcgen_vertex_sequence._shorten;
+begin
+ result:=m_shorten;
+
+end;
+
+{ REMOVE_ALL }
+procedure vcgen_vertex_sequence.remove_all;
+begin
+ m_ready:=false;
+
+ m_src_vertices.remove_all;
+
+ m_cur_vertex:=0;
+ m_flags :=0;
+
+end;
+
+{ ADD_VERTEX }
+procedure vcgen_vertex_sequence.add_vertex;
+var
+ vc : vertex_dist_cmd;
+
+begin
+ m_ready:=false;
+
+ vc.x:=x;
+ vc.y:=y;
+
+ vc.dist:=0;
+ vc.cmd :=cmd;
+
+ if is_move_to(cmd ) then
+ m_src_vertices.modify_last(@vc )
+ else
+ if is_vertex(cmd ) then
+ m_src_vertices.add(@vc )
+ else
+ m_flags:=cmd and path_flags_mask;
+
+end;
+
+{ REWIND }
+procedure vcgen_vertex_sequence.rewind;
+begin
+ if not m_ready then
+ begin
+ m_src_vertices.close(is_closed(m_flags ) );
+
+ shorten_path(@m_src_vertices ,m_shorten ,get_close_flag(m_flags ) );
+
+ end;
+
+ m_ready :=true;
+ m_cur_vertex:=0;
+
+end;
+
+{ VERTEX }
+function vcgen_vertex_sequence.vertex;
+var
+ v : vertex_dist_cmd_ptr;
+
+begin
+ if not m_ready then
+ rewind(0 );
+
+ if m_cur_vertex = m_src_vertices.size then
+ begin
+ inc(m_cur_vertex );
+
+ result:=path_cmd_end_poly or m_flags;
+
+ exit;
+
+ end;
+
+ if m_cur_vertex > m_src_vertices.size then
+ begin
+ result:=path_cmd_stop;
+
+ exit;
+
+ end;
+
+ v:=m_src_vertices.array_operator(m_cur_vertex );
+
+ inc(m_cur_vertex );
+
+ x^:=v.x;
+ y^:=v.y;
+
+ result:=v.cmd;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_vertex_sequence.pas b/src/corelib/render/software/agg_vertex_sequence.pas
new file mode 100644
index 00000000..6814c258
--- /dev/null
+++ b/src/corelib/render/software/agg_vertex_sequence.pas
@@ -0,0 +1,180 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// vertex_sequence container and vertex_dist struct
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 19.12.2005-Milano: Unit port establishment
+//
+{ agg_vertex_sequence.pas }
+unit
+ agg_vertex_sequence ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_array ;
+
+{ TYPES DEFINITION }
+type
+ func_vertex_sequence = function(this ,val : pointer ) : boolean;
+
+//----------------------------------------------------------vertex_sequence
+// Modified agg::pod_deque. The data is interpreted as a sequence of vertices.
+ vertex_sequence_ptr = ^vertex_sequence;
+ vertex_sequence = object(pod_deque )
+ func_operator_vertex_sequence : func_vertex_sequence;
+
+ constructor Construct(entry_sz : unsigned; s_ : unsigned = 6; fovs : func_vertex_sequence = NIL );
+
+ procedure add(val : pointer );
+
+ procedure modify_last(val : pointer);
+
+ procedure close(remove_flag : boolean );
+
+ end;
+
+// Coinciding points maximal distance (Epsilon)
+const
+ vertex_dist_epsilon : double = 1e-14;
+
+//-------------------------------------------------------------vertex_dist
+// Vertex (x, y) with the distance to the next one. The last vertex has
+// distance between the last and the first points if the polygon is closed
+// and 0.0 if it's a polyline.
+type
+ vertex_dist_ptr = ^vertex_dist;
+ vertex_dist = record
+ x ,y ,dist : double;
+
+ end;
+
+ vertex_dist_cmd_ptr = ^vertex_dist_cmd;
+ vertex_dist_cmd = record
+ x ,y ,dist : double;
+
+ cmd : unsigned;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+ function vertex_dist_func_operator(this ,val : vertex_dist_ptr ) : boolean;
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+uses
+ agg_math ;
+
+{ UNIT IMPLEMENTATION }
+{ FUNC_OPERATOR_VERTEX_DIST }
+function vertex_dist_func_operator;
+var
+ ret : boolean;
+
+begin
+ this.dist:=calc_distance(this.x ,this.y ,val.x ,val.y );
+
+ ret:=this.dist > vertex_dist_epsilon;
+
+ if not ret then
+ this.dist:=1 / vertex_dist_epsilon;
+
+ result:=ret;
+
+end;
+
+{ CONSTRUCT }
+constructor vertex_sequence.Construct;
+begin
+ inherited Construct(entry_sz ,s_ );
+
+ if @fovs = NIL then
+ func_operator_vertex_sequence:=@vertex_dist_func_operator
+ else
+ func_operator_vertex_sequence:=fovs;
+
+end;
+
+{ ADD }
+procedure vertex_sequence.add;
+begin
+ if size > 1 then
+ if not func_operator_vertex_sequence(
+ array_operator(size - 2 ) ,
+ array_operator(size - 1 ) ) then
+ remove_last;
+
+ inherited add(val );
+
+end;
+
+{ MODIFY_LAST }
+procedure vertex_sequence.modify_last;
+begin
+ remove_last;
+
+ add(val );
+
+end;
+
+{ CLOSE }
+procedure vertex_sequence.close;
+var
+ t : pointer;
+
+begin
+ while size > 1 do
+ begin
+ if func_operator_vertex_sequence(
+ array_operator(size - 2 ) ,
+ array_operator(size - 1 ) ) then
+ break;
+
+ t:=array_operator(size - 1 );
+
+ remove_last;
+ modify_last(t );
+
+ end;
+
+ if remove_flag then
+ while size > 1 do
+ begin
+ if func_operator_vertex_sequence(
+ array_operator(size - 1 ) ,
+ array_operator(0 ) ) then
+ break;
+
+ remove_last;
+
+ end;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_vertex_source.pas b/src/corelib/render/software/agg_vertex_source.pas
new file mode 100644
index 00000000..19dea500
--- /dev/null
+++ b/src/corelib/render/software/agg_vertex_source.pas
@@ -0,0 +1,111 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// Pascal replacement of the vertex_source templetized concept from C++.
+// This file is originaly not a part of the AGG.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 19.12.2005-Milano: Unit port establishment
+//
+{ agg_vertex_source.pas }
+unit
+ agg_vertex_source ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ;
+
+{ TYPES DEFINITION }
+type
+ vertex_source_ptr = ^vertex_source;
+ vertex_source = object
+ constructor Construct;
+ destructor Destruct; virtual;
+
+ procedure remove_all; virtual;
+ procedure add_vertex(x ,y : double; cmd : unsigned ); virtual;
+
+ function num_paths : unsigned; virtual;
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ function func_operator_gamma(x : double ) : double; virtual;
+ function operator_array (i : unsigned ) : unsigned; virtual; abstract;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor vertex_source.Construct;
+begin
+end;
+
+{ DESTRUCT }
+destructor vertex_source.Destruct;
+begin
+end;
+
+{ REMOVE_ALL }
+procedure vertex_source.remove_all;
+begin
+end;
+
+{ ADD_VERTEX }
+procedure vertex_source.add_vertex;
+begin
+end;
+
+{ NUM_PATHS }
+function vertex_source.num_paths;
+begin
+ result:=0;
+
+end;
+
+{ REWIND }
+procedure vertex_source.rewind;
+begin
+end;
+
+{ VERTEX }
+function vertex_source.vertex;
+begin
+end;
+
+{ FUNC_OPERATOR_GAMMA }
+function vertex_source.func_operator_gamma;
+begin
+ result:=x;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_vpgen_clip_polygon.pas b/src/corelib/render/software/agg_vpgen_clip_polygon.pas
new file mode 100644
index 00000000..ad106c43
--- /dev/null
+++ b/src/corelib/render/software/agg_vpgen_clip_polygon.pas
@@ -0,0 +1,329 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 07.02.2006-Milano: Unit port establishment
+//
+{ agg_vpgen_clip_polygon.pas }
+unit
+ agg_vpgen_clip_polygon ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_vertex_source ,
+ agg_clip_liang_barsky ;
+
+{ TYPES DEFINITION }
+type
+ vpgen_clip_polygon_ptr = ^vpgen_clip_polygon;
+ vpgen_clip_polygon = object(vertex_source )
+ m_clip_box : rect_d;
+
+ m_x1 ,
+ m_y1 : double;
+
+ m_clip_flags : unsigned;
+
+ m_x ,
+ m_y : array[0..3 ] of double;
+
+ m_num_vertices ,
+ m_vertex ,
+ m_cmd : unsigned;
+
+ constructor Construct;
+
+ procedure clip_box_(x1 ,y1 ,x2 ,y2 : double );
+
+ function _x1 : double;
+ function _y1 : double;
+ function _x2 : double;
+ function _y2 : double;
+
+ function _auto_close : boolean;
+ function _auto_unclose : boolean;
+
+ procedure reset;
+ procedure move_to(x ,y : double );
+ procedure line_to(x ,y : double );
+
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ function clipping_flags(x ,y : double ) : unsigned;
+
+ end;
+
+{ GLOBAL VARIABLES & CONSTANTS }
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor vpgen_clip_polygon.Construct;
+begin
+ m_clip_box.Construct(0 ,0 ,1 ,1 );
+
+ m_x1:=0;
+ m_y1:=0;
+
+ m_clip_flags :=0;
+ m_num_vertices:=0;
+
+ m_vertex:=0;
+ m_cmd :=path_cmd_move_to;
+
+end;
+
+{ CLIP_BOX_ }
+procedure vpgen_clip_polygon.clip_box_;
+begin
+ m_clip_box.x1:=x1;
+ m_clip_box.y1:=y1;
+ m_clip_box.x2:=x2;
+ m_clip_box.y2:=y2;
+
+ m_clip_box.normalize;
+
+end;
+
+{ _X1 }
+function vpgen_clip_polygon._x1;
+begin
+ result:=m_clip_box.x1;
+
+end;
+
+{ _Y1 }
+function vpgen_clip_polygon._y1;
+begin
+ result:=m_clip_box.y1;
+
+end;
+
+{ _X2 }
+function vpgen_clip_polygon._x2;
+begin
+ result:=m_clip_box.x2;
+
+end;
+
+{ _Y2 }
+function vpgen_clip_polygon._y2;
+begin
+ result:=m_clip_box.y2;
+
+end;
+
+{ _AUTO_CLOSE }
+function vpgen_clip_polygon._auto_close;
+begin
+ result:=true;
+
+end;
+
+{ _AUTO_UNCLOSE }
+function vpgen_clip_polygon._auto_unclose;
+begin
+ result:=false;
+
+end;
+
+{ RESET }
+procedure vpgen_clip_polygon.reset;
+begin
+ m_vertex :=0;
+ m_num_vertices:=0;
+
+end;
+
+{ MOVE_TO }
+procedure vpgen_clip_polygon.move_to;
+begin
+ m_vertex :=0;
+ m_num_vertices:=0;
+ m_clip_flags :=clipping_flags(x ,y );
+
+ if m_clip_flags = 0 then
+ begin
+ m_x[0 ]:=x;
+ m_y[0 ]:=y;
+
+ m_num_vertices:=1;
+
+ end;
+
+ m_x1 :=x;
+ m_y1 :=y;
+ m_cmd:=path_cmd_move_to;
+
+end;
+
+{ LINE_TO }
+procedure vpgen_clip_polygon.line_to;
+var
+ flags : unsigned;
+
+begin
+ m_vertex :=0;
+ m_num_vertices:=0;
+
+ flags:=clipping_flags(x ,y );
+
+ if m_clip_flags = flags then
+ if flags = 0 then
+ begin
+ m_x[0 ]:=x;
+ m_y[0 ]:=y;
+
+ m_num_vertices:=1;
+
+ end
+ else
+ else
+ m_num_vertices:=
+ clip_liang_barsky_d(
+ m_x1 ,m_y1 ,x ,y ,@m_clip_box ,@m_x ,@m_y );
+
+ m_clip_flags:=flags;
+
+ m_x1:=x;
+ m_y1:=y;
+
+end;
+
+{ VERTEX }
+function vpgen_clip_polygon.vertex;
+var
+ cmd : unsigned;
+
+begin
+ if m_vertex < m_num_vertices then
+ begin
+ x^:=m_x[m_vertex ];
+ y^:=m_y[m_vertex ];
+
+ inc(m_vertex );
+
+ cmd :=m_cmd;
+ m_cmd:=path_cmd_line_to;
+
+ result:=cmd;
+
+ end
+ else
+ result:=path_cmd_stop;
+
+end;
+
+{ CLIPPING_FLAGS }
+// Determine the clipping code of the vertex according to the
+// Cyrus-Beck line clipping algorithm
+//
+// | |
+// 0110 | 0010 | 0011
+// | |
+// -------+--------+-------- clip_box.y2
+// | |
+// 0100 | 0000 | 0001
+// | |
+// -------+--------+-------- clip_box.y1
+// | |
+// 1100 | 1000 | 1001
+// | |
+// clip_box.x1 clip_box.x2
+function vpgen_clip_polygon.clipping_flags;
+begin
+ if x < m_clip_box.x1 then
+ begin
+ if y > m_clip_box.y2 then
+ begin
+ result:=6;
+
+ exit;
+
+ end;
+
+ if y < m_clip_box.y1 then
+ begin
+ result:=12;
+
+ exit;
+
+ end;
+
+ result:=4;
+
+ exit;
+
+ end;
+
+ if x > m_clip_box.x2 then
+ begin
+ if y > m_clip_box.y2 then
+ begin
+ result:=3;
+
+ exit;
+
+ end;
+
+ if y < m_clip_box.y1 then
+ begin
+ result:=9;
+
+ exit;
+
+ end;
+
+ result:=1;
+
+ exit;
+
+ end;
+
+ if y > m_clip_box.y2 then
+ begin
+ result:=2;
+
+ exit;
+
+ end;
+
+ if y < m_clip_box.y1 then
+ begin
+ result:=8;
+
+ exit;
+
+ end;
+
+ result:=0;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_vpgen_clip_polyline.pas b/src/corelib/render/software/agg_vpgen_clip_polyline.pas
new file mode 100644
index 00000000..32ba6d92
--- /dev/null
+++ b/src/corelib/render/software/agg_vpgen_clip_polyline.pas
@@ -0,0 +1,386 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 01.03.2006-Milano: Unit port establishment
+//
+{ agg_vpgen_clip_polyline.pas }
+unit
+ agg_vpgen_clip_polyline ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_vertex_source ;
+
+{ TYPES DEFINITION }
+const
+ clip_x1 = 1;
+ clip_x2 = 2;
+ clip_y1 = 4;
+ clip_y2 = 8;
+
+type
+ vpgen_clip_polyline_ptr = ^vpgen_clip_polyline;
+ vpgen_clip_polyline = object(vertex_source )
+ m_clip_box : rect_d;
+
+ m_x1 ,
+ m_y1 : double;
+ m_f1 : unsigned;
+ m_x2 ,
+ m_y2 : double;
+ m_f2 : unsigned;
+
+ m_x ,
+ m_y : array[0..1 ] of double;
+ m_cmd : array[0..1 ] of unsigned;
+
+ m_num_vertices ,
+ m_vertex : unsigned;
+
+ constructor Construct;
+
+ procedure clip_box_(x1 ,y1 ,x2 ,y2 : double );
+
+ function _x1 : double;
+ function _y1 : double;
+ function _x2 : double;
+ function _y2 : double;
+
+ function _auto_close : boolean;
+ function _auto_unclose : boolean;
+
+ procedure reset;
+ procedure move_to(x ,y : double );
+ procedure line_to(x ,y : double );
+
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ // Determine the clipping code of the vertex according to the
+ // Cyrus-Beck line clipping algorithm
+ function clipping_flags_x(x : double ) : unsigned;
+ function clipping_flags_y(y : double ) : unsigned;
+ function clipping_flags (x ,y : double ) : unsigned;
+
+ function move_point(x ,y : double_ptr; flags : unsigned_ptr ) : boolean;
+
+ procedure clip_line_segment;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+const
+ clip_epsilon = 1e-10;
+
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor vpgen_clip_polyline.Construct;
+begin
+ m_clip_box.Construct(0 ,0 ,1 ,1 );
+
+ m_x1:=0;
+ m_y1:=0;
+ m_f1:=0;
+ m_x2:=0;
+ m_y2:=0;
+ m_f2:=0;
+
+ m_num_vertices:=0;
+ m_vertex :=0;
+
+end;
+
+{ CLIP_BOX_ }
+procedure vpgen_clip_polyline.clip_box_;
+begin
+ m_clip_box.x1:=x1;
+ m_clip_box.y1:=y1;
+ m_clip_box.x2:=x2;
+ m_clip_box.y2:=y2;
+
+ m_clip_box.normalize;
+
+end;
+
+{ _X1 }
+function vpgen_clip_polyline._x1;
+begin
+ result:=m_clip_box.x1;
+
+end;
+
+{ _Y1 }
+function vpgen_clip_polyline._y1;
+begin
+ result:=m_clip_box.y1;
+
+end;
+
+{ _X2 }
+function vpgen_clip_polyline._x2;
+begin
+ result:=m_clip_box.x2;
+
+end;
+
+{ _Y2 }
+function vpgen_clip_polyline._y2;
+begin
+ result:=m_clip_box.y2;
+
+end;
+
+{ _AUTO_CLOSE }
+function vpgen_clip_polyline._auto_close;
+begin
+ result:=false;
+
+end;
+
+{ _AUTO_UNCLOSE }
+function vpgen_clip_polyline._auto_unclose;
+begin
+ result:=true;
+
+end;
+
+{ RESET }
+procedure vpgen_clip_polyline.reset;
+begin
+ m_vertex :=0;
+ m_num_vertices:=0;
+
+end;
+
+{ MOVE_TO }
+procedure vpgen_clip_polyline.move_to;
+begin
+ m_vertex :=0;
+ m_num_vertices:=0;
+
+ m_f1:=clipping_flags(x ,y );
+
+ if m_f1 = 0 then
+ begin
+ m_x[0 ]:=x;
+ m_y[0 ]:=y;
+
+ m_cmd[0 ]:=path_cmd_move_to;
+
+ m_num_vertices:=1;
+
+ end;
+
+ m_x1:=x;
+ m_y1:=y;
+
+end;
+
+{ LINE_TO }
+procedure vpgen_clip_polyline.line_to;
+var
+ f : unsigned;
+
+begin
+ m_vertex :=0;
+ m_num_vertices:=0;
+
+ m_x2:=x;
+ m_y2:=y;
+
+ f :=clipping_flags(m_x2 ,m_y2 );
+ m_f2:=f;
+
+ if m_f2 = m_f1 then
+ if m_f2 = 0 then
+ begin
+ m_x[0 ]:=x;
+ m_y[0 ]:=y;
+
+ m_cmd[0 ]:=path_cmd_line_to;
+
+ m_num_vertices:=1;
+
+ end
+ else
+ else
+ clip_line_segment;
+
+ m_f1:=f;
+ m_x1:=x;
+ m_y1:=y;
+
+end;
+
+{ VERTEX }
+function vpgen_clip_polyline.vertex;
+begin
+ if m_vertex < m_num_vertices then
+ begin
+ x^:=m_x[m_vertex ];
+ y^:=m_y[m_vertex ];
+
+ result:=m_cmd[m_vertex ];
+
+ inc(m_vertex );
+
+ end
+ else
+ result:=path_cmd_stop;
+
+end;
+
+{ CLIPPING_FLAGS_X }
+function vpgen_clip_polyline.clipping_flags_x;
+var
+ f : unsigned;
+
+begin
+ f:=0;
+
+ if x < m_clip_box.x1 then
+ f:=f or clip_x1;
+
+ if x > m_clip_box.x2 then
+ f:=f or clip_x2;
+
+ result:=f;
+
+end;
+
+{ CLIPPING_FLAGS_Y }
+function vpgen_clip_polyline.clipping_flags_y;
+var
+ f : unsigned;
+
+begin
+ f:=0;
+
+ if y < m_clip_box.y1 then
+ f:=f or clip_y1;
+
+ if y > m_clip_box.y2 then
+ f:=f or clip_y2;
+
+ result:=f;
+
+end;
+
+{ CLIPPING_FLAGS }
+function vpgen_clip_polyline.clipping_flags;
+begin
+ result:=clipping_flags_x(x ) or clipping_flags_y(y );
+
+end;
+
+{ MOVE_POINT }
+function vpgen_clip_polyline.move_point;
+var
+ bound : double;
+
+begin
+ if flags^ and (clip_x1 or clip_x2 ) <> 0 then
+ begin
+ if flags^ and clip_x1 <> 0 then
+ bound:=m_clip_box.x1
+ else
+ bound:=m_clip_box.x2;
+
+ y^:=(bound - m_x1 ) * (m_y2 - m_y1 ) / (m_x2 - m_x1 ) + m_y1;
+ x^:=bound;
+
+ flags^:=clipping_flags_y(y^ );
+
+ end;
+
+ if (Abs(m_y2 - m_y1 ) < clip_epsilon ) and
+ (Abs(m_x2 - m_x1 ) < clip_epsilon ) then
+ begin
+ result:=false;
+
+ exit;
+
+ end;
+
+ if flags^ and (clip_y1 or clip_y2 ) <> 0 then
+ begin
+ if flags^ and clip_y1 <> 0 then
+ bound:=m_clip_box.y1
+ else
+ bound:=m_clip_box.y2;
+
+ x^:=(bound - m_y1 ) * (m_x2 - m_x1 ) / (m_y2 - m_y1 ) + m_x1;
+ y^:=bound;
+
+ end;
+
+ flags^:=0;
+ result:=true;
+
+end;
+
+{ CLIP_LINE_SEGMENT }
+procedure vpgen_clip_polyline.clip_line_segment;
+begin
+ if (m_f1 and m_f2 ) = 0 then
+ begin
+ if m_f1 <> 0 then
+ begin
+ if not move_point(@m_x1 ,@m_y1 ,@m_f1 ) then
+ exit;
+
+ if m_f1 <> 0 then
+ exit;
+
+ m_x[0 ]:=m_x1;
+ m_y[0 ]:=m_y1;
+
+ m_cmd[0 ]:=path_cmd_move_to;
+
+ m_num_vertices:=1;
+
+ end;
+
+ if m_f2 <> 0 then // Move Point 2
+ if not move_point(@m_x2 ,@m_y2 ,@m_f2 ) then
+ exit;
+
+ m_x[m_num_vertices ]:=m_x2;
+ m_y[m_num_vertices ]:=m_y2;
+
+ m_cmd[m_num_vertices ]:=path_cmd_line_to;
+
+ inc(m_num_vertices );
+
+ end;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/agg_vpgen_segmentator.pas b/src/corelib/render/software/agg_vpgen_segmentator.pas
new file mode 100644
index 00000000..39af4cb3
--- /dev/null
+++ b/src/corelib/render/software/agg_vpgen_segmentator.pas
@@ -0,0 +1,205 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 25.01.2006-Milano: Unit port establishment
+//
+{ agg_vpgen_segmentator.pas }
+unit
+ agg_vpgen_segmentator ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_vertex_source ;
+
+{ TYPES DEFINITION }
+type
+ vpgen_segmentator_ptr = ^vpgen_segmentator;
+ vpgen_segmentator = object(vertex_source )
+ m_approximation_scale ,
+
+ m_x1 ,
+ m_y1 ,
+ m_dx ,
+ m_dy ,
+ m_dl ,
+ m_ddl : double;
+ m_cmd : unsigned;
+
+ constructor Construct;
+
+ procedure approximation_scale_(s : double );
+ function _approximation_scale : double;
+
+ function _auto_close : boolean;
+ function _auto_unclose : boolean;
+
+ procedure reset;
+ procedure move_to(x ,y : double );
+ procedure line_to(x ,y : double );
+
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor vpgen_segmentator.Construct;
+begin
+ m_approximation_scale:=1.0;
+
+ m_x1 :=0;
+ m_y1 :=0;
+ m_dx :=0;
+ m_dy :=0;
+ m_dl :=0;
+ m_ddl:=0;
+ m_cmd:=0;
+
+end;
+
+{ APPROXIMATION_SCALE_ }
+procedure vpgen_segmentator.approximation_scale_;
+begin
+ m_approximation_scale:=s;
+
+end;
+
+{ _APPROXIMATION_SCALE }
+function vpgen_segmentator._approximation_scale;
+begin
+ result:=m_approximation_scale;
+
+end;
+
+{ _AUTO_CLOSE }
+function vpgen_segmentator._auto_close;
+begin
+ result:=false
+
+end;
+
+{ _AUTO_UNCLOSE }
+function vpgen_segmentator._auto_unclose;
+begin
+ result:=false
+
+end;
+
+{ RESET }
+procedure vpgen_segmentator.reset;
+begin
+ m_cmd:=path_cmd_stop;
+
+end;
+
+{ MOVE_TO }
+procedure vpgen_segmentator.move_to;
+begin
+ m_x1 :=x;
+ m_y1 :=y;
+ m_dx :=0.0;
+ m_dy :=0.0;
+ m_dl :=2.0;
+ m_ddl:=2.0;
+ m_cmd:=path_cmd_move_to;
+
+end;
+
+{ LINE_TO }
+procedure vpgen_segmentator.line_to;
+var
+ len : double;
+
+begin
+ m_x1:=m_x1 + m_dx;
+ m_y1:=m_y1 + m_dy;
+ m_dx:=x - m_x1;
+ m_dy:=y - m_y1;
+
+ len:=Sqrt(m_dx * m_dx + m_dy * m_dy ) * m_approximation_scale;
+
+ if len < 1e-30 then
+ len:=1e-30;
+
+ m_ddl:=1.0 / len;
+
+ if m_cmd = path_cmd_move_to then
+ m_dl:=0.0
+ else
+ m_dl:=m_ddl;
+
+ if m_cmd = path_cmd_stop then
+ m_cmd:=path_cmd_line_to;
+
+end;
+
+{ VERTEX }
+function vpgen_segmentator.vertex;
+var
+ cmd : unsigned;
+
+begin
+ if m_cmd = path_cmd_stop then
+ result:=path_cmd_stop
+
+ else
+ begin
+ cmd :=m_cmd;
+ m_cmd:=path_cmd_line_to;
+
+ if m_dl >= 1.0 - m_ddl then
+ begin
+ m_dl :=1.0;
+ m_cmd:=path_cmd_stop;
+
+ x^:=m_x1 + m_dx;
+ y^:=m_y1 + m_dy;
+
+ result:=cmd;
+
+ end
+ else
+ begin
+ x^:=m_x1 + m_dx * m_dl;
+ y^:=m_y1 + m_dy * m_dl;
+
+ m_dl:=m_dl + m_ddl;
+
+ result:=cmd;
+
+ end;
+
+ end;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/ctrl/agg_bezier_ctrl.pas b/src/corelib/render/software/ctrl/agg_bezier_ctrl.pas
new file mode 100644
index 00000000..6f158c2b
--- /dev/null
+++ b/src/corelib/render/software/ctrl/agg_bezier_ctrl.pas
@@ -0,0 +1,887 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// classes bezier_ctrl_impl, bezier_ctrl
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.02.2006-Milano: Unit port establishment
+//
+{ agg_bezier_ctrl.pas }
+unit
+ agg_bezier_ctrl ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_ctrl ,
+ agg_math ,
+ agg_ellipse ,
+ agg_trans_affine ,
+ agg_color ,
+ agg_curves ,
+ agg_conv_stroke ,
+ agg_conv_curve ,
+ agg_polygon_ctrl ;
+
+{ TYPES DEFINITION }
+type
+ bezier_ctrl_impl = object(ctrl )
+ m_curve : curve4;
+ m_ellipse : ellipse;
+ m_stroke : conv_stroke;
+ m_poly : polygon_ctrl_impl;
+ m_idx : unsigned;
+
+ constructor Construct;
+ destructor Destruct; virtual;
+
+ procedure curve_(x1 ,y1 ,x2 ,y2 ,x3 ,y3 ,x4 ,y4 : double );
+ function _curve : curve4_ptr;
+
+ function _x1 : double;
+ function _y1 : double;
+ function _x2 : double;
+ function _y2 : double;
+ function _x3 : double;
+ function _y3 : double;
+ function _x4 : double;
+ function _y4 : double;
+
+ procedure x1_(x : double );
+ procedure y1_(y : double );
+ procedure x2_(x : double );
+ procedure y2_(y : double );
+ procedure x3_(x : double );
+ procedure y3_(y : double );
+ procedure x4_(x : double );
+ procedure y4_(y : double );
+
+ procedure line_width_(w : double );
+ function _line_width : double;
+
+ procedure point_radius_(r : double );
+ function _point_radius : double;
+
+ // Event handlers
+ function in_rect(x ,y : double ) : boolean; virtual;
+
+ function on_mouse_button_down(x ,y : double ) : boolean; virtual;
+ function on_mouse_button_up (x ,y : double ) : boolean; virtual;
+
+ function on_mouse_move(x ,y : double; button_flag : boolean ) : boolean; virtual;
+ function on_arrow_keys(left ,right ,down ,up : boolean ) : boolean; virtual;
+
+ // Vertex source interface
+ function num_paths : unsigned; virtual;
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ end;
+
+ bezier_ctrl = object(bezier_ctrl_impl )
+ m_color : aggclr;
+
+ constructor Construct;
+
+ procedure line_color_(c : aggclr_ptr );
+
+ function _color(i : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+ curve3_ctrl_impl = object(ctrl )
+ m_curve : curve3;
+ m_ellipse : ellipse;
+ m_stroke : conv_stroke;
+ m_poly : polygon_ctrl_impl;
+ m_idx : unsigned;
+
+ constructor Construct;
+ destructor Destruct; virtual;
+
+ procedure curve_(x1 ,y1 ,x2 ,y2 ,x3 ,y3 : double );
+ function _curve : curve3_ptr;
+
+ function _x1 : double;
+ function _y1 : double;
+ function _x2 : double;
+ function _y2 : double;
+ function _x3 : double;
+ function _y3 : double;
+
+ procedure x1_(x : double );
+ procedure y1_(y : double );
+ procedure x2_(x : double );
+ procedure y2_(y : double );
+ procedure x3_(x : double );
+ procedure y3_(y : double );
+
+ procedure line_width_(w : double );
+ function _line_width : double;
+
+ procedure point_radius_(r : double );
+ function _point_radius : double;
+
+ // Event handlers
+ function in_rect(x ,y : double ) : boolean; virtual;
+
+ function on_mouse_button_down(x ,y : double ) : boolean; virtual;
+ function on_mouse_button_up (x ,y : double ) : boolean; virtual;
+
+ function on_mouse_move(x ,y : double; button_flag : boolean ) : boolean; virtual;
+ function on_arrow_keys(left ,right ,down ,up : boolean ) : boolean; virtual;
+
+ // Vertex source interface
+ function num_paths : unsigned; virtual;
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ end;
+
+ curve3_ctrl = object(curve3_ctrl_impl )
+ m_color : aggclr;
+
+ constructor Construct;
+
+ procedure line_color_(c : aggclr_ptr );
+
+ function _color(i : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor bezier_ctrl_impl.Construct;
+begin
+ inherited Construct(0 ,0 ,1 ,1 ,false );
+
+ m_curve.Construct;
+ m_ellipse.Construct;
+ m_stroke.Construct(@m_curve );
+ m_poly.Construct (4 ,5.0 );
+
+ m_idx:=0;
+
+ m_poly.in_polygon_check_(false );
+
+ m_poly.xn_ptr(0 )^:=100.0;
+ m_poly.yn_ptr(0 )^:= 0.0;
+ m_poly.xn_ptr(1 )^:=100.0;
+ m_poly.yn_ptr(1 )^:= 50.0;
+ m_poly.xn_ptr(2 )^:= 50.0;
+ m_poly.yn_ptr(2 )^:=100.0;
+ m_poly.xn_ptr(3 )^:= 0.0;
+ m_poly.yn_ptr(3 )^:=100.0;
+
+end;
+
+{ DESTRUCT }
+destructor bezier_ctrl_impl.Destruct;
+begin
+ m_curve.Destruct;
+ m_stroke.Destruct;
+ m_poly.Destruct;
+
+end;
+
+{ CURVE_ }
+procedure bezier_ctrl_impl.curve_;
+begin
+ m_poly.xn_ptr(0 )^:=x1;
+ m_poly.yn_ptr(0 )^:=y1;
+ m_poly.xn_ptr(1 )^:=x2;
+ m_poly.yn_ptr(1 )^:=y2;
+ m_poly.xn_ptr(2 )^:=x3;
+ m_poly.yn_ptr(2 )^:=y3;
+ m_poly.xn_ptr(3 )^:=x4;
+ m_poly.yn_ptr(3 )^:=y4;
+
+ _curve;
+
+end;
+
+{ _CURVE }
+function bezier_ctrl_impl._curve;
+begin
+ m_curve.init4(
+ m_poly._xn(0 ) ,m_poly._yn(0 ) ,
+ m_poly._xn(1 ) ,m_poly._yn(1 ) ,
+ m_poly._xn(2 ) ,m_poly._yn(2 ) ,
+ m_poly._xn(3 ) ,m_poly._yn(3 ) );
+
+ result:=@m_curve;
+
+end;
+
+{ _X1 }
+function bezier_ctrl_impl._x1;
+begin
+ result:=m_poly._xn(0 );
+
+end;
+
+{ _Y1 }
+function bezier_ctrl_impl._y1;
+begin
+ result:=m_poly._yn(0 );
+
+end;
+
+{ _X2 }
+function bezier_ctrl_impl._x2;
+begin
+ result:=m_poly._xn(1 );
+
+end;
+
+{ _Y2 }
+function bezier_ctrl_impl._y2;
+begin
+ result:=m_poly._yn(1 );
+
+end;
+
+{ _X3 }
+function bezier_ctrl_impl._x3;
+begin
+ result:=m_poly._xn(2 );
+
+end;
+
+{ _Y3 }
+function bezier_ctrl_impl._y3;
+begin
+ result:=m_poly._yn(2 );
+
+end;
+
+{ _X4 }
+function bezier_ctrl_impl._x4;
+begin
+ result:=m_poly._xn(3 );
+
+end;
+
+{ _Y4 }
+function bezier_ctrl_impl._y4;
+begin
+ result:=m_poly._yn(3 );
+
+end;
+
+{ X1_ }
+procedure bezier_ctrl_impl.x1_;
+begin
+ m_poly.xn_ptr(0 )^:=x;
+
+end;
+
+{ Y1_ }
+procedure bezier_ctrl_impl.y1_;
+begin
+ m_poly.yn_ptr(0 )^:=y;
+
+end;
+
+{ X2_ }
+procedure bezier_ctrl_impl.x2_;
+begin
+ m_poly.xn_ptr(1 )^:=x;
+
+end;
+
+{ Y2_ }
+procedure bezier_ctrl_impl.y2_;
+begin
+ m_poly.yn_ptr(1 )^:=y;
+
+end;
+
+{ X3_ }
+procedure bezier_ctrl_impl.x3_;
+begin
+ m_poly.xn_ptr(2 )^:=x;
+
+end;
+
+{ Y3_ }
+procedure bezier_ctrl_impl.y3_;
+begin
+ m_poly.yn_ptr(2 )^:=y;
+
+end;
+
+{ X4_ }
+procedure bezier_ctrl_impl.x4_;
+begin
+ m_poly.xn_ptr(3 )^:=x;
+
+end;
+
+{ Y4_ }
+procedure bezier_ctrl_impl.y4_;
+begin
+ m_poly.yn_ptr(3 )^:=y;
+
+end;
+
+{ LINE_WIDTH_ }
+procedure bezier_ctrl_impl.line_width_;
+begin
+ m_stroke.width_(w );
+
+end;
+
+{ _LINE_WIDTH }
+function bezier_ctrl_impl._line_width;
+begin
+ result:=m_stroke._width;
+
+end;
+
+{ POINT_RADIUS_ }
+procedure bezier_ctrl_impl.point_radius_;
+begin
+ m_poly.point_radius_(r );
+
+end;
+
+{ _POINT_RADIUS }
+function bezier_ctrl_impl._point_radius;
+begin
+ result:=m_poly._point_radius;
+
+end;
+
+{ IN_RECT }
+function bezier_ctrl_impl.in_rect;
+begin
+ result:=false;
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+function bezier_ctrl_impl.on_mouse_button_down;
+begin
+ inverse_transform_xy(@x ,@y );
+
+ result:=m_poly.on_mouse_button_down(x ,y );
+
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+function bezier_ctrl_impl.on_mouse_button_up;
+begin
+ result:=m_poly.on_mouse_button_up(x ,y );
+
+end;
+
+{ ON_MOUSE_MOVE }
+function bezier_ctrl_impl.on_mouse_move;
+begin
+ inverse_transform_xy(@x ,@y );
+
+ result:=m_poly.on_mouse_move(x ,y ,button_flag );
+
+end;
+
+{ ON_ARROW_KEYS }
+function bezier_ctrl_impl.on_arrow_keys;
+begin
+ result:=m_poly.on_arrow_keys(left ,right ,down ,up );
+
+end;
+
+{ NUM_PATHS }
+function bezier_ctrl_impl.num_paths;
+begin
+ result:=7;
+
+end;
+
+{ REWIND }
+procedure bezier_ctrl_impl.rewind;
+begin
+ m_idx:=path_id;
+
+ m_curve.approximation_scale_(scale );
+
+ case path_id of
+ 0 : // Control line 1
+ begin
+ m_curve.init4(
+ m_poly._xn(0 ) ,m_poly._yn(0 ) ,
+ (m_poly._xn(0 ) + m_poly._xn(1 ) ) * 0.5 ,
+ (m_poly._yn(0 ) + m_poly._yn(1 ) ) * 0.5 ,
+ (m_poly._xn(0 ) + m_poly._xn(1 ) ) * 0.5 ,
+ (m_poly._yn(0 ) + m_poly._yn(1 ) ) * 0.5 ,
+ m_poly._xn(1 ) ,m_poly._yn(1 ) );
+
+ m_stroke.rewind(0 );
+
+ end;
+
+ 1 : // Control line 2
+ begin
+ m_curve.init4(
+ m_poly._xn(2 ) ,m_poly._yn(2 ) ,
+ (m_poly._xn(2 ) + m_poly._xn(3 ) ) * 0.5,
+ (m_poly._yn(2 ) + m_poly._yn(3 ) ) * 0.5,
+ (m_poly._xn(2 ) + m_poly._xn(3 ) ) * 0.5,
+ (m_poly._yn(2 ) + m_poly._yn(3 ) ) * 0.5,
+ m_poly._xn(3 ) ,m_poly._yn(3 ) );
+
+ m_stroke.rewind(0 );
+
+ end;
+
+ 2 : // Curve itself
+ begin
+ m_curve.init4(
+ m_poly._xn(0 ) ,m_poly._yn(0 ) ,
+ m_poly._xn(1 ) ,m_poly._yn(1 ) ,
+ m_poly._xn(2 ) ,m_poly._yn(2 ) ,
+ m_poly._xn(3 ) ,m_poly._yn(3 ) );
+
+ m_stroke.rewind(0 );
+
+ end;
+
+ 3 : // Point 1
+ begin
+ m_ellipse.init (m_poly._xn(0 ) ,m_poly._yn(0 ) ,_point_radius ,_point_radius ,20 );
+ m_ellipse.rewind(0 );
+
+ end;
+
+ 4 : // Point 2
+ begin
+ m_ellipse.init (m_poly._xn(1 ) ,m_poly._yn(1 ) ,_point_radius ,_point_radius ,20 );
+ m_ellipse.rewind(0 );
+
+ end;
+
+ 5 : // Point 3
+ begin
+ m_ellipse.init (m_poly._xn(2 ) ,m_poly._yn(2 ) ,_point_radius ,_point_radius ,20 );
+ m_ellipse.rewind(0 );
+
+ end;
+
+ 6 : // Point 4
+ begin
+ m_ellipse.init (m_poly._xn(3 ) ,m_poly._yn(3 ) ,_point_radius ,_point_radius ,20 );
+ m_ellipse.rewind(0 );
+
+ end;
+
+ end;
+
+end;
+
+{ VERTEX }
+function bezier_ctrl_impl.vertex;
+var
+ cmd : unsigned;
+
+begin
+ cmd:=path_cmd_stop;
+
+ case m_idx of
+ 0 ,1 ,2 :
+ cmd:=m_stroke.vertex(x ,y );
+
+ 3 ,4 ,5 ,6 ,7 :
+ cmd:=m_ellipse.vertex(x, y);
+
+ end;
+
+ if not is_stop(cmd ) then
+ transform_xy(x ,y );
+
+ result:=cmd;
+
+end;
+
+{ CONSTRUCT }
+constructor bezier_ctrl.Construct;
+begin
+ inherited Construct;
+
+ m_color.ConstrDbl(0.0 ,0.0 ,0.0 );
+
+end;
+
+{ LINE_COLOR_ }
+procedure bezier_ctrl.line_color_;
+begin
+ m_color:=c^;
+
+end;
+
+{ _COLOR }
+function bezier_ctrl._color;
+begin
+ result:=@m_color;
+
+end;
+
+{ CONSTRUCT }
+constructor curve3_ctrl_impl.Construct;
+begin
+ inherited Construct(0 ,0 ,1 ,1 ,false );
+
+ m_curve.Construct;
+ m_ellipse.Construct;
+ m_stroke.Construct(@m_curve );
+ m_poly.Construct (3 ,5.0 );
+
+ m_idx:=0;
+
+ m_poly.in_polygon_check_(false );
+
+ m_poly.xn_ptr(0 )^:=100.0;
+ m_poly.yn_ptr(0 )^:= 0.0;
+ m_poly.xn_ptr(1 )^:=100.0;
+ m_poly.yn_ptr(1 )^:= 50.0;
+ m_poly.xn_ptr(2 )^:= 50.0;
+ m_poly.yn_ptr(2 )^:=100.0;
+
+end;
+
+{ DESTRUCT }
+destructor curve3_ctrl_impl.Destruct;
+begin
+ m_curve.Destruct;
+ m_stroke.Destruct;
+ m_poly.Destruct;
+
+end;
+
+{ CURVE_ }
+procedure curve3_ctrl_impl.curve_;
+begin
+ m_poly.xn_ptr(0 )^:=x1;
+ m_poly.yn_ptr(0 )^:=y1;
+ m_poly.xn_ptr(1 )^:=x2;
+ m_poly.yn_ptr(1 )^:=y2;
+ m_poly.xn_ptr(2 )^:=x3;
+ m_poly.yn_ptr(2 )^:=y3;
+
+ _curve;
+
+end;
+
+{ _CURVE }
+function curve3_ctrl_impl._curve;
+begin
+ m_curve.init3(
+ m_poly._xn(0 ) ,m_poly._yn(0 ) ,
+ m_poly._xn(1 ) ,m_poly._yn(1 ) ,
+ m_poly._xn(2 ) ,m_poly._yn(2 ) );
+
+ result:=@m_curve;
+
+end;
+
+{ _X1 }
+function curve3_ctrl_impl._x1;
+begin
+ result:=m_poly._xn(0 );
+
+end;
+
+{ _Y1 }
+function curve3_ctrl_impl._y1;
+begin
+ result:=m_poly._yn(0 );
+
+end;
+
+{ _X2 }
+function curve3_ctrl_impl._x2;
+begin
+ result:=m_poly._xn(1 );
+
+end;
+
+{ _Y2 }
+function curve3_ctrl_impl._y2;
+begin
+ result:=m_poly._yn(1 );
+
+end;
+
+{ _X3 }
+function curve3_ctrl_impl._x3;
+begin
+ result:=m_poly._xn(2 );
+
+end;
+
+{ _Y3 }
+function curve3_ctrl_impl._y3;
+begin
+ result:=m_poly._yn(2 );
+
+end;
+
+{ X1_ }
+procedure curve3_ctrl_impl.x1_;
+begin
+ m_poly.xn_ptr(0 )^:=x;
+
+end;
+
+{ Y1_ }
+procedure curve3_ctrl_impl.y1_;
+begin
+ m_poly.yn_ptr(0 )^:=y;
+
+end;
+
+{ X2_ }
+procedure curve3_ctrl_impl.x2_;
+begin
+ m_poly.xn_ptr(1 )^:=x;
+
+end;
+
+{ Y2_ }
+procedure curve3_ctrl_impl.y2_;
+begin
+ m_poly.yn_ptr(1 )^:=y;
+
+end;
+
+{ X3_ }
+procedure curve3_ctrl_impl.x3_;
+begin
+ m_poly.xn_ptr(2 )^:=x;
+
+end;
+
+{ Y3_ }
+procedure curve3_ctrl_impl.y3_;
+begin
+ m_poly.yn_ptr(2 )^:=y;
+
+end;
+
+{ LINE_WIDTH_ }
+procedure curve3_ctrl_impl.line_width_;
+begin
+ m_stroke.width_(w );
+
+end;
+
+{ _LINE_WIDTH }
+function curve3_ctrl_impl._line_width;
+begin
+ result:=m_stroke._width;
+
+end;
+
+{ POINT_RADIUS_ }
+procedure curve3_ctrl_impl.point_radius_;
+begin
+ m_poly.point_radius_(r );
+
+end;
+
+{ _POINT_RADIUS }
+function curve3_ctrl_impl._point_radius;
+begin
+ result:=m_poly._point_radius;
+
+end;
+
+{ IN_RECT }
+function curve3_ctrl_impl.in_rect;
+begin
+ result:=false;
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+function curve3_ctrl_impl.on_mouse_button_down;
+begin
+ inverse_transform_xy(@x ,@y );
+
+ result:=m_poly.on_mouse_button_down(x ,y );
+
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+function curve3_ctrl_impl.on_mouse_button_up;
+begin
+ result:=m_poly.on_mouse_button_up(x ,y );
+
+end;
+
+{ ON_MOUSE_MOVE }
+function curve3_ctrl_impl.on_mouse_move;
+begin
+ inverse_transform_xy(@x ,@y );
+
+ result:=m_poly.on_mouse_move(x ,y ,button_flag );
+
+end;
+
+{ ON_ARROW_KEYS }
+function curve3_ctrl_impl.on_arrow_keys;
+begin
+ result:=m_poly.on_arrow_keys(left ,right ,down ,up );
+
+end;
+
+{ NUM_PATHS }
+function curve3_ctrl_impl.num_paths;
+begin
+ result:=6;
+
+end;
+
+{ REWIND }
+procedure curve3_ctrl_impl.rewind;
+begin
+ m_idx:=path_id;
+
+ case path_id of
+ 0 : // Control line
+ begin
+ m_curve.init3(
+ m_poly._xn(0 ) ,m_poly._yn(0 ) ,
+ (m_poly._xn(0 ) + m_poly._xn(1 ) ) * 0.5,
+ (m_poly._yn(0 ) + m_poly._yn(1 ) ) * 0.5,
+ m_poly._xn(1 ) ,m_poly._yn(1 ) );
+
+ m_stroke.rewind(0 );
+
+ end;
+
+ 1 : // Control line 2
+ begin
+ m_curve.init3(
+ m_poly._xn(1 ) ,m_poly._yn(1 ) ,
+ (m_poly._xn(1 ) + m_poly._xn(2 ) ) * 0.5,
+ (m_poly._yn(1 ) + m_poly._yn(2 ) ) * 0.5,
+ m_poly._xn(2 ) ,m_poly._yn(2 ) );
+
+ m_stroke.rewind(0 );
+
+ end;
+
+ 2 : // Curve itself
+ begin
+ m_curve.init3(
+ m_poly._xn(0 ) ,m_poly._yn(0 ) ,
+ m_poly._xn(1 ) ,m_poly._yn(1 ) ,
+ m_poly._xn(2 ) ,m_poly._yn(2 ) );
+
+ m_stroke.rewind(0 );
+
+ end;
+
+ 3 : // Point 1
+ begin
+ m_ellipse.init (m_poly._xn(0 ) ,m_poly._yn(0 ) ,_point_radius ,_point_radius ,20 );
+ m_ellipse.rewind(0 );
+
+ end;
+
+ 4 : // Point 2
+ begin
+ m_ellipse.init (m_poly._xn(1 ) ,m_poly._yn(1 ) ,_point_radius ,_point_radius ,20 );
+ m_ellipse.rewind(0 );
+
+ end;
+
+ 5 : // Point 3
+ begin
+ m_ellipse.init (m_poly._xn(2 ) ,m_poly._yn(2 ) ,_point_radius ,_point_radius ,20 );
+ m_ellipse.rewind(0 );
+
+ end;
+
+ end;
+
+end;
+
+{ VERTEX }
+function curve3_ctrl_impl.vertex;
+var
+ cmd : unsigned;
+
+begin
+ cmd:=path_cmd_stop;
+
+ case m_idx of
+ 0 ,1 ,2 :
+ cmd:=m_stroke.vertex(x ,y );
+
+ 3 ,4 ,5 ,6 :
+ cmd:=m_ellipse.vertex(x ,y );
+
+ end;
+
+ if not is_stop(cmd ) then
+ transform_xy(x ,y );
+
+ result:=cmd;
+
+end;
+
+{ CONSTRUCT }
+constructor curve3_ctrl.Construct;
+begin
+ inherited Construct;
+
+ m_color.ConstrDbl(0.0 ,0.0 ,0.0 );
+
+end;
+
+{ LINE_COLOR_ }
+procedure curve3_ctrl.line_color_;
+begin
+ m_color:=c^;
+
+end;
+
+{ _COLOR }
+function curve3_ctrl._color;
+begin
+ result:=@m_color;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/ctrl/agg_cbox_ctrl.pas b/src/corelib/render/software/ctrl/agg_cbox_ctrl.pas
new file mode 100644
index 00000000..f8245efa
--- /dev/null
+++ b/src/corelib/render/software/ctrl/agg_cbox_ctrl.pas
@@ -0,0 +1,430 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 15.01.2006-Milano: Unit port establishment
+//
+{ agg_cbox_ctrl.pas }
+unit
+ agg_cbox_ctrl ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ SysUtils ,
+ agg_basics ,
+ agg_ctrl ,
+ agg_conv_stroke ,
+ agg_gsv_text ,
+ agg_color ,
+ agg_math_stroke ;
+
+{ TYPES DEFINITION }
+type
+ cbox_ctrl_impl = object(ctrl )
+ m_text_thickness ,
+ m_text_height ,
+ m_text_width : double;
+
+ m_label : array[0..127 ] of char;
+ m_status : boolean;
+
+ m_vx ,
+ m_vy : array[0..31 ] of double;
+
+ m_text : gsv_text;
+ m_text_poly : conv_stroke;
+
+ m_idx ,
+ m_vertex : unsigned;
+
+ constructor Construct(x ,y : double; l : PChar; flip_y : boolean = false );
+ destructor Destruct; virtual;
+
+ procedure text_thickness_(t : double );
+ procedure text_size_ (h : double; w : double = 0 );
+
+ function _label : PChar;
+ procedure label_(l : PChar );
+
+ function _status : boolean;
+ procedure status_(st : boolean );
+
+ function in_rect(x ,y : double ) : boolean; virtual;
+
+ function on_mouse_button_down(x ,y : double ) : boolean; virtual;
+ function on_mouse_button_up (x ,y : double ) : boolean; virtual;
+
+ function on_mouse_move(x ,y : double; button_flag : boolean ) : boolean; virtual;
+ function on_arrow_keys(left ,right ,down ,up : boolean ) : boolean; virtual;
+
+ // Vertex source interface
+ function num_paths : unsigned; virtual;
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ end;
+
+ cbox_ctrl_ptr = ^cbox_ctrl;
+ cbox_ctrl = object(cbox_ctrl_impl )
+ m_text_color ,
+ m_inactive_color ,
+ m_active_color : aggclr;
+
+ m_colors : array[0..2 ] of aggclr_ptr;
+
+ constructor Construct(x ,y : double; l : PChar; flip_y : boolean = false );
+
+ procedure text_color_ (c : aggclr_ptr );
+ procedure inactive_color_(c : aggclr_ptr );
+ procedure active_color_ (c : aggclr_ptr );
+
+ function _color(i : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor cbox_ctrl_impl.Construct;
+begin
+ inherited Construct(x ,y ,x + 9.0 * 1.5 ,y + 9.0 * 1.5 ,flip_y );
+
+ m_text.Construct;
+ m_text_poly.Construct(@m_text );
+
+ m_text_thickness:=1.5;
+ m_text_height :=9.0;
+ m_text_width :=0.0;
+
+ m_status:=false;
+
+ label_(l );
+
+end;
+
+{ DESTRUCT }
+destructor cbox_ctrl_impl.Destruct;
+begin
+ m_text_poly.Destruct;
+ m_text.Destruct;
+
+end;
+
+{ TEXT_THICKNESS_ }
+procedure cbox_ctrl_impl.text_thickness_;
+begin
+ m_text_thickness:=t;
+
+end;
+
+{ TEXT_SIZE_ }
+procedure cbox_ctrl_impl.text_size_;
+begin
+ m_text_width :=w;
+ m_text_height:=h;
+
+end;
+
+{ _LABEL }
+function cbox_ctrl_impl._label;
+begin
+ result:=@m_label[0 ];
+
+end;
+
+{ LABEL_ }
+procedure cbox_ctrl_impl.label_;
+var
+ len : unsigned;
+
+begin
+ len:=StrLen(l );
+
+ if len > 127 then
+ len:=127;
+
+ move(l^ ,m_label[0 ] ,len );
+
+ m_label[len ]:=#0;
+
+end;
+
+{ _STATUS }
+function cbox_ctrl_impl._status;
+begin
+ result:=m_status;
+
+end;
+
+{ STATUS_ }
+procedure cbox_ctrl_impl.status_;
+begin
+ m_status:=st;
+
+end;
+
+{ IN_RECT }
+function cbox_ctrl_impl.in_rect;
+begin
+ inverse_transform_xy(@x ,@y );
+
+ result:=
+ (x >= m_x1 ) and
+ (y >= m_y1 ) and
+ (x <= m_x2 ) and
+ (y <= m_y2 );
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+function cbox_ctrl_impl.on_mouse_button_down;
+begin
+ inverse_transform_xy(@x ,@y );
+
+ if (x >= m_x1 ) and
+ (y >= m_y1 ) and
+ (x <= m_x2 ) and
+ (y <= m_y2 ) then
+ begin
+ m_status:=not m_status;
+
+ result:=true;
+
+ end
+ else
+ result:=false;
+
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+function cbox_ctrl_impl.on_mouse_button_up;
+begin
+ result:=false;
+
+end;
+
+{ ON_MOUSE_MOVE }
+function cbox_ctrl_impl.on_mouse_move;
+begin
+ result:=false;
+
+end;
+
+{ ON_ARROW_KEYS }
+function cbox_ctrl_impl.on_arrow_keys;
+begin
+ result:=false;
+
+end;
+
+{ NUM_PATHS }
+function cbox_ctrl_impl.num_paths;
+begin
+ result:=3;
+
+end;
+
+{ REWIND }
+procedure cbox_ctrl_impl.rewind;
+var
+ d2 ,t : double;
+
+begin
+ m_idx:=path_id;
+
+ case path_id of
+ 0 : // Border
+ begin
+ m_vertex:=0;
+
+ m_vx[0 ]:=m_x1;
+ m_vy[0 ]:=m_y1;
+ m_vx[1 ]:=m_x2;
+ m_vy[1 ]:=m_y1;
+ m_vx[2 ]:=m_x2;
+ m_vy[2 ]:=m_y2;
+ m_vx[3 ]:=m_x1;
+ m_vy[3 ]:=m_y2;
+ m_vx[4 ]:=m_x1 + m_text_thickness;
+ m_vy[4 ]:=m_y1 + m_text_thickness;
+ m_vx[5 ]:=m_x1 + m_text_thickness;
+ m_vy[5 ]:=m_y2 - m_text_thickness;
+ m_vx[6 ]:=m_x2 - m_text_thickness;
+ m_vy[6 ]:=m_y2 - m_text_thickness;
+ m_vx[7 ]:=m_x2 - m_text_thickness;
+ m_vy[7 ]:=m_y1 + m_text_thickness;
+
+ end;
+
+ 1 : // Text
+ begin
+ m_text.text_ (@m_label[0 ] );
+ m_text.start_point_(m_x1 + m_text_height * 2.0 ,m_y1 + m_text_height / 5.0 );
+ m_text.size_ (m_text_height ,m_text_width );
+
+ m_text_poly.width_ (m_text_thickness );
+ m_text_poly.line_join_(round_join );
+ m_text_poly.line_cap_ (round_cap );
+
+ m_text_poly.rewind(0 );
+
+ end;
+
+ 2 : // Active item
+ begin
+ m_vertex:=0;
+
+ d2:=(m_y2 - m_y1 ) / 2.0;
+ t :=m_text_thickness * 1.5;
+
+ m_vx[0 ]:=m_x1 + m_text_thickness;
+ m_vy[0 ]:=m_y1 + m_text_thickness;
+ m_vx[1 ]:=m_x1 + d2;
+ m_vy[1 ]:=m_y1 + d2 - t;
+ m_vx[2 ]:=m_x2 - m_text_thickness;
+ m_vy[2 ]:=m_y1 + m_text_thickness;
+ m_vx[3 ]:=m_x1 + d2 + t;
+ m_vy[3 ]:=m_y1 + d2;
+ m_vx[4 ]:=m_x2 - m_text_thickness;
+ m_vy[4 ]:=m_y2 - m_text_thickness;
+ m_vx[5 ]:=m_x1 + d2;
+ m_vy[5 ]:=m_y1 + d2 + t;
+ m_vx[6 ]:=m_x1 + m_text_thickness;
+ m_vy[6 ]:=m_y2 - m_text_thickness;
+ m_vx[7 ]:=m_x1 + d2 - t;
+ m_vy[7 ]:=m_y1 + d2;
+
+ end;
+
+ end;
+
+end;
+
+{ VERTEX }
+function cbox_ctrl_impl.vertex;
+var
+ cmd : unsigned;
+
+begin
+ cmd:=path_cmd_line_to;
+
+ case m_idx of
+ 0 :
+ begin
+ if (m_vertex = 0 ) or
+ (m_vertex = 4 ) then
+ cmd:=path_cmd_move_to;
+
+ if m_vertex >= 8then
+ cmd:=path_cmd_stop;
+
+ x^:=m_vx[m_vertex ];
+ y^:=m_vy[m_vertex ];
+
+ inc(m_vertex );
+
+ end;
+
+ 1 :
+ cmd:=m_text_poly.vertex(x ,y );
+
+ 2 :
+ if m_status then
+ begin
+ if m_vertex = 0 then
+ cmd:=path_cmd_move_to;
+
+ if m_vertex >= 8 then
+ cmd:=path_cmd_stop;
+
+ x^:=m_vx[m_vertex ];
+ y^:=m_vy[m_vertex ];
+
+ inc(m_vertex );
+
+ end
+ else
+ cmd:=path_cmd_stop;
+
+ else
+ cmd:=path_cmd_stop;
+
+ end;
+
+ if not is_stop(cmd ) then
+ transform_xy(x ,y );
+
+ result:=cmd;
+
+end;
+
+{ CONSTRUCT }
+constructor cbox_ctrl.Construct;
+begin
+ inherited Construct(x ,y ,l ,flip_y );
+
+ m_text_color.ConstrDbl (0.0 ,0.0 ,0.0 );
+ m_inactive_color.ConstrDbl(0.0 ,0.0 ,0.0 );
+ m_active_color.ConstrDbl (0.4 ,0.0 ,0.0 );
+
+ m_colors[0 ]:=@m_inactive_color;
+ m_colors[1 ]:=@m_text_color;
+ m_colors[2 ]:=@m_active_color;
+
+end;
+
+{ TEXT_COLOR_ }
+procedure cbox_ctrl.text_color_;
+begin
+ m_text_color:=c^;
+
+end;
+
+{ INACTIVE_COLOR_ }
+procedure cbox_ctrl.inactive_color_;
+begin
+ m_inactive_color:=c^;
+
+end;
+
+{ ACTIVE_COLOR_ }
+procedure cbox_ctrl.active_color_;
+begin
+ m_active_color:=c^;
+
+end;
+
+{ _COLOR }
+function cbox_ctrl._color;
+begin
+ result:=m_colors[i ];
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/ctrl/agg_ctrl.pas b/src/corelib/render/software/ctrl/agg_ctrl.pas
new file mode 100644
index 00000000..0c8d198e
--- /dev/null
+++ b/src/corelib/render/software/ctrl/agg_ctrl.pas
@@ -0,0 +1,223 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// Function render_ctrl
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 13.12.2005-Milano: Unit port establishment
+//
+{ agg_ctrl.pas }
+unit
+ agg_ctrl ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_trans_affine ,
+ agg_rasterizer_scanline_aa ,
+ agg_scanline ,
+ agg_renderer_scanline ,
+ agg_render_scanlines ,
+ agg_vertex_source ,
+ agg_color ;
+
+{ TYPES DEFINITION }
+type
+ ctrl_ptr = ^ctrl;
+ ctrl = object(vertex_source )
+ m_x1 ,
+ m_y1 ,
+ m_x2 ,
+ m_y2 : double;
+
+ m_flip_y : boolean;
+
+ m_mtx : trans_affine_ptr;
+
+ constructor Construct(x1 ,y1 ,x2 ,y2 : double; flip_y : boolean );
+ destructor Destruct; virtual;
+
+ function in_rect(x ,y : double ) : boolean; virtual;
+
+ function on_mouse_button_down(x ,y : double ) : boolean; virtual;
+ function on_mouse_button_up (x ,y : double ) : boolean; virtual;
+
+ function on_mouse_move(x ,y : double; button_flag : boolean ) : boolean; virtual;
+ function on_arrow_keys(left ,right ,down ,up : boolean ) : boolean; virtual;
+
+ procedure transform(mtx : trans_affine_ptr );
+ procedure no_transform;
+
+ procedure transform_xy(x ,y : double_ptr );
+
+ procedure inverse_transform_xy(x ,y : double_ptr );
+
+ function scale : double;
+
+ function _color(i : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+ procedure render_ctrl(ras : rasterizer_scanline_ptr; sl : scanline_ptr; r : renderer_scanline_ptr; c : ctrl_ptr );
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor ctrl.Construct;
+begin
+ inherited Construct;
+
+ m_x1:=x1;
+ m_y1:=y1;
+ m_x2:=x2;
+ m_y2:=y2;
+
+ m_flip_y:=flip_y;
+
+ m_mtx:=NIL;
+
+end;
+
+{ DESTRUCT }
+destructor ctrl.Destruct;
+begin
+ inherited Destruct;
+
+end;
+
+{ IN_RECT }
+function ctrl.in_rect;
+begin
+ result:=false;
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+function ctrl.on_mouse_button_down;
+begin
+ result:=false;
+
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+function ctrl.on_mouse_button_up;
+begin
+ result:=false;
+
+end;
+
+{ ON_MOUSE_MOVE }
+function ctrl.on_mouse_move;
+begin
+ result:=false;
+
+end;
+
+{ ON_ARROW_KEYS }
+function ctrl.on_arrow_keys;
+begin
+ result:=false;
+
+end;
+
+{ TRANSFORM }
+procedure ctrl.transform;
+begin
+ m_mtx:=mtx;
+
+end;
+
+{ NO_TRANSFORM }
+procedure ctrl.no_transform;
+begin
+ m_mtx:=NIL;
+
+end;
+
+{ TRANSFORM_XY }
+procedure ctrl.transform_xy;
+begin
+ if m_flip_y then
+ y^:=m_y1 + m_y2 - y^;
+
+ if m_mtx <> NIL then
+ m_mtx.transform(m_mtx ,x ,y );
+
+end;
+
+{ INVERSE_TRANSFORM_XY }
+procedure ctrl.inverse_transform_xy;
+begin
+ if m_mtx <> NIL then
+ m_mtx.inverse_transform(m_mtx ,x ,y );
+
+ if m_flip_y then
+ y^:=m_y1 + m_y2 - y^;
+
+end;
+
+{ SCALE }
+function ctrl.scale;
+begin
+ if m_mtx <> NIL then
+ result:=m_mtx.scale
+ else
+ result:=1.0;
+
+end;
+
+{ _COLOR }
+function ctrl._color;
+begin
+ result:=NIL;
+
+end;
+
+{ RENDER_CTRL }
+procedure render_ctrl;
+var
+ i : unsigned;
+
+begin
+ if c.num_paths > 0 then
+ for i:=0 to c.num_paths - 1 do
+ begin
+ ras.reset;
+ ras.add_path(c ,i );
+
+ r.color_(c._color(i ) );
+
+ render_scanlines(ras ,sl ,r );
+
+ end;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/ctrl/agg_gamma_ctrl.pas b/src/corelib/render/software/ctrl/agg_gamma_ctrl.pas
new file mode 100644
index 00000000..da79fdcf
--- /dev/null
+++ b/src/corelib/render/software/ctrl/agg_gamma_ctrl.pas
@@ -0,0 +1,881 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 30.01.2006-Milano: Unit port establishment
+//
+{ agg_gamma_ctrl.pas }
+unit
+ agg_gamma_ctrl ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ SysUtils ,
+ agg_basics ,
+ agg_gamma_spline ,
+ agg_ellipse ,
+ agg_conv_stroke ,
+ agg_gsv_text ,
+ agg_trans_affine ,
+ agg_color ,
+ agg_ctrl ,
+ agg_math ,
+ agg_math_stroke ;
+
+{ TYPES DEFINITION }
+type
+ gamma_ctrl_impl = object(ctrl )
+ m_gamma_spline : gamma_spline;
+
+ m_border_width ,
+ m_border_extra ,
+ m_curve_width ,
+ m_grid_width ,
+ m_text_thickness ,
+ m_point_size ,
+ m_text_height ,
+ m_text_width ,
+
+ m_xc1 ,
+ m_yc1 ,
+ m_xc2 ,
+ m_yc2 ,
+ m_xs1 ,
+ m_ys1 ,
+ m_xs2 ,
+ m_ys2 ,
+ m_xt1 ,
+ m_yt1 ,
+ m_xt2 ,
+ m_yt2 : double;
+
+ m_curve_poly : conv_stroke;
+ m_ellipse : ellipse;
+ m_text : gsv_text;
+ m_text_poly : conv_stroke;
+
+ m_idx ,
+ m_vertex : unsigned;
+
+ m_vx ,
+ m_vy : array[0..31 ] of double;
+
+ m_xp1 ,
+ m_yp1 ,
+ m_xp2 ,
+ m_yp2 : double;
+
+ m_p1_active : boolean;
+ m_mouse_point : unsigned;
+
+ m_pdx ,
+ m_pdy : double;
+
+ constructor Construct(x1 ,y1 ,x2 ,y2 : double; flip_y : boolean = false );
+ destructor Destruct; virtual;
+
+ // Set other parameters
+ procedure border_width_ (t : double; extra : double = 0.0 );
+ procedure curve_width_ (t : double );
+ procedure grid_width_ (t : double );
+ procedure text_thickness_(t : double );
+ procedure text_size_ (h : double; w : double = 0.0 );
+ procedure point_size_ (s : double );
+
+ // Event handlers. Just call them if the respective events
+ // in your system occure. The functions return true if redrawing
+ // is required.
+ function in_rect(x ,y : double ) : boolean; virtual;
+
+ function on_mouse_button_down(x ,y : double ) : boolean; virtual;
+ function on_mouse_button_up (x ,y : double ) : boolean; virtual;
+
+ function on_mouse_move(x ,y : double; button_flag : boolean ) : boolean; virtual;
+ function on_arrow_keys(left ,right ,down ,up : boolean ) : boolean; virtual;
+
+ procedure change_active_point;
+
+ // A copy of gamma_spline interface
+ procedure values(kx1 ,ky1 ,kx2 ,ky2 : double ); overload;
+ procedure values(kx1 ,ky1 ,kx2 ,ky2 : double_ptr ); overload;
+
+ function gamma : char_ptr;
+ function _y(x : double ) : double;
+
+ function func_operator_gamma(x : double ) : double; virtual;
+
+ // Vertex soutce interface
+ function num_paths : unsigned; virtual;
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ // Private
+ procedure calc_spline_box;
+ procedure calc_points;
+ procedure calc_values;
+
+ end;
+
+ gamma_ctrl = object(gamma_ctrl_impl )
+ m_background_color ,
+ m_border_color ,
+ m_curve_color ,
+ m_grid_color ,
+ m_inactive_pnt_color ,
+ m_active_pnt_color ,
+ m_text_color : aggclr;
+
+ m_colors : array[0..6 ] of aggclr_ptr;
+
+ constructor Construct(x1 ,y1 ,x2 ,y2 : double; flip_y : boolean = false );
+
+ procedure background_color_ (c : aggclr_ptr );
+ procedure border_color_ (c : aggclr_ptr );
+ procedure curve_color_ (c : aggclr_ptr );
+ procedure grid_color_ (c : aggclr_ptr );
+ procedure inactive_pnt_color_(c : aggclr_ptr );
+ procedure active_pnt_color_ (c : aggclr_ptr );
+ procedure text_color_ (c : aggclr_ptr );
+
+ function _color(i : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor gamma_ctrl_impl.Construct;
+begin
+ inherited Construct(x1 ,y1 ,x2 ,y2 ,flip_y );
+
+ m_border_width :=2.0;
+ m_border_extra :=0.0;
+ m_curve_width :=2.0;
+ m_grid_width :=0.2;
+ m_text_thickness:=1.5;
+ m_point_size :=5.0;
+ m_text_height :=9.0;
+ m_text_width :=0.0;
+
+ m_xc1:=x1;
+ m_yc1:=y1;
+ m_xc2:=x2;
+ m_yc2:=y2 - m_text_height * 2.0;
+ m_xt1:=x1;
+ m_yt1:=y2 - m_text_height * 2.0;
+ m_xt2:=x2;
+ m_yt2:=y2;
+
+ m_gamma_spline.Construct;
+ m_ellipse.Construct;
+ m_curve_poly.Construct(@m_gamma_spline );
+ m_text.Construct;
+ m_text_poly.Construct (@m_text );
+
+ m_idx :=0;
+ m_vertex:=0;
+
+ m_p1_active :=true;
+ m_mouse_point:=0;
+
+ m_pdx:=0.0;
+ m_pdy:=0.0;
+
+ calc_spline_box;
+
+end;
+
+{ DESTRUCT }
+destructor gamma_ctrl_impl.Destruct;
+begin
+ m_gamma_spline.Destruct;
+ m_curve_poly.Destruct;
+ m_text.Destruct;
+ m_text_poly.Destruct;
+
+end;
+
+{ BORDER_WIDTH_ }
+procedure gamma_ctrl_impl.border_width_;
+begin
+ m_border_width:=t;
+ m_border_extra:=extra;
+
+ calc_spline_box;
+
+end;
+
+{ CURVE_WIDTH_ }
+procedure gamma_ctrl_impl.curve_width_;
+begin
+ m_curve_width:=t;
+
+end;
+
+{ GRID_WIDTH_ }
+procedure gamma_ctrl_impl.grid_width_;
+begin
+ m_grid_width:=t;
+
+end;
+
+{ TEXT_THICKNESS_ }
+procedure gamma_ctrl_impl.text_thickness_;
+begin
+ m_text_thickness:=t;
+
+end;
+
+{ TEXT_SIZE_ }
+procedure gamma_ctrl_impl.text_size_;
+begin
+ m_text_width :=w;
+ m_text_height:=h;
+
+ m_yc2:=m_y2 - m_text_height * 2.0;
+ m_yt1:=m_y2 - m_text_height * 2.0;
+
+ calc_spline_box;
+
+end;
+
+{ POINT_SIZE_ }
+procedure gamma_ctrl_impl.point_size_;
+begin
+ m_point_size:=s;
+
+end;
+
+{ IN_RECT }
+function gamma_ctrl_impl.in_rect;
+begin
+ inverse_transform_xy(@x ,@y );
+
+ result:=
+ (x >= m_x1 ) and
+ (x <= m_x2 ) and
+ (y >= m_y1 ) and
+ (y <= m_y2 );
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+function gamma_ctrl_impl.on_mouse_button_down;
+begin
+ inverse_transform_xy(@x ,@y );
+ calc_points;
+
+ if calc_distance(x ,y ,m_xp1 ,m_yp1 ) <= m_point_size + 1 then
+ begin
+ m_mouse_point:=1;
+
+ m_pdx:=m_xp1 - x;
+ m_pdy:=m_yp1 - y;
+
+ m_p1_active:=true;
+
+ result:=true;
+
+ exit;
+
+ end;
+
+ if calc_distance(x ,y ,m_xp2 ,m_yp2 ) <= m_point_size + 1 then
+ begin
+ m_mouse_point:=2;
+
+ m_pdx:=m_xp2 - x;
+ m_pdy:=m_yp2 - y;
+
+ m_p1_active:=false;
+
+ result:=true;
+
+ exit;
+
+ end;
+
+ result:=false;
+
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+function gamma_ctrl_impl.on_mouse_button_up;
+begin
+ if m_mouse_point <> 0 then
+ begin
+ m_mouse_point:=0;
+
+ result:=true;
+
+ end
+ else
+ result:=false;
+
+end;
+
+{ ON_MOUSE_MOVE }
+function gamma_ctrl_impl.on_mouse_move;
+begin
+ inverse_transform_xy(@x ,@y );
+
+ if not button_flag then
+ result:=on_mouse_button_up(x ,y )
+ else
+ begin
+ if m_mouse_point = 1 then
+ begin
+ m_xp1:=x + m_pdx;
+ m_yp1:=y + m_pdy;
+
+ calc_values;
+
+ result:=true;
+
+ exit;
+
+ end;
+
+ if m_mouse_point = 2 then
+ begin
+ m_xp2:=x + m_pdx;
+ m_yp2:=y + m_pdy;
+
+ calc_values;
+
+ result:=true;
+
+ exit;
+
+ end;
+
+ result:=false;
+
+ end;
+
+end;
+
+{ ON_ARROW_KEYS }
+function gamma_ctrl_impl.on_arrow_keys;
+var
+ kx1 ,ky1 ,kx2 ,ky2 : double;
+
+ ret : boolean;
+
+begin
+ ret:=false;
+
+ m_gamma_spline.values(@kx1 ,@ky1 ,@kx2 ,@ky2 );
+
+ if m_p1_active then
+ begin
+ if left then
+ begin
+ kx1:=kx1 - 0.005;
+ ret:=true;
+
+ end;
+
+ if right then
+ begin
+ kx1:=kx1 + 0.005;
+ ret:=true;
+
+ end;
+
+ if down then
+ begin
+ ky1:=ky1 - 0.005;
+ ret:=true;
+
+ end;
+
+ if up then
+ begin
+ ky1:=ky1 + 0.005;
+ ret:=true;
+
+ end;
+
+ end
+ else
+ begin
+ if left then
+ begin
+ kx2:=kx2 + 0.005;
+ ret:=true;
+
+ end;
+
+ if right then
+ begin
+ kx2:=kx2 - 0.005;
+ ret:=true;
+
+ end;
+
+ if down then
+ begin
+ ky2:=ky2 + 0.005;
+ ret:=true;
+
+ end;
+
+ if up then
+ begin
+ ky2:=ky2 - 0.005;
+ ret:= true;
+
+ end;
+
+ end;
+
+ if ret then
+ m_gamma_spline.values(kx1 ,ky1 ,kx2 ,ky2 );
+
+ result:=ret;
+
+end;
+
+{ CHANGE_ACTIVE_POINT }
+procedure gamma_ctrl_impl.change_active_point;
+begin
+ if m_p1_active then
+ m_p1_active:=false
+ else
+ m_p1_active:=true;
+
+end;
+
+{ VALUES }
+procedure gamma_ctrl_impl.values(kx1 ,ky1 ,kx2 ,ky2 : double );
+begin
+ m_gamma_spline.values(kx1 ,ky1 ,kx2 ,ky2 );
+
+end;
+
+{ VALUES }
+procedure gamma_ctrl_impl.values(kx1 ,ky1 ,kx2 ,ky2 : double_ptr );
+begin
+ m_gamma_spline.values(kx1 ,ky1 ,kx2 ,ky2 );
+
+end;
+
+{ GAMMA }
+function gamma_ctrl_impl.gamma;
+begin
+ result:=m_gamma_spline.gamma;
+
+end;
+
+{ _Y }
+function gamma_ctrl_impl._y;
+begin
+ result:=m_gamma_spline._y(x );
+
+end;
+
+{ FUNC_OPERATOR_GAMMA }
+function gamma_ctrl_impl.func_operator_gamma;
+begin
+ result:=m_gamma_spline._y(x );
+
+end;
+
+{ NUM_PATHS }
+function gamma_ctrl_impl.num_paths;
+begin
+ result:=7;
+
+end;
+
+{ REWIND }
+procedure gamma_ctrl_impl.rewind;
+var
+ kx1 ,ky1 ,kx2 ,ky2 : double;
+
+ tbuf : array[0..31 ] of char;
+
+begin
+ m_idx:=path_id;
+
+ case path_id of
+ 0 : // Background
+ begin
+ m_vertex:=0;
+
+ m_vx[0 ]:=m_x1 - m_border_extra;
+ m_vy[0 ]:=m_y1 - m_border_extra;
+ m_vx[1 ]:=m_x2 + m_border_extra;
+ m_vy[1 ]:=m_y1 - m_border_extra;
+ m_vx[2 ]:=m_x2 + m_border_extra;
+ m_vy[2 ]:=m_y2 + m_border_extra;
+ m_vx[3 ]:=m_x1 - m_border_extra;
+ m_vy[3 ]:=m_y2 + m_border_extra;
+
+ end;
+
+ 1 : // Border
+ begin
+ m_vertex:=0;
+
+ m_vx[0 ]:=m_x1;
+ m_vy[0 ]:=m_y1;
+ m_vx[1 ]:=m_x2;
+ m_vy[1 ]:=m_y1;
+ m_vx[2 ]:=m_x2;
+ m_vy[2 ]:=m_y2;
+ m_vx[3 ]:=m_x1;
+ m_vy[3 ]:=m_y2;
+ m_vx[4 ]:=m_x1 + m_border_width;
+ m_vy[4 ]:=m_y1 + m_border_width;
+ m_vx[5 ]:=m_x1 + m_border_width;
+ m_vy[5 ]:=m_y2 - m_border_width;
+ m_vx[6 ]:=m_x2 - m_border_width;
+ m_vy[6 ]:=m_y2 - m_border_width;
+ m_vx[7 ]:=m_x2 - m_border_width;
+ m_vy[7 ]:=m_y1 + m_border_width;
+ m_vx[8 ]:=m_xc1 + m_border_width;
+ m_vy[8 ]:=m_yc2 - m_border_width * 0.5;
+ m_vx[9 ]:=m_xc2 - m_border_width;
+ m_vy[9 ]:=m_yc2 - m_border_width * 0.5;
+ m_vx[10 ]:=m_xc2 - m_border_width;
+ m_vy[10 ]:=m_yc2 + m_border_width * 0.5;
+ m_vx[11 ]:=m_xc1 + m_border_width;
+ m_vy[11 ]:=m_yc2 + m_border_width * 0.5;
+
+ end;
+
+ 2 : // Curve
+ begin
+ m_gamma_spline.box(m_xs1 ,m_ys1 ,m_xs2 ,m_ys2 );
+
+ m_curve_poly.width_(m_curve_width );
+ m_curve_poly.rewind(0 );
+
+ end;
+
+ 3 : // Grid
+ begin
+ m_vertex:=0;
+
+ m_vx[0 ]:=m_xs1;
+ m_vy[0 ]:=(m_ys1 + m_ys2) * 0.5 - m_grid_width * 0.5;
+ m_vx[1 ]:=m_xs2;
+ m_vy[1 ]:=(m_ys1 + m_ys2) * 0.5 - m_grid_width * 0.5;
+ m_vx[2 ]:=m_xs2;
+ m_vy[2 ]:=(m_ys1 + m_ys2) * 0.5 + m_grid_width * 0.5;
+ m_vx[3 ]:=m_xs1;
+ m_vy[3 ]:=(m_ys1 + m_ys2) * 0.5 + m_grid_width * 0.5;
+ m_vx[4 ]:=(m_xs1 + m_xs2) * 0.5 - m_grid_width * 0.5;
+ m_vy[4 ]:=m_ys1;
+ m_vx[5 ]:=(m_xs1 + m_xs2) * 0.5 - m_grid_width * 0.5;
+ m_vy[5 ]:=m_ys2;
+ m_vx[6 ]:=(m_xs1 + m_xs2) * 0.5 + m_grid_width * 0.5;
+ m_vy[6 ]:=m_ys2;
+ m_vx[7 ]:=(m_xs1 + m_xs2) * 0.5 + m_grid_width * 0.5;
+ m_vy[7 ]:=m_ys1;
+
+ calc_points;
+
+ m_vx[8 ]:=m_xs1;
+ m_vy[8 ]:=m_yp1 - m_grid_width * 0.5;
+ m_vx[9 ]:=m_xp1 - m_grid_width * 0.5;
+ m_vy[9 ]:=m_yp1 - m_grid_width * 0.5;
+ m_vx[10 ]:=m_xp1 - m_grid_width * 0.5;
+ m_vy[10 ]:=m_ys1;
+ m_vx[11 ]:=m_xp1 + m_grid_width * 0.5;
+ m_vy[11 ]:=m_ys1;
+ m_vx[12 ]:=m_xp1 + m_grid_width * 0.5;
+ m_vy[12 ]:=m_yp1 + m_grid_width * 0.5;
+ m_vx[13 ]:=m_xs1;
+ m_vy[13 ]:=m_yp1 + m_grid_width * 0.5;
+ m_vx[14 ]:=m_xs2;
+ m_vy[14 ]:=m_yp2 + m_grid_width * 0.5;
+ m_vx[15 ]:=m_xp2 + m_grid_width * 0.5;
+ m_vy[15 ]:=m_yp2 + m_grid_width * 0.5;
+ m_vx[16 ]:=m_xp2 + m_grid_width * 0.5;
+ m_vy[16 ]:=m_ys2;
+ m_vx[17 ]:=m_xp2 - m_grid_width * 0.5;
+ m_vy[17 ]:=m_ys2;
+ m_vx[18 ]:=m_xp2 - m_grid_width * 0.5;
+ m_vy[18 ]:=m_yp2 - m_grid_width * 0.5;
+ m_vx[19 ]:=m_xs2;
+ m_vy[19 ]:=m_yp2 - m_grid_width * 0.5;
+
+ end;
+
+ 4 : // Point1
+ begin
+ calc_points;
+
+ if m_p1_active then
+ m_ellipse.init(m_xp2 ,m_yp2 ,m_point_size ,m_point_size ,32 )
+ else
+ m_ellipse.init(m_xp1 ,m_yp1 ,m_point_size ,m_point_size ,32 );
+
+ end;
+
+ 5 : // Point2
+ begin
+ calc_points;
+
+ if m_p1_active then
+ m_ellipse.init(m_xp1 ,m_yp1 ,m_point_size ,m_point_size ,32 )
+ else
+ m_ellipse.init(m_xp2 ,m_yp2 ,m_point_size ,m_point_size ,32 );
+
+ end;
+
+ 6 : // Text
+ begin
+ m_gamma_spline.values(@kx1 ,@ky1 ,@kx2 ,@ky2 );
+
+ sprintf(@tbuf[0] , '%.3f '#0 ,kx1 );
+ sprintf(@tbuf[StrLen(@tbuf[0 ] ) ] ,'%.3f '#0 ,ky1 );
+ sprintf(@tbuf[StrLen(@tbuf[0 ] ) ] ,'%.3f '#0 ,kx2 );
+ sprintf(@tbuf[StrLen(@tbuf[0 ] ) ] ,'%.3f'#0 ,ky2 );
+
+ m_text.text_(@tbuf[0 ] );
+ m_text.size_(m_text_height ,m_text_width );
+
+ m_text.start_point_(m_xt1 + m_border_width * 2.0 ,(m_yt1 + m_yt2 ) * 0.5 - m_text_height * 0.5 );
+ m_text_poly.width_(m_text_thickness );
+
+ m_text_poly.line_join_(round_join );
+ m_text_poly.line_cap_ (round_cap );
+
+ m_text_poly.rewind(0);
+
+ end;
+
+ end;
+
+end;
+
+{ VERTEX }
+function gamma_ctrl_impl.vertex;
+var
+ cmd : unsigned;
+
+begin
+ cmd:=path_cmd_line_to;
+
+ case m_idx of
+ 0 :
+ begin
+ if m_vertex = 0 then
+ cmd:=path_cmd_move_to;
+
+ if m_vertex >= 4 then
+ cmd:=path_cmd_stop;
+
+ x^:=m_vx[m_vertex ];
+ y^:=m_vy[m_vertex ];
+
+ inc(m_vertex );
+
+ end;
+
+ 1 :
+ begin
+ if (m_vertex = 0 ) or
+ (m_vertex = 4 ) or
+ (m_vertex = 8 ) then
+ cmd:=path_cmd_move_to;
+
+ if m_vertex >= 12 then
+ cmd:=path_cmd_stop;
+
+ x^:=m_vx[m_vertex ];
+ y^:=m_vy[m_vertex ];
+
+ inc(m_vertex );
+
+ end;
+
+ 2 :
+ cmd:=m_curve_poly.vertex(x ,y );
+
+ 3 :
+ begin
+ if (m_vertex = 0 ) or
+ (m_vertex = 4 ) or
+ (m_vertex = 8 ) or
+ (m_vertex = 14 ) then
+ cmd:=path_cmd_move_to;
+
+ if m_vertex >= 20 then
+ cmd:=path_cmd_stop;
+
+ x^:=m_vx[m_vertex ];
+ y^:=m_vy[m_vertex ];
+
+ inc(m_vertex );
+
+ end;
+
+ 4 ,5 :
+ cmd:=m_ellipse.vertex(x ,y );
+
+ 6 :
+ cmd:=m_text_poly.vertex(x ,y );
+
+ else
+ cmd:=path_cmd_stop;
+
+ end;
+
+ if not is_stop(cmd ) then
+ transform_xy(x ,y );
+
+ result:=cmd;
+
+end;
+
+{ CALC_SPLINE_BOX }
+procedure gamma_ctrl_impl.calc_spline_box;
+begin
+ m_xs1:=m_xc1 + m_border_width;
+ m_ys1:=m_yc1 + m_border_width;
+ m_xs2:=m_xc2 - m_border_width;
+ m_ys2:=m_yc2 - m_border_width * 0.5;
+
+end;
+
+{ CALC_POINTS }
+procedure gamma_ctrl_impl.calc_points;
+var
+ kx1 ,ky1 ,kx2 ,ky2 : double;
+
+begin
+ m_gamma_spline.values(@kx1 ,@ky1 ,@kx2 ,@ky2 );
+
+ m_xp1:=m_xs1 + (m_xs2 - m_xs1 ) * kx1 * 0.25;
+ m_yp1:=m_ys1 + (m_ys2 - m_ys1 ) * ky1 * 0.25;
+ m_xp2:=m_xs2 - (m_xs2 - m_xs1 ) * kx2 * 0.25;
+ m_yp2:=m_ys2 - (m_ys2 - m_ys1 ) * ky2 * 0.25;
+
+end;
+
+{ CALC_VALUES }
+procedure gamma_ctrl_impl.calc_values;
+var
+ kx1 ,ky1 ,kx2 ,ky2 : double;
+
+begin
+ kx1:=(m_xp1 - m_xs1 ) * 4.0 / (m_xs2 - m_xs1 );
+ ky1:=(m_yp1 - m_ys1 ) * 4.0 / (m_ys2 - m_ys1 );
+ kx2:=(m_xs2 - m_xp2 ) * 4.0 / (m_xs2 - m_xs1 );
+ ky2:=(m_ys2 - m_yp2 ) * 4.0 / (m_ys2 - m_ys1 );
+
+ m_gamma_spline.values(kx1 ,ky1 ,kx2 ,ky2 );
+
+end;
+
+{ CONSTRUCT }
+constructor gamma_ctrl.Construct;
+begin
+ inherited Construct(x1 ,y1 ,x2 ,y2 ,flip_y );
+
+ m_background_color.ConstrDbl (1.0 ,1.0 ,0.9 );
+ m_border_color.ConstrDbl (0.0 ,0.0 ,0.0 );
+ m_curve_color.ConstrDbl (0.0 ,0.0 ,0.0 );
+ m_grid_color.ConstrDbl (0.2 ,0.2 ,0.0 );
+ m_inactive_pnt_color.ConstrDbl(0.0 ,0.0 ,0.0 );
+ m_active_pnt_color.ConstrDbl (1.0 ,0.0 ,0.0 );
+ m_text_color.ConstrDbl (0.0 ,0.0 ,0.0 );
+
+ m_colors[0 ]:=@m_background_color;
+ m_colors[1 ]:=@m_border_color;
+ m_colors[2 ]:=@m_curve_color;
+ m_colors[3 ]:=@m_grid_color;
+ m_colors[4 ]:=@m_inactive_pnt_color;
+ m_colors[5 ]:=@m_active_pnt_color;
+ m_colors[6 ]:=@m_text_color;
+
+end;
+
+{ BACKGROUND_COLOR_ }
+procedure gamma_ctrl.background_color_;
+begin
+ m_background_color:=c^;
+
+end;
+
+{ BORDER_COLOR_ }
+procedure gamma_ctrl.border_color_;
+begin
+ m_border_color:=c^;
+
+end;
+
+{ CURVE_COLOR_ }
+procedure gamma_ctrl.curve_color_;
+begin
+ m_curve_color:=c^;
+
+end;
+
+{ GRID_COLOR_ }
+procedure gamma_ctrl.grid_color_;
+begin
+ m_grid_color:=c^;
+
+end;
+
+{ INACTIVE_PNT_COLOR_ }
+procedure gamma_ctrl.inactive_pnt_color_;
+begin
+ m_inactive_pnt_color:=c^;
+
+end;
+
+{ ACTIVE_PNT_COLOR_ }
+procedure gamma_ctrl.active_pnt_color_;
+begin
+ m_active_pnt_color:=c^;
+
+end;
+
+{ TEXT_COLOR_ }
+procedure gamma_ctrl.text_color_;
+begin
+ m_text_color:=c^;
+
+end;
+
+{ _COLOR }
+function gamma_ctrl._color;
+begin
+ result:=m_colors[i ];
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/ctrl/agg_gamma_spline.pas b/src/corelib/render/software/ctrl/agg_gamma_spline.pas
new file mode 100644
index 00000000..7be50692
--- /dev/null
+++ b/src/corelib/render/software/ctrl/agg_gamma_spline.pas
@@ -0,0 +1,265 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 30.01.2006-Milano: Unit port establishment
+//
+{ agg_gamma_spline.pas }
+unit
+ agg_gamma_spline ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_bspline ,
+ agg_vertex_source ;
+
+{ TYPES DEFINITION }
+type
+// Class-helper for calculation gamma-correction arrays. A gamma-correction
+// array is an array of 256 unsigned chars that determine the actual values
+// of Anti-Aliasing for each pixel coverage value from 0 to 255. If all the
+// values in the array are equal to its index, i.e. 0,1,2,3,... there's
+// no gamma-correction. Class agg::polyfill allows you to use custom
+// gamma-correction arrays. You can calculate it using any approach, and
+// class gamma_spline allows you to calculate almost any reasonable shape
+// of the gamma-curve with using only 4 values - kx1, ky1, kx2, ky2.
+//
+// kx2
+// +----------------------------------+
+// | | | . |
+// | | | . | ky2
+// | | . ------|
+// | | . |
+// | | . |
+// |----------------.|----------------|
+// | . | |
+// | . | |
+// |-------. | |
+// ky1 | . | | |
+// | . | | |
+// +----------------------------------+
+// kx1
+//
+// Each value can be in range [0...2]. Value 1.0 means one quarter of the
+// bounding rectangle. Function values() calculates the curve by these
+// 4 values. After calling it one can get the gamma-array with call gamma().
+// Class also supports the vertex source interface, i.e rewind() and
+// vertex(). It's made for convinience and used in class gamma_ctrl.
+// Before calling rewind/vertex one must set the bounding box
+// box() using pixel coordinates.
+ gamma_spline = object(vertex_source )
+ m_gamma : array[0..255 ] of char;
+
+ m_x ,
+ m_y : array[0..3 ] of double;
+ m_x1 ,
+ m_y1 ,
+ m_x2 ,
+ m_y2 ,
+
+ m_cur_x : double;
+ m_spline : bspline;
+
+ constructor Construct;
+ destructor Destruct; virtual;
+
+ procedure values(kx1 ,ky1 ,kx2 ,ky2 : double ); overload;
+ procedure values(kx1 ,ky1 ,kx2 ,ky2 : double_ptr ); overload;
+
+ function gamma : char_ptr;
+ function _y (x : double ) : double;
+ procedure box(x1 ,y1 ,x2 ,y2 : double );
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor gamma_spline.Construct;
+begin
+ m_spline.Construct;
+
+ m_x1:=0;
+ m_y1:=0;
+ m_x2:=10;
+ m_y2:=10;
+
+ m_cur_x:=0.0;
+
+ values(1.0 ,1.0 ,1.0 ,1.0 );
+
+end;
+
+{ DESTRUCT }
+destructor gamma_spline.Destruct;
+begin
+ m_spline.Destruct;
+
+end;
+
+{ VALUES }
+procedure gamma_spline.values(kx1 ,ky1 ,kx2 ,ky2 : double );
+var
+ i : int;
+
+begin
+ if kx1 < 0.001 then
+ kx1:=0.001;
+
+ if kx1 > 1.999 then
+ kx1:=1.999;
+
+ if ky1 < 0.001 then
+ ky1:=0.001;
+
+ if ky1 > 1.999 then
+ ky1:=1.999;
+
+ if kx2 < 0.001 then
+ kx2:=0.001;
+
+ if kx2 > 1.999 then
+ kx2:=1.999;
+
+ if ky2 < 0.001 then
+ ky2:=0.001;
+
+ if ky2 > 1.999 then
+ ky2:=1.999;
+
+ m_x[0 ]:=0.0;
+ m_y[0 ]:=0.0;
+ m_x[1 ]:=kx1 * 0.25;
+ m_y[1 ]:=ky1 * 0.25;
+ m_x[2 ]:=1.0 - kx2 * 0.25;
+ m_y[2 ]:=1.0 - ky2 * 0.25;
+ m_x[3 ]:=1.0;
+ m_y[3 ]:=1.0;
+
+ m_spline.init(4 ,@m_x ,@m_y );
+
+ for i:=0 to 255 do
+ m_gamma[i ]:=char(trunc(_y(i / 255.0 ) * 255.0 ) );
+
+end;
+
+{ VALUES }
+procedure gamma_spline.values(kx1 ,ky1 ,kx2 ,ky2 : double_ptr );
+begin
+ kx1^:=m_x[1 ] * 4.0;
+ ky1^:=m_y[1 ] * 4.0;
+ kx2^:=(1.0 - m_x[2 ] ) * 4.0;
+ ky2^:=(1.0 - m_y[2 ] ) * 4.0;
+
+end;
+
+{ GAMMA }
+function gamma_spline.gamma;
+begin
+ result:=@m_gamma[0 ];
+
+end;
+
+{ _Y }
+function gamma_spline._y;
+var
+ val : double;
+
+begin
+ if x < 0.0 then
+ x:=0.0;
+
+ if x > 1.0 then
+ x:=1.0;
+
+ val:=m_spline.get(x );
+
+ if val < 0.0 then
+ val:=0.0;
+
+ if val > 1.0 then
+ val:=1.0;
+
+ result:=val;
+
+end;
+
+{ BOX }
+procedure gamma_spline.box;
+begin
+ m_x1:=x1;
+ m_y1:=y1;
+ m_x2:=x2;
+ m_y2:=y2;
+
+end;
+
+{ REWIND }
+procedure gamma_spline.rewind;
+begin
+ m_cur_x:=0.0;
+
+end;
+
+{ VERTEX }
+function gamma_spline.vertex;
+begin
+ if m_cur_x = 0.0 then
+ begin
+ x^:=m_x1;
+ y^:=m_y1;
+
+ m_cur_x:=m_cur_x + (1.0 / (m_x2 - m_x1 ) );
+ result :=path_cmd_move_to;
+
+ exit;
+
+ end;
+
+ if m_cur_x > 1.0 then
+ begin
+ result:=path_cmd_stop;
+
+ exit;
+
+ end;
+
+ x^:=m_x1 + m_cur_x * (m_x2 - m_x1 );
+ y^:=m_y1 + _y(m_cur_x ) * (m_y2 - m_y1 );
+
+ m_cur_x:=m_cur_x + (1.0 / (m_x2 - m_x1 ) );
+ result :=path_cmd_line_to;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/ctrl/agg_polygon_ctrl.pas b/src/corelib/render/software/ctrl/agg_polygon_ctrl.pas
new file mode 100644
index 00000000..881c9d60
--- /dev/null
+++ b/src/corelib/render/software/ctrl/agg_polygon_ctrl.pas
@@ -0,0 +1,769 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 23.02.2006-Milano: Unit port establishment
+//
+{ agg_polygon_ctrl.pas }
+unit
+ agg_polygon_ctrl ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ Math ,
+ agg_basics ,
+ agg_conv_stroke ,
+ agg_ellipse ,
+ agg_color ,
+ agg_ctrl ,
+ agg_vertex_source ;
+
+{ TYPES DEFINITION }
+type
+ simple_polygon_vertex_source = object(vertex_source )
+ m_polygon : double_ptr;
+ m_num_points ,
+ m_vertex : unsigned;
+ m_roundoff ,
+ m_close : boolean;
+
+ constructor Construct(polygon : double_ptr; np : unsigned; roundoff : boolean = false; close : boolean = true );
+
+ procedure close_(f : boolean );
+ function _close : boolean;
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ end;
+
+ polygon_ctrl_impl = object(ctrl )
+ m_polygon : double_ptr;
+ m_num_points : unsigned;
+
+ m_node ,
+ m_edge : int;
+
+ m_vs : simple_polygon_vertex_source;
+ m_stroke : conv_stroke;
+
+ m_ellipse : ellipse;
+ m_point_radius : double;
+ m_status : unsigned;
+
+ m_dx ,
+ m_dy : double;
+
+ m_in_polygon_check : boolean;
+
+ constructor Construct(np : unsigned; point_radius : double = 5 );
+ destructor Destruct; virtual;
+
+ function _num_points : unsigned;
+
+ function _xn(n : unsigned ) : double;
+ function _yn(n : unsigned ) : double;
+
+ function xn_ptr(n : unsigned ) : double_ptr;
+ function yn_ptr(n : unsigned ) : double_ptr;
+
+ function _polygon : double_ptr;
+
+ procedure line_width_(w : double );
+ function _line_width : double;
+
+ procedure point_radius_(r : double );
+ function _point_radius : double;
+
+ procedure in_polygon_check_(f : boolean );
+ function _in_polygon_check : boolean;
+
+ procedure close_(f : boolean );
+ function _close : boolean;
+
+ // Vertex source interface
+ function num_paths : unsigned; virtual;
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ // Event handlers
+ function in_rect(x ,y : double ) : boolean; virtual;
+
+ function on_mouse_button_down(x ,y : double ) : boolean; virtual;
+ function on_mouse_button_up (x ,y : double ) : boolean; virtual;
+
+ function on_mouse_move(x ,y : double; button_flag : boolean ) : boolean; virtual;
+ function on_arrow_keys(left ,right ,down ,up : boolean ) : boolean; virtual;
+
+ // Private
+ function check_edge (i : unsigned; x ,y : double ) : boolean;
+ function point_in_polygon(x ,y : double ) : boolean;
+
+ end;
+
+ polygon_ctrl = object(polygon_ctrl_impl )
+ m_color : aggclr;
+
+ constructor Construct(np : unsigned; point_radius : double = 5 );
+
+ procedure line_color_(c : aggclr_ptr );
+
+ function _color(i : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor simple_polygon_vertex_source.Construct;
+begin
+ m_polygon :=polygon;
+ m_num_points:=np;
+ m_vertex :=0;
+ m_roundoff :=roundoff;
+ m_close :=close;
+
+end;
+
+{ CLOSE_ }
+procedure simple_polygon_vertex_source.close_;
+begin
+ m_close:=f;
+
+end;
+
+{ _CLOSE }
+function simple_polygon_vertex_source._close;
+begin
+ result:=m_close;
+
+end;
+
+{ REWIND }
+procedure simple_polygon_vertex_source.rewind;
+begin
+ m_vertex:=0;
+
+end;
+
+{ VERTEX }
+function simple_polygon_vertex_source.vertex;
+begin
+ if m_vertex > m_num_points then
+ begin
+ result:=path_cmd_stop;
+
+ exit;
+
+ end;
+
+ if m_vertex = m_num_points then
+ begin
+ inc(m_vertex );
+
+ if m_close then
+ result:=path_cmd_end_poly or path_flags_close
+ else
+ result:=path_cmd_end_poly or 0;
+
+ exit;
+
+ end;
+
+ x^:=double_ptr(ptrcomp(m_polygon ) + (m_vertex * 2 ) * sizeof(double ) )^;
+ y^:=double_ptr(ptrcomp(m_polygon ) + (m_vertex * 2 + 1 ) * sizeof(double ) )^;
+
+ if m_roundoff then
+ begin
+ x^:=Floor(x^ ) + 0.5;
+ y^:=Floor(y^ ) + 0.5;
+
+ end;
+
+ inc(m_vertex );
+
+ if m_vertex = 1 then
+ result:=path_cmd_move_to
+ else
+ result:=path_cmd_line_to;
+
+end;
+
+{ CONSTRUCT }
+constructor polygon_ctrl_impl.Construct;
+begin
+ inherited Construct(0 ,0 ,1 ,1 ,false );
+
+ agg_getmem(pointer(m_polygon ) ,np * 2 * sizeof(double ) );
+
+ m_num_points:=np;
+
+ m_node:=-1;
+ m_edge:=-1;
+
+ m_vs.Construct (m_polygon ,m_num_points ,false );
+ m_stroke.Construct(@m_vs );
+ m_ellipse.Construct;
+
+ m_point_radius:=point_radius;
+
+ m_status:=0;
+
+ m_dx:=0.0;
+ m_dy:=0.0;
+
+ m_in_polygon_check:=false;
+
+ m_stroke.width_(1.0 );
+
+end;
+
+{ DESTRUCT }
+destructor polygon_ctrl_impl.Destruct;
+begin
+ agg_freemem(pointer(m_polygon ) ,m_num_points * 2 * sizeof(double ) );
+
+ m_stroke.Destruct;
+
+end;
+
+{ _NUM_POINTS }
+function polygon_ctrl_impl._num_points;
+begin
+ result:=m_num_points;
+
+end;
+
+{ _XN }
+function polygon_ctrl_impl._xn;
+begin
+ result:=double_ptr(ptrcomp(m_polygon ) + (n * 2 ) * sizeof(double ) )^;
+
+end;
+
+{ _YN }
+function polygon_ctrl_impl._yn;
+begin
+ result:=double_ptr(ptrcomp(m_polygon ) + (n * 2 + 1 ) * sizeof(double ) )^;
+
+end;
+
+{ XN_PTR }
+function polygon_ctrl_impl.xn_ptr;
+begin
+ result:=double_ptr(ptrcomp(m_polygon ) + (n * 2 ) * sizeof(double ) );
+
+end;
+
+{ YN_PTR }
+function polygon_ctrl_impl.yn_ptr;
+begin
+ result:=double_ptr(ptrcomp(m_polygon ) + (n * 2 + 1 ) * sizeof(double ) );
+
+end;
+
+{ _POLYGON }
+function polygon_ctrl_impl._polygon;
+begin
+ result:=m_polygon;
+
+end;
+
+{ LINE_WIDTH_ }
+procedure polygon_ctrl_impl.line_width_;
+begin
+ m_stroke.width_(w );
+
+end;
+
+{ _LINE_WIDTH }
+function polygon_ctrl_impl._line_width;
+begin
+ result:=m_stroke._width;
+
+end;
+
+{ POINT_RADIUS_ }
+procedure polygon_ctrl_impl.point_radius_;
+begin
+ m_point_radius:=r;
+
+end;
+
+{ _POINT_RADIUS }
+function polygon_ctrl_impl._point_radius;
+begin
+ result:=m_point_radius;
+
+end;
+
+{ IN_POLYGON_CHECK_ }
+procedure polygon_ctrl_impl.in_polygon_check_;
+begin
+ m_in_polygon_check:=f;
+
+end;
+
+{ _IN_POLYGON_CHECK }
+function polygon_ctrl_impl._in_polygon_check;
+begin
+ result:=m_in_polygon_check;
+
+end;
+
+{ CLOSE_ }
+procedure polygon_ctrl_impl.close_;
+begin
+ m_vs.close_(f );
+
+end;
+
+{ _CLOSE }
+function polygon_ctrl_impl._close;
+begin
+ result:=m_vs._close;
+
+end;
+
+{ NUM_PATHS }
+function polygon_ctrl_impl.num_paths;
+begin
+ result:=1;
+
+end;
+
+{ REWIND }
+procedure polygon_ctrl_impl.rewind;
+begin
+ m_status:=0;
+
+ m_stroke.rewind(0 );
+
+end;
+
+{ VERTEX }
+function polygon_ctrl_impl.vertex;
+var
+ cmd : unsigned;
+ r : double;
+
+begin
+ cmd:=path_cmd_stop;
+ r :=m_point_radius;
+
+ if m_status = 0 then
+ begin
+ cmd:=m_stroke.vertex(x ,y );
+
+ if not is_stop(cmd ) then
+ begin
+ transform_xy(x ,y );
+
+ result:=cmd;
+
+ exit;
+
+ end;
+
+ if (m_node >= 0 ) and
+ (m_node = m_status ) then
+ r:=r * 1.2;
+
+ m_ellipse.init(_xn(m_status ) ,_yn(m_status ) ,r ,r ,32 );
+
+ inc(m_status );
+
+ end;
+
+ cmd:=m_ellipse.vertex(x ,y );
+
+ if not is_stop(cmd ) then
+ begin
+ transform_xy(x ,y );
+
+ result:=cmd;
+
+ exit;
+
+ end;
+
+ if m_status >= m_num_points then
+ begin
+ result:=path_cmd_stop;
+
+ exit;
+
+ end;
+
+ if (m_node >= 0 ) and
+ (m_node = m_status ) then
+ r:=r * 1.2;
+
+ m_ellipse.init(_xn(m_status ) ,_yn(m_status ) ,r ,r ,32 );
+
+ inc(m_status );
+
+ cmd:=m_ellipse.vertex(x ,y );
+
+ if not is_stop(cmd ) then
+ transform_xy(x ,y );
+
+ result:=cmd;
+
+end;
+
+{ IN_RECT }
+function polygon_ctrl_impl.in_rect;
+begin
+ result:=false;
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+function polygon_ctrl_impl.on_mouse_button_down;
+var
+ i : unsigned;
+ ret : boolean;
+
+begin
+ ret:=false;
+
+ m_node:=-1;
+ m_edge:=-1;
+
+ inverse_transform_xy(@x ,@y );
+
+ for i:=0 to m_num_points - 1 do
+ if Sqrt((x - _xn(i ) ) * (x - _xn(i ) ) + (y - _yn(i ) ) * (y - _yn(i ) ) ) < m_point_radius then
+ begin
+ m_dx :=x - _xn(i );
+ m_dy :=y - _yn(i );
+ m_node:=i;
+ ret :=true;
+
+ break;
+
+ end;
+
+ if not ret then
+ for i:=0 to m_num_points - 1 do
+ if check_edge(i ,x ,y ) then
+ begin
+ m_dx :=x;
+ m_dy :=y;
+ m_edge:=i;
+ ret :=true;
+
+ break;
+
+ end;
+
+ if not ret then
+ if point_in_polygon(x ,y ) then
+ begin
+ m_dx :=x;
+ m_dy :=y;
+ m_node:=m_num_points;
+ ret :=true;
+
+ end;
+
+ result:=ret;
+
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+function polygon_ctrl_impl.on_mouse_button_up;
+var
+ ret : boolean;
+
+begin
+ ret :=(m_node >= 0 ) or (m_edge >= 0 );
+ m_node:=-1;
+ m_edge:=-1;
+ result:=ret;
+
+end;
+
+{ ON_MOUSE_MOVE }
+function polygon_ctrl_impl.on_mouse_move;
+var
+ ret : boolean;
+
+ i ,n1 ,n2 : unsigned;
+
+ dx ,dy : double;
+
+begin
+ ret:=false;
+
+ inverse_transform_xy(@x ,@y );
+
+ if m_node = m_num_points then
+ begin
+ dx:=x - m_dx;
+ dy:=y - m_dy;
+
+ for i:=0 to m_num_points - 1 do
+ begin
+ xn_ptr(i )^:=_xn(i ) + dx;
+ yn_ptr(i )^:=_yn(i ) + dy;
+
+ end;
+
+ m_dx:=x;
+ m_dy:=y;
+ ret :=true;
+
+ end
+ else
+ if m_edge >= 0 then
+ begin
+ n1:=m_edge;
+ n2:=(n1 + m_num_points - 1 ) mod m_num_points;
+ dx:=x - m_dx;
+ dy:=y - m_dy;
+
+ xn_ptr(n1 )^:=_xn(n1 ) + dx;
+ yn_ptr(n1 )^:=_yn(n1 ) + dy;
+ xn_ptr(n2 )^:=_xn(n2 ) + dx;
+ yn_ptr(n2 )^:=_yn(n2 ) + dy;
+
+ m_dx:=x;
+ m_dy:=y;
+ ret :=true;
+
+ end
+ else
+ if m_node >= 0 then
+ begin
+ xn_ptr(m_node )^:=x - m_dx;
+ yn_ptr(m_node )^:=y - m_dy;
+
+ ret:=true;
+
+ end;
+
+ result:=ret;
+
+end;
+
+{ ON_ARROW_KEYS }
+function polygon_ctrl_impl.on_arrow_keys;
+begin
+ result:=false;
+
+end;
+
+{ CHECK_EDGE }
+function polygon_ctrl_impl.check_edge;
+var
+ ret : boolean;
+
+ n1 ,n2 : unsigned;
+
+ x1 ,y1 ,x2 ,y2 ,dx ,dy ,x3 ,y3 ,x4 ,y4 ,den ,u1 ,xi ,yi : double;
+
+begin
+ ret:=false;
+
+ n1:=i;
+ n2:=(i + m_num_points - 1 ) mod m_num_points;
+ x1:=_xn(n1 );
+ y1:=_yn(n1 );
+ x2:=_xn(n2 );
+ y2:=_yn(n2 );
+
+ dx:=x2 - x1;
+ dy:=y2 - y1;
+
+ if Sqrt(dx * dx + dy * dy ) > 0.0000001 then
+ begin
+ x3:=x;
+ y3:=y;
+ x4:=x3 - dy;
+ y4:=y3 + dx;
+
+ den:=(y4 - y3 ) * (x2 - x1 ) - (x4 - x3 ) * (y2 - y1 );
+ u1 :=((x4 - x3 ) * (y1 - y3 ) - (y4 - y3 ) * (x1 - x3 ) ) / den;
+
+ xi:=x1 + u1 * (x2 - x1 );
+ yi:=y1 + u1 * (y2 - y1 );
+
+ dx:=xi - x;
+ dy:=yi - y;
+
+ if (u1 > 0.0 ) and
+ (u1 < 1.0 ) and
+ (Sqrt(dx * dx + dy * dy ) <= m_point_radius ) then
+ ret:=true;
+
+ end;
+
+ result:=ret;
+
+end;
+
+{ POINT_IN_POLYGON }
+//======= Crossings Multiply algorithm of InsideTest ========================
+//
+// By Eric Haines, 3D/Eye Inc, erich@eye.com
+//
+// This version is usually somewhat faster than the original published in
+// Graphics Gems IV; by turning the division for testing the X axis crossing
+// into a tricky multiplication test this part of the test became faster,
+// which had the additional effect of making the test for "both to left or
+// both to right" a bit slower for triangles than simply computing the
+// intersection each time. The main increase is in triangle testing speed,
+// which was about 15% faster; all other polygon complexities were pretty much
+// the same as before. On machines where division is very expensive (not the
+// case on the HP 9000 series on which I tested) this test should be much
+// faster overall than the old code. Your mileage may (in fact, will) vary,
+// depending on the machine and the test data, but in general I believe this
+// code is both shorter and faster. This test was inspired by unpublished
+// Graphics Gems submitted by Joseph Samosky and Mark Haigh-Hutchinson.
+// Related work by Samosky is in:
+//
+// Samosky, Joseph, "SectionView: A system for interactively specifying and
+// visualizing sections through three-dimensional medical image data",
+// M.S. Thesis, Department of Electrical Engineering and Computer Science,
+// Massachusetts Institute of Technology, 1993.
+//
+// Shoot a test ray along +X axis. The strategy is to compare vertex Y values
+// to the testing point's Y and quickly discard edges which are entirely to one
+// side of the test ray. Note that CONVEX and WINDING code can be added as
+// for the CrossingsTest() code; it is left out here for clarity.
+//
+// Input 2D polygon _pgon_ with _numverts_ number of vertices and test point
+// _point_, returns 1 if inside, 0 if outside.
+function polygon_ctrl_impl.point_in_polygon;
+var
+ j ,k : unsigned;
+
+ yflag0 ,yflag1 ,inside_flag : int;
+
+ vtx0 ,vty0 ,vtx1 ,vty1 : double;
+
+begin
+ if m_num_points < 3 then
+ begin
+ result:=false;
+
+ exit;
+
+ end;
+
+ if not m_in_polygon_check then
+ begin
+ result:=false;
+
+ exit;
+
+ end;
+
+ vtx0:=_xn(m_num_points - 1 );
+ vty0:=_yn(m_num_points - 1 );
+
+// get test bit for above/below X axis
+ yflag0:=int(vty0 >= y);
+
+ vtx1:=_xn(0 );
+ vty1:=_yn(0 );
+
+ inside_flag:=0;
+
+ for j:=1 to m_num_points do
+ begin
+ yflag1:=int(vty1 >= y );
+
+ // Check if endpoints straddle (are on opposite sides) of X axis
+ // (i.e. the Y's differ); if so, +X ray could intersect this edge.
+ // The old test also checked whether the endpoints are both to the
+ // right or to the left of the test point. However, given the faster
+ // intersection point computation used below, this test was found to
+ // be a break-even proposition for most polygons and a loser for
+ // triangles (where 50% or more of the edges which survive this test
+ // will cross quadrants and so have to have the X intersection computed
+ // anyway). I credit Joseph Samosky with inspiring me to try dropping
+ // the "both left or both right" part of my code.
+ if yflag0 <> yflag1 then
+ // Check intersection of pgon segment with +X ray.
+ // Note if >= point's X; if so, the ray hits it.
+ // The division operation is avoided for the ">=" test by checking
+ // the sign of the first vertex wrto the test point; idea inspired
+ // by Joseph Samosky's and Mark Haigh-Hutchinson's different
+ // polygon inclusion tests.
+ if int((vty1 - y ) * (vtx0 - vtx1 ) >=
+ (vtx1 - x ) * (vty0 - vty1 ) ) = yflag1 then
+ inside_flag:=inside_flag xor 1;
+
+ // Move to the next pair of vertices, retaining info as possible.
+ yflag0:=yflag1;
+ vtx0 :=vtx1;
+ vty0 :=vty1;
+
+ if j >= m_num_points then
+ k:=j - m_num_points
+ else
+ k:=j;
+
+ vtx1:=_xn(k );
+ vty1:=_yn(k );
+
+ end;
+
+ result:=inside_flag <> 0;
+
+end;
+
+{ CONSTRUCT }
+constructor polygon_ctrl.Construct;
+begin
+ inherited Construct(np ,point_radius );
+
+ m_color.ConstrDbl(0.0 ,0.0 ,0.0 );
+
+end;
+
+{ LINE_COLOR_ }
+procedure polygon_ctrl.line_color_;
+begin
+ m_color:=c^;
+
+end;
+
+{ _COLOR }
+function polygon_ctrl._color;
+begin
+ result:=@m_color;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/ctrl/agg_rbox_ctrl.pas b/src/corelib/render/software/ctrl/agg_rbox_ctrl.pas
new file mode 100644
index 00000000..4b445138
--- /dev/null
+++ b/src/corelib/render/software/ctrl/agg_rbox_ctrl.pas
@@ -0,0 +1,621 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 19.01.2006-Milano: Unit port establishment
+//
+{ agg_rbox_ctrl.pas }
+unit
+ agg_rbox_ctrl ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ SysUtils ,
+ agg_basics ,
+ agg_ctrl ,
+ agg_conv_stroke ,
+ agg_gsv_text ,
+ agg_color ,
+ agg_ellipse ,
+ agg_math ,
+ agg_math_stroke ;
+
+{ TYPES DEFINITION }
+type
+ rbox_ctrl_impl = object(ctrl )
+ m_border_width ,
+ m_border_extra ,
+ m_text_thickness ,
+ m_text_height ,
+ m_text_width : double;
+
+ m_items : array[0..31 ] of char_ptr;
+ m_sizes : array[0..31 ] of int8u;
+
+ m_num_items : unsigned;
+ m_cur_item : int;
+
+ m_xs1 ,
+ m_ys1 ,
+ m_xs2 ,
+ m_ys2 ,
+ m_dy : double;
+
+ m_vx ,
+ m_vy : array[0..31 ] of double;
+
+ m_draw_item : unsigned;
+
+ m_ellipse : ellipse;
+ m_ellipse_poly : conv_stroke;
+ m_text : gsv_text;
+ m_text_poly : conv_stroke;
+
+ m_idx ,
+ m_vertex : unsigned;
+
+ constructor Construct(x1 ,y1 ,x2 ,y2 : double; flip_y_ : boolean = false );
+ destructor Destruct; virtual;
+
+ procedure border_width_ (t : double; extra : double = 0.0 );
+ procedure text_thickness_(t : double );
+ procedure text_size_ (h : double; w : double = 0.0 );
+
+ procedure add_item (text : PChar );
+ function _cur_item : int;
+ procedure cur_item_(i : int );
+
+ function in_rect(x ,y : double ) : boolean; virtual;
+
+ function on_mouse_button_down(x ,y : double ) : boolean; virtual;
+ function on_mouse_button_up (x ,y : double ) : boolean; virtual;
+
+ function on_mouse_move(x ,y : double; button_flag : boolean ) : boolean; virtual;
+ function on_arrow_keys(left ,right ,down ,up : boolean ) : boolean; virtual;
+
+ // Vertex source interface
+ function num_paths : unsigned; virtual;
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ procedure calc_rbox;
+
+ end;
+
+ rbox_ctrl_ptr = ^rbox_ctrl;
+ rbox_ctrl = object(rbox_ctrl_impl )
+ m_background_color ,
+ m_border_color ,
+ m_text_color ,
+ m_inactive_color ,
+ m_active_color : aggclr;
+
+ m_colors : array[0..4 ] of aggclr_ptr;
+
+ constructor Construct(x1 ,y1 ,x2 ,y2 : double; flip_y_ : boolean = false );
+
+ procedure background_color_(c : aggclr_ptr );
+ procedure border_color_ (c : aggclr_ptr );
+ procedure text_color_ (c : aggclr_ptr );
+ procedure inactive_color_ (c : aggclr_ptr );
+ procedure active_color_ (c : aggclr_ptr );
+
+ function _color(i : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor rbox_ctrl_impl.Construct;
+begin
+ inherited Construct(x1 ,y1 ,x2 ,y2 ,flip_y_ );
+
+ m_ellipse.Construct;
+ m_text.Construct;
+
+ m_ellipse_poly.Construct(@m_ellipse );
+ m_text_poly.Construct (@m_text );
+
+ m_border_width :=1.0;
+ m_border_extra :=0.0;
+ m_text_thickness:=1.5;
+ m_text_height :=9.0;
+ m_text_width :=0.0;
+
+ m_num_items:=0;
+ m_cur_item :=-1;
+
+ m_idx :=0;
+ m_vertex:=0;
+
+ calc_rbox;
+
+end;
+
+{ DESTRUCT }
+destructor rbox_ctrl_impl.Destruct;
+begin
+ m_ellipse_poly.Destruct;
+ m_text_poly.Destruct;
+
+ m_text.Destruct;
+
+ while m_num_items > 0 do
+ begin
+ agg_freemem(p32(m_items[m_num_items - 1 ] ).ptr ,m_sizes[m_num_items - 1 ] );
+
+ dec(m_num_items );
+
+ end;
+
+end;
+
+{ BORDER_WIDTH_ }
+procedure rbox_ctrl_impl.border_width_;
+begin
+ m_border_width:=t;
+ m_border_extra:=extra;
+
+ calc_rbox;
+
+end;
+
+{ TEXT_THICKNESS_ }
+procedure rbox_ctrl_impl.text_thickness_;
+begin
+ m_text_thickness:=t;
+
+end;
+
+{ TEXT_SIZE_ }
+procedure rbox_ctrl_impl.text_size_;
+begin
+ m_text_width :=w;
+ m_text_height:=h;
+
+end;
+
+{ ADD_ITEM }
+procedure rbox_ctrl_impl.add_item;
+begin
+ if m_num_items < 32 then
+ begin
+ if StrLen(text ) > 255 then
+ m_sizes[m_num_items ]:=255
+ else
+ m_sizes[m_num_items ]:=StrLen(text ) + 1;
+
+ agg_getmem(p32(m_items[m_num_items ] ).ptr ,m_sizes[m_num_items ] );
+
+ fillchar(p32(m_items[m_num_items ] ).ptr^ ,m_sizes[m_num_items ] ,0 );
+ move (text^ ,p32(m_items[m_num_items ] ).ptr^ ,m_sizes[m_num_items ] - 1 );
+
+ inc(m_num_items );
+
+ end;
+
+end;
+
+{ _CUR_ITEM }
+function rbox_ctrl_impl._cur_item;
+begin
+ result:=m_cur_item;
+
+end;
+
+{ CUR_ITEM_ }
+procedure rbox_ctrl_impl.cur_item_;
+begin
+ m_cur_item:=i;
+
+end;
+
+{ IN_RECT }
+function rbox_ctrl_impl.in_rect;
+begin
+ inverse_transform_xy(@x ,@y );
+
+ result:=
+ (x >= m_x1 ) and
+ (x <= m_x2 ) and
+ (y >= m_y1 ) and
+ (y <= m_y2 );
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+function rbox_ctrl_impl.on_mouse_button_down;
+var
+ i : unsigned;
+
+ xp ,yp : double;
+
+begin
+ inverse_transform_xy(@x ,@y );
+
+ for i:=0 to m_num_items - 1 do
+ begin
+ xp:=m_xs1 + m_dy / 1.3;
+ yp:=m_ys1 + m_dy * i + m_dy / 1.3;
+
+ if calc_distance(x ,y ,xp ,yp ) <= m_text_height / 1.5 then
+ begin
+ m_cur_item:=i;
+
+ result:=true;
+
+ exit;
+
+ end;
+
+ end;
+
+ result:=false;
+
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+function rbox_ctrl_impl.on_mouse_button_up;
+begin
+ result:=false;
+
+end;
+
+{ ON_MOUSE_MOVE }
+function rbox_ctrl_impl.on_mouse_move;
+begin
+ result:=false;
+
+end;
+
+{ ON_ARROW_KEYS }
+function rbox_ctrl_impl.on_arrow_keys;
+begin
+ if m_cur_item >= 0 then
+ begin
+ if up or right then
+ begin
+ inc(m_cur_item );
+
+ if m_cur_item >= m_num_items then
+ m_cur_item:=0;
+
+ result:=true;
+
+ exit;
+
+ end;
+
+ if down or left then
+ begin
+ dec(m_cur_item );
+
+ if m_cur_item < 0 then
+ m_cur_item:=m_num_items - 1;
+
+ result:=true;
+
+ exit;
+
+ end;
+
+ end;
+
+ result:=false;
+
+end;
+
+{ NUM_PATHS }
+function rbox_ctrl_impl.num_paths;
+begin
+ result:=5;
+
+end;
+
+{ REWIND }
+procedure rbox_ctrl_impl.rewind;
+begin
+ m_idx:=path_id;
+ m_dy :=m_text_height * 2.0;
+
+ m_draw_item:=0;
+
+ case path_id of
+ 0 : // Background
+ begin
+ m_vertex:=0;
+
+ m_vx[0 ]:=m_x1 - m_border_extra;
+ m_vy[0 ]:=m_y1 - m_border_extra;
+ m_vx[1 ]:=m_x2 + m_border_extra;
+ m_vy[1 ]:=m_y1 - m_border_extra;
+ m_vx[2 ]:=m_x2 + m_border_extra;
+ m_vy[2 ]:=m_y2 + m_border_extra;
+ m_vx[3 ]:=m_x1 - m_border_extra;
+ m_vy[3 ]:=m_y2 + m_border_extra;
+
+ end;
+
+ 1 : // Border
+ begin
+ m_vertex:=0;
+
+ m_vx[0 ]:=m_x1;
+ m_vy[0 ]:=m_y1;
+ m_vx[1 ]:=m_x2;
+ m_vy[1 ]:=m_y1;
+ m_vx[2 ]:=m_x2;
+ m_vy[2 ]:=m_y2;
+ m_vx[3 ]:=m_x1;
+ m_vy[3 ]:=m_y2;
+ m_vx[4 ]:=m_x1 + m_border_width;
+ m_vy[4 ]:=m_y1 + m_border_width;
+ m_vx[5 ]:=m_x1 + m_border_width;
+ m_vy[5 ]:=m_y2 - m_border_width;
+ m_vx[6 ]:=m_x2 - m_border_width;
+ m_vy[6 ]:=m_y2 - m_border_width;
+ m_vx[7 ]:=m_x2 - m_border_width;
+ m_vy[7 ]:=m_y1 + m_border_width;
+
+ end;
+
+ 2 : // Text
+ begin
+ m_text.text_ (pointer(m_items[0 ] ) );
+ m_text.start_point_(m_xs1 + m_dy * 1.5 ,m_ys1 + m_dy / 2.0 );
+ m_text.size_ (m_text_height ,m_text_width );
+
+ m_text_poly.width_ (m_text_thickness);
+ m_text_poly.line_join_(round_join );
+ m_text_poly.line_cap_ (round_cap );
+
+ m_text_poly.rewind(0 );
+
+ end;
+
+ 3 : // Inactive items
+ begin
+ m_ellipse.init(
+ m_xs1 + m_dy / 1.3 ,
+ m_ys1 + m_dy / 1.3 ,
+ m_text_height / 1.5 ,
+ m_text_height / 1.5 ,32 );
+
+ m_ellipse_poly.width_(m_text_thickness );
+ m_ellipse_poly.rewind(0 );
+
+ end;
+
+ 4 : // Active Item
+ if m_cur_item >= 0 then
+ begin
+ m_ellipse.init(
+ m_xs1 + m_dy / 1.3 ,
+ m_ys1 + m_dy * m_cur_item + m_dy / 1.3 ,
+ m_text_height / 2.0 ,
+ m_text_height / 2.0 ,32 );
+
+ m_ellipse.rewind(0 );
+
+ end;
+
+ end;
+
+end;
+
+{ VERTEX }
+function rbox_ctrl_impl.vertex;
+var
+ cmd : unsigned;
+
+label
+ _Esc ;
+
+begin
+ cmd:=path_cmd_line_to;
+
+ case m_idx of
+ 0 :
+ begin
+ if m_vertex = 0 then
+ cmd:=path_cmd_move_to;
+
+ if m_vertex >= 4 then
+ cmd:=path_cmd_stop;
+
+ x^:=m_vx[m_vertex ];
+ y^:=m_vy[m_vertex ];
+
+ inc(m_vertex );
+
+ end;
+
+ 1 :
+ begin
+ if (m_vertex = 0 ) or
+ (m_vertex = 4 ) then
+ cmd:=path_cmd_move_to;
+
+ if m_vertex >= 8 then
+ cmd:=path_cmd_stop;
+
+ x^:=m_vx[m_vertex ];
+ y^:=m_vy[m_vertex ];
+
+ inc(m_vertex );
+
+ end;
+
+ 2 :
+ begin
+ cmd:=m_text_poly.vertex(x ,y );
+
+ if is_stop(cmd ) then
+ begin
+ inc(m_draw_item );
+
+ if m_draw_item >= m_num_items then
+ goto _Esc
+ else
+ begin
+ m_text.text_ (pointer(m_items[m_draw_item ] ) );
+ m_text.start_point_(
+ m_xs1 + m_dy * 1.5 ,
+ m_ys1 + m_dy * (m_draw_item + 1 ) - m_dy / 2.0 );
+
+ m_text_poly.rewind(0 );
+
+ cmd:=m_text_poly.vertex(x ,y );
+
+ end;
+
+ end;
+
+ end;
+
+ 3 :
+ begin
+ cmd:=m_ellipse_poly.vertex(x ,y );
+
+ if is_stop(cmd ) then
+ begin
+ inc(m_draw_item );
+
+ if m_draw_item >= m_num_items then
+ goto _Esc
+ else
+ begin
+ m_ellipse.init(
+ m_xs1 + m_dy / 1.3 ,
+ m_ys1 + m_dy * m_draw_item + m_dy / 1.3 ,
+ m_text_height / 1.5 ,
+ m_text_height / 1.5 ,32 );
+
+ m_ellipse_poly.rewind(0 );
+
+ cmd:=m_ellipse_poly.vertex(x ,y );
+
+ end;
+
+ end;
+
+ end;
+
+ 4 :
+ if m_cur_item >= 0 then
+ cmd:=m_ellipse.vertex(x ,y )
+ else
+ cmd:=path_cmd_stop;
+
+ else
+ cmd:=path_cmd_stop;
+
+ end;
+
+_Esc:
+ if not is_stop(cmd ) then
+ transform_xy(x ,y );
+
+ result:=cmd;
+
+end;
+
+{ CALC_RBOX }
+procedure rbox_ctrl_impl.calc_rbox;
+begin
+ m_xs1:=m_x1 + m_border_width;
+ m_ys1:=m_y1 + m_border_width;
+ m_xs2:=m_x2 - m_border_width;
+ m_ys2:=m_y2 - m_border_width;
+
+end;
+
+{ CONSTRUCT }
+constructor rbox_ctrl.Construct;
+begin
+ inherited Construct(x1 ,y1 ,x2 ,y2 ,flip_y_ );
+
+ m_background_color.ConstrDbl(1.0 ,1.0 ,0.9 );
+ m_border_color.ConstrDbl (0.0 ,0.0 ,0.0 );
+ m_text_color.ConstrDbl (0.0 ,0.0 ,0.0 );
+ m_inactive_color.ConstrDbl (0.0 ,0.0 ,0.0 );
+ m_active_color.ConstrDbl (0.4 ,0.0 ,0.0 );
+
+ m_colors[0 ]:=@m_background_color;
+ m_colors[1 ]:=@m_border_color;
+ m_colors[2 ]:=@m_text_color;
+ m_colors[3 ]:=@m_inactive_color;
+ m_colors[4 ]:=@m_active_color;
+
+end;
+
+{ BACKGROUND_COLOR_ }
+procedure rbox_ctrl.background_color_;
+begin
+ m_background_color:=c^;
+
+end;
+
+{ BORDER_COLOR_ }
+procedure rbox_ctrl.border_color_;
+begin
+ m_border_color:=c^;
+
+end;
+
+{ TEXT_COLOR_ }
+procedure rbox_ctrl.text_color_;
+begin
+ m_text_color:=c^;
+
+end;
+
+{ INACTIVE_COLOR_ }
+procedure rbox_ctrl.inactive_color_;
+begin
+ m_inactive_color:=c^;
+
+end;
+
+{ ACTIVE_COLOR_ }
+procedure rbox_ctrl.active_color_;
+begin
+ m_active_color:=c^;
+
+end;
+
+{ _COLOR }
+function rbox_ctrl._color;
+begin
+ result:=m_colors[i ];
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/ctrl/agg_scale_ctrl.pas b/src/corelib/render/software/ctrl/agg_scale_ctrl.pas
new file mode 100644
index 00000000..afbfc1c0
--- /dev/null
+++ b/src/corelib/render/software/ctrl/agg_scale_ctrl.pas
@@ -0,0 +1,747 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 29.01.2006-Milano: Unit port establishment
+//
+{ agg_scale_ctrl.pas }
+unit
+ agg_scale_ctrl ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_ctrl ,
+ agg_color ,
+ agg_ellipse ,
+ agg_math ,
+ agg_trans_affine ;
+
+{ TYPES DEFINITION }
+type
+ move_e = (move_nothing ,move_value1 ,move_value2 ,move_slider );
+
+ scale_ctrl_impl = object(ctrl )
+ m_border_thickness ,
+ m_border_extra ,
+
+ m_value1 ,
+ m_value2 ,
+ m_min_d ,
+
+ m_xs1 ,
+ m_ys1 ,
+ m_xs2 ,
+ m_ys2 ,
+ m_pdx ,
+ m_pdy : double;
+
+ m_move_what : move_e;
+ m_vx ,
+ m_vy : array[0..31 ] of double;
+
+ m_ellipse : ellipse;
+
+ m_idx ,
+ m_vertex : unsigned;
+
+ constructor Construct(x1 ,y1 ,x2 ,y2 : double; flip_y : boolean = false );
+ destructor Destruct; virtual;
+
+ procedure border_thickness_(t : double; extra : double = 0.0 );
+
+ procedure resize(x1 ,y1 ,x2 ,y2 : double );
+
+ function _min_delta : double;
+ procedure min_delta_(d : double );
+
+ function _value1 : double;
+ procedure value1_(value : double );
+
+ function _value2 : double;
+ procedure value2_(value : double );
+
+ procedure move(d : double );
+
+ function in_rect(x ,y : double ) : boolean; virtual;
+
+ function on_mouse_button_down(x ,y : double ) : boolean; virtual;
+ function on_mouse_button_up (x ,y : double ) : boolean; virtual;
+
+ function on_mouse_move(x ,y : double; button_flag : boolean ) : boolean; virtual;
+ function on_arrow_keys(left ,right ,down ,up : boolean ) : boolean; virtual;
+
+ // Vertex source interface
+ function num_paths : unsigned; virtual;
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ // Private
+ procedure calc_box;
+
+ end;
+
+ scale_ctrl = object(scale_ctrl_impl )
+ m_background_color ,
+ m_border_color ,
+ m_pointers_color ,
+ m_slider_color : aggclr;
+
+ m_colors : array[0..5 ] of aggclr_ptr;
+
+ constructor Construct(x1 ,y1 ,x2 ,y2 : double; flip_y : boolean = false );
+
+ procedure background_color_(c : aggclr_ptr );
+ procedure border_color_ (c : aggclr_ptr );
+ procedure pointers_color_ (c : aggclr_ptr );
+ procedure slider_color_ (c : aggclr_ptr );
+
+ function _color(i : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor scale_ctrl_impl.Construct;
+begin
+ inherited Construct(x1 ,y1 ,x2 ,y2 ,flip_y );
+
+ m_border_thickness:=1.0;
+
+ if Abs(x2 - x1 ) > Abs(y2 - y1 ) then
+ m_border_extra:=(y2 - y1 ) / 2
+ else
+ m_border_extra:=(x2 - x1 ) / 2;
+
+ m_pdx:=0.0;
+ m_pdy:=0.0;
+
+ m_move_what:=move_nothing;
+
+ m_value1:=0.3;
+ m_value2:=0.7;
+ m_min_d :=0.01;
+
+ m_ellipse.Construct;
+
+ calc_box;
+
+end;
+
+{ DESTRUCT }
+destructor scale_ctrl_impl.destruct;
+begin
+end;
+
+{ BORDER_THICKNESS_ }
+procedure scale_ctrl_impl.border_thickness_;
+begin
+ m_border_thickness:=t;
+ m_border_extra :=extra;
+
+ calc_box;
+
+end;
+
+{ RESIZE }
+procedure scale_ctrl_impl.resize;
+begin
+ m_x1:=x1;
+ m_y1:=y1;
+ m_x2:=x2;
+ m_y2:=y2;
+
+ calc_box;
+
+ if Abs(x2 - x1 ) > Abs(y2 - y1 ) then
+ m_border_extra:=(y2 - y1 ) / 2
+ else
+ m_border_extra:=(x2 - x1 ) / 2;
+
+end;
+
+{ _MIN_DELTA }
+function scale_ctrl_impl._min_delta;
+begin
+ result:=m_min_d;
+
+end;
+
+{ MIN_DELTA_ }
+procedure scale_ctrl_impl.min_delta_;
+begin
+ m_min_d:=d;
+
+end;
+
+{ _VALUE1 }
+function scale_ctrl_impl._value1;
+begin
+ result:=m_value1;
+
+end;
+
+{ VALUE1_ }
+procedure scale_ctrl_impl.value1_;
+begin
+ if value < 0.0 then
+ value:=0.0;
+
+ if value > 1.0 then
+ value:=1.0;
+
+ if m_value2 - value < m_min_d then
+ value:=m_value2 - m_min_d;
+
+ m_value1:=value;
+
+end;
+
+{ _VALUE2 }
+function scale_ctrl_impl._value2;
+begin
+ result:=m_value2;
+
+end;
+
+{ VALUE2_ }
+procedure scale_ctrl_impl.value2_;
+begin
+ if value < 0.0 then
+ value:=0.0;
+
+ if value > 1.0 then
+ value:=1.0;
+
+ if m_value1 + value < m_min_d then
+ value:=m_value1 + m_min_d;
+
+ m_value2:=value;
+
+end;
+
+{ MOVE }
+procedure scale_ctrl_impl.move;
+begin
+ m_value1:=m_value1 + d;
+ m_value2:=m_value2 + d;
+
+ if m_value1 < 0.0 then
+ begin
+ m_value2:=m_value2 - m_value1;
+ m_value1:=0.0;
+
+ end;
+
+ if m_value2 > 1.0 then
+ begin
+ m_value1:=m_value1 - m_value2 - 1.0;
+ m_value2:=1.0;
+
+ end;
+
+end;
+
+{ IN_RECT }
+function scale_ctrl_impl.in_rect;
+begin
+ inverse_transform_xy(@x ,@y );
+
+ result:=
+ (x >= m_x1 ) and
+ (x <= m_x2 ) and
+ (y >= m_y1 ) and
+ (y <= m_y2 );
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+function scale_ctrl_impl.on_mouse_button_down;
+var
+ xp1 ,xp2 ,ys1 ,ys2 ,xp ,yp : double;
+
+begin
+ inverse_transform_xy(@x ,@y );
+
+ if Abs(m_x2 - m_x1 ) > Abs(m_y2 - m_y1 ) then
+ begin
+ xp1:=m_xs1 + (m_xs2 - m_xs1 ) * m_value1;
+ xp2:=m_xs1 + (m_xs2 - m_xs1 ) * m_value2;
+ ys1:=m_y1 - m_border_extra / 2.0;
+ ys2:=m_y2 + m_border_extra / 2.0;
+ yp :=(m_ys1 + m_ys2 ) / 2.0;
+
+ if (x > xp1 ) and
+ (y > ys1 ) and
+ (x < xp2 ) and
+ (y < ys2 ) then
+ begin
+ m_pdx:=xp1 - x;
+
+ m_move_what:=move_slider;
+
+ result:=true;
+
+ exit;
+
+ end;
+
+ //if(x < xp1 && calc_distance(x, y, xp1, yp) <= m_y2 - m_y1)
+ if calc_distance(x ,y ,xp1 ,yp ) <= m_y2 - m_y1 then
+ begin
+ m_pdx:=xp1 - x;
+
+ m_move_what:=move_value1;
+
+ result:=true;
+
+ exit;
+
+ end;
+
+ //if(x > xp2 && calc_distance(x, y, xp2, yp) <= m_y2 - m_y1)
+ if calc_distance(x ,y ,xp2 ,yp ) <= m_y2 - m_y1 then
+ begin
+ m_pdx:=xp2 - x;
+
+ m_move_what:=move_value2;
+
+ result:=true;
+
+ end;
+
+ end
+ else
+ begin
+ xp1:=m_x1 - m_border_extra / 2.0;
+ xp2:=m_x2 + m_border_extra / 2.0;
+ ys1:=m_ys1 + (m_ys2 - m_ys1 ) * m_value1;
+ ys2:=m_ys1 + (m_ys2 - m_ys1 ) * m_value2;
+ xp :=(m_xs1 + m_xs2 ) / 2.0;
+
+ if (x > xp1 ) and
+ (y > ys1 ) and
+ (x < xp2 ) and
+ (y < ys2 ) then
+ begin
+ m_pdy:=ys1 - y;
+
+ m_move_what:=move_slider;
+
+ result:=true;
+
+ exit;
+
+ end;
+
+ //if(y < ys1 && calc_distance(x, y, xp, ys1) <= m_x2 - m_x1)
+ if calc_distance(x ,y ,xp ,ys1 ) <= m_x2 - m_x1 then
+ begin
+ m_pdy:=ys1 - y;
+
+ m_move_what:=move_value1;
+
+ result:=true;
+
+ exit;
+
+ end;
+
+ //if(y > ys2 && calc_distance(x, y, xp, ys2) <= m_x2 - m_x1)
+ if calc_distance(x, y, xp, ys2) <= m_x2 - m_x1 then
+ begin
+ m_pdy:=ys2 - y;
+
+ m_move_what:=move_value2;
+
+ result:=true;
+
+ exit;
+
+ end;
+
+ end;
+
+ result:=false;
+
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+function scale_ctrl_impl.on_mouse_button_up;
+begin
+ m_move_what:=move_nothing;
+
+ result:=false;
+
+end;
+
+{ ON_MOUSE_MOVE }
+function scale_ctrl_impl.on_mouse_move;
+var
+ xp ,yp ,dv : double;
+
+begin
+ inverse_transform_xy(@x ,@y );
+
+ if not button_flag then
+ result:=on_mouse_button_up(x ,y )
+ else
+ begin
+ xp:=x + m_pdx;
+ yp:=y + m_pdy;
+
+ case m_move_what of
+ move_value1 :
+ begin
+ if Abs(m_x2 - m_x1 ) > Abs(m_y2 - m_y1 ) then
+ m_value1:=(xp - m_xs1 ) / (m_xs2 - m_xs1 )
+ else
+ m_value1:=(yp - m_ys1 ) / (m_ys2 - m_ys1 );
+
+ if m_value1 < 0.0 then
+ m_value1:=0.0;
+
+ if m_value1 > m_value2 - m_min_d then
+ m_value1:=m_value2 - m_min_d;
+
+ result:=true;
+
+ end;
+
+ move_value2 :
+ begin
+ if Abs(m_x2 - m_x1 ) > Abs(m_y2 - m_y1 ) then
+ m_value2:=(xp - m_xs1 ) / (m_xs2 - m_xs1 )
+ else
+ m_value2:=(yp - m_ys1 ) / (m_ys2 - m_ys1 );
+
+ if m_value2 > 1.0 then
+ m_value2:=1.0;
+
+ if m_value2 < m_value1 + m_min_d then
+ m_value2:=m_value1 + m_min_d;
+
+ result:=true;
+
+ end;
+
+ move_slider :
+ begin
+ dv:=m_value2 - m_value1;
+
+ if Abs(m_x2 - m_x1 ) > abs(m_y2 - m_y1 ) then
+ m_value1:=(xp - m_xs1 ) / (m_xs2 - m_xs1 )
+ else
+ m_value1:=(yp - m_ys1 ) / (m_ys2 - m_ys1 );
+
+ m_value2:=m_value1 + dv;
+
+ if m_value1 < 0.0 then
+ begin
+ dv:=m_value2 - m_value1;
+
+ m_value1:=0.0;
+ m_value2:=m_value1 + dv;
+
+ end;
+
+ if m_value2 > 1.0 then
+ begin
+ dv:=m_value2 - m_value1;
+
+ m_value2:=1.0;
+ m_value1:=m_value2 - dv;
+
+ end;
+
+ result:=true;
+
+ end;
+
+ else
+ result:=false;
+
+ end;
+
+ end;
+
+end;
+
+{ ON_ARROW_KEYS }
+function scale_ctrl_impl.on_arrow_keys;
+begin
+ result:=false
+
+end;
+
+{ NUM_PATHS }
+function scale_ctrl_impl.num_paths;
+begin
+ result:=5;
+
+end;
+
+{ REWIND }
+procedure scale_ctrl_impl.rewind;
+begin
+ m_idx:=path_id;
+
+ case path_id of
+ 0: // Background
+ begin
+ m_vertex:=0;
+
+ m_vx[0 ]:=m_x1 - m_border_extra;
+ m_vy[0 ]:=m_y1 - m_border_extra;
+ m_vx[1 ]:=m_x2 + m_border_extra;
+ m_vy[1 ]:=m_y1 - m_border_extra;
+ m_vx[2 ]:=m_x2 + m_border_extra;
+ m_vy[2 ]:=m_y2 + m_border_extra;
+ m_vx[3 ]:=m_x1 - m_border_extra;
+ m_vy[3 ]:=m_y2 + m_border_extra;
+
+ end;
+
+ 1: // Border
+ begin
+ m_vertex:=0;
+
+ m_vx[0 ]:=m_x1;
+ m_vy[0 ]:=m_y1;
+ m_vx[1 ]:=m_x2;
+ m_vy[1 ]:=m_y1;
+ m_vx[2 ]:=m_x2;
+ m_vy[2 ]:=m_y2;
+ m_vx[3 ]:=m_x1;
+ m_vy[3 ]:=m_y2;
+ m_vx[4 ]:=m_x1 + m_border_thickness;
+ m_vy[4 ]:=m_y1 + m_border_thickness;
+ m_vx[5 ]:=m_x1 + m_border_thickness;
+ m_vy[5 ]:=m_y2 - m_border_thickness;
+ m_vx[6 ]:=m_x2 - m_border_thickness;
+ m_vy[6 ]:=m_y2 - m_border_thickness;
+ m_vx[7 ]:=m_x2 - m_border_thickness;
+ m_vy[7 ]:=m_y1 + m_border_thickness;
+
+ end;
+
+ 2: // pointer1
+ begin
+ if Abs(m_x2 - m_x1 ) > Abs(m_y2 - m_y1 ) then
+ m_ellipse.init(
+ m_xs1 + (m_xs2 - m_xs1 ) * m_value1 ,
+ (m_ys1 + m_ys2 ) / 2.0 ,
+ m_y2 - m_y1 ,
+ m_y2 - m_y1 ,32 )
+ else
+ m_ellipse.init(
+ (m_xs1 + m_xs2 ) / 2.0,
+ m_ys1 + (m_ys2 - m_ys1 ) * m_value1 ,
+ m_x2 - m_x1 ,
+ m_x2 - m_x1 ,32 );
+
+ m_ellipse.rewind(0 );
+
+ end;
+
+ 3: // pointer2
+ begin
+ if Abs(m_x2 - m_x1 ) > Abs(m_y2 - m_y1 ) then
+ m_ellipse.init(
+ m_xs1 + (m_xs2 - m_xs1 ) * m_value2 ,
+ (m_ys1 + m_ys2 ) / 2.0 ,
+ m_y2 - m_y1 ,
+ m_y2 - m_y1 ,32 )
+ else
+ m_ellipse.init(
+ (m_xs1 + m_xs2 ) / 2.0 ,
+ m_ys1 + (m_ys2 - m_ys1 ) * m_value2 ,
+ m_x2 - m_x1 ,
+ m_x2 - m_x1 ,32 );
+
+ m_ellipse.rewind(0);
+
+ end;
+
+ 4: // slider
+ begin
+ m_vertex:=0;
+
+ if Abs(m_x2 - m_x1 ) > Abs(m_y2 - m_y1 ) then
+ begin
+ m_vx[0 ]:=m_xs1 + (m_xs2 - m_xs1 ) * m_value1;
+ m_vy[0 ]:=m_y1 - m_border_extra / 2.0;
+ m_vx[1 ]:=m_xs1 + (m_xs2 - m_xs1 ) * m_value2;
+ m_vy[1 ]:=m_vy[0 ];
+ m_vx[2 ]:=m_vx[1 ];
+ m_vy[2 ]:=m_y2 + m_border_extra / 2.0;
+ m_vx[3 ]:=m_vx[0 ];
+ m_vy[3 ]:=m_vy[2 ];
+
+ end
+ else
+ begin
+ m_vx[0 ]:=m_x1 - m_border_extra / 2.0;
+ m_vy[0 ]:=m_ys1 + (m_ys2 - m_ys1 ) * m_value1;
+ m_vx[1 ]:=m_vx[0 ];
+ m_vy[1 ]:=m_ys1 + (m_ys2 - m_ys1 ) * m_value2;
+ m_vx[2 ]:=m_x2 + m_border_extra / 2.0;
+ m_vy[2 ]:=m_vy[1 ];
+ m_vx[3 ]:=m_vx[2 ];
+ m_vy[3 ]:=m_vy[0 ];
+
+ end;
+
+ end;
+
+ end;
+
+end;
+
+{ VERTEX }
+function scale_ctrl_impl.vertex;
+var
+ cmd : unsigned;
+
+begin
+ cmd:=path_cmd_line_to;
+
+ case m_idx of
+ 0 ,4 :
+ begin
+ if m_vertex = 0 then
+ cmd:=path_cmd_move_to;
+
+ if m_vertex >= 4 then
+ cmd:=path_cmd_stop;
+
+ x^:=m_vx[m_vertex ];
+ y^:=m_vy[m_vertex ];
+
+ inc(m_vertex );
+
+ end;
+
+ 1 :
+ begin
+ if (m_vertex = 0 ) or
+ (m_vertex = 4 ) then
+ cmd:=path_cmd_move_to;
+
+ if m_vertex >= 8 then
+ cmd:=path_cmd_stop;
+
+ x^:=m_vx[m_vertex ];
+ y^:=m_vy[m_vertex ];
+
+ inc(m_vertex );
+
+ end;
+
+ 2 ,3 :
+ cmd:=m_ellipse.vertex(x ,y );
+
+ else
+ cmd:=path_cmd_stop;
+
+ end;
+
+ if not is_stop(cmd ) then
+ transform_xy(x ,y );
+
+ result:=cmd;
+
+end;
+
+{ CALC_BOX }
+procedure scale_ctrl_impl.calc_box;
+begin
+ m_xs1:=m_x1 + m_border_thickness;
+ m_ys1:=m_y1 + m_border_thickness;
+ m_xs2:=m_x2 - m_border_thickness;
+ m_ys2:=m_y2 - m_border_thickness;
+
+end;
+
+{ CONSTRUCT }
+constructor scale_ctrl.Construct;
+begin
+ inherited Construct(x1 ,y1 ,x2 ,y2 ,flip_y );
+
+ m_background_color.ConstrDbl(1.0 ,0.9 ,0.8 );
+ m_border_color.ConstrDbl (0.0 ,0.0 ,0.0 );
+ m_pointers_color.ConstrDbl (0.8 ,0.0 ,0.0 ,0.8 );
+ m_slider_color.ConstrDbl (0.2 ,0.1 ,0.0 ,0.6 );
+
+ m_colors[0 ]:=@m_background_color;
+ m_colors[1 ]:=@m_border_color;
+ m_colors[2 ]:=@m_pointers_color;
+ m_colors[3 ]:=@m_pointers_color;
+ m_colors[4 ]:=@m_slider_color;
+
+end;
+
+{ BACKGROUND_COLOR_ }
+procedure scale_ctrl.background_color_;
+begin
+ m_background_color:=c^;
+
+end;
+
+{ BORDER_COLOR_ }
+procedure scale_ctrl.border_color_;
+begin
+ m_border_color:=c^;
+
+end;
+
+{ POINTERS_COLOR_ }
+procedure scale_ctrl.pointers_color_;
+begin
+ m_pointers_color:=c^;
+
+end;
+
+{ SLIDER_COLOR_ }
+procedure scale_ctrl.slider_color_;
+begin
+ m_slider_color:=c^;
+
+end;
+
+{ _COLOR }
+function scale_ctrl._color;
+begin
+ result:=m_colors[i ];
+
+end;
+
+
+END.
+
diff --git a/src/corelib/render/software/ctrl/agg_slider_ctrl.pas b/src/corelib/render/software/ctrl/agg_slider_ctrl.pas
new file mode 100644
index 00000000..6bd35880
--- /dev/null
+++ b/src/corelib/render/software/ctrl/agg_slider_ctrl.pas
@@ -0,0 +1,695 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// classes slider_ctrl_impl, slider_ctrl
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 21.12.2005-Milano: Complete unit port
+// 18.12.2005-Milano: Unit port establishment
+//
+{ agg_slider_ctrl.pas }
+unit
+ agg_slider_ctrl ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ SysUtils ,
+ agg_basics ,
+ agg_ctrl ,
+ agg_color ,
+ agg_ellipse ,
+ agg_path_storage ,
+ agg_conv_stroke ,
+ agg_gsv_text ,
+ agg_math ,
+ agg_math_stroke ;
+
+{ TYPES DEFINITION }
+type
+ slider_ctrl_impl = object(ctrl )
+ m_border_width ,
+ m_border_extra ,
+ m_text_thickness ,
+ m_value ,
+ m_preview_value ,
+
+ m_min ,
+ m_max : double;
+
+ m_num_steps : unsigned;
+ m_descending : boolean;
+
+ m_label : array[0..63 ] of byte;
+
+ m_xs1 ,
+ m_ys1 ,
+ m_xs2 ,
+ m_ys2 ,
+ m_pdx : double;
+
+ m_mouse_move : boolean;
+
+ m_vx ,
+ m_vy : array[0..31 ] of double;
+
+ m_ellipse : ellipse;
+
+ m_idx ,
+ m_vertex : unsigned;
+
+ m_text : gsv_text;
+ m_text_poly : conv_stroke;
+ m_storage : path_storage;
+
+ constructor Construct(x1 ,y1 ,x2 ,y2 : double; flip_y : boolean = false );
+ destructor Destruct; virtual;
+
+ procedure border_width_(t : double; extra : double = 0.0 );
+
+ procedure range_ (min ,max : double );
+ procedure num_steps_ (num : unsigned );
+ procedure label_ (fmt : PChar );
+ procedure text_thickness_(t : double );
+
+ function _descending : boolean;
+ procedure descending_(v : boolean );
+
+ function _value : double;
+ procedure value_(v : double );
+
+ function in_rect(x ,y : double ) : boolean; virtual;
+
+ function on_mouse_button_down(x ,y : double ) : boolean; virtual;
+ function on_mouse_button_up (x ,y : double ) : boolean; virtual;
+
+ function on_mouse_move(x ,y : double; button_flag : boolean ) : boolean; virtual;
+ function on_arrow_keys(left ,right ,down ,up : boolean ) : boolean; virtual;
+
+ // Vertex source interface
+ function num_paths : unsigned; virtual;
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ // Private
+ procedure calc_box;
+ function normalize_value(preview_value_flag : boolean ) : boolean;
+
+ end;
+
+ slider_ctrl_ptr = ^slider_ctrl;
+ slider_ctrl = object(slider_ctrl_impl )
+ m_background_color ,
+ m_triangle_color ,
+ m_text_color ,
+ m_pointer_preview_color ,
+ m_pointer_color : aggclr;
+
+ m_colors : array[0..5 ] of aggclr_ptr;
+
+ constructor Construct(x1 ,y1 ,x2 ,y2 : double; flip_y : boolean = false );
+
+ procedure background_color_(c : aggclr_ptr );
+ procedure pointer_color_ (c : aggclr_ptr );
+
+ function _color(i : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor slider_ctrl_impl.Construct;
+begin
+ inherited Construct(x1 ,y1 ,x2 ,y2 ,flip_y );
+
+ m_ellipse.Construct;
+ m_text.Construct;
+ m_text_poly.Construct(@m_text );
+ m_storage.Construct;
+
+ m_border_width :=1.0;
+ m_border_extra :=(y2 - y1 ) / 2;
+ m_text_thickness:=1.0;
+ m_pdx :=0.0;
+ m_mouse_move :=false;
+ m_value :=0.5;
+ m_preview_value :=0.5;
+ m_min :=0.0;
+ m_max :=1.0;
+ m_num_steps :=0;
+ m_descending :=false;
+
+ m_label[0 ]:=0;
+
+ calc_box;
+
+end;
+
+{ DESTRUCT }
+destructor slider_ctrl_impl.Destruct;
+begin
+ m_storage.Destruct;
+ m_text_poly.Destruct;
+ m_text.Destruct;
+
+end;
+
+{ BORDER_WIDTH_ }
+procedure slider_ctrl_impl.border_width_;
+begin
+ m_border_width:=t;
+ m_border_extra:=extra;
+
+ calc_box;
+
+end;
+
+{ RANGE_ }
+procedure slider_ctrl_impl.range_;
+begin
+ m_min:=min;
+ m_max:=max;
+
+end;
+
+{ NUM_STEPS_ }
+procedure slider_ctrl_impl.num_steps_;
+begin
+ m_num_steps:=num;
+
+end;
+
+{ LABEL_ }
+procedure slider_ctrl_impl.label_;
+var
+ len : unsigned;
+
+begin
+ m_label[0 ]:=0;
+
+ if fmt <> NIL then
+ begin
+ len:=StrLen(fmt );
+
+ if len > 63 then
+ len:=63;
+
+ move(fmt^ ,m_label[0 ] ,len );
+
+ m_label[len ]:=0;
+
+ end;
+
+end;
+
+{ TEXT_THICKNESS_ }
+procedure slider_ctrl_impl.text_thickness_;
+begin
+ m_text_thickness:=t;
+
+end;
+
+{ _DESCENDING }
+function slider_ctrl_impl._descending;
+begin
+ result:=m_descending;
+
+end;
+
+{ DESCENDING_ }
+procedure slider_ctrl_impl.descending_;
+begin
+ m_descending:=v;
+
+end;
+
+{ _VALUE }
+function slider_ctrl_impl._value;
+begin
+ result:=m_value * (m_max - m_min ) + m_min;
+
+end;
+
+{ VALUE_ }
+procedure slider_ctrl_impl.value_;
+begin
+ m_preview_value:=(v - m_min ) / (m_max - m_min );
+
+ if m_preview_value > 1.0 then
+ m_preview_value:=1.0;
+
+ if m_preview_value < 0.0 then
+ m_preview_value:=0.0;
+
+ normalize_value(true );
+
+end;
+
+{ IN_RECT }
+function slider_ctrl_impl.in_rect;
+begin
+ inverse_transform_xy(@x ,@y );
+
+ result:=
+ (x >= m_x1 ) and
+ (x <= m_x2 ) and
+ (y >= m_y1 ) and
+ (y <= m_y2 );
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+function slider_ctrl_impl.on_mouse_button_down;
+var
+ xp ,yp : double;
+
+begin
+ inverse_transform_xy(@x ,@y );
+
+ xp:=m_xs1 + (m_xs2 - m_xs1 ) * m_value;
+ yp:=(m_ys1 + m_ys2 ) / 2.0;
+
+ if calc_distance(x ,y ,xp ,yp ) <= m_y2 - m_y1 then
+ begin
+ m_pdx:=xp - x;
+
+ m_mouse_move:= true;
+
+ result:=true;
+
+ end
+ else
+ result:=false;
+
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+function slider_ctrl_impl.on_mouse_button_up;
+begin
+ m_mouse_move:=false;
+
+ normalize_value(true );
+
+ result:=true;
+
+end;
+
+{ ON_MOUSE_MOVE }
+function slider_ctrl_impl.on_mouse_move;
+var
+ xp : double;
+
+begin
+ inverse_transform_xy(@x ,@y );
+
+ if not button_flag then
+ begin
+ on_mouse_button_up(x ,y );
+
+ result:=false;
+
+ exit;
+
+ end;
+
+ if m_mouse_move then
+ begin
+ xp:=x + m_pdx;
+
+ m_preview_value:=(xp - m_xs1 ) / (m_xs2 - m_xs1 );
+
+ if m_preview_value < 0.0 then
+ m_preview_value:=0.0;
+
+ if m_preview_value > 1.0 then
+ m_preview_value:=1.0;
+
+ result:=true;
+
+ end
+ else
+ result:=false;
+
+end;
+
+{ ON_ARROW_KEYS }
+function slider_ctrl_impl.on_arrow_keys;
+var
+ d : double;
+
+begin
+ d:=0.005;
+
+ if m_num_steps <> 0 then
+ d:=1.0 / m_num_steps;
+
+ if right or
+ up then
+ begin
+ m_preview_value:=m_preview_value + d;
+
+ if m_preview_value > 1.0 then
+ m_preview_value:=1.0;
+
+ normalize_value(true );
+
+ result:=true;
+
+ exit;
+
+ end;
+
+ if left or
+ down then
+ begin
+ m_preview_value:=m_preview_value - d;
+
+ if m_preview_value < 0.0 then
+ m_preview_value:=0.0;
+
+ normalize_value(true );
+
+ result:=true;
+
+ end
+ else
+ result:=false;
+
+end;
+
+{ NUM_PATHS }
+function slider_ctrl_impl.num_paths;
+begin
+ result:=6;
+
+end;
+
+{ REWIND }
+procedure slider_ctrl_impl.rewind;
+var
+ i : unsigned;
+
+ d ,x : double;
+
+ buf : array[0..255 ] of byte;
+
+label
+ _0 ;
+
+begin
+ m_idx:=path_id;
+
+ case path_id of
+ 0 : // Background
+ begin
+ _0 :
+ m_vertex:=0;
+
+ m_vx[0 ]:=m_x1 - m_border_extra;
+ m_vy[0 ]:=m_y1 - m_border_extra;
+ m_vx[1 ]:=m_x2 + m_border_extra;
+ m_vy[1 ]:=m_y1 - m_border_extra;
+ m_vx[2 ]:=m_x2 + m_border_extra;
+ m_vy[2 ]:=m_y2 + m_border_extra;
+ m_vx[3 ]:=m_x1 - m_border_extra;
+ m_vy[3 ]:=m_y2 + m_border_extra;
+
+ end;
+
+ 1 : // Triangle
+ begin
+ m_vertex:=0;
+
+ if m_descending then
+ begin
+ m_vx[0 ]:=m_x1;
+ m_vy[0 ]:=m_y1;
+ m_vx[1 ]:=m_x2;
+ m_vy[1 ]:=m_y1;
+ m_vx[2 ]:=m_x1;
+ m_vy[2 ]:=m_y2;
+ m_vx[3 ]:=m_x1;
+ m_vy[3 ]:=m_y1;
+
+ end
+ else
+ begin
+ m_vx[0 ]:=m_x1;
+ m_vy[0 ]:=m_y1;
+ m_vx[1 ]:=m_x2;
+ m_vy[1 ]:=m_y1;
+ m_vx[2 ]:=m_x2;
+ m_vy[2 ]:=m_y2;
+ m_vx[3 ]:=m_x1;
+ m_vy[3 ]:=m_y1;
+
+ end;
+
+ end;
+
+ 2 :
+ begin
+ m_text.text_(@m_label[0 ] );
+
+ if m_label[0 ] <> 0 then
+ begin
+ sprintf(@buf[0 ] ,@m_label[0 ] ,_value );
+
+ m_text.text_(@buf[0 ] );
+
+ end;
+
+ m_text.start_point_(m_x1 ,m_y1 );
+ m_text.size_ ((m_y2 - m_y1 ) * 1.2 ,m_y2 - m_y1 );
+
+ m_text_poly.width_ (m_text_thickness );
+ m_text_poly.line_join_(round_join );
+ m_text_poly.line_cap_ (round_cap );
+
+ m_text_poly.rewind(0 );
+
+ end;
+
+ 3 : // pointer preview
+ m_ellipse.init(
+ m_xs1 + (m_xs2 - m_xs1 ) * m_preview_value ,
+ (m_ys1 + m_ys2 ) / 2.0 ,
+ m_y2 - m_y1 ,
+ m_y2 - m_y1 ,
+ 32 );
+
+ 4 : // pointer
+ begin
+ normalize_value(false );
+
+ m_ellipse.init(
+ m_xs1 + (m_xs2 - m_xs1 ) * m_value ,
+ (m_ys1 + m_ys2 ) / 2.0 ,
+ m_y2 - m_y1 ,
+ m_y2 - m_y1 ,
+ 32 );
+
+ m_ellipse.rewind(0 );
+
+ end;
+
+ 5 :
+ begin
+ m_storage.remove_all;
+
+ if m_num_steps <> 0 then
+ begin
+ d:=(m_xs2 - m_xs1 ) / m_num_steps;
+
+ if d > 0.004 then
+ d:=0.004;
+
+ for i:=0 to m_num_steps do
+ begin
+ x:=m_xs1 + (m_xs2 - m_xs1 ) * i / m_num_steps;
+
+ m_storage.move_to(x ,m_y1 );
+
+ m_storage.line_to(x - d * (m_x2 - m_x1 ) ,m_y1 - m_border_extra );
+ m_storage.line_to(x + d * (m_x2 - m_x1 ) ,m_y1 - m_border_extra );
+
+ end;
+
+ end;
+
+ end;
+
+ else
+ goto _0;
+
+ end;
+
+end;
+
+{ VERTEX }
+function slider_ctrl_impl.vertex;
+var
+ cmd : unsigned;
+
+begin
+ cmd:=path_cmd_line_to;
+
+ case m_idx of
+ 0 :
+ begin
+ if m_vertex = 0 then
+ cmd:=path_cmd_move_to;
+
+ if m_vertex >= 4 then
+ cmd:=path_cmd_stop;
+
+ x^:=m_vx[m_vertex ];
+ y^:=m_vy[m_vertex ];
+
+ inc(m_vertex );
+
+ end;
+
+ 1 :
+ begin
+ if m_vertex = 0 then
+ cmd:=path_cmd_move_to;
+
+ if m_vertex >= 4 then
+ cmd:=path_cmd_stop;
+
+ x^:=m_vx[m_vertex ];
+ y^:=m_vy[m_vertex ];
+
+ inc(m_vertex );
+
+ end;
+
+ 2 :
+ cmd:=m_text_poly.vertex(x ,y );
+
+ 3 ,4 :
+ cmd:=m_ellipse.vertex(x ,y );
+
+ 5 :
+ cmd:=m_storage.vertex(x ,y );
+
+ else
+ cmd:=path_cmd_stop;
+
+ end;
+
+ if not is_stop(cmd ) then
+ transform_xy(x ,y );
+
+ result:=cmd;
+
+end;
+
+{ CALC_BOX }
+procedure slider_ctrl_impl.calc_box;
+begin
+ m_xs1:=m_x1 + m_border_width;
+ m_ys1:=m_y1 + m_border_width;
+ m_xs2:=m_x2 - m_border_width;
+ m_ys2:=m_y2 - m_border_width;
+
+end;
+
+{ NORMALIZE_VALUE }
+function slider_ctrl_impl.normalize_value;
+var
+ ret : boolean;
+ step : int;
+
+begin
+ ret:=true;
+
+ if m_num_steps <> 0 then
+ begin
+ step:=trunc(m_preview_value * m_num_steps + 0.5 );
+ ret :=m_value <> (step / m_num_steps );
+
+ m_value:=step / m_num_steps;
+
+ end
+ else
+ m_value:=m_preview_value;
+
+ if preview_value_flag then
+ m_preview_value:=m_value;
+
+ result:=ret;
+
+end;
+
+{ CONSTRUCT }
+constructor slider_ctrl.Construct;
+begin
+ inherited Construct(x1 ,y1 ,x2 ,y2 ,flip_y );
+
+ m_background_color.ConstrDbl (1.0 ,0.9 ,0.8 );
+ m_triangle_color.ConstrDbl (0.7 ,0.6 ,0.6 );
+ m_text_color.ConstrDbl (0.0 ,0.0 ,0.0 );
+ m_pointer_preview_color.ConstrDbl(0.6 ,0.4 ,0.4 ,0.4 );
+ m_pointer_color.ConstrDbl (0.8 ,0.0 ,0.0 ,0.6 );
+
+ m_colors[0 ]:=@m_background_color;
+ m_colors[1 ]:=@m_triangle_color;
+ m_colors[2 ]:=@m_text_color;
+ m_colors[3 ]:=@m_pointer_preview_color;
+ m_colors[4 ]:=@m_pointer_color;
+ m_colors[5 ]:=@m_text_color;
+
+end;
+
+{ BACKGROUND_COLOR_ }
+procedure slider_ctrl.background_color_;
+begin
+ m_background_color:=c^;
+
+end;
+
+{ POINTER_COLOR_ }
+procedure slider_ctrl.pointer_color_;
+begin
+ m_pointer_color:=c^;
+
+end;
+
+{ _COLOR }
+function slider_ctrl._color;
+begin
+ result:=m_colors[i ];
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/ctrl/agg_spline_ctrl.pas b/src/corelib/render/software/ctrl/agg_spline_ctrl.pas
new file mode 100644
index 00000000..255bdb27
--- /dev/null
+++ b/src/corelib/render/software/ctrl/agg_spline_ctrl.pas
@@ -0,0 +1,816 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// classes spline_ctrl_impl, spline_ctrl
+//
+// Class that can be used to create an interactive control to set up
+// gamma arrays.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.02.2006-Milano: Unit port establishment
+//
+{ agg_spline_ctrl.pas }
+unit
+ agg_spline_ctrl ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_ellipse ,
+ agg_bspline ,
+ agg_conv_stroke ,
+ agg_path_storage ,
+ agg_trans_affine ,
+ agg_color ,
+ agg_ctrl ,
+ agg_math ;
+
+{ TYPES DEFINITION }
+type
+ spline_ctrl_impl = object(ctrl )
+ m_num_pnt : unsigned;
+
+ m_xp ,
+ m_yp : array[0..31 ] of double;
+
+ m_spline : bspline;
+
+ m_spline_values : array[0..255 ] of double;
+ m_spline_values8 : array[0..255 ] of int8u;
+ m_border_width ,
+ m_border_extra ,
+ m_curve_width ,
+ m_point_size ,
+
+ m_xs1 ,
+ m_ys1 ,
+ m_xs2 ,
+ m_ys2 : double;
+
+ m_curve_pnt : path_storage;
+ m_curve_poly : conv_stroke;
+ m_ellipse : ellipse;
+
+ m_idx ,
+ m_vertex : unsigned;
+
+ m_vx ,
+ m_vy : array[0..31 ] of double;
+
+ m_active_pnt ,
+ m_move_pnt : int;
+
+ m_pdx ,
+ m_pdy : double;
+
+ constructor Construct(x1 ,y1 ,x2 ,y2 : double; num_pnt : unsigned; flip_y : boolean = false );
+ destructor Destruct; virtual;
+
+ // Set other parameters
+ procedure border_width_(t : double; extra : double = 0.0 );
+ procedure curve_width_ (t : double );
+ procedure point_size_ (s : double );
+
+ // Event handlers. Just call them if the respective events
+ // in your system occure. The functions return true if redrawing
+ // is required.
+ function in_rect(x ,y : double ) : boolean; virtual;
+
+ function on_mouse_button_down(x ,y : double ) : boolean; virtual;
+ function on_mouse_button_up (x ,y : double ) : boolean; virtual;
+
+ function on_mouse_move(x ,y : double; button_flag : boolean ) : boolean; virtual;
+ function on_arrow_keys(left ,right ,down ,up : boolean ) : boolean; virtual;
+
+ // Spline
+ procedure active_point_(i : int );
+
+ function _spline : double_ptr;
+ function _spline8 : int8u_ptr;
+
+ function _value(x : double ) : double;
+ procedure value_(idx : unsigned; y : double );
+ procedure point_(idx : unsigned; x ,y : double );
+
+ procedure x_(idx : unsigned; x : double );
+ procedure y_(idx : unsigned; y : double );
+ function _x(idx : unsigned ) : double;
+ function _y(idx : unsigned ) : double;
+
+ procedure update_spline;
+
+ // Vertex soutce interface
+ function num_paths : unsigned; virtual;
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ // Private
+ procedure calc_spline_box;
+ procedure calc_curve;
+ function calc_xp(idx : unsigned ) : double;
+ function calc_yp(idx : unsigned ) : double;
+ procedure set_xp (idx : unsigned; val : double );
+ procedure set_yp (idx : unsigned; val : double );
+
+ end;
+
+ spline_ctrl = object(spline_ctrl_impl )
+ m_background_color ,
+ m_border_color ,
+ m_curve_color ,
+ m_inactive_pnt_color ,
+ m_active_pnt_color : aggclr;
+
+ m_colors : array[0..4 ] of aggclr_ptr;
+
+ constructor Construct(x1 ,y1 ,x2 ,y2 : double; num_pnt : unsigned; flip_y : boolean = false );
+
+ procedure background_color_ (c : aggclr_ptr );
+ procedure border_color_ (c : aggclr_ptr );
+ procedure curve_color_ (c : aggclr_ptr );
+ procedure inactive_pnt_color_(c : aggclr_ptr );
+ procedure active_pnt_color_ (c : aggclr_ptr );
+
+ function _color(i : unsigned ) : aggclr_ptr; virtual;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor spline_ctrl_impl.Construct;
+var
+ i : unsigned;
+
+begin
+ inherited Construct(x1 ,y1 ,x2 ,y2 ,flip_y );
+
+ m_num_pnt:=num_pnt;
+
+ m_border_width:=1.0;
+ m_border_extra:=0.0;
+ m_curve_width :=1.0;
+ m_point_size :=3.0;
+
+ m_spline.Construct;
+ m_curve_pnt.Construct;
+ m_curve_poly.Construct(@m_curve_pnt );
+ m_ellipse.Construct;
+
+ m_idx :=0;
+ m_vertex :=0;
+ m_active_pnt:=-1;
+ m_move_pnt :=-1;
+
+ m_pdx:=0.0;
+ m_pdy:=0.0;
+
+ if m_num_pnt < 4 then
+ m_num_pnt:=4;
+
+ if m_num_pnt > 32 then
+ m_num_pnt:=32;
+
+ for i:=0 to m_num_pnt - 1 do
+ begin
+ m_xp[i ]:=i / (m_num_pnt - 1 );
+ m_yp[i ]:=0.5;
+
+ end;
+
+ calc_spline_box;
+ update_spline;
+
+end;
+
+{ DESTRUCT }
+destructor spline_ctrl_impl.Destruct;
+begin
+ m_spline.Destruct;
+ m_curve_pnt.Destruct;
+ m_curve_poly.Destruct;
+
+end;
+
+{ BORDER_WIDTH_ }
+procedure spline_ctrl_impl.border_width_;
+begin
+ m_border_width:=t;
+ m_border_extra:=extra;
+
+ calc_spline_box;
+
+end;
+
+{ CURVE_WIDTH_ }
+procedure spline_ctrl_impl.curve_width_;
+begin
+ m_curve_width:=t;
+
+end;
+
+{ POINT_SIZE_ }
+procedure spline_ctrl_impl.point_size_;
+begin
+ m_point_size:=s;
+
+end;
+
+{ IN_RECT }
+function spline_ctrl_impl.in_rect;
+begin
+ inverse_transform_xy(@x ,@y );
+
+ result:=
+ (x >= m_x1 ) and
+ (x <= m_x2 ) and
+ (y >= m_y1 ) and
+ (y <= m_y2 );
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+function spline_ctrl_impl.on_mouse_button_down;
+var
+ i : unsigned;
+
+ xp ,yp : double;
+
+begin
+ inverse_transform_xy(@x ,@y );
+
+ for i:=0 to m_num_pnt - 1 do
+ begin
+ xp:=calc_xp(i );
+ yp:=calc_yp(i );
+
+ if calc_distance(x ,y ,xp ,yp ) <= m_point_size + 1 then
+ begin
+ m_pdx:=xp - x;
+ m_pdy:=yp - y;
+
+ m_active_pnt:=i;
+ m_move_pnt :=i;
+
+ result:=true;
+
+ exit;
+
+ end;
+
+ end;
+
+ result:=false;
+
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+function spline_ctrl_impl.on_mouse_button_up;
+begin
+ if m_move_pnt >= 0 then
+ begin
+ m_move_pnt:=-1;
+
+ result:=true;
+
+ end
+ else
+ result:=false;
+
+end;
+
+{ ON_MOUSE_MOVE }
+function spline_ctrl_impl.on_mouse_move;
+var
+ xp ,yp : double;
+
+begin
+ inverse_transform_xy(@x ,@y );
+
+ if not button_flag then
+ begin
+ result:=on_mouse_button_up(x ,y );
+
+ exit;
+
+ end;
+
+ if m_move_pnt >= 0 then
+ begin
+ xp:=x + m_pdx;
+ yp:=y + m_pdy;
+
+ set_xp(m_move_pnt ,(xp - m_xs1 ) / (m_xs2 - m_xs1 ) );
+ set_yp(m_move_pnt ,(yp - m_ys1 ) / (m_ys2 - m_ys1 ) );
+
+ update_spline;
+
+ result:=true;
+
+ end
+ else
+ result:=false;
+
+end;
+
+{ ON_ARROW_KEYS }
+function spline_ctrl_impl.on_arrow_keys;
+var
+ kx ,ky : double;
+
+ ret : boolean;
+
+begin
+ kx :=0.0;
+ ky :=0.0;
+ ret:=false;
+
+ if m_active_pnt >= 0 then
+ begin
+ kx:=m_xp[m_active_pnt ];
+ ky:=m_yp[m_active_pnt ];
+
+ if left then
+ begin
+ kx :=kx - 0.001;
+ ret:=true;
+
+ end;
+
+ if right then
+ begin
+ kx :=kx + 0.001;
+ ret:=true;
+
+ end;
+
+ if down then
+ begin
+ ky :=ky - 0.001;
+ ret:=true;
+
+ end;
+
+ if up then
+ begin
+ ky :=ky + 0.001;
+ ret:=true;
+
+ end;
+
+ end;
+
+ if ret then
+ begin
+ set_xp(m_active_pnt ,kx );
+ set_yp(m_active_pnt ,ky );
+
+ update_spline;
+
+ end;
+
+ result:=ret;
+
+end;
+
+{ ACTIVE_POINT_ }
+procedure spline_ctrl_impl.active_point_;
+begin
+ m_active_pnt:=i;
+
+end;
+
+{ _SPLINE }
+function spline_ctrl_impl._spline;
+begin
+ result:=@m_spline_values;
+
+end;
+
+{ _SPLINE8 }
+function spline_ctrl_impl._spline8;
+begin
+ result:=@m_spline_values8;
+
+end;
+
+{ _VALUE }
+function spline_ctrl_impl._value;
+begin
+ x:=m_spline.get(x );
+
+ if x < 0.0 then
+ x:=0.0;
+
+ if x > 1.0 then
+ x:=1.0;
+
+ result:=x;
+
+end;
+
+{ VALUE_ }
+procedure spline_ctrl_impl.value_;
+begin
+ if idx < m_num_pnt then
+ set_yp(idx ,y );
+
+end;
+
+{ POINT_ }
+procedure spline_ctrl_impl.point_;
+begin
+ if idx < m_num_pnt then
+ begin
+ set_xp(idx ,x );
+ set_yp(idx ,y );
+
+ end;
+
+end;
+
+{ X_ }
+procedure spline_ctrl_impl.x_;
+begin
+ m_xp[idx ]:=x;
+
+end;
+
+{ Y_ }
+procedure spline_ctrl_impl.y_;
+begin
+ m_yp[idx ]:=y;
+
+end;
+
+{ _X }
+function spline_ctrl_impl._x;
+begin
+ result:=m_xp[idx ];
+
+end;
+
+{ _Y }
+function spline_ctrl_impl._y;
+begin
+ result:=m_yp[idx ];
+
+end;
+
+{ UPDATE_SPLINE }
+procedure spline_ctrl_impl.update_spline;
+var
+ i : int;
+
+begin
+ m_spline.init(m_num_pnt ,@m_xp ,@m_yp );
+
+ for i:=0 to 255 do
+ begin
+ m_spline_values[i ]:=m_spline.get(i / 255.0 );
+
+ if m_spline_values[i ] < 0.0 then
+ m_spline_values[i ]:=0.0;
+
+ if m_spline_values[i ] > 1.0 then
+ m_spline_values[i ]:=1.0;
+
+ m_spline_values8[i ]:=int8u(trunc(m_spline_values[i ] * 255.0 ) );
+
+ end;
+
+end;
+
+{ NUM_PATHS }
+function spline_ctrl_impl.num_paths;
+begin
+ result:=5;
+
+end;
+
+{ REWIND }
+procedure spline_ctrl_impl.rewind;
+var
+ i : unsigned;
+
+begin
+ m_idx:=path_id;
+
+ case path_id of
+ 0 : // Background
+ begin
+ m_vertex:=0;
+
+ m_vx[0 ]:=m_x1 - m_border_extra;
+ m_vy[0 ]:=m_y1 - m_border_extra;
+ m_vx[1 ]:=m_x2 + m_border_extra;
+ m_vy[1 ]:=m_y1 - m_border_extra;
+ m_vx[2 ]:=m_x2 + m_border_extra;
+ m_vy[2 ]:=m_y2 + m_border_extra;
+ m_vx[3 ]:=m_x1 - m_border_extra;
+ m_vy[3 ]:=m_y2 + m_border_extra;
+
+ end;
+
+ 1 : // Border
+ begin
+ m_vertex:=0;
+
+ m_vx[0 ]:=m_x1;
+ m_vy[0 ]:=m_y1;
+ m_vx[1 ]:=m_x2;
+ m_vy[1 ]:=m_y1;
+ m_vx[2 ]:=m_x2;
+ m_vy[2 ]:=m_y2;
+ m_vx[3 ]:=m_x1;
+ m_vy[3 ]:=m_y2;
+ m_vx[4 ]:=m_x1 + m_border_width;
+ m_vy[4 ]:=m_y1 + m_border_width;
+ m_vx[5 ]:=m_x1 + m_border_width;
+ m_vy[5 ]:=m_y2 - m_border_width;
+ m_vx[6 ]:=m_x2 - m_border_width;
+ m_vy[6 ]:=m_y2 - m_border_width;
+ m_vx[7 ]:=m_x2 - m_border_width;
+ m_vy[7 ]:=m_y1 + m_border_width;
+
+ end;
+
+ 2 : // Curve
+ begin
+ calc_curve;
+
+ m_curve_poly.width_(m_curve_width );
+ m_curve_poly.rewind(0 );
+
+ end;
+
+ 3 : // Inactive points
+ begin
+ m_curve_pnt.remove_all;
+
+ for i:=0 to m_num_pnt - 1 do
+ if i <> m_active_pnt then
+ begin
+ m_ellipse.init(
+ calc_xp(i ) ,calc_yp(i ) ,
+ m_point_size ,m_point_size ,32 );
+
+ m_curve_pnt.add_path(@m_ellipse ,0 ,false );
+
+ end;
+
+ m_curve_poly.rewind(0 );
+
+ end;
+
+ 4 : // Active point
+ begin
+ m_curve_pnt.remove_all;
+
+ if m_active_pnt >= 0 then
+ begin
+ m_ellipse.init(
+ calc_xp(m_active_pnt ) ,calc_yp(m_active_pnt ) ,
+ m_point_size ,m_point_size ,32 );
+
+ m_curve_pnt.add_path(@m_ellipse );
+
+ end;
+
+ m_curve_poly.rewind(0 );
+
+ end;
+
+ end;
+
+end;
+
+{ VERTEX }
+function spline_ctrl_impl.vertex;
+var
+ cmd : unsigned;
+
+begin
+ cmd:=path_cmd_line_to;
+
+ case m_idx of
+ 0 :
+ begin
+ if m_vertex = 0 then
+ cmd:=path_cmd_move_to;
+
+ if m_vertex >= 4 then
+ cmd:=path_cmd_stop;
+
+ x^:=m_vx[m_vertex ];
+ y^:=m_vy[m_vertex ];
+
+ inc(m_vertex );
+
+ end;
+
+ 1 :
+ begin
+ if (m_vertex = 0 ) or
+ (m_vertex = 4 ) then
+ cmd:=path_cmd_move_to;
+
+ if m_vertex >= 8 then
+ cmd:=path_cmd_stop;
+
+ x^:=m_vx[m_vertex ];
+ y^:=m_vy[m_vertex ];
+
+ inc(m_vertex );
+
+ end;
+
+ 2 :
+ cmd:=m_curve_poly.vertex(x ,y );
+
+ 3 ,4 :
+ cmd:=m_curve_pnt.vertex(x ,y );
+
+ else
+ cmd:=path_cmd_stop;
+
+ end;
+
+ if not is_stop(cmd ) then
+ transform_xy(x ,y );
+
+ result:=cmd;
+
+end;
+
+{ CALC_SPLINE_BOX }
+procedure spline_ctrl_impl.calc_spline_box;
+begin
+ m_xs1:=m_x1 + m_border_width;
+ m_ys1:=m_y1 + m_border_width;
+ m_xs2:=m_x2 - m_border_width;
+ m_ys2:=m_y2 - m_border_width;
+
+end;
+
+{ CALC_CURVE }
+procedure spline_ctrl_impl.calc_curve;
+var
+ i : int;
+
+begin
+ m_curve_pnt.remove_all;
+ m_curve_pnt.move_to(m_xs1 ,m_ys1 + (m_ys2 - m_ys1 ) * m_spline_values[0 ] );
+
+ for i:=1 to 255 do
+ m_curve_pnt.line_to(
+ m_xs1 + (m_xs2 - m_xs1 ) * i / 255.0 ,
+ m_ys1 + (m_ys2 - m_ys1 ) * m_spline_values[i ] );
+
+end;
+
+{ CALC_XP }
+function spline_ctrl_impl.calc_xp;
+begin
+ result:=m_xs1 + (m_xs2 - m_xs1 ) * m_xp[idx ];
+
+end;
+
+{ CALC_YP }
+function spline_ctrl_impl.calc_yp;
+begin
+ result:=m_ys1 + (m_ys2 - m_ys1 ) * m_yp[idx ];
+
+end;
+
+{ SET_XP }
+procedure spline_ctrl_impl.set_xp;
+begin
+ if val < 0.0 then
+ val:=0.0;
+
+ if val > 1.0 then
+ val:=1.0;
+
+ if idx = 0 then
+ val:=0.0
+ else
+ if idx = m_num_pnt - 1 then
+ val:=1.0
+ else
+ begin
+ if val < m_xp[idx - 1 ] + 0.001 then
+ val:=m_xp[idx - 1 ] + 0.001;
+
+ if val > m_xp[idx + 1 ] - 0.001 then
+ val:=m_xp[idx + 1 ] - 0.001;
+
+ end;
+
+ m_xp[idx ]:=val;
+
+end;
+
+{ SET_YP }
+procedure spline_ctrl_impl.set_yp;
+begin
+ if val < 0.0 then
+ val:=0.0;
+
+ if val > 1.0 then
+ val:=1.0;
+
+ m_yp[idx ]:=val;
+
+end;
+
+{ CONSTRUCT }
+constructor spline_ctrl.Construct;
+begin
+ inherited Construct(x1 ,y1 ,x2 ,y2 ,num_pnt ,flip_y );
+
+ m_background_color.ConstrDbl (1.0 ,1.0 ,0.9 );
+ m_border_color.ConstrDbl (0.0 ,0.0 ,0.0 );
+ m_curve_color.ConstrDbl (0.0 ,0.0 ,0.0 );
+ m_inactive_pnt_color.ConstrDbl(0.0 ,0.0 ,0.0 );
+ m_active_pnt_color.ConstrDbl (1.0 ,0.0 ,0.0 );
+
+ m_colors[0 ]:=@m_background_color;
+ m_colors[1 ]:=@m_border_color;
+ m_colors[2 ]:=@m_curve_color;
+ m_colors[3 ]:=@m_inactive_pnt_color;
+ m_colors[4 ]:=@m_active_pnt_color;
+
+end;
+
+{ BACKGROUND_COLOR_ }
+procedure spline_ctrl.background_color_;
+begin
+ m_background_color:=c^;
+
+end;
+
+{ BORDER_COLOR_ }
+procedure spline_ctrl.border_color_;
+begin
+ m_border_color:=c^;
+
+end;
+
+{ CURVE_COLOR_ }
+procedure spline_ctrl.curve_color_;
+begin
+ m_curve_color:=c^;
+
+end;
+
+{ INACTIVE_PNT_COLOR_ }
+procedure spline_ctrl.inactive_pnt_color_;
+begin
+ m_inactive_pnt_color:=c^;
+
+end;
+
+{ ACTIVE_PNT_COLOR_ }
+procedure spline_ctrl.active_pnt_color_;
+begin
+ m_active_pnt_color:=c^;
+
+end;
+
+{ _COLOR }
+function spline_ctrl._color;
+begin
+ result:=m_colors[i ];
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/pf_abgr32.inc b/src/corelib/render/software/pf_abgr32.inc
new file mode 100644
index 00000000..e5f7565e
--- /dev/null
+++ b/src/corelib/render/software/pf_abgr32.inc
@@ -0,0 +1,608 @@
+//
+// AggPas 2.4 RM3 pixel format definition file
+//
+{ blend_pix_abgr }
+procedure blend_pix_abgr(p : unsigned_ptr; cr ,cg ,cb ,alpha : int; cover : unsigned = 0 );
+var
+ r ,g ,b ,a : int8u;
+
+begin
+ r:=order_abgr(p^ ).R;
+ g:=order_abgr(p^ ).G;
+ b:=order_abgr(p^ ).B;
+ a:=order_abgr(p^ ).A;
+
+ order_abgr(p^ ).R:=((cr - r ) * alpha + (r shl base_shift ) ) shr base_shift;
+ order_abgr(p^ ).G:=((cg - g ) * alpha + (g shl base_shift ) ) shr base_shift;
+ order_abgr(p^ ).B:=((cb - b ) * alpha + (b shl base_shift ) ) shr base_shift;
+ order_abgr(p^ ).A:=(alpha + a ) - ((alpha * a + base_mask ) shr base_shift );
+
+end;
+
+{ copy_or_blend_pix_abgr }
+procedure copy_or_blend_pix_abgr(p : unsigned_ptr; cr ,cg ,cb ,alpha : unsigned ); overload;
+begin
+ if alpha <> 0 then
+ if alpha = base_mask then
+ begin
+ order_abgr(p^ ).R:=cr;
+ order_abgr(p^ ).G:=cg;
+ order_abgr(p^ ).B:=cb;
+ order_abgr(p^ ).A:=base_mask;
+
+ end
+ else
+ blend_pix_abgr(p ,cr ,cg ,cb ,alpha );
+
+end;
+
+{ copy_or_blend_pix_abgr }
+procedure copy_or_blend_pix_abgr(p : unsigned_ptr; cr ,cg ,cb ,alpha ,cover : unsigned ); overload;
+begin
+ if cover = 255 then
+ copy_or_blend_pix_abgr(p ,cr ,cg ,cb ,alpha )
+ else
+ if alpha <> 0 then
+ begin
+ alpha:=(alpha * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_abgr(p^ ).R:=cr;
+ order_abgr(p^ ).G:=cg;
+ order_abgr(p^ ).B:=cb;
+ order_abgr(p^ ).A:=base_mask;
+
+ end
+ else
+ blend_pix_abgr(p ,cr ,cg ,cb ,alpha ,cover );
+
+ end;
+
+end;
+
+{ abgr32_copy_pixel }
+procedure abgr32_copy_pixel(this : pixel_formats_ptr; x ,y : int; c : aggclr_ptr );
+var
+ p : unsigned_ptr;
+
+begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ order_abgr(p^ ).R:=c.r;
+ order_abgr(p^ ).G:=c.g;
+ order_abgr(p^ ).B:=c.b;
+ order_abgr(p^ ).A:=c.a;
+
+end;
+
+{ abgr32_blend_pixel }
+procedure abgr32_blend_pixel(this : pixel_formats_ptr; x ,y : int; c : aggclr_ptr; cover : int8u );
+begin
+ copy_or_blend_pix_abgr(
+ unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) ) ,
+ c.r ,c.g ,c.b ,c.a ,cover );
+
+end;
+
+{ abgr32_pixel }
+function abgr32_pixel(this : pixel_formats_ptr; x ,y : int ) : aggclr;
+var
+ p : unsigned_ptr;
+
+begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ result.ConstrInt(
+ order_abgr(p^ ).R ,
+ order_abgr(p^ ).G ,
+ order_abgr(p^ ).B ,
+ order_abgr(p^ ).A );
+
+end;
+
+{ abgr32_copy_hline }
+procedure abgr32_copy_hline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr );
+var
+ p : int8u_ptr;
+ v : unsigned;
+
+begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ order_abgr(v ).R:=c.r;
+ order_abgr(v ).G:=c.g;
+ order_abgr(v ).B:=c.b;
+ order_abgr(v ).A:=c.a;
+
+ if len > 0 then
+ repeat
+ unsigned(pointer(p )^ ):=v;
+
+ inc(ptrcomp(p ) ,4 );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ abgr32_copy_vline }
+procedure abgr32_copy_vline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr );
+var
+ p : unsigned_ptr;
+ v : unsigned;
+
+begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ order_abgr(v ).R:=c.r;
+ order_abgr(v ).G:=c.g;
+ order_abgr(v ).B:=c.b;
+ order_abgr(v ).A:=c.a;
+
+ if len > 0 then
+ repeat
+ p^:=v;
+ p :=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ abgr32_blend_hline }
+procedure abgr32_blend_hline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+var
+ p : unsigned_ptr;
+ v : unsigned;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_abgr(v ).R:=c.r;
+ order_abgr(v ).G:=c.g;
+ order_abgr(v ).B:=c.b;
+ order_abgr(v ).A:=c.a;
+
+ repeat
+ p^:=v;
+
+ inc(ptrcomp(p ) ,sizeof(unsigned ) );
+ dec(len );
+
+ until len = 0;
+
+ end
+ else
+ if cover = 255 then
+ repeat
+ blend_pix_abgr(p ,c.r ,c.g ,c.b ,alpha );
+
+ inc(ptrcomp(p ) ,sizeof(unsigned ) );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ blend_pix_abgr(p ,c.r ,c.g ,c.b ,alpha ,cover );
+
+ inc(ptrcomp(p ) ,sizeof(unsigned ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ abgr32_blend_vline }
+procedure abgr32_blend_vline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+var
+ p : unsigned_ptr;
+ v : unsigned;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_abgr(v ).R:=c.r;
+ order_abgr(v ).G:=c.g;
+ order_abgr(v ).B:=c.b;
+ order_abgr(v ).A:=c.a;
+
+ repeat
+ p^:=v;
+ p :=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ until len = 0;
+
+ end
+ else
+ if cover = 255 then
+ repeat
+ blend_pix_abgr(p ,c.r ,c.g ,c.b ,alpha );
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ blend_pix_abgr(p ,c.r ,c.g ,c.b ,alpha ,cover );
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ abgr32_blend_solid_hspan }
+procedure abgr32_blend_solid_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+var
+ p : unsigned_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ repeat
+ alpha:=(c.a * (covers^ + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_abgr(p^ ).R:=c.r;
+ order_abgr(p^ ).G:=c.g;
+ order_abgr(p^ ).B:=c.b;
+ order_abgr(p^ ).A:=base_mask;
+
+ end
+ else
+ blend_pix_abgr(p ,c.r ,c.g ,c.b ,alpha ,covers^ );
+
+ inc(ptrcomp(p ) ,4 );
+ inc(ptrcomp(covers ) );
+
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ abgr32_blend_solid_vspan }
+procedure abgr32_blend_solid_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+var
+ p : unsigned_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ repeat
+ alpha:=(c.a * (covers^ + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_abgr(p^ ).R:=c.r;
+ order_abgr(p^ ).G:=c.g;
+ order_abgr(p^ ).B:=c.b;
+ order_abgr(p^ ).A:=base_mask;
+
+ end
+ else
+ blend_pix_abgr(p ,c.r ,c.g ,c.b ,alpha ,covers^ );
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ abgr32_blend_color_hspan }
+procedure abgr32_blend_color_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+var
+ p : unsigned_ptr;
+
+begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ if covers <> NIL then
+ repeat
+ copy_or_blend_pix_abgr(p ,colors.r ,colors.g ,colors.b ,colors.a ,covers^ );
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+ inc(ptrcomp(p ) ,4 );
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0
+ else
+ if cover = 255 then
+ repeat
+ copy_or_blend_pix_abgr(p ,colors.r ,colors.g ,colors.b ,colors.a );
+
+ inc(ptrcomp(p ) ,4 );
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ copy_or_blend_pix_abgr(p ,colors.r ,colors.g ,colors.b ,colors.a ,cover );
+
+ inc(ptrcomp(p ) ,4 );
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ abgr32_blend_color_vspan }
+procedure abgr32_blend_color_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+var
+ p : unsigned_ptr;
+
+begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ if covers <> NIL then
+ repeat
+ copy_or_blend_pix_abgr(
+ p ,
+ colors.r ,
+ colors.g ,
+ colors.b ,
+ colors.a ,
+ covers^ );
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0
+ else
+ if cover = 255 then
+ repeat
+ copy_or_blend_pix_abgr(
+ p ,
+ colors.r ,
+ colors.g ,
+ colors.b ,
+ colors.a );
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ copy_or_blend_pix_abgr(
+ p ,
+ colors.r ,
+ colors.g ,
+ colors.b ,
+ colors.a ,
+ cover );
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ abgr32_blend_from }
+procedure abgr32_blend_from(this : pixel_formats_ptr; from : pixel_formats_ptr; psrc_ : int8u_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ psrc ,pdst : unsigned_ptr;
+
+ incp : int;
+
+begin
+ psrc:=unsigned_ptr(psrc_ );
+ pdst:=unsigned_ptr(ptrcomp(this.m_rbuf.row(ydst ) ) + (xdst shl 2 ) * sizeof(int8u ) );
+ incp:=4;
+
+ if ptrcomp(xdst ) > ptrcomp(xsrc ) then
+ begin
+ inc(ptrcomp(psrc ) ,((len - 1 ) shl 2 ) * sizeof(int8u ) );
+ inc(ptrcomp(pdst ) ,((len - 1 ) shl 2 ) * sizeof(int8u ) );
+
+ incp:=-4;
+
+ end;
+
+ if cover = 255 then
+ repeat
+ copy_or_blend_pix_abgr(
+ pdst ,
+ order_abgr(psrc^ ).R ,
+ order_abgr(psrc^ ).G ,
+ order_abgr(psrc^ ).B ,
+ order_abgr(psrc^ ).A );
+
+ inc(ptrcomp(psrc ) ,incp );
+ inc(ptrcomp(pdst ) ,incp );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ copy_or_blend_pix_abgr(
+ pdst ,
+ order_abgr(psrc^ ).R ,
+ order_abgr(psrc^ ).G ,
+ order_abgr(psrc^ ).B ,
+ order_abgr(psrc^ ).A ,
+ cover );
+
+ inc(ptrcomp(psrc ) ,incp );
+ inc(ptrcomp(pdst ) ,incp );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ abgr32_copy_color_hspan }
+procedure abgr32_copy_color_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr );
+var
+ p : unsigned_ptr;
+
+begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ repeat
+ order_abgr(pointer(p )^ ).R:=colors.r;
+ order_abgr(pointer(p )^ ).G:=colors.g;
+ order_abgr(pointer(p )^ ).B:=colors.b;
+ order_abgr(pointer(p )^ ).A:=colors.a;
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(ptrcomp(p ) ,4 );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ abgr32_copy_color_vspan }
+procedure abgr32_copy_color_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr );
+var
+ p : unsigned_ptr;
+
+begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ repeat
+ order_abgr(pointer(p )^ ).R:=colors.r;
+ order_abgr(pointer(p )^ ).G:=colors.g;
+ order_abgr(pointer(p )^ ).B:=colors.b;
+ order_abgr(pointer(p )^ ).A:=colors.a;
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ abgr32_blend_from_color }
+procedure abgr32_blend_from_color(this : pixel_formats_ptr; from : pixel_formats_ptr; color : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ ppsz : unsigned;
+
+ psrc : int8u_ptr;
+ pdst : unsigned_ptr;
+
+begin
+ ppsz:=from._pix_width;
+ psrc:=from.row_ptr(ysrc );
+
+ if psrc <> NIL then
+ begin
+ pdst:=unsigned_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + (xdst shl 2 ) );
+
+ repeat
+ copy_or_blend_pix_abgr(
+ pdst ,color.r, color.g, color.b, color.a,
+ shr_int32(psrc^ * cover + base_mask ,base_shift ) );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,4 );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ abgr32_blend_from_lut }
+procedure abgr32_blend_from_lut(this : pixel_formats_ptr; from : pixel_formats_ptr; color_lut : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ ppsz : unsigned;
+
+ psrc : int8u_ptr;
+ pdst : unsigned_ptr;
+
+ color : aggclr_ptr;
+
+begin
+ ppsz:=from._pix_width;
+ psrc:=from.row_ptr(ysrc );
+
+ if psrc <> NIL then
+ begin
+ pdst:=unsigned_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + (xdst shl 2 ) );
+
+ if cover = 255 then
+ repeat
+ color:=aggclr_ptr(ptrcomp(color_lut ) + psrc^ * sizeof(aggclr ) );
+
+ copy_or_blend_pix_abgr(pdst ,color.r, color.g, color.b, color.a );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,4 );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ color:=aggclr_ptr(ptrcomp(color_lut ) + psrc^ * sizeof(aggclr ) );
+
+ copy_or_blend_pix_abgr(pdst ,color.r, color.g, color.b, color.a ,cover );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,4 );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
diff --git a/src/corelib/render/software/pf_abgr32_pre.inc b/src/corelib/render/software/pf_abgr32_pre.inc
new file mode 100644
index 00000000..922b3175
--- /dev/null
+++ b/src/corelib/render/software/pf_abgr32_pre.inc
@@ -0,0 +1,489 @@
+//
+// AggPas 2.4 RM3 pixel format definition file
+//
+{ blend_pix_abgr_pre }
+procedure blend_pix_abgr_pre(p : unsigned_ptr; cr ,cg ,cb ,alpha : unsigned ); overload;
+begin
+ alpha:=base_mask - alpha;
+
+ order_abgr(p^ ).R:=int8u(((order_abgr(p^ ).R * alpha) shr base_shift ) + cr );
+ order_abgr(p^ ).G:=int8u(((order_abgr(p^ ).G * alpha) shr base_shift ) + cg );
+ order_abgr(p^ ).B:=int8u(((order_abgr(p^ ).B * alpha) shr base_shift ) + cb );
+ order_abgr(p^ ).A:=int8u(base_mask - ((alpha * (base_mask - order_abgr(p^ ).A ) ) shr base_shift) );
+
+end;
+
+{ blend_pix_abgr_pre }
+procedure blend_pix_abgr_pre(p : unsigned_ptr; cr ,cg ,cb ,alpha ,cover : unsigned ); overload;
+begin
+ alpha:=base_mask - alpha;
+ cover:=(cover + 1 ) shl (base_shift - 8 );
+
+ order_abgr(p^ ).R:=int8u((order_abgr(p^ ).R * alpha + cr * cover ) shr base_shift );
+ order_abgr(p^ ).G:=int8u((order_abgr(p^ ).G * alpha + cg * cover ) shr base_shift );
+ order_abgr(p^ ).B:=int8u((order_abgr(p^ ).B * alpha + cb * cover ) shr base_shift );
+ order_abgr(p^ ).A:=int8u(base_mask - ((alpha * (base_mask - order_abgr(p^ ).A ) ) shr base_shift ) );
+
+end;
+
+{ copy_or_blend_pix_abgr_pre }
+procedure copy_or_blend_pix_abgr_pre(p : unsigned_ptr; cr ,cg ,cb ,alpha : unsigned ); overload;
+begin
+ if alpha <> 0 then
+ if alpha = base_mask then
+ begin
+ order_abgr(p^ ).R:=cr;
+ order_abgr(p^ ).G:=cg;
+ order_abgr(p^ ).B:=cb;
+ order_abgr(p^ ).A:=base_mask;
+
+ end
+ else
+ blend_pix_abgr_pre(p ,cr ,cg ,cb ,alpha );
+
+end;
+
+{ copy_or_blend_pix_abgr_pre }
+procedure copy_or_blend_pix_abgr_pre(p : unsigned_ptr; cr ,cg ,cb ,alpha ,cover : unsigned ); overload;
+begin
+ if cover = 255 then
+ copy_or_blend_pix_abgr_pre(p ,cr ,cg ,cb ,alpha )
+ else
+ if alpha <> 0 then
+ begin
+ alpha:=(alpha * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_abgr(p^ ).R:=cr;
+ order_abgr(p^ ).G:=cg;
+ order_abgr(p^ ).B:=cb;
+ order_abgr(p^ ).A:=base_mask;
+
+ end
+ else
+ blend_pix_abgr_pre(p ,cr ,cg ,cb ,alpha ,cover );
+
+ end;
+
+end;
+
+{ abgr32_pre_blend_pixel }
+procedure abgr32_pre_blend_pixel(this : pixel_formats_ptr; x ,y : int; c : aggclr_ptr; cover : int8u );
+begin
+ copy_or_blend_pix_abgr_pre(
+ unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) ) ,
+ c.r ,c.g ,c.b ,c.a ,cover );
+
+end;
+
+{ abgr32_pre_blend_hline }
+procedure abgr32_pre_blend_hline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+var
+ p : unsigned_ptr;
+ v : unsigned;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_abgr(v ).R:=c.r;
+ order_abgr(v ).G:=c.g;
+ order_abgr(v ).B:=c.b;
+ order_abgr(v ).A:=c.a;
+
+ repeat
+ p^:=v;
+
+ inc(ptrcomp(p ) ,sizeof(unsigned ) );
+ dec(len );
+
+ until len = 0;
+
+ end
+ else
+ if cover = 255 then
+ repeat
+ blend_pix_abgr_pre(p ,c.r ,c.g ,c.b ,alpha );
+
+ inc(ptrcomp(p ) ,sizeof(unsigned ) );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ blend_pix_abgr_pre(p ,c.r ,c.g ,c.b ,alpha ,cover );
+
+ inc(ptrcomp(p ) ,sizeof(unsigned ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ abgr32_pre_blend_vline }
+procedure abgr32_pre_blend_vline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+var
+ p : unsigned_ptr;
+ v : unsigned;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_abgr(v ).R:=c.r;
+ order_abgr(v ).G:=c.g;
+ order_abgr(v ).B:=c.b;
+ order_abgr(v ).A:=c.a;
+
+ repeat
+ p^:=v;
+ p :=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ until len = 0;
+
+ end
+ else
+ if cover = 255 then
+ repeat
+ blend_pix_abgr_pre(p ,c.r ,c.g ,c.b ,alpha );
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ blend_pix_abgr_pre(p ,c.r ,c.g ,c.b ,alpha ,cover );
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ abgr32_pre_blend_solid_hspan }
+procedure abgr32_pre_blend_solid_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+var
+ p : unsigned_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ repeat
+ alpha:=(c.a * (covers^ + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_abgr(p^ ).R:=c.r;
+ order_abgr(p^ ).G:=c.g;
+ order_abgr(p^ ).B:=c.b;
+ order_abgr(p^ ).A:=base_mask;
+
+ end
+ else
+ blend_pix_abgr_pre(p ,c.r ,c.g ,c.b ,alpha ,covers^ );
+
+ inc(ptrcomp(p ) ,4 );
+ inc(ptrcomp(covers ) );
+
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ abgr32_pre_blend_solid_vspan }
+procedure abgr32_pre_blend_solid_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+var
+ p : unsigned_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ repeat
+ alpha:=(c.a * (covers^ + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_abgr(p^ ).R:=c.r;
+ order_abgr(p^ ).G:=c.g;
+ order_abgr(p^ ).B:=c.b;
+ order_abgr(p^ ).A:=base_mask;
+
+ end
+ else
+ blend_pix_abgr_pre(p ,c.r ,c.g ,c.b ,alpha ,covers^ );
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ abgr32_pre_blend_color_hspan }
+procedure abgr32_pre_blend_color_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+var
+ p : unsigned_ptr;
+
+begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ if covers <> NIL then
+ repeat
+ copy_or_blend_pix_abgr_pre(p ,colors.r ,colors.g ,colors.b ,colors.a ,covers^ );
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+ inc(ptrcomp(p ) ,4 );
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0
+ else
+ if cover = 255 then
+ repeat
+ copy_or_blend_pix_abgr_pre(p ,colors.r ,colors.g ,colors.b ,colors.a );
+
+ inc(ptrcomp(p ) ,4 );
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ copy_or_blend_pix_abgr_pre(p ,colors.r ,colors.g ,colors.b ,colors.a ,cover );
+
+ inc(ptrcomp(p ) ,4 );
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ abgr32_pre_blend_color_vspan }
+procedure abgr32_pre_blend_color_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+var
+ p : unsigned_ptr;
+
+begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ if covers <> NIL then
+ repeat
+ copy_or_blend_pix_abgr_pre(
+ p ,
+ colors.r ,
+ colors.g ,
+ colors.b ,
+ colors.a ,
+ covers^ );
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0
+ else
+ if cover = 255 then
+ repeat
+ copy_or_blend_pix_abgr_pre(
+ p ,
+ colors.r ,
+ colors.g ,
+ colors.b ,
+ colors.a );
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ copy_or_blend_pix_abgr_pre(
+ p ,
+ colors.r ,
+ colors.g ,
+ colors.b ,
+ colors.a ,
+ cover );
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ abgr32_pre_blend_from }
+procedure abgr32_pre_blend_from(this : pixel_formats_ptr; from : pixel_formats_ptr; psrc_ : int8u_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ psrc ,pdst : unsigned_ptr;
+
+ incp : int;
+
+begin
+ psrc:=unsigned_ptr(psrc_ );
+ pdst:=unsigned_ptr(ptrcomp(this.m_rbuf.row(ydst ) ) + (xdst shl 2 ) * sizeof(int8u ) );
+ incp:=4;
+
+ if ptrcomp(xdst ) > ptrcomp(xsrc ) then
+ begin
+ inc(ptrcomp(psrc ) ,((len - 1 ) shl 2 ) * sizeof(int8u ) );
+ inc(ptrcomp(pdst ) ,((len - 1 ) shl 2 ) * sizeof(int8u ) );
+
+ incp:=-4;
+
+ end;
+
+ if cover = 255 then
+ repeat
+ copy_or_blend_pix_abgr_pre(
+ pdst ,
+ order_abgr(psrc^ ).R ,
+ order_abgr(psrc^ ).G ,
+ order_abgr(psrc^ ).B ,
+ order_abgr(psrc^ ).A );
+
+ inc(ptrcomp(psrc ) ,incp );
+ inc(ptrcomp(pdst ) ,incp );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ copy_or_blend_pix_abgr_pre(
+ pdst ,
+ order_abgr(psrc^ ).R ,
+ order_abgr(psrc^ ).G ,
+ order_abgr(psrc^ ).B ,
+ order_abgr(psrc^ ).A ,
+ cover );
+
+ inc(ptrcomp(psrc ) ,incp );
+ inc(ptrcomp(pdst ) ,incp );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ abgr32_pre_blend_from_color }
+procedure abgr32_pre_blend_from_color(this : pixel_formats_ptr; from : pixel_formats_ptr; color : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ ppsz : unsigned;
+
+ psrc : int8u_ptr;
+ pdst : unsigned_ptr;
+
+begin
+ ppsz:=from._pix_width;
+ psrc:=from.row_ptr(ysrc );
+
+ if psrc <> NIL then
+ begin
+ pdst:=unsigned_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + (xdst shl 2 ) );
+
+ repeat
+ copy_or_blend_pix_abgr_pre(
+ pdst ,color.r, color.g, color.b, color.a,
+ shr_int32(psrc^ * cover + base_mask ,base_shift ) );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,4 );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ abgr32_pre_blend_from_lut }
+procedure abgr32_pre_blend_from_lut(this : pixel_formats_ptr; from : pixel_formats_ptr; color_lut : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ ppsz : unsigned;
+
+ psrc : int8u_ptr;
+ pdst : unsigned_ptr;
+
+ color : aggclr_ptr;
+
+begin
+ ppsz:=from._pix_width;
+ psrc:=from.row_ptr(ysrc );
+
+ if psrc <> NIL then
+ begin
+ pdst:=unsigned_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + (xdst shl 2 ) );
+
+ if cover = 255 then
+ repeat
+ color:=aggclr_ptr(ptrcomp(color_lut ) + psrc^ * sizeof(aggclr ) );
+
+ copy_or_blend_pix_abgr_pre(pdst ,color.r, color.g, color.b, color.a );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,4 );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ color:=aggclr_ptr(ptrcomp(color_lut ) + psrc^ * sizeof(aggclr ) );
+
+ copy_or_blend_pix_abgr_pre(pdst ,color.r, color.g, color.b, color.a ,cover );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,4 );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
diff --git a/src/corelib/render/software/pf_alpha32.inc b/src/corelib/render/software/pf_alpha32.inc
new file mode 100644
index 00000000..8d10336b
--- /dev/null
+++ b/src/corelib/render/software/pf_alpha32.inc
@@ -0,0 +1,781 @@
+//
+// AggPas 2.4 RM3 pixel format definition file
+//
+{ alpha32_copy_hline }
+procedure alpha32_copy_hline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr );
+var
+ p : unsigned_ptr;
+ v : unsigned;
+
+begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row_xy(x ,y ,len ) ) + (x shl 2 ) );
+
+ int8u_ptr(ptrcomp(@v ) + this.m_order.R )^:=c.r;
+ int8u_ptr(ptrcomp(@v ) + this.m_order.G )^:=c.g;
+ int8u_ptr(ptrcomp(@v ) + this.m_order.B )^:=c.b;
+ int8u_ptr(ptrcomp(@v ) + this.m_order.A )^:=c.a;
+
+ if len > 0 then
+ repeat
+ p^:=v;
+
+ inc(ptrcomp(p ) ,4 );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ alpha32_blend_solid_hspan }
+procedure alpha32_blend_solid_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+var
+ p : unsigned_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row_xy(x ,y ,len ) ) + (x shl 2 ) );
+
+ repeat
+ alpha:=(c.a * (covers^ + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=c.r;
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=c.g;
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=c.b;
+ int8u_ptr(ptrcomp(p ) + this.m_order.A )^:=base_mask;
+
+ end
+ else
+ case this.m_order.R of
+ 0 : blend_pix_rgba(p ,c.r ,c.g ,c.b ,alpha ,covers^ );
+ 1 : blend_pix_argb(p ,c.r ,c.g ,c.b ,alpha ,covers^ );
+ 2 : blend_pix_bgra(p ,c.r ,c.g ,c.b ,alpha ,covers^ );
+ 3 : blend_pix_abgr(p ,c.r ,c.g ,c.b ,alpha ,covers^ );
+
+ end;
+
+ inc(ptrcomp(p ) ,4 );
+ inc(ptrcomp(covers ) );
+
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ alpha32_blend_color_hspan }
+procedure alpha32_blend_color_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+var
+ p : unsigned_ptr;
+
+begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row_xy(x ,y ,len ) ) + (x shl 2 ) );
+
+ if covers <> NIL then
+ repeat
+ case this.m_order.R of
+ 0 : copy_or_blend_pix_rgba(p ,colors.r ,colors.g ,colors.b ,colors.a ,covers^ );
+ 1 : copy_or_blend_pix_argb(p ,colors.r ,colors.g ,colors.b ,colors.a ,covers^ );
+ 2 : copy_or_blend_pix_bgra(p ,colors.r ,colors.g ,colors.b ,colors.a ,covers^ );
+ 3 : copy_or_blend_pix_abgr(p ,colors.r ,colors.g ,colors.b ,colors.a ,covers^ );
+
+ end;
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+ inc(ptrcomp(p ) ,4 );
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0
+ else
+ if cover = 255 then
+ repeat
+ case this.m_order.R of
+ 0 : copy_or_blend_pix_rgba(p ,colors.r ,colors.g ,colors.b ,colors.a );
+ 1 : copy_or_blend_pix_argb(p ,colors.r ,colors.g ,colors.b ,colors.a );
+ 2 : copy_or_blend_pix_bgra(p ,colors.r ,colors.g ,colors.b ,colors.a );
+ 3 : copy_or_blend_pix_abgr(p ,colors.r ,colors.g ,colors.b ,colors.a );
+
+ end;
+
+ inc(ptrcomp(p ) ,4 );
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ case this.m_order.R of
+ 0 : copy_or_blend_pix_rgba(p ,colors.r ,colors.g ,colors.b ,colors.a ,cover );
+ 1 : copy_or_blend_pix_argb(p ,colors.r ,colors.g ,colors.b ,colors.a ,cover );
+ 2 : copy_or_blend_pix_bgra(p ,colors.r ,colors.g ,colors.b ,colors.a ,cover );
+ 3 : copy_or_blend_pix_abgr(p ,colors.r ,colors.g ,colors.b ,colors.a ,cover );
+
+ end;
+
+ inc(ptrcomp(p ) ,4 );
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ alpha32_blend_from }
+procedure alpha32_blend_from(this : pixel_formats_ptr; from : pixel_formats_ptr; psrc_ : int8u_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ psrc ,pdst : unsigned_ptr;
+
+ incp : int;
+
+begin
+ psrc:=unsigned_ptr(psrc_ );
+ pdst:=unsigned_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + (xdst shl 2 ) * sizeof(int8u ) );
+ incp:=4;
+
+ if ptrcomp(xdst ) > ptrcomp(xsrc ) then
+ begin
+ inc(ptrcomp(psrc ) ,((len - 1 ) shl 2 ) * sizeof(int8u ) );
+ inc(ptrcomp(pdst ) ,((len - 1 ) shl 2 ) * sizeof(int8u ) );
+
+ incp:=-4;
+
+ end;
+
+ if cover = 255 then
+ repeat
+ case this.m_order.R of
+ 0 : copy_or_blend_pix_rgba(
+ pdst ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.R )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.G )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.B )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.A )^ );
+
+ 1 : copy_or_blend_pix_argb(
+ pdst ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.R )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.G )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.B )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.A )^ );
+
+ 2 : copy_or_blend_pix_bgra(
+ pdst ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.R )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.G )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.B )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.A )^ );
+
+ 3 : copy_or_blend_pix_abgr(
+ pdst ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.R )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.G )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.B )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.A )^ );
+
+ end;
+
+ inc(ptrcomp(psrc ) ,incp );
+ inc(ptrcomp(pdst ) ,incp );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ case this.m_order.R of
+ 0 : copy_or_blend_pix_rgba(
+ pdst ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.R )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.G )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.B )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.A )^ ,
+ cover );
+
+ 1 : copy_or_blend_pix_argb(
+ pdst ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.R )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.G )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.B )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.A )^ ,
+ cover );
+
+ 2 : copy_or_blend_pix_bgra(
+ pdst ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.R )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.G )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.B )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.A )^ ,
+ cover );
+
+ 3 : copy_or_blend_pix_abgr(
+ pdst ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.R )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.G )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.B )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.A )^ ,
+ cover );
+
+ end;
+
+ inc(ptrcomp(psrc ) ,incp );
+ inc(ptrcomp(pdst ) ,incp );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ alpha32_pixel }
+function alpha32_pixel(this : pixel_formats_ptr; x ,y : int ) : aggclr;
+var
+ p : unsigned_ptr;
+
+begin
+ p:=unsigned_ptr(this.m_rbuf.row(y ) );
+
+ if p <> NIL then
+ begin
+ inc(ptrcomp(p ) ,x shl 2 );
+
+ result.ConstrInt(
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^ ,
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^ ,
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^ ,
+ int8u_ptr(ptrcomp(p ) + this.m_order.A )^ );
+
+ end
+ else
+ result.Construct;
+
+end;
+
+{ alpha32_copy_pixel }
+procedure alpha32_copy_pixel(this : pixel_formats_ptr; x ,y : int; c : aggclr_ptr );
+var
+ p : unsigned_ptr;
+
+begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row_xy(x ,y ,1 ) ) + (x shl 2 ) );
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=c.r;
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=c.g;
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=c.b;
+ int8u_ptr(ptrcomp(p ) + this.m_order.A )^:=c.a;
+
+end;
+
+{ alpha32_blend_pixel }
+procedure alpha32_blend_pixel(this : pixel_formats_ptr; x ,y : int; c : aggclr_ptr; cover : int8u );
+begin
+ case this.m_order.R of
+ 0 : copy_or_blend_pix_rgba(
+ unsigned_ptr(ptrcomp(this.m_rbuf.row_xy(x ,y ,1 ) ) + (x shl 2 ) ) ,
+ c.r ,c.g ,c.b ,c.a ,cover );
+
+ 1 : copy_or_blend_pix_argb(
+ unsigned_ptr(ptrcomp(this.m_rbuf.row_xy(x ,y ,1 ) ) + (x shl 2 ) ) ,
+ c.r ,c.g ,c.b ,c.a ,cover );
+
+ 2 : copy_or_blend_pix_bgra(
+ unsigned_ptr(ptrcomp(this.m_rbuf.row_xy(x ,y ,1 ) ) + (x shl 2 ) ) ,
+ c.r ,c.g ,c.b ,c.a ,cover );
+
+ 3 : copy_or_blend_pix_abgr(
+ unsigned_ptr(ptrcomp(this.m_rbuf.row_xy(x ,y ,1 ) ) + (x shl 2 ) ) ,
+ c.r ,c.g ,c.b ,c.a ,cover );
+
+ end;
+
+end;
+
+{ alpha32_copy_vline }
+procedure alpha32_copy_vline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr );
+var
+ p : unsigned_ptr;
+ v : unsigned;
+
+begin
+ int8u_ptr(ptrcomp(@v ) + this.m_order.R )^:=c.r;
+ int8u_ptr(ptrcomp(@v ) + this.m_order.G )^:=c.g;
+ int8u_ptr(ptrcomp(@v ) + this.m_order.B )^:=c.b;
+ int8u_ptr(ptrcomp(@v ) + this.m_order.A )^:=c.a;
+
+ if len > 0 then
+ repeat
+ p :=unsigned_ptr(ptrcomp(this.m_rbuf.row_xy(x ,y ,1 ) ) + (x shl 2 ) );
+ p^:=v;
+
+ inc(y );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ alpha32_blend_hline }
+procedure alpha32_blend_hline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+var
+ p : unsigned_ptr;
+ v : unsigned;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row_xy(x ,y ,len ) ) + (x shl 2 ) );
+
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ int8u_ptr(ptrcomp(@v ) + this.m_order.R )^:=c.r;
+ int8u_ptr(ptrcomp(@v ) + this.m_order.G )^:=c.g;
+ int8u_ptr(ptrcomp(@v ) + this.m_order.B )^:=c.b;
+ int8u_ptr(ptrcomp(@v ) + this.m_order.A )^:=c.a;
+
+ repeat
+ p^:=v;
+
+ inc(ptrcomp(p ) ,sizeof(unsigned ) );
+ dec(len );
+
+ until len = 0;
+
+ end
+ else
+ if cover = 255 then
+ repeat
+ case this.m_order.R of
+ 0 : blend_pix_rgba(p ,c.r ,c.g ,c.b ,alpha );
+ 1 : blend_pix_argb(p ,c.r ,c.g ,c.b ,alpha );
+ 2 : blend_pix_bgra(p ,c.r ,c.g ,c.b ,alpha );
+ 3 : blend_pix_abgr(p ,c.r ,c.g ,c.b ,alpha );
+
+ end;
+
+ inc(ptrcomp(p ) ,sizeof(unsigned ) );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ case this.m_order.R of
+ 0 : blend_pix_rgba(p ,c.r ,c.g ,c.b ,alpha ,cover );
+ 1 : blend_pix_argb(p ,c.r ,c.g ,c.b ,alpha ,cover );
+ 2 : blend_pix_bgra(p ,c.r ,c.g ,c.b ,alpha ,cover );
+ 3 : blend_pix_abgr(p ,c.r ,c.g ,c.b ,alpha ,cover );
+
+ end;
+
+ inc(ptrcomp(p ) ,sizeof(unsigned ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ alpha32_blend_vline }
+procedure alpha32_blend_vline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+var
+ p : unsigned_ptr;
+ v : unsigned;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ int8u_ptr(ptrcomp(@v ) + this.m_order.R )^:=c.r;
+ int8u_ptr(ptrcomp(@v ) + this.m_order.G )^:=c.g;
+ int8u_ptr(ptrcomp(@v ) + this.m_order.B )^:=c.b;
+ int8u_ptr(ptrcomp(@v ) + this.m_order.A )^:=c.a;
+
+ repeat
+ p :=unsigned_ptr(ptrcomp(this.m_rbuf.row_xy(x ,y ,1 ) ) + (x shl 2 ) );
+ p^:=v;
+
+ inc(y );
+ dec(len );
+
+ until len = 0;
+
+ end
+ else
+ if cover = 255 then
+ repeat
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row_xy(x ,y ,1 ) ) + (x shl 2 ) );
+
+ case this.m_order.R of
+ 0 : blend_pix_rgba(p ,c.r ,c.g ,c.b ,alpha );
+ 1 : blend_pix_argb(p ,c.r ,c.g ,c.b ,alpha );
+ 2 : blend_pix_bgra(p ,c.r ,c.g ,c.b ,alpha );
+ 3 : blend_pix_abgr(p ,c.r ,c.g ,c.b ,alpha );
+
+ end;
+
+ inc(y );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row_xy(x ,y ,1 ) ) + (x shl 2 ) );
+
+ case this.m_order.R of
+ 0 : blend_pix_rgba(p ,c.r ,c.g ,c.b ,alpha ,cover );
+ 1 : blend_pix_argb(p ,c.r ,c.g ,c.b ,alpha ,cover );
+ 2 : blend_pix_bgra(p ,c.r ,c.g ,c.b ,alpha ,cover );
+ 3 : blend_pix_abgr(p ,c.r ,c.g ,c.b ,alpha ,cover );
+
+ end;
+
+ inc(y );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ alpha32_blend_solid_vspan }
+procedure alpha32_blend_solid_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+var
+ p : unsigned_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ repeat
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row_xy(x ,y ,1 ) ) + (x shl 2 ) );
+
+ alpha:=(c.a * (covers^ + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=c.r;
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=c.g;
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=c.b;
+ int8u_ptr(ptrcomp(p ) + this.m_order.A )^:=base_mask;
+
+ end
+ else
+ case this.m_order.R of
+ 0 : blend_pix_rgba(p ,c.r ,c.g ,c.b ,alpha ,covers^ );
+ 1 : blend_pix_argb(p ,c.r ,c.g ,c.b ,alpha ,covers^ );
+ 2 : blend_pix_bgra(p ,c.r ,c.g ,c.b ,alpha ,covers^ );
+ 3 : blend_pix_abgr(p ,c.r ,c.g ,c.b ,alpha ,covers^ );
+
+ end;
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+ inc(y );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ alpha32_blend_color_vspan }
+procedure alpha32_blend_color_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+var
+ p : unsigned_ptr;
+
+begin
+ if covers <> NIL then
+ repeat
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row_xy(x ,y ,1 ) ) + (x shl 2 ) );
+
+ case this.m_order.R of
+ 0 : copy_or_blend_pix_rgba(
+ p ,
+ colors.r ,
+ colors.g ,
+ colors.b ,
+ colors.a ,
+ covers^ );
+
+ 1 : copy_or_blend_pix_argb(
+ p ,
+ colors.r ,
+ colors.g ,
+ colors.b ,
+ colors.a ,
+ covers^ );
+
+ 2 : copy_or_blend_pix_bgra(
+ p ,
+ colors.r ,
+ colors.g ,
+ colors.b ,
+ colors.a ,
+ covers^ );
+
+ 3 : copy_or_blend_pix_abgr(
+ p ,
+ colors.r ,
+ colors.g ,
+ colors.b ,
+ colors.a ,
+ covers^ );
+
+ end;
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(y );
+ dec(len );
+
+ until len = 0
+ else
+ if cover = 255 then
+ repeat
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row_xy(x ,y ,1 ) ) + (x shl 2 ) );
+
+ case this.m_order.R of
+ 0 : copy_or_blend_pix_rgba(
+ p ,
+ colors.r ,
+ colors.g ,
+ colors.b ,
+ colors.a );
+
+ 1 : copy_or_blend_pix_argb(
+ p ,
+ colors.r ,
+ colors.g ,
+ colors.b ,
+ colors.a );
+
+ 2 : copy_or_blend_pix_bgra(
+ p ,
+ colors.r ,
+ colors.g ,
+ colors.b ,
+ colors.a );
+
+ 3 : copy_or_blend_pix_abgr(
+ p ,
+ colors.r ,
+ colors.g ,
+ colors.b ,
+ colors.a );
+
+ end;
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(y );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row_xy(x ,y ,1 ) ) + (x shl 2 ) );
+
+ case this.m_order.R of
+ 0 : copy_or_blend_pix_rgba(
+ p ,
+ colors.r ,
+ colors.g ,
+ colors.b ,
+ colors.a ,
+ cover );
+
+ 1 : copy_or_blend_pix_argb(
+ p ,
+ colors.r ,
+ colors.g ,
+ colors.b ,
+ colors.a ,
+ cover );
+
+ 2 : copy_or_blend_pix_bgra(
+ p ,
+ colors.r ,
+ colors.g ,
+ colors.b ,
+ colors.a ,
+ cover );
+
+ 3 : copy_or_blend_pix_abgr(
+ p ,
+ colors.r ,
+ colors.g ,
+ colors.b ,
+ colors.a ,
+ cover );
+
+ end;
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(y );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ alpha32_copy_color_hspan }
+procedure alpha32_copy_color_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr );
+var
+ p : unsigned_ptr;
+
+begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row_xy(x ,y ,len ) ) + (x shl 2 ) );
+
+ repeat
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=colors.r;
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=colors.g;
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=colors.b;
+ int8u_ptr(ptrcomp(p ) + this.m_order.A )^:=colors.a;
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(ptrcomp(p ) ,4 );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ alpha32_copy_color_vspan }
+procedure alpha32_copy_color_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr );
+var
+ p : unsigned_ptr;
+
+begin
+ repeat
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row_xy(x ,y ,1 ) ) + (x shl 2 ) );
+
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=colors.r;
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=colors.g;
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=colors.b;
+ int8u_ptr(ptrcomp(p ) + this.m_order.A )^:=colors.a;
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(y );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ alpha32_blend_from_color }
+procedure alpha32_blend_from_color(this : pixel_formats_ptr; from : pixel_formats_ptr; color : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ ppsz : unsigned;
+
+ psrc : int8u_ptr;
+ pdst : unsigned_ptr;
+
+begin
+ ppsz:=from._pix_width;
+ psrc:=from.row_ptr(ysrc );
+
+ if psrc <> NIL then
+ begin
+ pdst:=unsigned_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + (xdst shl 2 ) );
+
+ repeat
+ case this.m_order.R of
+ 0 : copy_or_blend_pix_rgba(
+ pdst ,color.r, color.g, color.b, color.a,
+ shr_int32(psrc^ * cover + base_mask ,base_shift ) );
+
+ 1 : copy_or_blend_pix_argb(
+ pdst ,color.r, color.g, color.b, color.a,
+ shr_int32(psrc^ * cover + base_mask ,base_shift ) );
+
+ 2 : copy_or_blend_pix_bgra(
+ pdst ,color.r, color.g, color.b, color.a,
+ shr_int32(psrc^ * cover + base_mask ,base_shift ) );
+
+ 3 : copy_or_blend_pix_abgr(
+ pdst ,color.r, color.g, color.b, color.a,
+ shr_int32(psrc^ * cover + base_mask ,base_shift ) );
+
+ end;
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,4 );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ alpha32_blend_from_lut }
+procedure alpha32_blend_from_lut(this : pixel_formats_ptr; from : pixel_formats_ptr; color_lut : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ ppsz : unsigned;
+
+ psrc : int8u_ptr;
+ pdst : unsigned_ptr;
+
+ color : aggclr_ptr;
+
+begin
+ ppsz:=from._pix_width;
+ psrc:=from.row_ptr(ysrc );
+
+ if psrc <> NIL then
+ begin
+ pdst:=unsigned_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + (xdst shl 2 ) );
+
+ if cover = 255 then
+ repeat
+ color:=aggclr_ptr(ptrcomp(color_lut ) + psrc^ * sizeof(aggclr ) );
+
+ case this.m_order.R of
+ 0 : copy_or_blend_pix_rgba(pdst ,color.r, color.g, color.b, color.a );
+ 1 : copy_or_blend_pix_argb(pdst ,color.r, color.g, color.b, color.a );
+ 2 : copy_or_blend_pix_bgra(pdst ,color.r, color.g, color.b, color.a );
+ 3 : copy_or_blend_pix_abgr(pdst ,color.r, color.g, color.b, color.a );
+
+ end;
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,4 );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ color:=aggclr_ptr(ptrcomp(color_lut ) + psrc^ * sizeof(aggclr ) );
+
+ case this.m_order.R of
+ 0 : copy_or_blend_pix_rgba(pdst ,color.r, color.g, color.b, color.a ,cover );
+ 1 : copy_or_blend_pix_argb(pdst ,color.r, color.g, color.b, color.a ,cover );
+ 2 : copy_or_blend_pix_bgra(pdst ,color.r, color.g, color.b, color.a ,cover );
+ 3 : copy_or_blend_pix_abgr(pdst ,color.r, color.g, color.b, color.a ,cover );
+
+ end;
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,4 );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
diff --git a/src/corelib/render/software/pf_argb32.inc b/src/corelib/render/software/pf_argb32.inc
new file mode 100644
index 00000000..455b5e57
--- /dev/null
+++ b/src/corelib/render/software/pf_argb32.inc
@@ -0,0 +1,608 @@
+//
+// AggPas 2.4 RM3 pixel format definition file
+//
+{ blend_pix_argb }
+procedure blend_pix_argb(p : unsigned_ptr; cr ,cg ,cb ,alpha : int; cover : unsigned = 0 );
+var
+ r ,g ,b ,a : int8u;
+
+begin
+ r:=order_argb(p^ ).R;
+ g:=order_argb(p^ ).G;
+ b:=order_argb(p^ ).B;
+ a:=order_argb(p^ ).A;
+
+ order_argb(p^ ).R:=((cr - r ) * alpha + (r shl base_shift ) ) shr base_shift;
+ order_argb(p^ ).G:=((cg - g ) * alpha + (g shl base_shift ) ) shr base_shift;
+ order_argb(p^ ).B:=((cb - b ) * alpha + (b shl base_shift ) ) shr base_shift;
+ order_argb(p^ ).A:=(alpha + a ) - ((alpha * a + base_mask ) shr base_shift );
+
+end;
+
+{ copy_or_blend_pix_argb }
+procedure copy_or_blend_pix_argb(p : unsigned_ptr; cr ,cg ,cb ,alpha : unsigned ); overload;
+begin
+ if alpha <> 0 then
+ if alpha = base_mask then
+ begin
+ order_argb(p^ ).R:=cr;
+ order_argb(p^ ).G:=cg;
+ order_argb(p^ ).B:=cb;
+ order_argb(p^ ).A:=base_mask;
+
+ end
+ else
+ blend_pix_argb(p ,cr ,cg ,cb ,alpha );
+
+end;
+
+{ copy_or_blend_pix_argb }
+procedure copy_or_blend_pix_argb(p : unsigned_ptr; cr ,cg ,cb ,alpha ,cover : unsigned ); overload;
+begin
+ if cover = 255 then
+ copy_or_blend_pix_argb(p ,cr ,cg ,cb ,alpha )
+ else
+ if alpha <> 0 then
+ begin
+ alpha:=(alpha * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_argb(p^ ).R:=cr;
+ order_argb(p^ ).G:=cg;
+ order_argb(p^ ).B:=cb;
+ order_argb(p^ ).A:=base_mask;
+
+ end
+ else
+ blend_pix_argb(p ,cr ,cg ,cb ,alpha ,cover );
+
+ end;
+
+end;
+
+{ argb32_copy_pixel }
+procedure argb32_copy_pixel(this : pixel_formats_ptr; x ,y : int; c : aggclr_ptr );
+var
+ p : unsigned_ptr;
+
+begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ order_argb(p^ ).R:=c.r;
+ order_argb(p^ ).G:=c.g;
+ order_argb(p^ ).B:=c.b;
+ order_argb(p^ ).A:=c.a;
+
+end;
+
+{ argb32_blend_pixel }
+procedure argb32_blend_pixel(this : pixel_formats_ptr; x ,y : int; c : aggclr_ptr; cover : int8u );
+begin
+ copy_or_blend_pix_argb(
+ unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) ) ,
+ c.r ,c.g ,c.b ,c.a ,cover );
+
+end;
+
+{ argb32_pixel }
+function argb32_pixel(this : pixel_formats_ptr; x ,y : int ) : aggclr;
+var
+ p : unsigned_ptr;
+
+begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ result.ConstrInt(
+ order_argb(p^ ).R ,
+ order_argb(p^ ).G ,
+ order_argb(p^ ).B ,
+ order_argb(p^ ).A );
+
+end;
+
+{ argb32_copy_hline }
+procedure argb32_copy_hline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr );
+var
+ p : int8u_ptr;
+ v : unsigned;
+
+begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ order_argb(v ).R:=c.r;
+ order_argb(v ).G:=c.g;
+ order_argb(v ).B:=c.b;
+ order_argb(v ).A:=c.a;
+
+ if len > 0 then
+ repeat
+ unsigned(pointer(p )^ ):=v;
+
+ inc(ptrcomp(p ) ,4 );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ argb32_copy_vline }
+procedure argb32_copy_vline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr );
+var
+ p : unsigned_ptr;
+ v : unsigned;
+
+begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ order_argb(v ).R:=c.r;
+ order_argb(v ).G:=c.g;
+ order_argb(v ).B:=c.b;
+ order_argb(v ).A:=c.a;
+
+ if len > 0 then
+ repeat
+ p^:=v;
+ p :=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ argb32_blend_hline }
+procedure argb32_blend_hline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+var
+ p : unsigned_ptr;
+ v : unsigned;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_argb(v ).R:=c.r;
+ order_argb(v ).G:=c.g;
+ order_argb(v ).B:=c.b;
+ order_argb(v ).A:=c.a;
+
+ repeat
+ p^:=v;
+
+ inc(ptrcomp(p ) ,sizeof(unsigned ) );
+ dec(len );
+
+ until len = 0;
+
+ end
+ else
+ if cover = 255 then
+ repeat
+ blend_pix_argb(p ,c.r ,c.g ,c.b ,alpha );
+
+ inc(ptrcomp(p ) ,sizeof(unsigned ) );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ blend_pix_argb(p ,c.r ,c.g ,c.b ,alpha ,cover );
+
+ inc(ptrcomp(p ) ,sizeof(unsigned ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ argb32_blend_vline }
+procedure argb32_blend_vline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+var
+ p : unsigned_ptr;
+ v : unsigned;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_argb(v ).R:=c.r;
+ order_argb(v ).G:=c.g;
+ order_argb(v ).B:=c.b;
+ order_argb(v ).A:=c.a;
+
+ repeat
+ p^:=v;
+ p :=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ until len = 0;
+
+ end
+ else
+ if cover = 255 then
+ repeat
+ blend_pix_argb(p ,c.r ,c.g ,c.b ,alpha );
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ blend_pix_argb(p ,c.r ,c.g ,c.b ,alpha ,cover );
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ argb32_blend_solid_hspan }
+procedure argb32_blend_solid_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+var
+ p : unsigned_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ repeat
+ alpha:=(c.a * (covers^ + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_argb(p^ ).R:=c.r;
+ order_argb(p^ ).G:=c.g;
+ order_argb(p^ ).B:=c.b;
+ order_argb(p^ ).A:=base_mask;
+
+ end
+ else
+ blend_pix_argb(p ,c.r ,c.g ,c.b ,alpha ,covers^ );
+
+ inc(ptrcomp(p ) ,4 );
+ inc(ptrcomp(covers ) );
+
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ argb32_blend_solid_vspan }
+procedure argb32_blend_solid_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+var
+ p : unsigned_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ repeat
+ alpha:=(c.a * (covers^ + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_argb(p^ ).R:=c.r;
+ order_argb(p^ ).G:=c.g;
+ order_argb(p^ ).B:=c.b;
+ order_argb(p^ ).A:=base_mask;
+
+ end
+ else
+ blend_pix_argb(p ,c.r ,c.g ,c.b ,alpha ,covers^ );
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ argb32_blend_color_hspan }
+procedure argb32_blend_color_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+var
+ p : unsigned_ptr;
+
+begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ if covers <> NIL then
+ repeat
+ copy_or_blend_pix_argb(p ,colors.r ,colors.g ,colors.b ,colors.a ,covers^ );
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+ inc(ptrcomp(p ) ,4 );
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0
+ else
+ if cover = 255 then
+ repeat
+ copy_or_blend_pix_argb(p ,colors.r ,colors.g ,colors.b ,colors.a );
+
+ inc(ptrcomp(p ) ,4 );
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ copy_or_blend_pix_argb(p ,colors.r ,colors.g ,colors.b ,colors.a ,cover );
+
+ inc(ptrcomp(p ) ,4 );
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ argb32_blend_color_vspan }
+procedure argb32_blend_color_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+var
+ p : unsigned_ptr;
+
+begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ if covers <> NIL then
+ repeat
+ copy_or_blend_pix_argb(
+ p ,
+ colors.r ,
+ colors.g ,
+ colors.b ,
+ colors.a ,
+ covers^ );
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0
+ else
+ if cover = 255 then
+ repeat
+ copy_or_blend_pix_argb(
+ p ,
+ colors.r ,
+ colors.g ,
+ colors.b ,
+ colors.a );
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ copy_or_blend_pix_argb(
+ p ,
+ colors.r ,
+ colors.g ,
+ colors.b ,
+ colors.a ,
+ cover );
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ argb32_blend_from }
+procedure argb32_blend_from(this : pixel_formats_ptr; from : pixel_formats_ptr; psrc_ : int8u_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ psrc ,pdst : unsigned_ptr;
+
+ incp : int;
+
+begin
+ psrc:=unsigned_ptr(psrc_ );
+ pdst:=unsigned_ptr(ptrcomp(this.m_rbuf.row(ydst ) ) + (xdst shl 2 ) * sizeof(int8u ) );
+ incp:=4;
+
+ if ptrcomp(xdst ) > ptrcomp(xsrc ) then
+ begin
+ inc(ptrcomp(psrc ) ,((len - 1 ) shl 2 ) * sizeof(int8u ) );
+ inc(ptrcomp(pdst ) ,((len - 1 ) shl 2 ) * sizeof(int8u ) );
+
+ incp:=-4;
+
+ end;
+
+ if cover = 255 then
+ repeat
+ copy_or_blend_pix_argb(
+ pdst ,
+ order_argb(psrc^ ).R ,
+ order_argb(psrc^ ).G ,
+ order_argb(psrc^ ).B ,
+ order_argb(psrc^ ).A );
+
+ inc(ptrcomp(psrc ) ,incp );
+ inc(ptrcomp(pdst ) ,incp );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ copy_or_blend_pix_argb(
+ pdst ,
+ order_argb(psrc^ ).R ,
+ order_argb(psrc^ ).G ,
+ order_argb(psrc^ ).B ,
+ order_argb(psrc^ ).A ,
+ cover );
+
+ inc(ptrcomp(psrc ) ,incp );
+ inc(ptrcomp(pdst ) ,incp );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ argb32_copy_color_hspan }
+procedure argb32_copy_color_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr );
+var
+ p : unsigned_ptr;
+
+begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ repeat
+ order_argb(pointer(p )^ ).R:=colors.r;
+ order_argb(pointer(p )^ ).G:=colors.g;
+ order_argb(pointer(p )^ ).B:=colors.b;
+ order_argb(pointer(p )^ ).A:=colors.a;
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(ptrcomp(p ) ,4 );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ argb32_copy_color_vspan }
+procedure argb32_copy_color_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr );
+var
+ p : unsigned_ptr;
+
+begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ repeat
+ order_argb(pointer(p )^ ).R:=colors.r;
+ order_argb(pointer(p )^ ).G:=colors.g;
+ order_argb(pointer(p )^ ).B:=colors.b;
+ order_argb(pointer(p )^ ).A:=colors.a;
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ argb32_blend_from_color }
+procedure argb32_blend_from_color(this : pixel_formats_ptr; from : pixel_formats_ptr; color : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ ppsz : unsigned;
+
+ psrc : int8u_ptr;
+ pdst : unsigned_ptr;
+
+begin
+ ppsz:=from._pix_width;
+ psrc:=from.row_ptr(ysrc );
+
+ if psrc <> NIL then
+ begin
+ pdst:=unsigned_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + (xdst shl 2 ) );
+
+ repeat
+ copy_or_blend_pix_argb(
+ pdst ,color.r, color.g, color.b, color.a,
+ shr_int32(psrc^ * cover + base_mask ,base_shift ) );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,4 );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ argb32_blend_from_lut }
+procedure argb32_blend_from_lut(this : pixel_formats_ptr; from : pixel_formats_ptr; color_lut : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ ppsz : unsigned;
+
+ psrc : int8u_ptr;
+ pdst : unsigned_ptr;
+
+ color : aggclr_ptr;
+
+begin
+ ppsz:=from._pix_width;
+ psrc:=from.row_ptr(ysrc );
+
+ if psrc <> NIL then
+ begin
+ pdst:=unsigned_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + (xdst shl 2 ) );
+
+ if cover = 255 then
+ repeat
+ color:=aggclr_ptr(ptrcomp(color_lut ) + psrc^ * sizeof(aggclr ) );
+
+ copy_or_blend_pix_argb(pdst ,color.r, color.g, color.b, color.a );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,4 );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ color:=aggclr_ptr(ptrcomp(color_lut ) + psrc^ * sizeof(aggclr ) );
+
+ copy_or_blend_pix_argb(pdst ,color.r, color.g, color.b, color.a ,cover );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,4 );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
diff --git a/src/corelib/render/software/pf_argb32_pre.inc b/src/corelib/render/software/pf_argb32_pre.inc
new file mode 100644
index 00000000..d7eb792b
--- /dev/null
+++ b/src/corelib/render/software/pf_argb32_pre.inc
@@ -0,0 +1,489 @@
+//
+// AggPas 2.4 RM3 pixel format definition file
+//
+{ blend_pix_argb_pre }
+procedure blend_pix_argb_pre(p : unsigned_ptr; cr ,cg ,cb ,alpha : unsigned ); overload;
+begin
+ alpha:=base_mask - alpha;
+
+ order_argb(p^ ).R:=int8u(((order_argb(p^ ).R * alpha) shr base_shift ) + cr );
+ order_argb(p^ ).G:=int8u(((order_argb(p^ ).G * alpha) shr base_shift ) + cg );
+ order_argb(p^ ).B:=int8u(((order_argb(p^ ).B * alpha) shr base_shift ) + cb );
+ order_argb(p^ ).A:=int8u(base_mask - ((alpha * (base_mask - order_argb(p^ ).A ) ) shr base_shift) );
+
+end;
+
+{ blend_pix_argb_pre }
+procedure blend_pix_argb_pre(p : unsigned_ptr; cr ,cg ,cb ,alpha ,cover : unsigned ); overload;
+begin
+ alpha:=base_mask - alpha;
+ cover:=(cover + 1 ) shl (base_shift - 8 );
+
+ order_argb(p^ ).R:=int8u((order_argb(p^ ).R * alpha + cr * cover ) shr base_shift );
+ order_argb(p^ ).G:=int8u((order_argb(p^ ).G * alpha + cg * cover ) shr base_shift );
+ order_argb(p^ ).B:=int8u((order_argb(p^ ).B * alpha + cb * cover ) shr base_shift );
+ order_argb(p^ ).A:=int8u(base_mask - ((alpha * (base_mask - order_argb(p^ ).A ) ) shr base_shift ) );
+
+end;
+
+{ copy_or_blend_pix_argb_pre }
+procedure copy_or_blend_pix_argb_pre(p : unsigned_ptr; cr ,cg ,cb ,alpha : unsigned ); overload;
+begin
+ if alpha <> 0 then
+ if alpha = base_mask then
+ begin
+ order_argb(p^ ).R:=cr;
+ order_argb(p^ ).G:=cg;
+ order_argb(p^ ).B:=cb;
+ order_argb(p^ ).A:=base_mask;
+
+ end
+ else
+ blend_pix_argb_pre(p ,cr ,cg ,cb ,alpha );
+
+end;
+
+{ copy_or_blend_pix_argb_pre }
+procedure copy_or_blend_pix_argb_pre(p : unsigned_ptr; cr ,cg ,cb ,alpha ,cover : unsigned ); overload;
+begin
+ if cover = 255 then
+ copy_or_blend_pix_argb_pre(p ,cr ,cg ,cb ,alpha )
+ else
+ if alpha <> 0 then
+ begin
+ alpha:=(alpha * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_argb(p^ ).R:=cr;
+ order_argb(p^ ).G:=cg;
+ order_argb(p^ ).B:=cb;
+ order_argb(p^ ).A:=base_mask;
+
+ end
+ else
+ blend_pix_argb_pre(p ,cr ,cg ,cb ,alpha ,cover );
+
+ end;
+
+end;
+
+{ argb32_pre_blend_pixel }
+procedure argb32_pre_blend_pixel(this : pixel_formats_ptr; x ,y : int; c : aggclr_ptr; cover : int8u );
+begin
+ copy_or_blend_pix_argb_pre(
+ unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) ) ,
+ c.r ,c.g ,c.b ,c.a ,cover );
+
+end;
+
+{ argb32_pre_blend_hline }
+procedure argb32_pre_blend_hline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+var
+ p : unsigned_ptr;
+ v : unsigned;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_argb(v ).R:=c.r;
+ order_argb(v ).G:=c.g;
+ order_argb(v ).B:=c.b;
+ order_argb(v ).A:=c.a;
+
+ repeat
+ p^:=v;
+
+ inc(ptrcomp(p ) ,sizeof(unsigned ) );
+ dec(len );
+
+ until len = 0;
+
+ end
+ else
+ if cover = 255 then
+ repeat
+ blend_pix_argb_pre(p ,c.r ,c.g ,c.b ,alpha );
+
+ inc(ptrcomp(p ) ,sizeof(unsigned ) );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ blend_pix_argb_pre(p ,c.r ,c.g ,c.b ,alpha ,cover );
+
+ inc(ptrcomp(p ) ,sizeof(unsigned ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ argb32_pre_blend_vline }
+procedure argb32_pre_blend_vline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+var
+ p : unsigned_ptr;
+ v : unsigned;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_argb(v ).R:=c.r;
+ order_argb(v ).G:=c.g;
+ order_argb(v ).B:=c.b;
+ order_argb(v ).A:=c.a;
+
+ repeat
+ p^:=v;
+ p :=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ until len = 0;
+
+ end
+ else
+ if cover = 255 then
+ repeat
+ blend_pix_argb_pre(p ,c.r ,c.g ,c.b ,alpha );
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ blend_pix_argb_pre(p ,c.r ,c.g ,c.b ,alpha ,cover );
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ argb32_pre_blend_solid_hspan }
+procedure argb32_pre_blend_solid_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+var
+ p : unsigned_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ repeat
+ alpha:=(c.a * (covers^ + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_argb(p^ ).R:=c.r;
+ order_argb(p^ ).G:=c.g;
+ order_argb(p^ ).B:=c.b;
+ order_argb(p^ ).A:=base_mask;
+
+ end
+ else
+ blend_pix_argb_pre(p ,c.r ,c.g ,c.b ,alpha ,covers^ );
+
+ inc(ptrcomp(p ) ,4 );
+ inc(ptrcomp(covers ) );
+
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ argb32_pre_blend_solid_vspan }
+procedure argb32_pre_blend_solid_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+var
+ p : unsigned_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ repeat
+ alpha:=(c.a * (covers^ + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_argb(p^ ).R:=c.r;
+ order_argb(p^ ).G:=c.g;
+ order_argb(p^ ).B:=c.b;
+ order_argb(p^ ).A:=base_mask;
+
+ end
+ else
+ blend_pix_argb_pre(p ,c.r ,c.g ,c.b ,alpha ,covers^ );
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ argb32_pre_blend_color_hspan }
+procedure argb32_pre_blend_color_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+var
+ p : unsigned_ptr;
+
+begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ if covers <> NIL then
+ repeat
+ copy_or_blend_pix_argb_pre(p ,colors.r ,colors.g ,colors.b ,colors.a ,covers^ );
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+ inc(ptrcomp(p ) ,4 );
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0
+ else
+ if cover = 255 then
+ repeat
+ copy_or_blend_pix_argb_pre(p ,colors.r ,colors.g ,colors.b ,colors.a );
+
+ inc(ptrcomp(p ) ,4 );
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ copy_or_blend_pix_argb_pre(p ,colors.r ,colors.g ,colors.b ,colors.a ,cover );
+
+ inc(ptrcomp(p ) ,4 );
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ argb32_pre_blend_color_vspan }
+procedure argb32_pre_blend_color_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+var
+ p : unsigned_ptr;
+
+begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ if covers <> NIL then
+ repeat
+ copy_or_blend_pix_argb_pre(
+ p ,
+ colors.r ,
+ colors.g ,
+ colors.b ,
+ colors.a ,
+ covers^ );
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0
+ else
+ if cover = 255 then
+ repeat
+ copy_or_blend_pix_argb_pre(
+ p ,
+ colors.r ,
+ colors.g ,
+ colors.b ,
+ colors.a );
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ copy_or_blend_pix_argb_pre(
+ p ,
+ colors.r ,
+ colors.g ,
+ colors.b ,
+ colors.a ,
+ cover );
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ argb32_pre_blend_from }
+procedure argb32_pre_blend_from(this : pixel_formats_ptr; from : pixel_formats_ptr; psrc_ : int8u_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ psrc ,pdst : unsigned_ptr;
+
+ incp : int;
+
+begin
+ psrc:=unsigned_ptr(psrc_ );
+ pdst:=unsigned_ptr(ptrcomp(this.m_rbuf.row(ydst ) ) + (xdst shl 2 ) * sizeof(int8u ) );
+ incp:=4;
+
+ if ptrcomp(xdst ) > ptrcomp(xsrc ) then
+ begin
+ inc(ptrcomp(psrc ) ,((len - 1 ) shl 2 ) * sizeof(int8u ) );
+ inc(ptrcomp(pdst ) ,((len - 1 ) shl 2 ) * sizeof(int8u ) );
+
+ incp:=-4;
+
+ end;
+
+ if cover = 255 then
+ repeat
+ copy_or_blend_pix_argb_pre(
+ pdst ,
+ order_argb(psrc^ ).R ,
+ order_argb(psrc^ ).G ,
+ order_argb(psrc^ ).B ,
+ order_argb(psrc^ ).A );
+
+ inc(ptrcomp(psrc ) ,incp );
+ inc(ptrcomp(pdst ) ,incp );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ copy_or_blend_pix_argb_pre(
+ pdst ,
+ order_argb(psrc^ ).R ,
+ order_argb(psrc^ ).G ,
+ order_argb(psrc^ ).B ,
+ order_argb(psrc^ ).A ,
+ cover );
+
+ inc(ptrcomp(psrc ) ,incp );
+ inc(ptrcomp(pdst ) ,incp );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ argb32_pre_blend_from_color }
+procedure argb32_pre_blend_from_color(this : pixel_formats_ptr; from : pixel_formats_ptr; color : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ ppsz : unsigned;
+
+ psrc : int8u_ptr;
+ pdst : unsigned_ptr;
+
+begin
+ ppsz:=from._pix_width;
+ psrc:=from.row_ptr(ysrc );
+
+ if psrc <> NIL then
+ begin
+ pdst:=unsigned_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + (xdst shl 2 ) );
+
+ repeat
+ copy_or_blend_pix_argb_pre(
+ pdst ,color.r, color.g, color.b, color.a,
+ shr_int32(psrc^ * cover + base_mask ,base_shift ) );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,4 );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ argb32_pre_blend_from_lut }
+procedure argb32_pre_blend_from_lut(this : pixel_formats_ptr; from : pixel_formats_ptr; color_lut : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ ppsz : unsigned;
+
+ psrc : int8u_ptr;
+ pdst : unsigned_ptr;
+
+ color : aggclr_ptr;
+
+begin
+ ppsz:=from._pix_width;
+ psrc:=from.row_ptr(ysrc );
+
+ if psrc <> NIL then
+ begin
+ pdst:=unsigned_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + (xdst shl 2 ) );
+
+ if cover = 255 then
+ repeat
+ color:=aggclr_ptr(ptrcomp(color_lut ) + psrc^ * sizeof(aggclr ) );
+
+ copy_or_blend_pix_argb_pre(pdst ,color.r, color.g, color.b, color.a );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,4 );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ color:=aggclr_ptr(ptrcomp(color_lut ) + psrc^ * sizeof(aggclr ) );
+
+ copy_or_blend_pix_argb_pre(pdst ,color.r, color.g, color.b, color.a ,cover );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,4 );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
diff --git a/src/corelib/render/software/pf_bgr24.inc b/src/corelib/render/software/pf_bgr24.inc
new file mode 100644
index 00000000..daa0bbec
--- /dev/null
+++ b/src/corelib/render/software/pf_bgr24.inc
@@ -0,0 +1,533 @@
+//
+// AggPas 2.4 RM3 pixel format definition file
+//
+{ blend_pix_bgr }
+procedure blend_pix_bgr(p : int8u_ptr; cr ,cg ,cb ,alpha : int; cover : unsigned = 0 );
+begin
+ order_bgr(pointer(p )^ ).R:=order_bgr(pointer(p )^ ).R + ((cr - order_bgr(pointer(p )^ ).R ) * alpha ) shr base_shift;
+ order_bgr(pointer(p )^ ).G:=order_bgr(pointer(p )^ ).G + ((cg - order_bgr(pointer(p )^ ).G ) * alpha ) shr base_shift;
+ order_bgr(pointer(p )^ ).B:=order_bgr(pointer(p )^ ).B + ((cb - order_bgr(pointer(p )^ ).B ) * alpha ) shr base_shift;
+
+end;
+
+{ copy_or_blend_pix_bgr }
+procedure copy_or_blend_pix_bgr(p : int8u_ptr; c : aggclr_ptr; cover : unsigned ); overload;
+var
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_bgr(pointer(p )^ ).R:=c.r;
+ order_bgr(pointer(p )^ ).G:=c.g;
+ order_bgr(pointer(p )^ ).B:=c.b;
+
+ end
+ else
+ blend_pix_bgr(p ,c.r ,c.g ,c.b ,alpha ,cover );
+
+ end;
+
+end;
+
+{ copy_or_blend_pix_bgr }
+procedure copy_or_blend_pix_bgr(p : int8u_ptr; c : aggclr_ptr ); overload;
+begin
+ if c.a <> 0 then
+ if c.a = base_mask then
+ begin
+ order_bgr(pointer(p )^ ).R:=c.r;
+ order_bgr(pointer(p )^ ).G:=c.g;
+ order_bgr(pointer(p )^ ).B:=c.b;
+
+ end
+ else
+ blend_pix_bgr(p ,c.r ,c.g ,c.b ,c.a );
+
+end;
+
+{ bgr24_copy_pixel }
+procedure bgr24_copy_pixel(this : pixel_formats_ptr; x ,y : int; c : aggclr_ptr );
+var
+ p : int8u_ptr;
+
+begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x );
+
+ order_bgr(pointer(p )^ ).R:=c.r;
+ order_bgr(pointer(p )^ ).G:=c.g;
+ order_bgr(pointer(p )^ ).B:=c.b;
+
+end;
+
+{ bgr24_blend_pixel }
+procedure bgr24_blend_pixel(this : pixel_formats_ptr; x ,y : int; c : aggclr_ptr; cover : int8u );
+begin
+ copy_or_blend_pix_bgr(int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x ) ,c ,cover );
+
+end;
+
+{ bgr24_pixel }
+function bgr24_pixel(this : pixel_formats_ptr; x ,y : int ) : aggclr;
+var
+ p : int8u_ptr;
+
+begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x );
+
+ result.ConstrInt(
+ order_bgr(pointer(p )^ ).R ,
+ order_bgr(pointer(p )^ ).G ,
+ order_bgr(pointer(p )^ ).B );
+
+end;
+
+{ bgr24_copy_hline }
+procedure bgr24_copy_hline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr );
+var
+ p : int8u_ptr;
+
+begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x );
+
+ repeat
+ order_bgr(pointer(p )^ ).R:=c.r;
+ order_bgr(pointer(p )^ ).G:=c.g;
+ order_bgr(pointer(p )^ ).B:=c.b;
+
+ inc(ptrcomp(p ) ,3 );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ bgr24_copy_vline }
+procedure bgr24_copy_vline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr );
+var
+ p : int8u_ptr;
+
+begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x );
+
+ repeat
+ order_bgr(pointer(p )^ ).R:=c.r;
+ order_bgr(pointer(p )^ ).G:=c.g;
+ order_bgr(pointer(p )^ ).B:=c.b;
+
+ p:=this.m_rbuf.next_row(p );
+
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ bgr24_blend_hline }
+procedure bgr24_blend_hline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+var
+ p : int8u_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x );
+
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ repeat
+ order_bgr(pointer(p )^ ).R:=c.r;
+ order_bgr(pointer(p )^ ).G:=c.g;
+ order_bgr(pointer(p )^ ).B:=c.b;
+
+ inc(ptrcomp(p ) ,3 );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ blend_pix_bgr(p ,c.r ,c.g ,c.b ,alpha );
+
+ inc(ptrcomp(p ) ,3 );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ bgr24_blend_vline }
+procedure bgr24_blend_vline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+var
+ p : int8u_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x );
+
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ repeat
+ order_bgr(pointer(p )^ ).R:=c.r;
+ order_bgr(pointer(p )^ ).G:=c.g;
+ order_bgr(pointer(p )^ ).B:=c.b;
+
+ p:=int8u_ptr(this.m_rbuf.next_row(p ) );
+
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ blend_pix_bgr(p ,c.r ,c.g ,c.b ,alpha ,cover );
+
+ p:=int8u_ptr(this.m_rbuf.next_row(p ) );
+
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ bgr24_blend_solid_hspan }
+procedure bgr24_blend_solid_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+var
+ p : int8u_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x );
+
+ repeat
+ alpha:=(c.a * (covers^ + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_bgr(pointer(p )^ ).R:=c.r;
+ order_bgr(pointer(p )^ ).G:=c.g;
+ order_bgr(pointer(p )^ ).B:=c.b;
+
+ end
+ else
+ blend_pix_bgr(p ,c.r ,c.g ,c.b ,alpha ,covers^ );
+
+ inc(ptrcomp(p ) ,3 );
+ inc(ptrcomp(covers ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ bgr24_blend_solid_vspan }
+procedure bgr24_blend_solid_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+var
+ p : int8u_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x );
+
+ repeat
+ alpha:=(c.a * (covers^ + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_bgr(pointer(p )^ ).R:=c.r;
+ order_bgr(pointer(p )^ ).G:=c.g;
+ order_bgr(pointer(p )^ ).B:=c.b;
+
+ end
+ else
+ blend_pix_bgr(p ,c.r ,c.g ,c.b ,alpha,covers^ );
+
+ p:=int8u_ptr(this.m_rbuf.next_row(p ) );
+
+ inc(ptrcomp(covers ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ bgr24_blend_color_hspan }
+procedure bgr24_blend_color_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+var
+ p : int8u_ptr;
+
+begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x );
+
+ if covers <> NIL then
+ repeat
+ copy_or_blend_pix_bgr(p ,colors ,covers^ );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+ inc(ptrcomp(p ) ,3 );
+ dec(len );
+
+ until len = 0
+ else
+ if cover = 255 then
+ repeat
+ copy_or_blend_pix_bgr(p ,colors );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(ptrcomp(p ) ,3 );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ copy_or_blend_pix_bgr(p ,colors ,cover );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(ptrcomp(p ) ,3 );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ bgr24_blend_color_vspan }
+procedure bgr24_blend_color_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+var
+ p : int8u_ptr;
+
+begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x );
+
+ if covers <> NIL then
+ repeat
+ copy_or_blend_pix_bgr(p ,colors ,covers^ );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+
+ p:=int8u_ptr(this.m_rbuf.next_row(p ) );
+
+ dec(len );
+
+ until len = 0
+ else
+ if cover = 255 then
+ repeat
+ copy_or_blend_pix_bgr(p ,colors );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+
+ p:=int8u_ptr(this.m_rbuf.next_row(p ) );
+
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ copy_or_blend_pix_bgr(p ,colors ,cover );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+
+ p:=int8u_ptr(this.m_rbuf.next_row(p ) );
+
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ bgr24_blend_from }
+procedure bgr24_blend_from(this : pixel_formats_ptr; from : pixel_formats_ptr; psrc_ : int8u_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ psrc ,pdst : int8u_ptr;
+
+ color : aggclr;
+ alpha : unsigned;
+
+begin
+ psrc:=psrc_;
+ pdst:=int8u_ptr(ptrcomp(this.m_rbuf.row(ydst ) ) + xdst * 3 * sizeof(int8u ) );
+
+ if cover = 255 then
+ repeat
+ alpha:=int8u_ptr(ptrcomp(psrc ) + from.m_order.A )^;
+
+ if alpha <> 0 then
+ if alpha = base_mask then
+ begin
+ order_bgr(pointer(pdst )^ ).R:=int8u_ptr(ptrcomp(psrc ) + from.m_order.R )^;
+ order_bgr(pointer(pdst )^ ).G:=int8u_ptr(ptrcomp(psrc ) + from.m_order.G )^;
+ order_bgr(pointer(pdst )^ ).B:=int8u_ptr(ptrcomp(psrc ) + from.m_order.B )^;
+
+ end
+ else
+ blend_pix_bgr(
+ pdst ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.R )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.G )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.B )^ ,
+ alpha );
+
+ inc(ptrcomp(psrc ) ,4 );
+ inc(ptrcomp(pdst ) ,3 );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ color.ConstrInt(
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.R )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.G )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.B )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.A )^ );
+
+ copy_or_blend_pix_bgr(pdst ,@color ,cover );
+
+ inc(ptrcomp(psrc ) ,4 );
+ inc(ptrcomp(pdst ) ,3 );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ bgr24_copy_color_hspan }
+procedure bgr24_copy_color_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr );
+var
+ p : int8u_ptr;
+
+begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x );
+
+ repeat
+ order_bgr(pointer(p )^ ).R:=colors.r;
+ order_bgr(pointer(p )^ ).G:=colors.g;
+ order_bgr(pointer(p )^ ).B:=colors.b;
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(ptrcomp(p ) ,3 );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ bgr24_copy_color_vspan }
+procedure bgr24_copy_color_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr );
+var
+ p : int8u_ptr;
+
+begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x );
+
+ repeat
+ order_bgr(pointer(p )^ ).R:=colors.r;
+ order_bgr(pointer(p )^ ).G:=colors.g;
+ order_bgr(pointer(p )^ ).B:=colors.b;
+
+ p:=int8u_ptr(this.m_rbuf.next_row(p ) );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ bgr24_blend_from_color }
+procedure bgr24_blend_from_color(this : pixel_formats_ptr; from : pixel_formats_ptr; color : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ ppsz : unsigned;
+
+ psrc ,pdst : int8u_ptr;
+
+begin
+ ppsz:=from._pix_width;
+ psrc:=from.row_ptr(ysrc );
+
+ if psrc <> NIL then
+ begin
+ pdst:=int8u_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + xdst * 3 * sizeof(int8u ) );
+
+ repeat
+ copy_or_blend_pix_bgr(
+ pdst ,color ,
+ shr_int32(psrc^ * cover + base_mask ,base_shift ) );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,3 );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ bgr24_blend_from_lut }
+procedure bgr24_blend_from_lut(this : pixel_formats_ptr; from : pixel_formats_ptr; color_lut : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ ppsz : unsigned;
+
+ psrc ,pdst : int8u_ptr;
+
+ color : aggclr_ptr;
+
+begin
+ ppsz:=from._pix_width;
+ psrc:=from.row_ptr(ysrc );
+
+ if psrc <> NIL then
+ begin
+ pdst:=int8u_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + xdst * 3 * sizeof(int8u ) );
+
+ if cover = 255 then
+ repeat
+ color:=aggclr_ptr(ptrcomp(color_lut ) + psrc^ * sizeof(aggclr ) );
+
+ blend_pix_bgr(pdst ,color.r ,color.g ,color.b ,color.a );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,3 );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ copy_or_blend_pix_bgr(
+ pdst ,aggclr_ptr(ptrcomp(color_lut ) + psrc^ * sizeof(aggclr ) ) ,cover);
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,3 );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
diff --git a/src/corelib/render/software/pf_bgr24_gamma.inc b/src/corelib/render/software/pf_bgr24_gamma.inc
new file mode 100644
index 00000000..c46a31c5
--- /dev/null
+++ b/src/corelib/render/software/pf_bgr24_gamma.inc
@@ -0,0 +1,429 @@
+//
+// AggPas 2.4 RM3 pixel format definition file
+//
+{ blend_pix_bgr_gamma }
+procedure blend_pix_bgr_gamma(gamma : gamma_ptr; p : int8u_ptr; cr ,cg ,cb ,alpha : int; cover : unsigned = 0 );
+var
+ r ,g ,b : unsigned;
+
+begin
+ r:=gamma.dir(order_bgr(pointer(p )^ ).R );
+ g:=gamma.dir(order_bgr(pointer(p )^ ).G );
+ b:=gamma.dir(order_bgr(pointer(p )^ ).B );
+
+ order_bgr(pointer(p )^ ).R:=int8u(int(gamma.inv((((int(gamma.dir(cr ) ) - r ) * alpha ) shr base_shift ) + r ) ) );
+ order_bgr(pointer(p )^ ).G:=int8u(int(gamma.inv((((int(gamma.dir(cg ) ) - g ) * alpha ) shr base_shift ) + g ) ) );
+ order_bgr(pointer(p )^ ).B:=int8u(int(gamma.inv((((int(gamma.dir(cb ) ) - b ) * alpha ) shr base_shift ) + b ) ) );
+
+end;
+
+{ copy_or_blend_pix_bgr_gamma }
+procedure copy_or_blend_pix_bgr_gamma(gamma : gamma_ptr; p : int8u_ptr; c : aggclr_ptr; cover : unsigned ); overload;
+var
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_bgr(pointer(p )^ ).R:=c.r;
+ order_bgr(pointer(p )^ ).G:=c.g;
+ order_bgr(pointer(p )^ ).B:=c.b;
+
+ end
+ else
+ blend_pix_bgr_gamma(gamma ,p ,c.r ,c.g ,c.b ,alpha ,cover );
+
+ end;
+
+end;
+
+{ copy_or_blend_pix_bgr_gamma }
+procedure copy_or_blend_pix_bgr_gamma(gamma : gamma_ptr; p : int8u_ptr; c : aggclr_ptr ); overload;
+begin
+ if c.a <> 0 then
+ if c.a = base_mask then
+ begin
+ order_bgr(pointer(p )^ ).R:=c.r;
+ order_bgr(pointer(p )^ ).G:=c.g;
+ order_bgr(pointer(p )^ ).B:=c.b;
+
+ end
+ else
+ blend_pix_bgr_gamma(gamma ,p ,c.r ,c.g ,c.b ,c.a );
+
+end;
+
+{ bgr24_gamma_blend_pixel }
+procedure bgr24_gamma_blend_pixel(this : pixel_formats_ptr; x ,y : int; c : aggclr_ptr; cover : int8u );
+begin
+ copy_or_blend_pix_bgr_gamma(this.m_gamma ,int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x ) ,c ,cover );
+
+end;
+
+{ bgr24_gamma_blend_hline }
+procedure bgr24_gamma_blend_hline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+var
+ p : int8u_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x );
+
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ repeat
+ order_bgr(pointer(p )^ ).R:=c.r;
+ order_bgr(pointer(p )^ ).G:=c.g;
+ order_bgr(pointer(p )^ ).B:=c.b;
+
+ inc(ptrcomp(p ) ,3 );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ blend_pix_bgr_gamma(this.m_gamma ,p ,c.r ,c.g ,c.b ,alpha );
+
+ inc(ptrcomp(p ) ,3 );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ bgr24_gamma_blend_vline }
+procedure bgr24_gamma_blend_vline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+var
+ p : int8u_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x );
+
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ repeat
+ order_bgr(pointer(p )^ ).R:=c.r;
+ order_bgr(pointer(p )^ ).G:=c.g;
+ order_bgr(pointer(p )^ ).B:=c.b;
+
+ p:=int8u_ptr(this.m_rbuf.next_row(p ) );
+
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ blend_pix_bgr_gamma(this.m_gamma ,p ,c.r ,c.g ,c.b ,alpha ,cover );
+
+ p:=int8u_ptr(this.m_rbuf.next_row(p ) );
+
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ bgr24_gamma_blend_solid_hspan }
+procedure bgr24_gamma_blend_solid_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+var
+ p : int8u_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x );
+
+ repeat
+ alpha:=(c.a * (covers^ + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_bgr(pointer(p )^ ).R:=c.r;
+ order_bgr(pointer(p )^ ).G:=c.g;
+ order_bgr(pointer(p )^ ).B:=c.b;
+
+ end
+ else
+ blend_pix_bgr_gamma(this.m_gamma ,p ,c.r ,c.g ,c.b ,alpha ,covers^ );
+
+ inc(ptrcomp(p ) ,3 );
+ inc(ptrcomp(covers ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ bgr24_gamma_blend_solid_vspan }
+procedure bgr24_gamma_blend_solid_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+var
+ p : int8u_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x );
+
+ repeat
+ alpha:=(c.a * (covers^ + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_bgr(pointer(p )^ ).R:=c.r;
+ order_bgr(pointer(p )^ ).G:=c.g;
+ order_bgr(pointer(p )^ ).B:=c.b;
+
+ end
+ else
+ blend_pix_bgr_gamma(this.m_gamma ,p ,c.r ,c.g ,c.b ,alpha,covers^ );
+
+ p:=int8u_ptr(this.m_rbuf.next_row(p ) );
+
+ inc(ptrcomp(covers ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ bgr24_gamma_blend_color_hspan }
+procedure bgr24_gamma_blend_color_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+var
+ p : int8u_ptr;
+
+begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x );
+
+ if covers <> NIL then
+ repeat
+ copy_or_blend_pix_bgr_gamma(this.m_gamma ,p ,colors ,covers^ );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+ inc(ptrcomp(p ) ,3 );
+ dec(len );
+
+ until len = 0
+ else
+ if cover = 255 then
+ repeat
+ copy_or_blend_pix_bgr_gamma(this.m_gamma ,p ,colors );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(ptrcomp(p ) ,3 );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ copy_or_blend_pix_bgr_gamma(this.m_gamma ,p ,colors ,cover );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(ptrcomp(p ) ,3 );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ bgr24_gamma_blend_color_vspan }
+procedure bgr24_gamma_blend_color_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+var
+ p : int8u_ptr;
+
+begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x );
+
+ if covers <> NIL then
+ repeat
+ copy_or_blend_pix_bgr_gamma(this.m_gamma ,p ,colors ,covers^ );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+
+ p:=int8u_ptr(this.m_rbuf.next_row(p ) );
+
+ dec(len );
+
+ until len = 0
+ else
+ if cover = 255 then
+ repeat
+ copy_or_blend_pix_bgr_gamma(this.m_gamma ,p ,colors );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+
+ p:=int8u_ptr(this.m_rbuf.next_row(p ) );
+
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ copy_or_blend_pix_bgr_gamma(this.m_gamma ,p ,colors ,cover );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+
+ p:=int8u_ptr(this.m_rbuf.next_row(p ) );
+
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ bgr24_gamma_blend_from }
+procedure bgr24_gamma_blend_from(this : pixel_formats_ptr; from : pixel_formats_ptr; psrc_ : int8u_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ psrc ,pdst : int8u_ptr;
+
+ color : aggclr;
+ alpha : unsigned;
+
+begin
+ psrc:=psrc_;
+ pdst:=int8u_ptr(ptrcomp(this.m_rbuf.row(ydst ) ) + xdst * 3 * sizeof(int8u ) );
+
+ if cover = 255 then
+ repeat
+ alpha:=int8u_ptr(ptrcomp(psrc ) + from.m_order.A )^;
+
+ if alpha <> 0 then
+ if alpha = base_mask then
+ begin
+ order_bgr(pointer(pdst )^ ).R:=int8u_ptr(ptrcomp(psrc ) + from.m_order.R )^;
+ order_bgr(pointer(pdst )^ ).G:=int8u_ptr(ptrcomp(psrc ) + from.m_order.G )^;
+ order_bgr(pointer(pdst )^ ).B:=int8u_ptr(ptrcomp(psrc ) + from.m_order.B )^;
+
+ end
+ else
+ blend_pix_bgr_gamma(
+ this.m_gamma ,pdst ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.R )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.G )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.B )^ ,
+ alpha );
+
+ inc(ptrcomp(psrc ) ,4 );
+ inc(ptrcomp(pdst ) ,3 );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ color.ConstrInt(
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.R )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.G )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.B )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.A )^ );
+
+ copy_or_blend_pix_bgr_gamma(this.m_gamma ,pdst ,@color ,cover );
+
+ inc(ptrcomp(psrc ) ,4 );
+ inc(ptrcomp(pdst ) ,3 );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ bgr24_gamma_blend_from_color }
+procedure bgr24_gamma_blend_from_color(this : pixel_formats_ptr; from : pixel_formats_ptr; color : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ ppsz : unsigned;
+
+ psrc ,pdst : int8u_ptr;
+
+begin
+ ppsz:=from._pix_width;
+ psrc:=from.row_ptr(ysrc );
+
+ if psrc <> NIL then
+ begin
+ pdst:=int8u_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + xdst * 3 * sizeof(int8u ) );
+
+ repeat
+ copy_or_blend_pix_bgr_gamma(
+ this.m_gamma ,
+ pdst ,color ,
+ shr_int32(psrc^ * cover + base_mask ,base_shift ) );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,3 );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ bgr24_gamma_blend_from_lut }
+procedure bgr24_gamma_blend_from_lut(this : pixel_formats_ptr; from : pixel_formats_ptr; color_lut : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ ppsz : unsigned;
+
+ psrc ,pdst : int8u_ptr;
+
+ color : aggclr_ptr;
+
+begin
+ ppsz:=from._pix_width;
+ psrc:=from.row_ptr(ysrc );
+
+ if psrc <> NIL then
+ begin
+ pdst:=int8u_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + xdst * 3 * sizeof(int8u ) );
+
+ if cover = 255 then
+ repeat
+ color:=aggclr_ptr(ptrcomp(color_lut ) + psrc^ * sizeof(aggclr ) );
+
+ blend_pix_bgr_gamma(this.m_gamma ,pdst ,color.r ,color.g ,color.b ,color.a );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,3 );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ copy_or_blend_pix_bgr_gamma(
+ this.m_gamma ,
+ pdst ,aggclr_ptr(ptrcomp(color_lut ) + psrc^ * sizeof(aggclr ) ) ,cover);
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,3 );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
diff --git a/src/corelib/render/software/pf_bgr24_pre.inc b/src/corelib/render/software/pf_bgr24_pre.inc
new file mode 100644
index 00000000..ce23a02a
--- /dev/null
+++ b/src/corelib/render/software/pf_bgr24_pre.inc
@@ -0,0 +1,434 @@
+//
+// AggPas 2.4 RM3 pixel format definition file
+//
+{ blend_pix_bgr_pre }
+procedure blend_pix_bgr_pre(p : int8u_ptr; cr ,cg ,cb ,alpha ,cover : unsigned ); overload;
+begin
+ alpha:=base_mask - alpha;
+ cover:=(cover + 1 ) shl (base_shift - 8 );
+
+ order_bgr(pointer(p )^ ).R:=int8u((order_bgr(pointer(p )^ ).R * alpha + cr * cover ) shr base_shift );
+ order_bgr(pointer(p )^ ).G:=int8u((order_bgr(pointer(p )^ ).G * alpha + cg * cover ) shr base_shift );
+ order_bgr(pointer(p )^ ).B:=int8u((order_bgr(pointer(p )^ ).B * alpha + cb * cover ) shr base_shift );
+
+end;
+
+{ blend_pix_bgr_pre }
+procedure blend_pix_bgr_pre(p : int8u_ptr; cr ,cg ,cb ,alpha : unsigned ); overload;
+begin
+ alpha:=base_mask - alpha;
+
+ order_bgr(pointer(p )^ ).R:=int8u(((order_bgr(pointer(p )^ ).R * alpha ) shr base_shift ) + cr );
+ order_bgr(pointer(p )^ ).G:=int8u(((order_bgr(pointer(p )^ ).G * alpha ) shr base_shift ) + cg );
+ order_bgr(pointer(p )^ ).B:=int8u(((order_bgr(pointer(p )^ ).B * alpha ) shr base_shift ) + cb );
+
+end;
+
+{ copy_or_blend_pix_bgr_pre }
+procedure copy_or_blend_pix_bgr_pre(p : int8u_ptr; c : aggclr_ptr; cover : unsigned ); overload;
+var
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_bgr(pointer(p )^ ).R:=c.r;
+ order_bgr(pointer(p )^ ).G:=c.g;
+ order_bgr(pointer(p )^ ).B:=c.b;
+
+ end
+ else
+ blend_pix_bgr_pre(p ,c.r ,c.g ,c.b ,alpha ,cover );
+
+ end;
+
+end;
+
+{ copy_or_blend_pix_bgr_pre }
+procedure copy_or_blend_pix_bgr_pre(p : int8u_ptr; c : aggclr_ptr ); overload;
+begin
+ if c.a <> 0 then
+ if c.a = base_mask then
+ begin
+ order_bgr(pointer(p )^ ).R:=c.r;
+ order_bgr(pointer(p )^ ).G:=c.g;
+ order_bgr(pointer(p )^ ).B:=c.b;
+
+ end
+ else
+ blend_pix_bgr_pre(p ,c.r ,c.g ,c.b ,c.a );
+
+end;
+
+{ bgr24_pre_blend_pixel }
+procedure bgr24_pre_blend_pixel(this : pixel_formats_ptr; x ,y : int; c : aggclr_ptr; cover : int8u );
+begin
+ copy_or_blend_pix_bgr_pre(int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x ) ,c ,cover );
+
+end;
+
+{ bgr24_pre_blend_hline }
+procedure bgr24_pre_blend_hline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+var
+ p : int8u_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x );
+
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ repeat
+ order_bgr(pointer(p )^ ).R:=c.r;
+ order_bgr(pointer(p )^ ).G:=c.g;
+ order_bgr(pointer(p )^ ).B:=c.b;
+
+ inc(ptrcomp(p ) ,3 );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ blend_pix_bgr_pre(p ,c.r ,c.g ,c.b ,alpha );
+
+ inc(ptrcomp(p ) ,3 );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ bgr24_pre_blend_vline }
+procedure bgr24_pre_blend_vline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+var
+ p : int8u_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x );
+
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ repeat
+ order_bgr(pointer(p )^ ).R:=c.r;
+ order_bgr(pointer(p )^ ).G:=c.g;
+ order_bgr(pointer(p )^ ).B:=c.b;
+
+ p:=int8u_ptr(this.m_rbuf.next_row(p ) );
+
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ blend_pix_bgr_pre(p ,c.r ,c.g ,c.b ,alpha ,cover );
+
+ p:=int8u_ptr(this.m_rbuf.next_row(p ) );
+
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ bgr24_pre_blend_solid_hspan }
+procedure bgr24_pre_blend_solid_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+var
+ p : int8u_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x );
+
+ repeat
+ alpha:=(c.a * (covers^ + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_bgr(pointer(p )^ ).R:=c.r;
+ order_bgr(pointer(p )^ ).G:=c.g;
+ order_bgr(pointer(p )^ ).B:=c.b;
+
+ end
+ else
+ blend_pix_bgr_pre(p ,c.r ,c.g ,c.b ,alpha ,covers^ );
+
+ inc(ptrcomp(p ) ,3 );
+ inc(ptrcomp(covers ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ bgr24_pre_blend_solid_vspan }
+procedure bgr24_pre_blend_solid_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+var
+ p : int8u_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x );
+
+ repeat
+ alpha:=(c.a * (covers^ + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_bgr(pointer(p )^ ).R:=c.r;
+ order_bgr(pointer(p )^ ).G:=c.g;
+ order_bgr(pointer(p )^ ).B:=c.b;
+
+ end
+ else
+ blend_pix_bgr_pre(p ,c.r ,c.g ,c.b ,alpha,covers^ );
+
+ p:=int8u_ptr(this.m_rbuf.next_row(p ) );
+
+ inc(ptrcomp(covers ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ bgr24_pre_blend_color_hspan }
+procedure bgr24_pre_blend_color_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+var
+ p : int8u_ptr;
+
+begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x );
+
+ if covers <> NIL then
+ repeat
+ copy_or_blend_pix_bgr_pre(p ,colors ,covers^ );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+ inc(ptrcomp(p ) ,3 );
+ dec(len );
+
+ until len = 0
+ else
+ if cover = 255 then
+ repeat
+ copy_or_blend_pix_bgr_pre(p ,colors );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(ptrcomp(p ) ,3 );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ copy_or_blend_pix_bgr_pre(p ,colors ,cover );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(ptrcomp(p ) ,3 );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ bgr24_pre_blend_color_vspan }
+procedure bgr24_pre_blend_color_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+var
+ p : int8u_ptr;
+
+begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x );
+
+ if covers <> NIL then
+ repeat
+ copy_or_blend_pix_bgr_pre(p ,colors ,covers^ );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+
+ p:=int8u_ptr(this.m_rbuf.next_row(p ) );
+
+ dec(len );
+
+ until len = 0
+ else
+ if cover = 255 then
+ repeat
+ copy_or_blend_pix_bgr_pre(p ,colors );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+
+ p:=int8u_ptr(this.m_rbuf.next_row(p ) );
+
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ copy_or_blend_pix_bgr_pre(p ,colors ,cover );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+
+ p:=int8u_ptr(this.m_rbuf.next_row(p ) );
+
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ bgr24_pre_blend_from }
+procedure bgr24_pre_blend_from(this : pixel_formats_ptr; from : pixel_formats_ptr; psrc_ : int8u_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ psrc ,pdst : int8u_ptr;
+
+ color : aggclr;
+ alpha : unsigned;
+
+begin
+ psrc:=psrc_;
+ pdst:=int8u_ptr(ptrcomp(this.m_rbuf.row(ydst ) ) + xdst * 3 * sizeof(int8u ) );
+
+ if cover = 255 then
+ repeat
+ alpha:=int8u_ptr(ptrcomp(psrc ) + from.m_order.A )^;
+
+ if alpha <> 0 then
+ if alpha = base_mask then
+ begin
+ order_bgr(pointer(pdst )^ ).R:=int8u_ptr(ptrcomp(psrc ) + from.m_order.R )^;
+ order_bgr(pointer(pdst )^ ).G:=int8u_ptr(ptrcomp(psrc ) + from.m_order.G )^;
+ order_bgr(pointer(pdst )^ ).B:=int8u_ptr(ptrcomp(psrc ) + from.m_order.B )^;
+
+ end
+ else
+ blend_pix_bgr_pre(
+ pdst ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.R )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.G )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.B )^ ,
+ alpha );
+
+ inc(ptrcomp(psrc ) ,4 );
+ inc(ptrcomp(pdst ) ,3 );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ color.ConstrInt(
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.R )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.G )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.B )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.A )^ );
+
+ copy_or_blend_pix_bgr_pre(pdst ,@color ,cover );
+
+ inc(ptrcomp(psrc ) ,4 );
+ inc(ptrcomp(pdst ) ,3 );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ bgr24_pre_blend_from_color }
+procedure bgr24_pre_blend_from_color(this : pixel_formats_ptr; from : pixel_formats_ptr; color : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ ppsz : unsigned;
+
+ psrc ,pdst : int8u_ptr;
+
+begin
+ ppsz:=from._pix_width;
+ psrc:=from.row_ptr(ysrc );
+
+ if psrc <> NIL then
+ begin
+ pdst:=int8u_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + xdst * 3 * sizeof(int8u ) );
+
+ repeat
+ copy_or_blend_pix_bgr_pre(
+ pdst ,color ,
+ shr_int32(psrc^ * cover + base_mask ,base_shift ) );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,3 );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ bgr24_pre_blend_from_lut }
+procedure bgr24_pre_blend_from_lut(this : pixel_formats_ptr; from : pixel_formats_ptr; color_lut : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ ppsz : unsigned;
+
+ psrc ,pdst : int8u_ptr;
+
+ color : aggclr_ptr;
+
+begin
+ ppsz:=from._pix_width;
+ psrc:=from.row_ptr(ysrc );
+
+ if psrc <> NIL then
+ begin
+ pdst:=int8u_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + xdst * 3 * sizeof(int8u ) );
+
+ if cover = 255 then
+ repeat
+ color:=aggclr_ptr(ptrcomp(color_lut ) + psrc^ * sizeof(aggclr ) );
+
+ blend_pix_bgr_pre(pdst ,color.r ,color.g ,color.b ,color.a );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,3 );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ copy_or_blend_pix_bgr_pre(
+ pdst ,aggclr_ptr(ptrcomp(color_lut ) + psrc^ * sizeof(aggclr ) ) ,cover);
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,3 );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
diff --git a/src/corelib/render/software/pf_bgra32.inc b/src/corelib/render/software/pf_bgra32.inc
new file mode 100644
index 00000000..0cd968c8
--- /dev/null
+++ b/src/corelib/render/software/pf_bgra32.inc
@@ -0,0 +1,610 @@
+//
+// AggPas 2.4 RM3 pixel format definition file
+//
+{ blend_pix_bgra }
+procedure blend_pix_bgra(p : unsigned_ptr; cr ,cg ,cb ,alpha : int; cover : unsigned = 0 );
+var
+ r ,g ,b ,a : int8u;
+
+begin
+ r:=order_bgra(p^ ).R;
+ g:=order_bgra(p^ ).G;
+ b:=order_bgra(p^ ).B;
+ a:=order_bgra(p^ ).A;
+
+ order_bgra(p^ ).R:=((cr - r ) * alpha + (r shl base_shift ) ) shr base_shift;
+ order_bgra(p^ ).G:=((cg - g ) * alpha + (g shl base_shift ) ) shr base_shift;
+ order_bgra(p^ ).B:=((cb - b ) * alpha + (b shl base_shift ) ) shr base_shift;
+ order_bgra(p^ ).A:=(alpha + a ) - ((alpha * a + base_mask ) shr base_shift );
+
+end;
+
+{ copy_or_blend_pix_bgra }
+procedure copy_or_blend_pix_bgra(p : unsigned_ptr; cr ,cg ,cb ,alpha : unsigned ); overload;
+begin
+ if alpha <> 0 then
+ if alpha = base_mask then
+ begin
+ order_bgra(p^ ).R:=cr;
+ order_bgra(p^ ).G:=cg;
+ order_bgra(p^ ).B:=cb;
+ order_bgra(p^ ).A:=base_mask;
+
+ end
+ else
+ blend_pix_bgra(p ,cr ,cg ,cb ,alpha );
+
+end;
+
+{ copy_or_blend_pix_bgra }
+procedure copy_or_blend_pix_bgra(p : unsigned_ptr; cr ,cg ,cb ,alpha ,cover : unsigned ); overload;
+begin
+ if cover = 255 then
+ copy_or_blend_pix_bgra(p ,cr ,cg ,cb ,alpha )
+ else
+ if alpha <> 0 then
+ begin
+ alpha:=(alpha * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_bgra(p^ ).R:=cr;
+ order_bgra(p^ ).G:=cg;
+ order_bgra(p^ ).B:=cb;
+ order_bgra(p^ ).A:=base_mask;
+
+ end
+ else
+ blend_pix_bgra(p ,cr ,cg ,cb ,alpha ,cover );
+
+ end;
+
+end;
+
+{ bgra32_copy_pixel }
+procedure bgra32_copy_pixel(this : pixel_formats_ptr; x ,y : int; c : aggclr_ptr );
+var
+ p : unsigned_ptr;
+
+begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ order_bgra(p^ ).R:=c.r;
+ order_bgra(p^ ).G:=c.g;
+ order_bgra(p^ ).B:=c.b;
+ order_bgra(p^ ).A:=c.a;
+
+end;
+
+{ bgra32_blend_pixel }
+procedure bgra32_blend_pixel(this : pixel_formats_ptr; x ,y : int; c : aggclr_ptr; cover : int8u );
+begin
+ copy_or_blend_pix_bgra(
+ unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) ) ,
+ c.r ,c.g ,c.b ,c.a ,cover );
+
+end;
+
+{ bgra32_pixel }
+function bgra32_pixel(this : pixel_formats_ptr; x ,y : int ) : aggclr;
+var
+ p : unsigned_ptr;
+
+begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ result.ConstrInt(
+ order_bgra(p^ ).R ,
+ order_bgra(p^ ).G ,
+ order_bgra(p^ ).B ,
+ order_bgra(p^ ).A );
+
+end;
+
+{ bgra32_copy_hline }
+procedure bgra32_copy_hline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr );
+var
+ p : unsigned_ptr;
+ v : unsigned;
+
+begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ order_bgra(v ).R:=c.r;
+ order_bgra(v ).G:=c.g;
+ order_bgra(v ).B:=c.b;
+ order_bgra(v ).A:=c.a;
+
+ if len > 0 then
+ repeat
+ p^:=v;
+
+ inc(ptrcomp(p ) ,4 );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ bgra32_copy_vline }
+procedure bgra32_copy_vline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr );
+var
+ p : unsigned_ptr;
+ v : unsigned;
+
+begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ order_bgra(v ).R:=c.r;
+ order_bgra(v ).G:=c.g;
+ order_bgra(v ).B:=c.b;
+ order_bgra(v ).A:=c.a;
+
+ if len > 0 then
+ repeat
+ p^:=v;
+ p :=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ bgra32_blend_hline }
+procedure bgra32_blend_hline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+var
+ p : unsigned_ptr;
+ v : unsigned;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_bgra(v ).R:=c.r;
+ order_bgra(v ).G:=c.g;
+ order_bgra(v ).B:=c.b;
+ order_bgra(v ).A:=c.a;
+
+ repeat
+ p^:=v;
+
+ inc(ptrcomp(p ) ,sizeof(unsigned ) );
+ dec(len );
+
+ until len = 0;
+
+ end
+ else
+ if cover = 255 then
+ repeat
+ blend_pix_bgra(p ,c.r ,c.g ,c.b ,alpha );
+
+ inc(ptrcomp(p ) ,sizeof(unsigned ) );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ blend_pix_bgra(p ,c.r ,c.g ,c.b ,alpha ,cover );
+
+ inc(ptrcomp(p ) ,sizeof(unsigned ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ bgra32_blend_vline }
+procedure bgra32_blend_vline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+var
+ p : unsigned_ptr;
+ v : unsigned;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_bgra(v ).R:=c.r;
+ order_bgra(v ).G:=c.g;
+ order_bgra(v ).B:=c.b;
+ order_bgra(v ).A:=c.a;
+
+ repeat
+ p^:=v;
+ p :=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ dec(len );
+
+ until len = 0;
+
+ end
+ else
+ if cover = 255 then
+ repeat
+ blend_pix_bgra(p ,c.r ,c.g ,c.b ,alpha );
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ blend_pix_bgra(p ,c.r ,c.g ,c.b ,alpha ,cover );
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ bgra32_blend_solid_hspan }
+procedure bgra32_blend_solid_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+var
+ p : unsigned_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ repeat
+ alpha:=(c.a * (covers^ + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_bgra(p^ ).R:=c.r;
+ order_bgra(p^ ).G:=c.g;
+ order_bgra(p^ ).B:=c.b;
+ order_bgra(p^ ).A:=base_mask;
+
+ end
+ else
+ blend_pix_bgra(p ,c.r ,c.g ,c.b ,alpha ,covers^ );
+
+ inc(ptrcomp(p ) ,4 );
+ inc(ptrcomp(covers ) );
+
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ bgra32_blend_solid_vspan }
+procedure bgra32_blend_solid_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+var
+ p : unsigned_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ repeat
+ alpha:=(c.a * (covers^ + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_bgra(p^ ).R:=c.r;
+ order_bgra(p^ ).G:=c.g;
+ order_bgra(p^ ).B:=c.b;
+ order_bgra(p^ ).A:=base_mask;
+
+ end
+ else
+ blend_pix_bgra(p ,c.r ,c.g ,c.b ,alpha ,covers^ );
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ bgra32_blend_color_hspan }
+procedure bgra32_blend_color_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+var
+ p : unsigned_ptr;
+
+begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ if covers <> NIL then
+ repeat
+ copy_or_blend_pix_bgra(p ,colors.r ,colors.g ,colors.b ,colors.a ,covers^ );
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+ inc(ptrcomp(p ) ,4 );
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0
+ else
+ if cover = 255 then
+ repeat
+ copy_or_blend_pix_bgra(p ,colors.r ,colors.g ,colors.b ,colors.a );
+
+ inc(ptrcomp(p ) ,4 );
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ copy_or_blend_pix_bgra(p ,colors.r ,colors.g ,colors.b ,colors.a ,cover );
+
+ inc(ptrcomp(p ) ,4 );
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ bgra32_blend_color_vspan }
+procedure bgra32_blend_color_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+var
+ p : unsigned_ptr;
+
+begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ if covers <> NIL then
+ repeat
+ copy_or_blend_pix_bgra(
+ p ,
+ colors.r ,
+ colors.g ,
+ colors.b ,
+ colors.a ,
+ covers^ );
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0
+ else
+ if cover = 255 then
+ repeat
+ copy_or_blend_pix_bgra(
+ p ,
+ colors.r ,
+ colors.g ,
+ colors.b ,
+ colors.a );
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ copy_or_blend_pix_bgra(
+ p ,
+ colors.r ,
+ colors.g ,
+ colors.b ,
+ colors.a ,
+ cover );
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ bgra32_blend_from }
+procedure bgra32_blend_from(this : pixel_formats_ptr; from : pixel_formats_ptr; psrc_ : int8u_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ psrc ,pdst : unsigned_ptr;
+
+ incp : int;
+
+begin
+ psrc:=unsigned_ptr(psrc_ );
+ pdst:=unsigned_ptr(ptrcomp(this.m_rbuf.row(ydst ) ) + (xdst shl 2 ) * sizeof(int8u ) );
+ incp:=4;
+
+ if ptrcomp(xdst ) > ptrcomp(xsrc ) then
+ begin
+ inc(ptrcomp(psrc ) ,((len - 1 ) shl 2 ) * sizeof(int8u ) );
+ inc(ptrcomp(pdst ) ,((len - 1 ) shl 2 ) * sizeof(int8u ) );
+
+ incp:=-4;
+
+ end;
+
+ if cover = 255 then
+ repeat
+ copy_or_blend_pix_bgra(
+ pdst ,
+ order_bgra(psrc^ ).R ,
+ order_bgra(psrc^ ).G ,
+ order_bgra(psrc^ ).B ,
+ order_bgra(psrc^ ).A );
+
+ inc(ptrcomp(psrc ) ,incp );
+ inc(ptrcomp(pdst ) ,incp );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ copy_or_blend_pix_bgra(
+ pdst ,
+ order_bgra(psrc^ ).R ,
+ order_bgra(psrc^ ).G ,
+ order_bgra(psrc^ ).B ,
+ order_bgra(psrc^ ).A ,
+ cover );
+
+ inc(ptrcomp(psrc ) ,incp );
+ inc(ptrcomp(pdst ) ,incp );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ bgra32_copy_color_hspan }
+procedure bgra32_copy_color_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr );
+var
+ p : unsigned_ptr;
+
+begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ repeat
+ order_bgra(pointer(p )^ ).R:=colors.r;
+ order_bgra(pointer(p )^ ).G:=colors.g;
+ order_bgra(pointer(p )^ ).B:=colors.b;
+ order_bgra(pointer(p )^ ).A:=colors.a;
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(ptrcomp(p ) ,4 );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ bgra32_copy_color_vspan }
+procedure bgra32_copy_color_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr );
+var
+ p : unsigned_ptr;
+
+begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ repeat
+ order_bgra(pointer(p )^ ).R:=colors.r;
+ order_bgra(pointer(p )^ ).G:=colors.g;
+ order_bgra(pointer(p )^ ).B:=colors.b;
+ order_bgra(pointer(p )^ ).A:=colors.a;
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ bgra32_blend_from_color }
+procedure bgra32_blend_from_color(this : pixel_formats_ptr; from : pixel_formats_ptr; color : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ ppsz : unsigned;
+
+ psrc : int8u_ptr;
+ pdst : unsigned_ptr;
+
+begin
+ ppsz:=from._pix_width;
+ psrc:=pointer(ptrcomp(from.row_ptr(ysrc ) ) + xsrc * ppsz );
+
+ if psrc <> NIL then
+ begin
+ pdst:=unsigned_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + (xdst shl 2 ) );
+
+ repeat
+ copy_or_blend_pix_bgra(
+ pdst ,color.r, color.g, color.b, color.a,
+ shr_int32(psrc^ * cover + base_mask ,base_shift ) );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,4 );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ bgra32_blend_from_lut }
+procedure bgra32_blend_from_lut(this : pixel_formats_ptr; from : pixel_formats_ptr; color_lut : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ ppsz : unsigned;
+
+ psrc : int8u_ptr;
+ pdst : unsigned_ptr;
+
+ color : aggclr_ptr;
+
+begin
+ ppsz:=from._pix_width;
+ psrc:=pointer(ptrcomp(from.row_ptr(ysrc ) ) + xsrc * ppsz );
+
+ if psrc <> NIL then
+ begin
+ pdst:=unsigned_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + (xdst shl 2 ) );
+
+ if cover = 255 then
+ repeat
+ color:=aggclr_ptr(ptrcomp(color_lut ) + psrc^ * sizeof(aggclr ) );
+
+ copy_or_blend_pix_bgra(pdst ,color.r, color.g, color.b, color.a );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,4 );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ color:=aggclr_ptr(ptrcomp(color_lut ) + psrc^ * sizeof(aggclr ) );
+
+ copy_or_blend_pix_bgra(pdst ,color.r, color.g, color.b, color.a ,cover );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,4 );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
diff --git a/src/corelib/render/software/pf_bgra32_pre.inc b/src/corelib/render/software/pf_bgra32_pre.inc
new file mode 100644
index 00000000..2f3947d3
--- /dev/null
+++ b/src/corelib/render/software/pf_bgra32_pre.inc
@@ -0,0 +1,490 @@
+//
+// AggPas 2.4 RM3 pixel format definition file
+//
+{ blend_pix_bgra_pre }
+procedure blend_pix_bgra_pre(p : unsigned_ptr; cr ,cg ,cb ,alpha : unsigned ); overload;
+begin
+ alpha:=base_mask - alpha;
+
+ order_bgra(p^ ).R:=int8u(((order_bgra(p^ ).R * alpha) shr base_shift ) + cr );
+ order_bgra(p^ ).G:=int8u(((order_bgra(p^ ).G * alpha) shr base_shift ) + cg );
+ order_bgra(p^ ).B:=int8u(((order_bgra(p^ ).B * alpha) shr base_shift ) + cb );
+ order_bgra(p^ ).A:=int8u(base_mask - ((alpha * (base_mask - order_bgra(p^ ).A ) ) shr base_shift) );
+
+end;
+
+{ blend_pix_bgra_pre }
+procedure blend_pix_bgra_pre(p : unsigned_ptr; cr ,cg ,cb ,alpha ,cover : unsigned ); overload;
+begin
+ alpha:=base_mask - alpha;
+ cover:=(cover + 1 ) shl (base_shift - 8 );
+
+ order_bgra(p^ ).R:=int8u((order_bgra(p^ ).R * alpha + cr * cover ) shr base_shift );
+ order_bgra(p^ ).G:=int8u((order_bgra(p^ ).G * alpha + cg * cover ) shr base_shift );
+ order_bgra(p^ ).B:=int8u((order_bgra(p^ ).B * alpha + cb * cover ) shr base_shift );
+ order_bgra(p^ ).A:=int8u(base_mask - ((alpha * (base_mask - order_bgra(p^ ).A ) ) shr base_shift ) );
+
+end;
+
+{ copy_or_blend_pix_bgra_pre }
+procedure copy_or_blend_pix_bgra_pre(p : unsigned_ptr; cr ,cg ,cb ,alpha : unsigned ); overload;
+begin
+ if alpha <> 0 then
+ if alpha = base_mask then
+ begin
+ order_bgra(p^ ).R:=cr;
+ order_bgra(p^ ).G:=cg;
+ order_bgra(p^ ).B:=cb;
+ order_bgra(p^ ).A:=base_mask;
+
+ end
+ else
+ blend_pix_bgra_pre(p ,cr ,cg ,cb ,alpha );
+
+end;
+
+{ copy_or_blend_pix_bgra_pre }
+procedure copy_or_blend_pix_bgra_pre(p : unsigned_ptr; cr ,cg ,cb ,alpha ,cover : unsigned ); overload;
+begin
+ if cover = 255 then
+ copy_or_blend_pix_bgra_pre(p ,cr ,cg ,cb ,alpha )
+ else
+ if alpha <> 0 then
+ begin
+ alpha:=(alpha * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_bgra(p^ ).R:=cr;
+ order_bgra(p^ ).G:=cg;
+ order_bgra(p^ ).B:=cb;
+ order_bgra(p^ ).A:=base_mask;
+
+ end
+ else
+ blend_pix_bgra_pre(p ,cr ,cg ,cb ,alpha ,cover );
+
+ end;
+
+end;
+
+{ bgra32_pre_blend_pixel }
+procedure bgra32_pre_blend_pixel(this : pixel_formats_ptr; x ,y : int; c : aggclr_ptr; cover : int8u );
+begin
+ copy_or_blend_pix_bgra_pre(
+ unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) ) ,
+ c.r ,c.g ,c.b ,c.a ,cover );
+
+end;
+
+{ bgra32_pre_blend_hline }
+procedure bgra32_pre_blend_hline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+var
+ p : unsigned_ptr;
+ v : unsigned;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_bgra(v ).R:=c.r;
+ order_bgra(v ).G:=c.g;
+ order_bgra(v ).B:=c.b;
+ order_bgra(v ).A:=c.a;
+
+ repeat
+ p^:=v;
+
+ inc(ptrcomp(p ) ,sizeof(unsigned ) );
+ dec(len );
+
+ until len = 0;
+
+ end
+ else
+ if cover = 255 then
+ repeat
+ blend_pix_bgra_pre(p ,c.r ,c.g ,c.b ,alpha );
+
+ inc(ptrcomp(p ) ,sizeof(unsigned ) );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ blend_pix_bgra_pre(p ,c.r ,c.g ,c.b ,alpha ,cover );
+
+ inc(ptrcomp(p ) ,sizeof(unsigned ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ bgra32_pre_blend_vline }
+procedure bgra32_pre_blend_vline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+var
+ p : unsigned_ptr;
+ v : unsigned;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_bgra(v ).R:=c.r;
+ order_bgra(v ).G:=c.g;
+ order_bgra(v ).B:=c.b;
+ order_bgra(v ).A:=c.a;
+
+ repeat
+ p^:=v;
+ p :=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ until len = 0;
+
+ end
+ else
+ if cover = 255 then
+ repeat
+ blend_pix_bgra_pre(p ,c.r ,c.g ,c.b ,alpha );
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ blend_pix_bgra_pre(p ,c.r ,c.g ,c.b ,alpha ,cover );
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ bgra32_pre_blend_solid_hspan }
+procedure bgra32_pre_blend_solid_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+var
+ p : unsigned_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ repeat
+ alpha:=(c.a * (covers^ + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_bgra(p^ ).R:=c.r;
+ order_bgra(p^ ).G:=c.g;
+ order_bgra(p^ ).B:=c.b;
+ order_bgra(p^ ).A:=base_mask;
+
+ end
+ else
+ blend_pix_bgra_pre(p ,c.r ,c.g ,c.b ,alpha ,covers^ );
+
+ inc(ptrcomp(p ) ,4 );
+ inc(ptrcomp(covers ) );
+
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ bgra32_pre_blend_solid_vspan }
+procedure bgra32_pre_blend_solid_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+var
+ p : unsigned_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ repeat
+ alpha:=(c.a * (covers^ + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_bgra(p^ ).R:=c.r;
+ order_bgra(p^ ).G:=c.g;
+ order_bgra(p^ ).B:=c.b;
+ order_bgra(p^ ).A:=base_mask;
+
+ end
+ else
+ blend_pix_bgra_pre(p ,c.r ,c.g ,c.b ,alpha ,covers^ );
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ bgra32_pre_blend_color_hspan }
+procedure bgra32_pre_blend_color_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+var
+ p : unsigned_ptr;
+
+begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ if covers <> NIL then
+ repeat
+ copy_or_blend_pix_bgra_pre(p ,colors.r ,colors.g ,colors.b ,colors.a ,covers^ );
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+ inc(ptrcomp(p ) ,4 );
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0
+ else
+ if cover = 255 then
+ repeat
+ copy_or_blend_pix_bgra_pre(p ,colors.r ,colors.g ,colors.b ,colors.a );
+
+ inc(ptrcomp(p ) ,4 );
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ copy_or_blend_pix_bgra_pre(p ,colors.r ,colors.g ,colors.b ,colors.a ,cover );
+
+ inc(ptrcomp(p ) ,4 );
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ bgra32_pre_blend_color_vspan }
+procedure bgra32_pre_blend_color_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+var
+ p : unsigned_ptr;
+
+begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ if covers <> NIL then
+ repeat
+ copy_or_blend_pix_bgra_pre(
+ p ,
+ colors.r ,
+ colors.g ,
+ colors.b ,
+ colors.a ,
+ covers^ );
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0
+ else
+ if cover = 255 then
+ repeat
+ copy_or_blend_pix_bgra_pre(
+ p ,
+ colors.r ,
+ colors.g ,
+ colors.b ,
+ colors.a );
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ copy_or_blend_pix_bgra_pre(
+ p ,
+ colors.r ,
+ colors.g ,
+ colors.b ,
+ colors.a ,
+ cover );
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ bgra32_pre_blend_from }
+procedure bgra32_pre_blend_from(this : pixel_formats_ptr; from : pixel_formats_ptr; psrc_ : int8u_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ psrc ,pdst : unsigned_ptr;
+
+ incp : int;
+
+begin
+ psrc:=unsigned_ptr(psrc_ );
+ pdst:=unsigned_ptr(ptrcomp(this.m_rbuf.row(ydst ) ) + (xdst shl 2 ) * sizeof(int8u ) );
+ incp:=4;
+
+ if ptrcomp(xdst ) > ptrcomp(xsrc ) then
+ begin
+ inc(ptrcomp(psrc ) ,((len - 1 ) shl 2 ) * sizeof(int8u ) );
+ inc(ptrcomp(pdst ) ,((len - 1 ) shl 2 ) * sizeof(int8u ) );
+
+ incp:=-4;
+
+ end;
+
+ if cover = 255 then
+ repeat
+ copy_or_blend_pix_bgra_pre(
+ pdst ,
+ order_bgra(psrc^ ).R ,
+ order_bgra(psrc^ ).G ,
+ order_bgra(psrc^ ).B ,
+ order_bgra(psrc^ ).A );
+
+ inc(ptrcomp(psrc ) ,incp );
+ inc(ptrcomp(pdst ) ,incp );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ copy_or_blend_pix_bgra_pre(
+ pdst ,
+ order_bgra(psrc^ ).R ,
+ order_bgra(psrc^ ).G ,
+ order_bgra(psrc^ ).B ,
+ order_bgra(psrc^ ).A ,
+ cover );
+
+ inc(ptrcomp(psrc ) ,incp );
+ inc(ptrcomp(pdst ) ,incp );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ bgra32_pre_blend_from_color }
+procedure bgra32_pre_blend_from_color(this : pixel_formats_ptr; from : pixel_formats_ptr; color : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ ppsz : unsigned;
+
+ psrc : int8u_ptr;
+ pdst : unsigned_ptr;
+
+begin
+ ppsz:=from._pix_width;
+ psrc:=from.row_ptr(ysrc );
+
+ if psrc <> NIL then
+ begin
+ pdst:=unsigned_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + (xdst shl 2 ) );
+
+ repeat
+ copy_or_blend_pix_bgra_pre(
+ pdst ,color.r, color.g, color.b, color.a,
+ shr_int32(psrc^ * cover + base_mask ,base_shift ) );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,4 );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ bgra32_pre_blend_from_lut }
+procedure bgra32_pre_blend_from_lut(this : pixel_formats_ptr; from : pixel_formats_ptr; color_lut : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ ppsz : unsigned;
+
+ psrc : int8u_ptr;
+ pdst : unsigned_ptr;
+
+ color : aggclr_ptr;
+
+begin
+ ppsz:=from._pix_width;
+ psrc:=from.row_ptr(ysrc );
+
+ if psrc <> NIL then
+ begin
+ pdst:=unsigned_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + (xdst shl 2 ) );
+
+ if cover = 255 then
+ repeat
+ color:=aggclr_ptr(ptrcomp(color_lut ) + psrc^ * sizeof(aggclr ) );
+
+ copy_or_blend_pix_bgra_pre(pdst ,color.r, color.g, color.b, color.a );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,4 );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ color:=aggclr_ptr(ptrcomp(color_lut ) + psrc^ * sizeof(aggclr ) );
+
+ copy_or_blend_pix_bgra_pre(pdst ,color.r, color.g, color.b, color.a ,cover );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,4 );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+
diff --git a/src/corelib/render/software/pf_cubl32.inc b/src/corelib/render/software/pf_cubl32.inc
new file mode 100644
index 00000000..e5a177f2
--- /dev/null
+++ b/src/corelib/render/software/pf_cubl32.inc
@@ -0,0 +1,361 @@
+//
+// AggPas 2.4 RM3 pixel format definition file
+//
+{ cubl_copy_pixel }
+procedure cubl_copy_pixel(this : pixel_formats_ptr; x ,y : int; c : aggclr_ptr );
+begin
+ this.blender(
+ this ,this.m_comp_op ,
+ int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) * sizeof(int8u ) ) ,
+ c.r ,c.g ,c.b ,c.a ,255 );
+
+end;
+
+{ cubl_blend_pixel }
+procedure cubl_blend_pixel(this : pixel_formats_ptr; x ,y : int; c : aggclr_ptr; cover : int8u );
+begin
+ this.blender(
+ this ,this.m_comp_op ,
+ int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) * sizeof(int8u ) ) ,
+ c.r ,c.g ,c.b ,c.a ,cover );
+
+end;
+
+{ cubl_pixel }
+function cubl_pixel(this : pixel_formats_ptr; x ,y : int ) : aggclr;
+var
+ p : int8u_ptr;
+
+begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) * sizeof(int8u ) );
+
+ result.ConstrInt(
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^ ,
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^ ,
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^ ,
+ int8u_ptr(ptrcomp(p ) + this.m_order.A )^ );
+
+end;
+
+{ cubl_copy_hline }
+procedure cubl_copy_hline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr );
+var
+ p : int8u_ptr;
+
+begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) * sizeof(int8u ) );
+
+ repeat
+ this.blender(this ,this.m_comp_op ,p ,c.r ,c.g ,c.b ,c.a ,255 );
+
+ inc(ptrcomp(p ) ,4 );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ cubl_copy_vline }
+procedure cubl_copy_vline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr );
+var
+ p : int8u_ptr;
+
+begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) * sizeof(int8u ) );
+
+ repeat
+ this.blender(this ,this.m_comp_op ,p ,c.r ,c.g ,c.b ,c.a ,255 );
+
+ p:=this.m_rbuf.next_row(p );
+
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ cubl_blend_hline }
+procedure cubl_blend_hline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+var
+ p : int8u_ptr;
+
+begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) * sizeof(int8u ) );
+
+ repeat
+ this.blender(this ,this.m_comp_op ,p ,c.r ,c.g ,c.b ,c.a ,cover );
+
+ inc(ptrcomp(p ) ,4 );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ cubl_blend_vline }
+procedure cubl_blend_vline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+var
+ p : int8u_ptr;
+
+begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) * sizeof(int8u ) );
+
+ repeat
+ this.blender(this ,this.m_comp_op ,p ,c.r ,c.g ,c.b ,c.a ,cover );
+
+ p:=this.m_rbuf.next_row(p );
+
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ cubl_blend_solid_hspan }
+procedure cubl_blend_solid_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+var
+ p : int8u_ptr;
+
+begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) * sizeof(int8u ) );
+
+ repeat
+ this.blender(this ,this.m_comp_op ,p ,c.r ,c.g ,c.b ,c.a ,covers^ );
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+ inc(ptrcomp(p ) ,4 );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ cubl_blend_solid_vspan }
+procedure cubl_blend_solid_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+var
+ p : int8u_ptr;
+
+begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) * sizeof(int8u ) );
+
+ repeat
+ this.blender(this ,this.m_comp_op ,p ,c.r ,c.g ,c.b ,c.a ,covers^ );
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+
+ p:=this.m_rbuf.next_row(p );
+
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ cubl_blend_color_hspan }
+procedure cubl_blend_color_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+var
+ p : int8u_ptr;
+
+begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) * sizeof(int8u ) );
+
+ repeat
+ if covers <> NIL then
+ begin
+ this.blender(this ,this.m_comp_op ,p ,colors.r ,colors.g ,colors.b ,colors.a ,covers^ );
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+
+ end
+ else
+ this.blender(this ,this.m_comp_op ,p ,colors.r ,colors.g ,colors.b ,colors.a ,cover );
+
+ inc(ptrcomp(p ) ,4 );
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ cubl_blend_color_vspan }
+procedure cubl_blend_color_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+var
+ p : int8u_ptr;
+
+begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) * sizeof(int8u ) );
+
+ repeat
+ if covers <> NIL then
+ begin
+ this.blender(this ,this.m_comp_op ,p ,colors.r ,colors.g ,colors.b ,colors.a ,covers^ );
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+
+ end
+ else
+ this.blender(this ,this.m_comp_op ,p ,colors.r ,colors.g ,colors.b ,colors.a ,cover );
+
+ p:=this.m_rbuf.next_row(p );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ cubl_blend_from }
+procedure cubl_blend_from(this : pixel_formats_ptr; from : pixel_formats_ptr; psrc_ : int8u_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ psrc ,
+ pdst : int8u_ptr;
+ incp : int;
+
+begin
+ psrc:=psrc_;
+ pdst:=int8u_ptr(ptrcomp(this.m_rbuf.row(ydst ) ) + (xdst shl 2 ) * sizeof(int8u ) );
+ incp:=4;
+
+ if xdst > xsrc then
+ begin
+ inc(ptrcomp(psrc ) ,(len - 1 ) shl 2 );
+ inc(ptrcomp(pdst ) ,(len - 1 ) shl 2 );
+
+ incp:=-4;
+
+ end;
+
+ repeat
+ this.blender(
+ this ,this.m_comp_op ,pdst ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.R )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.G )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.B )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.A )^ ,
+ cover );
+
+ inc(ptrcomp(psrc ) ,incp );
+ inc(ptrcomp(pdst ) ,incp );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ cubl_copy_color_hspan }
+procedure cubl_copy_color_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr );
+var
+ p : int8u_ptr;
+
+begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) * sizeof(int8u ) );
+
+ repeat
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=colors.r;
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=colors.g;
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=colors.b;
+ int8u_ptr(ptrcomp(p ) + this.m_order.A )^:=colors.a;
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(ptrcomp(p ) ,4 );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ cubl_copy_color_vspan }
+procedure cubl_copy_color_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr );
+var
+ p : int8u_ptr;
+
+begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) * sizeof(int8u ) );
+
+ repeat
+ int8u_ptr(ptrcomp(p ) + this.m_order.R )^:=colors.r;
+ int8u_ptr(ptrcomp(p ) + this.m_order.G )^:=colors.g;
+ int8u_ptr(ptrcomp(p ) + this.m_order.B )^:=colors.b;
+ int8u_ptr(ptrcomp(p ) + this.m_order.A )^:=colors.a;
+
+ p:=this.m_rbuf.next_row(p );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ cubl_blend_from_color }
+procedure cubl_blend_from_color(this : pixel_formats_ptr; from : pixel_formats_ptr; color : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ ppsz : unsigned;
+
+ psrc ,
+ pdst : int8u_ptr;
+
+begin
+ ppsz:=from._pix_width;
+ psrc:=from.row_ptr(ysrc );
+
+ if psrc <> NIL then
+ begin
+ pdst:=int8u_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + (xdst shl 2 ) );
+
+ repeat
+ this.blender(
+ this ,this.m_comp_op ,pdst ,
+ color.r ,color.g ,color.b ,color.a ,
+ shr_int32(psrc^ * cover + base_mask ,base_shift ) );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,4 );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ cubl_blend_from_lut }
+procedure cubl_blend_from_lut(this : pixel_formats_ptr; from : pixel_formats_ptr; color_lut : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ ppsz : unsigned;
+
+ psrc ,
+ pdst : int8u_ptr;
+
+ color : aggclr_ptr;
+
+begin
+ ppsz:=from._pix_width;
+ psrc:=from.row_ptr(ysrc );
+
+ if psrc <> NIL then
+ begin
+ pdst:=int8u_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + (xdst shl 2 ) );
+
+ repeat
+ color:=aggclr_ptr(ptrcomp(color_lut ) + psrc^ * sizeof(aggclr ) );
+
+ this.blender(
+ this ,this.m_comp_op ,pdst ,
+ color.r ,color.g ,color.b ,color.a ,
+ shr_int32(psrc^ * cover + base_mask ,base_shift ) );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,4 );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+
+
diff --git a/src/corelib/render/software/pf_gray8.inc b/src/corelib/render/software/pf_gray8.inc
new file mode 100644
index 00000000..47454637
--- /dev/null
+++ b/src/corelib/render/software/pf_gray8.inc
@@ -0,0 +1,437 @@
+//
+// AggPas 2.4 RM3 pixel format definition file
+//
+{ blend_pix_gray }
+procedure blend_pix_gray(p : int8u_ptr; cv ,alpha : unsigned; cover : unsigned = 0 );
+begin
+ p^:=int8u((((cv - p^ ) * alpha ) + (p^ shl base_shift ) ) shr base_shift );
+
+end;
+
+{ copy_or_blend_pix_gray }
+procedure copy_or_blend_pix_gray(p : int8u_ptr; c : aggclr_ptr; cover : unsigned ); overload;
+var
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ p^:=c.v
+ else
+ blend_pix_gray(p ,c.v ,alpha ,cover );
+
+ end;
+
+end;
+
+{ copy_or_blend_pix_gray }
+procedure copy_or_blend_pix_gray(p : int8u_ptr; c : aggclr_ptr ); overload;
+begin
+ if c.a <> 0 then
+ if c.a = base_mask then
+ p^:=c.v
+ else
+ blend_pix_gray(p ,c.v ,c.a );
+
+end;
+
+{ gray8_copy_pixel }
+procedure gray8_copy_pixel(this : pixel_formats_ptr; x ,y : int; c : aggclr_ptr );
+begin
+ int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * this.m_step + this.m_offset )^:=c.v;
+
+end;
+
+{ gray8_blend_pixel }
+procedure gray8_blend_pixel(this : pixel_formats_ptr; x ,y : int; c : aggclr_ptr; cover : int8u );
+begin
+ copy_or_blend_pix_gray(
+ int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * this.m_step + this.m_offset ) ,
+ c ,cover );
+
+end;
+
+{ gray8_pixel }
+function gray8_pixel(this : pixel_formats_ptr; x ,y : int ) : aggclr;
+var
+ p : int8u_ptr;
+
+begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * this.m_step + this.m_offset );
+
+ result.ConstrInt(p^ );
+
+end;
+
+{ gray8_copy_hline }
+procedure gray8_copy_hline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr );
+var
+ p : int8u_ptr;
+
+begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * this.m_step + this.m_offset );
+
+ repeat
+ p^:=c.v;
+
+ inc(ptrcomp(p ) ,this.m_step );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ gray8_copy_vline }
+procedure gray8_copy_vline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr );
+var
+ p : int8u_ptr;
+
+begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * this.m_step + this.m_offset );
+
+ repeat
+ p^:=c.v;
+ p :=this.m_rbuf.next_row(p );
+
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ gray8_blend_hline }
+procedure gray8_blend_hline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+var
+ p : int8u_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * this.m_step + this.m_offset );
+
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ repeat
+ p^:=c.v;
+
+ inc(ptrcomp(p ) ,this.m_step );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ blend_pix_gray(p ,c.v ,alpha ,cover );
+
+ inc(ptrcomp(p ) ,this.m_step );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ gray8_blend_vline }
+procedure gray8_blend_vline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+var
+ p : int8u_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * this.m_step + this.m_offset );
+
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ repeat
+ p^:=c.v;
+ p :=this.m_rbuf.next_row(p );
+
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ blend_pix_gray(p ,c.v ,alpha ,cover );
+
+ p:=this.m_rbuf.next_row(p );
+
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ gray8_blend_solid_hspan }
+procedure gray8_blend_solid_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+var
+ p : int8u_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * this.m_step + this.m_offset );
+
+ repeat
+ alpha:=(c.a * (covers^ + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ p^:=c.v
+ else
+ blend_pix_gray(p ,c.v ,alpha ,covers^ );
+
+ inc(ptrcomp(p ) ,this.m_step );
+ inc(ptrcomp(covers ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ gray8_blend_solid_vspan }
+procedure gray8_blend_solid_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+var
+ p : int8u_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * this.m_step + this.m_offset );
+
+ repeat
+ alpha:=(c.a * (covers^ + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ p^:=c.v
+ else
+ blend_pix_gray(p ,c.v ,alpha ,covers^ );
+
+ p:=this.m_rbuf.next_row(p );
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ gray8_blend_color_hspan }
+procedure gray8_blend_color_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+var
+ p : int8u_ptr;
+
+begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * this.m_step + this.m_offset );
+
+ if covers <> NIL then
+ repeat
+ copy_or_blend_pix_gray(p ,colors ,covers^ );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+ inc(ptrcomp(p ) ,this.m_step );
+ dec(len );
+
+ until len = 0
+ else
+ if cover = 255 then
+ repeat
+ if colors.a = base_mask then
+ p^:=colors.v
+ else
+ copy_or_blend_pix_gray(p ,colors );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(ptrcomp(p ) ,this.m_step );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ copy_or_blend_pix_gray(p ,colors ,cover );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(ptrcomp(p ) ,this.m_step );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ gray8_blend_color_vspan }
+procedure gray8_blend_color_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+var
+ p : int8u_ptr;
+
+begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * this.m_step + this.m_offset );
+
+ if covers <> NIL then
+ repeat
+ copy_or_blend_pix_gray(p ,colors ,covers^ );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+
+ p:=this.m_rbuf.next_row(p );
+
+ dec(len );
+
+ until len = 0
+ else
+ if cover = 255 then
+ repeat
+ if colors.a = base_mask then
+ p^:=colors.v
+ else
+ copy_or_blend_pix_gray(p ,colors );
+
+ p:=this.m_rbuf.next_row(p );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0
+
+ else
+ repeat
+ copy_or_blend_pix_gray(p ,colors ,cover );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+
+ p:=this.m_rbuf.next_row(p );
+
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ gray8_copy_from }
+procedure gray8_copy_from(this : pixel_formats_ptr; from : rendering_buffer_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned );
+begin
+ move(
+ int8u_ptr(ptrcomp(from.row(ysrc ) ) + xsrc * sizeof(int8u ) )^ ,
+ int8u_ptr(ptrcomp(this.m_rbuf.row(ydst ) ) + xdst * sizeof(int8u ) )^ ,
+ len * sizeof(int8u ) );
+
+end;
+
+{ gray8_copy_color_hspan }
+procedure gray8_copy_color_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr );
+var
+ p : int8u_ptr;
+
+begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * this.m_step + this.m_offset );
+
+ repeat
+ p^:=colors.v;
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(ptrcomp(p ) ,this.m_step );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ gray8_copy_color_vspan }
+procedure gray8_copy_color_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr );
+var
+ p : int8u_ptr;
+
+begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * this.m_step + this.m_offset );
+
+ repeat
+ p^:=colors.v;
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+
+ p:=this.m_rbuf.next_row(p );
+
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ gray8_blend_from_color }
+procedure gray8_blend_from_color(this : pixel_formats_ptr; from : pixel_formats_ptr; color : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ ppsz : unsigned;
+
+ psrc ,pdst : int8u_ptr;
+
+begin
+ ppsz:=from._pix_width;
+ psrc:=from.row_ptr(ysrc );
+
+ if psrc <> NIL then
+ begin
+ pdst:=int8u_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + xdst * this.m_step + this.m_offset );
+
+ repeat
+ copy_or_blend_pix_gray(
+ pdst ,color ,
+ shr_int32(psrc^ * cover + base_mask ,base_shift ) );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,this.m_step );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ gray8_blend_from_lut }
+procedure gray8_blend_from_lut(this : pixel_formats_ptr; from : pixel_formats_ptr; color_lut : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ ppsz : unsigned;
+
+ psrc ,pdst : int8u_ptr;
+
+begin
+ ppsz:=from._pix_width;
+ psrc:=from.row_ptr(ysrc );
+
+ if psrc <> NIL then
+ begin
+ pdst:=int8u_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + xdst * this.m_step + this.m_offset );
+
+ repeat
+ copy_or_blend_pix_gray(
+ pdst ,aggclr_ptr(ptrcomp(color_lut ) + psrc^ * sizeof(aggclr ) ) ,cover );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,this.m_step );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
diff --git a/src/corelib/render/software/pf_gray8_pre.inc b/src/corelib/render/software/pf_gray8_pre.inc
new file mode 100644
index 00000000..12aacb30
--- /dev/null
+++ b/src/corelib/render/software/pf_gray8_pre.inc
@@ -0,0 +1,342 @@
+//
+// AggPas 2.4 RM3 pixel format definition file
+//
+{ blend_pix_gray_pre }
+procedure blend_pix_gray_pre(p : int8u_ptr; cv ,alpha ,cover : unsigned ); overload;
+begin
+ alpha:=base_mask - alpha;
+ cover:=(cover + 1 ) shl (base_shift - 8 );
+
+ p^:=int8u((p^ * alpha + cv * cover ) shr base_shift );
+
+end;
+
+{ blend_pix_gray_pre }
+procedure blend_pix_gray_pre(p : int8u_ptr; cv ,alpha : unsigned ); overload;
+begin
+ p^:=int8u(((p^ * (base_mask - alpha ) ) shr base_shift ) + cv );
+
+end;
+
+{ copy_or_blend_pix_gray_pre }
+procedure copy_or_blend_pix_gray_pre(p : int8u_ptr; c : aggclr_ptr; cover : unsigned ); overload;
+var
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ p^:=c.v
+ else
+ blend_pix_gray_pre(p ,c.v ,alpha ,cover );
+
+ end;
+
+end;
+
+{ copy_or_blend_pix_pre }
+procedure copy_or_blend_pix_pre(p : int8u_ptr; c : aggclr_ptr ); overload;
+begin
+ if c.a <> 0 then
+ if c.a = base_mask then
+ p^:=c.v
+ else
+ blend_pix_gray_pre(p ,c.v ,c.a );
+
+end;
+
+{ gray8_pre_blend_pixel }
+procedure gray8_pre_blend_pixel(this : pixel_formats_ptr; x ,y : int; c : aggclr_ptr; cover : int8u );
+begin
+ copy_or_blend_pix_gray_pre(
+ int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * this.m_step + this.m_offset ) ,
+ c ,cover );
+
+end;
+
+{ gray8_pre_blend_hline }
+procedure gray8_pre_blend_hline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+var
+ p : int8u_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * this.m_step + this.m_offset );
+
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ repeat
+ p^:=c.v;
+
+ inc(ptrcomp(p ) ,this.m_step );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ blend_pix_gray_pre(p ,c.v ,alpha ,cover );
+
+ inc(ptrcomp(p ) ,this.m_step );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ gray8_pre_blend_vline }
+procedure gray8_pre_blend_vline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+var
+ p : int8u_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * this.m_step + this.m_offset );
+
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ repeat
+ p^:=c.v;
+ p :=this.m_rbuf.next_row(p );
+
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ blend_pix_gray_pre(p ,c.v ,alpha ,cover );
+
+ p:=this.m_rbuf.next_row(p );
+
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ gray8_pre_blend_solid_hspan }
+procedure gray8_pre_blend_solid_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+var
+ p : int8u_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * this.m_step + this.m_offset );
+
+ repeat
+ alpha:=(c.a * (covers^ + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ p^:=c.v
+ else
+ blend_pix_gray_pre(p ,c.v ,alpha ,covers^ );
+
+ inc(ptrcomp(p ) ,this.m_step );
+ inc(ptrcomp(covers ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ gray8_pre_blend_solid_vspan }
+procedure gray8_pre_blend_solid_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+var
+ p : int8u_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * this.m_step + this.m_offset );
+
+ repeat
+ alpha:=(c.a * (covers^ + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ p^:=c.v
+ else
+ blend_pix_gray_pre(p ,c.v ,alpha ,covers^ );
+
+ p:=this.m_rbuf.next_row(p );
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ gray8_pre_blend_color_hspan }
+procedure gray8_pre_blend_color_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+var
+ p : int8u_ptr;
+
+begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * this.m_step + this.m_offset );
+
+ if covers <> NIL then
+ repeat
+ copy_or_blend_pix_gray_pre(p ,colors ,covers^ );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+ inc(ptrcomp(p ) ,this.m_step );
+ dec(len );
+
+ until len = 0
+ else
+ if cover = 255 then
+ repeat
+ if colors.a = base_mask then
+ p^:=colors.v
+ else
+ copy_or_blend_pix_pre(p ,colors );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(ptrcomp(p ) ,this.m_step );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ copy_or_blend_pix_gray_pre(p ,colors ,cover );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(ptrcomp(p ) ,this.m_step );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ gray8_pre_blend_color_vspan }
+procedure gray8_pre_blend_color_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+var
+ p : int8u_ptr;
+
+begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * this.m_step + this.m_offset );
+
+ if covers <> NIL then
+ repeat
+ copy_or_blend_pix_gray_pre(p ,colors ,covers^ );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+
+ p:=this.m_rbuf.next_row(p );
+
+ dec(len );
+
+ until len = 0
+ else
+ if cover = 255 then
+ repeat
+ if colors.a = base_mask then
+ p^:=colors.v
+ else
+ copy_or_blend_pix_pre(p ,colors );
+
+ p:=this.m_rbuf.next_row(p );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0
+
+ else
+ repeat
+ copy_or_blend_pix_gray_pre(p ,colors ,cover );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+
+ p:=this.m_rbuf.next_row(p );
+
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ gray8_pre_blend_from_color }
+procedure gray8_pre_blend_from_color(this : pixel_formats_ptr; from : pixel_formats_ptr; color : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ ppsz : unsigned;
+
+ psrc ,pdst : int8u_ptr;
+
+begin
+ ppsz:=from._pix_width;
+ psrc:=from.row_ptr(ysrc );
+
+ if psrc <> NIL then
+ begin
+ pdst:=int8u_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + xdst * this.m_step + this.m_offset );
+
+ repeat
+ copy_or_blend_pix_gray_pre(
+ pdst ,color ,
+ shr_int32(psrc^ * cover + base_mask ,base_shift ) );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,this.m_step );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ gray8_pre_blend_from_lut }
+procedure gray8_pre_blend_from_lut(this : pixel_formats_ptr; from : pixel_formats_ptr; color_lut : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ ppsz : unsigned;
+
+ psrc ,pdst : int8u_ptr;
+
+begin
+ ppsz:=from._pix_width;
+ psrc:=from.row_ptr(ysrc );
+
+ if psrc <> NIL then
+ begin
+ pdst:=int8u_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + xdst * this.m_step + this.m_offset );
+
+ repeat
+ copy_or_blend_pix_gray_pre(
+ pdst ,aggclr_ptr(ptrcomp(color_lut ) + psrc^ * sizeof(aggclr ) ) ,cover );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,this.m_step );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
diff --git a/src/corelib/render/software/pf_rgb24.inc b/src/corelib/render/software/pf_rgb24.inc
new file mode 100644
index 00000000..96ecc01b
--- /dev/null
+++ b/src/corelib/render/software/pf_rgb24.inc
@@ -0,0 +1,533 @@
+//
+// AggPas 2.4 RM3 pixel format definition file
+//
+{ blend_pix_rgb }
+procedure blend_pix_rgb(p : int8u_ptr; cr ,cg ,cb ,alpha : int; cover : unsigned = 0 );
+begin
+ order_rgb(pointer(p )^ ).R:=order_rgb(pointer(p )^ ).R + ((cr - order_rgb(pointer(p )^ ).R ) * alpha ) shr base_shift;
+ order_rgb(pointer(p )^ ).G:=order_rgb(pointer(p )^ ).G + ((cg - order_rgb(pointer(p )^ ).G ) * alpha ) shr base_shift;
+ order_rgb(pointer(p )^ ).B:=order_rgb(pointer(p )^ ).B + ((cb - order_rgb(pointer(p )^ ).B ) * alpha ) shr base_shift;
+
+end;
+
+{ copy_or_blend_pix_rgb }
+procedure copy_or_blend_pix_rgb(p : int8u_ptr; c : aggclr_ptr; cover : unsigned ); overload;
+var
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_rgb(pointer(p )^ ).R:=c.r;
+ order_rgb(pointer(p )^ ).G:=c.g;
+ order_rgb(pointer(p )^ ).B:=c.b;
+
+ end
+ else
+ blend_pix_rgb(p ,c.r ,c.g ,c.b ,alpha ,cover );
+
+ end;
+
+end;
+
+{ copy_or_blend_pix_rgb }
+procedure copy_or_blend_pix_rgb(p : int8u_ptr; c : aggclr_ptr ); overload;
+begin
+ if c.a <> 0 then
+ if c.a = base_mask then
+ begin
+ order_rgb(pointer(p )^ ).R:=c.r;
+ order_rgb(pointer(p )^ ).G:=c.g;
+ order_rgb(pointer(p )^ ).B:=c.b;
+
+ end
+ else
+ blend_pix_rgb(p ,c.r ,c.g ,c.b ,c.a );
+
+end;
+
+{ rgb24_copy_pixel }
+procedure rgb24_copy_pixel(this : pixel_formats_ptr; x ,y : int; c : aggclr_ptr );
+var
+ p : int8u_ptr;
+
+begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x );
+
+ order_rgb(pointer(p )^ ).R:=c.r;
+ order_rgb(pointer(p )^ ).G:=c.g;
+ order_rgb(pointer(p )^ ).B:=c.b;
+
+end;
+
+{ rgb24_blend_pixel }
+procedure rgb24_blend_pixel(this : pixel_formats_ptr; x ,y : int; c : aggclr_ptr; cover : int8u );
+begin
+ copy_or_blend_pix_rgb(int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x ) ,c ,cover );
+
+end;
+
+{ rgb24_pixel }
+function rgb24_pixel(this : pixel_formats_ptr; x ,y : int ) : aggclr;
+var
+ p : int8u_ptr;
+
+begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x );
+
+ result.ConstrInt(
+ order_rgb(pointer(p )^ ).R ,
+ order_rgb(pointer(p )^ ).G ,
+ order_rgb(pointer(p )^ ).B );
+
+end;
+
+{ rgb24_copy_hline }
+procedure rgb24_copy_hline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr );
+var
+ p : int8u_ptr;
+
+begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x );
+
+ repeat
+ order_rgb(pointer(p )^ ).R:=c.r;
+ order_rgb(pointer(p )^ ).G:=c.g;
+ order_rgb(pointer(p )^ ).B:=c.b;
+
+ inc(ptrcomp(p ) ,3 );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb24_copy_vline }
+procedure rgb24_copy_vline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr );
+var
+ p : int8u_ptr;
+
+begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x );
+
+ repeat
+ order_rgb(pointer(p )^ ).R:=c.r;
+ order_rgb(pointer(p )^ ).G:=c.g;
+ order_rgb(pointer(p )^ ).B:=c.b;
+
+ p:=this.m_rbuf.next_row(p );
+
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb24_blend_hline }
+procedure rgb24_blend_hline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+var
+ p : int8u_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x );
+
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ repeat
+ order_rgb(pointer(p )^ ).R:=c.r;
+ order_rgb(pointer(p )^ ).G:=c.g;
+ order_rgb(pointer(p )^ ).B:=c.b;
+
+ inc(ptrcomp(p ) ,3 );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ blend_pix_rgb(p ,c.r ,c.g ,c.b ,alpha );
+
+ inc(ptrcomp(p ) ,3 );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ rgb24_blend_vline }
+procedure rgb24_blend_vline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+var
+ p : int8u_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x );
+
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ repeat
+ order_rgb(pointer(p )^ ).R:=c.r;
+ order_rgb(pointer(p )^ ).G:=c.g;
+ order_rgb(pointer(p )^ ).B:=c.b;
+
+ p:=int8u_ptr(this.m_rbuf.next_row(p ) );
+
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ blend_pix_rgb(p ,c.r ,c.g ,c.b ,alpha ,cover );
+
+ p:=int8u_ptr(this.m_rbuf.next_row(p ) );
+
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ rgb24_blend_solid_hspan }
+procedure rgb24_blend_solid_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+var
+ p : int8u_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x );
+
+ repeat
+ alpha:=(c.a * (covers^ + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_rgb(pointer(p )^ ).R:=c.r;
+ order_rgb(pointer(p )^ ).G:=c.g;
+ order_rgb(pointer(p )^ ).B:=c.b;
+
+ end
+ else
+ blend_pix_rgb(p ,c.r ,c.g ,c.b ,alpha ,covers^ );
+
+ inc(ptrcomp(p ) ,3 );
+ inc(ptrcomp(covers ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ rgb24_blend_solid_vspan }
+procedure rgb24_blend_solid_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+var
+ p : int8u_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x );
+
+ repeat
+ alpha:=(c.a * (covers^ + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_rgb(pointer(p )^ ).R:=c.r;
+ order_rgb(pointer(p )^ ).G:=c.g;
+ order_rgb(pointer(p )^ ).B:=c.b;
+
+ end
+ else
+ blend_pix_rgb(p ,c.r ,c.g ,c.b ,alpha,covers^ );
+
+ p:=int8u_ptr(this.m_rbuf.next_row(p ) );
+
+ inc(ptrcomp(covers ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ rgb24_blend_color_hspan }
+procedure rgb24_blend_color_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+var
+ p : int8u_ptr;
+
+begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x );
+
+ if covers <> NIL then
+ repeat
+ copy_or_blend_pix_rgb(p ,colors ,covers^ );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+ inc(ptrcomp(p ) ,3 );
+ dec(len );
+
+ until len = 0
+ else
+ if cover = 255 then
+ repeat
+ copy_or_blend_pix_rgb(p ,colors );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(ptrcomp(p ) ,3 );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ copy_or_blend_pix_rgb(p ,colors ,cover );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(ptrcomp(p ) ,3 );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb24_blend_color_vspan }
+procedure rgb24_blend_color_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+var
+ p : int8u_ptr;
+
+begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x );
+
+ if covers <> NIL then
+ repeat
+ copy_or_blend_pix_rgb(p ,colors ,covers^ );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+
+ p:=int8u_ptr(this.m_rbuf.next_row(p ) );
+
+ dec(len );
+
+ until len = 0
+ else
+ if cover = 255 then
+ repeat
+ copy_or_blend_pix_rgb(p ,colors );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+
+ p:=int8u_ptr(this.m_rbuf.next_row(p ) );
+
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ copy_or_blend_pix_rgb(p ,colors ,cover );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+
+ p:=int8u_ptr(this.m_rbuf.next_row(p ) );
+
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb24_blend_from }
+procedure rgb24_blend_from(this : pixel_formats_ptr; from : pixel_formats_ptr; psrc_ : int8u_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ psrc ,pdst : int8u_ptr;
+
+ color : aggclr;
+ alpha : unsigned;
+
+begin
+ psrc:=psrc_;
+ pdst:=int8u_ptr(ptrcomp(this.m_rbuf.row(ydst ) ) + xdst * 3 * sizeof(int8u ) );
+
+ if cover = 255 then
+ repeat
+ alpha:=int8u_ptr(ptrcomp(psrc ) + from.m_order.A )^;
+
+ if alpha <> 0 then
+ if alpha = base_mask then
+ begin
+ order_rgb(pointer(pdst )^ ).R:=int8u_ptr(ptrcomp(psrc ) + from.m_order.R )^;
+ order_rgb(pointer(pdst )^ ).G:=int8u_ptr(ptrcomp(psrc ) + from.m_order.G )^;
+ order_rgb(pointer(pdst )^ ).B:=int8u_ptr(ptrcomp(psrc ) + from.m_order.B )^;
+
+ end
+ else
+ blend_pix_rgb(
+ pdst ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.R )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.G )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.B )^ ,
+ alpha );
+
+ inc(ptrcomp(psrc ) ,4 );
+ inc(ptrcomp(pdst ) ,3 );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ color.ConstrInt(
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.R )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.G )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.B )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.A )^ );
+
+ copy_or_blend_pix_rgb(pdst ,@color ,cover );
+
+ inc(ptrcomp(psrc ) ,4 );
+ inc(ptrcomp(pdst ) ,3 );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb24_copy_color_hspan }
+procedure rgb24_copy_color_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr );
+var
+ p : int8u_ptr;
+
+begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x );
+
+ repeat
+ order_rgb(pointer(p )^ ).R:=colors.r;
+ order_rgb(pointer(p )^ ).G:=colors.g;
+ order_rgb(pointer(p )^ ).B:=colors.b;
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(ptrcomp(p ) ,3 );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb24_copy_color_vspan }
+procedure rgb24_copy_color_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr );
+var
+ p : int8u_ptr;
+
+begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x );
+
+ repeat
+ order_rgb(pointer(p )^ ).R:=colors.r;
+ order_rgb(pointer(p )^ ).G:=colors.g;
+ order_rgb(pointer(p )^ ).B:=colors.b;
+
+ p:=int8u_ptr(this.m_rbuf.next_row(p ) );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb24_blend_from_color }
+procedure rgb24_blend_from_color(this : pixel_formats_ptr; from : pixel_formats_ptr; color : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ ppsz : unsigned;
+
+ psrc ,pdst : int8u_ptr;
+
+begin
+ ppsz:=from._pix_width;
+ psrc:=from.row_ptr(ysrc );
+
+ if psrc <> NIL then
+ begin
+ pdst:=int8u_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + xdst * 3 * sizeof(int8u ) );
+
+ repeat
+ copy_or_blend_pix_rgb(
+ pdst ,color ,
+ shr_int32(psrc^ * cover + base_mask ,base_shift ) );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,3 );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ rgb24_blend_from_lut }
+procedure rgb24_blend_from_lut(this : pixel_formats_ptr; from : pixel_formats_ptr; color_lut : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ ppsz : unsigned;
+
+ psrc ,pdst : int8u_ptr;
+
+ color : aggclr_ptr;
+
+begin
+ ppsz:=from._pix_width;
+ psrc:=from.row_ptr(ysrc );
+
+ if psrc <> NIL then
+ begin
+ pdst:=int8u_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + xdst * 3 * sizeof(int8u ) );
+
+ if cover = 255 then
+ repeat
+ color:=aggclr_ptr(ptrcomp(color_lut ) + psrc^ * sizeof(aggclr ) );
+
+ blend_pix_rgb(pdst ,color.r ,color.g ,color.b ,color.a );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,3 );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ copy_or_blend_pix_rgb(
+ pdst ,aggclr_ptr(ptrcomp(color_lut ) + psrc^ * sizeof(aggclr ) ) ,cover );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,3 );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
diff --git a/src/corelib/render/software/pf_rgb24_gamma.inc b/src/corelib/render/software/pf_rgb24_gamma.inc
new file mode 100644
index 00000000..63d659f8
--- /dev/null
+++ b/src/corelib/render/software/pf_rgb24_gamma.inc
@@ -0,0 +1,429 @@
+//
+// AggPas 2.4 RM3 pixel format definition file
+//
+{ blend_pix_rgb_gamma }
+procedure blend_pix_rgb_gamma(gamma : gamma_ptr; p : int8u_ptr; cr ,cg ,cb ,alpha : int; cover : unsigned = 0 );
+var
+ r ,g ,b : unsigned;
+
+begin
+ r:=gamma.dir(order_rgb(pointer(p )^ ).R );
+ g:=gamma.dir(order_rgb(pointer(p )^ ).G );
+ b:=gamma.dir(order_rgb(pointer(p )^ ).B );
+
+ order_rgb(pointer(p )^ ).R:=int8u(int(gamma.inv((((int(gamma.dir(cr ) ) - r ) * alpha ) shr base_shift ) + r ) ) );
+ order_rgb(pointer(p )^ ).G:=int8u(int(gamma.inv((((int(gamma.dir(cg ) ) - g ) * alpha ) shr base_shift ) + g ) ) );
+ order_rgb(pointer(p )^ ).B:=int8u(int(gamma.inv((((int(gamma.dir(cb ) ) - b ) * alpha ) shr base_shift ) + b ) ) );
+
+end;
+
+{ copy_or_blend_pix_rgb_gamma }
+procedure copy_or_blend_pix_rgb_gamma(gamma : gamma_ptr; p : int8u_ptr; c : aggclr_ptr; cover : unsigned ); overload;
+var
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_rgb(pointer(p )^ ).R:=c.r;
+ order_rgb(pointer(p )^ ).G:=c.g;
+ order_rgb(pointer(p )^ ).B:=c.b;
+
+ end
+ else
+ blend_pix_rgb_gamma(gamma ,p ,c.r ,c.g ,c.b ,alpha ,cover );
+
+ end;
+
+end;
+
+{ copy_or_blend_pix_rgb_gamma }
+procedure copy_or_blend_pix_rgb_gamma(gamma : gamma_ptr; p : int8u_ptr; c : aggclr_ptr ); overload;
+begin
+ if c.a <> 0 then
+ if c.a = base_mask then
+ begin
+ order_rgb(pointer(p )^ ).R:=c.r;
+ order_rgb(pointer(p )^ ).G:=c.g;
+ order_rgb(pointer(p )^ ).B:=c.b;
+
+ end
+ else
+ blend_pix_rgb_gamma(gamma ,p ,c.r ,c.g ,c.b ,c.a );
+
+end;
+
+{ rgb24_gamma_blend_pixel }
+procedure rgb24_gamma_blend_pixel(this : pixel_formats_ptr; x ,y : int; c : aggclr_ptr; cover : int8u );
+begin
+ copy_or_blend_pix_rgb_gamma(this.m_gamma ,int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x ) ,c ,cover );
+
+end;
+
+{ rgb24_gamma_blend_hline }
+procedure rgb24_gamma_blend_hline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+var
+ p : int8u_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x );
+
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ repeat
+ order_rgb(pointer(p )^ ).R:=c.r;
+ order_rgb(pointer(p )^ ).G:=c.g;
+ order_rgb(pointer(p )^ ).B:=c.b;
+
+ inc(ptrcomp(p ) ,3 );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ blend_pix_rgb_gamma(this.m_gamma ,p ,c.r ,c.g ,c.b ,alpha );
+
+ inc(ptrcomp(p ) ,3 );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ rgb24_gamma_blend_vline }
+procedure rgb24_gamma_blend_vline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+var
+ p : int8u_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x );
+
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ repeat
+ order_rgb(pointer(p )^ ).R:=c.r;
+ order_rgb(pointer(p )^ ).G:=c.g;
+ order_rgb(pointer(p )^ ).B:=c.b;
+
+ p:=int8u_ptr(this.m_rbuf.next_row(p ) );
+
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ blend_pix_rgb_gamma(this.m_gamma ,p ,c.r ,c.g ,c.b ,alpha ,cover );
+
+ p:=int8u_ptr(this.m_rbuf.next_row(p ) );
+
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ rgb24_gamma_blend_solid_hspan }
+procedure rgb24_gamma_blend_solid_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+var
+ p : int8u_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x );
+
+ repeat
+ alpha:=(c.a * (covers^ + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_rgb(pointer(p )^ ).R:=c.r;
+ order_rgb(pointer(p )^ ).G:=c.g;
+ order_rgb(pointer(p )^ ).B:=c.b;
+
+ end
+ else
+ blend_pix_rgb_gamma(this.m_gamma ,p ,c.r ,c.g ,c.b ,alpha ,covers^ );
+
+ inc(ptrcomp(p ) ,3 );
+ inc(ptrcomp(covers ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ rgb24_gamma_blend_solid_vspan }
+procedure rgb24_gamma_blend_solid_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+var
+ p : int8u_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x );
+
+ repeat
+ alpha:=(c.a * (covers^ + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_rgb(pointer(p )^ ).R:=c.r;
+ order_rgb(pointer(p )^ ).G:=c.g;
+ order_rgb(pointer(p )^ ).B:=c.b;
+
+ end
+ else
+ blend_pix_rgb_gamma(this.m_gamma ,p ,c.r ,c.g ,c.b ,alpha,covers^ );
+
+ p:=int8u_ptr(this.m_rbuf.next_row(p ) );
+
+ inc(ptrcomp(covers ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ rgb24_gamma_blend_color_hspan }
+procedure rgb24_gamma_blend_color_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+var
+ p : int8u_ptr;
+
+begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x );
+
+ if covers <> NIL then
+ repeat
+ copy_or_blend_pix_rgb_gamma(this.m_gamma ,p ,colors ,covers^ );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+ inc(ptrcomp(p ) ,3 );
+ dec(len );
+
+ until len = 0
+ else
+ if cover = 255 then
+ repeat
+ copy_or_blend_pix_rgb_gamma(this.m_gamma ,p ,colors );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(ptrcomp(p ) ,3 );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ copy_or_blend_pix_rgb_gamma(this.m_gamma ,p ,colors ,cover );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(ptrcomp(p ) ,3 );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb24_gamma_blend_color_vspan }
+procedure rgb24_gamma_blend_color_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+var
+ p : int8u_ptr;
+
+begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x );
+
+ if covers <> NIL then
+ repeat
+ copy_or_blend_pix_rgb_gamma(this.m_gamma ,p ,colors ,covers^ );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+
+ p:=int8u_ptr(this.m_rbuf.next_row(p ) );
+
+ dec(len );
+
+ until len = 0
+ else
+ if cover = 255 then
+ repeat
+ copy_or_blend_pix_rgb_gamma(this.m_gamma ,p ,colors );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+
+ p:=int8u_ptr(this.m_rbuf.next_row(p ) );
+
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ copy_or_blend_pix_rgb_gamma(this.m_gamma ,p ,colors ,cover );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+
+ p:=int8u_ptr(this.m_rbuf.next_row(p ) );
+
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb24_gamma_blend_from }
+procedure rgb24_gamma_blend_from(this : pixel_formats_ptr; from : pixel_formats_ptr; psrc_ : int8u_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ psrc ,pdst : int8u_ptr;
+
+ color : aggclr;
+ alpha : unsigned;
+
+begin
+ psrc:=psrc_;
+ pdst:=int8u_ptr(ptrcomp(this.m_rbuf.row(ydst ) ) + xdst * 3 * sizeof(int8u ) );
+
+ if cover = 255 then
+ repeat
+ alpha:=int8u_ptr(ptrcomp(psrc ) + from.m_order.A )^;
+
+ if alpha <> 0 then
+ if alpha = base_mask then
+ begin
+ order_rgb(pointer(pdst )^ ).R:=int8u_ptr(ptrcomp(psrc ) + from.m_order.R )^;
+ order_rgb(pointer(pdst )^ ).G:=int8u_ptr(ptrcomp(psrc ) + from.m_order.G )^;
+ order_rgb(pointer(pdst )^ ).B:=int8u_ptr(ptrcomp(psrc ) + from.m_order.B )^;
+
+ end
+ else
+ blend_pix_rgb_gamma(
+ this.m_gamma ,pdst ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.R )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.G )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.B )^ ,
+ alpha );
+
+ inc(ptrcomp(psrc ) ,4 );
+ inc(ptrcomp(pdst ) ,3 );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ color.ConstrInt(
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.R )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.G )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.B )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.A )^ );
+
+ copy_or_blend_pix_rgb_gamma(this.m_gamma ,pdst ,@color ,cover );
+
+ inc(ptrcomp(psrc ) ,4 );
+ inc(ptrcomp(pdst ) ,3 );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb24_gamma_blend_from_color }
+procedure rgb24_gamma_blend_from_color(this : pixel_formats_ptr; from : pixel_formats_ptr; color : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ ppsz : unsigned;
+
+ psrc ,pdst : int8u_ptr;
+
+begin
+ ppsz:=from._pix_width;
+ psrc:=from.row_ptr(ysrc );
+
+ if psrc <> NIL then
+ begin
+ pdst:=int8u_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + xdst * 3 * sizeof(int8u ) );
+
+ repeat
+ copy_or_blend_pix_rgb_gamma(
+ this.m_gamma ,
+ pdst ,color ,
+ shr_int32(psrc^ * cover + base_mask ,base_shift ) );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,3 );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ rgb24_gamma_blend_from_lut }
+procedure rgb24_gamma_blend_from_lut(this : pixel_formats_ptr; from : pixel_formats_ptr; color_lut : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ ppsz : unsigned;
+
+ psrc ,pdst : int8u_ptr;
+
+ color : aggclr_ptr;
+
+begin
+ ppsz:=from._pix_width;
+ psrc:=from.row_ptr(ysrc );
+
+ if psrc <> NIL then
+ begin
+ pdst:=int8u_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + xdst * 3 * sizeof(int8u ) );
+
+ if cover = 255 then
+ repeat
+ color:=aggclr_ptr(ptrcomp(color_lut ) + psrc^ * sizeof(aggclr ) );
+
+ blend_pix_rgb_gamma(this.m_gamma ,pdst ,color.r ,color.g ,color.b ,color.a );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,3 );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ copy_or_blend_pix_rgb_gamma(
+ this.m_gamma ,
+ pdst ,aggclr_ptr(ptrcomp(color_lut ) + psrc^ * sizeof(aggclr ) ) ,cover);
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,3 );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
diff --git a/src/corelib/render/software/pf_rgb24_pre.inc b/src/corelib/render/software/pf_rgb24_pre.inc
new file mode 100644
index 00000000..e71f23ed
--- /dev/null
+++ b/src/corelib/render/software/pf_rgb24_pre.inc
@@ -0,0 +1,434 @@
+//
+// AggPas 2.4 RM3 pixel format definition file
+//
+{ blend_pix_rgb_pre }
+procedure blend_pix_rgb_pre(p : int8u_ptr; cr ,cg ,cb ,alpha ,cover : unsigned ); overload;
+begin
+ alpha:=base_mask - alpha;
+ cover:=(cover + 1 ) shl (base_shift - 8 );
+
+ order_rgb(pointer(p )^ ).R:=int8u((order_rgb(pointer(p )^ ).R * alpha + cr * cover ) shr base_shift );
+ order_rgb(pointer(p )^ ).G:=int8u((order_rgb(pointer(p )^ ).G * alpha + cg * cover ) shr base_shift );
+ order_rgb(pointer(p )^ ).B:=int8u((order_rgb(pointer(p )^ ).B * alpha + cb * cover ) shr base_shift );
+
+end;
+
+{ blend_pix_rgb_pre }
+procedure blend_pix_rgb_pre(p : int8u_ptr; cr ,cg ,cb ,alpha : unsigned ); overload;
+begin
+ alpha:=base_mask - alpha;
+
+ order_rgb(pointer(p )^ ).R:=int8u(((order_rgb(pointer(p )^ ).R * alpha ) shr base_shift ) + cr );
+ order_rgb(pointer(p )^ ).G:=int8u(((order_rgb(pointer(p )^ ).G * alpha ) shr base_shift ) + cg );
+ order_rgb(pointer(p )^ ).B:=int8u(((order_rgb(pointer(p )^ ).B * alpha ) shr base_shift ) + cb );
+
+end;
+
+{ copy_or_blend_pix_rgb_pre }
+procedure copy_or_blend_pix_rgb_pre(p : int8u_ptr; c : aggclr_ptr; cover : unsigned ); overload;
+var
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_rgb(pointer(p )^ ).R:=c.r;
+ order_rgb(pointer(p )^ ).G:=c.g;
+ order_rgb(pointer(p )^ ).B:=c.b;
+
+ end
+ else
+ blend_pix_rgb_pre(p ,c.r ,c.g ,c.b ,alpha ,cover );
+
+ end;
+
+end;
+
+{ copy_or_blend_pix_rgb_pre }
+procedure copy_or_blend_pix_rgb_pre(p : int8u_ptr; c : aggclr_ptr ); overload;
+begin
+ if c.a <> 0 then
+ if c.a = base_mask then
+ begin
+ order_rgb(pointer(p )^ ).R:=c.r;
+ order_rgb(pointer(p )^ ).G:=c.g;
+ order_rgb(pointer(p )^ ).B:=c.b;
+
+ end
+ else
+ blend_pix_rgb_pre(p ,c.r ,c.g ,c.b ,c.a );
+
+end;
+
+{ rgb24_pre_blend_pixel }
+procedure rgb24_pre_blend_pixel(this : pixel_formats_ptr; x ,y : int; c : aggclr_ptr; cover : int8u );
+begin
+ copy_or_blend_pix_rgb_pre(int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x ) ,c ,cover );
+
+end;
+
+{ rgb24_pre_blend_hline }
+procedure rgb24_pre_blend_hline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+var
+ p : int8u_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x );
+
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ repeat
+ order_rgb(pointer(p )^ ).R:=c.r;
+ order_rgb(pointer(p )^ ).G:=c.g;
+ order_rgb(pointer(p )^ ).B:=c.b;
+
+ inc(ptrcomp(p ) ,3 );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ blend_pix_rgb_pre(p ,c.r ,c.g ,c.b ,alpha );
+
+ inc(ptrcomp(p ) ,3 );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ rgb24_pre_blend_vline }
+procedure rgb24_pre_blend_vline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+var
+ p : int8u_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x );
+
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ repeat
+ order_rgb(pointer(p )^ ).R:=c.r;
+ order_rgb(pointer(p )^ ).G:=c.g;
+ order_rgb(pointer(p )^ ).B:=c.b;
+
+ p:=int8u_ptr(this.m_rbuf.next_row(p ) );
+
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ blend_pix_rgb_pre(p ,c.r ,c.g ,c.b ,alpha ,cover );
+
+ p:=int8u_ptr(this.m_rbuf.next_row(p ) );
+
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ rgb24_pre_blend_solid_hspan }
+procedure rgb24_pre_blend_solid_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+var
+ p : int8u_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x );
+
+ repeat
+ alpha:=(c.a * (covers^ + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_rgb(pointer(p )^ ).R:=c.r;
+ order_rgb(pointer(p )^ ).G:=c.g;
+ order_rgb(pointer(p )^ ).B:=c.b;
+
+ end
+ else
+ blend_pix_rgb_pre(p ,c.r ,c.g ,c.b ,alpha ,covers^ );
+
+ inc(ptrcomp(p ) ,3 );
+ inc(ptrcomp(covers ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ rgb24_pre_blend_solid_vspan }
+procedure rgb24_pre_blend_solid_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+var
+ p : int8u_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x );
+
+ repeat
+ alpha:=(c.a * (covers^ + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_rgb(pointer(p )^ ).R:=c.r;
+ order_rgb(pointer(p )^ ).G:=c.g;
+ order_rgb(pointer(p )^ ).B:=c.b;
+
+ end
+ else
+ blend_pix_rgb_pre(p ,c.r ,c.g ,c.b ,alpha,covers^ );
+
+ p:=int8u_ptr(this.m_rbuf.next_row(p ) );
+
+ inc(ptrcomp(covers ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ rgb24_pre_blend_color_hspan }
+procedure rgb24_pre_blend_color_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+var
+ p : int8u_ptr;
+
+begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x );
+
+ if covers <> NIL then
+ repeat
+ copy_or_blend_pix_rgb_pre(p ,colors ,covers^ );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+ inc(ptrcomp(p ) ,3 );
+ dec(len );
+
+ until len = 0
+ else
+ if cover = 255 then
+ repeat
+ copy_or_blend_pix_rgb_pre(p ,colors );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(ptrcomp(p ) ,3 );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ copy_or_blend_pix_rgb_pre(p ,colors ,cover );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(ptrcomp(p ) ,3 );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb24_pre_blend_color_vspan }
+procedure rgb24_pre_blend_color_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+var
+ p : int8u_ptr;
+
+begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x + x + x );
+
+ if covers <> NIL then
+ repeat
+ copy_or_blend_pix_rgb_pre(p ,colors ,covers^ );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+
+ p:=int8u_ptr(this.m_rbuf.next_row(p ) );
+
+ dec(len );
+
+ until len = 0
+ else
+ if cover = 255 then
+ repeat
+ copy_or_blend_pix_rgb_pre(p ,colors );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+
+ p:=int8u_ptr(this.m_rbuf.next_row(p ) );
+
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ copy_or_blend_pix_rgb_pre(p ,colors ,cover );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+
+ p:=int8u_ptr(this.m_rbuf.next_row(p ) );
+
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb24_pre_blend_from }
+procedure rgb24_pre_blend_from(this : pixel_formats_ptr; from : pixel_formats_ptr; psrc_ : int8u_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ psrc ,pdst : int8u_ptr;
+
+ color : aggclr;
+ alpha : unsigned;
+
+begin
+ psrc:=psrc_;
+ pdst:=int8u_ptr(ptrcomp(this.m_rbuf.row(ydst ) ) + xdst * 3 * sizeof(int8u ) );
+
+ if cover = 255 then
+ repeat
+ alpha:=int8u_ptr(ptrcomp(psrc ) + from.m_order.A )^;
+
+ if alpha <> 0 then
+ if alpha = base_mask then
+ begin
+ order_rgb(pointer(pdst )^ ).R:=int8u_ptr(ptrcomp(psrc ) + from.m_order.R )^;
+ order_rgb(pointer(pdst )^ ).G:=int8u_ptr(ptrcomp(psrc ) + from.m_order.G )^;
+ order_rgb(pointer(pdst )^ ).B:=int8u_ptr(ptrcomp(psrc ) + from.m_order.B )^;
+
+ end
+ else
+ blend_pix_rgb_pre(
+ pdst ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.R )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.G )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.B )^ ,
+ alpha );
+
+ inc(ptrcomp(psrc ) ,4 );
+ inc(ptrcomp(pdst ) ,3 );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ color.ConstrInt(
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.R )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.G )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.B )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.A )^ );
+
+ copy_or_blend_pix_rgb_pre(pdst ,@color ,cover );
+
+ inc(ptrcomp(psrc ) ,4 );
+ inc(ptrcomp(pdst ) ,3 );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb24_pre_blend_from_color }
+procedure rgb24_pre_blend_from_color(this : pixel_formats_ptr; from : pixel_formats_ptr; color : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ ppsz : unsigned;
+
+ psrc ,pdst : int8u_ptr;
+
+begin
+ ppsz:=from._pix_width;
+ psrc:=from.row_ptr(ysrc );
+
+ if psrc <> NIL then
+ begin
+ pdst:=int8u_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + xdst * 3 * sizeof(int8u ) );
+
+ repeat
+ copy_or_blend_pix_rgb_pre(
+ pdst ,color ,
+ shr_int32(psrc^ * cover + base_mask ,base_shift ) );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,3 );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ rgb24_pre_blend_from_lut }
+procedure rgb24_pre_blend_from_lut(this : pixel_formats_ptr; from : pixel_formats_ptr; color_lut : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ ppsz : unsigned;
+
+ psrc ,pdst : int8u_ptr;
+
+ color : aggclr_ptr;
+
+begin
+ ppsz:=from._pix_width;
+ psrc:=from.row_ptr(ysrc );
+
+ if psrc <> NIL then
+ begin
+ pdst:=int8u_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + xdst * 3 * sizeof(int8u ) );
+
+ if cover = 255 then
+ repeat
+ color:=aggclr_ptr(ptrcomp(color_lut ) + psrc^ * sizeof(aggclr ) );
+
+ blend_pix_rgb_pre(pdst ,color.r ,color.g ,color.b ,color.a );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,3 );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ copy_or_blend_pix_rgb_pre(
+ pdst ,aggclr_ptr(ptrcomp(color_lut ) + psrc^ * sizeof(aggclr ) ) ,cover);
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,3 );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
diff --git a/src/corelib/render/software/pf_rgb555.inc b/src/corelib/render/software/pf_rgb555.inc
new file mode 100644
index 00000000..12c6546c
--- /dev/null
+++ b/src/corelib/render/software/pf_rgb555.inc
@@ -0,0 +1,453 @@
+//
+// AggPas 2.4 RM3 pixel format definition file
+//
+{ make_pix_555 }
+function make_pix_555(r ,g ,b : unsigned ) : int16u;
+begin
+ result:=int16u(
+ ((r and $F8 ) shl 7 ) or
+ ((g and $F8 ) shl 2 ) or
+ (b shr 3 ) or
+ $8000 );
+
+end;
+
+{ make_color_555 }
+procedure make_color_555(var color : aggclr; p : int16u_ptr );
+begin
+ color.ConstrInt(
+ (p^ shr 7) and $F8 ,
+ (p^ shr 2) and $F8 ,
+ (p^ shl 3) and $F8 );
+
+end;
+
+{ blend_pix_555 }
+procedure blend_pix_555(p : int16u_ptr; cr ,cg ,cb ,alpha : unsigned );
+var
+ rgb : int16u;
+
+ r ,g ,b : int;
+
+begin
+ rgb:=p^;
+
+ r:=(rgb shr 7) and $F8;
+ g:=(rgb shr 2) and $F8;
+ b:=(rgb shl 3) and $F8;
+
+ p^:=int16u(
+ ((((cr - r ) * alpha + (r shl 8 ) ) shr 1 ) and $7C00 ) or
+ ((((cg - g ) * alpha + (g shl 8 ) ) shr 6 ) and $03E0 ) or
+ (((cb - b ) * alpha + (b shl 8 ) ) shr 11 ) or $8000 );
+
+end;
+
+{ copy_or_blend_pix_555 }
+procedure copy_or_blend_pix_555(p : int16u_ptr; c : aggclr_ptr; cover : unsigned );
+var
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ p^:=make_pix_555(c.r ,c.g ,c.b )
+ else
+ blend_pix_555(p ,c.r ,c.g ,c.b ,alpha );
+
+ end;
+
+end;
+
+{ rgb555_copy_pixel }
+procedure rgb555_copy_pixel(this : pixel_formats_ptr; x ,y : int; c : aggclr_ptr );
+begin
+ int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) )^:=make_pix_555(c.r ,c.g ,c.b );
+
+end;
+
+{ rgb555_blend_pixel }
+procedure rgb555_blend_pixel(this : pixel_formats_ptr; x ,y : int; c : aggclr_ptr; cover : int8u );
+begin
+ copy_or_blend_pix_555(int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) ) ,c ,cover );
+
+end;
+
+{ rgb555_pixel }
+function rgb555_pixel(this : pixel_formats_ptr; x ,y : int ) : aggclr;
+begin
+ make_color_555(
+ result ,
+ int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) ) );
+
+end;
+
+{ rgb555_copy_hline }
+procedure rgb555_copy_hline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr );
+var
+ p : int16u_ptr;
+ v : int16u;
+
+begin
+ p:=int16u_ptr (ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+ v:=make_pix_555(c.r ,c.g ,c.b );
+
+ repeat
+ p^:=v;
+
+ inc(ptrcomp(p ) ,sizeof(int16u ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb555_copy_vline }
+procedure rgb555_copy_vline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr );
+var
+ p : int16u_ptr;
+ v : int16u;
+
+begin
+ p:=int16u_ptr (ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+ v:=make_pix_555(c.r ,c.g ,c.b );
+
+ repeat
+ p^:=v;
+ p :=int16u_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb555_blend_hline }
+procedure rgb555_blend_hline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+var
+ p : int16u_ptr;
+ v : int16u;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ v:=make_pix_555(c.r ,c.g ,c.b );
+
+ repeat
+ p^:=v;
+
+ inc(ptrcomp(p ) ,sizeof(int16u ) );
+ dec(len );
+
+ until len = 0;
+
+ end
+ else
+ repeat
+ blend_pix_555(p ,c.r ,c.g ,c.b ,alpha );
+
+ inc(ptrcomp(p ) ,sizeof(int16u ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ rgb555_blend_vline }
+procedure rgb555_blend_vline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+var
+ p : int16u_ptr;
+ v : int16u;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ v:=make_pix_555(c.r ,c.g ,c.b );
+
+ repeat
+ p^:=v;
+ p :=int16u_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ dec(len );
+
+ until len = 0;
+
+ end
+ else
+ repeat
+ blend_pix_555(p ,c.r ,c.g ,c.b ,alpha );
+
+ p:=int16u_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ rgb555_blend_solid_hspan }
+procedure rgb555_blend_solid_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+var
+ p : int16u_ptr;
+
+begin
+ p:=int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+
+ repeat
+ copy_or_blend_pix_555(p ,c ,covers^ );
+
+ inc(ptrcomp(covers ) );
+ inc(ptrcomp(p ) ,sizeof(int16u ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb555_blend_solid_vspan }
+procedure rgb555_blend_solid_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+var
+ p : int16u_ptr;
+
+begin
+ p:=int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+
+ repeat
+ copy_or_blend_pix_555(p ,c ,covers^ );
+
+ inc(ptrcomp(covers ) );
+
+ p:=int16u_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb555_blend_color_hspan }
+procedure rgb555_blend_color_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+var
+ p : int16u_ptr;
+
+begin
+ p:=int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+
+ repeat
+ if covers <> NIL then
+ begin
+ copy_or_blend_pix_555(p ,colors ,covers^ );
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+
+ end
+ else
+ copy_or_blend_pix_555(p ,colors ,cover );
+
+ inc(ptrcomp(p ) ,sizeof(int16u ) );
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb555_blend_color_vspan }
+procedure rgb555_blend_color_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+var
+ p : int16u_ptr;
+
+begin
+ p:=int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+
+ repeat
+ if covers <> NIL then
+ begin
+ copy_or_blend_pix_555(p ,colors ,covers^ );
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+
+ end
+ else
+ copy_or_blend_pix_555(p ,colors ,cover );
+
+ p:=int16u_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb555_copy_from }
+procedure rgb555_copy_from(this : pixel_formats_ptr; from : rendering_buffer_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned );
+begin
+ move(
+ int16u_ptr(ptrcomp(from.row(ysrc ) ) + xsrc * sizeof(int16u ) )^ ,
+ int16u_ptr(ptrcomp(this.m_rbuf.row(ydst ) ) + xdst * sizeof(int16 ) )^ ,
+ len * sizeof(int16u ) );
+
+end;
+
+{ rgb555_blend_from }
+procedure rgb555_blend_from(this : pixel_formats_ptr; from : pixel_formats_ptr; psrc_ : int8u_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ psrc : int8u_ptr;
+ pdst : int16u_ptr;
+
+ alpha : unsigned;
+
+begin
+ psrc:=psrc_;
+ pdst:=int16u_ptr(ptrcomp(this.m_rbuf.row(ydst ) ) + xdst * sizeof(int16u ) );
+
+ repeat
+ alpha:=int8u_ptr(ptrcomp(psrc ) + from.m_order.A )^;
+
+ if alpha <> 0 then
+ if (alpha = base_mask ) and
+ (cover = 255 ) then
+ pdst^:=make_pix_555(
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.R )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.G )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.B )^ )
+ else
+ blend_pix_555(
+ pdst ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.R )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.G )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.B )^ ,
+ alpha );
+
+ inc(ptrcomp(psrc ) ,4 );
+ inc(ptrcomp(pdst ) ,sizeof(int16u ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb555_copy_color_hspan }
+procedure rgb555_copy_color_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr );
+var
+ p : int16u_ptr;
+
+begin
+ p:=int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+
+ repeat
+ p^:=make_pix_555(colors.r ,colors.g ,colors.b );
+
+ inc(ptrcomp(p ) ,sizeof(int16u ) );
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb555_copy_color_vspan }
+procedure rgb555_copy_color_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr );
+var
+ p : int16u_ptr;
+
+begin
+ p:=int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+
+ repeat
+ p^:=make_pix_555(colors.r ,colors.g ,colors.b );
+ p :=int16u_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb555_blend_from_color }
+procedure rgb555_blend_from_color(this : pixel_formats_ptr; from : pixel_formats_ptr; color : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ ppsz : unsigned;
+
+ psrc : int8u_ptr;
+ pdst : int16u_ptr;
+
+begin
+ ppsz:=from._pix_width;
+ psrc:=from.row_ptr(ysrc );
+
+ if psrc <> NIL then
+ begin
+ pdst:=int16u_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + xdst * sizeof(int16u ) );
+
+ repeat
+ blend_pix_555(pdst ,color.r ,color.g ,color.b ,shr_int32(psrc^ * cover + base_mask ,base_shift ) );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,sizeof(int16u ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ rgb555_blend_from_lut }
+procedure rgb555_blend_from_lut(this : pixel_formats_ptr; from : pixel_formats_ptr; color_lut : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ ppsz : unsigned;
+
+ psrc : int8u_ptr;
+ pdst : int16u_ptr;
+
+ color : aggclr_ptr;
+
+begin
+ ppsz:=from._pix_width;
+ psrc:=from.row_ptr(ysrc );
+
+ if psrc <> NIL then
+ begin
+ pdst:=int16u_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + xdst * sizeof(int16u ) );
+
+ repeat
+ color:=aggclr_ptr(ptrcomp(color_lut ) + psrc^ * sizeof(aggclr ) );
+
+ blend_pix_555(pdst ,color.r ,color.g ,color.b ,shr_int32(psrc^ * cover + base_mask ,base_shift ) );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,sizeof(int16u ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
diff --git a/src/corelib/render/software/pf_rgb555_gamma.inc b/src/corelib/render/software/pf_rgb555_gamma.inc
new file mode 100644
index 00000000..c86ec0b8
--- /dev/null
+++ b/src/corelib/render/software/pf_rgb555_gamma.inc
@@ -0,0 +1,458 @@
+//
+// AggPas 2.4 RM3 pixel format definition file
+//
+{ make_pix_555_gamma }
+function make_pix_555_gamma(r ,g ,b : unsigned ) : int16u;
+begin
+ result:=int16u(
+ ((r and $F8 ) shl 7 ) or
+ ((g and $F8 ) shl 2 ) or
+ (b shr 3 ) or
+ $8000 );
+
+end;
+
+{ make_color_555_gamma }
+procedure make_color_555_gamma(var color : aggclr; p : int16u_ptr );
+begin
+ color.ConstrInt(
+ (p^ shr 7 ) and $F8 ,
+ (p^ shr 2 ) and $F8 ,
+ (p^ shl 3 ) and $F8 )
+
+end;
+
+{ blend_pix_555_gamma }
+procedure blend_pix_555_gamma(gamma : gamma_ptr; p : int16u_ptr; cr ,cg ,cb ,alpha ,cover : unsigned );
+var
+ rgb : int16u;
+
+ r ,g ,b : int;
+
+begin
+ rgb:=p^;
+
+ r:=gamma.dir((rgb shr 7 ) and $F8 );
+ g:=gamma.dir((rgb shr 2 ) and $F8 );
+ b:=gamma.dir((rgb shl 3 ) and $F8 );
+
+ p^:=int16u(
+ ((gamma.inv(((gamma.dir(cr ) - r ) * alpha + (r shl 8 ) ) shr 8 ) shl 7 ) and $7C00 ) or
+ ((gamma.inv(((gamma.dir(cg ) - g ) * alpha + (g shl 8 ) ) shr 8 ) shl 2 ) and $03E0 ) or
+ (gamma.inv(((gamma.dir(cb ) - b ) * alpha + (b shl 8 ) ) shr 8 ) shr 3 ) or $8000 );
+
+end;
+
+{ copy_or_blend_pix_555_gamma }
+procedure copy_or_blend_pix_555_gamma(gamma : gamma_ptr; p : int16u_ptr; c : aggclr_ptr; cover : unsigned );
+var
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ p^:=make_pix_555_gamma(c.r ,c.g ,c.b )
+ else
+ blend_pix_555_gamma(gamma ,p ,c.r ,c.g ,c.b ,alpha ,cover );
+
+ end;
+
+end;
+
+{ rgb555_gamma_copy_pixel }
+procedure rgb555_gamma_copy_pixel(this : pixel_formats_ptr; x ,y : int; c : aggclr_ptr );
+begin
+ int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) )^:=make_pix_555_gamma(c.r ,c.g ,c.b );
+
+end;
+
+{ rgb555_gamma_blend_pixel }
+procedure rgb555_gamma_blend_pixel(this : pixel_formats_ptr; x ,y : int; c : aggclr_ptr; cover : int8u );
+begin
+ copy_or_blend_pix_555_gamma(this.m_gamma ,int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) ) ,c ,cover );
+
+end;
+
+{ rgb555_gamma_pixel }
+function rgb555_gamma_pixel(this : pixel_formats_ptr; x ,y : int ) : aggclr;
+begin
+ make_color_555_gamma(
+ result ,
+ int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) ) );
+
+end;
+
+{ rgb555_gamma_copy_hline }
+procedure rgb555_gamma_copy_hline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr );
+var
+ p : int16u_ptr;
+ v : int16u;
+
+begin
+ p:=int16u_ptr (ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+ v:=make_pix_555_gamma(c.r ,c.g ,c.b );
+
+ repeat
+ p^:=v;
+
+ inc(ptrcomp(p ) ,sizeof(int16u ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb555_gamma_copy_vline }
+procedure rgb555_gamma_copy_vline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr );
+var
+ p : int16u_ptr;
+ v : int16u;
+
+begin
+ p:=int16u_ptr (ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+ v:=make_pix_555_gamma(c.r ,c.g ,c.b );
+
+ repeat
+ p^:=v;
+ p :=int16u_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb555_gamma_blend_hline }
+procedure rgb555_gamma_blend_hline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+var
+ p : int16u_ptr;
+ v : int16u;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ v:=make_pix_555_gamma(c.r ,c.g ,c.b );
+
+ repeat
+ p^:=v;
+
+ inc(ptrcomp(p ) ,sizeof(int16u ) );
+ dec(len );
+
+ until len = 0;
+
+ end
+ else
+ repeat
+ blend_pix_555_gamma(this.m_gamma ,p ,c.r ,c.g ,c.b ,alpha ,cover );
+
+ inc(ptrcomp(p ) ,sizeof(int16u ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ rgb555_gamma_blend_vline }
+procedure rgb555_gamma_blend_vline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+var
+ p : int16u_ptr;
+ v : int16u;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ v:=make_pix_555_gamma(c.r ,c.g ,c.b );
+
+ repeat
+ p^:=v;
+ p :=int16u_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ dec(len );
+
+ until len = 0;
+
+ end
+ else
+ repeat
+ blend_pix_555_gamma(this.m_gamma ,p ,c.r ,c.g ,c.b ,alpha ,cover );
+
+ p:=int16u_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ rgb555_gamma_blend_solid_hspan }
+procedure rgb555_gamma_blend_solid_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+var
+ p : int16u_ptr;
+
+begin
+ p:=int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+
+ repeat
+ copy_or_blend_pix_555_gamma(this.m_gamma ,p ,c ,covers^ );
+
+ inc(ptrcomp(covers ) );
+ inc(ptrcomp(p ) ,sizeof(int16u ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb555_gamma_blend_solid_vspan }
+procedure rgb555_gamma_blend_solid_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+var
+ p : int16u_ptr;
+
+begin
+ p:=int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+
+ repeat
+ copy_or_blend_pix_555_gamma(this.m_gamma ,p ,c ,covers^ );
+
+ inc(ptrcomp(covers ) );
+
+ p:=int16u_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb555_gamma_blend_color_hspan }
+procedure rgb555_gamma_blend_color_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+var
+ p : int16u_ptr;
+
+begin
+ p:=int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+
+ repeat
+ if covers <> NIL then
+ begin
+ copy_or_blend_pix_555_gamma(this.m_gamma ,p ,colors ,covers^ );
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+
+ end
+ else
+ copy_or_blend_pix_555_gamma(this.m_gamma ,p ,colors ,cover );
+
+ inc(ptrcomp(p ) ,sizeof(int16u ) );
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb555_gamma_blend_color_vspan }
+procedure rgb555_gamma_blend_color_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+var
+ p : int16u_ptr;
+
+begin
+ p:=int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+
+ repeat
+ if covers <> NIL then
+ begin
+ copy_or_blend_pix_555_gamma(this.m_gamma ,p ,colors ,covers^ );
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+
+ end
+ else
+ copy_or_blend_pix_555_gamma(this.m_gamma ,p ,colors ,cover );
+
+ p:=int16u_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb555_gamma_copy_from }
+procedure rgb555_gamma_copy_from(this : pixel_formats_ptr; from : rendering_buffer_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned );
+begin
+ move(
+ int16u_ptr(ptrcomp(from.row(ysrc ) ) + xsrc * sizeof(int16u ) )^ ,
+ int16u_ptr(ptrcomp(this.m_rbuf.row(ydst ) ) + xdst * sizeof(int16 ) )^ ,
+ len * sizeof(int16u ) );
+
+end;
+
+{ rgb555_gamma_blend_from }
+procedure rgb555_gamma_blend_from(this : pixel_formats_ptr; from : pixel_formats_ptr; psrc_ : int8u_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ psrc : int8u_ptr;
+ pdst : int16u_ptr;
+
+ alpha : unsigned;
+
+begin
+ psrc:=psrc_;
+ pdst:=int16u_ptr(ptrcomp(this.m_rbuf.row(ydst ) ) + xdst * sizeof(int16u ) );
+
+ repeat
+ alpha:=int8u_ptr(ptrcomp(psrc ) + from.m_order.A )^;
+
+ if alpha <> 0 then
+ if (alpha = base_mask ) and
+ (cover = 255 ) then
+ pdst^:=make_pix_555_gamma(
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.R )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.G )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.B )^ )
+ else
+ blend_pix_555_gamma(
+ this.m_gamma ,
+ pdst ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.R )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.G )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.B )^ ,
+ alpha ,cover );
+
+ inc(ptrcomp(psrc ) ,4 );
+ inc(ptrcomp(pdst ) ,sizeof(int16u ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb555_gamma_copy_color_hspan }
+procedure rgb555_gamma_copy_color_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr );
+var
+ p : int16u_ptr;
+
+begin
+ p:=int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+
+ repeat
+ p^:=make_pix_555_gamma(colors.r ,colors.g ,colors.b );
+
+ inc(ptrcomp(p ) ,sizeof(int16u ) );
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb555_gamma_copy_color_vspan }
+procedure rgb555_gamma_copy_color_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr );
+var
+ p : int16u_ptr;
+
+begin
+ p:=int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+
+ repeat
+ p^:=make_pix_555_gamma(colors.r ,colors.g ,colors.b );
+ p :=int16u_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb555_gamma_blend_from_color }
+procedure rgb555_gamma_blend_from_color(this : pixel_formats_ptr; from : pixel_formats_ptr; color : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ ppsz : unsigned;
+
+ psrc : int8u_ptr;
+ pdst : int16u_ptr;
+
+begin
+ ppsz:=from._pix_width;
+ psrc:=from.row_ptr(ysrc );
+
+ if psrc <> NIL then
+ begin
+ pdst:=int16u_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + xdst * sizeof(int16u ) );
+
+ repeat
+ blend_pix_555_gamma(
+ this.m_gamma ,
+ pdst ,color.r ,color.g ,color.b ,color.a ,shr_int32(psrc^ * cover + base_mask ,base_shift ) );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,sizeof(int16u ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ rgb555_gamma_blend_from_lut }
+procedure rgb555_gamma_blend_from_lut(this : pixel_formats_ptr; from : pixel_formats_ptr; color_lut : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ ppsz : unsigned;
+
+ psrc : int8u_ptr;
+ pdst : int16u_ptr;
+
+ color : aggclr_ptr;
+
+begin
+ ppsz:=from._pix_width;
+ psrc:=from.row_ptr(ysrc );
+
+ if psrc <> NIL then
+ begin
+ pdst:=int16u_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + xdst * sizeof(int16u ) );
+
+ repeat
+ color:=aggclr_ptr(ptrcomp(color_lut ) + psrc^ * sizeof(aggclr ) );
+
+ blend_pix_555_gamma(
+ this.m_gamma ,
+ pdst ,color.r ,color.g ,color.b ,color.a ,shr_int32(psrc^ * cover + base_mask ,base_shift ) );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,sizeof(int16u ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
diff --git a/src/corelib/render/software/pf_rgb555_pre.inc b/src/corelib/render/software/pf_rgb555_pre.inc
new file mode 100644
index 00000000..0d80418b
--- /dev/null
+++ b/src/corelib/render/software/pf_rgb555_pre.inc
@@ -0,0 +1,454 @@
+//
+// AggPas 2.4 RM3 pixel format definition file
+//
+{ make_pix_555_pre }
+function make_pix_555_pre(r ,g ,b : unsigned ) : int16u;
+begin
+ result:=int16u(
+ ((r and $F8 ) shl 7 ) or
+ ((g and $F8 ) shl 2 ) or
+ (b shr 3 ) or
+ $8000 );
+
+end;
+
+{ make_color_555_pre }
+procedure make_color_555_pre(var color : aggclr; p : int16u_ptr );
+begin
+ color.ConstrInt(
+ (p^ shr 7 ) and $F8 ,
+ (p^ shr 2 ) and $F8 ,
+ (p^ shl 3 ) and $F8 )
+
+end;
+
+{ blend_pix_555_pre }
+procedure blend_pix_555_pre(p : int16u_ptr; cr ,cg ,cb ,alpha ,cover : unsigned );
+var
+ rgb : int16u;
+
+ r ,g ,b : int;
+
+begin
+ alpha:=base_mask - alpha;
+ rgb :=p^;
+
+ r:=(rgb shr 7 ) and $F8;
+ g:=(rgb shr 2 ) and $F8;
+ b:=(rgb shl 3 ) and $F8;
+
+ p^:=int16u(
+ (((r * alpha + cr * cover ) shr 1 ) and $7C00 ) or
+ (((g * alpha + cg * cover ) shr 6 ) and $03E0 ) or
+ ((b * alpha + cb * cover ) shr 11 ) or $8000 );
+
+end;
+
+{ copy_or_blend_pix_555_pre }
+procedure copy_or_blend_pix_555_pre(p : int16u_ptr; c : aggclr_ptr; cover : unsigned );
+var
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ p^:=make_pix_555_pre(c.r ,c.g ,c.b )
+ else
+ blend_pix_555_pre(p ,c.r ,c.g ,c.b ,alpha ,cover );
+
+ end;
+
+end;
+
+{ rgb555_pre_copy_pixel }
+procedure rgb555_pre_copy_pixel(this : pixel_formats_ptr; x ,y : int; c : aggclr_ptr );
+begin
+ int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) )^:=make_pix_555_pre(c.r ,c.g ,c.b );
+
+end;
+
+{ rgb555_pre_blend_pixel }
+procedure rgb555_pre_blend_pixel(this : pixel_formats_ptr; x ,y : int; c : aggclr_ptr; cover : int8u );
+begin
+ copy_or_blend_pix_555_pre(int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) ) ,c ,cover );
+
+end;
+
+{ rgb555_pre_pixel }
+function rgb555_pre_pixel(this : pixel_formats_ptr; x ,y : int ) : aggclr;
+begin
+ make_color_555_pre(
+ result ,
+ int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) ) );
+
+end;
+
+{ rgb555_pre_copy_hline }
+procedure rgb555_pre_copy_hline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr );
+var
+ p : int16u_ptr;
+ v : int16u;
+
+begin
+ p:=int16u_ptr (ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+ v:=make_pix_555_pre(c.r ,c.g ,c.b );
+
+ repeat
+ p^:=v;
+
+ inc(ptrcomp(p ) ,sizeof(int16u ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb555_pre_copy_vline }
+procedure rgb555_pre_copy_vline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr );
+var
+ p : int16u_ptr;
+ v : int16u;
+
+begin
+ p:=int16u_ptr (ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+ v:=make_pix_555_pre(c.r ,c.g ,c.b );
+
+ repeat
+ p^:=v;
+ p :=int16u_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb555_pre_blend_hline }
+procedure rgb555_pre_blend_hline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+var
+ p : int16u_ptr;
+ v : int16u;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ v:=make_pix_555_pre(c.r ,c.g ,c.b );
+
+ repeat
+ p^:=v;
+
+ inc(ptrcomp(p ) ,sizeof(int16u ) );
+ dec(len );
+
+ until len = 0;
+
+ end
+ else
+ repeat
+ blend_pix_555_pre(p ,c.r ,c.g ,c.b ,alpha ,cover );
+
+ inc(ptrcomp(p ) ,sizeof(int16u ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ rgb555_pre_blend_vline }
+procedure rgb555_pre_blend_vline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+var
+ p : int16u_ptr;
+ v : int16u;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ v:=make_pix_555_pre(c.r ,c.g ,c.b );
+
+ repeat
+ p^:=v;
+ p :=int16u_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ dec(len );
+
+ until len = 0;
+
+ end
+ else
+ repeat
+ blend_pix_555_pre(p ,c.r ,c.g ,c.b ,alpha ,cover );
+
+ p:=int16u_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ rgb555_pre_blend_solid_hspan }
+procedure rgb555_pre_blend_solid_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+var
+ p : int16u_ptr;
+
+begin
+ p:=int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+
+ repeat
+ copy_or_blend_pix_555_pre(p ,c ,covers^ );
+
+ inc(ptrcomp(covers ) );
+ inc(ptrcomp(p ) ,sizeof(int16u ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb555_pre_blend_solid_vspan }
+procedure rgb555_pre_blend_solid_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+var
+ p : int16u_ptr;
+
+begin
+ p:=int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+
+ repeat
+ copy_or_blend_pix_555_pre(p ,c ,covers^ );
+
+ inc(ptrcomp(covers ) );
+
+ p:=int16u_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb555_pre_blend_color_hspan }
+procedure rgb555_pre_blend_color_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+var
+ p : int16u_ptr;
+
+begin
+ p:=int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+
+ repeat
+ if covers <> NIL then
+ begin
+ copy_or_blend_pix_555_pre(p ,colors ,covers^ );
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+
+ end
+ else
+ copy_or_blend_pix_555_pre(p ,colors ,cover );
+
+ inc(ptrcomp(p ) ,sizeof(int16u ) );
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb555_pre_blend_color_vspan }
+procedure rgb555_pre_blend_color_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+var
+ p : int16u_ptr;
+
+begin
+ p:=int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+
+ repeat
+ if covers <> NIL then
+ begin
+ copy_or_blend_pix_555_pre(p ,colors ,covers^ );
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+
+ end
+ else
+ copy_or_blend_pix_555_pre(p ,colors ,cover );
+
+ p:=int16u_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb555_pre_copy_from }
+procedure rgb555_pre_copy_from(this : pixel_formats_ptr; from : rendering_buffer_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned );
+begin
+ move(
+ int16u_ptr(ptrcomp(from.row(ysrc ) ) + xsrc * sizeof(int16u ) )^ ,
+ int16u_ptr(ptrcomp(this.m_rbuf.row(ydst ) ) + xdst * sizeof(int16 ) )^ ,
+ len * sizeof(int16u ) );
+
+end;
+
+{ rgb555_pre_blend_from }
+procedure rgb555_pre_blend_from(this : pixel_formats_ptr; from : pixel_formats_ptr; psrc_ : int8u_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ psrc : int8u_ptr;
+ pdst : int16u_ptr;
+
+ alpha : unsigned;
+
+begin
+ psrc:=psrc_;
+ pdst:=int16u_ptr(ptrcomp(this.m_rbuf.row(ydst ) ) + xdst * sizeof(int16u ) );
+
+ repeat
+ alpha:=int8u_ptr(ptrcomp(psrc ) + from.m_order.A )^;
+
+ if alpha <> 0 then
+ if (alpha = base_mask ) and
+ (cover = 255 ) then
+ pdst^:=make_pix_555_pre(
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.R )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.G )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.B )^ )
+ else
+ blend_pix_555_pre(
+ pdst ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.R )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.G )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.B )^ ,
+ alpha ,cover );
+
+ inc(ptrcomp(psrc ) ,4 );
+ inc(ptrcomp(pdst ) ,sizeof(int16u ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb555_pre_copy_color_hspan }
+procedure rgb555_pre_copy_color_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr );
+var
+ p : int16u_ptr;
+
+begin
+ p:=int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+
+ repeat
+ p^:=make_pix_555_pre(colors.r ,colors.g ,colors.b );
+
+ inc(ptrcomp(p ) ,sizeof(int16u ) );
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb555_pre_copy_color_vspan }
+procedure rgb555_pre_copy_color_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr );
+var
+ p : int16u_ptr;
+
+begin
+ p:=int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+
+ repeat
+ p^:=make_pix_555_pre(colors.r ,colors.g ,colors.b );
+ p :=int16u_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb555_pre_blend_from_color }
+procedure rgb555_pre_blend_from_color(this : pixel_formats_ptr; from : pixel_formats_ptr; color : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ ppsz : unsigned;
+
+ psrc : int8u_ptr;
+ pdst : int16u_ptr;
+
+begin
+ ppsz:=from._pix_width;
+ psrc:=from.row_ptr(ysrc );
+
+ if psrc <> NIL then
+ begin
+ pdst:=int16u_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + xdst * sizeof(int16u ) );
+
+ repeat
+ blend_pix_555_pre(pdst ,color.r ,color.g ,color.b ,color.a ,shr_int32(psrc^ * cover + base_mask ,base_shift ) );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,sizeof(int16u ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ rgb555_pre_blend_from_lut }
+procedure rgb555_pre_blend_from_lut(this : pixel_formats_ptr; from : pixel_formats_ptr; color_lut : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ ppsz : unsigned;
+
+ psrc : int8u_ptr;
+ pdst : int16u_ptr;
+
+ color : aggclr_ptr;
+
+begin
+ ppsz:=from._pix_width;
+ psrc:=from.row_ptr(ysrc );
+
+ if psrc <> NIL then
+ begin
+ pdst:=int16u_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + xdst * sizeof(int16u ) );
+
+ repeat
+ color:=aggclr_ptr(ptrcomp(color_lut ) + psrc^ * sizeof(aggclr ) );
+
+ blend_pix_555_pre(pdst ,color.r ,color.g ,color.b ,color.a ,shr_int32(psrc^ * cover + base_mask ,base_shift ) );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,sizeof(int16u ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
diff --git a/src/corelib/render/software/pf_rgb565.inc b/src/corelib/render/software/pf_rgb565.inc
new file mode 100644
index 00000000..e31453b9
--- /dev/null
+++ b/src/corelib/render/software/pf_rgb565.inc
@@ -0,0 +1,452 @@
+//
+// AggPas 2.4 RM3 pixel format definition file
+//
+{ make_pix_565 }
+function make_pix_565(r ,g ,b : unsigned ) : int16u;
+begin
+ result:=
+ ((r and $F8 ) shl 8 ) or
+ ((g and $FC ) shl 3 ) or
+ (b shr 3 );
+
+end;
+
+{ make_color_565 }
+procedure make_color_565(var color : aggclr; p : int16u_ptr );
+begin
+ color.ConstrInt(
+ (p^ shr 8 ) and $F8 ,
+ (p^ shr 3 ) and $FC ,
+ (p^ shl 3 ) and $F8 );
+
+end;
+
+{ blend_pix_565 }
+procedure blend_pix_565(p : int16u_ptr; cr ,cg ,cb ,alpha : int );
+var
+ rgb : int16u;
+
+ r ,g ,b : int;
+
+begin
+ rgb:=p^;
+
+ r:=(rgb shr 8 ) and $F8;
+ g:=(rgb shr 3 ) and $FC;
+ b:=(rgb shl 3 ) and $F8;
+
+ p^:=
+ ((((cr - r ) * alpha + (r shl 8 ) ) ) and $F800 ) or
+ ((((cg - g ) * alpha + (g shl 8 ) ) shr 5 ) and $07E0 ) or
+ (((cb - b ) * alpha + (b shl 8 ) ) shr 11 );
+
+end;
+
+{ copy_or_blend_pix_565 }
+procedure copy_or_blend_pix_565(p : int16u_ptr; c : aggclr_ptr; cover : unsigned );
+var
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ p^:=make_pix_565(c.r ,c.g ,c.b )
+ else
+ blend_pix_565(p ,c.r ,c.g ,c.b ,alpha );
+
+ end;
+
+end;
+
+{ rgb565_copy_pixel }
+procedure rgb565_copy_pixel(this : pixel_formats_ptr; x ,y : int; c : aggclr_ptr );
+begin
+ int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) )^:=make_pix_565(c.r ,c.g ,c.b );
+
+end;
+
+{ rgb565_blend_pixel }
+procedure rgb565_blend_pixel(this : pixel_formats_ptr; x ,y : int; c : aggclr_ptr; cover : int8u );
+begin
+ copy_or_blend_pix_565(int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) ) ,c ,cover );
+
+end;
+
+{ rgb565_pixel }
+function rgb565_pixel(this : pixel_formats_ptr; x ,y : int ) : aggclr;
+begin
+ make_color_565(
+ result ,
+ int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) ) );
+
+end;
+
+{ rgb565_copy_hline }
+procedure rgb565_copy_hline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr );
+var
+ p : int16u_ptr;
+ v : int16u;
+
+begin
+ p:=int16u_ptr (ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+ v:=make_pix_565(c.r ,c.g ,c.b );
+
+ repeat
+ p^:=v;
+
+ inc(ptrcomp(p ) ,sizeof(int16u ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb565_copy_vline }
+procedure rgb565_copy_vline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr );
+var
+ p : int16u_ptr;
+ v : int16u;
+
+begin
+ p:=int16u_ptr (ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+ v:=make_pix_565(c.r ,c.g ,c.b );
+
+ repeat
+ p^:=v;
+ p :=int16u_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb565_blend_hline }
+procedure rgb565_blend_hline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+var
+ p : int16u_ptr;
+ v : int16u;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ v:=make_pix_565(c.r ,c.g ,c.b );
+
+ repeat
+ p^:=v;
+
+ inc(ptrcomp(p ) ,sizeof(int16u ) );
+ dec(len );
+
+ until len = 0;
+
+ end
+ else
+ repeat
+ blend_pix_565(p ,c.r ,c.g ,c.b ,alpha );
+
+ inc(ptrcomp(p ) ,sizeof(int16u ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ rgb565_blend_vline }
+procedure rgb565_blend_vline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+var
+ p : int16u_ptr;
+ v : int16u;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ v:=make_pix_565(c.r ,c.g ,c.b );
+
+ repeat
+ p^:=v;
+ p :=int16u_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ dec(len );
+
+ until len = 0;
+
+ end
+ else
+ repeat
+ blend_pix_565(p ,c.r ,c.g ,c.b ,alpha );
+
+ p:=int16u_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ rgb565_blend_solid_hspan }
+procedure rgb565_blend_solid_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+var
+ p : int16u_ptr;
+
+begin
+ p:=int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+
+ repeat
+ copy_or_blend_pix_565(p ,c ,covers^ );
+
+ inc(ptrcomp(covers ) );
+ inc(ptrcomp(p ) ,sizeof(int16u ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb565_blend_solid_vspan }
+procedure rgb565_blend_solid_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+var
+ p : int16u_ptr;
+
+begin
+ p:=int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+
+ repeat
+ copy_or_blend_pix_565(p ,c ,covers^ );
+
+ inc(ptrcomp(covers ) );
+
+ p:=int16u_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb565_blend_color_hspan }
+procedure rgb565_blend_color_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+var
+ p : int16u_ptr;
+
+begin
+ p:=int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+
+ repeat
+ if covers <> NIL then
+ begin
+ copy_or_blend_pix_565(p ,colors ,covers^ );
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+
+ end
+ else
+ copy_or_blend_pix_565(p ,colors ,cover );
+
+ inc(ptrcomp(p ) ,sizeof(int16u ) );
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb565_blend_color_vspan }
+procedure rgb565_blend_color_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+var
+ p : int16u_ptr;
+
+begin
+ p:=int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+
+ repeat
+ if covers <> NIL then
+ begin
+ copy_or_blend_pix_565(p ,colors ,covers^ );
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+
+ end
+ else
+ copy_or_blend_pix_565(p ,colors ,cover );
+
+ p:=int16u_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb565_copy_from }
+procedure rgb565_copy_from(this : pixel_formats_ptr; from : rendering_buffer_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned );
+begin
+ move(
+ int16u_ptr(ptrcomp(from.row(ysrc ) ) + xsrc * sizeof(int16u ) )^ ,
+ int16u_ptr(ptrcomp(this.m_rbuf.row(ydst ) ) + xdst * sizeof(int16 ) )^ ,
+ len * sizeof(int16u ) );
+
+end;
+
+{ rgb565_blend_from }
+procedure rgb565_blend_from(this : pixel_formats_ptr; from : pixel_formats_ptr; psrc_ : int8u_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ psrc : int8u_ptr;
+ pdst : int16u_ptr;
+
+ alpha : unsigned;
+
+begin
+ psrc:=psrc_;
+ pdst:=int16u_ptr(ptrcomp(this.m_rbuf.row(ydst ) ) + xdst * sizeof(int16u ) );
+
+ repeat
+ alpha:=int8u_ptr(ptrcomp(psrc ) + from.m_order.A )^;
+
+ if alpha <> 0 then
+ if (alpha = base_mask ) and
+ (cover = 255 ) then
+ pdst^:=make_pix_565(
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.R )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.G )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.B )^ )
+ else
+ blend_pix_565(
+ pdst ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.R )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.G )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.B )^ ,
+ alpha );
+
+ inc(ptrcomp(psrc ) ,4 );
+ inc(ptrcomp(pdst ) ,sizeof(int16u ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb565_copy_color_hspan }
+procedure rgb565_copy_color_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr );
+var
+ p : int16u_ptr;
+
+begin
+ p:=int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+
+ repeat
+ p^:=make_pix_565(colors.r ,colors.g ,colors.b );
+
+ inc(ptrcomp(p ) ,sizeof(int16u ) );
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb565_copy_color_vspan }
+procedure rgb565_copy_color_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr );
+var
+ p : int16u_ptr;
+
+begin
+ p:=int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+
+ repeat
+ p^:=make_pix_565(colors.r ,colors.g ,colors.b );
+ p :=int16u_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb565_blend_from_color }
+procedure rgb565_blend_from_color(this : pixel_formats_ptr; from : pixel_formats_ptr; color : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ ppsz : unsigned;
+
+ psrc : int8u_ptr;
+ pdst : int16u_ptr;
+
+begin
+ ppsz:=from._pix_width;
+ psrc:=from.row_ptr(ysrc );
+
+ if psrc <> NIL then
+ begin
+ pdst:=int16u_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + xdst * sizeof(int16u ) );
+
+ repeat
+ blend_pix_565(pdst ,color.r ,color.g ,color.b ,shr_int32(psrc^ * cover + base_mask ,base_shift ) );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,sizeof(int16u ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ rgb565_blend_from_lut }
+procedure rgb565_blend_from_lut(this : pixel_formats_ptr; from : pixel_formats_ptr; color_lut : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ ppsz : unsigned;
+
+ psrc : int8u_ptr;
+ pdst : int16u_ptr;
+
+ color : aggclr_ptr;
+
+begin
+ ppsz:=from._pix_width;
+ psrc:=from.row_ptr(ysrc );
+
+ if psrc <> NIL then
+ begin
+ pdst:=int16u_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + xdst * sizeof(int16u ) );
+
+ repeat
+ color:=aggclr_ptr(ptrcomp(color_lut ) + psrc^ * sizeof(aggclr ) );
+
+ blend_pix_565(pdst ,color.r ,color.g ,color.b ,shr_int32(psrc^ * cover + base_mask ,base_shift ) );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,sizeof(int16u ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
diff --git a/src/corelib/render/software/pf_rgb565_gamma.inc b/src/corelib/render/software/pf_rgb565_gamma.inc
new file mode 100644
index 00000000..d2d9ec94
--- /dev/null
+++ b/src/corelib/render/software/pf_rgb565_gamma.inc
@@ -0,0 +1,456 @@
+//
+// AggPas 2.4 RM3 pixel format definition file
+//
+{ make_pix_565_gamma }
+function make_pix_565_gamma(r ,g ,b : unsigned ) : int16u;
+begin
+ result:=int16u(
+ ((r and $F8 ) shl 8 ) or
+ ((g and $FC ) shl 3 ) or
+ (b shr 3 ) );
+
+end;
+
+{ make_color_565_gamma }
+procedure make_color_565_gamma(var color : aggclr; p : int16u_ptr );
+begin
+ color.ConstrInt(
+ (p^ shr 8 ) and $F8 ,
+ (p^ shr 3 ) and $FC ,
+ (p^ shl 3 ) and $F8 );
+
+end;
+
+{ blend_pix_565_gamma }
+procedure blend_pix_565_gamma(gamma : gamma_ptr; p : int16u_ptr; cr ,cg ,cb ,alpha ,cover : unsigned );
+var
+ rgb : int16u;
+
+ r ,g ,b : int;
+
+begin
+ rgb:=p^;
+
+ r:=gamma.dir((rgb shr 8 ) and $F8 );
+ g:=gamma.dir((rgb shr 3 ) and $FC );
+ b:=gamma.dir((rgb shl 3 ) and $F8 );
+
+ p^:=int16u(
+ ((gamma.inv(((gamma.dir(cr ) - r ) * alpha + (r shl 8 ) ) shr 8 ) shl 8 ) and $F800 ) or
+ ((gamma.inv(((gamma.dir(cg ) - g ) * alpha + (g shl 8 ) ) shr 8 ) shl 3 ) and $07E0 ) or
+ (gamma.inv(((gamma.dir(cb ) - b ) * alpha + (b shl 8 ) ) shr 8 ) shr 3 ) );
+
+end;
+
+{ copy_or_blend_pix_565_gamma }
+procedure copy_or_blend_pix_565_gamma(gamma : gamma_ptr; p : int16u_ptr; c : aggclr_ptr; cover : unsigned );
+var
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ p^:=make_pix_565_gamma(c.r ,c.g ,c.b )
+ else
+ blend_pix_565_gamma(gamma ,p ,c.r ,c.g ,c.b ,alpha ,cover );
+
+ end;
+
+end;
+
+{ rgb565_gamma_copy_pixel }
+procedure rgb565_gamma_copy_pixel(this : pixel_formats_ptr; x ,y : int; c : aggclr_ptr );
+begin
+ int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) )^:=make_pix_565_gamma(c.r ,c.g ,c.b );
+
+end;
+
+{ rgb565_gamma_blend_pixel }
+procedure rgb565_gamma_blend_pixel(this : pixel_formats_ptr; x ,y : int; c : aggclr_ptr; cover : int8u );
+begin
+ copy_or_blend_pix_565_gamma(this.m_gamma ,int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) ) ,c ,cover );
+
+end;
+
+{ rgb565_gamma_pixel }
+function rgb565_gamma_pixel(this : pixel_formats_ptr; x ,y : int ) : aggclr;
+begin
+ make_color_565_gamma(
+ result ,
+ int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) ) );
+
+end;
+
+{ rgb565_gamma_copy_hline }
+procedure rgb565_gamma_copy_hline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr );
+var
+ p : int16u_ptr;
+ v : int16u;
+
+begin
+ p:=int16u_ptr (ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+ v:=make_pix_565_gamma(c.r ,c.g ,c.b );
+
+ repeat
+ p^:=v;
+
+ inc(ptrcomp(p ) ,sizeof(int16u ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb565_gamma_copy_vline }
+procedure rgb565_gamma_copy_vline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr );
+var
+ p : int16u_ptr;
+ v : int16u;
+
+begin
+ p:=int16u_ptr (ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+ v:=make_pix_565_gamma(c.r ,c.g ,c.b );
+
+ repeat
+ p^:=v;
+ p :=int16u_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb565_gamma_blend_hline }
+procedure rgb565_gamma_blend_hline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+var
+ p : int16u_ptr;
+ v : int16u;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ v:=make_pix_565_gamma(c.r ,c.g ,c.b );
+
+ repeat
+ p^:=v;
+
+ inc(ptrcomp(p ) ,sizeof(int16u ) );
+ dec(len );
+
+ until len = 0;
+
+ end
+ else
+ repeat
+ blend_pix_565_gamma(this.m_gamma ,p ,c.r ,c.g ,c.b ,alpha ,cover );
+
+ inc(ptrcomp(p ) ,sizeof(int16u ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ rgb565_gamma_blend_vline }
+procedure rgb565_gamma_blend_vline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+var
+ p : int16u_ptr;
+ v : int16u;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ v:=make_pix_565_gamma(c.r ,c.g ,c.b );
+
+ repeat
+ p^:=v;
+ p :=int16u_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ dec(len );
+
+ until len = 0;
+
+ end
+ else
+ repeat
+ blend_pix_565_gamma(this.m_gamma ,p ,c.r ,c.g ,c.b ,alpha ,cover );
+
+ p:=int16u_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ rgb565_gamma_blend_solid_hspan }
+procedure rgb565_gamma_blend_solid_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+var
+ p : int16u_ptr;
+
+begin
+ p:=int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+
+ repeat
+ copy_or_blend_pix_565_gamma(this.m_gamma ,p ,c ,covers^ );
+
+ inc(ptrcomp(covers ) );
+ inc(ptrcomp(p ) ,sizeof(int16u ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb565_gamma_blend_solid_vspan }
+procedure rgb565_gamma_blend_solid_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+var
+ p : int16u_ptr;
+
+begin
+ p:=int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+
+ repeat
+ copy_or_blend_pix_565_gamma(this.m_gamma ,p ,c ,covers^ );
+
+ inc(ptrcomp(covers ) );
+
+ p:=int16u_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb565_gamma_blend_color_hspan }
+procedure rgb565_gamma_blend_color_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+var
+ p : int16u_ptr;
+
+begin
+ p:=int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+
+ repeat
+ if covers <> NIL then
+ begin
+ copy_or_blend_pix_565_gamma(this.m_gamma ,p ,colors ,covers^ );
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+
+ end
+ else
+ copy_or_blend_pix_565_gamma(this.m_gamma ,p ,colors ,cover );
+
+ inc(ptrcomp(p ) ,sizeof(int16u ) );
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb565_gamma_blend_color_vspan }
+procedure rgb565_gamma_blend_color_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+var
+ p : int16u_ptr;
+
+begin
+ p:=int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+
+ repeat
+ if covers <> NIL then
+ begin
+ copy_or_blend_pix_565_gamma(this.m_gamma ,p ,colors ,covers^ );
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+
+ end
+ else
+ copy_or_blend_pix_565_gamma(this.m_gamma ,p ,colors ,cover );
+
+ p:=int16u_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb565_gamma_copy_from }
+procedure rgb565_gamma_copy_from(this : pixel_formats_ptr; from : rendering_buffer_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned );
+begin
+ move(
+ int16u_ptr(ptrcomp(from.row(ysrc ) ) + xsrc * sizeof(int16u ) )^ ,
+ int16u_ptr(ptrcomp(this.m_rbuf.row(ydst ) ) + xdst * sizeof(int16 ) )^ ,
+ len * sizeof(int16u ) );
+
+end;
+
+{ rgb565_gamma_blend_from }
+procedure rgb565_gamma_blend_from(this : pixel_formats_ptr; from : pixel_formats_ptr; psrc_ : int8u_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ psrc : int8u_ptr;
+ pdst : int16u_ptr;
+
+ alpha : unsigned;
+
+begin
+ psrc:=psrc_;
+ pdst:=int16u_ptr(ptrcomp(this.m_rbuf.row(ydst ) ) + xdst * sizeof(int16u ) );
+
+ repeat
+ alpha:=int8u_ptr(ptrcomp(psrc ) + from.m_order.A )^;
+
+ if alpha <> 0 then
+ if (alpha = base_mask ) and
+ (cover = 255 ) then
+ pdst^:=make_pix_565_gamma(
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.R )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.G )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.B )^ )
+ else
+ blend_pix_565_gamma(
+ this.m_gamma ,pdst ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.R )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.G )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.B )^ ,
+ alpha ,cover );
+
+ inc(ptrcomp(psrc ) ,4 );
+ inc(ptrcomp(pdst ) ,sizeof(int16u ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb565_gamma_copy_color_hspan }
+procedure rgb565_gamma_copy_color_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr );
+var
+ p : int16u_ptr;
+
+begin
+ p:=int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+
+ repeat
+ p^:=make_pix_565_gamma(colors.r ,colors.g ,colors.b );
+
+ inc(ptrcomp(p ) ,sizeof(int16u ) );
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb565_pre_copy_color_vspan }
+procedure rgb565_gamma_copy_color_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr );
+var
+ p : int16u_ptr;
+
+begin
+ p:=int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+
+ repeat
+ p^:=make_pix_565_gamma(colors.r ,colors.g ,colors.b );
+ p :=int16u_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb565_gamma_blend_from_color }
+procedure rgb565_gamma_blend_from_color(this : pixel_formats_ptr; from : pixel_formats_ptr; color : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ ppsz : unsigned;
+
+ psrc : int8u_ptr;
+ pdst : int16u_ptr;
+
+begin
+ ppsz:=from._pix_width;
+ psrc:=from.row_ptr(ysrc );
+
+ if psrc <> NIL then
+ begin
+ pdst:=int16u_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + xdst * sizeof(int16u ) );
+
+ repeat
+ blend_pix_565_gamma(
+ this.m_gamma ,
+ pdst ,color.r ,color.g ,color.b ,color.a ,shr_int32(psrc^ * cover + base_mask ,base_shift ) );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,sizeof(int16u ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ rgb565_gamma_blend_from_lut }
+procedure rgb565_gamma_blend_from_lut(this : pixel_formats_ptr; from : pixel_formats_ptr; color_lut : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ ppsz : unsigned;
+
+ psrc : int8u_ptr;
+ pdst : int16u_ptr;
+
+ color : aggclr_ptr;
+
+begin
+ ppsz:=from._pix_width;
+ psrc:=from.row_ptr(ysrc );
+
+ if psrc <> NIL then
+ begin
+ pdst:=int16u_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + xdst * sizeof(int16u ) );
+
+ repeat
+ color:=aggclr_ptr(ptrcomp(color_lut ) + psrc^ * sizeof(aggclr ) );
+
+ blend_pix_565_gamma(
+ this.m_gamma ,
+ pdst ,color.r ,color.g ,color.b ,color.a ,shr_int32(psrc^ * cover + base_mask ,base_shift ) );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,sizeof(int16u ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
diff --git a/src/corelib/render/software/pf_rgb565_pre.inc b/src/corelib/render/software/pf_rgb565_pre.inc
new file mode 100644
index 00000000..252023a2
--- /dev/null
+++ b/src/corelib/render/software/pf_rgb565_pre.inc
@@ -0,0 +1,453 @@
+//
+// AggPas 2.4 RM3 pixel format definition file
+//
+{ make_pix_565_pre }
+function make_pix_565_pre(r ,g ,b : unsigned ) : int16u;
+begin
+ result:=int16u(
+ ((r and $F8 ) shl 8 ) or
+ ((g and $FC ) shl 3 ) or
+ (b shr 3 ) );
+
+end;
+
+{ make_color_565_pre }
+procedure make_color_565_pre(var color : aggclr; p : int16u_ptr );
+begin
+ color.ConstrInt(
+ (p^ shr 8 ) and $F8 ,
+ (p^ shr 3 ) and $FC ,
+ (p^ shl 3 ) and $F8 );
+
+end;
+
+{ blend_pix_565_pre }
+procedure blend_pix_565_pre(p : int16u_ptr; cr ,cg ,cb ,alpha ,cover : unsigned );
+var
+ rgb : int16u;
+
+ r ,g ,b : int;
+
+begin
+ alpha:=base_mask - alpha;
+ rgb :=p^;
+
+ r:=(rgb shr 8 ) and $F8;
+ g:=(rgb shr 3 ) and $FC;
+ b:=(rgb shl 3 ) and $F8;
+
+ p^:=int16u(
+ (((r * alpha + cr * cover ) ) and $F800) or
+ (((g * alpha + cg * cover ) shr 5 ) and $07E0) or
+ ((b * alpha + cb * cover ) shr 11 ) );
+
+end;
+
+{ copy_or_blend_pix_565_pre }
+procedure copy_or_blend_pix_565_pre(p : int16u_ptr; c : aggclr_ptr; cover : unsigned );
+var
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ p^:=make_pix_565_pre(c.r ,c.g ,c.b )
+ else
+ blend_pix_565_pre(p ,c.r ,c.g ,c.b ,alpha ,cover );
+
+ end;
+
+end;
+
+{ rgb565_pre_copy_pixel }
+procedure rgb565_pre_copy_pixel(this : pixel_formats_ptr; x ,y : int; c : aggclr_ptr );
+begin
+ int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) )^:=make_pix_565_pre(c.r ,c.g ,c.b );
+
+end;
+
+{ rgb565_pre_blend_pixel }
+procedure rgb565_pre_blend_pixel(this : pixel_formats_ptr; x ,y : int; c : aggclr_ptr; cover : int8u );
+begin
+ copy_or_blend_pix_565_pre(int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) ) ,c ,cover );
+
+end;
+
+{ rgb565_pre_pixel }
+function rgb565_pre_pixel(this : pixel_formats_ptr; x ,y : int ) : aggclr;
+begin
+ make_color_565_pre(
+ result ,
+ int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) ) );
+
+end;
+
+{ rgb565_pre_copy_hline }
+procedure rgb565_pre_copy_hline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr );
+var
+ p : int16u_ptr;
+ v : int16u;
+
+begin
+ p:=int16u_ptr (ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+ v:=make_pix_565_pre(c.r ,c.g ,c.b );
+
+ repeat
+ p^:=v;
+
+ inc(ptrcomp(p ) ,sizeof(int16u ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb565_pre_copy_vline }
+procedure rgb565_pre_copy_vline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr );
+var
+ p : int16u_ptr;
+ v : int16u;
+
+begin
+ p:=int16u_ptr (ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+ v:=make_pix_565_pre(c.r ,c.g ,c.b );
+
+ repeat
+ p^:=v;
+ p :=int16u_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb565_pre_blend_hline }
+procedure rgb565_pre_blend_hline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+var
+ p : int16u_ptr;
+ v : int16u;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ v:=make_pix_565_pre(c.r ,c.g ,c.b );
+
+ repeat
+ p^:=v;
+
+ inc(ptrcomp(p ) ,sizeof(int16u ) );
+ dec(len );
+
+ until len = 0;
+
+ end
+ else
+ repeat
+ blend_pix_565_pre(p ,c.r ,c.g ,c.b ,alpha ,cover );
+
+ inc(ptrcomp(p ) ,sizeof(int16u ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ rgb565_pre_blend_vline }
+procedure rgb565_pre_blend_vline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+var
+ p : int16u_ptr;
+ v : int16u;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ v:=make_pix_565_pre(c.r ,c.g ,c.b );
+
+ repeat
+ p^:=v;
+ p :=int16u_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ dec(len );
+
+ until len = 0;
+
+ end
+ else
+ repeat
+ blend_pix_565_pre(p ,c.r ,c.g ,c.b ,alpha ,cover );
+
+ p:=int16u_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ rgb565_pre_blend_solid_hspan }
+procedure rgb565_pre_blend_solid_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+var
+ p : int16u_ptr;
+
+begin
+ p:=int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+
+ repeat
+ copy_or_blend_pix_565_pre(p ,c ,covers^ );
+
+ inc(ptrcomp(covers ) );
+ inc(ptrcomp(p ) ,sizeof(int16u ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb565_pre_blend_solid_vspan }
+procedure rgb565_pre_blend_solid_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+var
+ p : int16u_ptr;
+
+begin
+ p:=int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+
+ repeat
+ copy_or_blend_pix_565_pre(p ,c ,covers^ );
+
+ inc(ptrcomp(covers ) );
+
+ p:=int16u_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb565_pre_blend_color_hspan }
+procedure rgb565_pre_blend_color_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+var
+ p : int16u_ptr;
+
+begin
+ p:=int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+
+ repeat
+ if covers <> NIL then
+ begin
+ copy_or_blend_pix_565_pre(p ,colors ,covers^ );
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+
+ end
+ else
+ copy_or_blend_pix_565_pre(p ,colors ,cover );
+
+ inc(ptrcomp(p ) ,sizeof(int16u ) );
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb565_pre_blend_color_vspan }
+procedure rgb565_pre_blend_color_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+var
+ p : int16u_ptr;
+
+begin
+ p:=int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+
+ repeat
+ if covers <> NIL then
+ begin
+ copy_or_blend_pix_565_pre(p ,colors ,covers^ );
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+
+ end
+ else
+ copy_or_blend_pix_565_pre(p ,colors ,cover );
+
+ p:=int16u_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb565_pre_copy_from }
+procedure rgb565_pre_copy_from(this : pixel_formats_ptr; from : rendering_buffer_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned );
+begin
+ move(
+ int16u_ptr(ptrcomp(from.row(ysrc ) ) + xsrc * sizeof(int16u ) )^ ,
+ int16u_ptr(ptrcomp(this.m_rbuf.row(ydst ) ) + xdst * sizeof(int16 ) )^ ,
+ len * sizeof(int16u ) );
+
+end;
+
+{ rgb565_pre_blend_from }
+procedure rgb565_pre_blend_from(this : pixel_formats_ptr; from : pixel_formats_ptr; psrc_ : int8u_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ psrc : int8u_ptr;
+ pdst : int16u_ptr;
+
+ alpha : unsigned;
+
+begin
+ psrc:=psrc_;
+ pdst:=int16u_ptr(ptrcomp(this.m_rbuf.row(ydst ) ) + xdst * sizeof(int16u ) );
+
+ repeat
+ alpha:=int8u_ptr(ptrcomp(psrc ) + from.m_order.A )^;
+
+ if alpha <> 0 then
+ if (alpha = base_mask ) and
+ (cover = 255 ) then
+ pdst^:=make_pix_565_pre(
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.R )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.G )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.B )^ )
+ else
+ blend_pix_565_pre(
+ pdst ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.R )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.G )^ ,
+ int8u_ptr(ptrcomp(psrc ) + from.m_order.B )^ ,
+ alpha ,cover );
+
+ inc(ptrcomp(psrc ) ,4 );
+ inc(ptrcomp(pdst ) ,sizeof(int16u ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb565_pre_copy_color_hspan }
+procedure rgb565_pre_copy_color_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr );
+var
+ p : int16u_ptr;
+
+begin
+ p:=int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+
+ repeat
+ p^:=make_pix_565_pre(colors.r ,colors.g ,colors.b );
+
+ inc(ptrcomp(p ) ,sizeof(int16u ) );
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb565_pre_copy_color_vspan }
+procedure rgb565_pre_copy_color_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr );
+var
+ p : int16u_ptr;
+
+begin
+ p:=int16u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + x * sizeof(int16u ) );
+
+ repeat
+ p^:=make_pix_565_pre(colors.r ,colors.g ,colors.b );
+ p :=int16u_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgb565_pre_blend_from_color }
+procedure rgb565_pre_blend_from_color(this : pixel_formats_ptr; from : pixel_formats_ptr; color : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ ppsz : unsigned;
+
+ psrc : int8u_ptr;
+ pdst : int16u_ptr;
+
+begin
+ ppsz:=from._pix_width;
+ psrc:=from.row_ptr(ysrc );
+
+ if psrc <> NIL then
+ begin
+ pdst:=int16u_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + xdst * sizeof(int16u ) );
+
+ repeat
+ blend_pix_565_pre(pdst ,color.r ,color.g ,color.b ,color.a ,shr_int32(psrc^ * cover + base_mask ,base_shift ) );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,sizeof(int16u ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ rgb565_pre_blend_from_lut }
+procedure rgb565_pre_blend_from_lut(this : pixel_formats_ptr; from : pixel_formats_ptr; color_lut : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ ppsz : unsigned;
+
+ psrc : int8u_ptr;
+ pdst : int16u_ptr;
+
+ color : aggclr_ptr;
+
+begin
+ ppsz:=from._pix_width;
+ psrc:=from.row_ptr(ysrc );
+
+ if psrc <> NIL then
+ begin
+ pdst:=int16u_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + xdst * sizeof(int16u ) );
+
+ repeat
+ color:=aggclr_ptr(ptrcomp(color_lut ) + psrc^ * sizeof(aggclr ) );
+
+ blend_pix_565_pre(pdst ,color.r ,color.g ,color.b ,color.a ,shr_int32(psrc^ * cover + base_mask ,base_shift ) );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,sizeof(int16u ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
diff --git a/src/corelib/render/software/pf_rgba32.inc b/src/corelib/render/software/pf_rgba32.inc
new file mode 100644
index 00000000..42495f23
--- /dev/null
+++ b/src/corelib/render/software/pf_rgba32.inc
@@ -0,0 +1,608 @@
+//
+// AggPas 2.4 RM3 pixel format definition file
+//
+{ blend_pix_rgba }
+procedure blend_pix_rgba(p : unsigned_ptr; cr ,cg ,cb ,alpha : int; cover : unsigned = 0 );
+var
+ r ,g ,b ,a : int8u;
+
+begin
+ r:=order_rgba(p^ ).R;
+ g:=order_rgba(p^ ).G;
+ b:=order_rgba(p^ ).B;
+ a:=order_rgba(p^ ).A;
+
+ order_rgba(p^ ).R:=((cr - r ) * alpha + (r shl base_shift ) ) shr base_shift;
+ order_rgba(p^ ).G:=((cg - g ) * alpha + (g shl base_shift ) ) shr base_shift;
+ order_rgba(p^ ).B:=((cb - b ) * alpha + (b shl base_shift ) ) shr base_shift;
+ order_rgba(p^ ).A:=(alpha + a ) - ((alpha * a + base_mask ) shr base_shift );
+
+end;
+
+{ copy_or_blend_pix_rgba }
+procedure copy_or_blend_pix_rgba(p : unsigned_ptr; cr ,cg ,cb ,alpha : unsigned ); overload;
+begin
+ if alpha <> 0 then
+ if alpha = base_mask then
+ begin
+ order_rgba(p^ ).R:=cr;
+ order_rgba(p^ ).G:=cg;
+ order_rgba(p^ ).B:=cb;
+ order_rgba(p^ ).A:=base_mask;
+
+ end
+ else
+ blend_pix_rgba(p ,cr ,cg ,cb ,alpha );
+
+end;
+
+{ copy_or_blend_pix_rgba }
+procedure copy_or_blend_pix_rgba(p : unsigned_ptr; cr ,cg ,cb ,alpha ,cover : unsigned ); overload;
+begin
+ if cover = 255 then
+ copy_or_blend_pix_rgba(p ,cr ,cg ,cb ,alpha )
+ else
+ if alpha <> 0 then
+ begin
+ alpha:=(alpha * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_rgba(p^ ).R:=cr;
+ order_rgba(p^ ).G:=cg;
+ order_rgba(p^ ).B:=cb;
+ order_rgba(p^ ).A:=base_mask;
+
+ end
+ else
+ blend_pix_rgba(p ,cr ,cg ,cb ,alpha ,cover );
+
+ end;
+
+end;
+
+{ rgba32_copy_pixel }
+procedure rgba32_copy_pixel(this : pixel_formats_ptr; x ,y : int; c : aggclr_ptr );
+var
+ p : unsigned_ptr;
+
+begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ order_rgba(p^ ).R:=c.r;
+ order_rgba(p^ ).G:=c.g;
+ order_rgba(p^ ).B:=c.b;
+ order_rgba(p^ ).A:=c.a;
+
+end;
+
+{ rgba32_blend_pixel }
+procedure rgba32_blend_pixel(this : pixel_formats_ptr; x ,y : int; c : aggclr_ptr; cover : int8u );
+begin
+ copy_or_blend_pix_rgba(
+ unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) ) ,
+ c.r ,c.g ,c.b ,c.a ,cover );
+
+end;
+
+{ rgba32_pixel }
+function rgba32_pixel(this : pixel_formats_ptr; x ,y : int ) : aggclr;
+var
+ p : unsigned_ptr;
+
+begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ result.ConstrInt(
+ order_rgba(p^ ).R ,
+ order_rgba(p^ ).G ,
+ order_rgba(p^ ).B ,
+ order_rgba(p^ ).A );
+
+end;
+
+{ rgba32_copy_hline }
+procedure rgba32_copy_hline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr );
+var
+ p : int8u_ptr;
+ v : unsigned;
+
+begin
+ p:=int8u_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ order_rgba(v ).R:=c.r;
+ order_rgba(v ).G:=c.g;
+ order_rgba(v ).B:=c.b;
+ order_rgba(v ).A:=c.a;
+
+ if len > 0 then
+ repeat
+ unsigned(pointer(p )^ ):=v;
+
+ inc(ptrcomp(p ) ,4 );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgba32_copy_vline }
+procedure rgba32_copy_vline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr );
+var
+ p : unsigned_ptr;
+ v : unsigned;
+
+begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ order_rgba(v ).R:=c.r;
+ order_rgba(v ).G:=c.g;
+ order_rgba(v ).B:=c.b;
+ order_rgba(v ).A:=c.a;
+
+ if len > 0 then
+ repeat
+ p^:=v;
+ p :=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgba32_blend_hline }
+procedure rgba32_blend_hline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+var
+ p : unsigned_ptr;
+ v : unsigned;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_rgba(v ).R:=c.r;
+ order_rgba(v ).G:=c.g;
+ order_rgba(v ).B:=c.b;
+ order_rgba(v ).A:=c.a;
+
+ repeat
+ p^:=v;
+
+ inc(ptrcomp(p ) ,sizeof(unsigned ) );
+ dec(len );
+
+ until len = 0;
+
+ end
+ else
+ if cover = 255 then
+ repeat
+ blend_pix_rgba(p ,c.r ,c.g ,c.b ,alpha );
+
+ inc(ptrcomp(p ) ,sizeof(unsigned ) );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ blend_pix_rgba(p ,c.r ,c.g ,c.b ,alpha ,cover );
+
+ inc(ptrcomp(p ) ,sizeof(unsigned ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ rgba32_blend_vline }
+procedure rgba32_blend_vline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+var
+ p : unsigned_ptr;
+ v : unsigned;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_rgba(v ).R:=c.r;
+ order_rgba(v ).G:=c.g;
+ order_rgba(v ).B:=c.b;
+ order_rgba(v ).A:=c.a;
+
+ repeat
+ p^:=v;
+ p :=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ until len = 0;
+
+ end
+ else
+ if cover = 255 then
+ repeat
+ blend_pix_rgba(p ,c.r ,c.g ,c.b ,alpha );
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ blend_pix_rgba(p ,c.r ,c.g ,c.b ,alpha ,cover );
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ rgba32_blend_solid_hspan }
+procedure rgba32_blend_solid_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+var
+ p : unsigned_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ repeat
+ alpha:=(c.a * (covers^ + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_rgba(p^ ).R:=c.r;
+ order_rgba(p^ ).G:=c.g;
+ order_rgba(p^ ).B:=c.b;
+ order_rgba(p^ ).A:=base_mask;
+
+ end
+ else
+ blend_pix_rgba(p ,c.r ,c.g ,c.b ,alpha ,covers^ );
+
+ inc(ptrcomp(p ) ,4 );
+ inc(ptrcomp(covers ) );
+
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ rgba32_blend_solid_vspan }
+procedure rgba32_blend_solid_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+var
+ p : unsigned_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ repeat
+ alpha:=(c.a * (covers^ + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_rgba(p^ ).R:=c.r;
+ order_rgba(p^ ).G:=c.g;
+ order_rgba(p^ ).B:=c.b;
+ order_rgba(p^ ).A:=base_mask;
+
+ end
+ else
+ blend_pix_rgba(p ,c.r ,c.g ,c.b ,alpha ,covers^ );
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ rgba32_blend_color_hspan }
+procedure rgba32_blend_color_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+var
+ p : unsigned_ptr;
+
+begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ if covers <> NIL then
+ repeat
+ copy_or_blend_pix_rgba(p ,colors.r ,colors.g ,colors.b ,colors.a ,covers^ );
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+ inc(ptrcomp(p ) ,4 );
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0
+ else
+ if cover = 255 then
+ repeat
+ copy_or_blend_pix_rgba(p ,colors.r ,colors.g ,colors.b ,colors.a );
+
+ inc(ptrcomp(p ) ,4 );
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ copy_or_blend_pix_rgba(p ,colors.r ,colors.g ,colors.b ,colors.a ,cover );
+
+ inc(ptrcomp(p ) ,4 );
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgba32_blend_color_vspan }
+procedure rgba32_blend_color_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+var
+ p : unsigned_ptr;
+
+begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ if covers <> NIL then
+ repeat
+ copy_or_blend_pix_rgba(
+ p ,
+ colors.r ,
+ colors.g ,
+ colors.b ,
+ colors.a ,
+ covers^ );
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0
+ else
+ if cover = 255 then
+ repeat
+ copy_or_blend_pix_rgba(
+ p ,
+ colors.r ,
+ colors.g ,
+ colors.b ,
+ colors.a );
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ copy_or_blend_pix_rgba(
+ p ,
+ colors.r ,
+ colors.g ,
+ colors.b ,
+ colors.a ,
+ cover );
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgba32_blend_from }
+procedure rgba32_blend_from(this : pixel_formats_ptr; from : pixel_formats_ptr; psrc_ : int8u_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ psrc ,pdst : unsigned_ptr;
+
+ incp : int;
+
+begin
+ psrc:=unsigned_ptr(psrc_ );
+ pdst:=unsigned_ptr(ptrcomp(this.m_rbuf.row(ydst ) ) + (xdst shl 2 ) * sizeof(int8u ) );
+ incp:=4;
+
+ if ptrcomp(xdst ) > ptrcomp(xsrc ) then
+ begin
+ inc(ptrcomp(psrc ) ,((len - 1 ) shl 2 ) * sizeof(int8u ) );
+ inc(ptrcomp(pdst ) ,((len - 1 ) shl 2 ) * sizeof(int8u ) );
+
+ incp:=-4;
+
+ end;
+
+ if cover = 255 then
+ repeat
+ copy_or_blend_pix_rgba(
+ pdst ,
+ order_rgba(psrc^ ).R ,
+ order_rgba(psrc^ ).G ,
+ order_rgba(psrc^ ).B ,
+ order_rgba(psrc^ ).A );
+
+ inc(ptrcomp(psrc ) ,incp );
+ inc(ptrcomp(pdst ) ,incp );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ copy_or_blend_pix_rgba(
+ pdst ,
+ order_rgba(psrc^ ).R ,
+ order_rgba(psrc^ ).G ,
+ order_rgba(psrc^ ).B ,
+ order_rgba(psrc^ ).A ,
+ cover );
+
+ inc(ptrcomp(psrc ) ,incp );
+ inc(ptrcomp(pdst ) ,incp );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgba32_copy_color_hspan }
+procedure rgba32_copy_color_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr );
+var
+ p : unsigned_ptr;
+
+begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ repeat
+ order_rgba(pointer(p )^ ).R:=colors.r;
+ order_rgba(pointer(p )^ ).G:=colors.g;
+ order_rgba(pointer(p )^ ).B:=colors.b;
+ order_rgba(pointer(p )^ ).A:=colors.a;
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ inc(ptrcomp(p ) ,4 );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgba32_copy_color_vspan }
+procedure rgba32_copy_color_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr );
+var
+ p : unsigned_ptr;
+
+begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ repeat
+ order_rgba(pointer(p )^ ).R:=colors.r;
+ order_rgba(pointer(p )^ ).G:=colors.g;
+ order_rgba(pointer(p )^ ).B:=colors.b;
+ order_rgba(pointer(p )^ ).A:=colors.a;
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgba32_blend_from_color }
+procedure rgba32_blend_from_color(this : pixel_formats_ptr; from : pixel_formats_ptr; color : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ ppsz : unsigned;
+
+ psrc : int8u_ptr;
+ pdst : unsigned_ptr;
+
+begin
+ ppsz:=from._pix_width;
+ psrc:=from.row_ptr(ysrc );
+
+ if psrc <> NIL then
+ begin
+ pdst:=unsigned_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + (xdst shl 2 ) );
+
+ repeat
+ copy_or_blend_pix_rgba(
+ pdst ,color.r, color.g, color.b, color.a,
+ shr_int32(psrc^ * cover + base_mask ,base_shift ) );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,4 );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ rgba32_blend_from_lut }
+procedure rgba32_blend_from_lut(this : pixel_formats_ptr; from : pixel_formats_ptr; color_lut : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ ppsz : unsigned;
+
+ psrc : int8u_ptr;
+ pdst : unsigned_ptr;
+
+ color : aggclr_ptr;
+
+begin
+ ppsz:=from._pix_width;
+ psrc:=from.row_ptr(ysrc );
+
+ if psrc <> NIL then
+ begin
+ pdst:=unsigned_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + (xdst shl 2 ) );
+
+ if cover = 255 then
+ repeat
+ color:=aggclr_ptr(ptrcomp(color_lut ) + psrc^ * sizeof(aggclr ) );
+
+ copy_or_blend_pix_rgba(pdst ,color.r, color.g, color.b, color.a );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,4 );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ color:=aggclr_ptr(ptrcomp(color_lut ) + psrc^ * sizeof(aggclr ) );
+
+ copy_or_blend_pix_rgba(pdst ,color.r, color.g, color.b, color.a ,cover );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,4 );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
diff --git a/src/corelib/render/software/pf_rgba32_pre.inc b/src/corelib/render/software/pf_rgba32_pre.inc
new file mode 100644
index 00000000..58858b64
--- /dev/null
+++ b/src/corelib/render/software/pf_rgba32_pre.inc
@@ -0,0 +1,489 @@
+//
+// AggPas 2.4 RM3 pixel format definition file
+//
+{ blend_pix_rgba_pre }
+procedure blend_pix_rgba_pre(p : unsigned_ptr; cr ,cg ,cb ,alpha : unsigned ); overload;
+begin
+ alpha:=base_mask - alpha;
+
+ order_rgba(p^ ).R:=int8u(((order_rgba(p^ ).R * alpha) shr base_shift ) + cr );
+ order_rgba(p^ ).G:=int8u(((order_rgba(p^ ).G * alpha) shr base_shift ) + cg );
+ order_rgba(p^ ).B:=int8u(((order_rgba(p^ ).B * alpha) shr base_shift ) + cb );
+ order_rgba(p^ ).A:=int8u(base_mask - ((alpha * (base_mask - order_rgba(p^ ).A ) ) shr base_shift) );
+
+end;
+
+{ blend_pix_rgba_pre }
+procedure blend_pix_rgba_pre(p : unsigned_ptr; cr ,cg ,cb ,alpha ,cover : unsigned ); overload;
+begin
+ alpha:=base_mask - alpha;
+ cover:=(cover + 1 ) shl (base_shift - 8 );
+
+ order_rgba(p^ ).R:=int8u((order_rgba(p^ ).R * alpha + cr * cover ) shr base_shift );
+ order_rgba(p^ ).G:=int8u((order_rgba(p^ ).G * alpha + cg * cover ) shr base_shift );
+ order_rgba(p^ ).B:=int8u((order_rgba(p^ ).B * alpha + cb * cover ) shr base_shift );
+ order_rgba(p^ ).A:=int8u(base_mask - ((alpha * (base_mask - order_rgba(p^ ).A ) ) shr base_shift ) );
+
+end;
+
+{ copy_or_blend_pix_rgba_pre }
+procedure copy_or_blend_pix_rgba_pre(p : unsigned_ptr; cr ,cg ,cb ,alpha : unsigned ); overload;
+begin
+ if alpha <> 0 then
+ if alpha = base_mask then
+ begin
+ order_rgba(p^ ).R:=cr;
+ order_rgba(p^ ).G:=cg;
+ order_rgba(p^ ).B:=cb;
+ order_rgba(p^ ).A:=base_mask;
+
+ end
+ else
+ blend_pix_rgba_pre(p ,cr ,cg ,cb ,alpha );
+
+end;
+
+{ copy_or_blend_pix_rgba_pre }
+procedure copy_or_blend_pix_rgba_pre(p : unsigned_ptr; cr ,cg ,cb ,alpha ,cover : unsigned ); overload;
+begin
+ if cover = 255 then
+ copy_or_blend_pix_rgba_pre(p ,cr ,cg ,cb ,alpha )
+ else
+ if alpha <> 0 then
+ begin
+ alpha:=(alpha * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_rgba(p^ ).R:=cr;
+ order_rgba(p^ ).G:=cg;
+ order_rgba(p^ ).B:=cb;
+ order_rgba(p^ ).A:=base_mask;
+
+ end
+ else
+ blend_pix_rgba_pre(p ,cr ,cg ,cb ,alpha ,cover );
+
+ end;
+
+end;
+
+{ rgba32_pre_blend_pixel }
+procedure rgba32_pre_blend_pixel(this : pixel_formats_ptr; x ,y : int; c : aggclr_ptr; cover : int8u );
+begin
+ copy_or_blend_pix_rgba_pre(
+ unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) ) ,
+ c.r ,c.g ,c.b ,c.a ,cover );
+
+end;
+
+{ rgba32_pre_blend_hline }
+procedure rgba32_pre_blend_hline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+var
+ p : unsigned_ptr;
+ v : unsigned;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_rgba(v ).R:=c.r;
+ order_rgba(v ).G:=c.g;
+ order_rgba(v ).B:=c.b;
+ order_rgba(v ).A:=c.a;
+
+ repeat
+ p^:=v;
+
+ inc(ptrcomp(p ) ,sizeof(unsigned ) );
+ dec(len );
+
+ until len = 0;
+
+ end
+ else
+ if cover = 255 then
+ repeat
+ blend_pix_rgba_pre(p ,c.r ,c.g ,c.b ,alpha );
+
+ inc(ptrcomp(p ) ,sizeof(unsigned ) );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ blend_pix_rgba_pre(p ,c.r ,c.g ,c.b ,alpha ,cover );
+
+ inc(ptrcomp(p ) ,sizeof(unsigned ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ rgba32_pre_blend_vline }
+procedure rgba32_pre_blend_vline(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; cover : int8u );
+var
+ p : unsigned_ptr;
+ v : unsigned;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ alpha:=(c.a * (cover + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_rgba(v ).R:=c.r;
+ order_rgba(v ).G:=c.g;
+ order_rgba(v ).B:=c.b;
+ order_rgba(v ).A:=c.a;
+
+ repeat
+ p^:=v;
+ p :=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ until len = 0;
+
+ end
+ else
+ if cover = 255 then
+ repeat
+ blend_pix_rgba_pre(p ,c.r ,c.g ,c.b ,alpha );
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ blend_pix_rgba_pre(p ,c.r ,c.g ,c.b ,alpha ,cover );
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ rgba32_pre_blend_solid_hspan }
+procedure rgba32_pre_blend_solid_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+var
+ p : unsigned_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ repeat
+ alpha:=(c.a * (covers^ + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_rgba(p^ ).R:=c.r;
+ order_rgba(p^ ).G:=c.g;
+ order_rgba(p^ ).B:=c.b;
+ order_rgba(p^ ).A:=base_mask;
+
+ end
+ else
+ blend_pix_rgba_pre(p ,c.r ,c.g ,c.b ,alpha ,covers^ );
+
+ inc(ptrcomp(p ) ,4 );
+ inc(ptrcomp(covers ) );
+
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ rgba32_pre_blend_solid_vspan }
+procedure rgba32_pre_blend_solid_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; c : aggclr_ptr; covers : int8u_ptr );
+var
+ p : unsigned_ptr;
+
+ alpha : unsigned;
+
+begin
+ if c.a <> 0 then
+ begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ repeat
+ alpha:=(c.a * (covers^ + 1 ) ) shr 8;
+
+ if alpha = base_mask then
+ begin
+ order_rgba(p^ ).R:=c.r;
+ order_rgba(p^ ).G:=c.g;
+ order_rgba(p^ ).B:=c.b;
+ order_rgba(p^ ).A:=base_mask;
+
+ end
+ else
+ blend_pix_rgba_pre(p ,c.r ,c.g ,c.b ,alpha ,covers^ );
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ rgba32_pre_blend_color_hspan }
+procedure rgba32_pre_blend_color_hspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+var
+ p : unsigned_ptr;
+
+begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ if covers <> NIL then
+ repeat
+ copy_or_blend_pix_rgba_pre(p ,colors.r ,colors.g ,colors.b ,colors.a ,covers^ );
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+ inc(ptrcomp(p ) ,4 );
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0
+ else
+ if cover = 255 then
+ repeat
+ copy_or_blend_pix_rgba_pre(p ,colors.r ,colors.g ,colors.b ,colors.a );
+
+ inc(ptrcomp(p ) ,4 );
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ copy_or_blend_pix_rgba_pre(p ,colors.r ,colors.g ,colors.b ,colors.a ,cover );
+
+ inc(ptrcomp(p ) ,4 );
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgba32_pre_blend_color_vspan }
+procedure rgba32_pre_blend_color_vspan(this : pixel_formats_ptr; x ,y : int; len : unsigned; colors : aggclr_ptr; covers : int8u_ptr; cover : int8u );
+var
+ p : unsigned_ptr;
+
+begin
+ p:=unsigned_ptr(ptrcomp(this.m_rbuf.row(y ) ) + (x shl 2 ) );
+
+ if covers <> NIL then
+ repeat
+ copy_or_blend_pix_rgba_pre(
+ p ,
+ colors.r ,
+ colors.g ,
+ colors.b ,
+ colors.a ,
+ covers^ );
+
+ inc(ptrcomp(covers ) ,sizeof(int8u ) );
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0
+ else
+ if cover = 255 then
+ repeat
+ copy_or_blend_pix_rgba_pre(
+ p ,
+ colors.r ,
+ colors.g ,
+ colors.b ,
+ colors.a );
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ copy_or_blend_pix_rgba_pre(
+ p ,
+ colors.r ,
+ colors.g ,
+ colors.b ,
+ colors.a ,
+ cover );
+
+ p:=unsigned_ptr(this.m_rbuf.next_row(int8u_ptr(p ) ) );
+
+ inc(ptrcomp(colors ) ,sizeof(aggclr ) );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgba32_pre_blend_from }
+procedure rgba32_pre_blend_from(this : pixel_formats_ptr; from : pixel_formats_ptr; psrc_ : int8u_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ psrc ,pdst : unsigned_ptr;
+
+ incp : int;
+
+begin
+ psrc:=unsigned_ptr(psrc_ );
+ pdst:=unsigned_ptr(ptrcomp(this.m_rbuf.row(ydst ) ) + (xdst shl 2 ) * sizeof(int8u ) );
+ incp:=4;
+
+ if ptrcomp(xdst ) > ptrcomp(xsrc ) then
+ begin
+ inc(ptrcomp(psrc ) ,((len - 1 ) shl 2 ) * sizeof(int8u ) );
+ inc(ptrcomp(pdst ) ,((len - 1 ) shl 2 ) * sizeof(int8u ) );
+
+ incp:=-4;
+
+ end;
+
+ if cover = 255 then
+ repeat
+ copy_or_blend_pix_rgba_pre(
+ pdst ,
+ order_rgba(psrc^ ).R ,
+ order_rgba(psrc^ ).G ,
+ order_rgba(psrc^ ).B ,
+ order_rgba(psrc^ ).A );
+
+ inc(ptrcomp(psrc ) ,incp );
+ inc(ptrcomp(pdst ) ,incp );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ copy_or_blend_pix_rgba_pre(
+ pdst ,
+ order_rgba(psrc^ ).R ,
+ order_rgba(psrc^ ).G ,
+ order_rgba(psrc^ ).B ,
+ order_rgba(psrc^ ).A ,
+ cover );
+
+ inc(ptrcomp(psrc ) ,incp );
+ inc(ptrcomp(pdst ) ,incp );
+ dec(len );
+
+ until len = 0;
+
+end;
+
+{ rgba32_pre_blend_from_color }
+procedure rgba32_pre_blend_from_color(this : pixel_formats_ptr; from : pixel_formats_ptr; color : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ ppsz : unsigned;
+
+ psrc : int8u_ptr;
+ pdst : unsigned_ptr;
+
+begin
+ ppsz:=from._pix_width;
+ psrc:=from.row_ptr(ysrc );
+
+ if psrc <> NIL then
+ begin
+ pdst:=unsigned_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + (xdst shl 2 ) );
+
+ repeat
+ copy_or_blend_pix_rgba_pre(
+ pdst ,color.r, color.g, color.b, color.a,
+ shr_int32(psrc^ * cover + base_mask ,base_shift ) );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,4 );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
+{ rgba32_pre_blend_from_lut }
+procedure rgba32_pre_blend_from_lut(this : pixel_formats_ptr; from : pixel_formats_ptr; color_lut : aggclr_ptr; xdst ,ydst ,xsrc ,ysrc : int; len : unsigned; cover : int8u );
+var
+ ppsz : unsigned;
+
+ psrc : int8u_ptr;
+ pdst : unsigned_ptr;
+
+ color : aggclr_ptr;
+
+begin
+ ppsz:=from._pix_width;
+ psrc:=from.row_ptr(ysrc );
+
+ if psrc <> NIL then
+ begin
+ pdst:=unsigned_ptr(ptrcomp(this.m_rbuf.row_xy(xdst ,ydst ,len ) ) + (xdst shl 2 ) );
+
+ if cover = 255 then
+ repeat
+ color:=aggclr_ptr(ptrcomp(color_lut ) + psrc^ * sizeof(aggclr ) );
+
+ copy_or_blend_pix_rgba_pre(pdst ,color.r, color.g, color.b, color.a );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,4 );
+ dec(len );
+
+ until len = 0
+ else
+ repeat
+ color:=aggclr_ptr(ptrcomp(color_lut ) + psrc^ * sizeof(aggclr ) );
+
+ copy_or_blend_pix_rgba_pre(pdst ,color.r, color.g, color.b, color.a ,cover );
+
+ inc(ptrcomp(psrc ) ,ppsz );
+ inc(ptrcomp(pdst ) ,4 );
+ dec(len );
+
+ until len = 0;
+
+ end;
+
+end;
+
diff --git a/src/corelib/render/software/platform/linux/agg_platform_support.pas b/src/corelib/render/software/platform/linux/agg_platform_support.pas
new file mode 100644
index 00000000..0ba97803
--- /dev/null
+++ b/src/corelib/render/software/platform/linux/agg_platform_support.pas
@@ -0,0 +1,2505 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// class platform_support
+//
+// It's not a part of the AGG library, it's just a helper class to create
+// interactive demo examples. Since the examples should not be too complex
+// this class is provided to support some very basic interactive graphical
+// funtionality, such as putting the rendered image to the window, simple
+// keyboard and mouse input, window resizing, setting the window title,
+// and catching the "idle" events.
+//
+// The most popular platforms are:
+//
+// Windows-32 API
+// X-Window API
+// SDL library (see http://www.libsdl.org/)
+// MacOS C/C++ API
+//
+// All the system dependent stuff sits in the platform_specific class.
+// The platform_support class has just a pointer to it and it's
+// the responsibility of the implementation to create/delete it.
+// This class being defined in the implementation file can have
+// any platform dependent stuff such as HWND, X11 Window and so on.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 29.03.2006-Milano: finished & tested OK
+// 28.03.2006-Milano: platform_specific & platform_support
+// 20.03.2006-Milano: Unit port establishment
+//
+{ agg_platform_support.pas }
+unit
+ agg_platform_support ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+{$I- }
+uses
+ X ,Xlib ,Xutil ,Xatom ,keysym ,libc ,CTypes ,SysUtils ,
+ agg_basics ,
+ agg_ctrl ,
+ agg_rendering_buffer ,
+ agg_trans_affine ,
+ agg_trans_viewport ,
+ agg_color_conv ,
+ file_utils_ ;
+
+{ TYPES DEFINITION }
+const
+//----------------------------------------------------------window_flag_e
+// These are flags used in method init(). Not all of them are
+// applicable on different platforms, for example the win32_api
+// cannot use a hardware buffer (window_hw_buffer).
+// The implementation should simply ignore unsupported flags.
+ window_resize = 1;
+ window_hw_buffer = 2;
+ window_keep_aspect_ratio = 4;
+ window_process_all_keys = 8;
+
+type
+//-----------------------------------------------------------pix_format_e
+// Possible formats of the rendering buffer. Initially I thought that it's
+// reasonable to create the buffer and the rendering functions in
+// accordance with the native pixel format of the system because it
+// would have no overhead for pixel format conersion.
+// But eventually I came to a conclusion that having a possibility to
+// convert pixel formats on demand is a good idea. First, it was X11 where
+// there lots of different formats and visuals and it would be great to
+// render everything in, say, RGB-24 and display it automatically without
+// any additional efforts. The second reason is to have a possibility to
+// debug renderers for different pixel formats and colorspaces having only
+// one computer and one system.
+//
+// This stuff is not included into the basic AGG functionality because the
+// number of supported pixel formats (and/or colorspaces) can be great and
+// if one needs to add new format it would be good only to add new
+// rendering files without having to modify any existing ones (a general
+// principle of incapsulation and isolation).
+//
+// Using a particular pixel format doesn't obligatory mean the necessity
+// of software conversion. For example, win32 API can natively display
+// gray8, 15-bit RGB, 24-bit BGR, and 32-bit BGRA formats.
+// This list can be (and will be!) extended in future.
+ pix_format_e = (
+
+ pix_format_undefined , // By default. No conversions are applied
+ pix_format_bw, // 1 bit per color B/W
+ pix_format_gray8, // Simple 256 level grayscale
+ pix_format_gray16, // Simple 65535 level grayscale
+ pix_format_rgb555, // 15 bit rgb. Depends on the byte ordering!
+ pix_format_rgb565, // 16 bit rgb. Depends on the byte ordering!
+ pix_format_rgbAAA, // 30 bit rgb. Depends on the byte ordering!
+ pix_format_rgbBBA, // 32 bit rgb. Depends on the byte ordering!
+ pix_format_bgrAAA, // 30 bit bgr. Depends on the byte ordering!
+ pix_format_bgrABB, // 32 bit bgr. Depends on the byte ordering!
+ pix_format_rgb24, // R-G-B, one byte per color component
+ pix_format_bgr24, // B-G-R, native win32 BMP format.
+ pix_format_rgba32, // R-G-B-A, one byte per color component
+ pix_format_argb32, // A-R-G-B, native MAC format
+ pix_format_abgr32, // A-B-G-R, one byte per color component
+ pix_format_bgra32, // B-G-R-A, native win32 BMP format
+ pix_format_rgb48, // R-G-B, 16 bits per color component
+ pix_format_bgr48, // B-G-R, native win32 BMP format.
+ pix_format_rgba64, // R-G-B-A, 16 bits byte per color component
+ pix_format_argb64, // A-R-G-B, native MAC format
+ pix_format_abgr64, // A-B-G-R, one byte per color component
+ pix_format_bgra64, // B-G-R-A, native win32 BMP format
+
+ end_of_pix_formats );
+
+const
+//-------------------------------------------------------------input_flag_e
+// Mouse and keyboard flags. They can be different on different platforms
+// and the ways they are obtained are also different. But in any case
+// the system dependent flags should be mapped into these ones. The meaning
+// of that is as follows. For example, if kbd_ctrl is set it means that the
+// ctrl key is pressed and being held at the moment. They are also used in
+// the overridden methods such as on_mouse_move(), on_mouse_button_down(),
+// on_mouse_button_dbl_click(), on_mouse_button_up(), on_key().
+// In the method on_mouse_button_up() the mouse flags have different
+// meaning. They mean that the respective button is being released, but
+// the meaning of the keyboard flags remains the same.
+// There's absolut minimal set of flags is used because they'll be most
+// probably supported on different platforms. Even the mouse_right flag
+// is restricted because Mac's mice have only one button, but AFAIK
+// it can be simulated with holding a special key on the keydoard.
+ mouse_left = 1;
+ mouse_right = 2;
+ kbd_shift = 4;
+ kbd_ctrl = 8;
+
+//--------------------------------------------------------------key_code_e
+// Keyboard codes. There's also a restricted set of codes that are most
+// probably supported on different platforms. Any platform dependent codes
+// should be converted into these ones. There're only those codes are
+// defined that cannot be represented as printable ASCII-characters.
+// All printable ASCII-set can be used in a regilar C/C++ manner:
+// ' ', 'A', '0' '+' and so on.
+// Since the clasas is used for creating very simple demo-applications
+// we don't need very rich possibilities here, just basic ones.
+// Actually the numeric key codes are taken from the SDL library, so,
+// the implementation of the SDL support does not require any mapping.
+// ASCII set. Should be supported everywhere
+ key_backspace = 8;
+ key_tab = 9;
+ key_clear = 12;
+ key_return = 13;
+ key_pause = 19;
+ key_escape = 27;
+
+// Keypad
+ key_delete = 127;
+ key_kp0 = 256;
+ key_kp1 = 257;
+ key_kp2 = 258;
+ key_kp3 = 259;
+ key_kp4 = 260;
+ key_kp5 = 261;
+ key_kp6 = 262;
+ key_kp7 = 263;
+ key_kp8 = 264;
+ key_kp9 = 265;
+ key_kp_period = 266;
+ key_kp_divide = 267;
+ key_kp_multiply = 268;
+ key_kp_minus = 269;
+ key_kp_plus = 270;
+ key_kp_enter = 271;
+ key_kp_equals = 272;
+
+// Arrow-keys and stuff
+ key_up = 273;
+ key_down = 274;
+ key_right = 275;
+ key_left = 276;
+ key_insert = 277;
+ key_home = 278;
+ key_end = 279;
+ key_page_up = 280;
+ key_page_down = 281;
+
+// Functional keys. You'd better avoid using
+// f11...f15 in your applications if you want
+// the applications to be portable
+ key_f1 = 282;
+ key_f2 = 283;
+ key_f3 = 284;
+ key_f4 = 285;
+ key_f5 = 286;
+ key_f6 = 287;
+ key_f7 = 288;
+ key_f8 = 289;
+ key_f9 = 290;
+ key_f10 = 291;
+ key_f11 = 292;
+ key_f12 = 293;
+ key_f13 = 294;
+ key_f14 = 295;
+ key_f15 = 296;
+
+// The possibility of using these keys is
+// very restricted. Actually it's guaranteed
+// only in win32_api and win32_sdl implementations
+ key_numlock = 300;
+ key_capslock = 301;
+ key_scrollock = 302;
+
+ max_ctrl = 128;
+
+type
+//----------------------------------------------------------ctrl_container
+// A helper class that contains pointers to a number of controls.
+// This class is used to ease the event handling with controls.
+// The implementation should simply call the appropriate methods
+// of this class when appropriate events occure.
+ crtl_container_ptr = ^ctrl_container;
+ ctrl_container = object
+ m_ctrl : array[0..max_ctrl - 1 ] of ctrl_ptr;
+
+ m_num_ctrl : unsigned;
+ m_cur_ctrl : int;
+
+ constructor Construct;
+ destructor Destruct;
+
+ procedure add(c : ctrl_ptr );
+
+ function in_rect(x ,y : double ) : boolean;
+
+ function on_mouse_button_down(x ,y : double ) : boolean;
+ function on_mouse_button_up (x ,y : double ) : boolean;
+
+ function on_mouse_move(x ,y : double; button_flag : boolean ) : boolean;
+ function on_arrow_keys(left ,right ,down ,up : boolean ) : boolean;
+
+ function set_cur(x ,y : double ) : boolean;
+
+ end;
+
+//---------------------------------------------------------platform_support
+// This class is a base one to the apllication classes. It can be used
+// as follows:
+//
+// the_application = object(platform_support )
+//
+// constructor Construct(bpp : unsigned; flip_y : boolean );
+// . . .
+//
+// //override stuff . . .
+// procedure on_init; virtual;
+// procedure on_draw; virtual;
+// procedure on_resize(sx ,sy : int ); virtual;
+// // . . . and so on, see virtual functions
+//
+// //any your own stuff . . .
+// };
+//
+// VAR
+// app : the_application;
+//
+// BEGIN
+// app.Construct(pix_format_rgb24 ,true );
+// app.caption ("AGG Example. Lion" );
+//
+// if app.init(500 ,400 ,window_resize ) then
+// app.run;
+//
+// app.Destruct;
+//
+// END.
+//
+const
+ max_images = 16;
+
+type
+ platform_specific_ptr = ^platform_specific;
+ platform_specific = object
+ m_format ,
+ m_sys_format : pix_format_e;
+ m_byte_order : int;
+
+ m_flip_y : boolean;
+ m_bpp ,
+ m_sys_bpp : unsigned;
+ m_display : PDisplay;
+ m_screen ,
+ m_depth : int;
+ m_visual : PVisual;
+ m_window : TWindow;
+ m_gc : TGC;
+
+ m_window_attributes : TXSetWindowAttributes;
+
+ m_ximg_window : PXImage;
+ m_close_atom : TAtom;
+ m_buf_window : pointer;
+ m_buf_alloc : unsigned;
+ m_buf_img : array[0..max_images - 1 ] of pointer;
+ m_img_alloc : array[0..max_images - 1 ] of unsigned;
+
+ m_keymap : array[0..255 ] of unsigned;
+
+ m_update_flag ,
+ m_resize_flag ,
+ m_initialized : boolean;
+
+ //m_wait_mode : boolean;
+ m_sw_start : clock_t;
+
+ constructor Construct(format : pix_format_e; flip_y : boolean );
+ destructor Destruct;
+
+ procedure caption_ (capt : PChar );
+ procedure put_image(src : rendering_buffer_ptr );
+
+ end;
+
+ platform_support_ptr = ^platform_support;
+ platform_support = object
+ m_specific : platform_specific_ptr;
+ m_ctrls : ctrl_container;
+
+ m_format : pix_format_e;
+
+ m_bpp : unsigned;
+
+ m_rbuf_window : rendering_buffer;
+ m_rbuf_img : array[0..max_images - 1 ] of rendering_buffer;
+
+ m_window_flags : unsigned;
+ m_wait_mode ,
+ m_flip_y : boolean; // flip_y - true if you want to have the Y-axis flipped vertically
+ m_caption : shortstring;
+ m_resize_mtx : trans_affine;
+
+ m_initial_width ,
+ m_initial_height : int;
+
+ m_quit : boolean;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ // Setting the windows caption (title). Should be able
+ // to be called at least before calling init().
+ // It's perfect if they can be called anytime.
+ procedure caption_(cap : shortstring );
+
+ // These 3 menthods handle working with images. The image
+ // formats are the simplest ones, such as .BMP in Windows or
+ // .ppm in Linux. In the applications the names of the files
+ // should not have any file extensions. Method load_img() can
+ // be called before init(), so, the application could be able
+ // to determine the initial size of the window depending on
+ // the size of the loaded image.
+ // The argument "idx" is the number of the image 0...max_images-1
+ function load_img (idx : unsigned; file_ : shortstring ) : boolean;
+ function save_img (idx : unsigned; file_ : shortstring ) : boolean;
+ function create_img(idx : unsigned; width_ : unsigned = 0; height_ : unsigned = 0 ) : boolean;
+
+ // init() and run(). See description before the class for details.
+ // The necessity of calling init() after creation is that it's
+ // impossible to call the overridden virtual function (on_init())
+ // from the constructor. On the other hand it's very useful to have
+ // some on_init() event handler when the window is created but
+ // not yet displayed. The rbuf_window() method (see below) is
+ // accessible from on_init().
+ function init(width_ ,height_ ,flags : unsigned ) : boolean;
+ function run : int;
+ procedure quit;
+
+ // The very same parameters that were used in the constructor
+ function _format : pix_format_e;
+ function _flip_y : boolean;
+ function _bpp : unsigned;
+
+ // The following provides a very simple mechanism of doing someting
+ // in background. It's not multitheading. When whait_mode is true
+ // the class waits for the events and it does not ever call on_idle().
+ // When it's false it calls on_idle() when the event queue is empty.
+ // The mode can be changed anytime. This mechanism is satisfactory
+ // for creation very simple animations.
+ function _wait_mode : boolean;
+ procedure wait_mode_(wait_mode : boolean );
+
+ // These two functions control updating of the window.
+ // force_redraw() is an analog of the Win32 InvalidateRect() function.
+ // Being called it sets a flag (or sends a message) which results
+ // in calling on_draw() and updating the content of the window
+ // when the next event cycle comes.
+ // update_window() results in just putting immediately the content
+ // of the currently rendered buffer to the window without calling
+ // on_draw().
+ procedure force_redraw;
+ procedure update_window;
+
+ // So, finally, how to draw anythig with AGG? Very simple.
+ // rbuf_window() returns a reference to the main rendering
+ // buffer which can be attached to any rendering class.
+ // rbuf_img() returns a reference to the previously created
+ // or loaded image buffer (see load_img()). The image buffers
+ // are not displayed directly, they should be copied to or
+ // combined somehow with the rbuf_window(). rbuf_window() is
+ // the only buffer that can be actually displayed.
+ function rbuf_window : rendering_buffer_ptr;
+ function rbuf_img(idx : unsigned ) : rendering_buffer_ptr;
+
+ // Returns file extension used in the implemenation for the particular
+ // system.
+ function _img_ext : shortstring;
+
+ //
+ procedure copy_img_to_window(idx : unsigned );
+ procedure copy_window_to_img(idx : unsigned );
+ procedure copy_img_to_img (idx_to ,idx_from : unsigned );
+
+ // Event handlers. They are not pure functions, so you don't have
+ // to override them all.
+ // In my demo applications these functions are defined inside
+ // the the_application class
+ procedure on_init; virtual;
+ procedure on_resize(sx ,sy : int ); virtual;
+ procedure on_idle; virtual;
+
+ procedure on_mouse_move(x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_up (x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+ procedure on_ctrl_change; virtual;
+ procedure on_draw; virtual;
+ procedure on_post_draw(raw_handler : pointer ); virtual;
+
+ // Adding control elements. A control element once added will be
+ // working and reacting to the mouse and keyboard events. Still, you
+ // will have to render them in the on_draw() using function
+ // render_ctrl() because platform_support doesn't know anything about
+ // renderers you use. The controls will be also scaled automatically
+ // if they provide a proper scaling mechanism (all the controls
+ // included into the basic AGG package do).
+ // If you don't need a particular control to be scaled automatically
+ // call ctrl::no_transform() after adding.
+ procedure add_ctrl(c : ctrl_ptr );
+
+ // Auxiliary functions. trans_affine_resizing() modifier sets up the resizing
+ // matrix on the basis of the given width and height and the initial
+ // width and height of the window. The implementation should simply
+ // call this function every time when it catches the resizing event
+ // passing in the new values of width and height of the window.
+ // Nothing prevents you from "cheating" the scaling matrix if you
+ // call this function from somewhere with wrong arguments.
+ // trans_affine_resizing() accessor simply returns current resizing matrix
+ // which can be used to apply additional scaling of any of your
+ // stuff when the window is being resized.
+ // width(), height(), initial_width(), and initial_height() must be
+ // clear to understand with no comments :-)
+ procedure trans_affine_resizing_(width_ ,height_ : int );
+ function _trans_affine_resizing : trans_affine_ptr;
+
+ function _width : double;
+ function _height : double;
+ function _initial_width : double;
+ function _initial_height : double;
+ function _window_flags : unsigned;
+
+ // Get raw display handler depending on the system.
+ // For win32 its an HDC, for other systems it can be a pointer to some
+ // structure. See the implementation files for detals.
+ // It's provided "as is", so, first you should check if it's not null.
+ // If it's null the raw_display_handler is not supported. Also, there's
+ // no guarantee that this function is implemented, so, in some
+ // implementations you may have simply an unresolved symbol when linking.
+ function _raw_display_handler : pointer;
+
+ // display message box or print the message to the console
+ // (depending on implementation)
+ procedure message_(msg : PChar );
+
+ // Stopwatch functions. Function elapsed_time() returns time elapsed
+ // since the latest start_timer() invocation in millisecods.
+ // The resolutoin depends on the implementation.
+ // In Win32 it uses QueryPerformanceFrequency() / QueryPerformanceCounter().
+ procedure start_timer;
+ function elapsed_time : double;
+
+ // Get the full file name. In most cases it simply returns
+ // file_name. As it's appropriate in many systems if you open
+ // a file by its name without specifying the path, it tries to
+ // open it in the current directory. The demos usually expect
+ // all the supplementary files to be placed in the current
+ // directory, that is usually coincides with the directory where
+ // the the executable is. However, in some systems (BeOS) it's not so.
+ // For those kinds of systems full_file_name() can help access files
+ // preserving commonly used policy.
+ // So, it's a good idea to use in the demos the following:
+ // FILE* fd = fopen(full_file_name("some.file"), "r");
+ // instead of
+ // FILE* fd = fopen("some.file", "r");
+ function full_file_name(file_name : shortstring ) : shortstring;
+ function file_source (path ,fname : shortstring ) : shortstring;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor ctrl_container.Construct;
+begin
+ m_num_ctrl:=0;
+ m_cur_ctrl:=-1;
+
+end;
+
+{ DESTRUCT }
+destructor ctrl_container.Destruct;
+begin
+end;
+
+{ ADD }
+procedure ctrl_container.add;
+begin
+ if m_num_ctrl < max_ctrl then
+ begin
+ m_ctrl[m_num_ctrl ]:=c;
+
+ inc(m_num_ctrl );
+
+ end;
+
+end;
+
+{ IN_RECT }
+function ctrl_container.in_rect;
+var
+ i : unsigned;
+
+begin
+ result:=false;
+
+ if m_num_ctrl > 0 then
+ for i:=0 to m_num_ctrl - 1 do
+ if m_ctrl[i ].in_rect(x ,y ) then
+ begin
+ result:=true;
+
+ exit;
+
+ end;
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+function ctrl_container.on_mouse_button_down;
+var
+ i : unsigned;
+
+begin
+ result:=false;
+
+ if m_num_ctrl > 0 then
+ for i:=0 to m_num_ctrl - 1 do
+ if m_ctrl[i ].on_mouse_button_down(x ,y ) then
+ begin
+ result:=true;
+
+ exit;
+
+ end;
+
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+function ctrl_container.on_mouse_button_up;
+var
+ i : unsigned;
+
+begin
+ result:=false;
+
+ if m_num_ctrl > 0 then
+ for i:=0 to m_num_ctrl - 1 do
+ if m_ctrl[i ].on_mouse_button_up(x ,y ) then
+ begin
+ result:=true;
+
+ exit;
+
+ end;
+
+end;
+
+{ ON_MOUSE_MOVE }
+function ctrl_container.on_mouse_move;
+var
+ i : unsigned;
+
+begin
+ result:=false;
+
+ if m_num_ctrl > 0 then
+ for i:=0 to m_num_ctrl - 1 do
+ if m_ctrl[i ].on_mouse_move(x ,y ,button_flag ) then
+ begin
+ result:=true;
+
+ exit;
+
+ end;
+
+end;
+
+{ ON_ARROW_KEYS }
+function ctrl_container.on_arrow_keys;
+begin
+ result:=false;
+
+ if m_cur_ctrl >= 0 then
+ result:=m_ctrl[m_cur_ctrl ].on_arrow_keys(left ,right ,down ,up );
+
+end;
+
+{ SET_CUR }
+function ctrl_container.set_cur;
+var
+ i : unsigned;
+
+begin
+ result:=false;
+
+ if m_num_ctrl > 0 then
+ for i:=0 to m_num_ctrl - 1 do
+ if m_ctrl[i ].in_rect(x ,y ) then
+ begin
+ if m_cur_ctrl <> i then
+ begin
+ m_cur_ctrl:=i;
+
+ result:=true;
+
+ end;
+
+ exit;
+
+ end;
+
+ if m_cur_ctrl <> -1 then
+ begin
+ m_cur_ctrl:=-1;
+
+ result:=true;
+
+ end;
+
+end;
+
+{ CONSTRUCT }
+constructor platform_specific.Construct;
+var
+ i : unsigned;
+
+begin
+ m_format :=format;
+ m_sys_format:=pix_format_undefined;
+ m_byte_order:=LSBFirst;
+ m_flip_y :=flip_y;
+
+ m_bpp :=0;
+ m_sys_bpp:=0;
+ m_display:=NIL;
+ m_screen :=0;
+ m_depth :=0;
+ m_visual :=NIL;
+ m_window :=0;
+ m_gc :=NIL;
+
+ m_ximg_window:=NIL;
+ m_close_atom :=0;
+ m_buf_window :=NIL;
+ m_buf_alloc :=0;
+
+ m_update_flag:=true;
+ m_resize_flag:=true;
+ m_initialized:=false;
+ //m_wait_mode:=true;
+
+ fillchar(m_buf_img[0 ] ,sizeof(m_buf_img ) ,0 );
+
+ for i:=0 to 255 do
+ m_keymap[i ]:=i;
+
+ m_keymap[XK_Pause and $FF ]:=key_pause;
+ m_keymap[XK_Clear and $FF ]:=key_clear;
+
+ m_keymap[XK_KP_0 and $FF ]:=key_kp0;
+ m_keymap[XK_KP_1 and $FF ]:=key_kp1;
+ m_keymap[XK_KP_2 and $FF ]:=key_kp2;
+ m_keymap[XK_KP_3 and $FF ]:=key_kp3;
+ m_keymap[XK_KP_4 and $FF ]:=key_kp4;
+ m_keymap[XK_KP_5 and $FF ]:=key_kp5;
+ m_keymap[XK_KP_6 and $FF ]:=key_kp6;
+ m_keymap[XK_KP_7 and $FF ]:=key_kp7;
+ m_keymap[XK_KP_8 and $FF ]:=key_kp8;
+ m_keymap[XK_KP_9 and $FF ]:=key_kp9;
+
+ m_keymap[XK_KP_Insert and $FF ] :=key_kp0;
+ m_keymap[XK_KP_End and $FF ] :=key_kp1;
+ m_keymap[XK_KP_Down and $FF ] :=key_kp2;
+ m_keymap[XK_KP_Page_Down and $FF ]:=key_kp3;
+ m_keymap[XK_KP_Left and $FF ] :=key_kp4;
+ m_keymap[XK_KP_Begin and $FF ] :=key_kp5;
+ m_keymap[XK_KP_Right and $FF ] :=key_kp6;
+ m_keymap[XK_KP_Home and $FF ] :=key_kp7;
+ m_keymap[XK_KP_Up and $FF ] :=key_kp8;
+ m_keymap[XK_KP_Page_Up and $FF ] :=key_kp9;
+ m_keymap[XK_KP_Delete and $FF ] :=key_kp_period;
+ m_keymap[XK_KP_Decimal and $FF ] :=key_kp_period;
+ m_keymap[XK_KP_Divide and $FF ] :=key_kp_divide;
+ m_keymap[XK_KP_Multiply and $FF ] :=key_kp_multiply;
+ m_keymap[XK_KP_Subtract and $FF ] :=key_kp_minus;
+ m_keymap[XK_KP_Add and $FF ] :=key_kp_plus;
+ m_keymap[XK_KP_Enter and $FF ] :=key_kp_enter;
+ m_keymap[XK_KP_Equal and $FF ] :=key_kp_equals;
+
+ m_keymap[XK_Up and $FF ] :=key_up;
+ m_keymap[XK_Down and $FF ] :=key_down;
+ m_keymap[XK_Right and $FF ] :=key_right;
+ m_keymap[XK_Left and $FF ] :=key_left;
+ m_keymap[XK_Insert and $FF ] :=key_insert;
+ m_keymap[XK_Home and $FF ] :=key_delete;
+ m_keymap[XK_End and $FF ] :=key_end;
+ m_keymap[XK_Page_Up and $FF ] :=key_page_up;
+ m_keymap[XK_Page_Down and $FF ]:=key_page_down;
+
+ m_keymap[XK_F1 and $FF ] :=key_f1;
+ m_keymap[XK_F2 and $FF ] :=key_f2;
+ m_keymap[XK_F3 and $FF ] :=key_f3;
+ m_keymap[XK_F4 and $FF ] :=key_f4;
+ m_keymap[XK_F5 and $FF ] :=key_f5;
+ m_keymap[XK_F6 and $FF ] :=key_f6;
+ m_keymap[XK_F7 and $FF ] :=key_f7;
+ m_keymap[XK_F8 and $FF ] :=key_f8;
+ m_keymap[XK_F9 and $FF ] :=key_f9;
+ m_keymap[XK_F10 and $FF ]:=key_f10;
+ m_keymap[XK_F11 and $FF ]:=key_f11;
+ m_keymap[XK_F12 and $FF ]:=key_f12;
+ m_keymap[XK_F13 and $FF ]:=key_f13;
+ m_keymap[XK_F14 and $FF ]:=key_f14;
+ m_keymap[XK_F15 and $FF ]:=key_f15;
+
+ m_keymap[XK_Num_Lock and $FF ] :=key_numlock;
+ m_keymap[XK_Caps_Lock and $FF ] :=key_capslock;
+ m_keymap[XK_Scroll_Lock and $FF ]:=key_scrollock;
+
+ case m_format of
+ pix_format_gray8 :
+ m_bpp:=8;
+
+ pix_format_rgb565 ,
+ pix_format_rgb555 :
+ m_bpp:=16;
+
+ pix_format_rgb24 ,
+ pix_format_bgr24 :
+ m_bpp:=24;
+
+ pix_format_bgra32 ,
+ pix_format_abgr32 ,
+ pix_format_argb32 ,
+ pix_format_rgba32 :
+ m_bpp:=32;
+
+ end;
+
+ m_sw_start:=clock;
+
+end;
+
+{ DESTRUCT }
+destructor platform_specific.Destruct;
+begin
+end;
+
+{ CAPTION_ }
+procedure platform_specific.caption_;
+var
+ tp : TXTextProperty;
+
+begin
+ tp.value :=PCUChar(@capt[1 ] );
+ tp.encoding:=XA_WM_NAME;
+ tp.format :=8;
+ tp.nitems :=strlen(capt );
+
+ XSetWMName (m_display ,m_window ,@tp );
+ XStoreName (m_display ,m_window ,capt );
+ XSetIconName (m_display ,m_window ,capt );
+ XSetWMIconName(m_display ,m_window ,@tp );
+
+end;
+
+{ PUT_IMAGE }
+procedure platform_specific.put_image;
+var
+ row_len : int;
+ buf_tmp : pointer;
+
+ rbuf_tmp : rendering_buffer;
+
+begin
+ if m_ximg_window = NIL then
+ exit;
+
+ m_ximg_window.data:=m_buf_window;
+
+ if m_format = m_sys_format then
+ XPutImage(
+ m_display ,
+ m_window ,
+ m_gc ,
+ m_ximg_window ,
+ 0 ,0 ,0 ,0 ,
+ src._width ,
+ src._height )
+
+ else
+ begin
+ row_len:=src._width * m_sys_bpp div 8;
+
+ agg_getmem(buf_tmp ,row_len * src._height );
+
+ rbuf_tmp.Construct;
+
+ if m_flip_y then
+ rbuf_tmp.attach(
+ buf_tmp ,
+ src._width,
+ src._height ,
+ -row_len )
+ else
+ rbuf_tmp.attach(
+ buf_tmp ,
+ src._width,
+ src._height ,
+ row_len );
+
+ case m_sys_format of
+ pix_format_rgb555 :
+ case m_format of
+ pix_format_rgb555 : color_conv(@rbuf_tmp ,src ,color_conv_rgb555_to_rgb555 );
+ pix_format_rgb565 : color_conv(@rbuf_tmp ,src ,color_conv_rgb565_to_rgb555 );
+ //pix_format_rgb24 : color_conv(@rbuf_tmp ,src ,color_conv_rgb24_to_rgb555 );
+ pix_format_bgr24 : color_conv(@rbuf_tmp ,src ,color_conv_bgr24_to_rgb555 );
+ //pix_format_rgba32 : color_conv(@rbuf_tmp ,src ,color_conv_rgba32_to_rgb555 );
+ //pix_format_argb32 : color_conv(@rbuf_tmp ,src ,color_conv_argb32_to_rgb555 );
+ pix_format_bgra32 : color_conv(@rbuf_tmp ,src ,color_conv_bgra32_to_rgb555 );
+ //pix_format_abgr32 : color_conv(@rbuf_tmp ,src ,color_conv_abgr32_to_rgb555 );
+
+ end;
+
+ pix_format_rgb565 :
+ case m_format of
+ pix_format_rgb555 : color_conv(@rbuf_tmp ,src ,color_conv_rgb555_to_rgb565 );
+ //pix_format_rgb565 : color_conv(@rbuf_tmp ,src ,color_conv_rgb565_to_rgb565 );
+ //pix_format_rgb24 : color_conv(@rbuf_tmp ,src ,color_conv_rgb24_to_rgb565 );
+ pix_format_bgr24 : color_conv(@rbuf_tmp ,src ,color_conv_bgr24_to_rgb565 );
+ //pix_format_rgba32 : color_conv(@rbuf_tmp ,src ,color_conv_rgba32_to_rgb565 );
+ //pix_format_argb32 : color_conv(@rbuf_tmp ,src ,color_conv_argb32_to_rgb565 );
+ pix_format_bgra32 : color_conv(@rbuf_tmp ,src ,color_conv_bgra32_to_rgb565 );
+ //pix_format_abgr32 : color_conv(@rbuf_tmp ,src ,color_conv_abgr32_to_rgb565 );
+
+ end;
+
+ pix_format_rgba32 :
+ case m_format of
+ pix_format_rgb555 : color_conv(@rbuf_tmp ,src ,color_conv_rgb555_to_rgba32 );
+ //pix_format_rgb565 : color_conv(@rbuf_tmp ,src ,color_conv_rgb565_to_rgba32 );
+ //pix_format_rgb24 : color_conv(@rbuf_tmp ,src ,color_conv_rgb24_to_rgba32 );
+ pix_format_bgr24 : color_conv(@rbuf_tmp ,src ,color_conv_bgr24_to_rgba32 );
+ //pix_format_rgba32 : color_conv(@rbuf_tmp ,src ,color_conv_rgba32_to_rgba32 );
+ //pix_format_argb32 : color_conv(@rbuf_tmp ,src ,color_conv_argb32_to_rgba32 );
+ pix_format_bgra32 : color_conv(@rbuf_tmp ,src ,color_conv_bgra32_to_rgba32 );
+ //pix_format_abgr32 : color_conv(@rbuf_tmp ,src ,color_conv_abgr32_to_rgba32 );
+
+ end;
+
+ pix_format_abgr32 :
+ case m_format of
+ pix_format_rgb555 : color_conv(@rbuf_tmp ,src ,color_conv_rgb555_to_abgr32 );
+ //pix_format_rgb565 : color_conv(@rbuf_tmp ,src ,color_conv_rgb565_to_abgr32 );
+ //pix_format_rgb24 : color_conv(@rbuf_tmp ,src ,color_conv_rgb24_to_abgr32 );
+ pix_format_bgr24 : color_conv(@rbuf_tmp ,src ,color_conv_bgr24_to_abgr32 );
+ //pix_format_abgr32 : color_conv(@rbuf_tmp ,src ,color_conv_abgr32_to_abgr32 );
+ //pix_format_rgba32 : color_conv(@rbuf_tmp ,src ,color_conv_rgba32_to_abgr32 );
+ //pix_format_argb32 : color_conv(@rbuf_tmp ,src ,color_conv_argb32_to_abgr32 );
+ pix_format_bgra32 : color_conv(@rbuf_tmp ,src ,color_conv_bgra32_to_abgr32 );
+
+ end;
+
+ pix_format_argb32 :
+ case m_format of
+ pix_format_rgb555 : color_conv(@rbuf_tmp ,src ,color_conv_rgb555_to_argb32 );
+ //pix_format_rgb565 : color_conv(@rbuf_tmp ,src ,color_conv_rgb565_to_argb32 );
+ //pix_format_rgb24 : color_conv(@rbuf_tmp ,src ,color_conv_rgb24_to_argb32 );
+ pix_format_bgr24 : color_conv(@rbuf_tmp ,src ,color_conv_bgr24_to_argb32 );
+ pix_format_rgba32 : color_conv(@rbuf_tmp ,src ,color_conv_rgba32_to_argb32 );
+ //pix_format_argb32 : color_conv(@rbuf_tmp ,src ,color_conv_argb32_to_argb32 );
+ pix_format_abgr32 : color_conv(@rbuf_tmp ,src ,color_conv_abgr32_to_argb32 );
+ pix_format_bgra32 : color_conv(@rbuf_tmp ,src ,color_conv_bgra32_to_argb32 );
+
+ end;
+
+ pix_format_bgra32 :
+ case m_format of
+ pix_format_rgb555 : color_conv(@rbuf_tmp ,src ,color_conv_rgb555_to_bgra32 );
+ //pix_format_rgb565 : color_conv(@rbuf_tmp ,src ,color_conv_rgb565_to_bgra32 );
+ //pix_format_rgb24 : color_conv(@rbuf_tmp ,src ,color_conv_rgb24_to_bgra32 );
+ pix_format_bgr24 : color_conv(@rbuf_tmp ,src ,color_conv_bgr24_to_bgra32 );
+ pix_format_rgba32 : color_conv(@rbuf_tmp ,src ,color_conv_rgba32_to_bgra32 );
+ pix_format_argb32 : color_conv(@rbuf_tmp ,src ,color_conv_argb32_to_bgra32 );
+ pix_format_abgr32 : color_conv(@rbuf_tmp ,src ,color_conv_abgr32_to_bgra32 );
+ pix_format_bgra32 : color_conv(@rbuf_tmp ,src ,color_conv_bgra32_to_bgra32 );
+
+ end;
+
+ end;
+
+ m_ximg_window.data:=buf_tmp;
+
+ XPutImage(
+ m_display ,
+ m_window ,
+ m_gc ,
+ m_ximg_window ,
+ 0 ,0 ,0 ,0 ,
+ src._width ,
+ src._height );
+
+ agg_freemem(buf_tmp ,row_len * src._height );
+
+ rbuf_tmp.Destruct;
+
+ end;
+
+end;
+
+{ CONSTRUCT }
+constructor platform_support.Construct;
+var
+ i : unsigned;
+
+ p ,n ,x : shortstring;
+
+begin
+ new(m_specific ,Construct(format_ ,flip_y_ ) );
+
+ m_ctrls.Construct;
+ m_rbuf_window.Construct;
+
+ for i:=0 to max_images - 1 do
+ m_rbuf_img[i ].Construct;
+
+ m_resize_mtx.Construct;
+
+ m_format:=format_;
+
+ m_bpp:=m_specific.m_bpp;
+
+ m_window_flags:=0;
+ m_wait_mode :=true;
+ m_flip_y :=flip_y_;
+
+ m_initial_width :=10;
+ m_initial_height:=10;
+
+ m_caption:='Anti-Grain Geometry Application'#0;
+
+// Change working dir to the application one
+ spread_name(ParamStr(0 ) ,p ,n ,x );
+
+ p:=p + #0;
+
+ libc.__chdir(PChar(@p[1 ] ) );
+
+end;
+
+{ DESTRUCT }
+destructor platform_support.Destruct;
+var
+ i : unsigned;
+
+begin
+ dispose(m_specific ,Destruct );
+
+ m_ctrls.Destruct;
+ m_rbuf_window.Destruct;
+
+ for i:=0 to max_images - 1 do
+ m_rbuf_img[i ].Destruct;
+
+end;
+
+{ CAPTION_ }
+procedure platform_support.caption_;
+begin
+ m_caption:=cap + #0;
+
+ dec(byte(m_caption[0 ] ) );
+
+ if m_specific.m_initialized then
+ m_specific.caption_(PChar(@m_caption[1 ] ) );
+
+end;
+
+{ isdigit }
+function isdigit(c : char ) : boolean;
+begin
+ case c of
+ '0'..'9' :
+ result:=true;
+
+ else
+ result:=false;
+
+ end;
+
+end;
+
+{ atoi }
+function atoi(c : char_ptr ) : int;
+var
+ s : shortstring;
+ e : int;
+
+begin
+ s:='';
+
+ repeat
+ case c^ of
+ '0'..'9' :
+ s:=s + c^;
+
+ else
+ break;
+
+ end;
+
+ inc(ptrcomp(c ) );
+
+ until false;
+
+ val(s ,result ,e );
+
+end;
+
+{ LOAD_IMG }
+function platform_support.load_img;
+var
+ fd : file;
+ buf : array[0..1023 ] of char;
+ len : int;
+ ptr : char_ptr;
+ ret : boolean;
+
+ width ,height : unsigned;
+
+ buf_img : pointer;
+ rbuf_img_ : rendering_buffer;
+
+begin
+ result:=false;
+
+ if idx < max_images then
+ begin
+ file_:=file_ + _img_ext;
+
+ if not file_exists(file_ ) then
+ file_:='ppm/' + file_;
+
+ AssignFile(fd ,file_ );
+ reset (fd ,1 );
+
+ if IOResult <> 0 then
+ exit;
+
+ blockread(fd ,buf ,1022 ,len );
+
+ if len = 0 then
+ begin
+ close(fd );
+ exit;
+
+ end;
+
+ buf[len ]:=#0;
+
+ if (buf[0 ] <> 'P' ) and
+ (buf[1 ] <> '6' ) then
+ begin
+ close(fd );
+ exit;
+
+ end;
+
+ ptr:=@buf[2 ];
+
+ while (ptr^ <> #0 ) and
+ not isdigit(ptr^ ) do
+ inc(ptrcomp(ptr ) );
+
+ if ptr^ = #0 then
+ begin
+ close(fd );
+ exit;
+
+ end;
+
+ width:=atoi(ptr );
+
+ if (width = 0 ) or
+ (width > 4096 ) then
+ begin
+ close(fd );
+ exit;
+
+ end;
+
+ while (ptr^ <> #0 ) and
+ isdigit(ptr^ ) do
+ inc(ptrcomp(ptr ) );
+
+ while (ptr^ <> #0 ) and
+ not isdigit(ptr^ ) do
+ inc(ptrcomp(ptr ) );
+
+ if ptr^ = #0 then
+ begin
+ close(fd );
+ exit;
+
+ end;
+
+ height:=atoi(ptr );
+
+ if (height = 0 ) or
+ (height > 4096 ) then
+ begin
+ close(fd );
+ exit;
+
+ end;
+
+ while (ptr^ <> #0 ) and
+ isdigit(ptr^ ) do
+ inc(ptrcomp(ptr ) );
+
+ while (ptr^ <> #0 ) and
+ not isdigit(ptr^ ) do
+ inc(ptrcomp(ptr ) );
+
+ if atoi(ptr ) <> 255 then
+ begin
+ close(fd );
+ exit;
+
+ end;
+
+ while (ptr^ <> #0 ) and
+ isdigit(ptr^ ) do
+ inc(ptrcomp(ptr ) );
+
+ if ptr^ = #0 then
+ begin
+ close(fd );
+ exit;
+
+ end;
+
+ inc (ptrcomp(ptr ) );
+ seek (fd ,ptrcomp(ptr ) - ptrcomp(@buf ) );
+ create_img(idx ,width ,height );
+
+ ret:=true;
+
+ if m_format = pix_format_rgb24 then
+ blockread(fd ,m_specific.m_buf_img[idx ]^ ,width * height * 3 )
+ else
+ begin
+ agg_getmem(buf_img ,width * height * 3 );
+
+ rbuf_img_.Construct;
+
+ if m_flip_y then
+ rbuf_img_.attach(buf_img ,width ,height ,-width * 3 )
+ else
+ rbuf_img_.attach(buf_img ,width ,height ,width * 3 );
+
+ blockread(fd ,buf_img^ ,width * height * 3 );
+
+ case m_format of
+ //pix_format_rgb555 : color_conv(@m_rbuf_img[idx ] ,@rbuf_img_ ,color_conv_rgb24_to_rgb555 );
+ //pix_format_rgb565 : color_conv(@m_rbuf_img[idx ] ,@rbuf_img_ ,color_conv_rgb24_to_rgb565 );
+ pix_format_bgr24 : color_conv(@m_rbuf_img[idx ] ,@rbuf_img_ ,color_conv_rgb24_to_bgr24 );
+ //pix_format_rgba32 : color_conv(@m_rbuf_img[idx ] ,@rbuf_img_ ,color_conv_rgb24_to_rgba32 );
+ //pix_format_argb32 : color_conv(@m_rbuf_img[idx ] ,@rbuf_img_ ,color_conv_rgb24_to_argb32 );
+ pix_format_bgra32 : color_conv(@m_rbuf_img[idx ] ,@rbuf_img_ ,color_conv_rgb24_to_bgra32 );
+ //pix_format_abgr32 : color_conv(@m_rbuf_img[idx ] ,@rbuf_img_ ,color_conv_rgb24_to_abgr32 );
+ else
+ ret:=false;
+
+ end;
+
+ agg_freemem(buf_img ,width * height * 3 );
+
+ rbuf_img_.Destruct;
+
+ end;
+
+ close(fd );
+
+ result:=ret;
+
+ end;
+
+end;
+
+{ SAVE_IMG }
+function platform_support.save_img;
+var
+ fd : file;
+
+ s ,c : shortstring;
+
+ w ,h ,y : unsigned;
+
+ tmp_buf ,src : pointer;
+
+begin
+ result:=false;
+
+ if (idx < max_images ) and
+ (rbuf_img(idx )._buf <> NIL ) then
+ begin
+ AssignFile(fd ,file_ );
+ rewrite (fd ,1 );
+
+ if IOResult <> 0 then
+ exit;
+
+ w:=rbuf_img(idx )._width;
+ h:=rbuf_img(idx )._height;
+
+ str(w ,c );
+
+ s:='P6'#13 + c + ' ';
+
+ str(h ,c );
+
+ s:=s + c + #13'255'#13;
+
+ blockwrite(fd ,s[1 ] ,length(s ) );
+
+ agg_getmem(tmp_buf ,w * 3 );
+
+ y:=0;
+
+ while y < rbuf_img(idx )._height do
+ begin
+ if m_flip_y then
+ src:=rbuf_img(idx ).row(h - 1 - y )
+ else
+ src:=rbuf_img(idx ).row(y );
+
+ case m_format of
+ pix_format_rgb555 : color_conv_rgb555_to_rgb24(tmp_buf ,src ,w );
+ //pix_format_rgb565 : color_conv_rgb565_to_rgb24(tmp_buf ,src ,w );
+ pix_format_bgr24 : color_conv_bgr24_to_rgb24 (tmp_buf ,src ,w );
+ //pix_format_rgb24 : color_conv_rgb24_to_rgb24 (tmp_buf ,src ,w );
+ //pix_format_rgba32 : color_conv_rgba32_to_rgb24(tmp_buf ,src ,w );
+ //pix_format_argb32 : color_conv_argb32_to_rgb24(tmp_buf ,src ,w );
+ pix_format_bgra32 : color_conv_bgra32_to_rgb24(tmp_buf ,src ,w );
+ //pix_format_abgr32 : color_conv_abgr32_to_rgb24(tmp_buf ,src ,w );
+
+ end;
+
+ blockwrite(fd ,tmp_buf^ ,w * 3 );
+ inc (y );
+
+ end;
+
+ agg_getmem(tmp_buf ,w * 3 );
+ close (fd );
+
+ result:=true;
+
+ end;
+
+end;
+
+{ CREATE_IMG }
+function platform_support.create_img;
+begin
+ result:=false;
+
+ if idx < max_images then
+ begin
+ if width_ = 0 then
+ width_:=trunc(rbuf_window._width );
+
+ if height_ = 0 then
+ height_:=trunc(rbuf_window._height );
+
+ agg_freemem(m_specific.m_buf_img[idx ] ,m_specific.m_img_alloc[idx ] );
+
+ m_specific.m_img_alloc[idx ]:=width_ * height_ * (m_bpp div 8 );
+
+ agg_getmem(m_specific.m_buf_img[idx ] ,m_specific.m_img_alloc[idx ] );
+
+ if m_flip_y then
+ m_rbuf_img[idx ].attach(
+ m_specific.m_buf_img[idx ] ,
+ width_ ,height_ ,
+ -width_ * (m_bpp div 8 ) )
+ else
+ m_rbuf_img[idx ].attach(
+ m_specific.m_buf_img[idx ] ,
+ width_ ,height_ ,
+ width_ * (m_bpp div 8 ) );
+
+ result:=true;
+
+ end;
+
+end;
+
+{ INIT }
+function platform_support.init;
+const
+ xevent_mask =
+ PointerMotionMask or
+ ButtonPressMask or
+ ButtonReleaseMask or
+ ExposureMask or
+ KeyPressMask or
+ StructureNotifyMask;
+
+var
+ r_mask ,g_mask ,b_mask ,window_mask : unsigned;
+
+ t ,hw_byte_order : int;
+
+ hints : PXSizeHints;
+
+begin
+ m_window_flags:=flags;
+
+ m_specific.m_display:=XOpenDisplay(NIL );
+
+ if m_specific.m_display = NIL then
+ begin
+ writeln(stderr ,'Unable to open DISPLAY!' );
+
+ result:=false;
+
+ exit;
+
+ end;
+
+ m_specific.m_screen:=XDefaultScreen(m_specific.m_display );
+ m_specific.m_depth :=XDefaultDepth (m_specific.m_display ,m_specific.m_screen );
+ m_specific.m_visual:=XDefaultVisual(m_specific.m_display ,m_specific.m_screen );
+
+ r_mask:=m_specific.m_visual.red_mask;
+ g_mask:=m_specific.m_visual.green_mask;
+ b_mask:=m_specific.m_visual.blue_mask;
+
+ if (m_specific.m_depth < 15 ) or
+ (r_mask = 0 ) or
+ (g_mask = 0 ) or
+ (b_mask = 0 ) then
+ begin
+ writeln(stderr ,'There''s no Visual compatible with minimal AGG requirements:' );
+ writeln(stderr ,'At least 15-bit color depth and True- or DirectColor class.' );
+ writeln(stderr );
+
+ XCloseDisplay(m_specific.m_display );
+
+ result:=false;
+
+ exit;
+
+ end;
+
+ t:=1;
+
+ hw_byte_order:=LSBFirst;
+
+ if byte(pointer(@t )^ ) = 0 then
+ hw_byte_order:=MSBFirst;
+
+// Perceive SYS-format by mask
+ case m_specific.m_depth of
+ 15 :
+ begin
+ m_specific.m_sys_bpp:=16;
+
+ if (r_mask = $7C00 ) and
+ (g_mask = $3E0 ) and
+ (b_mask = $1F ) then
+ begin
+ m_specific.m_sys_format:=pix_format_rgb555;
+ m_specific.m_byte_order:=hw_byte_order;
+
+ end;
+
+ end;
+
+ 16 :
+ begin
+ m_specific.m_sys_bpp:=16;
+
+ if (r_mask = $F800 ) and
+ (g_mask = $7E0 ) and
+ (b_mask = $1F ) then
+ begin
+ m_specific.m_sys_format:=pix_format_rgb565;
+ m_specific.m_byte_order:=hw_byte_order;
+
+ end;
+
+ end;
+
+ 24 ,32 :
+ begin
+ m_specific.m_sys_bpp:=32;
+
+ if g_mask = $FF00 then
+ begin
+ if (r_mask = $FF ) and
+ (b_mask = $FF0000 ) then
+ case m_specific.m_format of
+ pix_format_rgba32 :
+ begin
+ m_specific.m_sys_format:=pix_format_rgba32;
+ m_specific.m_byte_order:=LSBFirst;
+
+ end;
+
+ pix_format_abgr32 :
+ begin
+ m_specific.m_sys_format:=pix_format_abgr32;
+ m_specific.m_byte_order:=MSBFirst;
+
+ end;
+
+ else
+ begin
+ m_specific.m_byte_order:=hw_byte_order;
+
+ if hw_byte_order = LSBFirst then
+ m_specific.m_sys_format:=pix_format_rgba32
+ else
+ m_specific.m_sys_format:=pix_format_abgr32;
+
+ end;
+
+ end;
+
+ if (r_mask = $FF0000 ) and
+ (b_mask = $FF ) then
+ case m_specific.m_format of
+ pix_format_argb32 :
+ begin
+ m_specific.m_sys_format:=pix_format_argb32;
+ m_specific.m_byte_order:=MSBFirst;
+
+ end;
+
+ pix_format_bgra32 :
+ begin
+ m_specific.m_sys_format:=pix_format_bgra32;
+ m_specific.m_byte_order:=LSBFirst;
+
+ end;
+
+ else
+ begin
+ m_specific.m_byte_order:=hw_byte_order;
+
+ if hw_byte_order = MSBFirst then
+ m_specific.m_sys_format:=pix_format_argb32
+ else
+ m_specific.m_sys_format:=pix_format_bgra32;
+
+ end;
+
+ end;
+
+ end;
+
+ end;
+
+ end;
+
+ if m_specific.m_sys_format = pix_format_undefined then
+ begin
+ writeln(stderr ,'RGB masks are not compatible with AGG pixel formats:' );
+ write (stderr ,'R=' ,r_mask ,'G=' ,g_mask ,'B=' ,b_mask );
+
+ XCloseDisplay(m_specific.m_display );
+
+ result:=false;
+
+ exit;
+
+ end;
+
+ fillchar(
+ m_specific.m_window_attributes ,
+ sizeof(m_specific.m_window_attributes ) ,0 );
+
+ m_specific.m_window_attributes.border_pixel:=
+ XBlackPixel(m_specific.m_display ,m_specific.m_screen );
+
+ m_specific.m_window_attributes.background_pixel:=
+ XWhitePixel(m_specific.m_display ,m_specific.m_screen );
+
+ m_specific.m_window_attributes.override_redirect:=false;
+
+ window_mask:=CWBackPixel or CWBorderPixel;
+
+ m_specific.m_window:=
+ XCreateWindow(
+ m_specific.m_display ,
+ XDefaultRootWindow(m_specific.m_display ) ,
+ 0 ,0 ,
+ width_ ,height_ ,
+ 0 ,
+ m_specific.m_depth ,
+ InputOutput ,
+ CopyFromParent ,
+ window_mask ,
+ @m_specific.m_window_attributes );
+
+ m_specific.m_gc:=XCreateGC(m_specific.m_display ,m_specific.m_window ,0 ,0 );
+
+ m_specific.m_buf_alloc:=width_ * height_ * (m_bpp div 8 );
+
+ agg_getmem(m_specific.m_buf_window ,m_specific.m_buf_alloc );
+ fillchar (m_specific.m_buf_window^ ,m_specific.m_buf_alloc ,255 );
+
+ if m_flip_y then
+ m_rbuf_window.attach(
+ m_specific.m_buf_window ,
+ width_ ,height_ ,
+ -width_ * (m_bpp div 8 ) )
+ else
+ m_rbuf_window.attach(
+ m_specific.m_buf_window ,
+ width_ ,height_ ,
+ width_ * (m_bpp div 8 ) );
+
+ m_specific.m_ximg_window:=
+ XCreateImage(
+ m_specific.m_display ,
+ m_specific.m_visual , //CopyFromParent,
+ m_specific.m_depth ,
+ ZPixmap ,
+ 0 ,
+ m_specific.m_buf_window ,
+ width_ ,height_ ,
+ m_specific.m_sys_bpp ,
+ width_ * (m_specific.m_sys_bpp div 8 ) );
+
+ m_specific.m_ximg_window.byte_order:=m_specific.m_byte_order;
+
+ m_specific.caption_(PChar(@m_caption[1 ] ) );
+
+ m_initial_width :=width_;
+ m_initial_height:=height_;
+
+ if not m_specific.m_initialized then
+ begin
+ on_init;
+
+ m_specific.m_initialized:=true;
+
+ end;
+
+ trans_affine_resizing_(width_ ,height_ );
+
+ on_resize(width_ ,height_ );
+
+ m_specific.m_update_flag:=true;
+
+ hints:=XAllocSizeHints;
+
+ if hints <> NIL then
+ begin
+ if flags and window_resize <> 0 then
+ begin
+ hints.min_width :=32;
+ hints.min_height:=32;
+ hints.max_width :=4096;
+ hints.max_height:=4096;
+
+ end
+ else
+ begin
+ hints.min_width :=width_;
+ hints.min_height:=height_;
+ hints.max_width :=width_;
+ hints.max_height:=height_;
+
+ end;
+
+ hints.flags:=PMaxSize or PMinSize;
+
+ XSetWMNormalHints(m_specific.m_display ,m_specific.m_window ,hints );
+ XFree (hints );
+
+ end;
+
+ XMapWindow (m_specific.m_display ,m_specific.m_window );
+ XSelectInput(m_specific.m_display ,m_specific.m_window ,xevent_mask );
+
+ m_specific.m_close_atom:=
+ XInternAtom(m_specific.m_display ,'WM_DELETE_WINDOW' ,false );
+
+ XSetWMProtocols(
+ m_specific.m_display ,
+ m_specific.m_window ,
+ @m_specific.m_close_atom ,1 );
+
+ result:=true;
+
+end;
+
+{ RUN }
+function platform_support.run;
+var
+ flags ,i : unsigned;
+
+ cur_x ,cur_y ,width ,height : int;
+
+ x_event ,te : TXEvent;
+
+ key : TKeySym;
+
+ left ,up ,right ,down : boolean;
+
+begin
+ XFlush(m_specific.m_display );
+
+ m_quit:=false;
+
+ while not m_quit do
+ begin
+ if m_specific.m_update_flag then
+ begin
+ on_draw;
+ update_window;
+
+ m_specific.m_update_flag:=false;
+
+ end;
+
+ if not m_wait_mode then
+ if XPending(m_specific.m_display ) = 0 then
+ begin
+ on_idle;
+ continue;
+
+ end;
+
+ XNextEvent(m_specific.m_display ,@x_event );
+
+ // In the Idle mode discard all intermediate MotionNotify events
+ if not m_wait_mode and
+ (x_event._type = MotionNotify ) then
+ begin
+ te:=x_event;
+
+ repeat
+ if XPending(m_specific.m_display ) = 0 then
+ break;
+
+ XNextEvent(m_specific.m_display ,@te );
+
+ if te._type <> MotionNotify then
+ break;
+
+ until false;
+
+ x_event:=te;
+
+ end;
+
+ case x_event._type of
+ ConfigureNotify :
+ if (x_event.xconfigure.width <> trunc(m_rbuf_window._width ) ) or
+ (x_event.xconfigure.height <> trunc(m_rbuf_window._height ) ) then
+ begin
+ width :=x_event.xconfigure.width;
+ height:=x_event.xconfigure.height;
+
+ agg_freemem(m_specific.m_buf_window ,m_specific.m_buf_alloc );
+
+ m_specific.m_ximg_window.data:=0;
+
+ XDestroyImage(m_specific.m_ximg_window );
+
+ m_specific.m_buf_alloc:=width * height * (m_bpp div 8 );
+
+ agg_getmem(m_specific.m_buf_window ,m_specific.m_buf_alloc );
+
+ if m_flip_y then
+ m_rbuf_window.attach(
+ m_specific.m_buf_window ,
+ width ,height ,
+ -width * (m_bpp div 8 ) )
+ else
+ m_rbuf_window.attach(
+ m_specific.m_buf_window ,
+ width ,height ,
+ width * (m_bpp div 8 ) );
+
+ m_specific.m_ximg_window:=
+ XCreateImage(m_specific.m_display ,
+ m_specific.m_visual , //CopyFromParent,
+ m_specific.m_depth ,
+ ZPixmap ,
+ 0 ,
+ m_specific.m_buf_window ,
+ width ,height ,
+ m_specific.m_sys_bpp ,
+ width * (m_specific.m_sys_bpp div 8 ) );
+
+ m_specific.m_ximg_window.byte_order:=m_specific.m_byte_order;
+
+ trans_affine_resizing_(width ,height );
+
+ on_resize(width ,height );
+ on_draw;
+ update_window;
+
+ end;
+
+ Expose :
+ begin
+ m_specific.put_image(@m_rbuf_window );
+
+ XFlush(m_specific.m_display );
+ XSync (m_specific.m_display ,false );
+
+ end;
+
+ KeyPress :
+ begin
+ key :=XLookupKeysym(@x_event.xkey ,0 );
+ flags:=0;
+
+ if x_event.xkey.state and Button1Mask <> 0 then
+ flags:=flags or mouse_left;
+
+ if x_event.xkey.state and Button3Mask <> 0 then
+ flags:=flags or mouse_right;
+
+ if x_event.xkey.state and ShiftMask <> 0 then
+ flags:=flags or kbd_shift;
+
+ if x_event.xkey.state and ControlMask <> 0 then
+ flags:=flags or kbd_ctrl;
+
+ left :=false;
+ up :=false;
+ right:=false;
+ down :=false;
+
+ case m_specific.m_keymap[key and $FF ] of
+ key_left : left :=true;
+ key_up : up :=true;
+ key_right : right:=true;
+ key_down : down :=true;
+
+ key_f2 :
+ begin
+ copy_window_to_img(max_images - 1 );
+ save_img (max_images - 1 ,'screenshot.ppm' );
+
+ end;
+
+ end;
+
+ if m_ctrls.on_arrow_keys(left ,right ,down ,up ) then
+ begin
+ on_ctrl_change;
+ force_redraw;
+
+ end
+ else
+ if m_flip_y then
+ on_key(
+ x_event.xkey.x ,
+ trunc(m_rbuf_window._height ) - x_event.xkey.y ,
+ m_specific.m_keymap[key and $FF ] ,flags )
+ else
+ on_key(
+ x_event.xkey.x ,
+ x_event.xkey.y ,
+ m_specific.m_keymap[key and $FF ] ,flags )
+
+ end;
+
+ ButtonPress :
+ begin
+ flags:=0;
+
+ if x_event.xbutton.state and ShiftMask <> 0 then
+ flags:=flags or kbd_shift;
+
+ if x_event.xbutton.state and ControlMask <> 0 then
+ flags:=flags or kbd_ctrl;
+
+ if x_event.xbutton.button = Button1 then
+ flags:=flags or mouse_left;
+
+ if x_event.xbutton.button = Button3 then
+ flags:=flags or mouse_right;
+
+ cur_x:=x_event.xbutton.x;
+
+ if m_flip_y then
+ cur_y:=trunc(m_rbuf_window._height ) - x_event.xbutton.y
+ else
+ cur_y:=x_event.xbutton.y;
+
+ if flags and mouse_left <> 0 then
+ if m_ctrls.on_mouse_button_down(cur_x ,cur_y ) then
+ begin
+ m_ctrls.set_cur(cur_x ,cur_y );
+ on_ctrl_change;
+ force_redraw;
+
+ end
+ else
+ if m_ctrls.in_rect(cur_x ,cur_y ) then
+ if m_ctrls.set_cur(cur_x ,cur_y ) then
+ begin
+ on_ctrl_change;
+ force_redraw;
+
+ end
+ else
+ else
+ on_mouse_button_down(cur_x ,cur_y ,flags );
+
+ if flags and mouse_right <> 0 then
+ on_mouse_button_down(cur_x ,cur_y ,flags );
+
+ //m_specific.m_wait_mode:=m_wait_mode;
+ //m_wait_mode :=true;
+
+ end;
+
+ MotionNotify :
+ begin
+ flags:=0;
+
+ if x_event.xmotion.state and Button1Mask <> 0 then
+ flags:=flags or mouse_left;
+
+ if x_event.xmotion.state and Button3Mask <> 0 then
+ flags:=flags or mouse_right;
+
+ if x_event.xmotion.state and ShiftMask <> 0 then
+ flags:=flags or kbd_shift;
+
+ if x_event.xmotion.state and ControlMask <> 0 then
+ flags:=flags or kbd_ctrl;
+
+ cur_x:=x_event.xbutton.x;
+
+ if m_flip_y then
+ cur_y:=trunc(m_rbuf_window._height ) - x_event.xbutton.y
+ else
+ cur_y:=x_event.xbutton.y;
+
+ if m_ctrls.on_mouse_move(cur_x ,cur_y ,flags and mouse_left <> 0 ) then
+ begin
+ on_ctrl_change;
+ force_redraw;
+
+ end
+ else
+ if not m_ctrls.in_rect(cur_x ,cur_y ) then
+ on_mouse_move(cur_x ,cur_y ,flags );
+
+ end;
+
+ ButtonRelease :
+ begin
+ flags:=0;
+
+ if x_event.xbutton.state and ShiftMask <> 0 then
+ flags:=flags or kbd_shift;
+
+ if x_event.xbutton.state and ControlMask <> 0 then
+ flags:=flags or kbd_ctrl;
+
+ if x_event.xbutton.button = Button1 then
+ flags:=flags or mouse_left;
+
+ if x_event.xbutton.button = Button3 then
+ flags:=flags or mouse_right;
+
+ cur_x:=x_event.xbutton.x;
+
+ if m_flip_y then
+ cur_y:=trunc(m_rbuf_window._height ) - x_event.xbutton.y
+ else
+ cur_y:=x_event.xbutton.y;
+
+ if flags and mouse_left <> 0 then
+ if m_ctrls.on_mouse_button_up(cur_x ,cur_y ) then
+ begin
+ on_ctrl_change;
+ force_redraw;
+
+ end;
+
+ if flags and (mouse_left or mouse_right ) <> 0 then
+ on_mouse_button_up(cur_x ,cur_y ,flags );
+
+ //m_wait_mode:=m_specific.m_wait_mode;
+
+ end;
+
+ ClientMessage :
+ if (x_event.xclient.format = 32 ) and
+ (x_event.xclient.data.l[0 ] = int(m_specific.m_close_atom ) ) then
+ m_quit:=true;
+
+ end;
+
+ end;
+
+ i:=max_images;
+
+ while i <> 0 do
+ begin
+ dec(i );
+
+ if m_specific.m_buf_img[i ] <> NIL then
+ agg_freemem(m_specific.m_buf_img[i ] ,m_specific.m_img_alloc[i ] );
+
+ end;
+
+ agg_freemem(m_specific.m_buf_window ,m_specific.m_buf_alloc );
+
+ m_specific.m_ximg_window.data:=NIL;
+
+ XDestroyImage (m_specific.m_ximg_window );
+ XFreeGC (m_specific.m_display ,m_specific.m_gc );
+ XDestroyWindow(m_specific.m_display ,m_specific.m_window );
+ XCloseDisplay (m_specific.m_display );
+
+ result:=0;
+
+end;
+
+{ QUIT }
+procedure platform_support.quit;
+begin
+ m_quit:=true;
+
+end;
+
+{ _FORMAT }
+function platform_support._format;
+begin
+ result:=m_format;
+
+end;
+
+{ _FLIP_Y }
+function platform_support._flip_y;
+begin
+ result:=m_flip_y;
+
+end;
+
+{ _BPP }
+function platform_support._bpp;
+begin
+ result:=m_bpp;
+
+end;
+
+{ _WAIT_MODE }
+function platform_support._wait_mode;
+begin
+ result:=m_wait_mode;
+
+end;
+
+{ WAIT_MODE_ }
+procedure platform_support.wait_mode_;
+begin
+ m_wait_mode:=wait_mode;
+
+end;
+
+{ FORCE_REDRAW }
+procedure platform_support.force_redraw;
+begin
+ m_specific.m_update_flag:=true;
+
+end;
+
+{ UPDATE_WINDOW }
+procedure platform_support.update_window;
+begin
+ m_specific.put_image(@m_rbuf_window );
+
+// When m_wait_mode is true we can discard all the events
+// came while the image is being drawn. In this case
+// the X server does not accumulate mouse motion events.
+// When m_wait_mode is false, i.e. we have some idle drawing
+// we cannot afford to miss any events
+ XSync(m_specific.m_display ,m_wait_mode );
+
+end;
+
+{ RBUF_WINDOW }
+function platform_support.rbuf_window;
+begin
+ result:=@m_rbuf_window;
+
+end;
+
+{ RBUF_IMG }
+function platform_support.rbuf_img;
+begin
+ result:=@m_rbuf_img[idx ];
+
+end;
+
+{ _IMG_EXT }
+function platform_support._img_ext;
+begin
+ result:='.ppm';
+
+end;
+
+{ COPY_IMG_TO_WINDOW }
+procedure platform_support.copy_img_to_window;
+begin
+ if (idx < max_images ) and
+ (rbuf_img(idx )._buf <> NIL ) then
+ rbuf_window.copy_from(rbuf_img(idx ) );
+
+end;
+
+{ COPY_WINDOW_TO_IMG }
+procedure platform_support.copy_window_to_img;
+begin
+ if idx < max_images then
+ begin
+ create_img(idx ,rbuf_window._width ,rbuf_window._height );
+ rbuf_img (idx ).copy_from(rbuf_window );
+
+ end;
+
+end;
+
+{ COPY_IMG_TO_IMG }
+procedure platform_support.copy_img_to_img;
+begin
+ if (idx_from < max_images ) and
+ (idx_to < max_images ) and
+ (rbuf_img(idx_from )._buf <> NIL ) then
+ begin
+ create_img(
+ idx_to ,
+ rbuf_img(idx_from )._width ,
+ rbuf_img(idx_from )._height );
+
+ rbuf_img(idx_to ).copy_from(rbuf_img(idx_from ) );
+
+ end;
+
+end;
+
+{ ON_INIT }
+procedure platform_support.on_init;
+begin
+end;
+
+{ ON_RESIZE }
+procedure platform_support.on_resize;
+begin
+end;
+
+{ ON_IDLE }
+procedure platform_support.on_idle;
+begin
+end;
+
+{ ON_MOUSE_MOVE }
+procedure platform_support.on_mouse_move;
+begin
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure platform_support.on_mouse_button_down;
+begin
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+procedure platform_support.on_mouse_button_up;
+begin
+end;
+
+{ ON_KEY }
+procedure platform_support.on_key;
+begin
+end;
+
+{ ON_CTRL_CHANGE }
+procedure platform_support.on_ctrl_change;
+begin
+end;
+
+{ ON_DRAW }
+procedure platform_support.on_draw;
+begin
+end;
+
+{ ON_POST_DRAW }
+procedure platform_support.on_post_draw;
+begin
+end;
+
+{ ADD_CTRL }
+procedure platform_support.add_ctrl;
+begin
+ m_ctrls.add(c );
+
+ c.transform(@m_resize_mtx );
+
+end;
+
+{ TRANS_AFFINE_RESIZING_ }
+procedure platform_support.trans_affine_resizing_;
+var
+ vp : trans_viewport;
+ ts : trans_affine_scaling;
+
+begin
+ if m_window_flags and window_keep_aspect_ratio <> 0 then
+ begin
+ vp.Construct;
+ vp.preserve_aspect_ratio(0.5 ,0.5 ,aspect_ratio_meet );
+
+ vp.device_viewport(0 ,0 ,width_ ,height_ );
+ vp.world_viewport (0 ,0 ,m_initial_width ,m_initial_height );
+
+ vp.to_affine(@m_resize_mtx );
+
+ end
+ else
+ begin
+ ts.Construct(
+ width_ / m_initial_width ,
+ height_ / m_initial_height );
+
+ m_resize_mtx.assign(@ts );
+
+ end;
+
+end;
+
+{ _TRANS_AFFINE_RESIZING }
+function platform_support._trans_affine_resizing;
+begin
+ result:=@m_resize_mtx;
+
+end;
+
+{ _WIDTH }
+function platform_support._width;
+begin
+ result:=m_rbuf_window._width;
+
+end;
+
+{ _HEIGHT }
+function platform_support._height;
+begin
+ result:=m_rbuf_window._height;
+
+end;
+
+{ _INITIAL_WIDTH }
+function platform_support._initial_width;
+begin
+ result:=m_initial_width;
+
+end;
+
+{ _INITIAL_HEIGHT }
+function platform_support._initial_height;
+begin
+ result:=m_initial_height;
+
+end;
+
+{ _WINDOW_FLAGS }
+function platform_support._window_flags;
+begin
+ result:=m_window_flags;
+
+end;
+
+{ _RAW_DISPLAY_HANDLER }
+function platform_support._raw_display_handler;
+begin
+end;
+
+{ MESSAGE_ }
+procedure platform_support.message_;
+const
+ x_event_mask =
+ ExposureMask or
+ KeyPressMask;
+
+ capt = ' PRESS ANY KEY TO CONTINUE THE AGGPAS DEMO ...';
+ plus = 4;
+
+var
+ x_display : PDisplay;
+ x_window : TWindow;
+ x_event : TXEvent;
+ x_close : TAtom;
+ x_changes : TXWindowChanges;
+ x_hints : PXSizeHints;
+
+ x_gc : TGC;
+ x_tp : TXTextProperty;
+ x_tx : TXTextItem;
+
+ str ,cur : char_ptr;
+
+ y ,len ,cnt ,max ,x_dx ,x_dy : unsigned;
+
+ font_dir ,font_ascent ,font_descent : int;
+
+ font_str : TXCharStruct;
+
+procedure draw_text;
+begin
+ x_dx:=0;
+ x_dy:=0;
+
+ y :=20;
+ cur:=PChar(@msg[0 ] );
+ max:=strlen(msg );
+ len:=0;
+ cnt:=0;
+
+ while cnt < max do
+ begin
+ if len = 0 then
+ str:=cur;
+
+ case cur^ of
+ #13 :
+ begin
+ XDrawString (x_display ,x_window ,x_gc ,10 ,y ,str ,len );
+ XQueryTextExtents(
+ x_display ,XGContextFromGC(x_gc) ,
+ str ,len ,
+ @font_dir ,
+ @font_ascent ,
+ @font_descent ,
+ @font_str );
+
+ inc(y ,font_str.ascent + font_str.descent + plus );
+ inc(x_dy ,font_str.ascent + font_str.descent + plus );
+
+ if font_str.width > x_dx then
+ x_dx:=font_str.width;
+
+ len:=0;
+
+ end;
+
+ else
+ inc(len );
+
+ end;
+
+ inc(ptrcomp(cur ) );
+ inc(cnt );
+
+ end;
+
+ if len > 0 then
+ begin
+ XDrawString (x_display ,x_window ,x_gc ,10 ,y ,str ,len );
+ XQueryTextExtents(
+ x_display ,XGContextFromGC(x_gc) ,
+ str ,len ,
+ @font_dir ,
+ @font_ascent ,
+ @font_descent ,
+ @font_str );
+
+ inc(x_dy ,font_str.ascent + font_str.descent + plus );
+
+ if font_str.width > x_dx then
+ x_dx:=font_str.width;
+
+ end;
+
+end;
+
+begin
+ x_display:=XOpenDisplay(NIL );
+
+ if x_display <> NIL then
+ begin
+ x_window :=
+ XCreateSimpleWindow(
+ x_display ,
+ XDefaultRootWindow(x_display ) ,
+ 50 ,50 ,
+ 550 ,300 ,
+ 0 ,0 ,
+ 255 + (255 shl 8 ) + (255 shl 16 ) );
+
+ x_gc:=XCreateGC(x_display ,x_window ,0 ,0 );
+
+ draw_text;
+ XResizeWindow(x_display ,x_window ,x_dx + 20 ,x_dy + 40 );
+
+ x_hints:=XAllocSizeHints;
+
+ if x_hints <> NIL then
+ begin
+ x_hints.min_width :=x_dx + 20;
+ x_hints.min_height:=x_dy + 40;
+ x_hints.max_width :=x_dx + 20;
+ x_hints.max_height:=x_dy + 40;
+
+ x_hints.flags:=PMaxSize or PMinSize;
+
+ XSetWMNormalHints(x_display ,x_window ,x_hints );
+ XFree (x_hints );
+
+ end;
+
+ x_tp.value :=PCUChar(@capt[1 ] );
+ x_tp.encoding:=XA_WM_NAME;
+ x_tp.format :=8;
+ x_tp.nitems :=strlen(capt );
+
+ XSetWMName (x_display ,x_window ,@x_tp );
+ XStoreName (x_display ,x_window ,capt );
+ XSetIconName (x_display ,x_window ,capt );
+ XSetWMIconName(x_display ,x_window ,@x_tp );
+
+ XMapWindow (x_display ,x_window );
+ XSelectInput(x_display ,x_window ,x_event_mask );
+
+ x_close:=
+ XInternAtom(x_display ,'WM_DELETE_WINDOW' ,false );
+
+ XSetWMProtocols(
+ x_display ,
+ x_window ,
+ @x_close ,1 );
+
+ XFlush(x_display );
+
+ repeat
+ XNextEvent(x_display ,@x_event );
+
+ XFlush(x_display );
+ XSync (x_display ,true );
+
+ case x_event._type of
+ Expose :
+ draw_text;
+
+ KeyPress :
+ break;
+
+ ClientMessage :
+ if (x_event.xclient.format = 32 ) and
+ (x_event.xclient.data.l[0 ] = int(x_close ) ) then
+ break;
+
+ end;
+
+
+ until false;
+
+ while XPending(x_display ) > 0 do
+ begin
+ XNextEvent(x_display ,@x_event );
+
+ XFlush(x_display );
+ XSync (x_display ,true );
+
+ end;
+
+ XFreeGC (x_display ,x_gc );
+ XDestroyWindow(x_display ,x_window );
+ XCloseDisplay (x_display );
+
+ end
+ else
+ writeln(stderr ,msg );
+
+end;
+
+{ START_TIMER }
+procedure platform_support.start_timer;
+begin
+ m_specific.m_sw_start:=clock;
+
+end;
+
+{ ELAPSED_TIME }
+function platform_support.elapsed_time;
+var
+ stop : clock_t;
+
+begin
+ stop:=clock;
+
+ result:=(stop - m_specific.m_sw_start ) * 1000.0 / CLOCKS_PER_SEC;
+
+end;
+
+{ FULL_FILE_NAME }
+function platform_support.full_file_name;
+begin
+ result:=file_name;
+
+end;
+
+{ FILE_SOURCE }
+function platform_support.file_source;
+var
+ f : file;
+ e : integer;
+
+begin
+ result:=fname;
+
+ e:=ioresult;
+
+ AssignFile(f ,result );
+ reset (f ,1 );
+
+ if ioresult <> 0 then
+ result:=path + '/' + fname;
+
+ close(f );
+
+ e:=ioresult;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/platform/linux/file_utils_.pas b/src/corelib/render/software/platform/linux/file_utils_.pas
new file mode 100644
index 00000000..ddb08187
--- /dev/null
+++ b/src/corelib/render/software/platform/linux/file_utils_.pas
@@ -0,0 +1,776 @@
+//
+// AggPas 2.4 RM3 demo framework file utility library
+// Milan Marusinec alias Milano (c) 2006
+//
+unit
+ file_utils_ ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+{$I- }
+uses
+ agg_basics ;
+
+{ TYPES DEFINITION }
+type
+ api_file_ptr = ^api_file;
+ api_file = record
+ fileName : shortstring;
+ isOpened : boolean;
+
+ fSize ,
+ fRead : int;
+
+ // FSOpenFork parameters
+ df : file;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+ function cut_str(s : shortstring ) : shortstring;
+ function up_str (s : shortstring ) : shortstring;
+ function cmp_str(s : shortstring ) : shortstring;
+
+ function str_dir(s : shortstring ) : shortstring;
+ function dir_str(s : shortstring ) : shortstring;
+
+ function str_disk(fn : shortstring ) : shortstring;
+ function str_path(fn : shortstring ) : shortstring;
+ function str_name(fn : shortstring ) : shortstring;
+ function str_ext (fn : shortstring ) : shortstring;
+
+ function fold_name (p ,n ,x : shortstring ) : shortstring;
+ procedure spread_name(fn : shortstring; var p ,n ,x : shortstring );
+
+ function file_exists(fn : shortstring ) : boolean;
+
+ function api_open_file (var af : api_file; fname : shortstring ) : boolean;
+ function api_read_file (var af : api_file; buff : pointer; aloc : int; var read : int ) : boolean;
+ function api_close_file(var af : api_file ) : boolean;
+
+ function param_count : int;
+ function param_str(i : int ) : shortstring;
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+type
+ tSCAN = (
+
+ SCAN_0 ,
+ SCAN_1 ,SCAN_2 ,SCAN_3 ,SCAN_4 ,SCAN_5 ,SCAN_6 ,SCAN_7 ,SCAN_8 ,SCAN_9 ,
+ SCAN_A ,SCAN_B ,SCAN_C ,SCAN_D ,SCAN_E ,SCAN_F ,SCAN_G ,SCAN_H ,SCAN_I ,
+ SCAN_J ,SCAN_K ,SCAN_L ,SCAN_M ,SCAN_N ,SCAN_O ,SCAN_P ,SCAN_Q ,SCAN_R ,
+ SCAN_S ,SCAN_T ,SCAN_U ,SCAN_V ,SCAN_W ,SCAN_X ,SCAN_Y ,SCAN_Z
+
+ );
+
+ tITEM = (
+
+ ITEM_0 ,
+ ITEM_1 ,ITEM_2 ,ITEM_3 ,ITEM_4 ,ITEM_5 ,ITEM_6 ,ITEM_7 ,ITEM_8 ,ITEM_9 ,
+ ITEM_A ,ITEM_B ,ITEM_C ,ITEM_D ,ITEM_E ,ITEM_F ,ITEM_G ,ITEM_H ,ITEM_I ,
+ ITEM_J ,ITEM_K ,ITEM_L ,ITEM_M ,ITEM_N ,ITEM_O ,ITEM_P ,ITEM_Q ,ITEM_R ,
+ ITEM_S ,ITEM_T ,ITEM_U ,ITEM_V ,ITEM_W ,ITEM_X ,ITEM_Y ,ITEM_Z
+
+ );
+
+const
+ dir_slash = '/';
+
+ pageEqHigh : shortstring =
+ #1#2#3#4#5#6#7#8#9#10#11#12#13#14#15#16 +
+ #17#18#19#20#21#22#23#24#25#26#27#28#29#30#31#32 +
+ #33#34#35#36#37#38#39#40#41#42#43#44#45#46#47#48 +
+ #49#50#51#52#53#54#55#56#57#58#59#60#61#62#63#64 +
+ #65#66#67#68#69#70#71#72#73#74#75#76#77#78#79#80 +
+ #81#82#83#84#85#86#87#88#89#90#91#92#93#94#95#96 +
+ #65#66#67#68#69#70#71#72#73#74#75#76#77#78#79#80 +
+ #81#82#83#84#85#86#87#88#89#90#123#124#125#126#127#128 +
+ #129#130#131#132#133#134#135#136#137#138#139#140#141#142#143#144 +
+ #145#146#147#148#149#150#151#152#153#154#155#156#157#158#159#160 +
+ #161#162#163#164#165#166#167#168#169#170#171#172#173#174#175#176 +
+ #177#178#179#180#181#182#183#184#185#186#187#188#189#190#191#192 +
+ #193#194#195#196#197#198#199#200#201#202#203#204#205#206#207#208 +
+ #209#210#211#212#213#214#215#216#217#218#219#220#221#222#223#224 +
+ #225#226#227#228#229#230#231#232#233#234#235#236#237#238#239#240 +
+ #241#242#243#244#245#246#247#248#249#250#251#252#253#254#255;
+
+{ UNIT IMPLEMENTATION }
+{ CUT_STR }
+function cut_str;
+var
+ fcb : byte;
+ scn : tSCAN;
+
+begin
+ result:='';
+
+ scn:=SCAN_1;
+
+ if length(s ) > 0 then
+ for fcb:=length(s ) downto 1 do
+ case scn of
+ SCAN_1 :
+ case s[fcb ] of
+ ' ' :
+ else
+ begin
+ result:=s[fcb ];
+
+ scn:=SCAN_2;
+
+ end;
+
+ end;
+
+ SCAN_2 :
+ result:=s[fcb ] + result;
+
+ end;
+
+end;
+
+{ CMP_STR }
+function cmp_str;
+begin
+ cmp_str:=up_str(cut_str(s ) );
+
+end;
+
+{ UP_STR }
+function up_str;
+var
+ fcb : byte;
+
+begin
+ if length(s ) > 0 then
+ for fcb:=1 to length(s ) do
+ if byte(s[fcb ] ) > 0 then
+ s[fcb ]:=pageEqHigh[byte(s[fcb ] ) ];
+
+ result:=s;
+
+end;
+
+{ STR_DIR }
+function str_dir;
+begin
+ s:=cut_str(s );
+
+ if length(s ) > 0 then
+ if s[length(s ) ] <> dir_slash then
+ s:=s + dir_slash;
+
+ result:=s;
+
+end;
+
+{ DIR_STR }
+function dir_str;
+begin
+ s:=cut_str(s );
+
+ if length(s ) > 0 then
+ if s[length(s ) ] = dir_slash then
+ dec(byte(s[0 ] ) );
+
+ result:=s;
+
+end;
+
+{ STR_DISK }
+function str_disk;
+var
+ fcb : byte;
+ str : shortstring;
+ itm : tITEM;
+
+begin
+ str:='';
+ itm:=ITEM_1;
+
+ if length(fn ) > 0 then
+ for fcb:=1 to length(fn ) do
+ case itm of
+ ITEM_1 :
+ case fn[fcb ] of
+ 'a'..'z' ,'A'..'Z' :
+ begin
+ str:=fn[fcb ];
+ itm:=ITEM_2;
+
+ end;
+
+ '\' ,'/' :
+ begin
+ str:=fn[fcb ];
+ itm:=ITEM_3;
+
+ end;
+
+ else
+ break;
+
+ end;
+
+ ITEM_2 :
+ case fn[fcb ] of
+ ':' :
+ begin
+ str:=str + fn[fcb ];
+ itm:=ITEM_F;
+
+ break;
+
+ end;
+
+ else
+ break;
+
+ end;
+
+ ITEM_3 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ str:=str + fn[fcb ];
+ itm:=ITEM_4;
+
+ end;
+
+ else
+ break;
+
+ end;
+
+ ITEM_4 :
+ case fn[fcb ] of
+ '\' ,'/' ,':' ,'<' ,'>' ,'.' ,'"' ,'|' ,#0..#31 :
+ break;
+
+ else
+ begin
+ str:=str + fn[fcb ];
+ itm:=ITEM_F;
+
+ end;
+
+ end;
+
+ ITEM_F :
+ case fn[fcb ] of
+ '\' ,'/' :
+ break;
+
+ else
+ str:=str + fn[fcb ];
+
+ end;
+
+ end;
+
+ if itm = ITEM_F then
+ result:=str
+ else
+ result:='';
+
+end;
+
+{ STR_PATH }
+function str_path;
+var
+ fcb : byte;
+ pth ,
+ str : shortstring;
+ itm : tITEM;
+
+begin
+ pth:='';
+ str:='';
+ itm:=ITEM_1;
+
+ if length(fn ) > 0 then
+ for fcb:=1 to length(fn ) do
+ case itm of
+ ITEM_1 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ str:=fn[fcb ];
+ itm:=ITEM_2;
+
+ end;
+
+ else
+ begin
+ str:=fn[fcb ];
+ itm:=ITEM_3;
+
+ end;
+
+ end;
+
+ ITEM_2 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ str:=str + fn[fcb ];
+ itm:=ITEM_3;
+
+ end;
+
+ else
+ begin
+ pth:=str;
+ str:=fn[fcb ];
+ itm:=ITEM_A;
+
+ end;
+
+ end;
+
+ ITEM_3 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ pth:=fn[fcb ];
+ str:='';
+ itm:=ITEM_A;
+
+ end;
+
+ else
+ str:=str + fn[fcb ];
+
+ end;
+
+ ITEM_A :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ pth:=pth + str + fn[fcb ];
+ str:='';
+
+ end;
+
+ else
+ str:=str + fn[fcb ];
+
+ end;
+
+ end;
+
+ result:=pth;
+
+end;
+
+{ STR_NAME }
+function str_name;
+var
+ fcb : byte;
+ str ,
+ ext : shortstring;
+ itm : tITEM;
+
+begin
+ str:='';
+ ext:='';
+ itm:=ITEM_1;
+
+ if length(fn ) > 0 then
+ for fcb:=1 to length(fn ) do
+ case itm of
+ ITEM_1 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ itm:=ITEM_2;
+
+ 'a'..'z' ,'A'..'Z' :
+ begin
+ ext:=fn[fcb ];
+ itm:=ITEM_4;
+
+ end;
+
+ '.' :
+ begin
+ str:='';
+ ext:=fn[fcb ];
+ itm:=ITEM_B;
+
+ end;
+
+ else
+ begin
+ str:=fn[fcb ];
+ itm:=ITEM_A;
+
+ end;
+
+ end;
+
+ ITEM_2 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ itm:=ITEM_3;
+
+ '.' :
+ begin
+ str:='';
+ ext:=fn[fcb ];
+ itm:=ITEM_B;
+
+ end;
+
+ else
+ begin
+ str:=fn[fcb ];
+ itm:=ITEM_A;
+
+ end;
+
+ end;
+
+ ITEM_3 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ str:='';
+ itm:=ITEM_A;
+
+ end;
+
+ end;
+
+ ITEM_4 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ str:='';
+ itm:=ITEM_A;
+
+ end;
+
+ ':' :
+ itm:=ITEM_5;
+
+ '.' :
+ begin
+ str:=ext;
+ ext:=fn[fcb ];
+ itm:=ITEM_B;
+
+ end;
+
+ else
+ begin
+ str:=ext + fn[fcb ];
+ ext:='';
+ itm:=ITEM_A;
+
+ end;
+
+ end;
+
+ ITEM_5 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ str:='';
+ itm:=ITEM_A;
+
+ end;
+
+ '.' :
+ begin
+ str:='';
+ ext:=fn[fcb ];
+ itm:=ITEM_B;
+
+ end;
+
+ else
+ begin
+ str:=fn[fcb ];
+ itm:=ITEM_A;
+
+ end;
+
+ end;
+
+ ITEM_A :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ str:='';
+ ext:='';
+
+ end;
+
+ '.' :
+ begin
+ ext:=fn[fcb ];
+ itm:=ITEM_B;
+
+ end;
+
+ else
+ str:=str + fn[fcb ];
+
+ end;
+
+ ITEM_B :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ str:='';
+ ext:='';
+ itm:=ITEM_A;
+
+ end;
+
+ '.' :
+ begin
+ str:=str + ext;
+ ext:=fn[fcb ];
+
+ end;
+
+ end;
+
+ end;
+
+ result:=str;
+
+end;
+
+{ STR_EXT }
+function str_ext;
+var
+ fcb : byte;
+ ext : shortstring;
+ itm : tITEM;
+
+begin
+ ext:='';
+ itm:=ITEM_1;
+
+ if length(fn ) > 0 then
+ for fcb:=1 to length(fn ) do
+ case itm of
+ ITEM_1 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ itm:=ITEM_2;
+
+ '.' :
+ begin
+ ext:=fn[fcb ];
+ itm:=ITEM_B;
+
+ end;
+
+ else
+ itm:=ITEM_A;
+
+ end;
+
+ ITEM_2 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ itm:=ITEM_3;
+
+ '.' :
+ begin
+ ext:=fn[fcb ];
+ itm:=ITEM_B;
+
+ end;
+
+ else
+ itm:=ITEM_A;
+
+ end;
+
+ ITEM_3 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ itm:=ITEM_A;
+
+ end;
+
+ ITEM_A :
+ case fn[fcb ] of
+ '.' :
+ begin
+ ext:=fn[fcb ];
+ itm:=ITEM_B;
+
+ end;
+
+ end;
+
+ ITEM_B :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ ext:='';
+ itm:=ITEM_A;
+
+ end;
+
+ '.' :
+ ext:=fn[fcb ];
+
+ else
+ ext:=ext + fn[fcb ];
+
+ end;
+
+ end;
+
+ result:=cut_str(ext );
+
+ if result = '.' then
+ result:='';
+
+end;
+
+{ FOLD_NAME }
+function fold_name;
+var
+ dsk ,
+ nme ,
+ pth ,
+ ext : shortstring;
+
+begin
+ dsk:=str_disk(p );
+ pth:=str_dir (str_path(p ) );
+ nme:=str_name(n );
+ ext:=str_ext (x );
+
+ result:=dsk + pth + nme + ext;
+
+end;
+
+{ SPREAD_NAME }
+procedure spread_name;
+begin
+ p:=str_disk(fn ) + str_dir(str_path(fn ) );
+ n:=str_name(fn );
+ x:=str_ext (fn );
+
+end;
+
+{ FILE_EXISTS }
+function file_exists;
+var
+ f : file;
+
+begin
+ AssignFile(f ,fn );
+ reset (f );
+
+ if IOResult = 0 then
+ begin
+ close(f );
+
+ result:=true;
+
+ end
+ else
+ result:=false;
+
+end;
+
+{ API_OPEN_FILE }
+function api_open_file;
+begin
+ result:=false;
+
+ fillchar(af ,sizeof(api_file ) ,0 );
+
+ af.fileName:=fname;
+ af.isOpened:=false;
+
+ IOResult;
+
+ AssignFile(af.df ,fname );
+ reset (af.df ,1 );
+
+ if IOResult = 0 then
+ begin
+ af.isOpened:=true;
+
+ af.fSize:=filesize(af.df );
+ af.fRead:=0;
+
+ end;
+
+ result:=af.isOpened;
+
+end;
+
+{ API_READ_FILE }
+function api_read_file;
+begin
+ result:=false;
+ read :=0;
+
+ if af.isOpened then
+ begin
+ if aloc > af.fSize - af.fRead then
+ aloc:=af.fSize - af.fRead;
+
+ blockread(af.df ,buff^ ,aloc ,read );
+
+ if aloc = read then
+ begin
+ inc(af.fRead ,read );
+
+ result:=true;
+
+ end
+ else
+ read:=0;
+
+ end;
+
+end;
+
+{ API_CLOSE_FILE }
+function api_close_file;
+begin
+ result:=false;
+
+ if af.isOpened then
+ begin
+ system.close(af.df );
+
+ af.isOpened:=false;
+
+ result:=true;
+
+ end;
+
+end;
+
+{ PARAM_COUNT }
+function param_count;
+begin
+ result:=ParamCount;
+
+end;
+
+{ PARAM_STR }
+function param_str;
+begin
+ result:=ParamStr(i );
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/platform/mac/agg_mac_pmap.pas b/src/corelib/render/software/platform/mac/agg_mac_pmap.pas
new file mode 100644
index 00000000..7e5ad44e
--- /dev/null
+++ b/src/corelib/render/software/platform/mac/agg_mac_pmap.pas
@@ -0,0 +1,471 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+// Copyright (C) 2002 Hansruedi Baer (MacOS support)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+// baer@karto.baug.eth.ch
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 24.03.2006-Milano: Finished MacOS port
+// 20.03.2006-Milano: Unit port establishment
+//
+{ agg_mac_pmap.pas }
+unit
+ agg_mac_pmap ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ QuickTimeComponents ,ImageCompression ,Carbon ,
+ agg_basics ;
+
+{ TYPES DEFINITION }
+const
+ org_mono8 = 8;
+ org_color16 = 16;
+ org_color24 = 24;
+ org_color32 = 32;
+
+type
+ pixel_map = object
+ m_pmap : ^CGrafPort;
+ m_buf : pointer;
+
+ m_bpp ,
+ m_img_size : unsigned;
+
+ constructor Construct;
+ destructor Destruct;
+
+ procedure destroy;
+ procedure create(width ,height ,org : unsigned; clear_val : unsigned = 255 );
+ procedure clear (clear_val : unsigned = 255 );
+
+ function load_from_qt(filename : shortstring ) : boolean;
+ function save_as_qt (filename : shortstring ) : boolean;
+
+ procedure draw(window : WindowRef; device_rect : RectPtr = NIL; bmp_rect : RectPtr = NIL ); overload;
+ procedure draw(window : WindowRef; x ,y : int; scale : double = 1.0 ); overload;
+
+ procedure blend(window : WindowRef; device_rect : RectPtr = NIL; bmp_rect : RectPtr = NIL ); overload;
+ procedure blend(window : WindowRef; x ,y : int; scale : double = 1.0 ); overload;
+
+ function _buf : pointer;
+ function _width : unsigned;
+ function _height : unsigned;
+ function _row_bytes : int;
+ function _bpp : unsigned;
+
+ //Auxiliary static functions
+ function calc_row_len(width ,bits_per_pixel : unsigned ) : unsigned;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor pixel_map.Construct;
+begin
+ m_pmap:=NIL;
+ m_buf :=NIL;
+ m_bpp :=0;
+
+ m_img_size:=0;
+
+end;
+
+{ DESTRUCT }
+destructor pixel_map.Destruct;
+begin
+ destroy;
+
+end;
+
+{ DESTROY }
+procedure pixel_map.destroy;
+begin
+ agg_freemem(m_buf ,m_img_size );
+
+ m_buf:=NIL;
+
+ if m_pmap <> NIL then
+ begin
+ DisposeGWorld(GrafPtr(m_pmap ) );
+
+ m_pmap:=NIL;
+
+ end;
+
+end;
+
+{ CREATE }
+procedure pixel_map.create;
+var
+ r : Carbon.Rect;
+
+ row_bytes : int;
+
+begin
+ destroy;
+
+ if width = 0 then
+ width:=1;
+
+ if height = 0 then
+ height:=1;
+
+ m_bpp :=org;
+ row_bytes:=calc_row_len(width ,m_bpp );
+
+ SetRect(r ,0 ,0 ,width ,height );
+
+ m_img_size:=row_bytes * height;
+
+ agg_getmem(m_buf ,m_img_size );
+
+// The Quicktime version for creating GWorlds is more flexible than the classical function.
+ QTNewGWorldFromPtr(m_pmap ,m_bpp ,ImageCompression.Rect(r ) ,NIL ,NIL ,0 ,m_buf ,row_bytes );
+
+// create_gray_scale_palette(m_pmap); I didn't care about gray scale palettes so far.
+ if clear_val <= 255 then
+ fillchar(m_buf^ ,m_img_size ,clear_val );
+
+end;
+
+{ CLEAR }
+procedure pixel_map.clear;
+begin
+ if m_buf <> NIL then
+ fillchar(m_buf^ ,m_img_size ,clear_val );
+
+end;
+
+{ LOAD_FROM_QT }
+function pixel_map.load_from_qt;
+var
+ fss : FSSpec;
+ err : OSErr;
+ gi : GraphicsImportComponent;
+ buf : int8u_ptr;
+
+ desc : ImageDescriptionHandle;
+ depth : int16;
+ size : unsigned;
+
+begin
+// get file specification to application directory
+ err:=HGetVol(NIL ,fss.vRefNum ,fss.parID );
+
+ if err = noErr then
+ begin
+ // CopyCStringToPascal(filename ,fss.name );
+ fss.name:=filename;
+
+ err:=GetGraphicsImporterForFile(ImageCompression.FSSpec(fss ) ,gi );
+
+ if err = noErr then
+ begin
+ GraphicsImportGetImageDescription(gi ,desc );
+
+ // For simplicity, all images are currently converted to 32 bit.
+ // create an empty pixelmap
+ depth:=24;
+
+ create (desc^.width ,desc^.height ,depth ,$ff );
+ DisposeHandle(Handle(desc ) );
+
+ // let Quicktime draw to pixelmap
+ GraphicsImportSetGWorld(gi ,m_pmap ,NIL );
+ GraphicsImportDraw (gi );
+
+ end;
+
+ end;
+
+ result:=err = noErr;
+
+end;
+
+{ SAVE_AS_QT }
+function pixel_map.save_as_qt;
+var
+ fss : FSSpec;
+ err : OSErr;
+ ge : GraphicsExportComponent;
+ cnt : UInt32;
+
+begin
+// get file specification to application directory
+ err:=HGetVol(NIL ,fss.vRefNum ,fss.parID );
+
+ if err = noErr then
+ begin
+ // CopyCStringToPascal(filename ,fss.name );
+ fss.name:=filename;
+
+ // I decided to use PNG as output image file type.
+ // There are a number of other available formats.
+ // Should I check the file suffix to choose the image file format?
+ err:=
+ OpenADefaultComponent(
+ LongWord(int32_ptr(@GraphicsExporterComponentType[1 ] )^ ) ,
+ LongWord(int32_ptr(@kQTFileTypePNG[1 ] )^ ) ,
+ Carbon.ComponentInstance(ge ) );
+
+ if err = noErr then
+ begin
+ err:=GraphicsExportSetInputGWorld(ge ,m_pmap );
+
+ if err = noErr then
+ begin
+ err:=GraphicsExportSetOutputFile(ge ,ImageCompression.FSSpec(fss ) );
+ cnt:=0;
+
+ if err = noErr then
+ GraphicsExportDoExport(ge ,cnt );
+
+ end;
+
+ CloseComponent(Carbon.ComponentInstance(ge ) );
+
+ end;
+
+ end;
+
+ result:=err = noErr;
+
+end;
+
+{ DRAW }
+procedure pixel_map.draw(window : WindowRef; device_rect : RectPtr = NIL; bmp_rect : RectPtr = NIL );
+var
+ pm : PixMapHandle;
+ port : CGrafPtr;
+
+ src_rect ,dest_rect : Carbon.Rect;
+
+ image_description : ImageDescriptionHandle;
+
+begin
+ if (m_pmap = NIL ) or
+ (m_buf = NIL ) then
+ exit;
+
+ pm :=GetGWorldPixMap(GrafPtr(m_pmap ) );
+ port:=GetWindowPort (window );
+
+// Again, I used the Quicktime version.
+// Good old 'CopyBits' does better interpolation when scaling
+// but does not support all pixel depths.
+ SetRect(dest_rect ,0 ,0 ,_width ,_height );
+
+ MakeImageDescriptionForPixMap(ImageCompression.PixMapHandle(pm ) ,image_description );
+
+ if image_description <> NIL then
+ begin
+ SetRect(src_rect ,0 ,0 ,image_description^.width ,image_description^.height );
+
+ DecompressImage(
+ GetPixBaseAddr(pm ) ,
+ image_description ,
+ ImageCompression.PixMapHandle(GetPortPixMap(port ) ) ,
+ ImageCompression.Rect(src_rect ) ,
+ ImageCompression.Rect(dest_rect ) ,
+ ditherCopy ,NIL );
+
+ DisposeHandle(Handle(image_description ) );
+
+ end;
+
+end;
+
+{ DRAW }
+procedure pixel_map.draw(window : WindowRef; x ,y : int; scale : double = 1.0 );
+var
+ width ,height : unsigned;
+
+ r : Carbon.Rect;
+
+begin
+ if (m_pmap = NIL ) or
+ (m_buf = NIL ) then
+ exit;
+
+ width :=System.Trunc(_width * scale );
+ height:=System.Trunc(_height * scale );
+
+ SetRect(r ,x ,y ,x + width ,y + height );
+ draw (window ,@r );
+
+end;
+
+{ BLEND }
+procedure pixel_map.blend(window : WindowRef; device_rect : RectPtr = NIL; bmp_rect : RectPtr = NIL );
+begin
+ draw(window ,device_rect ,bmp_rect ); // currently just mapped to drawing method
+
+end;
+
+{ BLEND }
+procedure pixel_map.blend(window : WindowRef; x ,y : int; scale : double = 1.0 );
+begin
+ draw(window ,x ,y ,scale ); // currently just mapped to drawing method
+
+end;
+
+{ _BUF }
+function pixel_map._buf;
+begin
+ result:=m_buf;
+
+end;
+
+{ _WIDTH }
+function pixel_map._width;
+var
+ pm : PixMapHandle;
+
+ bounds : Carbon.Rect;
+
+begin
+ if m_pmap = NIL then
+ begin
+ result:=0;
+
+ exit;
+
+ end;
+
+ pm:=GetGWorldPixMap(GrafPtr(m_pmap ) );
+
+ GetPixBounds(pm ,bounds );
+
+ result:=bounds.right - bounds.left;
+
+end;
+
+{ _HEIGHT }
+function pixel_map._height;
+var
+ pm : PixMapHandle;
+
+ bounds : Carbon.Rect;
+
+begin
+ if m_pmap = NIL then
+ begin
+ result:=0;
+
+ exit;
+
+ end;
+
+ pm:=GetGWorldPixMap(GrafPtr(m_pmap ) );
+
+ GetPixBounds(pm ,bounds );
+
+ result:=bounds.bottom - bounds.top;
+
+end;
+
+{ _ROW_BYTES }
+function pixel_map._row_bytes;
+var
+ pm : PixMapHandle;
+
+begin
+ if m_pmap = NIL then
+ begin
+ result:=0;
+
+ exit;
+
+ end;
+
+ pm:=GetGWorldPixMap(GrafPtr(m_pmap ) );
+
+ result:=calc_row_len(_width ,GetPixDepth(pm ) );
+
+end;
+
+{ _BPP }
+function pixel_map._bpp;
+begin
+ result:=m_bpp;
+
+end;
+
+{ CALC_ROW_LEN }
+function pixel_map.calc_row_len;
+var
+ n ,k : unsigned;
+
+begin
+ n:=width;
+
+ case bits_per_pixel of
+ 1 :
+ begin
+ k:=n;
+ n:=n shr 3;
+
+ if k and 7 <> 0 then
+ inc(n );
+
+ end;
+
+ 4 :
+ begin
+ k:=n;
+ n:=n shr 1;
+
+ if k and 3 <> 0 then
+ inc(n );
+
+ end;
+
+ 8 :
+ NoP;
+
+ 16 :
+ n:=n shl 1;
+
+ 24 :
+ n:=(n shl 1 ) + n;
+
+ 32 :
+ n:=n shl 2;
+
+ else
+ n:=0;
+
+ end;
+
+ result:=((n + 3 ) shr 2 ) shl 2;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/platform/mac/agg_platform_support.pas b/src/corelib/render/software/platform/mac/agg_platform_support.pas
new file mode 100644
index 00000000..9fc3fd20
--- /dev/null
+++ b/src/corelib/render/software/platform/mac/agg_platform_support.pas
@@ -0,0 +1,2212 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+// Copyright (C) 2003 Hansruedi Baer (MacOS support)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+// baer@karto.baug.eth.ch
+//
+//----------------------------------------------------------------------------
+//
+// Note:
+// I tried to retain the original structure for the Win32 platform as far
+// as possible. Currently, not all features are implemented but the examples
+// should work properly.
+// HB
+//
+//----------------------------------------------------------------------------
+//
+// class platform_support
+//
+// It's not a part of the AGG library, it's just a helper class to create
+// interactive demo examples. Since the examples should not be too complex
+// this class is provided to support some very basic interactive graphical
+// funtionality, such as putting the rendered image to the window, simple
+// keyboard and mouse input, window resizing, setting the window title,
+// and catching the "idle" events.
+//
+// The most popular platforms are:
+//
+// Windows-32 API
+// X-Window API
+// SDL library (see http://www.libsdl.org/)
+// MacOS C/C++ API
+//
+// All the system dependent stuff sits in the platform_specific class.
+// The platform_support class has just a pointer to it and it's
+// the responsibility of the implementation to create/delete it.
+// This class being defined in the implementation file can have
+// any platform dependent stuff such as HWND, X11 Window and so on.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 26.03.2006-Milano: Finished & tested MacOS X port
+// 20.03.2006-Milano: Unit port establishment
+//
+{ agg_platform_support.pas }
+unit
+ agg_platform_support ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ Carbon ,
+ agg_basics ,
+ agg_ctrl ,
+ agg_rendering_buffer ,
+ agg_trans_affine ,
+ agg_trans_viewport ,
+ agg_mac_pmap ,
+ agg_color_conv ;
+
+{ TYPES DEFINITION }
+const
+//----------------------------------------------------------window_flag_e
+// These are flags used in method init(). Not all of them are
+// applicable on different platforms, for example the win32_api
+// cannot use a hardware buffer (window_hw_buffer).
+// The implementation should simply ignore unsupported flags.
+ window_resize = 1;
+ window_hw_buffer = 2;
+ window_keep_aspect_ratio = 4;
+ window_process_all_keys = 8;
+
+type
+//-----------------------------------------------------------pix_format_e
+// Possible formats of the rendering buffer. Initially I thought that it's
+// reasonable to create the buffer and the rendering functions in
+// accordance with the native pixel format of the system because it
+// would have no overhead for pixel format conersion.
+// But eventually I came to a conclusion that having a possibility to
+// convert pixel formats on demand is a good idea. First, it was X11 where
+// there lots of different formats and visuals and it would be great to
+// render everything in, say, RGB-24 and display it automatically without
+// any additional efforts. The second reason is to have a possibility to
+// debug renderers for different pixel formats and colorspaces having only
+// one computer and one system.
+//
+// This stuff is not included into the basic AGG functionality because the
+// number of supported pixel formats (and/or colorspaces) can be great and
+// if one needs to add new format it would be good only to add new
+// rendering files without having to modify any existing ones (a general
+// principle of incapsulation and isolation).
+//
+// Using a particular pixel format doesn't obligatory mean the necessity
+// of software conversion. For example, win32 API can natively display
+// gray8, 15-bit RGB, 24-bit BGR, and 32-bit BGRA formats.
+// This list can be (and will be!) extended in future.
+ pix_format_e = (
+
+ pix_format_undefined , // By default. No conversions are applied
+ pix_format_bw, // 1 bit per color B/W
+ pix_format_gray8, // Simple 256 level grayscale
+ pix_format_gray16, // Simple 65535 level grayscale
+ pix_format_rgb555, // 15 bit rgb. Depends on the byte ordering!
+ pix_format_rgb565, // 16 bit rgb. Depends on the byte ordering!
+ pix_format_rgbAAA, // 30 bit rgb. Depends on the byte ordering!
+ pix_format_rgbBBA, // 32 bit rgb. Depends on the byte ordering!
+ pix_format_bgrAAA, // 30 bit bgr. Depends on the byte ordering!
+ pix_format_bgrABB, // 32 bit bgr. Depends on the byte ordering!
+ pix_format_rgb24, // R-G-B, one byte per color component
+ pix_format_bgr24, // B-G-R, native win32 BMP format.
+ pix_format_rgba32, // R-G-B-A, one byte per color component
+ pix_format_argb32, // A-R-G-B, native MAC format
+ pix_format_abgr32, // A-B-G-R, one byte per color component
+ pix_format_bgra32, // B-G-R-A, native win32 BMP format
+ pix_format_rgb48, // R-G-B, 16 bits per color component
+ pix_format_bgr48, // B-G-R, native win32 BMP format.
+ pix_format_rgba64, // R-G-B-A, 16 bits byte per color component
+ pix_format_argb64, // A-R-G-B, native MAC format
+ pix_format_abgr64, // A-B-G-R, one byte per color component
+ pix_format_bgra64, // B-G-R-A, native win32 BMP format
+
+ end_of_pix_formats );
+
+const
+//-------------------------------------------------------------input_flag_e
+// Mouse and keyboard flags. They can be different on different platforms
+// and the ways they are obtained are also different. But in any case
+// the system dependent flags should be mapped into these ones. The meaning
+// of that is as follows. For example, if kbd_ctrl is set it means that the
+// ctrl key is pressed and being held at the moment. They are also used in
+// the overridden methods such as on_mouse_move(), on_mouse_button_down(),
+// on_mouse_button_dbl_click(), on_mouse_button_up(), on_key().
+// In the method on_mouse_button_up() the mouse flags have different
+// meaning. They mean that the respective button is being released, but
+// the meaning of the keyboard flags remains the same.
+// There's absolut minimal set of flags is used because they'll be most
+// probably supported on different platforms. Even the mouse_right flag
+// is restricted because Mac's mice have only one button, but AFAIK
+// it can be simulated with holding a special key on the keydoard.
+ mouse_left = 1;
+ mouse_right = 2;
+ kbd_shift = 4;
+ kbd_ctrl = 8;
+
+//--------------------------------------------------------------key_code_e
+// Keyboard codes. There's also a restricted set of codes that are most
+// probably supported on different platforms. Any platform dependent codes
+// should be converted into these ones. There're only those codes are
+// defined that cannot be represented as printable ASCII-characters.
+// All printable ASCII-set can be used in a regilar C/C++ manner:
+// ' ', 'A', '0' '+' and so on.
+// Since the clasas is used for creating very simple demo-applications
+// we don't need very rich possibilities here, just basic ones.
+// Actually the numeric key codes are taken from the SDL library, so,
+// the implementation of the SDL support does not require any mapping.
+// ASCII set. Should be supported everywhere
+ key_backspace = 8;
+ key_tab = 9;
+ key_clear = 12;
+ key_return = 13;
+ key_pause = 19;
+ key_escape = 27;
+
+// Keypad
+ key_delete = 127;
+ key_kp0 = 256;
+ key_kp1 = 257;
+ key_kp2 = 258;
+ key_kp3 = 259;
+ key_kp4 = 260;
+ key_kp5 = 261;
+ key_kp6 = 262;
+ key_kp7 = 263;
+ key_kp8 = 264;
+ key_kp9 = 265;
+ key_kp_period = 266;
+ key_kp_divide = 267;
+ key_kp_multiply = 268;
+ key_kp_minus = 269;
+ key_kp_plus = 270;
+ key_kp_enter = 271;
+ key_kp_equals = 272;
+
+// Arrow-keys and stuff
+ key_up = 273;
+ key_down = 274;
+ key_right = 275;
+ key_left = 276;
+ key_insert = 277;
+ key_home = 278;
+ key_end = 279;
+ key_page_up = 280;
+ key_page_down = 281;
+
+// Functional keys. You'd better avoid using
+// f11...f15 in your applications if you want
+// the applications to be portable
+ key_f1 = 282;
+ key_f2 = 283;
+ key_f3 = 284;
+ key_f4 = 285;
+ key_f5 = 286;
+ key_f6 = 287;
+ key_f7 = 288;
+ key_f8 = 289;
+ key_f9 = 290;
+ key_f10 = 291;
+ key_f11 = 292;
+ key_f12 = 293;
+ key_f13 = 294;
+ key_f14 = 295;
+ key_f15 = 296;
+
+// The possibility of using these keys is
+// very restricted. Actually it's guaranteed
+// only in win32_api and win32_sdl implementations
+ key_numlock = 300;
+ key_capslock = 301;
+ key_scrollock = 302;
+
+ max_ctrl = 128;
+
+type
+//----------------------------------------------------------ctrl_container
+// A helper class that contains pointers to a number of controls.
+// This class is used to ease the event handling with controls.
+// The implementation should simply call the appropriate methods
+// of this class when appropriate events occure.
+ crtl_container_ptr = ^ctrl_container;
+ ctrl_container = object
+ m_ctrl : array[0..max_ctrl - 1 ] of ctrl_ptr;
+
+ m_num_ctrl : unsigned;
+ m_cur_ctrl : int;
+
+ constructor Construct;
+ destructor Destruct;
+
+ procedure add(c : ctrl_ptr );
+
+ function in_rect(x ,y : double ) : boolean;
+
+ function on_mouse_button_down(x ,y : double ) : boolean;
+ function on_mouse_button_up (x ,y : double ) : boolean;
+
+ function on_mouse_move(x ,y : double; button_flag : boolean ) : boolean;
+ function on_arrow_keys(left ,right ,down ,up : boolean ) : boolean;
+
+ function set_cur(x ,y : double ) : boolean;
+
+ end;
+
+//---------------------------------------------------------platform_support
+// This class is a base one to the apllication classes. It can be used
+// as follows:
+//
+// the_application = object(platform_support )
+//
+// constructor Construct(bpp : unsigned; flip_y : boolean );
+// . . .
+//
+// //override stuff . . .
+// procedure on_init; virtual;
+// procedure on_draw; virtual;
+// procedure on_resize(sx ,sy : int ); virtual;
+// // . . . and so on, see virtual functions
+//
+// //any your own stuff . . .
+// };
+//
+// VAR
+// app : the_application;
+//
+// BEGIN
+// app.Construct(pix_format_rgb24 ,true );
+// app.caption ("AGG Example. Lion" );
+//
+// if app.init(500 ,400 ,window_resize ) then
+// app.run;
+//
+// app.Destruct;
+//
+// END.
+//
+const
+ max_images = 16;
+
+type
+ platform_specific_ptr = ^platform_specific;
+ platform_specific = object
+ m_format ,
+ m_sys_format : pix_format_e;
+
+ m_flip_y : boolean;
+ m_bpp ,
+ m_sys_bpp : unsigned;
+ m_window : WindowRef;
+
+ m_pmap_window : pixel_map;
+ m_pmap_img : array[0..max_images - 1 ] of pixel_map;
+
+ m_keymap : array[0..255 ] of unsigned;
+
+ m_last_translated_key : unsigned;
+
+ m_cur_x ,
+ m_cur_y : int;
+
+ m_input_flags : unsigned;
+ m_redraw_flag : boolean;
+
+ m_sw_freq ,
+ m_sw_start : UnsignedWide;
+
+ constructor Construct(format : pix_format_e; flip_y : boolean );
+ destructor Destruct;
+
+ procedure create_pmap (width ,height : unsigned; wnd : rendering_buffer_ptr );
+ procedure display_pmap(window : WindowRef; src : rendering_buffer_ptr );
+
+ function load_pmap(fn : shortstring; idx : unsigned; dst : rendering_buffer_ptr ) : boolean;
+ function save_pmap(fn : shortstring; idx : unsigned; src : rendering_buffer_ptr ) : boolean;
+
+ function translate(keycode : unsigned ) : unsigned;
+
+ end;
+
+ platform_support_ptr = ^platform_support;
+ platform_support = object
+ m_specific : platform_specific_ptr;
+ m_ctrls : ctrl_container;
+
+ m_format : pix_format_e;
+
+ m_bpp : unsigned;
+
+ m_rbuf_window : rendering_buffer;
+ m_rbuf_img : array[0..max_images - 1 ] of rendering_buffer;
+
+ m_window_flags : unsigned;
+ m_wait_mode ,
+ m_flip_y : boolean; // flip_y - true if you want to have the Y-axis flipped vertically
+ m_caption : shortstring;
+ m_resize_mtx : trans_affine;
+
+ m_initial_width ,
+ m_initial_height : int;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ // Setting the windows caption (title). Should be able
+ // to be called at least before calling init().
+ // It's perfect if they can be called anytime.
+ procedure caption_(cap : shortstring );
+
+ // These 3 menthods handle working with images. The image
+ // formats are the simplest ones, such as .BMP in Windows or
+ // .ppm in Linux. In the applications the names of the files
+ // should not have any file extensions. Method load_img() can
+ // be called before init(), so, the application could be able
+ // to determine the initial size of the window depending on
+ // the size of the loaded image.
+ // The argument "idx" is the number of the image 0...max_images-1
+ function load_img (idx : unsigned; file_ : shortstring ) : boolean;
+ function save_img (idx : unsigned; file_ : shortstring ) : boolean;
+ function create_img(idx : unsigned; width_ : unsigned = 0; height_ : unsigned = 0 ) : boolean;
+
+ // init() and run(). See description before the class for details.
+ // The necessity of calling init() after creation is that it's
+ // impossible to call the overridden virtual function (on_init())
+ // from the constructor. On the other hand it's very useful to have
+ // some on_init() event handler when the window is created but
+ // not yet displayed. The rbuf_window() method (see below) is
+ // accessible from on_init().
+ function init(width_ ,height_ ,flags : unsigned ) : boolean;
+ function run : int;
+ procedure quit;
+
+ // The very same parameters that were used in the constructor
+ function _format : pix_format_e;
+ function _flip_y : boolean;
+ function _bpp : unsigned;
+
+ // The following provides a very simple mechanism of doing someting
+ // in background. It's not multitheading. When whait_mode is true
+ // the class waits for the events and it does not ever call on_idle().
+ // When it's false it calls on_idle() when the event queue is empty.
+ // The mode can be changed anytime. This mechanism is satisfactory
+ // for creation very simple animations.
+ function _wait_mode : boolean;
+ procedure wait_mode_(wait_mode : boolean );
+
+ // These two functions control updating of the window.
+ // force_redraw() is an analog of the Win32 InvalidateRect() function.
+ // Being called it sets a flag (or sends a message) which results
+ // in calling on_draw() and updating the content of the window
+ // when the next event cycle comes.
+ // update_window() results in just putting immediately the content
+ // of the currently rendered buffer to the window without calling
+ // on_draw().
+ procedure force_redraw;
+ procedure update_window;
+
+ // So, finally, how to draw anythig with AGG? Very simple.
+ // rbuf_window() returns a reference to the main rendering
+ // buffer which can be attached to any rendering class.
+ // rbuf_img() returns a reference to the previously created
+ // or loaded image buffer (see load_img()). The image buffers
+ // are not displayed directly, they should be copied to or
+ // combined somehow with the rbuf_window(). rbuf_window() is
+ // the only buffer that can be actually displayed.
+ function rbuf_window : rendering_buffer_ptr;
+ function rbuf_img(idx : unsigned ) : rendering_buffer_ptr;
+
+ // Returns file extension used in the implemenation for the particular
+ // system.
+ function _img_ext : shortstring;
+
+ //
+ procedure copy_img_to_window(idx : unsigned );
+ procedure copy_window_to_img(idx : unsigned );
+ procedure copy_img_to_img (idx_to ,idx_from : unsigned );
+
+ // Event handlers. They are not pure functions, so you don't have
+ // to override them all.
+ // In my demo applications these functions are defined inside
+ // the the_application class
+ procedure on_init; virtual;
+ procedure on_resize(sx ,sy : int ); virtual;
+ procedure on_idle; virtual;
+
+ procedure on_mouse_move(x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_up (x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+ procedure on_ctrl_change; virtual;
+ procedure on_draw; virtual;
+ procedure on_post_draw(raw_handler : pointer ); virtual;
+
+ // Adding control elements. A control element once added will be
+ // working and reacting to the mouse and keyboard events. Still, you
+ // will have to render them in the on_draw() using function
+ // render_ctrl() because platform_support doesn't know anything about
+ // renderers you use. The controls will be also scaled automatically
+ // if they provide a proper scaling mechanism (all the controls
+ // included into the basic AGG package do).
+ // If you don't need a particular control to be scaled automatically
+ // call ctrl::no_transform() after adding.
+ procedure add_ctrl(c : ctrl_ptr );
+
+ // Auxiliary functions. trans_affine_resizing() modifier sets up the resizing
+ // matrix on the basis of the given width and height and the initial
+ // width and height of the window. The implementation should simply
+ // call this function every time when it catches the resizing event
+ // passing in the new values of width and height of the window.
+ // Nothing prevents you from "cheating" the scaling matrix if you
+ // call this function from somewhere with wrong arguments.
+ // trans_affine_resizing() accessor simply returns current resizing matrix
+ // which can be used to apply additional scaling of any of your
+ // stuff when the window is being resized.
+ // width(), height(), initial_width(), and initial_height() must be
+ // clear to understand with no comments :-)
+ procedure trans_affine_resizing_(width_ ,height_ : int );
+ function _trans_affine_resizing : trans_affine_ptr;
+
+ function _width : double;
+ function _height : double;
+ function _initial_width : double;
+ function _initial_height : double;
+ function _window_flags : unsigned;
+
+ // Get raw display handler depending on the system.
+ // For win32 its an HDC, for other systems it can be a pointer to some
+ // structure. See the implementation files for detals.
+ // It's provided "as is", so, first you should check if it's not null.
+ // If it's null the raw_display_handler is not supported. Also, there's
+ // no guarantee that this function is implemented, so, in some
+ // implementations you may have simply an unresolved symbol when linking.
+ function _raw_display_handler : pointer;
+
+ // display message box or print the message to the console
+ // (depending on implementation)
+ procedure message_(msg : PChar );
+
+ // Stopwatch functions. Function elapsed_time() returns time elapsed
+ // since the latest start_timer() invocation in millisecods.
+ // The resolutoin depends on the implementation.
+ // In Win32 it uses QueryPerformanceFrequency() / QueryPerformanceCounter().
+ procedure start_timer;
+ function elapsed_time : double;
+
+ // Get the full file name. In most cases it simply returns
+ // file_name. As it's appropriate in many systems if you open
+ // a file by its name without specifying the path, it tries to
+ // open it in the current directory. The demos usually expect
+ // all the supplementary files to be placed in the current
+ // directory, that is usually coincides with the directory where
+ // the the executable is. However, in some systems (BeOS) it's not so.
+ // For those kinds of systems full_file_name() can help access files
+ // preserving commonly used policy.
+ // So, it's a good idea to use in the demos the following:
+ // FILE* fd = fopen(full_file_name("some.file"), "r");
+ // instead of
+ // FILE* fd = fopen("some.file", "r");
+ function full_file_name(file_name : shortstring ) : shortstring;
+ function file_source (path ,fname : shortstring ) : shortstring;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor ctrl_container.Construct;
+begin
+ m_num_ctrl:=0;
+ m_cur_ctrl:=-1;
+
+end;
+
+{ DESTRUCT }
+destructor ctrl_container.Destruct;
+begin
+end;
+
+{ ADD }
+procedure ctrl_container.add;
+begin
+ if m_num_ctrl < max_ctrl then
+ begin
+ m_ctrl[m_num_ctrl ]:=c;
+
+ inc(m_num_ctrl );
+
+ end;
+
+end;
+
+{ IN_RECT }
+function ctrl_container.in_rect;
+var
+ i : unsigned;
+
+begin
+ result:=false;
+
+ if m_num_ctrl > 0 then
+ for i:=0 to m_num_ctrl - 1 do
+ if m_ctrl[i ].in_rect(x ,y ) then
+ begin
+ result:=true;
+
+ exit;
+
+ end;
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+function ctrl_container.on_mouse_button_down;
+var
+ i : unsigned;
+
+begin
+ result:=false;
+
+ if m_num_ctrl > 0 then
+ for i:=0 to m_num_ctrl - 1 do
+ if m_ctrl[i ].on_mouse_button_down(x ,y ) then
+ begin
+ result:=true;
+
+ exit;
+
+ end;
+
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+function ctrl_container.on_mouse_button_up;
+var
+ i : unsigned;
+
+begin
+ result:=false;
+
+ if m_num_ctrl > 0 then
+ for i:=0 to m_num_ctrl - 1 do
+ if m_ctrl[i ].on_mouse_button_up(x ,y ) then
+ begin
+ result:=true;
+
+ exit;
+
+ end;
+
+end;
+
+{ ON_MOUSE_MOVE }
+function ctrl_container.on_mouse_move;
+var
+ i : unsigned;
+
+begin
+ result:=false;
+
+ if m_num_ctrl > 0 then
+ for i:=0 to m_num_ctrl - 1 do
+ if m_ctrl[i ].on_mouse_move(x ,y ,button_flag ) then
+ begin
+ result:=true;
+
+ exit;
+
+ end;
+
+end;
+
+{ ON_ARROW_KEYS }
+function ctrl_container.on_arrow_keys;
+begin
+ result:=false;
+
+ if m_cur_ctrl >= 0 then
+ result:=m_ctrl[m_cur_ctrl ].on_arrow_keys(left ,right ,down ,up );
+
+end;
+
+{ SET_CUR }
+function ctrl_container.set_cur;
+var
+ i : unsigned;
+
+begin
+ result:=false;
+
+ if m_num_ctrl > 0 then
+ for i:=0 to m_num_ctrl - 1 do
+ if m_ctrl[i ].in_rect(x ,y ) then
+ begin
+ if m_cur_ctrl <> i then
+ begin
+ m_cur_ctrl:=i;
+
+ result:=true;
+
+ end;
+
+ exit;
+
+ end;
+
+ if m_cur_ctrl <> -1 then
+ begin
+ m_cur_ctrl:=-1;
+
+ result:=true;
+
+ end;
+
+end;
+
+{ CONSTRUCT }
+constructor platform_specific.Construct;
+var
+ i : unsigned;
+
+begin
+ m_pmap_window.Construct;
+
+ for i:=0 to max_images - 1 do
+ m_pmap_img[i ].Construct;
+
+ m_format :=format;
+ m_sys_format:=pix_format_undefined;
+
+ m_flip_y :=flip_y;
+ m_bpp :=0;
+ m_sys_bpp:=0;
+ m_window :=NIL;
+
+ m_last_translated_key:=0;
+
+ m_cur_x:=0;
+ m_cur_y:=0;
+
+ m_input_flags:=0;
+ m_redraw_flag:=true;
+
+ fillchar(m_keymap[0 ] ,sizeof(m_keymap ) ,0 );
+
+//Keyboard input is not yet fully supported nor tested
+ //m_keymap[VK_PAUSE ]:=key_pause;
+ m_keymap[kClearCharCode ]:=key_clear;
+
+ //m_keymap[VK_NUMPAD0 ] :=key_kp0;
+ //m_keymap[VK_NUMPAD1 ] :=key_kp1;
+ //m_keymap[VK_NUMPAD2 ] :=key_kp2;
+ //m_keymap[VK_NUMPAD3 ] :=key_kp3;
+ //m_keymap[VK_NUMPAD4 ] :=key_kp4;
+ //m_keymap[VK_NUMPAD5 ] :=key_kp5;
+ //m_keymap[VK_NUMPAD6 ] :=key_kp6;
+ //m_keymap[VK_NUMPAD7 ] :=key_kp7;
+ //m_keymap[VK_NUMPAD8 ] :=key_kp8;
+ //m_keymap[VK_NUMPAD9 ] :=key_kp9;
+ //m_keymap[VK_DECIMAL ] :=key_kp_period;
+ //m_keymap[VK_DIVIDE ] :=key_kp_divide;
+ //m_keymap[VK_MULTIPLY ]:=key_kp_multiply;
+ //m_keymap[VK_SUBTRACT ]:=key_kp_minus;
+ //m_keymap[VK_ADD ] :=key_kp_plus;
+
+ m_keymap[kUpArrowCharCode ] :=key_up;
+ m_keymap[kDownArrowCharCode ] :=key_down;
+ m_keymap[kRightArrowCharCode ] :=key_right;
+ m_keymap[kLeftArrowCharCode ] :=key_left;
+ //m_keymap[VK_INSERT ]:=key_insert;
+ m_keymap[kDeleteCharCode ] :=key_delete;
+ m_keymap[kHomeCharCode ] :=key_home;
+ m_keymap[kEndCharCode ] :=key_end;
+ m_keymap[kPageUpCharCode ] :=key_page_up;
+ m_keymap[kPageDownCharCode ] :=key_page_down;
+
+ //m_keymap[VK_F1 ] :=key_f1;
+ //m_keymap[VK_F2 ] :=key_f2;
+ //m_keymap[VK_F3 ] :=key_f3;
+ //m_keymap[VK_F4 ] :=key_f4;
+ //m_keymap[VK_F5 ] :=key_f5;
+ //m_keymap[VK_F6 ] :=key_f6;
+ //m_keymap[VK_F7 ] :=key_f7;
+ //m_keymap[VK_F8 ] :=key_f8;
+ //m_keymap[VK_F9 ] :=key_f9;
+ //m_keymap[VK_F10 ]:=key_f10;
+ //m_keymap[VK_F11 ]:=key_f11;
+ //m_keymap[VK_F12 ]:=key_f12;
+ //m_keymap[VK_F13 ]:=key_f13;
+ //m_keymap[VK_F14 ]:=key_f14;
+ //m_keymap[VK_F15 ]:=key_f15;
+
+ //m_keymap[VK_NUMLOCK ]:=key_numlock;
+ //m_keymap[VK_CAPITAL ]:=key_capslock;
+ //m_keymap[VK_SCROLL ] :=key_scrollock;
+
+ case m_format of
+ pix_format_gray8 :
+ begin
+ m_sys_format:=pix_format_rgb24;
+ m_bpp :=8;
+ m_sys_bpp :=24;
+
+ end;
+
+ pix_format_rgb565 ,
+ pix_format_rgb555 :
+ begin
+ m_sys_format:=pix_format_rgb555;
+ m_bpp :=16;
+ m_sys_bpp :=16;
+
+ end;
+
+ pix_format_rgb24 ,
+ pix_format_bgr24 :
+ begin
+ m_sys_format:=pix_format_rgb24;
+ m_bpp :=24;
+ m_sys_bpp :=24;
+
+ end;
+
+ pix_format_bgra32 ,
+ pix_format_abgr32 ,
+ pix_format_argb32 ,
+ pix_format_rgba32 :
+ begin
+ m_sys_format:=pix_format_argb32;
+ m_bpp :=32;
+ m_sys_bpp :=32;
+
+ end;
+
+ end;
+
+ Microseconds(m_sw_freq );
+ Microseconds(m_sw_start );
+
+end;
+
+{ DESTRUCT }
+destructor platform_specific.Destruct;
+var
+ i : unsigned;
+
+begin
+ m_pmap_window.Destruct;
+
+ for i:=0 to max_images - 1 do
+ m_pmap_img[i ].Destruct;
+
+end;
+
+{ CREATE_PMAP }
+procedure platform_specific.create_pmap;
+begin
+ m_pmap_window.create(width ,height ,m_bpp );
+
+ if m_flip_y then
+ wnd.attach(
+ m_pmap_window._buf ,
+ m_pmap_window._width ,
+ m_pmap_window._height ,
+ -m_pmap_window._row_bytes )
+
+ else
+ wnd.attach(
+ m_pmap_window._buf ,
+ m_pmap_window._width ,
+ m_pmap_window._height ,
+ m_pmap_window._row_bytes )
+
+end;
+
+{ convert_pmap }
+procedure convert_pmap(dst ,src : rendering_buffer_ptr; format : pix_format_e );
+begin
+ case format of
+ pix_format_gray8 :
+ color_conv(dst ,src ,color_conv_gray8_to_rgb24 );
+
+ pix_format_rgb565 :
+ color_conv(dst ,src ,color_conv_rgb565_to_rgb555 );
+
+ pix_format_bgr24 :
+ color_conv(dst ,src ,color_conv_bgr24_to_rgb24 );
+
+ pix_format_abgr32 :
+ color_conv(dst ,src ,color_conv_abgr32_to_argb32 );
+
+ pix_format_bgra32 :
+ color_conv(dst ,src ,color_conv_bgra32_to_argb32 );
+
+ pix_format_rgba32 :
+ color_conv(dst ,src ,color_conv_rgba32_to_argb32 );
+
+ end;
+
+end;
+
+{ DISPLAY_PMAP }
+procedure platform_specific.display_pmap;
+var
+ pmap_tmp : pixel_map;
+ rbuf_tmp : rendering_buffer;
+
+begin
+ if m_sys_format = m_format then
+ m_pmap_window.draw(window )
+
+ else
+ begin
+ pmap_tmp.Construct;
+ pmap_tmp.create(m_pmap_window._width ,m_pmap_window._height ,m_sys_bpp );
+
+ rbuf_tmp.Construct;
+
+ if m_flip_y then
+ rbuf_tmp.attach(pmap_tmp._buf ,pmap_tmp._width ,pmap_tmp._height ,-pmap_tmp._row_bytes )
+ else
+ rbuf_tmp.attach(pmap_tmp._buf ,pmap_tmp._width ,pmap_tmp._height ,pmap_tmp._row_bytes );
+
+ convert_pmap (@rbuf_tmp ,src ,m_format );
+ pmap_tmp.draw(window );
+
+ rbuf_tmp.Destruct;
+ pmap_tmp.Destruct;
+
+ end;
+
+end;
+
+{ LOAD_PMAP }
+function platform_specific.load_pmap;
+var
+ pmap_tmp : pixel_map;
+ rbuf_tmp : rendering_buffer;
+
+begin
+ pmap_tmp.Construct;
+
+ if not pmap_tmp.load_from_qt(fn ) then
+ begin
+ result:=false;
+
+ pmap_tmp.Destruct;
+ exit;
+
+ end;
+
+ rbuf_tmp.Construct;
+
+ if m_flip_y then
+ rbuf_tmp.attach(pmap_tmp._buf ,pmap_tmp._width ,pmap_tmp._height ,-pmap_tmp._row_bytes )
+ else
+ rbuf_tmp.attach(pmap_tmp._buf ,pmap_tmp._width ,pmap_tmp._height ,pmap_tmp._row_bytes );
+
+ m_pmap_img[idx ].create(pmap_tmp._width ,pmap_tmp._height ,m_bpp ,0 );
+
+ if m_flip_y then
+ dst.attach(
+ m_pmap_img[idx ]._buf ,
+ m_pmap_img[idx ]._width ,
+ m_pmap_img[idx ]._height ,
+ -m_pmap_img[idx ]._row_bytes )
+ else
+ dst.attach(
+ m_pmap_img[idx ]._buf ,
+ m_pmap_img[idx ]._width ,
+ m_pmap_img[idx ]._height ,
+ m_pmap_img[idx ]._row_bytes );
+
+ case m_format of
+ pix_format_rgb555 :
+ case pmap_tmp._bpp of
+ 16 : color_conv(dst ,@rbuf_tmp ,color_conv_rgb555_to_rgb555 );
+ 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_rgb555 );
+ 32 : color_conv(dst ,@rbuf_tmp ,color_conv_bgra32_to_rgb555 );
+
+ end;
+
+ pix_format_rgb565 :
+ case pmap_tmp._bpp of
+ 16 : color_conv(dst ,@rbuf_tmp ,color_conv_rgb555_to_rgb565 );
+ 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_rgb565 );
+ 32 : color_conv(dst ,@rbuf_tmp ,color_conv_bgra32_to_rgb565 );
+
+ end;
+
+ pix_format_rgb24 :
+ case pmap_tmp._bpp of
+ 16 : color_conv(dst ,@rbuf_tmp ,color_conv_rgb555_to_rgb24 );
+ 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_rgb24 );
+ 32 : color_conv(dst ,@rbuf_tmp ,color_conv_bgra32_to_rgb24 );
+
+ end;
+
+ pix_format_bgr24 :
+ case pmap_tmp._bpp of
+ 16 : color_conv(dst ,@rbuf_tmp ,color_conv_rgb555_to_bgr24 );
+ 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_bgr24 );
+ 32 : color_conv(dst ,@rbuf_tmp ,color_conv_bgra32_to_bgr24 );
+
+ end;
+
+ pix_format_abgr32 :
+ case pmap_tmp._bpp of
+ 16 : color_conv(dst ,@rbuf_tmp ,color_conv_rgb555_to_abgr32 );
+ 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_abgr32 );
+ 32 : color_conv(dst ,@rbuf_tmp ,color_conv_bgra32_to_abgr32 );
+
+ end;
+
+ pix_format_argb32 :
+ case pmap_tmp._bpp of
+ 16 : color_conv(dst ,@rbuf_tmp ,color_conv_rgb555_to_argb32 );
+ 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_argb32 );
+ 32 : color_conv(dst ,@rbuf_tmp ,color_conv_bgra32_to_argb32 );
+
+ end;
+
+ pix_format_bgra32 :
+ case pmap_tmp._bpp of
+ 16 : color_conv(dst ,@rbuf_tmp ,color_conv_rgb555_to_bgra32 );
+ 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_bgra32 );
+ 32 : color_conv(dst ,@rbuf_tmp ,color_conv_bgra32_to_bgra32 );
+
+ end;
+
+ pix_format_rgba32 :
+ case pmap_tmp._bpp of
+ 16 : color_conv(dst ,@rbuf_tmp ,color_conv_rgb555_to_rgba32 );
+ 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_rgba32 );
+ 32 : color_conv(dst ,@rbuf_tmp ,color_conv_bgra32_to_rgba32 );
+
+ end;
+
+ end;
+
+ pmap_tmp.Destruct;
+ rbuf_tmp.Destruct;
+
+ result:=true;
+
+end;
+
+{ SAVE_PMAP }
+function platform_specific.save_pmap;
+var
+ pmap_tmp : pixel_map;
+ rbuf_tmp : rendering_buffer;
+
+begin
+ if m_sys_format = m_format then
+ begin
+ result:=m_pmap_img[idx ].save_as_qt(fn );
+
+ exit;
+
+ end;
+
+ pmap_tmp.Construct;
+ pmap_tmp.create(
+ m_pmap_img[idx ]._width ,
+ m_pmap_img[idx ]._height ,
+ m_sys_bpp );
+
+ rbuf_tmp.Construct;
+
+ if m_flip_y then
+ rbuf_tmp.attach(pmap_tmp._buf ,pmap_tmp._width ,pmap_tmp._height ,-pmap_tmp._row_bytes )
+ else
+ rbuf_tmp.attach(pmap_tmp._buf ,pmap_tmp._width ,pmap_tmp._height ,pmap_tmp._row_bytes );
+
+ convert_pmap(@rbuf_tmp ,src ,m_format );
+
+ result:=pmap_tmp.save_as_qt(fn );
+
+ rbuf_tmp.Destruct;
+ pmap_tmp.Destruct;
+
+end;
+
+{ TRANSLATE }
+function platform_specific.translate;
+begin
+ if keycode > 255 then
+ m_last_translated_key:=0
+ else
+ m_last_translated_key:=m_keymap[keycode ];
+
+end;
+
+{ CONSTRUCT }
+constructor platform_support.Construct;
+var
+ i : unsigned;
+
+begin
+ new(m_specific ,Construct(format_ ,flip_y_ ) );
+
+ m_ctrls.Construct;
+ m_rbuf_window.Construct;
+
+ for i:=0 to max_images - 1 do
+ m_rbuf_img[i ].Construct;
+
+ m_resize_mtx.Construct;
+
+ m_format:=format_;
+
+ m_bpp:=m_specific.m_bpp;
+
+ m_window_flags:=0;
+ m_wait_mode :=true;
+ m_flip_y :=flip_y_;
+
+ m_initial_width :=10;
+ m_initial_height:=10;
+
+ m_caption:='Anti-Grain Geometry Application'#0;
+
+end;
+
+{ DESTRUCT }
+destructor platform_support.Destruct;
+var
+ i : unsigned;
+
+begin
+ dispose(m_specific ,Destruct );
+
+ m_ctrls.Destruct;
+ m_rbuf_window.Destruct;
+
+ for i:=0 to max_images - 1 do
+ m_rbuf_img[i ].Destruct;
+
+end;
+
+{ CAPTION_ }
+procedure platform_support.caption_;
+begin
+ m_caption:=cap + #0;
+
+ dec(byte(m_caption[0 ] ) );
+
+ if m_specific.m_window <> NIL then
+ SetWindowTitleWithCFString(
+ m_specific.m_window ,
+ CFStringCreateWithPascalStringNoCopy(
+ NIL ,cap ,kCFStringEncodingASCII ,NIL ) );
+
+end;
+
+{ LOAD_IMG }
+function platform_support.load_img;
+begin
+ if idx < max_images then
+ begin
+ file_ :=file_ + _img_ext;
+ result:=m_specific.load_pmap(file_ ,idx ,@m_rbuf_img[idx ] );
+
+ end
+ else
+ result:=true;
+
+end;
+
+{ SAVE_IMG }
+function platform_support.save_img;
+begin
+ if idx < max_images then
+ result:=m_specific.save_pmap(file_ ,idx ,@m_rbuf_img[idx ] )
+ else
+ result:=true;
+
+end;
+
+{ CREATE_IMG }
+function platform_support.create_img;
+begin
+ if idx < max_images then
+ begin
+ if width_ = 0 then
+ width_:=m_specific.m_pmap_window._width;
+
+ if height_ = 0 then
+ height_:=m_specific.m_pmap_window._height;
+
+ m_specific.m_pmap_img[idx ].create(width_ ,height_ ,m_specific.m_bpp );
+
+ if m_flip_y then
+ m_rbuf_img[idx ].attach(
+ m_specific.m_pmap_img[idx ]._buf ,
+ m_specific.m_pmap_img[idx ]._width ,
+ m_specific.m_pmap_img[idx ]._height ,
+ -m_specific.m_pmap_img[idx ]._row_bytes )
+ else
+ m_rbuf_img[idx ].attach(
+ m_specific.m_pmap_img[idx ]._buf ,
+ m_specific.m_pmap_img[idx ]._width ,
+ m_specific.m_pmap_img[idx ]._height ,
+ m_specific.m_pmap_img[idx ]._row_bytes );
+
+ result:=true;
+
+ end
+ else
+ result:=false;
+
+end;
+
+{ get_key_flags }
+function get_key_flags(wflags : int ) : unsigned;
+var
+ flags : unsigned;
+
+begin
+ flags:=0;
+
+ if wflags and shiftKey <> 0 then
+ flags:=flags or kbd_shift;
+
+ if wflags and controlKey <> 0 then
+ flags:=flags or kbd_ctrl;
+
+ result:=flags;
+
+end;
+
+{ DOWINDOWCLOSE }
+function DoWindowClose(nextHandler : EventHandlerCallRef; theEvent : EventRef; userData : pointer ) : OSStatus;
+begin
+ QuitApplicationEventLoop;
+
+ result:=CallNextEventHandler(nextHandler ,theEvent );
+
+end;
+
+{ DOWINDOWDRAWCONTENT }
+function DoWindowDrawContent(nextHandler : EventHandlerCallRef; theEvent : EventRef; userData : pointer ) : OSStatus;
+var
+ app : platform_support_ptr;
+
+begin
+ app:=platform_support_ptr(userData );
+
+ if app <> NIL then
+ begin
+ if app.m_specific.m_redraw_flag then
+ begin
+ app.on_draw;
+
+ app.m_specific.m_redraw_flag:=false;
+
+ end;
+
+ app.m_specific.display_pmap(app.m_specific.m_window ,app.rbuf_window );
+
+ end;
+
+ result:=CallNextEventHandler(nextHandler ,theEvent );
+
+end;
+
+{ DOWINDOWRESIZE }
+function DoWindowResize(nextHandler : EventHandlerCallRef; theEvent : EventRef; userData : pointer ) : OSStatus;
+var
+ app : platform_support_ptr;
+ Rect : Carbon.Rect;
+
+ width ,height : unsigned;
+
+begin
+ app:=platform_support_ptr(userData );
+
+ GetWindowBounds(app.m_specific.m_window ,kWindowContentRgn ,Rect );
+
+ width :=Rect.Right - Rect.Left;
+ height:=Rect.Bottom - Rect.Top;
+
+ if (width <> app.rbuf_window._width ) or
+ (height <> app.rbuf_window._height ) then
+ begin
+ app.m_specific.create_pmap(width ,height ,app.rbuf_window );
+ app.trans_affine_resizing_(width ,height );
+
+ app.on_resize(width ,height );
+
+ end;
+
+ app.force_redraw;
+
+ result:=CallNextEventHandler(nextHandler ,theEvent );
+
+end;
+
+{ DOAPPQUIT }
+function DoAppQuit(nextHandler : EventHandlerCallRef; theEvent : EventRef; userData : pointer ) : OSStatus;
+begin
+ result:=CallNextEventHandler(nextHandler ,theEvent );
+
+end;
+
+{ DOMOUSEDOWN }
+function DoMouseDown(nextHandler : EventHandlerCallRef; theEvent : EventRef; userData : pointer ) : OSStatus;
+var
+ wheresMyMouse : Carbon.Point;
+
+ modifier : UInt32;
+ button : EventMouseButton;
+
+ sz : UInt32;
+ app : platform_support_ptr;
+ ept : EventParamType;
+
+begin
+ ept:=0;
+
+ GetEventParameter(
+ theEvent ,
+ LongWord(int32_ptr(@kEventParamMouseLocation[1 ] )^ ) ,
+ LongWord(int32_ptr(@typeQDPoint[1 ] )^ ) ,
+ ept ,
+ sizeof(Carbon.Point ) ,
+ sz ,
+ @wheresMyMouse );
+
+ GlobalToLocal(wheresMyMouse );
+ GetEventParameter(
+ theEvent ,
+ LongWord(int32_ptr(@kEventParamKeyModifiers[1 ] )^ ) ,
+ LongWord(int32_ptr(@typeUInt32[1 ] )^ ) ,
+ ept ,
+ sizeof(UInt32 ) ,
+ sz ,
+ @modifier );
+
+ app:=platform_support_ptr(userData );
+
+ app.m_specific.m_cur_x:=wheresMyMouse.h;
+
+ if app._flip_y then
+ app.m_specific.m_cur_y:=app.rbuf_window._height - wheresMyMouse.v
+ else
+ app.m_specific.m_cur_y:=wheresMyMouse.v;
+
+ GetEventParameter(
+ theEvent ,
+ LongWord(int32_ptr(@kEventParamMouseButton[1 ] )^ ) ,
+ LongWord(int32_ptr(@typeMouseButton[1 ] )^ ) ,
+ ept ,
+ sizeof(EventMouseButton ) ,
+ sz ,
+ @button );
+
+ case button of
+ kEventMouseButtonSecondary :
+ app.m_specific.m_input_flags:=mouse_right or get_key_flags(modifier );
+
+ else
+ app.m_specific.m_input_flags:=mouse_left or get_key_flags(modifier );
+
+ end;
+
+ app.m_ctrls.set_cur(
+ app.m_specific.m_cur_x ,
+ app.m_specific.m_cur_y );
+
+ if app.m_ctrls.on_mouse_button_down(
+ app.m_specific.m_cur_x ,
+ app.m_specific.m_cur_y ) then
+ begin
+ app.on_ctrl_change;
+ app.force_redraw;
+
+ end
+ else
+ if app.m_ctrls.in_rect(
+ app.m_specific.m_cur_x ,
+ app.m_specific.m_cur_y ) then
+ if app.m_ctrls.set_cur(
+ app.m_specific.m_cur_x ,
+ app.m_specific.m_cur_y ) then
+ begin
+ app.on_ctrl_change;
+ app.force_redraw;
+
+ end
+ else
+ else
+ app.on_mouse_button_down(
+ app.m_specific.m_cur_x ,
+ app.m_specific.m_cur_y ,
+ app.m_specific.m_input_flags );
+
+ result:=CallNextEventHandler(nextHandler ,theEvent );
+
+end;
+
+{ DOMOUSEUP }
+function DoMouseUp(nextHandler : EventHandlerCallRef; theEvent : EventRef; userData : pointer ) : OSStatus;
+var
+ wheresMyMouse : Carbon.Point;
+
+ modifier : UInt32;
+ button : EventMouseButton;
+
+ sz : UInt32;
+ app : platform_support_ptr;
+ ept : EventParamType;
+
+begin
+ ept:=0;
+
+ GetEventParameter(
+ theEvent ,
+ LongWord(int32_ptr(@kEventParamMouseLocation[1 ] )^ ) ,
+ LongWord(int32_ptr(@typeQDPoint[1 ] )^ ) ,
+ ept ,
+ sizeof(Carbon.Point ) ,
+ sz ,
+ @wheresMyMouse );
+
+ GlobalToLocal(wheresMyMouse );
+
+ GetEventParameter(
+ theEvent ,
+ LongWord(int32_ptr(@kEventParamKeyModifiers[1 ] )^ ) ,
+ LongWord(int32_ptr(@typeUInt32[1 ] )^ ) ,
+ ept ,
+ sizeof(UInt32 ) ,
+ sz ,
+ @modifier );
+
+ app:=platform_support_ptr(userData );
+
+ app.m_specific.m_cur_x:=wheresMyMouse.h;
+
+ if app._flip_y then
+ app.m_specific.m_cur_y:=app.rbuf_window._height - wheresMyMouse.v
+ else
+ app.m_specific.m_cur_y:=wheresMyMouse.v;
+
+ GetEventParameter(
+ theEvent ,
+ LongWord(int32_ptr(@kEventParamMouseButton[1 ] )^ ) ,
+ LongWord(int32_ptr(@typeMouseButton[1 ] )^ ) ,
+ ept ,
+ sizeof(EventMouseButton ) ,
+ sz ,
+ @button );
+
+ case button of
+ kEventMouseButtonSecondary :
+ app.m_specific.m_input_flags:=mouse_right or get_key_flags(modifier );
+
+ else
+ app.m_specific.m_input_flags:=mouse_left or get_key_flags(modifier );
+
+ end;
+
+ if app.m_ctrls.on_mouse_button_up(
+ app.m_specific.m_cur_x ,
+ app.m_specific.m_cur_y ) then
+ begin
+ app.on_ctrl_change;
+ app.force_redraw;
+
+ end;
+
+ app.on_mouse_button_up(
+ app.m_specific.m_cur_x ,
+ app.m_specific.m_cur_y ,
+ app.m_specific.m_input_flags );
+
+ result:=CallNextEventHandler(nextHandler ,theEvent );
+
+end;
+
+{ DOMOUSEDRAGGED }
+function DoMouseDragged(nextHandler : EventHandlerCallRef; theEvent : EventRef; userData : pointer ) : OSStatus;
+var
+ wheresMyMouse : Carbon.Point;
+
+ modifier : UInt32;
+ button : EventMouseButton;
+
+ sz : UInt32;
+ app : platform_support_ptr;
+ ept : EventParamType;
+
+begin
+ ept:=0;
+
+ GetEventParameter(
+ theEvent ,
+ LongWord(int32_ptr(@kEventParamMouseLocation[1 ] )^ ) ,
+ LongWord(int32_ptr(@typeQDPoint[1 ] )^ ) ,
+ ept ,
+ sizeof(Carbon.Point ) ,
+ sz ,
+ @wheresMyMouse );
+
+ GlobalToLocal(wheresMyMouse );
+ GetEventParameter(
+ theEvent ,
+ LongWord(int32_ptr(@kEventParamKeyModifiers[1 ] )^ ) ,
+ LongWord(int32_ptr(@typeUInt32[1 ] )^ ) ,
+ ept ,
+ sizeof(UInt32 ) ,
+ sz ,
+ @modifier );
+
+ app:=platform_support_ptr(userData );
+
+ app.m_specific.m_cur_x:=wheresMyMouse.h;
+
+ if app._flip_y then
+ app.m_specific.m_cur_y:=app.rbuf_window._height - wheresMyMouse.v
+ else
+ app.m_specific.m_cur_y:=wheresMyMouse.v;
+
+ GetEventParameter(
+ theEvent ,
+ LongWord(int32_ptr(@kEventParamMouseButton[1 ] )^ ) ,
+ LongWord(int32_ptr(@typeMouseButton[1 ] )^ ) ,
+ ept ,
+ sizeof(EventMouseButton ) ,
+ sz ,
+ @button );
+
+ case button of
+ kEventMouseButtonSecondary :
+ app.m_specific.m_input_flags:=mouse_right or get_key_flags(modifier );
+
+ else
+ app.m_specific.m_input_flags:=mouse_left or get_key_flags(modifier );
+
+ end;
+
+ if app.m_ctrls.on_mouse_move(
+ app.m_specific.m_cur_x ,
+ app.m_specific.m_cur_y ,
+ app.m_specific.m_input_flags and mouse_left <> 0 ) then
+ begin
+ app.on_ctrl_change;
+ app.force_redraw;
+
+ end
+ else
+ app.on_mouse_move(
+ app.m_specific.m_cur_x ,
+ app.m_specific.m_cur_y ,
+ app.m_specific.m_input_flags );
+
+ result:=CallNextEventHandler(nextHandler ,theEvent );
+
+end;
+
+{ DOKEYDOWN }
+function DoKeyDown(nextHandler : EventHandlerCallRef; theEvent : EventRef; userData : pointer ) : OSStatus;
+var
+ key_char : byte;
+ key_code ,
+ modifier : UInt32;
+
+ sz : UInt32;
+ app : platform_support_ptr;
+ ept : EventParamType;
+
+ left ,up ,right ,down : boolean;
+
+begin
+ ept:=0;
+
+ GetEventParameter(
+ theEvent ,
+ LongWord(int32_ptr(@kEventParamKeyMacCharCodes[1 ] )^ ) ,
+ LongWord(int32_ptr(@typeChar[1 ] )^ ) ,
+ ept ,
+ sizeof(byte ) ,
+ sz ,
+ @key_char );
+
+ GetEventParameter(
+ theEvent ,
+ LongWord(int32_ptr(@kEventParamKeyCode[1 ] )^ ) ,
+ LongWord(int32_ptr(@typeUInt32[1 ] )^ ) ,
+ ept ,
+ sizeof(UInt32 ) ,
+ sz ,
+ @key_code );
+
+ GetEventParameter(
+ theEvent ,
+ LongWord(int32_ptr(@kEventParamKeyModifiers[1 ] )^ ) ,
+ LongWord(int32_ptr(@typeUInt32[1 ] )^ ) ,
+ ept ,
+ sizeof(UInt32 ) ,
+ sz ,
+ @modifier );
+
+ app:=platform_support_ptr(userData );
+
+ app.m_specific.m_last_translated_key:=0;
+
+ case modifier of
+ controlKey :
+ app.m_specific.m_input_flags:=
+ app.m_specific.m_input_flags or kbd_ctrl;
+
+ shiftKey :
+ app.m_specific.m_input_flags:=
+ app.m_specific.m_input_flags or kbd_shift;
+
+ else
+ app.m_specific.translate(key_char );
+
+ end;
+
+ case key_char of
+ kFunctionKeyCharCode :
+ case key_code of
+ 122 : app.m_specific.m_last_translated_key:=key_f1;
+ 120 : app.m_specific.m_last_translated_key:=key_f2;
+ 99 : app.m_specific.m_last_translated_key:=key_f3;
+ 118 : app.m_specific.m_last_translated_key:=key_f4;
+ 96 : app.m_specific.m_last_translated_key:=key_f5;
+ 97 : app.m_specific.m_last_translated_key:=key_f6;
+ 98 : app.m_specific.m_last_translated_key:=key_f7;
+ 100 : app.m_specific.m_last_translated_key:=key_f8;
+
+ end;
+
+ end;
+
+ if (app.m_specific.m_last_translated_key = 0 ) and
+ (key_char > 31 ) then
+ app.m_specific.m_last_translated_key:=key_char;
+
+ if app.m_specific.m_last_translated_key <> 0 then
+ begin
+ left :=false;
+ up :=false;
+ right:=false;
+ down :=false;
+
+ case app.m_specific.m_last_translated_key of
+ key_left : left :=true;
+ key_up : up :=true;
+ key_right : right:=true;
+ key_down : down :=true;
+
+ //On a Mac, screenshots are handled by the system.
+ key_f2 :
+ begin
+ app.copy_window_to_img(max_images - 1 );
+ app.save_img (max_images - 1 ,'screenshot.png' );
+
+ end;
+
+ key_f4 :
+ if modifier = optionKey then
+ app.quit;
+
+ end;
+
+ if app.m_ctrls.on_arrow_keys(left ,right ,down ,up ) then
+ begin
+ app.on_ctrl_change;
+ app.force_redraw;
+
+ end
+ else
+ app.on_key(
+ app.m_specific.m_cur_x ,
+ app.m_specific.m_cur_y ,
+ app.m_specific.m_last_translated_key ,
+ app.m_specific.m_input_flags );
+
+ end;
+
+ result:=CallNextEventHandler(nextHandler ,theEvent );
+
+end;
+
+{ DOKEYUP }
+function DoKeyUp(nextHandler : EventHandlerCallRef; theEvent : EventRef; userData : pointer ) : OSStatus;
+var
+ key_code : byte;
+ modifier : UInt32;
+
+ sz : UInt32;
+ app : platform_support_ptr;
+ ept : EventParamType;
+
+begin
+ ept:=0;
+
+ GetEventParameter(
+ theEvent ,
+ LongWord(int32_ptr(@kEventParamKeyMacCharCodes[1 ] )^ ) ,
+ LongWord(int32_ptr(@typeChar[1 ] )^ ) ,
+ ept ,
+ sizeof(byte ) ,
+ sz ,
+ @key_code );
+
+ GetEventParameter(
+ theEvent ,
+ LongWord(int32_ptr(@kEventParamKeyModifiers[1 ] )^ ) ,
+ LongWord(int32_ptr(@typeUInt32[1 ] )^ ) ,
+ ept ,
+ sizeof(UInt32 ) ,
+ sz ,
+ @modifier );
+
+ app:=platform_support_ptr(userData );
+
+ app.m_specific.m_last_translated_key:=0;
+
+ case modifier of
+ controlKey :
+ app.m_specific.m_input_flags:=
+ app.m_specific.m_input_flags and not kbd_ctrl;
+
+ shiftKey :
+ app.m_specific.m_input_flags:=
+ app.m_specific.m_input_flags and not kbd_shift;
+
+ end;
+
+ result:=CallNextEventHandler(nextHandler ,theEvent );
+
+end;
+
+{ DOPERIODICTASK }
+procedure DoPeriodicTask(theTimer : EventLoopTimerRef; userData : pointer );
+var
+ app : platform_support_ptr;
+
+begin
+ app:=platform_support_ptr(userData );
+
+ if not app._wait_mode then
+ app.on_idle;
+
+end;
+
+{ INIT }
+function platform_support.init;
+var
+ eventType : EventTypeSpec;
+ handlerUPP : EventHandlerUPP;
+ theTarget : CFStringRef;
+ windowAttrs : WindowAttributes;
+ bounds : Carbon.Rect;
+ mainLoop : EventLoopRef;
+ timerUPP : EventLoopTimerUPP;
+ theTimer : EventLoopTimerRef;
+
+begin
+ if m_specific.m_sys_format = pix_format_undefined then
+ begin
+ result:=false;
+
+ exit;
+
+ end;
+
+ m_window_flags:=flags;
+
+// application
+ theTarget:=GetApplicationEventTarget;
+
+ eventType.eventClass:=LongWord(int32_ptr(@kEventClassApplication[1 ] )^ );
+ eventType.eventKind :=kEventAppQuit;
+
+ handlerUPP:=NewEventHandlerUPP(@DoAppQuit );
+
+ InstallEventHandler(theTarget ,handlerUPP ,1 ,eventType ,NIL ,NIL );
+
+
+ eventType.eventClass:=LongWord(int32_ptr(@kEventClassMouse[1 ] )^ );
+ eventType.eventKind :=kEventMouseDown;
+
+ handlerUPP:=NewEventHandlerUPP(@DoMouseDown );
+
+ InstallEventHandler(theTarget ,handlerUPP ,1 ,eventType ,@self ,NIL );
+
+
+ eventType.eventKind:=kEventMouseUp;
+
+ handlerUPP:=NewEventHandlerUPP(@DoMouseUp );
+
+ InstallEventHandler(theTarget ,handlerUPP ,1 ,eventType ,@self ,NIL );
+
+
+ eventType.eventKind:=kEventMouseDragged;
+
+ handlerUPP:=NewEventHandlerUPP(@DoMouseDragged );
+
+ InstallEventHandler(theTarget ,handlerUPP ,1 ,eventType ,@self ,NIL );
+
+
+ eventType.eventClass:=LongWord(int32_ptr(@kEventClassKeyboard[1 ] )^ );
+ eventType.eventKind :=kEventRawKeyDown;
+
+ handlerUPP:=NewEventHandlerUPP(@DoKeyDown );
+
+ InstallEventHandler(theTarget ,handlerUPP ,1 ,eventType ,@self ,NIL );
+
+
+ eventType.eventKind:=kEventRawKeyUp;
+
+ handlerUPP:=NewEventHandlerUPP(@DoKeyUp );
+
+ InstallEventHandler(theTarget ,handlerUPP ,1 ,eventType ,@self ,NIL );
+
+
+ eventType.eventKind:=kEventRawKeyRepeat;
+
+ handlerUPP:=NewEventHandlerUPP(@DoKeyDown ); // 'key repeat' is translated to 'key down'
+
+ InstallEventHandler(theTarget ,handlerUPP ,1 ,eventType ,@self ,NIL );
+
+// window
+ windowAttrs:=kWindowCloseBoxAttribute or kWindowCollapseBoxAttribute or kWindowStandardHandlerAttribute;
+
+ if flags and window_resize <> 0 then
+ windowAttrs:=
+ windowAttrs or
+ kWindowResizableAttribute or
+ kWindowFullZoomAttribute or
+ kWindowLiveResizeAttribute;
+
+ SetRect (bounds ,0 ,0 ,width_ ,height_ );
+ OffsetRect(bounds ,100 ,100 );
+
+ CreateNewWindow(
+ kDocumentWindowClass ,
+ windowAttrs ,
+ bounds ,
+ m_specific.m_window );
+
+ if m_specific.m_window = NIL then
+ begin
+ result:=false;
+
+ exit;
+
+ end;
+
+// I assume the text is ASCII.
+// Change to kCFStringEncodingMacRoman, kCFStringEncodingISOLatin1, kCFStringEncodingUTF8 or what else you need.
+ SetWindowTitleWithCFString(
+ m_specific.m_window ,
+ CFStringCreateWithPascalStringNoCopy(
+ NIL ,m_caption ,kCFStringEncodingASCII ,NIL ) );
+
+ theTarget:=GetWindowEventTarget(m_specific.m_window );
+
+ eventType.eventClass:=LongWord(int32_ptr(@kEventClassWindow[1 ] )^ );
+ eventType.eventKind :=kEventWindowClose;
+
+ handlerUPP:=NewEventHandlerUPP(@DoWindowClose );
+
+ InstallEventHandler(theTarget ,handlerUPP ,1 ,eventType ,@self ,NIL );
+
+
+ eventType.eventKind:=kEventWindowDrawContent;
+
+ handlerUPP:=NewEventHandlerUPP(@DoWindowDrawContent );
+
+ InstallEventHandler(theTarget ,handlerUPP ,1 ,eventType ,@self ,NIL );
+
+
+ eventType.eventKind:=kEventWindowBoundsChanged;
+
+ handlerUPP:=NewEventHandlerUPP(@DoWindowResize );
+
+ InstallEventHandler(theTarget ,handlerUPP ,1 ,eventType ,@self ,NIL );
+
+// Periodic task
+// Instead of an idle function I use the Carbon event timer.
+// You may decide to change the wait value which is currently 50 milliseconds.
+ mainLoop:=GetMainEventLoop;
+ timerUPP:=NewEventLoopTimerUPP(@DoPeriodicTask );
+
+ InstallEventLoopTimer(mainLoop ,0 ,50 * kEventDurationMillisecond ,timerUPP ,@self ,theTimer );
+
+ m_specific.create_pmap(width_ ,height_ ,@m_rbuf_window );
+
+ m_initial_width :=width_;
+ m_initial_height:=height_;
+
+ on_init;
+ on_resize(width_ ,height_ );
+
+ m_specific.m_redraw_flag:=true;
+
+ ShowWindow (m_specific.m_window );
+ SetPortWindowPort(m_specific.m_window );
+
+ result:=true;
+
+end;
+
+{ RUN }
+function platform_support.run;
+begin
+ RunApplicationEventLoop;
+
+ result:=1;
+
+end;
+
+{ QUIT }
+procedure platform_support.quit;
+begin
+ QuitApplicationEventLoop;
+
+end;
+
+{ _FORMAT }
+function platform_support._format;
+begin
+ result:=m_format;
+
+end;
+
+{ _FLIP_Y }
+function platform_support._flip_y;
+begin
+ result:=m_flip_y;
+
+end;
+
+{ _BPP }
+function platform_support._bpp;
+begin
+ result:=m_bpp;
+
+end;
+
+{ _WAIT_MODE }
+function platform_support._wait_mode;
+begin
+ result:=m_wait_mode;
+
+end;
+
+{ WAIT_MODE_ }
+procedure platform_support.wait_mode_;
+begin
+ m_wait_mode:=wait_mode;
+
+end;
+
+{ FORCE_REDRAW }
+procedure platform_support.force_redraw;
+var
+ bounds : Carbon.Rect;
+
+begin
+ m_specific.m_redraw_flag:=true;
+
+// on_ctrl_change
+ on_draw;
+
+ SetRect (bounds ,0 ,0 ,m_rbuf_window._width ,m_rbuf_window._height );
+ InvalWindowRect(m_specific.m_window ,bounds );
+
+end;
+
+{ UPDATE_WINDOW }
+procedure platform_support.update_window;
+begin
+ m_specific.display_pmap(m_specific.m_window ,@m_rbuf_window );
+
+end;
+
+{ RBUF_WINDOW }
+function platform_support.rbuf_window;
+begin
+ result:=@m_rbuf_window;
+
+end;
+
+{ RBUF_IMG }
+function platform_support.rbuf_img;
+begin
+ result:=@m_rbuf_img[idx ];
+
+end;
+
+{ _IMG_EXT }
+function platform_support._img_ext;
+begin
+ result:='.bmp';
+
+end;
+
+{ COPY_IMG_TO_WINDOW }
+procedure platform_support.copy_img_to_window;
+begin
+ if (idx < max_images ) and
+ (rbuf_img(idx )._buf <> NIL ) then
+ rbuf_window.copy_from(rbuf_img(idx ) );
+
+end;
+
+{ COPY_WINDOW_TO_IMG }
+procedure platform_support.copy_window_to_img;
+begin
+ if idx < max_images then
+ begin
+ create_img(idx ,rbuf_window._width ,rbuf_window._height );
+ rbuf_img (idx ).copy_from(rbuf_window );
+
+ end;
+
+end;
+
+{ COPY_IMG_TO_IMG }
+procedure platform_support.copy_img_to_img;
+begin
+ if (idx_from < max_images ) and
+ (idx_to < max_images ) and
+ (rbuf_img(idx_from )._buf <> NIL ) then
+ begin
+ create_img(
+ idx_to ,
+ rbuf_img(idx_from )._width ,
+ rbuf_img(idx_from )._height );
+
+ rbuf_img(idx_to ).copy_from(rbuf_img(idx_from ) );
+
+ end;
+
+end;
+
+{ ON_INIT }
+procedure platform_support.on_init;
+begin
+end;
+
+{ ON_RESIZE }
+procedure platform_support.on_resize;
+begin
+end;
+
+{ ON_IDLE }
+procedure platform_support.on_idle;
+begin
+end;
+
+{ ON_MOUSE_MOVE }
+procedure platform_support.on_mouse_move;
+begin
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure platform_support.on_mouse_button_down;
+begin
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+procedure platform_support.on_mouse_button_up;
+begin
+end;
+
+{ ON_KEY }
+procedure platform_support.on_key;
+begin
+end;
+
+{ ON_CTRL_CHANGE }
+procedure platform_support.on_ctrl_change;
+begin
+end;
+
+{ ON_DRAW }
+procedure platform_support.on_draw;
+begin
+end;
+
+{ ON_POST_DRAW }
+procedure platform_support.on_post_draw;
+begin
+end;
+
+{ ADD_CTRL }
+procedure platform_support.add_ctrl;
+begin
+ m_ctrls.add(c );
+
+ c.transform(@m_resize_mtx );
+
+end;
+
+{ TRANS_AFFINE_RESIZING_ }
+procedure platform_support.trans_affine_resizing_;
+var
+ vp : trans_viewport;
+ ts : trans_affine_scaling;
+
+begin
+ if m_window_flags and window_keep_aspect_ratio <> 0 then
+ begin
+ //double sx = double(width) / double(m_initial_width);
+ //double sy = double(height) / double(m_initial_height);
+ //if(sy < sx) sx = sy;
+ //m_resize_mtx = trans_affine_scaling(sx, sx);
+
+ vp.Construct;
+ vp.preserve_aspect_ratio(0.5 ,0.5 ,aspect_ratio_meet );
+
+ vp.device_viewport(0 ,0 ,width_ ,height_ );
+ vp.world_viewport (0 ,0 ,m_initial_width ,m_initial_height );
+
+ vp.to_affine(@m_resize_mtx );
+
+ end
+ else
+ begin
+ ts.Construct(
+ width_ / m_initial_width ,
+ height_ / m_initial_height );
+
+ m_resize_mtx.assign(@ts );
+
+ end;
+
+end;
+
+{ _TRANS_AFFINE_RESIZING }
+function platform_support._trans_affine_resizing;
+begin
+ result:=@m_resize_mtx;
+
+end;
+
+{ _WIDTH }
+function platform_support._width;
+begin
+ result:=m_rbuf_window._width;
+
+end;
+
+{ _HEIGHT }
+function platform_support._height;
+begin
+ result:=m_rbuf_window._height;
+
+end;
+
+{ _INITIAL_WIDTH }
+function platform_support._initial_width;
+begin
+ result:=m_initial_width;
+
+end;
+
+{ _INITIAL_HEIGHT }
+function platform_support._initial_height;
+begin
+ result:=m_initial_height;
+
+end;
+
+{ _WINDOW_FLAGS }
+function platform_support._window_flags;
+begin
+ result:=m_window_flags;
+
+end;
+
+{ _RAW_DISPLAY_HANDLER }
+function platform_support._raw_display_handler;
+begin
+end;
+
+{ MESSAGE_ }
+procedure platform_support.message_;
+var
+ dlg : DialogRef;
+ itm : DialogItemIndex;
+
+begin
+ CreateStandardAlert(
+ kAlertPlainAlert ,
+ CFStringCreateWithCStringNoCopy(
+ NIL ,'AGG Message' ,kCFStringEncodingASCII ,NIL ) ,
+ CFStringCreateWithCStringNoCopy(
+ NIL ,msg ,kCFStringEncodingASCII ,NIL ) ,
+ NIL ,
+ dlg );
+
+ RunStandardAlert(dlg ,NIL ,itm );
+
+end;
+
+{ START_TIMER }
+procedure platform_support.start_timer;
+begin
+ Microseconds(m_specific.m_sw_start );
+
+end;
+
+{ ELAPSED_TIME }
+function platform_support.elapsed_time;
+var
+ stop : UnsignedWide;
+
+begin
+ Microseconds(stop );
+
+ result:=
+ (stop.lo - m_specific.m_sw_start.lo) * 1e6 /
+ m_specific.m_sw_freq.lo;
+
+end;
+
+{ FULL_FILE_NAME }
+function platform_support.full_file_name;
+begin
+ result:=file_name;
+
+end;
+
+{ FILE_SOURCE }
+function platform_support.file_source;
+begin
+ result:=fname;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/platform/mac/file_utils_.pas b/src/corelib/render/software/platform/mac/file_utils_.pas
new file mode 100644
index 00000000..fc804997
--- /dev/null
+++ b/src/corelib/render/software/platform/mac/file_utils_.pas
@@ -0,0 +1,846 @@
+//
+// AggPas 2.4 RM3 demo framework file utility library
+// Milan Marusinec alias Milano (c) 2006
+//
+unit
+ file_utils_ ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+{$I- }
+uses
+ agg_basics ,
+ Carbon ;
+
+{ TYPES DEFINITION }
+type
+ api_file_ptr = ^api_file;
+ api_file = record
+ fileName : shortstring;
+ isOpened : boolean;
+
+ fSize ,
+ fRead : SInt64;
+
+ // FSOpenFork parameters
+ fFSRef : FSRef;
+ fName ,
+ fFork : HFSUniStr255;
+ fRef : SInt16;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+ function cut_str(s : shortstring ) : shortstring;
+ function up_str (s : shortstring ) : shortstring;
+ function cmp_str(s : shortstring ) : shortstring;
+
+ function str_dir(s : shortstring ) : shortstring;
+ function dir_str(s : shortstring ) : shortstring;
+
+ function str_disk(fn : shortstring ) : shortstring;
+ function str_path(fn : shortstring ) : shortstring;
+ function str_name(fn : shortstring ) : shortstring;
+ function str_ext (fn : shortstring ) : shortstring;
+
+ function fold_name (p ,n ,x : shortstring ) : shortstring;
+ procedure spread_name(fn : shortstring; var p ,n ,x : shortstring );
+
+ function file_exists(fn : shortstring ) : boolean;
+
+ procedure display(msg : PChar );
+ function pasc (msg : shortstring ) : PChar;
+
+ function api_open_file (var af : api_file; fname : shortstring ) : boolean;
+ function api_read_file (var af : api_file; buff : pointer; aloc : int; var read : int ) : boolean;
+ function api_close_file(var af : api_file ) : boolean;
+
+ function param_count : int;
+ function param_str(i : int ) : shortstring;
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+type
+ tSCAN = (
+
+ SCAN_0 ,
+ SCAN_1 ,SCAN_2 ,SCAN_3 ,SCAN_4 ,SCAN_5 ,SCAN_6 ,SCAN_7 ,SCAN_8 ,SCAN_9 ,
+ SCAN_A ,SCAN_B ,SCAN_C ,SCAN_D ,SCAN_E ,SCAN_F ,SCAN_G ,SCAN_H ,SCAN_I ,
+ SCAN_J ,SCAN_K ,SCAN_L ,SCAN_M ,SCAN_N ,SCAN_O ,SCAN_P ,SCAN_Q ,SCAN_R ,
+ SCAN_S ,SCAN_T ,SCAN_U ,SCAN_V ,SCAN_W ,SCAN_X ,SCAN_Y ,SCAN_Z
+
+ );
+
+ tITEM = (
+
+ ITEM_0 ,
+ ITEM_1 ,ITEM_2 ,ITEM_3 ,ITEM_4 ,ITEM_5 ,ITEM_6 ,ITEM_7 ,ITEM_8 ,ITEM_9 ,
+ ITEM_A ,ITEM_B ,ITEM_C ,ITEM_D ,ITEM_E ,ITEM_F ,ITEM_G ,ITEM_H ,ITEM_I ,
+ ITEM_J ,ITEM_K ,ITEM_L ,ITEM_M ,ITEM_N ,ITEM_O ,ITEM_P ,ITEM_Q ,ITEM_R ,
+ ITEM_S ,ITEM_T ,ITEM_U ,ITEM_V ,ITEM_W ,ITEM_X ,ITEM_Y ,ITEM_Z
+
+ );
+
+const
+ dir_slash = '/';
+
+ pageEqHigh : shortstring =
+ #1#2#3#4#5#6#7#8#9#10#11#12#13#14#15#16 +
+ #17#18#19#20#21#22#23#24#25#26#27#28#29#30#31#32 +
+ #33#34#35#36#37#38#39#40#41#42#43#44#45#46#47#48 +
+ #49#50#51#52#53#54#55#56#57#58#59#60#61#62#63#64 +
+ #65#66#67#68#69#70#71#72#73#74#75#76#77#78#79#80 +
+ #81#82#83#84#85#86#87#88#89#90#91#92#93#94#95#96 +
+ #65#66#67#68#69#70#71#72#73#74#75#76#77#78#79#80 +
+ #81#82#83#84#85#86#87#88#89#90#123#124#125#126#127#128 +
+ #129#130#131#132#133#134#135#136#137#138#139#140#141#142#143#144 +
+ #145#146#147#148#149#150#151#152#153#154#155#156#157#158#159#160 +
+ #161#162#163#164#165#166#167#168#169#170#171#172#173#174#175#176 +
+ #177#178#179#180#181#182#183#184#185#186#187#188#189#190#191#192 +
+ #193#194#195#196#197#198#199#200#201#202#203#204#205#206#207#208 +
+ #209#210#211#212#213#214#215#216#217#218#219#220#221#222#223#224 +
+ #225#226#227#228#229#230#231#232#233#234#235#236#237#238#239#240 +
+ #241#242#243#244#245#246#247#248#249#250#251#252#253#254#255;
+
+{ UNIT IMPLEMENTATION }
+{ CUT_STR }
+function cut_str;
+var
+ fcb : byte;
+ scn : tSCAN;
+
+begin
+ result:='';
+
+ scn:=SCAN_1;
+
+ if length(s ) > 0 then
+ for fcb:=length(s ) downto 1 do
+ case scn of
+ SCAN_1 :
+ case s[fcb ] of
+ ' ' :
+ else
+ begin
+ result:=s[fcb ];
+
+ scn:=SCAN_2;
+
+ end;
+
+ end;
+
+ SCAN_2 :
+ result:=s[fcb ] + result;
+
+ end;
+
+end;
+
+{ CMP_STR }
+function cmp_str;
+begin
+ cmp_str:=up_str(cut_str(s ) );
+
+end;
+
+{ UP_STR }
+function up_str;
+var
+ fcb : byte;
+
+begin
+ if length(s ) > 0 then
+ for fcb:=1 to length(s ) do
+ if byte(s[fcb ] ) > 0 then
+ s[fcb ]:=pageEqHigh[byte(s[fcb ] ) ];
+
+ result:=s;
+
+end;
+
+{ STR_DIR }
+function str_dir;
+begin
+ s:=cut_str(s );
+
+ if length(s ) > 0 then
+ if s[length(s ) ] <> dir_slash then
+ s:=s + dir_slash;
+
+ result:=s;
+
+end;
+
+{ DIR_STR }
+function dir_str;
+begin
+ s:=cut_str(s );
+
+ if length(s ) > 0 then
+ if s[length(s ) ] = dir_slash then
+ dec(byte(s[0 ] ) );
+
+ result:=s;
+
+end;
+
+{ STR_DISK }
+function str_disk;
+var
+ fcb : byte;
+ str : shortstring;
+ itm : tITEM;
+
+begin
+ str:='';
+ itm:=ITEM_1;
+
+ if length(fn ) > 0 then
+ for fcb:=1 to length(fn ) do
+ case itm of
+ ITEM_1 :
+ case fn[fcb ] of
+ 'a'..'z' ,'A'..'Z' :
+ begin
+ str:=fn[fcb ];
+ itm:=ITEM_2;
+
+ end;
+
+ '\' ,'/' :
+ begin
+ str:=fn[fcb ];
+ itm:=ITEM_3;
+
+ end;
+
+ else
+ break;
+
+ end;
+
+ ITEM_2 :
+ case fn[fcb ] of
+ ':' :
+ begin
+ str:=str + fn[fcb ];
+ itm:=ITEM_F;
+
+ break;
+
+ end;
+
+ else
+ break;
+
+ end;
+
+ ITEM_3 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ str:=str + fn[fcb ];
+ itm:=ITEM_4;
+
+ end;
+
+ else
+ break;
+
+ end;
+
+ ITEM_4 :
+ case fn[fcb ] of
+ '\' ,'/' ,':' ,'<' ,'>' ,'.' ,'"' ,'|' ,#0..#31 :
+ break;
+
+ else
+ begin
+ str:=str + fn[fcb ];
+ itm:=ITEM_F;
+
+ end;
+
+ end;
+
+ ITEM_F :
+ case fn[fcb ] of
+ '\' ,'/' :
+ break;
+
+ else
+ str:=str + fn[fcb ];
+
+ end;
+
+ end;
+
+ if itm = ITEM_F then
+ result:=str
+ else
+ result:='';
+
+end;
+
+{ STR_PATH }
+function str_path;
+var
+ fcb : byte;
+ pth ,
+ str : shortstring;
+ itm : tITEM;
+
+begin
+ pth:='';
+ str:='';
+ itm:=ITEM_1;
+
+ if length(fn ) > 0 then
+ for fcb:=1 to length(fn ) do
+ case itm of
+ ITEM_1 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ str:=fn[fcb ];
+ itm:=ITEM_2;
+
+ end;
+
+ else
+ begin
+ str:=fn[fcb ];
+ itm:=ITEM_3;
+
+ end;
+
+ end;
+
+ ITEM_2 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ str:=str + fn[fcb ];
+ itm:=ITEM_3;
+
+ end;
+
+ else
+ begin
+ pth:=str;
+ str:=fn[fcb ];
+ itm:=ITEM_A;
+
+ end;
+
+ end;
+
+ ITEM_3 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ pth:=fn[fcb ];
+ str:='';
+ itm:=ITEM_A;
+
+ end;
+
+ else
+ str:=str + fn[fcb ];
+
+ end;
+
+ ITEM_A :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ pth:=pth + str + fn[fcb ];
+ str:='';
+
+ end;
+
+ else
+ str:=str + fn[fcb ];
+
+ end;
+
+ end;
+
+ result:=pth;
+
+end;
+
+{ STR_NAME }
+function str_name;
+var
+ fcb : byte;
+ str ,
+ ext : shortstring;
+ itm : tITEM;
+
+begin
+ str:='';
+ ext:='';
+ itm:=ITEM_1;
+
+ if length(fn ) > 0 then
+ for fcb:=1 to length(fn ) do
+ case itm of
+ ITEM_1 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ itm:=ITEM_2;
+
+ 'a'..'z' ,'A'..'Z' :
+ begin
+ ext:=fn[fcb ];
+ itm:=ITEM_4;
+
+ end;
+
+ '.' :
+ begin
+ str:='';
+ ext:=fn[fcb ];
+ itm:=ITEM_B;
+
+ end;
+
+ else
+ begin
+ str:=fn[fcb ];
+ itm:=ITEM_A;
+
+ end;
+
+ end;
+
+ ITEM_2 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ itm:=ITEM_3;
+
+ '.' :
+ begin
+ str:='';
+ ext:=fn[fcb ];
+ itm:=ITEM_B;
+
+ end;
+
+ else
+ begin
+ str:=fn[fcb ];
+ itm:=ITEM_A;
+
+ end;
+
+ end;
+
+ ITEM_3 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ str:='';
+ itm:=ITEM_A;
+
+ end;
+
+ end;
+
+ ITEM_4 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ str:='';
+ itm:=ITEM_A;
+
+ end;
+
+ ':' :
+ itm:=ITEM_5;
+
+ '.' :
+ begin
+ str:=ext;
+ ext:=fn[fcb ];
+ itm:=ITEM_B;
+
+ end;
+
+ else
+ begin
+ str:=ext + fn[fcb ];
+ ext:='';
+ itm:=ITEM_A;
+
+ end;
+
+ end;
+
+ ITEM_5 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ str:='';
+ itm:=ITEM_A;
+
+ end;
+
+ '.' :
+ begin
+ str:='';
+ ext:=fn[fcb ];
+ itm:=ITEM_B;
+
+ end;
+
+ else
+ begin
+ str:=fn[fcb ];
+ itm:=ITEM_A;
+
+ end;
+
+ end;
+
+ ITEM_A :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ str:='';
+ ext:='';
+
+ end;
+
+ '.' :
+ begin
+ ext:=fn[fcb ];
+ itm:=ITEM_B;
+
+ end;
+
+ else
+ str:=str + fn[fcb ];
+
+ end;
+
+ ITEM_B :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ str:='';
+ ext:='';
+ itm:=ITEM_A;
+
+ end;
+
+ '.' :
+ begin
+ str:=str + ext;
+ ext:=fn[fcb ];
+
+ end;
+
+ end;
+
+ end;
+
+ result:=str;
+
+end;
+
+{ STR_EXT }
+function str_ext;
+var
+ fcb : byte;
+ ext : shortstring;
+ itm : tITEM;
+
+begin
+ ext:='';
+ itm:=ITEM_1;
+
+ if length(fn ) > 0 then
+ for fcb:=1 to length(fn ) do
+ case itm of
+ ITEM_1 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ itm:=ITEM_2;
+
+ '.' :
+ begin
+ ext:=fn[fcb ];
+ itm:=ITEM_B;
+
+ end;
+
+ else
+ itm:=ITEM_A;
+
+ end;
+
+ ITEM_2 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ itm:=ITEM_3;
+
+ '.' :
+ begin
+ ext:=fn[fcb ];
+ itm:=ITEM_B;
+
+ end;
+
+ else
+ itm:=ITEM_A;
+
+ end;
+
+ ITEM_3 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ itm:=ITEM_A;
+
+ end;
+
+ ITEM_A :
+ case fn[fcb ] of
+ '.' :
+ begin
+ ext:=fn[fcb ];
+ itm:=ITEM_B;
+
+ end;
+
+ end;
+
+ ITEM_B :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ ext:='';
+ itm:=ITEM_A;
+
+ end;
+
+ '.' :
+ ext:=fn[fcb ];
+
+ else
+ ext:=ext + fn[fcb ];
+
+ end;
+
+ end;
+
+ result:=cut_str(ext );
+
+ if result = '.' then
+ result:='';
+
+end;
+
+{ FOLD_NAME }
+function fold_name;
+var
+ dsk ,
+ nme ,
+ pth ,
+ ext : shortstring;
+
+begin
+ dsk:=str_disk(p );
+ pth:=str_dir (str_path(p ) );
+ nme:=str_name(n );
+ ext:=str_ext (x );
+
+ result:=dsk + pth + nme + ext;
+
+end;
+
+{ SPREAD_NAME }
+procedure spread_name;
+begin
+ p:=str_disk(fn ) + str_dir(str_path(fn ) );
+ n:=str_name(fn );
+ x:=str_ext (fn );
+
+end;
+
+{ FILE_EXISTS }
+function file_exists;
+var
+ f : file;
+
+begin
+ AssignFile(f ,fn );
+ reset (f );
+
+ if IOResult = 0 then
+ begin
+ close(f );
+
+ result:=true;
+
+ end
+ else
+ result:=false;
+
+end;
+
+{ DISPLAY }
+procedure display;
+var
+ dlg : DialogRef;
+ itm : DialogItemIndex;
+
+begin
+ CreateStandardAlert(
+ kAlertPlainAlert ,
+ CFStringCreateWithCStringNoCopy(
+ NIL ,'AGG Message' ,kCFStringEncodingASCII ,NIL ) ,
+ CFStringCreateWithCStringNoCopy(
+ NIL ,msg ,kCFStringEncodingASCII ,NIL ) ,
+ NIL ,
+ dlg );
+
+ RunStandardAlert(dlg ,NIL ,itm );
+
+end;
+
+var
+ mout : shortstring;
+
+{ PASC }
+function pasc;
+begin
+ if length(msg ) = 255 then
+ dec(byte(msg[0 ] ) );
+
+ mout :=msg + #0;
+ result:=PChar(@mout[1 ] );
+
+end;
+
+{ API_OPEN_FILE }
+function api_open_file;
+var
+ i : unsigned;
+
+ ossError : OSErr;
+ outStatus : OSStatus;
+ fileSpecs : FSSpec;
+
+begin
+ result:=false;
+
+ fillchar(af ,sizeof(api_file ) ,0 );
+
+ af.fileName:=fname;
+ af.isOpened:=false;
+
+{ Fill In Unicode Name }
+ for i:=1 to length(fname ) do
+ af.fName.unicode[i - 1 ]:=byte(fname[i ] );
+
+ af.fName.length:=length(fname );
+
+{ Create FSRef }
+ outStatus:=FSMakeFSSpec(0 ,0 ,fname ,fileSpecs );
+
+ if outStatus <> noErr then
+ exit;
+
+ outStatus:=FSpMakeFSRef(fileSpecs ,af.fFSRef );
+
+ if outStatus <> noErr then
+ exit;
+
+{ Open Fork }
+ FSGetDataForkName(af.fFork );
+
+ ossError:=FSOpenFork(af.fFSRef ,af.fFork.length ,af.fFork.unicode[0 ] ,fsRdPerm ,af.fRef );
+
+ if ossError = noErr then
+ begin
+ af.isOpened:=true;
+
+ FSGetForkSize(af.fRef ,af.fSize );
+
+ af.fRead:=0;
+
+ end;
+
+ result:=af.isOpened;
+
+end;
+
+{ API_READ_FILE }
+function api_read_file;
+var
+ ossError : OSStatus;
+ forkLoad : ByteCount;
+
+begin
+ result:=false;
+ read :=0;
+
+ if af.isOpened then
+ begin
+ if aloc > af.fSize - af.fRead then
+ aloc:=af.fSize - af.fRead;
+
+ ossError:=FSReadFork(af.fRef ,fsAtMark + noCacheMask ,af.fRead ,aloc ,buff ,forkLoad );
+
+ if ossError = noErr then
+ begin
+ read:=forkLoad;
+
+ inc(af.fRead ,read );
+
+ result:=true;
+
+ end;
+
+ end;
+
+end;
+
+{ API_CLOSE_FILE }
+function api_close_file;
+begin
+ result:=false;
+
+ if af.isOpened then
+ begin
+ FSCloseFork(af.fRef );
+
+ af.isOpened:=false;
+
+ result:=true;
+
+ end;
+
+end;
+
+{ PARAM_COUNT }
+function param_count;
+begin
+ result:=0;
+
+end;
+
+{ PARAM_STR }
+function param_str;
+begin
+ result:='';
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/platform/win/agg_platform_support.pas b/src/corelib/render/software/platform/win/agg_platform_support.pas
new file mode 100644
index 00000000..3c4c8b0a
--- /dev/null
+++ b/src/corelib/render/software/platform/win/agg_platform_support.pas
@@ -0,0 +1,2121 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// class platform_support
+//
+// It's not a part of the AGG library, it's just a helper class to create
+// interactive demo examples. Since the examples should not be too complex
+// this class is provided to support some very basic interactive graphical
+// funtionality, such as putting the rendered image to the window, simple
+// keyboard and mouse input, window resizing, setting the window title,
+// and catching the "idle" events.
+//
+// The most popular platforms are:
+//
+// Windows-32 API
+// X-Window API
+// SDL library (see http://www.libsdl.org/)
+// MacOS C/C++ API
+//
+// All the system dependent stuff sits in the platform_specific class.
+// The platform_support class has just a pointer to it and it's
+// the responsibility of the implementation to create/delete it.
+// This class being defined in the implementation file can have
+// any platform dependent stuff such as HWND, X11 Window and so on.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 16.12.2005-Milano: platform_specific
+// 15.12.2005-Milano: platform_support
+// 12.12.2005-Milano: Unit port establishment
+//
+{ agg_platform_support.pas }
+unit
+ agg_platform_support ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+{$I- }
+uses
+ Windows ,Messages ,
+ agg_basics ,
+ agg_ctrl ,
+ agg_rendering_buffer ,
+ agg_trans_affine ,
+ agg_trans_viewport ,
+ agg_win32_bmp ,
+ agg_color_conv ;
+
+{ TYPES DEFINITION }
+const
+//----------------------------------------------------------window_flag_e
+// These are flags used in method init(). Not all of them are
+// applicable on different platforms, for example the win32_api
+// cannot use a hardware buffer (window_hw_buffer).
+// The implementation should simply ignore unsupported flags.
+ window_resize = 1;
+ window_hw_buffer = 2;
+ window_keep_aspect_ratio = 4;
+ window_process_all_keys = 8;
+
+type
+//-----------------------------------------------------------pix_format_e
+// Possible formats of the rendering buffer. Initially I thought that it's
+// reasonable to create the buffer and the rendering functions in
+// accordance with the native pixel format of the system because it
+// would have no overhead for pixel format conersion.
+// But eventually I came to a conclusion that having a possibility to
+// convert pixel formats on demand is a good idea. First, it was X11 where
+// there lots of different formats and visuals and it would be great to
+// render everything in, say, RGB-24 and display it automatically without
+// any additional efforts. The second reason is to have a possibility to
+// debug renderers for different pixel formats and colorspaces having only
+// one computer and one system.
+//
+// This stuff is not included into the basic AGG functionality because the
+// number of supported pixel formats (and/or colorspaces) can be great and
+// if one needs to add new format it would be good only to add new
+// rendering files without having to modify any existing ones (a general
+// principle of incapsulation and isolation).
+//
+// Using a particular pixel format doesn't obligatory mean the necessity
+// of software conversion. For example, win32 API can natively display
+// gray8, 15-bit RGB, 24-bit BGR, and 32-bit BGRA formats.
+// This list can be (and will be!) extended in future.
+ pix_format_e = (
+
+ pix_format_undefined , // By default. No conversions are applied
+ pix_format_bw, // 1 bit per color B/W
+ pix_format_gray8, // Simple 256 level grayscale
+ pix_format_gray16, // Simple 65535 level grayscale
+ pix_format_rgb555, // 15 bit rgb. Depends on the byte ordering!
+ pix_format_rgb565, // 16 bit rgb. Depends on the byte ordering!
+ pix_format_rgbAAA, // 30 bit rgb. Depends on the byte ordering!
+ pix_format_rgbBBA, // 32 bit rgb. Depends on the byte ordering!
+ pix_format_bgrAAA, // 30 bit bgr. Depends on the byte ordering!
+ pix_format_bgrABB, // 32 bit bgr. Depends on the byte ordering!
+ pix_format_rgb24, // R-G-B, one byte per color component
+ pix_format_bgr24, // B-G-R, native win32 BMP format.
+ pix_format_rgba32, // R-G-B-A, one byte per color component
+ pix_format_argb32, // A-R-G-B, native MAC format
+ pix_format_abgr32, // A-B-G-R, one byte per color component
+ pix_format_bgra32, // B-G-R-A, native win32 BMP format
+ pix_format_rgb48, // R-G-B, 16 bits per color component
+ pix_format_bgr48, // B-G-R, native win32 BMP format.
+ pix_format_rgba64, // R-G-B-A, 16 bits byte per color component
+ pix_format_argb64, // A-R-G-B, native MAC format
+ pix_format_abgr64, // A-B-G-R, one byte per color component
+ pix_format_bgra64, // B-G-R-A, native win32 BMP format
+
+ end_of_pix_formats );
+
+const
+//-------------------------------------------------------------input_flag_e
+// Mouse and keyboard flags. They can be different on different platforms
+// and the ways they are obtained are also different. But in any case
+// the system dependent flags should be mapped into these ones. The meaning
+// of that is as follows. For example, if kbd_ctrl is set it means that the
+// ctrl key is pressed and being held at the moment. They are also used in
+// the overridden methods such as on_mouse_move(), on_mouse_button_down(),
+// on_mouse_button_dbl_click(), on_mouse_button_up(), on_key().
+// In the method on_mouse_button_up() the mouse flags have different
+// meaning. They mean that the respective button is being released, but
+// the meaning of the keyboard flags remains the same.
+// There's absolut minimal set of flags is used because they'll be most
+// probably supported on different platforms. Even the mouse_right flag
+// is restricted because Mac's mice have only one button, but AFAIK
+// it can be simulated with holding a special key on the keydoard.
+ mouse_left = 1;
+ mouse_right = 2;
+ kbd_shift = 4;
+ kbd_ctrl = 8;
+
+//--------------------------------------------------------------key_code_e
+// Keyboard codes. There's also a restricted set of codes that are most
+// probably supported on different platforms. Any platform dependent codes
+// should be converted into these ones. There're only those codes are
+// defined that cannot be represented as printable ASCII-characters.
+// All printable ASCII-set can be used in a regilar C/C++ manner:
+// ' ', 'A', '0' '+' and so on.
+// Since the clasas is used for creating very simple demo-applications
+// we don't need very rich possibilities here, just basic ones.
+// Actually the numeric key codes are taken from the SDL library, so,
+// the implementation of the SDL support does not require any mapping.
+// ASCII set. Should be supported everywhere
+ key_backspace = 8;
+ key_tab = 9;
+ key_clear = 12;
+ key_return = 13;
+ key_pause = 19;
+ key_escape = 27;
+
+// Keypad
+ key_delete = 127;
+ key_kp0 = 256;
+ key_kp1 = 257;
+ key_kp2 = 258;
+ key_kp3 = 259;
+ key_kp4 = 260;
+ key_kp5 = 261;
+ key_kp6 = 262;
+ key_kp7 = 263;
+ key_kp8 = 264;
+ key_kp9 = 265;
+ key_kp_period = 266;
+ key_kp_divide = 267;
+ key_kp_multiply = 268;
+ key_kp_minus = 269;
+ key_kp_plus = 270;
+ key_kp_enter = 271;
+ key_kp_equals = 272;
+
+// Arrow-keys and stuff
+ key_up = 273;
+ key_down = 274;
+ key_right = 275;
+ key_left = 276;
+ key_insert = 277;
+ key_home = 278;
+ key_end = 279;
+ key_page_up = 280;
+ key_page_down = 281;
+
+// Functional keys. You'd better avoid using
+// f11...f15 in your applications if you want
+// the applications to be portable
+ key_f1 = 282;
+ key_f2 = 283;
+ key_f3 = 284;
+ key_f4 = 285;
+ key_f5 = 286;
+ key_f6 = 287;
+ key_f7 = 288;
+ key_f8 = 289;
+ key_f9 = 290;
+ key_f10 = 291;
+ key_f11 = 292;
+ key_f12 = 293;
+ key_f13 = 294;
+ key_f14 = 295;
+ key_f15 = 296;
+
+// The possibility of using these keys is
+// very restricted. Actually it's guaranteed
+// only in win32_api and win32_sdl implementations
+ key_numlock = 300;
+ key_capslock = 301;
+ key_scrollock = 302;
+
+ max_ctrl = 128;
+
+type
+//----------------------------------------------------------ctrl_container
+// A helper class that contains pointers to a number of controls.
+// This class is used to ease the event handling with controls.
+// The implementation should simply call the appropriate methods
+// of this class when appropriate events occure.
+ crtl_container_ptr = ^ctrl_container;
+ ctrl_container = object
+ m_ctrl : array[0..max_ctrl - 1 ] of ctrl_ptr;
+
+ m_num_ctrl : unsigned;
+ m_cur_ctrl : int;
+
+ constructor Construct;
+ destructor Destruct;
+
+ procedure add(c : ctrl_ptr );
+
+ function in_rect(x ,y : double ) : boolean;
+
+ function on_mouse_button_down(x ,y : double ) : boolean;
+ function on_mouse_button_up (x ,y : double ) : boolean;
+
+ function on_mouse_move(x ,y : double; button_flag : boolean ) : boolean;
+ function on_arrow_keys(left ,right ,down ,up : boolean ) : boolean;
+
+ function set_cur(x ,y : double ) : boolean;
+
+ end;
+
+//---------------------------------------------------------platform_support
+// This class is a base one to the apllication classes. It can be used
+// as follows:
+//
+// the_application = object(platform_support )
+//
+// constructor Construct(bpp : unsigned; flip_y : boolean );
+// . . .
+//
+// //override stuff . . .
+// procedure on_init; virtual;
+// procedure on_draw; virtual;
+// procedure on_resize(sx ,sy : int ); virtual;
+// // . . . and so on, see virtual functions
+//
+// //any your own stuff . . .
+// };
+//
+// VAR
+// app : the_application;
+//
+// BEGIN
+// app.Construct(pix_format_rgb24 ,true );
+// app.caption ("AGG Example. Lion" );
+//
+// if app.init(500 ,400 ,window_resize ) then
+// app.run;
+//
+// app.Destruct;
+//
+// END.
+//
+const
+ max_images = 16;
+
+var
+// Hmmm, I had to rip the fields below out of the platform_specific object,
+// because being them the part of that object/class, the corresponding
+// Windows API calls QueryPerformanceXXX are working NOT!.
+// Anyway, since we use usually only one instance of platform_specific in
+// our agg demos, it's okay to do that this way. See {hack}.
+ m_sw_freq ,
+ m_sw_start : int64;
+
+type
+ platform_specific_ptr = ^platform_specific;
+ platform_specific = object
+ m_format ,
+ m_sys_format : pix_format_e;
+
+ m_flip_y : boolean;
+ m_bpp ,
+ m_sys_bpp : unsigned;
+ m_hwnd : HWND;
+
+ m_pmap_window : pixel_map;
+ m_pmap_img : array[0..max_images - 1 ] of pixel_map;
+
+ m_keymap : array[0..255 ] of unsigned;
+
+ m_last_translated_key : unsigned;
+
+ m_cur_x ,
+ m_cur_y : int;
+
+ m_input_flags : unsigned;
+ m_redraw_flag : boolean;
+ m_current_dc : HDC;
+
+ //m_sw_freq ,
+ //m_sw_start : int64;{hack}
+
+ constructor Construct(format : pix_format_e; flip_y : boolean );
+ destructor Destruct; {OpenCPL++} virtual; {/OpenCPL++}
+
+ procedure create_pmap (width ,height : unsigned; wnd : rendering_buffer_ptr ); {OpenCPL++} virtual; {/OpenCPL++}
+ procedure display_pmap(dc : HDC; src : rendering_buffer_ptr ); {OpenCPL++} virtual; {/OpenCPL++}
+
+ function load_pmap(fn : shortstring; idx : unsigned; dst : rendering_buffer_ptr ) : boolean;
+ function save_pmap(fn : shortstring; idx : unsigned; src : rendering_buffer_ptr ) : boolean;
+
+ function translate(keycode : unsigned ) : unsigned;
+
+ end;
+
+ platform_support_ptr = ^platform_support;
+ platform_support = object
+ m_specific : platform_specific_ptr;
+ m_ctrls : ctrl_container;
+
+ m_format : pix_format_e;
+
+ m_bpp : unsigned;
+
+ m_rbuf_window : rendering_buffer;
+ m_rbuf_img : array[0..max_images - 1 ] of rendering_buffer;
+
+ m_window_flags : unsigned;
+ m_wait_mode ,
+ m_flip_y : boolean; // flip_y - true if you want to have the Y-axis flipped vertically
+ m_caption : shortstring;
+ m_resize_mtx : trans_affine;
+
+ m_initial_width ,
+ m_initial_height : int;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean; {OpenCPL++} specific : platform_specific_ptr = NIL {/OpenCPL++} );
+ destructor Destruct;
+
+ // Setting the windows caption (title). Should be able
+ // to be called at least before calling init().
+ // It's perfect if they can be called anytime.
+ procedure caption_(cap : shortstring );
+
+ // These 3 menthods handle working with images. The image
+ // formats are the simplest ones, such as .BMP in Windows or
+ // .ppm in Linux. In the applications the names of the files
+ // should not have any file extensions. Method load_img() can
+ // be called before init(), so, the application could be able
+ // to determine the initial size of the window depending on
+ // the size of the loaded image.
+ // The argument "idx" is the number of the image 0...max_images-1
+ function load_img (idx : unsigned; file_ : shortstring ) : boolean;
+ function save_img (idx : unsigned; file_ : shortstring ) : boolean;
+ function create_img(idx : unsigned; width_ : unsigned = 0; height_ : unsigned = 0 ) : boolean;
+
+ // init() and run(). See description before the class for details.
+ // The necessity of calling init() after creation is that it's
+ // impossible to call the overridden virtual function (on_init())
+ // from the constructor. On the other hand it's very useful to have
+ // some on_init() event handler when the window is created but
+ // not yet displayed. The rbuf_window() method (see below) is
+ // accessible from on_init().
+ function init(width_ ,height_ ,flags : unsigned ) : boolean;
+ function run : int;
+ procedure quit;
+
+ // The very same parameters that were used in the constructor
+ function _format : pix_format_e;
+ function _flip_y : boolean;
+ function _bpp : unsigned;
+
+ // The following provides a very simple mechanism of doing someting
+ // in background. It's not multitheading. When whait_mode is true
+ // the class waits for the events and it does not ever call on_idle().
+ // When it's false it calls on_idle() when the event queue is empty.
+ // The mode can be changed anytime. This mechanism is satisfactory
+ // for creation very simple animations.
+ function _wait_mode : boolean;
+ procedure wait_mode_(wait_mode : boolean );
+
+ // These two functions control updating of the window.
+ // force_redraw() is an analog of the Win32 InvalidateRect() function.
+ // Being called it sets a flag (or sends a message) which results
+ // in calling on_draw() and updating the content of the window
+ // when the next event cycle comes.
+ // update_window() results in just putting immediately the content
+ // of the currently rendered buffer to the window without calling
+ // on_draw().
+ procedure force_redraw;
+ procedure update_window;
+
+ // So, finally, how to draw anythig with AGG? Very simple.
+ // rbuf_window() returns a reference to the main rendering
+ // buffer which can be attached to any rendering class.
+ // rbuf_img() returns a reference to the previously created
+ // or loaded image buffer (see load_img()). The image buffers
+ // are not displayed directly, they should be copied to or
+ // combined somehow with the rbuf_window(). rbuf_window() is
+ // the only buffer that can be actually displayed.
+ function rbuf_window : rendering_buffer_ptr;
+ function rbuf_img(idx : unsigned ) : rendering_buffer_ptr;
+
+ // Returns file extension used in the implemenation for the particular
+ // system.
+ function _img_ext : shortstring;
+
+ //
+ procedure copy_img_to_window(idx : unsigned );
+ procedure copy_window_to_img(idx : unsigned );
+ procedure copy_img_to_img (idx_to ,idx_from : unsigned );
+
+ // Event handlers. They are not pure functions, so you don't have
+ // to override them all.
+ // In my demo applications these functions are defined inside
+ // the the_application class
+ procedure on_init; virtual;
+ procedure on_resize(sx ,sy : int ); virtual;
+ procedure on_idle; virtual;
+
+ procedure on_mouse_move(x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_up (x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+ procedure on_ctrl_change; virtual;
+ procedure on_draw; virtual;
+ procedure on_post_draw(raw_handler : pointer ); virtual;
+
+ // Adding control elements. A control element once added will be
+ // working and reacting to the mouse and keyboard events. Still, you
+ // will have to render them in the on_draw() using function
+ // render_ctrl() because platform_support doesn't know anything about
+ // renderers you use. The controls will be also scaled automatically
+ // if they provide a proper scaling mechanism (all the controls
+ // included into the basic AGG package do).
+ // If you don't need a particular control to be scaled automatically
+ // call ctrl::no_transform() after adding.
+ procedure add_ctrl(c : ctrl_ptr );
+
+ // Auxiliary functions. trans_affine_resizing() modifier sets up the resizing
+ // matrix on the basis of the given width and height and the initial
+ // width and height of the window. The implementation should simply
+ // call this function every time when it catches the resizing event
+ // passing in the new values of width and height of the window.
+ // Nothing prevents you from "cheating" the scaling matrix if you
+ // call this function from somewhere with wrong arguments.
+ // trans_affine_resizing() accessor simply returns current resizing matrix
+ // which can be used to apply additional scaling of any of your
+ // stuff when the window is being resized.
+ // width(), height(), initial_width(), and initial_height() must be
+ // clear to understand with no comments :-)
+ procedure trans_affine_resizing_(width_ ,height_ : int );
+ function _trans_affine_resizing : trans_affine_ptr;
+
+ function _width : double;
+ function _height : double;
+ function _initial_width : double;
+ function _initial_height : double;
+ function _window_flags : unsigned;
+
+ // Get raw display handler depending on the system.
+ // For win32 its an HDC, for other systems it can be a pointer to some
+ // structure. See the implementation files for detals.
+ // It's provided "as is", so, first you should check if it's not null.
+ // If it's null the raw_display_handler is not supported. Also, there's
+ // no guarantee that this function is implemented, so, in some
+ // implementations you may have simply an unresolved symbol when linking.
+ function _raw_display_handler : pointer;
+
+ // display message box or print the message to the console
+ // (depending on implementation)
+ procedure message_(msg : PChar );
+
+ // Stopwatch functions. Function elapsed_time() returns time elapsed
+ // since the latest start_timer() invocation in millisecods.
+ // The resolutoin depends on the implementation.
+ // In Win32 it uses QueryPerformanceFrequency() / QueryPerformanceCounter().
+ procedure start_timer;
+ function elapsed_time : double;
+
+ // Get the full file name. In most cases it simply returns
+ // file_name. As it's appropriate in many systems if you open
+ // a file by its name without specifying the path, it tries to
+ // open it in the current directory. The demos usually expect
+ // all the supplementary files to be placed in the current
+ // directory, that is usually coincides with the directory where
+ // the the executable is. However, in some systems (BeOS) it's not so.
+ // For those kinds of systems full_file_name() can help access files
+ // preserving commonly used policy.
+ // So, it's a good idea to use in the demos the following:
+ // FILE* fd = fopen(full_file_name("some.file"), "r");
+ // instead of
+ // FILE* fd = fopen("some.file", "r");
+ function full_file_name(file_name : shortstring ) : shortstring;
+ function file_source (path ,fname : shortstring ) : shortstring;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor ctrl_container.Construct;
+begin
+ m_num_ctrl:=0;
+ m_cur_ctrl:=-1;
+
+end;
+
+{ DESTRUCT }
+destructor ctrl_container.Destruct;
+begin
+end;
+
+{ ADD }
+procedure ctrl_container.add;
+begin
+ if m_num_ctrl < max_ctrl then
+ begin
+ m_ctrl[m_num_ctrl ]:=c;
+
+ inc(m_num_ctrl );
+
+ end;
+
+end;
+
+{ IN_RECT }
+function ctrl_container.in_rect;
+var
+ i : unsigned;
+
+begin
+ result:=false;
+
+ if m_num_ctrl > 0 then
+ for i:=0 to m_num_ctrl - 1 do
+ if m_ctrl[i ].in_rect(x ,y ) then
+ begin
+ result:=true;
+
+ exit;
+
+ end;
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+function ctrl_container.on_mouse_button_down;
+var
+ i : unsigned;
+
+begin
+ result:=false;
+
+ if m_num_ctrl > 0 then
+ for i:=0 to m_num_ctrl - 1 do
+ if m_ctrl[i ].on_mouse_button_down(x ,y ) then
+ begin
+ result:=true;
+
+ exit;
+
+ end;
+
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+function ctrl_container.on_mouse_button_up;
+var
+ i : unsigned;
+
+begin
+ result:=false;
+
+ if m_num_ctrl > 0 then
+ for i:=0 to m_num_ctrl - 1 do
+ if m_ctrl[i ].on_mouse_button_up(x ,y ) then
+ begin
+ result:=true;
+
+ exit;
+
+ end;
+
+end;
+
+{ ON_MOUSE_MOVE }
+function ctrl_container.on_mouse_move;
+var
+ i : unsigned;
+
+begin
+ result:=false;
+
+ if m_num_ctrl > 0 then
+ for i:=0 to m_num_ctrl - 1 do
+ if m_ctrl[i ].on_mouse_move(x ,y ,button_flag ) then
+ begin
+ result:=true;
+
+ exit;
+
+ end;
+
+end;
+
+{ ON_ARROW_KEYS }
+function ctrl_container.on_arrow_keys;
+begin
+ result:=false;
+
+ if m_cur_ctrl >= 0 then
+ result:=m_ctrl[m_cur_ctrl ].on_arrow_keys(left ,right ,down ,up );
+
+end;
+
+{ SET_CUR }
+function ctrl_container.set_cur;
+var
+ i : unsigned;
+
+begin
+ result:=false;
+
+ if m_num_ctrl > 0 then
+ for i:=0 to m_num_ctrl - 1 do
+ if m_ctrl[i ].in_rect(x ,y ) then
+ begin
+ if m_cur_ctrl <> i then
+ begin
+ m_cur_ctrl:=i;
+
+ result:=true;
+
+ end;
+
+ exit;
+
+ end;
+
+ if m_cur_ctrl <> -1 then
+ begin
+ m_cur_ctrl:=-1;
+
+ result:=true;
+
+ end;
+
+end;
+
+{ CONSTRUCT }
+constructor platform_specific.Construct;
+var
+ i : unsigned;
+
+begin
+ m_pmap_window.Construct;
+
+ for i:=0 to max_images - 1 do
+ m_pmap_img[i ].Construct;
+
+ m_format :=format;
+ m_sys_format:=pix_format_undefined;
+
+ m_flip_y :=flip_y;
+ m_bpp :=0;
+ m_sys_bpp:=0;
+ m_hwnd :=0;
+
+ m_last_translated_key:=0;
+
+ m_cur_x:=0;
+ m_cur_y:=0;
+
+ m_input_flags:=0;
+ m_redraw_flag:=true;
+ m_current_dc :=0;
+
+ fillchar(m_keymap[0 ] ,sizeof(m_keymap ) ,0 );
+
+ m_keymap[VK_PAUSE ]:=key_pause;
+ m_keymap[VK_CLEAR ]:=key_clear;
+
+ m_keymap[VK_NUMPAD0 ] :=key_kp0;
+ m_keymap[VK_NUMPAD1 ] :=key_kp1;
+ m_keymap[VK_NUMPAD2 ] :=key_kp2;
+ m_keymap[VK_NUMPAD3 ] :=key_kp3;
+ m_keymap[VK_NUMPAD4 ] :=key_kp4;
+ m_keymap[VK_NUMPAD5 ] :=key_kp5;
+ m_keymap[VK_NUMPAD6 ] :=key_kp6;
+ m_keymap[VK_NUMPAD7 ] :=key_kp7;
+ m_keymap[VK_NUMPAD8 ] :=key_kp8;
+ m_keymap[VK_NUMPAD9 ] :=key_kp9;
+ m_keymap[VK_DECIMAL ] :=key_kp_period;
+ m_keymap[VK_DIVIDE ] :=key_kp_divide;
+ m_keymap[VK_MULTIPLY ]:=key_kp_multiply;
+ m_keymap[VK_SUBTRACT ]:=key_kp_minus;
+ m_keymap[VK_ADD ] :=key_kp_plus;
+
+ m_keymap[VK_UP ] :=key_up;
+ m_keymap[VK_DOWN ] :=key_down;
+ m_keymap[VK_RIGHT ] :=key_right;
+ m_keymap[VK_LEFT ] :=key_left;
+ m_keymap[VK_INSERT ]:=key_insert;
+ m_keymap[VK_DELETE ]:=key_delete;
+ m_keymap[VK_HOME ] :=key_home;
+ m_keymap[VK_END ] :=key_end;
+ m_keymap[VK_PRIOR ] :=key_page_up;
+ m_keymap[VK_NEXT ] :=key_page_down;
+
+ m_keymap[VK_F1 ] :=key_f1;
+ m_keymap[VK_F2 ] :=key_f2;
+ m_keymap[VK_F3 ] :=key_f3;
+ m_keymap[VK_F4 ] :=key_f4;
+ m_keymap[VK_F5 ] :=key_f5;
+ m_keymap[VK_F6 ] :=key_f6;
+ m_keymap[VK_F7 ] :=key_f7;
+ m_keymap[VK_F8 ] :=key_f8;
+ m_keymap[VK_F9 ] :=key_f9;
+ m_keymap[VK_F10 ]:=key_f10;
+ m_keymap[VK_F11 ]:=key_f11;
+ m_keymap[VK_F12 ]:=key_f12;
+ m_keymap[VK_F13 ]:=key_f13;
+ m_keymap[VK_F14 ]:=key_f14;
+ m_keymap[VK_F15 ]:=key_f15;
+
+ m_keymap[VK_NUMLOCK ]:=key_numlock;
+ m_keymap[VK_CAPITAL ]:=key_capslock;
+ m_keymap[VK_SCROLL ] :=key_scrollock;
+
+ case m_format of
+ pix_format_bw :
+ begin
+ m_sys_format:=pix_format_bw;
+ m_bpp :=1;
+ m_sys_bpp :=1;
+
+ end;
+
+ pix_format_gray8 :
+ begin
+ m_sys_format:=pix_format_bgr24;//pix_format_gray8;{hack}
+ m_bpp :=8;
+ m_sys_bpp :=24;//8;
+
+ end;
+
+ pix_format_gray16 :
+ begin
+ m_sys_format:=pix_format_gray8;
+ m_bpp :=16;
+ m_sys_bpp :=8;
+
+ end;
+
+ pix_format_rgb565 ,
+ pix_format_rgb555 :
+ begin
+ m_sys_format:=pix_format_rgb555;
+ m_bpp :=16;
+ m_sys_bpp :=16;
+
+ end;
+
+ pix_format_rgbAAA ,
+ pix_format_bgrAAA ,
+ pix_format_rgbBBA ,
+ pix_format_bgrABB :
+ begin
+ m_sys_format:=pix_format_bgr24;
+ m_bpp :=32;
+ m_sys_bpp :=24;
+
+ end;
+
+ pix_format_rgb24 ,
+ pix_format_bgr24 :
+ begin
+ m_sys_format:=pix_format_bgr24;
+ m_bpp :=24;
+ m_sys_bpp :=24;
+
+ end;
+
+ pix_format_rgb48 ,
+ pix_format_bgr48 :
+ begin
+ m_sys_format:=pix_format_bgr24;
+ m_bpp :=48;
+ m_sys_bpp :=24;
+
+ end;
+
+ pix_format_bgra32 ,
+ pix_format_abgr32 ,
+ pix_format_argb32 ,
+ pix_format_rgba32 :
+ begin
+ m_sys_format:=pix_format_bgra32;
+ m_bpp :=32;
+ m_sys_bpp :=32;
+
+ end;
+
+ pix_format_bgra64 ,
+ pix_format_abgr64 ,
+ pix_format_argb64 ,
+ pix_format_rgba64 :
+ begin
+ m_sys_format:=pix_format_bgra32;
+ m_bpp :=64;
+ m_sys_bpp :=32;
+
+ end;
+
+ end;
+
+ QueryPerformanceFrequency(m_sw_freq );{hack}
+ QueryPerformanceCounter (m_sw_start );
+
+end;
+
+{ DESTRUCT }
+destructor platform_specific.Destruct;
+var
+ i : unsigned;
+
+begin
+ m_pmap_window.Destruct;
+
+ for i:=0 to max_images - 1 do
+ m_pmap_img[i ].Destruct;
+
+end;
+
+{ CREATE_PMAP }
+procedure platform_specific.create_pmap;
+begin
+ m_pmap_window.create(width ,height ,m_bpp );
+
+ if m_flip_y then
+ wnd.attach(
+ m_pmap_window._buf ,
+ m_pmap_window._width ,
+ m_pmap_window._height ,
+ m_pmap_window._stride )
+
+ else
+ wnd.attach(
+ m_pmap_window._buf ,
+ m_pmap_window._width ,
+ m_pmap_window._height ,
+ -m_pmap_window._stride )
+
+end;
+
+{ convert_pmap }
+procedure convert_pmap(dst ,src : rendering_buffer_ptr; format : pix_format_e );
+begin
+ case format of
+ pix_format_gray8 :
+ color_conv(dst ,src ,color_conv_gray8_to_bgr24 );
+
+ pix_format_gray16 :
+ color_conv(dst ,src ,color_conv_gray16_to_gray8 );
+
+ pix_format_rgb565 :
+ color_conv(dst ,src ,color_conv_rgb565_to_rgb555 );
+
+ pix_format_rgbAAA :
+ color_conv(dst ,src ,color_conv_rgbAAA_to_bgr24 );
+
+ pix_format_bgrAAA :
+ color_conv(dst ,src ,color_conv_bgrAAA_to_bgr24 );
+
+ pix_format_rgbBBA :
+ color_conv(dst ,src ,color_conv_rgbBBA_to_bgr24 );
+
+ pix_format_bgrABB :
+ color_conv(dst ,src ,color_conv_bgrABB_to_bgr24 );
+
+ pix_format_rgb24 :
+ color_conv(dst ,src ,color_conv_rgb24_to_bgr24 );
+
+ pix_format_rgb48 :
+ color_conv(dst ,src ,color_conv_rgb48_to_bgr24 );
+
+ pix_format_bgr48 :
+ color_conv(dst ,src ,color_conv_bgr48_to_bgr24 );
+
+ pix_format_abgr32 :
+ color_conv(dst ,src ,color_conv_abgr32_to_bgra32 );
+
+ pix_format_argb32 :
+ color_conv(dst ,src ,color_conv_argb32_to_bgra32 );
+
+ pix_format_rgba32 :
+ color_conv(dst ,src ,color_conv_rgba32_to_bgra32 );
+
+ pix_format_bgra64 :
+ color_conv(dst ,src ,color_conv_bgra64_to_bgra32 );
+
+ pix_format_abgr64 :
+ color_conv(dst ,src ,color_conv_abgr64_to_bgra32 );
+
+ pix_format_argb64 :
+ color_conv(dst ,src ,color_conv_argb64_to_bgra32 );
+
+ pix_format_rgba64 :
+ color_conv(dst ,src ,color_conv_rgba64_to_bgra32 );
+
+ end;
+
+end;
+
+{ DISPLAY_PMAP }
+procedure platform_specific.display_pmap;
+var
+ pmap_tmp : pixel_map;
+ rbuf_tmp : rendering_buffer;
+
+begin
+ if m_sys_format = m_format then
+ m_pmap_window.draw(dc )
+
+ else
+ begin
+ pmap_tmp.Construct;
+ pmap_tmp.create(m_pmap_window._width ,m_pmap_window._height ,m_sys_bpp );
+
+ rbuf_tmp.Construct;
+
+ if m_flip_y then
+ rbuf_tmp.attach(pmap_tmp._buf ,pmap_tmp._width ,pmap_tmp._height ,pmap_tmp._stride )
+ else
+ rbuf_tmp.attach(pmap_tmp._buf ,pmap_tmp._width ,pmap_tmp._height ,-pmap_tmp._stride );
+
+ convert_pmap (@rbuf_tmp ,src ,m_format );
+ pmap_tmp.draw(dc );
+
+ rbuf_tmp.Destruct;
+ pmap_tmp.Destruct;
+
+ end;
+
+end;
+
+{ LOAD_PMAP }
+function platform_specific.load_pmap;
+var
+ pmap_tmp : pixel_map;
+ rbuf_tmp : rendering_buffer;
+
+begin
+ pmap_tmp.Construct;
+
+ if not pmap_tmp.load_from_bmp(fn ) then
+ begin
+ result:=false;
+
+ pmap_tmp.Destruct;
+ exit;
+
+ end;
+
+ rbuf_tmp.Construct;
+
+ if m_flip_y then
+ rbuf_tmp.attach(pmap_tmp._buf ,pmap_tmp._width ,pmap_tmp._height ,pmap_tmp._stride )
+ else
+ rbuf_tmp.attach(pmap_tmp._buf ,pmap_tmp._width ,pmap_tmp._height ,-pmap_tmp._stride );
+
+ m_pmap_img[idx ].create(pmap_tmp._width ,pmap_tmp._height ,m_bpp ,0 );
+
+ if m_flip_y then
+ dst.attach(
+ m_pmap_img[idx ]._buf ,
+ m_pmap_img[idx ]._width ,
+ m_pmap_img[idx ]._height ,
+ m_pmap_img[idx ]._stride )
+ else
+ dst.attach(
+ m_pmap_img[idx ]._buf ,
+ m_pmap_img[idx ]._width ,
+ m_pmap_img[idx ]._height ,
+ -m_pmap_img[idx ]._stride );
+
+ case m_format of
+ pix_format_gray8 :
+ case pmap_tmp._bpp of
+ 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_gray8 );
+
+ end;
+
+ pix_format_gray16 :
+ case pmap_tmp._bpp of
+ 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_gray16 );
+
+ end;
+
+ pix_format_rgb555 :
+ case pmap_tmp._bpp of
+ 16 : color_conv(dst ,@rbuf_tmp ,color_conv_rgb555_to_rgb555 );
+ 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_rgb555 );
+ 32 : color_conv(dst ,@rbuf_tmp ,color_conv_bgra32_to_rgb555 );
+
+ end;
+
+ pix_format_rgb565 :
+ case pmap_tmp._bpp of
+ 16 : color_conv(dst ,@rbuf_tmp ,color_conv_rgb555_to_rgb565 );
+ 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_rgb565 );
+ 32 : color_conv(dst ,@rbuf_tmp ,color_conv_bgra32_to_rgb565 );
+
+ end;
+
+ pix_format_rgb24 :
+ case pmap_tmp._bpp of
+ 16 : color_conv(dst ,@rbuf_tmp ,color_conv_rgb555_to_rgb24 );
+ 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_rgb24 );
+ 32 : color_conv(dst ,@rbuf_tmp ,color_conv_bgra32_to_rgb24 );
+
+ end;
+
+ pix_format_bgr24 :
+ case pmap_tmp._bpp of
+ 16 : color_conv(dst ,@rbuf_tmp ,color_conv_rgb555_to_bgr24 );
+ 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_bgr24 );
+ 32 : color_conv(dst ,@rbuf_tmp ,color_conv_bgra32_to_bgr24 );
+
+ end;
+
+ pix_format_rgb48 :
+ case pmap_tmp._bpp of
+ 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_rgb48 );
+
+ end;
+
+ pix_format_bgr48 :
+ case pmap_tmp._bpp of
+ 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_bgr48 );
+
+ end;
+
+ pix_format_abgr32 :
+ case pmap_tmp._bpp of
+ 16 : color_conv(dst ,@rbuf_tmp ,color_conv_rgb555_to_abgr32 );
+ 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_abgr32 );
+ 32 : color_conv(dst ,@rbuf_tmp ,color_conv_bgra32_to_abgr32 );
+
+ end;
+
+ pix_format_argb32 :
+ case pmap_tmp._bpp of
+ 16 : color_conv(dst ,@rbuf_tmp ,color_conv_rgb555_to_argb32 );
+ 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_argb32 );
+ 32 : color_conv(dst ,@rbuf_tmp ,color_conv_bgra32_to_argb32 );
+
+ end;
+
+ pix_format_bgra32 :
+ case pmap_tmp._bpp of
+ 16 : color_conv(dst ,@rbuf_tmp ,color_conv_rgb555_to_bgra32 );
+ 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_bgra32 );
+ 32 : color_conv(dst ,@rbuf_tmp ,color_conv_bgra32_to_bgra32 );
+
+ end;
+
+ pix_format_rgba32 :
+ case pmap_tmp._bpp of
+ 16 : color_conv(dst ,@rbuf_tmp ,color_conv_rgb555_to_rgba32 );
+ 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_rgba32 );
+ 32 : color_conv(dst ,@rbuf_tmp ,color_conv_bgra32_to_rgba32 );
+
+ end;
+
+ pix_format_abgr64 :
+ case pmap_tmp._bpp of
+ 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_abgr64 );
+
+ end;
+
+ pix_format_argb64 :
+ case pmap_tmp._bpp of
+ 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_argb64 );
+
+ end;
+
+ pix_format_bgra64 :
+ case pmap_tmp._bpp of
+ 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_bgra64 );
+
+ end;
+
+ pix_format_rgba64 :
+ case pmap_tmp._bpp of
+ 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_rgba64 );
+
+ end;
+
+ end;
+
+ pmap_tmp.Destruct;
+ rbuf_tmp.Destruct;
+
+ result:=true;
+
+end;
+
+{ SAVE_PMAP }
+function platform_specific.save_pmap;
+var
+ pmap_tmp : pixel_map;
+ rbuf_tmp : rendering_buffer;
+
+begin
+ if m_sys_format = m_format then
+ begin
+ result:=m_pmap_img[idx ].save_as_bmp(fn );
+
+ exit;
+
+ end;
+
+ pmap_tmp.Construct;
+ pmap_tmp.create(
+ m_pmap_img[idx ]._width ,
+ m_pmap_img[idx ]._height ,
+ m_sys_bpp );
+
+ rbuf_tmp.Construct;
+
+ if m_flip_y then
+ rbuf_tmp.attach(pmap_tmp._buf ,pmap_tmp._width ,pmap_tmp._height ,pmap_tmp._stride )
+ else
+ rbuf_tmp.attach(pmap_tmp._buf ,pmap_tmp._width ,pmap_tmp._height ,-pmap_tmp._stride );
+
+ convert_pmap(@rbuf_tmp ,src ,m_format );
+
+ result:=pmap_tmp.save_as_bmp(fn );
+
+ rbuf_tmp.Destruct;
+ pmap_tmp.Destruct;
+
+end;
+
+{ TRANSLATE }
+function platform_specific.translate;
+begin
+ if keycode > 255 then
+ m_last_translated_key:=0
+ else
+ m_last_translated_key:=m_keymap[keycode ];
+
+end;
+
+{ CONSTRUCT }
+constructor platform_support.Construct;
+var
+ i : unsigned;
+
+begin
+{OpenCPL++}
+ if specific <> NIL then
+ m_specific:=specific
+
+ else
+{/OpenCPL++}
+ new(m_specific ,Construct(format_ ,flip_y_ ) );
+
+ m_ctrls.Construct;
+ m_rbuf_window.Construct;
+
+ for i:=0 to max_images - 1 do
+ m_rbuf_img[i ].Construct;
+
+ m_resize_mtx.Construct;
+
+ m_format:=format_;
+
+ m_bpp:=m_specific.m_bpp;
+
+ m_window_flags:=0;
+ m_wait_mode :=true;
+ m_flip_y :=flip_y_;
+
+ m_initial_width :=10;
+ m_initial_height:=10;
+
+ m_caption:='Anti-Grain Geometry Application'#0;
+
+end;
+
+{ DESTRUCT }
+destructor platform_support.Destruct;
+var
+ i : unsigned;
+
+begin
+ dispose(m_specific ,Destruct );
+
+ m_ctrls.Destruct;
+ m_rbuf_window.Destruct;
+
+ for i:=0 to max_images - 1 do
+ m_rbuf_img[i ].Destruct;
+
+end;
+
+{ CAPTION_ }
+procedure platform_support.caption_;
+begin
+ m_caption:=cap + #0;
+
+ dec(byte(m_caption[0 ] ) );
+
+ if m_specific.m_hwnd <> 0 then
+ SetWindowText(m_specific.m_hwnd ,@m_caption[1 ] );
+
+end;
+
+{ LOAD_IMG }
+function platform_support.load_img;
+var
+ f : file;
+
+begin
+ if idx < max_images then
+ begin
+ file_:=file_ + _img_ext;
+
+ AssignFile(f ,file_ );
+ reset (f ,1 );
+
+ if ioresult <> 0 then
+ file_:='bmp\' + file_;
+
+ close(f );
+
+ result:=m_specific.load_pmap(file_ ,idx ,@m_rbuf_img[idx ] );
+
+ end
+ else
+ result:=true;
+
+end;
+
+{ SAVE_IMG }
+function platform_support.save_img;
+begin
+ if idx < max_images then
+ result:=m_specific.save_pmap(file_ ,idx ,@m_rbuf_img[idx ] )
+ else
+ result:=true;
+
+end;
+
+{ CREATE_IMG }
+function platform_support.create_img;
+begin
+ if idx < max_images then
+ begin
+ if width_ = 0 then
+ width_:=m_specific.m_pmap_window._width;
+
+ if height_ = 0 then
+ height_:=m_specific.m_pmap_window._height;
+
+ m_specific.m_pmap_img[idx ].create(width_ ,height_ ,m_specific.m_bpp );
+
+ if m_flip_y then
+ m_rbuf_img[idx ].attach(
+ m_specific.m_pmap_img[idx ]._buf ,
+ m_specific.m_pmap_img[idx ]._width ,
+ m_specific.m_pmap_img[idx ]._height ,
+ m_specific.m_pmap_img[idx ]._stride )
+ else
+ m_rbuf_img[idx ].attach(
+ m_specific.m_pmap_img[idx ]._buf ,
+ m_specific.m_pmap_img[idx ]._width ,
+ m_specific.m_pmap_img[idx ]._height ,
+ -m_specific.m_pmap_img[idx ]._stride );
+
+ result:=true;
+
+ end
+ else
+ result:=false;
+
+end;
+
+{ get_key_flags }
+function get_key_flags(wflags : int ) : unsigned;
+var
+ flags : unsigned;
+
+begin
+ flags:=0;
+
+ if wflags and MK_LBUTTON <> 0 then
+ flags:=flags or mouse_left;
+
+ if wflags and MK_RBUTTON <> 0 then
+ flags:=flags or mouse_right;
+
+ if wflags and MK_SHIFT <> 0 then
+ flags:=flags or kbd_shift;
+
+ if wflags and MK_CONTROL <> 0 then
+ flags:=flags or kbd_ctrl;
+
+ result:=flags;
+
+end;
+
+{ window_proc }
+function window_proc(Wnd : HWND; Msg : UINT; WPar : WParam; LPar : LParam ) : LResult; stdcall;
+var
+ ps : TPaintStruct;
+ app : platform_support_ptr;
+ ret : LResult;
+
+ dc ,paintDC : HDC;
+
+ left ,up ,right ,down : boolean;
+
+ ss : shortstring;
+
+begin
+ app:=platform_support_ptr(GetWindowLong(Wnd ,GWL_USERDATA ) );
+
+ if app = NIL then
+ begin
+ if Msg = WM_DESTROY then
+ begin
+ PostQuitMessage(0 );
+
+ result:=0;
+
+ exit;
+
+ end;
+
+ result:=DefWindowProc(Wnd ,msg ,WPar ,LPar );
+
+ exit;
+
+ end;
+
+ dc:=GetDC(app.m_specific.m_hwnd );
+
+ app.m_specific.m_current_dc:=dc;
+
+ ret:=0;
+
+ case Msg of
+ WM_CREATE :
+ NoP;
+
+ WM_SIZE :
+ begin
+ app.m_specific.create_pmap(int16(int32u_(LPar ).low ) ,int16(int32u_(LPar ).high ) ,app.rbuf_window );
+ app.trans_affine_resizing_(int16(int32u_(LPar ).low ) ,int16(int32u_(LPar ).high ) );
+
+ app.on_resize(int16(int32u_(LPar ).low ) ,int16(int32u_(LPar ).high ) );
+ app.force_redraw;
+
+ end;
+
+ WM_ERASEBKGND :
+ NoP;
+
+ WM_LBUTTONDOWN :
+ begin
+ SetCapture(app.m_specific.m_hwnd );
+
+ app.m_specific.m_cur_x:=int16(int32u_(LPar ).low );
+
+ if app._flip_y then
+ app.m_specific.m_cur_y:=int(app.rbuf_window._height ) - int16(int32u_(LPar ).high )
+ else
+ app.m_specific.m_cur_y:=int16(int32u_(LPar ).high );
+
+ app.m_specific.m_input_flags:=mouse_left or get_key_flags(WPar );
+
+ app.m_ctrls.set_cur(app.m_specific.m_cur_x ,app.m_specific.m_cur_y );
+
+ if app.m_ctrls.on_mouse_button_down(app.m_specific.m_cur_x ,app.m_specific.m_cur_y ) then
+ begin
+ app.on_ctrl_change;
+ app.force_redraw;
+
+ end
+ else
+ if app.m_ctrls.in_rect(app.m_specific.m_cur_x ,app.m_specific.m_cur_y ) then
+ if app.m_ctrls.set_cur(app.m_specific.m_cur_x ,app.m_specific.m_cur_y ) then
+ begin
+ app.on_ctrl_change;
+ app.force_redraw;
+
+ end
+ else
+ else
+ app.on_mouse_button_down(
+ app.m_specific.m_cur_x ,
+ app.m_specific.m_cur_y ,
+ app.m_specific.m_input_flags );
+
+ end;
+
+ WM_LBUTTONUP :
+ begin
+ ReleaseCapture;
+
+ app.m_specific.m_cur_x:=int16(int32u_(LPar ).low );
+
+ if app._flip_y then
+ app.m_specific.m_cur_y:=int(app.rbuf_window._height ) - int16(int32u_(LPar ).high )
+ else
+ app.m_specific.m_cur_y:=int16(int32u_(LPar ).high );
+
+ app.m_specific.m_input_flags:=mouse_left or get_key_flags(WPar );
+
+ if app.m_ctrls.on_mouse_button_up(app.m_specific.m_cur_x ,app.m_specific.m_cur_y ) then
+ begin
+ app.on_ctrl_change;
+ app.force_redraw;
+
+ end;
+
+ app.on_mouse_button_up(
+ app.m_specific.m_cur_x ,
+ app.m_specific.m_cur_y ,
+ app.m_specific.m_input_flags );
+
+ end;
+
+ WM_RBUTTONDOWN :
+ begin
+ SetCapture(app.m_specific.m_hwnd );
+
+ app.m_specific.m_cur_x:=int16(int32u_(LPar ).low );
+
+ if app._flip_y then
+ app.m_specific.m_cur_y:=int(app.rbuf_window._height ) - int16(int32u_(LPar ).high )
+ else
+ app.m_specific.m_cur_y:=int16(int32u_(LPar ).high );
+
+ app.m_specific.m_input_flags:=mouse_right or get_key_flags(WPar );
+
+ app.on_mouse_button_down(
+ app.m_specific.m_cur_x ,
+ app.m_specific.m_cur_y ,
+ app.m_specific.m_input_flags );
+
+ end;
+
+ WM_RBUTTONUP :
+ begin
+ ReleaseCapture;
+
+ app.m_specific.m_cur_x:=int16(int32u_(LPar ).low );
+
+ if app._flip_y then
+ app.m_specific.m_cur_y:=int(app.rbuf_window._height ) - int16(int32u_(LPar ).high )
+ else
+ app.m_specific.m_cur_y:=int16(int32u_(LPar ).high );
+
+ app.m_specific.m_input_flags:=mouse_right or get_key_flags(WPar );
+
+ app.on_mouse_button_up(
+ app.m_specific.m_cur_x ,
+ app.m_specific.m_cur_y ,
+ app.m_specific.m_input_flags );
+
+ end;
+
+ WM_MOUSEMOVE :
+ begin
+ app.m_specific.m_cur_x:=int16(int32u_(LPar ).low );
+
+ if app._flip_y then
+ app.m_specific.m_cur_y:=int(app.rbuf_window._height ) - int16(int32u_(LPar ).high )
+ else
+ app.m_specific.m_cur_y:=int16(int32u_(LPar ).high );
+
+ app.m_specific.m_input_flags:=get_key_flags(WPar );
+
+ if app.m_ctrls.on_mouse_move(
+ app.m_specific.m_cur_x ,
+ app.m_specific.m_cur_y ,
+ ((app.m_specific.m_input_flags and mouse_left ) <> 0 ) ) then
+ begin
+ app.on_ctrl_change;
+ app.force_redraw;
+
+ end
+ else
+ if not app.m_ctrls.in_rect(app.m_specific.m_cur_x ,app.m_specific.m_cur_y ) then
+ app.on_mouse_move(
+ app.m_specific.m_cur_x ,
+ app.m_specific.m_cur_y ,
+ app.m_specific.m_input_flags );
+
+ end;
+
+ WM_SYSKEYDOWN ,WM_KEYDOWN :
+ begin
+ app.m_specific.m_last_translated_key:=0;
+
+ case WPar of
+ VK_CONTROL :
+ app.m_specific.m_input_flags:=app.m_specific.m_input_flags or kbd_ctrl;
+
+ VK_SHIFT :
+ app.m_specific.m_input_flags:=app.m_specific.m_input_flags or kbd_shift;
+
+ VK_F4 :
+ if LPar and $20000000 <> 0 then
+ app.quit
+ else
+ app.m_specific.translate(WPar );
+
+ else
+ app.m_specific.translate(WPar );
+
+ end;
+
+ if app.m_specific.m_last_translated_key <> 0 then
+ begin
+ left :=false;
+ up :=false;
+ right:=false;
+ down :=false;
+
+ case app.m_specific.m_last_translated_key of
+ key_left :
+ left:=true;
+
+ key_up :
+ up:=true;
+
+ key_right :
+ right:=true;
+
+ key_down :
+ down:=true;
+
+ key_f2 :
+ begin
+ app.copy_window_to_img(max_images - 1 );
+ app.save_img (max_images - 1 ,'screenshot.bmp' );
+
+ end;
+
+ end;
+
+ if app._window_flags and window_process_all_keys <> 0 then
+ app.on_key(
+ app.m_specific.m_cur_x ,
+ app.m_specific.m_cur_y ,
+ app.m_specific.m_last_translated_key ,
+ app.m_specific.m_input_flags )
+
+ else
+ if app.m_ctrls.on_arrow_keys(left ,right ,down ,up ) then
+ begin
+ app.on_ctrl_change;
+ app.force_redraw;
+
+ end
+ else
+ app.on_key(
+ app.m_specific.m_cur_x ,
+ app.m_specific.m_cur_y ,
+ app.m_specific.m_last_translated_key ,
+ app.m_specific.m_input_flags );
+
+ end;
+
+ end;
+
+ WM_SYSKEYUP ,WM_KEYUP :
+ begin
+ app.m_specific.m_last_translated_key:=0;
+
+ case WPar of
+ VK_CONTROL :
+ app.m_specific.m_input_flags:=app.m_specific.m_input_flags and (not kbd_ctrl );
+
+ VK_SHIFT :
+ app.m_specific.m_input_flags:=app.m_specific.m_input_flags and (not kbd_shift );
+
+ end;
+
+ end;
+
+ WM_CHAR ,WM_SYSCHAR :
+ if app.m_specific.m_last_translated_key = 0 then
+ app.on_key(
+ app.m_specific.m_cur_x ,
+ app.m_specific.m_cur_y ,
+ WPar ,
+ app.m_specific.m_input_flags );
+
+ WM_PAINT :
+ begin
+ paintDC:=BeginPaint(Wnd ,ps );
+
+ app.m_specific.m_current_dc:=paintDC;
+
+ if app.m_specific.m_redraw_flag then
+ begin
+ app.on_draw;
+
+ app.m_specific.m_redraw_flag:=false;
+
+ end;
+
+ app.m_specific.display_pmap(paintDC ,app.rbuf_window );
+ app.on_post_draw (pointer(@paintDC ) );
+
+ app.m_specific.m_current_dc:=0;
+
+ EndPaint(Wnd ,ps );
+
+ end;
+
+ WM_COMMAND :
+ NoP;
+
+ WM_DESTROY :
+ PostQuitMessage(0 );
+
+ else
+ ret:=DefWindowProc(Wnd ,Msg ,WPar ,LPar );
+
+ end;
+
+ app.m_specific.m_current_dc:=0;
+
+ ReleaseDC(app.m_specific.m_hwnd ,dc );
+
+ result:=ret;
+
+end;
+
+{ INIT }
+function platform_support.init;
+var
+ wc : WNDCLASS;
+ rct : TRect;
+
+ wflags : int;
+
+begin
+ result:=false;
+
+ if m_specific.m_sys_format = pix_format_undefined then
+ exit;
+
+ m_window_flags:=flags;
+
+ wflags:=CS_OWNDC or CS_VREDRAW or CS_HREDRAW;
+
+ wc.lpszClassName:='AGGAppClass';
+ wc.lpfnWndProc :=@window_proc;
+ wc.style :=wflags;
+ wc.hInstance :=hInstance;
+ wc.hIcon :=LoadIcon (0, IDI_APPLICATION);
+ wc.hCursor :=LoadCursor(0, IDC_ARROW);
+ wc.hbrBackground:=COLOR_WINDOW + 1;
+ wc.lpszMenuName :='AGGAppMenu';
+ wc.cbClsExtra :=0;
+ wc.cbWndExtra :=0;
+
+ RegisterClass(wc );
+
+ wflags:=WS_OVERLAPPED or WS_CAPTION or WS_SYSMENU or WS_MINIMIZEBOX;
+
+ if m_window_flags and window_resize <> 0 then
+ wflags:=wflags or WS_THICKFRAME or WS_MAXIMIZEBOX;
+
+ m_specific.m_hwnd:=
+ CreateWindow(
+ 'AGGAppClass' ,@m_caption[1 ] ,wflags ,
+ 10 ,10 ,width_ ,height_ ,
+ 0 ,0 ,hInstance ,0 );
+
+ if m_specific.m_hwnd = 0 then
+ exit;
+
+ GetClientRect(m_specific.m_hwnd ,rct );
+
+ MoveWindow(
+ m_specific.m_hwnd , // handle to window
+ 10 , // horizontal position
+ 10 , // vertical position
+ width_ + (width_ - (rct.right - rct.left ) ) ,
+ height_ + (height_ - (rct.bottom - rct.top ) ) ,
+ false );
+
+ SetWindowLong(m_specific.m_hwnd ,GWL_USERDATA ,ptrcomp(@self ) );
+
+ m_specific.create_pmap(width_ ,height_ ,@m_rbuf_window );
+
+ m_initial_width :=width_;
+ m_initial_height:=height_;
+
+ on_init;
+
+ m_specific.m_redraw_flag:=true;
+
+ ShowWindow(m_specific.m_hwnd ,SW_SHOW );
+
+ result:=true;
+
+end;
+
+{ RUN }
+function platform_support.run;
+var
+ msg : TMsg;
+
+begin
+ repeat
+ if m_wait_mode then
+ begin
+ if not GetMessage(msg ,0 ,0 ,0 ) then
+ break;
+
+ TranslateMessage(msg );
+ DispatchMessage (msg );
+
+ end
+ else
+ if PeekMessage(msg ,0 ,0 ,0 ,PM_REMOVE ) then
+ begin
+ TranslateMessage(msg );
+
+ if msg.message = WM_QUIT then
+ break;
+
+ DispatchMessage(msg );
+
+ end
+ else
+ on_idle;
+
+ until false;
+
+ result:=msg.wParam;
+
+end;
+
+{ QUIT }
+procedure platform_support.quit;
+begin
+ if m_specific.m_hwnd <> 0 then
+ DestroyWindow(m_specific.m_hwnd );
+
+ PostQuitMessage(0 );
+
+end;
+
+{ _FORMAT }
+function platform_support._format;
+begin
+ result:=m_format;
+
+end;
+
+{ _FLIP_Y }
+function platform_support._flip_y;
+begin
+ result:=m_flip_y;
+
+end;
+
+{ _BPP }
+function platform_support._bpp;
+begin
+ result:=m_bpp;
+
+end;
+
+{ _WAIT_MODE }
+function platform_support._wait_mode;
+begin
+ result:=m_wait_mode;
+
+end;
+
+{ WAIT_MODE_ }
+procedure platform_support.wait_mode_;
+begin
+ m_wait_mode:=wait_mode;
+
+end;
+
+{ FORCE_REDRAW }
+procedure platform_support.force_redraw;
+begin
+ m_specific.m_redraw_flag:=true;
+
+ InvalidateRect(m_specific.m_hwnd ,0 ,false );
+
+end;
+
+{ UPDATE_WINDOW }
+procedure platform_support.update_window;
+var
+ dc : HDC;
+
+begin
+ dc:=GetDC(m_specific.m_hwnd );
+
+ m_specific.display_pmap(dc ,@m_rbuf_window );
+
+ ReleaseDC(m_specific.m_hwnd ,dc );
+
+end;
+
+{ RBUF_WINDOW }
+function platform_support.rbuf_window;
+begin
+ result:=@m_rbuf_window;
+
+end;
+
+{ RBUF_IMG }
+function platform_support.rbuf_img;
+begin
+ result:=@m_rbuf_img[idx ];
+
+end;
+
+{ _IMG_EXT }
+function platform_support._img_ext;
+begin
+ result:='.bmp';
+
+end;
+
+{ COPY_IMG_TO_WINDOW }
+procedure platform_support.copy_img_to_window;
+begin
+ if (idx < max_images ) and
+ (rbuf_img(idx )._buf <> NIL ) then
+ rbuf_window.copy_from(rbuf_img(idx ) );
+
+end;
+
+{ COPY_WINDOW_TO_IMG }
+procedure platform_support.copy_window_to_img;
+begin
+ if idx < max_images then
+ begin
+ create_img(idx ,rbuf_window._width ,rbuf_window._height );
+ rbuf_img (idx ).copy_from(rbuf_window );
+
+ end;
+
+end;
+
+{ COPY_IMG_TO_IMG }
+procedure platform_support.copy_img_to_img;
+begin
+ if (idx_from < max_images ) and
+ (idx_to < max_images ) and
+ (rbuf_img(idx_from )._buf <> NIL ) then
+ begin
+ create_img(
+ idx_to ,
+ rbuf_img(idx_from )._width ,
+ rbuf_img(idx_from )._height );
+
+ rbuf_img(idx_to ).copy_from(rbuf_img(idx_from ) );
+
+ end;
+
+end;
+
+{ ON_INIT }
+procedure platform_support.on_init;
+begin
+end;
+
+{ ON_RESIZE }
+procedure platform_support.on_resize;
+begin
+end;
+
+{ ON_IDLE }
+procedure platform_support.on_idle;
+begin
+end;
+
+{ ON_MOUSE_MOVE }
+procedure platform_support.on_mouse_move;
+begin
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure platform_support.on_mouse_button_down;
+begin
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+procedure platform_support.on_mouse_button_up;
+begin
+end;
+
+{ ON_KEY }
+procedure platform_support.on_key;
+begin
+end;
+
+{ ON_CTRL_CHANGE }
+procedure platform_support.on_ctrl_change;
+begin
+end;
+
+{ ON_DRAW }
+procedure platform_support.on_draw;
+begin
+end;
+
+{ ON_POST_DRAW }
+procedure platform_support.on_post_draw;
+begin
+end;
+
+{ ADD_CTRL }
+procedure platform_support.add_ctrl;
+begin
+ m_ctrls.add(c );
+
+ c.transform(@m_resize_mtx );
+
+end;
+
+{ TRANS_AFFINE_RESIZING_ }
+procedure platform_support.trans_affine_resizing_;
+var
+ vp : trans_viewport;
+ ts : trans_affine_scaling;
+
+begin
+ if m_window_flags and window_keep_aspect_ratio <> 0 then
+ begin
+ //double sx = double(width) / double(m_initial_width);
+ //double sy = double(height) / double(m_initial_height);
+ //if(sy < sx) sx = sy;
+ //m_resize_mtx = trans_affine_scaling(sx, sx);
+
+ vp.Construct;
+ vp.preserve_aspect_ratio(0.5 ,0.5 ,aspect_ratio_meet );
+
+ vp.device_viewport(0 ,0 ,width_ ,height_ );
+ vp.world_viewport (0 ,0 ,m_initial_width ,m_initial_height );
+
+ vp.to_affine(@m_resize_mtx );
+
+ end
+ else
+ begin
+ ts.Construct(
+ width_ / m_initial_width ,
+ height_ / m_initial_height );
+
+ m_resize_mtx.assign(@ts );
+
+ end;
+
+end;
+
+{ _TRANS_AFFINE_RESIZING }
+function platform_support._trans_affine_resizing;
+begin
+ result:=@m_resize_mtx;
+
+end;
+
+{ _WIDTH }
+function platform_support._width;
+begin
+ result:=m_rbuf_window._width;
+
+end;
+
+{ _HEIGHT }
+function platform_support._height;
+begin
+ result:=m_rbuf_window._height;
+
+end;
+
+{ _INITIAL_WIDTH }
+function platform_support._initial_width;
+begin
+ result:=m_initial_width;
+
+end;
+
+{ _INITIAL_HEIGHT }
+function platform_support._initial_height;
+begin
+ result:=m_initial_height;
+
+end;
+
+{ _WINDOW_FLAGS }
+function platform_support._window_flags;
+begin
+ result:=m_window_flags;
+
+end;
+
+{ _RAW_DISPLAY_HANDLER }
+function platform_support._raw_display_handler;
+begin
+ result:=@m_specific.m_current_dc;
+
+end;
+
+{ MESSAGE_ }
+procedure platform_support.message_;
+begin
+ MessageBox(m_specific.m_hwnd ,@msg[0 ] ,'AGG Message' ,MB_OK );
+
+end;
+
+{ START_TIMER }
+procedure platform_support.start_timer;
+begin
+ QueryPerformanceCounter({m_specific.}m_sw_start );{hack}
+
+end;
+
+{ ELAPSED_TIME }
+function platform_support.elapsed_time;
+var
+ stop : TLargeInteger;
+
+begin
+ QueryPerformanceCounter(stop );
+
+ result:=(stop - {m_specific.}m_sw_start ) * 1000.0 / {m_specific.}m_sw_freq;{hack}
+
+end;
+
+{ FULL_FILE_NAME }
+function platform_support.full_file_name;
+begin
+ result:=file_name;
+
+end;
+
+{ FILE_SOURCE }
+function platform_support.file_source;
+var
+ f : file;
+ e : integer;
+
+begin
+ result:=fname;
+
+ e:=ioresult;
+
+ AssignFile(f ,result );
+ reset (f ,1 );
+
+ if ioresult <> 0 then
+ result:=path + '\' + fname;
+
+ close(f );
+
+ e:=ioresult;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/platform/win/agg_win32_bmp.pas b/src/corelib/render/software/platform/win/agg_win32_bmp.pas
new file mode 100644
index 00000000..808cb1b6
--- /dev/null
+++ b/src/corelib/render/software/platform/win/agg_win32_bmp.pas
@@ -0,0 +1,719 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// class pixel_map
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 15.12.2005-Milano: Unit port establishment
+//
+{ agg_win32_bmp.pas }
+unit
+ agg_win32_bmp ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ Windows ,
+ agg_basics ;
+
+{ TYPES DEFINITION }
+const
+ org_mono8 = 8;
+ org_color16 = 16;
+ org_color24 = 24;
+ org_color32 = 32;
+ org_color48 = 48;
+ org_color64 = 64;
+
+type
+ pixel_map = object
+ m_bmp : PBITMAPINFO;
+ m_buf : pointer;
+ m_bpp : unsigned;
+
+ m_is_internal : boolean;
+
+ m_img_size ,
+ m_full_size : unsigned;
+
+ constructor Construct;
+ destructor Destruct;
+
+ procedure destroy;
+ procedure create(width_ ,height_ ,org : unsigned; clear_val : unsigned = 256 );
+
+ function load_from_bmp(var fd : file ) : boolean; overload;
+ function load_from_bmp(filename : shortstring ) : boolean; overload;
+
+ function save_as_bmp(var fd : file ) : boolean; overload;
+ function save_as_bmp(filename : shortstring ) : boolean; overload;
+
+ procedure draw(h_dc : HDC; device_rect : PRect = NIL; bmp_rect : PRect = NIL ); overload;
+ procedure draw(h_dc : HDC; x ,y : int; scale : double = 1.0 ); overload;
+
+ function _buf : pointer;
+ function _width : unsigned;
+ function _height : unsigned;
+ function _stride : int;
+ function _bpp : unsigned;
+
+ function create_bitmap_info (width_ ,height_ ,bits_per_pixel : unsigned ) : PBITMAPINFO;
+ procedure create_gray_scale_palette(bmp : PBITMAPINFO );
+
+ function calc_full_size (bmp : PBITMAPINFO ) : unsigned;
+ function calc_header_size(bmp : PBITMAPINFO ) : unsigned;
+ function calc_img_ptr (bmp : PBITMAPINFO ) : unsigned;
+
+ function calc_palette_size(clr_used ,bits_per_pixel : unsigned ) : unsigned; overload;
+ function calc_palette_size(bmp : PBITMAPINFO ) : unsigned; overload;
+
+ function calc_row_len (width_ ,bits_per_pixel : unsigned ) : unsigned;
+ procedure create_from_bmp(bmp : PBITMAPINFO );
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor pixel_map.Construct;
+begin
+ m_bmp:=NIL;
+ m_buf:=NIL;
+ m_bpp:=0;
+
+ m_is_internal:=false;
+
+ m_img_size :=0;
+ m_full_size:=0;
+
+end;
+
+{ DESTRUCT }
+destructor pixel_map.Destruct;
+begin
+ destroy;
+
+end;
+
+{ DESTROY }
+procedure pixel_map.destroy;
+begin
+ if (m_bmp <> NIL ) and
+ m_is_internal then
+ agg_freemem(pointer(m_bmp ) ,m_full_size );
+
+ m_bmp:=NIL;
+ m_buf:=NIL;
+
+ m_is_internal:=false;
+
+end;
+
+{ CREATE }
+procedure pixel_map.create;
+begin
+ destroy;
+
+ if width_ = 0 then
+ width_:=1;
+
+ if height_ = 0 then
+ height_:=1;
+
+ m_bpp:=org;
+
+ create_from_bmp(create_bitmap_info(width_ ,height_ ,m_bpp ) );
+
+ create_gray_scale_palette(m_bmp );
+
+ m_is_internal:=true;
+
+ if clear_val <= 255 then
+ fillchar(m_buf^ ,m_img_size ,clear_val );
+
+end;
+
+{ LOAD_FROM_BMP }
+function pixel_map.load_from_bmp(var fd : file ) : boolean;
+var
+ sz : int;
+
+ bmf : BITMAPFILEHEADER;
+ bmi : PBITMAPINFO;
+
+ bmp_size : unsigned;
+
+label
+ bmperr;
+
+begin
+ blockread(fd ,bmf ,sizeof(bmf ) );
+
+ if bmf.bfType <> $4D42 then
+ goto bmperr;
+
+ bmp_size:=bmf.bfSize - sizeof(BITMAPFILEHEADER );
+
+ agg_getmem(pointer(bmi ) ,bmp_size );
+ blockread (fd ,bmi^ ,bmp_size ,sz );
+
+ if sz <> bmp_size then
+ goto bmperr;
+
+ destroy;
+
+ m_bpp:=bmi.bmiHeader.biBitCount;
+
+ create_from_bmp(bmi );
+
+ m_is_internal:=true;
+
+ result:=true;
+
+ exit;
+
+bmperr:
+ if bmi <> NIL then
+ agg_freemem(pointer(bmi ) ,bmp_size );
+
+ result:=false;
+
+end;
+
+{ LOAD_FROM_BMP }
+function pixel_map.load_from_bmp(filename : shortstring ) : boolean;
+var
+ fd : file;
+ err : integer;
+ ret : boolean;
+
+begin
+{$I- }
+ err:=ioresult;
+
+ assignfile(fd ,filename );
+ reset (fd ,1 );
+
+ err:=ioresult;
+ ret:=false;
+
+ if err = 0 then
+ begin
+ ret:=load_from_bmp(fd );
+
+ close(fd );
+
+ end;
+
+ result:=ret;
+
+end;
+
+{ SAVE_AS_BMP }
+function pixel_map.save_as_bmp(var fd : file ) : boolean;
+var
+ bmf : BITMAPFILEHEADER;
+
+begin
+ if m_bmp = NIL then
+ result:=false
+
+ else
+ begin
+ bmf.bfType :=$4D42;
+ bmf.bfOffBits :=calc_header_size(m_bmp ) + sizeof(bmf );
+ bmf.bfSize :=bmf.bfOffBits + m_img_size;
+ bmf.bfReserved1:=0;
+ bmf.bfReserved2:=0;
+
+ blockwrite(fd ,bmf ,sizeof(bmf ) );
+ blockwrite(fd ,m_bmp^ ,m_full_size );
+
+ result:=true;
+
+ end;
+
+end;
+
+{ SAVE_AS_BMP }
+function pixel_map.save_as_bmp(filename : shortstring ) : boolean;
+var
+ fd : file;
+ err : integer;
+ ret : boolean;
+
+begin
+{$I- }
+ err:=ioresult;
+
+ assignfile(fd ,filename );
+ rewrite (fd ,1 );
+
+ err:=ioresult;
+ ret:=false;
+
+ if err = 0 then
+ begin
+ ret:=save_as_bmp(fd );
+
+ close(fd );
+
+ end;
+
+ result:=ret;
+
+end;
+
+{ DRAW }
+procedure pixel_map.draw(h_dc : HDC; device_rect : PRect = NIL; bmp_rect : PRect = NIL );
+var
+ bmp_x ,
+ bmp_y ,
+
+ bmp_width ,
+ bmp_height ,
+
+ dvc_x ,
+ dvc_y ,
+
+ dvc_width ,
+ dvc_height : unsigned;
+
+ err : int;
+ bok : boolean;
+
+ compdc : HDC;
+ handle ,
+ backup : HBITMAP;
+ bminfo : TBitmapInfo;
+ buffer : pointer;
+
+ rinc ,rgap ,size ,stride : int;
+
+begin
+ if (m_bmp = NIL ) or
+ (m_buf = NIL ) then
+ exit;
+
+ bmp_x:=0;
+ bmp_y:=0;
+
+ bmp_width :=m_bmp.bmiHeader.biWidth;
+ bmp_height:=m_bmp.bmiHeader.biHeight;
+
+ dvc_x:=0;
+ dvc_y:=0;
+
+ dvc_width :=m_bmp.bmiHeader.biWidth;
+ dvc_height:=m_bmp.bmiHeader.biHeight;
+
+ if bmp_rect <> NIL then
+ begin
+ bmp_x :=bmp_rect.left;
+ bmp_y :=bmp_rect.top;
+ bmp_width :=bmp_rect.right - bmp_rect.left;
+ bmp_height:=bmp_rect.bottom - bmp_rect.top;
+
+ end;
+
+ dvc_x :=bmp_x;
+ dvc_x :=bmp_x;
+ dvc_width :=bmp_width;
+ dvc_height:=bmp_height;
+
+ if device_rect <> NIL then
+ begin
+ dvc_x :=device_rect.left;
+ dvc_y :=device_rect.top;
+ dvc_width :=device_rect.right - device_rect.left;
+ dvc_height:=device_rect.bottom - device_rect.top;
+
+ end;
+
+ if (dvc_width <> bmp_width ) or
+ (dvc_height <> bmp_height ) then
+ begin
+ SetStretchBltMode(h_dc ,COLORONCOLOR );
+
+ StretchDIBits(
+ h_dc , // handle of device context
+ dvc_x , // x-coordinate of upper-left corner of source rect.
+ dvc_y , // y-coordinate of upper-left corner of source rect.
+ dvc_width , // width of source rectangle
+ dvc_height , // height of source rectangle
+ bmp_x ,
+ bmp_y , // x, y -coordinates of upper-left corner of dest. rect.
+ bmp_width , // width of destination rectangle
+ bmp_height , // height of destination rectangle
+ m_buf , // address of bitmap bits
+ m_bmp^ , // address of bitmap data
+ DIB_RGB_COLORS , // usage
+ SRCCOPY ); // raster operation code
+
+ end
+ else
+ begin
+ err:=SetDIBitsToDevice(
+ h_dc , // handle to device context
+ dvc_x , // x-coordinate of upper-left corner of
+ dvc_y , // y-coordinate of upper-left corner of
+ dvc_width , // source rectangle width
+ dvc_height , // source rectangle height
+ bmp_x , // x-coordinate of lower-left corner of
+ bmp_y , // y-coordinate of lower-left corner of
+ 0 , // first scan line in array
+ bmp_height , // number of scan lines
+ m_buf , // address of array with DIB bits
+ m_bmp^ , // address of structure with bitmap info.
+ DIB_RGB_COLORS ); // RGB or palette indexes
+
+ {hack}
+ if err = 0 then
+ begin
+ compdc:=CreateCompatibleDC(h_dc );
+
+ if compdc <> 0 then
+ begin
+ fillchar(bminfo ,sizeof(TBitmapInfoHeader ) ,0 );
+
+ bminfo.bmiHeader.biSize :=m_bmp.bmiHeader.biSize;
+ bminfo.bmiHeader.biCompression:=m_bmp.bmiHeader.biCompression;
+
+ bminfo.bmiHeader.biPlanes :=m_bmp.bmiHeader.biPlanes;
+ bminfo.bmiHeader.biBitCount:=m_bmp.bmiHeader.biBitCount;
+
+ bminfo.bmiHeader.biWidth :=m_bmp.bmiHeader.biWidth;
+ bminfo.bmiHeader.biHeight:=m_bmp.bmiHeader.biHeight;
+
+ handle:=CreateDIBSection(compdc ,bminfo ,DIB_RGB_COLORS ,buffer ,0 ,0 );
+ stride:=_stride;
+
+ rinc:=((bminfo.bmiHeader.biWidth * bminfo.bmiHeader.biBitCount + 31 ) shr 5 ) shl 2;
+ rgap:=bminfo.bmiHeader.biWidth mod 4;
+ size:=rinc * bminfo.bmiHeader.biHeight;
+
+ if handle <> 0 then
+ begin
+ backup:=SelectObject(compdc ,handle );
+
+ if (rinc = stride ) and
+ (size = m_img_size ) then
+ begin
+ move(m_buf^ ,buffer^ ,size );
+
+ bok:=BitBlt(
+ h_dc ,dvc_x ,dvc_y ,dvc_width ,dvc_height ,
+ compdc ,bmp_x ,bmp_y ,
+ SRCCOPY );
+
+ end
+ else
+ MessageBox(0 ,'Cannot draw - different format !' ,'pixel_map.draw message' ,MB_OK );
+
+ if backup <> 0 then
+ SelectObject(compdc ,backup );
+
+ DeleteObject(handle );
+
+ end;
+
+ DeleteDC(compdc );
+
+ end;
+
+ end;
+
+ end;
+
+end;
+
+{ DRAW }
+procedure pixel_map.draw(h_dc : HDC; x ,y : int; scale : double = 1.0 );
+var
+ rect : TRect;
+
+ width_ ,
+ height_ : unsigned;
+
+begin
+ if (m_bmp = NIL ) or
+ (m_buf = NIL ) then
+ exit;
+
+ width_ :=trunc(m_bmp.bmiHeader.biWidth * scale );
+ height_:=trunc(m_bmp.bmiHeader.biHeight * scale );
+
+ rect.left :=x;
+ rect.top :=y;
+ rect.right :=x + width_;
+ rect.bottom:=y + height_;
+
+ draw(h_dc ,@rect );
+
+end;
+
+{ _BUF }
+function pixel_map._buf;
+begin
+ result:=m_buf;
+
+end;
+
+{ _WIDTH }
+function pixel_map._width;
+begin
+ result:=m_bmp.bmiHeader.biWidth;
+
+end;
+
+{ _HEIGHT }
+function pixel_map._height;
+begin
+ result:=m_bmp.bmiHeader.biHeight;
+
+end;
+
+{ _STRIDE }
+function pixel_map._stride;
+begin
+ result:=calc_row_len(m_bmp.bmiHeader.biWidth ,m_bmp.bmiHeader.biBitCount );
+
+end;
+
+{ _BPP }
+function pixel_map._bpp;
+begin
+ result:=m_bpp;
+
+end;
+
+{ CALC_FULL_SIZE }
+function pixel_map.calc_full_size;
+begin
+ if bmp = NIL then
+ result:=0
+ else
+ result:=
+ sizeof(TBITMAPINFOHEADER ) +
+ sizeof(RGBQUAD ) * calc_palette_size(bmp ) +
+ bmp.bmiHeader.biSizeImage;
+
+end;
+
+{ CALC_HEADER_SIZE }
+function pixel_map.calc_header_size;
+begin
+ if bmp = NIL then
+ result:=0
+ else
+ result:=sizeof(TBITMAPINFOHEADER ) + sizeof(RGBQUAD ) * calc_palette_size(bmp );
+
+end;
+
+{ CALC_IMG_PTR }
+function pixel_map.calc_img_ptr;
+begin
+ if bmp = NIL then
+ result:=0
+ else
+ result:=ptrcomp(bmp ) + calc_header_size(bmp );
+
+end;
+
+{ CREATE_BITMAP_INFO }
+function pixel_map.create_bitmap_info;
+var
+ bmp : PBITMAPINFO;
+
+ line_len ,
+ img_size ,
+ rgb_size ,
+ full_size : unsigned;
+
+begin
+ line_len :=calc_row_len(width_ ,bits_per_pixel );
+ img_size :=line_len * height_;
+ rgb_size :=calc_palette_size(0 ,bits_per_pixel ) * sizeof(RGBQUAD );
+ full_size:=sizeof(TBITMAPINFOHEADER ) + rgb_size + img_size;
+
+ agg_getmem(pointer(bmp ) ,full_size );
+ fillchar (bmp^ ,full_size ,0 );
+
+ bmp.bmiHeader.biSize :=sizeof(TBITMAPINFOHEADER );
+ bmp.bmiHeader.biWidth :=width_;
+ bmp.bmiHeader.biHeight :=height_;
+ bmp.bmiHeader.biPlanes :=1;
+ bmp.bmiHeader.biBitCount :=bits_per_pixel;
+ bmp.bmiHeader.biCompression :=0;
+ bmp.bmiHeader.biSizeImage :=img_size;
+ bmp.bmiHeader.biXPelsPerMeter:=0;
+ bmp.bmiHeader.biYPelsPerMeter:=0;
+ bmp.bmiHeader.biClrUsed :=0;
+ bmp.bmiHeader.biClrImportant :=0;
+
+ result:=bmp;
+
+end;
+
+{ CREATE_GRAY_SCALE_PALETTE }
+procedure pixel_map.create_gray_scale_palette;
+var
+ rgb : PRGBQUAD;
+
+ i ,rgb_size ,
+ brightness : unsigned;
+
+begin
+ if bmp = NIL then
+ exit;
+
+ rgb_size:=calc_palette_size(bmp );
+
+ rgb:=PRGBQUAD(ptrcomp(bmp ) + sizeof(TBITMAPINFOHEADER ) );
+
+ if rgb_size > 0 then
+ for i:=0 to rgb_size - 1 do
+ begin
+ brightness:=trunc((255 * i ) / (rgb_size - 1 ) );
+
+ rgb.rgbBlue :=brightness;
+ rgb.rgbGreen:=brightness;
+ rgb.rgbRed :=brightness;
+
+ rgb.rgbReserved:=0;
+
+ inc(ptrcomp(rgb ) ,sizeof(RGBQUAD ) );
+
+ end;
+
+end;
+
+{ CALC_PALETTE_SIZE }
+function pixel_map.calc_palette_size(clr_used ,bits_per_pixel : unsigned ) : unsigned;
+var
+ palette_size : int;
+
+begin
+ palette_size:=0;
+
+ if bits_per_pixel <= 8 then
+ begin
+ palette_size:=clr_used;
+
+ if palette_size = 0 then
+ palette_size:=1 shl bits_per_pixel;
+
+ end;
+
+ result:=palette_size;
+
+end;
+
+{ CALC_PALETTE_SIZE }
+function pixel_map.calc_palette_size(bmp : PBITMAPINFO ) : unsigned;
+begin
+ if bmp = NIL then
+ result:=0
+ else
+ result:=calc_palette_size(bmp.bmiHeader.biClrUsed ,bmp.bmiHeader.biBitCount );
+
+end;
+
+{ CALC_ROW_LEN }
+function pixel_map.calc_row_len;
+var
+ n ,k : unsigned;
+
+begin
+ n:=width_;
+
+ case bits_per_pixel of
+ 1 :
+ begin
+ k:=n;
+ n:=n shr 3;
+
+ if k and 7 <> 0 then
+ inc(n );
+
+ end;
+
+ 4 :
+ begin
+ k:=n;
+ n:=n shr 1;
+
+ if k and 3 <> 0 then
+ inc(n );
+
+ end;
+
+ 8 : NoP;
+
+ 16 : n:=n * 2;
+
+ 24 : n:=n * 3;
+
+ 32 : n:=n * 4;
+
+ 48 : n:=n * 6;
+
+ 64 : n:=n * 8;
+
+ else
+ n:=0;
+
+ end;
+
+ result:=((n + 3 ) shr 2 ) shl 2;
+
+end;
+
+{ CREATE_FROM_BMP }
+procedure pixel_map.create_from_bmp;
+begin
+ if bmp <> NIL then
+ begin
+ m_img_size:=
+ calc_row_len(
+ bmp.bmiHeader.biWidth ,
+ bmp.bmiHeader.biBitCount ) * bmp.bmiHeader.biHeight;
+
+ m_full_size:=calc_full_size(bmp );
+
+ m_bmp:=bmp;
+ m_buf:=pointer(calc_img_ptr(bmp ) );
+
+ end;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/platform/win/file_utils_.pas b/src/corelib/render/software/platform/win/file_utils_.pas
new file mode 100644
index 00000000..525548e4
--- /dev/null
+++ b/src/corelib/render/software/platform/win/file_utils_.pas
@@ -0,0 +1,776 @@
+//
+// AggPas 2.4 RM3 demo framework file utility library
+// Milan Marusinec alias Milano (c) 2006
+//
+unit
+ file_utils_ ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+{$I- }
+uses
+ agg_basics ;
+
+{ TYPES DEFINITION }
+type
+ api_file_ptr = ^api_file;
+ api_file = record
+ fileName : shortstring;
+ isOpened : boolean;
+
+ fSize ,
+ fRead : int;
+
+ // FSOpenFork parameters
+ df : file;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+ function cut_str(s : shortstring ) : shortstring;
+ function up_str (s : shortstring ) : shortstring;
+ function cmp_str(s : shortstring ) : shortstring;
+
+ function str_dir(s : shortstring ) : shortstring;
+ function dir_str(s : shortstring ) : shortstring;
+
+ function str_disk(fn : shortstring ) : shortstring;
+ function str_path(fn : shortstring ) : shortstring;
+ function str_name(fn : shortstring ) : shortstring;
+ function str_ext (fn : shortstring ) : shortstring;
+
+ function fold_name (p ,n ,x : shortstring ) : shortstring;
+ procedure spread_name(fn : shortstring; var p ,n ,x : shortstring );
+
+ function file_exists(fn : shortstring ) : boolean;
+
+ function api_open_file (var af : api_file; fname : shortstring ) : boolean;
+ function api_read_file (var af : api_file; buff : pointer; aloc : int; var read : int ) : boolean;
+ function api_close_file(var af : api_file ) : boolean;
+
+ function param_count : int;
+ function param_str(i : int ) : shortstring;
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+type
+ tSCAN = (
+
+ SCAN_0 ,
+ SCAN_1 ,SCAN_2 ,SCAN_3 ,SCAN_4 ,SCAN_5 ,SCAN_6 ,SCAN_7 ,SCAN_8 ,SCAN_9 ,
+ SCAN_A ,SCAN_B ,SCAN_C ,SCAN_D ,SCAN_E ,SCAN_F ,SCAN_G ,SCAN_H ,SCAN_I ,
+ SCAN_J ,SCAN_K ,SCAN_L ,SCAN_M ,SCAN_N ,SCAN_O ,SCAN_P ,SCAN_Q ,SCAN_R ,
+ SCAN_S ,SCAN_T ,SCAN_U ,SCAN_V ,SCAN_W ,SCAN_X ,SCAN_Y ,SCAN_Z
+
+ );
+
+ tITEM = (
+
+ ITEM_0 ,
+ ITEM_1 ,ITEM_2 ,ITEM_3 ,ITEM_4 ,ITEM_5 ,ITEM_6 ,ITEM_7 ,ITEM_8 ,ITEM_9 ,
+ ITEM_A ,ITEM_B ,ITEM_C ,ITEM_D ,ITEM_E ,ITEM_F ,ITEM_G ,ITEM_H ,ITEM_I ,
+ ITEM_J ,ITEM_K ,ITEM_L ,ITEM_M ,ITEM_N ,ITEM_O ,ITEM_P ,ITEM_Q ,ITEM_R ,
+ ITEM_S ,ITEM_T ,ITEM_U ,ITEM_V ,ITEM_W ,ITEM_X ,ITEM_Y ,ITEM_Z
+
+ );
+
+const
+ dir_slash = '\';
+
+ pageEqHigh : shortstring =
+ #1#2#3#4#5#6#7#8#9#10#11#12#13#14#15#16 +
+ #17#18#19#20#21#22#23#24#25#26#27#28#29#30#31#32 +
+ #33#34#35#36#37#38#39#40#41#42#43#44#45#46#47#48 +
+ #49#50#51#52#53#54#55#56#57#58#59#60#61#62#63#64 +
+ #65#66#67#68#69#70#71#72#73#74#75#76#77#78#79#80 +
+ #81#82#83#84#85#86#87#88#89#90#91#92#93#94#95#96 +
+ #65#66#67#68#69#70#71#72#73#74#75#76#77#78#79#80 +
+ #81#82#83#84#85#86#87#88#89#90#123#124#125#126#127#128 +
+ #129#130#131#132#133#134#135#136#137#138#139#140#141#142#143#144 +
+ #145#146#147#148#149#150#151#152#153#154#155#156#157#158#159#160 +
+ #161#162#163#164#165#166#167#168#169#170#171#172#173#174#175#176 +
+ #177#178#179#180#181#182#183#184#185#186#187#188#189#190#191#192 +
+ #193#194#195#196#197#198#199#200#201#202#203#204#205#206#207#208 +
+ #209#210#211#212#213#214#215#216#217#218#219#220#221#222#223#224 +
+ #225#226#227#228#229#230#231#232#233#234#235#236#237#238#239#240 +
+ #241#242#243#244#245#246#247#248#249#250#251#252#253#254#255;
+
+{ UNIT IMPLEMENTATION }
+{ CUT_STR }
+function cut_str;
+var
+ fcb : byte;
+ scn : tSCAN;
+
+begin
+ result:='';
+
+ scn:=SCAN_1;
+
+ if length(s ) > 0 then
+ for fcb:=length(s ) downto 1 do
+ case scn of
+ SCAN_1 :
+ case s[fcb ] of
+ ' ' :
+ else
+ begin
+ result:=s[fcb ];
+
+ scn:=SCAN_2;
+
+ end;
+
+ end;
+
+ SCAN_2 :
+ result:=s[fcb ] + result;
+
+ end;
+
+end;
+
+{ CMP_STR }
+function cmp_str;
+begin
+ cmp_str:=up_str(cut_str(s ) );
+
+end;
+
+{ UP_STR }
+function up_str;
+var
+ fcb : byte;
+
+begin
+ if length(s ) > 0 then
+ for fcb:=1 to length(s ) do
+ if byte(s[fcb ] ) > 0 then
+ s[fcb ]:=pageEqHigh[byte(s[fcb ] ) ];
+
+ result:=s;
+
+end;
+
+{ STR_DIR }
+function str_dir;
+begin
+ s:=cut_str(s );
+
+ if length(s ) > 0 then
+ if s[length(s ) ] <> dir_slash then
+ s:=s + dir_slash;
+
+ result:=s;
+
+end;
+
+{ DIR_STR }
+function dir_str;
+begin
+ s:=cut_str(s );
+
+ if length(s ) > 0 then
+ if s[length(s ) ] = dir_slash then
+ dec(byte(s[0 ] ) );
+
+ result:=s;
+
+end;
+
+{ STR_DISK }
+function str_disk;
+var
+ fcb : byte;
+ str : shortstring;
+ itm : tITEM;
+
+begin
+ str:='';
+ itm:=ITEM_1;
+
+ if length(fn ) > 0 then
+ for fcb:=1 to length(fn ) do
+ case itm of
+ ITEM_1 :
+ case fn[fcb ] of
+ 'a'..'z' ,'A'..'Z' :
+ begin
+ str:=fn[fcb ];
+ itm:=ITEM_2;
+
+ end;
+
+ '\' ,'/' :
+ begin
+ str:=fn[fcb ];
+ itm:=ITEM_3;
+
+ end;
+
+ else
+ break;
+
+ end;
+
+ ITEM_2 :
+ case fn[fcb ] of
+ ':' :
+ begin
+ str:=str + fn[fcb ];
+ itm:=ITEM_F;
+
+ break;
+
+ end;
+
+ else
+ break;
+
+ end;
+
+ ITEM_3 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ str:=str + fn[fcb ];
+ itm:=ITEM_4;
+
+ end;
+
+ else
+ break;
+
+ end;
+
+ ITEM_4 :
+ case fn[fcb ] of
+ '\' ,'/' ,':' ,'<' ,'>' ,'.' ,'"' ,'|' ,#0..#31 :
+ break;
+
+ else
+ begin
+ str:=str + fn[fcb ];
+ itm:=ITEM_F;
+
+ end;
+
+ end;
+
+ ITEM_F :
+ case fn[fcb ] of
+ '\' ,'/' :
+ break;
+
+ else
+ str:=str + fn[fcb ];
+
+ end;
+
+ end;
+
+ if itm = ITEM_F then
+ result:=str
+ else
+ result:='';
+
+end;
+
+{ STR_PATH }
+function str_path;
+var
+ fcb : byte;
+ pth ,
+ str : shortstring;
+ itm : tITEM;
+
+begin
+ pth:='';
+ str:='';
+ itm:=ITEM_1;
+
+ if length(fn ) > 0 then
+ for fcb:=1 to length(fn ) do
+ case itm of
+ ITEM_1 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ str:=fn[fcb ];
+ itm:=ITEM_2;
+
+ end;
+
+ else
+ begin
+ str:=fn[fcb ];
+ itm:=ITEM_3;
+
+ end;
+
+ end;
+
+ ITEM_2 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ str:=str + fn[fcb ];
+ itm:=ITEM_3;
+
+ end;
+
+ else
+ begin
+ pth:=str;
+ str:=fn[fcb ];
+ itm:=ITEM_A;
+
+ end;
+
+ end;
+
+ ITEM_3 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ pth:=fn[fcb ];
+ str:='';
+ itm:=ITEM_A;
+
+ end;
+
+ else
+ str:=str + fn[fcb ];
+
+ end;
+
+ ITEM_A :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ pth:=pth + str + fn[fcb ];
+ str:='';
+
+ end;
+
+ else
+ str:=str + fn[fcb ];
+
+ end;
+
+ end;
+
+ result:=pth;
+
+end;
+
+{ STR_NAME }
+function str_name;
+var
+ fcb : byte;
+ str ,
+ ext : shortstring;
+ itm : tITEM;
+
+begin
+ str:='';
+ ext:='';
+ itm:=ITEM_1;
+
+ if length(fn ) > 0 then
+ for fcb:=1 to length(fn ) do
+ case itm of
+ ITEM_1 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ itm:=ITEM_2;
+
+ 'a'..'z' ,'A'..'Z' :
+ begin
+ ext:=fn[fcb ];
+ itm:=ITEM_4;
+
+ end;
+
+ '.' :
+ begin
+ str:='';
+ ext:=fn[fcb ];
+ itm:=ITEM_B;
+
+ end;
+
+ else
+ begin
+ str:=fn[fcb ];
+ itm:=ITEM_A;
+
+ end;
+
+ end;
+
+ ITEM_2 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ itm:=ITEM_3;
+
+ '.' :
+ begin
+ str:='';
+ ext:=fn[fcb ];
+ itm:=ITEM_B;
+
+ end;
+
+ else
+ begin
+ str:=fn[fcb ];
+ itm:=ITEM_A;
+
+ end;
+
+ end;
+
+ ITEM_3 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ str:='';
+ itm:=ITEM_A;
+
+ end;
+
+ end;
+
+ ITEM_4 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ str:='';
+ itm:=ITEM_A;
+
+ end;
+
+ ':' :
+ itm:=ITEM_5;
+
+ '.' :
+ begin
+ str:=ext;
+ ext:=fn[fcb ];
+ itm:=ITEM_B;
+
+ end;
+
+ else
+ begin
+ str:=ext + fn[fcb ];
+ ext:='';
+ itm:=ITEM_A;
+
+ end;
+
+ end;
+
+ ITEM_5 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ str:='';
+ itm:=ITEM_A;
+
+ end;
+
+ '.' :
+ begin
+ str:='';
+ ext:=fn[fcb ];
+ itm:=ITEM_B;
+
+ end;
+
+ else
+ begin
+ str:=fn[fcb ];
+ itm:=ITEM_A;
+
+ end;
+
+ end;
+
+ ITEM_A :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ str:='';
+ ext:='';
+
+ end;
+
+ '.' :
+ begin
+ ext:=fn[fcb ];
+ itm:=ITEM_B;
+
+ end;
+
+ else
+ str:=str + fn[fcb ];
+
+ end;
+
+ ITEM_B :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ str:='';
+ ext:='';
+ itm:=ITEM_A;
+
+ end;
+
+ '.' :
+ begin
+ str:=str + ext;
+ ext:=fn[fcb ];
+
+ end;
+
+ end;
+
+ end;
+
+ result:=str;
+
+end;
+
+{ STR_EXT }
+function str_ext;
+var
+ fcb : byte;
+ ext : shortstring;
+ itm : tITEM;
+
+begin
+ ext:='';
+ itm:=ITEM_1;
+
+ if length(fn ) > 0 then
+ for fcb:=1 to length(fn ) do
+ case itm of
+ ITEM_1 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ itm:=ITEM_2;
+
+ '.' :
+ begin
+ ext:=fn[fcb ];
+ itm:=ITEM_B;
+
+ end;
+
+ else
+ itm:=ITEM_A;
+
+ end;
+
+ ITEM_2 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ itm:=ITEM_3;
+
+ '.' :
+ begin
+ ext:=fn[fcb ];
+ itm:=ITEM_B;
+
+ end;
+
+ else
+ itm:=ITEM_A;
+
+ end;
+
+ ITEM_3 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ itm:=ITEM_A;
+
+ end;
+
+ ITEM_A :
+ case fn[fcb ] of
+ '.' :
+ begin
+ ext:=fn[fcb ];
+ itm:=ITEM_B;
+
+ end;
+
+ end;
+
+ ITEM_B :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ ext:='';
+ itm:=ITEM_A;
+
+ end;
+
+ '.' :
+ ext:=fn[fcb ];
+
+ else
+ ext:=ext + fn[fcb ];
+
+ end;
+
+ end;
+
+ result:=cut_str(ext );
+
+ if result = '.' then
+ result:='';
+
+end;
+
+{ FOLD_NAME }
+function fold_name;
+var
+ dsk ,
+ nme ,
+ pth ,
+ ext : shortstring;
+
+begin
+ dsk:=str_disk(p );
+ pth:=str_dir (str_path(p ) );
+ nme:=str_name(n );
+ ext:=str_ext (x );
+
+ result:=dsk + pth + nme + ext;
+
+end;
+
+{ SPREAD_NAME }
+procedure spread_name;
+begin
+ p:=str_disk(fn ) + str_dir(str_path(fn ) );
+ n:=str_name(fn );
+ x:=str_ext (fn );
+
+end;
+
+{ FILE_EXISTS }
+function file_exists;
+var
+ f : file;
+
+begin
+ AssignFile(f ,fn );
+ reset (f );
+
+ if IOResult = 0 then
+ begin
+ close(f );
+
+ result:=true;
+
+ end
+ else
+ result:=false;
+
+end;
+
+{ API_OPEN_FILE }
+function api_open_file;
+begin
+ result:=false;
+
+ fillchar(af ,sizeof(api_file ) ,0 );
+
+ af.fileName:=fname;
+ af.isOpened:=false;
+
+ IOResult;
+
+ AssignFile(af.df ,fname );
+ reset (af.df ,1 );
+
+ if IOResult = 0 then
+ begin
+ af.isOpened:=true;
+
+ af.fSize:=filesize(af.df );
+ af.fRead:=0;
+
+ end;
+
+ result:=af.isOpened;
+
+end;
+
+{ API_READ_FILE }
+function api_read_file;
+begin
+ result:=false;
+ read :=0;
+
+ if af.isOpened then
+ begin
+ if aloc > af.fSize - af.fRead then
+ aloc:=af.fSize - af.fRead;
+
+ blockread(af.df ,buff^ ,aloc ,read );
+
+ if aloc = read then
+ begin
+ inc(af.fRead ,read );
+
+ result:=true;
+
+ end
+ else
+ read:=0;
+
+ end;
+
+end;
+
+{ API_CLOSE_FILE }
+function api_close_file;
+begin
+ result:=false;
+
+ if af.isOpened then
+ begin
+ system.close(af.df );
+
+ af.isOpened:=false;
+
+ result:=true;
+
+ end;
+
+end;
+
+{ PARAM_COUNT }
+function param_count;
+begin
+ result:=ParamCount;
+
+end;
+
+{ PARAM_STR }
+function param_str;
+begin
+ result:=ParamStr(i );
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/svg/agg_svg_exception.pas b/src/corelib/render/software/svg/agg_svg_exception.pas
new file mode 100644
index 00000000..0a52836e
--- /dev/null
+++ b/src/corelib/render/software/svg/agg_svg_exception.pas
@@ -0,0 +1,172 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 24.04.2006-Milano: Unit port establishment
+//
+{ agg_svg_exception.pas }
+unit
+ agg_svg_exception ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ SysUtils ,
+ agg_basics ;
+
+{ TYPES DEFINITION }
+type
+ svg_exception_ptr = ^svg_exception;
+ svg_exception = class(Exception )
+ m_msg : pointer;
+
+ constructor Construct; overload;
+ constructor Construct(fmt : PChar ); overload;
+ constructor Construct(exc : svg_exception_ptr ); overload;
+
+ procedure Free;
+ function _msg : char_ptr;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+ function get_double(ptr : agg_basics.char_ptr ) : double;
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor svg_exception.Construct;
+begin
+ m_msg:=NIL;
+
+end;
+
+{ CONSTRUCT }
+constructor svg_exception.Construct(fmt : PChar );
+var
+ max : int;
+
+begin
+ m_msg:=NIL;
+
+ if agg_getmem(m_msg ,4096 ) then
+ begin
+ max:=StrLen(fmt );
+
+ if max > 4095 then
+ max:=4095;
+
+ move(fmt[0 ] ,m_msg^ ,max );
+
+ int8_ptr(ptrcomp(m_msg ) + max )^:=0;
+
+ end;
+
+end;
+
+{ CONSTRUCT }
+constructor svg_exception.Construct(exc : svg_exception_ptr );
+var
+ max : int;
+
+begin
+ m_msg:=NIL;
+
+ if (exc <> NIL ) and
+ (exc.m_msg <> NIL ) then
+ if agg_getmem(m_msg ,4096 ) then
+ begin
+ max:=StrLen(exc.m_msg );
+
+ if max > 4095 then
+ max:=4095;
+
+ move(exc.m_msg^ ,m_msg^ ,max );
+
+ int8_ptr(ptrcomp(m_msg ) + max )^:=0;
+
+ end;
+
+end;
+
+{ FREE }
+procedure svg_exception.Free;
+begin
+ if m_msg <> NIL then
+ agg_freemem(m_msg ,4096 );
+
+end;
+
+{ _MSG }
+function svg_exception._msg;
+begin
+ result:=char_ptr(m_msg );
+
+end;
+
+{ GET_DOUBLE }
+function get_double;
+var
+ buf : array[0..49 ] of char;
+ dst ,
+ max : char_ptr;
+ err : integer;
+
+begin
+ dst:=@buf[0 ];
+ max:=@buf[48 ];
+
+ while ptr^ <> #0 do
+ begin
+ case ptr^ of
+ '-' ,'.' ,'0'..'9' :
+ if dst <> max then
+ begin
+ dst^:=ptr^;
+
+ inc(ptrcomp(dst ) );
+
+ end
+ else
+ break;
+
+ else
+ break;
+
+ end;
+
+ inc(ptrcomp(ptr ) );
+
+ end;
+
+ dst^:=#0;
+
+ val(PChar(@buf[0 ] ) ,result ,err );
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/svg/agg_svg_parser.pas b/src/corelib/render/software/svg/agg_svg_parser.pas
new file mode 100644
index 00000000..a2ec372a
--- /dev/null
+++ b/src/corelib/render/software/svg/agg_svg_parser.pas
@@ -0,0 +1,1386 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 03.01.2007-Milano: Adjustments for ExpatWrap (Win,Linux & Mac)
+// 23.06.2006-Milano: ptrcomp adjustments
+// 24.04.2006-Milano: Unit port establishment
+//
+{ agg_svg_parser.pas }
+unit
+ agg_svg_parser ;
+
+INTERFACE
+
+{$DEFINE EXPAT_WRAPPER }
+{$I agg_mode.inc }
+
+uses
+ SysUtils ,
+ agg_basics ,
+ agg_color ,
+ agg_svg_path_tokenizer ,
+ agg_svg_path_renderer ,
+ agg_svg_exception ,
+ agg_trans_affine ,
+ agg_math_stroke ,
+ expat ,
+ file_utils_ ;
+
+{ TYPES DEFINITION }
+const
+ buf_size = 512;
+
+type
+ parser_ptr = ^parser;
+ parser = object
+ m_path : path_renderer_ptr;
+ m_tokenizer : path_tokenizer;
+
+ m_buf ,
+ m_title : char_ptr;
+
+ m_title_len : unsigned;
+ m_title_flag ,
+ m_path_flag : boolean;
+ m_attr_name ,
+ m_attr_value : char_ptr;
+
+ m_attr_name_len ,
+ m_attr_name_aloc ,
+ m_attr_value_len ,
+ m_attr_value_aloc : unsigned;
+
+ constructor Construct(path : path_renderer_ptr );
+ destructor Destruct;
+
+ procedure parse(fname : shortstring );
+ function title : char_ptr;
+
+ // XML event handlers
+ procedure parse_attr (attr : char_ptr_ptr ); overload;
+ procedure parse_path (attr : char_ptr_ptr );
+ procedure parse_poly (attr : char_ptr_ptr; close_flag : boolean );
+ procedure parse_rect (attr : char_ptr_ptr );
+ procedure parse_line (attr : char_ptr_ptr );
+ procedure parse_style (str : agg_basics.char_ptr );
+ procedure parse_transform(str : agg_basics.char_ptr );
+
+ function parse_matrix (str : agg_basics.char_ptr ) : unsigned;
+ function parse_translate(str : agg_basics.char_ptr ) : unsigned;
+ function parse_rotate (str : agg_basics.char_ptr ) : unsigned;
+ function parse_scale (str : agg_basics.char_ptr ) : unsigned;
+ function parse_skew_x (str : agg_basics.char_ptr ) : unsigned;
+ function parse_skew_y (str : agg_basics.char_ptr ) : unsigned;
+
+ function parse_attr (name ,value : agg_basics.char_ptr ) : boolean; overload;
+ function parse_name_value(nv_start ,nv_end : agg_basics.char_ptr ) : boolean;
+
+ procedure copy_name (start ,end_ : agg_basics.char_ptr );
+ procedure copy_value(start ,end_ : agg_basics.char_ptr );
+
+ end;
+
+{ GLOBAL PROCEDURES }
+ procedure start_element(data : pointer; el : char_ptr; attr : char_ptr_ptr ); {$IFDEF EXPAT_WRAPPER }cdecl; {$ENDIF }
+ procedure end_element (data : pointer; el : char_ptr ); {$IFDEF EXPAT_WRAPPER }cdecl; {$ENDIF }
+ procedure content (data : pointer; s : char_ptr; len : int ); {$IFDEF EXPAT_WRAPPER }cdecl; {$ENDIF }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+type
+ named_color_ptr = ^named_color;
+ named_color = record
+ name : array[0..21 ] of char;
+
+ r ,g ,b ,a : int8u;
+
+ end;
+
+const
+ colors_num = 148;
+
+ colors : array[0..colors_num - 1 ] of named_color =
+ ((name:'aliceblue'; r:240; g:248; b:255; a:255 ) ,
+ (name:'antiquewhite'; r:250; g:235; b:215; a:255 ) ,
+ (name:'aqua'; r:0; g:255; b:255; a:255 ) ,
+ (name:'aquamarine'; r:127; g:255; b:212; a:255 ) ,
+ (name:'azure'; r:240; g:255; b:255; a:255 ) ,
+ (name:'beige'; r:245; g:245; b:220; a:255 ) ,
+ (name:'bisque'; r:255; g:228; b:196; a:255 ) ,
+ (name:'black'; r:0; g:0; b:0; a:255 ) ,
+ (name:'blanchedalmond'; r:255; g:235; b:205; a:255 ) ,
+ (name:'blue'; r:0; g:0; b:255; a:255 ) ,
+ (name:'blueviolet'; r:138; g:43; b:226; a:255 ) ,
+ (name:'brown'; r:165; g:42; b:42; a:255 ) ,
+ (name:'burlywood'; r:222; g:184; b:135; a:255 ) ,
+ (name:'cadetblue'; r:95; g:158; b:160; a:255 ) ,
+ (name:'chartreuse'; r:127; g:255; b:0; a:255 ) ,
+ (name:'chocolate'; r:210; g:105; b:30; a:255 ) ,
+ (name:'coral'; r:255; g:127; b:80; a:255 ) ,
+ (name:'cornflowerblue'; r:100; g:149; b:237; a:255 ) ,
+ (name:'cornsilk'; r:255; g:248; b:220; a:255 ) ,
+ (name:'crimson'; r:220; g:20; b:60; a:255 ) ,
+ (name:'cyan'; r:0; g:255; b:255; a:255 ) ,
+ (name:'darkblue'; r:0; g:0; b:139; a:255 ) ,
+ (name:'darkcyan'; r:0; g:139; b:139; a:255 ) ,
+ (name:'darkgoldenrod'; r:184; g:134; b:11; a:255 ) ,
+ (name:'darkgray'; r:169; g:169; b:169; a:255 ) ,
+ (name:'darkgreen'; r:0; g:100; b:0; a:255 ) ,
+ (name:'darkgrey'; r:169; g:169; b:169; a:255 ) ,
+ (name:'darkkhaki'; r:189; g:183; b:107; a:255 ) ,
+ (name:'darkmagenta'; r:139; g:0; b:139; a:255 ) ,
+ (name:'darkolivegreen'; r:85; g:107; b:47; a:255 ) ,
+ (name:'darkorange'; r:255; g:140; b:0; a:255 ) ,
+ (name:'darkorchid'; r:153; g:50; b:204; a:255 ) ,
+ (name:'darkred'; r:139; g:0; b:0; a:255 ) ,
+ (name:'darksalmon'; r:233; g:150; b:122; a:255 ) ,
+ (name:'darkseagreen'; r:143; g:188; b:143; a:255 ) ,
+ (name:'darkslateblue'; r:72; g:61; b:139; a:255 ) ,
+ (name:'darkslategray'; r:47; g:79; b:79; a:255 ) ,
+ (name:'darkslategrey'; r:47; g:79; b:79; a:255 ) ,
+ (name:'darkturquoise'; r:0; g:206; b:209; a:255 ) ,
+ (name:'darkviolet'; r:148; g:0; b:211; a:255 ) ,
+ (name:'deeppink'; r:255; g:20; b:147; a:255 ) ,
+ (name:'deepskyblue'; r:0; g:191; b:255; a:255 ) ,
+ (name:'dimgray'; r:105; g:105; b:105; a:255 ) ,
+ (name:'dimgrey'; r:105; g:105; b:105; a:255 ) ,
+ (name:'dodgerblue'; r:30; g:144; b:255; a:255 ) ,
+ (name:'firebrick'; r:178; g:34; b:34; a:255 ) ,
+ (name:'floralwhite'; r:255; g:250; b:240; a:255 ) ,
+ (name:'forestgreen'; r:34; g:139; b:34; a:255 ) ,
+ (name:'fuchsia'; r:255; g:0; b:255; a:255 ) ,
+ (name:'gainsboro'; r:220; g:220; b:220; a:255 ) ,
+ (name:'ghostwhite'; r:248; g:248; b:255; a:255 ) ,
+ (name:'gold'; r:255; g:215; b:0; a:255 ) ,
+ (name:'goldenrod'; r:218; g:165; b:32; a:255 ) ,
+ (name:'gray'; r:128; g:128; b:128; a:255 ) ,
+ (name:'green'; r:0; g:128; b:0; a:255 ) ,
+ (name:'greenyellow'; r:173; g:255; b:47; a:255 ) ,
+ (name:'grey'; r:128; g:128; b:128; a:255 ) ,
+ (name:'honeydew'; r:240; g:255; b:240; a:255 ) ,
+ (name:'hotpink'; r:255; g:105; b:180; a:255 ) ,
+ (name:'indianred'; r:205; g:92; b:92; a:255 ) ,
+ (name:'indigo'; r:75; g:0; b:130; a:255 ) ,
+ (name:'ivory'; r:255; g:255; b:240; a:255 ) ,
+ (name:'khaki'; r:240; g:230; b:140; a:255 ) ,
+ (name:'lavender'; r:230; g:230; b:250; a:255 ) ,
+ (name:'lavenderblush'; r:255; g:240; b:245; a:255 ) ,
+ (name:'lawngreen'; r:124; g:252; b:0; a:255 ) ,
+ (name:'lemonchiffon'; r:255; g:250; b:205; a:255 ) ,
+ (name:'lightblue'; r:173; g:216; b:230; a:255 ) ,
+ (name:'lightcoral'; r:240; g:128; b:128; a:255 ) ,
+ (name:'lightcyan'; r:224; g:255; b:255; a:255 ) ,
+ (name:'lightgoldenrodyellow'; r:250; g:250; b:210; a:255 ) ,
+ (name:'lightgray'; r:211; g:211; b:211; a:255 ) ,
+ (name:'lightgreen'; r:144; g:238; b:144; a:255 ) ,
+ (name:'lightgrey'; r:211; g:211; b:211; a:255 ) ,
+ (name:'lightpink'; r:255; g:182; b:193; a:255 ) ,
+ (name:'lightsalmon'; r:255; g:160; b:122; a:255 ) ,
+ (name:'lightseagreen'; r:32; g:178; b:170; a:255 ) ,
+ (name:'lightskyblue'; r:135; g:206; b:250; a:255 ) ,
+ (name:'lightslategray'; r:119; g:136; b:153; a:255 ) ,
+ (name:'lightslategrey'; r:119; g:136; b:153; a:255 ) ,
+ (name:'lightsteelblue'; r:176; g:196; b:222; a:255 ) ,
+ (name:'lightyellow'; r:255; g:255; b:224; a:255 ) ,
+ (name:'lime'; r:0; g:255; b:0; a:255 ) ,
+ (name:'limegreen'; r:50; g:205; b:50; a:255 ) ,
+ (name:'linen'; r:250; g:240; b:230; a:255 ) ,
+ (name:'magenta'; r:255; g:0; b:255; a:255 ) ,
+ (name:'maroon'; r:128; g:0; b:0; a:255 ) ,
+ (name:'mediumaquamarine'; r:102; g:205; b:170; a:255 ) ,
+ (name:'mediumblue'; r:0; g:0; b:205; a:255 ) ,
+ (name:'mediumorchid'; r:186; g:85; b:211; a:255 ) ,
+ (name:'mediumpurple'; r:147; g:112; b:219; a:255 ) ,
+ (name:'mediumseagreen'; r:60; g:179; b:113; a:255 ) ,
+ (name:'mediumslateblue'; r:123; g:104; b:238; a:255 ) ,
+ (name:'mediumspringgreen'; r:0; g:250; b:154; a:255 ) ,
+ (name:'mediumturquoise'; r:72; g:209; b:204; a:255 ) ,
+ (name:'mediumvioletred'; r:199; g:21; b:133; a:255 ) ,
+ (name:'midnightblue'; r:25; g:25; b:112; a:255 ) ,
+ (name:'mintcream'; r:245; g:255; b:250; a:255 ) ,
+ (name:'mistyrose'; r:255; g:228; b:225; a:255 ) ,
+ (name:'moccasin'; r:255; g:228; b:181; a:255 ) ,
+ (name:'navajowhite'; r:255; g:222; b:173; a:255 ) ,
+ (name:'navy'; r:0; g:0; b:128; a:255 ) ,
+ (name:'oldlace'; r:253; g:245; b:230; a:255 ) ,
+ (name:'olive'; r:128; g:128; b:0; a:255 ) ,
+ (name:'olivedrab'; r:107; g:142; b:35; a:255 ) ,
+ (name:'orange'; r:255; g:165; b:0; a:255 ) ,
+ (name:'orangered'; r:255; g:69; b:0; a:255 ) ,
+ (name:'orchid'; r:218; g:112; b:214; a:255 ) ,
+ (name:'palegoldenrod'; r:238; g:232; b:170; a:255 ) ,
+ (name:'palegreen'; r:152; g:251; b:152; a:255 ) ,
+ (name:'paleturquoise'; r:175; g:238; b:238; a:255 ) ,
+ (name:'palevioletred'; r:219; g:112; b:147; a:255 ) ,
+ (name:'papayawhip'; r:255; g:239; b:213; a:255 ) ,
+ (name:'peachpuff'; r:255; g:218; b:185; a:255 ) ,
+ (name:'peru'; r:205; g:133; b:63; a:255 ) ,
+ (name:'pink'; r:255; g:192; b:203; a:255 ) ,
+ (name:'plum'; r:221; g:160; b:221; a:255 ) ,
+ (name:'powderblue'; r:176; g:224; b:230; a:255 ) ,
+ (name:'purple'; r:128; g:0; b:128; a:255 ) ,
+ (name:'red'; r:255; g:0; b:0; a:255 ) ,
+ (name:'rosybrown'; r:188; g:143; b:143; a:255 ) ,
+ (name:'royalblue'; r:65; g:105; b:225; a:255 ) ,
+ (name:'saddlebrown'; r:139; g:69; b:19; a:255 ) ,
+ (name:'salmon'; r:250; g:128; b:114; a:255 ) ,
+ (name:'sandybrown'; r:244; g:164; b:96; a:255 ) ,
+ (name:'seagreen'; r:46; g:139; b:87; a:255 ) ,
+ (name:'seashell'; r:255; g:245; b:238; a:255 ) ,
+ (name:'sienna'; r:160; g:82; b:45; a:255 ) ,
+ (name:'silver'; r:192; g:192; b:192; a:255 ) ,
+ (name:'skyblue'; r:135; g:206; b:235; a:255 ) ,
+ (name:'slateblue'; r:106; g:90; b:205; a:255 ) ,
+ (name:'slategray'; r:112; g:128; b:144; a:255 ) ,
+ (name:'slategrey'; r:112; g:128; b:144; a:255 ) ,
+ (name:'snow'; r:255; g:250; b:250; a:255 ) ,
+ (name:'springgreen'; r:0; g:255; b:127; a:255 ) ,
+ (name:'steelblue'; r:70; g:130; b:180; a:255 ) ,
+ (name:'tan'; r:210; g:180; b:140; a:255 ) ,
+ (name:'teal'; r:0; g:128; b:128; a:255 ) ,
+ (name:'thistle'; r:216; g:191; b:216; a:255 ) ,
+ (name:'tomato'; r:255; g:99; b:71; a:255 ) ,
+ (name:'turquoise'; r:64; g:224; b:208; a:255 ) ,
+ (name:'violet'; r:238; g:130; b:238; a:255 ) ,
+ (name:'wheat'; r:245; g:222; b:179; a:255 ) ,
+ (name:'white'; r:255; g:255; b:255; a:255 ) ,
+ (name:'whitesmoke'; r:245; g:245; b:245; a:255 ) ,
+ (name:'yellow'; r:255; g:255; b:0; a:255 ) ,
+ (name:'yellowgreen'; r:154; g:205; b:50; a:255 ) ,
+ (name:'zzzzzzzzzzz'; r:0; g:0; b:0; a:0 ) );
+
+ pageEqHigh : shortstring =
+ #1#2#3#4#5#6#7#8#9#10#11#12#13#14#15#16 +
+ #17#18#19#20#21#22#23#24#25#26#27#28#29#30#31#32 +
+ #33#34#35#36#37#38#39#40#41#42#43#44#45#46#47#48 +
+ #49#50#51#52#53#54#55#56#57#58#59#60#61#62#63#64 +
+ #65#66#67#68#69#70#71#72#73#74#75#76#77#78#79#80 +
+ #81#82#83#84#85#86#87#88#89#90#91#92#93#94#95#96 +
+ #65#66#67#68#69#70#71#72#73#74#75#76#77#78#79#80 +
+ #81#82#83#84#85#86#87#88#89#90#123#124#125#126#127#128 +
+ #129#130#131#132#133#134#135#136#137#138#139#140#141#142#143#144 +
+ #145#146#147#148#149#150#151#152#153#154#155#156#157#158#159#160 +
+ #161#162#163#164#165#166#167#168#169#170#171#172#173#174#175#176 +
+ #177#178#179#180#181#182#183#184#185#186#187#188#189#190#191#192 +
+ #193#194#195#196#197#198#199#200#201#202#203#204#205#206#207#208 +
+ #209#210#211#212#213#214#215#216#217#218#219#220#221#222#223#224 +
+ #225#226#227#228#229#230#231#232#233#234#235#236#237#238#239#240 +
+ #241#242#243#244#245#246#247#248#249#250#251#252#253#254#255;
+
+{ UNIT IMPLEMENTATION }
+{ START_ELEMENT }
+procedure start_element;
+var
+ this : parser_ptr;
+
+begin
+ this:=parser_ptr(data );
+
+ if StrComp(PChar(el ) ,'title' ) = 0 then
+ this.m_title_flag:=true
+ else
+ if StrComp(PChar(el ) ,'g' ) = 0 then
+ begin
+ this.m_path.push_attr;
+ this.parse_attr(attr );
+
+ end
+ else
+ if StrComp(PChar(el ) ,'path' ) = 0 then
+ begin
+ if this.m_path_flag then
+ raise svg_exception.Construct(PChar('start_element: Nested path' ) );
+
+ this.m_path.begin_path;
+ this.parse_path(attr );
+ this.m_path.end_path;
+
+ this.m_path_flag:=true;
+
+ end
+ else
+ if StrComp(PChar(el ) ,'rect' ) = 0 then
+ this.parse_rect(attr )
+ else
+ if StrComp(PChar(el ) ,'line' ) = 0 then
+ this.parse_line(attr )
+ else
+ if StrComp(PChar(el ) ,'polyline' ) = 0 then
+ this.parse_poly(attr ,false )
+ else
+ if StrComp(PChar(el ) ,'polygon' ) = 0 then
+ this.parse_poly(attr ,true );
+
+ //else
+ // if StrComp(PChar(el ) ,'<OTHER_ELEMENTS>' ) = 0 then
+ // begin
+ // end
+ //...
+
+end;
+
+{ END_ELEMENT }
+procedure end_element;
+var
+ this : parser_ptr;
+
+begin
+ this:=parser_ptr(data );
+
+ if StrComp(PChar(el ) ,'title' ) = 0 then
+ this.m_title_flag:=false
+ else
+ if StrComp(PChar(el ) ,'g' ) = 0 then
+ this.m_path.pop_attr
+ else
+ if StrComp(PChar(el ) ,'path' ) = 0 then
+ this.m_path_flag:=false;
+
+ //else
+ // if StrComp(PChar(el ) ,'<OTHER_ELEMENTS>' ) = 0 then
+ // begin
+ // end
+ // ...
+
+end;
+
+{ CONTENT }
+procedure content;
+var
+ this : parser_ptr;
+
+begin
+ this:=parser_ptr(data );
+
+// m_title_flag signals that the <title> tag is being parsed now.
+// The following code concatenates the pieces of content of the <title> tag.
+ if this.m_title_flag then
+ begin
+ if len + this.m_title_len > 255 then
+ len:=255 - this.m_title_len;
+
+ if len > 0 then
+ begin
+ move(
+ s^ ,
+ char_ptr(ptrcomp(this.m_title ) + this.m_title_len )^ ,
+ len );
+
+ inc(this.m_title_len ,len );
+
+ char_ptr(ptrcomp(this.m_title ) + this.m_title_len )^:=#0;
+
+ end;
+
+ end;
+
+end;
+
+{ hex_unsigned }
+function hex_unsigned(hexstr : agg_basics.char_ptr ) : unsigned;
+
+function xyint(x ,y : integer ) : integer;
+var
+ f : integer;
+ m : boolean;
+
+begin
+ m:=false;
+
+ if y < 0 then
+ begin
+ y:=y * -1;
+ m:=true;
+
+ end;
+
+ result:=x;
+
+ if y > 1 then
+ for f:=1 to y - 1 do
+ result:=result * x;
+
+ if m then
+ result:=result * -1;
+
+end;
+
+var
+ h : shortstring;
+ fcb : byte;
+ yps ,
+ mul ,
+ num : unsigned;
+
+label
+ Err ,Esc ;
+
+const
+ hex : string[16 ] = '0123456789ABCDEF';
+
+begin
+ h:='';
+
+ while hexstr^ <> #0 do
+ begin
+ h:=h + pageEqHigh[byte(hexstr^ ) ];
+
+ inc(ptrcomp(hexstr ) );
+
+ end;
+
+ if length(h ) > 0 then
+ begin
+ case h[length(h ) ] of
+ '0'..'9' ,'A'..'F' :
+ else
+ goto Err;
+
+ end;
+
+ num:=pos(h[length(h ) ] ,hex ) - 1;
+ yps:=2;
+ mul:=xyint(4 ,yps );
+
+ if length(h ) > 1 then
+ for fcb:=length(h ) - 1 downto 1 do
+ begin
+ case h[fcb ] of
+ '0'..'9' ,'A'..'F' :
+ else
+ goto Err;
+
+ end;
+
+ inc(num ,(pos(h[fcb ] ,hex ) - 1 ) * mul );
+ inc(yps ,2 );
+
+ mul:=xyint(4 ,yps );
+
+ end;
+
+ goto Esc;
+
+ end;
+
+Err:
+ num:=0;
+
+Esc:
+ result:=num;
+
+end;
+
+{ parse_color }
+function parse_color(str : agg_basics.char_ptr ) : aggclr;
+var
+ u : unsigned;
+ p : named_color_ptr;
+ m : shortstring;
+
+begin
+ while str^ = ' ' do
+ inc(ptrcomp(str ) );
+
+ if str^ = '#' then
+ begin
+ inc(ptrcomp(str ) );
+
+ u:=hex_unsigned(str );
+
+ result.Construct(rgb8_packed(u ) );
+
+ end
+ else
+ begin
+ p:=NIL;
+
+ for u:=0 to colors_num - 1 do
+ if StrComp(colors[u ].name ,PChar(str ) ) = 0 then
+ begin
+ p:=@colors[u ];
+
+ break;
+
+ end;
+
+ if p = NIL then
+ begin
+ m:='parse_color: Invalid color name ' + StrPas(PChar(str ) ) + #0;
+
+ raise svg_exception.Construct(PChar(@m[1 ] ) );
+
+ end;
+
+ result.ConstrInt(p.r ,p.g ,p.b ,p.a );
+
+ end;
+
+end;
+
+{ parse_double }
+function parse_double(str : agg_basics.char_ptr ) : double;
+begin
+ while str^ = ' ' do
+ inc(ptrcomp(str ) );
+
+ result:=get_double(pointer(PChar(str ) ) );
+
+end;
+
+{ islower }
+function islower(ch : char ) : boolean;
+begin
+ case ch of
+ #97..#122 :
+ result:=true;
+
+ else
+ result:=false;
+
+ end;
+
+end;
+
+{ is_numeric }
+function is_numeric(ch : char ) : boolean;
+begin
+ result:=Pos(ch ,'0123456789+-.eE' ) <> 0;
+
+end;
+
+{ parse_transform_args }
+function parse_transform_args(str : agg_basics.char_ptr; args : double_ptr; max_na : unsigned; na : unsigned_ptr ) : unsigned;
+var
+ ptr ,end_ : agg_basics.char_ptr;
+
+begin
+ na^:=0;
+ ptr:=str;
+
+ while (ptr^ <> #0 ) and
+ (ptr^ <> '(' ) do
+ inc(ptrcomp(ptr ) );
+
+ if ptr^ = #0 then
+ raise svg_exception.Construct(PChar('parse_transform_args: Invalid syntax' ) );
+
+ end_:=ptr;
+
+ while (end_^ <> #0 ) and
+ (end_^ <> ')' ) do
+ inc(ptrcomp(end_ ) );
+
+ if end_^ = #0 then
+ raise svg_exception.Construct(PChar('parse_transform_args: Invalid syntax' ) );
+
+ while ptrcomp(ptr ) < ptrcomp(end_ ) do
+ if is_numeric(ptr^ ) then
+ begin
+ if na^ >= max_na then
+ raise svg_exception.Construct(PChar('parse_transform_args: Too many arguments' ) );
+
+ double_ptr(ptrcomp(args ) + na^ * sizeof(double ) )^:=get_double(ptr );
+
+ inc(na^ );
+
+ while (ptrcomp(ptr ) < ptrcomp(end_ ) ) and
+ is_numeric(ptr^ ) do
+ inc(ptrcomp(ptr ) );
+
+ end
+ else
+ inc(ptrcomp(ptr ) );
+
+ result:=unsigned(ptrcomp(end_ ) - ptrcomp(str ) );
+
+end;
+
+{ CONSTRUCT }
+constructor parser.Construct;
+begin
+ m_path:=path;
+
+ m_tokenizer.Construct;
+
+ agg_getmem(pointer(m_buf ) ,buf_size );
+ agg_getmem(pointer(m_title ) ,256 );
+
+ m_title_len :=0;
+ m_title_flag:=false;
+ m_path_flag :=false;
+
+ m_attr_name_aloc :=128;
+ m_attr_value_aloc:=1024;
+
+ agg_getmem(pointer(m_attr_name ) ,m_attr_name_aloc );
+ agg_getmem(pointer(m_attr_value ) ,m_attr_value_aloc );
+
+ m_attr_name_len :=127;
+ m_attr_value_len:=1023;
+
+ m_title^:=#0;
+
+end;
+
+{ DESTRUCT }
+destructor parser.Destruct;
+begin
+ agg_freemem(pointer(m_attr_value ) ,m_attr_value_aloc );
+ agg_freemem(pointer(m_attr_name ) ,m_attr_name_aloc );
+ agg_freemem(pointer(m_title ) ,256 );
+ agg_freemem(pointer(m_buf ) ,buf_size );
+
+end;
+
+{ PARSE }
+procedure parser.parse;
+var
+ msg : array[0..1023 ] of char;
+
+ p : XML_Parser;
+ af : api_file;
+ ts : char_ptr;
+
+ done : boolean;
+ len : int;
+
+begin
+ p:=XML_ParserCreate(NIL );
+
+ if p = NIL then
+ raise svg_exception.Construct(PChar('Couldn''t allocate memory for parser' ) );
+
+ XML_SetUserData (p ,@self );
+ XML_SetElementHandler (p ,@start_element ,@end_element );
+ XML_SetCharacterDataHandler(p ,@content );
+
+ fname:=fname + #0;
+
+ dec(byte(fname[0 ] ) );
+
+ if not api_open_file(af ,fname ) then
+ begin
+ sprintf(@msg[0 ] ,'Couldn''t open file %s' ,unsigned(@fname[1 ] ) );
+
+ XML_ParserFree(p );
+
+ raise svg_exception.Construct(PChar(@msg[0 ] ) );
+
+ end;
+
+ done:=false;
+
+ repeat
+ api_read_file(af ,m_buf ,buf_size ,len );
+
+ done:=len < buf_size;
+
+ if XML_Parse(p ,pointer(m_buf ) ,len ,int(done ) ) = XML_STATUS_ERROR then
+ begin
+ api_close_file(af );
+ XML_ParserFree(p );
+
+ sprintf(
+ @msg[0 ] ,
+ '%s at line ' ,
+ unsigned(
+ XML_ErrorString(
+ int(XML_GetErrorCode(p ) ) ) ) );
+
+ sprintf(
+ @msg[StrLen(msg ) ] ,
+ '%d'#13 ,
+ XML_GetCurrentLineNumber(p ) );
+
+ raise svg_exception.Construct(PChar(@msg[0 ] ) );
+
+ end;
+
+ until done;
+
+ api_close_file(af );
+ XML_ParserFree(p );
+
+ ts:=m_title;
+
+ while ts^ <> #0 do
+ begin
+ if byte(ts^ ) < byte(' ' ) then
+ ts^:=' ';
+
+ inc(ptrcomp(ts ) );
+
+ end;
+
+end;
+
+{ TITLE }
+function parser.title;
+begin
+ result:=m_title;
+
+end;
+
+{ PARSE_ATTR }
+procedure parser.parse_attr(attr : char_ptr_ptr );
+var
+ i : int;
+
+begin
+ i:=0;
+
+ while char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ <> NIL do
+ begin
+ if StrComp(PChar(char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ) ,'style' ) = 0 then
+ parse_style(agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ )
+ else
+ parse_attr(
+ agg_basics.char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ,
+ agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ );
+
+ inc(i ,2 );
+
+ end;
+
+end;
+
+{ PARSE_PATH }
+procedure parser.parse_path;
+var
+ i : int;
+
+ tmp : array[0..3 ] of agg_basics.char_ptr;
+
+begin
+ i:=0;
+
+ while char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ <> NIL do
+ begin
+ // The <path> tag can consist of the path itself ("d=")
+ // as well as of other parameters like "style=", "transform=", etc.
+ // In the last case we simply rely on the function of parsing
+ // attributes (see 'else' branch).
+ if StrComp(PChar(char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ) ,'d' ) = 0 then
+ begin
+ m_tokenizer.set_path_str(agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ );
+
+ m_path.parse_path(@m_tokenizer );
+
+ end
+ else
+ begin
+ // Create a temporary single pair "name-value" in order
+ // to avoid multiple calls for the same attribute.
+ tmp[0 ]:=agg_basics.char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^;
+ tmp[1 ]:=agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^;
+ tmp[2 ]:=NIL;
+ tmp[3 ]:=NIL;
+
+ parse_attr(@tmp );
+
+ end;
+
+ inc(i ,2 );
+
+ end;
+
+end;
+
+{ PARSE_POLY }
+procedure parser.parse_poly;
+var
+ i : int;
+
+ x ,y : double;
+
+begin
+ x:=0.0;
+ y:=0.0;
+
+ m_path.begin_path;
+
+ i:=0;
+
+ while char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ <> NIL do
+ begin
+ if not parse_attr(
+ agg_basics.char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ,
+ agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ ) then
+ if StrComp(PChar(agg_basics.char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ) ,'points' ) = 0 then
+ begin
+ m_tokenizer.set_path_str(agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ );
+
+ if not m_tokenizer.next then
+ raise svg_exception.Construct(PChar('parse_poly: Too few coordinates' ) );
+
+ x:=m_tokenizer.last_number;
+
+ if not m_tokenizer.next then
+ raise svg_exception.Construct(PChar('parse_poly: Too few coordinates' ) );
+
+ y:=m_tokenizer.last_number;
+
+ m_path.move_to(x ,y );
+
+ while m_tokenizer.next do
+ begin
+ x:=m_tokenizer.last_number;
+
+ if not m_tokenizer.next then
+ raise svg_exception.Construct(PChar('parse_poly: Odd number of coordinates' ) );
+
+ y:=m_tokenizer.last_number;
+
+ m_path.line_to(x ,y );
+
+ end;
+
+ end;
+
+ inc(i ,2 );
+
+ end;
+
+ m_path.end_path;
+
+end;
+
+{ PARSE_RECT }
+procedure parser.parse_rect;
+var
+ i : int;
+
+ x ,y ,w ,h : double;
+
+begin
+ x:=0.0;
+ y:=0.0;
+ w:=0.0;
+ h:=0.0;
+
+ m_path.begin_path;
+
+ i:=0;
+
+ while char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ <> NIL do
+ begin
+ if not parse_attr(
+ agg_basics.char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ,
+ agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ ) then
+ begin
+ if StrComp(PChar(char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ) ,'x' ) = 0 then
+ x:=parse_double(agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ );
+
+ if StrComp(PChar(char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ) ,'y' ) = 0 then
+ y:=parse_double(agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ );
+
+ if StrComp(PChar(char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ) ,'width' ) = 0 then
+ w:=parse_double(agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ );
+
+ if StrComp(PChar(char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ) ,'height' ) = 0 then
+ h:=parse_double(agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ );
+
+ // rx - to be implemented
+ // ry - to be implemented
+
+ end;
+
+ inc(i ,2 );
+
+ end;
+
+ if (w <> 0.0 ) and
+ (h <> 0.0 ) then
+ begin
+ if w < 0.0 then
+ raise svg_exception.Construct(PChar('parse_rect: Invalid width: ' ) );
+
+ if h < 0.0 then
+ raise svg_exception.Construct(PChar('parse_rect: Invalid height: ' ) );
+
+ m_path.move_to(x ,y );
+ m_path.line_to(x + w ,y );
+ m_path.line_to(x + w ,y + h );
+ m_path.line_to(x ,y + h );
+ m_path.close_subpath;
+
+ end;
+
+ m_path.end_path;
+
+end;
+
+{ PARSE_LINE }
+procedure parser.parse_line;
+var
+ i : int;
+
+ x1 ,y1 ,x2 ,y2 : double;
+
+begin
+ x1:=0.0;
+ y1:=0.0;
+ x2:=0.0;
+ y2:=0.0;
+
+ m_path.begin_path;
+
+ i:=0;
+
+ while char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ <> NIL do
+ begin
+ if not parse_attr(
+ agg_basics.char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ,
+ agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ ) then
+ begin
+ if StrComp(PChar(char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ) ,'x1' ) = 0 then
+ x1:=parse_double(agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ );
+
+ if StrComp(PChar(char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ) ,'y1' ) = 0 then
+ y1:=parse_double(agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ );
+
+ if StrComp(PChar(char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ) ,'x2' ) = 0 then
+ x2:=parse_double(agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ );
+
+ if StrComp(PChar(char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ) ,'y2' ) = 0 then
+ y2:=parse_double(agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ );
+
+ end;
+
+ inc(i ,2 );
+
+ end;
+
+ m_path.move_to(x1 ,y1 );
+ m_path.line_to(x2 ,y2 );
+ m_path.end_path;
+
+end;
+
+{ PARSE_STYLE }
+procedure parser.parse_style;
+var
+ nv_start ,nv_end : agg_basics.char_ptr;
+
+begin
+ while str^ <> #0 do
+ begin
+ // Left Trim
+ while (str^ <> #0 ) and
+ (str^ = ' ' ) do
+ inc(ptrcomp(str ) );
+
+ nv_start:=str;
+
+ while (str^ <> #0 ) and
+ (str^ <> ';' ) do
+ inc(ptrcomp(str ) );
+
+ nv_end:=str;
+
+ // Right Trim
+ while (ptrcomp(nv_end ) > ptrcomp(nv_start ) ) and
+ ((nv_end^ = ';' ) or
+ (nv_end^ = ' ' ) ) do
+ dec(ptrcomp(nv_end ) );
+
+ inc(ptrcomp(nv_end ) );
+
+ parse_name_value(nv_start ,nv_end );
+
+ if str^ <> #0 then
+ inc(ptrcomp(str ) );
+
+ end;
+
+end;
+
+{ PARSE_TRANSFORM }
+procedure parser.parse_transform;
+begin
+ while str^ <> #0 do
+ begin
+ if islower(str^ ) then
+ if StrLComp(PChar(str ) ,'matrix' ,6 ) = 0 then
+ inc(ptrcomp(str ) ,parse_matrix(str ) )
+ else
+ if StrLComp(PChar(str ) ,'translate' ,9 ) = 0 then
+ inc(ptrcomp(str ) ,parse_translate(str ) )
+ else
+ if StrLComp(PChar(str ) ,'rotate' ,6 ) = 0 then
+ inc(ptrcomp(str ) ,parse_rotate(str ) )
+ else
+ if StrLComp(PChar(str ) ,'scale' ,5 ) = 0 then
+ inc(ptrcomp(str ) ,parse_scale(str ) )
+ else
+ if StrLComp(PChar(str ) ,'skewX' ,5 ) = 0 then
+ inc(ptrcomp(str ) ,parse_skew_x(str ) )
+ else
+ if StrLComp(PChar(str ) ,'skewY' ,5 ) = 0 then
+ inc(ptrcomp(str ) ,parse_skew_y(str ) )
+ else
+ inc(ptrcomp(str ) )
+
+ else
+ inc(ptrcomp(str ) );
+
+ end;
+
+end;
+
+{ PARSE_MATRIX }
+function parser.parse_matrix;
+var
+ args : array[0..5 ] of double;
+
+ na ,len : unsigned;
+
+ ta : trans_affine;
+
+begin
+ na :=0;
+ len:=parse_transform_args(str ,@args ,6 ,@na );
+
+ if na <> 6 then
+ raise svg_exception.Construct(PChar('parse_matrix: Invalid number of arguments' ) );
+
+ ta.Construct(args[0 ] ,args[1 ] ,args[2 ] ,args[3 ] ,args[4 ] ,args[5 ] );
+
+ m_path.transform.premultiply(@ta );
+
+ result:=len;
+
+end;
+
+{ PARSE_TRANSLATE }
+function parser.parse_translate;
+var
+ args : array[0..1 ] of double;
+
+ na ,len : unsigned;
+
+ tat : trans_affine_translation;
+
+begin
+ na :=0;
+ len:=parse_transform_args(str ,@args ,2 ,@na );
+
+ if na = 1 then
+ args[1 ]:=0.0;
+
+ tat.Construct(args[0 ] ,args[1 ] );
+
+ m_path.transform.premultiply(@tat );
+
+ result:=len;
+
+end;
+
+{ PARSE_ROTATE }
+function parser.parse_rotate;
+var
+ args : array[0..2 ] of double;
+
+ na ,len : unsigned;
+
+ tar : trans_affine_rotation;
+
+ tat ,t : trans_affine_translation;
+
+begin
+ na :=0;
+ len:=parse_transform_args(str ,@args ,3 ,@na );
+
+ if na = 1 then
+ begin
+ tar.Construct(deg2rad(args[0 ] ) );
+
+ m_path.transform.premultiply(@tar );
+
+ end
+ else
+ if na = 3 then
+ begin
+ t.Construct(-args[1 ] ,-args[2 ] );
+
+ tar.Construct(deg2rad(args[0 ] ) );
+ tat.Construct(args[1 ] ,args[2 ] );
+
+ t.multiply(@tar );
+ t.multiply(@tat );
+
+ m_path.transform.premultiply(@t );
+
+ end
+ else
+ raise svg_exception.Construct(PChar('parse_rotate: Invalid number of arguments' ) );
+
+ result:=len;
+
+end;
+
+{ PARSE_SCALE }
+function parser.parse_scale;
+var
+ args : array[0..1 ] of double;
+
+ na ,len : unsigned;
+
+ tas : trans_affine_scaling;
+
+begin
+ na :=0;
+ len:=parse_transform_args(str ,@args ,2 ,@na );
+
+ if na = 1 then
+ args[1 ]:=args[0 ];
+
+ tas.Construct(args[0 ] ,args[1 ] );
+
+ m_path.transform.premultiply(@tas );
+
+ result:=len;
+
+end;
+
+{ PARSE_SKEW_X }
+function parser.parse_skew_x;
+var
+ arg : double;
+
+ na ,len : unsigned;
+
+ tas : trans_affine_skewing;
+
+begin
+ na :=0;
+ len:=parse_transform_args(str ,@arg ,1 ,@na );
+
+ tas.Construct(deg2rad(arg ) ,0.0 );
+
+ m_path.transform.premultiply(@tas );
+
+ result:=len;
+
+end;
+
+{ PARSE_SKEW_Y }
+function parser.parse_skew_y;
+var
+ arg : double;
+
+ na ,len : unsigned;
+
+ tas : trans_affine_skewing;
+
+begin
+ na :=0;
+ len:=parse_transform_args(str ,@arg ,1 ,@na );
+
+ tas.Construct(0.0 ,deg2rad(arg ) );
+
+ m_path.transform.premultiply(@tas );
+
+ result:=len;
+
+end;
+
+{ PARSE_ATTR }
+function parser.parse_attr(name ,value : agg_basics.char_ptr ) : boolean;
+var
+ clr : aggclr;
+
+begin
+ result:=true;
+
+ if StrComp(PChar(name ) ,'style' ) = 0 then
+ parse_style(value )
+ else
+ if StrComp(PChar(name ) ,'fill' ) = 0 then
+ if StrComp(PChar(value ) ,'none' ) = 0 then
+ m_path.fill_none
+ else
+ begin
+ clr:=parse_color(value );
+
+ m_path.fill(@clr );
+
+ end
+ else
+ if StrComp(PChar(name ) ,'fill-opacity' ) = 0 then
+ m_path.fill_opacity(parse_double(value ) )
+ else
+ if StrComp(PChar(name ) ,'stroke' ) = 0 then
+ if StrComp(PChar(value ) ,'none' ) = 0 then
+ m_path.stroke_none
+ else
+ begin
+ clr:=parse_color(value );
+
+ m_path.stroke(@clr );
+
+ end
+ else
+ if StrComp(PChar(name ) ,'stroke-width' ) = 0 then
+ m_path.stroke_width(parse_double(value ) )
+ else
+ if StrComp(PChar(name ) ,'stroke-linecap' ) = 0 then
+ begin
+ if StrComp(PChar(value ) ,'butt' ) = 0 then
+ m_path.line_cap(butt_cap )
+ else
+ if StrComp(PChar(value ) ,'round' ) = 0 then
+ m_path.line_cap(round_cap )
+ else
+ if StrComp(PChar(value ) ,'square' ) = 0 then
+ m_path.line_cap(square_cap );
+
+ end
+ else
+ if StrComp(PChar(name ) ,'stroke-linejoin' ) = 0 then
+ begin
+ if StrComp(PChar(value ) ,'miter' ) = 0 then
+ m_path.line_join(miter_join )
+ else
+ if StrComp(PChar(value ) ,'round' ) = 0 then
+ m_path.line_join(round_join )
+ else
+ if StrComp(PChar(value ) ,'bevel' ) = 0 then
+ m_path.line_join(bevel_join );
+
+ end
+ else
+ if StrComp(PChar(name ) ,'stroke-miterlimit' ) = 0 then
+ m_path.miter_limit(parse_double(value ) )
+ else
+ if StrComp(PChar(name ) ,'stroke-opacity' ) = 0 then
+ m_path.stroke_opacity(parse_double(value ) )
+ else
+ if StrComp(PChar(name ) ,'transform' ) = 0 then
+ parse_transform(value )
+
+ //else
+ // if StrComp(PChar(el ) ,'<OTHER_ATTRIBUTES>' ) = 0 then
+ // begin
+ // end
+ // ...
+
+ else
+ result:=false;
+
+end;
+
+{ PARSE_NAME_VALUE }
+function parser.parse_name_value;
+var
+ str ,val : agg_basics.char_ptr;
+
+begin
+ str:=nv_start;
+
+ while (ptrcomp(str ) < ptrcomp(nv_end ) ) and
+ (str^ <> ':' ) do
+ inc(ptrcomp(str ) );
+
+ val:=str;
+
+// Right Trim
+ while (ptrcomp(str ) > ptrcomp(nv_start ) ) and
+ ((str^ = ':' ) or
+ (str^ = ' ' ) ) do
+ dec(ptrcomp(str ) );
+
+ inc(ptrcomp(str ) );
+
+ copy_name(nv_start ,str );
+
+ while (ptrcomp(val ) < ptrcomp(nv_end ) ) and
+ ((val^ = ':' ) or
+ (val^ = ' ' ) ) do
+ inc(ptrcomp(val ) );
+
+ copy_value(val ,nv_end );
+
+ result:=parse_attr(agg_basics.char_ptr(m_attr_name ) ,agg_basics.char_ptr(m_attr_value ) );
+
+end;
+
+{ COPY_NAME }
+procedure parser.copy_name;
+var
+ len : unsigned;
+
+begin
+ len:=ptrcomp(end_ ) - ptrcomp(start );
+
+ if (m_attr_name_len = 0 ) or
+ (len > m_attr_name_len ) then
+ begin
+ agg_freemem(pointer(m_attr_name ) ,m_attr_name_aloc );
+
+ m_attr_name_aloc:=len + 1;
+
+ agg_freemem(pointer(m_attr_name ) ,m_attr_name_aloc );
+
+ m_attr_name_len:=len;
+
+ end;
+
+ if len <> 0 then
+ move(start^ ,m_attr_name^ ,len );
+
+ char_ptr(ptrcomp(m_attr_name ) + len )^:=#0;
+
+end;
+
+{ COPY_VALUE }
+procedure parser.copy_value;
+var
+ len : unsigned;
+
+begin
+ len:=ptrcomp(end_ ) - ptrcomp(start );
+
+ if (m_attr_value_len = 0 ) or
+ (len > m_attr_value_len ) then
+ begin
+ agg_freemem(pointer(m_attr_value ) ,m_attr_value_aloc );
+
+ m_attr_value_aloc:=len + 1;
+
+ agg_getmem(pointer(m_attr_value ) ,m_attr_value_aloc );
+
+ m_attr_value_len:=len;
+
+ end;
+
+ if len <> 0 then
+ move(start^ ,m_attr_value^ ,len );
+
+ char_ptr(ptrcomp(m_attr_value ) + len )^:=#0;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/svg/agg_svg_path_renderer.pas b/src/corelib/render/software/svg/agg_svg_path_renderer.pas
new file mode 100644
index 00000000..c1fa0614
--- /dev/null
+++ b/src/corelib/render/software/svg/agg_svg_path_renderer.pas
@@ -0,0 +1,893 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 24.04.2006-Milano: Unit port establishment
+//
+{ agg_svg_path_renderer.pas }
+unit
+ agg_svg_path_renderer ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_path_storage ,
+ agg_conv_transform ,
+ agg_conv_stroke ,
+ agg_conv_contour ,
+ agg_conv_curve ,
+ agg_color ,
+ agg_array ,
+ agg_bounding_rect ,
+ agg_rasterizer_scanline_aa ,
+ agg_vertex_source ,
+ agg_svg_path_tokenizer ,
+ agg_svg_exception ,
+ agg_trans_affine ,
+ agg_math_stroke ,
+ agg_scanline ,
+ agg_renderer_scanline ,
+ agg_render_scanlines ;
+
+{ TYPES DEFINITION }
+type
+ conv_count = object(vertex_source )
+ m_source : vertex_source_ptr;
+ m_count : unsigned;
+
+ constructor Construct(vs : vertex_source_ptr );
+
+ procedure count_(n : unsigned );
+ function _count : unsigned;
+
+ procedure rewind(path_id : unsigned ); virtual;
+ function vertex(x ,y : double_ptr ) : unsigned; virtual;
+
+ end;
+
+// Basic path attributes
+ path_attributes_ptr = ^path_attributes;
+ path_attributes = object
+ index : unsigned;
+
+ fill_color ,
+ stroke_color : aggclr;
+ fill_flag ,
+ stroke_flag ,
+ even_odd_flag : boolean;
+
+ line_join ,
+ line_cap : unsigned;
+ miter_limit ,
+ stroke_width : double;
+
+ transform : trans_affine;
+
+ // Empty constructor
+ constructor Construct; overload;
+
+ // Copy constructor
+ constructor Construct(attr : path_attributes_ptr ); overload;
+
+ // Copy constructor with new index value
+ constructor Construct(attr : path_attributes_ptr; idx : unsigned ); overload;
+
+ end;
+
+// Path container and renderer.
+ path_renderer_ptr = ^path_renderer;
+ path_renderer = object(unsigned_list )
+ m_storage : path_storage;
+ m_attr_storage ,
+ m_attr_stack : pod_deque;
+ m_transform : trans_affine;
+
+ m_curved : conv_curve;
+ m_curved_count : conv_count;
+
+ m_curved_stroked : conv_stroke;
+ m_curved_stroked_trans : conv_transform;
+
+ m_curved_trans : conv_transform;
+ m_curved_trans_contour : conv_contour;
+
+ constructor Construct;
+ destructor Destruct;
+
+ procedure remove_all;
+
+ // Use these functions as follows:
+ // begin_path when the XML tag <path> comes ("start_element" handler)
+ // parse_path on "d=" tag attribute
+ // end_path when parsing of the entire tag is done.
+ procedure begin_path;
+ procedure parse_path(tok : path_tokenizer_ptr );
+ procedure end_path;
+
+ // The following functions are essentially a "reflection" of
+ // the respective SVG path commands.
+ procedure move_to (x ,y : double; rel : boolean = false ); // M, m
+ procedure line_to (x ,y : double; rel : boolean = false ); // L, l
+ procedure hline_to(x : double; rel : boolean = false ); // H, h
+ procedure vline_to(y : double; rel : boolean = false ); // V, v
+
+ procedure curve3(x1 ,y1 ,x ,y : double; rel : boolean = false ); overload; // Q, q
+ procedure curve3(x ,y : double; rel : boolean = false ); overload; // T, t
+ procedure curve4(x1 ,y1 ,x2 ,y2 ,x ,y : double; rel : boolean = false ); overload; // C, c
+ procedure curve4(x2 ,y2 ,x ,y : double; rel : boolean = false ); overload; // S, s
+
+ procedure close_subpath; // Z, z
+
+ procedure add_path(vs : vertex_source_ptr; path_id : unsigned = 0; solid_path : boolean = true );
+ function vertex_count : unsigned;
+
+ // Call these functions on <g> tag (start_element, end_element respectively)
+ procedure push_attr;
+ procedure pop_attr;
+
+ // Attribute setting functions
+ procedure fill (f : aggclr_ptr );
+ procedure stroke (s : aggclr_ptr );
+ procedure even_odd (flag : boolean );
+ procedure stroke_width(w : double );
+
+ procedure fill_none;
+ procedure stroke_none;
+
+ procedure fill_opacity (op : double );
+ procedure stroke_opacity(op : double );
+ procedure line_join (join : unsigned );
+ procedure line_cap (cap : unsigned );
+ procedure miter_limit (ml : double );
+
+ function transform : trans_affine_ptr;
+
+ // Make all polygons CCW-oriented
+ procedure arrange_orientations;
+
+ // Expand all polygons
+ procedure expand(value : double );
+
+ function array_operator(idx : unsigned ) : unsigned; virtual;
+ procedure bounding_rect (x1 ,y1 ,x2 ,y2 : double_ptr );
+
+ // Rendering. One can specify two additional parameters:
+ // trans_affine and opacity. They can be used to transform the whole
+ // image and/or to make it translucent.
+ procedure render(
+ ras : rasterizer_scanline_ptr;
+ sl : scanline_ptr;
+ ren : renderer_scanline_ptr;
+ mtx : trans_affine_ptr;
+ cb : rect_ptr;
+ opacity : double = 1.0 );
+
+ // Private
+ function cur_attr : path_attributes_ptr;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor conv_count.Construct;
+begin
+ m_source:=vs;
+ m_count :=0;
+
+end;
+
+{ COUNT_ }
+procedure conv_count.count_;
+begin
+ m_count:=n;
+
+end;
+
+{ _COUNT }
+function conv_count._count;
+begin
+ result:=m_count;
+
+end;
+
+{ REWIND }
+procedure conv_count.rewind;
+begin
+ m_source.rewind(path_id );
+
+end;
+
+{ VERTEX }
+function conv_count.vertex;
+begin
+ inc(m_count );
+
+ result:=m_source.vertex(x ,y );
+
+end;
+
+{ CONSTRUCT }
+constructor path_attributes.Construct;
+begin
+ index:=0;
+
+ fill_color.ConstrInt (0 ,0 ,0 );
+ stroke_color.ConstrInt(0 ,0 ,0 );
+
+ fill_flag :=true;
+ stroke_flag :=false;
+ even_odd_flag:=false;
+ line_join :=miter_join;
+ line_cap :=butt_cap;
+ miter_limit :=4.0;
+ stroke_width :=1.0;
+
+ transform.Construct;
+
+end;
+
+{ CONSTRUCT }
+constructor path_attributes.Construct(attr : path_attributes_ptr );
+begin
+ index:=attr.index;
+
+ fill_color.Construct (@attr.fill_color );
+ stroke_color.Construct(@attr.stroke_color );
+
+ fill_flag :=attr.fill_flag;
+ stroke_flag :=attr.stroke_flag;
+ even_odd_flag:=attr.even_odd_flag;
+ line_join :=attr.line_join;
+ line_cap :=attr.line_cap;
+ miter_limit :=attr.miter_limit;
+ stroke_width :=attr.stroke_width;
+
+ transform.Construct;
+ transform.assign_all(@attr.transform );
+
+end;
+
+{ CONSTRUCT }
+constructor path_attributes.Construct(attr : path_attributes_ptr; idx : unsigned );
+begin
+ index:=idx;
+
+ fill_color.Construct (@attr.fill_color );
+ stroke_color.Construct(@attr.stroke_color );
+
+ fill_flag :=attr.fill_flag;
+ stroke_flag :=attr.stroke_flag;
+ even_odd_flag:=attr.even_odd_flag;
+ line_join :=attr.line_join;
+ line_cap :=attr.line_cap;
+ miter_limit :=attr.miter_limit;
+ stroke_width :=attr.stroke_width;
+
+ transform.Construct;
+ transform.assign_all(@attr.transform );
+
+end;
+
+{ CONSTRUCT }
+constructor path_renderer.Construct;
+begin
+ m_storage.Construct;
+ m_attr_storage.Construct(sizeof(path_attributes ) );
+ m_attr_stack.Construct(sizeof(path_attributes ) );
+ m_transform.Construct;
+
+ m_curved.Construct (@m_storage );
+ m_curved_count.Construct(@m_curved );
+
+ m_curved_stroked.Construct (@m_curved_count );
+ m_curved_stroked_trans.Construct(@m_curved_stroked ,@m_transform );
+
+ m_curved_trans.Construct (@m_curved_count ,@m_transform );
+ m_curved_trans_contour.Construct(@m_curved_trans );
+
+end;
+
+{ DESTRUCT }
+destructor path_renderer.Destruct;
+begin
+ m_curved_trans_contour.Destruct;
+ m_curved_stroked.Destruct;
+ m_curved.Destruct;
+
+ m_attr_stack.Destruct;
+ m_attr_storage.Destruct;
+ m_storage.Destruct;
+
+end;
+
+{ REMOVE_ALL }
+procedure path_renderer.remove_all;
+begin
+ m_storage.remove_all;
+ m_attr_storage.remove_all;
+ m_attr_stack.remove_all;
+ m_transform.reset;
+
+end;
+
+{ BEGIN_PATH }
+procedure path_renderer.begin_path;
+var
+ idx : unsigned;
+ attr : path_attributes;
+
+begin
+ push_attr;
+
+ idx:=m_storage.start_new_path;
+
+ attr.Construct(cur_attr ,idx );
+
+ m_attr_storage.add(@attr );
+
+end;
+
+{ PARSE_PATH }
+procedure path_renderer.parse_path;
+var
+ arg : array[0..9 ] of double;
+ i : unsigned;
+ cmd : char;
+ buf : array[0..99 ] of char;
+
+begin
+ while tok.next do
+ begin
+ cmd:=tok.last_command;
+
+ case cmd of
+ 'M' ,'m' :
+ begin
+ arg[0 ]:=tok.last_number;
+ arg[1 ]:=tok.next(cmd );
+
+ move_to(arg[0 ] ,arg[1 ] ,cmd = 'm' );
+
+ end;
+
+ 'L' ,'l' :
+ begin
+ arg[0 ]:=tok.last_number;
+ arg[1 ]:=tok.next(cmd );
+
+ line_to(arg[0 ] ,arg[1 ] ,cmd = 'l' );
+
+ end;
+
+ 'V' ,'v' :
+ vline_to(tok.last_number ,cmd = 'v' );
+
+ 'H' ,'h' :
+ hline_to(tok.last_number ,cmd = 'h' );
+
+ 'Q' ,'q' :
+ begin
+ arg[0 ]:=tok.last_number;
+
+ for i:=1 to 3 do
+ arg[i ]:=tok.next(cmd );
+
+ curve3(arg[0 ] ,arg[1 ] ,arg[2 ] ,arg[3 ] ,cmd = 'q' );
+
+ end;
+
+ 'T' ,'t' :
+ begin
+ arg[0 ]:=tok.last_number;
+ arg[1 ]:=tok.next(cmd );
+
+ curve3(arg[0 ] ,arg[1 ] ,cmd = 't' );
+
+ end;
+
+ 'C' ,'c' :
+ begin
+ arg[0 ]:=tok.last_number;
+
+ for i:=1 to 5 do
+ arg[i ]:=tok.next(cmd );
+
+ curve4(arg[0 ] ,arg[1 ] ,arg[2 ] ,arg[3 ] ,arg[4 ] ,arg[5 ] ,cmd = 'c' );
+
+ end;
+
+ 'S' ,'s' :
+ begin
+ arg[0 ]:=tok.last_number;
+
+ for i:=1 to 3 do
+ arg[i ]:=tok.next(cmd );
+
+ curve4(arg[0 ] ,arg[1 ] ,arg[2 ] ,arg[3 ] ,cmd = 's' );
+
+ end;
+
+ 'A' ,'a' :
+ raise svg_exception.Construct(PChar('parse_path: Command A: NOT IMPLEMENTED YET' ) );
+
+ 'Z' ,'z' :
+ close_subpath;
+
+ else
+ begin
+ sprintf(@buf[0 ] ,'parse_path: Invalid Command %c' ,unsigned(cmd ) );
+
+ raise svg_exception.Construct(PChar(@buf[0 ] ) );
+
+ end;
+
+ end;
+
+ end;
+
+end;
+
+{ END_PATH }
+procedure path_renderer.end_path;
+var
+ idx : unsigned;
+ attr : path_attributes;
+
+begin
+ if m_attr_storage.size = 0 then
+ raise svg_exception(PChar('end_path : The path was not begun' ) );
+
+ attr.Construct(cur_attr );
+
+ idx :=path_attributes_ptr(m_attr_storage.array_operator(m_attr_storage.size - 1 ) ).index;
+ attr.index:=idx;
+
+ move(
+ pointer(@attr )^ ,
+ path_attributes_ptr(m_attr_storage.array_operator(m_attr_storage.size - 1 ) )^ ,
+ sizeof(path_attributes ) );
+
+ pop_attr;
+
+end;
+
+{ MOVE_TO }
+procedure path_renderer.move_to;
+begin
+ if rel then
+ m_storage.rel_to_abs(@x ,@y );
+
+ m_storage.move_to(x ,y );
+
+end;
+
+{ LINE_TO }
+procedure path_renderer.line_to;
+begin
+ if rel then
+ m_storage.rel_to_abs(@x ,@y );
+
+ m_storage.line_to(x ,y );
+
+end;
+
+{ HLINE_TO }
+procedure path_renderer.hline_to;
+var
+ x2 ,y2 : double;
+
+begin
+ x2:=0.0;
+ y2:=0.0;
+
+ if m_storage.total_vertices <> 0 then
+ begin
+ m_storage.vertex_(m_storage.total_vertices - 1 ,@x2 ,@y2 );
+
+ if rel then
+ x:=x + x2;
+
+ m_storage.line_to(x ,y2 );
+
+ end;
+
+end;
+
+{ VLINE_TO }
+procedure path_renderer.vline_to;
+var
+ x2 ,y2 : double;
+
+begin
+ x2:=0.0;
+ y2:=0.0;
+
+ if m_storage.total_vertices <> 0 then
+ begin
+ m_storage.vertex_(m_storage.total_vertices - 1 ,@x2 ,@y2 );
+
+ if rel then
+ y:=y + y2;
+
+ m_storage.line_to(x2 ,y );
+
+ end;
+
+end;
+
+{ CURVE3 }
+procedure path_renderer.curve3(x1 ,y1 ,x ,y : double; rel : boolean = false );
+begin
+ if rel then
+ begin
+ m_storage.rel_to_abs(@x1 ,@y1 );
+ m_storage.rel_to_abs(@x ,@y );
+
+ end;
+
+ m_storage.curve3(x1 ,y1 ,x ,y );
+
+end;
+
+{ CURVE3 }
+procedure path_renderer.curve3(x ,y : double; rel : boolean = false );
+begin
+// raise exception("curve3(x, y) : NOT IMPLEMENTED YET");
+ if rel then
+ m_storage.curve3_rel(x ,y )
+ else
+ m_storage.curve3(x ,y );
+
+end;
+
+{ CURVE4 }
+procedure path_renderer.curve4(x1 ,y1 ,x2 ,y2 ,x ,y : double; rel : boolean = false );
+begin
+ if rel then
+ begin
+ m_storage.rel_to_abs(@x1 ,@y1 );
+ m_storage.rel_to_abs(@x2 ,@y2 );
+ m_storage.rel_to_abs(@x ,@y );
+
+ end;
+
+ m_storage.curve4(x1 ,y1 ,x2 ,y2 ,x ,y );
+
+end;
+
+{ CURVE4 }
+procedure path_renderer.curve4(x2 ,y2 ,x ,y : double; rel : boolean = false );
+begin
+//throw exception("curve4(x2, y2, x, y) : NOT IMPLEMENTED YET");
+ if rel then
+ m_storage.curve4_rel(x2 ,y2 ,x ,y )
+ else
+ m_storage.curve4(x2 ,y2 ,x ,y );
+
+end;
+
+{ CLOSE_SUBPATH }
+procedure path_renderer.close_subpath;
+begin
+ m_storage.end_poly(path_flags_close );
+
+end;
+
+{ ADD_PATH }
+procedure path_renderer.add_path;
+begin
+ m_storage.add_path(vs ,path_id ,solid_path );
+
+end;
+
+{ VERTEX_COUNT }
+function path_renderer.vertex_count;
+begin
+ result:=m_curved_count._count;
+
+end;
+
+{ PUSH_ATTR }
+procedure path_renderer.push_attr;
+var
+ attr : path_attributes;
+
+begin
+ if m_attr_stack.size <> 0 then
+ m_attr_stack.add(
+ m_attr_stack.array_operator(m_attr_stack.size - 1 ) )
+ else
+ begin
+ attr.Construct;
+
+ m_attr_stack.add(@attr );
+
+ end;
+
+end;
+
+{ POP_ATTR }
+procedure path_renderer.pop_attr;
+begin
+ if m_attr_stack.size = 0 then
+ raise svg_exception(PChar('pop_attr : Attribute stack is empty' ) );
+
+ m_attr_stack.remove_last;
+
+end;
+
+{ FILL }
+procedure path_renderer.fill;
+var
+ attr : path_attributes_ptr;
+
+begin
+ attr:=cur_attr;
+
+ attr.fill_color:=f^;
+ attr.fill_flag :=true;
+
+end;
+
+{ STROKE }
+procedure path_renderer.stroke;
+var
+ attr : path_attributes_ptr;
+
+begin
+ attr:=cur_attr;
+
+ attr.stroke_color:=s^;
+ attr.stroke_flag :=true;
+
+end;
+
+{ EVEN_ODD }
+procedure path_renderer.even_odd;
+begin
+ cur_attr.even_odd_flag:=flag;
+
+end;
+
+{ STROKE_WIDTH }
+procedure path_renderer.stroke_width;
+var
+ attr : path_attributes_ptr;
+
+begin
+ attr:=cur_attr;
+
+ attr.stroke_width:=w;
+ attr.stroke_flag :=true;
+
+end;
+
+{ FILL_NONE }
+procedure path_renderer.fill_none;
+begin
+ cur_attr.fill_flag:=false;
+
+end;
+
+{ STROKE_NONE }
+procedure path_renderer.stroke_none;
+begin
+ cur_attr.stroke_flag:=false;
+
+end;
+
+{ FILL_OPACITY }
+procedure path_renderer.fill_opacity;
+begin
+ cur_attr.fill_color.opacity_(op );
+
+end;
+
+{ STROKE_OPACITY }
+procedure path_renderer.stroke_opacity;
+begin
+ cur_attr.stroke_color.opacity_(op );
+
+end;
+
+{ LINE_JOIN }
+procedure path_renderer.line_join;
+begin
+ cur_attr.line_join:=join;
+
+end;
+
+{ LINE_CAP }
+procedure path_renderer.line_cap;
+begin
+ cur_attr.line_cap:=cap;
+
+end;
+
+{ MITER_LIMIT }
+procedure path_renderer.miter_limit;
+begin
+ cur_attr.miter_limit:=ml;
+
+end;
+
+{ TRANSFORM }
+function path_renderer.transform;
+begin
+ result:=@cur_attr.transform;
+
+end;
+
+{ ARRANGE_ORIENTATIONS }
+procedure path_renderer.arrange_orientations;
+begin
+ m_storage.arrange_orientations_all_paths(path_flags_ccw );
+
+end;
+
+{ EXPAND }
+procedure path_renderer.expand;
+begin
+ m_curved_trans_contour.width_(value );
+
+end;
+
+{ ARRAY_OPERATOR }
+function path_renderer.array_operator;
+begin
+ m_transform.assign_all(
+ @path_attributes_ptr(
+ m_attr_storage.array_operator(idx ) ).transform );
+
+ result:=path_attributes_ptr(m_attr_storage.array_operator(idx ) ).index;
+
+end;
+
+{ BOUNDING_RECT }
+procedure path_renderer.bounding_rect;
+var
+ trans : conv_transform;
+
+begin
+ trans.Construct(@m_storage ,@m_transform );
+
+ bounding_rect_ul(
+ @trans ,@self ,0 ,m_attr_storage.size ,x1 ,y1 ,x2 ,y2 );
+
+end;
+
+{ RENDER }
+procedure path_renderer.render;
+var
+ i : unsigned;
+
+ scl : double;
+
+ attr : path_attributes_ptr;
+
+ color : aggclr;
+
+begin
+ ras.clip_box (cb.x1 ,cb.y1 ,cb.x2 ,cb.y2 );
+ m_curved_count.count_(0 );
+
+ i:=0;
+
+ while i < m_attr_storage.size do
+ begin
+ attr:=path_attributes_ptr(m_attr_storage.array_operator(i ) );
+
+ m_transform.assign_all(@attr.transform );
+ m_transform.multiply (mtx );
+
+ scl:=m_transform.scale;
+
+ //m_curved.approximation_method(curve_inc );
+
+ m_curved.approximation_scale_(scl );
+ m_curved.angle_tolerance_ (0.0 );
+
+ color.Construct;
+
+ if attr.fill_flag then
+ begin
+ ras.reset;
+
+ if attr.even_odd_flag then
+ ras.filling_rule(fill_even_odd )
+ else
+ ras.filling_rule(fill_non_zero );
+
+ if Abs(m_curved_trans_contour._width ) < 0.0001 then
+ ras.add_path(@m_curved_trans ,attr.index )
+ else
+ begin
+ m_curved_trans_contour.miter_limit_(attr.miter_limit );
+
+ ras.add_path(@m_curved_trans_contour ,attr.index );
+
+ end;
+
+ color:=attr.fill_color;
+
+ color.opacity_ (color._opacity * opacity );
+ ren.color_ (@color );
+ render_scanlines(ras ,sl ,ren );
+
+ end;
+
+ if attr.stroke_flag then
+ begin
+ m_curved_stroked.width_(attr.stroke_width );
+
+ //m_curved_stroked.line_join_((attr.line_join == miter_join) ? miter_join_round : attr.line_join);
+
+ m_curved_stroked.line_join_ (attr.line_join );
+ m_curved_stroked.line_cap_ (attr.line_cap );
+ m_curved_stroked.miter_limit_ (attr.miter_limit );
+ m_curved_stroked.approximation_scale_(scl );
+
+ // If the *visual* line width is considerable we
+ // turn on processing of curve cusps.
+ //---------------------
+ if attr.stroke_width * scl > 1.0 then
+ m_curved.angle_tolerance_(0.2 );
+
+ ras.reset;
+ ras.filling_rule(fill_non_zero );
+ ras.add_path (@m_curved_stroked_trans ,attr.index );
+
+ color:=attr.stroke_color;
+
+ color.opacity_ (color._opacity * opacity);
+ ren.color_ (@color );
+ render_scanlines(ras ,sl ,ren );
+
+ end;
+
+ inc(i );
+
+ end;
+
+end;
+
+{ CUR_ATTR }
+function path_renderer.cur_attr;
+begin
+ if m_attr_stack.size = 0 then
+ raise svg_exception.Construct(PChar('cur_attr : Attribute stack is empty' ) );
+
+ result:=
+ path_attributes_ptr(
+ m_attr_stack.array_operator(m_attr_stack.size - 1 ) );
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/svg/agg_svg_path_tokenizer.pas b/src/corelib/render/software/svg/agg_svg_path_tokenizer.pas
new file mode 100644
index 00000000..e96df6a9
--- /dev/null
+++ b/src/corelib/render/software/svg/agg_svg_path_tokenizer.pas
@@ -0,0 +1,325 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 24.04.2006-Milano: Unit port establishment
+//
+{ agg_svg_path_tokenizer.pas }
+unit
+ agg_svg_path_tokenizer ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_svg_exception ;
+
+{ TYPES DEFINITION }
+const
+ s_commands = '+-MmZzLlHhVvCcSsQqTtAaFfPp';
+ s_numeric = '.Ee0123456789';
+ s_separators = ' ,'#9#10#13;
+
+type
+// SVG path tokenizer.
+// Example:
+//
+// agg::svg::path_tokenizer tok;
+//
+// tok.set_str("M-122.304 84.285L-122.304 84.285 122.203 86.179 ");
+// while(tok.next())
+// {
+// printf("command='%c' number=%f\n",
+// tok.last_command(),
+// tok.last_number());
+// }
+//
+// The tokenizer does all the routine job of parsing the SVG paths.
+// It doesn't recognize any graphical primitives, it even doesn't know
+// anything about pairs of coordinates (X,Y). The purpose of this class
+// is to tokenize the numeric values and commands. SVG paths can
+// have single numeric values for Horizontal or Vertical line_to commands
+// as well as more than two coordinates (4 or 6) for Bezier curves
+// depending on the semantics of the command.
+// The behaviour is as follows:
+//
+// Each call to next() returns true if there's new command or new numeric
+// value or false when the path ends. How to interpret the result
+// depends on the sematics of the command. For example, command "C"
+// (cubic Bezier curve) implies 6 floating point numbers preceded by this
+// command. If the command assumes no arguments (like z or Z) the
+// the last_number() values won't change, that is, last_number() always
+// returns the last recognized numeric value, so does last_command().
+ path_tokenizer_ptr = ^path_tokenizer;
+ path_tokenizer = object
+ m_separators_mask ,
+ m_commands_mask ,
+ m_numeric_mask : array[0..256 div 8 - 1 ] of char;
+
+ m_path : char_ptr;
+ m_last_number : double;
+ m_last_command : char;
+
+ constructor Construct;
+
+ procedure set_path_str(str : char_ptr );
+
+ function next : boolean; overload;
+ function next(cmd : char ) : double; overload;
+
+ function last_command : char;
+ function last_number : double;
+
+ procedure init_char_mask(mask ,char_set : char_ptr );
+
+ function contains_ (mask : char_ptr; c : unsigned ) : boolean;
+ function is_command (c : unsigned ) : boolean;
+ function is_numeric (c : unsigned ) : boolean;
+ function is_separator(c : unsigned ) : boolean;
+ function parse_number : boolean;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor path_tokenizer.Construct;
+begin
+ m_path :=NIL;
+ m_last_command:=#0;
+ m_last_number :=0.0;
+
+ init_char_mask(@m_commands_mask[0 ] ,@s_commands[1 ] );
+ init_char_mask(@m_numeric_mask[0 ] ,@s_numeric[1 ] );
+ init_char_mask(@m_separators_mask[0 ] ,@s_separators[1 ] );
+
+end;
+
+{ SET_PATH_STR }
+procedure path_tokenizer.set_path_str;
+begin
+ m_path :=str;
+ m_last_command:=#0;
+ m_last_number :=0.0;
+
+end;
+
+{ NEXT }
+function path_tokenizer.next : boolean;
+var
+ buf : array[0..99 ] of char;
+
+begin
+ result:=false;
+
+ if m_path = NIL then
+ result:=false;
+
+// Skip all white spaces and other garbage
+ while (m_path^ <> #0 ) and
+ not is_command(unsigned(m_path^ ) ) and
+ not is_numeric(unsigned(m_path^ ) ) do
+ begin
+ if not is_separator(unsigned(m_path^ ) ) then
+ begin
+ sprintf(@buf[0 ] ,'path_tokenizer::next : Invalid Character %c' ,unsigned(m_path^ ) );
+
+ raise svg_exception.Construct(PChar(@buf[0 ] ) );
+
+ end;
+
+ inc(ptrcomp(m_path ) );
+
+ end;
+
+ if m_path^ = #0 then
+ exit;
+
+ if is_command(unsigned(m_path^ ) ) then
+ begin
+ // Check if the command is a numeric sign character
+ if (m_path^ = '-' ) or
+ (m_path^ = '+' ) then
+ begin
+ result:=parse_number;
+
+ exit;
+
+ end;
+
+ m_last_command:=m_path^;
+
+ inc(ptrcomp(m_path ) );
+
+ while (m_path^ <> #0 ) and
+ is_separator(unsigned(m_path^ ) ) do
+ inc(ptrcomp(m_path ) );
+
+ if m_path^ = #0 then
+ begin
+ result:=true;
+
+ exit;
+
+ end;
+
+ end;
+
+ result:=parse_number;
+
+end;
+
+{ NEXT }
+function path_tokenizer.next(cmd : char ) : double;
+var
+ buf : array[0..99 ] of char;
+
+begin
+ if not next then
+ raise svg_exception.Construct(PChar('parse_path: Unexpected end of path' ) );
+
+ if last_command <> cmd then
+ begin
+ sprintf(@buf[0 ] ,'parse_path: Command %c: bad or missing parameters' ,unsigned(cmd ) );
+
+ raise svg_exception.Construct(PChar(@buf[0 ] ) );
+
+ end;
+
+ result:=last_number;
+
+end;
+
+{ LAST_COMMAND }
+function path_tokenizer.last_command;
+begin
+ result:=m_last_command;
+
+end;
+
+{ LAST_NUMBER }
+function path_tokenizer.last_number;
+begin
+ result:=m_last_number;
+
+end;
+
+{ INIT_CHAR_MASK }
+procedure path_tokenizer.init_char_mask;
+var
+ c : unsigned;
+
+begin
+ fillchar(mask^ ,256 div 8 ,0 );
+
+ while char_set^ <> #0 do
+ begin
+ c:=int8u_ptr(char_set )^;
+
+ int8u_ptr(ptrcomp(mask ) + (c shr 3 ) )^:=
+ int8u_ptr(ptrcomp(mask ) + (c shr 3 ) )^ or (1 shl (c and 7 ) );
+
+ inc(ptrcomp(char_set ) );
+
+ end;
+
+end;
+
+{ CONTAINS_ }
+function path_tokenizer.contains_;
+begin
+ result:=
+ (int8u_ptr(ptrcomp(mask ) + (c shr 3 ) and (256 div 8 - 1 ) )^ and
+ (1 shl (c and 7 ) ) ) <> 0;
+
+end;
+
+{ IS_COMMAND }
+function path_tokenizer.is_command;
+begin
+ result:=contains_(@m_commands_mask[0 ] ,c );
+
+end;
+
+{ IS_NUMERIC }
+function path_tokenizer.is_numeric;
+begin
+ result:=contains_(@m_numeric_mask[0 ] ,c );
+
+end;
+
+{ IS_SEPARATOR }
+function path_tokenizer.is_separator;
+begin
+ result:=contains_(@m_separators_mask[0 ] ,c );
+
+end;
+
+{ PARSE_NUMBER }
+function path_tokenizer.parse_number;
+var
+ buf : array[0..255 ] of char; // Should be enough for any number
+
+ buf_ptr : char_ptr;
+
+begin
+ buf_ptr:=@buf[0 ];
+
+// Copy all sign characters
+ while (ptrcomp(buf_ptr ) < ptrcomp(@buf[0 ] ) + 255 ) and
+ ((m_path^ = '-' ) or
+ (m_path^ = '+' ) ) do
+ begin
+ buf_ptr^:=m_path^;
+
+ inc(ptrcomp(buf_ptr ) );
+ inc(ptrcomp(m_path ) );
+
+ end;
+
+// Copy all numeric characters
+ while (ptrcomp(buf_ptr ) < ptrcomp(@buf[0 ] ) + 255 ) and
+ is_numeric(unsigned(m_path^ ) ) do
+ begin
+ buf_ptr^:=m_path^;
+
+ inc(ptrcomp(buf_ptr ) );
+ inc(ptrcomp(m_path ) );
+
+ end;
+
+ buf_ptr^:=#0;
+
+ m_last_number:=get_double(pointer(PChar(@buf[0 ] ) ) );
+
+ result:=true;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/util/agg_color_conv.pas b/src/corelib/render/software/util/agg_color_conv.pas
new file mode 100644
index 00000000..b00c590e
--- /dev/null
+++ b/src/corelib/render/software/util/agg_color_conv.pas
@@ -0,0 +1,565 @@
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// Conversion from one colorspace/pixel format to another
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 16.12.2005-Milano: Unit port establishment
+//
+{ agg_color_conv.pas }
+unit
+ agg_color_conv ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ,
+ agg_color ,
+ agg_rendering_buffer ;
+
+{ TYPES DEFINITION }
+type
+ CopyRow = procedure(dst ,src : int8u_ptr; width : unsigned );
+
+{ GLOBAL PROCEDURES }
+ procedure color_conv(dst ,src : rendering_buffer_ptr; copy_row_functor : CopyRow );
+
+ procedure color_conv_gray8_to_bgr24 (dst ,src : int8u_ptr; width : unsigned );
+ procedure color_conv_gray8_to_rgb24 (dst ,src : int8u_ptr; width : unsigned );
+
+ procedure color_conv_gray16_to_gray8 (dst ,src : int8u_ptr; width : unsigned );
+
+ procedure color_conv_rgb555_to_rgb555(dst ,src : int8u_ptr; width : unsigned );
+ procedure color_conv_rgb555_to_rgb565(dst ,src : int8u_ptr; width : unsigned );
+ procedure color_conv_rgb555_to_rgb24 (dst ,src : int8u_ptr; width : unsigned );
+ procedure color_conv_rgb555_to_bgr24 (dst ,src : int8u_ptr; width : unsigned );
+ procedure color_conv_rgb555_to_abgr32(dst ,src : int8u_ptr; width : unsigned );
+ procedure color_conv_rgb555_to_argb32(dst ,src : int8u_ptr; width : unsigned );
+ procedure color_conv_rgb555_to_bgra32(dst ,src : int8u_ptr; width : unsigned );
+ procedure color_conv_rgb555_to_rgba32(dst ,src : int8u_ptr; width : unsigned );
+
+ procedure color_conv_rgb565_to_rgb555(dst ,src : int8u_ptr; width : unsigned );
+
+ procedure color_conv_bgr24_to_gray8 (dst ,src : int8u_ptr; width : unsigned );
+ procedure color_conv_bgr24_to_gray16 (dst ,src : int8u_ptr; width : unsigned );
+ procedure color_conv_bgr24_to_rgb555 (dst ,src : int8u_ptr; width : unsigned );
+ procedure color_conv_bgr24_to_rgb565 (dst ,src : int8u_ptr; width : unsigned );
+ procedure color_conv_bgr24_to_rgb24 (dst ,src : int8u_ptr; width : unsigned );
+ procedure color_conv_bgr24_to_bgr24 (dst ,src : int8u_ptr; width : unsigned );
+ procedure color_conv_bgr24_to_abgr32 (dst ,src : int8u_ptr; width : unsigned );
+ procedure color_conv_bgr24_to_argb32 (dst ,src : int8u_ptr; width : unsigned );
+ procedure color_conv_bgr24_to_bgra32 (dst ,src : int8u_ptr; width : unsigned );
+ procedure color_conv_bgr24_to_rgba32 (dst ,src : int8u_ptr; width : unsigned );
+ procedure color_conv_bgr24_to_rgb48 (dst ,src : int8u_ptr; width : unsigned );
+ procedure color_conv_bgr24_to_bgr48 (dst ,src : int8u_ptr; width : unsigned );
+ procedure color_conv_bgr24_to_abgr64 (dst ,src : int8u_ptr; width : unsigned );
+ procedure color_conv_bgr24_to_argb64 (dst ,src : int8u_ptr; width : unsigned );
+ procedure color_conv_bgr24_to_bgra64 (dst ,src : int8u_ptr; width : unsigned );
+ procedure color_conv_bgr24_to_rgba64 (dst ,src : int8u_ptr; width : unsigned );
+
+ procedure color_conv_rgb24_to_bgr24 (dst ,src : int8u_ptr; width : unsigned );
+ procedure color_conv_rgb24_to_bgra32 (dst ,src : int8u_ptr; width : unsigned );
+
+ procedure color_conv_bgra32_to_rgb555(dst ,src : int8u_ptr; width : unsigned );
+ procedure color_conv_bgra32_to_rgb565(dst ,src : int8u_ptr; width : unsigned );
+ procedure color_conv_bgra32_to_rgb24 (dst ,src : int8u_ptr; width : unsigned );
+ procedure color_conv_bgra32_to_bgr24 (dst ,src : int8u_ptr; width : unsigned );
+ procedure color_conv_bgra32_to_abgr32(dst ,src : int8u_ptr; width : unsigned );
+ procedure color_conv_bgra32_to_argb32(dst ,src : int8u_ptr; width : unsigned );
+ procedure color_conv_bgra32_to_bgra32(dst ,src : int8u_ptr; width : unsigned );
+ procedure color_conv_bgra32_to_rgba32(dst ,src : int8u_ptr; width : unsigned );
+ procedure color_conv_bgra64_to_bgra32(dst ,src : int8u_ptr; width : unsigned );
+
+ procedure color_conv_abgr32_to_argb32(dst ,src : int8u_ptr; width : unsigned );
+ procedure color_conv_abgr32_to_bgra32(dst ,src : int8u_ptr; width : unsigned );
+ procedure color_conv_abgr64_to_bgra32(dst ,src : int8u_ptr; width : unsigned );
+
+ procedure color_conv_rgba32_to_argb32(dst ,src : int8u_ptr; width : unsigned );
+ procedure color_conv_rgba32_to_bgra32(dst ,src : int8u_ptr; width : unsigned );
+
+ procedure color_conv_argb32_to_bgra32(dst ,src : int8u_ptr; width : unsigned );
+ procedure color_conv_argb64_to_bgra32(dst ,src : int8u_ptr; width : unsigned );
+
+ procedure color_conv_rgbAAA_to_bgr24 (dst ,src : int8u_ptr; width : unsigned );
+
+ procedure color_conv_bgrAAA_to_bgr24 (dst ,src : int8u_ptr; width : unsigned );
+
+ procedure color_conv_rgbBBA_to_bgr24 (dst ,src : int8u_ptr; width : unsigned );
+
+ procedure color_conv_bgrABB_to_bgr24 (dst ,src : int8u_ptr; width : unsigned );
+
+ procedure color_conv_rgb48_to_bgr24 (dst ,src : int8u_ptr; width : unsigned );
+
+ procedure color_conv_bgr48_to_bgr24 (dst ,src : int8u_ptr; width : unsigned );
+
+ procedure color_conv_rgba64_to_bgra32(dst ,src : int8u_ptr; width : unsigned );
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ COLOR_CONV }
+procedure color_conv;
+var
+ y ,width ,height : unsigned;
+
+begin
+ width :=src._width;
+ height:=src._height;
+
+ if dst._width < width then
+ width:=dst._width;
+
+ if dst._height < height then
+ height:=dst._height;
+
+ if width > 0 then
+ for y:=0 to height - 1 do
+ copy_row_functor(dst.row(y ) ,src.row(y ) ,width );
+
+end;
+
+{ color_conv_bgr24_to_gray8 {..}
+procedure color_conv_bgr24_to_gray8;
+begin
+end;
+
+{ color_conv_gray8_to_bgr24 }
+procedure color_conv_gray8_to_bgr24;
+begin
+ repeat
+ int8u_ptr(ptrcomp(dst ) + bgr_order.R )^:=src^;
+ int8u_ptr(ptrcomp(dst ) + bgr_order.G )^:=src^;
+ int8u_ptr(ptrcomp(dst ) + bgr_order.B )^:=src^;
+
+ inc(ptrcomp(dst ) ,3 );
+ inc(ptrcomp(src ) );
+ dec(width );
+
+ until width = 0;
+
+end;
+
+{ color_conv_gray8_to_rgb24 }
+procedure color_conv_gray8_to_rgb24;
+begin
+ repeat
+ int8u_ptr(ptrcomp(dst ) + rgb_order.R )^:=src^;
+ int8u_ptr(ptrcomp(dst ) + rgb_order.G )^:=src^;
+ int8u_ptr(ptrcomp(dst ) + rgb_order.B )^:=src^;
+
+ inc(ptrcomp(dst ) ,3 );
+ inc(ptrcomp(src ) );
+ dec(width );
+
+ until width = 0;
+
+end;
+
+{ color_conv_bgr24_to_gray16 {..}
+procedure color_conv_bgr24_to_gray16;
+begin
+end;
+
+{ color_conv_rgb555_to_rgb555 {..}
+procedure color_conv_rgb555_to_rgb555;
+begin
+end;
+
+{ color_conv_bgr24_to_rgb555 {..}
+procedure color_conv_bgr24_to_rgb555;
+begin
+end;
+
+{ color_conv_bgra32_to_rgb555 {..}
+procedure color_conv_bgra32_to_rgb555;
+begin
+end;
+
+{ color_conv_rgb555_to_rgb565 {..}
+procedure color_conv_rgb555_to_rgb565;
+begin
+end;
+
+{ color_conv_bgr24_to_rgb565 {..}
+procedure color_conv_bgr24_to_rgb565;
+begin
+end;
+
+{ color_conv_bgra32_to_rgb565 {..}
+procedure color_conv_bgra32_to_rgb565;
+begin
+end;
+
+{ color_conv_rgb555_to_rgb24 {..}
+procedure color_conv_rgb555_to_rgb24;
+begin
+end;
+
+{ color_conv_bgr24_to_rgb24 }
+procedure color_conv_bgr24_to_rgb24;
+begin
+ repeat
+ int8u_ptr(ptrcomp(dst ) + bgr_order.R )^:=int8u_ptr(ptrcomp(src ) + rgb_order.R )^;
+ int8u_ptr(ptrcomp(dst ) + bgr_order.G )^:=int8u_ptr(ptrcomp(src ) + rgb_order.G )^;
+ int8u_ptr(ptrcomp(dst ) + bgr_order.B )^:=int8u_ptr(ptrcomp(src ) + rgb_order.B )^;
+
+ inc(ptrcomp(dst ) ,3 );
+ inc(ptrcomp(src ) ,3 );
+ dec(width );
+
+ until width = 0;
+
+end;
+
+{ color_conv_bgra32_to_rgb24 {..}
+procedure color_conv_bgra32_to_rgb24;
+begin
+end;
+
+{ color_conv_rgb555_to_bgr24 {..}
+procedure color_conv_rgb555_to_bgr24;
+begin
+end;
+
+{ color_conv_bgr24_to_bgr24 }
+procedure color_conv_bgr24_to_bgr24;
+begin
+ move(src^ ,dst^ ,width * 3 );
+
+end;
+
+{ color_conv_bgra32_to_bgr24 {..}
+procedure color_conv_bgra32_to_bgr24;
+begin
+end;
+
+{ color_conv_bgr24_to_rgb48 {..}
+procedure color_conv_bgr24_to_rgb48;
+begin
+end;
+
+{ color_conv_bgr24_to_bgr48 {..}
+procedure color_conv_bgr24_to_bgr48;
+begin
+end;
+
+{ color_conv_rgb555_to_abgr32 {..}
+procedure color_conv_rgb555_to_abgr32;
+begin
+end;
+
+{ color_conv_bgr24_to_abgr32 {..}
+procedure color_conv_bgr24_to_abgr32;
+begin
+end;
+
+{ color_conv_bgra32_to_abgr32 {..}
+procedure color_conv_bgra32_to_abgr32;
+begin
+end;
+
+{ color_conv_rgb555_to_argb32 {..}
+procedure color_conv_rgb555_to_argb32;
+begin
+end;
+
+{ color_conv_bgr24_to_argb32 {..}
+procedure color_conv_bgr24_to_argb32;
+begin
+end;
+
+{ color_conv_bgra32_to_argb32 }
+procedure color_conv_bgra32_to_argb32;
+begin
+ repeat
+ int8u_ptr(ptrcomp(dst ) + argb_order.R )^:=int8u_ptr(ptrcomp(src ) + bgra_order.R )^;
+ int8u_ptr(ptrcomp(dst ) + argb_order.G )^:=int8u_ptr(ptrcomp(src ) + bgra_order.G )^;
+ int8u_ptr(ptrcomp(dst ) + argb_order.B )^:=int8u_ptr(ptrcomp(src ) + bgra_order.B )^;
+ int8u_ptr(ptrcomp(dst ) + argb_order.A )^:=int8u_ptr(ptrcomp(src ) + bgra_order.A )^;
+
+ inc(ptrcomp(dst ) ,4 );
+ inc(ptrcomp(src ) ,4 );
+ dec(width );
+
+ until width = 0;
+
+end;
+
+{ color_conv_abgr32_to_argb32 }
+procedure color_conv_abgr32_to_argb32;
+begin
+ repeat
+ int8u_ptr(ptrcomp(dst ) + argb_order.R )^:=int8u_ptr(ptrcomp(src ) + abgr_order.R )^;
+ int8u_ptr(ptrcomp(dst ) + argb_order.G )^:=int8u_ptr(ptrcomp(src ) + abgr_order.G )^;
+ int8u_ptr(ptrcomp(dst ) + argb_order.B )^:=int8u_ptr(ptrcomp(src ) + abgr_order.B )^;
+ int8u_ptr(ptrcomp(dst ) + argb_order.A )^:=int8u_ptr(ptrcomp(src ) + abgr_order.A )^;
+
+ inc(ptrcomp(dst ) ,4 );
+ inc(ptrcomp(src ) ,4 );
+ dec(width );
+
+ until width = 0;
+
+end;
+
+{ color_conv_rgba32_to_argb32 }
+procedure color_conv_rgba32_to_argb32;
+begin
+ repeat
+ int8u_ptr(ptrcomp(dst ) + argb_order.R )^:=int8u_ptr(ptrcomp(src ) + rgba_order.R )^;
+ int8u_ptr(ptrcomp(dst ) + argb_order.G )^:=int8u_ptr(ptrcomp(src ) + rgba_order.G )^;
+ int8u_ptr(ptrcomp(dst ) + argb_order.B )^:=int8u_ptr(ptrcomp(src ) + rgba_order.B )^;
+ int8u_ptr(ptrcomp(dst ) + argb_order.A )^:=int8u_ptr(ptrcomp(src ) + rgba_order.A )^;
+
+ inc(ptrcomp(dst ) ,4 );
+ inc(ptrcomp(src ) ,4 );
+ dec(width );
+
+ until width = 0;
+
+end;
+
+{ color_conv_rgb555_to_bgra32 {..}
+procedure color_conv_rgb555_to_bgra32;
+begin
+end;
+
+{ color_conv_bgr24_to_bgra32 }
+procedure color_conv_bgr24_to_bgra32;
+begin
+ repeat
+ int8u_ptr(ptrcomp(dst ) + 0 )^:=src^; inc(ptrcomp(src ) );
+ int8u_ptr(ptrcomp(dst ) + 1 )^:=src^; inc(ptrcomp(src ) );
+ int8u_ptr(ptrcomp(dst ) + 2 )^:=src^; inc(ptrcomp(src ) );
+ int8u_ptr(ptrcomp(dst ) + 3 )^:=255;
+
+ inc(ptrcomp(dst ) ,4 );
+ dec(width );
+
+ until width = 0;
+
+end;
+
+{ color_conv_bgra32_to_bgra32 {..}
+procedure color_conv_bgra32_to_bgra32;
+begin
+end;
+
+{ color_conv_rgb555_to_rgba32 {..}
+procedure color_conv_rgb555_to_rgba32;
+begin
+end;
+
+{ color_conv_bgr24_to_rgba32 {..}
+procedure color_conv_bgr24_to_rgba32;
+begin
+end;
+
+{ color_conv_bgra32_to_rgba32 {..}
+procedure color_conv_bgra32_to_rgba32;
+begin
+end;
+
+{ color_conv_bgr24_to_abgr64 {..}
+procedure color_conv_bgr24_to_abgr64;
+begin
+end;
+
+{ color_conv_bgr24_to_argb64 {..}
+procedure color_conv_bgr24_to_argb64;
+begin
+end;
+
+{ color_conv_bgr24_to_bgra64 {..}
+procedure color_conv_bgr24_to_bgra64;
+begin
+end;
+
+{ color_conv_bgr24_to_rgba64 {..}
+procedure color_conv_bgr24_to_rgba64;
+begin
+end;
+
+{ color_conv_gray16_to_gray8 {..}
+procedure color_conv_gray16_to_gray8;
+begin
+end;
+
+{ color_conv_rgb565_to_rgb555 }
+procedure color_conv_rgb565_to_rgb555;
+var
+ rgb : int;
+
+begin
+ repeat
+ rgb:=int16u(p32(src ).ptr^ );
+
+ int16u(p32(dst ).ptr^ ):=((rgb shr 1 ) and $7FE0 ) or (rgb and $1F );
+
+ inc(ptrcomp(src ) ,2 );
+ inc(ptrcomp(dst ) ,2 );
+ dec(width );
+
+ until width = 0;
+
+end;
+
+{ color_conv_rgbAAA_to_bgr24 {..}
+procedure color_conv_rgbAAA_to_bgr24;
+begin
+end;
+
+{ color_conv_bgrAAA_to_bgr24 {..}
+procedure color_conv_bgrAAA_to_bgr24;
+begin
+end;
+
+{ color_conv_rgbBBA_to_bgr24 {..}
+procedure color_conv_rgbBBA_to_bgr24;
+begin
+end;
+
+{ color_conv_bgrABB_to_bgr24 {..}
+procedure color_conv_bgrABB_to_bgr24;
+begin
+end;
+
+{ color_conv_rgb24_to_bgr24 }
+procedure color_conv_rgb24_to_bgr24;
+begin
+ repeat
+ int8u_ptr(p32(dst ).int + 0 )^:=int8u_ptr(p32(src ).int + 2 )^;
+ int8u_ptr(p32(dst ).int + 1 )^:=int8u_ptr(p32(src ).int + 1 )^;
+ int8u_ptr(p32(dst ).int + 2 )^:=int8u_ptr(p32(src ).int + 0 )^;
+
+ inc(ptrcomp(src ) ,3 );
+ inc(ptrcomp(dst ) ,3 );
+ dec(width );
+
+ until width = 0;
+
+end;
+
+{ color_conv_rgb48_to_bgr24 {..}
+procedure color_conv_rgb48_to_bgr24;
+begin
+end;
+
+{ color_conv_bgr48_to_bgr24 {..}
+procedure color_conv_bgr48_to_bgr24;
+begin
+end;
+
+{ color_conv_abgr32_to_bgra32 }
+procedure color_conv_abgr32_to_bgra32;
+begin
+ repeat
+ int8u_ptr(p32(dst ).int + 0 )^:=int8u_ptr(p32(src ).int + 1 )^;
+ int8u_ptr(p32(dst ).int + 1 )^:=int8u_ptr(p32(src ).int + 2 )^;
+ int8u_ptr(p32(dst ).int + 2 )^:=int8u_ptr(p32(src ).int + 3 )^;
+ int8u_ptr(p32(dst ).int + 3 )^:=int8u_ptr(p32(src ).int + 0 )^;
+
+ inc(ptrcomp(src ) ,4 );
+ inc(ptrcomp(dst ) ,4 );
+ dec(width );
+
+ until width = 0;
+
+end;
+
+{ color_conv_argb32_to_bgra32 }
+procedure color_conv_argb32_to_bgra32;
+begin
+ repeat
+ int8u_ptr(p32(dst ).int + 0 )^:=int8u_ptr(p32(src ).int + 3 )^;
+ int8u_ptr(p32(dst ).int + 1 )^:=int8u_ptr(p32(src ).int + 2 )^;
+ int8u_ptr(p32(dst ).int + 2 )^:=int8u_ptr(p32(src ).int + 1 )^;
+ int8u_ptr(p32(dst ).int + 3 )^:=int8u_ptr(p32(src ).int + 0 )^;
+
+ inc(ptrcomp(src ) ,4 );
+ inc(ptrcomp(dst ) ,4 );
+ dec(width );
+
+ until width = 0;
+
+end;
+
+{ color_conv_rgba32_to_bgra32 }
+procedure color_conv_rgba32_to_bgra32;
+begin
+ repeat
+ int8u_ptr(p32(dst ).int + 0 )^:=int8u_ptr(p32(src ).int + 2 )^;
+ int8u_ptr(p32(dst ).int + 1 )^:=int8u_ptr(p32(src ).int + 1 )^;
+ int8u_ptr(p32(dst ).int + 2 )^:=int8u_ptr(p32(src ).int + 0 )^;
+ int8u_ptr(p32(dst ).int + 3 )^:=int8u_ptr(p32(src ).int + 3 )^;
+
+ inc(ptrcomp(src ) ,4 );
+ inc(ptrcomp(dst ) ,4 );
+ dec(width );
+
+ until width = 0;
+
+end;
+
+{ color_conv_bgra64_to_bgra32 {..}
+procedure color_conv_bgra64_to_bgra32;
+begin
+end;
+
+{ color_conv_abgr64_to_bgra32 {..}
+procedure color_conv_abgr64_to_bgra32;
+begin
+end;
+
+{ color_conv_argb64_to_bgra32 {..}
+procedure color_conv_argb64_to_bgra32;
+begin
+end;
+
+{ color_conv_rgba64_to_bgra32 {..}
+procedure color_conv_rgba64_to_bgra32;
+begin
+end;
+
+{ color_conv_rgb24_to_bgra32 }
+procedure color_conv_rgb24_to_bgra32;
+begin
+ repeat
+ int8u_ptr(ptrcomp(dst ) + bgra_order.R )^:=src^; inc(ptrcomp(src ) );
+ int8u_ptr(ptrcomp(dst ) + bgra_order.G )^:=src^; inc(ptrcomp(src ) );
+ int8u_ptr(ptrcomp(dst ) + bgra_order.B )^:=src^; inc(ptrcomp(src ) );
+ int8u_ptr(ptrcomp(dst ) + bgra_order.A )^:=255;
+
+ inc(ptrcomp(dst ) ,4 );
+ dec(width );
+
+ until width = 0;
+
+end;
+
+END.
+