[DEV] basic port
This commit is contained in:
parent
c7dc43629d
commit
ef4e3be43f
7
.checkstyle
Normal file
7
.checkstyle
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<fileset-config file-format-version="1.2.0" simple-config="true" sync-formatter="false">
|
||||
<fileset name="all" enabled="true" check-config-name="ewol" local="false">
|
||||
<file-match-pattern match-pattern="." include-pattern="true"/>
|
||||
</fileset>
|
||||
</fileset-config>
|
30
.classpath
Normal file
30
.classpath
Normal file
@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry including="**/*.java" kind="src" output="out/eclipse/classes-test" path="test/src">
|
||||
<attributes>
|
||||
<attribute name="test" value="true"/>
|
||||
<attribute name="optional" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-14">
|
||||
<attributes>
|
||||
<attribute name="module" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/5">
|
||||
<attributes>
|
||||
<attribute name="test" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry combineaccessrules="false" exported="true" kind="src" path="/scenarium-logger">
|
||||
<attributes>
|
||||
<attribute name="module" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="output" path="out/eclipse/classes"/>
|
||||
</classpath>
|
17
.gitignore
vendored
Normal file
17
.gitignore
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
/bin/
|
||||
/Operator/
|
||||
/DrawerProperties/
|
||||
*.pdfd
|
||||
*.dbc
|
||||
SchedulerConfig.txt
|
||||
scenicView.properties
|
||||
ScenariumConfig.txt
|
||||
*.class
|
||||
*~
|
||||
*.bck
|
||||
build.number
|
||||
/extern/
|
||||
/out/
|
||||
/.settings/
|
||||
/junit/
|
||||
/target/
|
24
.project
Normal file
24
.project
Normal file
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>atriasoft-esvg</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
<project>atriasoft-esvg</project>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>net.sf.eclipsecs.core.CheckstyleBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
<nature>net.sf.eclipsecs.core.CheckstyleNature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
66
CheckStyle.xml
Executable file
66
CheckStyle.xml
Executable file
@ -0,0 +1,66 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE module PUBLIC "-//Checkstyle//DTD Check Configuration 1.3//EN" "https://checkstyle.org/dtds/configuration_1_3.dtd">
|
||||
|
||||
<!--
|
||||
This configuration file was written by the eclipse-cs plugin configuration editor
|
||||
-->
|
||||
<!--
|
||||
Checkstyle-Configuration: Marc Checks
|
||||
Description:
|
||||
Checkstyle configuration that checks the sun coding conventions.
|
||||
-->
|
||||
<module name="Checker">
|
||||
<property name="severity" value="error"/>
|
||||
<property name="fileExtensions" value="java, properties, xml"/>
|
||||
<module name="TreeWalker">
|
||||
<module name="ConstantName"/>
|
||||
<module name="LocalFinalVariableName"/>
|
||||
<module name="LocalVariableName"/>
|
||||
<module name="MemberName"/>
|
||||
<module name="MethodName"/>
|
||||
<module name="PackageName"/>
|
||||
<module name="ParameterName"/>
|
||||
<module name="StaticVariableName"/>
|
||||
<module name="TypeName"/>
|
||||
<module name="AvoidStarImport"/>
|
||||
<module name="IllegalImport"/>
|
||||
<module name="RedundantImport"/>
|
||||
<module name="UnusedImports">
|
||||
<property name="processJavadoc" value="false"/>
|
||||
</module>
|
||||
<module name="ModifierOrder"/>
|
||||
<module name="EmptyStatement"/>
|
||||
<module name="EqualsHashCode"/>
|
||||
<module name="IllegalInstantiation"/>
|
||||
<module name="MissingSwitchDefault"/>
|
||||
<module name="SimplifyBooleanExpression"/>
|
||||
<module name="SimplifyBooleanReturn"/>
|
||||
<module name="HideUtilityClassConstructor"/>
|
||||
<module name="InterfaceIsType"/>
|
||||
<module name="ArrayTypeStyle"/>
|
||||
<module name="TodoComment"/>
|
||||
<module name="UpperEll"/>
|
||||
<module name="AnnotationUseStyle"/>
|
||||
<module name="MissingDeprecated"/>
|
||||
<module name="MissingOverride"/>
|
||||
<module name="PackageAnnotation"/>
|
||||
<module name="SuppressWarnings"/>
|
||||
<module name="AnnotationLocation"/>
|
||||
<module name="ClassTypeParameterName"/>
|
||||
<module name="MethodTypeParameterName"/>
|
||||
<module name="InterfaceTypeParameterName"/>
|
||||
<module name="CatchParameterName"/>
|
||||
<module name="LambdaParameterName"/>
|
||||
<module name="Regexp"/>
|
||||
<module name="RegexpSinglelineJava"/>
|
||||
</module>
|
||||
<module name="BeforeExecutionExclusionFileFilter">
|
||||
<property name="fileNamePattern" value="module\-info\.java$"/>
|
||||
</module>
|
||||
<module name="Translation"/>
|
||||
<module name="Header"/>
|
||||
<module name="RegexpHeader"/>
|
||||
<module name="RegexpMultiline"/>
|
||||
<module name="RegexpOnFilename"/>
|
||||
<module name="RegexpSingleline"/>
|
||||
</module>
|
106
CleanUp.xml
Normal file
106
CleanUp.xml
Normal file
@ -0,0 +1,106 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<profiles version="2">
|
||||
<profile kind="CleanUpProfile" name="EWOL" version="2">
|
||||
<setting id="cleanup.use_autoboxing" value="false"/>
|
||||
<setting id="cleanup.always_use_this_for_non_static_method_access" value="false"/>
|
||||
<setting id="cleanup.remove_trailing_whitespaces_ignore_empty" value="false"/>
|
||||
<setting id="cleanup.format_source_code_changes_only" value="false"/>
|
||||
<setting id="cleanup.remove_redundant_semicolons" value="false"/>
|
||||
<setting id="cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class" value="true"/>
|
||||
<setting id="cleanup.useless_continue" value="false"/>
|
||||
<setting id="cleanup.remove_redundant_type_arguments" value="true"/>
|
||||
<setting id="cleanup.remove_unused_imports" value="true"/>
|
||||
<setting id="cleanup.break_loop" value="false"/>
|
||||
<setting id="cleanup.pull_up_assignment" value="false"/>
|
||||
<setting id="cleanup.stringbuilder" value="false"/>
|
||||
<setting id="cleanup.no_super" value="false"/>
|
||||
<setting id="cleanup.arrays_fill" value="false"/>
|
||||
<setting id="cleanup.use_lambda" value="true"/>
|
||||
<setting id="cleanup.simplify_lambda_expression_and_method_ref" value="false"/>
|
||||
<setting id="cleanup.always_use_blocks" value="true"/>
|
||||
<setting id="cleanup.sort_members_all" value="false"/>
|
||||
<setting id="cleanup.instanceof" value="false"/>
|
||||
<setting id="cleanup.add_missing_annotations" value="true"/>
|
||||
<setting id="cleanup.precompile_regex" value="false"/>
|
||||
<setting id="cleanup.always_use_this_for_non_static_field_access" value="true"/>
|
||||
<setting id="cleanup.boolean_literal" value="false"/>
|
||||
<setting id="cleanup.always_use_parentheses_in_expressions" value="false"/>
|
||||
<setting id="cleanup.sort_members" value="false"/>
|
||||
<setting id="cleanup.remove_unused_local_variables" value="false"/>
|
||||
<setting id="cleanup.add_missing_deprecated_annotations" value="true"/>
|
||||
<setting id="cleanup.no_string_creation" value="false"/>
|
||||
<setting id="cleanup.use_unboxing" value="false"/>
|
||||
<setting id="cleanup.use_blocks_only_for_return_and_throw" value="false"/>
|
||||
<setting id="cleanup.if_condition" value="false"/>
|
||||
<setting id="cleanup.remove_trailing_whitespaces" value="true"/>
|
||||
<setting id="cleanup.map_cloning" value="false"/>
|
||||
<setting id="cleanup.add_serial_version_id" value="true"/>
|
||||
<setting id="cleanup.try_with_resource" value="false"/>
|
||||
<setting id="cleanup.use_this_for_non_static_method_access" value="false"/>
|
||||
<setting id="cleanup.use_this_for_non_static_method_access_only_if_necessary" value="true"/>
|
||||
<setting id="cleanup.make_local_variable_final" value="false"/>
|
||||
<setting id="cleanup.add_missing_methods" value="false"/>
|
||||
<setting id="cleanup.qualify_static_member_accesses_with_declaring_class" value="true"/>
|
||||
<setting id="cleanup.add_missing_override_annotations" value="true"/>
|
||||
<setting id="cleanup.use_blocks" value="true"/>
|
||||
<setting id="cleanup.collection_cloning" value="false"/>
|
||||
<setting id="cleanup.convert_to_enhanced_for_loop_if_loop_var_used" value="false"/>
|
||||
<setting id="cleanup.make_variable_declarations_final" value="true"/>
|
||||
<setting id="cleanup.remove_unused_private_types" value="true"/>
|
||||
<setting id="cleanup.qualify_static_method_accesses_with_declaring_class" value="false"/>
|
||||
<setting id="cleanup.organize_imports" value="true"/>
|
||||
<setting id="cleanup.lazy_logical_operator" value="false"/>
|
||||
<setting id="cleanup.bitwise_conditional_expression" value="false"/>
|
||||
<setting id="cleanup.add_all" value="false"/>
|
||||
<setting id="cleanup.use_directly_map_method" value="false"/>
|
||||
<setting id="cleanup.qualify_static_field_accesses_with_declaring_class" value="false"/>
|
||||
<setting id="cleanup.add_generated_serial_version_id" value="false"/>
|
||||
<setting id="cleanup.primitive_serialization" value="false"/>
|
||||
<setting id="cleanup.comparison_statement" value="false"/>
|
||||
<setting id="cleanup.insert_inferred_type_arguments" value="false"/>
|
||||
<setting id="cleanup.make_private_fields_final" value="true"/>
|
||||
<setting id="cleanup.useless_return" value="false"/>
|
||||
<setting id="cleanup.use_this_for_non_static_field_access_only_if_necessary" value="false"/>
|
||||
<setting id="cleanup.remove_trailing_whitespaces_all" value="true"/>
|
||||
<setting id="cleanup.remove_unnecessary_array_creation" value="false"/>
|
||||
<setting id="cleanup.remove_private_constructors" value="true"/>
|
||||
<setting id="cleanup.make_parameters_final" value="false"/>
|
||||
<setting id="cleanup.ternary_operator" value="false"/>
|
||||
<setting id="cleanup.merge_conditional_blocks" value="false"/>
|
||||
<setting id="cleanup.convert_to_enhanced_for_loop" value="false"/>
|
||||
<setting id="cleanup.remove_unused_private_fields" value="true"/>
|
||||
<setting id="cleanup.never_use_blocks" value="false"/>
|
||||
<setting id="cleanup.remove_redundant_modifiers" value="false"/>
|
||||
<setting id="cleanup.redundant_falling_through_block_end" value="false"/>
|
||||
<setting id="cleanup.switch" value="false"/>
|
||||
<setting id="cleanup.number_suffix" value="false"/>
|
||||
<setting id="cleanup.remove_unnecessary_nls_tags" value="true"/>
|
||||
<setting id="cleanup.convert_to_switch_expressions" value="false"/>
|
||||
<setting id="cleanup.use_this_for_non_static_field_access" value="true"/>
|
||||
<setting id="cleanup.add_missing_nls_tags" value="false"/>
|
||||
<setting id="cleanup.qualify_static_member_accesses_through_instances_with_declaring_class" value="true"/>
|
||||
<setting id="cleanup.remove_unnecessary_casts" value="true"/>
|
||||
<setting id="cleanup.objects_equals" value="false"/>
|
||||
<setting id="cleanup.convert_functional_interfaces" value="true"/>
|
||||
<setting id="cleanup.format_source_code" value="true"/>
|
||||
<setting id="cleanup.else_if" value="true"/>
|
||||
<setting id="cleanup.add_default_serial_version_id" value="true"/>
|
||||
<setting id="cleanup.remove_unused_private_methods" value="true"/>
|
||||
<setting id="cleanup.make_type_abstract_if_missing_method" value="false"/>
|
||||
<setting id="cleanup.join" value="false"/>
|
||||
<setting id="cleanup.embedded_if" value="false"/>
|
||||
<setting id="cleanup.use_anonymous_class_creation" value="false"/>
|
||||
<setting id="cleanup.add_missing_override_annotations_interface_methods" value="true"/>
|
||||
<setting id="cleanup.remove_unused_private_members" value="false"/>
|
||||
<setting id="cleanup.strictly_equal_or_different" value="false"/>
|
||||
<setting id="cleanup.never_use_parentheses_in_expressions" value="true"/>
|
||||
<setting id="cleanup.push_down_negation" value="false"/>
|
||||
<setting id="cleanup.evaluate_nullable" value="false"/>
|
||||
<setting id="cleanup.use_parentheses_in_expressions" value="true"/>
|
||||
<setting id="cleanup.hash" value="false"/>
|
||||
<setting id="cleanup.double_negation" value="false"/>
|
||||
<setting id="cleanup.overridden_assignment" value="false"/>
|
||||
<setting id="cleanup.correct_indentation" value="true"/>
|
||||
<setting id="cleanup.use_var" value="false"/>
|
||||
</profile>
|
||||
</profiles>
|
390
Formatter.xml
Normal file
390
Formatter.xml
Normal file
@ -0,0 +1,390 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<profiles version="20">
|
||||
<profile kind="CodeFormatterProfile" name="EWOL" version="20">
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment" value="common_lines"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration" value="common_lines"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.align_with_spaces" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_before_code_block" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_switch_case_expressions" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="48"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.count_line_length_from_starting_position" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_record_components" value="49"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_multiplicative_operator" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_logical_operator" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_annotation_declaration_on_one_line" value="one_line_if_empty"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_record_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_multiplicative_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_abstract_method" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_enum_constant_declaration_on_one_line" value="one_line_if_empty"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.align_variable_declarations_on_columns" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause" value="common_lines"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiplicative_operator" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_anonymous_type_declaration_on_one_line" value="one_line_if_empty"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_switch_case_expressions" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_shift_operator" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_code_block" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_bitwise_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_parameters" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_loops" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_simple_for_body_on_same_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation" value="common_lines"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_enum_constant" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.text_block_indentation" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_module_statements" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.align_tags_names_descriptions" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_if_then_body_block_on_one_line" value="one_line_if_empty"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression_chain" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_annotations" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_assertion_message_operator" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines" value="2147483647"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_bitwise_operator" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="80"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_not_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration" value="common_lines"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_arguments" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_package" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_case" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_record_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_bitwise_operator" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.indent_tag_description" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_record_constructor" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_string_concatenation" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_shift_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_shift_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_simple_do_while_body_on_same_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_record_components" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_additive_operator" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_simple_getter_setter_on_one_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_string_concatenation" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_record_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_relational_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_logical_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation" value="common_lines"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_record_declaration" value="common_lines"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement" value="common_lines"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_default" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="49"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_method_body" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement" value="common_lines"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_case" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.align_tags_descriptions_grouped" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="200"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_method_body_on_one_line" value="one_line_if_empty"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_loop_body_block_on_one_line" value="one_line_if_empty"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_type_declaration_on_one_line" value="one_line_if_empty"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_additive_operator" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_constructor" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_relational_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_record_declaration_on_one_line" value="one_line_if_empty"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_lambda_body" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_parameter" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_relational_operator" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_additive_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_string_concatenation" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_record_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_after_code_block" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_type" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_local_variable" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_default" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_between_different_tags" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_additive_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_field" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_conditional_operator" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_shift_operator" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause" value="common_lines"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_code_block_on_one_line" value="one_line_if_empty"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_record_components" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_bitwise_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_record_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="33"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_assignment_operator" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_lambda_body_block_on_one_line" value="one_line_if_empty"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_method" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_record_constructor_on_one_line" value="one_line_if_empty"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assertion_message" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_logical_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_record_declaration" value="33"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_relational_operator" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_last_class_body_declaration" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_simple_while_body_on_same_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_logical_operator" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_statement_group_in_switch" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration" value="common_lines"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_enum_declaration_on_one_line" value="one_line_if_empty"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_multiplicative_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_code_block" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="tab"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_string_concatenation" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="200"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
|
||||
</profile>
|
||||
</profiles>
|
373
LICENSE
Normal file
373
LICENSE
Normal file
@ -0,0 +1,373 @@
|
||||
Mozilla Public License Version 2.0
|
||||
==================================
|
||||
|
||||
1. Definitions
|
||||
--------------
|
||||
|
||||
1.1. "Contributor"
|
||||
means each individual or legal entity that creates, contributes to
|
||||
the creation of, or owns Covered Software.
|
||||
|
||||
1.2. "Contributor Version"
|
||||
means the combination of the Contributions of others (if any) used
|
||||
by a Contributor and that particular Contributor's Contribution.
|
||||
|
||||
1.3. "Contribution"
|
||||
means Covered Software of a particular Contributor.
|
||||
|
||||
1.4. "Covered Software"
|
||||
means Source Code Form to which the initial Contributor has attached
|
||||
the notice in Exhibit A, the Executable Form of such Source Code
|
||||
Form, and Modifications of such Source Code Form, in each case
|
||||
including portions thereof.
|
||||
|
||||
1.5. "Incompatible With Secondary Licenses"
|
||||
means
|
||||
|
||||
(a) that the initial Contributor has attached the notice described
|
||||
in Exhibit B to the Covered Software; or
|
||||
|
||||
(b) that the Covered Software was made available under the terms of
|
||||
version 1.1 or earlier of the License, but not also under the
|
||||
terms of a Secondary License.
|
||||
|
||||
1.6. "Executable Form"
|
||||
means any form of the work other than Source Code Form.
|
||||
|
||||
1.7. "Larger Work"
|
||||
means a work that combines Covered Software with other material, in
|
||||
a separate file or files, that is not Covered Software.
|
||||
|
||||
1.8. "License"
|
||||
means this document.
|
||||
|
||||
1.9. "Licensable"
|
||||
means having the right to grant, to the maximum extent possible,
|
||||
whether at the time of the initial grant or subsequently, any and
|
||||
all of the rights conveyed by this License.
|
||||
|
||||
1.10. "Modifications"
|
||||
means any of the following:
|
||||
|
||||
(a) any file in Source Code Form that results from an addition to,
|
||||
deletion from, or modification of the contents of Covered
|
||||
Software; or
|
||||
|
||||
(b) any new file in Source Code Form that contains any Covered
|
||||
Software.
|
||||
|
||||
1.11. "Patent Claims" of a Contributor
|
||||
means any patent claim(s), including without limitation, method,
|
||||
process, and apparatus claims, in any patent Licensable by such
|
||||
Contributor that would be infringed, but for the grant of the
|
||||
License, by the making, using, selling, offering for sale, having
|
||||
made, import, or transfer of either its Contributions or its
|
||||
Contributor Version.
|
||||
|
||||
1.12. "Secondary License"
|
||||
means either the GNU General Public License, Version 2.0, the GNU
|
||||
Lesser General Public License, Version 2.1, the GNU Affero General
|
||||
Public License, Version 3.0, or any later versions of those
|
||||
licenses.
|
||||
|
||||
1.13. "Source Code Form"
|
||||
means the form of the work preferred for making modifications.
|
||||
|
||||
1.14. "You" (or "Your")
|
||||
means an individual or a legal entity exercising rights under this
|
||||
License. For legal entities, "You" includes any entity that
|
||||
controls, is controlled by, or is under common control with You. For
|
||||
purposes of this definition, "control" means (a) the power, direct
|
||||
or indirect, to cause the direction or management of such entity,
|
||||
whether by contract or otherwise, or (b) ownership of more than
|
||||
fifty percent (50%) of the outstanding shares or beneficial
|
||||
ownership of such entity.
|
||||
|
||||
2. License Grants and Conditions
|
||||
--------------------------------
|
||||
|
||||
2.1. Grants
|
||||
|
||||
Each Contributor hereby grants You a world-wide, royalty-free,
|
||||
non-exclusive license:
|
||||
|
||||
(a) under intellectual property rights (other than patent or trademark)
|
||||
Licensable by such Contributor to use, reproduce, make available,
|
||||
modify, display, perform, distribute, and otherwise exploit its
|
||||
Contributions, either on an unmodified basis, with Modifications, or
|
||||
as part of a Larger Work; and
|
||||
|
||||
(b) under Patent Claims of such Contributor to make, use, sell, offer
|
||||
for sale, have made, import, and otherwise transfer either its
|
||||
Contributions or its Contributor Version.
|
||||
|
||||
2.2. Effective Date
|
||||
|
||||
The licenses granted in Section 2.1 with respect to any Contribution
|
||||
become effective for each Contribution on the date the Contributor first
|
||||
distributes such Contribution.
|
||||
|
||||
2.3. Limitations on Grant Scope
|
||||
|
||||
The licenses granted in this Section 2 are the only rights granted under
|
||||
this License. No additional rights or licenses will be implied from the
|
||||
distribution or licensing of Covered Software under this License.
|
||||
Notwithstanding Section 2.1(b) above, no patent license is granted by a
|
||||
Contributor:
|
||||
|
||||
(a) for any code that a Contributor has removed from Covered Software;
|
||||
or
|
||||
|
||||
(b) for infringements caused by: (i) Your and any other third party's
|
||||
modifications of Covered Software, or (ii) the combination of its
|
||||
Contributions with other software (except as part of its Contributor
|
||||
Version); or
|
||||
|
||||
(c) under Patent Claims infringed by Covered Software in the absence of
|
||||
its Contributions.
|
||||
|
||||
This License does not grant any rights in the trademarks, service marks,
|
||||
or logos of any Contributor (except as may be necessary to comply with
|
||||
the notice requirements in Section 3.4).
|
||||
|
||||
2.4. Subsequent Licenses
|
||||
|
||||
No Contributor makes additional grants as a result of Your choice to
|
||||
distribute the Covered Software under a subsequent version of this
|
||||
License (see Section 10.2) or under the terms of a Secondary License (if
|
||||
permitted under the terms of Section 3.3).
|
||||
|
||||
2.5. Representation
|
||||
|
||||
Each Contributor represents that the Contributor believes its
|
||||
Contributions are its original creation(s) or it has sufficient rights
|
||||
to grant the rights to its Contributions conveyed by this License.
|
||||
|
||||
2.6. Fair Use
|
||||
|
||||
This License is not intended to limit any rights You have under
|
||||
applicable copyright doctrines of fair use, fair dealing, or other
|
||||
equivalents.
|
||||
|
||||
2.7. Conditions
|
||||
|
||||
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
|
||||
in Section 2.1.
|
||||
|
||||
3. Responsibilities
|
||||
-------------------
|
||||
|
||||
3.1. Distribution of Source Form
|
||||
|
||||
All distribution of Covered Software in Source Code Form, including any
|
||||
Modifications that You create or to which You contribute, must be under
|
||||
the terms of this License. You must inform recipients that the Source
|
||||
Code Form of the Covered Software is governed by the terms of this
|
||||
License, and how they can obtain a copy of this License. You may not
|
||||
attempt to alter or restrict the recipients' rights in the Source Code
|
||||
Form.
|
||||
|
||||
3.2. Distribution of Executable Form
|
||||
|
||||
If You distribute Covered Software in Executable Form then:
|
||||
|
||||
(a) such Covered Software must also be made available in Source Code
|
||||
Form, as described in Section 3.1, and You must inform recipients of
|
||||
the Executable Form how they can obtain a copy of such Source Code
|
||||
Form by reasonable means in a timely manner, at a charge no more
|
||||
than the cost of distribution to the recipient; and
|
||||
|
||||
(b) You may distribute such Executable Form under the terms of this
|
||||
License, or sublicense it under different terms, provided that the
|
||||
license for the Executable Form does not attempt to limit or alter
|
||||
the recipients' rights in the Source Code Form under this License.
|
||||
|
||||
3.3. Distribution of a Larger Work
|
||||
|
||||
You may create and distribute a Larger Work under terms of Your choice,
|
||||
provided that You also comply with the requirements of this License for
|
||||
the Covered Software. If the Larger Work is a combination of Covered
|
||||
Software with a work governed by one or more Secondary Licenses, and the
|
||||
Covered Software is not Incompatible With Secondary Licenses, this
|
||||
License permits You to additionally distribute such Covered Software
|
||||
under the terms of such Secondary License(s), so that the recipient of
|
||||
the Larger Work may, at their option, further distribute the Covered
|
||||
Software under the terms of either this License or such Secondary
|
||||
License(s).
|
||||
|
||||
3.4. Notices
|
||||
|
||||
You may not remove or alter the substance of any license notices
|
||||
(including copyright notices, patent notices, disclaimers of warranty,
|
||||
or limitations of liability) contained within the Source Code Form of
|
||||
the Covered Software, except that You may alter any license notices to
|
||||
the extent required to remedy known factual inaccuracies.
|
||||
|
||||
3.5. Application of Additional Terms
|
||||
|
||||
You may choose to offer, and to charge a fee for, warranty, support,
|
||||
indemnity or liability obligations to one or more recipients of Covered
|
||||
Software. However, You may do so only on Your own behalf, and not on
|
||||
behalf of any Contributor. You must make it absolutely clear that any
|
||||
such warranty, support, indemnity, or liability obligation is offered by
|
||||
You alone, and You hereby agree to indemnify every Contributor for any
|
||||
liability incurred by such Contributor as a result of warranty, support,
|
||||
indemnity or liability terms You offer. You may include additional
|
||||
disclaimers of warranty and limitations of liability specific to any
|
||||
jurisdiction.
|
||||
|
||||
4. Inability to Comply Due to Statute or Regulation
|
||||
---------------------------------------------------
|
||||
|
||||
If it is impossible for You to comply with any of the terms of this
|
||||
License with respect to some or all of the Covered Software due to
|
||||
statute, judicial order, or regulation then You must: (a) comply with
|
||||
the terms of this License to the maximum extent possible; and (b)
|
||||
describe the limitations and the code they affect. Such description must
|
||||
be placed in a text file included with all distributions of the Covered
|
||||
Software under this License. Except to the extent prohibited by statute
|
||||
or regulation, such description must be sufficiently detailed for a
|
||||
recipient of ordinary skill to be able to understand it.
|
||||
|
||||
5. Termination
|
||||
--------------
|
||||
|
||||
5.1. The rights granted under this License will terminate automatically
|
||||
if You fail to comply with any of its terms. However, if You become
|
||||
compliant, then the rights granted under this License from a particular
|
||||
Contributor are reinstated (a) provisionally, unless and until such
|
||||
Contributor explicitly and finally terminates Your grants, and (b) on an
|
||||
ongoing basis, if such Contributor fails to notify You of the
|
||||
non-compliance by some reasonable means prior to 60 days after You have
|
||||
come back into compliance. Moreover, Your grants from a particular
|
||||
Contributor are reinstated on an ongoing basis if such Contributor
|
||||
notifies You of the non-compliance by some reasonable means, this is the
|
||||
first time You have received notice of non-compliance with this License
|
||||
from such Contributor, and You become compliant prior to 30 days after
|
||||
Your receipt of the notice.
|
||||
|
||||
5.2. If You initiate litigation against any entity by asserting a patent
|
||||
infringement claim (excluding declaratory judgment actions,
|
||||
counter-claims, and cross-claims) alleging that a Contributor Version
|
||||
directly or indirectly infringes any patent, then the rights granted to
|
||||
You by any and all Contributors for the Covered Software under Section
|
||||
2.1 of this License shall terminate.
|
||||
|
||||
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
|
||||
end user license agreements (excluding distributors and resellers) which
|
||||
have been validly granted by You or Your distributors under this License
|
||||
prior to termination shall survive termination.
|
||||
|
||||
************************************************************************
|
||||
* *
|
||||
* 6. Disclaimer of Warranty *
|
||||
* ------------------------- *
|
||||
* *
|
||||
* Covered Software is provided under this License on an "as is" *
|
||||
* basis, without warranty of any kind, either expressed, implied, or *
|
||||
* statutory, including, without limitation, warranties that the *
|
||||
* Covered Software is free of defects, merchantable, fit for a *
|
||||
* particular purpose or non-infringing. The entire risk as to the *
|
||||
* quality and performance of the Covered Software is with You. *
|
||||
* Should any Covered Software prove defective in any respect, You *
|
||||
* (not any Contributor) assume the cost of any necessary servicing, *
|
||||
* repair, or correction. This disclaimer of warranty constitutes an *
|
||||
* essential part of this License. No use of any Covered Software is *
|
||||
* authorized under this License except under this disclaimer. *
|
||||
* *
|
||||
************************************************************************
|
||||
|
||||
************************************************************************
|
||||
* *
|
||||
* 7. Limitation of Liability *
|
||||
* -------------------------- *
|
||||
* *
|
||||
* Under no circumstances and under no legal theory, whether tort *
|
||||
* (including negligence), contract, or otherwise, shall any *
|
||||
* Contributor, or anyone who distributes Covered Software as *
|
||||
* permitted above, be liable to You for any direct, indirect, *
|
||||
* special, incidental, or consequential damages of any character *
|
||||
* including, without limitation, damages for lost profits, loss of *
|
||||
* goodwill, work stoppage, computer failure or malfunction, or any *
|
||||
* and all other commercial damages or losses, even if such party *
|
||||
* shall have been informed of the possibility of such damages. This *
|
||||
* limitation of liability shall not apply to liability for death or *
|
||||
* personal injury resulting from such party's negligence to the *
|
||||
* extent applicable law prohibits such limitation. Some *
|
||||
* jurisdictions do not allow the exclusion or limitation of *
|
||||
* incidental or consequential damages, so this exclusion and *
|
||||
* limitation may not apply to You. *
|
||||
* *
|
||||
************************************************************************
|
||||
|
||||
8. Litigation
|
||||
-------------
|
||||
|
||||
Any litigation relating to this License may be brought only in the
|
||||
courts of a jurisdiction where the defendant maintains its principal
|
||||
place of business and such litigation shall be governed by laws of that
|
||||
jurisdiction, without reference to its conflict-of-law provisions.
|
||||
Nothing in this Section shall prevent a party's ability to bring
|
||||
cross-claims or counter-claims.
|
||||
|
||||
9. Miscellaneous
|
||||
----------------
|
||||
|
||||
This License represents the complete agreement concerning the subject
|
||||
matter hereof. If any provision of this License is held to be
|
||||
unenforceable, such provision shall be reformed only to the extent
|
||||
necessary to make it enforceable. Any law or regulation which provides
|
||||
that the language of a contract shall be construed against the drafter
|
||||
shall not be used to construe this License against a Contributor.
|
||||
|
||||
10. Versions of the License
|
||||
---------------------------
|
||||
|
||||
10.1. New Versions
|
||||
|
||||
Mozilla Foundation is the license steward. Except as provided in Section
|
||||
10.3, no one other than the license steward has the right to modify or
|
||||
publish new versions of this License. Each version will be given a
|
||||
distinguishing version number.
|
||||
|
||||
10.2. Effect of New Versions
|
||||
|
||||
You may distribute the Covered Software under the terms of the version
|
||||
of the License under which You originally received the Covered Software,
|
||||
or under the terms of any subsequent version published by the license
|
||||
steward.
|
||||
|
||||
10.3. Modified Versions
|
||||
|
||||
If you create software not governed by this License, and you want to
|
||||
create a new license for such software, you may create and use a
|
||||
modified version of this License if you rename the license and remove
|
||||
any references to the name of the license steward (except to note that
|
||||
such modified license differs from this License).
|
||||
|
||||
10.4. Distributing Source Code Form that is Incompatible With Secondary
|
||||
Licenses
|
||||
|
||||
If You choose to distribute Source Code Form that is Incompatible With
|
||||
Secondary Licenses under the terms of this version of the License, the
|
||||
notice described in Exhibit B of this License must be attached.
|
||||
|
||||
Exhibit A - Source Code Form License Notice
|
||||
-------------------------------------------
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public
|
||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
If it is not possible or desirable to put the notice in a particular
|
||||
file, then You may include the notice in a location (such as a LICENSE
|
||||
file in a relevant directory) where a recipient would be likely to look
|
||||
for such a notice.
|
||||
|
||||
You may add additional accurate notices of copyright ownership.
|
||||
|
||||
Exhibit B - "Incompatible With Secondary Licenses" Notice
|
||||
---------------------------------------------------------
|
||||
|
||||
This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||
defined by the Mozilla Public License, v. 2.0.
|
10
src/module-info.java
Normal file
10
src/module-info.java
Normal file
@ -0,0 +1,10 @@
|
||||
/** Basic module interface.
|
||||
*
|
||||
* @author Edouard DUPIN */
|
||||
|
||||
open module org.atriasoft.esvg {
|
||||
exports org.atriasoft.esvg;
|
||||
exports org.atriasoft.esvg.render;
|
||||
|
||||
requires transitive io.scenarium.logger;
|
||||
}
|
439
src/org/atriasoft/esvg/Base.cpp
Normal file
439
src/org/atriasoft/esvg/Base.cpp
Normal file
@ -0,0 +1,439 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
|
||||
#include <esvg/debug.hpp>
|
||||
#include <esvg/Base.hpp>
|
||||
#include <cmath>
|
||||
|
||||
const float esvg::kappa90(0.5522847493f);
|
||||
|
||||
esvg::PaintState::PaintState() :
|
||||
fill(etk::Pair<etk::Color<float,4>, etk::String>(etk::color::black, "")),
|
||||
stroke(etk::Pair<etk::Color<float,4>, etk::String>(etk::color::none, "")),
|
||||
strokeWidth(1.0f),
|
||||
flagEvenOdd(false),
|
||||
lineCap(esvg::cap_butt),
|
||||
lineJoin(esvg::join_miter),
|
||||
miterLimit(4.0f),
|
||||
viewPort(vec2(0.0f,0.0f), vec2(0.0f,0.0f)),
|
||||
opacity(1.0) {
|
||||
|
||||
}
|
||||
|
||||
void esvg::PaintState::clear() {
|
||||
fill = etk::Pair<etk::Color<float,4>, etk::String>(etk::color::black, "");
|
||||
stroke = etk::Pair<etk::Color<float,4>, etk::String>(etk::color::none, "");
|
||||
strokeWidth = 1.0;
|
||||
viewPort.first.setValue(0.0f,0.0f);
|
||||
viewPort.first.setValue(0.0f,0.0f);
|
||||
flagEvenOdd = false;
|
||||
lineJoin = esvg::join_miter;
|
||||
lineCap = esvg::cap_butt;
|
||||
miterLimit = 4.0f;
|
||||
opacity = 1.0;
|
||||
}
|
||||
|
||||
|
||||
esvg::Base::Base(PaintState _parentPaintState) {
|
||||
// copy the parent painting properties ...
|
||||
m_paint = _parentPaintState;
|
||||
}
|
||||
|
||||
etk::String extractTransformData(const etk::String& _value, const etk::String& _base) {
|
||||
size_t posStart = _value.find(_base);
|
||||
if (posStart == etk::String::npos) {
|
||||
// Not find element is a normal case ...
|
||||
return "";
|
||||
}
|
||||
posStart += _base.size();
|
||||
if (_value.size() < posStart+2) {
|
||||
Log.error("Not enought spece in the String to have transform value for ' (' or '()' in '" << _value << "'");
|
||||
return "";
|
||||
}
|
||||
if (_value[posStart] == '(') {
|
||||
// normal SVG does not support this case ...
|
||||
posStart++;
|
||||
} else if ( _value[posStart] == ' '
|
||||
&& _value[posStart+1] == '(') {
|
||||
posStart+=2;
|
||||
} else {
|
||||
Log.error("Can not find ' (' or '(' in '" << &_value[posStart] << "' for '" << _value << "'");
|
||||
return "";
|
||||
}
|
||||
if (_value.size() < posStart+1) {
|
||||
Log.error("Not enought spece in the String to have transform value for ')' in '" << _value << "'");
|
||||
return "";
|
||||
}
|
||||
size_t posEnd = _value.find(')', posStart);
|
||||
if (posEnd == etk::String::npos) {
|
||||
Log.error("Missing element ')' in '" << _value << "' for " << _base);
|
||||
return "";
|
||||
}
|
||||
Log.verbose("Find : '" << etk::String(_value.begin()+posStart, _value.begin()+posEnd) << "' for " << _base);
|
||||
return etk::String(_value.begin()+posStart, _value.begin()+posEnd);
|
||||
}
|
||||
|
||||
void esvg::Base::parseTransform(const exml::Element& _element) {
|
||||
if (_element.exist() == false) {
|
||||
return;
|
||||
}
|
||||
etk::String inputString = _element.attributes["transform"];
|
||||
if (inputString.size() == 0) {
|
||||
return;
|
||||
}
|
||||
Log.verbose("find transform : \"" << inputString << "\"");
|
||||
for (size_t iii=0; iii<inputString.size(); iii++) {
|
||||
if (inputString[iii] == ',') {
|
||||
inputString[iii] = ' ';
|
||||
}
|
||||
}
|
||||
Log.verbose("find transform : \"" << inputString << "\"");
|
||||
// need to find elements in order ...
|
||||
etk::String data = extractTransformData(inputString, "matrix");
|
||||
if (data.size() != 0) {
|
||||
double matrix[6];
|
||||
if (sscanf(data.c_str(), "%lf %lf %lf %lf %lf %lf", &matrix[0], &matrix[1], &matrix[2], &matrix[3], &matrix[4], &matrix[5]) == 6) {
|
||||
m_transformMatrix = mat2x3(matrix);
|
||||
// find a matrix : simply exit ...
|
||||
return;
|
||||
} else {
|
||||
Log.error("Parsing matrix() with wrong data ... '" << data << "'");
|
||||
}
|
||||
}
|
||||
data = extractTransformData(inputString, "translate");
|
||||
if (data.size() != 0) {
|
||||
float xxx, yyy;
|
||||
if (sscanf(data.c_str(), "%f %f", &xxx, &yyy) == 2) {
|
||||
m_transformMatrix *= etk::mat2x3Translate(vec2(xxx, yyy));
|
||||
Log.verbose("Translate : " << xxx << ", " << yyy);
|
||||
} else if (sscanf(data.c_str(), "%f", &xxx) == 1) {
|
||||
m_transformMatrix *= etk::mat2x3Translate(vec2(xxx, 0));
|
||||
Log.verbose("Translate : " << xxx << ", " << 0);
|
||||
} else {
|
||||
Log.error("Parsing translate() with wrong data ... '" << data << "'");
|
||||
}
|
||||
}
|
||||
data = extractTransformData(inputString, "scale");
|
||||
if (data.size() != 0) {
|
||||
float xxx, yyy;
|
||||
if (sscanf(data.c_str(), "%f %f", &xxx, &yyy) == 2) {
|
||||
m_transformMatrix *= etk::mat2x3Scale(vec2(xxx, yyy));
|
||||
Log.verbose("Scale : " << xxx << ", " << yyy);
|
||||
} else if (sscanf(data.c_str(), "%f", &xxx) == 1) {
|
||||
m_transformMatrix *= etk::mat2x3Scale(xxx);
|
||||
Log.verbose("Scale : " << xxx << ", " << xxx);
|
||||
} else {
|
||||
Log.error("Parsing scale() with wrong data ... '" << data << "'");
|
||||
}
|
||||
}
|
||||
data = extractTransformData(inputString, "rotate");
|
||||
if (data.size() != 0) {
|
||||
float angle, xxx, yyy;
|
||||
if (sscanf(data.c_str(), "%f %f %f", &angle, &xxx, &yyy) == 3) {
|
||||
angle = angle / 180 * M_PI;
|
||||
m_transformMatrix *= etk::mat2x3Translate(vec2(-xxx, -yyy));
|
||||
m_transformMatrix *= etk::mat2x3Rotate(angle);
|
||||
m_transformMatrix *= etk::mat2x3Translate(vec2(xxx, yyy));
|
||||
} else if (sscanf(data.c_str(), "%f", &angle) == 1) {
|
||||
angle = angle / 180 * M_PI;
|
||||
Log.verbose("rotate : " << angle << "rad, " << (angle/M_PI*180) << "°");
|
||||
m_transformMatrix *= etk::mat2x3Rotate(angle);
|
||||
} else {
|
||||
Log.error("Parsing rotate() with wrong data ... '" << data << "'");
|
||||
}
|
||||
}
|
||||
data = extractTransformData(inputString, "skewX");
|
||||
if (data.size() != 0) {
|
||||
float angle;
|
||||
if (sscanf(data.c_str(), "%f", &angle) == 1) {
|
||||
angle = angle / 180 * M_PI;
|
||||
Log.verbose("skewX : " << angle << "rad, " << (angle/M_PI*180) << "°");
|
||||
m_transformMatrix *= etk::mat2x3Skew(vec2(angle, 0.0f));
|
||||
} else {
|
||||
Log.error("Parsing skewX() with wrong data ... '" << data << "'");
|
||||
}
|
||||
}
|
||||
data = extractTransformData(inputString, "skewY");
|
||||
if (data.size() != 0) {
|
||||
float angle;
|
||||
if (sscanf(data.c_str(), "%f", &angle) == 1) {
|
||||
angle = angle / 180 * M_PI;
|
||||
Log.verbose("skewY : " << angle << "rad, " << (angle/M_PI*180) << "°");
|
||||
m_transformMatrix *= etk::mat2x3Skew(vec2(0.0f, angle));
|
||||
} else {
|
||||
Log.error("Parsing skewY() with wrong data ... '" << data << "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void esvg::Base::parsePosition(const exml::Element& _element, vec2 &_pos, vec2 &_size) {
|
||||
_pos.setValue(0,0);
|
||||
_size.setValue(0,0);
|
||||
|
||||
if (_element.exist() == false) {
|
||||
return;
|
||||
}
|
||||
etk::String content = _element.attributes["x"];
|
||||
if (content.size()!=0) {
|
||||
_pos.setX(parseLength(content));
|
||||
}
|
||||
content = _element.attributes["y"];
|
||||
if (content.size()!=0) {
|
||||
_pos.setY(parseLength(content));
|
||||
}
|
||||
content = _element.attributes["width"];
|
||||
if (content.size()!=0) {
|
||||
_size.setX(parseLength(content));
|
||||
}
|
||||
content = _element.attributes["height"];
|
||||
if (content.size()!=0) {
|
||||
_size.setY(parseLength(content));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
etk::Pair<float, enum esvg::distance> esvg::Base::parseLength2(const etk::String& _dataInput) {
|
||||
Log.verbose(" lenght : '" << _dataInput << "'");
|
||||
float n = _dataInput.to<float>();
|
||||
etk::String unit;
|
||||
for (size_t iii=0; iii<_dataInput.size(); ++iii) {
|
||||
if( (_dataInput[iii]>='0' && _dataInput[iii]<='9')
|
||||
|| _dataInput[iii]=='+'
|
||||
|| _dataInput[iii]=='-'
|
||||
|| _dataInput[iii]=='.') {
|
||||
continue;
|
||||
}
|
||||
unit = etk::String(_dataInput, iii);
|
||||
break;
|
||||
}
|
||||
Log.verbose(" lenght : '" << n << "' => unit=" << unit);
|
||||
// note : ";" is for the parsing of the style elements ...
|
||||
if(unit.size() == 0) {
|
||||
return etk::makePair(n, esvg::distance_pixel);
|
||||
} else if (unit[0] == '%') { // xxx %
|
||||
return etk::makePair(n, esvg::distance_pourcent);
|
||||
} else if ( unit[0] == 'e'
|
||||
&& unit[1] == 'm') { // xxx em
|
||||
return etk::makePair(n, esvg::distance_element);
|
||||
} else if ( unit[0] == 'e'
|
||||
&& unit[1] == 'x') { // xxx ex
|
||||
return etk::makePair(n, esvg::distance_ex);
|
||||
} else if ( unit[0] == 'p'
|
||||
&& unit[1] == 'x') { // xxx px
|
||||
return etk::makePair(n, esvg::distance_pixel);
|
||||
} else if ( unit[0] == 'p'
|
||||
&& unit[1] == 't') { // xxx pt
|
||||
return etk::makePair(n, esvg::distance_point);
|
||||
} else if ( unit[0] == 'p'
|
||||
&& unit[1] == 'c') { // xxx pc
|
||||
return etk::makePair(n, esvg::distance_pc);
|
||||
} else if ( unit[0] == 'm'
|
||||
&& unit[1] == 'm') { // xxx mm
|
||||
return etk::makePair(n, esvg::distance_millimeter);
|
||||
} else if ( unit[0] == 'c'
|
||||
&& unit[1] == 'm') { // xxx cm
|
||||
return etk::makePair(n, esvg::distance_centimeter);
|
||||
} else if ( unit[0] == 'i'
|
||||
&& unit[1] == 'n') { // xxx in
|
||||
return etk::makePair(n, esvg::distance_inch);
|
||||
}
|
||||
return etk::makePair(0.0f, esvg::distance_pixel);
|
||||
}
|
||||
|
||||
|
||||
float esvg::Base::parseLength(const etk::String& _dataInput) {
|
||||
etk::Pair<float, enum esvg::distance> value = parseLength2(_dataInput);
|
||||
Log.verbose(" lenght : '" << value.first << "' => unit=" << value.second);
|
||||
float font_size = 20.0f;
|
||||
switch (value.second) {
|
||||
case esvg::distance_pourcent:
|
||||
return value.first;// / 100.0 * m_paint.viewPort.x();
|
||||
case esvg::distance_element:
|
||||
return value.first * font_size;
|
||||
case esvg::distance_ex:
|
||||
return value.first / 2.0f * font_size;
|
||||
case esvg::distance_pixel:
|
||||
return value.first;
|
||||
case esvg::distance_point:
|
||||
return value.first * 1.25f;
|
||||
case esvg::distance_pc:
|
||||
return value.first * 15.0f;
|
||||
case esvg::distance_millimeter:
|
||||
return value.first * 3.543307f;
|
||||
case esvg::distance_centimeter:
|
||||
return value.first * 35.43307f;
|
||||
case esvg::distance_inch:
|
||||
return value.first * 90.0f;
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
void esvg::Base::parsePaintAttr(const exml::Element& _element) {
|
||||
if (_element.exist() == false) {
|
||||
return;
|
||||
}
|
||||
/*
|
||||
bool fillNone = false;
|
||||
bool strokeNone = false;
|
||||
*/
|
||||
etk::String content;
|
||||
// ---------------- get unique ID ----------------
|
||||
m_id = _element.attributes["id"];
|
||||
// ---------------- stroke ----------------
|
||||
content = _element.attributes["stroke"];
|
||||
if (content == "none") {
|
||||
m_paint.stroke = etk::Pair<etk::Color<float,4>, etk::String>(etk::color::none, "");
|
||||
} else {
|
||||
if (content.size()!=0) {
|
||||
m_paint.stroke = parseColor(content);
|
||||
}
|
||||
content = _element.attributes["stroke-width"];
|
||||
if (content.size()!=0) {
|
||||
m_paint.strokeWidth = parseLength(content);
|
||||
}
|
||||
content = _element.attributes["stroke-opacity"];
|
||||
if (content.size()!=0) {
|
||||
float opacity = parseLength(content);
|
||||
opacity = etk::avg(0.0f, opacity, 1.0f);
|
||||
m_paint.stroke.first.setA(opacity);
|
||||
}
|
||||
|
||||
content = _element.attributes["stroke-dasharray"];
|
||||
if (content.size()!=0) {
|
||||
if (content == "none" ) {
|
||||
// OK, Nothing to do ...
|
||||
} else {
|
||||
ESVG_TODO(" 'stroke-dasharray' not implemented ...");
|
||||
}
|
||||
}
|
||||
content = _element.attributes["stroke-linecap"];
|
||||
if (content.size()!=0) {
|
||||
if (content == "butt" ) {
|
||||
m_paint.lineCap = esvg::cap_butt;
|
||||
} else if (content == "round" ) {
|
||||
m_paint.lineCap = esvg::cap_round;
|
||||
} else if (content == "square" ) {
|
||||
m_paint.lineCap = esvg::cap_square;
|
||||
} else {
|
||||
m_paint.lineCap = esvg::cap_butt;
|
||||
Log.error("not know stroke-linecap value : \"" << content << "\", not in [butt,round,square]");
|
||||
}
|
||||
}
|
||||
content = _element.attributes["stroke-linejoin"];
|
||||
if (content.size()!=0) {
|
||||
if (content == "miter" ) {
|
||||
m_paint.lineJoin = esvg::join_miter;
|
||||
} else if (content == "round" ) {
|
||||
m_paint.lineJoin = esvg::join_round;
|
||||
} else if (content == "bevel" ) {
|
||||
m_paint.lineJoin = esvg::join_bevel;
|
||||
} else {
|
||||
m_paint.lineJoin = esvg::join_miter;
|
||||
Log.error("not know stroke-linejoin value : \"" << content << "\", not in [miter,round,bevel]");
|
||||
}
|
||||
}
|
||||
content = _element.attributes["stroke-miterlimit"];
|
||||
if (content.size()!=0) {
|
||||
float tmp = parseLength(content);
|
||||
m_paint.miterLimit = etk::max(0.0f, tmp);
|
||||
}
|
||||
}
|
||||
// ---------------- FILL ----------------
|
||||
content = _element.attributes["fill"];
|
||||
if (content == "none") {
|
||||
m_paint.fill = etk::Pair<etk::Color<float,4>, etk::String>(etk::color::none, "");
|
||||
} else {
|
||||
if (content.size()!=0) {
|
||||
m_paint.fill = parseColor(content);
|
||||
}
|
||||
content = _element.attributes["fill-opacity"];
|
||||
if (content.size()!=0) {
|
||||
float opacity = parseLength(content);
|
||||
opacity = etk::avg(0.0f, opacity, 1.0f);
|
||||
m_paint.fill.first.setA(opacity);
|
||||
}
|
||||
content = _element.attributes["fill-rule"];
|
||||
if (content.size()!=0) {
|
||||
if (content == "nonzero") {
|
||||
m_paint.flagEvenOdd = false;
|
||||
} else if (content == "evenodd" ) {
|
||||
m_paint.flagEvenOdd = true;
|
||||
} else {
|
||||
Log.error("not know fill-rule value : \"" << content << "\", not in [nonzero,evenodd]");
|
||||
}
|
||||
}
|
||||
// ---------------- opacity ----------------
|
||||
content = _element.attributes["opacity"];
|
||||
if (content.size()!=0) {
|
||||
m_paint.opacity = parseLength(content);
|
||||
m_paint.opacity = etk::avg(0.0f, m_paint.opacity, 1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
etk::Pair<etk::Color<float,4>, etk::String> esvg::Base::parseColor(const etk::String& _inputData) {
|
||||
etk::Pair<etk::Color<float,4>, etk::String> localColor(etk::color::white, "");
|
||||
|
||||
if( _inputData.size() > 4
|
||||
&& _inputData[0] == 'u'
|
||||
&& _inputData[1] == 'r'
|
||||
&& _inputData[2] == 'l'
|
||||
&& _inputData[3] == '(') {
|
||||
if (_inputData[4] == '#') {
|
||||
etk::String color(_inputData.begin() + 5, _inputData.end()-1);
|
||||
localColor = etk::Pair<etk::Color<float,4>, etk::String>(etk::color::none, color);
|
||||
} else {
|
||||
Log.error("Problem in parsing the color : \"" << _inputData << "\" == > url(XXX) is not supported now ...");
|
||||
}
|
||||
} else {
|
||||
localColor = etk::Pair<etk::Color<float,4>, etk::String>(_inputData, "");
|
||||
}
|
||||
Log.verbose("Parse color : \"" << _inputData << "\" == > " << localColor.first << " " << localColor.second);
|
||||
return localColor;
|
||||
}
|
||||
|
||||
bool esvg::Base::parseXML(const exml::Element& _element, mat2x3& _parentTrans, vec2& _sizeMax) {
|
||||
// TODO : UNDERSTAND why nothing is done here ...
|
||||
// Parse basic elements (ID...):
|
||||
m_id = _element.attributes["id"];
|
||||
_sizeMax = vec2(0.0f, 0.0f);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
const char * esvg::Base::spacingDist(int32_t _spacing) {
|
||||
static const char *tmpValue = " ";
|
||||
if (_spacing>20) {
|
||||
_spacing = 20;
|
||||
}
|
||||
return tmpValue + 20*4 - _spacing*4;
|
||||
}
|
||||
|
||||
void esvg::Base::draw(esvg::Renderer& _myRenderer, mat2x3& _basicTrans, int32_t _level) {
|
||||
Log.warning(spacingDist(_level) << "DRAW esvg::Base ... ==> No drawing availlable");
|
||||
}
|
||||
|
||||
|
||||
|
||||
const etk::String& esvg::Base::getId() const {
|
||||
return m_id;
|
||||
}
|
||||
|
||||
void esvg::Base::setId(const etk::String& _newId) {
|
||||
// TODO : Check if it is UNIQUE ...
|
||||
m_id = _newId;
|
||||
}
|
||||
|
||||
|
||||
void esvg::Base::drawShapePoints(etk::Vector<etk::Vector<vec2>>& _out,
|
||||
int32_t _recurtionMax,
|
||||
float _threshold,
|
||||
mat2x3& _basicTrans,
|
||||
int32_t _level) {
|
||||
|
||||
}
|
||||
|
129
src/org/atriasoft/esvg/Base.java
Normal file
129
src/org/atriasoft/esvg/Base.java
Normal file
@ -0,0 +1,129 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
|
||||
#include <esvg/join.hpp>
|
||||
#include <esvg/cap.hpp>
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <etk/types.hpp>
|
||||
#include <etk/Vector.hpp>
|
||||
#include <etk/math/Vector2D.hpp>
|
||||
#include <etk/math/Matrix2x3.hpp>
|
||||
#include <etk/Color.hpp>
|
||||
#include <esvg/render/Path.hpp>
|
||||
|
||||
#include <exml/exml.hpp>
|
||||
#include <esvg/Renderer.hpp>
|
||||
#include <esvg/Dimension.hpp>
|
||||
|
||||
namespace esvg {
|
||||
extern const float kappa90; //!< proportional lenght to the radius of a bezier handle for 90° arcs.
|
||||
/**
|
||||
* @brief Painting mode of the Object:
|
||||
*/
|
||||
enum paint {
|
||||
paint_none, //!< No painting.
|
||||
paint_color, //!< Painting a color.
|
||||
paint_gradientLinear, //!< Painting a linear gradient.
|
||||
paint_gradientRadial //!< Painting a radial gradient.
|
||||
};
|
||||
|
||||
class PaintState {
|
||||
public:
|
||||
PaintState();
|
||||
void clear();
|
||||
public:
|
||||
etk::Pair<etk::Color<float,4>, etk::String> fill;
|
||||
etk::Pair<etk::Color<float,4>, etk::String> stroke;
|
||||
float strokeWidth;
|
||||
bool flagEvenOdd; //!< Fill rules
|
||||
enum esvg::cap lineCap;
|
||||
enum esvg::join lineJoin;
|
||||
float miterLimit;
|
||||
etk::Pair<vec2, vec2> viewPort; //!< min pos, max pos
|
||||
float opacity;
|
||||
};
|
||||
|
||||
class Base {
|
||||
protected:
|
||||
PaintState m_paint;
|
||||
mat2x3 m_transformMatrix; //!< specific render of the curent element
|
||||
const char * spacingDist(int32_t _spacing);
|
||||
public:
|
||||
Base() {};
|
||||
Base(PaintState _parentPaintState);
|
||||
virtual ~Base() { };
|
||||
/**
|
||||
* @brief parse all the element needed in the basic node
|
||||
* @param[in] _element standart XML node
|
||||
* @return true if no problem arrived
|
||||
*/
|
||||
virtual bool parseXML(const exml::Element& _element, mat2x3& _parentTrans, vec2& _sizeMax);
|
||||
/**
|
||||
* @brief Draw the form in the renderer
|
||||
* @param[in] _myRenderer Renderer engine
|
||||
* @param[in] _basicTrans Parant transformation of the environement
|
||||
* @param[in] _level Level of the tree
|
||||
*/
|
||||
virtual void draw(esvg::Renderer& _myRenderer, mat2x3& _basicTrans, int32_t _level=1);
|
||||
/**
|
||||
* @brief Draw rhe shape with all points
|
||||
* @param[in] _out where the lines are added
|
||||
* @param[in] _recurtionMax interpolation recurtion max
|
||||
* @param[in] _threshold threshold to stop recurtion
|
||||
* @param[in] _basicTrans Parant transformation of the environement
|
||||
* @param[in] _level Level of the tree
|
||||
*/
|
||||
virtual void drawShapePoints(etk::Vector<etk::Vector<vec2>>& _out,
|
||||
int32_t _recurtionMax,
|
||||
float _threshold,
|
||||
mat2x3& _basicTrans,
|
||||
int32_t _level=1);
|
||||
|
||||
virtual void display(int32_t _spacing) { };
|
||||
void parseTransform(const exml::Element& _element);
|
||||
/**
|
||||
* @brief parse x, y, width, height attribute of the xml node
|
||||
* @param[in] _element XML node
|
||||
* @param[out] _pos parsed position
|
||||
* @param[out] _size parsed dimention
|
||||
*/
|
||||
void parsePosition(const exml::Element& _element, vec2 &_pos, vec2 &_size);
|
||||
/**
|
||||
* @brief parse a lenght of the xml element
|
||||
* @param[in] _dataInput Data C String with the printed lenght
|
||||
* @return standard number of pixels
|
||||
*/
|
||||
float parseLength(const etk::String& _dataInput);
|
||||
etk::Pair<float, enum esvg::distance> parseLength2(const etk::String& _dataInput);
|
||||
/**
|
||||
* @brief parse a Painting attribute of a specific node
|
||||
* @param[in] _element Basic node of the XML that might be parsed
|
||||
*/
|
||||
void parsePaintAttr(const exml::Element& _element);
|
||||
/**
|
||||
* @brief parse a color specification from the svg file
|
||||
* @param[in] _inputData Data C String with the xml definition
|
||||
* @return The parsed color (color used and the link if needed)
|
||||
*/
|
||||
etk::Pair<etk::Color<float,4>, etk::String> parseColor(const etk::String& _inputData);
|
||||
protected:
|
||||
etk::String m_id; //!< unique ID of the element.
|
||||
public:
|
||||
/**
|
||||
* @brief Get the ID of the Element
|
||||
* @return UniqueId in the svg file
|
||||
*/
|
||||
const etk::String& getId() const;
|
||||
/**
|
||||
* @brief Set the ID of the Element
|
||||
* @param[in] _newId New Id of the element
|
||||
*/
|
||||
void setId(const etk::String& _newId);
|
||||
};
|
||||
};
|
166
src/org/atriasoft/esvg/Circle.cpp
Normal file
166
src/org/atriasoft/esvg/Circle.cpp
Normal file
@ -0,0 +1,166 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <esvg/debug.hpp>
|
||||
#include <esvg/Circle.hpp>
|
||||
#include <esvg/render/Path.hpp>
|
||||
#include <esvg/render/Weight.hpp>
|
||||
|
||||
esvg::Circle::Circle(PaintState _parentPaintState) : esvg::Base(_parentPaintState) {
|
||||
|
||||
}
|
||||
|
||||
esvg::Circle::~Circle() {
|
||||
|
||||
}
|
||||
|
||||
bool esvg::Circle::parseXML(const exml::Element& _element, mat2x3& _parentTrans, vec2& _sizeMax) {
|
||||
m_radius = 0.0;
|
||||
m_position.setValue(0,0);
|
||||
if (_element.exist() == false) {
|
||||
return false;
|
||||
}
|
||||
parseTransform(_element);
|
||||
parsePaintAttr(_element);
|
||||
|
||||
// add the property of the parrent modifications ...
|
||||
m_transformMatrix *= _parentTrans;
|
||||
|
||||
etk::String content = _element.attributes["cx"];
|
||||
if (content.size()!=0) {
|
||||
m_position.setX(parseLength(content));
|
||||
}
|
||||
content = _element.attributes["cy"];
|
||||
if (content.size()!=0) {
|
||||
m_position.setY(parseLength(content));
|
||||
}
|
||||
content = _element.attributes["r"];
|
||||
if (content.size()!=0) {
|
||||
m_radius = parseLength(content);
|
||||
} else {
|
||||
Log.error("(l "<<_element.getPos()<<") Circle \"r\" is not present");
|
||||
return false;
|
||||
}
|
||||
if (0 > m_radius) {
|
||||
m_radius = 0;
|
||||
Log.error("(l "<<_element.getPos()<<") Circle \"r\" is negative");
|
||||
return false;
|
||||
}
|
||||
_sizeMax.setValue(m_position.x() + m_radius, m_position.y() + m_radius);
|
||||
return true;
|
||||
}
|
||||
|
||||
void esvg::Circle::display(int32_t _spacing) {
|
||||
Log.debug(spacingDist(_spacing) << "Circle " << m_position << " radius=" << m_radius);
|
||||
}
|
||||
|
||||
esvg::render::Path esvg::Circle::createPath() {
|
||||
esvg::render::Path out;
|
||||
|
||||
out.clear();
|
||||
out.moveTo(false, m_position + vec2(m_radius, 0.0f));
|
||||
out.curveTo(false,
|
||||
m_position + vec2(m_radius, m_radius*esvg::kappa90),
|
||||
m_position + vec2(m_radius*esvg::kappa90, m_radius),
|
||||
m_position + vec2(0.0f, m_radius));
|
||||
out.curveTo(false,
|
||||
m_position + vec2(-m_radius*esvg::kappa90, m_radius),
|
||||
m_position + vec2(-m_radius, m_radius*esvg::kappa90),
|
||||
m_position + vec2(-m_radius, 0.0f));
|
||||
out.curveTo(false,
|
||||
m_position + vec2(-m_radius, -m_radius*esvg::kappa90),
|
||||
m_position + vec2(-m_radius*esvg::kappa90, -m_radius),
|
||||
m_position + vec2(0.0f, -m_radius));
|
||||
out.curveTo(false,
|
||||
m_position + vec2(m_radius*esvg::kappa90, -m_radius),
|
||||
m_position + vec2(m_radius, -m_radius*esvg::kappa90),
|
||||
m_position + vec2(m_radius, 0.0f));
|
||||
out.close();
|
||||
return out;
|
||||
}
|
||||
|
||||
void esvg::Circle::draw(esvg::Renderer& _myRenderer, mat2x3& _basicTrans, int32_t _level) {
|
||||
Log.verbose(spacingDist(_level) << "DRAW esvg::Circle");
|
||||
if (m_radius <= 0.0f) {
|
||||
Log.verbose(spacingDist(_level+1) << "Too small radius" << m_radius);
|
||||
return;
|
||||
}
|
||||
esvg::render::Path listElement = createPath();
|
||||
|
||||
mat2x3 mtx = m_transformMatrix;
|
||||
mtx *= _basicTrans;
|
||||
|
||||
esvg::render::PointList listPoints;
|
||||
listPoints = listElement.generateListPoints(_level,
|
||||
_myRenderer.getInterpolationRecurtionMax(),
|
||||
_myRenderer.getInterpolationThreshold());
|
||||
//listPoints.applyMatrix(mtx);
|
||||
esvg::render::SegmentList listSegmentFill;
|
||||
esvg::render::SegmentList listSegmentStroke;
|
||||
esvg::render::Weight tmpFill;
|
||||
esvg::render::Weight tmpStroke;
|
||||
ememory::SharedPtr<esvg::render::DynamicColor> colorFill = esvg::render::createColor(m_paint.fill, mtx);
|
||||
ememory::SharedPtr<esvg::render::DynamicColor> colorStroke;
|
||||
if (m_paint.strokeWidth > 0.0f) {
|
||||
colorStroke = esvg::render::createColor(m_paint.stroke, mtx);
|
||||
}
|
||||
// Check if we need to display background
|
||||
if (colorFill != null) {
|
||||
listSegmentFill.createSegmentList(listPoints);
|
||||
colorFill->setViewPort(listSegmentFill.getViewPort());
|
||||
listSegmentFill.applyMatrix(mtx);
|
||||
// now, traverse the scanlines and find the intersections on each scanline, use non-zero rule
|
||||
tmpFill.generate(_myRenderer.getSize(),
|
||||
_myRenderer.getNumberSubScanLine(),
|
||||
listSegmentFill);
|
||||
}
|
||||
// check if we need to display stroke:
|
||||
if (colorStroke != null) {
|
||||
listSegmentStroke.createSegmentListStroke(listPoints,
|
||||
m_paint.strokeWidth,
|
||||
m_paint.lineCap,
|
||||
m_paint.lineJoin,
|
||||
m_paint.miterLimit);
|
||||
colorStroke->setViewPort(listSegmentStroke.getViewPort());
|
||||
listSegmentStroke.applyMatrix(mtx);
|
||||
// now, traverse the scanlines and find the intersections on each scanline, use non-zero rule
|
||||
tmpStroke.generate(_myRenderer.getSize(),
|
||||
_myRenderer.getNumberSubScanLine(),
|
||||
listSegmentStroke);
|
||||
}
|
||||
// add on images:
|
||||
_myRenderer.print(tmpFill,
|
||||
colorFill,
|
||||
tmpStroke,
|
||||
colorStroke,
|
||||
m_paint.opacity);
|
||||
#ifdef DEBUG
|
||||
_myRenderer.addDebugSegment(listSegmentFill);
|
||||
_myRenderer.addDebugSegment(listSegmentStroke);
|
||||
#endif
|
||||
}
|
||||
|
||||
void esvg::Circle::drawShapePoints(etk::Vector<etk::Vector<vec2>>& _out,
|
||||
int32_t _recurtionMax,
|
||||
float _threshold,
|
||||
mat2x3& _basicTrans,
|
||||
int32_t _level) {
|
||||
Log.verbose(spacingDist(_level) << "DRAW Shape esvg::Circle");
|
||||
esvg::render::Path listElement = createPath();
|
||||
mat2x3 mtx = m_transformMatrix;
|
||||
mtx *= _basicTrans;
|
||||
esvg::render::PointList listPoints;
|
||||
listPoints = listElement.generateListPoints(_level, _recurtionMax, _threshold);
|
||||
listPoints.applyMatrix(mtx);
|
||||
for (auto &it : listPoints.m_data) {
|
||||
etk::Vector<vec2> listPoint;
|
||||
for (auto &itDot : it) {
|
||||
listPoint.pushBack(itDot.m_pos);
|
||||
}
|
||||
_out.pushBack(listPoint);
|
||||
}
|
||||
}
|
||||
|
31
src/org/atriasoft/esvg/Circle.java
Normal file
31
src/org/atriasoft/esvg/Circle.java
Normal file
@ -0,0 +1,31 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <esvg/Base.hpp>
|
||||
|
||||
namespace esvg {
|
||||
class Circle : public esvg::Base {
|
||||
private:
|
||||
vec2 m_position; //!< Position of the Circle
|
||||
float m_radius; //!< Radius of the Circle
|
||||
public:
|
||||
Circle(PaintState _parentPaintState);
|
||||
~Circle();
|
||||
bool parseXML(const exml::Element& _element, mat2x3& _parentTrans, vec2& _sizeMax) override;
|
||||
void display(int32_t _spacing) override;
|
||||
void draw(esvg::Renderer& _myRenderer, mat2x3& _basicTrans, int32_t _level) override;
|
||||
void drawShapePoints(etk::Vector<etk::Vector<vec2>>& _out,
|
||||
int32_t _recurtionMax,
|
||||
float _threshold,
|
||||
mat2x3& _basicTrans,
|
||||
int32_t _level=1) override;
|
||||
private:
|
||||
esvg::render::Path createPath();
|
||||
};
|
||||
}
|
||||
|
||||
|
445
src/org/atriasoft/esvg/Dimension.cpp
Normal file
445
src/org/atriasoft/esvg/Dimension.cpp
Normal file
@ -0,0 +1,445 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <esvg/Dimension.hpp>
|
||||
#include <esvg/debug.hpp>
|
||||
|
||||
static const float inchToMillimeter = 1.0f/25.4f;
|
||||
static const float footToMillimeter = 1.0f/304.8f;
|
||||
static const float meterToMillimeter = 1.0f/1000.0f;
|
||||
static const float centimeterToMillimeter = 1.0f/10.0f;
|
||||
static const float kilometerToMillimeter = 1.0f/1000000.0f;
|
||||
static const float millimeterToInch = 25.4f;
|
||||
static const float millimeterToFoot = 304.8f;
|
||||
static const float millimeterToMeter =1000.0f;
|
||||
static const float millimeterToCentimeter = 10.0f;
|
||||
static const float millimeterToKilometer = 1000000.0f;
|
||||
|
||||
// 72 px /inch(2.54cm)
|
||||
static const float basicRatio = 72.0f / 25.4f;
|
||||
|
||||
esvg::Dimension::Dimension() :
|
||||
m_data(0,0),
|
||||
m_type(esvg::distance_pixel) {
|
||||
// notinh to do ...
|
||||
}
|
||||
|
||||
esvg::Dimension::Dimension(const vec2& _size, enum esvg::distance _type) :
|
||||
m_data(0,0),
|
||||
m_type(esvg::distance_pixel) {
|
||||
set(_size, _type);
|
||||
}
|
||||
|
||||
void esvg::Dimension::set(etk::String _config) {
|
||||
m_data.setValue(0,0);
|
||||
m_type = esvg::distance_pixel;
|
||||
enum distance type = esvg::distance_pixel;
|
||||
if (etk::end_with(_config, "%", false) == true) {
|
||||
type = esvg::distance_pourcent;
|
||||
_config.erase(_config.size()-1, 1);
|
||||
} else if (etk::end_with(_config, "px",false) == true) {
|
||||
type = esvg::distance_pixel;
|
||||
_config.erase(_config.size()-2, 2);
|
||||
} else if (etk::end_with(_config, "ft",false) == true) {
|
||||
type = esvg::distance_foot;
|
||||
_config.erase(_config.size()-2, 2);
|
||||
} else if (etk::end_with(_config, "in",false) == true) {
|
||||
type = esvg::distance_inch;
|
||||
_config.erase(_config.size()-2, 2);
|
||||
} else if (etk::end_with(_config, "km",false) == true) {
|
||||
type = esvg::distance_kilometer;
|
||||
_config.erase(_config.size()-2, 2);
|
||||
} else if (etk::end_with(_config, "mm",false) == true) {
|
||||
type = esvg::distance_millimeter;
|
||||
_config.erase(_config.size()-2, 2);
|
||||
} else if (etk::end_with(_config, "cm",false) == true) {
|
||||
type = esvg::distance_centimeter;
|
||||
_config.erase(_config.size()-2, 2);
|
||||
} else if (etk::end_with(_config, "m",false) == true) {
|
||||
type = esvg::distance_meter;
|
||||
_config.erase(_config.size()-1, 1);
|
||||
} else {
|
||||
type = esvg::distance_pixel;
|
||||
Log.verbose("default dimention type for: '" << _config << "' ==> pixel");
|
||||
return;
|
||||
}
|
||||
vec2 tmp = _config;
|
||||
set(tmp, type);
|
||||
Log.verbose(" config dimention : \"" << _config << "\" == > " << *this );
|
||||
}
|
||||
|
||||
static enum esvg::distance parseType(etk::String& _config) {
|
||||
enum esvg::distance type = esvg::distance_pixel;
|
||||
if (etk::end_with(_config, "%", false) == true) {
|
||||
type = esvg::distance_pourcent;
|
||||
_config.erase(_config.size()-1, 1);
|
||||
} else if (etk::end_with(_config, "px",false) == true) {
|
||||
type = esvg::distance_pixel;
|
||||
_config.erase(_config.size()-2, 2);
|
||||
} else if (etk::end_with(_config, "ft",false) == true) {
|
||||
type = esvg::distance_foot;
|
||||
_config.erase(_config.size()-2, 2);
|
||||
} else if (etk::end_with(_config, "in",false) == true) {
|
||||
type = esvg::distance_inch;
|
||||
_config.erase(_config.size()-2, 2);
|
||||
} else if (etk::end_with(_config, "km",false) == true) {
|
||||
type = esvg::distance_kilometer;
|
||||
_config.erase(_config.size()-2, 2);
|
||||
} else if (etk::end_with(_config, "mm",false) == true) {
|
||||
type = esvg::distance_millimeter;
|
||||
_config.erase(_config.size()-2, 2);
|
||||
} else if (etk::end_with(_config, "cm",false) == true) {
|
||||
type = esvg::distance_centimeter;
|
||||
_config.erase(_config.size()-2, 2);
|
||||
} else if (etk::end_with(_config, "m",false) == true) {
|
||||
type = esvg::distance_meter;
|
||||
_config.erase(_config.size()-1, 1);
|
||||
} else {
|
||||
type = esvg::distance_pixel;
|
||||
Log.verbose("default dimention type for: '" << _config << "' ==> pixel");
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
void esvg::Dimension::set(etk::String _configX, etk::String _configY) {
|
||||
m_data.setValue(0,0);
|
||||
m_type = esvg::distance_pixel;
|
||||
enum distance type = esvg::distance_pixel;
|
||||
// First Parse X
|
||||
enum distance typeX = parseType(_configX);
|
||||
float valueX = etk::string_to_float(_configX);
|
||||
// Second Parse Y
|
||||
enum distance typeY = parseType(_configY);
|
||||
float valueY = etk::string_to_float(_configY);
|
||||
// TODO : Check difference ...
|
||||
set(vec2(valueX, valueY), typeX);
|
||||
Log.verbose(" config dimention : '" << _configX << "' '" << _configY << "' == > " << *this );
|
||||
}
|
||||
|
||||
|
||||
esvg::Dimension::~Dimension() {
|
||||
// nothing to do ...
|
||||
}
|
||||
|
||||
esvg::Dimension::operator etk::String() const {
|
||||
etk::String str;
|
||||
str = getValue();
|
||||
switch(getType()) {
|
||||
case esvg::distance_pourcent:
|
||||
str += "%";
|
||||
break;
|
||||
case esvg::distance_pixel:
|
||||
str += "px";
|
||||
break;
|
||||
case esvg::distance_meter:
|
||||
str += "m";
|
||||
break;
|
||||
case esvg::distance_centimeter:
|
||||
str += "cm";
|
||||
break;
|
||||
case esvg::distance_millimeter:
|
||||
str += "mm";
|
||||
break;
|
||||
case esvg::distance_kilometer:
|
||||
str += "km";
|
||||
break;
|
||||
case esvg::distance_inch:
|
||||
str += "in";
|
||||
break;
|
||||
case esvg::distance_foot:
|
||||
str += "ft";
|
||||
break;
|
||||
case esvg::distance_element:
|
||||
str += "em";
|
||||
break;
|
||||
case esvg::distance_ex:
|
||||
str += "ex";
|
||||
break;
|
||||
case esvg::distance_point:
|
||||
str += "pt";
|
||||
break;
|
||||
case esvg::distance_pc:
|
||||
str += "pc";
|
||||
break;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
void esvg::Dimension::set(const vec2& _size, enum esvg::distance _type) {
|
||||
m_data = _size;
|
||||
m_type = _type;
|
||||
switch(_type) {
|
||||
case esvg::distance_pourcent:
|
||||
case esvg::distance_pixel:
|
||||
// nothing to do: Supported ...
|
||||
break;
|
||||
case esvg::distance_meter:
|
||||
case esvg::distance_centimeter:
|
||||
case esvg::distance_millimeter:
|
||||
case esvg::distance_kilometer:
|
||||
case esvg::distance_inch:
|
||||
case esvg::distance_foot:
|
||||
case esvg::distance_element:
|
||||
case esvg::distance_ex:
|
||||
case esvg::distance_point:
|
||||
case esvg::distance_pc:
|
||||
Log.error("Does not support other than Px and % type of dimention : " << _type << " automaticly convert with {72,72} pixel/inch");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
vec2 esvg::Dimension::getPixel(const vec2& _upperSize) const {
|
||||
switch(m_type) {
|
||||
case esvg::distance_pourcent:
|
||||
return vec2(_upperSize.x()*m_data.x()*0.01f, _upperSize.y()*m_data.y()*0.01f);
|
||||
case esvg::distance_pixel:
|
||||
return m_data;
|
||||
case esvg::distance_meter:
|
||||
return vec2(m_data.x()*meterToMillimeter*basicRatio, m_data.y()*meterToMillimeter*basicRatio);
|
||||
case esvg::distance_centimeter:
|
||||
return vec2(m_data.x()*centimeterToMillimeter*basicRatio, m_data.y()*centimeterToMillimeter*basicRatio);
|
||||
case esvg::distance_millimeter:
|
||||
return vec2(m_data.x()*basicRatio, m_data.y()*basicRatio);
|
||||
case esvg::distance_kilometer:
|
||||
return vec2(m_data.x()*kilometerToMillimeter*basicRatio, m_data.y()*kilometerToMillimeter*basicRatio);
|
||||
case esvg::distance_inch:
|
||||
return vec2(m_data.x()*inchToMillimeter*basicRatio, m_data.y()*inchToMillimeter*basicRatio);
|
||||
case esvg::distance_foot:
|
||||
return vec2(m_data.x()*footToMillimeter*basicRatio, m_data.y()*footToMillimeter*basicRatio);
|
||||
}
|
||||
return vec2(128.0f, 128.0f);
|
||||
}
|
||||
|
||||
etk::Stream& esvg::operator <<(etk::Stream& _os, enum esvg::distance _obj) {
|
||||
switch(_obj) {
|
||||
case esvg::distance_pourcent:
|
||||
_os << "%";
|
||||
break;
|
||||
case esvg::distance_pixel:
|
||||
_os << "px";
|
||||
break;
|
||||
case esvg::distance_meter:
|
||||
_os << "m";
|
||||
break;
|
||||
case esvg::distance_centimeter:
|
||||
_os << "cm";
|
||||
break;
|
||||
case esvg::distance_millimeter:
|
||||
_os << "mm";
|
||||
break;
|
||||
case esvg::distance_kilometer:
|
||||
_os << "km";
|
||||
break;
|
||||
case esvg::distance_inch:
|
||||
_os << "in";
|
||||
break;
|
||||
case esvg::distance_foot:
|
||||
_os << "ft";
|
||||
break;
|
||||
case esvg::distance_element:
|
||||
_os << "em";
|
||||
break;
|
||||
case esvg::distance_ex:
|
||||
_os << "ex";
|
||||
break;
|
||||
case esvg::distance_point:
|
||||
_os << "pt";
|
||||
break;
|
||||
case esvg::distance_pc:
|
||||
_os << "pc";
|
||||
break;
|
||||
}
|
||||
return _os;
|
||||
}
|
||||
|
||||
etk::Stream& esvg::operator <<(etk::Stream& _os, const esvg::Dimension& _obj) {
|
||||
_os << _obj.getValue() << _obj.getType();
|
||||
return _os;
|
||||
}
|
||||
|
||||
namespace etk {
|
||||
template<> etk::String toString<esvg::Dimension>(const esvg::Dimension& _obj) {
|
||||
return _obj;
|
||||
}
|
||||
template<> etk::UString toUString<esvg::Dimension>(const esvg::Dimension& _obj) {
|
||||
return etk::toUString(etk::toString(_obj));
|
||||
}
|
||||
template<> bool from_string<esvg::Dimension>(esvg::Dimension& _variableRet, const etk::String& _value) {
|
||||
_variableRet = esvg::Dimension(_value);
|
||||
return true;
|
||||
}
|
||||
template<> bool from_string<esvg::Dimension>(esvg::Dimension& _variableRet, const etk::UString& _value) {
|
||||
return from_string(_variableRet, etk::toString(_value));
|
||||
}
|
||||
};
|
||||
|
||||
esvg::Dimension1D::Dimension1D() :
|
||||
m_data(0.0f),
|
||||
m_type(esvg::distance_pixel) {
|
||||
// notinh to do ...
|
||||
}
|
||||
|
||||
esvg::Dimension1D::Dimension1D(float _size, enum esvg::distance _type) :
|
||||
m_data(0.0f),
|
||||
m_type(esvg::distance_pixel) {
|
||||
set(_size, _type);
|
||||
}
|
||||
|
||||
void esvg::Dimension1D::set(etk::String _config) {
|
||||
m_data = 0;
|
||||
m_type = esvg::distance_pixel;
|
||||
enum distance type = esvg::distance_pixel;
|
||||
if (etk::end_with(_config, "%", false) == true) {
|
||||
type = esvg::distance_pourcent;
|
||||
_config.erase(_config.size()-1, 1);
|
||||
} else if (etk::end_with(_config, "px",false) == true) {
|
||||
type = esvg::distance_pixel;
|
||||
_config.erase(_config.size()-2, 2);
|
||||
} else if (etk::end_with(_config, "ft",false) == true) {
|
||||
type = esvg::distance_foot;
|
||||
_config.erase(_config.size()-2, 2);
|
||||
} else if (etk::end_with(_config, "in",false) == true) {
|
||||
type = esvg::distance_inch;
|
||||
_config.erase(_config.size()-2, 2);
|
||||
} else if (etk::end_with(_config, "km",false) == true) {
|
||||
type = esvg::distance_kilometer;
|
||||
_config.erase(_config.size()-2, 2);
|
||||
} else if (etk::end_with(_config, "mm",false) == true) {
|
||||
type = esvg::distance_millimeter;
|
||||
_config.erase(_config.size()-2, 2);
|
||||
} else if (etk::end_with(_config, "cm",false) == true) {
|
||||
type = esvg::distance_centimeter;
|
||||
_config.erase(_config.size()-2, 2);
|
||||
} else if (etk::end_with(_config, "m",false) == true) {
|
||||
type = esvg::distance_meter;
|
||||
_config.erase(_config.size()-1, 1);
|
||||
} else {
|
||||
type = esvg::distance_pixel;
|
||||
Log.verbose("default dimention type for: '" << _config << "' ==> pixel");
|
||||
}
|
||||
float tmp = etk::string_to_float(_config);
|
||||
set(tmp, type);
|
||||
Log.verbose(" config dimention : \"" << _config << "\" == > " << *this );
|
||||
}
|
||||
|
||||
esvg::Dimension1D::~Dimension1D() {
|
||||
// nothing to do ...
|
||||
}
|
||||
|
||||
esvg::Dimension1D::operator etk::String() const {
|
||||
etk::String str;
|
||||
str = getValue();
|
||||
switch(getType()) {
|
||||
case esvg::distance_pourcent:
|
||||
str += "%";
|
||||
break;
|
||||
case esvg::distance_pixel:
|
||||
str += "px";
|
||||
break;
|
||||
case esvg::distance_meter:
|
||||
str += "m";
|
||||
break;
|
||||
case esvg::distance_centimeter:
|
||||
str += "cm";
|
||||
break;
|
||||
case esvg::distance_millimeter:
|
||||
str += "mm";
|
||||
break;
|
||||
case esvg::distance_kilometer:
|
||||
str += "km";
|
||||
break;
|
||||
case esvg::distance_inch:
|
||||
str += "in";
|
||||
break;
|
||||
case esvg::distance_foot:
|
||||
str += "ft";
|
||||
break;
|
||||
case esvg::distance_element:
|
||||
str += "em";
|
||||
break;
|
||||
case esvg::distance_ex:
|
||||
str += "ex";
|
||||
break;
|
||||
case esvg::distance_point:
|
||||
str += "pt";
|
||||
break;
|
||||
case esvg::distance_pc:
|
||||
str += "pc";
|
||||
break;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
void esvg::Dimension1D::set(float _size, enum esvg::distance _type) {
|
||||
m_data = _size;
|
||||
m_type = _type;
|
||||
switch(_type) {
|
||||
case esvg::distance_pourcent:
|
||||
case esvg::distance_pixel:
|
||||
// nothing to do: Supported ...
|
||||
break;
|
||||
case esvg::distance_meter:
|
||||
case esvg::distance_centimeter:
|
||||
case esvg::distance_millimeter:
|
||||
case esvg::distance_kilometer:
|
||||
case esvg::distance_inch:
|
||||
case esvg::distance_foot:
|
||||
case esvg::distance_element:
|
||||
case esvg::distance_ex:
|
||||
case esvg::distance_point:
|
||||
case esvg::distance_pc:
|
||||
Log.error("Does not support other than Px and % type of dimention1D : " << _type << " automaticly convert with {72,72} pixel/inch");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
float esvg::Dimension1D::getPixel(float _upperSize) const {
|
||||
switch(m_type) {
|
||||
case esvg::distance_pourcent:
|
||||
return _upperSize*m_data*0.01f;
|
||||
case esvg::distance_pixel:
|
||||
return m_data;
|
||||
case esvg::distance_meter:
|
||||
return m_data*meterToMillimeter*basicRatio;
|
||||
case esvg::distance_centimeter:
|
||||
return m_data*centimeterToMillimeter*basicRatio;
|
||||
case esvg::distance_millimeter:
|
||||
return m_data*basicRatio;
|
||||
case esvg::distance_kilometer:
|
||||
return m_data*kilometerToMillimeter*basicRatio;
|
||||
case esvg::distance_inch:
|
||||
return m_data*inchToMillimeter*basicRatio;
|
||||
case esvg::distance_foot:
|
||||
return m_data*footToMillimeter*basicRatio;
|
||||
}
|
||||
return 128.0f;
|
||||
}
|
||||
|
||||
etk::Stream& esvg::operator <<(etk::Stream& _os, const esvg::Dimension1D& _obj) {
|
||||
_os << _obj.getValue() << _obj.getType();
|
||||
return _os;
|
||||
}
|
||||
|
||||
namespace etk {
|
||||
template<> etk::String toString<esvg::Dimension1D>(const esvg::Dimension1D& _obj) {
|
||||
return _obj;
|
||||
}
|
||||
template<> etk::UString toUString<esvg::Dimension1D>(const esvg::Dimension1D& _obj) {
|
||||
return etk::toUString(etk::toString(_obj));
|
||||
}
|
||||
template<> bool from_string<esvg::Dimension1D>(esvg::Dimension1D& _variableRet, const etk::String& _value) {
|
||||
_variableRet = esvg::Dimension1D(_value);
|
||||
return true;
|
||||
}
|
||||
template<> bool from_string<esvg::Dimension1D>(esvg::Dimension1D& _variableRet, const etk::UString& _value) {
|
||||
return from_string(_variableRet, etk::toString(_value));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
252
src/org/atriasoft/esvg/Dimension.java
Normal file
252
src/org/atriasoft/esvg/Dimension.java
Normal file
@ -0,0 +1,252 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <etk/types.hpp>
|
||||
#include <etk/math/Vector2D.hpp>
|
||||
|
||||
namespace esvg {
|
||||
enum distance {
|
||||
distance_pourcent=0, //!< "%"
|
||||
distance_pixel, //!< "px"
|
||||
distance_meter, //!< "m"
|
||||
distance_centimeter, //!< "cm"
|
||||
distance_millimeter, //!< "mm"
|
||||
distance_kilometer, //!< "km"
|
||||
distance_inch, //!< "in"
|
||||
distance_foot, //!< "ft"
|
||||
distance_element, //!< "em"
|
||||
distance_ex, //!< "ex"
|
||||
distance_point, //!< "pt"
|
||||
distance_pc //!< "pc"
|
||||
};
|
||||
/**
|
||||
* @brief in the dimention class we store the data as the more usefull unit (pixel)
|
||||
* but one case need to be dynamic the %, then when requested in % the register the % value
|
||||
*/
|
||||
class Dimension {
|
||||
private:
|
||||
vec2 m_data;
|
||||
enum distance m_type;
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor (default :0,0 mode pixel)
|
||||
*/
|
||||
Dimension();
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param[in] _size Requested dimention
|
||||
* @param[in] _type Unit of the Dimention
|
||||
*/
|
||||
Dimension(const vec2& _size, enum esvg::distance _type=esvg::distance_pixel);
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param[in] _config dimension configuration.
|
||||
*/
|
||||
Dimension(const etk::String& _config) :
|
||||
m_data(0,0),
|
||||
m_type(esvg::distance_pixel) {
|
||||
set(_config);
|
||||
};
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param[in] _configX dimension X configuration.
|
||||
* @param[in] _configY dimension Y configuration.
|
||||
*/
|
||||
Dimension(const etk::String& _configX, const etk::String& _configY) :
|
||||
m_data(0,0),
|
||||
m_type(esvg::distance_pixel) {
|
||||
set(_configX, _configY);
|
||||
};
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~Dimension();
|
||||
|
||||
/**
|
||||
* @brief string cast :
|
||||
*/
|
||||
operator etk::String() const;
|
||||
|
||||
/**
|
||||
* @brief get the current dimention.
|
||||
* @return dimention requested.
|
||||
*/
|
||||
const vec2& getValue() const {
|
||||
return m_data;
|
||||
}
|
||||
/**
|
||||
* @breif get the dimension type
|
||||
* @return the type
|
||||
*/
|
||||
enum distance getType() const {
|
||||
return m_type;
|
||||
};
|
||||
/**
|
||||
* @brief set the current dimention in requested type
|
||||
* @param[in] _size Dimention to set
|
||||
* @param[in] _type Type of unit requested.
|
||||
*/
|
||||
void set(const vec2& _size, enum distance _type);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief set the current dimention in requested type
|
||||
* @param[in] _config dimension configuration.
|
||||
*/
|
||||
void set(etk::String _config);
|
||||
/**
|
||||
* @brief set the current dimention in requested type
|
||||
* @param[in] _configX dimension X configuration.
|
||||
* @param[in] _configY dimension Y configuration.
|
||||
*/
|
||||
void set(etk::String _configX, etk::String _configY);
|
||||
public:
|
||||
/**
|
||||
* @brief get the current dimention in pixel
|
||||
* @param[in] _upperSize Size in pixel of the upper value
|
||||
* @return dimention in Pixel
|
||||
*/
|
||||
vec2 getPixel(const vec2& _upperSize) const;
|
||||
/*****************************************************
|
||||
* = assigment
|
||||
*****************************************************/
|
||||
const Dimension& operator= (const Dimension& _obj ) {
|
||||
if (this!=&_obj) {
|
||||
m_data = _obj.m_data;
|
||||
m_type = _obj.m_type;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
/*****************************************************
|
||||
* == operator
|
||||
*****************************************************/
|
||||
bool operator == (const Dimension& _obj) const {
|
||||
if( m_data == _obj.m_data
|
||||
&& m_type == _obj.m_type) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/*****************************************************
|
||||
* != operator
|
||||
*****************************************************/
|
||||
bool operator!= (const Dimension& _obj) const {
|
||||
if( m_data != _obj.m_data
|
||||
|| m_type != _obj.m_type) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
etk::Stream& operator <<(etk::Stream& _os, enum esvg::distance _obj);
|
||||
etk::Stream& operator <<(etk::Stream& _os, const esvg::Dimension& _obj);
|
||||
/**
|
||||
* @brief in the dimention class we store the data as the more usefull unit (pixel)
|
||||
* but one case need to be dynamic the %, then when requested in % the register the % value
|
||||
*/
|
||||
class Dimension1D {
|
||||
private:
|
||||
float m_data;
|
||||
enum distance m_type;
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor (default :0,0 mode pixel)
|
||||
*/
|
||||
Dimension1D();
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param[in] _size Requested dimention
|
||||
* @param[in] _type Unit of the Dimention
|
||||
*/
|
||||
Dimension1D(float _size, enum esvg::distance _type=esvg::distance_pixel);
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param[in] _config dimension configuration.
|
||||
*/
|
||||
Dimension1D(const etk::String& _config) :
|
||||
m_data(0.0f),
|
||||
m_type(esvg::distance_pixel) {
|
||||
set(_config);
|
||||
};
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~Dimension1D();
|
||||
|
||||
/**
|
||||
* @brief string cast :
|
||||
*/
|
||||
operator etk::String() const;
|
||||
|
||||
/**
|
||||
* @brief get the current dimention.
|
||||
* @return dimention requested.
|
||||
*/
|
||||
const float& getValue() const {
|
||||
return m_data;
|
||||
}
|
||||
/**
|
||||
* @breif get the dimension type
|
||||
* @return the type
|
||||
*/
|
||||
enum distance getType() const {
|
||||
return m_type;
|
||||
};
|
||||
/**
|
||||
* @brief set the current dimention in requested type
|
||||
* @param[in] _size Dimention to set
|
||||
* @param[in] _type Type of unit requested.
|
||||
*/
|
||||
void set(float _size, enum distance _type);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief set the current dimention in requested type
|
||||
* @param[in] _config dimension configuration.
|
||||
*/
|
||||
void set(etk::String _config);
|
||||
public:
|
||||
/**
|
||||
* @brief get the current dimention in pixel
|
||||
* @param[in] _upperSize Size in pixel of the upper value
|
||||
* @return dimention in Pixel
|
||||
*/
|
||||
float getPixel(float _upperSize) const;
|
||||
/*****************************************************
|
||||
* = assigment
|
||||
*****************************************************/
|
||||
const Dimension1D& operator= (const Dimension1D& _obj ) {
|
||||
if (this!=&_obj) {
|
||||
m_data = _obj.m_data;
|
||||
m_type = _obj.m_type;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
/*****************************************************
|
||||
* == operator
|
||||
*****************************************************/
|
||||
bool operator == (const Dimension1D& _obj) const {
|
||||
if( m_data == _obj.m_data
|
||||
&& m_type == _obj.m_type) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/*****************************************************
|
||||
* != operator
|
||||
*****************************************************/
|
||||
bool operator!= (const Dimension1D& _obj) const {
|
||||
if( m_data != _obj.m_data
|
||||
|| m_type != _obj.m_type) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
etk::Stream& operator <<(etk::Stream& _os, const esvg::Dimension1D& _obj);
|
||||
}
|
||||
|
172
src/org/atriasoft/esvg/Ellipse.cpp
Normal file
172
src/org/atriasoft/esvg/Ellipse.cpp
Normal file
@ -0,0 +1,172 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <esvg/debug.hpp>
|
||||
#include <esvg/Ellipse.hpp>
|
||||
#include <esvg/render/Path.hpp>
|
||||
#include <esvg/render/Weight.hpp>
|
||||
|
||||
esvg::Ellipse::Ellipse(PaintState _parentPaintState) : esvg::Base(_parentPaintState) {
|
||||
|
||||
}
|
||||
|
||||
esvg::Ellipse::~Ellipse() {
|
||||
|
||||
}
|
||||
|
||||
bool esvg::Ellipse::parseXML(const exml::Element& _element, mat2x3& _parentTrans, vec2& _sizeMax) {
|
||||
if (_element.exist() == false) {
|
||||
return false;
|
||||
}
|
||||
parseTransform(_element);
|
||||
parsePaintAttr(_element);
|
||||
|
||||
// add the property of the parrent modifications ...
|
||||
m_transformMatrix *= _parentTrans;
|
||||
|
||||
m_c.setValue(0,0);
|
||||
m_r.setValue(0,0);
|
||||
|
||||
etk::String content = _element.attributes["cx"];
|
||||
if (content.size()!=0) {
|
||||
m_c.setX(parseLength(content));
|
||||
}
|
||||
content = _element.attributes["cy"];
|
||||
if (content.size()!=0) {
|
||||
m_c.setY(parseLength(content));
|
||||
}
|
||||
content = _element.attributes["rx"];
|
||||
if (content.size()!=0) {
|
||||
m_r.setX(parseLength(content));
|
||||
} else {
|
||||
Log.error("(l "<<_element.getPos()<<") Ellipse \"rx\" is not present");
|
||||
return false;
|
||||
}
|
||||
content = _element.attributes["ry"];
|
||||
if (content.size()!=0) {
|
||||
m_r.setY(parseLength(content));
|
||||
} else {
|
||||
Log.error("(l "<<_element.getPos()<<") Ellipse \"ry\" is not present");
|
||||
return false;
|
||||
}
|
||||
_sizeMax.setValue(m_c.x() + m_r.x(), m_c.y() + m_r.y());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void esvg::Ellipse::display(int32_t _spacing) {
|
||||
Log.debug(spacingDist(_spacing) << "Ellipse c=" << m_c << " r=" << m_r);
|
||||
}
|
||||
|
||||
|
||||
esvg::render::Path esvg::Ellipse::createPath() {
|
||||
esvg::render::Path out;
|
||||
out.clear();
|
||||
out.moveTo(false, m_c + vec2(m_r.x(), 0.0f));
|
||||
out.curveTo(false,
|
||||
m_c + vec2(m_r.x(), m_r.y()*esvg::kappa90),
|
||||
m_c + vec2(m_r.x()*esvg::kappa90, m_r.y()),
|
||||
m_c + vec2(0.0f, m_r.y()));
|
||||
out.curveTo(false,
|
||||
m_c + vec2(-m_r.x()*esvg::kappa90, m_r.y()),
|
||||
m_c + vec2(-m_r.x(), m_r.y()*esvg::kappa90),
|
||||
m_c + vec2(-m_r.x(), 0.0f));
|
||||
out.curveTo(false,
|
||||
m_c + vec2(-m_r.x(), -m_r.y()*esvg::kappa90),
|
||||
m_c + vec2(-m_r.x()*esvg::kappa90, -m_r.y()),
|
||||
m_c + vec2(0.0f, -m_r.y()));
|
||||
out.curveTo(false,
|
||||
m_c + vec2(m_r.x()*esvg::kappa90, -m_r.y()),
|
||||
m_c + vec2(m_r.x(), -m_r.y()*esvg::kappa90),
|
||||
m_c + vec2(m_r.x(), 0.0f));
|
||||
out.close();
|
||||
return out;
|
||||
}
|
||||
|
||||
void esvg::Ellipse::draw(esvg::Renderer& _myRenderer, mat2x3& _basicTrans, int32_t _level) {
|
||||
Log.verbose(spacingDist(_level) << "DRAW esvg::Ellipse");
|
||||
if ( m_r.x()<=0.0f
|
||||
|| m_r.y()<=0.0f) {
|
||||
Log.verbose(spacingDist(_level+1) << "Too small radius" << m_r);
|
||||
return;
|
||||
}
|
||||
esvg::render::Path listElement = createPath();
|
||||
|
||||
mat2x3 mtx = m_transformMatrix;
|
||||
mtx *= _basicTrans;
|
||||
|
||||
esvg::render::PointList listPoints;
|
||||
listPoints = listElement.generateListPoints(_level,
|
||||
_myRenderer.getInterpolationRecurtionMax(),
|
||||
_myRenderer.getInterpolationThreshold());
|
||||
//listPoints.applyMatrix(mtx);
|
||||
esvg::render::SegmentList listSegmentFill;
|
||||
esvg::render::SegmentList listSegmentStroke;
|
||||
esvg::render::Weight tmpFill;
|
||||
esvg::render::Weight tmpStroke;
|
||||
ememory::SharedPtr<esvg::render::DynamicColor> colorFill = esvg::render::createColor(m_paint.fill, mtx);
|
||||
ememory::SharedPtr<esvg::render::DynamicColor> colorStroke;
|
||||
if (m_paint.strokeWidth > 0.0f) {
|
||||
colorStroke = esvg::render::createColor(m_paint.stroke, mtx);
|
||||
}
|
||||
// Check if we need to display background
|
||||
if (colorFill != null) {
|
||||
listSegmentFill.createSegmentList(listPoints);
|
||||
colorFill->setViewPort(listSegmentFill.getViewPort());
|
||||
listSegmentFill.applyMatrix(mtx);
|
||||
// now, traverse the scanlines and find the intersections on each scanline, use non-zero rule
|
||||
tmpFill.generate(_myRenderer.getSize(),
|
||||
_myRenderer.getNumberSubScanLine(),
|
||||
listSegmentFill);
|
||||
}
|
||||
// check if we need to display stroke:
|
||||
if (colorStroke != null) {
|
||||
listSegmentStroke.createSegmentListStroke(listPoints,
|
||||
m_paint.strokeWidth,
|
||||
m_paint.lineCap,
|
||||
m_paint.lineJoin,
|
||||
m_paint.miterLimit);
|
||||
colorStroke->setViewPort(listSegmentStroke.getViewPort());
|
||||
listSegmentStroke.applyMatrix(mtx);
|
||||
// now, traverse the scanlines and find the intersections on each scanline, use non-zero rule
|
||||
tmpStroke.generate(_myRenderer.getSize(),
|
||||
_myRenderer.getNumberSubScanLine(),
|
||||
listSegmentStroke);
|
||||
}
|
||||
// add on images:
|
||||
_myRenderer.print(tmpFill,
|
||||
colorFill,
|
||||
tmpStroke,
|
||||
colorStroke,
|
||||
m_paint.opacity);
|
||||
#ifdef DEBUG
|
||||
_myRenderer.addDebugSegment(listSegmentFill);
|
||||
_myRenderer.addDebugSegment(listSegmentStroke);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void esvg::Ellipse::drawShapePoints(etk::Vector<etk::Vector<vec2>>& _out,
|
||||
int32_t _recurtionMax,
|
||||
float _threshold,
|
||||
mat2x3& _basicTrans,
|
||||
int32_t _level) {
|
||||
Log.verbose(spacingDist(_level) << "DRAW Shape esvg::Ellipse");
|
||||
esvg::render::Path listElement = createPath();
|
||||
mat2x3 mtx = m_transformMatrix;
|
||||
mtx *= _basicTrans;
|
||||
esvg::render::PointList listPoints;
|
||||
listPoints = listElement.generateListPoints(_level, _recurtionMax, _threshold);
|
||||
listPoints.applyMatrix(mtx);
|
||||
for (auto &it : listPoints.m_data) {
|
||||
etk::Vector<vec2> listPoint;
|
||||
for (auto &itDot : it) {
|
||||
listPoint.pushBack(itDot.m_pos);
|
||||
}
|
||||
_out.pushBack(listPoint);
|
||||
}
|
||||
}
|
||||
|
30
src/org/atriasoft/esvg/Ellipse.java
Normal file
30
src/org/atriasoft/esvg/Ellipse.java
Normal file
@ -0,0 +1,30 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <esvg/Base.hpp>
|
||||
|
||||
namespace esvg {
|
||||
class Ellipse : public esvg::Base {
|
||||
private:
|
||||
vec2 m_c; //!< Center property of the ellipse
|
||||
vec2 m_r; //!< Radius property of the ellipse
|
||||
public:
|
||||
Ellipse(PaintState _parentPaintState);
|
||||
~Ellipse();
|
||||
bool parseXML(const exml::Element& _element, mat2x3& _parentTrans, vec2& _sizeMax) override;
|
||||
void display(int32_t _spacing) override;
|
||||
void draw(esvg::Renderer& _myRenderer, mat2x3& _basicTrans, int32_t _level) override;
|
||||
void drawShapePoints(etk::Vector<etk::Vector<vec2>>& _out,
|
||||
int32_t _recurtionMax,
|
||||
float _threshold,
|
||||
mat2x3& _basicTrans,
|
||||
int32_t _level=1) override;
|
||||
private:
|
||||
esvg::render::Path createPath();
|
||||
};
|
||||
}
|
||||
|
129
src/org/atriasoft/esvg/Group.cpp
Normal file
129
src/org/atriasoft/esvg/Group.cpp
Normal file
@ -0,0 +1,129 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <esvg/debug.hpp>
|
||||
#include <esvg/Group.hpp>
|
||||
#include <etk/types.hpp>
|
||||
#include <esvg/Base.hpp>
|
||||
#include <esvg/Circle.hpp>
|
||||
#include <esvg/Ellipse.hpp>
|
||||
#include <esvg/Line.hpp>
|
||||
#include <esvg/Path.hpp>
|
||||
#include <esvg/Polygon.hpp>
|
||||
#include <esvg/Polyline.hpp>
|
||||
#include <esvg/Rectangle.hpp>
|
||||
#include <esvg/Text.hpp>
|
||||
#include <esvg/Group.hpp>
|
||||
|
||||
esvg::Group::Group(PaintState _parentPaintState) : esvg::Base(_parentPaintState) {
|
||||
|
||||
}
|
||||
|
||||
esvg::Group::~Group() {
|
||||
|
||||
}
|
||||
|
||||
bool esvg::Group::parseXML(const exml::Element& _element, mat2x3& _parentTrans, vec2& _sizeMax) {
|
||||
if (_element.exist() == false) {
|
||||
return false;
|
||||
}
|
||||
// parse ...
|
||||
vec2 pos(0,0);
|
||||
vec2 size(0,0);
|
||||
parseTransform(_element);
|
||||
parsePosition(_element, pos, size);
|
||||
parsePaintAttr(_element);
|
||||
Log.verbose("parsed G1. trans : " << m_transformMatrix);
|
||||
|
||||
// add the property of the parrent modifications ...
|
||||
m_transformMatrix *= _parentTrans;
|
||||
|
||||
Log.verbose("parsed G2. trans : " << m_transformMatrix);
|
||||
|
||||
_sizeMax.setValue(0,0);
|
||||
vec2 tmpPos(0,0);
|
||||
// parse all sub node :
|
||||
for(const auto it : _element.nodes) {
|
||||
exml::Element child = it.toElement();
|
||||
if (child.exist() == false) {
|
||||
// can be a comment ...
|
||||
continue;
|
||||
}
|
||||
ememory::SharedPtr<esvg::Base> elementParser;
|
||||
if (child.getValue() == "g") {
|
||||
elementParser = ememory::makeShared<esvg::Group>(m_paint);
|
||||
} else if (child.getValue() == "a") {
|
||||
// TODO ...
|
||||
} else if (child.getValue() == "path") {
|
||||
elementParser = ememory::makeShared<esvg::Path>(m_paint);
|
||||
} else if (child.getValue() == "rect") {
|
||||
elementParser = ememory::makeShared<esvg::Rectangle>(m_paint);
|
||||
} else if (child.getValue() == "circle") {
|
||||
elementParser = ememory::makeShared<esvg::Circle>(m_paint);
|
||||
} else if (child.getValue() == "ellipse") {
|
||||
elementParser = ememory::makeShared<esvg::Ellipse>(m_paint);
|
||||
} else if (child.getValue() == "line") {
|
||||
elementParser = ememory::makeShared<esvg::Line>(m_paint);
|
||||
} else if (child.getValue() == "polyline") {
|
||||
elementParser = ememory::makeShared<esvg::Polyline>(m_paint);
|
||||
} else if (child.getValue() == "polygon") {
|
||||
elementParser = ememory::makeShared<esvg::Polygon>(m_paint);
|
||||
} else if (child.getValue() == "text") {
|
||||
elementParser = ememory::makeShared<esvg::Text>(m_paint);
|
||||
} else {
|
||||
Log.error("(l " << child.getPos() << ") node not suported : '" << child.getValue() << "' must be [g,a,path,rect,circle,ellipse,line,polyline,polygon,text]");
|
||||
}
|
||||
if (elementParser == null) {
|
||||
Log.error("(l " << child.getPos() << ") error on node: '" << child.getValue() << "' allocation error or not supported ...");
|
||||
continue;
|
||||
}
|
||||
if (elementParser->parseXML(child, m_transformMatrix, tmpPos) == false) {
|
||||
Log.error("(l " << child.getPos() << ") error on node: '" << child.getValue() << "' Sub Parsing ERROR");
|
||||
elementParser.reset();
|
||||
continue;
|
||||
}
|
||||
_sizeMax.setValue(etk::max(_sizeMax.x(), tmpPos.x()),
|
||||
etk::max(_sizeMax.y(), tmpPos.y()));
|
||||
// add element in the system
|
||||
m_subElementList.pushBack(elementParser);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void esvg::Group::display(int32_t _spacing) {
|
||||
Log.debug(spacingDist(_spacing) << "Group (START) fill=" << m_paint.fill.first << "/" << m_paint.fill.second
|
||||
<< " stroke=" << m_paint.stroke.first << "/" << m_paint.stroke.second
|
||||
<< " stroke-width=" << m_paint.strokeWidth );
|
||||
for (auto &it : m_subElementList) {
|
||||
if (it != null) {
|
||||
it->display(_spacing+1);
|
||||
}
|
||||
}
|
||||
Log.debug(spacingDist(_spacing) << "Group (STOP)");
|
||||
}
|
||||
|
||||
void esvg::Group::draw(esvg::Renderer& _myRenderer, mat2x3& _basicTrans, int32_t _level) {
|
||||
Log.verbose(spacingDist(_level) << "DRAW esvg::group");
|
||||
for (auto &it : m_subElementList) {
|
||||
if (it != null) {
|
||||
it->draw(_myRenderer, _basicTrans, _level+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void esvg::Group::drawShapePoints(etk::Vector<etk::Vector<vec2>>& _out,
|
||||
int32_t _recurtionMax,
|
||||
float _threshold,
|
||||
mat2x3& _basicTrans,
|
||||
int32_t _level) {
|
||||
Log.verbose(spacingDist(_level) << "DRAW shape esvg::group");
|
||||
for (auto &it : m_subElementList) {
|
||||
if (it != null) {
|
||||
it->drawShapePoints(_out, _recurtionMax, _threshold, _basicTrans, _level+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
28
src/org/atriasoft/esvg/Group.java
Normal file
28
src/org/atriasoft/esvg/Group.java
Normal file
@ -0,0 +1,28 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <esvg/Base.hpp>
|
||||
#include <etk/Vector.hpp>
|
||||
|
||||
namespace esvg {
|
||||
class Group : public esvg::Base {
|
||||
private:
|
||||
etk::Vector<ememory::SharedPtr<esvg::Base>> m_subElementList; //!< sub elements ...
|
||||
public:
|
||||
Group(PaintState _parentPaintState);
|
||||
~Group();
|
||||
bool parseXML(const exml::Element& _element, mat2x3& _parentTrans, vec2& _sizeMax) override;
|
||||
void display(int32_t spacing) override;
|
||||
void draw(esvg::Renderer& _myRenderer, mat2x3& _basicTrans, int32_t _level) override;
|
||||
void drawShapePoints(etk::Vector<etk::Vector<vec2>>& _out,
|
||||
int32_t _recurtionMax,
|
||||
float _threshold,
|
||||
mat2x3& _basicTrans,
|
||||
int32_t _level=1) override;
|
||||
};
|
||||
}
|
||||
|
139
src/org/atriasoft/esvg/Line.cpp
Normal file
139
src/org/atriasoft/esvg/Line.cpp
Normal file
@ -0,0 +1,139 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <esvg/debug.hpp>
|
||||
#include <esvg/Line.hpp>
|
||||
#include <esvg/render/Path.hpp>
|
||||
#include <esvg/render/Weight.hpp>
|
||||
|
||||
esvg::Line::Line(PaintState _parentPaintState) : esvg::Base(_parentPaintState) {
|
||||
m_startPos.setValue(0,0);
|
||||
m_stopPos.setValue(0,0);
|
||||
}
|
||||
|
||||
esvg::Line::~Line() {
|
||||
|
||||
}
|
||||
|
||||
bool esvg::Line::parseXML(const exml::Element& _element, mat2x3& _parentTrans, vec2& _sizeMax) {
|
||||
// line must have a minimum size...
|
||||
m_paint.strokeWidth = 1;
|
||||
if (_element.exist() == false) {
|
||||
return false;
|
||||
}
|
||||
parseTransform(_element);
|
||||
parsePaintAttr(_element);
|
||||
|
||||
// add the property of the parrent modifications ...
|
||||
m_transformMatrix *= _parentTrans;
|
||||
|
||||
etk::String content = _element.attributes["x1"];
|
||||
if (content.size() != 0) {
|
||||
m_startPos.setX(parseLength(content));
|
||||
}
|
||||
content = _element.attributes["y1"];
|
||||
if (content.size() != 0) {
|
||||
m_startPos.setY(parseLength(content));
|
||||
}
|
||||
content = _element.attributes["x2"];
|
||||
if (content.size() != 0) {
|
||||
m_stopPos.setX(parseLength(content));
|
||||
}
|
||||
content = _element.attributes["y2"];
|
||||
if (content.size() != 0) {
|
||||
m_stopPos.setY(parseLength(content));
|
||||
}
|
||||
_sizeMax.setValue(etk::max(m_startPos.x(), m_stopPos.x()),
|
||||
etk::max(m_startPos.y(), m_stopPos.y()));
|
||||
return true;
|
||||
}
|
||||
|
||||
void esvg::Line::display(int32_t _spacing) {
|
||||
Log.debug(spacingDist(_spacing) << "Line " << m_startPos << " to " << m_stopPos);
|
||||
}
|
||||
|
||||
esvg::render::Path esvg::Line::createPath() {
|
||||
esvg::render::Path out;
|
||||
out.clear();
|
||||
out.moveTo(false, m_startPos);
|
||||
out.lineTo(false, m_stopPos);
|
||||
out.stop();
|
||||
return out;
|
||||
}
|
||||
|
||||
void esvg::Line::draw(esvg::Renderer& _myRenderer, mat2x3& _basicTrans, int32_t _level) {
|
||||
Log.verbose(spacingDist(_level) << "DRAW esvg::Line");
|
||||
|
||||
esvg::render::Path listElement = createPath();
|
||||
|
||||
mat2x3 mtx = m_transformMatrix;
|
||||
mtx *= _basicTrans;
|
||||
|
||||
esvg::render::PointList listPoints;
|
||||
listPoints = listElement.generateListPoints(_level,
|
||||
_myRenderer.getInterpolationRecurtionMax(),
|
||||
_myRenderer.getInterpolationThreshold());
|
||||
//listPoints.applyMatrix(mtx);
|
||||
esvg::render::SegmentList listSegmentFill;
|
||||
esvg::render::SegmentList listSegmentStroke;
|
||||
esvg::render::Weight tmpFill;
|
||||
esvg::render::Weight tmpStroke;
|
||||
ememory::SharedPtr<esvg::render::DynamicColor> colorFill = esvg::render::createColor(m_paint.fill, mtx);
|
||||
ememory::SharedPtr<esvg::render::DynamicColor> colorStroke;
|
||||
if (m_paint.strokeWidth > 0.0f) {
|
||||
colorStroke = esvg::render::createColor(m_paint.stroke, mtx);
|
||||
}
|
||||
// Check if we need to display background
|
||||
// No background ...
|
||||
// check if we need to display stroke:
|
||||
if (colorStroke != null) {
|
||||
listSegmentStroke.createSegmentListStroke(listPoints,
|
||||
m_paint.strokeWidth,
|
||||
m_paint.lineCap,
|
||||
m_paint.lineJoin,
|
||||
m_paint.miterLimit);
|
||||
colorStroke->setViewPort(listSegmentStroke.getViewPort());
|
||||
listSegmentStroke.applyMatrix(mtx);
|
||||
// now, traverse the scanlines and find the intersections on each scanline, use non-zero rule
|
||||
tmpStroke.generate(_myRenderer.getSize(),
|
||||
_myRenderer.getNumberSubScanLine(),
|
||||
listSegmentStroke);
|
||||
}
|
||||
// add on images:
|
||||
_myRenderer.print(tmpFill,
|
||||
colorFill,
|
||||
tmpStroke,
|
||||
colorStroke,
|
||||
m_paint.opacity);
|
||||
#ifdef DEBUG
|
||||
_myRenderer.addDebugSegment(listSegmentFill);
|
||||
_myRenderer.addDebugSegment(listSegmentStroke);
|
||||
_myRenderer.addDebugSegment(listElement.m_debugInformation);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void esvg::Line::drawShapePoints(etk::Vector<etk::Vector<vec2>>& _out,
|
||||
int32_t _recurtionMax,
|
||||
float _threshold,
|
||||
mat2x3& _basicTrans,
|
||||
int32_t _level) {
|
||||
Log.verbose(spacingDist(_level) << "DRAW Shape esvg::Line");
|
||||
esvg::render::Path listElement = createPath();
|
||||
mat2x3 mtx = m_transformMatrix;
|
||||
mtx *= _basicTrans;
|
||||
esvg::render::PointList listPoints;
|
||||
listPoints = listElement.generateListPoints(_level, _recurtionMax, _threshold);
|
||||
listPoints.applyMatrix(mtx);
|
||||
for (auto &it : listPoints.m_data) {
|
||||
etk::Vector<vec2> listPoint;
|
||||
for (auto &itDot : it) {
|
||||
listPoint.pushBack(itDot.m_pos);
|
||||
}
|
||||
_out.pushBack(listPoint);
|
||||
}
|
||||
}
|
||||
|
30
src/org/atriasoft/esvg/Line.java
Normal file
30
src/org/atriasoft/esvg/Line.java
Normal file
@ -0,0 +1,30 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <esvg/Base.hpp>
|
||||
|
||||
namespace esvg {
|
||||
class Line : public esvg::Base {
|
||||
private:
|
||||
vec2 m_startPos; //!< Start line position
|
||||
vec2 m_stopPos; //!< Stop line position
|
||||
public:
|
||||
Line(PaintState _parentPaintState);
|
||||
~Line();
|
||||
bool parseXML(const exml::Element& _element, mat2x3& _parentTrans, vec2& _sizeMax) override;
|
||||
void display(int32_t _spacing) override;
|
||||
void draw(esvg::Renderer& _myRenderer, mat2x3& _basicTrans, int32_t _level) override;
|
||||
void drawShapePoints(etk::Vector<etk::Vector<vec2>>& _out,
|
||||
int32_t _recurtionMax,
|
||||
float _threshold,
|
||||
mat2x3& _basicTrans,
|
||||
int32_t _level=1) override;
|
||||
private:
|
||||
esvg::render::Path createPath();
|
||||
};
|
||||
}
|
||||
|
176
src/org/atriasoft/esvg/LinearGradient.cpp
Normal file
176
src/org/atriasoft/esvg/LinearGradient.cpp
Normal file
@ -0,0 +1,176 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <esvg/debug.hpp>
|
||||
#include <esvg/LinearGradient.hpp>
|
||||
#include <esvg/RadialGradient.hpp>
|
||||
#include <esvg/render/Path.hpp>
|
||||
#include <esvg/render/Weight.hpp>
|
||||
#include <esvg/esvg.hpp>
|
||||
|
||||
esvg::LinearGradient::LinearGradient(PaintState _parentPaintState) :
|
||||
esvg::Base(_parentPaintState),
|
||||
m_pos1(vec2(50,50), esvg::distance_pourcent),
|
||||
m_pos2(vec2(50,50), esvg::distance_pourcent),
|
||||
m_unit(gradientUnits_objectBoundingBox),
|
||||
m_spread(spreadMethod_pad) {
|
||||
|
||||
}
|
||||
|
||||
esvg::LinearGradient::~LinearGradient() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool esvg::LinearGradient::parseXML(const exml::Element& _element, mat2x3& _parentTrans, vec2& _sizeMax) {
|
||||
// line must have a minimum size...
|
||||
//m_paint.strokeWidth = 1;
|
||||
if (_element.exist() == false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// ---------------- get unique ID ----------------
|
||||
m_id = _element.attributes["id"];
|
||||
|
||||
//parseTransform(_element);
|
||||
//parsePaintAttr(_element);
|
||||
|
||||
// add the property of the parrent modifications ...
|
||||
m_transformMatrix *= _parentTrans;
|
||||
|
||||
etk::String contentX = _element.attributes["x1"];
|
||||
etk::String contentY = _element.attributes["y1"];
|
||||
if ( contentX != ""
|
||||
&& contentY != "") {
|
||||
m_pos1.set(contentX, contentY);
|
||||
}
|
||||
contentX = _element.attributes["x2"];
|
||||
contentY = _element.attributes["y2"];
|
||||
if ( contentX != ""
|
||||
&& contentY != "") {
|
||||
m_pos2.set(contentX, contentY);
|
||||
}
|
||||
contentX = _element.attributes["gradientUnits"];
|
||||
if (contentX == "userSpaceOnUse") {
|
||||
m_unit = gradientUnits_userSpaceOnUse;
|
||||
} else {
|
||||
m_unit = gradientUnits_objectBoundingBox;
|
||||
if ( contentX.size() != 0
|
||||
&& contentX != "objectBoundingBox") {
|
||||
Log.error("Parsing error of 'gradientUnits' ==> not suported value: '" << contentX << "' not in : {userSpaceOnUse/objectBoundingBox} use objectBoundingBox");
|
||||
}
|
||||
}
|
||||
contentX = _element.attributes["spreadMethod"];
|
||||
if (contentX == "reflect") {
|
||||
m_spread = spreadMethod_reflect;
|
||||
} else if (contentX == "repeat") {
|
||||
m_spread = spreadMethod_repeat;
|
||||
} else {
|
||||
m_spread = spreadMethod_pad;
|
||||
if ( contentX.size() != 0
|
||||
&& contentX != "pad") {
|
||||
Log.error("Parsing error of 'spreadMethod' ==> not suported value: '" << contentX << "' not in : {reflect/repeate/pad} use pad");
|
||||
}
|
||||
}
|
||||
// note: xlink:href is incompatible with subNode "stop"
|
||||
m_href = _element.attributes["xlink:href"];
|
||||
if (m_href.size() != 0) {
|
||||
m_href = etk::String(m_href.begin()+1, m_href.end());
|
||||
}
|
||||
// parse all sub node :
|
||||
for(const auto it : _element.nodes) {
|
||||
exml::Element child = it.toElement();
|
||||
if (child.exist() == false) {
|
||||
// can be a comment ...
|
||||
continue;
|
||||
}
|
||||
if (child.getValue() == "stop") {
|
||||
float offset = 100;
|
||||
etk::Color<float,4> stopColor = etk::color::none;
|
||||
etk::String content = child.attributes["offset"];
|
||||
if (content.size()!=0) {
|
||||
etk::Pair<float, enum esvg::distance> tmp = parseLength2(content);
|
||||
if (tmp.second == esvg::distance_pixel) {
|
||||
// special case ==> all time % then no type define ==> % in [0.0 .. 1.0]
|
||||
offset = tmp.first*100.0f;
|
||||
} else if (tmp.second != esvg::distance_pourcent) {
|
||||
Log.error("offset : " << content << " res=" << tmp.first << "," << tmp.second << " Not support other than pourcent %");
|
||||
} else {
|
||||
offset = tmp.first;
|
||||
}
|
||||
}
|
||||
content = child.attributes["stop-color"];
|
||||
if (content.size()!=0) {
|
||||
stopColor = parseColor(content).first;
|
||||
Log.verbose(" color : '" << content << "' == > " << stopColor);
|
||||
}
|
||||
content = child.attributes["stop-opacity"];
|
||||
if (content.size()!=0) {
|
||||
float opacity = parseLength(content);
|
||||
opacity = etk::avg(0.0f, opacity, 1.0f);
|
||||
stopColor.setA(opacity);
|
||||
Log.verbose(" opacity : '" << content << "' == > " << stopColor);
|
||||
}
|
||||
m_data.pushBack(etk::Pair<float, etk::Color<float,4>>(offset, stopColor));
|
||||
} else {
|
||||
Log.error("(l " << child.getPos() << ") node not suported : '" << child.getValue() << "' must be [stop]");
|
||||
}
|
||||
}
|
||||
if (m_data.size() != 0) {
|
||||
if (m_href != "") {
|
||||
Log.error("(l " << _element.getPos() << ") node can not have an xlink:href element with sub node named: stop ==> removing href");
|
||||
m_href = "";
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void esvg::LinearGradient::display(int32_t _spacing) {
|
||||
Log.debug(spacingDist(_spacing) << "LinearGradient " << m_pos1 << " to " << m_pos2);
|
||||
for (auto &it : m_data) {
|
||||
Log.debug(spacingDist(_spacing+1) << "STOP: offset=" << it.first << " color=" << it.second);
|
||||
}
|
||||
}
|
||||
|
||||
void esvg::LinearGradient::draw(esvg::Renderer& _myRenderer, mat2x3& _basicTrans, int32_t _level) {
|
||||
Log.verbose(spacingDist(_level) << "DRAW esvg::LinearGradient");
|
||||
}
|
||||
|
||||
const esvg::Dimension& esvg::LinearGradient::getPosition1() {
|
||||
return m_pos1;
|
||||
}
|
||||
|
||||
const esvg::Dimension& esvg::LinearGradient::getPosition2() {
|
||||
return m_pos2;
|
||||
}
|
||||
|
||||
const etk::Vector<etk::Pair<float, etk::Color<float,4>>>& esvg::LinearGradient::getColors(esvg::Document* _document) {
|
||||
if (m_href == "") {
|
||||
return m_data;
|
||||
}
|
||||
if (_document == null) {
|
||||
Log.error("Get null input for document");
|
||||
return m_data;
|
||||
}
|
||||
ememory::SharedPtr<esvg::Base> base = _document->getReference(m_href);
|
||||
if (base == null) {
|
||||
Log.error("Can not get base : '" << m_href << "'");
|
||||
return m_data;
|
||||
}
|
||||
ememory::SharedPtr<esvg::RadialGradient> gradientR = ememory::dynamicPointerCast<esvg::RadialGradient>(base);
|
||||
if (gradientR == null) {
|
||||
ememory::SharedPtr<esvg::LinearGradient> gradientL = ememory::dynamicPointerCast<esvg::LinearGradient>(base);
|
||||
if (gradientL == null) {
|
||||
Log.error("Can not cast in a linear/radial gradient: '" << m_href << "' ==> wrong type");
|
||||
return m_data;
|
||||
}
|
||||
return gradientL->getColors(_document);
|
||||
}
|
||||
return gradientR->getColors(_document);
|
||||
}
|
||||
|
||||
|
||||
|
36
src/org/atriasoft/esvg/LinearGradient.java
Normal file
36
src/org/atriasoft/esvg/LinearGradient.java
Normal file
@ -0,0 +1,36 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <esvg/Base.hpp>
|
||||
#include <esvg/gradientUnits.hpp>
|
||||
#include <esvg/spreadMethod.hpp>
|
||||
|
||||
namespace esvg {
|
||||
class Document;
|
||||
class LinearGradient : public esvg::Base {
|
||||
private:
|
||||
esvg::Dimension m_pos1; //!< gradient position x1 y1
|
||||
esvg::Dimension m_pos2; //!< gradient position x2 y2
|
||||
public:
|
||||
enum gradientUnits m_unit;
|
||||
enum spreadMethod m_spread;
|
||||
private:
|
||||
etk::String m_href; //!< in case of using a single gradient in multiple gradient, the gradient is store in an other element...
|
||||
etk::Vector<etk::Pair<float, etk::Color<float,4>>> m_data; //!< incompatible with href
|
||||
public:
|
||||
LinearGradient(PaintState _parentPaintState);
|
||||
~LinearGradient();
|
||||
virtual bool parseXML(const exml::Element& _element, mat2x3& _parentTrans, vec2& _sizeMax);
|
||||
virtual void display(int32_t _spacing);
|
||||
virtual void draw(esvg::Renderer& _myRenderer, mat2x3& _basicTrans, int32_t _level);
|
||||
public:
|
||||
const esvg::Dimension& getPosition1();
|
||||
const esvg::Dimension& getPosition2();
|
||||
const etk::Vector<etk::Pair<float, etk::Color<float,4>>>& getColors(esvg::Document* _document);
|
||||
};
|
||||
}
|
||||
|
349
src/org/atriasoft/esvg/Path.cpp
Normal file
349
src/org/atriasoft/esvg/Path.cpp
Normal file
@ -0,0 +1,349 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <esvg/debug.hpp>
|
||||
#include <esvg/Path.hpp>
|
||||
#include <esvg/render/PointList.hpp>
|
||||
#include <esvg/render/Weight.hpp>
|
||||
|
||||
esvg::Path::Path(PaintState _parentPaintState) : esvg::Base(_parentPaintState) {
|
||||
|
||||
}
|
||||
|
||||
esvg::Path::~Path() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
// return the next char position ... (after 'X' or NULL)
|
||||
const char * extractCmd(const char* _input, char& _cmd, etk::Vector<float>& _outputList) {
|
||||
if (*_input == '\0') {
|
||||
return null;
|
||||
}
|
||||
_outputList.clear();
|
||||
_cmd = '\0';
|
||||
const char * outputPointer = null;
|
||||
if (!( ( _input[0] <= 'Z'
|
||||
&& _input[0] >= 'A')
|
||||
|| ( _input[0] <= 'z'
|
||||
&& _input[0] >= 'a') ) ) {
|
||||
Log.error("Error in the SVG Path : \"" << _input << "\"");
|
||||
return null;
|
||||
}
|
||||
_cmd = _input[0];
|
||||
Log.verbose("Find command : " << _cmd);
|
||||
if (_input[1] == '\0') {
|
||||
return &_input[1];
|
||||
}
|
||||
int32_t iii=1;
|
||||
// extract every float separated by a ' ' or a ','
|
||||
float element;
|
||||
char spacer[10];
|
||||
int32_t nbElementRead;
|
||||
while( sscanf(&_input[iii], "%1[, ]%f%n", spacer, &element, &nbElementRead) == 2
|
||||
|| sscanf(&_input[iii], "%f%n", &element, &nbElementRead) == 1) {
|
||||
Log.verbose("Find element : " << element);
|
||||
_outputList.pushBack(element);
|
||||
iii += nbElementRead;
|
||||
}
|
||||
outputPointer = &_input[iii];
|
||||
while(*outputPointer!= '\0' && *outputPointer == ' ') {
|
||||
outputPointer++;
|
||||
}
|
||||
//outputPointer++;
|
||||
return outputPointer;
|
||||
}
|
||||
etk::String cleanBadSpaces(const etk::String& _input) {
|
||||
etk::String out;
|
||||
bool haveSpace = false;
|
||||
for (auto &it : _input) {
|
||||
if ( it == ' '
|
||||
|| it == '\t'
|
||||
|| it == '\t'
|
||||
|| it == '\r') {
|
||||
haveSpace = true;
|
||||
} else {
|
||||
if (haveSpace == true) {
|
||||
haveSpace = false;
|
||||
out += ' ';
|
||||
}
|
||||
out += it;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
bool esvg::Path::parseXML(const exml::Element& _element, mat2x3& _parentTrans, vec2& _sizeMax) {
|
||||
if (_element.exist() == false) {
|
||||
return false;
|
||||
}
|
||||
parseTransform(_element);
|
||||
parsePaintAttr(_element);
|
||||
|
||||
// add the property of the parrent modifications ...
|
||||
m_transformMatrix *= _parentTrans;
|
||||
|
||||
|
||||
etk::String elementXML1 = _element.attributes["d"];
|
||||
if (elementXML1.size() == 0) {
|
||||
Log.warning("(l "<<_element.getPos()<<") path: missing 'd' attribute or empty");
|
||||
return false;
|
||||
}
|
||||
Log.verbose("Parse Path : \"" << elementXML1 << "\"");
|
||||
|
||||
char command;
|
||||
etk::Vector<float> listDot;
|
||||
elementXML1 = cleanBadSpaces(elementXML1);
|
||||
const char* elementXML = elementXML1.c_str();
|
||||
|
||||
for( const char *sss=extractCmd(elementXML, command, listDot);
|
||||
sss != null;
|
||||
sss=extractCmd(sss, command, listDot) ) {
|
||||
bool relative = false;
|
||||
switch(command) {
|
||||
case 'm': // Move to (relative)
|
||||
relative = true;
|
||||
case 'M': // Move to (absolute)
|
||||
// 2 Elements ...
|
||||
if(listDot.size()%2 != 0) {
|
||||
Log.warning("the PATH command "<< command << " has not the good number of element = " << listDot.size() );
|
||||
break;
|
||||
}
|
||||
if (listDot.size() >= 2) {
|
||||
m_listElement.moveTo(relative,
|
||||
vec2(listDot[0], listDot[1]));
|
||||
}
|
||||
for (size_t iii=2; iii<listDot.size(); iii+=2) {
|
||||
m_listElement.lineTo(relative,
|
||||
vec2(listDot[iii], listDot[iii+1]));
|
||||
}
|
||||
break;
|
||||
case 'l': // Line to (relative)
|
||||
relative = true;
|
||||
case 'L': // Line to (absolute)
|
||||
// 2 Elements ...
|
||||
if(listDot.size()%2 != 0) {
|
||||
Log.warning("the PATH command "<< command << " has not the good number of element = " << listDot.size() );
|
||||
break;
|
||||
}
|
||||
for (size_t iii=0; iii<listDot.size(); iii+=2) {
|
||||
m_listElement.lineTo(relative,
|
||||
vec2(listDot[iii], listDot[iii+1]));
|
||||
}
|
||||
break;
|
||||
|
||||
case 'v': // Vertical Line to (relative)
|
||||
relative = true;
|
||||
case 'V': // Vertical Line to (absolute)
|
||||
// 1 Element ...
|
||||
if(listDot.size() == 0) {
|
||||
Log.warning("the PATH command "<< command << " has not the good number of element = " << listDot.size() );
|
||||
break;
|
||||
}
|
||||
for (size_t iii=0; iii<listDot.size(); iii+=1) {
|
||||
m_listElement.lineToV(relative,
|
||||
listDot[iii]);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'h': // Horizantal Line to (relative)
|
||||
relative = true;
|
||||
case 'H': // Horizantal Line to (absolute)
|
||||
// 1 Element ...
|
||||
if (listDot.size() == 0) {
|
||||
Log.warning("the PATH command "<< command << " has not the good number of element = " << listDot.size() );
|
||||
break;
|
||||
}
|
||||
for (size_t iii=0; iii<listDot.size(); iii+=1) {
|
||||
m_listElement.lineToH(relative,
|
||||
listDot[iii]);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'q': // Quadratic Bezier curve (relative)
|
||||
relative = true;
|
||||
case 'Q': // Quadratic Bezier curve (absolute)
|
||||
// 4 Elements ...
|
||||
if (listDot.size()%4 != 0) {
|
||||
Log.warning("the PATH command "<< command << " has not the good number of element = " << listDot.size() );
|
||||
break;
|
||||
}
|
||||
for (size_t iii=0; iii<listDot.size(); iii+=4) {
|
||||
m_listElement.bezierCurveTo(relative,
|
||||
vec2(listDot[iii],listDot[iii+1]),
|
||||
vec2(listDot[iii+2],listDot[iii+3]));
|
||||
}
|
||||
break;
|
||||
|
||||
case 't': // smooth quadratic Bezier curve to (relative)
|
||||
relative = true;
|
||||
case 'T': // smooth quadratic Bezier curve to (absolute)
|
||||
// 2 Elements ...
|
||||
if (listDot.size()%2 != 0) {
|
||||
Log.warning("the PATH command "<< command << " has not the good number of element = " << listDot.size() );
|
||||
break;
|
||||
}
|
||||
for (size_t iii=0; iii<listDot.size(); iii+=2) {
|
||||
m_listElement.bezierSmoothCurveTo(relative,
|
||||
vec2(listDot[iii],listDot[iii+1]));
|
||||
}
|
||||
break;
|
||||
|
||||
case 'c': // curve to (relative)
|
||||
relative = true;
|
||||
case 'C': // curve to (absolute)
|
||||
// 6 Elements ...
|
||||
if (listDot.size()%6 != 0) {
|
||||
Log.warning("the PATH command "<< command << " has not the good number of element = " << listDot.size() );
|
||||
break;
|
||||
}
|
||||
for (size_t iii=0; iii<listDot.size(); iii+=6) {
|
||||
m_listElement.curveTo(relative,
|
||||
vec2(listDot[iii],listDot[iii+1]),
|
||||
vec2(listDot[iii+2],listDot[iii+3]),
|
||||
vec2(listDot[iii+4],listDot[iii+5]));
|
||||
}
|
||||
break;
|
||||
|
||||
case 's': // smooth curve to (relative)
|
||||
relative = true;
|
||||
case 'S': // smooth curve to (absolute)
|
||||
// 4 Elements ...
|
||||
if (listDot.size()%4 != 0) {
|
||||
Log.warning("the PATH command "<< command << " has not the good number of element = " << listDot.size() );
|
||||
break;
|
||||
}
|
||||
for (size_t iii=0; iii<listDot.size(); iii+=4) {
|
||||
m_listElement.smoothCurveTo(relative,
|
||||
vec2(listDot[iii],listDot[iii+1]),
|
||||
vec2(listDot[iii+2],listDot[iii+3]));
|
||||
}
|
||||
break;
|
||||
|
||||
case 'a': // elliptical Arc (relative)
|
||||
relative = true;
|
||||
case 'A': // elliptical Arc (absolute)
|
||||
// 7 Elements ...
|
||||
if (listDot.size()%7 != 0) {
|
||||
Log.warning("the PATH command "<< command << " has not the good number of element = " << listDot.size() );
|
||||
break;
|
||||
}
|
||||
for (size_t iii=0; iii<listDot.size(); iii+=7) {
|
||||
bool largeArcFlag = true;
|
||||
bool sweepFlag = true;
|
||||
if (listDot[iii+3] == 0.0f) {
|
||||
largeArcFlag = false;
|
||||
}
|
||||
if (listDot[iii+4] == 0.0f) {
|
||||
sweepFlag = false;
|
||||
}
|
||||
m_listElement.ellipticTo(relative,
|
||||
vec2(listDot[iii], listDot[iii+1]),
|
||||
listDot[iii+2],
|
||||
largeArcFlag,
|
||||
sweepFlag,
|
||||
vec2(listDot[iii+5], listDot[iii+6]) );
|
||||
}
|
||||
break;
|
||||
case 'z': // closepath (relative)
|
||||
relative = true;
|
||||
case 'Z': // closepath (absolute)
|
||||
// 0 Element ...
|
||||
if (listDot.size() != 0) {
|
||||
Log.warning("the PATH command "<< command << " has not the good number of element = " << listDot.size() );
|
||||
break;
|
||||
}
|
||||
m_listElement.close(relative);
|
||||
break;
|
||||
default:
|
||||
ESVG_ERROR ("Unknow error : \"" << command << "\"");
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void esvg::Path::display(int32_t _spacing) {
|
||||
m_listElement.display(_spacing);
|
||||
}
|
||||
|
||||
void esvg::Path::draw(esvg::Renderer& _myRenderer, mat2x3& _basicTrans, int32_t _level) {
|
||||
Log.verbose(spacingDist(_level) << "DRAW esvg::Path");
|
||||
|
||||
mat2x3 mtx = m_transformMatrix;
|
||||
mtx *= _basicTrans;
|
||||
|
||||
esvg::render::PointList listPoints;
|
||||
listPoints = m_listElement.generateListPoints(_level,
|
||||
_myRenderer.getInterpolationRecurtionMax(),
|
||||
_myRenderer.getInterpolationThreshold());
|
||||
//listPoints.applyMatrix(mtx);
|
||||
esvg::render::SegmentList listSegmentFill;
|
||||
esvg::render::SegmentList listSegmentStroke;
|
||||
esvg::render::Weight tmpFill;
|
||||
esvg::render::Weight tmpStroke;
|
||||
ememory::SharedPtr<esvg::render::DynamicColor> colorFill = esvg::render::createColor(m_paint.fill, mtx);
|
||||
ememory::SharedPtr<esvg::render::DynamicColor> colorStroke;
|
||||
if (m_paint.strokeWidth > 0.0f) {
|
||||
colorStroke = esvg::render::createColor(m_paint.stroke, mtx);
|
||||
}
|
||||
// Check if we need to display background
|
||||
if (colorFill != null) {
|
||||
listSegmentFill.createSegmentList(listPoints);
|
||||
colorFill->setViewPort(listSegmentFill.getViewPort());
|
||||
listSegmentFill.applyMatrix(mtx);
|
||||
// now, traverse the scanlines and find the intersections on each scanline, use non-zero rule
|
||||
tmpFill.generate(_myRenderer.getSize(), _myRenderer.getNumberSubScanLine(), listSegmentFill);
|
||||
}
|
||||
// check if we need to display stroke:
|
||||
if (colorStroke != null) {
|
||||
listSegmentStroke.createSegmentListStroke(listPoints,
|
||||
m_paint.strokeWidth,
|
||||
m_paint.lineCap,
|
||||
m_paint.lineJoin,
|
||||
m_paint.miterLimit);
|
||||
colorStroke->setViewPort(listSegmentStroke.getViewPort());
|
||||
listSegmentStroke.applyMatrix(mtx);
|
||||
// now, traverse the scanlines and find the intersections on each scanline, use non-zero rule
|
||||
tmpStroke.generate(_myRenderer.getSize(), _myRenderer.getNumberSubScanLine(), listSegmentStroke);
|
||||
}
|
||||
// add on images:
|
||||
_myRenderer.print(tmpFill,
|
||||
colorFill,
|
||||
tmpStroke,
|
||||
colorStroke,
|
||||
m_paint.opacity);
|
||||
#ifdef DEBUG
|
||||
_myRenderer.addDebugSegment(listSegmentFill);
|
||||
_myRenderer.addDebugSegment(listSegmentStroke);
|
||||
m_listElement.m_debugInformation.applyMatrix(mtx);
|
||||
_myRenderer.addDebugSegment(m_listElement.m_debugInformation);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void esvg::Path::drawShapePoints(etk::Vector<etk::Vector<vec2>>& _out,
|
||||
int32_t _recurtionMax,
|
||||
float _threshold,
|
||||
mat2x3& _basicTrans,
|
||||
int32_t _level) {
|
||||
Log.verbose(spacingDist(_level) << "DRAW Shape esvg::Path");
|
||||
|
||||
mat2x3 mtx = m_transformMatrix;
|
||||
mtx *= _basicTrans;
|
||||
|
||||
esvg::render::PointList listPoints;
|
||||
listPoints = m_listElement.generateListPoints(_level, _recurtionMax, _threshold);
|
||||
listPoints.applyMatrix(mtx);
|
||||
for (auto &it : listPoints.m_data) {
|
||||
etk::Vector<vec2> listPoint;
|
||||
for (auto &itDot : it) {
|
||||
listPoint.pushBack(itDot.m_pos);
|
||||
}
|
||||
_out.pushBack(listPoint);
|
||||
}
|
||||
}
|
||||
|
28
src/org/atriasoft/esvg/Path.java
Normal file
28
src/org/atriasoft/esvg/Path.java
Normal file
@ -0,0 +1,28 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <esvg/Base.hpp>
|
||||
#include <esvg/render/Path.hpp>
|
||||
|
||||
namespace esvg {
|
||||
class Path : public esvg::Base {
|
||||
public:
|
||||
esvg::render::Path m_listElement;
|
||||
public:
|
||||
Path(PaintState _parentPaintState);
|
||||
~Path();
|
||||
bool parseXML(const exml::Element& _element, mat2x3& _parentTrans, vec2& _sizeMax) override;
|
||||
void display(int32_t _spacing) override;
|
||||
void draw(esvg::Renderer& _myRenderer, mat2x3& _basicTrans, int32_t _level) override;
|
||||
void drawShapePoints(etk::Vector<etk::Vector<vec2>>& _out,
|
||||
int32_t _recurtionMax,
|
||||
float _threshold,
|
||||
mat2x3& _basicTrans,
|
||||
int32_t _level=1) override;
|
||||
};
|
||||
}
|
||||
|
153
src/org/atriasoft/esvg/Polygon.cpp
Normal file
153
src/org/atriasoft/esvg/Polygon.cpp
Normal file
@ -0,0 +1,153 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <esvg/debug.hpp>
|
||||
#include <esvg/Polygon.hpp>
|
||||
#include <esvg/render/Path.hpp>
|
||||
#include <esvg/render/Weight.hpp>
|
||||
|
||||
esvg::Polygon::Polygon(PaintState parentPaintState) : esvg::Base(parentPaintState) {
|
||||
|
||||
}
|
||||
|
||||
esvg::Polygon::~Polygon() {
|
||||
|
||||
}
|
||||
|
||||
bool esvg::Polygon::parseXML(const exml::Element& _element, mat2x3& _parentTrans, vec2& _sizeMax) {
|
||||
if (_element.exist() == false) {
|
||||
return false;
|
||||
}
|
||||
parseTransform(_element);
|
||||
parsePaintAttr(_element);
|
||||
|
||||
Log.verbose("parsed P1. trans: " << m_transformMatrix);
|
||||
|
||||
// add the property of the parrent modifications ...
|
||||
m_transformMatrix *= _parentTrans;
|
||||
|
||||
Log.verbose("parsed P2. trans: " << m_transformMatrix);
|
||||
|
||||
const etk::String sss1 = _element.attributes["points"];
|
||||
if (sss1.size() == 0) {
|
||||
Log.error("(l "/*<<_element->Pos()*/<<") polygon: missing points attribute");
|
||||
return false;
|
||||
}
|
||||
const char * sss = sss1.c_str();
|
||||
_sizeMax.setValue(0,0);
|
||||
Log.verbose("Parse polygon : \"" << sss << "\"");
|
||||
while ('\0' != sss[0]) {
|
||||
vec2 pos(0,0);
|
||||
int32_t n;
|
||||
if (sscanf(sss, "%f,%f%n", &pos.m_floats[0], &pos.m_floats[1], &n) == 2) {
|
||||
m_listPoint.pushBack(pos);
|
||||
sss += n;
|
||||
_sizeMax.setValue(etk::max(_sizeMax.x(), pos.x()),
|
||||
etk::max(_sizeMax.y(), pos.y()));
|
||||
if(sss[0] == ' ' || sss[0] == ',') {
|
||||
sss++;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void esvg::Polygon::display(int32_t _spacing) {
|
||||
Log.debug(spacingDist(_spacing) << "Polygon nbPoint=" << m_listPoint.size());
|
||||
}
|
||||
|
||||
esvg::render::Path esvg::Polygon::createPath() {
|
||||
esvg::render::Path out;
|
||||
out.moveTo(false, m_listPoint[0]);
|
||||
for(size_t iii=1; iii< m_listPoint.size(); iii++) {
|
||||
out.lineTo(false, m_listPoint[iii]);
|
||||
}
|
||||
out.close();
|
||||
return out;
|
||||
}
|
||||
|
||||
void esvg::Polygon::draw(esvg::Renderer& _myRenderer, mat2x3& _basicTrans, int32_t _level) {
|
||||
Log.verbose(spacingDist(_level) << "DRAW esvg::Polygon");
|
||||
|
||||
esvg::render::Path listElement = createPath();
|
||||
|
||||
mat2x3 mtx = m_transformMatrix;
|
||||
mtx *= _basicTrans;
|
||||
|
||||
esvg::render::PointList listPoints;
|
||||
listPoints = listElement.generateListPoints(_level,
|
||||
_myRenderer.getInterpolationRecurtionMax(),
|
||||
_myRenderer.getInterpolationThreshold());
|
||||
//listPoints.applyMatrix(mtx);
|
||||
esvg::render::SegmentList listSegmentFill;
|
||||
esvg::render::SegmentList listSegmentStroke;
|
||||
esvg::render::Weight tmpFill;
|
||||
esvg::render::Weight tmpStroke;
|
||||
ememory::SharedPtr<esvg::render::DynamicColor> colorFill = esvg::render::createColor(m_paint.fill, mtx);
|
||||
ememory::SharedPtr<esvg::render::DynamicColor> colorStroke;
|
||||
if (m_paint.strokeWidth > 0.0f) {
|
||||
colorStroke = esvg::render::createColor(m_paint.stroke, mtx);
|
||||
}
|
||||
// Check if we need to display background
|
||||
if (colorFill != null) {
|
||||
listSegmentFill.createSegmentList(listPoints);
|
||||
colorFill->setViewPort(listSegmentFill.getViewPort());
|
||||
listSegmentFill.applyMatrix(mtx);
|
||||
// now, traverse the scanlines and find the intersections on each scanline, use non-zero rule
|
||||
tmpFill.generate(_myRenderer.getSize(),
|
||||
_myRenderer.getNumberSubScanLine(),
|
||||
listSegmentFill);
|
||||
}
|
||||
// check if we need to display stroke:
|
||||
if (colorStroke != null) {
|
||||
listSegmentStroke.createSegmentListStroke(listPoints,
|
||||
m_paint.strokeWidth,
|
||||
m_paint.lineCap,
|
||||
m_paint.lineJoin,
|
||||
m_paint.miterLimit);
|
||||
colorStroke->setViewPort(listSegmentStroke.getViewPort());
|
||||
listSegmentStroke.applyMatrix(mtx);
|
||||
// now, traverse the scanlines and find the intersections on each scanline, use non-zero rule
|
||||
tmpStroke.generate(_myRenderer.getSize(),
|
||||
_myRenderer.getNumberSubScanLine(),
|
||||
listSegmentStroke);
|
||||
}
|
||||
// add on images:
|
||||
_myRenderer.print(tmpFill,
|
||||
colorFill,
|
||||
tmpStroke,
|
||||
colorStroke,
|
||||
m_paint.opacity);
|
||||
#ifdef DEBUG
|
||||
_myRenderer.addDebugSegment(listSegmentFill);
|
||||
_myRenderer.addDebugSegment(listSegmentStroke);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void esvg::Polygon::drawShapePoints(etk::Vector<etk::Vector<vec2>>& _out,
|
||||
int32_t _recurtionMax,
|
||||
float _threshold,
|
||||
mat2x3& _basicTrans,
|
||||
int32_t _level) {
|
||||
Log.verbose(spacingDist(_level) << "DRAW Shape esvg::Polygon");
|
||||
esvg::render::Path listElement = createPath();
|
||||
mat2x3 mtx = m_transformMatrix;
|
||||
mtx *= _basicTrans;
|
||||
esvg::render::PointList listPoints;
|
||||
listPoints = listElement.generateListPoints(_level, _recurtionMax, _threshold);
|
||||
listPoints.applyMatrix(mtx);
|
||||
for (auto &it : listPoints.m_data) {
|
||||
etk::Vector<vec2> listPoint;
|
||||
for (auto &itDot : it) {
|
||||
listPoint.pushBack(itDot.m_pos);
|
||||
}
|
||||
_out.pushBack(listPoint);
|
||||
}
|
||||
}
|
||||
|
37
src/org/atriasoft/esvg/Polygon.java
Normal file
37
src/org/atriasoft/esvg/Polygon.java
Normal file
@ -0,0 +1,37 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <esvg/Base.hpp>
|
||||
#include <etk/Vector.hpp>
|
||||
|
||||
namespace esvg {
|
||||
/*
|
||||
enum polygonMode {
|
||||
polygoneModeNonZero,
|
||||
polygoneModeEvenOdd
|
||||
};
|
||||
*/
|
||||
class Polygon : public esvg::Base {
|
||||
private:
|
||||
etk::Vector<vec2 > m_listPoint; //!< list of all point of the polygone
|
||||
//enum esvg::polygonMode m_diplayMode; //!< polygone specific display mode
|
||||
public:
|
||||
Polygon(PaintState parentPaintState);
|
||||
~Polygon();
|
||||
bool parseXML(const exml::Element& _element, mat2x3& _parentTrans, vec2& _sizeMax) override;
|
||||
void display(int32_t _spacing) override;
|
||||
void draw(esvg::Renderer& _myRenderer, mat2x3& _basicTrans, int32_t _level) override;
|
||||
void drawShapePoints(etk::Vector<etk::Vector<vec2>>& _out,
|
||||
int32_t _recurtionMax,
|
||||
float _threshold,
|
||||
mat2x3& _basicTrans,
|
||||
int32_t _level=1) override;
|
||||
private:
|
||||
esvg::render::Path createPath();
|
||||
};
|
||||
}
|
||||
|
149
src/org/atriasoft/esvg/Polyline.cpp
Normal file
149
src/org/atriasoft/esvg/Polyline.cpp
Normal file
@ -0,0 +1,149 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <esvg/debug.hpp>
|
||||
#include <esvg/Polyline.hpp>
|
||||
#include <esvg/render/Path.hpp>
|
||||
#include <esvg/render/Weight.hpp>
|
||||
|
||||
esvg::Polyline::Polyline(PaintState _parentPaintState) : esvg::Base(_parentPaintState) {
|
||||
|
||||
}
|
||||
|
||||
esvg::Polyline::~Polyline() {
|
||||
|
||||
}
|
||||
|
||||
bool esvg::Polyline::parseXML(const exml::Element& _element, mat2x3& _parentTrans, vec2& _sizeMax) {
|
||||
// line must have a minimum size...
|
||||
m_paint.strokeWidth = 1;
|
||||
if (_element.exist() == false) {
|
||||
return false;
|
||||
}
|
||||
parseTransform(_element);
|
||||
parsePaintAttr(_element);
|
||||
|
||||
// add the property of the parrent modifications ...
|
||||
m_transformMatrix *= _parentTrans;
|
||||
|
||||
etk::String sss1 = _element.attributes["points"];
|
||||
if (sss1.size() == 0) {
|
||||
Log.error("(l "<<_element.getPos()<<") polyline: missing points attribute");
|
||||
return false;
|
||||
}
|
||||
_sizeMax.setValue(0,0);
|
||||
Log.verbose("Parse polyline : \"" << sss1 << "\"");
|
||||
const char* sss = sss1.c_str();
|
||||
while ('\0' != sss[0]) {
|
||||
vec2 pos;
|
||||
int32_t n;
|
||||
if (sscanf(sss, "%f,%f %n", &pos.m_floats[0], &pos.m_floats[1], &n) == 2) {
|
||||
m_listPoint.pushBack(pos);
|
||||
_sizeMax.setValue(etk::max(_sizeMax.x(), pos.x()),
|
||||
etk::max(_sizeMax.y(), pos.y()));
|
||||
sss += n;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void esvg::Polyline::display(int32_t _spacing) {
|
||||
Log.debug(spacingDist(_spacing) << "Polyline nbPoint=" << m_listPoint.size());
|
||||
}
|
||||
|
||||
|
||||
esvg::render::Path esvg::Polyline::createPath() {
|
||||
esvg::render::Path out;
|
||||
out.clear();
|
||||
out.moveTo(false, m_listPoint[0]);
|
||||
for(size_t iii=1; iii< m_listPoint.size(); iii++) {
|
||||
out.lineTo(false, m_listPoint[iii]);
|
||||
}
|
||||
out.stop();
|
||||
return out;
|
||||
}
|
||||
|
||||
void esvg::Polyline::draw(esvg::Renderer& _myRenderer, mat2x3& _basicTrans, int32_t _level) {
|
||||
Log.verbose(spacingDist(_level) << "DRAW esvg::Polyline");
|
||||
|
||||
esvg::render::Path listElement = createPath();
|
||||
|
||||
mat2x3 mtx = m_transformMatrix;
|
||||
mtx *= _basicTrans;
|
||||
|
||||
esvg::render::PointList listPoints;
|
||||
listPoints = listElement.generateListPoints(_level,
|
||||
_myRenderer.getInterpolationRecurtionMax(),
|
||||
_myRenderer.getInterpolationThreshold());
|
||||
//listPoints.applyMatrix(mtx);
|
||||
esvg::render::SegmentList listSegmentFill;
|
||||
esvg::render::SegmentList listSegmentStroke;
|
||||
esvg::render::Weight tmpFill;
|
||||
esvg::render::Weight tmpStroke;
|
||||
ememory::SharedPtr<esvg::render::DynamicColor> colorFill = esvg::render::createColor(m_paint.fill, mtx);
|
||||
ememory::SharedPtr<esvg::render::DynamicColor> colorStroke;
|
||||
if (m_paint.strokeWidth > 0.0f) {
|
||||
colorStroke = esvg::render::createColor(m_paint.stroke, mtx);
|
||||
}
|
||||
// Check if we need to display background
|
||||
if (colorFill != null) {
|
||||
listSegmentFill.createSegmentList(listPoints);
|
||||
colorFill->setViewPort(listSegmentFill.getViewPort());
|
||||
listSegmentFill.applyMatrix(mtx);
|
||||
// now, traverse the scanlines and find the intersections on each scanline, use non-zero rule
|
||||
tmpFill.generate(_myRenderer.getSize(),
|
||||
_myRenderer.getNumberSubScanLine(),
|
||||
listSegmentFill);
|
||||
}
|
||||
// check if we need to display stroke:
|
||||
if (colorStroke != null) {
|
||||
listSegmentStroke.createSegmentListStroke(listPoints,
|
||||
m_paint.strokeWidth,
|
||||
m_paint.lineCap,
|
||||
m_paint.lineJoin,
|
||||
m_paint.miterLimit);
|
||||
colorStroke->setViewPort(listSegmentStroke.getViewPort());
|
||||
listSegmentStroke.applyMatrix(mtx);
|
||||
// now, traverse the scanlines and find the intersections on each scanline, use non-zero rule
|
||||
tmpStroke.generate(_myRenderer.getSize(),
|
||||
_myRenderer.getNumberSubScanLine(),
|
||||
listSegmentStroke);
|
||||
}
|
||||
// add on images:
|
||||
_myRenderer.print(tmpFill,
|
||||
colorFill,
|
||||
tmpStroke,
|
||||
colorStroke,
|
||||
m_paint.opacity);
|
||||
#ifdef DEBUG
|
||||
_myRenderer.addDebugSegment(listSegmentFill);
|
||||
_myRenderer.addDebugSegment(listSegmentStroke);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void esvg::Polyline::drawShapePoints(etk::Vector<etk::Vector<vec2>>& _out,
|
||||
int32_t _recurtionMax,
|
||||
float _threshold,
|
||||
mat2x3& _basicTrans,
|
||||
int32_t _level) {
|
||||
Log.verbose(spacingDist(_level) << "DRAW Shape esvg::Polyline");
|
||||
esvg::render::Path listElement = createPath();
|
||||
mat2x3 mtx = m_transformMatrix;
|
||||
mtx *= _basicTrans;
|
||||
esvg::render::PointList listPoints;
|
||||
listPoints = listElement.generateListPoints(_level, _recurtionMax, _threshold);
|
||||
listPoints.applyMatrix(mtx);
|
||||
for (auto &it : listPoints.m_data) {
|
||||
etk::Vector<vec2> listPoint;
|
||||
for (auto &itDot : it) {
|
||||
listPoint.pushBack(itDot.m_pos);
|
||||
}
|
||||
_out.pushBack(listPoint);
|
||||
}
|
||||
}
|
30
src/org/atriasoft/esvg/Polyline.java
Normal file
30
src/org/atriasoft/esvg/Polyline.java
Normal file
@ -0,0 +1,30 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <esvg/Base.hpp>
|
||||
#include <etk/Vector.hpp>
|
||||
|
||||
namespace esvg {
|
||||
class Polyline : public esvg::Base {
|
||||
private:
|
||||
etk::Vector<vec2 > m_listPoint; //!< list of all point of the polyline
|
||||
public:
|
||||
Polyline(PaintState _parentPaintState);
|
||||
~Polyline();
|
||||
bool parseXML(const exml::Element& _element, mat2x3& _parentTrans, vec2& _sizeMax) override;
|
||||
void display(int32_t _spacing) override;
|
||||
void draw(esvg::Renderer& _myRenderer, mat2x3& _basicTrans, int32_t _level) override;
|
||||
void drawShapePoints(etk::Vector<etk::Vector<vec2>>& _out,
|
||||
int32_t _recurtionMax,
|
||||
float _threshold,
|
||||
mat2x3& _basicTrans,
|
||||
int32_t _level=1) override;
|
||||
private:
|
||||
esvg::render::Path createPath();
|
||||
};
|
||||
}
|
||||
|
185
src/org/atriasoft/esvg/RadialGradient.cpp
Normal file
185
src/org/atriasoft/esvg/RadialGradient.cpp
Normal file
@ -0,0 +1,185 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <esvg/debug.hpp>
|
||||
#include <esvg/LinearGradient.hpp>
|
||||
#include <esvg/RadialGradient.hpp>
|
||||
#include <esvg/render/Path.hpp>
|
||||
#include <esvg/render/Weight.hpp>
|
||||
#include <esvg/esvg.hpp>
|
||||
|
||||
esvg::RadialGradient::RadialGradient(PaintState _parentPaintState) :
|
||||
esvg::Base(_parentPaintState),
|
||||
m_center(vec2(50,50), esvg::distance_pourcent),
|
||||
m_radius(50, esvg::distance_pourcent),
|
||||
m_focal(vec2(50,50), esvg::distance_pourcent),
|
||||
m_unit(gradientUnits_objectBoundingBox),
|
||||
m_spread(spreadMethod_pad) {
|
||||
|
||||
}
|
||||
|
||||
esvg::RadialGradient::~RadialGradient() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool esvg::RadialGradient::parseXML(const exml::Element& _element, mat2x3& _parentTrans, vec2& _sizeMax) {
|
||||
// line must have a minimum size...
|
||||
//m_paint.strokeWidth = 1;
|
||||
if (_element.exist() == false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// ---------------- get unique ID ----------------
|
||||
m_id = _element.attributes["id"];
|
||||
|
||||
//parseTransform(_element);
|
||||
//parsePaintAttr(_element);
|
||||
|
||||
// add the property of the parrent modifications ...
|
||||
m_transformMatrix *= _parentTrans;
|
||||
|
||||
etk::String contentX = _element.attributes["cx"];
|
||||
etk::String contentY = _element.attributes["cy"];
|
||||
if ( contentX != ""
|
||||
&& contentY != "") {
|
||||
m_center.set(contentX, contentY);
|
||||
}
|
||||
contentX = _element.attributes["r"];
|
||||
if (contentX != "") {
|
||||
m_radius.set(contentX);
|
||||
}
|
||||
contentX = _element.attributes["fx"];
|
||||
contentY = _element.attributes["fy"];
|
||||
if ( contentX != ""
|
||||
&& contentY != "") {
|
||||
m_focal.set(contentX, contentY);
|
||||
}
|
||||
contentX = _element.attributes["gradientUnits"];
|
||||
if (contentX == "userSpaceOnUse") {
|
||||
m_unit = gradientUnits_userSpaceOnUse;
|
||||
} else {
|
||||
m_unit = gradientUnits_objectBoundingBox;
|
||||
if ( contentX.size() != 0
|
||||
&& contentX != "objectBoundingBox") {
|
||||
Log.error("Parsing error of 'gradientUnits' ==> not suported value: '" << contentX << "' not in : {userSpaceOnUse/objectBoundingBox} use objectBoundingBox");
|
||||
}
|
||||
}
|
||||
contentX = _element.attributes["spreadMethod"];
|
||||
if (contentX == "reflect") {
|
||||
m_spread = spreadMethod_reflect;
|
||||
} else if (contentX == "repeat") {
|
||||
m_spread = spreadMethod_repeat;
|
||||
} else {
|
||||
m_spread = spreadMethod_pad;
|
||||
if ( contentX.size() != 0
|
||||
&& contentX != "pad") {
|
||||
Log.error("Parsing error of 'spreadMethod' ==> not suported value: '" << contentX << "' not in : {reflect/repeate/pad} use pad");
|
||||
}
|
||||
}
|
||||
// note: xlink:href is incompatible with subNode "stop"
|
||||
m_href = _element.attributes["xlink:href"];
|
||||
if (m_href.size() != 0) {
|
||||
m_href = etk::String(m_href.begin()+1, m_href.end());
|
||||
}
|
||||
// parse all sub node :
|
||||
for(auto it : _element.nodes) {
|
||||
exml::Element child = it.toElement();
|
||||
if (child.exist() == false) {
|
||||
// can be a comment ...
|
||||
continue;
|
||||
}
|
||||
if (child.getValue() == "stop") {
|
||||
float offset = 100;
|
||||
etk::Color<float,4> stopColor = etk::color::none;
|
||||
etk::String content = child.attributes["offset"];
|
||||
if (content.size()!=0) {
|
||||
etk::Pair<float, enum esvg::distance> tmp = parseLength2(content);
|
||||
if (tmp.second == esvg::distance_pixel) {
|
||||
// special case ==> all time % then no type define ==> % in [0.0 .. 1.0]
|
||||
offset = tmp.first*100.0f;
|
||||
} else if (tmp.second != esvg::distance_pourcent) {
|
||||
Log.error("offset : " << content << " res=" << tmp.first << "," << tmp.second << " Not support other than pourcent %");
|
||||
} else {
|
||||
offset = tmp.first;
|
||||
}
|
||||
}
|
||||
content = child.attributes["stop-color"];
|
||||
if (content.size()!=0) {
|
||||
stopColor = parseColor(content).first;
|
||||
Log.verbose(" color : \"" << content << "\" == > " << stopColor);
|
||||
}
|
||||
content = child.attributes["stop-opacity"];
|
||||
if (content.size()!=0) {
|
||||
float opacity = parseLength(content);
|
||||
opacity = etk::avg(0.0f, opacity, 1.0f);
|
||||
stopColor.setA(opacity);
|
||||
Log.verbose(" opacity : '" << content << "' == > " << stopColor);
|
||||
}
|
||||
m_data.pushBack(etk::Pair<float, etk::Color<float,4>>(offset, stopColor));
|
||||
} else {
|
||||
Log.error("(l " << child.getPos() << ") node not suported : '" << child.getValue() << "' must be [stop]");
|
||||
}
|
||||
}
|
||||
if (m_data.size() != 0) {
|
||||
if (m_href != "") {
|
||||
Log.error("(l " << _element.getPos() << ") node can not have an xlink:href element with sub node named: stop ==> removing href");
|
||||
m_href = "";
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void esvg::RadialGradient::display(int32_t _spacing) {
|
||||
Log.debug(spacingDist(_spacing) << "RadialGradient center=" << m_center << " focal=" << m_focal << " radius=" << m_radius);
|
||||
for (auto &it : m_data) {
|
||||
Log.debug(spacingDist(_spacing+1) << "STOP: offset=" << it.first << " color=" << it.second);
|
||||
}
|
||||
}
|
||||
|
||||
void esvg::RadialGradient::draw(esvg::Renderer& _myRenderer, mat2x3& _basicTrans, int32_t _level) {
|
||||
Log.verbose(spacingDist(_level) << "DRAW esvg::RadialGradient");
|
||||
}
|
||||
|
||||
const esvg::Dimension& esvg::RadialGradient::getCenter() {
|
||||
return m_center;
|
||||
}
|
||||
|
||||
const esvg::Dimension& esvg::RadialGradient::getFocal() {
|
||||
return m_focal;
|
||||
}
|
||||
|
||||
const esvg::Dimension1D& esvg::RadialGradient::getRadius() {
|
||||
return m_radius;
|
||||
}
|
||||
|
||||
const etk::Vector<etk::Pair<float, etk::Color<float,4>>>& esvg::RadialGradient::getColors(esvg::Document* _document) {
|
||||
if (m_href == "") {
|
||||
return m_data;
|
||||
}
|
||||
if (_document == null) {
|
||||
Log.error("Get null input for document");
|
||||
return m_data;
|
||||
}
|
||||
ememory::SharedPtr<esvg::Base> base = _document->getReference(m_href);
|
||||
if (base == null) {
|
||||
Log.error("Can not get base : '" << m_href << "'");
|
||||
return m_data;
|
||||
}
|
||||
ememory::SharedPtr<esvg::RadialGradient> gradientR = ememory::dynamicPointerCast<esvg::RadialGradient>(base);
|
||||
if (gradientR == null) {
|
||||
ememory::SharedPtr<esvg::LinearGradient> gradientL = ememory::dynamicPointerCast<esvg::LinearGradient>(base);
|
||||
if (gradientL == null) {
|
||||
Log.error("Can not cast in a linear/radial gradient: '" << m_href << "' ==> wrong type");
|
||||
return m_data;
|
||||
}
|
||||
return gradientL->getColors(_document);
|
||||
}
|
||||
return gradientR->getColors(_document);
|
||||
}
|
||||
|
||||
|
||||
|
38
src/org/atriasoft/esvg/RadialGradient.java
Normal file
38
src/org/atriasoft/esvg/RadialGradient.java
Normal file
@ -0,0 +1,38 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <esvg/Base.hpp>
|
||||
#include <esvg/gradientUnits.hpp>
|
||||
#include <esvg/spreadMethod.hpp>
|
||||
|
||||
namespace esvg {
|
||||
class Document;
|
||||
class RadialGradient : public esvg::Base {
|
||||
private:
|
||||
esvg::Dimension m_center; //!< gradient position cx cy
|
||||
esvg::Dimension1D m_radius; //!< Radius of the gradient
|
||||
esvg::Dimension m_focal; //!< gradient Focal fx fy
|
||||
public:
|
||||
enum gradientUnits m_unit;
|
||||
enum spreadMethod m_spread;
|
||||
private:
|
||||
etk::String m_href; //!< in case of using a single gradient in multiple gradient, the gradient is store in an other element...
|
||||
etk::Vector<etk::Pair<float, etk::Color<float,4>>> m_data; //!< incompatible with href
|
||||
public:
|
||||
RadialGradient(PaintState _parentPaintState);
|
||||
~RadialGradient();
|
||||
virtual bool parseXML(const exml::Element& _element, mat2x3& _parentTrans, vec2& _sizeMax);
|
||||
virtual void display(int32_t _spacing);
|
||||
virtual void draw(esvg::Renderer& _myRenderer, mat2x3& _basicTrans, int32_t _level);
|
||||
public:
|
||||
const esvg::Dimension& getCenter();
|
||||
const esvg::Dimension& getFocal();
|
||||
const esvg::Dimension1D& getRadius();
|
||||
const etk::Vector<etk::Pair<float, etk::Color<float,4>>>& getColors(esvg::Document* _document);
|
||||
};
|
||||
}
|
||||
|
166
src/org/atriasoft/esvg/Rectangle.cpp
Normal file
166
src/org/atriasoft/esvg/Rectangle.cpp
Normal file
@ -0,0 +1,166 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <esvg/debug.hpp>
|
||||
#include <esvg/Rectangle.hpp>
|
||||
#include <esvg/render/Path.hpp>
|
||||
#include <esvg/render/Weight.hpp>
|
||||
|
||||
esvg::Rectangle::Rectangle(PaintState _parentPaintState) : esvg::Base(_parentPaintState) {
|
||||
m_position.setValue(0,0);
|
||||
m_size.setValue(0,0);
|
||||
m_roundedCorner.setValue(0,0);
|
||||
}
|
||||
|
||||
esvg::Rectangle::~Rectangle() {
|
||||
|
||||
}
|
||||
|
||||
bool esvg::Rectangle::parseXML(const exml::Element& _element, mat2x3& _parentTrans, vec2& _sizeMax) {
|
||||
if (_element.exist() == false) {
|
||||
return false;
|
||||
}
|
||||
m_position.setValue(0.0f, 0.0f);
|
||||
m_size.setValue(0.0f, 0.0f);
|
||||
m_roundedCorner.setValue(0.0f, 0.0f);
|
||||
|
||||
parseTransform(_element);
|
||||
parsePaintAttr(_element);
|
||||
|
||||
// add the property of the parrent modifications ...
|
||||
m_transformMatrix *= _parentTrans;
|
||||
|
||||
parsePosition(_element, m_position, m_size);
|
||||
|
||||
etk::String content = _element.attributes["rx"];
|
||||
if (content.size()!=0) {
|
||||
m_roundedCorner.setX(parseLength(content));
|
||||
}
|
||||
content = _element.attributes["ry"];
|
||||
if (content.size()!=0) {
|
||||
m_roundedCorner.setY(parseLength(content));
|
||||
}
|
||||
_sizeMax.setValue(m_position.x() + m_size.x() + m_paint.strokeWidth,
|
||||
m_position.y() + m_size.y() + m_paint.strokeWidth);
|
||||
return true;
|
||||
}
|
||||
|
||||
void esvg::Rectangle::display(int32_t _spacing) {
|
||||
Log.debug(spacingDist(_spacing) << "Rectangle : pos=" << m_position << " size=" << m_size << " corner=" << m_roundedCorner);
|
||||
}
|
||||
|
||||
esvg::render::Path esvg::Rectangle::createPath() {
|
||||
esvg::render::Path out;
|
||||
out.clear();
|
||||
if ( m_roundedCorner.x() == 0.0f
|
||||
|| m_roundedCorner.y() == 0.0f) {
|
||||
out.moveTo(false, m_position);
|
||||
out.lineToH(true, m_size.x());
|
||||
out.lineToV(true, m_size.y());
|
||||
out.lineToH(true, -m_size.x());
|
||||
} else {
|
||||
// Rounded rectangle
|
||||
out.moveTo(false, m_position + vec2(m_roundedCorner.x(), 0.0f));
|
||||
out.lineToH(true, m_size.x()-m_roundedCorner.x()*2.0f);
|
||||
out.curveTo(true, vec2(m_roundedCorner.x()*esvg::kappa90, 0.0f),
|
||||
vec2(m_roundedCorner.x(), m_roundedCorner.y() * (1.0f - esvg::kappa90)),
|
||||
vec2(m_roundedCorner.x(), m_roundedCorner.y()) );
|
||||
out.lineToV(true, m_size.y()-m_roundedCorner.y()*2.0f);
|
||||
out.curveTo(true, vec2(0.0f, m_roundedCorner.y() * esvg::kappa90),
|
||||
vec2(-m_roundedCorner.x()* (1.0f - esvg::kappa90), m_roundedCorner.y()),
|
||||
vec2(-m_roundedCorner.x(), m_roundedCorner.y()) );
|
||||
out.lineToH(true, -(m_size.x()-m_roundedCorner.x()*2.0f));
|
||||
out.curveTo(true, vec2(-m_roundedCorner.x()*esvg::kappa90, 0.0f),
|
||||
vec2(-m_roundedCorner.x(), -m_roundedCorner.y() * (1.0f - esvg::kappa90)),
|
||||
vec2(-m_roundedCorner.x(), -m_roundedCorner.y()) );
|
||||
out.lineToV(true, -(m_size.y()-m_roundedCorner.y()*2.0f));
|
||||
out.curveTo(true, vec2(0.0f, -m_roundedCorner.y() * esvg::kappa90),
|
||||
vec2(m_roundedCorner.x()* (1.0f - esvg::kappa90), -m_roundedCorner.y()),
|
||||
vec2(m_roundedCorner.x(), -m_roundedCorner.y()) );
|
||||
}
|
||||
out.close();
|
||||
return out;
|
||||
}
|
||||
|
||||
void esvg::Rectangle::draw(esvg::Renderer& _myRenderer, mat2x3& _basicTrans, int32_t _level) {
|
||||
Log.verbose(spacingDist(_level) << "DRAW esvg::Rectangle: fill=" << m_paint.fill.first << "/" << m_paint.fill.second
|
||||
<< " stroke=" << m_paint.stroke.first << "/" << m_paint.stroke.second);
|
||||
esvg::render::Path listElement = createPath();
|
||||
|
||||
mat2x3 mtx = m_transformMatrix;
|
||||
mtx *= _basicTrans;
|
||||
|
||||
esvg::render::PointList listPoints;
|
||||
listPoints = listElement.generateListPoints(_level,
|
||||
_myRenderer.getInterpolationRecurtionMax(),
|
||||
_myRenderer.getInterpolationThreshold());
|
||||
//listPoints.applyMatrix(mtx);
|
||||
esvg::render::SegmentList listSegmentFill;
|
||||
esvg::render::SegmentList listSegmentStroke;
|
||||
esvg::render::Weight tmpFill;
|
||||
esvg::render::Weight tmpStroke;
|
||||
ememory::SharedPtr<esvg::render::DynamicColor> colorFill = esvg::render::createColor(m_paint.fill, mtx);
|
||||
ememory::SharedPtr<esvg::render::DynamicColor> colorStroke;
|
||||
if (m_paint.strokeWidth > 0.0f) {
|
||||
colorStroke = esvg::render::createColor(m_paint.stroke, mtx);
|
||||
}
|
||||
// Check if we need to display background
|
||||
if (colorFill != null) {
|
||||
listSegmentFill.createSegmentList(listPoints);
|
||||
colorFill->setViewPort(listSegmentFill.getViewPort());
|
||||
listSegmentFill.applyMatrix(mtx);
|
||||
// now, traverse the scanlines and find the intersections on each scanline, use non-zero rule
|
||||
tmpFill.generate(_myRenderer.getSize(),
|
||||
_myRenderer.getNumberSubScanLine(),
|
||||
listSegmentFill);
|
||||
}
|
||||
// check if we need to display stroke:
|
||||
if (colorStroke != null) {
|
||||
listSegmentStroke.createSegmentListStroke(listPoints,
|
||||
m_paint.strokeWidth,
|
||||
m_paint.lineCap,
|
||||
m_paint.lineJoin,
|
||||
m_paint.miterLimit);
|
||||
colorStroke->setViewPort(listSegmentStroke.getViewPort());
|
||||
listSegmentStroke.applyMatrix(mtx);
|
||||
// now, traverse the scanlines and find the intersections on each scanline, use non-zero rule
|
||||
tmpStroke.generate(_myRenderer.getSize(),
|
||||
_myRenderer.getNumberSubScanLine(),
|
||||
listSegmentStroke);
|
||||
}
|
||||
// add on images:
|
||||
_myRenderer.print(tmpFill,
|
||||
colorFill,
|
||||
tmpStroke,
|
||||
colorStroke,
|
||||
m_paint.opacity);
|
||||
#ifdef DEBUG
|
||||
_myRenderer.addDebugSegment(listSegmentFill);
|
||||
_myRenderer.addDebugSegment(listSegmentStroke);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void esvg::Rectangle::drawShapePoints(etk::Vector<etk::Vector<vec2>>& _out,
|
||||
int32_t _recurtionMax,
|
||||
float _threshold,
|
||||
mat2x3& _basicTrans,
|
||||
int32_t _level) {
|
||||
Log.verbose(spacingDist(_level) << "DRAW Shape esvg::Rectangle");
|
||||
esvg::render::Path listElement = createPath();
|
||||
mat2x3 mtx = m_transformMatrix;
|
||||
mtx *= _basicTrans;
|
||||
esvg::render::PointList listPoints;
|
||||
listPoints = listElement.generateListPoints(_level, _recurtionMax, _threshold);
|
||||
listPoints.applyMatrix(mtx);
|
||||
for (auto &it : listPoints.m_data) {
|
||||
etk::Vector<vec2> listPoint;
|
||||
for (auto &itDot : it) {
|
||||
listPoint.pushBack(itDot.m_pos);
|
||||
}
|
||||
_out.pushBack(listPoint);
|
||||
}
|
||||
}
|
31
src/org/atriasoft/esvg/Rectangle.java
Normal file
31
src/org/atriasoft/esvg/Rectangle.java
Normal file
@ -0,0 +1,31 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <esvg/Base.hpp>
|
||||
|
||||
namespace esvg {
|
||||
class Rectangle : public esvg::Base {
|
||||
private:
|
||||
vec2 m_position; //!< position of the rectangle
|
||||
vec2 m_size; //!< size of the rectangle
|
||||
vec2 m_roundedCorner; //!< property of the rounded corner
|
||||
public:
|
||||
Rectangle(PaintState _parentPaintState);
|
||||
~Rectangle();
|
||||
bool parseXML(const exml::Element& _element, mat2x3& _parentTrans, vec2& _sizeMax) override;
|
||||
void display(int32_t _spacing) override;
|
||||
void draw(esvg::Renderer& _myRenderer, mat2x3& _basicTrans, int32_t _level) override;
|
||||
void drawShapePoints(etk::Vector<etk::Vector<vec2>>& _out,
|
||||
int32_t _recurtionMax,
|
||||
float _threshold,
|
||||
mat2x3& _basicTrans,
|
||||
int32_t _level=1) override;
|
||||
private:
|
||||
esvg::render::Path createPath();
|
||||
};
|
||||
}
|
||||
|
427
src/org/atriasoft/esvg/Renderer.cpp
Normal file
427
src/org/atriasoft/esvg/Renderer.cpp
Normal file
@ -0,0 +1,427 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <esvg/debug.hpp>
|
||||
#include <esvg/Renderer.hpp>
|
||||
#include <etk/uri/Uri.hpp>
|
||||
#include <etk/uri/provider/provider.hpp>
|
||||
|
||||
esvg::Renderer::Renderer(const ivec2& _size, esvg::Document* _document, bool _visualDebug) :
|
||||
#ifdef DEBUG
|
||||
m_visualDebug(_visualDebug),
|
||||
m_factor(1),
|
||||
#endif
|
||||
m_interpolationRecurtionMax(10),
|
||||
m_interpolationThreshold(0.25f),
|
||||
m_nbSubScanLine(8),
|
||||
m_document(_document) {
|
||||
#ifdef DEBUG
|
||||
if (m_visualDebug == true) {
|
||||
m_factor = 20;
|
||||
}
|
||||
#endif
|
||||
setSize(_size);
|
||||
}
|
||||
|
||||
esvg::Renderer::~Renderer() {
|
||||
m_buffer.clear();
|
||||
m_size = ivec2(0,0);
|
||||
}
|
||||
|
||||
etk::Color<float,4> esvg::Renderer::mergeColor(etk::Color<float,4> _base, etk::Color<float,4> _integration) {
|
||||
etk::Color<float,4> result;
|
||||
/*
|
||||
if (_integration.a() < _base.a()) {
|
||||
result = _integration;
|
||||
_integration = _base;
|
||||
_base = result;
|
||||
}
|
||||
*/
|
||||
result.setR(_integration.a() * _integration.r() + _base.a() * (1.0f - _integration.a()) * _base.r());
|
||||
result.setG(_integration.a() * _integration.g() + _base.a() * (1.0f - _integration.a()) * _base.g());
|
||||
result.setB(_integration.a() * _integration.b() + _base.a() * (1.0f - _integration.a()) * _base.b());
|
||||
result.setA(_integration.a() + _base.a() * (1.0f - _integration.a()));
|
||||
if (result.a() != 0.0f) {
|
||||
float reverse = 1.0f/result.a();
|
||||
result.setR(result.r()*reverse);
|
||||
result.setG(result.g()*reverse);
|
||||
result.setB(result.b()*reverse);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void esvg::Renderer::print(const esvg::render::Weight& _weightFill,
|
||||
ememory::SharedPtr<esvg::render::DynamicColor>& _colorFill,
|
||||
const esvg::render::Weight& _weightStroke,
|
||||
ememory::SharedPtr<esvg::render::DynamicColor>& _colorStroke,
|
||||
float _opacity) {
|
||||
if (_colorFill != null) {
|
||||
//_colorFill->setViewPort(etk::Pair<vec2, vec2>(vec2(0,0), vec2(sizeX, sizeY)));
|
||||
_colorFill->generate(m_document);
|
||||
}
|
||||
if (_colorStroke != null) {
|
||||
//_colorStroke->setViewPort(etk::Pair<vec2, vec2>(vec2(0,0), vec2(sizeX, sizeY)));
|
||||
_colorStroke->generate(m_document);
|
||||
}
|
||||
// all together
|
||||
for (int32_t yyy=0; yyy<m_size.y(); ++yyy) {
|
||||
for (int32_t xxx=0; xxx<m_size.x(); ++xxx) {
|
||||
ivec2 pos(xxx, yyy);
|
||||
float valueFill = _weightFill.get(pos);
|
||||
float valueStroke = _weightStroke.get(pos);
|
||||
// calculate merge of stroke and fill value:
|
||||
etk::Color<float,4> intermediateColorFill(etk::color::none);
|
||||
etk::Color<float,4> intermediateColorStroke(etk::color::none);
|
||||
if ( _colorFill != null
|
||||
&& valueFill != 0.0f) {
|
||||
intermediateColorFill = _colorFill->getColor(pos);
|
||||
intermediateColorFill.setA(intermediateColorFill.a()*valueFill);
|
||||
}
|
||||
if ( _colorStroke != null
|
||||
&& valueStroke != 0.0f) {
|
||||
intermediateColorStroke = _colorStroke->getColor(pos);
|
||||
intermediateColorStroke.setA(intermediateColorStroke.a()*valueStroke);
|
||||
}
|
||||
etk::Color<float,4> intermediateColor = mergeColor(intermediateColorFill, intermediateColorStroke);
|
||||
intermediateColor.setA(intermediateColor.a() * _opacity);
|
||||
#if DEBUG
|
||||
for (int32_t deltaY=0; deltaY<m_factor; ++deltaY) {
|
||||
for (int32_t deltaX=0; deltaX<m_factor; ++deltaX) {
|
||||
int32_t id = m_size.x()*m_factor*(yyy*m_factor+deltaY) + (xxx*m_factor+deltaX);
|
||||
m_buffer[id] = mergeColor(m_buffer[id], intermediateColor);
|
||||
}
|
||||
}
|
||||
#else
|
||||
m_buffer[m_size.x()*yyy + xxx] = mergeColor(m_buffer[m_size.x()*yyy + xxx], intermediateColor);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
// display the gradient position:
|
||||
ememory::SharedPtr<esvg::render::DynamicColorSpecial> tmpColor = ememory::dynamicPointerCast<esvg::render::DynamicColorSpecial>(_colorFill);
|
||||
if (tmpColor != null) {
|
||||
esvg::render::SegmentList listSegment;
|
||||
// Display bounding box
|
||||
listSegment.addSegment(esvg::render::Point(tmpColor->m_viewPort.first),
|
||||
esvg::render::Point(vec2(tmpColor->m_viewPort.first.x(), tmpColor->m_viewPort.second.y()) ),
|
||||
false);
|
||||
listSegment.addSegment(esvg::render::Point(vec2(tmpColor->m_viewPort.first.x(), tmpColor->m_viewPort.second.y()) ),
|
||||
esvg::render::Point(tmpColor->m_viewPort.second),
|
||||
false);
|
||||
listSegment.addSegment(esvg::render::Point(tmpColor->m_viewPort.second),
|
||||
esvg::render::Point(vec2(tmpColor->m_viewPort.second.x(), tmpColor->m_viewPort.first.y()) ),
|
||||
false);
|
||||
listSegment.addSegment(esvg::render::Point(vec2(tmpColor->m_viewPort.second.x(), tmpColor->m_viewPort.first.y()) ),
|
||||
esvg::render::Point(tmpColor->m_viewPort.first),
|
||||
false);
|
||||
listSegment.applyMatrix(tmpColor->m_matrix);
|
||||
// display the gradient axis
|
||||
listSegment.addSegment(esvg::render::Point(tmpColor->m_pos1),
|
||||
esvg::render::Point(tmpColor->m_pos2),
|
||||
false);
|
||||
/*
|
||||
mat2x3 m_matrix;
|
||||
etk::Pair<vec2, vec2> m_viewPort;
|
||||
vec2 m_pos1;
|
||||
vec2 m_pos2;
|
||||
*/
|
||||
addDebugSegment(listSegment);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void esvg::Renderer::addDebugSegment(const esvg::render::SegmentList& _listSegment) {
|
||||
if (m_visualDebug == false) {
|
||||
return;
|
||||
}
|
||||
ivec2 dynamicSize = m_size * m_factor;
|
||||
// for each lines:
|
||||
for (int32_t yyy=0; yyy<dynamicSize.y(); ++yyy) {
|
||||
// Reduce the number of lines in the subsampling parsing:
|
||||
etk::Vector<esvg::render::Segment> availlableSegmentPixel;
|
||||
for (auto &it : _listSegment.m_data) {
|
||||
if ( it.p0.y() * m_factor <= float(yyy+1)
|
||||
&& it.p1.y() * m_factor >= float(yyy)) {
|
||||
availlableSegmentPixel.pushBack(it);
|
||||
}
|
||||
}
|
||||
//find all the segment that cross the middle of the line of the center of the pixel line:
|
||||
float subSamplingCenterPos = yyy + 0.5f;
|
||||
etk::Vector<esvg::render::Segment> availlableSegment;
|
||||
// find in the subList ...
|
||||
for (auto &it : availlableSegmentPixel) {
|
||||
if ( it.p0.y() * m_factor <= subSamplingCenterPos
|
||||
&& it.p1.y() * m_factor >= subSamplingCenterPos ) {
|
||||
availlableSegment.pushBack(it);
|
||||
}
|
||||
}
|
||||
// x position, angle
|
||||
etk::Vector<etk::Pair<float, float>> listPosition;
|
||||
for (auto &it : availlableSegment) {
|
||||
vec2 delta = it.p0 * m_factor - it.p1 * m_factor;
|
||||
// x = coefficent*y+bbb;
|
||||
float coefficient = delta.x()/delta.y();
|
||||
float bbb = it.p0.x() * m_factor - coefficient*it.p0.y() * m_factor;
|
||||
float xpos = coefficient * subSamplingCenterPos + bbb;
|
||||
if ( xpos >= 0
|
||||
&& xpos < dynamicSize.x()
|
||||
&& yyy >= 0
|
||||
&& yyy < dynamicSize.y() ) {
|
||||
if (it.direction == 1.0f) {
|
||||
m_buffer[(dynamicSize.x()*yyy + int32_t(xpos))] = etk::color::blue;
|
||||
} else {
|
||||
m_buffer[(dynamicSize.x()*yyy + int32_t(xpos))] = etk::color::darkRed;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// for each colomn:
|
||||
for (int32_t xxx=0; xxx<dynamicSize.x(); ++xxx) {
|
||||
// Reduce the number of lines in the subsampling parsing:
|
||||
etk::Vector<esvg::render::Segment> availlableSegmentPixel;
|
||||
for (auto &it : _listSegment.m_data) {
|
||||
if ( ( it.p0.x() * m_factor <= float(xxx+1)
|
||||
&& it.p1.x() * m_factor >= float(xxx) )
|
||||
|| ( it.p0.x() * m_factor >= float(xxx+1)
|
||||
&& it.p1.x() * m_factor <= float(xxx) ) ) {
|
||||
availlableSegmentPixel.pushBack(it);
|
||||
}
|
||||
}
|
||||
//find all the segment that cross the middle of the line of the center of the pixel line:
|
||||
float subSamplingCenterPos = xxx + 0.5f;
|
||||
etk::Vector<esvg::render::Segment> availlableSegment;
|
||||
// find in the subList ...
|
||||
for (auto &it : availlableSegmentPixel) {
|
||||
if ( ( it.p0.x() * m_factor <= subSamplingCenterPos
|
||||
&& it.p1.x() * m_factor >= subSamplingCenterPos)
|
||||
|| ( it.p0.x() * m_factor >= subSamplingCenterPos
|
||||
&& it.p1.x() * m_factor <= subSamplingCenterPos) ) {
|
||||
availlableSegment.pushBack(it);
|
||||
}
|
||||
}
|
||||
// x position, angle
|
||||
etk::Vector<etk::Pair<float, float>> listPosition;
|
||||
for (auto &it : availlableSegment) {
|
||||
vec2 delta = it.p0 * m_factor - it.p1 * m_factor;
|
||||
// x = coefficent*y+bbb;
|
||||
if (delta.x() == 0) {
|
||||
continue;
|
||||
}
|
||||
float coefficient = delta.y()/delta.x();
|
||||
float bbb = it.p0.y() * m_factor - coefficient*it.p0.x() * m_factor;
|
||||
float ypos = coefficient * subSamplingCenterPos + bbb;
|
||||
if ( ypos >= 0
|
||||
&& ypos < dynamicSize.y()
|
||||
&& xxx >= 0
|
||||
&& xxx < dynamicSize.y() ) {
|
||||
if (it.direction == 1.0f) {
|
||||
m_buffer[(dynamicSize.x()*int32_t(ypos) + xxx)] = etk::color::blue;
|
||||
} else {
|
||||
m_buffer[(dynamicSize.x()*int32_t(ypos) + xxx)] = etk::color::darkRed;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void esvg::Renderer::writePPM(const etk::Uri& _uri) {
|
||||
if (m_buffer.size() == 0) {
|
||||
return;
|
||||
}
|
||||
auto fileIo = etk::uri::get(_uri);
|
||||
if (fileIo == null) {
|
||||
Log.error("Can not create the uri: " << _uri);
|
||||
return;
|
||||
}
|
||||
if (fileIo->open(etk::io::OpenMode::Write) == false) {
|
||||
Log.error("Can not open (r) the file : " << _uri);
|
||||
return;
|
||||
}
|
||||
int32_t sizeX = m_size.x();
|
||||
int32_t sizeY = m_size.y();
|
||||
#if DEBUG
|
||||
sizeX *= m_factor;
|
||||
sizeY *= m_factor;
|
||||
#endif
|
||||
Log.debug("Generate ppm : " << m_size << " debug size=" << ivec2(sizeX,sizeY));
|
||||
char tmpValue[1024];
|
||||
sprintf(tmpValue, "P6 %d %d 255 ", sizeX, sizeY);
|
||||
fileIo->write(tmpValue,1,sizeof(tmpValue));
|
||||
for (int32_t iii=0 ; iii<sizeX*sizeY; iii++) {
|
||||
etk::Color<uint8_t,3> tmp = m_buffer[iii];
|
||||
fileIo->write(&tmp, 1, 3);
|
||||
}
|
||||
fileIo->close();
|
||||
}
|
||||
#define PLOPPP
|
||||
extern "C" {
|
||||
#pragma pack(push,1)
|
||||
struct bitmapFileHeader {
|
||||
int16_t bfType;
|
||||
int32_t bfSize;
|
||||
int32_t bfReserved;
|
||||
int32_t bfOffBits;
|
||||
};
|
||||
struct bitmapInfoHeader {
|
||||
int32_t biSize;
|
||||
int32_t biWidth;
|
||||
int32_t biHeight;
|
||||
int16_t biPlanes;
|
||||
int16_t biBitCount;
|
||||
int32_t biCompression;
|
||||
int32_t biSizeImage;
|
||||
int32_t biXPelsPerMeter;
|
||||
int32_t biYPelsPerMeter;
|
||||
#ifndef PLOPPP
|
||||
int32_t biClrUsed;
|
||||
int32_t biClrImportant;
|
||||
#else
|
||||
// https://en.wikipedia.org/wiki/BMP_file_format / example 2
|
||||
int32_t biPaletteNumber;
|
||||
int32_t biImportantColor;
|
||||
int32_t biBitMaskRed;
|
||||
int32_t biBitMaskGreen;
|
||||
int32_t biBitMaskBlue;
|
||||
int32_t biBitMaskAlpha;
|
||||
int32_t biLCSColorSpace;
|
||||
int32_t biUnused[16];
|
||||
#endif
|
||||
};
|
||||
#pragma pack(pop)
|
||||
}
|
||||
void esvg::Renderer::writeBMP(const etk::Uri& _uri) {
|
||||
if (m_buffer.size() == 0) {
|
||||
return;
|
||||
}
|
||||
auto fileIo = etk::uri::get(_uri);
|
||||
if (fileIo == null) {
|
||||
Log.error("Can not create the uri: " << _uri);
|
||||
return;
|
||||
}
|
||||
if (fileIo->open(etk::io::OpenMode::Write) == false) {
|
||||
Log.error("Can not open (r) the file : " << _uri);
|
||||
return;
|
||||
}
|
||||
struct bitmapFileHeader fileHeader;
|
||||
struct bitmapInfoHeader infoHeader;
|
||||
|
||||
int32_t sizeX = m_size.x();
|
||||
int32_t sizeY = m_size.y();
|
||||
#if DEBUG
|
||||
sizeX *= m_factor;
|
||||
sizeY *= m_factor;
|
||||
#endif
|
||||
|
||||
fileHeader.bfType = 0x4D42;
|
||||
fileHeader.bfSize = sizeof(struct bitmapFileHeader) + sizeof(struct bitmapInfoHeader) + sizeX*sizeY*4;
|
||||
fileHeader.bfReserved = 0;
|
||||
fileHeader.bfOffBits = sizeof(struct bitmapFileHeader) + sizeof(struct bitmapInfoHeader);
|
||||
|
||||
|
||||
infoHeader.biSize = sizeof(struct bitmapInfoHeader);
|
||||
infoHeader.biWidth = sizeX;
|
||||
infoHeader.biHeight = sizeY;
|
||||
infoHeader.biPlanes = 1;
|
||||
infoHeader.biBitCount = 32;
|
||||
#ifndef PLOPPP
|
||||
infoHeader.biCompression = 0;
|
||||
#else
|
||||
infoHeader.biCompression = 3;
|
||||
#endif
|
||||
infoHeader.biSizeImage = sizeX*sizeY*4;
|
||||
infoHeader.biXPelsPerMeter = 75;
|
||||
infoHeader.biYPelsPerMeter = 75;
|
||||
#ifndef PLOPPP
|
||||
infoHeader.biClrUsed = 0;
|
||||
infoHeader.biClrImportant = 0;
|
||||
#else
|
||||
infoHeader.biPaletteNumber = 0;
|
||||
infoHeader.biImportantColor = 0;
|
||||
infoHeader.biBitMaskRed = 0xFF000000;
|
||||
infoHeader.biBitMaskGreen = 0x00FF0000;
|
||||
infoHeader.biBitMaskBlue =0x0000FF00;
|
||||
infoHeader.biBitMaskAlpha = 0x000000FF;
|
||||
infoHeader.biLCSColorSpace = 0x73524742; // "Win "
|
||||
for (int32_t jjj=0; jjj<16; ++jjj) {
|
||||
infoHeader.biUnused[jjj] = 0;
|
||||
}
|
||||
infoHeader.biUnused[12] = 0x00000002;
|
||||
#endif
|
||||
// get the data :
|
||||
fileIo->write(&fileHeader, sizeof(struct bitmapFileHeader), 1);
|
||||
fileIo->write(&infoHeader, sizeof(struct bitmapInfoHeader), 1);
|
||||
|
||||
uint8_t data[16];
|
||||
for(int32_t yyy=sizeY-1; yyy>=0; --yyy) {
|
||||
for(int32_t xxx=0; xxx<sizeX; ++xxx) {
|
||||
const etk::Color<uint8_t,4>& tmpColor = m_buffer[sizeX*yyy + xxx];
|
||||
uint8_t* pointer = data;
|
||||
#ifndef PLOPPP
|
||||
*pointer++ = tmpColor.a();
|
||||
*pointer++ = tmpColor.r();
|
||||
*pointer++ = tmpColor.g();
|
||||
*pointer++ = tmpColor.b();
|
||||
#else
|
||||
*pointer++ = tmpColor.a();
|
||||
*pointer++ = tmpColor.b();
|
||||
*pointer++ = tmpColor.g();
|
||||
*pointer++ = tmpColor.r();
|
||||
#endif
|
||||
fileIo->write(data,1,4);
|
||||
}
|
||||
}
|
||||
fileIo->close();
|
||||
}
|
||||
|
||||
|
||||
void esvg::Renderer::setSize(const ivec2& _size) {
|
||||
m_size = _size;
|
||||
m_buffer.resize(m_size.x() * m_size.y()
|
||||
#if DEBUG
|
||||
* m_factor * m_factor
|
||||
#endif
|
||||
, etk::color::none);
|
||||
}
|
||||
|
||||
const ivec2& esvg::Renderer::getSize() const {
|
||||
return m_size;
|
||||
}
|
||||
|
||||
etk::Vector<etk::Color<float,4>> esvg::Renderer::getData() {
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void esvg::Renderer::setInterpolationRecurtionMax(int32_t _value) {
|
||||
m_interpolationRecurtionMax = etk::avg(1, _value, 200);
|
||||
}
|
||||
|
||||
int32_t esvg::Renderer::getInterpolationRecurtionMax() const {
|
||||
return m_interpolationRecurtionMax;
|
||||
}
|
||||
|
||||
void esvg::Renderer::setInterpolationThreshold(float _value) {
|
||||
m_interpolationThreshold = etk::avg(0.0f, _value, 20000.0f);
|
||||
}
|
||||
|
||||
float esvg::Renderer::getInterpolationThreshold() const {
|
||||
return m_interpolationThreshold;
|
||||
}
|
||||
|
||||
void esvg::Renderer::setNumberSubScanLine(int32_t _value) {
|
||||
m_nbSubScanLine = etk::avg(1, _value, 200);
|
||||
}
|
||||
|
||||
int32_t esvg::Renderer::getNumberSubScanLine() const {
|
||||
return m_nbSubScanLine;
|
||||
}
|
||||
|
||||
|
73
src/org/atriasoft/esvg/Renderer.java
Normal file
73
src/org/atriasoft/esvg/Renderer.java
Normal file
@ -0,0 +1,73 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <etk/types.hpp>
|
||||
#include <etk/math/Vector2D.hpp>
|
||||
#include <etk/Color.hpp>
|
||||
#include <esvg/render/Weight.hpp>
|
||||
#include <esvg/render/DynamicColor.hpp>
|
||||
#include <etk/uri/uri.hpp>
|
||||
|
||||
namespace esvg {
|
||||
class Document;
|
||||
class Renderer {
|
||||
#ifdef DEBUG
|
||||
private:
|
||||
bool m_visualDebug;
|
||||
int32_t m_factor;
|
||||
#endif
|
||||
public:
|
||||
Renderer(const ivec2& _size, esvg::Document* _document, bool _visualDebug=false);
|
||||
~Renderer();
|
||||
protected:
|
||||
ivec2 m_size;
|
||||
public:
|
||||
void setSize(const ivec2& _size);
|
||||
const ivec2& getSize() const;
|
||||
protected:
|
||||
etk::Vector<etk::Color<float,4>> m_buffer;
|
||||
public:
|
||||
etk::Vector<etk::Color<float,4>> getData();
|
||||
protected:
|
||||
int32_t m_interpolationRecurtionMax;
|
||||
public:
|
||||
void setInterpolationRecurtionMax(int32_t _value);
|
||||
int32_t getInterpolationRecurtionMax() const;
|
||||
protected:
|
||||
float m_interpolationThreshold;
|
||||
public:
|
||||
void setInterpolationThreshold(float _value);
|
||||
float getInterpolationThreshold() const;
|
||||
protected:
|
||||
int32_t m_nbSubScanLine;
|
||||
public:
|
||||
void setNumberSubScanLine(int32_t _value);
|
||||
int32_t getNumberSubScanLine() const;
|
||||
public:
|
||||
void writePPM(const etk::Uri& _uri);
|
||||
void writeBMP(const etk::Uri& _uri);
|
||||
protected:
|
||||
etk::Color<float,4> mergeColor(etk::Color<float,4> _base, etk::Color<float,4> _integration);
|
||||
public:
|
||||
void print(const esvg::render::Weight& _weightFill,
|
||||
ememory::SharedPtr<esvg::render::DynamicColor>& _colorFill,
|
||||
const esvg::render::Weight& _weightStroke,
|
||||
ememory::SharedPtr<esvg::render::DynamicColor>& _colorStroke,
|
||||
float _opacity);
|
||||
#ifdef DEBUG
|
||||
void addDebugSegment(const esvg::render::SegmentList& _listSegment);
|
||||
void addDebug(const etk::Vector<etk::Pair<vec2,vec2>>& _info);
|
||||
#endif
|
||||
protected:
|
||||
esvg::Document* m_document;
|
||||
public:
|
||||
esvg::Document* getMainDocument() {
|
||||
return m_document;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
28
src/org/atriasoft/esvg/Text.cpp
Normal file
28
src/org/atriasoft/esvg/Text.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <esvg/debug.hpp>
|
||||
#include <esvg/Text.hpp>
|
||||
|
||||
esvg::Text::Text(PaintState _parentPaintState) : esvg::Base(_parentPaintState) {
|
||||
|
||||
}
|
||||
|
||||
esvg::Text::~Text() {
|
||||
|
||||
}
|
||||
|
||||
bool esvg::Text::parse(const exml::Element& _element, mat2x3& _parentTrans, vec2& _sizeMax) {
|
||||
_sizeMax.setValue(0,0);
|
||||
Log.error("NOT IMPLEMENTED");
|
||||
return false;
|
||||
}
|
||||
|
||||
void esvg::Text::display(int32_t _spacing) {
|
||||
Log.debug(spacingDist(_spacing) << "Text");
|
||||
}
|
||||
|
||||
|
19
src/org/atriasoft/esvg/Text.java
Normal file
19
src/org/atriasoft/esvg/Text.java
Normal file
@ -0,0 +1,19 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <esvg/Base.hpp>
|
||||
|
||||
namespace esvg {
|
||||
class Text : public esvg::Base {
|
||||
public:
|
||||
Text(PaintState _parentPaintState);
|
||||
~Text();
|
||||
bool parse(const exml::Element& _element, mat2x3& _parentTrans, vec2& _sizeMax);
|
||||
void display(int32_t _spacing) override;
|
||||
};
|
||||
}
|
||||
|
20
src/org/atriasoft/esvg/cap.cpp
Normal file
20
src/org/atriasoft/esvg/cap.cpp
Normal file
@ -0,0 +1,20 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <esvg/cap.hpp>
|
||||
#include <esvg/debug.hpp>
|
||||
|
||||
static const char* values[] = {
|
||||
"butt",
|
||||
"round",
|
||||
"square"
|
||||
};
|
||||
|
||||
etk::Stream& esvg::operator <<(etk::Stream& _os, enum esvg::cap _obj) {
|
||||
_os << values[_obj];
|
||||
return _os;
|
||||
}
|
||||
|
22
src/org/atriasoft/esvg/cap.java
Normal file
22
src/org/atriasoft/esvg/cap.java
Normal file
@ -0,0 +1,22 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <etk/types.hpp>
|
||||
#include <etk/Stream.hpp>
|
||||
|
||||
namespace esvg {
|
||||
enum cap {
|
||||
cap_butt,
|
||||
cap_round,
|
||||
cap_square
|
||||
};
|
||||
/**
|
||||
* @brief Debug operator To display the curent element in a Human redeable information
|
||||
*/
|
||||
etk::Stream& operator <<(etk::Stream& _os, enum esvg::cap _obj);
|
||||
}
|
||||
|
13
src/org/atriasoft/esvg/debug.cpp
Normal file
13
src/org/atriasoft/esvg/debug.cpp
Normal file
@ -0,0 +1,13 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <esvg/debug.hpp>
|
||||
|
||||
int32_t esvg::getLogId() {
|
||||
static int32_t g_val = elog::registerInstance("esvg");
|
||||
return g_val;
|
||||
}
|
||||
|
400
src/org/atriasoft/esvg/esvg.cpp
Normal file
400
src/org/atriasoft/esvg/esvg.cpp
Normal file
@ -0,0 +1,400 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <esvg/debug.hpp>
|
||||
#include <esvg/esvg.hpp>
|
||||
#include <esvg/Base.hpp>
|
||||
#include <esvg/Circle.hpp>
|
||||
#include <esvg/Ellipse.hpp>
|
||||
#include <esvg/Line.hpp>
|
||||
#include <esvg/Path.hpp>
|
||||
#include <esvg/Polygon.hpp>
|
||||
#include <esvg/Polyline.hpp>
|
||||
#include <esvg/Rectangle.hpp>
|
||||
#include <esvg/Text.hpp>
|
||||
#include <esvg/Group.hpp>
|
||||
#include <esvg/LinearGradient.hpp>
|
||||
#include <esvg/RadialGradient.hpp>
|
||||
|
||||
esvg::Document::Document() {
|
||||
m_uri = "";
|
||||
m_version = "0.0";
|
||||
m_loadOK = false;
|
||||
m_size.setValue(0,0);
|
||||
}
|
||||
|
||||
esvg::Document::~Document() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void esvg::Document::displayDebug() {
|
||||
Log.debug("Main SVG: size=" << m_size);
|
||||
Log.debug(" refs:");
|
||||
for (size_t iii=0; iii<m_refList.size(); iii++) {
|
||||
if (m_refList[iii] != null) {
|
||||
m_refList[iii]->display(2);
|
||||
}
|
||||
}
|
||||
Log.debug(" Nodes:");
|
||||
for (size_t iii=0; iii<m_subElementList.size(); iii++) {
|
||||
if (m_subElementList[iii] != null) {
|
||||
m_subElementList[iii]->display(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void esvg::Document::draw(esvg::Renderer& _myRenderer, mat2x3& _basicTrans, int32_t _level) {
|
||||
for (size_t iii=0; iii<m_subElementList.size(); iii++) {
|
||||
if (m_subElementList[iii] != null) {
|
||||
m_subElementList[iii]->draw(_myRenderer, _basicTrans);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FOR TEST only ...
|
||||
void esvg::Document::generateAnImage(const etk::Uri& _uri, bool _visualDebug) {
|
||||
generateAnImage(m_size, _uri, _visualDebug);
|
||||
}
|
||||
void esvg::Document::generateAnImage(const ivec2& _size, const etk::Uri& _uri, bool _visualDebug) {
|
||||
ivec2 sizeRender = _size;
|
||||
if (sizeRender.x() <= 0) {
|
||||
sizeRender.setX(m_size.x());
|
||||
}
|
||||
if (sizeRender.y() <= 0) {
|
||||
sizeRender.setY(m_size.y());
|
||||
}
|
||||
Log.debug("Generate size " << sizeRender);
|
||||
|
||||
ememory::SharedPtr<esvg::Renderer> renderedElement = ememory::makeShared<esvg::Renderer>(sizeRender, this, _visualDebug);
|
||||
// create the first element matrix modification ...
|
||||
mat2x3 basicTrans;
|
||||
basicTrans *= etk::mat2x3Scale(vec2(sizeRender.x()/m_size.x(), sizeRender.y()/m_size.y()));
|
||||
|
||||
draw(*renderedElement, basicTrans);
|
||||
|
||||
if (_uri.getPath().getExtention() == "ppm") {
|
||||
renderedElement->writePPM(_uri);
|
||||
} else if (_uri.getPath().getExtention() == "bmp") {
|
||||
renderedElement->writeBMP(_uri);
|
||||
} else {
|
||||
Log.error("Can not store with this extention : " << _uri << " not in .bmp/.ppm");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
etk::Vector<etk::Color<float,4>> esvg::Document::renderImageFloatRGBA(ivec2& _size) {
|
||||
if (_size.x() <= 0) {
|
||||
_size.setX(m_size.x());
|
||||
}
|
||||
if (_size.y() <= 0) {
|
||||
_size.setY(m_size.y());
|
||||
}
|
||||
Log.debug("Generate size " << _size);
|
||||
ememory::SharedPtr<esvg::Renderer> renderedElement = ememory::makeShared<esvg::Renderer>(_size, this);
|
||||
// create the first element matrix modification ...
|
||||
mat2x3 basicTrans;
|
||||
basicTrans *= etk::mat2x3Scale(vec2(_size.x()/m_size.x(), _size.y()/m_size.y()));
|
||||
draw(*renderedElement, basicTrans);
|
||||
|
||||
// direct return the generated data ...
|
||||
return renderedElement->getData();
|
||||
}
|
||||
|
||||
etk::Vector<etk::Color<float,3>> esvg::Document::renderImageFloatRGB(ivec2& _size) {
|
||||
etk::Vector<etk::Color<float,4>> data = renderImageFloatRGBA(_size);
|
||||
// Reduce scope:
|
||||
etk::Vector<etk::Color<float,3>> out;
|
||||
out.resize(data.size());
|
||||
for (size_t iii=0; iii<data.size(); ++iii) {
|
||||
out[iii] = data[iii];
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
etk::Vector<etk::Color<uint8_t,4>> esvg::Document::renderImageU8RGBA(ivec2& _size) {
|
||||
etk::Vector<etk::Color<float,4>> data = renderImageFloatRGBA(_size);
|
||||
// Reduce scope:
|
||||
etk::Vector<etk::Color<uint8_t,4>> out;
|
||||
out.resize(data.size());
|
||||
for (size_t iii=0; iii<data.size(); ++iii) {
|
||||
out[iii] = data[iii];
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
etk::Vector<etk::Color<uint8_t,3>> esvg::Document::renderImageU8RGB(ivec2& _size) {
|
||||
etk::Vector<etk::Color<float,4>> data = renderImageFloatRGBA(_size);
|
||||
// Reduce scope:
|
||||
etk::Vector<etk::Color<uint8_t,3>> out;
|
||||
out.resize(data.size());
|
||||
for (size_t iii=0; iii<data.size(); ++iii) {
|
||||
out[iii] = data[iii];
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
void esvg::Document::clear() {
|
||||
m_uri = "";
|
||||
m_version = "0.0";
|
||||
m_loadOK = true;
|
||||
m_paint.clear();
|
||||
m_size.setValue(0,0);
|
||||
}
|
||||
|
||||
|
||||
bool esvg::Document::parse(const etk::String& _data) {
|
||||
clear();
|
||||
exml::Document doc;
|
||||
if (doc.parse(_data) == false) {
|
||||
Log.error("Error occured when loading SVG: " << m_uri);
|
||||
m_loadOK = false;
|
||||
return m_loadOK;
|
||||
}
|
||||
if (doc.nodes.size() == 0) {
|
||||
Log.error("(l ?) No nodes in the SVG file ... '" << m_uri << "'");
|
||||
m_loadOK = false;
|
||||
return m_loadOK;
|
||||
}
|
||||
exml::Element root = doc.nodes["svg"];
|
||||
if (root.exist() == false) {
|
||||
Log.error("(l ?) main node not find: 'svg' in '" << m_uri << "'");
|
||||
m_loadOK = false;
|
||||
return m_loadOK;
|
||||
}
|
||||
cleanStyleProperty(root);
|
||||
m_loadOK = parseXMLData(root);
|
||||
return m_loadOK;
|
||||
}
|
||||
|
||||
bool esvg::Document::generate(etk::String& _data) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool esvg::Document::load(const etk::Uri& _uri) {
|
||||
clear();
|
||||
m_uri = _uri;
|
||||
exml::Document doc;
|
||||
if (doc.load(m_uri) == false) {
|
||||
Log.error("Error occured when loading SVG : " << m_uri);
|
||||
m_loadOK = false;
|
||||
return m_loadOK;
|
||||
}
|
||||
if (doc.nodes.size() == 0) {
|
||||
Log.error("(l ?) No nodes in the SVG file ... '" << m_uri << "'");
|
||||
m_loadOK = false;
|
||||
return m_loadOK;
|
||||
}
|
||||
exml::Element root = doc.nodes["svg"];
|
||||
if (root.exist() == false) {
|
||||
Log.error("(l ?) main node not find: 'svg' in '" << m_uri << "'");
|
||||
m_loadOK = false;
|
||||
return m_loadOK;
|
||||
}
|
||||
cleanStyleProperty(root);
|
||||
m_loadOK = parseXMLData(root);
|
||||
return m_loadOK;
|
||||
}
|
||||
|
||||
bool esvg::Document::store(const etk::Uri& _uri) {
|
||||
ESVG_TODO("not implemented store in SVG...");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool esvg::Document::cleanStyleProperty(const exml::Element& _root) {
|
||||
// for each nodes:
|
||||
for(auto it: _root.nodes) {
|
||||
exml::Element child = it.toElement();
|
||||
if (child.exist() == false) {
|
||||
continue;
|
||||
}
|
||||
// get attribute style:
|
||||
if (child.attributes.exist("style") == true) {
|
||||
etk::String content = child.attributes["style"];
|
||||
if (content.size() != 0) {
|
||||
etk::Vector<etk::String> listStyle = etk::split(content, ';');
|
||||
for (auto &it : listStyle) {
|
||||
etk::Vector<etk::String> value = etk::split(it, ':');
|
||||
if (value.size() != 2) {
|
||||
Log.error("parsing style with a wrong patern : " << it << " missing ':'");
|
||||
continue;
|
||||
}
|
||||
// TODO : Check if the attibute already exist ...
|
||||
child.attributes.set(value[0], value[1]);
|
||||
}
|
||||
}
|
||||
// remove attribute style:
|
||||
child.attributes.remove("style");
|
||||
}
|
||||
// sub-parsing ...
|
||||
cleanStyleProperty(child);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool esvg::Document::parseXMLData(const exml::Element& _root, bool _isReference) {
|
||||
// get the svg version :
|
||||
m_version = _root.attributes["version"];
|
||||
// parse ...
|
||||
vec2 pos(0,0);
|
||||
if (_isReference == false) {
|
||||
parseTransform(_root);
|
||||
parsePosition(_root, pos, m_size);
|
||||
parsePaintAttr(_root);
|
||||
Log.verbose("parsed .ROOT trans: " << m_transformMatrix);
|
||||
} else {
|
||||
Log.verbose("Parse Reference section ... (no attibute)");
|
||||
}
|
||||
vec2 maxSize(0,0);
|
||||
vec2 size(0,0);
|
||||
// parse all sub node:
|
||||
for(auto it : _root.nodes) {
|
||||
exml::Element child = it.toElement();
|
||||
if (child.exist() == false) {
|
||||
// comment can be here...
|
||||
continue;
|
||||
}
|
||||
ememory::SharedPtr<esvg::Base> elementParser;
|
||||
if (child.getValue() == "g") {
|
||||
elementParser = ememory::makeShared<esvg::Group>(m_paint);
|
||||
} else if (child.getValue() == "a") {
|
||||
Log.info("Note : 'a' balise is parsed like a g balise ...");
|
||||
elementParser = ememory::makeShared<esvg::Group>(m_paint);
|
||||
} else if (child.getValue() == "title") {
|
||||
m_title = "TODO : set the title here ...";
|
||||
continue;
|
||||
} else if (child.getValue() == "path") {
|
||||
elementParser = ememory::makeShared<esvg::Path>(m_paint);
|
||||
} else if (child.getValue() == "rect") {
|
||||
elementParser = ememory::makeShared<esvg::Rectangle>(m_paint);
|
||||
} else if (child.getValue() == "circle") {
|
||||
elementParser = ememory::makeShared<esvg::Circle>(m_paint);
|
||||
} else if (child.getValue() == "ellipse") {
|
||||
elementParser = ememory::makeShared<esvg::Ellipse>(m_paint);
|
||||
} else if (child.getValue() == "line") {
|
||||
elementParser = ememory::makeShared<esvg::Line>(m_paint);
|
||||
} else if (child.getValue() == "polyline") {
|
||||
elementParser = ememory::makeShared<esvg::Polyline>(m_paint);
|
||||
} else if (child.getValue() == "polygon") {
|
||||
elementParser = ememory::makeShared<esvg::Polygon>(m_paint);
|
||||
} else if (child.getValue() == "text") {
|
||||
elementParser = ememory::makeShared<esvg::Text>(m_paint);
|
||||
} else if (child.getValue() == "radialGradient") {
|
||||
if (_isReference == false) {
|
||||
Log.error("'" << child.getValue() << "' node must not be defined outside a defs Section");
|
||||
continue;
|
||||
} else {
|
||||
elementParser = ememory::makeShared<esvg::RadialGradient>(m_paint);
|
||||
}
|
||||
} else if (child.getValue() == "linearGradient") {
|
||||
if (_isReference == false) {
|
||||
Log.error("'" << child.getValue() << "' node must not be defined outside a defs Section");
|
||||
continue;
|
||||
} else {
|
||||
elementParser = ememory::makeShared<esvg::LinearGradient>(m_paint);
|
||||
}
|
||||
} else if (child.getValue() == "defs") {
|
||||
if (_isReference == true) {
|
||||
Log.error("'" << child.getValue() << "' node must not be defined in a defs Section");
|
||||
continue;
|
||||
} else {
|
||||
bool retRefs = parseXMLData(child, true);
|
||||
// TODO : Use retRefs ...
|
||||
continue;
|
||||
}
|
||||
} else if (child.getValue() == "sodipodi:namedview") {
|
||||
// Node ignore : generaly inkscape data
|
||||
continue;
|
||||
} else if (child.getValue() == "metadata") {
|
||||
// Node ignore : generaly inkscape data
|
||||
continue;
|
||||
} else {
|
||||
Log.error("(l " << child.getPos() << ") node not suported : '" << child.getValue() << "' must be [title,g,a,path,rect,circle,ellipse,line,polyline,polygon,text,metadata]");
|
||||
}
|
||||
if (elementParser == null) {
|
||||
Log.error("(l " << child.getPos() << ") error on node: '" << child.getValue() << "' allocation error or not supported ...");
|
||||
continue;
|
||||
}
|
||||
if (elementParser->parseXML(child, m_transformMatrix, size) == false) {
|
||||
Log.error("(l " << child.getPos() << ") error on node: '" << child.getValue() << "' Sub Parsing ERROR");
|
||||
elementParser.reset();
|
||||
continue;
|
||||
}
|
||||
if (maxSize.x()<size.x()) {
|
||||
maxSize.setX(size.x());
|
||||
}
|
||||
if (maxSize.y()<size.y()) {
|
||||
maxSize.setY(size.y());
|
||||
}
|
||||
// add element in the system
|
||||
if (_isReference == false) {
|
||||
m_subElementList.pushBack(elementParser);
|
||||
} else {
|
||||
m_refList.pushBack(elementParser);
|
||||
}
|
||||
}
|
||||
if ( m_size.x() == 0
|
||||
|| m_size.y()==0) {
|
||||
m_size.setValue((int32_t)maxSize.x(), (int32_t)maxSize.y());
|
||||
} else {
|
||||
m_size.setValue((int32_t)m_size.x(), (int32_t)m_size.y());
|
||||
}
|
||||
if (_isReference == false) {
|
||||
displayDebug();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ememory::SharedPtr<esvg::Base> esvg::Document::getReference(const etk::String& _name) {
|
||||
if (_name == "") {
|
||||
Log.error("request a reference with no name ... ");
|
||||
return null;
|
||||
}
|
||||
for (auto &it : m_refList) {
|
||||
if (it == null) {
|
||||
continue;
|
||||
}
|
||||
if (it->getId() == _name) {
|
||||
return it;
|
||||
}
|
||||
}
|
||||
Log.error("Can not find reference name : '" << _name << "'");
|
||||
return null;
|
||||
}
|
||||
|
||||
etk::Vector<etk::Vector<vec2>> esvg::Document::getLines(vec2 _size) {
|
||||
etk::Vector<etk::Vector<vec2>> out;
|
||||
if (_size.x() <= 0) {
|
||||
_size.setX(m_size.x());
|
||||
}
|
||||
if (_size.y() <= 0) {
|
||||
_size.setY(m_size.y());
|
||||
}
|
||||
Log.debug("lineification size " << _size);
|
||||
// create the first element matrix modification ...
|
||||
mat2x3 basicTrans;
|
||||
basicTrans *= etk::mat2x3Scale(vec2(_size.x()/m_size.x(), _size.y()/m_size.y()));
|
||||
drawShapePoints(out, 10, 0.25f, basicTrans);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
void esvg::Document::drawShapePoints(etk::Vector<etk::Vector<vec2>>& _out,
|
||||
int32_t _recurtionMax,
|
||||
float _threshold,
|
||||
mat2x3& _basicTrans,
|
||||
int32_t _level) {
|
||||
Log.verbose(spacingDist(_level) << "DRAW shape esvg::Document");
|
||||
for (auto &it : m_subElementList) {
|
||||
if (it != null) {
|
||||
it->drawShapePoints(_out, _recurtionMax, _threshold, _basicTrans, _level+1);
|
||||
}
|
||||
}
|
||||
}
|
105
src/org/atriasoft/esvg/esvg.java
Normal file
105
src/org/atriasoft/esvg/esvg.java
Normal file
@ -0,0 +1,105 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <etk/types.hpp>
|
||||
#include <etk/Vector.hpp>
|
||||
#include <etk/math/Vector2D.hpp>
|
||||
#include <etk/uri/uri.hpp>
|
||||
|
||||
#include <esvg/Base.hpp>
|
||||
|
||||
/**
|
||||
* @brief Main esvg namespace
|
||||
*/
|
||||
namespace esvg {
|
||||
class Document : public esvg::Base {
|
||||
private:
|
||||
etk::Uri m_uri;
|
||||
bool m_loadOK;
|
||||
etk::String m_version;
|
||||
etk::String m_title;
|
||||
etk::Vector<ememory::SharedPtr<esvg::Base>> m_subElementList; //!< sub-element list
|
||||
etk::Vector<ememory::SharedPtr<esvg::Base>> m_refList; //!< reference elements ...
|
||||
vec2 m_size;
|
||||
public:
|
||||
Document();
|
||||
~Document();
|
||||
void clear();
|
||||
/**
|
||||
* @brief parse a string that contain an svg stream
|
||||
* @param[in] _data Data to parse
|
||||
* @return false : An error occured
|
||||
* @return true : Parsing is OK
|
||||
*/
|
||||
bool parse(const etk::String& _data);
|
||||
/**
|
||||
* @brief generate a string that contain the created SVG
|
||||
* @param[out] _data Data where the svg is stored
|
||||
* @return false : An error occured
|
||||
* @return true : Parsing is OK
|
||||
*/
|
||||
bool generate(etk::String& _data);
|
||||
/**
|
||||
* @brief Load the file that might contain the svg
|
||||
* @param[in] _uri File of the svg
|
||||
* @return false : An error occured
|
||||
* @return true : Parsing is OK
|
||||
*/
|
||||
bool load(const etk::Uri& _uri);
|
||||
/**
|
||||
* @brief Store the SVG in the file
|
||||
* @param[in] _uri File of the svg
|
||||
* @return false : An error occured
|
||||
* @return true : Parsing is OK
|
||||
*/
|
||||
bool store(const etk::Uri& _uri);
|
||||
protected:
|
||||
/**
|
||||
* @brief change all style in a xml atribute
|
||||
*/
|
||||
virtual bool cleanStyleProperty(const exml::Element& _root);
|
||||
virtual bool parseXMLData(const exml::Element& _root, bool _isReference = false);
|
||||
public:
|
||||
bool isLoadOk() {
|
||||
return m_loadOK;
|
||||
};
|
||||
/**
|
||||
* @brief Display all the node in the svg file.
|
||||
*/
|
||||
void displayDebug();
|
||||
// TODO: remove this fucntion : use generic function ...
|
||||
void generateAnImage(const etk::Uri& _uri, bool _visualDebug=false);
|
||||
void generateAnImage(const ivec2& _size, const etk::Uri& _uri, bool _visualDebug=false);
|
||||
/**
|
||||
* @brief Generate Image in a specific format.
|
||||
* @param[in,out] _size Size expected of the rendered image (value <=0 if it need to be automatic.) return the size generate
|
||||
* @return Vector of the data used to display (simple vector: generic to transmit)
|
||||
*/
|
||||
etk::Vector<etk::Color<float,4>> renderImageFloatRGBA(ivec2& _size);
|
||||
//! @previous
|
||||
etk::Vector<etk::Color<float,3>> renderImageFloatRGB(ivec2& _size);
|
||||
//! @previous
|
||||
etk::Vector<etk::Color<uint8_t,4>> renderImageU8RGBA(ivec2& _size);
|
||||
//! @previous
|
||||
etk::Vector<etk::Color<uint8_t,3>> renderImageU8RGB(ivec2& _size);
|
||||
etk::Vector<etk::Vector<vec2>> getLines(vec2 _size=vec2(256,256));
|
||||
protected:
|
||||
void draw(esvg::Renderer& _myRenderer, mat2x3& _basicTrans, int32_t _level=0) override;
|
||||
public:
|
||||
vec2 getDefinedSize() {
|
||||
return m_size;
|
||||
};
|
||||
ememory::SharedPtr<esvg::Base> getReference(const etk::String& _name);
|
||||
protected:
|
||||
void drawShapePoints(etk::Vector<etk::Vector<vec2>>& _out,
|
||||
int32_t _recurtionMax,
|
||||
float _threshold,
|
||||
mat2x3& _basicTrans,
|
||||
int32_t _level=1) override;
|
||||
};
|
||||
}
|
||||
|
19
src/org/atriasoft/esvg/gradientUnits.cpp
Normal file
19
src/org/atriasoft/esvg/gradientUnits.cpp
Normal file
@ -0,0 +1,19 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <esvg/gradientUnits.hpp>
|
||||
#include <esvg/debug.hpp>
|
||||
|
||||
static const char* values[] = {
|
||||
"userSpaceOnUse",
|
||||
"objectBoundingBox"
|
||||
};
|
||||
|
||||
etk::Stream& esvg::operator <<(etk::Stream& _os, enum esvg::gradientUnits _obj) {
|
||||
_os << values[_obj];
|
||||
return _os;
|
||||
}
|
||||
|
20
src/org/atriasoft/esvg/gradientUnits.java
Normal file
20
src/org/atriasoft/esvg/gradientUnits.java
Normal file
@ -0,0 +1,20 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <etk/types.hpp>
|
||||
#include <etk/Stream.hpp>
|
||||
|
||||
namespace esvg {
|
||||
enum gradientUnits {
|
||||
gradientUnits_userSpaceOnUse,
|
||||
gradientUnits_objectBoundingBox
|
||||
};
|
||||
/**
|
||||
* @brief Debug operator To display the curent element in a Human redeable information
|
||||
*/
|
||||
etk::Stream& operator <<(etk::Stream& _os, enum esvg::gradientUnits _obj);
|
||||
}
|
68
src/org/atriasoft/esvg/internal/Log.java
Normal file
68
src/org/atriasoft/esvg/internal/Log.java
Normal file
@ -0,0 +1,68 @@
|
||||
package org.atriasoft.esvg.internal;
|
||||
|
||||
import io.scenarium.logger.LogLevel;
|
||||
import io.scenarium.logger.Logger;
|
||||
|
||||
class Log {
|
||||
private static final String LIB_NAME = "esvg";
|
||||
private static final String LIB_NAME_DRAW = Logger.getDrawableName(LIB_NAME);
|
||||
private static final boolean PRINT_CRITICAL = Logger.getNeedPrint(LIB_NAME, LogLevel.CRITICAL);
|
||||
private static final boolean PRINT_ERROR = Logger.getNeedPrint(LIB_NAME, LogLevel.ERROR);
|
||||
private static final boolean PRINT_WARNING = Logger.getNeedPrint(LIB_NAME, LogLevel.WARNING);
|
||||
private static final boolean PRINT_INFO = Logger.getNeedPrint(LIB_NAME, LogLevel.INFO);
|
||||
private static final boolean PRINT_DEBUG = Logger.getNeedPrint(LIB_NAME, LogLevel.DEBUG);
|
||||
private static final boolean PRINT_VERBOSE = Logger.getNeedPrint(LIB_NAME, LogLevel.VERBOSE);
|
||||
private static final boolean PRINT_TODO = Logger.getNeedPrint(LIB_NAME, LogLevel.TODO);
|
||||
private static final boolean PRINT_PRINT = Logger.getNeedPrint(LIB_NAME, LogLevel.PRINT);
|
||||
|
||||
public static void critical(final String data) {
|
||||
if (PRINT_CRITICAL) {
|
||||
Logger.critical(LIB_NAME_DRAW, data);
|
||||
}
|
||||
}
|
||||
|
||||
public static void debug(final String data) {
|
||||
if (PRINT_DEBUG) {
|
||||
Logger.debug(LIB_NAME_DRAW, data);
|
||||
}
|
||||
}
|
||||
|
||||
public static void error(final String data) {
|
||||
if (PRINT_ERROR) {
|
||||
Logger.error(LIB_NAME_DRAW, data);
|
||||
}
|
||||
}
|
||||
|
||||
public static void info(final String data) {
|
||||
if (PRINT_INFO) {
|
||||
Logger.info(LIB_NAME_DRAW, data);
|
||||
}
|
||||
}
|
||||
|
||||
public static void print(final String data) {
|
||||
if (PRINT_PRINT) {
|
||||
Logger.print(LIB_NAME_DRAW, data);
|
||||
}
|
||||
}
|
||||
|
||||
public static void todo(final String data) {
|
||||
if (PRINT_TODO) {
|
||||
Logger.todo(LIB_NAME_DRAW, data);
|
||||
}
|
||||
}
|
||||
|
||||
public static void verbose(final String data) {
|
||||
if (PRINT_VERBOSE) {
|
||||
Logger.verbose(LIB_NAME_DRAW, data);
|
||||
}
|
||||
}
|
||||
|
||||
public static void warning(final String data) {
|
||||
if (PRINT_WARNING) {
|
||||
Logger.warning(LIB_NAME_DRAW, data);
|
||||
}
|
||||
}
|
||||
|
||||
private Log() {}
|
||||
|
||||
}
|
20
src/org/atriasoft/esvg/join.cpp
Normal file
20
src/org/atriasoft/esvg/join.cpp
Normal file
@ -0,0 +1,20 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <esvg/join.hpp>
|
||||
#include <esvg/debug.hpp>
|
||||
|
||||
static const char* values[] = {
|
||||
"miter",
|
||||
"round",
|
||||
"bevel"
|
||||
};
|
||||
|
||||
etk::Stream& esvg::operator <<(etk::Stream& _os, enum esvg::join _obj) {
|
||||
_os << values[_obj];
|
||||
return _os;
|
||||
}
|
||||
|
23
src/org/atriasoft/esvg/join.java
Normal file
23
src/org/atriasoft/esvg/join.java
Normal file
@ -0,0 +1,23 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <etk/types.hpp>
|
||||
#include <etk/Stream.hpp>
|
||||
|
||||
namespace esvg {
|
||||
enum join {
|
||||
join_miter,
|
||||
join_round,
|
||||
join_bevel
|
||||
};
|
||||
/**
|
||||
* @brief Debug operator To display the curent element in a Human redeable information
|
||||
*/
|
||||
etk::Stream& operator <<(etk::Stream& _os, enum esvg::join _obj);
|
||||
}
|
||||
|
||||
|
452
src/org/atriasoft/esvg/render/DynamicColor.cpp
Normal file
452
src/org/atriasoft/esvg/render/DynamicColor.cpp
Normal file
@ -0,0 +1,452 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <esvg/debug.hpp>
|
||||
#include <esvg/render/DynamicColor.hpp>
|
||||
#include <esvg/LinearGradient.hpp>
|
||||
#include <esvg/RadialGradient.hpp>
|
||||
#include <esvg/esvg.hpp>
|
||||
|
||||
esvg::render::DynamicColorSpecial::DynamicColorSpecial(const etk::String& _link, const mat2x3& _mtx) :
|
||||
m_linear(true),
|
||||
m_colorName(_link),
|
||||
m_matrix(_mtx),
|
||||
m_viewPort(vec2(9999999999.0,9999999999.0),vec2(-9999999999.0,-9999999999.0)) {
|
||||
|
||||
}
|
||||
|
||||
void esvg::render::DynamicColorSpecial::setViewPort(const etk::Pair<vec2, vec2>& _viewPort) {
|
||||
m_viewPort = _viewPort;
|
||||
}
|
||||
|
||||
|
||||
static vec2 getIntersect(const vec2& _point1,
|
||||
const vec2& _vect1,
|
||||
const vec2& _point2,
|
||||
const vec2& _vect2) {
|
||||
float diviseur = _vect1.x() * _vect2.y() - _vect1.y() * _vect2.x();
|
||||
if(diviseur != 0.0f) {
|
||||
float mmm = ( _vect1.x() * _point1.y()
|
||||
- _vect1.x() * _point2.y()
|
||||
- _vect1.y() * _point1.x()
|
||||
+ _vect1.y() * _point2.x()
|
||||
) / diviseur;
|
||||
return vec2(_point2 + _vect2 * mmm);
|
||||
}
|
||||
Log.error("Get divider / 0.0f");
|
||||
return _point2;
|
||||
}
|
||||
|
||||
etk::Color<float,4> esvg::render::DynamicColorSpecial::getColor(const ivec2& _pos) const {
|
||||
if (m_data.size() < 2) {
|
||||
return etk::color::purple;
|
||||
}
|
||||
if (m_linear == true) {
|
||||
return getColorLinear(_pos);
|
||||
} else {
|
||||
return getColorRadial(_pos);
|
||||
}
|
||||
return etk::color::purple;
|
||||
}
|
||||
|
||||
etk::Color<float,4> esvg::render::DynamicColorSpecial::getColorLinear(const ivec2& _pos) const {
|
||||
float ratio = 0.0f;
|
||||
if (m_unit == gradientUnits_userSpaceOnUse) {
|
||||
vec2 vectorBase = m_pos2 - m_pos1;
|
||||
vec2 vectorOrtho(vectorBase.y(), -vectorBase.x());
|
||||
vec2 intersec = getIntersect(m_pos1, vectorBase,
|
||||
vec2(_pos.x(), _pos.y()), vectorOrtho);
|
||||
float baseSize = vectorBase.length();
|
||||
vec2 vectorBaseDraw = intersec - m_pos1;
|
||||
float baseDraw = vectorBaseDraw.length();
|
||||
ratio = baseDraw / baseSize;
|
||||
switch(m_spread) {
|
||||
case spreadMethod_pad:
|
||||
if (vectorBase.dot(vectorBaseDraw) < 0) {
|
||||
ratio *= -1.0;
|
||||
}
|
||||
break;
|
||||
case spreadMethod_reflect:
|
||||
ratio -= float((int32_t(ratio)>>1)<<1);
|
||||
if (ratio > 1.0f) {
|
||||
ratio = 2.0f-ratio;
|
||||
}
|
||||
break;
|
||||
case spreadMethod_repeat:
|
||||
if (vectorBase.dot(vectorBaseDraw) < 0) {
|
||||
ratio *= -1.0;
|
||||
}
|
||||
ratio -= float(int32_t(ratio));
|
||||
if (ratio <0.0f) {
|
||||
#ifndef __STDCPP_LLVM__
|
||||
ratio = 1.0f-etk::abs(ratio);
|
||||
#else
|
||||
ratio = 1.0f-abs(ratio);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// in the basic vertion of the gradient the color is calculated with the ration in X and Y in the bonding box associated (it is rotate with the object..
|
||||
vec2 intersecX = getIntersect(m_pos1, m_axeX,
|
||||
vec2(_pos.x(), _pos.y()), m_axeY);
|
||||
vec2 intersecY = getIntersect(m_pos1, m_axeY,
|
||||
vec2(_pos.x(), _pos.y()), m_axeX);
|
||||
vec2 vectorBaseDrawX = intersecX - m_pos1;
|
||||
vec2 vectorBaseDrawY = intersecY - m_pos1;
|
||||
float baseDrawX = vectorBaseDrawX.length();
|
||||
float baseDrawY = vectorBaseDrawY.length();
|
||||
if (m_axeX.dot(vectorBaseDrawX) < 0) {
|
||||
baseDrawX *= -1.0f;
|
||||
}
|
||||
if (m_axeY.dot(vectorBaseDrawY) < 0) {
|
||||
baseDrawY *= -1.0f;
|
||||
}
|
||||
if (m_baseSize.x()+m_baseSize.y() != 0.0f) {
|
||||
if ( m_baseSize.x() != 0.0f
|
||||
&& m_baseSize.y() != 0.0f) {
|
||||
ratio = (baseDrawX*m_baseSize.y() + baseDrawY*m_baseSize.x())/(m_baseSize.x()*m_baseSize.y()*2.0f);
|
||||
} else if (m_baseSize.x() != 0.0f) {
|
||||
ratio = baseDrawX/m_baseSize.x();
|
||||
} else {
|
||||
ratio = baseDrawY/m_baseSize.y();
|
||||
}
|
||||
} else {
|
||||
ratio = 1.0f;
|
||||
}
|
||||
switch(m_spread) {
|
||||
case spreadMethod_pad:
|
||||
// nothing to do ...
|
||||
break;
|
||||
case spreadMethod_reflect:
|
||||
#ifndef __STDCPP_LLVM__
|
||||
ratio = etk::abs(ratio);
|
||||
#else
|
||||
ratio = abs(ratio);
|
||||
#endif
|
||||
ratio -= float((int32_t(ratio)>>1)<<1);
|
||||
if (ratio > 1.0f) {
|
||||
ratio = 2.0f-ratio;
|
||||
}
|
||||
break;
|
||||
case spreadMethod_repeat:
|
||||
ratio -= float(int32_t(ratio));
|
||||
if (ratio <0.0f) {
|
||||
#ifndef __STDCPP_LLVM__
|
||||
ratio = 1.0f-etk::abs(ratio);
|
||||
#else
|
||||
ratio = 1.0f-abs(ratio);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ratio <= m_data[0].first*0.01f) {
|
||||
return m_data[0].second;
|
||||
}
|
||||
if (ratio >= m_data.back().first*0.01f) {
|
||||
return m_data.back().second;
|
||||
}
|
||||
for (size_t iii=1; iii<m_data.size(); ++iii) {
|
||||
if (ratio <= m_data[iii].first*0.01f) {
|
||||
float localRatio = ratio - m_data[iii-1].first*0.01f;
|
||||
localRatio = localRatio / ((m_data[iii].first - m_data[iii-1].first) * 0.01f);
|
||||
return etk::Color<float,4>(m_data[iii-1].second.r() * (1.0-localRatio) + m_data[iii].second.r() * localRatio,
|
||||
m_data[iii-1].second.g() * (1.0-localRatio) + m_data[iii].second.g() * localRatio,
|
||||
m_data[iii-1].second.b() * (1.0-localRatio) + m_data[iii].second.b() * localRatio,
|
||||
m_data[iii-1].second.a() * (1.0-localRatio) + m_data[iii].second.a() * localRatio);
|
||||
}
|
||||
}
|
||||
return etk::color::green;
|
||||
}
|
||||
static etk::Pair<vec2,vec2> intersectLineToCircle(const vec2& _pos1,
|
||||
const vec2& _pos2,
|
||||
const vec2& _center = vec2(0.0f, 0.0f),
|
||||
float _radius = 1.0f) {
|
||||
vec2 v1;
|
||||
vec2 v2;
|
||||
//vector2D from point 1 to point 2
|
||||
v1 = _pos2 - _pos1;
|
||||
//vector2D from point 1 to the circle's center
|
||||
v2 = _center - _pos1;
|
||||
|
||||
float dot = v1.dot(v2);
|
||||
vec2 proj1 = vec2(((dot / (v1.length2())) * v1.x()),
|
||||
((dot / (v1.length2())) * v1.y()));
|
||||
vec2 midpt = _pos1 + proj1;
|
||||
|
||||
float distToCenter = (midpt - _center).length2();
|
||||
if (distToCenter > _radius * _radius) {
|
||||
return etk::Pair<vec2,vec2>(vec2(0.0,0.0), vec2(0.0,0.0));
|
||||
}
|
||||
if (distToCenter == _radius * _radius) {
|
||||
return etk::Pair<vec2,vec2>(midpt, midpt);
|
||||
}
|
||||
float distToIntersection;
|
||||
if (distToCenter == 0.0f) {
|
||||
distToIntersection = _radius;
|
||||
} else {
|
||||
#ifndef __STDCPP_LLVM__
|
||||
distToCenter = etk::sqrt(distToCenter);
|
||||
distToIntersection = etk::sqrt(_radius * _radius - distToCenter * distToCenter);
|
||||
#else
|
||||
distToCenter = sqrtf(distToCenter);
|
||||
distToIntersection = sqrtf(_radius * _radius - distToCenter * distToCenter);
|
||||
#endif
|
||||
}
|
||||
// normalize...
|
||||
v1.safeNormalize();
|
||||
v1 *= distToIntersection;
|
||||
return etk::Pair<vec2,vec2>(midpt + v1, midpt - v1);
|
||||
}
|
||||
|
||||
etk::Color<float,4> esvg::render::DynamicColorSpecial::getColorRadial(const ivec2& _pos) const {
|
||||
float ratio = 0.0f;
|
||||
// in the basic vertion of the gradient the color is calculated with the ration in X and Y in the bonding box associated (it is rotate with the object)..
|
||||
vec2 intersecX = getIntersect(m_pos1, m_axeX,
|
||||
vec2(_pos.x(), _pos.y()), m_axeY);
|
||||
vec2 intersecY = getIntersect(m_pos1, m_axeY,
|
||||
vec2(_pos.x(), _pos.y()), m_axeX);
|
||||
vec2 vectorBaseDrawX = intersecX - m_pos1;
|
||||
vec2 vectorBaseDrawY = intersecY - m_pos1;
|
||||
float baseDrawX = vectorBaseDrawX.length();
|
||||
float baseDrawY = vectorBaseDrawY.length();
|
||||
// specal case when focal == center (this is faster ...)
|
||||
if (m_centerIsFocal == true) {
|
||||
ratio = vec2(baseDrawX, baseDrawY).length();
|
||||
if (m_baseSize.x()+m_baseSize.y() != 0.0f) {
|
||||
if ( m_baseSize.x() != 0.0f
|
||||
&& m_baseSize.y() != 0.0f) {
|
||||
ratio = vec2(baseDrawX/m_baseSize.x(), baseDrawY/m_baseSize.y()).length();
|
||||
} else if (m_baseSize.x() != 0.0f) {
|
||||
ratio = baseDrawX/m_baseSize.x();
|
||||
} else {
|
||||
ratio = baseDrawY/m_baseSize.y();
|
||||
}
|
||||
} else {
|
||||
ratio = 1.0f;
|
||||
}
|
||||
} else {
|
||||
// set the sense of the elements:
|
||||
if (m_axeX.dot(vectorBaseDrawX) < 0) {
|
||||
baseDrawX *= -1.0f;
|
||||
}
|
||||
if (m_axeY.dot(vectorBaseDrawY) < 0) {
|
||||
baseDrawY *= -1.0f;
|
||||
}
|
||||
if (m_baseSize.y() != 0.0f) {
|
||||
baseDrawY /= m_baseSize.y();
|
||||
}
|
||||
// normalize to 1.0f
|
||||
baseDrawX /= m_baseSize.x();
|
||||
if ( m_clipOut == true
|
||||
&& baseDrawX <= -1.0f) {
|
||||
ratio = 1.0f;
|
||||
} else {
|
||||
float tmpLength = -m_focalLength/m_baseSize.x();
|
||||
vec2 focalCenter = vec2(tmpLength, 0.0f);
|
||||
vec2 currentPoint = vec2(baseDrawX, baseDrawY);
|
||||
if (focalCenter == currentPoint) {
|
||||
ratio = 0.0f;
|
||||
} else {
|
||||
etk::Pair<vec2,vec2> positions = intersectLineToCircle(focalCenter, currentPoint);
|
||||
float lenghtBase = (currentPoint - focalCenter).length();
|
||||
float lenghtBorder1 = (positions.first - focalCenter).length();
|
||||
float lenghtBorder2 = (positions.second - focalCenter).length();
|
||||
ratio = lenghtBase/lenghtBorder1;
|
||||
}
|
||||
}
|
||||
}
|
||||
switch(m_spread) {
|
||||
case spreadMethod_pad:
|
||||
// nothing to do ...
|
||||
break;
|
||||
case spreadMethod_reflect:
|
||||
ratio -= float((int32_t(ratio)>>1)<<1);
|
||||
if (ratio > 1.0f) {
|
||||
ratio = 2.0f-ratio;
|
||||
}
|
||||
break;
|
||||
case spreadMethod_repeat:
|
||||
ratio -= float(int32_t(ratio));
|
||||
if (ratio <0.0f) {
|
||||
#ifndef __STDCPP_LLVM__
|
||||
ratio = 1.0f-etk::abs(ratio);
|
||||
#else
|
||||
ratio = 1.0f-abs(ratio);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (ratio <= m_data[0].first*0.01f) {
|
||||
return m_data[0].second;
|
||||
}
|
||||
if (ratio >= m_data.back().first*0.01f) {
|
||||
return m_data.back().second;
|
||||
}
|
||||
for (size_t iii=1; iii<m_data.size(); ++iii) {
|
||||
if (ratio <= m_data[iii].first*0.01f) {
|
||||
float localRatio = ratio - m_data[iii-1].first*0.01f;
|
||||
localRatio = localRatio / ((m_data[iii].first - m_data[iii-1].first) * 0.01f);
|
||||
return etk::Color<float,4>(m_data[iii-1].second.r() * (1.0-localRatio) + m_data[iii].second.r() * localRatio,
|
||||
m_data[iii-1].second.g() * (1.0-localRatio) + m_data[iii].second.g() * localRatio,
|
||||
m_data[iii-1].second.b() * (1.0-localRatio) + m_data[iii].second.b() * localRatio,
|
||||
m_data[iii-1].second.a() * (1.0-localRatio) + m_data[iii].second.a() * localRatio);
|
||||
}
|
||||
}
|
||||
return etk::color::green;
|
||||
}
|
||||
|
||||
|
||||
void esvg::render::DynamicColorSpecial::generate(esvg::Document* _document) {
|
||||
if (_document == null) {
|
||||
Log.error("Get null input for document");
|
||||
return;
|
||||
}
|
||||
ememory::SharedPtr<esvg::Base> base = _document->getReference(m_colorName);
|
||||
if (base == null) {
|
||||
Log.error("Can not get base : '" << m_colorName << "'");
|
||||
return;
|
||||
}
|
||||
// Now we can know if we use linear or radial gradient ...
|
||||
ememory::SharedPtr<esvg::LinearGradient> gradient = ememory::dynamicPointerCast<esvg::LinearGradient>(base);
|
||||
if (gradient != null) {
|
||||
m_linear = true;
|
||||
Log.verbose("get for color linear:");
|
||||
gradient->display(2);
|
||||
m_unit = gradient->m_unit;
|
||||
m_spread = gradient->m_spread;
|
||||
Log.verbose(" viewport = {" << m_viewPort.first << "," << m_viewPort.second << "}");
|
||||
vec2 size = m_viewPort.second - m_viewPort.first;
|
||||
|
||||
esvg::Dimension dimPos1 = gradient->getPosition1();
|
||||
m_pos1 = dimPos1.getPixel(size);
|
||||
if (dimPos1.getType() == esvg::distance_pourcent) {
|
||||
m_pos1 += m_viewPort.first;
|
||||
}
|
||||
esvg::Dimension dimPos2 = gradient->getPosition2();
|
||||
m_pos2 = dimPos2.getPixel(size);
|
||||
if (dimPos2.getType() == esvg::distance_pourcent) {
|
||||
m_pos2 += m_viewPort.first;
|
||||
}
|
||||
// in the basic vertion of the gradient the color is calculated with the ration in X and Y in the bonding box associated (it is rotate with the object..
|
||||
vec2 delta = m_pos2 - m_pos1;
|
||||
if (delta.x() < 0.0f) {
|
||||
m_axeX = vec2(-1.0f, 0.0f);
|
||||
} else {
|
||||
m_axeX = vec2(1.0f, 0.0f);
|
||||
}
|
||||
if (delta.y() < 0.0f) {
|
||||
m_axeY = vec2(0.0f, -1.0f);
|
||||
} else {
|
||||
m_axeY = vec2(0.0f, 1.0f);
|
||||
}
|
||||
// Move the positions ...
|
||||
m_pos1 = m_matrix * m_pos1;
|
||||
m_pos2 = m_matrix * m_pos2;
|
||||
m_axeX = m_matrix.applyScaleRotation(m_axeX);
|
||||
m_axeY = m_matrix.applyScaleRotation(m_axeY);
|
||||
// in the basic vertion of the gradient the color is calculated with the ration in X and Y in the bonding box associated (it is rotate with the object..
|
||||
vec2 intersecX = getIntersect(m_pos1, m_axeX,
|
||||
m_pos2, m_axeY);
|
||||
vec2 intersecY = getIntersect(m_pos1, m_axeY,
|
||||
m_pos2, m_axeX);
|
||||
m_baseSize = vec2((m_pos1 - intersecX).length(),
|
||||
(m_pos1 - intersecY).length());
|
||||
// get all the colors
|
||||
m_data = gradient->getColors(_document);
|
||||
} else {
|
||||
m_linear = false;
|
||||
ememory::SharedPtr<esvg::RadialGradient> gradient = ememory::dynamicPointerCast<esvg::RadialGradient>(base);
|
||||
if (gradient == null) {
|
||||
Log.error("Can not cast in a linear gradient: '" << m_colorName << "' ==> wrong type");
|
||||
return;
|
||||
}
|
||||
Log.verbose("get for color Radial:");
|
||||
gradient->display(2);
|
||||
m_unit = gradient->m_unit;
|
||||
m_spread = gradient->m_spread;
|
||||
Log.verbose(" viewport = {" << m_viewPort.first << "," << m_viewPort.second << "}");
|
||||
vec2 size = m_viewPort.second - m_viewPort.first;
|
||||
|
||||
esvg::Dimension dimCenter = gradient->getCenter();
|
||||
vec2 center = dimCenter.getPixel(size);
|
||||
if (dimCenter.getType() == esvg::distance_pourcent) {
|
||||
center += m_viewPort.first;
|
||||
}
|
||||
esvg::Dimension dimFocal = gradient->getFocal();
|
||||
vec2 focal = dimFocal.getPixel(size);
|
||||
if (dimFocal.getType() == esvg::distance_pourcent) {
|
||||
focal += m_viewPort.first;
|
||||
}
|
||||
esvg::Dimension1D dimRadius = gradient->getRadius();
|
||||
// in the basic vertion of the gradient the color is calculated with the ration in X and Y in the bonding box associated (it is rotate with the object)..
|
||||
if (center == focal) {
|
||||
m_centerIsFocal = true;
|
||||
m_pos2.setX(dimRadius.getPixel(size.x()));
|
||||
m_pos2.setY(dimRadius.getPixel(size.y()));
|
||||
m_pos2 += center;
|
||||
vec2 delta = center - m_pos2;
|
||||
if (delta.x() < 0.0f) {
|
||||
m_axeX = vec2(-1.0f, 0.0f);
|
||||
} else {
|
||||
m_axeX = vec2(1.0f, 0.0f);
|
||||
}
|
||||
if (delta.y() < 0.0f) {
|
||||
m_axeY = vec2(0.0f, -1.0f);
|
||||
} else {
|
||||
m_axeY = vec2(0.0f, 1.0f);
|
||||
}
|
||||
m_pos1 = center;
|
||||
} else {
|
||||
m_centerIsFocal = false;
|
||||
m_axeX = (center - focal).safeNormalize();
|
||||
m_axeY = vec2(m_axeX.y(), -m_axeX.x());
|
||||
|
||||
m_pos2 = m_axeX * dimRadius.getPixel(size.x()) + m_axeY * dimRadius.getPixel(size.y());
|
||||
m_pos2 += center;
|
||||
m_pos1 = center;
|
||||
}
|
||||
// Move the positions ...
|
||||
m_pos1 = m_matrix * m_pos1;
|
||||
center = m_matrix * center;
|
||||
m_pos2 = m_matrix * m_pos2;
|
||||
m_axeX = m_matrix.applyScaleRotation(m_axeX);
|
||||
m_axeY = m_matrix.applyScaleRotation(m_axeY);
|
||||
// in the basic vertion of the gradient the color is calculated with the ration in X and Y in the bonding box associated (it is rotate with the object..
|
||||
vec2 intersecX = getIntersect(m_pos1, m_axeX,
|
||||
m_pos2, m_axeY);
|
||||
vec2 intersecY = getIntersect(m_pos1, m_axeY,
|
||||
m_pos2, m_axeX);
|
||||
m_baseSize = vec2((intersecX - m_pos1).length(),
|
||||
(intersecY - m_pos1).length());
|
||||
if (m_centerIsFocal == false) {
|
||||
m_focalLength = (center - m_matrix * focal).length();
|
||||
if (m_focalLength >= m_baseSize.x()) {
|
||||
Log.debug("Change position of the Focal ... ==> set it inside the circle");
|
||||
m_focalLength = m_baseSize.x()*0.999998f;
|
||||
m_clipOut = true;
|
||||
} else {
|
||||
m_clipOut = false;
|
||||
}
|
||||
}
|
||||
Log.verbose("baseSize=" << m_baseSize << " m_pos1=" << m_pos1 << " dim=" << dimCenter << " m_focal=" << m_focal << " m_pos2=" << m_pos2 << " dim=" << dimRadius);
|
||||
// get all the colors
|
||||
m_data = gradient->getColors(_document);
|
||||
}
|
||||
}
|
||||
|
||||
ememory::SharedPtr<esvg::render::DynamicColor> esvg::render::createColor(etk::Pair<etk::Color<float,4>, etk::String> _color, const mat2x3& _mtx) {
|
||||
// Check if need to create a color:
|
||||
if ( _color.first.a() == 0x00
|
||||
&& _color.second == "") {
|
||||
return null;
|
||||
}
|
||||
if (_color.second != "") {
|
||||
return ememory::makeShared<esvg::render::DynamicColorSpecial>(_color.second, _mtx);
|
||||
}
|
||||
return ememory::makeShared<esvg::render::DynamicColorUni>(_color.first);
|
||||
}
|
80
src/org/atriasoft/esvg/render/DynamicColor.java
Normal file
80
src/org/atriasoft/esvg/render/DynamicColor.java
Normal file
@ -0,0 +1,80 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <ememory/memory.hpp>
|
||||
#include <etk/types.hpp>
|
||||
#include <etk/Pair.hpp>
|
||||
#include <etk/Color.hpp>
|
||||
#include <etk/math/Vector2D.hpp>
|
||||
#include <etk/math/Matrix2x3.hpp>
|
||||
#include <esvg/gradientUnits.hpp>
|
||||
#include <esvg/spreadMethod.hpp>
|
||||
|
||||
namespace esvg {
|
||||
class Document;
|
||||
namespace render {
|
||||
class DynamicColor {
|
||||
public:
|
||||
DynamicColor() {
|
||||
// nothing to do ...
|
||||
}
|
||||
virtual ~DynamicColor() {};
|
||||
virtual etk::Color<float,4> getColor(const ivec2& _pos) const = 0;
|
||||
virtual void generate(esvg::Document* _document) = 0;
|
||||
virtual void setViewPort(const etk::Pair<vec2, vec2>& _viewPort) = 0;
|
||||
};
|
||||
class DynamicColorUni : public esvg::render::DynamicColor {
|
||||
public:
|
||||
etk::Color<float,4> m_color;
|
||||
public:
|
||||
DynamicColorUni(const etk::Color<float,4>& _color) :
|
||||
m_color(_color) {
|
||||
|
||||
}
|
||||
virtual etk::Color<float,4> getColor(const ivec2& _pos) const {
|
||||
return m_color;
|
||||
}
|
||||
virtual void generate(esvg::Document* _document) {
|
||||
// nothing to do ...
|
||||
}
|
||||
virtual void setViewPort(const etk::Pair<vec2, vec2>& _viewPort) {
|
||||
// nothing to do ...
|
||||
};
|
||||
};
|
||||
class DynamicColorSpecial : public esvg::render::DynamicColor {
|
||||
public:
|
||||
bool m_linear;
|
||||
esvg::spreadMethod m_spread;
|
||||
esvg::gradientUnits m_unit;
|
||||
etk::String m_colorName;
|
||||
mat2x3 m_matrix;
|
||||
etk::Pair<vec2, vec2> m_viewPort;
|
||||
vec2 m_pos1; // in radius ==> center
|
||||
vec2 m_pos2; // in radius ==> radius end position
|
||||
vec2 m_focal; // Specific radius
|
||||
vec2 m_axeX;
|
||||
vec2 m_axeY;
|
||||
vec2 m_baseSize;
|
||||
float m_focalLength;
|
||||
bool m_clipOut;
|
||||
bool m_centerIsFocal;
|
||||
etk::Vector<etk::Pair<float, etk::Color<float,4>>> m_data;
|
||||
public:
|
||||
DynamicColorSpecial(const etk::String& _link, const mat2x3& _mtx);
|
||||
virtual etk::Color<float,4> getColor(const ivec2& _pos) const;
|
||||
private:
|
||||
etk::Color<float,4> getColorLinear(const ivec2& _pos) const;
|
||||
etk::Color<float,4> getColorRadial(const ivec2& _pos) const;
|
||||
public:
|
||||
virtual void generate(esvg::Document* _document);
|
||||
virtual void setViewPort(const etk::Pair<vec2, vec2>& _viewPort);
|
||||
};
|
||||
|
||||
ememory::SharedPtr<DynamicColor> createColor(etk::Pair<etk::Color<float,4>, etk::String> _color, const mat2x3& _mtx);
|
||||
}
|
||||
}
|
||||
|
57
src/org/atriasoft/esvg/render/Element.cpp
Normal file
57
src/org/atriasoft/esvg/render/Element.cpp
Normal file
@ -0,0 +1,57 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <esvg/render/Element.hpp>
|
||||
#include <esvg/debug.hpp>
|
||||
|
||||
etk::Stream& esvg::operator <<(etk::Stream& _os, enum esvg::render::path _obj) {
|
||||
switch (_obj) {
|
||||
case esvg::render::path_stop:
|
||||
_os << "path_stop";
|
||||
break;
|
||||
case esvg::render::path_close:
|
||||
_os << "path_close";
|
||||
break;
|
||||
case esvg::render::path_moveTo:
|
||||
_os << "path_moveTo";
|
||||
break;
|
||||
case esvg::render::path_lineTo:
|
||||
_os << "path_lineTo";
|
||||
break;
|
||||
case esvg::render::path_lineToH:
|
||||
_os << "path_lineToH";
|
||||
break;
|
||||
case esvg::render::path_lineToV:
|
||||
_os << "path_lineToV";
|
||||
break;
|
||||
case esvg::render::path_curveTo:
|
||||
_os << "path_curveTo";
|
||||
break;
|
||||
case esvg::render::path_smoothCurveTo:
|
||||
_os << "path_smoothCurveTo";
|
||||
break;
|
||||
case esvg::render::path_bezierCurveTo:
|
||||
_os << "path_bezierCurveTo";
|
||||
break;
|
||||
case esvg::render::path_bezierSmoothCurveTo:
|
||||
_os << "path_bezierSmoothCurveTo";
|
||||
break;
|
||||
case esvg::render::path_elliptic:
|
||||
_os << "path_elliptic";
|
||||
break;
|
||||
default:
|
||||
_os << "????";
|
||||
break;
|
||||
};
|
||||
return _os;
|
||||
}
|
||||
etk::Stream& esvg::operator <<(etk::Stream& _os, const esvg::render::Element& _obj) {
|
||||
_os << _obj.getType();
|
||||
_os << ": rel=" << etk::toString(_obj.getRelative()) << " ";
|
||||
_os << _obj.display();
|
||||
return _os;
|
||||
}
|
||||
|
101
src/org/atriasoft/esvg/render/Element.java
Normal file
101
src/org/atriasoft/esvg/render/Element.java
Normal file
@ -0,0 +1,101 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <etk/types.hpp>
|
||||
#include <etk/math/Vector2D.hpp>
|
||||
|
||||
namespace esvg {
|
||||
namespace render {
|
||||
enum path {
|
||||
path_stop,
|
||||
path_close,
|
||||
path_moveTo,
|
||||
path_lineTo,
|
||||
path_lineToH,
|
||||
path_lineToV,
|
||||
path_curveTo,
|
||||
path_smoothCurveTo,
|
||||
path_bezierCurveTo,
|
||||
path_bezierSmoothCurveTo,
|
||||
path_elliptic
|
||||
};
|
||||
class Element {
|
||||
public:
|
||||
Element(enum path _type, bool _relative=false) :
|
||||
m_cmd(_type),
|
||||
m_relative(_relative) {
|
||||
|
||||
}
|
||||
virtual ~Element() { }
|
||||
private:
|
||||
enum path m_cmd;
|
||||
public:
|
||||
enum path getType() const {
|
||||
return m_cmd;
|
||||
}
|
||||
protected:
|
||||
bool m_relative;
|
||||
public:
|
||||
bool getRelative() const {
|
||||
return m_relative;
|
||||
}
|
||||
void setRelative(bool _relative) {
|
||||
m_relative = _relative;
|
||||
}
|
||||
protected:
|
||||
vec2 m_pos;
|
||||
public:
|
||||
const vec2& getPos() const {
|
||||
return m_pos;
|
||||
}
|
||||
void setPos(const vec2& _val) {
|
||||
m_pos = _val;
|
||||
}
|
||||
protected:
|
||||
vec2 m_pos1;
|
||||
public:
|
||||
const vec2& getPos1() const {
|
||||
return m_pos1;
|
||||
}
|
||||
void setPos1(const vec2& _val) {
|
||||
m_pos1 = _val;
|
||||
}
|
||||
protected:
|
||||
vec2 m_pos2;
|
||||
public:
|
||||
const vec2& getPos2() const {
|
||||
return m_pos2;
|
||||
}
|
||||
void setPos2(const vec2& _val) {
|
||||
m_pos2 = _val;
|
||||
}
|
||||
public:
|
||||
virtual etk::String display() const = 0;
|
||||
};
|
||||
}
|
||||
/**
|
||||
* @brief Debug operator To display the curent element in a Human redeable information
|
||||
*/
|
||||
etk::Stream& operator <<(etk::Stream& _os, const esvg::render::Element& _obj);
|
||||
/**
|
||||
* @brief Debug operator To display the curent element in a Human redeable information
|
||||
*/
|
||||
etk::Stream& operator <<(etk::Stream& _os, enum esvg::render::path _obj);
|
||||
}
|
||||
|
||||
#include <esvg/render/ElementStop.hpp>
|
||||
#include <esvg/render/ElementClose.hpp>
|
||||
#include <esvg/render/ElementMoveTo.hpp>
|
||||
#include <esvg/render/ElementLineTo.hpp>
|
||||
#include <esvg/render/ElementLineToH.hpp>
|
||||
#include <esvg/render/ElementLineToV.hpp>
|
||||
#include <esvg/render/ElementCurveTo.hpp>
|
||||
#include <esvg/render/ElementSmoothCurveTo.hpp>
|
||||
#include <esvg/render/ElementBezierCurveTo.hpp>
|
||||
#include <esvg/render/ElementBezierSmoothCurveTo.hpp>
|
||||
#include <esvg/render/ElementElliptic.hpp>
|
||||
|
18
src/org/atriasoft/esvg/render/ElementBezierCurveTo.cpp
Normal file
18
src/org/atriasoft/esvg/render/ElementBezierCurveTo.cpp
Normal file
@ -0,0 +1,18 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <esvg/render/Element.hpp>
|
||||
#include <esvg/debug.hpp>
|
||||
|
||||
esvg::render::ElementBezierCurveTo::ElementBezierCurveTo(bool _relative, const vec2& _pos1, const vec2& _pos):
|
||||
Element(esvg::render::path_bezierCurveTo, _relative) {
|
||||
m_pos = _pos;
|
||||
m_pos1 = _pos1;
|
||||
}
|
||||
|
||||
etk::String esvg::render::ElementBezierCurveTo::display() const {
|
||||
return etk::String("pos=") + etk::toString(m_pos) + " pos1=" + etk::toString(m_pos1);
|
||||
}
|
22
src/org/atriasoft/esvg/render/ElementBezierCurveTo.java
Normal file
22
src/org/atriasoft/esvg/render/ElementBezierCurveTo.java
Normal file
@ -0,0 +1,22 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <etk/types.hpp>
|
||||
#include <etk/math/Vector2D.hpp>
|
||||
#include <esvg/render/Element.hpp>
|
||||
|
||||
namespace esvg {
|
||||
namespace render {
|
||||
class ElementBezierCurveTo : public esvg::render::Element {
|
||||
public:
|
||||
ElementBezierCurveTo(bool _relative, const vec2& _pos1, const vec2& _pos);
|
||||
public:
|
||||
virtual etk::String display() const;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
18
src/org/atriasoft/esvg/render/ElementBezierSmoothCurveTo.cpp
Normal file
18
src/org/atriasoft/esvg/render/ElementBezierSmoothCurveTo.cpp
Normal file
@ -0,0 +1,18 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <esvg/render/Element.hpp>
|
||||
#include <esvg/debug.hpp>
|
||||
|
||||
esvg::render::ElementBezierSmoothCurveTo::ElementBezierSmoothCurveTo(bool _relative, const vec2& _pos):
|
||||
Element(esvg::render::path_bezierSmoothCurveTo, _relative) {
|
||||
m_pos = _pos;
|
||||
}
|
||||
|
||||
|
||||
etk::String esvg::render::ElementBezierSmoothCurveTo::display() const {
|
||||
return etk::String("pos=") + etk::toString(m_pos);
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <etk/types.hpp>
|
||||
#include <etk/math/Vector2D.hpp>
|
||||
#include <esvg/render/Element.hpp>
|
||||
|
||||
namespace esvg {
|
||||
namespace render {
|
||||
class ElementBezierSmoothCurveTo : public esvg::render::Element {
|
||||
public:
|
||||
ElementBezierSmoothCurveTo(bool _relative, const vec2& _pos);
|
||||
public:
|
||||
virtual etk::String display() const;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
19
src/org/atriasoft/esvg/render/ElementClose.cpp
Normal file
19
src/org/atriasoft/esvg/render/ElementClose.cpp
Normal file
@ -0,0 +1,19 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <esvg/render/Element.hpp>
|
||||
#include <esvg/debug.hpp>
|
||||
|
||||
esvg::render::ElementClose::ElementClose(bool _relative):
|
||||
Element(esvg::render::path_close, _relative) {
|
||||
|
||||
}
|
||||
|
||||
etk::String esvg::render::ElementClose::display() const {
|
||||
return "";
|
||||
}
|
||||
|
||||
|
22
src/org/atriasoft/esvg/render/ElementClose.java
Normal file
22
src/org/atriasoft/esvg/render/ElementClose.java
Normal file
@ -0,0 +1,22 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <etk/types.hpp>
|
||||
#include <etk/math/Vector2D.hpp>
|
||||
#include <esvg/render/Element.hpp>
|
||||
|
||||
namespace esvg {
|
||||
namespace render {
|
||||
class ElementClose : public esvg::render::Element {
|
||||
public:
|
||||
ElementClose(bool _relative=false);
|
||||
public:
|
||||
virtual etk::String display() const;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
21
src/org/atriasoft/esvg/render/ElementCurveTo.cpp
Normal file
21
src/org/atriasoft/esvg/render/ElementCurveTo.cpp
Normal file
@ -0,0 +1,21 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <esvg/render/Element.hpp>
|
||||
#include <esvg/debug.hpp>
|
||||
|
||||
esvg::render::ElementCurveTo::ElementCurveTo(bool _relative, const vec2& _pos1, const vec2& _pos2, const vec2& _pos):
|
||||
Element(esvg::render::path_curveTo, _relative) {
|
||||
m_pos = _pos;
|
||||
m_pos1 = _pos1;
|
||||
m_pos2 = _pos2;
|
||||
}
|
||||
|
||||
|
||||
|
||||
etk::String esvg::render::ElementCurveTo::display() const {
|
||||
return etk::String("pos=") + etk::toString(m_pos) + " pos1=" + etk::toString(m_pos1) + " pos2=" + etk::toString(m_pos2);
|
||||
}
|
21
src/org/atriasoft/esvg/render/ElementCurveTo.java
Normal file
21
src/org/atriasoft/esvg/render/ElementCurveTo.java
Normal file
@ -0,0 +1,21 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <etk/types.hpp>
|
||||
#include <etk/math/Vector2D.hpp>
|
||||
#include <esvg/render/Element.hpp>
|
||||
|
||||
namespace esvg {
|
||||
namespace render {
|
||||
class ElementCurveTo : public esvg::render::Element {
|
||||
public:
|
||||
ElementCurveTo(bool _relative, const vec2& _pos1, const vec2& _pos2, const vec2& _pos);
|
||||
public:
|
||||
virtual etk::String display() const;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
31
src/org/atriasoft/esvg/render/ElementElliptic.cpp
Normal file
31
src/org/atriasoft/esvg/render/ElementElliptic.cpp
Normal file
@ -0,0 +1,31 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <esvg/render/Element.hpp>
|
||||
#include <esvg/debug.hpp>
|
||||
|
||||
esvg::render::ElementElliptic::ElementElliptic(bool _relative,
|
||||
const vec2& _radius, // in m_vec1
|
||||
float _angle,
|
||||
bool _largeArcFlag,
|
||||
bool _sweepFlag,
|
||||
const vec2& _pos):
|
||||
Element(esvg::render::path_elliptic, _relative) {
|
||||
m_pos1 = _radius;
|
||||
m_pos = _pos;
|
||||
m_angle = _angle;
|
||||
m_largeArcFlag = _largeArcFlag;
|
||||
m_sweepFlag = _sweepFlag;
|
||||
}
|
||||
|
||||
|
||||
etk::String esvg::render::ElementElliptic::display() const {
|
||||
return etk::String("pos=") + etk::toString(m_pos)
|
||||
+ " radius=" + etk::toString(m_pos1)
|
||||
+ " angle=" + etk::toString(m_angle)
|
||||
+ " largeArcFlag=" + etk::toString(m_largeArcFlag)
|
||||
+ " sweepFlag=" + etk::toString(m_sweepFlag);
|
||||
}
|
31
src/org/atriasoft/esvg/render/ElementElliptic.java
Normal file
31
src/org/atriasoft/esvg/render/ElementElliptic.java
Normal file
@ -0,0 +1,31 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <etk/types.hpp>
|
||||
#include <etk/math/Vector2D.hpp>
|
||||
#include <esvg/render/Element.hpp>
|
||||
|
||||
namespace esvg {
|
||||
namespace render {
|
||||
class ElementElliptic : public esvg::render::Element {
|
||||
public:
|
||||
float m_angle;
|
||||
bool m_largeArcFlag;
|
||||
bool m_sweepFlag;
|
||||
public:
|
||||
ElementElliptic(bool _relative,
|
||||
const vec2& _radius, // in m_pos1
|
||||
float _angle,
|
||||
bool _largeArcFlag,
|
||||
bool _sweepFlag,
|
||||
const vec2& _pos);
|
||||
public:
|
||||
virtual etk::String display() const;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
18
src/org/atriasoft/esvg/render/ElementLineTo.cpp
Normal file
18
src/org/atriasoft/esvg/render/ElementLineTo.cpp
Normal file
@ -0,0 +1,18 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <esvg/render/Element.hpp>
|
||||
#include <esvg/debug.hpp>
|
||||
|
||||
esvg::render::ElementLineTo::ElementLineTo(bool _relative, const vec2& _pos):
|
||||
Element(esvg::render::path_lineTo, _relative) {
|
||||
m_pos = _pos;
|
||||
}
|
||||
|
||||
|
||||
etk::String esvg::render::ElementLineTo::display() const {
|
||||
return etk::String("pos=") + etk::toString(m_pos);
|
||||
}
|
22
src/org/atriasoft/esvg/render/ElementLineTo.java
Normal file
22
src/org/atriasoft/esvg/render/ElementLineTo.java
Normal file
@ -0,0 +1,22 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <etk/types.hpp>
|
||||
#include <etk/math/Vector2D.hpp>
|
||||
#include <esvg/render/Element.hpp>
|
||||
|
||||
namespace esvg {
|
||||
namespace render {
|
||||
class ElementLineTo : public esvg::render::Element {
|
||||
public:
|
||||
ElementLineTo(bool _relative, const vec2& _pos);
|
||||
public:
|
||||
virtual etk::String display() const;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
18
src/org/atriasoft/esvg/render/ElementLineToH.cpp
Normal file
18
src/org/atriasoft/esvg/render/ElementLineToH.cpp
Normal file
@ -0,0 +1,18 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <esvg/render/Element.hpp>
|
||||
#include <esvg/debug.hpp>
|
||||
|
||||
esvg::render::ElementLineToH::ElementLineToH(bool _relative, float _posX):
|
||||
Element(esvg::render::path_lineToH, _relative) {
|
||||
m_pos = vec2(_posX, 0.0f);
|
||||
}
|
||||
|
||||
|
||||
etk::String esvg::render::ElementLineToH::display() const {
|
||||
return etk::String("posX=") + etk::toString(m_pos.x());
|
||||
}
|
22
src/org/atriasoft/esvg/render/ElementLineToH.java
Normal file
22
src/org/atriasoft/esvg/render/ElementLineToH.java
Normal file
@ -0,0 +1,22 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <etk/types.hpp>
|
||||
#include <etk/math/Vector2D.hpp>
|
||||
#include <esvg/render/Element.hpp>
|
||||
|
||||
namespace esvg {
|
||||
namespace render {
|
||||
class ElementLineToH : public esvg::render::Element {
|
||||
public:
|
||||
ElementLineToH(bool _relative, float _posX);
|
||||
public:
|
||||
virtual etk::String display() const;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
18
src/org/atriasoft/esvg/render/ElementLineToV.cpp
Normal file
18
src/org/atriasoft/esvg/render/ElementLineToV.cpp
Normal file
@ -0,0 +1,18 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <esvg/render/Element.hpp>
|
||||
#include <esvg/debug.hpp>
|
||||
|
||||
esvg::render::ElementLineToV::ElementLineToV(bool _relative, float _posY):
|
||||
Element(esvg::render::path_lineToV, _relative) {
|
||||
m_pos = vec2(0.0f, _posY);
|
||||
}
|
||||
|
||||
|
||||
etk::String esvg::render::ElementLineToV::display() const {
|
||||
return etk::String("posY=") + etk::toString(m_pos.y());
|
||||
}
|
23
src/org/atriasoft/esvg/render/ElementLineToV.java
Normal file
23
src/org/atriasoft/esvg/render/ElementLineToV.java
Normal file
@ -0,0 +1,23 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <etk/types.hpp>
|
||||
#include <etk/math/Vector2D.hpp>
|
||||
#include <esvg/render/Element.hpp>
|
||||
|
||||
namespace esvg {
|
||||
namespace render {
|
||||
class ElementLineToV : public esvg::render::Element {
|
||||
public:
|
||||
ElementLineToV(bool _relative, float _posY);
|
||||
public:
|
||||
virtual etk::String display() const;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
18
src/org/atriasoft/esvg/render/ElementMoveTo.cpp
Normal file
18
src/org/atriasoft/esvg/render/ElementMoveTo.cpp
Normal file
@ -0,0 +1,18 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <esvg/render/Element.hpp>
|
||||
#include <esvg/debug.hpp>
|
||||
|
||||
esvg::render::ElementMoveTo::ElementMoveTo(bool _relative, const vec2& _pos):
|
||||
Element(esvg::render::path_moveTo, _relative) {
|
||||
m_pos = _pos;
|
||||
}
|
||||
|
||||
|
||||
etk::String esvg::render::ElementMoveTo::display() const {
|
||||
return etk::String("pos=") + etk::toString(m_pos);
|
||||
}
|
22
src/org/atriasoft/esvg/render/ElementMoveTo.java
Normal file
22
src/org/atriasoft/esvg/render/ElementMoveTo.java
Normal file
@ -0,0 +1,22 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <etk/types.hpp>
|
||||
#include <etk/math/Vector2D.hpp>
|
||||
#include <esvg/render/Element.hpp>
|
||||
|
||||
namespace esvg {
|
||||
namespace render {
|
||||
class ElementMoveTo : public esvg::render::Element {
|
||||
public:
|
||||
ElementMoveTo(bool _relative, const vec2& _pos);
|
||||
public:
|
||||
virtual etk::String display() const;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
19
src/org/atriasoft/esvg/render/ElementSmoothCurveTo.cpp
Normal file
19
src/org/atriasoft/esvg/render/ElementSmoothCurveTo.cpp
Normal file
@ -0,0 +1,19 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <esvg/render/Element.hpp>
|
||||
#include <esvg/debug.hpp>
|
||||
|
||||
esvg::render::ElementSmoothCurveTo::ElementSmoothCurveTo(bool _relative, const vec2& _pos2, const vec2& _pos):
|
||||
Element(esvg::render::path_smoothCurveTo, _relative) {
|
||||
m_pos = _pos;
|
||||
m_pos2 = _pos2;
|
||||
}
|
||||
|
||||
|
||||
etk::String esvg::render::ElementSmoothCurveTo::display() const {
|
||||
return etk::String("pos=") + etk::toString(m_pos) + " pos2=" + etk::toString(m_pos2);
|
||||
}
|
22
src/org/atriasoft/esvg/render/ElementSmoothCurveTo.java
Normal file
22
src/org/atriasoft/esvg/render/ElementSmoothCurveTo.java
Normal file
@ -0,0 +1,22 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <etk/types.hpp>
|
||||
#include <etk/math/Vector2D.hpp>
|
||||
#include <esvg/render/Element.hpp>
|
||||
|
||||
namespace esvg {
|
||||
namespace render {
|
||||
class ElementSmoothCurveTo : public esvg::render::Element {
|
||||
public:
|
||||
ElementSmoothCurveTo(bool _relative, const vec2& _pos2, const vec2& _pos);
|
||||
public:
|
||||
virtual etk::String display() const;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
19
src/org/atriasoft/esvg/render/ElementStop.cpp
Normal file
19
src/org/atriasoft/esvg/render/ElementStop.cpp
Normal file
@ -0,0 +1,19 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <esvg/render/Element.hpp>
|
||||
#include <esvg/debug.hpp>
|
||||
|
||||
esvg::render::ElementStop::ElementStop():
|
||||
Element(esvg::render::path_stop) {
|
||||
|
||||
}
|
||||
|
||||
etk::String esvg::render::ElementStop::display() const {
|
||||
return "";
|
||||
}
|
||||
|
||||
|
22
src/org/atriasoft/esvg/render/ElementStop.java
Normal file
22
src/org/atriasoft/esvg/render/ElementStop.java
Normal file
@ -0,0 +1,22 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <etk/types.hpp>
|
||||
#include <etk/math/Vector2D.hpp>
|
||||
#include <esvg/render/Element.hpp>
|
||||
|
||||
namespace esvg {
|
||||
namespace render {
|
||||
class ElementStop : public esvg::render::Element {
|
||||
public:
|
||||
ElementStop();
|
||||
public:
|
||||
virtual etk::String display() const;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
513
src/org/atriasoft/esvg/render/Path.cpp
Normal file
513
src/org/atriasoft/esvg/render/Path.cpp
Normal file
@ -0,0 +1,513 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#include <esvg/debug.hpp>
|
||||
#include <esvg/render/Path.hpp>
|
||||
#include <esvg/render/Element.hpp>
|
||||
|
||||
void esvg::render::Path::clear() {
|
||||
m_listElement.clear();
|
||||
}
|
||||
|
||||
void esvg::render::Path::stop() {
|
||||
m_listElement.pushBack(ememory::makeShared<esvg::render::ElementStop>());
|
||||
}
|
||||
|
||||
void esvg::render::Path::close(bool _relative) {
|
||||
m_listElement.pushBack(ememory::makeShared<esvg::render::ElementClose>(_relative));
|
||||
}
|
||||
|
||||
void esvg::render::Path::moveTo(bool _relative, const vec2& _pos) {
|
||||
m_listElement.pushBack(ememory::makeShared<esvg::render::ElementMoveTo>(_relative, _pos));
|
||||
}
|
||||
|
||||
void esvg::render::Path::lineTo(bool _relative, const vec2& _pos) {
|
||||
m_listElement.pushBack(ememory::makeShared<esvg::render::ElementLineTo>(_relative, _pos));
|
||||
}
|
||||
|
||||
void esvg::render::Path::lineToH(bool _relative, float _posX) {
|
||||
m_listElement.pushBack(ememory::makeShared<esvg::render::ElementLineToH>(_relative, _posX));
|
||||
}
|
||||
|
||||
void esvg::render::Path::lineToV(bool _relative, float _posY) {
|
||||
m_listElement.pushBack(ememory::makeShared<esvg::render::ElementLineToV>(_relative, _posY));
|
||||
}
|
||||
|
||||
void esvg::render::Path::curveTo(bool _relative, const vec2& _pos1, const vec2& _pos2, const vec2& _pos) {
|
||||
m_listElement.pushBack(ememory::makeShared<esvg::render::ElementCurveTo>(_relative, _pos1, _pos2, _pos));
|
||||
}
|
||||
|
||||
void esvg::render::Path::smoothCurveTo(bool _relative, const vec2& _pos2, const vec2& _pos) {
|
||||
m_listElement.pushBack(ememory::makeShared<esvg::render::ElementSmoothCurveTo>(_relative, _pos2, _pos));
|
||||
}
|
||||
|
||||
void esvg::render::Path::bezierCurveTo(bool _relative, const vec2& _pos1, const vec2& _pos) {
|
||||
m_listElement.pushBack(ememory::makeShared<esvg::render::ElementBezierCurveTo>(_relative, _pos1, _pos));
|
||||
}
|
||||
|
||||
void esvg::render::Path::bezierSmoothCurveTo(bool _relative, const vec2& _pos) {
|
||||
m_listElement.pushBack(ememory::makeShared<esvg::render::ElementBezierSmoothCurveTo>(_relative, _pos));
|
||||
}
|
||||
|
||||
void esvg::render::Path::ellipticTo(bool _relative,
|
||||
const vec2& _radius,
|
||||
float _angle,
|
||||
bool _largeArcFlag,
|
||||
bool _sweepFlag,
|
||||
const vec2& _pos) {
|
||||
m_listElement.pushBack(ememory::makeShared<esvg::render::ElementElliptic>(_relative, _radius, _angle, _largeArcFlag, _sweepFlag, _pos));
|
||||
}
|
||||
|
||||
static const char* spacingDist(int32_t _spacing) {
|
||||
static const char *tmpValue = " ";
|
||||
if (_spacing>20) {
|
||||
_spacing = 20;
|
||||
}
|
||||
return tmpValue + 20*4 - _spacing*4;
|
||||
}
|
||||
|
||||
void esvg::render::Path::display(int32_t _spacing) {
|
||||
Log.debug(spacingDist(_spacing) << "Path");
|
||||
for(auto &it : m_listElement) {
|
||||
if (it == null) {
|
||||
continue;
|
||||
}
|
||||
Log.debug(spacingDist(_spacing+1) << *it);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void interpolateCubicBezier(etk::Vector<esvg::render::Point>& _listPoint,
|
||||
int32_t _recurtionMax,
|
||||
float _threshold,
|
||||
vec2 _pos1,
|
||||
vec2 _pos2,
|
||||
vec2 _pos3,
|
||||
vec2 _pos4,
|
||||
int32_t _level,
|
||||
enum esvg::render::Point::type _type) {
|
||||
if (_level > _recurtionMax) {
|
||||
return;
|
||||
}
|
||||
vec2 pos12 = (_pos1+_pos2)*0.5f;
|
||||
vec2 pos23 = (_pos2+_pos3)*0.5f;
|
||||
vec2 pos34 = (_pos3+_pos4)*0.5f;
|
||||
|
||||
vec2 delta = _pos4 - _pos1;
|
||||
#ifndef __STDCPP_LLVM__
|
||||
float distance2 = etk::abs(((_pos2.x() - _pos4.x()) * delta.y() - (_pos2.y() - _pos4.y()) * delta.x() ));
|
||||
float distance3 = etk::abs(((_pos3.x() - _pos4.x()) * delta.y() - (_pos3.y() - _pos4.y()) * delta.x() ));
|
||||
#else
|
||||
float distance2 = fabs(((_pos2.x() - _pos4.x()) * delta.y() - (_pos2.y() - _pos4.y()) * delta.x() ));
|
||||
float distance3 = fabs(((_pos3.x() - _pos4.x()) * delta.y() - (_pos3.y() - _pos4.y()) * delta.x() ));
|
||||
#endif
|
||||
|
||||
if ((distance2 + distance3)*(distance2 + distance3) < _threshold * delta.length2()) {
|
||||
_listPoint.pushBack(esvg::render::Point(_pos4, _type) );
|
||||
return;
|
||||
}
|
||||
vec2 pos123 = (pos12+pos23)*0.5f;
|
||||
vec2 pos234 = (pos23+pos34)*0.5f;
|
||||
vec2 pos1234 = (pos123+pos234)*0.5f;
|
||||
|
||||
interpolateCubicBezier(_listPoint, _recurtionMax, _threshold, _pos1, pos12, pos123, pos1234, _level+1, esvg::render::Point::type::interpolation);
|
||||
interpolateCubicBezier(_listPoint, _recurtionMax, _threshold, pos1234, pos234, pos34, _pos4, _level+1, _type);
|
||||
}
|
||||
|
||||
static float vectorAngle(vec2 _uuu, vec2 _vvv) {
|
||||
_uuu.safeNormalize();
|
||||
_vvv.safeNormalize();
|
||||
return atan2(_uuu.cross(_vvv), _uuu.dot(_vvv));
|
||||
}
|
||||
|
||||
esvg::render::PointList esvg::render::Path::generateListPoints(int32_t _level, int32_t _recurtionMax, float _threshold) {
|
||||
Log.verbose(spacingDist(_level) << "Generate List Points ... from a path");
|
||||
esvg::render::PointList out;
|
||||
etk::Vector<esvg::render::Point> tmpListPoint;
|
||||
vec2 lastPosition(0.0f, 0.0f);
|
||||
vec2 lastAngle(0.0f, 0.0f);
|
||||
int32_t lastPointId = -1;
|
||||
bool PathStart = false;
|
||||
// Foreach element, we move in the path:
|
||||
for(auto &it : m_listElement) {
|
||||
if (it == null) {
|
||||
continue;
|
||||
}
|
||||
Log.verbose(spacingDist(_level+1) << " Draw : " << *it);
|
||||
switch (it->getType()) {
|
||||
case esvg::render::path_stop:
|
||||
if (tmpListPoint.size() != 0) {
|
||||
if (tmpListPoint.size() == 0) {
|
||||
Log.warning(spacingDist(_level+1) << " Request path stop of not starting path ...");
|
||||
} else {
|
||||
tmpListPoint.back().setEndPath();
|
||||
out.addList(tmpListPoint);
|
||||
tmpListPoint.clear();
|
||||
}
|
||||
}
|
||||
lastAngle = vec2(0.0f, 0.0f);
|
||||
// nothing alse to do ...
|
||||
break;
|
||||
case esvg::render::path_close:
|
||||
if (tmpListPoint.size() != 0) {
|
||||
if (tmpListPoint.size() == 0) {
|
||||
Log.warning(spacingDist(_level+1) << " Request path close of not starting path ...");
|
||||
} else {
|
||||
// find the previous tart of the path ...
|
||||
tmpListPoint.front().m_type = esvg::render::Point::type::join;
|
||||
// Remove the last point if it is the same position...
|
||||
vec2 delta = (tmpListPoint.front().m_pos - tmpListPoint.back().m_pos).absolute();
|
||||
if ( delta.x() <= 0.00001
|
||||
&& delta.y() <= 0.00001) {
|
||||
tmpListPoint.popBack();
|
||||
Log.verbose(" Remove point Z property : " << tmpListPoint.back().m_pos << " with delta=" << delta);
|
||||
}
|
||||
out.addList(tmpListPoint);
|
||||
tmpListPoint.clear();
|
||||
}
|
||||
}
|
||||
lastAngle = vec2(0.0f, 0.0f);
|
||||
// nothing alse to do ...
|
||||
break;
|
||||
case esvg::render::path_moveTo:
|
||||
// stop last path
|
||||
if (tmpListPoint.size() != 0) {
|
||||
tmpListPoint.back().setEndPath();
|
||||
out.addList(tmpListPoint);
|
||||
tmpListPoint.clear();
|
||||
}
|
||||
// create a new one
|
||||
if (it->getRelative() == false) {
|
||||
lastPosition = vec2(0.0f, 0.0f);
|
||||
}
|
||||
lastPosition += it->getPos();
|
||||
tmpListPoint.pushBack(esvg::render::Point(lastPosition, esvg::render::Point::type::start));
|
||||
lastAngle = lastPosition;
|
||||
break;
|
||||
case esvg::render::path_lineTo:
|
||||
// If no previous point, we need to create the last point has start ...
|
||||
if (tmpListPoint.size() == 0) {
|
||||
tmpListPoint.pushBack(esvg::render::Point(lastPosition, esvg::render::Point::type::start));
|
||||
}
|
||||
if (it->getRelative() == false) {
|
||||
lastPosition = vec2(0.0f, 0.0f);
|
||||
}
|
||||
lastPosition += it->getPos();
|
||||
tmpListPoint.pushBack(esvg::render::Point(lastPosition, esvg::render::Point::type::join));
|
||||
lastAngle = lastPosition;
|
||||
break;
|
||||
case esvg::render::path_lineToH:
|
||||
// If no previous point, we need to create the last point has start ...
|
||||
if (tmpListPoint.size() == 0) {
|
||||
tmpListPoint.pushBack(esvg::render::Point(lastPosition, esvg::render::Point::type::start));
|
||||
}
|
||||
if (it->getRelative() == false) {
|
||||
lastPosition = vec2(0.0f, 0.0f);
|
||||
}
|
||||
lastPosition += it->getPos();
|
||||
tmpListPoint.pushBack(esvg::render::Point(lastPosition, esvg::render::Point::type::join));
|
||||
lastAngle = lastPosition;
|
||||
break;
|
||||
case esvg::render::path_lineToV:
|
||||
// If no previous point, we need to create the last point has start ...
|
||||
if (tmpListPoint.size() == 0) {
|
||||
tmpListPoint.pushBack(esvg::render::Point(lastPosition, esvg::render::Point::type::start));
|
||||
}
|
||||
if (it->getRelative() == false) {
|
||||
lastPosition = vec2(0.0f, 0.0f);
|
||||
}
|
||||
lastPosition += it->getPos();
|
||||
tmpListPoint.pushBack(esvg::render::Point(lastPosition, esvg::render::Point::type::join));
|
||||
lastAngle = lastPosition;
|
||||
break;
|
||||
case esvg::render::path_curveTo:
|
||||
// If no previous point, we need to create the last point has start ...
|
||||
if (tmpListPoint.size() == 0) {
|
||||
tmpListPoint.pushBack(esvg::render::Point(lastPosition, esvg::render::Point::type::join));
|
||||
}
|
||||
{
|
||||
vec2 lastPosStore(lastPosition);
|
||||
if (it->getRelative() == false) {
|
||||
lastPosition = vec2(0.0f, 0.0f);
|
||||
}
|
||||
vec2 pos1 = lastPosition + it->getPos1();
|
||||
vec2 pos2 = lastPosition + it->getPos2();
|
||||
vec2 pos = lastPosition + it->getPos();
|
||||
interpolateCubicBezier(tmpListPoint,
|
||||
_recurtionMax,
|
||||
_threshold,
|
||||
lastPosStore,
|
||||
pos1,
|
||||
pos2,
|
||||
pos,
|
||||
0,
|
||||
esvg::render::Point::type::join);
|
||||
lastPosition = pos;
|
||||
lastAngle = pos2;
|
||||
}
|
||||
break;
|
||||
case esvg::render::path_smoothCurveTo:
|
||||
// If no previous point, we need to create the last point has start ...
|
||||
if (tmpListPoint.size() == 0) {
|
||||
tmpListPoint.pushBack(esvg::render::Point(lastPosition, esvg::render::Point::type::join));
|
||||
}
|
||||
{
|
||||
vec2 lastPosStore(lastPosition);
|
||||
if (it->getRelative() == false) {
|
||||
lastPosition = vec2(0.0f, 0.0f);
|
||||
}
|
||||
vec2 pos2 = lastPosition + it->getPos2();
|
||||
vec2 pos = lastPosition + it->getPos();
|
||||
// generate Pos 1
|
||||
vec2 pos1 = lastPosStore*2.0f - lastAngle;
|
||||
interpolateCubicBezier(tmpListPoint,
|
||||
_recurtionMax,
|
||||
_threshold,
|
||||
lastPosStore,
|
||||
pos1,
|
||||
pos2,
|
||||
pos,
|
||||
0,
|
||||
esvg::render::Point::type::join);
|
||||
lastPosition = pos;
|
||||
lastAngle = pos2;
|
||||
}
|
||||
break;
|
||||
case esvg::render::path_bezierCurveTo:
|
||||
// If no previous point, we need to create the last point has start ...
|
||||
if (tmpListPoint.size() == 0) {
|
||||
tmpListPoint.pushBack(esvg::render::Point(lastPosition, esvg::render::Point::type::join));
|
||||
}
|
||||
{
|
||||
vec2 lastPosStore(lastPosition);
|
||||
if (it->getRelative() == false) {
|
||||
lastPosition = vec2(0.0f, 0.0f);
|
||||
}
|
||||
vec2 pos = lastPosition + it->getPos();
|
||||
vec2 tmp1 = lastPosition + it->getPos1();
|
||||
// generate pos1 and pos2
|
||||
vec2 pos1 = lastPosStore + (tmp1 - lastPosStore)*0.666666666f;
|
||||
vec2 pos2 = pos + (tmp1 - pos)*0.666666666f;
|
||||
interpolateCubicBezier(tmpListPoint,
|
||||
_recurtionMax,
|
||||
_threshold,
|
||||
lastPosStore,
|
||||
pos1,
|
||||
pos2,
|
||||
pos,
|
||||
0,
|
||||
esvg::render::Point::type::join);
|
||||
lastPosition = pos;
|
||||
lastAngle = tmp1;
|
||||
}
|
||||
break;
|
||||
case esvg::render::path_bezierSmoothCurveTo:
|
||||
// If no previous point, we need to create the last point has start ...
|
||||
if (tmpListPoint.size() == 0) {
|
||||
tmpListPoint.pushBack(esvg::render::Point(lastPosition, esvg::render::Point::type::join));
|
||||
}
|
||||
{
|
||||
vec2 lastPosStore(lastPosition);
|
||||
if (it->getRelative() == false) {
|
||||
lastPosition = vec2(0.0f, 0.0f);
|
||||
}
|
||||
vec2 pos = lastPosition + it->getPos();
|
||||
vec2 tmp1 = lastPosStore*2.0f - lastAngle;
|
||||
// generate pos1 and pos2
|
||||
vec2 pos1 = lastPosStore + (tmp1 - lastPosStore)*0.666666666f;
|
||||
vec2 pos2 = pos + (tmp1 - pos)*0.66666666f;
|
||||
interpolateCubicBezier(tmpListPoint,
|
||||
_recurtionMax,
|
||||
_threshold,
|
||||
lastPosStore,
|
||||
pos1,
|
||||
pos2,
|
||||
pos,
|
||||
0,
|
||||
esvg::render::Point::type::join);
|
||||
lastPosition = pos;
|
||||
lastAngle = tmp1;
|
||||
}
|
||||
break;
|
||||
case esvg::render::path_elliptic:
|
||||
// If no previous point, we need to create the last point has start ...
|
||||
if (tmpListPoint.size() == 0) {
|
||||
tmpListPoint.pushBack(esvg::render::Point(lastPosition, esvg::render::Point::type::join));
|
||||
}
|
||||
{
|
||||
ememory::SharedPtr<esvg::render::ElementElliptic> tmpIt(ememory::dynamicPointerCast<esvg::render::ElementElliptic>(it));
|
||||
float angle = tmpIt->m_angle * (M_PI / 180.0);
|
||||
ESVG_TODO(spacingDist(_level+1) << " Elliptic arc: radius=" << tmpIt->getPos1());
|
||||
ESVG_TODO(spacingDist(_level+1) << " angle=" << tmpIt->m_angle);
|
||||
ESVG_TODO(spacingDist(_level+1) << " m_largeArcFlag=" << tmpIt->m_largeArcFlag);
|
||||
ESVG_TODO(spacingDist(_level+1) << " m_sweepFlag=" << tmpIt->m_sweepFlag);
|
||||
|
||||
|
||||
vec2 lastPosStore(lastPosition);
|
||||
if (it->getRelative() == false) {
|
||||
lastPosition = vec2(0.0f, 0.0f);
|
||||
}
|
||||
vec2 pos = lastPosition + it->getPos();
|
||||
float rotationX = tmpIt->m_angle * (M_PI / 180.0);
|
||||
vec2 radius = tmpIt->getPos1();
|
||||
|
||||
#ifdef DEBUG
|
||||
m_debugInformation.addSegment(lastPosStore, pos);
|
||||
#endif
|
||||
vec2 delta = lastPosStore - pos;
|
||||
float ddd = delta.length();
|
||||
if ( ddd < 1e-6f
|
||||
|| radius.x() < 1e-6f
|
||||
|| radius.y() < 1e-6f) {
|
||||
Log.warning("Degenerate arc in Line");
|
||||
if (tmpListPoint.size() == 0) {
|
||||
tmpListPoint.pushBack(esvg::render::Point(lastPosition, esvg::render::Point::type::join));
|
||||
}
|
||||
tmpListPoint.pushBack(esvg::render::Point(pos, esvg::render::Point::type::join));
|
||||
} else {
|
||||
// Convert to center point parameterization.
|
||||
// http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
|
||||
// procedure describe here : http://www.w3.org/TR/SVG11/implnote.html#ArcConversionCenterToEndpoint
|
||||
// Compute delta'
|
||||
mat2x3 matrixRotationCenter = etk::mat2x3Rotate(-rotationX);
|
||||
vec2 deltaPrim = matrixRotationCenter * (delta*0.5f);
|
||||
ddd = (deltaPrim.x()*deltaPrim.x())/(radius.x()*radius.x())
|
||||
+ (deltaPrim.y()*deltaPrim.y())/(radius.y()*radius.y());
|
||||
if (ddd > 1.0f) {
|
||||
#ifndef __STDCPP_LLVM__
|
||||
ddd = etk::sqrt(ddd);
|
||||
#else
|
||||
ddd = sqrtf(ddd);
|
||||
#endif
|
||||
radius *= ddd;
|
||||
}
|
||||
// Compute center'
|
||||
float sss = 0.0f;
|
||||
float ssa = radius.x()*radius.x()*radius.y()*radius.y()
|
||||
- radius.x()*radius.x()*deltaPrim.y()*deltaPrim.y()
|
||||
- radius.y()*radius.y()*deltaPrim.x()*deltaPrim.x();
|
||||
float ssb = radius.x()*radius.x()*deltaPrim.y()*deltaPrim.y()
|
||||
+ radius.y()*radius.y()*deltaPrim.x()*deltaPrim.x();
|
||||
if (ssa < 0.0f) {
|
||||
ssa = 0.0f;
|
||||
}
|
||||
if (ssb > 0.0f) {
|
||||
#ifndef __STDCPP_LLVM__
|
||||
sss = etk::sqrt(ssa / ssb);
|
||||
#else
|
||||
sss = sqrtf(ssa / ssb);
|
||||
#endif
|
||||
}
|
||||
if (tmpIt->m_largeArcFlag == tmpIt->m_sweepFlag) {
|
||||
sss *= -1.0f;
|
||||
}
|
||||
vec2 centerPrime(sss * radius.x() * deltaPrim.y() / radius.y(),
|
||||
sss * -radius.y() * deltaPrim.x() / radius.x());
|
||||
// Compute center from center'
|
||||
mat2x3 matrix = etk::mat2x3Rotate(rotationX);
|
||||
vec2 center = (lastPosStore + pos)*0.5f + matrix*centerPrime;
|
||||
#ifdef DEBUG
|
||||
m_debugInformation.addSegment(center-vec2(3.0,3.0), center+vec2(3.0,3.0));
|
||||
m_debugInformation.addSegment(center-vec2(3.0,-3.0), center+vec2(3.0,-3.0));
|
||||
#endif
|
||||
// Calculate theta1, and delta theta.
|
||||
vec2 vectorA = (deltaPrim - centerPrime) / radius;
|
||||
vec2 vectorB = (deltaPrim + centerPrime) / radius * -1.0f;
|
||||
#ifdef DEBUG
|
||||
m_debugInformation.addSegment(center, center+vectorA*radius.x());
|
||||
m_debugInformation.addSegment(center, center+vectorB*radius.y());
|
||||
#endif
|
||||
// Initial angle
|
||||
float theta1 = vectorAngle(vec2(1.0f,0.0f), vectorA);
|
||||
// Delta angle
|
||||
float deltaTheta = vectorAngle(vectorA, vectorB);
|
||||
// special case of invert angle...
|
||||
if ( ( deltaTheta == float(M_PI)
|
||||
|| deltaTheta == -float(M_PI))
|
||||
&& tmpIt->m_sweepFlag == false) {
|
||||
deltaTheta *= -1.0f;
|
||||
}
|
||||
if (tmpIt->m_largeArcFlag == true) {
|
||||
// Choose large arc
|
||||
if (deltaTheta > 0.0f) {
|
||||
deltaTheta -= 2.0f*M_PI;
|
||||
} else {
|
||||
deltaTheta += 2.0f*M_PI;
|
||||
}
|
||||
}
|
||||
// Approximate the arc using cubic spline segments.
|
||||
matrix.translate(center);
|
||||
// Split arc into max 90 degree segments.
|
||||
// The loop assumes an iteration per end point (including start and end), this +1.
|
||||
#ifndef __STDCPP_LLVM__
|
||||
int32_t ndivs = int32_t(etk::abs(deltaTheta) / (M_PI*0.5f)) + 1;
|
||||
#else
|
||||
int32_t ndivs = int32_t(fabs(deltaTheta) / (M_PI*0.5f)) + 1;
|
||||
#endif
|
||||
float hda = (deltaTheta / float(ndivs)) * 0.5f;
|
||||
#ifndef __STDCPP_LLVM__
|
||||
float kappa = etk::abs(4.0f / 3.0f * (1.0f - etk::cos(hda)) / etk::sin(hda));
|
||||
#else
|
||||
float kappa = fabs(4.0f / 3.0f * (1.0f - cosf(hda)) / sinf(hda));
|
||||
#endif
|
||||
if (deltaTheta < 0.0f) {
|
||||
kappa = -kappa;
|
||||
}
|
||||
vec2 pointPosPrevious(0.0,0.0);
|
||||
vec2 tangentPrevious(0.0,0.0);
|
||||
for (int32_t iii=0; iii<=ndivs; ++iii) {
|
||||
float a = theta1 + deltaTheta * (float(iii)/(float)ndivs);
|
||||
#ifndef __STDCPP_LLVM__
|
||||
delta = vec2(etk::cos(a), etk::sin(a));
|
||||
#else
|
||||
delta = vec2(cosf(a), sinf(a));
|
||||
#endif
|
||||
// position
|
||||
vec2 pointPos = matrix * vec2(delta.x()*radius.x(), delta.y()*radius.y());
|
||||
// tangent
|
||||
vec2 tangent = matrix.applyScaleRotation(vec2(-delta.y()*radius.x() * kappa, delta.x()*radius.y() * kappa));
|
||||
if (iii > 0) {
|
||||
vec2 zlastPosStore(lastPosition);
|
||||
if (it->getRelative() == false) {
|
||||
lastPosition = vec2(0.0f, 0.0f);
|
||||
}
|
||||
vec2 zpos1 = pointPosPrevious + tangentPrevious;
|
||||
vec2 zpos2 = pointPos - tangent;
|
||||
vec2 zpos = pointPos;
|
||||
interpolateCubicBezier(tmpListPoint,
|
||||
_recurtionMax,
|
||||
_threshold,
|
||||
zlastPosStore,
|
||||
zpos1,
|
||||
zpos2,
|
||||
zpos,
|
||||
0,
|
||||
esvg::render::Point::type::join);
|
||||
lastPosition = zpos;
|
||||
lastAngle = zpos2;
|
||||
}
|
||||
pointPosPrevious = pointPos;
|
||||
tangentPrevious = tangent;
|
||||
}
|
||||
}
|
||||
lastPosition = pos;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Log.error(spacingDist(_level+1) << " Unknow PATH commant (internal error)");
|
||||
break;
|
||||
}
|
||||
}
|
||||
// special case : No request end of path ==> open path:
|
||||
if (tmpListPoint.size() != 0) {
|
||||
Log.verbose("Auto-end PATH");
|
||||
tmpListPoint.back().setEndPath();
|
||||
out.addList(tmpListPoint);
|
||||
tmpListPoint.clear();
|
||||
}
|
||||
out.display();
|
||||
return out;
|
||||
}
|
||||
|
55
src/org/atriasoft/esvg/render/Path.java
Normal file
55
src/org/atriasoft/esvg/render/Path.java
Normal file
@ -0,0 +1,55 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <etk/types.hpp>
|
||||
#include <etk/math/Vector2D.hpp>
|
||||
#include <esvg/render/Element.hpp>
|
||||
#include <esvg/render/PointList.hpp>
|
||||
#include <ememory/memory.hpp>
|
||||
#ifdef DEBUG
|
||||
#include <esvg/render/SegmentList.hpp>
|
||||
#endif
|
||||
|
||||
namespace esvg {
|
||||
namespace render {
|
||||
class Path {
|
||||
public:
|
||||
etk::Vector<ememory::SharedPtr<esvg::render::Element>> m_listElement;
|
||||
#ifdef DEBUG
|
||||
esvg::render::SegmentList m_debugInformation;
|
||||
#endif
|
||||
public:
|
||||
Path() {
|
||||
|
||||
}
|
||||
|
||||
~Path() {
|
||||
|
||||
}
|
||||
void clear();
|
||||
void stop();
|
||||
void close(bool _relative=false);
|
||||
void moveTo(bool _relative, const vec2& _pos);
|
||||
void lineTo(bool _relative, const vec2& _pos);
|
||||
void lineToH(bool _relative, float _posX);
|
||||
void lineToV(bool _relative, float _posY);
|
||||
void curveTo(bool _relative, const vec2& _pos1, const vec2& _pos2, const vec2& _pos);
|
||||
void smoothCurveTo(bool _relative, const vec2& _pos2, const vec2& _pos);
|
||||
void bezierCurveTo(bool _relative, const vec2& _pos1, const vec2& _pos);
|
||||
void bezierSmoothCurveTo(bool _relative, const vec2& _pos);
|
||||
void ellipticTo(bool _relative,
|
||||
const vec2& _radius,
|
||||
float _angle,
|
||||
bool _largeArcFlag,
|
||||
bool _sweepFlag,
|
||||
const vec2& _pos);
|
||||
void display(int32_t _spacing);
|
||||
esvg::render::PointList generateListPoints(int32_t _level, int32_t _recurtionMax = 10, float _threshold = 0.25f);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
31
src/org/atriasoft/esvg/render/Point.cpp
Normal file
31
src/org/atriasoft/esvg/render/Point.cpp
Normal file
@ -0,0 +1,31 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <esvg/render/Point.hpp>
|
||||
#include <esvg/debug.hpp>
|
||||
|
||||
void esvg::render::Point::setEndPath() {
|
||||
if (m_type == esvg::render::Point::type::interpolation) {
|
||||
Log.warning("Request stop path of an interpolate Point");
|
||||
m_type = esvg::render::Point::type::stop;
|
||||
return;
|
||||
}
|
||||
if (m_type == esvg::render::Point::type::stop) {
|
||||
Log.warning("Request stop path of an STOP Point");
|
||||
return;
|
||||
}
|
||||
if (m_type == esvg::render::Point::type::start) {
|
||||
m_type = esvg::render::Point::type::single;
|
||||
return;
|
||||
}
|
||||
m_type = esvg::render::Point::type::stop;
|
||||
}
|
||||
|
||||
void esvg::render::Point::normalize(const vec2& _nextPoint) {
|
||||
m_delta = _nextPoint - m_pos;
|
||||
m_len = m_delta.length();
|
||||
}
|
||||
|
50
src/org/atriasoft/esvg/render/Point.java
Normal file
50
src/org/atriasoft/esvg/render/Point.java
Normal file
@ -0,0 +1,50 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <etk/types.hpp>
|
||||
#include <etk/math/Vector2D.hpp>
|
||||
#include <esvg/render/Element.hpp>
|
||||
|
||||
namespace esvg {
|
||||
namespace render {
|
||||
class Point {
|
||||
public:
|
||||
enum class type {
|
||||
single, //!< Point type is single, this mean that it start and stop of a path
|
||||
start, //!< Point type is starting of a path
|
||||
stop, //!< Point type is stoping of a path
|
||||
join, //!< Point type in an user point provided inside a path
|
||||
interpolation, //!< This point is dynamicly calculated to create an interpolation
|
||||
};
|
||||
public:
|
||||
// TODO : Clean all element here ...
|
||||
vec2 m_pos; //!< position of the point
|
||||
enum esvg::render::Point::type m_type;
|
||||
vec2 m_miterAxe;
|
||||
vec2 m_orthoAxePrevious;
|
||||
vec2 m_orthoAxeNext;
|
||||
vec2 m_posPrevious;
|
||||
vec2 m_posNext;
|
||||
vec2 m_delta;
|
||||
float m_len;
|
||||
// TODO: Update etk::Vector to support not having it ...
|
||||
Point() :
|
||||
m_pos(0,0),
|
||||
m_type(esvg::render::Point::type::join) {
|
||||
// nothing to do ...
|
||||
}
|
||||
Point(const vec2& _pos, enum esvg::render::Point::type _type = esvg::render::Point::type::join) :
|
||||
m_pos(_pos),
|
||||
m_type(_type) {
|
||||
// nothing to do ...
|
||||
}
|
||||
void setEndPath();
|
||||
void normalize(const vec2& _nextPoint);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
64
src/org/atriasoft/esvg/render/PointList.cpp
Normal file
64
src/org/atriasoft/esvg/render/PointList.cpp
Normal file
@ -0,0 +1,64 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <esvg/debug.hpp>
|
||||
#include <esvg/render/PointList.hpp>
|
||||
|
||||
esvg::render::PointList::PointList() {
|
||||
// nothing to do ...
|
||||
}
|
||||
|
||||
void esvg::render::PointList::addList(etk::Vector<esvg::render::Point>& _list) {
|
||||
m_data.pushBack(_list);
|
||||
// TODO : Add a checker of correct list ...
|
||||
}
|
||||
|
||||
void esvg::render::PointList::applyMatrix(const mat2x3& _transformationMatrix) {
|
||||
for (auto &it : m_data) {
|
||||
for (auto &val : it) {
|
||||
val.m_pos = _transformationMatrix * val.m_pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
etk::Pair<vec2, vec2> esvg::render::PointList::getViewPort() {
|
||||
etk::Pair<vec2, vec2> out(vec2(9999999999.0,9999999999.0),vec2(-9999999999.0,-9999999999.0));
|
||||
for (auto &it : m_data) {
|
||||
for (auto &it2 : it) {
|
||||
out.first.setMin(it2.m_pos);
|
||||
out.second.setMax(it2.m_pos);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
void esvg::render::PointList::display() {
|
||||
Log.verbose(" Display list of points : size=" << m_data.size());
|
||||
for (auto &it : m_data) {
|
||||
Log.verbose(" Find List " << it.size() << " members");
|
||||
for (size_t iii=0;
|
||||
iii < it.size();
|
||||
++iii) {
|
||||
switch (it[iii].m_type) {
|
||||
case esvg::render::Point::type::single:
|
||||
Log.verbose(" [" << iii << "] Find Single " << it[iii].m_pos);
|
||||
break;
|
||||
case esvg::render::Point::type::start:
|
||||
Log.verbose(" [" << iii << "] Find Start " << it[iii].m_pos);
|
||||
break;
|
||||
case esvg::render::Point::type::stop:
|
||||
Log.verbose(" [" << iii << "] Find Stop " << it[iii].m_pos);
|
||||
break;
|
||||
case esvg::render::Point::type::interpolation:
|
||||
Log.verbose(" [" << iii << "] Find interpolation " << it[iii].m_pos);
|
||||
break;
|
||||
case esvg::render::Point::type::join:
|
||||
Log.verbose(" [" << iii << "] Find Join " << it[iii].m_pos);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
28
src/org/atriasoft/esvg/render/PointList.java
Normal file
28
src/org/atriasoft/esvg/render/PointList.java
Normal file
@ -0,0 +1,28 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <etk/types.hpp>
|
||||
#include <etk/math/Vector2D.hpp>
|
||||
#include <etk/math/Matrix2x3.hpp>
|
||||
#include <etk/Pair.hpp>
|
||||
#include <esvg/render/Element.hpp>
|
||||
#include <esvg/render/Point.hpp>
|
||||
|
||||
namespace esvg {
|
||||
namespace render {
|
||||
class PointList {
|
||||
public:
|
||||
etk::Vector<etk::Vector<esvg::render::Point>> m_data;
|
||||
public:
|
||||
PointList();
|
||||
void addList(etk::Vector<esvg::render::Point>& _list);
|
||||
void display();
|
||||
void applyMatrix(const mat2x3& _transformationMatrix);
|
||||
etk::Pair<vec2, vec2> getViewPort();
|
||||
};
|
||||
}
|
||||
}
|
38
src/org/atriasoft/esvg/render/Scanline.cpp
Normal file
38
src/org/atriasoft/esvg/render/Scanline.cpp
Normal file
@ -0,0 +1,38 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <esvg/render/Scanline.hpp>
|
||||
#include <esvg/debug.hpp>
|
||||
|
||||
esvg::render::Scanline::Scanline(size_t _size) {
|
||||
m_data.resize(_size, 0.0f);
|
||||
}
|
||||
|
||||
size_t esvg::render::Scanline::size() const {
|
||||
return m_data.size();
|
||||
}
|
||||
|
||||
void esvg::render::Scanline::clear(float _fill) {
|
||||
for (auto &it : m_data) {
|
||||
it = _fill;
|
||||
}
|
||||
}
|
||||
|
||||
float esvg::render::Scanline::get(int32_t _pos) const {
|
||||
if( _pos >= 0
|
||||
&& size_t(_pos) < m_data.size()) {
|
||||
return m_data[_pos];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void esvg::render::Scanline::set(int32_t _pos, float _newColor) {
|
||||
if( _pos >= 0
|
||||
&& size_t(_pos) < m_data.size()) {
|
||||
m_data[_pos] = _newColor;
|
||||
}
|
||||
}
|
||||
|
29
src/org/atriasoft/esvg/render/Scanline.java
Normal file
29
src/org/atriasoft/esvg/render/Scanline.java
Normal file
@ -0,0 +1,29 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <etk/types.hpp>
|
||||
#include <etk/math/Vector2D.hpp>
|
||||
|
||||
namespace esvg {
|
||||
namespace render {
|
||||
class Scanline {
|
||||
private:
|
||||
etk::Vector<float> m_data;
|
||||
public:
|
||||
// constructor :
|
||||
Scanline(size_t _size=32);
|
||||
// destructor
|
||||
~Scanline() { };
|
||||
public:
|
||||
size_t size() const;
|
||||
void clear(float _fill);
|
||||
float get(int32_t _pos) const;
|
||||
void set(int32_t _pos, float _newColor);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
39
src/org/atriasoft/esvg/render/Segment.cpp
Normal file
39
src/org/atriasoft/esvg/render/Segment.cpp
Normal file
@ -0,0 +1,39 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <esvg/render/Segment.hpp>
|
||||
#include <esvg/debug.hpp>
|
||||
|
||||
esvg::render::Segment::Segment() {
|
||||
p0 = vec2(0,0);
|
||||
p1 = vec2(0,0);
|
||||
direction = 0;
|
||||
}
|
||||
|
||||
esvg::render::Segment::Segment(const vec2& _p0, const vec2& _p1) {
|
||||
// segment register all time the lower at P0n then we need to register the sens of the path
|
||||
p0 = _p0;
|
||||
p1 = _p1;
|
||||
direction = 0;
|
||||
}
|
||||
|
||||
void esvg::render::Segment::applyMatrix(const mat2x3& _transformationMatrix) {
|
||||
p0 = _transformationMatrix * p0;
|
||||
p1 = _transformationMatrix * p1;
|
||||
createDirection();
|
||||
}
|
||||
|
||||
void esvg::render::Segment::createDirection() {
|
||||
if (p0.y() < p1.y()) {
|
||||
direction = 1; // direction like clock
|
||||
} else {
|
||||
vec2 tmp(p0);
|
||||
p0 = p1;
|
||||
p1 = tmp;
|
||||
direction = -1; // direction like anti-clock
|
||||
}
|
||||
}
|
||||
|
27
src/org/atriasoft/esvg/render/Segment.java
Normal file
27
src/org/atriasoft/esvg/render/Segment.java
Normal file
@ -0,0 +1,27 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <etk/types.hpp>
|
||||
#include <etk/math/Vector2D.hpp>
|
||||
#include <etk/math/Matrix2x3.hpp>
|
||||
|
||||
namespace esvg {
|
||||
namespace render {
|
||||
class Segment {
|
||||
public:
|
||||
// TODO: Update etk::Vector to support not having it ...
|
||||
Segment();
|
||||
Segment(const vec2& _p0, const vec2& _p1);
|
||||
vec2 p0;
|
||||
vec2 p1;
|
||||
int32_t direction;
|
||||
void applyMatrix(const mat2x3& _transformationMatrix);
|
||||
void createDirection();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
508
src/org/atriasoft/esvg/render/SegmentList.cpp
Normal file
508
src/org/atriasoft/esvg/render/SegmentList.cpp
Normal file
@ -0,0 +1,508 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <esvg/render/SegmentList.hpp>
|
||||
#include <esvg/debug.hpp>
|
||||
#include <etk/math/Matrix2x3.hpp>
|
||||
|
||||
esvg::render::SegmentList::SegmentList() {
|
||||
|
||||
}
|
||||
#ifdef DEBUG
|
||||
void esvg::render::SegmentList::addSegment(const vec2& _pos0, const vec2& _pos1) {
|
||||
m_data.pushBack(Segment(_pos0, _pos1));
|
||||
}
|
||||
#endif
|
||||
|
||||
void esvg::render::SegmentList::addSegment(const esvg::render::Point& _pos0, const esvg::render::Point& _pos1) {
|
||||
// Skip horizontal Segments
|
||||
if (_pos0.m_pos.y() == _pos1.m_pos.y()) {
|
||||
// remove /0 operation
|
||||
return;
|
||||
}
|
||||
m_data.pushBack(Segment(_pos0.m_pos, _pos1.m_pos));
|
||||
}
|
||||
|
||||
void esvg::render::SegmentList::addSegment(const esvg::render::Point& _pos0, const esvg::render::Point& _pos1, bool _disableHorizontal) {
|
||||
// Skip horizontal Segments
|
||||
if ( _disableHorizontal == true
|
||||
&& _pos0.m_pos.y() == _pos1.m_pos.y()) {
|
||||
// remove /0 operation
|
||||
return;
|
||||
}
|
||||
m_data.pushBack(Segment(_pos0.m_pos, _pos1.m_pos));
|
||||
}
|
||||
|
||||
etk::Pair<vec2, vec2> esvg::render::SegmentList::getViewPort() {
|
||||
etk::Pair<vec2, vec2> out(vec2(9999999999.0,9999999999.0),vec2(-9999999999.0,-9999999999.0));
|
||||
for (auto &it : m_data) {
|
||||
out.first.setMin(it.p0);
|
||||
out.second.setMax(it.p0);
|
||||
out.first.setMin(it.p1);
|
||||
out.second.setMax(it.p1);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
void esvg::render::SegmentList::createSegmentList(const esvg::render::PointList& _listPoint) {
|
||||
for (auto &it : _listPoint.m_data) {
|
||||
// Build Segments
|
||||
for (size_t iii=0, jjj=it.size()-1;
|
||||
iii < it.size();
|
||||
jjj = iii++) {
|
||||
addSegment(it[jjj], it[iii]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static vec2 getIntersect(const vec2& _point1,
|
||||
const vec2& _vect1,
|
||||
const vec2& _point2,
|
||||
const vec2& _vect2) {
|
||||
float diviseur = _vect1.x() * _vect2.y() - _vect1.y() * _vect2.x();
|
||||
if(diviseur != 0.0f) {
|
||||
float mmm = ( _vect1.x() * _point1.y()
|
||||
- _vect1.x() * _point2.y()
|
||||
- _vect1.y() * _point1.x()
|
||||
+ _vect1.y() * _point2.x()
|
||||
) / diviseur;
|
||||
return vec2(_point2 + _vect2 * mmm);
|
||||
}
|
||||
Log.error("Get divider / 0.0f");
|
||||
return _point2;
|
||||
}
|
||||
|
||||
void esvg::render::SegmentList::createSegmentListStroke(const vec2& _point1,
|
||||
const vec2& _point2,
|
||||
const vec2& _center,
|
||||
float _width,
|
||||
bool _isStart) {
|
||||
int32_t nbDot = int32_t(_width);
|
||||
if (nbDot <= 2) {
|
||||
nbDot = 2;
|
||||
}
|
||||
float angleToDraw = acos((_point1 - _center).safeNormalize().dot((_point2 - _center).safeNormalize()));
|
||||
float baseAngle = angleToDraw/float(nbDot);
|
||||
float iii;
|
||||
vec2 axe = (_point1 - _center).safeNormalize();
|
||||
vec2 ppp1(_point1);
|
||||
vec2 ppp2(_point2);
|
||||
for (iii=baseAngle; iii<angleToDraw; iii+=baseAngle) {
|
||||
mat2x3 tmpMat;
|
||||
if (_isStart == true) {
|
||||
tmpMat = etk::mat2x3Rotate(-iii);
|
||||
} else {
|
||||
tmpMat = etk::mat2x3Rotate(iii);
|
||||
}
|
||||
vec2 axeRotate = tmpMat * axe;
|
||||
ppp2 = _center
|
||||
+ axeRotate*_width*0.5f;
|
||||
if (_isStart == true) {
|
||||
addSegment(ppp2, ppp1);
|
||||
Log.verbose(" segment :" << ppp2 << " -> " << ppp1);
|
||||
} else {
|
||||
addSegment(ppp1, ppp2);
|
||||
Log.verbose(" segment :" << ppp1 << " -> " << ppp2);
|
||||
}
|
||||
ppp1 = ppp2;
|
||||
}
|
||||
if (_isStart == true) {
|
||||
addSegment(_point2, ppp1);
|
||||
Log.verbose(" segment :" << _point2 << " -> " << ppp1);
|
||||
} else {
|
||||
addSegment(ppp1, _point2);
|
||||
Log.verbose(" segment :" << ppp1 << " -> " << _point2);
|
||||
}
|
||||
}
|
||||
|
||||
void esvg::render::SegmentList::createSegmentListStroke(esvg::render::PointList& _listPoint,
|
||||
float _width,
|
||||
enum esvg::cap _cap,
|
||||
enum esvg::join _join,
|
||||
float _miterLimit) {
|
||||
for (auto &itListPoint : _listPoint.m_data) {
|
||||
// generate for every point all the orthogonal elements
|
||||
//
|
||||
// normal edge * end path
|
||||
// (mitter) * | * * * * * * * * * * * * * *
|
||||
// * |<--*----this | *
|
||||
// * | * this -->| *
|
||||
// * * * | *
|
||||
// * . | . * . . . . . . . . * *
|
||||
// * . | . * | *
|
||||
// * A . | . B * | *
|
||||
// . * . | *
|
||||
// . * * . * * * * * * * * * * * * *
|
||||
// * *
|
||||
// * *
|
||||
for (int64_t idPevious=itListPoint.size()-1, idCurrent=0, idNext=1;
|
||||
idCurrent < int64_t(itListPoint.size());
|
||||
idPevious = idCurrent++, idNext++) {
|
||||
if (idNext == int64_t(itListPoint.size())) {
|
||||
idNext = 0;
|
||||
}
|
||||
if ( itListPoint[idCurrent].m_type == esvg::render::Point::type::join
|
||||
|| itListPoint[idCurrent].m_type == esvg::render::Point::type::interpolation) {
|
||||
if (idPevious < 0 ) {
|
||||
Log.error("an error occure a previous ID is < 0.... ");
|
||||
continue;
|
||||
}
|
||||
if (idNext >= int64_t(itListPoint.size())) {
|
||||
Log.error("an error occure a next ID is >= nbPoint len .... ");
|
||||
continue;
|
||||
}
|
||||
//Log.debug("JOIN : id : prev/curr/next : " << idPevious << "/" << idCurrent << "/" << idNext);
|
||||
//Log.debug("JOIN : val : prev/curr/next : " << itListPoint[idPevious].m_pos << "/" << itListPoint[idCurrent].m_pos << "/" << itListPoint[idNext].m_pos);
|
||||
vec2 vecA = itListPoint[idCurrent].m_pos - itListPoint[idPevious].m_pos;
|
||||
//Log.debug("JOIN : vecA : " << vecA);
|
||||
vecA.safeNormalize();
|
||||
vec2 vecB = itListPoint[idNext].m_pos - itListPoint[idCurrent].m_pos;
|
||||
//Log.debug("JOIN : vecB : " << vecB);
|
||||
vecB.safeNormalize();
|
||||
vec2 vecC = vecA - vecB;
|
||||
//Log.debug("JOIN : vecC : " << vecC);
|
||||
if (vecC == vec2(0.0f, 0.0f)) {
|
||||
// special case: 1 line ...
|
||||
itListPoint[idCurrent].m_miterAxe = vec2(vecA.y(), vecA.x());
|
||||
} else {
|
||||
vecC.safeNormalize();
|
||||
itListPoint[idCurrent].m_miterAxe = vecC;
|
||||
}
|
||||
itListPoint[idCurrent].m_posPrevious = itListPoint[idPevious].m_pos;
|
||||
itListPoint[idCurrent].m_posNext = itListPoint[idNext].m_pos;
|
||||
vecB = itListPoint[idNext].m_pos - itListPoint[idCurrent].m_pos;
|
||||
vecB.safeNormalize();
|
||||
itListPoint[idCurrent].m_orthoAxeNext = vec2(vecB.y(), -vecB.x());
|
||||
vecB = itListPoint[idCurrent].m_pos - itListPoint[idPevious].m_pos;
|
||||
vecB.safeNormalize();
|
||||
itListPoint[idCurrent].m_orthoAxePrevious = vec2(vecB.y(), -vecB.x());
|
||||
//Log.debug("JOIN : miterAxe " << itListPoint[idCurrent].m_miterAxe);
|
||||
} else if (itListPoint[idCurrent].m_type == esvg::render::Point::type::start) {
|
||||
itListPoint[idCurrent].m_posNext = itListPoint[idNext].m_pos;
|
||||
vec2 vecB = itListPoint[idNext].m_pos - itListPoint[idCurrent].m_pos;
|
||||
vecB.safeNormalize();
|
||||
itListPoint[idCurrent].m_miterAxe = vec2(vecB.y(), -vecB.x());
|
||||
itListPoint[idCurrent].m_orthoAxePrevious = itListPoint[idCurrent].m_miterAxe;
|
||||
itListPoint[idCurrent].m_orthoAxeNext = itListPoint[idCurrent].m_miterAxe;
|
||||
} else if (itListPoint[idCurrent].m_type == esvg::render::Point::type::stop) {
|
||||
if (idPevious < 0 ) {
|
||||
Log.error("an error occure a previous ID is < 0.... ");
|
||||
continue;
|
||||
}
|
||||
itListPoint[idCurrent].m_posPrevious = itListPoint[idPevious].m_pos;
|
||||
vec2 vecA = itListPoint[idCurrent].m_pos - itListPoint[idPevious].m_pos;
|
||||
vecA.safeNormalize();
|
||||
itListPoint[idCurrent].m_miterAxe = vec2(vecA.y(), -vecA.x());
|
||||
itListPoint[idCurrent].m_orthoAxePrevious = itListPoint[idCurrent].m_miterAxe;
|
||||
itListPoint[idCurrent].m_orthoAxeNext = itListPoint[idCurrent].m_miterAxe;
|
||||
} else {
|
||||
ESVG_TODO("Unsupported type of point ....");
|
||||
}
|
||||
}
|
||||
// create segment list:
|
||||
bool haveStartLine = false;
|
||||
vec2 leftPoint(0,0);
|
||||
vec2 rightPoint(0,0);
|
||||
if (itListPoint.size() > 0) {
|
||||
if (itListPoint.front().m_type == esvg::render::Point::type::join) {
|
||||
const esvg::render::Point& it = itListPoint.back();
|
||||
// Calculate the perpendiculary axis ...
|
||||
leftPoint = itListPoint.back().m_pos
|
||||
+ itListPoint.back().m_orthoAxePrevious*_width*0.5f;
|
||||
rightPoint = itListPoint.back().m_pos
|
||||
- itListPoint.back().m_orthoAxePrevious*_width*0.5f;
|
||||
// cyclic path...
|
||||
if (it.m_type == esvg::render::Point::type::interpolation) {
|
||||
leftPoint = getIntersect(leftPoint, it.m_pos-it.m_posPrevious, it.m_pos, it.m_miterAxe);
|
||||
rightPoint = getIntersect(rightPoint, it.m_pos-it.m_posPrevious, it.m_pos, it.m_miterAxe);
|
||||
} else if (it.m_type == esvg::render::Point::type::join) {
|
||||
// Calculate the perpendiculary axis ...
|
||||
leftPoint = it.m_pos
|
||||
+ it.m_orthoAxePrevious*_width*0.5f;
|
||||
rightPoint = it.m_pos
|
||||
- it.m_orthoAxePrevious*_width*0.5f;
|
||||
// project on the miter Axis ...
|
||||
switch (_join) {
|
||||
case esvg::join_miter:
|
||||
{
|
||||
vec2 left = getIntersect(leftPoint, it.m_pos-it.m_posPrevious, it.m_pos, it.m_miterAxe);
|
||||
vec2 right = getIntersect(rightPoint, it.m_pos-it.m_posPrevious, it.m_pos, it.m_miterAxe);
|
||||
// Check the miter limit:
|
||||
float limitRight = (left - it.m_pos).length() / _width * 2.0f;
|
||||
float limitLeft = (right - it.m_pos).length() / _width * 2.0f;
|
||||
Log.verbose(" miter Limit: " << limitRight << " " << limitLeft << " <= " << _miterLimit);
|
||||
if ( limitRight <= _miterLimit
|
||||
&& limitLeft <= _miterLimit) {
|
||||
leftPoint = left;
|
||||
rightPoint = right;
|
||||
break;
|
||||
} else {
|
||||
// BEVEL the miter point ...
|
||||
}
|
||||
}
|
||||
case esvg::join_round:
|
||||
case esvg::join_bevel:
|
||||
{
|
||||
vec2 axePrevious = (it.m_pos-it.m_posPrevious).safeNormalize();
|
||||
vec2 axeNext = (it.m_posNext - it.m_pos).safeNormalize();
|
||||
float cross = axePrevious.cross(axeNext);
|
||||
if (cross > 0.0f) {
|
||||
rightPoint = getIntersect(rightPoint, it.m_pos-it.m_posPrevious, it.m_pos, it.m_miterAxe);
|
||||
leftPoint = it.m_pos
|
||||
+ it.m_orthoAxeNext*_width*0.5f;
|
||||
} else {
|
||||
leftPoint = getIntersect(leftPoint, it.m_pos-it.m_posPrevious, it.m_pos, it.m_miterAxe);
|
||||
rightPoint = it.m_pos
|
||||
- it.m_orthoAxeNext*_width*0.5f;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Log.error("Start list point with a join, but last lement is not a join");
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto &it : itListPoint) {
|
||||
switch (it.m_type) {
|
||||
case esvg::render::Point::type::single:
|
||||
// just do nothing ....
|
||||
Log.verbose("Find Single " << it.m_pos);
|
||||
break;
|
||||
case esvg::render::Point::type::start:
|
||||
Log.verbose("Find Start " << it.m_pos);
|
||||
if (haveStartLine == true) {
|
||||
// close previous :
|
||||
Log.warning(" find a non close path ...");
|
||||
addSegment(leftPoint, rightPoint);
|
||||
}
|
||||
haveStartLine = true;
|
||||
startStopPoint(leftPoint, rightPoint, it, _cap, _width, true);
|
||||
break;
|
||||
case esvg::render::Point::type::stop:
|
||||
Log.verbose("Find Stop " << it.m_pos);
|
||||
if (haveStartLine == false) {
|
||||
Log.warning("find close path without start part ...");
|
||||
break;
|
||||
}
|
||||
haveStartLine = false;
|
||||
startStopPoint(leftPoint, rightPoint, it, _cap, _width, false);
|
||||
break;
|
||||
case esvg::render::Point::type::interpolation:
|
||||
{
|
||||
Log.verbose("Find interpolation " << it.m_pos);
|
||||
vec2 left = getIntersect(leftPoint, it.m_pos-it.m_posPrevious, it.m_pos, it.m_miterAxe);
|
||||
vec2 right = getIntersect(rightPoint, it.m_pos-it.m_posPrevious, it.m_pos, it.m_miterAxe);
|
||||
//Draw from previous point:
|
||||
addSegment(leftPoint, left);
|
||||
Log.verbose(" segment :" << leftPoint << " -> " << left);
|
||||
addSegment(right, rightPoint);
|
||||
Log.verbose(" segment :" << right << " -> " << rightPoint);
|
||||
leftPoint = left;
|
||||
rightPoint = right;
|
||||
}
|
||||
break;
|
||||
case esvg::render::Point::type::join:
|
||||
Log.verbose("Find join " << it.m_pos);
|
||||
switch (_join) {
|
||||
case esvg::join_miter:
|
||||
{
|
||||
vec2 left = getIntersect(leftPoint, it.m_pos-it.m_posPrevious, it.m_pos, it.m_miterAxe);
|
||||
vec2 right = getIntersect(rightPoint, it.m_pos-it.m_posPrevious, it.m_pos, it.m_miterAxe);
|
||||
// Check the miter limit:
|
||||
float limitRight = (left - it.m_pos).length() / _width * 2.0f;
|
||||
float limitLeft = (right - it.m_pos).length() / _width * 2.0f;
|
||||
Log.verbose(" miter Limit: " << limitRight << " " << limitLeft << " <= " << _miterLimit);
|
||||
if ( limitRight <= _miterLimit
|
||||
&& limitLeft <= _miterLimit) {
|
||||
//Draw from previous point:
|
||||
addSegment(leftPoint, left);
|
||||
Log.verbose(" segment :" << leftPoint << " -> " << left);
|
||||
addSegment(right, rightPoint);
|
||||
Log.verbose(" segment :" << right << " -> " << rightPoint);
|
||||
leftPoint = left;
|
||||
rightPoint = right;
|
||||
break;
|
||||
} else {
|
||||
// We do a bevel join ...
|
||||
Log.verbose(" Find miter Limit ... ==> create BEVEL");
|
||||
}
|
||||
}
|
||||
case esvg::join_round:
|
||||
case esvg::join_bevel:
|
||||
{
|
||||
vec2 axePrevious = (it.m_pos-it.m_posPrevious).safeNormalize();
|
||||
vec2 axeNext = (it.m_posNext - it.m_pos).safeNormalize();
|
||||
float cross = axePrevious.cross(axeNext);
|
||||
if (cross > 0.0f) {
|
||||
vec2 right = getIntersect(rightPoint, it.m_pos-it.m_posPrevious, it.m_pos, it.m_miterAxe);
|
||||
vec2 left1 = it.m_pos
|
||||
+ it.m_orthoAxePrevious*_width*0.5f;
|
||||
vec2 left2 = it.m_pos
|
||||
+ it.m_orthoAxeNext*_width*0.5f;
|
||||
//Draw from previous point:
|
||||
addSegment(leftPoint, left1);
|
||||
Log.verbose(" segment :" << leftPoint << " -> " << left1);
|
||||
if (_join != esvg::join_round) {
|
||||
// Miter and bevel:
|
||||
addSegment(left1, left2);
|
||||
Log.verbose(" segment :" << left1 << " -> " << left2);
|
||||
}else {
|
||||
createSegmentListStroke(left1,
|
||||
left2,
|
||||
it.m_pos,
|
||||
_width,
|
||||
false);
|
||||
}
|
||||
addSegment(right, rightPoint);
|
||||
Log.verbose(" segment :" << right << " -> " << rightPoint);
|
||||
leftPoint = left2;
|
||||
rightPoint = right;
|
||||
} else {
|
||||
vec2 left = getIntersect(leftPoint, it.m_pos-it.m_posPrevious, it.m_pos, it.m_miterAxe);
|
||||
vec2 right1 = it.m_pos
|
||||
- it.m_orthoAxePrevious*_width*0.5f;
|
||||
vec2 right2 = it.m_pos
|
||||
- it.m_orthoAxeNext*_width*0.5f;//Draw from previous point:
|
||||
addSegment(leftPoint, left);
|
||||
Log.verbose(" segment :" << leftPoint << " -> " << left);
|
||||
addSegment(right1, rightPoint);
|
||||
Log.verbose(" segment :" << right1 << " -> " << rightPoint);
|
||||
if (_join != esvg::join_round) {
|
||||
// Miter and bevel:
|
||||
addSegment(right2, right1);
|
||||
Log.verbose(" segment :" << right2 << " -> " << right1);
|
||||
} else {
|
||||
createSegmentListStroke(right1,
|
||||
right2,
|
||||
it.m_pos,
|
||||
_width,
|
||||
true);
|
||||
}
|
||||
leftPoint = left;
|
||||
rightPoint = right2;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void esvg::render::SegmentList::startStopPoint(vec2& _leftPoint,
|
||||
vec2& _rightPoint,
|
||||
const esvg::render::Point& _point,
|
||||
enum esvg::cap _cap,
|
||||
float _width,
|
||||
bool _isStart) {
|
||||
switch (_cap) {
|
||||
case esvg::cap_butt:
|
||||
{
|
||||
vec2 left = _point.m_pos
|
||||
+ _point.m_miterAxe*_width*0.5f;
|
||||
vec2 right = _point.m_pos
|
||||
- _point.m_miterAxe*_width*0.5f;
|
||||
if (_isStart == false) {
|
||||
//Draw from previous point:
|
||||
addSegment(_leftPoint, left);
|
||||
Log.verbose(" segment :" << _leftPoint << " -> " << left);
|
||||
addSegment(right, _rightPoint);
|
||||
Log.verbose(" segment :" << right << " -> " << _rightPoint);
|
||||
}
|
||||
_leftPoint = left;
|
||||
_rightPoint = right;
|
||||
}
|
||||
if (_isStart == false) {
|
||||
addSegment(_leftPoint, _rightPoint);
|
||||
Log.verbose(" segment :" << _leftPoint << " -> " << _rightPoint);
|
||||
} else {
|
||||
addSegment(_rightPoint, _leftPoint);
|
||||
Log.verbose(" segment :" << _rightPoint << " -> " << _leftPoint);
|
||||
}
|
||||
break;
|
||||
case esvg::cap_round:
|
||||
{
|
||||
if (_isStart == false) {
|
||||
vec2 left = _point.m_pos
|
||||
+ _point.m_miterAxe*_width*0.5f;
|
||||
vec2 right = _point.m_pos
|
||||
- _point.m_miterAxe*_width*0.5f;
|
||||
if (_isStart == false) {
|
||||
//Draw from previous point:
|
||||
addSegment(_leftPoint, left);
|
||||
Log.verbose(" segment :" << _leftPoint << " -> " << left);
|
||||
addSegment(right, _rightPoint);
|
||||
Log.verbose(" segment :" << right << " -> " << _rightPoint);
|
||||
}
|
||||
_leftPoint = left;
|
||||
_rightPoint = right;
|
||||
}
|
||||
int32_t nbDot = int32_t(_width);
|
||||
if (nbDot <= 2) {
|
||||
nbDot = 2;
|
||||
}
|
||||
float baseAngle = M_PI/float(nbDot);
|
||||
float iii;
|
||||
_leftPoint = _point.m_pos
|
||||
+ _point.m_miterAxe*_width*0.5f;
|
||||
_rightPoint = _point.m_pos
|
||||
- _point.m_miterAxe*_width*0.5f;
|
||||
createSegmentListStroke(_leftPoint,
|
||||
_rightPoint,
|
||||
_point.m_pos,
|
||||
_width,
|
||||
_isStart);
|
||||
}
|
||||
break;
|
||||
case esvg::cap_square:
|
||||
{
|
||||
vec2 nextAxe;
|
||||
if (_isStart == true) {
|
||||
nextAxe = _point.m_posNext - _point.m_pos;
|
||||
} else {
|
||||
nextAxe = _point.m_posPrevious - _point.m_pos;
|
||||
}
|
||||
vec2 left = _point.m_pos
|
||||
+ _point.m_miterAxe*_width*0.5f;
|
||||
vec2 right = _point.m_pos
|
||||
- _point.m_miterAxe*_width*0.5f;
|
||||
mat2x3 tmpMat = etk::mat2x3Translate(nextAxe.safeNormalize()*_width*-0.5f);
|
||||
left = tmpMat*left;
|
||||
right = tmpMat*right;
|
||||
if (_isStart == false) {
|
||||
if (_isStart == false) {
|
||||
//Draw from previous point:
|
||||
addSegment(_leftPoint, left);
|
||||
Log.verbose(" segment :" << _leftPoint << " -> " << left);
|
||||
addSegment(right, _rightPoint);
|
||||
Log.verbose(" segment :" << right << " -> " << _rightPoint);
|
||||
}
|
||||
}
|
||||
_leftPoint = left;
|
||||
_rightPoint = right;
|
||||
if (_isStart == false) {
|
||||
addSegment(_leftPoint, _rightPoint);
|
||||
Log.verbose(" segment :" << _leftPoint << " -> " << _rightPoint);
|
||||
} else {
|
||||
addSegment(_rightPoint, _leftPoint);
|
||||
Log.verbose(" segment :" << _rightPoint << " -> " << _leftPoint);
|
||||
}
|
||||
Log.verbose(" segment :" << _leftPoint << " -> " << _rightPoint);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Log.error(" Undefined CAP TYPE");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void esvg::render::SegmentList::applyMatrix(const mat2x3& _transformationMatrix) {
|
||||
for (auto &it : m_data) {
|
||||
it.applyMatrix(_transformationMatrix);
|
||||
}
|
||||
}
|
||||
|
50
src/org/atriasoft/esvg/render/SegmentList.java
Normal file
50
src/org/atriasoft/esvg/render/SegmentList.java
Normal file
@ -0,0 +1,50 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <etk/types.hpp>
|
||||
#include <etk/math/Vector2D.hpp>
|
||||
#include <esvg/cap.hpp>
|
||||
#include <esvg/join.hpp>
|
||||
#include <esvg/render/Segment.hpp>
|
||||
#include <esvg/render/PointList.hpp>
|
||||
|
||||
namespace esvg {
|
||||
namespace render {
|
||||
class SegmentList {
|
||||
public:
|
||||
etk::Vector<esvg::render::Segment> m_data;
|
||||
public:
|
||||
SegmentList();
|
||||
#ifdef DEBUG
|
||||
void addSegment(const vec2& _pos0, const vec2& _pos1);
|
||||
#endif
|
||||
void addSegment(const esvg::render::Point& _pos0, const esvg::render::Point& _pos1);
|
||||
void addSegment(const esvg::render::Point& _pos0, const esvg::render::Point& _pos1, bool _disableHorizontal);
|
||||
void createSegmentList(const esvg::render::PointList& _listPoint);
|
||||
void createSegmentListStroke(esvg::render::PointList& _listPoint,
|
||||
float _width,
|
||||
enum esvg::cap _cap,
|
||||
enum esvg::join _join,
|
||||
float _miterLimit);
|
||||
private:
|
||||
void startStopPoint(vec2& _leftPoint,
|
||||
vec2& _rightPoint,
|
||||
const esvg::render::Point& _point,
|
||||
enum esvg::cap _cap,
|
||||
float _width,
|
||||
bool _isStart);
|
||||
void createSegmentListStroke(const vec2& _point1,
|
||||
const vec2& _point2,
|
||||
const vec2& _center,
|
||||
float _width,
|
||||
bool _isStart);
|
||||
public:
|
||||
etk::Pair<vec2, vec2> getViewPort();
|
||||
void applyMatrix(const mat2x3& _transformationMatrix);
|
||||
};
|
||||
}
|
||||
}
|
203
src/org/atriasoft/esvg/render/Weight.cpp
Normal file
203
src/org/atriasoft/esvg/render/Weight.cpp
Normal file
@ -0,0 +1,203 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <esvg/render/Weight.hpp>
|
||||
#include <esvg/debug.hpp>
|
||||
#include <etk/algorithm.hpp>
|
||||
|
||||
esvg::render::Weight::Weight() :
|
||||
m_size(0,0) {
|
||||
|
||||
}
|
||||
|
||||
esvg::render::Weight::Weight(const ivec2& _size) :
|
||||
m_size(_size) {
|
||||
resize(_size);
|
||||
}
|
||||
|
||||
esvg::render::Weight::~Weight() {
|
||||
|
||||
}
|
||||
|
||||
void esvg::render::Weight::resize(const ivec2& _size) {
|
||||
m_size = _size;
|
||||
float tmp(0);
|
||||
m_data.resize(m_size.x()*m_size.y(), tmp);
|
||||
if ((uint32_t)m_size.x()*m_size.y() > m_data.size()) {
|
||||
Log.warning("Wrong weigth buffer size ...");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const ivec2& esvg::render::Weight::getSize() const {
|
||||
return m_size;
|
||||
}
|
||||
|
||||
int32_t esvg::render::Weight::getWidth() const {
|
||||
return m_size.x();
|
||||
}
|
||||
|
||||
int32_t esvg::render::Weight::getHeight() const {
|
||||
return m_size.y();
|
||||
}
|
||||
|
||||
void esvg::render::Weight::clear(float _fill) {
|
||||
for (int32_t iii=0; iii<m_size.x()*m_size.y(); iii++) {
|
||||
m_data[iii] = _fill;
|
||||
}
|
||||
}
|
||||
|
||||
float esvg::render::Weight::get(const ivec2& _pos) const {
|
||||
if ( _pos.x()>=0 && _pos.x()<m_size.x()
|
||||
&& _pos.y()>=0 && _pos.y()<m_size.y()) {
|
||||
return m_data[_pos.x()+_pos.y()*m_size.x()];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void esvg::render::Weight::set(const ivec2& _pos, float _newColor) {
|
||||
if ( _pos.x()>=0 && _pos.x()<m_size.x()
|
||||
&& _pos.y()>=0 && _pos.y()<m_size.y()) {
|
||||
m_data[_pos.x()+_pos.y()*m_size.x()] = _newColor;
|
||||
}
|
||||
}
|
||||
|
||||
void esvg::render::Weight::set(int32_t _posY, const esvg::render::Scanline& _data) {
|
||||
if ( _posY>=0
|
||||
&& _posY<m_size.y()) {
|
||||
for (int32_t xxx=0; xxx<m_size.x(); ++xxx) {
|
||||
m_data[xxx+_posY*m_size.x()] = _data.get(xxx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void esvg::render::Weight::append(int32_t _posY, const esvg::render::Scanline& _data) {
|
||||
if ( _posY>=0
|
||||
&& _posY<m_size.y()) {
|
||||
for (int32_t xxx=0; xxx<m_size.x(); ++xxx) {
|
||||
m_data[xxx+_posY*m_size.x()] += _data.get(xxx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool sortXPosFunction(const etk::Pair<float,int32_t>& _e1, const etk::Pair<float,int32_t>& _e2) {
|
||||
return _e1.first < _e2.first;
|
||||
}
|
||||
|
||||
|
||||
void esvg::render::Weight::generate(ivec2 _size, int32_t _subSamplingCount, const esvg::render::SegmentList& _listSegment) {
|
||||
resize(_size);
|
||||
// for each lines:
|
||||
for (int32_t yyy=0; yyy<_size.y(); ++yyy) {
|
||||
Log.verbose("Weighting ... " << yyy << " / " << _size.y());
|
||||
// Reduce the number of lines in the subsampling parsing:
|
||||
etk::Vector<Segment> availlableSegmentPixel;
|
||||
for (auto &it : _listSegment.m_data) {
|
||||
if ( it.p0.y() < float(yyy+1)
|
||||
&& it.p1.y() > float(yyy)) {
|
||||
availlableSegmentPixel.pushBack(it);
|
||||
}
|
||||
}
|
||||
if (availlableSegmentPixel.size() == 0) {
|
||||
continue;
|
||||
}
|
||||
Log.verbose(" Find Basic segments " << availlableSegmentPixel.size());
|
||||
// This represent the pondaration on the subSampling
|
||||
float deltaSize = 1.0f/_subSamplingCount;
|
||||
for (int32_t kkk=0; kkk<_subSamplingCount ; ++kkk) {
|
||||
Log.verbose(" Scanline ... " << kkk << " / " << _subSamplingCount);
|
||||
Scanline scanline(_size.x());
|
||||
//find all the segment that cross the middle of the line of the center of the pixel line:
|
||||
float subSamplingCenterPos = yyy + deltaSize*0.5f + deltaSize*kkk;
|
||||
etk::Vector<Segment> availlableSegment;
|
||||
// find in the subList ...
|
||||
for (auto &it : availlableSegmentPixel) {
|
||||
if ( it.p0.y() <= subSamplingCenterPos
|
||||
&& it.p1.y() > subSamplingCenterPos) {
|
||||
// check if we not get 2 identical lines:
|
||||
if ( availlableSegment.size() > 0
|
||||
&& availlableSegment.back().p1 == it.p0
|
||||
&& availlableSegment.back().direction == it.direction) {
|
||||
// we not add this point in this case to prevent double count of the same point.
|
||||
} else {
|
||||
availlableSegment.pushBack(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
Log.verbose(" Availlable Segment " << availlableSegment.size());
|
||||
if (availlableSegment.size() == 0) {
|
||||
continue;
|
||||
}
|
||||
for (auto &it : availlableSegment) {
|
||||
Log.verbose(" Availlable Segment " << it.p0 << " -> " << it.p1 << " dir=" << it.direction);
|
||||
}
|
||||
// x position, angle
|
||||
etk::Vector<etk::Pair<float, int32_t>> listPosition;
|
||||
for (auto &it : availlableSegment) {
|
||||
vec2 delta = it.p0 - it.p1;
|
||||
// x = coefficent*y+bbb;
|
||||
float coefficient = delta.x()/delta.y();
|
||||
float bbb = it.p0.x() - coefficient*it.p0.y();
|
||||
float xpos = coefficient * subSamplingCenterPos + bbb;
|
||||
listPosition.pushBack(etk::Pair<float,int32_t>(xpos, it.direction));
|
||||
}
|
||||
Log.verbose(" List position " << listPosition.size());
|
||||
// now we order position of the xPosition:
|
||||
etk::algorithm::quickSort(listPosition, sortXPosFunction);
|
||||
// move through all element in the point:
|
||||
int32_t lastState = 0;
|
||||
float currentValue = 0.0f;
|
||||
int32_t lastPos = -1;
|
||||
int32_t currentPos = -1;
|
||||
float lastX = 0.0f;
|
||||
// * | \---------------/ |
|
||||
// * current pos
|
||||
// * pos ...
|
||||
// TODO : Code the Odd/even and non-zero ...
|
||||
for (auto &it : listPosition) {
|
||||
if (currentPos != int32_t(it.first)) {
|
||||
// fill to the new pos -1:
|
||||
#if __CPP_VERSION__ >= 2011 && !defined(__TARGET_OS__MacOs) && !defined(__TARGET_OS__IOs)
|
||||
float endValue = float(etk::min(1,etk::abs(lastState))) * deltaSize;
|
||||
#else
|
||||
float endValue = float(etk::min(1,abs(lastState))) * deltaSize;
|
||||
#endif
|
||||
for (int32_t iii=currentPos+1; iii<int32_t(it.first); ++iii) {
|
||||
scanline.set(iii, endValue);
|
||||
}
|
||||
currentPos = int32_t(it.first);
|
||||
currentValue = endValue;
|
||||
}
|
||||
int32_t oldState = lastState;
|
||||
lastState += it.second;
|
||||
if (oldState == 0) {
|
||||
// nothing to draw before ...
|
||||
float ratio = 1.0f - (it.first - float(int32_t(it.first)));
|
||||
currentValue += ratio * deltaSize;
|
||||
} else if (lastState == 0) {
|
||||
// something new to draw ...
|
||||
float ratio = 1.0f - (it.first - float(int32_t(it.first)));
|
||||
currentValue -= ratio * deltaSize;
|
||||
} else {
|
||||
// nothing to do ...
|
||||
}
|
||||
|
||||
if (currentPos == int32_t(it.first)) {
|
||||
scanline.set(currentPos, currentValue);
|
||||
}
|
||||
}
|
||||
// if the counter is not at 0 ==> fill if to the end with full value ... 2.0
|
||||
if (lastState != 0) {
|
||||
// just past the last state to the end of the image ...
|
||||
Log.error("end of Path whith no end ... " << currentPos << " -> " << _size.x());
|
||||
for (int32_t xxx=currentPos; xxx<_size.x(); ++xxx) {
|
||||
scanline.set(xxx, 100.0);
|
||||
}
|
||||
}
|
||||
append(yyy, scanline);
|
||||
}
|
||||
}
|
||||
}
|
42
src/org/atriasoft/esvg/render/Weight.java
Normal file
42
src/org/atriasoft/esvg/render/Weight.java
Normal file
@ -0,0 +1,42 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <etk/types.hpp>
|
||||
#include <etk/math/Vector2D.hpp>
|
||||
#include <esvg/render/Scanline.hpp>
|
||||
#include <esvg/render/SegmentList.hpp>
|
||||
|
||||
namespace esvg {
|
||||
namespace render {
|
||||
class Weight {
|
||||
private:
|
||||
ivec2 m_size;
|
||||
etk::Vector<float> m_data;
|
||||
public:
|
||||
// constructor :
|
||||
Weight();
|
||||
Weight(const ivec2& _size);
|
||||
// destructor
|
||||
~Weight();
|
||||
// -----------------------------------------------
|
||||
// -- basic tools :
|
||||
// -----------------------------------------------
|
||||
public:
|
||||
void resize(const ivec2& _size);
|
||||
const ivec2& getSize() const;
|
||||
int32_t getWidth() const;
|
||||
int32_t getHeight() const;
|
||||
void clear(float _fill);
|
||||
float get(const ivec2& _pos) const;
|
||||
void set(const ivec2& _pos, float _newColor);
|
||||
void set(int32_t _posY, const esvg::render::Scanline& _data);
|
||||
void append(int32_t _posY, const esvg::render::Scanline& _data);
|
||||
void generate(ivec2 _size, int32_t _subSamplingCount, const esvg::render::SegmentList& _listSegment);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
20
src/org/atriasoft/esvg/spreadMethod.cpp
Normal file
20
src/org/atriasoft/esvg/spreadMethod.cpp
Normal file
@ -0,0 +1,20 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <esvg/spreadMethod.hpp>
|
||||
#include <esvg/debug.hpp>
|
||||
|
||||
static const char* values[] = {
|
||||
"pad",
|
||||
"reflect",
|
||||
"repeat"
|
||||
};
|
||||
|
||||
etk::Stream& esvg::operator <<(etk::Stream& _os, enum esvg::spreadMethod _obj) {
|
||||
_os << values[_obj];
|
||||
return _os;
|
||||
}
|
||||
|
23
src/org/atriasoft/esvg/spreadMethod.java
Normal file
23
src/org/atriasoft/esvg/spreadMethod.java
Normal file
@ -0,0 +1,23 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <etk/types.hpp>
|
||||
#include <etk/Stream.hpp>
|
||||
|
||||
namespace esvg {
|
||||
enum spreadMethod {
|
||||
spreadMethod_pad,
|
||||
spreadMethod_reflect,
|
||||
spreadMethod_repeat
|
||||
};
|
||||
/**
|
||||
* @brief Debug operator To display the curent element in a Human redeable information
|
||||
*/
|
||||
etk::Stream& operator <<(etk::Stream& _os, enum esvg::spreadMethod _obj);
|
||||
}
|
||||
|
||||
|
1
test/.gitignore
vendored
Normal file
1
test/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/bin/
|
15
test/src/test/atriasoft/esvg/main.hpp
Normal file
15
test/src/test/atriasoft/esvg/main.hpp
Normal file
@ -0,0 +1,15 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <etk/types.hpp>
|
||||
#include <etk/uri/uri.hpp>
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
extern bool g_visualDebug;
|
40
test/src/test/atriasoft/esvg/main.java
Normal file
40
test/src/test/atriasoft/esvg/main.java
Normal file
@ -0,0 +1,40 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <test-debug/debug.hpp>
|
||||
#include <etk/Vector.hpp>
|
||||
#include <etest/etest.hpp>
|
||||
#include <etk/etk.hpp>
|
||||
|
||||
bool g_visualDebug = false;
|
||||
|
||||
|
||||
int main(int _argc, const char *_argv[]) {
|
||||
etest::init(_argc, _argv);
|
||||
etk::init(_argc, _argv);
|
||||
for (int32_t iii=0; iii<_argc ; ++iii) {
|
||||
etk::String data = _argv[iii];
|
||||
#ifdef DEBUG
|
||||
if (data == "--visual-test") {
|
||||
TEST_PRINT("visual-test=enable");
|
||||
g_visualDebug = true;
|
||||
} else
|
||||
#endif
|
||||
if ( data == "-h"
|
||||
|| data == "--help") {
|
||||
TEST_PRINT("esvg-test - help : ");
|
||||
TEST_PRINT(" " << _argv[0] << " [options]");
|
||||
#ifdef DEBUG
|
||||
TEST_PRINT(" --visual-test Enable decoration in logged file in debug mode only");
|
||||
#else
|
||||
TEST_PRINT(" No optiions ...");
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
//etk::initDefaultFolder("esvg-test");
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
158
test/src/test/atriasoft/esvg/testCap.java
Normal file
158
test/src/test/atriasoft/esvg/testCap.java
Normal file
@ -0,0 +1,158 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <etest/etest.hpp>
|
||||
#include <esvg/esvg.hpp>
|
||||
#include "main.hpp"
|
||||
|
||||
TEST(TestCap, butt) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <polyline points='20,75 80,75' stroke='green' stroke-width='20' fill='none' stroke-linecap='butt'/>"
|
||||
" <polyline points='80,25 20,25' stroke='orange' stroke-width='20' fill='none' stroke-linecap='butt'/>"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestCap_butt.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestCap_butt.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestCap, round) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <polyline points='20,75 80,75' stroke='green' stroke-width='20' fill='none' stroke-linecap='round'/>"
|
||||
" <polyline points='80,25 20,25' stroke='orange' stroke-width='20' fill='none' stroke-linecap='round'/>"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestCap_round.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestCap_round.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestCap, square) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <polyline points='20,75 80,75' stroke='green' stroke-width='20' fill='none' stroke-linecap='square'/>"
|
||||
" <polyline points='80,25 20,25' stroke='orange' stroke-width='20' fill='none' stroke-linecap='square'/>"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestCap_square.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestCap_square.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
|
||||
TEST(TestCap, buttVert) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <polyline points='25,20 25,80' stroke='green' stroke-width='20' fill='none' stroke-linecap='butt'/>"
|
||||
" <polyline points='75,80 75,20' stroke='orange' stroke-width='20' fill='none' stroke-linecap='butt'/>"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestCap_buttVert.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestCap_buttVert.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestCap, roundVert) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <polyline points='25,20 25,80' stroke='green' stroke-width='20' fill='none' stroke-linecap='round'/>"
|
||||
" <polyline points='75,80 75,20' stroke='orange' stroke-width='20' fill='none' stroke-linecap='round'/>"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestCap_roundVert.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestCap_roundVert.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestCap, squareVert) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <polyline points='25,20 25,80' stroke='green' stroke-width='20' fill='none' stroke-linecap='square'/>"
|
||||
" <polyline points='75,80 75,20' stroke='orange' stroke-width='20' fill='none' stroke-linecap='square'/>"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestCap_squareVert.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestCap_squareVert.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
|
||||
|
||||
TEST(TestCap, buttDiag1) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <polyline points='20,20 80,80' stroke='green' stroke-width='20' fill='none' stroke-linecap='butt'/>"
|
||||
" <polyline points='80,20 20,80' stroke='orange' stroke-width='20' fill='none' stroke-linecap='butt'/>"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestCap_buttDiag1.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestCap_buttDiag1.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestCap, roundDiag1) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <polyline points='20,20 80,80' stroke='green' stroke-width='20' fill='none' stroke-linecap='round'/>"
|
||||
" <polyline points='80,20 20,80' stroke='orange' stroke-width='20' fill='none' stroke-linecap='round'/>"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestCap_roundDiag1.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestCap_roundDiag1.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestCap, squareDiag1) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <polyline points='20,20 80,80' stroke='green' stroke-width='20' fill='none' stroke-linecap='square'/>"
|
||||
" <polyline points='80,20 20,80' stroke='orange' stroke-width='20' fill='none' stroke-linecap='square'/>"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestCap_squareDiag1.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestCap_squareDiag1.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
|
||||
TEST(TestCap, buttDiag2) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <polyline points='20,80 80,20' stroke='green' stroke-width='20' fill='none' stroke-linecap='butt'/>"
|
||||
" <polyline points='80,80 20,20' stroke='orange' stroke-width='20' fill='none' stroke-linecap='butt'/>"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestCap_buttDiag2.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestCap_buttDiag2.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestCap, roundDiag2) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <polyline points='20,80 80,20' stroke='green' stroke-width='20' fill='none' stroke-linecap='round'/>"
|
||||
" <polyline points='80,80 20,20' stroke='orange' stroke-width='20' fill='none' stroke-linecap='round'/>"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestCap_roundDiag2.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestCap_roundDiag2.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestCap, squareDiag2) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <polyline points='20,80 80,20' stroke='green' stroke-width='20' fill='none' stroke-linecap='square'/>"
|
||||
" <polyline points='80,80 20,20' stroke='orange' stroke-width='20' fill='none' stroke-linecap='square'/>"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestCap_squareDiag2.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestCap_squareDiag2.bmp"), g_visualDebug);
|
||||
}
|
||||
|
42
test/src/test/atriasoft/esvg/testCircle.java
Normal file
42
test/src/test/atriasoft/esvg/testCircle.java
Normal file
@ -0,0 +1,42 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <etest/etest.hpp>
|
||||
#include <esvg/esvg.hpp>
|
||||
#include "main.hpp"
|
||||
|
||||
TEST(TestCircle, fill) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <circle cx='50' cy='50' r='40' fill='red' />"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestCircle_fill.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestCircle_fill.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestCircle, stroke) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <circle cx='50' cy='50' r='40' stroke='green' stroke-width='3' />"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestCircle_stroke.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestCircle_stroke.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestCircle, fill_and_stroke) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <circle cx='50' cy='50' r='40' stroke='green' stroke-width='3' fill='red' />"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestCircle_fill_and_stroke.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestCircle_fill_and_stroke.bmp"), g_visualDebug);
|
||||
}
|
55
test/src/test/atriasoft/esvg/testColor.java
Normal file
55
test/src/test/atriasoft/esvg/testColor.java
Normal file
@ -0,0 +1,55 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <etest/etest.hpp>
|
||||
#include <esvg/esvg.hpp>
|
||||
#include "main.hpp"
|
||||
|
||||
TEST(TestColor, blending) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <rect x='12.5' y='12.5' width='75' height='50' stroke='#0F0' stroke-opacity='0.5' stroke-width='3' fill='#F00' fill-opacity='0.5' />"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestColor_blending.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestColor_blending.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestColor, opacity) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <rect x='12.5' y='12.5' width='75' height='50' stroke='#0F0' stroke-width='3' fill='#F00' opacity='0.5' />"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestColor_opacity.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestColor_opacity.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestColor, blending_and_opacity) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <rect x='12.5' y='12.5' width='75' height='50' stroke='#0F0' stroke-opacity='0.5' stroke-width='3' fill='#F00' fill-opacity='0.5' opacity='0.7' />"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestColor_blending_and_opacity.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestColor_blending_and_opacity.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestColor, multiple_layer) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <rect x='50' y='5' width='15' height='75' stroke='blue' stroke-width='9' fill='green'/>"
|
||||
" <rect x='12.5' y='12.5' width='75' height='30' stroke='#0F0' stroke-opacity='0.5' stroke-width='3' fill='#F00' fill-opacity='0.5' opacity='0.7' />"
|
||||
" <rect x='30' y='30' width='20' height='20' stroke='orange' stroke-width='1' fill='violet'/>"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestColor_multiple_layer.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestColor_multiple_layer.bmp"), g_visualDebug);
|
||||
}
|
43
test/src/test/atriasoft/esvg/testEllipse.java
Normal file
43
test/src/test/atriasoft/esvg/testEllipse.java
Normal file
@ -0,0 +1,43 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <etest/etest.hpp>
|
||||
#include <esvg/esvg.hpp>
|
||||
#include "main.hpp"
|
||||
|
||||
TEST(TestEllipse, fill) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <ellipse cx='50' cy='50' rx='80' ry='30' fill='red' />"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestEllipse_fill.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestEllipse_fill.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestEllipse, stroke) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <ellipse cx='50' cy='50' rx='80' ry='30' stroke='green' stroke-width='3' />"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestEllipse_stroke.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestEllipse_stroke.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestEllipse, fill_and_stroke) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <ellipse cx='50' cy='50' rx='80' ry='30' stroke='green' stroke-width='3' fill='red' />"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestEllipse_fill_and_stroke.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestEllipse_fill_and_stroke.bmp"), g_visualDebug);
|
||||
}
|
||||
|
343
test/src/test/atriasoft/esvg/testGradientLinear.java
Normal file
343
test/src/test/atriasoft/esvg/testGradientLinear.java
Normal file
@ -0,0 +1,343 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <etest/etest.hpp>
|
||||
#include <esvg/esvg.hpp>
|
||||
#include "main.hpp"
|
||||
|
||||
TEST(TestGradientLinear, horizontal) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n"
|
||||
"<svg height='100' width='100'>\n"
|
||||
" <defs>\n"
|
||||
" <linearGradient id='grad1' x1='0%' y1='0%' x2='100%' y2='0%'>\n"
|
||||
" <stop offset='0%' style='stop-color:rgb(255,0,0);stop-opacity:1' />\n"
|
||||
" <stop offset='45%' style='stop-color:rgb(0,255,0);stop-opacity:1' />\n"
|
||||
" <stop offset='55%' style='stop-color:rgb(0,0,255);stop-opacity:1' />\n"
|
||||
" <stop offset='100%' style='stop-color:rgb(255,0,255);stop-opacity:1' />\n"
|
||||
" </linearGradient>\n"
|
||||
" </defs>\n"
|
||||
" <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad1)' />\n"
|
||||
"</svg>\n");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestGradientLinear_horizontal.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestGradientLinear_horizontal.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
|
||||
TEST(TestGradientLinear, vertical) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n"
|
||||
"<svg height='100' width='100'>\n"
|
||||
" <defs>\n"
|
||||
" <linearGradient id='grad2' x1='0%' y1='0%' x2='0%' y2='100%'>\n"
|
||||
" <stop offset='0%' style='stop-color:rgb(255,0,0);stop-opacity:1' />\n"
|
||||
" <stop offset='45%' style='stop-color:rgb(0,255,0);stop-opacity:1' />\n"
|
||||
" <stop offset='55%' style='stop-color:rgb(0,0,255);stop-opacity:1' />\n"
|
||||
" <stop offset='100%' style='stop-color:rgb(255,0,255);stop-opacity:1' />\n"
|
||||
" </linearGradient>\n"
|
||||
" </defs>\n"
|
||||
" <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad2)' />\n"
|
||||
"</svg>\n");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestGradientLinear_vertical.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestGradientLinear_vertical.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestGradientLinear, diag1) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n"
|
||||
"<svg height='100' width='100'>\n"
|
||||
" <defs>\n"
|
||||
" <linearGradient id='grad2' x1='0%' y1='0%' x2='100%' y2='100%'>\n"
|
||||
" <stop offset='0%' style='stop-color:rgb(255,0,0);stop-opacity:1' />\n"
|
||||
" <stop offset='45%' style='stop-color:rgb(0,255,0);stop-opacity:1' />\n"
|
||||
" <stop offset='55%' style='stop-color:rgb(0,0,255);stop-opacity:1' />\n"
|
||||
" <stop offset='100%' style='stop-color:rgb(255,0,255);stop-opacity:1' />\n"
|
||||
" </linearGradient>\n"
|
||||
" </defs>\n"
|
||||
" <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad2)' />\n"
|
||||
"</svg>\n");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestGradientLinear_diag1.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestGradientLinear_diag1.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestGradientLinear, diag1Partiel) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n"
|
||||
"<svg height='100' width='100'>\n"
|
||||
" <defs>\n"
|
||||
" <linearGradient id='grad2' x1='40%' y1='40%' x2='70%' y2='70%'>\n"
|
||||
" <stop offset='0%' style='stop-color:rgb(0,255,0);stop-opacity:1' />\n"
|
||||
" <stop offset='100%' style='stop-color:rgb(0,0,255);stop-opacity:1' />\n"
|
||||
" </linearGradient>\n"
|
||||
" </defs>\n"
|
||||
" <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad2)' />\n"
|
||||
"</svg>\n");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestGradientLinear_diag1Partiel.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestGradientLinear_diag1Partiel.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestGradientLinear, diag2) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n"
|
||||
"<svg height='100' width='100'>\n"
|
||||
" <defs>\n"
|
||||
" <linearGradient id='grad2' x1='0%' y1='100%' x2='100%' y2='0%'>\n"
|
||||
" <stop offset='0%' style='stop-color:rgb(255,0,0);stop-opacity:1' />\n"
|
||||
" <stop offset='45%' style='stop-color:rgb(0,255,0);stop-opacity:1' />\n"
|
||||
" <stop offset='55%' style='stop-color:rgb(0,0,255);stop-opacity:1' />\n"
|
||||
" <stop offset='100%' style='stop-color:rgb(255,0,255);stop-opacity:1' />\n"
|
||||
" </linearGradient>\n"
|
||||
" </defs>\n"
|
||||
" <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad2)' />\n"
|
||||
"</svg>\n");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestGradientLinear_diag2.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestGradientLinear_diag2.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
|
||||
|
||||
TEST(TestGradientLinear, diag2Rotate0) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n"
|
||||
"<svg height='100' width='100'>\n"
|
||||
" <defs>\n"
|
||||
" <linearGradient id='grad2' x1='0%' y1='50%' x2='100%' y2='50%'>\n"
|
||||
" <stop offset='0%' style='stop-color:rgb(255,0,0);stop-opacity:1' />\n"
|
||||
" <stop offset='45%' style='stop-color:rgb(0,255,0);stop-opacity:1' />\n"
|
||||
" <stop offset='55%' style='stop-color:rgb(0,0,255);stop-opacity:1' />\n"
|
||||
" <stop offset='100%' style='stop-color:rgb(255,0,255);stop-opacity:1' />\n"
|
||||
" </linearGradient>\n"
|
||||
" </defs>\n"
|
||||
" <ellipse transform='rotate (30 50 50)' cx='50' cy='50' rx='50' ry='20' fill='url(#grad2)' />\n"
|
||||
"</svg>\n");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestGradientLinear_diag2Rotate0.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestGradientLinear_diag2Rotate0.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestGradientLinear, diag2Rotate1) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n"
|
||||
"<svg height='100' width='100'>\n"
|
||||
" <defs>\n"
|
||||
" <linearGradient id='grad2' x1='0%' y1='100%' x2='100%' y2='0%'>\n"
|
||||
" <stop offset='0%' style='stop-color:rgb(255,0,0);stop-opacity:1' />\n"
|
||||
" <stop offset='45%' style='stop-color:rgb(0,255,0);stop-opacity:1' />\n"
|
||||
" <stop offset='55%' style='stop-color:rgb(0,0,255);stop-opacity:1' />\n"
|
||||
" <stop offset='100%' style='stop-color:rgb(255,0,255);stop-opacity:1' />\n"
|
||||
" </linearGradient>\n"
|
||||
" </defs>\n"
|
||||
" <ellipse transform='rotate (45 50 50)' cx='50' cy='50' rx='50' ry='20' fill='url(#grad2)' />\n"
|
||||
"</svg>\n");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestGradientLinear_diag2Rotate1.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestGradientLinear_diag2Rotate1.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestGradientLinear, diag2Rotate2) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n"
|
||||
"<svg height='100' width='100'>\n"
|
||||
" <defs>\n"
|
||||
" <linearGradient id='grad2' x1='0%' y1='100%' x2='100%' y2='0%'>\n"
|
||||
" <stop offset='0%' style='stop-color:rgb(255,0,0);stop-opacity:1' />\n"
|
||||
" <stop offset='45%' style='stop-color:rgb(0,255,0);stop-opacity:1' />\n"
|
||||
" <stop offset='55%' style='stop-color:rgb(0,0,255);stop-opacity:1' />\n"
|
||||
" <stop offset='100%' style='stop-color:rgb(255,0,255);stop-opacity:1' />\n"
|
||||
" </linearGradient>\n"
|
||||
" </defs>\n"
|
||||
" <ellipse transform='rotate (-45 50 50)' cx='50' cy='50' rx='50' ry='20' fill='url(#grad2)' />\n"
|
||||
"</svg>\n");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestGradientLinear_diag2Rotate2.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestGradientLinear_diag2Rotate2.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestGradientLinear, diag2scale) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n"
|
||||
"<svg height='100' width='100'>\n"
|
||||
" <defs>\n"
|
||||
" <linearGradient id='grad2' x1='0%' y1='100%' x2='100%' y2='0%'>\n"
|
||||
" <stop offset='0%' style='stop-color:rgb(255,0,0);stop-opacity:1' />\n"
|
||||
" <stop offset='45%' style='stop-color:rgb(0,255,0);stop-opacity:1' />\n"
|
||||
" <stop offset='55%' style='stop-color:rgb(0,0,255);stop-opacity:1' />\n"
|
||||
" <stop offset='100%' style='stop-color:rgb(255,0,255);stop-opacity:1' />\n"
|
||||
" </linearGradient>\n"
|
||||
" </defs>\n"
|
||||
" <ellipse transform='scale (0.5 2.0) translate (10,-25)' cx='50' cy='50' rx='50' ry='20' fill='url(#grad2)' />\n"
|
||||
"</svg>\n");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestGradientLinear_diag2scale.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestGradientLinear_diag2scale.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestGradientLinear, internalHref) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n"
|
||||
"<svg height='100' width='100'>\n"
|
||||
" <defs>\n"
|
||||
" <linearGradient id='grad2Values'>\n"
|
||||
" <stop offset='0%' style='stop-color:rgb(255,0,0);stop-opacity:1' />\n"
|
||||
" <stop offset='45%' style='stop-color:rgb(0,255,0);stop-opacity:1' />\n"
|
||||
" <stop offset='55%' style='stop-color:rgb(0,0,255);stop-opacity:1' />\n"
|
||||
" <stop offset='100%' style='stop-color:rgb(255,0,255);stop-opacity:1' />\n"
|
||||
" </linearGradient>\n"
|
||||
" <linearGradient id='grad2' x1='0%' y1='100%' x2='100%' y2='0%' xlink:href='#grad2Values' />\n"
|
||||
" </defs>\n"
|
||||
" <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad2)' />\n"
|
||||
"</svg>\n");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestGradientLinear_internalHref.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestGradientLinear_internalHref.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
|
||||
TEST(TestGradientLinear, unitBox_spreadNone) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n"
|
||||
"<svg height='100' width='100'>\n"
|
||||
" <defs>\n"
|
||||
" <linearGradient id='grad2' x1='40%' y1='40%' x2='60%' y2='60%'>\n"
|
||||
" <stop offset='0%' style='stop-color:rgb(0,255,0);stop-opacity:1' />\n"
|
||||
" <stop offset='100%' style='stop-color:rgb(0,0,255);stop-opacity:1' />\n"
|
||||
" </linearGradient>\n"
|
||||
" </defs>\n"
|
||||
" <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad2)'/>\n"
|
||||
"</svg>\n");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestGradientLinear_unitBox_spreadNone.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestGradientLinear_unitBox_spreadNone.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestGradientLinear, unitBox_spreadPad) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n"
|
||||
"<svg height='100' width='100'>\n"
|
||||
" <defs>\n"
|
||||
" <linearGradient id='grad2' x1='40%' y1='40%' x2='60%' y2='60%' spreadMethod='pad'>\n"
|
||||
" <stop offset='0%' style='stop-color:rgb(0,255,0);stop-opacity:1' />\n"
|
||||
" <stop offset='100%' style='stop-color:rgb(0,0,255);stop-opacity:1' />\n"
|
||||
" </linearGradient>\n"
|
||||
" </defs>\n"
|
||||
" <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad2)'/>\n"
|
||||
"</svg>\n");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestGradientLinear_unitBox_spreadPad.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestGradientLinear_unitBox_spreadPad.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
|
||||
TEST(TestGradientLinear, unitBox_spreadReflect) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n"
|
||||
"<svg height='100' width='100'>\n"
|
||||
" <defs>\n"
|
||||
" <linearGradient id='grad2' x1='40%' y1='40%' x2='60%' y2='60%' spreadMethod='reflect'>\n"
|
||||
" <stop offset='0%' style='stop-color:rgb(0,255,0);stop-opacity:1' />\n"
|
||||
" <stop offset='100%' style='stop-color:rgb(0,0,255);stop-opacity:1' />\n"
|
||||
" </linearGradient>\n"
|
||||
" </defs>\n"
|
||||
" <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad2)'/>\n"
|
||||
"</svg>\n");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestGradientLinear_unitBox_spreadReflect.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestGradientLinear_unitBox_spreadReflect.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
|
||||
TEST(TestGradientLinear, unitBox_spreadRepeat) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n"
|
||||
"<svg height='100' width='100'>\n"
|
||||
" <defs>\n"
|
||||
" <linearGradient id='grad2' x1='40%' y1='40%' x2='60%' y2='60%' spreadMethod='repeat'>\n"
|
||||
" <stop offset='0%' style='stop-color:rgb(0,255,0);stop-opacity:1' />\n"
|
||||
" <stop offset='100%' style='stop-color:rgb(0,0,255);stop-opacity:1' />\n"
|
||||
" </linearGradient>\n"
|
||||
" </defs>\n"
|
||||
" <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad2)'/>\n"
|
||||
"</svg>\n");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestGradientLinear_unitBox_spreadRepeat.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestGradientLinear_unitBox_spreadRepeat.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestGradientLinear, unitUser_spreadNone) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n"
|
||||
"<svg height='100' width='100'>\n"
|
||||
" <defs>\n"
|
||||
" <linearGradient id='grad2' x1='45' y1='45' x2='55' y2='55' gradientUnits='userSpaceOnUse'>\n"
|
||||
" <stop offset='0%' style='stop-color:rgb(0,255,0);stop-opacity:1' />\n"
|
||||
" <stop offset='100%' style='stop-color:rgb(0,0,255);stop-opacity:1' />\n"
|
||||
" </linearGradient>\n"
|
||||
" </defs>\n"
|
||||
" <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad2)'/>\n"
|
||||
"</svg>\n");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestGradientLinear_unitUser_spreadNone.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestGradientLinear_unitUser_spreadNone.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestGradientLinear, unitUser_spreadPad) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n"
|
||||
"<svg height='100' width='100'>\n"
|
||||
" <defs>\n"
|
||||
" <linearGradient id='grad2' x1='45' y1='45' x2='55' y2='55' spreadMethod='pad' gradientUnits='userSpaceOnUse' >\n"
|
||||
" <stop offset='0%' style='stop-color:rgb(0,255,0);stop-opacity:1' />\n"
|
||||
" <stop offset='100%' style='stop-color:rgb(0,0,255);stop-opacity:1' />\n"
|
||||
" </linearGradient>\n"
|
||||
" </defs>\n"
|
||||
" <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad2)'/>\n"
|
||||
"</svg>\n");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestGradientLinear_unitUser_spreadPad.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestGradientLinear_unitUser_spreadPad.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
|
||||
TEST(TestGradientLinear, unitUser_spreadReflect) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n"
|
||||
"<svg height='100' width='100'>\n"
|
||||
" <defs>\n"
|
||||
" <linearGradient id='grad2' x1='45' y1='45' x2='55' y2='55' spreadMethod='reflect' gradientUnits='userSpaceOnUse' >\n"
|
||||
" <stop offset='0%' style='stop-color:rgb(0,255,0);stop-opacity:1' />\n"
|
||||
" <stop offset='100%' style='stop-color:rgb(0,0,255);stop-opacity:1' />\n"
|
||||
" </linearGradient>\n"
|
||||
" </defs>\n"
|
||||
" <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad2)'/>\n"
|
||||
"</svg>\n");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestGradientLinear_unitUser_spreadReflect.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestGradientLinear_unitUser_spreadReflect.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
|
||||
TEST(TestGradientLinear, unitUser_spreadRepeate) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n"
|
||||
"<svg height='100' width='100'>\n"
|
||||
" <defs>\n"
|
||||
" <linearGradient id='grad2' x1='45' y1='45' x2='55' y2='55' spreadMethod='repeat' gradientUnits='userSpaceOnUse' >\n"
|
||||
" <stop offset='0%' style='stop-color:rgb(0,255,0);stop-opacity:1' />\n"
|
||||
" <stop offset='100%' style='stop-color:rgb(0,0,255);stop-opacity:1' />\n"
|
||||
" </linearGradient>\n"
|
||||
" </defs>\n"
|
||||
" <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad2)'/>\n"
|
||||
"</svg>\n");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestGradientLinear_unitUser_spreadRepeate.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestGradientLinear_unitUser_spreadRepeate.bmp"), g_visualDebug);
|
||||
}
|
||||
|
319
test/src/test/atriasoft/esvg/testGradientRadial.java
Normal file
319
test/src/test/atriasoft/esvg/testGradientRadial.java
Normal file
@ -0,0 +1,319 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <etest/etest.hpp>
|
||||
#include <esvg/esvg.hpp>
|
||||
#include "main.hpp"
|
||||
|
||||
TEST(TestGradientRadial, circle) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n"
|
||||
"<svg height='100' width='100'>\n"
|
||||
" <defs>\n"
|
||||
" <radialGradient id='grad1' cx='50%' cy='50%' r='50%' fx='50%' fy='50%'>\n"
|
||||
" <stop offset='0%' style='stop-color:orange;stop-opacity:1' />\n"
|
||||
" <stop offset='45%' style='stop-color:red;stop-opacity:1' />\n"
|
||||
" <stop offset='55%' style='stop-color:blue;stop-opacity:1' />\n"
|
||||
" <stop offset='100%' style='stop-color:green;stop-opacity:1' />\n"
|
||||
" </radialGradient>\n"
|
||||
" </defs>\n"
|
||||
" <ellipse cx='50' cy='50' rx='50' ry='50' fill='url(#grad1)' />\n"
|
||||
"</svg>\n");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestGradientRadial_circle.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestGradientRadial_circle.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
|
||||
TEST(TestGradientRadial, full) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n"
|
||||
"<svg height='100' width='100'>\n"
|
||||
" <defs>\n"
|
||||
" <radialGradient id='grad1' cx='50%' cy='50%' r='50%' fx='50%' fy='50%'>\n"
|
||||
" <stop offset='0%' style='stop-color:orange;stop-opacity:1' />\n"
|
||||
" <stop offset='45%' style='stop-color:red;stop-opacity:1' />\n"
|
||||
" <stop offset='55%' style='stop-color:blue;stop-opacity:1' />\n"
|
||||
" <stop offset='100%' style='stop-color:green;stop-opacity:1' />\n"
|
||||
" </radialGradient>\n"
|
||||
" </defs>\n"
|
||||
" <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad1)' />\n"
|
||||
"</svg>\n");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestGradientRadial_full.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestGradientRadial_full.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
|
||||
TEST(TestGradientRadial, partial) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n"
|
||||
"<svg height='100' width='100'>\n"
|
||||
" <defs>\n"
|
||||
" <radialGradient id='grad2' cx='20%' cy='30%' r='30%' fx='50%' fy='50%'>\n"
|
||||
" <stop offset='0%' style='stop-color:orange;stop-opacity:1' />\n"
|
||||
" <stop offset='45%' style='stop-color:red;stop-opacity:1' />\n"
|
||||
" <stop offset='55%' style='stop-color:blue;stop-opacity:1' />\n"
|
||||
" <stop offset='100%' style='stop-color:green;stop-opacity:1' />\n"
|
||||
" </radialGradient>\n"
|
||||
" </defs>\n"
|
||||
" <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad2)' />\n"
|
||||
"</svg>\n");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestGradientRadial_partial.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestGradientRadial_partial.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestGradientRadial, unitBox_spreadNone) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n"
|
||||
"<svg height='100' width='100'>\n"
|
||||
" <defs>\n"
|
||||
" <radialGradient id='grad1' cx='50%' cy='50%' r='10%' fx='50%' fy='50%'>\n"
|
||||
" <stop offset='0%' style='stop-color:orange;stop-opacity:1' />\n"
|
||||
" <stop offset='45%' style='stop-color:red;stop-opacity:1' />\n"
|
||||
" <stop offset='55%' style='stop-color:blue;stop-opacity:1' />\n"
|
||||
" <stop offset='100%' style='stop-color:green;stop-opacity:1' />\n"
|
||||
" </radialGradient>\n"
|
||||
" </defs>\n"
|
||||
" <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad1)' />\n"
|
||||
"</svg>\n");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestGradientRadial_unitBox_spreadNone.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestGradientRadial_unitBox_spreadNone.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestGradientRadial, unitBox_spreadPad) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n"
|
||||
"<svg height='100' width='100'>\n"
|
||||
" <defs>\n"
|
||||
" <radialGradient id='grad1' cx='50%' cy='50%' r='10%' fx='50%' fy='50%' spreadMethod='pad'>\n"
|
||||
" <stop offset='0%' style='stop-color:orange;stop-opacity:1' />\n"
|
||||
" <stop offset='45%' style='stop-color:red;stop-opacity:1' />\n"
|
||||
" <stop offset='55%' style='stop-color:blue;stop-opacity:1' />\n"
|
||||
" <stop offset='100%' style='stop-color:green;stop-opacity:1' />\n"
|
||||
" </radialGradient>\n"
|
||||
" </defs>\n"
|
||||
" <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad1)' />\n"
|
||||
"</svg>\n");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestGradientRadial_unitBox_spreadPad.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestGradientRadial_unitBox_spreadPad.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestGradientRadial, unitBox_spreadReflect) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n"
|
||||
"<svg height='100' width='100'>\n"
|
||||
" <defs>\n"
|
||||
" <radialGradient id='grad1' cx='50%' cy='50%' r='10%' fx='50%' fy='50%' spreadMethod='reflect'>\n"
|
||||
" <stop offset='0%' style='stop-color:orange;stop-opacity:1' />\n"
|
||||
" <stop offset='45%' style='stop-color:red;stop-opacity:1' />\n"
|
||||
" <stop offset='55%' style='stop-color:blue;stop-opacity:1' />\n"
|
||||
" <stop offset='100%' style='stop-color:green;stop-opacity:1' />\n"
|
||||
" </radialGradient>\n"
|
||||
" </defs>\n"
|
||||
" <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad1)' />\n"
|
||||
"</svg>\n");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestGradientRadial_unitBox_spreadReflect.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestGradientRadial_unitBox_spreadReflect.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
|
||||
TEST(TestGradientRadial, unitBox_spreadRepeat) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n"
|
||||
"<svg height='100' width='100'>\n"
|
||||
" <defs>\n"
|
||||
" <radialGradient id='grad1' cx='50%' cy='50%' r='10%' fx='50%' fy='50%' spreadMethod='repeat'>\n"
|
||||
" <stop offset='0%' style='stop-color:orange;stop-opacity:1' />\n"
|
||||
" <stop offset='45%' style='stop-color:red;stop-opacity:1' />\n"
|
||||
" <stop offset='55%' style='stop-color:blue;stop-opacity:1' />\n"
|
||||
" <stop offset='100%' style='stop-color:green;stop-opacity:1' />\n"
|
||||
" </radialGradient>\n"
|
||||
" </defs>\n"
|
||||
" <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad1)' />\n"
|
||||
"</svg>\n");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestGradientRadial_unitBox_spreadRepeat.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestGradientRadial_unitBox_spreadRepeat.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
|
||||
TEST(TestGradientRadial, unitUser_spreadNone) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n"
|
||||
"<svg height='100' width='100'>\n"
|
||||
" <defs>\n"
|
||||
" <radialGradient id='grad1' cx='50' cy='50' r='10' fx='50' fy='50%' gradientUnits='userSpaceOnUse' >\n"
|
||||
" <stop offset='0%' style='stop-color:orange;stop-opacity:1' />\n"
|
||||
" <stop offset='45%' style='stop-color:red;stop-opacity:1' />\n"
|
||||
" <stop offset='55%' style='stop-color:blue;stop-opacity:1' />\n"
|
||||
" <stop offset='100%' style='stop-color:green;stop-opacity:1' />\n"
|
||||
" </radialGradient>\n"
|
||||
" </defs>\n"
|
||||
" <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad1)' />\n"
|
||||
"</svg>\n");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestGradientRadial_unitUser_spreadNone.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestGradientRadial_unitUser_spreadNone.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestGradientRadial, unitUser_spreadPad) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n"
|
||||
"<svg height='100' width='100'>\n"
|
||||
" <defs>\n"
|
||||
" <radialGradient id='grad1' cx='50' cy='50' r='10' fx='50' fy='50' spreadMethod='pad' gradientUnits='userSpaceOnUse' >\n"
|
||||
" <stop offset='0%' style='stop-color:orange;stop-opacity:1' />\n"
|
||||
" <stop offset='45%' style='stop-color:red;stop-opacity:1' />\n"
|
||||
" <stop offset='55%' style='stop-color:blue;stop-opacity:1' />\n"
|
||||
" <stop offset='100%' style='stop-color:green;stop-opacity:1' />\n"
|
||||
" </radialGradient>\n"
|
||||
" </defs>\n"
|
||||
" <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad1)' />\n"
|
||||
"</svg>\n");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestGradientRadial_unitUser_spreadPad.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestGradientRadial_unitUser_spreadPad.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestGradientRadial, unitUser_spreadReflect) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n"
|
||||
"<svg height='100' width='100'>\n"
|
||||
" <defs>\n"
|
||||
" <radialGradient id='grad1' cx='50' cy='50' r='10' fx='50' fy='50' spreadMethod='reflect' gradientUnits='userSpaceOnUse' >\n"
|
||||
" <stop offset='0%' style='stop-color:orange;stop-opacity:1' />\n"
|
||||
" <stop offset='45%' style='stop-color:red;stop-opacity:1' />\n"
|
||||
" <stop offset='55%' style='stop-color:blue;stop-opacity:1' />\n"
|
||||
" <stop offset='100%' style='stop-color:green;stop-opacity:1' />\n"
|
||||
" </radialGradient>\n"
|
||||
" </defs>\n"
|
||||
" <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad1)' />\n"
|
||||
"</svg>\n");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestGradientRadial_unitUser_spreadReflect.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestGradientRadial_unitUser_spreadReflect.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
|
||||
TEST(TestGradientRadial, unitUser_spreadRepeat) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n"
|
||||
"<svg height='100' width='100'>\n"
|
||||
" <defs>\n"
|
||||
" <radialGradient id='grad1' cx='50' cy='50' r='10' fx='50' fy='50' spreadMethod='repeat' gradientUnits='userSpaceOnUse' >\n"
|
||||
" <stop offset='0%' style='stop-color:orange;stop-opacity:1' />\n"
|
||||
" <stop offset='45%' style='stop-color:red;stop-opacity:1' />\n"
|
||||
" <stop offset='55%' style='stop-color:blue;stop-opacity:1' />\n"
|
||||
" <stop offset='100%' style='stop-color:green;stop-opacity:1' />\n"
|
||||
" </radialGradient>\n"
|
||||
" </defs>\n"
|
||||
" <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad1)' />\n"
|
||||
"</svg>\n");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestGradientRadial_unitUser_spreadRepeat.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestGradientRadial_unitUser_spreadRepeat.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestGradientRadial, unitUser_spreadPad_unCenter) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n"
|
||||
"<svg height='100' width='100'>\n"
|
||||
" <defs>\n"
|
||||
" <radialGradient id='grad1' cx='50' cy='50' r='24' fx='40' fy='40' spreadMethod='pad' gradientUnits='userSpaceOnUse' >\n"
|
||||
" <stop offset='0%' style='stop-color:orange;stop-opacity:1' />\n"
|
||||
" <stop offset='45%' style='stop-color:red;stop-opacity:1' />\n"
|
||||
" <stop offset='55%' style='stop-color:blue;stop-opacity:1' />\n"
|
||||
" <stop offset='100%' style='stop-color:green;stop-opacity:1' />\n"
|
||||
" </radialGradient>\n"
|
||||
" </defs>\n"
|
||||
" <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad1)' />\n"
|
||||
"</svg>\n");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestGradientRadial_unitUser_spreadPad_unCenter.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestGradientRadial_unitUser_spreadPad_unCenter.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestGradientRadial, unitUser_spreadReflect_unCenter) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n"
|
||||
"<svg height='100' width='100'>\n"
|
||||
" <defs>\n"
|
||||
" <radialGradient id='grad1' cx='50' cy='50' r='24' fx='40' fy='40' spreadMethod='reflect' gradientUnits='userSpaceOnUse' >\n"
|
||||
" <stop offset='0%' style='stop-color:orange;stop-opacity:1' />\n"
|
||||
" <stop offset='45%' style='stop-color:red;stop-opacity:1' />\n"
|
||||
" <stop offset='55%' style='stop-color:blue;stop-opacity:1' />\n"
|
||||
" <stop offset='100%' style='stop-color:green;stop-opacity:1' />\n"
|
||||
" </radialGradient>\n"
|
||||
" </defs>\n"
|
||||
" <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad1)' />\n"
|
||||
"</svg>\n");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestGradientRadial_unitUser_spreadReflect_unCenter.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestGradientRadial_unitUser_spreadReflect_unCenter.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestGradientRadial, unitUser_spreadRepeat_unCenter) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n"
|
||||
"<svg height='100' width='100'>\n"
|
||||
" <defs>\n"
|
||||
" <radialGradient id='grad1' cx='50' cy='50' r='24' fx='40' fy='40' spreadMethod='repeat' gradientUnits='userSpaceOnUse' >\n"
|
||||
" <stop offset='0%' style='stop-color:orange;stop-opacity:1' />\n"
|
||||
" <stop offset='45%' style='stop-color:red;stop-opacity:1' />\n"
|
||||
" <stop offset='55%' style='stop-color:blue;stop-opacity:1' />\n"
|
||||
" <stop offset='100%' style='stop-color:green;stop-opacity:1' />\n"
|
||||
" </radialGradient>\n"
|
||||
" </defs>\n"
|
||||
" <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad1)' />\n"
|
||||
"</svg>\n");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestGradientRadial_unitUser_spreadRepeat_unCenter.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestGradientRadial_unitUser_spreadRepeat_unCenter.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestGradientRadial, unitUser_spreadRepeat_unCenter2) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n"
|
||||
"<svg height='100' width='100'>\n"
|
||||
" <defs>\n"
|
||||
" <radialGradient id='grad1' cx='50' cy='50' r='24' fx='60' fy='60' spreadMethod='repeat' gradientUnits='userSpaceOnUse' >\n"
|
||||
" <stop offset='0%' style='stop-color:orange;stop-opacity:1' />\n"
|
||||
" <stop offset='45%' style='stop-color:red;stop-opacity:1' />\n"
|
||||
" <stop offset='55%' style='stop-color:blue;stop-opacity:1' />\n"
|
||||
" <stop offset='100%' style='stop-color:green;stop-opacity:1' />\n"
|
||||
" </radialGradient>\n"
|
||||
" </defs>\n"
|
||||
" <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad1)' />\n"
|
||||
"</svg>\n");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestGradientRadial_unitUser_spreadRepeat_unCenter2.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestGradientRadial_unitUser_spreadRepeat_unCenter2.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
|
||||
TEST(TestGradientRadial, unitUser_spreadRepeat_out) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n"
|
||||
"<svg height='100' width='100'>\n"
|
||||
" <defs>\n"
|
||||
" <radialGradient id='grad1' cx='50' cy='50' r='24' fx='20' fy='40' spreadMethod='reflect' gradientUnits='userSpaceOnUse' >\n"
|
||||
" <stop offset='0%' style='stop-color:orange;stop-opacity:1' />\n"
|
||||
" <stop offset='45%' style='stop-color:red;stop-opacity:1' />\n"
|
||||
" <stop offset='55%' style='stop-color:blue;stop-opacity:1' />\n"
|
||||
" <stop offset='100%' style='stop-color:green;stop-opacity:1' />\n"
|
||||
" </radialGradient>\n"
|
||||
" </defs>\n"
|
||||
" <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad1)' />\n"
|
||||
"</svg>\n");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestGradientRadial_unitUser_spreadRepeat_out.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestGradientRadial_unitUser_spreadRepeat_out.bmp"), g_visualDebug);
|
||||
}
|
0
test/src/test/atriasoft/esvg/testGroup.java
Normal file
0
test/src/test/atriasoft/esvg/testGroup.java
Normal file
376
test/src/test/atriasoft/esvg/testJoin.java
Normal file
376
test/src/test/atriasoft/esvg/testJoin.java
Normal file
@ -0,0 +1,376 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <etest/etest.hpp>
|
||||
#include <esvg/esvg.hpp>
|
||||
#include "main.hpp"
|
||||
|
||||
// ------------------------------------------------------ Miter test -----------------------------------------------------
|
||||
|
||||
TEST(TestJoin, miterRight1) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <polyline points='20,20 50,50 20,80' stroke='green' stroke-width='20' fill='none' stroke-linejoin='miter'/>"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestJoin_miterRight1.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestJoin_miterRight1.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestJoin, miterRight2) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <polyline points='20,80 50,50 80,80' stroke='green' stroke-width='20' fill='none' stroke-linejoin='miter'/>"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestJoin_miterRight2.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestJoin_miterRight2.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestJoin, miterRight3) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <polyline points='80,80 50,50 80,20' stroke='green' stroke-width='20' fill='none' stroke-linejoin='miter'/>"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestJoin_miterRight3.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestJoin_miterRight3.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestJoin, miterRight4) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <polyline points='80,20 50,50 20,20' stroke='green' stroke-width='20' fill='none' stroke-linejoin='miter'/>"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestJoin_miterRight4.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestJoin_miterRight4.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestJoin, miterLeft1) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <polyline points='80,20 50,50 80,80' stroke='green' stroke-width='20' fill='none' stroke-linejoin='miter'/>"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestJoin_miterLeft1.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestJoin_miterLeft1.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestJoin, miterLeft2) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <polyline points='80,80 50,50 20,80' stroke='green' stroke-width='20' fill='none' stroke-linejoin='miter'/>"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestJoin_miterLeft2.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestJoin_miterLeft2.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestJoin, miterLeft3) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <polyline points='20,80 50,50 20,20' stroke='green' stroke-width='20' fill='none' stroke-linejoin='miter'/>"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestJoin_miterLeft3.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestJoin_miterLeft3.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestJoin, miterLeft4) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <polyline points='20,20 50,50 80,20' stroke='green' stroke-width='20' fill='none' stroke-linejoin='miter'/>"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestJoin_miterLeft4.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestJoin_miterLeft4.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestJoin, miterLimit1) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <polyline points='10,10 25,25 10,40' stroke='green' stroke-width='20' fill='none' stroke-linejoin='miter'/>"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestJoin_miterLimit1.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestJoin_miterLimit1.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestJoin, miterLimit2) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <polyline points='10,10 50,25 10,40' stroke='green' stroke-width='20' fill='none' stroke-linejoin='miter'/>"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestJoin_miterLimit2.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestJoin_miterLimit2.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestJoin, miterLimit3) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <polyline points='10,10 75,25 10,40' stroke='green' stroke-width='20' fill='none' stroke-linejoin='miter'/>"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestJoin_miterLimit3.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestJoin_miterLimit3.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestJoin, miterLimit4) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <polyline points='10,10 90,25 10,40' stroke='green' stroke-width='20' fill='none' stroke-linejoin='miter'/>"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestJoin_miterLimit4.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestJoin_miterLimit4.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestJoin, miterCornerCasePath) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <path"
|
||||
" d='m 37.984608,9.9629707 c 6.211703,0 12.423406,0 18.635109,0 0,2.5633883 0,5.1267763 0,7.6901643 -6.211703,0 -12.423406,0 -18.635109,0 0,-2.563388 0,-5.126776 0,-7.6901643 z'\n"
|
||||
" stroke='green' stroke-width='5' fill='orange' stroke-linejoin='miter'/>"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestJoin_miterCornerCasePath.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestJoin_miterCornerCasePath.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestJoin, miterCornerCasePathLimit) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <path"
|
||||
" d='m 37.984608,9.9629707 c 6.211703,0 12.423406,0 18.635109,0 0,2.5633883 0,5.1267763 0,7.6901643 -6.211703,0 -12.423406,0 -18.635109,0 0,-2.563388 0,-5.126776 0,-7.6901643 z'\n"
|
||||
" stroke='green' stroke-width='5' fill='orange' stroke-linejoin='miter' stroke-miterlimit='0.3'/>"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestJoin_miterCornerCasePathLimit.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestJoin_miterCornerCasePathLimit.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------ Round test -----------------------------------------------------
|
||||
|
||||
TEST(TestJoin, roundRight1) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <polyline points='20,20 50,50 20,80' stroke='green' stroke-width='20' fill='none' stroke-linejoin='round'/>"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestJoin_roundRight1.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestJoin_roundRight1.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestJoin, roundRight2) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <polyline points='20,80 50,50 80,80' stroke='green' stroke-width='20' fill='none' stroke-linejoin='round'/>"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestJoin_roundRight2.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestJoin_roundRight2.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestJoin, roundRight3) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <polyline points='80,80 50,50 80,20' stroke='green' stroke-width='20' fill='none' stroke-linejoin='round'/>"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestJoin_roundRight3.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestJoin_roundRight3.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestJoin, roundRight4) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <polyline points='80,20 50,50 20,20' stroke='green' stroke-width='20' fill='none' stroke-linejoin='round'/>"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestJoin_roundRight4.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestJoin_roundRight4.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestJoin, roundLeft1) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <polyline points='80,20 50,50 80,80' stroke='green' stroke-width='20' fill='none' stroke-linejoin='round'/>"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestJoin_roundLeft1.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestJoin_roundLeft1.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestJoin, roundLeft2) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <polyline points='80,80 50,50 20,80' stroke='green' stroke-width='20' fill='none' stroke-linejoin='round'/>"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestJoin_roundLeft2.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestJoin_roundLeft2.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestJoin, roundLeft3) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <polyline points='20,80 50,50 20,20' stroke='green' stroke-width='20' fill='none' stroke-linejoin='round'/>"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestJoin_roundLeft3.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestJoin_roundLeft3.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestJoin, roundLeft4) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <polyline points='20,20 50,50 80,20' stroke='green' stroke-width='20' fill='none' stroke-linejoin='round'/>"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestJoin_roundLeft4.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestJoin_roundLeft4.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestJoin, roundCornerCasePath) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <path"
|
||||
" d='m 37.984608,9.9629707 c 6.211703,0 12.423406,0 18.635109,0 0,2.5633883 0,5.1267763 0,7.6901643 -6.211703,0 -12.423406,0 -18.635109,0 0,-2.563388 0,-5.126776 0,-7.6901643 z'\n"
|
||||
" stroke='green' stroke-width='5' fill='orange' stroke-linejoin='round'/>"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestJoin_roundCornerCasePath.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestJoin_roundCornerCasePath.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------ Bevel test -----------------------------------------------------
|
||||
|
||||
TEST(TestJoin, bevelRight1) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <polyline points='20,20 50,50 20,80' stroke='green' stroke-width='20' fill='none' stroke-linejoin='bevel'/>"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestJoin_bevelRight1.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestJoin_bevelRight1.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestJoin, bevelRight2) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <polyline points='20,80 50,50 80,80' stroke='green' stroke-width='20' fill='none' stroke-linejoin='bevel'/>"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestJoin_bevelRight2.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestJoin_bevelRight2.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestJoin, bevelRight3) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <polyline points='80,80 50,50 80,20' stroke='green' stroke-width='20' fill='none' stroke-linejoin='bevel'/>"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestJoin_bevelRight3.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestJoin_bevelRight3.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestJoin, bevelRight4) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <polyline points='80,20 50,50 20,20' stroke='green' stroke-width='20' fill='none' stroke-linejoin='bevel'/>"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestJoin_bevelRight4.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestJoin_bevelRight4.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestJoin, bevelLeft1) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <polyline points='80,20 50,50 80,80' stroke='green' stroke-width='20' fill='none' stroke-linejoin='bevel'/>"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestJoin_bevelLeft1.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestJoin_bevelLeft1.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestJoin, bevelLeft2) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <polyline points='80,80 50,50 20,80' stroke='green' stroke-width='20' fill='none' stroke-linejoin='bevel'/>"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestJoin_bevelLeft2.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestJoin_bevelLeft2.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestJoin, bevelLeft3) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <polyline points='20,80 50,50 20,20' stroke='green' stroke-width='20' fill='none' stroke-linejoin='bevel'/>"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestJoin_bevelLeft3.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestJoin_bevelLeft3.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestJoin, bevelLeft4) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <polyline points='20,20 50,50 80,20' stroke='green' stroke-width='20' fill='none' stroke-linejoin='bevel'/>"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestJoin_bevelLeft4.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestJoin_bevelLeft4.bmp"), g_visualDebug);
|
||||
}
|
||||
|
||||
TEST(TestJoin, bevelCornerCasePath) {
|
||||
etk::String data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg height='100' width='100'>"
|
||||
" <path"
|
||||
" d='m 37.984608,9.9629707 c 6.211703,0 12.423406,0 18.635109,0 0,2.5633883 0,5.1267763 0,7.6901643 -6.211703,0 -12.423406,0 -18.635109,0 0,-2.563388 0,-5.126776 0,-7.6901643 z'\n"
|
||||
" stroke='green' stroke-width='5' fill='orange' stroke-linejoin='bevel'/>"
|
||||
"</svg>");
|
||||
esvg::Document doc;
|
||||
doc.parse(data);
|
||||
etk::uri::writeAll(etk::Path("TestJoin_bevelCornerCasePath.svg"), data);
|
||||
doc.generateAnImage(etk::Path("TestJoin_bevelCornerCasePath.bmp"), g_visualDebug);
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user