diff options
Diffstat (limited to 'ardor3d-ui')
120 files changed, 20607 insertions, 0 deletions
diff --git a/ardor3d-ui/.classpath b/ardor3d-ui/.classpath new file mode 100644 index 0000000..3563801 --- /dev/null +++ b/ardor3d-ui/.classpath @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="src" path="src/main/java"/> + <classpathentry kind="src" path="src/main/resources"/> + <classpathentry combineaccessrules="false" kind="src" path="/ardor3d-core"/> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/> + <classpathentry kind="output" path="bin"/> +</classpath> diff --git a/ardor3d-ui/.project b/ardor3d-ui/.project new file mode 100644 index 0000000..ce06751 --- /dev/null +++ b/ardor3d-ui/.project @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>ardor3d-ui</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> diff --git a/ardor3d-ui/.settings/org.eclipse.jdt.core.prefs b/ardor3d-ui/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..48337de --- /dev/null +++ b/ardor3d-ui/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,268 @@ +#Tue Apr 06 11:31:34 CDT 2010 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 +org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_assignment=0 +org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=0 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.blank_lines_before_package=1 +org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false +org.eclipse.jdt.core.formatter.comment.format_block_comments=true +org.eclipse.jdt.core.formatter.comment.format_header=false +org.eclipse.jdt.core.formatter.comment.format_html=true +org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true +org.eclipse.jdt.core.formatter.comment.format_line_comments=true +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true +org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert +org.eclipse.jdt.core.formatter.comment.line_length=120 +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.continuation_indentation=2 +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true +org.eclipse.jdt.core.formatter.indentation.size=4 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.lineSplit=120 +org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false +org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true +org.eclipse.jdt.core.formatter.tabulation.char=space +org.eclipse.jdt.core.formatter.tabulation.size=4 +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false +org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true diff --git a/ardor3d-ui/.settings/org.eclipse.jdt.ui.prefs b/ardor3d-ui/.settings/org.eclipse.jdt.ui.prefs new file mode 100644 index 0000000..fc19842 --- /dev/null +++ b/ardor3d-ui/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,110 @@ +#Fri Jun 12 09:32:15 CDT 2009 +cleanup.add_default_serial_version_id=true +cleanup.add_generated_serial_version_id=false +cleanup.add_missing_annotations=true +cleanup.add_missing_deprecated_annotations=true +cleanup.add_missing_methods=true +cleanup.add_missing_nls_tags=false +cleanup.add_missing_override_annotations=true +cleanup.add_serial_version_id=true +cleanup.always_use_blocks=true +cleanup.always_use_parentheses_in_expressions=true +cleanup.always_use_this_for_non_static_field_access=false +cleanup.always_use_this_for_non_static_method_access=false +cleanup.convert_to_enhanced_for_loop=false +cleanup.correct_indentation=true +cleanup.format_source_code=true +cleanup.format_source_code_changes_only=false +cleanup.make_local_variable_final=true +cleanup.make_parameters_final=true +cleanup.make_private_fields_final=true +cleanup.make_type_abstract_if_missing_method=false +cleanup.make_variable_declarations_final=true +cleanup.never_use_blocks=false +cleanup.never_use_parentheses_in_expressions=false +cleanup.organize_imports=true +cleanup.qualify_static_field_accesses_with_declaring_class=false +cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +cleanup.qualify_static_member_accesses_with_declaring_class=true +cleanup.qualify_static_method_accesses_with_declaring_class=false +cleanup.remove_private_constructors=true +cleanup.remove_trailing_whitespaces=true +cleanup.remove_trailing_whitespaces_all=true +cleanup.remove_trailing_whitespaces_ignore_empty=false +cleanup.remove_unnecessary_casts=true +cleanup.remove_unnecessary_nls_tags=true +cleanup.remove_unused_imports=true +cleanup.remove_unused_local_variables=false +cleanup.remove_unused_private_fields=true +cleanup.remove_unused_private_members=false +cleanup.remove_unused_private_methods=true +cleanup.remove_unused_private_types=true +cleanup.sort_members=false +cleanup.sort_members_all=false +cleanup.use_blocks=true +cleanup.use_blocks_only_for_return_and_throw=false +cleanup.use_parentheses_in_expressions=false +cleanup.use_this_for_non_static_field_access=true +cleanup.use_this_for_non_static_field_access_only_if_necessary=true +cleanup.use_this_for_non_static_method_access=true +cleanup.use_this_for_non_static_method_access_only_if_necessary=true +cleanup_profile=_ArdorLabs +cleanup_settings_version=2 +eclipse.preferences.version=1 +editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true +formatter_profile=_ArdorLabs +formatter_settings_version=11 +org.eclipse.jdt.ui.javadoc=false +org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8"?><templates><template autoinsert\="true" context\="gettercomment_context" deleted\="false" description\="Comment for getter function" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.gettercomment" name\="gettercomment">/**\n * @return the ${bare_field_name}\n */</template><template autoinsert\="true" context\="settercomment_context" deleted\="false" description\="Comment for setter function" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.settercomment" name\="settercomment">/**\n * @param ${param} the ${bare_field_name} to set\n */</template><template autoinsert\="true" context\="constructorcomment_context" deleted\="false" description\="Comment for created constructors" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.constructorcomment" name\="constructorcomment">/**\n * ${tags}\n */</template><template autoinsert\="true" context\="filecomment_context" deleted\="false" description\="Comment for created JavaScript files" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.filecomment" name\="filecomment">/**\n * \n */</template><template autoinsert\="true" context\="typecomment_context" deleted\="false" description\="Comment for created types" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.typecomment" name\="typecomment">/**\n * @author ${user}\n *\n * ${tags}\n */</template><template autoinsert\="true" context\="fieldcomment_context" deleted\="false" description\="Comment for vars" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.fieldcomment" name\="fieldcomment">/**\n * \n */</template><template autoinsert\="true" context\="methodcomment_context" deleted\="false" description\="Comment for non-overriding function" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.methodcomment" name\="methodcomment">/**\n * ${tags}\n */</template><template autoinsert\="true" context\="overridecomment_context" deleted\="false" description\="Comment for overriding functions" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.overridecomment" name\="overridecomment">/* (non-Jsdoc)\n * ${see_to_overridden}\n */</template><template autoinsert\="true" context\="delegatecomment_context" deleted\="false" description\="Comment for delegate functions" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.delegatecomment" name\="delegatecomment">/**\n * ${tags}\n * ${see_to_target}\n */</template><template autoinsert\="true" context\="newtype_context" deleted\="false" description\="Newly created files" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.newtype" name\="newtype">${filecomment}\n${package_declaration}\n\n${typecomment}\n${type_declaration}</template><template autoinsert\="true" context\="classbody_context" deleted\="false" description\="Code in new class type bodies" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.classbody" name\="classbody">\n</template><template autoinsert\="true" context\="catchblock_context" deleted\="false" description\="Code in new catch blocks" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.catchblock" name\="catchblock">// ${todo} Auto-generated catch block\n${exception_var}.printStackTrace();</template><template autoinsert\="true" context\="methodbody_context" deleted\="false" description\="Code in created function stubs" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.methodbody" name\="methodbody">// ${todo} Auto-generated function stub\n${body_statement}</template><template autoinsert\="true" context\="constructorbody_context" deleted\="false" description\="Code in created constructor stubs" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.constructorbody" name\="constructorbody">${body_statement}\n// ${todo} Auto-generated constructor stub</template><template autoinsert\="true" context\="getterbody_context" deleted\="false" description\="Code in created getters" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.getterbody" name\="getterbody">return ${field};</template><template autoinsert\="true" context\="setterbody_context" deleted\="false" description\="Code in created setters" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.setterbody" name\="setterbody">${field} \= ${param};</template><template autoinsert\="true" context\="gettercomment_context" deleted\="false" description\="Comment for getter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.gettercomment" name\="gettercomment">/**\n * @return the ${bare_field_name}\n */</template><template autoinsert\="true" context\="settercomment_context" deleted\="false" description\="Comment for setter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.settercomment" name\="settercomment">/**\n * @param ${param} the ${bare_field_name} to set\n */</template><template autoinsert\="true" context\="constructorcomment_context" deleted\="false" description\="Comment for created constructors" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorcomment" name\="constructorcomment">/**\n * ${tags}\n */</template><template autoinsert\="true" context\="filecomment_context" deleted\="false" description\="Comment for created Java files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.filecomment" name\="filecomment">/**\n * \n */</template><template autoinsert\="false" context\="typecomment_context" deleted\="false" description\="Comment for created types" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.typecomment" name\="typecomment">/**\n * ${tags}\n */</template><template autoinsert\="true" context\="fieldcomment_context" deleted\="false" description\="Comment for fields" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.fieldcomment" name\="fieldcomment">/**\n * \n */</template><template autoinsert\="true" context\="methodcomment_context" deleted\="false" description\="Comment for non-overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodcomment" name\="methodcomment">/**\n * ${tags}\n */</template><template autoinsert\="false" context\="overridecomment_context" deleted\="false" description\="Comment for overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.overridecomment" name\="overridecomment"></template><template autoinsert\="true" context\="delegatecomment_context" deleted\="false" description\="Comment for delegate methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.delegatecomment" name\="delegatecomment">/**\n * ${tags}\n * ${see_to_target}\n */</template><template autoinsert\="false" context\="newtype_context" deleted\="false" description\="Newly created files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.newtype" name\="newtype">/**\n * Copyright (c) 2008-2010 Ardor Labs, Inc.\n *\n * This file is part of Ardor3D.\n *\n * Ardor3D is free software\: you can redistribute it and/or modify it \n * under the terms of its license which may be found in the accompanying\n * LICENSE file or at <http\://www.ardor3d.com/LICENSE>.\n */\n\n${filecomment}\n${package_declaration}\n\n${typecomment}\n${type_declaration}</template><template autoinsert\="true" context\="classbody_context" deleted\="false" description\="Code in new class type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.classbody" name\="classbody">\n</template><template autoinsert\="true" context\="interfacebody_context" deleted\="false" description\="Code in new interface type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.interfacebody" name\="interfacebody">\n</template><template autoinsert\="true" context\="enumbody_context" deleted\="false" description\="Code in new enum type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.enumbody" name\="enumbody">\n</template><template autoinsert\="true" context\="annotationbody_context" deleted\="false" description\="Code in new annotation type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.annotationbody" name\="annotationbody">\n</template><template autoinsert\="true" context\="catchblock_context" deleted\="false" description\="Code in new catch blocks" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.catchblock" name\="catchblock">// ${todo} Auto-generated catch block\n${exception_var}.printStackTrace();</template><template autoinsert\="true" context\="methodbody_context" deleted\="false" description\="Code in created method stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodbody" name\="methodbody">// ${todo} Auto-generated method stub\n${body_statement}</template><template autoinsert\="true" context\="constructorbody_context" deleted\="false" description\="Code in created constructor stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorbody" name\="constructorbody">${body_statement}\n// ${todo} Auto-generated constructor stub</template><template autoinsert\="true" context\="getterbody_context" deleted\="false" description\="Code in created getters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.getterbody" name\="getterbody">return ${field};</template><template autoinsert\="true" context\="setterbody_context" deleted\="false" description\="Code in created setters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.setterbody" name\="setterbody">${field} \= ${param};</template></templates> +sp_cleanup.add_default_serial_version_id=true +sp_cleanup.add_generated_serial_version_id=false +sp_cleanup.add_missing_annotations=true +sp_cleanup.add_missing_deprecated_annotations=true +sp_cleanup.add_missing_methods=false +sp_cleanup.add_missing_nls_tags=false +sp_cleanup.add_missing_override_annotations=true +sp_cleanup.add_serial_version_id=false +sp_cleanup.always_use_blocks=true +sp_cleanup.always_use_parentheses_in_expressions=false +sp_cleanup.always_use_this_for_non_static_field_access=false +sp_cleanup.always_use_this_for_non_static_method_access=false +sp_cleanup.convert_to_enhanced_for_loop=false +sp_cleanup.correct_indentation=true +sp_cleanup.format_source_code=true +sp_cleanup.format_source_code_changes_only=false +sp_cleanup.make_local_variable_final=true +sp_cleanup.make_parameters_final=true +sp_cleanup.make_private_fields_final=true +sp_cleanup.make_type_abstract_if_missing_method=false +sp_cleanup.make_variable_declarations_final=true +sp_cleanup.never_use_blocks=false +sp_cleanup.never_use_parentheses_in_expressions=true +sp_cleanup.on_save_use_additional_actions=true +sp_cleanup.organize_imports=true +sp_cleanup.qualify_static_field_accesses_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_with_declaring_class=true +sp_cleanup.qualify_static_method_accesses_with_declaring_class=true +sp_cleanup.remove_private_constructors=true +sp_cleanup.remove_trailing_whitespaces=true +sp_cleanup.remove_trailing_whitespaces_all=true +sp_cleanup.remove_trailing_whitespaces_ignore_empty=false +sp_cleanup.remove_unnecessary_casts=true +sp_cleanup.remove_unnecessary_nls_tags=true +sp_cleanup.remove_unused_imports=true +sp_cleanup.remove_unused_local_variables=false +sp_cleanup.remove_unused_private_fields=true +sp_cleanup.remove_unused_private_members=false +sp_cleanup.remove_unused_private_methods=true +sp_cleanup.remove_unused_private_types=true +sp_cleanup.sort_members=false +sp_cleanup.sort_members_all=false +sp_cleanup.use_blocks=true +sp_cleanup.use_blocks_only_for_return_and_throw=false +sp_cleanup.use_parentheses_in_expressions=true +sp_cleanup.use_this_for_non_static_field_access=true +sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true +sp_cleanup.use_this_for_non_static_method_access=true +sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/ardor3d-ui/pom.xml b/ardor3d-ui/pom.xml new file mode 100644 index 0000000..06c5215 --- /dev/null +++ b/ardor3d-ui/pom.xml @@ -0,0 +1,32 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>com.ardor3d</groupId>
+ <artifactId>ardor3d</artifactId>
+ <version>0.9-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>ardor3d-ui</artifactId>
+ <packaging>bundle</packaging>
+ <name>Ardor 3D UI</name>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.6</source>
+ <target>1.6</target>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>ardor3d-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/AbstractLabelUIComponent.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/AbstractLabelUIComponent.java new file mode 100644 index 0000000..9683bb9 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/AbstractLabelUIComponent.java @@ -0,0 +1,268 @@ +/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui;
+
+import com.ardor3d.extension.ui.text.RenderedText;
+import com.ardor3d.extension.ui.text.TextFactory;
+import com.ardor3d.extension.ui.util.Alignment;
+import com.ardor3d.extension.ui.util.Dimension;
+import com.ardor3d.extension.ui.util.SubTex;
+import com.ardor3d.extension.ui.util.SubTexUtil;
+import com.ardor3d.math.Transform;
+import com.ardor3d.math.Vector3;
+import com.ardor3d.renderer.Renderer;
+
+/**
+ * A state component containing a text label and an icon. These are separated by an optional gap and can also be given a
+ * specific alignment. By default, the text is aligned LEFT and has no icon or gap.
+ */
+public abstract class AbstractLabelUIComponent extends StateBasedUIComponent implements Textable {
+
+ /** Distance between text and icon if both are present. */
+ private int _gap = 0;
+
+ /** Alignment value to use to position the icon/text within the overall dimensions of this component. */
+ private Alignment _alignment = Alignment.LEFT;
+
+ /** The icon the draw on this icon. */
+ private SubTex _icon = null;
+
+ /** The size to draw our icon at. */
+ private final Dimension _iconDimensions = new Dimension();
+
+ /** The text object to use for drawing label text. */
+ private RenderedText _uiText;
+
+ /** If true, our text could be marked up with style information. */
+ protected boolean _styled = false;
+
+ @Override
+ public void updateMinimumSizeFromContents() {
+ int width = 0;
+ int height = 0;
+
+ final String textVal = getText();
+ if (textVal != null && textVal.length() > 0) {
+ width += Math.round(_uiText.getWidth());
+ height += Math.round(_uiText.getHeight());
+ }
+
+ if (_iconDimensions != null) {
+ width += _iconDimensions.getWidth();
+ if (textVal != null && textVal.length() > 0) {
+ width += _gap;
+ }
+
+ height = Math.max(_iconDimensions.getHeight(), height);
+ }
+
+ setMinimumContentSize(width, height);
+ if (getContentWidth() < width) {
+ setContentWidth(width);
+ }
+ if (getContentHeight() < height) {
+ setContentHeight(height);
+ }
+ fireComponentDirty();
+ }
+
+ /**
+ * @return the currently set text value of this label.
+ */
+ public String getText() {
+ return _uiText != null ? _uiText.getText() : null;
+ }
+
+ /**
+ * Set the text for this component. Also updates the minimum size of the component.
+ *
+ * @param text
+ * the new text
+ */
+ public void setText(String text) {
+ if (text != null && text.length() == 0) {
+ text = null;
+ }
+
+ if (text != null) {
+ _uiText = TextFactory.INSTANCE.generateText(text, isStyledText(), getFontStyles(), _uiText, -1);
+ } else {
+ _uiText = null;
+ }
+
+ updateMinimumSizeFromContents();
+ }
+
+ public boolean isStyledText() {
+ return _styled;
+ }
+
+ public void setStyledText(final boolean value) {
+ _styled = value;
+ fireStyleChanged();
+ fireComponentDirty();
+ }
+
+ @Override
+ protected void updateChildren(final double time) {
+ super.updateChildren(time);
+ if (_uiText != null) {
+ _uiText.updateGeometricState(time);
+ }
+ }
+
+ public Alignment getAlignment() {
+ return _alignment;
+ }
+
+ public void setAlignment(final Alignment alignment) {
+ _alignment = alignment;
+ }
+
+ public int getGap() {
+ return _gap;
+ }
+
+ /**
+ * Note: Also updates the minimum size of the component.
+ *
+ * @param gap
+ * the size of the gap, in pixels, between the text and the label text. This is only used if both icon
+ * and text are set.
+ */
+ public void setGap(final int gap) {
+ _gap = gap;
+ updateMinimumSizeFromContents();
+ }
+
+ public SubTex getIcon() {
+ return _icon;
+ }
+
+ /**
+ * Note: Also updates the minimum size of the component.
+ *
+ * @param icon
+ * the new icon for this label.
+ */
+ public void setIcon(final SubTex icon) {
+ _icon = icon;
+ if (icon != null && _iconDimensions.getHeight() == 0 && _iconDimensions.getWidth() == 0) {
+ updateIconDimensionsFromIcon();
+ }
+ updateMinimumSizeFromContents();
+ }
+
+ /**
+ * Set the icon dimensions from the currently set icon. If no icon is set, the dimensions are set to 0x0.
+ */
+ public void updateIconDimensionsFromIcon() {
+ if (_icon != null) {
+ _iconDimensions.set(_icon.getWidth(), _icon.getHeight());
+ } else {
+ _iconDimensions.set(0, 0);
+ }
+ updateMinimumSizeFromContents();
+ }
+
+ /**
+ * Overrides any currently set icon size. Call this after setting the icon to prevent overriding.
+ *
+ * @param dimensions
+ * a new icon size.
+ */
+ public void setIconDimensions(final Dimension dimensions) {
+ _iconDimensions.set(dimensions);
+ updateMinimumSizeFromContents();
+ }
+
+ public Dimension getIconDimensions() {
+ return _iconDimensions;
+ }
+
+ @Override
+ public void fireStyleChanged() {
+ super.fireStyleChanged();
+ setText(getText());
+ }
+
+ @Override
+ protected void drawComponent(final Renderer renderer) {
+
+ double x = 0;
+ double y = 0;
+ int width = 0;
+ final boolean hasTextObject = getText() != null;
+
+ // Gather our width... check for icon and text and gap.
+ if (_icon != null) {
+ width = _iconDimensions.getWidth();
+ if (hasTextObject && getText().length() > 0) {
+ width += _gap;
+ }
+ } else if (!hasTextObject) {
+ // no text OR icon, so no content to render.
+ return;
+ }
+
+ if (hasTextObject) {
+ width += Math.round(_uiText.getWidth());
+ }
+
+ // find left most x location of content (icon+text) based on alignment.
+ x = _alignment.alignX(getContentWidth(), width);
+
+ if (_icon != null) {
+ // find bottom most y location of icon based on alignment.
+ // TODO: recheck for proper vertical alignment with new text impl
+ // if (hasTextObject && _uiText.getHeight() > _iconDimensions.getHeight()) {
+ // final int trailing = _uiText.getFont().getLineHeight() - _uiText.getFont().getBaseHeight();
+ // y = _alignment.alignY(getContentHeight() - trailing, _iconDimensions.getHeight()) + trailing - 1;
+ // } else {
+ y = _alignment.alignY(getContentHeight(), _iconDimensions.getHeight());
+ // }
+
+ final double dix = getTotalLeft();
+ final double diy = getTotalBottom();
+ // draw icon
+ SubTexUtil.drawSubTex(renderer, _icon, dix + x, diy + y, _iconDimensions.getWidth(), _iconDimensions
+ .getHeight(), getWorldTransform());
+ // shift X over by width of icon and gap
+ x += _iconDimensions.getWidth() + _gap;
+ }
+
+ if (hasTextObject) {
+ // find bottom most y location of text based on alignment.
+ y = _alignment.alignY(getContentHeight(), Math.round(_uiText.getHeight()));
+
+ // set our text location
+ final Vector3 v = Vector3.fetchTempInstance();
+ // note: we round to get the text pixel aligned... otherwise it can get blurry
+ v.set(Math.round(x + getTotalLeft()), Math.round(y + getTotalBottom()), 0);
+
+ final Transform t = Transform.fetchTempInstance();
+ t.set(getWorldTransform());
+ t.applyForwardVector(v);
+ t.translate(v);
+ Vector3.releaseTempInstance(v);
+
+ _uiText.setWorldTransform(t);
+ Transform.releaseTempInstance(t);
+
+ // TODO: alpha of text...
+ _uiText.render(renderer);
+ }
+ }
+
+ public RenderedText getTextObject() {
+ return _uiText;
+ }
+}
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/AbstractUITextEntryComponent.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/AbstractUITextEntryComponent.java new file mode 100644 index 0000000..8eccf5e --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/AbstractUITextEntryComponent.java @@ -0,0 +1,249 @@ +/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui;
+
+import java.util.Map;
+
+import com.ardor3d.extension.ui.text.RenderedText;
+import com.ardor3d.extension.ui.text.StyleConstants;
+import com.ardor3d.extension.ui.text.TextCaret;
+import com.ardor3d.extension.ui.text.TextFactory;
+import com.ardor3d.extension.ui.text.TextSelection;
+import com.ardor3d.extension.ui.text.UIKeyHandler;
+import com.ardor3d.extension.ui.text.RenderedText.RenderedTextData;
+import com.ardor3d.extension.ui.util.Alignment;
+import com.ardor3d.input.InputState;
+import com.ardor3d.input.MouseButton;
+import com.google.common.collect.ImmutableSet;
+
+public abstract class AbstractUITextEntryComponent extends StateBasedUIComponent implements Textable {
+
+ protected int _caretPosition = 0;
+
+ protected boolean _editable = false;
+ protected boolean _copyable = true;
+
+ protected UIState _disabledState;
+ protected UIState _defaultState;
+ protected UIState _writingState;
+
+ /** The text object to use for drawing label text. */
+ protected RenderedText _uiText;
+
+ /** If true, our text could be marked up with style information. */
+ protected boolean _styled = false;
+
+ /** Alignment value to use to position the icon/text within the overall dimensions of this component. */
+ protected Alignment _alignment = Alignment.BOTTOM_LEFT;
+
+ protected TextCaret _caret = new TextCaret();
+
+ protected TextSelection _selection = new TextSelection() {
+ @Override
+ public int getCaretPosition() {
+ return AbstractUITextEntryComponent.this.getCaretPosition();
+ }
+
+ @Override
+ public RenderedTextData getTextData() {
+ return _uiText.getData();
+ }
+ };
+
+ protected abstract UIKeyHandler getKeyHandler();
+
+ @Override
+ public UIState getDefaultState() {
+ return _defaultState;
+ }
+
+ @Override
+ public UIState getDisabledState() {
+ return _disabledState;
+ }
+
+ public UIState getWritingState() {
+ return _writingState;
+ }
+
+ /**
+ * @return the text value of this text entry widget
+ */
+ public String getText() {
+ return _uiText != null ? _uiText.getText() : "";
+ }
+
+ /**
+ * Set the text for this component. Also updates the minimum size of the component.
+ *
+ * @param text
+ * the new text
+ */
+ public void setText(String text) {
+ if (text != null && text.length() == 0) {
+ text = null;
+ }
+
+ if (text != null) {
+ // no need to do anything if text is the same
+ if (text.equals(getText())) {
+ return;
+ }
+ int maxWidth = getMaximumLocalComponentWidth() - getTotalLeft() - getTotalRight();
+ if (maxWidth <= 0) {
+ maxWidth = -1;
+ }
+ _uiText = TextFactory.INSTANCE.generateText(text, isStyledText(), getFontStyles(), _uiText, maxWidth);
+ } else {
+ _uiText = null;
+ // reset caret position
+ setCaretPosition(0);
+ }
+
+ updateMinimumSizeFromContents();
+ }
+
+ public boolean isStyledText() {
+ return _styled;
+ }
+
+ public void setStyledText(final boolean value) {
+ _styled = value;
+ }
+
+ public boolean isCopyable() {
+ return _copyable;
+ }
+
+ public void setCopyable(final boolean copyable) {
+ _copyable = copyable;
+ }
+
+ /**
+ * Set the position of the text caret as an index to the current set text string. If the specified position is after
+ * the last possible index, it is set to the last possible index.
+ *
+ * @param index
+ * the new position
+ */
+ public int setCaretPosition(int index) {
+ final String text = getText();
+ if (index > text.length()) {
+ index = text.length();
+ }
+ if (index < 0) {
+ index = 0;
+ }
+ _caretPosition = index;
+ return _caretPosition;
+ }
+
+ public int getCaretPosition() {
+ return _caretPosition;
+ }
+
+ public int getSelectionLength() {
+ return _selection.getSelectionLength();
+ }
+
+ public void clearSelection() {
+ _selection.reset();
+ }
+
+ public boolean isEditable() {
+ return _editable;
+ }
+
+ /**
+ * @param editable
+ * true if the text of this component can be changed by keyboard interaction
+ */
+ public void setEditable(final boolean editable) {
+ _editable = editable;
+ }
+
+ public TextCaret getCaret() {
+ return _caret;
+ }
+
+ public TextSelection getSelection() {
+ return _selection;
+ }
+
+ public Alignment getAlignment() {
+ return _alignment;
+ }
+
+ public void setAlignment(final Alignment alignment) {
+ _alignment = alignment;
+ }
+
+ @Override
+ public void fireStyleChanged() {
+ super.fireStyleChanged();
+ setText(getText());
+ }
+
+ @Override
+ public void updateMinimumSizeFromContents() {
+ int width = 0;
+ int height = 0;
+
+ final String textVal = getText();
+ if (textVal.length() > 0) {
+ width += Math.round(_uiText.getWidth());
+ height += Math.round(_uiText.getHeight());
+ }
+
+ if (height == 0) {
+ final Map<String, Object> styles = getFontStyles();
+ if (styles.containsKey(StyleConstants.KEY_SIZE)) {
+ height = (Integer) styles.get(StyleConstants.KEY_SIZE);
+ } else {
+ height = UIComponent.getDefaultFontSize();
+ }
+ }
+
+ setMinimumContentSize(width, height);
+ fireComponentDirty();
+ }
+
+ @Override
+ public ImmutableSet<UIState> getStates() {
+ return ImmutableSet.of(_defaultState, _disabledState, _writingState);
+ }
+
+ protected class DefaultTextEntryState extends UIState {
+ @Override
+ public boolean mousePressed(final MouseButton button, final InputState state) {
+ switchState(_writingState);
+
+ final int x = state.getMouseState().getX() - AbstractUITextEntryComponent.this.getHudX()
+ - AbstractUITextEntryComponent.this.getPadding().getLeft();
+ final int y = state.getMouseState().getY() - AbstractUITextEntryComponent.this.getHudY()
+ - AbstractUITextEntryComponent.this.getPadding().getBottom();
+
+ setCaretPosition(_uiText != null ? _uiText.findCaretPosition(x, y) : 0);
+
+ return true;
+ }
+
+ @Override
+ public void mouseEntered(final int mouseX, final int mouseY, final InputState state) {
+ // CursorUtil.getCursorFactory().getTextCursor().setActive();
+ }
+
+ @Override
+ public void mouseDeparted(final int mouseX, final int mouseY, final InputState state) {
+ // CursorUtil.getCursorFactory().getDefaultCursor().setActive();
+ }
+ }
+}
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/FloatingUIContainer.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/FloatingUIContainer.java new file mode 100644 index 0000000..f505a37 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/FloatingUIContainer.java @@ -0,0 +1,39 @@ +/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui;
+
+import com.ardor3d.extension.ui.border.EmptyBorder;
+import com.ardor3d.extension.ui.layout.RowLayout;
+
+/**
+ * An simple, undecorated frame meant for showing content in the UI that can not be moved or resized by the user.
+ */
+public class FloatingUIContainer extends UIFrame {
+
+ public FloatingUIContainer() {
+ super(null);
+ setDecorated(false);
+ getContentPanel().setBorder(new EmptyBorder());
+ getContentPanel().setLayout(new RowLayout(false));
+ setBackdrop(null);
+
+ applySuperSkin();
+ }
+
+ protected void applySuperSkin() {
+ super.applySkin();
+ }
+
+ @Override
+ protected void applySkin() {
+ ;
+ }
+}
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/LabelState.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/LabelState.java new file mode 100644 index 0000000..fc1a8d6 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/LabelState.java @@ -0,0 +1,107 @@ +/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui;
+
+import com.ardor3d.extension.ui.util.Alignment;
+import com.ardor3d.extension.ui.util.Dimension;
+import com.ardor3d.extension.ui.util.SubTex;
+
+/**
+ * A state useful for maintaining and setting label properties such as text, icon, gap, and alignment.
+ */
+public class LabelState extends UIState {
+
+ /** Text to set on component, or null if to leave unchanged. */
+ protected String _text = null;
+ /** Icon to set on component, or null if to leave unchanged. */
+ protected SubTex _icon = null;
+ /** Icon size to set on component, or null if to leave unchanged. */
+ protected Dimension _iconDimensions = null;
+ /** Alignment to set on component, or null if to leave unchanged. */
+ protected Alignment _alignment = null;
+ /** Gap to set on component, or null if to leave unchanged. */
+ protected Integer _gap = null;
+ /** If true, our text could be marked up with style information - null to leave unchanged. */
+ protected Boolean _styled = null;
+
+ @Override
+ public void setupAppearance(final UIComponent component) {
+ super.setupAppearance(component);
+
+ // Add some extra settings if this is a label component.
+ if (component instanceof AbstractLabelUIComponent) {
+ final AbstractLabelUIComponent labelComponent = (AbstractLabelUIComponent) component;
+ if (_text != null) {
+ labelComponent.setText(_text);
+ }
+ if (_icon != null) {
+ labelComponent.setIcon(_icon);
+ }
+ if (_iconDimensions != null) {
+ labelComponent.setIconDimensions(_iconDimensions);
+ }
+ if (_gap != null) {
+ labelComponent.setGap(_gap);
+ }
+ if (_alignment != null) {
+ labelComponent.setAlignment(_alignment);
+ }
+ }
+ }
+
+ public Alignment getAlignment() {
+ return _alignment;
+ }
+
+ public void setAlignment(final Alignment align) {
+ _alignment = align;
+ }
+
+ public Integer getGap() {
+ return _gap;
+ }
+
+ public void setGap(final int gap) {
+ _gap = gap;
+ }
+
+ public SubTex getIcon() {
+ return _icon;
+ }
+
+ public void setIcon(final SubTex icon) {
+ _icon = icon;
+ }
+
+ public Dimension getIconDimensions() {
+ return _iconDimensions;
+ }
+
+ public void setIconDimensions(final Dimension iconDimensions) {
+ _iconDimensions = iconDimensions;
+ }
+
+ public String getText() {
+ return _text;
+ }
+
+ public void setText(final String text) {
+ _text = text;
+ }
+
+ public Boolean isStyledText() {
+ return _styled;
+ }
+
+ public void setStyledText(final Boolean value) {
+ _styled = value;
+ }
+}
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/Orientation.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/Orientation.java new file mode 100644 index 0000000..812f839 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/Orientation.java @@ -0,0 +1,15 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui; + +public enum Orientation { + Vertical, Horizontal; +} diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/StateBasedUIComponent.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/StateBasedUIComponent.java new file mode 100644 index 0000000..357d87e --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/StateBasedUIComponent.java @@ -0,0 +1,174 @@ +/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui;
+
+import com.ardor3d.input.InputState;
+import com.ardor3d.input.Key;
+import com.ardor3d.input.MouseButton;
+import com.ardor3d.math.type.ReadOnlyColorRGBA;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * StateBasedUIComponent describes a component that acts as a state machine, containing multiple states, one of which is
+ * currently active. Each of these states may override the current appearance and behavior of the component, making this
+ * class an ideal base for components such as "mouse over" buttons, components that can be visibly "disabled",
+ * toggleable components, etc.
+ */
+public abstract class StateBasedUIComponent extends UIComponent {
+
+ /** The state currently active on this component. */
+ private UIState _currentState = null;
+
+ /**
+ * @return the state that represents the default appearance and behavior for this component.
+ */
+ public abstract UIState getDefaultState();
+
+ /**
+ * @return the state that represents the disabled appearance and behavior for this component.
+ */
+ public abstract UIState getDisabledState();
+
+ /**
+ * @return this component's currently active state
+ */
+ public UIState getCurrentState() {
+ return _currentState;
+ }
+
+ /**
+ * @param enabled
+ * if true, sets the defaultState to active, otherwise sets the disabledState to active.
+ */
+ @Override
+ public void setEnabled(final boolean enabled) {
+ super.setEnabled(enabled);
+ if (enabled) {
+ switchState(getDefaultState());
+ } else {
+ switchState(getDisabledState());
+ }
+ }
+
+ /**
+ * Set our current active state.
+ *
+ * @param nextState
+ * the state to set as active for this component. If null, this is a no-op.
+ */
+ public final void switchState(final UIState nextState) {
+ if (nextState == null) {
+ return;
+ }
+
+ // Release any current state.
+ if (_currentState != null) {
+ _currentState.release();
+ }
+
+ // initialize component from state
+ nextState.setupAppearance(this);
+
+ // set as current and fire dirty to notify we have changed.
+ _currentState = nextState;
+ fireComponentDirty();
+ }
+
+ /**
+ * Re-apply the current state.
+ */
+ public void refreshState() {
+ switchState(_currentState);
+ }
+
+ /**
+ * Sets the text color on this component and (optionally) all contained states.
+ *
+ * @param color
+ * the new foreground color
+ * @param allStates
+ * if true, set across all contained states as well as self.
+ */
+ public void setForegroundColor(final ReadOnlyColorRGBA color, final boolean allStates) {
+ super.setForegroundColor(color);
+ if (allStates) {
+ for (final UIState state : getStates()) {
+ state.setForegroundColor(color);
+ }
+ }
+ }
+
+ // Redirect input / event methods to current state.
+
+ @Override
+ public void mouseDeparted(final int mouseX, final int mouseY, final InputState state) {
+ getCurrentState().mouseDeparted(mouseX, mouseY, state);
+ super.mouseDeparted(mouseX, mouseY, state);
+ }
+
+ @Override
+ public void mouseEntered(final int mouseX, final int mouseY, final InputState state) {
+ getCurrentState().mouseEntered(mouseX, mouseY, state);
+ super.mouseEntered(mouseX, mouseY, state);
+ }
+
+ @Override
+ public boolean mouseMoved(final int mouseX, final int mouseY, final InputState state) {
+ return getCurrentState().mouseMoved(mouseX, mouseY, state) || super.mouseMoved(mouseX, mouseY, state);
+ }
+
+ @Override
+ public boolean mousePressed(final MouseButton button, final InputState state) {
+ return getCurrentState().mousePressed(button, state) || super.mousePressed(button, state);
+ }
+
+ @Override
+ public boolean mouseReleased(final MouseButton button, final InputState state) {
+ return getCurrentState().mouseReleased(button, state) || super.mouseReleased(button, state);
+ }
+
+ @Override
+ public boolean mouseWheel(final int wheelDx, final InputState state) {
+ return getCurrentState().mouseWheel(wheelDx, state) || super.mouseWheel(wheelDx, state);
+ }
+
+ @Override
+ public boolean keyPressed(final Key key, final InputState state) {
+ return getCurrentState().keyPressed(key, state) || super.keyPressed(key, state);
+ }
+
+ @Override
+ public boolean keyReleased(final Key key, final InputState state) {
+ return getCurrentState().keyReleased(key, state) || super.keyReleased(key, state);
+ }
+
+ @Override
+ public boolean keyHeld(final Key key, final InputState state) {
+ return getCurrentState().keyHeld(key, state) || super.keyHeld(key, state);
+ }
+
+ @Override
+ public void gainedFocus() {
+ getCurrentState().gainedFocus();
+ super.gainedFocus();
+ }
+
+ @Override
+ public void lostFocus() {
+ getCurrentState().lostFocus();
+ super.lostFocus();
+ }
+
+ /**
+ * @return an ImmutableSet of possible states for this component.
+ */
+ public abstract ImmutableSet<UIState> getStates();
+}
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/Textable.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/Textable.java new file mode 100644 index 0000000..5fd2e9f --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/Textable.java @@ -0,0 +1,26 @@ +/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui;
+
+/**
+ * Interface for items that can take and return a text string value.
+ */
+public interface Textable {
+
+ public void setText(String value);
+
+ public String getText();
+
+ public boolean isStyledText();
+
+ public void setStyledText(boolean value);
+
+}
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIButton.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIButton.java new file mode 100644 index 0000000..cd9a6ba --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIButton.java @@ -0,0 +1,450 @@ +/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.ardor3d.extension.ui.event.ActionEvent;
+import com.ardor3d.extension.ui.event.ActionListener;
+import com.ardor3d.extension.ui.util.ButtonGroup;
+import com.ardor3d.extension.ui.util.SubTex;
+import com.ardor3d.input.InputState;
+import com.ardor3d.input.MouseButton;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * A state based component that can be interacted with via the mouse to trigger actions.
+ */
+public class UIButton extends AbstractLabelUIComponent {
+
+ /** Default state to use for the button. */
+ protected LabelState _defaultState = new DefaultState();
+ /** State to use when the mouse button is disabled. */
+ protected LabelState _disabledState = new LabelState();
+
+ /** State to use when the mouse button is pressed and held down over this button. */
+ protected LabelState _pressedState = new PressedState();
+
+ /** State to use when the mouse is hovering over this button. */
+ protected LabelState _mouseOverState = new MouseOverState();
+
+ /** State to use when the mouse button is currently selected. */
+ protected LabelState _selectedState = new SelectedState();
+ /** State to use when the mouse is hovering over this button while currently selected. */
+ protected LabelState _mouseOverSelectedState = new MouseOverSelectedState();
+ /** State to use when the mouse button is disabled while currently selected. */
+ protected LabelState _disabledSelectedState = new LabelState();
+
+ /** List of action listeners notified when this button is pressed. */
+ private final List<ActionListener> _listeners = new ArrayList<ActionListener>();
+
+ /** True if this is button is selectable/toggleable. */
+ private boolean _selectable = false;
+ /** True if this is button is currently selected. */
+ private boolean _selected = false;
+
+ /** ButtonGroup this button belongs to. */
+ private ButtonGroup _group = null;
+
+ /** Configurable action command */
+ private String _actionCommand = null;
+
+ /**
+ * Construct a new, blank button
+ */
+ public UIButton() {
+ this("");
+ }
+
+ /**
+ * Construct a new button with the given text.
+ *
+ * @param text
+ */
+ public UIButton(final String text) {
+ this(text, null);
+ }
+
+ /**
+ * Construct a new button with the given text and icon.
+ *
+ * @param text
+ * @param icon
+ */
+ public UIButton(final String text, final SubTex icon) {
+ setConsumeMouseEvents(true);
+ setIcon(icon);
+
+ applySkin();
+ setButtonText(text);
+
+ switchState(getDefaultState());
+ }
+
+ /**
+ * @return true if the pressed state is our current state.
+ */
+ public boolean isPressed() {
+ return getCurrentState().equals(getPressedState());
+ }
+
+ /**
+ * @return true if the mouse over state is our current state.
+ */
+ public boolean isMouseOver() {
+ return getCurrentState().equals(getMouseOverState());
+ }
+
+ /**
+ * Add the specified listener to this button's list of listeners notified when pressed.
+ *
+ * @param listener
+ */
+ public void addActionListener(final ActionListener listener) {
+ _listeners.add(listener);
+ }
+
+ /**
+ * Remove the given listener from the notification list.
+ *
+ * @param listener
+ */
+ public boolean removeActionListener(final ActionListener listener) {
+ return _listeners.remove(listener);
+ }
+
+ /**
+ * Removes all of this button's listeners from notification list.
+ */
+ public void removeAllListeners() {
+ _listeners.clear();
+ }
+
+ /**
+ * Notifies all of this button's registered listeners that this button was pressed.
+ */
+ public void fireActionEvent() {
+ if (!isEnabled()) {
+ return;
+ }
+ final ActionEvent event = new ActionEvent(this);
+ for (final ActionListener l : _listeners) {
+ l.actionPerformed(event);
+ }
+ }
+
+ public LabelState getMouseOverState() {
+ return _mouseOverState;
+ }
+
+ public LabelState getMouseOverSelectedState() {
+ return _mouseOverSelectedState;
+ }
+
+ public LabelState getPressedState() {
+ return _pressedState;
+ }
+
+ public LabelState getSelectedState() {
+ return _selectedState;
+ }
+
+ public LabelState getDisabledSelectedState() {
+ return _disabledSelectedState;
+ }
+
+ /**
+ * always mark consumed.
+ */
+ @Override
+ public boolean mousePressed(final MouseButton button, final InputState state) {
+ // always consume
+ super.mousePressed(button, state);
+ return true;
+ }
+
+ /**
+ * always mark consumed.
+ */
+ @Override
+ public boolean mouseReleased(final MouseButton button, final InputState state) {
+ // always consume
+ super.mouseReleased(button, state);
+ return true;
+ }
+
+ /**
+ * @return true if button is selectable and is selected.
+ */
+ public boolean isSelected() {
+ if (!_selectable) {
+ return false;
+ }
+ return _selected;
+ }
+
+ /**
+ * If selectable, set this button's state to either selected (true) or default (false) - or disabled versions of
+ * each if currently disabled.
+ *
+ * @param selected
+ */
+ public void setSelected(boolean selected) {
+ if (!_selectable) {
+ return;
+ }
+
+ if (_group != null) {
+ _group.setSelected(this, selected);
+ selected = _group.isSelected(this);
+ }
+
+ if (isSelected() == selected) {
+ return;
+ }
+
+ _selected = selected;
+
+ if (_selected) {
+ if (getCurrentState() instanceof PressedState) {
+ switchState(getMouseOverSelectedState());
+ } else {
+ switchState(isEnabled() ? getSelectedState() : getDisabledSelectedState());
+ }
+ } else {
+ if (getCurrentState() instanceof MouseOverSelectedState) {
+ switchState(getMouseOverState());
+ } else {
+ switchState(isEnabled() ? getDefaultState() : getDisabledState());
+ }
+ }
+ }
+
+ /**
+ * @param selectable
+ * true if this button should be selectable
+ */
+ public void setSelectable(final boolean selectable) {
+ if (isSelectable() && !selectable && isSelected()) {
+ setSelected(false);
+ }
+ _selectable = selectable;
+ }
+
+ /**
+ * @return true if button is selectable
+ */
+ public boolean isSelectable() {
+ return _selectable;
+ }
+
+ /**
+ * @param group
+ * the group this button should belong to. Removes the button from any group it currently belongs to.
+ */
+ public void setGroup(final ButtonGroup group) {
+ final ButtonGroup oldGroup = _group;
+ _group = group;
+
+ if (oldGroup != null) {
+ oldGroup.remove(this);
+ }
+
+ _group.add(this);
+ if (isSelected()) {
+ _group.setSelected(this, isSelected());
+ }
+ }
+
+ /**
+ * @return the button group this button belongs to or null if it belongs to none.
+ */
+ public ButtonGroup getGroup() {
+ return _group;
+ }
+
+ /**
+ * @param enabled
+ * if true, sets the defaultState to active, otherwise sets the disabledState or disabledSelectedState to
+ * active.
+ */
+ @Override
+ public void setEnabled(final boolean enabled) {
+ super.setEnabled(enabled);
+ if (isSelectable() && isSelected()) {
+ switchState(enabled ? getSelectedState() : getDisabledSelectedState());
+ }
+ }
+
+ @Override
+ public LabelState getDefaultState() {
+ return _defaultState;
+ }
+
+ @Override
+ public LabelState getDisabledState() {
+ return _disabledState;
+ }
+
+ /**
+ * Sets the text on this button and all contained states.
+ *
+ * @param text
+ * the new text
+ */
+ public void setButtonText(final String text) {
+ super.setText(text);
+ for (final UIState state : getStates()) {
+ if (state instanceof LabelState) {
+ ((LabelState) state).setText(text);
+ }
+ }
+ }
+
+ /**
+ * Sets the text on this button and all contained states.
+ *
+ * @param text
+ * the new text
+ * @param isStyled
+ * if true, the text may contain style markup.
+ */
+ public void setButtonText(final String text, final boolean isStyled) {
+ super.setStyledText(isStyled);
+ super.setText(text);
+ for (final UIState state : getStates()) {
+ if (state instanceof LabelState) {
+ ((LabelState) state).setText(text);
+ ((LabelState) state).setStyledText(isStyled);
+ }
+ }
+ }
+
+ /**
+ * Sets the icon on this button and all contained states.
+ *
+ * @param icon
+ * the new icon
+ */
+ public void setButtonIcon(final SubTex icon) {
+ super.setIcon(icon);
+ for (final UIState state : getStates()) {
+ if (state instanceof LabelState) {
+ ((LabelState) state).setIcon(icon);
+ }
+ }
+ }
+
+ public String getActionCommand() {
+ if (_actionCommand == null) {
+ return getText();
+ } else {
+ return _actionCommand;
+ }
+ }
+
+ public void setActionCommand(final String actionCommand) {
+ _actionCommand = actionCommand;
+ }
+
+ /**
+ * Manually click the button.
+ */
+ public void doClick() {
+ _pressedState.mouseReleased(MouseButton.LEFT, null);
+ }
+
+ // Button UI states that handles switching to other states based on mouse events.
+
+ class DefaultState extends LabelState {
+
+ @Override
+ public void mouseEntered(final int mouseX, final int mouseY, final InputState state) {
+ switchState(getMouseOverState());
+ }
+
+ @Override
+ public boolean mousePressed(final MouseButton button, final InputState state) {
+ switchState(getPressedState());
+ return true;
+ }
+ }
+
+ class MouseOverState extends LabelState {
+
+ @Override
+ public void mouseDeparted(final int mouseX, final int mouseY, final InputState state) {
+ switchState(getDefaultState());
+ }
+
+ @Override
+ public boolean mousePressed(final MouseButton button, final InputState state) {
+ switchState(getPressedState());
+ return true;
+ }
+ }
+
+ class PressedState extends LabelState {
+
+ @Override
+ public void mouseDeparted(final int mouseX, final int mouseY, final InputState state) {
+ switchState(getDefaultState());
+ }
+
+ @Override
+ public boolean mouseReleased(final MouseButton button, final InputState state) {
+ if (_selectable) {
+ setSelected(!isSelected());
+ } else {
+ switchState(getMouseOverState());
+ }
+ fireActionEvent();
+ return true;
+ }
+ }
+
+ class SelectedState extends LabelState {
+
+ @Override
+ public void mouseEntered(final int mouseX, final int mouseY, final InputState state) {
+ switchState(getMouseOverSelectedState());
+ }
+
+ @Override
+ public boolean mouseReleased(final MouseButton button, final InputState state) {
+ setSelected(!isSelected());
+ fireActionEvent();
+ return true;
+ }
+ }
+
+ class MouseOverSelectedState extends LabelState {
+
+ @Override
+ public void mouseDeparted(final int mouseX, final int mouseY, final InputState state) {
+ switchState(getSelectedState());
+ }
+
+ @Override
+ public boolean mouseReleased(final MouseButton button, final InputState state) {
+ setSelected(!isSelected());
+ fireActionEvent();
+ return true;
+ }
+ }
+
+ @Override
+ public ImmutableSet<UIState> getStates() {
+ return ImmutableSet.of((UIState) _defaultState, _disabledState, _pressedState, _selectedState,
+ _disabledSelectedState, _mouseOverState, _mouseOverSelectedState);
+ }
+}
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UICheckBox.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UICheckBox.java new file mode 100644 index 0000000..d6bf163 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UICheckBox.java @@ -0,0 +1,49 @@ +/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui;
+
+import com.ardor3d.extension.ui.util.SubTex;
+
+/**
+ * A extension of button that is specifically selectable. This class is defined distinctly from UIButton to allow for
+ * specific skinning.
+ */
+public class UICheckBox extends UIButton {
+
+ public UICheckBox() {
+ this("");
+ }
+
+ public UICheckBox(final String text) {
+ this(text, null);
+ }
+
+ public UICheckBox(final String text, final SubTex icon) {
+ super(text, icon);
+ super.setSelectable(true);
+ }
+
+ /**
+ * Ignored
+ */
+ @Override
+ public void setSelectable(final boolean selectable) {
+ ;
+ }
+
+ /**
+ * @return true
+ */
+ @Override
+ public boolean isSelectable() {
+ return true;
+ }
+}
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIComboBox.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIComboBox.java new file mode 100644 index 0000000..df93d7f --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIComboBox.java @@ -0,0 +1,239 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui; + +import java.util.List; + +import com.ardor3d.extension.ui.event.ActionEvent; +import com.ardor3d.extension.ui.event.ActionListener; +import com.ardor3d.extension.ui.event.SelectionListener; +import com.ardor3d.extension.ui.layout.BorderLayout; +import com.ardor3d.extension.ui.layout.BorderLayoutData; +import com.ardor3d.extension.ui.model.ComboBoxModel; +import com.ardor3d.extension.ui.model.DefaultComboBoxModel; +import com.ardor3d.extension.ui.skin.SkinningTask; +import com.ardor3d.extension.ui.text.StyleConstants; +import com.ardor3d.input.InputState; +import com.ardor3d.input.MouseButton; +import com.ardor3d.scenegraph.Spatial; +import com.google.common.collect.Lists; + +/** + * A UI component that contains several possible choices, but shows only the currently selected one. Changing the + * selection is allowed via a popup menu shown when the component is clicked on. + */ +public class UIComboBox extends UIPanel { + + protected ComboBoxModel _model; + + protected UILabel _valueLabel; + protected UIButton _openButton; + protected UIPopupMenu _valuesMenu; + + protected int _selectedIndex = 0; + + private final List<SelectionListener<UIComboBox>> _listeners = Lists.newArrayList(); + + private SkinningTask _itemSkinCallback; + + public UIComboBox() { + this(new DefaultComboBoxModel()); + } + + public UIComboBox(final ComboBoxModel model) { + super(new BorderLayout()); + if (model == null) { + throw new IllegalArgumentException("model can not be null."); + } + _model = model; + + _valueLabel = new UILabel(_model.size() > 0 ? _model.getViewAt(0) : "") { + @Override + public boolean mouseReleased(final MouseButton button, final InputState state) { + _openButton.doClick(); + return true; + } + }; + _valueLabel.setLayoutData(BorderLayoutData.CENTER); + add(_valueLabel); + + _openButton = new UIButton("\\/"); + _openButton.setLayoutData(BorderLayoutData.EAST); + add(_openButton); + + _valuesMenu = new UIPopupMenu() { + @Override + public UIComponent getUIComponent(final int hudX, final int hudY) { + final UIComponent component = super.getUIComponent(hudX, hudY); + if (component != null) { + if (component instanceof UIButton) { + final UIButton over = (UIButton) component; + final UIState state = over.getCurrentState(); + if (state == over.getDefaultState() || state == over.getSelectedState()) { + clearOver(); + } + } + } + return component; + } + }; + + _openButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(final ActionEvent event) { + if (!isEnabled()) { + return; + } + + if (_valuesMenu.isAttachedToHUD()) { + _valuesMenu.getHud().closePopupMenus(); + } + + _valuesMenu.clearItems(); + for (int i = 0; i < _model.size(); i++) { + final UIMenuItem item = new UIMenuItem("" + _model.getValueAt(i)); + if (_itemSkinCallback != null) { + _itemSkinCallback.skinComponent(item); + } + if (i == getSelectedIndex()) { + item.addFontStyle(StyleConstants.KEY_BOLD, Boolean.TRUE); + } + final int index = i; + item.addActionListener(new ActionListener() { + @Override + public void actionPerformed(final ActionEvent event) { + setSelectedIndex(index); + } + }); + + // Apply model for name and toolTipText + item.setName(_model.getViewAt(i)); + item.setTooltipText(_model.getToolTipAt(i)); + _valuesMenu.addItem(item); + } + + _valuesMenu.updateMinimumSizeFromContents(); + _valuesMenu.pack(); + if (_valuesMenu.getLocalComponentWidth() < UIComboBox.this.getLocalComponentWidth()) { + _valuesMenu.setLocalComponentWidth(UIComboBox.this.getLocalComponentWidth()); + } + _valuesMenu.layout(); + getHud().closePopupMenus(); + getHud().showSubPopupMenu(_valuesMenu); + _valuesMenu.showAt(_valueLabel.getHudX(), _valueLabel.getHudY()); + } + }); + + applySkin(); + } + + protected void clearOver() { + _openButton.switchState(_openButton.getDefaultState()); + for (int i = _valuesMenu.getNumberOfChildren(); --i >= 0;) { + final Spatial item = _valuesMenu.getChild(i); + if (item instanceof UIButton) { + final UIButton over = (UIButton) item; + over.switchState(over.getDefaultState()); + } + } + } + + public int getSelectedIndex() { + return _selectedIndex; + } + + public Object getSelectedValue() { + return _model.getValueAt(getSelectedIndex()); + } + + public void setSelectedIndex(final int index) { + setSelectedIndex(index, true); + } + + public void setSelectedIndex(final int index, final boolean fireEvent) { + if (index != _selectedIndex) { + _selectedIndex = index; + if (fireEvent) { + fireSelectionEvent(); + } + fireComponentDirty(); + } + + if (index == -1 || _model == null || _model.size() == 0) { + _valueLabel.setText(""); + } else { + _valueLabel.setText(_model.getViewAt(index)); + } + } + + protected void fireSelectionEvent() { + if (!isEnabled()) { + return; + } + for (final SelectionListener<UIComboBox> listener : _listeners) { + listener.selectionChanged(this, getSelectedValue()); + } + } + + @Override + public void setEnabled(final boolean enabled) { + super.setEnabled(enabled); + _valueLabel.setEnabled(enabled); + _openButton.setEnabled(enabled); + } + + @Override + public String getTooltipText() { + if (_tooltipText == null) { + final String rVal = _model.getToolTipAt(_selectedIndex); + if (rVal != null) { + return rVal; + } + } + return super.getTooltipText(); + } + + public UILabel getValueLabel() { + return _valueLabel; + } + + public ComboBoxModel getModel() { + return _model; + } + + public UIButton getOpenButton() { + return _openButton; + } + + public UIPopupMenu getValuesMenu() { + return _valuesMenu; + } + + public void addSelectionListener(final SelectionListener<UIComboBox> listener) { + _listeners.add(listener); + } + + public void removeSelectionListener(final SelectionListener<UIComboBox> listener) { + _listeners.remove(listener); + } + + public void clearSelectionListeners() { + _listeners.clear(); + } + + public void setItemSkinCallback(final SkinningTask callback) { + _itemSkinCallback = callback; + } + + public SkinningTask getItemSkinCallback() { + return _itemSkinCallback; + } +} diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIComponent.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIComponent.java new file mode 100644 index 0000000..9d2b983 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIComponent.java @@ -0,0 +1,1599 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui; + +import java.util.Map; +import java.util.concurrent.Callable; +import java.util.concurrent.FutureTask; + +import com.ardor3d.extension.ui.backdrop.EmptyBackdrop; +import com.ardor3d.extension.ui.backdrop.UIBackdrop; +import com.ardor3d.extension.ui.border.EmptyBorder; +import com.ardor3d.extension.ui.border.UIBorder; +import com.ardor3d.extension.ui.layout.UILayoutData; +import com.ardor3d.extension.ui.skin.SkinManager; +import com.ardor3d.extension.ui.text.StyleConstants; +import com.ardor3d.extension.ui.text.UIKeyHandler; +import com.ardor3d.extension.ui.util.Dimension; +import com.ardor3d.extension.ui.util.Insets; +import com.ardor3d.input.InputState; +import com.ardor3d.input.Key; +import com.ardor3d.input.MouseButton; +import com.ardor3d.math.ColorRGBA; +import com.ardor3d.math.MathUtils; +import com.ardor3d.math.Rectangle2; +import com.ardor3d.math.Transform; +import com.ardor3d.math.Vector3; +import com.ardor3d.math.type.ReadOnlyColorRGBA; +import com.ardor3d.math.type.ReadOnlyTransform; +import com.ardor3d.math.type.ReadOnlyVector3; +import com.ardor3d.renderer.Camera; +import com.ardor3d.renderer.ContextManager; +import com.ardor3d.renderer.Renderer; +import com.ardor3d.renderer.state.BlendState; +import com.ardor3d.renderer.state.BlendState.BlendEquation; +import com.ardor3d.renderer.state.BlendState.DestinationFunction; +import com.ardor3d.renderer.state.BlendState.SourceFunction; +import com.ardor3d.renderer.state.RenderState.StateType; +import com.ardor3d.scenegraph.Node; +import com.ardor3d.scenegraph.event.DirtyType; +import com.ardor3d.scenegraph.hint.PickingHint; +import com.google.common.collect.Maps; + +/** + * Base UI class. All UI components/widgets/controls extend this class. + * + * TODO: alert/dirty needed for font style changes. + */ +public abstract class UIComponent extends Node implements UIKeyHandler { + /** If true, use opacity settings to blend the components. Default is false. */ + private static boolean _useTransparency = false; + + /** The opacity of the component currently being rendered. */ + private static float _currentOpacity = 1f; + + /** The internal contents portion of this component. */ + private final Dimension _contentsSize = new Dimension(10, 10); + /** The absolute minimum size of the internal contents portion of this component. */ + private final Dimension _minimumContentsSize = new Dimension(10, 10); + /** The absolute maximum size of the internal contents portion of this component. */ + private final Dimension _maximumContentsSize = new Dimension(10000, 10000); + /** A spacing between the component's border and its inner content area. */ + private Insets _padding = new Insets(0, 0, 0, 0); + /** A border around this component. */ + private UIBorder _border = new EmptyBorder(); + /** A spacing between the component's border and other content outside this component. Used during layout. */ + private Insets _margin = new Insets(0, 0, 0, 0); + + /** The renderer responsible for drawing this component's backdrop. */ + private UIBackdrop _backdrop = new EmptyBackdrop(); + + /** White */ + public static ReadOnlyColorRGBA DEFAULT_FOREGROUND_COLOR = ColorRGBA.WHITE; + /** The color of any text or other such foreground elements. Inherited from parent if null. */ + private ColorRGBA _foregroundColor = null; + + /** Text to display using UITooltip when hovered over. Inherited from parent if null. */ + protected String _tooltipText = null; + /** The amount of time (in ms) before we should show the tooltip on this component. */ + protected int _tooltipPopTime = 1000; + + /** The default font family (Vera) used when font family field and all parents font fields are null. */ + private static String _defaultFontFamily = "Vera"; + + /** The default font size (18) used when font size field and all parents font size fields are 0. */ + private static int _defaultFontSize = 18; + + /** The default font styles to use. */ + private static Map<String, Object> _defaultFontStyles = Maps.newHashMap(); + /** The font styles to use for text on this component, if needed. */ + private Map<String, Object> _fontStyles = Maps.newHashMap(); + + /** Optional information used by a parent container's layout. */ + private UILayoutData _layoutData = null; + + /** If true, this component is drawn. */ + private boolean _visible = true; + /** If false, this component may optionally disable input to it and its children (as applicable). */ + private boolean _enabled = true; + /** If true, we will consume any mouse events that are sent to this component. (default is false) */ + private boolean _consumeMouseEvents = false; + /** If true, we will consume any key events that are sent to this component. (default is false) */ + private boolean _consumeKeyEvents = false; + + /** The opacity of this component. 0 is fully transparent and 1 is fully opaque. The default is 1. */ + private float _opacity = 1.0f; + + /** If we are selected for key focus, we'll redirect that focus to this target if not null. */ + private UIComponent _keyFocusTarget = null; + + /** + * flag to indicate if a component has touched its content area. Used to determine blending operations for child + * components. + */ + private boolean _virginContentArea = false; + + /** The current future task set to show a tooltip in the near future. */ + private FutureTask<Void> _showTask; + + /** The system time when the tool tip should show up next (if currently being timed.) */ + private long _toolDone; + + /** Blend states to use when drawing components as cached container contents. */ + private static BlendState _srcRGBmaxAlphaBlend = UIComponent.createSrcRGBMaxAlphaBlend(); + private static BlendState _blendRGBmaxAlphaBlend = UIComponent.createBlendRGBMaxAlphaBlend(); + + protected void applySkin() { + SkinManager.applyCurrentSkin(this); + updateMinimumSizeFromContents(); + } + + /** + * @return true if this component should be considered "enabled"... a concept that is interpreted by each individual + * component type. + */ + public boolean isEnabled() { + return _enabled; + } + + /** + * @param enabled + * true if this component should be considered "enabled"... a concept that is interpreted by each + * individual component type. + */ + public void setEnabled(final boolean enabled) { + _enabled = enabled; + } + + /** + * @return true if this component should be drawn. + */ + public boolean isVisible() { + return _visible; + } + + /** + * @param visible + * true if this component should be drawn. + */ + public void setVisible(final boolean visible) { + _visible = visible; + } + + /** + * Used primarily during rendering to determine how alpha blending should be done. + * + * @return true if nothing has been drawn by this component or its ancestors yet that would affect its content area. + */ + public boolean hasVirginContentArea() { + if (!_virginContentArea) { + return false; + } else if (getParent() instanceof UIComponent) { + return ((UIComponent) getParent()).hasVirginContentArea(); + } else { + return true; + } + } + + /** + * @param virgin + * true if nothing has been drawn by this component yet that would affect its content area. + */ + public void setVirginContentArea(final boolean virgin) { + _virginContentArea = virgin; + } + + /** + * Add a new font style to this component. Will be inherited by children if they do not have the same key. + * + * @param styleKey + * style key + * @param styleValue + * the value to associate with the key. + */ + public void addFontStyle(final String styleKey, final Object styleValue) { + _fontStyles.put(styleKey, styleValue); + fireStyleChanged(); + } + + /** + * Removes a font style locally from this component, if present. + * + * @param styleKey + * style key + * @return the style value we were mapped to, or null if none (or was mapped to null). + */ + public Object clearFontStyle(final String styleKey) { + final Object removedValue = _fontStyles.remove(styleKey); + fireStyleChanged(); + return removedValue; + } + + /** + * @return the locally set font styles. + */ + public Map<String, Object> getLocalFontStyles() { + return _fontStyles; + } + + /** + * @return our combined font styles, merged downward from root, including defaults. + */ + public Map<String, Object> getFontStyles() { + final Map<String, Object> styles; + if (getParent() != null && getParent() instanceof UIComponent) { + styles = ((UIComponent) getParent()).getFontStyles(); + } else { + styles = Maps.newHashMap(UIComponent._defaultFontStyles); + styles.put(StyleConstants.KEY_COLOR, UIComponent.DEFAULT_FOREGROUND_COLOR); + } + styles.putAll(_fontStyles); + + if (_foregroundColor != null) { + styles.put(StyleConstants.KEY_COLOR, _foregroundColor); + } + return styles; + } + + /** + * @param styles + * the font styles to use (as needed) for this component. Note that this can be inherited by child + * components if this is a container class and styles is null. + */ + public void setFontStyles(final Map<String, Object> styles) { + if (styles == null) { + _fontStyles = null; + } else { + _fontStyles.clear(); + _fontStyles.putAll(styles); + } + fireStyleChanged(); + } + + /** + * @return the set layout data object or null if none has been set. + */ + public UILayoutData getLayoutData() { + return _layoutData; + } + + /** + * @param layoutData + * the layout data object set on this component. The object would provide specific layout directions to + * the layout class of the container this component is placed in. + */ + public void setLayoutData(final UILayoutData layoutData) { + _layoutData = layoutData; + } + + /** + * @return the width of this entire component as a whole, including all margins, borders, padding and content (in + * the component's coordinate space.) + */ + public int getLocalComponentWidth() { + return _contentsSize.getWidth() + getTotalLeft() + getTotalRight(); + } + + /** + * @return the height of this entire component as a whole, including all margins, borders, padding and content (in + * the component's coordinate space.) + */ + public int getLocalComponentHeight() { + return _contentsSize.getHeight() + getTotalTop() + getTotalBottom(); + } + + /** + * + * @param store + * the object to store our results in. If null, a new Rectangle2 is created and returned. + * @return + */ + public Rectangle2 getRelativeMinComponentBounds(final Rectangle2 store) { + Rectangle2 rVal = store; + if (rVal == null) { + rVal = new Rectangle2(); + } + final int height = getMinimumLocalComponentHeight(); + final int width = getMinimumLocalComponentWidth(); + return getRelativeComponentBounds(rVal, width, height); + } + + /** + * + * @param store + * the object to store our results in. If null, a new Rectangle2 is created and returned. + * @return + */ + public Rectangle2 getRelativeMaxComponentBounds(final Rectangle2 store) { + Rectangle2 rVal = store; + if (rVal == null) { + rVal = new Rectangle2(); + } + final int height = getMaximumLocalComponentHeight(); + final int width = getMaximumLocalComponentWidth(); + return getRelativeComponentBounds(rVal, width, height); + } + + /** + * + * @param store + * the object to store our results in. If null, a new Rectangle2 is created and returned. + * @return the current bounds of this component, in the coordinate space of its parent. + */ + public Rectangle2 getRelativeComponentBounds(final Rectangle2 store) { + Rectangle2 rVal = store; + if (rVal == null) { + rVal = new Rectangle2(); + } + final int height = getLocalComponentHeight(); + final int width = getLocalComponentWidth(); + return getRelativeComponentBounds(rVal, width, height); + } + + private Rectangle2 getRelativeComponentBounds(final Rectangle2 store, final int width, final int height) { + final ReadOnlyTransform local = getTransform(); + if (local.isIdentity() || local.getMatrix().isIdentity()) { + store.set(0, 0, width, height); + } else { + float minX, maxX, minY, maxY; + final Vector3 t = Vector3.fetchTempInstance(); + + t.set(width, height, 0); + local.applyForwardVector(t); + minX = Math.min(t.getXf(), 0); + maxX = Math.max(t.getXf(), 0); + minY = Math.min(t.getYf(), 0); + maxY = Math.max(t.getYf(), 0); + + t.set(0, height, 0); + local.applyForwardVector(t); + minX = Math.min(t.getXf(), minX); + maxX = Math.max(t.getXf(), maxX); + minY = Math.min(t.getYf(), minY); + maxY = Math.max(t.getYf(), maxY); + + t.set(width, 0, 0); + local.applyForwardVector(t); + minX = Math.min(t.getXf(), minX); + maxX = Math.max(t.getXf(), maxX); + minY = Math.min(t.getYf(), minY); + maxY = Math.max(t.getYf(), maxY); + + Vector3.releaseTempInstance(t); + store.set(Math.round(minX), Math.round(minY), Math.round(maxX - minX), Math.round(maxY - minY)); + } + + return store; + } + + /** + * Sets the width and height of this component by forcing the content area to be of a proper size such that when the + * padding, margin and border are added, the total component size match those given. + * + * @param width + * the new width of the component + * @param height + * the new height of the component + */ + public void setLocalComponentSize(final int width, final int height) { + setLocalComponentWidth(width); + setLocalComponentHeight(height); + } + + /** + * @return the width contained in _minimumContentsSize + the margin, border and padding values for left and right. + */ + public int getMinimumLocalComponentWidth() { + return _minimumContentsSize.getWidth() + getTotalLeft() + getTotalRight(); + } + + /** + * @return the height contained in _minimumContentsSize + the margin, border and padding values for top and bottom. + */ + public int getMinimumLocalComponentHeight() { + return _minimumContentsSize.getHeight() + getTotalTop() + getTotalBottom(); + } + + /** + * @return the width contained in _maximumContentsSize + the margin, border and padding values for left and right. + */ + public int getMaximumLocalComponentWidth() { + return _maximumContentsSize.getWidth() + getTotalLeft() + getTotalRight(); + } + + /** + * @return the height contained in _maximumContentsSize + the margin, border and padding values for top and bottom. + */ + public int getMaximumLocalComponentHeight() { + return _maximumContentsSize.getHeight() + getTotalTop() + getTotalBottom(); + } + + /** + * Sets the width and height of the content area of this component. + * + * @param width + * the new width of the content area + * @param height + * the new height of the content area + */ + public void setContentSize(final int width, final int height) { + setContentWidth(width); + setContentHeight(height); + } + + /** + * Sets the height of the content area of this component to that given, as long as we're between min and max content + * height. + * + * @param height + * the new height + */ + public void setContentHeight(final int height) { + _contentsSize.setHeight(MathUtils.clamp(height, _minimumContentsSize.getHeight(), _maximumContentsSize + .getHeight())); + } + + /** + * Sets the width of the content area of this component to that given, as long as we're between min and max content + * width. + * + * @param width + * the new width + */ + public void setContentWidth(final int width) { + _contentsSize + .setWidth(MathUtils.clamp(width, _minimumContentsSize.getWidth(), _maximumContentsSize.getWidth())); + } + + /** + * Sets the current component height to that given, as long as it would not violate min and max content height. + * + * @param height + * the new height + */ + public void setLocalComponentHeight(final int height) { + setContentHeight(height - getTotalTop() - getTotalBottom()); + } + + /** + * Sets the current component width to that given, as long as it would not violate min and max content width. + * + * @param width + * the new width + */ + public void setLocalComponentWidth(final int width) { + setContentWidth(width - getTotalLeft() - getTotalRight()); + } + + /** + * @return the width of the content area of this component. + */ + public int getContentWidth() { + return _contentsSize.getWidth(); + } + + /** + * @return the height of the content area of this component. + */ + public int getContentHeight() { + return _contentsSize.getHeight(); + } + + /** + * Sets the maximum content size of this component to the values given. + * + * @param width + * @param height + */ + public void setMaximumContentSize(final int width, final int height) { + _maximumContentsSize.set(width, height); + validateContentSize(); + } + + /** + * Sets the maximum content width of this component to the value given. + * + * @param width + */ + public void setMaximumContentWidth(final int width) { + _maximumContentsSize.setWidth(width); + } + + /** + * Sets the maximum content height of this component to the value given. + * + * @param height + */ + public void setMaximumContentHeight(final int height) { + _maximumContentsSize.setHeight(height); + validateContentSize(); + } + + /** + * Sets the minimum content size of this component to the values given. + * + * @param width + * @param height + */ + public void setMinimumContentSize(final int width, final int height) { + _minimumContentsSize.set(width, height); + validateContentSize(); + } + + /** + * Sets the minimum content width of this component to the value given. + * + * @param width + */ + public void setMinimumContentWidth(final int width) { + _minimumContentsSize.setWidth(width); + validateContentSize(); + } + + /** + * Sets the minimum content height of this component to the value given. + * + * @param height + */ + public void setMinimumContentHeight(final int height) { + _minimumContentsSize.setHeight(height); + validateContentSize(); + } + + public boolean isConsumeKeyEvents() { + return _consumeKeyEvents; + } + + public void setConsumeKeyEvents(final boolean consume) { + _consumeKeyEvents = consume; + } + + public boolean isConsumeMouseEvents() { + return _consumeMouseEvents; + } + + public void setConsumeMouseEvents(final boolean consume) { + _consumeMouseEvents = consume; + } + + /** + * Ensures content size is between min and max. + */ + protected void validateContentSize() { + final int width = MathUtils.clamp(_contentsSize.getWidth(), _minimumContentsSize.getWidth(), + _maximumContentsSize.getWidth()); + final int height = MathUtils.clamp(_contentsSize.getHeight(), _minimumContentsSize.getHeight(), + _maximumContentsSize.getHeight()); + _contentsSize.set(width, height); + } + + /** + * Sets the size of the content area of this component to the current width and height set on _minimumContentsSize + * (if component is set to allow such resizing.) + */ + public void compact() { + setContentSize(_minimumContentsSize.getWidth(), _minimumContentsSize.getHeight()); + } + + /** + * Attempt to force this component to fit in the given rectangle. + * + * @param width + * @param height + */ + public void fitComponentIn(final int width, final int height) { + final ReadOnlyTransform local = getTransform(); + if (local.isIdentity() || local.getMatrix().isIdentity()) { + setLocalComponentSize(width, height); + return; + } + + final Vector3 temp = Vector3.fetchTempInstance(); + temp.set(1, 0, 0); + local.applyForwardVector(temp); + if (Math.abs(temp.getX()) >= 0.99999) { + setLocalComponentSize(width, height); + } else if (Math.abs(temp.getY()) >= 0.99999) { + setLocalComponentSize(height, width); + } else { + final Rectangle2 rect = getRelativeMinComponentBounds(null); + final float ratio = Math.min((float) width / rect.getWidth(), (float) height / rect.getHeight()); + + setLocalComponentSize(Math.round(getMinimumLocalComponentWidth() * ratio), Math + .round(getMinimumLocalComponentHeight() * ratio)); + } + } + + /** + * Override this to perform actual layout. + */ + public void layout() { + // Let our containers know we are sullied... + fireComponentDirty(); + } + + /** + * @return the sum of the bottom side of this component's margin, border and padding (if they are set). + */ + public int getTotalBottom() { + int bottom = 0; + if (getMargin() != null) { + bottom += getMargin().getBottom(); + } + if (getBorder() != null) { + bottom += getBorder().getBottom(); + } + if (getPadding() != null) { + bottom += getPadding().getBottom(); + } + return bottom; + } + + /** + * @return the sum of the top side of this component's margin, border and padding (if they are set). + */ + public int getTotalTop() { + int top = 0; + if (getMargin() != null) { + top += getMargin().getTop(); + } + if (getBorder() != null) { + top += getBorder().getTop(); + } + if (getPadding() != null) { + top += getPadding().getTop(); + } + return top; + } + + /** + * @return the sum of the left side of this component's margin, border and padding (if they are set). + */ + public int getTotalLeft() { + int left = 0; + if (getMargin() != null) { + left += getMargin().getLeft(); + } + if (getBorder() != null) { + left += getBorder().getLeft(); + } + if (getPadding() != null) { + left += getPadding().getLeft(); + } + return left; + } + + /** + * @return the sum of the right side of this component's margin, border and padding (if they are set). + */ + public int getTotalRight() { + int right = 0; + if (getMargin() != null) { + right += getMargin().getRight(); + } + if (getBorder() != null) { + right += getBorder().getRight(); + } + if (getPadding() != null) { + right += getPadding().getRight(); + } + return right; + } + + /** + * @return the current border set on this component, if any. + */ + public UIBorder getBorder() { + return _border; + } + + /** + * @param border + * the border we wish this component to use. May be null. + */ + public void setBorder(final UIBorder border) { + _border = border; + } + + /** + * @return the current backdrop set on this component, if any. + */ + public UIBackdrop getBackdrop() { + return _backdrop; + } + + /** + * @param backdrop + * the backdrop we wish this component to use. May be null. + */ + public void setBackdrop(final UIBackdrop backDrop) { + _backdrop = backDrop; + } + + /** + * @return the current margin set on this component, if any. + */ + public Insets getMargin() { + return _margin; + } + + /** + * @param margin + * the new margin (a spacing between the component's border and other components) to set on this + * component. Copied into the component and is allowed to be null. + */ + public void setMargin(final Insets margin) { + if (margin == null) { + _margin = null; + } else if (_margin == null) { + _margin = new Insets(margin); + } else { + _margin.set(margin); + } + } + + /** + * @return the current margin set on this component, if any. + */ + public Insets getPadding() { + return _padding; + } + + /** + * @param padding + * the new padding (a spacing between the component's border and its inner content area) to set on this + * component. Copied into the component and is allowed to be null. + */ + public void setPadding(final Insets padding) { + if (padding == null) { + _padding = null; + } else if (_padding == null) { + _padding = new Insets(padding); + } else { + _padding.set(padding); + } + } + + /** + * @return true if our parent is a UIHud. + */ + public boolean isAttachedToHUD() { + return getParent() instanceof UIHud; + } + + /** + * @return the first instance of UIComponent found in this Component's UIComponent ancestry that is attached to the + * hud, or null if none are found. Returns "this" component if it is directly attached to the hud. + */ + public UIComponent getTopLevelComponent() { + if (isAttachedToHUD()) { + return this; + } + final Node parent = getParent(); + if (parent instanceof UIComponent) { + return ((UIComponent) parent).getTopLevelComponent(); + } else { + return null; + } + } + + /** + * @return the first instance of UIHud found in this Component's UIComponent ancestry or null if none are found. + */ + public UIHud getHud() { + final Node parent = getParent(); + if (parent instanceof UIHud) { + return (UIHud) parent; + } else if (parent instanceof UIComponent) { + return ((UIComponent) parent).getHud(); + } else { + return null; + } + } + + /** + * Override to provide an action to take when this component or its top level component are attached to a UIHud. + */ + public void attachedToHud() {} + + /** + * Override to provide an action to take just before this component or its top level component are removed from a + * UIHud. + */ + public void detachedFromHud() {} + + /** + * @return current screen x coordinate of this component's origin (usually its lower left corner.) + */ + public int getHudX() { + return Math.round(getWorldTranslation().getXf()); + } + + /** + * @return current screen y coordinate of this component's origin (usually its lower left corner.) + */ + public int getHudY() { + return Math.round(getWorldTranslation().getYf()); + } + + /** + * Sets the screen x,y coordinate of this component's origin (usually its lower left corner.) + * + * @param x + * @param y + */ + public void setHudXY(final int x, final int y) { + final double newX = getHudX() - getTranslation().getX() + x; + final double newY = getHudY() - getTranslation().getY() + y; + setTranslation(newX, newY, getTranslation().getZ()); + } + + /** + * @param x + * the new screen x coordinate of this component's origin (usually its lower left corner.) + */ + public void setHudX(final int x) { + final ReadOnlyVector3 translation = getTranslation(); + setTranslation(getHudX() - translation.getX() + x, translation.getY(), translation.getZ()); + } + + /** + * @param y + * the new screen y coordinate of this component's origin (usually its lower left corner.) + */ + public void setHudY(final int y) { + final ReadOnlyVector3 translation = getTranslation(); + setTranslation(translation.getX(), getHudY() - translation.getY() + y, translation.getZ()); + } + + /** + * @return a local x translation from the parent component's content area. + */ + public int getLocalX() { + return (int) Math.round(getTranslation().getX()); + } + + /** + * @return a local y translation from the parent component's content area. + */ + public int getLocalY() { + return (int) Math.round(getTranslation().getY()); + } + + /** + * Set the x,y translation from the lower left corner of our parent's content area to the origin of this component. + * + * @param x + * @param y + */ + public void setLocalXY(final int x, final int y) { + setTranslation(x, y, getTranslation().getZ()); + fireComponentDirty(); + } + + /** + * Set the x translation from the lower left corner of our parent's content area to the origin of this component. + * + * @param x + */ + public void setLocalX(final int x) { + final ReadOnlyVector3 translation = getTranslation(); + setTranslation(x, translation.getY(), translation.getZ()); + fireComponentDirty(); + } + + /** + * Set the y translation from the lower left corner of our parent's content area to the origin of this component. + * + * @param y + */ + public void setLocalY(final int y) { + final ReadOnlyVector3 translation = getTranslation(); + setTranslation(translation.getX(), y, translation.getZ()); + fireComponentDirty(); + } + + /** + * @return the currently set foreground color on this component. Does not inherit from ancestors or default, so may + * return null. + */ + public ReadOnlyColorRGBA getLocalForegroundColor() { + return _foregroundColor; + } + + /** + * @return the foreground color associated with this component. If none has been set, we will ask our parent + * component and so on. If no component is found in our ancestry with a foreground color, we will use + * {@link #DEFAULT_FOREGROUND_COLOR} + */ + public ReadOnlyColorRGBA getForegroundColor() { + ReadOnlyColorRGBA foreColor = _foregroundColor; + if (foreColor == null) { + if (getParent() != null && getParent() instanceof UIComponent) { + foreColor = ((UIComponent) getParent()).getForegroundColor(); + } else { + foreColor = UIComponent.DEFAULT_FOREGROUND_COLOR; + } + } + return foreColor; + } + + /** + * @param color + * the foreground color of this component. + */ + public void setForegroundColor(final ReadOnlyColorRGBA color) { + if (color == null) { + _foregroundColor = null; + } else if (_foregroundColor == null) { + _foregroundColor = new ColorRGBA(color); + } else { + _foregroundColor.set(color); + } + fireStyleChanged(); + fireComponentDirty(); + } + + /** + * @return this component's tooltip text. If none has been set, we will ask our parent component and so on. returns + * null if no tooltips are found. + */ + public String getTooltipText() { + if (_tooltipText != null) { + return _tooltipText; + } else if (getParent() instanceof UIComponent) { + return ((UIComponent) getParent()).getTooltipText(); + } else { + return null; + } + } + + /** + * @param text + * the tooltip text of this component. + */ + public void setTooltipText(final String text) { + _tooltipText = text; + } + + /** + * @return the amount of time in ms to wait before showing a tooltip for this component. + */ + public int getTooltipPopTime() { + return _tooltipPopTime; + } + + /** + * @param ms + * the amount of time in ms to wait before showing a tooltip for this component. This is only granular to + * a tenth of a second (or 100ms) + */ + public void setTooltipPopTime(final int ms) { + _tooltipPopTime = ms; + } + + /** + * Check if our tooltip timer is active and cancel it. + */ + protected void cancelTooltipTimer() { + if (_showTask != null && !_showTask.isDone()) { + _showTask.cancel(true); + _showTask = null; + } + } + + /** + * @param hudX + * the x screen coordinate + * @param hudY + * the y screen coordinate + * @return true if the given screen coordinates fall inside the margin area of this component (or in other words, is + * at the border level or deeper.) + */ + public boolean insideMargin(final int hudX, final int hudY) { + final Vector3 vec = Vector3.fetchTempInstance(); + vec.set(hudX, hudY, 0); + getWorldTransform().applyInverse(vec); + + final double x = vec.getX() - getMargin().getLeft(); + final double y = vec.getY() - getMargin().getBottom(); + Vector3.releaseTempInstance(vec); + + return x >= 0 && x < getLocalComponentWidth() - getMargin().getLeft() - getMargin().getRight() && y >= 0 + && y < getLocalComponentHeight() - getMargin().getBottom() - getMargin().getTop(); + } + + /** + * @param hudX + * the x screen coordinate + * @param hudY + * the y screen coordinate + * @return this component (or an appropriate child coordinate in the case of a container) if the given screen + * coordinates fall inside the margin area of this component. + */ + public UIComponent getUIComponent(final int hudX, final int hudY) { + if (getSceneHints().isPickingHintEnabled(PickingHint.Pickable) && isVisible() && insideMargin(hudX, hudY)) { + return this; + } + return null; + } + + @Override + public void updateWorldTransform(final boolean recurse) { + updateWorldTransform(recurse, true); + } + + /** + * Allow skipping updating our own world transform. + * + * @param recurse + * @param self + */ + protected void updateWorldTransform(final boolean recurse, final boolean self) { + if (self) { + if (_parent != null) { + if (_parent instanceof UIComponent) { + final UIComponent gPar = (UIComponent) _parent; + + // grab our parent's world transform + final Transform t = Transform.fetchTempInstance(); + t.set(_parent.getWorldTransform()); + + // shift our origin by total left/bottom + final Vector3 v = Vector3.fetchTempInstance(); + v.set(gPar.getTotalLeft(), gPar.getTotalBottom(), 0); + t.applyForwardVector(v); + t.translate(v); + Vector3.releaseTempInstance(v); + + // apply our local transform + t.multiply(_localTransform, _worldTransform); + Transform.releaseTempInstance(t); + } else { + _parent.getWorldTransform().multiply(_localTransform, _worldTransform); + } + } else { + _worldTransform.set(_localTransform); + } + } + + if (recurse) { + for (int i = getNumberOfChildren() - 1; i >= 0; i--) { + getChild(i).updateWorldTransform(true); + } + } + clearDirty(DirtyType.Transform); + } + + @Override + public void draw(final Renderer r) { + // Don't draw if we are not visible. + if (!isVisible()) { + return; + } + + boolean clearAlpha = false; + // If we are drawing this component as part of cached container contents, we need to alter the blending to get a + // texture with the correct color and alpha. + if (UIContainer.isDrawingStandin()) { + if (getParent() instanceof UIComponent && !((UIComponent) getParent()).hasVirginContentArea()) { + // we are drawing a sub component onto a surface that already has color, so do a alpha based color blend + // and use the max alpha value. + ContextManager.getCurrentContext().enforceState(UIComponent._blendRGBmaxAlphaBlend); + } else { + // we are drawing a top level component onto an empty texture surface, so use the source color modulated + // by the source alpha and the source alpha value. + ContextManager.getCurrentContext().enforceState(UIComponent._srcRGBmaxAlphaBlend); + } + clearAlpha = true; + } + + // Call any predraw operation + predrawComponent(r); + + // Draw the component backdrop + if (getBackdrop() != null) { + _virginContentArea = false; + getBackdrop().draw(r, this); + } else { + _virginContentArea = true; + } + + // draw the component border + if (getBorder() != null) { + getBorder().draw(r, this); + } + + // draw the component, generally editing the content area. + drawComponent(r); + + // Call any postdraw operation + postdrawComponent(r); + + // Clear enforced blend, if set. + if (clearAlpha) { + ContextManager.getCurrentContext().clearEnforcedState(StateType.Blend); + } + } + + /** + * @param defaultFont + * the Font to use as "default" across all UI components that do not have one set. + */ + public static void setDefaultFontFamily(final String family) { + UIComponent._defaultFontFamily = family; + } + + /** + * @return the default Font family. Defaults to "Vera". + */ + public static String getDefaultFontFamily() { + return UIComponent._defaultFontFamily; + } + + /** + * @param size + * the Font size to use as "default" across all UI components that do not have one set. + */ + public static void setDefaultFontSize(final int size) { + UIComponent._defaultFontSize = size; + } + + /** + * @return the default Font size (height). Defaults to 18. + */ + public static int getDefaultFontSize() { + return UIComponent._defaultFontSize; + } + + /** + * @param defaultStyles + * the Font styles to use as "default" across all UI components that do not have one set. + */ + public static void setDefaultFontStyles(final Map<String, Object> defaultStyles) { + if (defaultStyles == null) { + UIComponent._defaultFontStyles = Maps.newHashMap(); + } else { + UIComponent._defaultFontStyles = Maps.newHashMap(defaultStyles); + } + } + + /** + * @return the default Font styles. + */ + public static Map<String, Object> getDefaultFontStyles() { + return UIComponent._defaultFontStyles; + } + + /** + * @return a blend state that does alpha blending and writes the max alpha value (source or destination) back to the + * color buffer. + */ + private static BlendState createSrcRGBMaxAlphaBlend() { + final BlendState state = new BlendState(); + state.setBlendEnabled(true); + state.setSourceFunctionRGB(SourceFunction.SourceAlpha); + state.setDestinationFunctionRGB(DestinationFunction.Zero); + state.setBlendEquationRGB(BlendEquation.Add); + state.setSourceFunctionAlpha(SourceFunction.SourceAlpha); + state.setDestinationFunctionAlpha(DestinationFunction.DestinationAlpha); + state.setBlendEquationAlpha(BlendEquation.Max); + return state; + } + + /** + * @return a blend state that does alpha blending and writes the max alpha value (source or destination) back to the + * color buffer. + */ + private static BlendState createBlendRGBMaxAlphaBlend() { + final BlendState state = new BlendState(); + state.setBlendEnabled(true); + state.setSourceFunctionRGB(SourceFunction.SourceAlpha); + state.setDestinationFunctionRGB(DestinationFunction.OneMinusSourceAlpha); + state.setBlendEquationRGB(BlendEquation.Add); + state.setSourceFunctionAlpha(SourceFunction.SourceAlpha); + state.setDestinationFunctionAlpha(DestinationFunction.DestinationAlpha); + state.setBlendEquationAlpha(BlendEquation.Max); + return state; + } + + /** + * @return the opacity level set on this component in [0,1], where 0 means completely transparent and 1 is + * completely opaque. If useTransparency is false, this will always return 1. + */ + public float getCombinedOpacity() { + if (UIComponent._useTransparency) { + if (getParent() instanceof UIComponent) { + return _opacity * ((UIComponent) getParent()).getCombinedOpacity(); + } else { + return _opacity; + } + } else { + return 1.0f; + } + } + + /** + * @return the opacity set on this component directly, not accounting for parent opacity levels. + */ + public float getLocalOpacity() { + return _opacity; + } + + /** + * Set the opacity level of this component. + * + * @param opacity + * value in [0,1], where 0 means completely transparent and 1 is completely opaque. + */ + public void setOpacity(final float opacity) { + _opacity = opacity; + } + + /** + * Tell all ancestors that use standins, if any, that they need to update any cached graphical representation. + */ + public void fireComponentDirty() { + if (getParent() instanceof UIComponent) { + ((UIComponent) getParent()).fireComponentDirty(); + } + } + + /** + * Let subcomponents know that style has been changed. + */ + public void fireStyleChanged() {} + + /** + * @return true if all components should use their opacity value to blend against other components (and/or the 3d + * background scene.) + */ + public static boolean isUseTransparency() { + return UIComponent._useTransparency; + } + + /** + * @param useTransparency + * true if all components should use their opacity value to blend against the 3d scene (and each other) + */ + public static void setUseTransparency(final boolean useTransparency) { + UIComponent._useTransparency = useTransparency; + } + + /** + * @return the currently rendering component's opacity level. Used by the renderer to alter alpha values based of + * component elements. + */ + public static float getCurrentOpacity() { + return UIComponent._currentOpacity; + } + + /** + * Ask this component to update its minimum allowed size, based on its contents. + */ + protected void updateMinimumSizeFromContents() {} + + /** + * Perform any pre-draw operations on this component. + * + * @param renderer + */ + protected void predrawComponent(final Renderer renderer) { + UIComponent._currentOpacity = getCombinedOpacity(); + } + + /** + * Perform any post-draw operations on this component. + * + * @param renderer + */ + protected void postdrawComponent(final Renderer renderer) {} + + /** + * Draw this component's contents using the given renderer. + * + * @param renderer + */ + protected void drawComponent(final Renderer renderer) {} + + // ******************* + // ** INPUT methods + // ******************* + + /** + * Called when a mouse cursor enters this component. + * + * @param mouseX + * mouse x coordinate. + * @param mouseY + * mouse y coordinate. + * @param state + * the current tracked state of the input system. + */ + public void mouseEntered(final int mouseX, final int mouseY, final InputState state) { + scheduleToolTip(); + } + + /** + * + */ + private void scheduleToolTip() { + final UIHud hud = getHud(); + if (hud != null && getTooltipText() != null) { + final Callable<Void> show = new Callable<Void>() { + public Void call() throws Exception { + + while (true) { + if (System.currentTimeMillis() >= _toolDone) { + break; + } + Thread.sleep(100); + } + + final UITooltip ttip = hud.getTooltip(); + + // set contents and size + ttip.getLabel().setText(getTooltipText()); + ttip.updateMinimumSizeFromContents(); + ttip.getLabel().compact(); + ttip.compact(); + ttip.layout(); + + // set position based on CURRENT mouse location. + int x = hud.getLastMouseX(); + int y = hud.getLastMouseY(); + + // Try to keep tooltip on screen. + if (Camera.getCurrentCamera() != null) { + final int displayWidth = Camera.getCurrentCamera().getWidth(); + final int displayHeight = Camera.getCurrentCamera().getHeight(); + + if (x < 0) { + x = 0; + } else if (x + ttip.getLocalComponentWidth() > displayWidth) { + x = displayWidth - ttip.getLocalComponentWidth(); + } + if (y < 0) { + y = 0; + } else if (y + ttip.getLocalComponentHeight() > displayHeight) { + y = displayHeight - ttip.getLocalComponentHeight(); + } + } + ttip.setHudXY(x, y); + + // fire off that we're dirty + ttip.fireComponentDirty(); + ttip.updateGeometricState(0, true); + + // show + ttip.setVisible(true); + return null; + } + }; + cancelTooltipTimer(); + resetToolTipTime(); + _showTask = new FutureTask<Void>(show); + final Thread t = new Thread() { + @Override + public void run() { + if (_showTask != null && !_showTask.isDone()) { + _showTask.run(); + } + } + }; + t.setDaemon(true); + t.start(); + } + } + + /** + * Called when a mouse cursor leaves this component. + * + * @param mouseX + * mouse x coordinate. + * @param mouseY + * mouse y coordinate. + * @param state + * the current tracked state of the input system. + */ + public void mouseDeparted(final int mouseX, final int mouseY, final InputState state) { + cancelTooltipTimer(); + final UIHud hud = getHud(); + + if (hud != null) { + hud.getTooltip().setVisible(false); + } + } + + /** + * Called when a mouse button is pressed while the cursor is over this component. + * + * @param button + * the button that was pressed + * @param state + * the current tracked state of the input system. + * @return true if we want to consider the event "consumed" by the UI system. + */ + public boolean mousePressed(final MouseButton button, final InputState state) { + // default is to offer event to parent, if it is a UIComponent + if (!_consumeMouseEvents && getParent() instanceof UIComponent) { + return ((UIComponent) getParent()).mousePressed(button, state); + } else { + return _consumeMouseEvents; + } + } + + /** + * Called when a mouse button is released while the cursor is over this component. + * + * @param button + * the button that was released + * @param state + * the current tracked state of the input system. + * @return true if we want to consider the event "consumed" by the UI system. + */ + public boolean mouseReleased(final MouseButton button, final InputState state) { + // default is to offer event to parent, if it is a UIComponent + if (getParent() instanceof UIComponent) { + return ((UIComponent) getParent()).mouseReleased(button, state); + } else { + return _consumeMouseEvents; + } + } + + /** + * Called when a mouse button is pressed and released in close proximity while the cursor is over this component. + * + * @param button + * the button that was released + * @param state + * the current tracked state of the input system. + * @return true if we want to consider the event "consumed" by the UI system. + */ + public boolean mouseClicked(final MouseButton button, final InputState state) { + // default is to offer event to parent, if it is a UIComponent + if (getParent() instanceof UIComponent) { + return ((UIComponent) getParent()).mouseClicked(button, state); + } else { + return _consumeMouseEvents; + } + } + + /** + * Called when a mouse is moved while the cursor is over this component. + * + * @param mouseX + * mouse x coordinate. + * @param mouseY + * mouse y coordinate. + * @param state + * the current tracked state of the input system. + * @return true if we want to consider the event "consumed" by the UI system. + */ + public boolean mouseMoved(final int mouseX, final int mouseY, final InputState state) { + resetToolTipTime(); + + // default is to offer event to parent, if it is a UIComponent + if (!_consumeMouseEvents && getParent() instanceof UIComponent) { + return ((UIComponent) getParent()).mouseMoved(mouseX, mouseY, state); + } else { + return _consumeMouseEvents; + } + } + + private void resetToolTipTime() { + _toolDone = System.currentTimeMillis() + getTooltipPopTime(); + } + + /** + * Called when the mouse wheel is moved while the cursor is over this component. + * + * @param wheelDx + * the last change of the wheel + * @param state + * the current tracked state of the input system. + * @return true if we want to consider the event "consumed" by the UI system. + */ + public boolean mouseWheel(final int wheelDx, final InputState state) { + // default is to offer event to parent, if it is a UIComponent + if (!_consumeMouseEvents && getParent() instanceof UIComponent) { + return ((UIComponent) getParent()).mouseWheel(wheelDx, state); + } else { + return _consumeMouseEvents; + } + } + + /** + * Called when this component has focus and a key is pressed. + * + * @param key + * the key pressed. + * @param the + * current tracked state of the input system. + * @return true if we want to consider the event "consumed" by the UI system. + */ + public boolean keyPressed(final Key key, final InputState state) { + if (!_consumeKeyEvents && getParent() instanceof UIComponent) { + return ((UIComponent) getParent()).keyPressed(key, state); + } else { + return _consumeKeyEvents; + } + } + + /** + * Called when this component has focus and a key is held down over more than 1 input cycle. + * + * @param key + * the key held. + * @param the + * current tracked state of the input system. + * @return true if we want to consider the event "consumed" by the UI system. + */ + public boolean keyHeld(final Key key, final InputState state) { + if (!_consumeKeyEvents && getParent() instanceof UIComponent) { + return ((UIComponent) getParent()).keyHeld(key, state); + } else { + return _consumeKeyEvents; + } + } + + /** + * Called when this component has focus and a key is released. + * + * @param key + * the key released. + * @param the + * current tracked state of the input system. + * @return true if we want to consider the event "consumed" by the UI system. + */ + public boolean keyReleased(final Key key, final InputState state) { + if (!_consumeKeyEvents && getParent() instanceof UIComponent) { + return ((UIComponent) getParent()).keyReleased(key, state); + } else { + return _consumeKeyEvents; + } + } + + /** + * Called by the hud when a component is given focus. + */ + public void gainedFocus() {} + + /** + * Called by the hud when a component loses focus. + */ + public void lostFocus() {} + + /** + * Looks up the scenegraph for a Hud and asks it to set us as the currently focused component. + */ + public void requestFocus() { + final UIHud hud = getHud(); + if (hud != null) { + hud.setFocusedComponent(this); + } + } + + /** + * @return a component we defer to for key focus. Default is null. + */ + public UIComponent getKeyFocusTarget() { + return _keyFocusTarget; + } + + /** + * @param target + * a component to set as the actual focused component if this component receives focus. + */ + public void setKeyFocusTarget(final UIComponent target) { + _keyFocusTarget = target; + } +}
\ No newline at end of file diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIContainer.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIContainer.java new file mode 100644 index 0000000..5b597f0 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIContainer.java @@ -0,0 +1,611 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui; + +import java.nio.FloatBuffer; +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.ardor3d.extension.ui.layout.RowLayout; +import com.ardor3d.extension.ui.layout.UILayout; +import com.ardor3d.extension.ui.util.UIQuad; +import com.ardor3d.image.Texture2D; +import com.ardor3d.image.TextureStoreFormat; +import com.ardor3d.image.Texture.MagnificationFilter; +import com.ardor3d.image.Texture.MinificationFilter; +import com.ardor3d.image.Texture.WrapMode; +import com.ardor3d.math.ColorRGBA; +import com.ardor3d.math.Matrix3; +import com.ardor3d.math.Rectangle2; +import com.ardor3d.math.type.ReadOnlyVector3; +import com.ardor3d.renderer.Camera; +import com.ardor3d.renderer.ContextManager; +import com.ardor3d.renderer.Renderer; +import com.ardor3d.renderer.TextureRenderer; +import com.ardor3d.renderer.TextureRendererFactory; +import com.ardor3d.renderer.queue.RenderBucketType; +import com.ardor3d.renderer.state.BlendState; +import com.ardor3d.renderer.state.TextureState; +import com.ardor3d.renderer.state.BlendState.DestinationFunction; +import com.ardor3d.renderer.state.BlendState.SourceFunction; +import com.ardor3d.renderer.state.BlendState.TestFunction; +import com.ardor3d.scenegraph.Spatial; +import com.ardor3d.scenegraph.hint.CullHint; +import com.ardor3d.scenegraph.hint.LightCombineMode; +import com.ardor3d.scenegraph.hint.PickingHint; +import com.ardor3d.scenegraph.hint.TextureCombineMode; + +/** + * Defines a component that can hold and manage other components or containers, using a layout manager to position and + * potentially resize them. + */ +public abstract class UIContainer extends UIComponent { + private static final Logger _logger = Logger.getLogger(UIContainer.class.getName()); + + /** Layout responsible for managing the size and position of this container's contents. */ + private UILayout _layout = new RowLayout(true); + + /** Toggles whether or not we add our content bounds to the current clip space during draw. */ + private boolean _doClip = true; + + /** Flag indicating whether a current render operation is drawing a "cached" version of a container. */ + private static boolean _drawingStandin = false; + + /** + * A flag indicating that some part of this container needs repainting. On the next draw call, we should update our + * cached texture, if using one. + */ + private boolean _dirty = true; + /** + * If true, use a cached texture to display this container (on a simple quad) instead of drawing all of its + * components. + */ + private boolean _useStandin = false; + + /** The quad used to draw the cached texture version of this container, if set to use one. */ + private UIQuad _standin = null; + /** The texture used to store the contents of this container. */ + private Texture2D _fakeTexture; + + // TODO: We likely need to change this TextureRenderer to be context sensitive. + /** A texture renderer to use for cache operations. */ + protected static TextureRenderer _textureRenderer; + + /** The minification filter to use for standin (if used) */ + private MinificationFilter _minificationFilter = MinificationFilter.BilinearNoMipMaps; + + /** A store for the clip rectangle. */ + private final Rectangle2 _clipRectangleStore = new Rectangle2(); + + /** + * Checks to see if a given UIComponent is in this container. + * + * @param component + * the component to look for + * @return true if the given component is in this container. + */ + public boolean contains(final UIComponent component) { + return contains(component, false); + } + + /** + * Checks to see if a given UIComponent is in this container or (if instructed) its subcontainers. + * + * @param component + * the component to look for + * @param recurse + * if true, recursively check any sub-containers for the given component. + * @return if the given component is found + */ + public boolean contains(final UIComponent component, final boolean recurse) { + for (int i = getNumberOfChildren(); --i >= 0;) { + final Spatial child = getChild(i); + if (child.equals(component)) { + return true; + } else if (recurse && component instanceof UIContainer) { + if (((UIContainer) component).contains(component, true)) { + return true; + } + } + } + return false; + } + + /** + * Add a component to this container. + * + * @param component + * the component to add + */ + public void add(final UIComponent component) { + attachChild(component); + // send relation event if we already have a hud + if (getHud() != null) { + component.attachedToHud(); + } + fireStyleChanged(); + fireComponentDirty(); + } + + /** + * Remove a component from this container. + * + * @param component + * the component to remove + */ + public void remove(final UIComponent component) { + if (getHud() != null) { + component.detachedFromHud(); + } + + detachChild(component); + } + + /** + * Removes all UI components from this container. If other types of Spatials are attached to this container, they + * are ignored. + * + * @param comp + * the component to remove + */ + public void removeAllComponents() { + for (int i = getNumberOfChildren(); --i >= 0;) { + final Spatial child = getChild(i); + if (child instanceof UIComponent) { + remove((UIComponent) child); + } + } + } + + @Override + public void detachAllChildren() { + // Override to make sure ui events are called for detach. + removeAllComponents(); + + // do the rest as normal + super.detachAllChildren(); + } + + /** + * @param layout + * the new layout to use with this container. If null, no layout is done by this container. + */ + public void setLayout(final UILayout layout) { + _layout = layout; + } + + /** + * @return the layout currently used by this container or null if no layout is used. + */ + public UILayout getLayout() { + return _layout; + } + + @Override + public void layout() { + if (_layout != null) { + _layout.layoutContents(this); + } + + // call layout on children + for (int x = 0, max = getNumberOfChildren(); x < max; x++) { + final Spatial child = getChild(x); + if (child instanceof UIComponent) { + ((UIComponent) child).layout(); + } + } + } + + @Override + public void updateMinimumSizeFromContents() { + // call update on children first + for (int x = 0, max = getNumberOfChildren(); x < max; x++) { + final Spatial child = getChild(x); + if (child instanceof UIComponent) { + ((UIComponent) child).updateMinimumSizeFromContents(); + } + } + + // update our min size. + if (_layout != null) { + _layout.updateMinimumSizeFromContents(this); + } + } + + @Override + public void attachedToHud() { + Spatial child; + for (int i = 0, cSize = getNumberOfChildren(); i < cSize; i++) { + child = getChild(i); + if (child != null) { + if (child instanceof UIComponent) { + ((UIComponent) child).attachedToHud(); + } + } + } + } + + @Override + public void detachedFromHud() { + Spatial child; + for (int i = 0, cSize = getNumberOfChildren(); i < cSize; i++) { + child = getChild(i); + if (child != null) { + if (child instanceof UIComponent) { + ((UIComponent) child).detachedFromHud(); + } + } + } + + // clean up visuals created for this container + clearStandin(); + } + + @Override + public UIComponent getUIComponent(final int hudX, final int hudY) { + if (!getSceneHints().isPickingHintEnabled(PickingHint.Pickable) || !insideMargin(hudX, hudY)) { + return null; + } + + UIComponent ret = null; + UIComponent found = this; + + for (int i = 0; i < getNumberOfChildren(); i++) { + final Spatial s = getChild(i); + if (s instanceof UIComponent) { + final UIComponent comp = (UIComponent) s; + ret = comp.getUIComponent(hudX, hudY); + + if (ret != null) { + found = ret; + } + } + } + + return found; + } + + @Override + protected void drawComponent(final Renderer renderer) { + if (getNumberOfChildren() > 0) { + // If asked, clip to just the internal region of this container. + boolean needsPop = false; + if (_doClip && getWorldRotation().isIdentity()) { + _clipRectangleStore.set(getHudX() + getTotalLeft(), getHudY() + getTotalBottom(), getContentWidth(), + getContentHeight()); + renderer.pushClip(_clipRectangleStore); + needsPop = true; + } + Spatial child; + for (int i = 0, cSize = getNumberOfChildren(); i < cSize; i++) { + child = getChild(i); + if (child != null) { + child.onDraw(renderer); + } + } + if (needsPop) { + renderer.popClip(); + } + } + } + + @Override + public synchronized void draw(final Renderer renderer) { + + // if we are not using standins, just draw as a normal Node. + if (!_useStandin) { + super.draw(renderer); + return; + } + + final int width = getLocalComponentWidth(); + final int height = getLocalComponentHeight(); + final int dispWidth = Camera.getCurrentCamera().getWidth(); + final int dispHeight = Camera.getCurrentCamera().getHeight(); + + // If we are currently in the process of rendering this container to a texture... + if (UIContainer._drawingStandin) { + renderer.setOrtho(); + + // hold onto our old translation + final ReadOnlyVector3 wTrans = getWorldTranslation(); + final double x = wTrans.getX(), y = wTrans.getY(), z = wTrans.getZ(); + final Matrix3 rot = Matrix3.fetchTempInstance().set(getWorldRotation()); + + // set our new translation so that we are drawn in the bottom left corner of the texture. + double newX = 0, newY = 0; + if (width > dispWidth && x < 0) { + newX = x; + } + if (height > dispHeight && y < 0) { + newY = y; + } + setWorldTranslation(newX, newY, 0); + setWorldRotation(Matrix3.IDENTITY); + updateWorldTransform(true, false); + + // draw to texture + super.draw(renderer); + + // replace our old translation + setWorldTranslation(x, y, z); + setWorldRotation(rot); + updateWorldTransform(true); + + renderer.unsetOrtho(); + + // exit + return; + } + + // Calculate our standin's translation (and size) so that we are drawn in the bottom left corner of the texture. + // Take into account containers that are bigger than the screen. + int newWidth = width, newHeight = height; + int x = getHudX(); + int y = getHudY(); + if (width > dispWidth && x < 0) { + newWidth += getHudX(); + x = 0; + } + if (height > dispHeight && y < 0) { + newHeight += getHudY(); + y = 0; + } + + // Otherwise we are not rendering to texture and we are using standins... + // So check if we are dirty. + if (isDirty()) { + renderer.unsetOrtho(); + // Check if we have a standin yet + if (_standin == null) { + try { + buildStandin(renderer); + } catch (final Exception e) { + _useStandin = false; + UIContainer._logger.warning("Unable to create standin: " + e.getMessage()); + UIContainer._logger.logp(Level.SEVERE, getClass().getName(), "draw(Renderer)", "Exception", e); + } + } + + // Check if we have a texture renderer yet before going further + if (UIContainer._textureRenderer != null) { + UIContainer._drawingStandin = true; + // Save aside our opacity + final float op = getLocalOpacity(); + // Set our opacity to 1.0 for the cached texture + setOpacity(1.0f); + // render the container to a texture + UIContainer._textureRenderer.render(this, _fakeTexture, Renderer.BUFFER_COLOR_AND_DEPTH); + // return our old transparency + setOpacity(op); + UIContainer._drawingStandin = false; + + // Prepare the texture coordinates for our container. + float dW = newWidth / (float) UIContainer._textureRenderer.getWidth(); + if (dW > 1) { + dW = 1; + } + float dH = newHeight / (float) UIContainer._textureRenderer.getHeight(); + if (dH > 1) { + dH = 1; + } + final FloatBuffer tbuf = _standin.getMeshData().getTextureBuffer(0); + tbuf.clear(); + tbuf.put(0).put(dH); + tbuf.put(0).put(0); + tbuf.put(dW).put(0); + tbuf.put(dW).put(dH); + tbuf.rewind(); + + _dirty = false; + } + renderer.setOrtho(); + } + + // Now, render the standin quad. + if (_standin != null) { + // See if we need to change the dimensions of our standin quad. + + if (newWidth != _standin.getWidth() || newHeight != _standin.getHeight()) { + _standin.resize(newWidth, newHeight); + } + + // Prepare our default color with the correct alpha value for opacity. + final ColorRGBA color = ColorRGBA.fetchTempInstance(); + color.set(1, 1, 1, getCombinedOpacity()); + _standin.setDefaultColor(color); + ColorRGBA.releaseTempInstance(color); + + // Position standin quad properly + _standin.setWorldTranslation(x, y, getWorldTranslation().getZ()); + _standin.setWorldRotation(getWorldRotation()); + + final boolean clipTest = renderer.isClipTestEnabled(); + renderer.setClipTestEnabled(false); + // draw our standin quad with cached container texture. + _standin.draw(renderer); + renderer.setClipTestEnabled(clipTest); + } + } + + /** + * Build our standin quad and (as necessary) a texture renderer. + * + * @param renderer + * the renderer to use if we need to generate a texture renderer + */ + private void buildStandin(final Renderer renderer) { + // Check for and create a texture renderer if none exists yet. + if (UIContainer._textureRenderer == null) { + final Camera cam = Camera.getCurrentCamera(); + UIContainer._textureRenderer = TextureRendererFactory.INSTANCE.createTextureRenderer(cam.getWidth(), cam + .getHeight(), renderer, ContextManager.getCurrentContext().getCapabilities()); + if (UIContainer._textureRenderer != null) { + UIContainer._textureRenderer.setBackgroundColor(new ColorRGBA(0f, 1f, 0f, 0f)); + UIContainer._textureRenderer.setMultipleTargets(true); + } else { + // Can't make standin. + _useStandin = false; + return; + } + } + + _standin = new UIQuad("container_standin", 1, 1); + // no frustum culling checks + _standin.getSceneHints().setCullHint(CullHint.Never); + // no lighting + _standin.getSceneHints().setLightCombineMode(LightCombineMode.Off); + // a single texture + _standin.getSceneHints().setTextureCombineMode(TextureCombineMode.Replace); + // immediate mode + _standin.getSceneHints().setRenderBucketType(RenderBucketType.Skip); + + // Add an alpha blend state + final BlendState blend = new BlendState(); + blend.setBlendEnabled(true); + blend.setSourceFunction(SourceFunction.SourceAlpha); + blend.setDestinationFunction(DestinationFunction.OneMinusSourceAlpha); + // throw out fragments with alpha of 0. + blend.setTestFunction(TestFunction.GreaterThan); + blend.setReference(0.0f); + blend.setTestEnabled(true); + _standin.setRenderState(blend); + + // Update our standin's texture + resetFakeTexture(); + + // Update the standin, getting states, etc. all set. + _standin.updateGeometricState(0); + } + + private void resetFakeTexture() { + // create a texture to cache the contents to + _fakeTexture = new Texture2D(); + _fakeTexture.setMagnificationFilter(MagnificationFilter.Bilinear); + _fakeTexture.setMinificationFilter(_minificationFilter); + _fakeTexture.setTextureStoreFormat(TextureStoreFormat.RGBA8); + _fakeTexture.setWrap(WrapMode.EdgeClamp); + UIContainer._textureRenderer.setupTexture(_fakeTexture); + + // Set a texturestate on the standin, using the fake texture + final TextureState ts = new TextureState(); + ts.setTexture(_fakeTexture); + _standin.setRenderState(ts); + } + + /** + * @return true if this container has had recent content changes that would require a repaint. + */ + public boolean isDirty() { + return _dirty; + } + + /** + * @param dirty + * true if this container has had recent content changes that would require a repaint. + */ + public void setDirty(final boolean dirty) { + _dirty = dirty; + } + + /** + * Set ourselves dirty. + */ + @Override + public void fireComponentDirty() { + super.fireComponentDirty(); + setDirty(true); + } + + @Override + public void fireStyleChanged() { + super.fireStyleChanged(); + Spatial child; + for (int i = 0, cSize = getNumberOfChildren(); i < cSize; i++) { + child = getChild(i); + if (child != null) { + if (child instanceof UIComponent) { + ((UIComponent) child).fireStyleChanged(); + } + } + } + } + + /** + * Release our standin and cached texture for gc. If needed again, they will be created from scratch. + */ + public void clearStandin() { + _fakeTexture = null; + _standin = null; + } + + /** + * + * @param doClip + * true (default) if we want this container to clip the drawing of its contents to the dimensions of its + * content area. + */ + public void setDoClip(final boolean doClip) { + _doClip = doClip; + } + + public boolean isDoClip() { + return _doClip; + } + + /** + * @param use + * if true, we will draw the container's contents to a cached texture and use that to display this + * container (on a simple quad) instead of drawing all of its components each time. When the container is + * marked as dirty, we will update the contents of the texture. + */ + public void setUseStandin(final boolean use) { + _useStandin = use; + if (!_useStandin) { + clearStandin(); + } + } + + /** + * + * @return true if we should use a cached texture copy to draw this container. + * @see #setUseStandin(boolean) + */ + public boolean isUseStandin() { + return _useStandin; + } + + /** + * @return true if we are currently rendering a container to texture. + */ + public static boolean isDrawingStandin() { + return UIContainer._drawingStandin; + } + + /** + * Set the minification filter for the standin. + * + * @param filter + */ + public void setMinificationFilter(final MinificationFilter filter) { + _minificationFilter = filter; + if (_fakeTexture != null) { + resetFakeTexture(); + } + } + + /** + * @return the minification filter used for standin. + */ + public MinificationFilter getMinificationFilter() { + return _minificationFilter; + } +} diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIFrame.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIFrame.java new file mode 100644 index 0000000..0d1269d --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIFrame.java @@ -0,0 +1,436 @@ +/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui;
+
+import java.util.EnumSet;
+import java.util.concurrent.Callable;
+
+import com.ardor3d.extension.ui.backdrop.SolidBackdrop;
+import com.ardor3d.extension.ui.event.DragListener;
+import com.ardor3d.extension.ui.event.FrameDragListener;
+import com.ardor3d.extension.ui.layout.BorderLayout;
+import com.ardor3d.extension.ui.layout.BorderLayoutData;
+import com.ardor3d.math.ColorRGBA;
+import com.ardor3d.math.Rectangle2;
+import com.ardor3d.renderer.Camera;
+import com.ardor3d.util.GameTaskQueueManager;
+
+/**
+ * A component similar to an inner frame in Swing. It can be dragged around the screen, minimized, expanded, closed, and
+ * resized. Frames can also have their opacity individually assigned which will affect all elements drawn within them.
+ */
+public class UIFrame extends UIContainer {
+ /** Minimum height we'll allow during manual resize */
+ public static int MIN_FRAME_HEIGHT = 60;
+ /** Minimum width we'll allow during manual resize */
+ public static int MIN_FRAME_WIDTH = 100;
+
+ /** The main panel containing the contents panel and status bar of the frame. */
+ private final UIPanel _basePanel;
+ /** The panel meant to hold the contents of the frame. */
+ private UIPanel _contentPanel;
+ /** The top title bar of the frame, part of the frame's "chrome" */
+ private final UIFrameBar _titleBar;
+ /** The bar running along the bottom of the frame. */
+ private final UIFrameStatusBar _statusBar;
+
+ /** If true, show our title and status bars. */
+ private boolean _decorated = true;
+
+ /** The drag listener responsible for allowing repositioning of the frame by dragging the title label. */
+ private DragListener _dragListener = new FrameDragListener(this);
+
+ /** If true, show a resize handle on this frame and allow its use. */
+ private boolean _resizeable = true;
+
+ /** If true (the default) then allow dragging of this frame using the frame bar. */
+ private boolean _draggable = true;
+
+ /** if true, the frame is maximized and can be restored */
+ private boolean _maximized = false;
+
+ private int widthBeforeMaximizing;
+ private int heightBeforeMaximizing;
+ private int hudXBeforeMaximizing;
+ private int hudYBeforeMaximizing;
+
+ /**
+ * Construct a new UIFrame with the given title and default buttons (CLOSE).
+ *
+ * @param title
+ * the text to display on the title bar of this frame
+ */
+ public UIFrame(final String title) {
+ this(title, EnumSet.of(FrameButtons.CLOSE));
+ }
+
+ /**
+ * Construct a new UIFrame with the given title and button.
+ *
+ * @param title
+ * the text to display on the title bar of this frame
+ * @param buttons
+ * which buttons we should show in the frame bar.
+ */
+ public UIFrame(final String title, final EnumSet<FrameButtons> buttons) {
+ setLayout(new BorderLayout());
+
+ _basePanel = new UIPanel(new BorderLayout());
+ _basePanel.setBackdrop(new SolidBackdrop(ColorRGBA.LIGHT_GRAY));
+ _basePanel.setLayoutData(BorderLayoutData.CENTER);
+ _basePanel.setConsumeMouseEvents(true);
+ add(_basePanel);
+
+ _contentPanel = new UIPanel();
+ _contentPanel.setLayoutData(BorderLayoutData.CENTER);
+ _basePanel.add(_contentPanel);
+
+ _titleBar = new UIFrameBar(buttons);
+ _titleBar.setLayoutData(BorderLayoutData.NORTH);
+ setTitle(title);
+ add(_titleBar);
+
+ _statusBar = new UIFrameStatusBar();
+ _statusBar.setLayoutData(BorderLayoutData.SOUTH);
+ _basePanel.add(_statusBar);
+
+ applySkin();
+ }
+
+ /**
+ * @param decorated
+ * true to show the title and status bars. False to remove both. Undecorated frames have no resize or
+ * drag handles, or close buttons, etc.
+ */
+ public void setDecorated(final boolean decorated) {
+ _decorated = decorated;
+ if (!_decorated) {
+ remove(_titleBar);
+ } else {
+ add(_titleBar);
+ }
+
+ if (!_decorated) {
+ _basePanel.remove(_statusBar);
+ } else {
+ _basePanel.add(_statusBar);
+ }
+ }
+
+ public void maximize() {
+ final UIHud hud = getHud();
+ if (_maximized || hud == null) {
+ return;
+ }
+ widthBeforeMaximizing = getLocalComponentWidth();
+ heightBeforeMaximizing = getLocalComponentHeight();
+ hudXBeforeMaximizing = getHudX();
+ hudYBeforeMaximizing = getHudY();
+ setLocalComponentSize(hud.getWidth(), hud.getHeight());
+ setHudXY(0, 0);
+ layout();
+ _maximized = true;
+ }
+
+ public void restore() {
+ final UIHud hud = getHud();
+ if (!_maximized || hud == null) {
+ return;
+ }
+ setLocalComponentSize(widthBeforeMaximizing, heightBeforeMaximizing);
+ setHudXY(hudXBeforeMaximizing, hudYBeforeMaximizing);
+ layout();
+ _maximized = false;
+ }
+
+ /**
+ * @return true if this frame is decorated.
+ */
+ public boolean isDecorated() {
+ return _decorated;
+ }
+
+ /**
+ * @param resizeable
+ * true if we should allow resizing of this frame via a resize handle in the status bar. This does not
+ * stop programmatic resizing of this frame.
+ */
+ public void setResizeable(final boolean resizeable) {
+ if (_resizeable != resizeable) {
+ _resizeable = resizeable;
+
+ if (!_resizeable) {
+ _statusBar.remove(_statusBar.getResizeButton());
+ } else {
+ _statusBar.add(_statusBar.getResizeButton());
+ }
+ _statusBar.updateMinimumSizeFromContents();
+ _statusBar.layout();
+ }
+ }
+
+ /**
+ * @return true if this frame allows manual resizing.
+ */
+ public boolean isResizeable() {
+ return _resizeable;
+ }
+
+ /**
+ * @param draggable
+ * true if we should allow dragging of this frame via a frame bar.
+ */
+ public void setDraggable(final boolean draggable) {
+ _draggable = draggable;
+ }
+
+ /**
+ * @return true if this frame allows dragging.
+ */
+ public boolean isDraggable() {
+ return _draggable;
+ }
+
+ /**
+ * Remove this frame from the hud it is attached to.
+ *
+ * @throws IllegalStateException
+ * if frame is not currently attached to a hud.
+ */
+ public void close() {
+ final UIHud hud = getHud();
+ if (hud == null) {
+ throw new IllegalStateException("UIFrame is not attached to a hud.");
+ }
+
+ // Remove our drag listener
+ hud.removeDragListener(_dragListener);
+
+ // When a frame closes, close any open tooltip
+ hud.getTooltip().setVisible(false);
+
+ // clear any resources for standin
+ clearStandin();
+
+ hud.remove(this);
+ _parent = null;
+ }
+
+ /**
+ * Centers this frame on the location of the given component.
+ *
+ * @param comp
+ * the component to center on.
+ */
+ public void setLocationRelativeTo(final UIComponent comp) {
+ final Rectangle2 rectA = comp.getRelativeComponentBounds(null);
+ final Rectangle2 rectB = getRelativeComponentBounds(null);
+ int x = (rectA.getWidth() - rectB.getWidth()) / 2;
+ int y = (rectA.getHeight() - rectB.getHeight()) / 2;
+ x += comp.getHudX() - rectA.getX() + rectB.getX();
+ y += comp.getHudY() - rectA.getY() + rectB.getY();
+ setHudXY(x, y);
+ updateGeometricState(0);
+ }
+
+ /**
+ * Centers this frame on the view of the camera
+ *
+ * @param cam
+ * the camera to center on.
+ */
+ public void setLocationRelativeTo(final Camera cam) {
+ final Rectangle2 rectA = getRelativeComponentBounds(null);
+ int x = (cam.getWidth() - rectA.getWidth()) / 2;
+ int y = (cam.getHeight() - rectA.getHeight()) / 2;
+ x -= rectA.getX();
+ y -= rectA.getY();
+ setHudXY(x, y);
+ updateGeometricState(0);
+ }
+
+ /**
+ * @return this frame's title bar
+ */
+ public UIFrameBar getTitleBar() {
+ return _titleBar;
+ }
+
+ /**
+ * @return this frame's status bar
+ */
+ public UIFrameStatusBar getStatusBar() {
+ return _statusBar;
+ }
+
+ /**
+ * @return the center content panel of this frame.
+ */
+ public UIPanel getContentPanel() {
+ return _contentPanel;
+ }
+
+ /**
+ * @return the base panel of this frame which holds the content panel and status bar.
+ */
+ public UIPanel getBasePanel() {
+ return _basePanel;
+ }
+
+ /**
+ * Replaces the content panel of this frame with a new one.
+ *
+ * @param panel
+ * the new content panel.
+ */
+ public void setContentPanel(final UIPanel panel) {
+ _basePanel.remove(_contentPanel);
+ _contentPanel = panel;
+ panel.setLayoutData(BorderLayoutData.CENTER);
+ _basePanel.add(panel);
+ }
+
+ /**
+ * @return the current title of this frame
+ */
+ public String getTitle() {
+ if (_titleBar != null) {
+ return _titleBar.getTitleLabel().getText();
+ }
+
+ return null;
+ }
+
+ /**
+ * Sets the title of this frame
+ *
+ * @param title
+ * the new title
+ */
+ public void setTitle(final String title) {
+ if (_titleBar != null) {
+ _titleBar.getTitleLabel().setText(title);
+ _titleBar.layout();
+ }
+ }
+
+ @Override
+ public void attachedToHud() {
+ super.attachedToHud();
+ // add our drag listener to the hud
+ getHud().addDragListener(_dragListener);
+ }
+
+ @Override
+ public void detachedFromHud() {
+ super.detachedFromHud();
+
+ // Remove our drag listener from the hud
+ if (getHud() != null) {
+ getHud().removeDragListener(_dragListener);
+ }
+ }
+
+ /**
+ * Resize the frame to fit the minimum size of its content panel.
+ */
+ public void pack() {
+ _contentPanel.updateMinimumSizeFromContents();
+ pack(_contentPanel.getMinimumLocalComponentWidth(), _contentPanel.getMinimumLocalComponentHeight());
+ }
+
+ /**
+ * Resize the frame to fit its content panel to the given dimensions
+ *
+ * @param contentWidth
+ * our desired content panel width
+ * @param contentHeight
+ * our desired content panel height
+ */
+ public void pack(final int contentWidth, final int contentHeight) {
+ // grab the desired width and height of the frame.
+ final int width = contentWidth + _basePanel.getTotalLeft() + _basePanel.getTotalRight();
+ int height = contentHeight + _basePanel.getTotalTop() + _basePanel.getTotalBottom();
+
+ // add in our frame chrome, if it is enabled.
+ if (isDecorated()) {
+ height += _statusBar.getLocalComponentHeight() + _titleBar.getLocalComponentHeight();
+ }
+
+ // Set our size, obeying min sizes.
+ setLocalComponentSize(Math.max(width, UIFrame.MIN_FRAME_WIDTH), Math.max(height, UIFrame.MIN_FRAME_HEIGHT));
+
+ // Layout the panel
+ layout();
+ }
+
+ /**
+ * Causes our shared texture renderer - used to draw cached versions of all frames - to be recreated on the next
+ * render loop.
+ */
+ public static void resetTextureRenderer(final Object queueKey) {
+ final Callable<Void> exe = new Callable<Void>() {
+ public Void call() {
+ if (UIContainer._textureRenderer != null) {
+ UIContainer._textureRenderer.cleanup();
+ }
+ UIContainer._textureRenderer = null;
+ return null;
+ }
+ };
+ GameTaskQueueManager.getManager(queueKey).render(exe);
+ }
+
+ /**
+ * Recursive convenience method for locating the first UIFrame above a given component.
+ *
+ * @param component
+ * the component to look above.
+ * @return the first UIFrame found above the given component, or null if none.
+ */
+ public static UIFrame findParentFrame(final UIComponent component) {
+ if (component.getParent() instanceof UIFrame) {
+ return (UIFrame) component.getParent();
+ } else if (component.getParent() instanceof UIComponent) {
+ return UIFrame.findParentFrame((UIComponent) component.getParent());
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Set a new drag listener on this frame.
+ *
+ * @param listener
+ * the drag listener. Must not be null.
+ */
+ public void setDragListener(final DragListener listener) {
+ assert listener != null : "listener must not be null";
+ if (isAttachedToHUD()) {
+ getHud().removeDragListener(_dragListener);
+ }
+ _dragListener = listener;
+ if (isAttachedToHUD()) {
+ getHud().addDragListener(_dragListener);
+ }
+ }
+
+ /**
+ * Enumeration of possible frame chrome buttons.
+ */
+ public enum FrameButtons {
+ CLOSE, MINIMIZE, MAXIMIZE, HELP;
+ }
+
+ public boolean isMaximized() {
+ return _maximized;
+ }
+}
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIFrameBar.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIFrameBar.java new file mode 100644 index 0000000..d10ec2e --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIFrameBar.java @@ -0,0 +1,128 @@ +/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui;
+
+import java.util.EnumSet;
+
+import com.ardor3d.extension.ui.UIFrame.FrameButtons;
+import com.ardor3d.extension.ui.event.ActionEvent;
+import com.ardor3d.extension.ui.event.ActionListener;
+
+/**
+ * This panel extension defines a standard frame title bar with optional buttons you might find in a typical windowing
+ * system (such as minimize, close, etc.)
+ */
+public class UIFrameBar extends UIPanel {
+
+ /** The title text label, and also our frame drag handle. */
+ private final UILabel _titleLabel;
+
+ /** Help button. */
+ private final UIButton _helpButton;
+ /** Minimize button. */
+ private final UIButton _minimizeButton;
+ /** Maximize button. */
+ private final UIButton _maximizeButton;
+ /** Close button used for removing the parent frame from its hud, hiding it. */
+ private final UIButton _closeButton;
+
+ /**
+ * Construct a new UIFrameBar, adding the buttons as specified in the given EnumSet
+ *
+ * @param buttons
+ * the button types we want shown
+ */
+ public UIFrameBar(final EnumSet<FrameButtons> buttons) {
+ _titleLabel = new UILabel("- untitled -");
+ attachChild(_titleLabel);
+
+ if (buttons.contains(FrameButtons.HELP)) {
+ _helpButton = createFrameButton("?");
+ _helpButton.addActionListener(new ActionListener() {
+ public void actionPerformed(final ActionEvent event) {
+ // TODO: Implement
+ }
+ });
+ attachChild(_helpButton);
+ } else {
+ _helpButton = null;
+ }
+
+ if (buttons.contains(FrameButtons.MINIMIZE)) {
+ _minimizeButton = createFrameButton("_");
+ _minimizeButton.addActionListener(new ActionListener() {
+ public void actionPerformed(final ActionEvent event) {
+ // TODO: Implement
+ }
+ });
+ attachChild(_minimizeButton);
+ } else {
+ _minimizeButton = null;
+ }
+
+ if (buttons.contains(FrameButtons.MAXIMIZE)) {
+ _maximizeButton = createFrameButton("^");
+ _maximizeButton.addActionListener(new ActionListener() {
+ public void actionPerformed(final ActionEvent event) {
+ // XXX: Should this also update the button img?
+ final UIFrame frame = (UIFrame) getParent();
+ if (frame.isMaximized()) {
+ frame.restore();
+ } else {
+ frame.maximize();
+ }
+ }
+ });
+ attachChild(_maximizeButton);
+ } else {
+ _maximizeButton = null;
+ }
+
+ if (buttons.contains(FrameButtons.CLOSE)) {
+ _closeButton = createFrameButton("x");
+ _closeButton.addActionListener(new ActionListener() {
+ public void actionPerformed(final ActionEvent event) {
+ ((UIFrame) getParent()).close();
+ }
+ });
+ attachChild(_closeButton);
+ } else {
+ _closeButton = null;
+ }
+ }
+
+ private UIButton createFrameButton(final String string) {
+ // Generate a standardized button.
+ final UIButton rVal = new UIButton(string);
+ rVal.refreshState();
+ return rVal;
+ }
+
+ public UIButton getCloseButton() {
+ return _closeButton;
+ }
+
+ public UIButton getExpandButton() {
+ return _maximizeButton;
+ }
+
+ public UIButton getHelpButton() {
+ return _helpButton;
+ }
+
+ public UIButton getMinimizeButton() {
+ return _minimizeButton;
+ }
+
+ public UILabel getTitleLabel() {
+ return _titleLabel;
+ }
+}
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIFrameStatusBar.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIFrameStatusBar.java new file mode 100644 index 0000000..5a34765 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIFrameStatusBar.java @@ -0,0 +1,127 @@ +/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui;
+
+import com.ardor3d.extension.ui.event.DragListener;
+import com.ardor3d.extension.ui.event.FrameResizeListener;
+import com.ardor3d.extension.ui.layout.BorderLayout;
+import com.ardor3d.extension.ui.layout.BorderLayoutData;
+import com.ardor3d.input.InputState;
+
+/**
+ * This panel extension defines a frame status bar (used at the bottom of a frame) with a text label and resize handle.
+ */
+public class UIFrameStatusBar extends UIPanel {
+
+ /** Our text label. */
+ private final UILabel _statusLabel;
+
+ /** Resize handle, used to drag out this content's size when the frame is set as resizeable. */
+ private final FrameResizeButton _resizeButton;
+
+ /** A drag listener used to perform resize operations on this frame. */
+ private DragListener _resizeListener = new FrameResizeListener(this);
+
+ /**
+ * Construct a new status bar
+ */
+ public UIFrameStatusBar() {
+ super(new BorderLayout());
+
+ _statusLabel = new UILabel("");
+ _statusLabel.setLayoutData(BorderLayoutData.CENTER);
+ add(_statusLabel);
+
+ _resizeButton = new FrameResizeButton();
+ _resizeButton.setLayoutData(BorderLayoutData.EAST);
+ add(_resizeButton);
+ }
+
+ public FrameResizeButton getResizeButton() {
+ return _resizeButton;
+ }
+
+ public UILabel getStatusLabel() {
+ return _statusLabel;
+ }
+
+ @Override
+ public void attachedToHud() {
+ super.attachedToHud();
+ final UIHud hud = getHud();
+ if (hud != null) {
+ hud.addDragListener(_resizeListener);
+ }
+ }
+
+ @Override
+ public void detachedFromHud() {
+ super.detachedFromHud();
+ final UIHud hud = getHud();
+ if (hud != null) {
+ hud.removeDragListener(_resizeListener);
+ }
+ }
+
+ public void setResizeListener(final DragListener listener) {
+ _resizeListener = listener;
+ }
+
+ public DragListener getResizeListener() {
+ return _resizeListener;
+ }
+
+ class FrameResizeButton extends UIButton {
+
+ public FrameResizeButton() {
+ super("...");
+ _pressedState = new MyPressedState();
+ _defaultState = new MyDefaultState();
+ _mouseOverState = new MyMouseOverState();
+ switchState(_defaultState);
+ }
+
+ @Override
+ protected void applySkin() {
+ ; // keep this from happening by default
+ }
+
+ class MyPressedState extends UIButton.PressedState {
+ @Override
+ public void mouseDeparted(final int mouseX, final int mouseY, final InputState state) {
+ super.mouseDeparted(mouseX, mouseY, state);
+ // TODO: Reset mouse cursor.
+ }
+ }
+
+ class MyDefaultState extends UIButton.DefaultState {
+ @Override
+ public void mouseEntered(final int mouseX, final int mouseY, final InputState state) {
+ super.mouseEntered(mouseX, mouseY, state);
+ // TODO: Set mouse cursor to resize.
+ }
+
+ @Override
+ public void mouseDeparted(final int mouseX, final int mouseY, final InputState state) {
+ super.mouseDeparted(mouseX, mouseY, state);
+ // TODO: Reset mouse cursor.
+ }
+ }
+
+ class MyMouseOverState extends UIButton.MouseOverState {
+ @Override
+ public void mouseDeparted(final int mouseX, final int mouseY, final InputState state) {
+ super.mouseDeparted(mouseX, mouseY, state);
+ // TODO: Reset mouse cursor.
+ }
+ }
+ }
+}
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIHud.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIHud.java new file mode 100644 index 0000000..1eae2d2 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIHud.java @@ -0,0 +1,895 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui; + +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.ardor3d.extension.ui.event.DragListener; +import com.ardor3d.extension.ui.util.HudListener; +import com.ardor3d.framework.Canvas; +import com.ardor3d.input.ButtonState; +import com.ardor3d.input.GrabbedState; +import com.ardor3d.input.InputState; +import com.ardor3d.input.Key; +import com.ardor3d.input.KeyboardState; +import com.ardor3d.input.MouseButton; +import com.ardor3d.input.MouseManager; +import com.ardor3d.input.MouseState; +import com.ardor3d.input.PhysicalLayer; +import com.ardor3d.input.logical.BasicTriggersApplier; +import com.ardor3d.input.logical.InputTrigger; +import com.ardor3d.input.logical.LogicalLayer; +import com.ardor3d.input.logical.TriggerAction; +import com.ardor3d.input.logical.TwoInputStates; +import com.ardor3d.renderer.Camera; +import com.ardor3d.renderer.Renderer; +import com.ardor3d.renderer.queue.RenderBucketType; +import com.ardor3d.renderer.state.ZBufferState; +import com.ardor3d.scenegraph.Node; +import com.ardor3d.scenegraph.Spatial; +import com.ardor3d.scenegraph.hint.CullHint; +import com.ardor3d.scenegraph.hint.LightCombineMode; +import com.ardor3d.scenegraph.hint.TextureCombineMode; +import com.google.common.base.Predicate; +import com.google.common.collect.Lists; + +/** + * UIHud represents a "Heads Up Display" or the base of a game UI scenegraph. Various UI Input, dragging, events, etc. + * are handled through this class. + */ +public class UIHud extends Node { + private static final Logger _logger = Logger.getLogger(UIHud.class.getName()); + + public static int MOUSE_CLICK_SENSITIVITY = 5; + + /** + * The logical layer used by this UI to receive input events. + */ + private final LogicalLayer _logicalLayer = new LogicalLayer(); + + /** + * The single tooltip used by this hud - lazy inited + */ + private UITooltip _ttip; + + /** + * Internal flag indicating whether the last input event was consumed by the UI. This is used to decide if we will + * forward the event to the next LogicalLayer. + */ + private boolean _mouseInputConsumed; + private boolean _keyInputConsumed; + + /** + * Flag used to determine if we should use mouse input when mouse is grabbed. Defaults to true. + */ + private boolean _ignoreMouseInputOnGrabbed = true; + + /** Which button is used for drag operations. Defaults to LEFT. */ + private MouseButton _dragButton = MouseButton.LEFT; + + /** Tracks the previous component our mouse was over so we can properly handle mouse entered and departed events. */ + private UIComponent _lastMouseOverComponent; + + /** Tracks last mouse location so we can detect movement. */ + private int _lastMouseX, _lastMouseY; + + /** Tracks last mouse pressed so we can detect clicks. */ + private int _mousePressedX, _mousePressedY; + + /** + * List of potential drag listeners. When a drag operation is detected, we will offer it to each item in the list + * until one accepts it. + */ + private final List<WeakReference<DragListener>> _dragListeners = new ArrayList<WeakReference<DragListener>>(); + + /** Our current drag listener. When an drag finished, this is set back to null. */ + private DragListener _dragListener = null; + + /** The component that currently has key focus - key events will be sent to this component. */ + private UIComponent _focusedComponent = null; + + /** The last component to be pressed. This component will receive any next mouseUp event. */ + private UIComponent _mousePressedComponent = null; + + /** + * List of hud listeners. + */ + private final List<HudListener> _hudListeners = Lists.newArrayList(); + + /** + * An optional mouseManager, required in order to test mouse is grabbed. + */ + private MouseManager _mouseManager; + + /** + * The list of currently displayed popup menus, with each entry being a submenu of the one previous. + */ + private final List<UIPopupMenu> _popupMenus = Lists.newArrayList(); + + /** + * Construct a new UIHud + */ + public UIHud() { + setName("UIHud"); + + getSceneHints().setCullHint(CullHint.Never); + getSceneHints().setRenderBucketType(RenderBucketType.Skip); + getSceneHints().setLightCombineMode(LightCombineMode.Off); + getSceneHints().setTextureCombineMode(TextureCombineMode.Replace); + + final ZBufferState zstate = new ZBufferState(); + zstate.setEnabled(false); + zstate.setWritable(false); + setRenderState(zstate); + + setupLogicalLayer(); + } + + /** + * @return the last detected x position of the mouse. + */ + public int getLastMouseX() { + return _lastMouseX; + } + + /** + * @return the last detected y position of the mouse. + */ + public int getLastMouseY() { + return _lastMouseY; + } + + /** + * @return this hud's associated tooltip object. + */ + public UITooltip getTooltip() { + if (_ttip == null) { + _ttip = new UITooltip(); + } + return _ttip; + } + + /** + * Add the given component to this hud. + * + * @param component + * the component to add + */ + public void add(final UIComponent component) { + attachChild(component); + component.attachedToHud(); + for (final HudListener hl : _hudListeners) { + hl.componentAdded(component); + } + } + + /** + * Remove the given component from the hud + * + * @param component + * the component to remove + */ + public void remove(final UIComponent component) { + // first lose focus, if appropriate + if (_focusedComponent != null && (_focusedComponent == component || _focusedComponent.hasAncestor(component))) { + setFocusedComponent(null); + } + // drop our mouse pressed component if applicable + if (_mousePressedComponent != null + && (_mousePressedComponent == component || _mousePressedComponent.hasAncestor(component))) { + _mousePressedComponent = null; + } + // drop our last mouse over component if applicable + if (_lastMouseOverComponent != null + && (_lastMouseOverComponent == component || _lastMouseOverComponent.hasAncestor(component))) { + _lastMouseOverComponent = null; + } + + component.detachedFromHud(); + detachChild(component); + for (final HudListener hl : _hudListeners) { + hl.componentRemoved(component); + } + } + + /** + * Overridden to force component detachments to go through {@link #remove(UIComponent)} + */ + @Override + public void detachAllChildren() { + if (getNumberOfChildren() > 0) { + for (int i = getNumberOfChildren() - 1; i >= 0; i--) { + final Spatial spat = getChild(i); + if (spat instanceof UIComponent) { + remove((UIComponent) spat); + } else { + detachChildAt(i); + } + } + } + } + + /** + * Reorder the components so that the given component is drawn last and is therefore "on top" of any others. + * + * @param component + * the component to bring to front + */ + public void bringToFront(final UIComponent component) { + getChildren().remove(component); + getChildren().add(component); + } + + /** + * Look for a UIComponent at the given screen coordinates. If no pickable component is at that location, null is + * returned. + * + * @param x + * the x screen coordinate + * @param y + * the y screen coordinate + * @return the picked component or null if nothing pickable was found at the given coordinates. + */ + public UIComponent getUIComponent(final int x, final int y) { + UIComponent found = null; + for (int i = _popupMenus.size(); --i >= 0;) { + final UIPopupMenu menu = _popupMenus.get(i); + found = menu.getUIComponent(x, y); + if (found != null) { + return found; + } + } + + for (int i = getNumberOfChildren(); --i >= 0;) { + final Spatial s = getChild(i); + if (s instanceof UIComponent) { + final UIComponent comp = (UIComponent) s; + if (!comp.isVisible()) { + continue; + } + + found = comp.getUIComponent(x, y); + + if (found != null) { + break; + } + } + } + + return found; + } + + /** + * @return the component that currently has key focus or null if none. + */ + public UIComponent getFocusedComponent() { + return _focusedComponent; + } + + /** + * @param compomponent + * the component that should now have key focus. If this component has a focus target, that will be used + * instead. + */ + public void setFocusedComponent(final UIComponent compomponent) { + // If we already have a different focused component, tell it that it has lost focus. + if (_focusedComponent != null && _focusedComponent != compomponent) { + _focusedComponent.lostFocus(); + } + + // Set our focused component to the given component (or its focus target) + if (compomponent != null) { + if (compomponent.getKeyFocusTarget() != null) { + // set null so we don't re-tell it that it lost focus. + _focusedComponent = null; + // recurse down to target. + setFocusedComponent(compomponent.getKeyFocusTarget()); + } else { + _focusedComponent = compomponent; + // let our new focused component know it has focus + _focusedComponent.gainedFocus(); + } + } else { + _focusedComponent = null; + } + } + + /** + * @return the MouseButton that triggers drag operations + */ + public MouseButton getDragButton() { + return _dragButton; + } + + /** + * @param dragButton + * set the MouseButton that triggers drag operations + */ + public void setDragButton(final MouseButton dragButton) { + _dragButton = dragButton; + } + + /** + * Override to force setting ortho before drawing and to specifically handle draw order of components and tool tip. + */ + @Override + public void draw(final Renderer r) { + r.setOrtho(); + try { + Spatial child; + int i, max; + for (i = 0, max = getNumberOfChildren(); i < max; i++) { + child = getChild(i); + if (child != null) { + child.onDraw(r); + } + } + if (!_popupMenus.isEmpty()) { + for (i = 0, max = _popupMenus.size(); i < max; i++) { + _popupMenus.get(i).onDraw(r); + } + } + if (_ttip != null && _ttip.isVisible()) { + _ttip.onDraw(r); + } + } catch (final Exception e) { + UIHud._logger.logp(Level.SEVERE, getClass().getName(), "draw(Renderer)", "Exception", e); + } finally { + if (r.isInOrthoMode()) { + r.unsetOrtho(); + } + r.clearClips(); + } + } + + @Override + public void updateGeometricState(final double time, final boolean initiator) { + super.updateGeometricState(time, initiator); + if (!_popupMenus.isEmpty()) { + for (int i = 0, max = _popupMenus.size(); i < max; i++) { + _popupMenus.get(i).updateGeometricState(time, true); + } + } + if (_ttip != null && _ttip.isVisible()) { + _ttip.updateGeometricState(time, true); + } + } + + /** + * Add the given drag listener to this hud. Expired WeakReferences are also cleaned. + * + * @param listener + * the listener to add + */ + public void addDragListener(final DragListener listener) { + _dragListeners.add(new WeakReference<DragListener>(listener)); + + // Clean list. + for (int i = _dragListeners.size(); --i >= 0;) { + if (_dragListeners.get(i).get() == null) { + _dragListeners.remove(i); + } + } + } + + /** + * Remove any matching drag listener from this hud. Expired WeakReferences are also cleaned. + * + * @param listener + * the listener to remove + * @return true if at least one "equal" DragListener was found in the pool of listeners and removed. + */ + public boolean removeDragListener(final DragListener listener) { + boolean rVal = false; + for (int i = _dragListeners.size(); --i >= 0;) { + final DragListener dl = _dragListeners.get(i).get(); + if (dl == null) { + _dragListeners.remove(i); + } else if (dl.equals(listener)) { + _dragListeners.remove(i); + rVal = true; + } + } + return rVal; + } + + /** + * Add the given hud listener to this hud. + * + * @param listener + * the listener to add + */ + public void addHudListener(final HudListener listener) { + _hudListeners.add(listener); + } + + /** + * Remove any matching hud listener from this hud. + * + * @param listener + * the listener to remove + * @return true if at least one "equal" HudListener was found in the pool of listeners and removed. + */ + public boolean removeHudListener(final HudListener listener) { + return _hudListeners.remove(listener); + } + + /** + * @return the logical layer associated with this hud. When chaining UI logic to game logic, this LogicalLayer is + * the one to call checkTriggers on. + */ + public LogicalLayer getLogicalLayer() { + return _logicalLayer; + } + + /** + * @return true if we should ignore (only forward) mouse input when the mouse is set to grabbed. If true, requires + * mouse manager to be set or this param is ignored. + */ + public boolean isIgnoreMouseInputOnGrabbed() { + return _ignoreMouseInputOnGrabbed; + } + + /** + * @param mouseInputOnGrabbed + * true if we should ignore (only forward) mouse input when the mouse is set to grabbed. If true, + * requires mouse manager to be set or this param is ignored. + * @see #setMouseManager(MouseManager) + */ + public void setIgnoreMouseInputOnGrabbed(final boolean mouseInputOnGrabbed) { + _ignoreMouseInputOnGrabbed = mouseInputOnGrabbed; + } + + /** + * @return a MouseManager used to test if mouse is grabbed, or null if none was set. + */ + public MouseManager getMouseManager() { + return _mouseManager; + } + + /** + * @param manager + * a MouseManager used to test if mouse is grabbed. + */ + public void setMouseManager(final MouseManager manager) { + _mouseManager = manager; + } + + /** + * Convenience method for setting up the UI's connection to the Ardor3D input system, along with a forwarding + * address for input events that the UI does not care about. + * + * @param canvas + * the canvas to register with + * @param physicalLayer + * the physical layer to register with + * @param forwardTo + * a LogicalLayer to send unconsumed (by the UI) input events to. + */ + public void setupInput(final Canvas canvas, final PhysicalLayer physicalLayer, final LogicalLayer forwardTo) { + // Set up this logical layer to listen for events from the given canvas and PhysicalLayer + _logicalLayer.registerInput(canvas, physicalLayer); + + // Set up forwarding for events not consumed. + if (forwardTo != null) { + _logicalLayer.setApplier(new BasicTriggersApplier() { + + @Override + public void checkAndPerformTriggers(final Set<InputTrigger> triggers, final Canvas source, + final TwoInputStates states, final double tpf) { + super.checkAndPerformTriggers(triggers, source, states, tpf); + + if (!_mouseInputConsumed) { + if (!_keyInputConsumed) { + // nothing consumed + forwardTo.getApplier() + .checkAndPerformTriggers(forwardTo.getTriggers(), source, states, tpf); + } else { + // only key state consumed + final TwoInputStates forwardingState = new TwoInputStates(states.getPrevious(), + new InputState(KeyboardState.NOTHING, states.getCurrent().getMouseState(), states + .getCurrent().getControllerState())); + forwardTo.getApplier().checkAndPerformTriggers(forwardTo.getTriggers(), source, + forwardingState, tpf); + } + } else { + if (!_keyInputConsumed) { + // only mouse consumed + final TwoInputStates forwardingState = new TwoInputStates(states.getPrevious(), + new InputState(states.getCurrent().getKeyboardState(), MouseState.NOTHING, states + .getCurrent().getControllerState())); + forwardTo.getApplier().checkAndPerformTriggers(forwardTo.getTriggers(), source, + forwardingState, tpf); + } else { + // both consumed, do nothing. + } + } + + _mouseInputConsumed = false; + _keyInputConsumed = false; + } + }); + } + } + + /** + * Set up our logical layer with a trigger that hands input to the UI and saves whether it was "consumed". + */ + private void setupLogicalLayer() { + _logicalLayer.registerTrigger(new InputTrigger(new Predicate<TwoInputStates>() { + public boolean apply(final TwoInputStates arg0) { + // always trigger this. + return true; + } + }, new TriggerAction() { + public void perform(final Canvas source, final TwoInputStates inputStates, final double tpf) { + _mouseInputConsumed = offerMouseInputToUI(inputStates); + _keyInputConsumed = offerKeyInputToUI(inputStates); + } + })); + } + + private boolean offerKeyInputToUI(final TwoInputStates inputStates) { + boolean consumed = false; + final InputState current = inputStates.getCurrent(); + + // Keyboard checks + { + final KeyboardState previousKState = inputStates.getPrevious().getKeyboardState(); + final KeyboardState currentKState = current.getKeyboardState(); + if (!currentKState.getKeysDown().isEmpty()) { + // new presses + final EnumSet<Key> pressed = currentKState.getKeysPressedSince(previousKState); + if (!pressed.isEmpty()) { + for (final Key key : pressed) { + consumed |= fireKeyPressedEvent(key, current); + } + } + + // repeats + final EnumSet<Key> repeats = currentKState.getKeysHeldSince(previousKState); + if (!repeats.isEmpty() && _focusedComponent != null) { + for (final Key key : repeats) { + consumed |= fireKeyHeldEvent(key, current); + } + } + } + + // key releases + if (!previousKState.getKeysDown().isEmpty()) { + final EnumSet<Key> released = currentKState.getKeysReleasedSince(previousKState); + if (!released.isEmpty()) { + for (final Key key : released) { + consumed |= fireKeyReleasedEvent(key, current); + } + } + } + } + + return consumed; + + } + + /** + * Parse a given set of input states for UI events and pass these events to the UI components contained in this hud. + * + * @param inputStates + * our two InputState objects, detailing a before and after snapshot of the input system. + * @return true if a UI element consumed the event described by inputStates. + */ + private boolean offerMouseInputToUI(final TwoInputStates inputStates) { + boolean consumed = false; + final InputState current = inputStates.getCurrent(); + + // Mouse checks. + if (!isIgnoreMouseInputOnGrabbed() || _mouseManager == null + || _mouseManager.getGrabbed() != GrabbedState.GRABBED) { + final MouseState previousMState = inputStates.getPrevious().getMouseState(); + final MouseState currentMState = current.getMouseState(); + if (previousMState != currentMState) { + + // Check for presses. + if (currentMState.hasButtonState(ButtonState.DOWN)) { + final EnumSet<MouseButton> pressed = currentMState.getButtonsPressedSince(previousMState); + if (!pressed.isEmpty()) { + for (final MouseButton button : pressed) { + consumed |= fireMouseButtonPressed(button, current); + } + } + } + + // Check for releases. + if (previousMState.hasButtonState(ButtonState.DOWN)) { + final EnumSet<MouseButton> released = currentMState.getButtonsReleasedSince(previousMState); + if (!released.isEmpty()) { + for (final MouseButton button : released) { + consumed |= fireMouseButtonReleased(button, current); + } + } + } + + // Check for mouse movement + if (currentMState.getDx() != 0 || currentMState.getDy() != 0) { + consumed |= fireMouseMoved(currentMState.getX(), currentMState.getY(), current); + } + + // Check for wheel change + if (currentMState.getDwheel() != 0) { + consumed |= fireMouseWheelMoved(currentMState.getDwheel(), current); + } + } + } + return consumed || _dragListener != null; + } + + /** + * Handle mouse presses. + * + * @param button + * the button that was pressed. + * @param currentIS + * the current input state. + * @return true if this event is consumed. + */ + public boolean fireMouseButtonPressed(final MouseButton button, final InputState currentIS) { + boolean consumed = false; + final int mouseX = currentIS.getMouseState().getX(), mouseY = currentIS.getMouseState().getY(); + final UIComponent over = getUIComponent(mouseX, mouseY); + + setFocusedComponent(over); + _mousePressedComponent = over; + _mousePressedX = mouseX; + _mousePressedY = mouseY; + + if (over == null) { + closePopupMenus(); + return false; + } else { + consumed |= over.mousePressed(button, currentIS); + } + + // Check if the component we are pressing on is "draggable" + for (final WeakReference<DragListener> ref : _dragListeners) { + final DragListener listener = ref.get(); + if (listener == null) { + continue; + } + + if (listener.isDragHandle(over, mouseX, mouseY)) { + listener.startDrag(mouseX, mouseY); + _dragListener = listener; + consumed = true; + break; + } + } + + // bring any clicked components to front + final UIComponent component = over.getTopLevelComponent(); + if (component != null && !(component instanceof UIPopupMenu)) { + bringToFront(component); + closePopupMenus(); + } + return consumed; + } + + /** + * Handle mouse releases. + * + * @param button + * the button that was release. + * @param currentIS + * the current input state. + * @return true if this event is consumed. + */ + public boolean fireMouseButtonReleased(final MouseButton button, final InputState currentIS) { + boolean consumed = false; + final int mouseX = currentIS.getMouseState().getX(), mouseY = currentIS.getMouseState().getY(); + + // if we have previously sent a component a mouseDown, send it the release event + final UIComponent component = _mousePressedComponent; + _mousePressedComponent = null; + + if (component != null) { + consumed |= component.mouseReleased(button, currentIS); + final int distance = Math.abs(mouseX - _mousePressedX) + Math.abs(mouseY - _mousePressedY); + + if (distance < UIHud.MOUSE_CLICK_SENSITIVITY) { + component.mouseClicked(button, currentIS); + } + } + + if (button == _dragButton && _dragListener != null) { + _dragListener.endDrag(component, mouseX, mouseY); + _dragListener = null; + consumed = true; + } + + return consumed; + } + + /** + * Handle movement events. + * + * @param mouseX + * the new x position of the mouse + * @param mouseY + * the new y position of the mouse + * @param currentIS + * the current input state. + * @return if this event is consumed. + */ + public boolean fireMouseMoved(final int mouseX, final int mouseY, final InputState currentIS) { + _lastMouseX = mouseX; + _lastMouseY = mouseY; + + // Check for drag movements. + if (currentIS.getMouseState().getButtonState(_dragButton) == ButtonState.DOWN) { + if (_dragListener != null) { + _dragListener.drag(mouseX, mouseY); + return true; + } + } + + // grab the component the mouse is over, if any + final UIComponent over = getUIComponent(mouseX, mouseY); + + boolean consumed = false; + + // Are we over a component? let it know we moved inside it. + if (over != null) { + consumed |= over.mouseMoved(mouseX, mouseY, currentIS); + } + + // component points to a different UIComponent than before, so mark departed + if (over == null || over != _lastMouseOverComponent) { + if (_lastMouseOverComponent != null) { + _lastMouseOverComponent.mouseDeparted(mouseX, mouseY, currentIS); + } + if (over != null) { + over.mouseEntered(mouseX, mouseY, currentIS); + } + } + _lastMouseOverComponent = over; + + return consumed; + } + + /** + * Handle wheel events. + * + * @param wheelDx + * the change in wheel position. + * @param currentIS + * the current input state. + * @return if this event is consumed. + */ + public boolean fireMouseWheelMoved(final int wheelDx, final InputState currentIS) { + final UIComponent over = getUIComponent(currentIS.getMouseState().getX(), currentIS.getMouseState().getY()); + + if (over == null) { + return false; + } + + return over.mouseWheel(wheelDx, currentIS); + } + + /** + * Handle key presses. + * + * @param key + * the pressed key + * @param currentIS + * the current input state. + * @return if this event is consumed. + */ + public boolean fireKeyPressedEvent(final Key key, final InputState currentIS) { + if (_focusedComponent != null) { + return _focusedComponent.keyPressed(key, currentIS); + } else { + return false; + } + } + + /** + * Handle key held (pressed down over more than one input update cycle.) + * + * @param key + * the held key + * @param currentIS + * the current input state. + * @return if this event is consumed. + */ + public boolean fireKeyHeldEvent(final Key key, final InputState currentIS) { + if (_focusedComponent != null) { + return _focusedComponent.keyHeld(key, currentIS); + } else { + return false; + } + } + + /** + * Handle key releases. + * + * @param key + * the released key + * @param currentIS + * the current input state. + * @return if this event is consumed. + */ + public boolean fireKeyReleasedEvent(final Key key, final InputState currentIS) { + if (_focusedComponent != null) { + return _focusedComponent.keyReleased(key, currentIS); + } else { + return false; + } + } + + public int getWidth() { + final Camera cam = Camera.getCurrentCamera(); + if (cam != null) { + return cam.getWidth(); + } else { + return 1; + } + } + + public int getHeight() { + final Camera cam = Camera.getCurrentCamera(); + if (cam != null) { + return cam.getHeight(); + } else { + return 1; + } + } + + public void closePopupMenus() { + for (final UIPopupMenu menu : _popupMenus) { + menu.close(); + } + _popupMenus.clear(); + } + + public void closePopupMenusAfter(final Object parent) { + if (parent == this) { + closePopupMenus(); + return; + } + + boolean found = false; + for (final Iterator<UIPopupMenu> it = _popupMenus.iterator(); it.hasNext();) { + final UIPopupMenu pMenu = it.next(); + if (found) { + pMenu.close(); + it.remove(); + } else if (pMenu == parent) { + found = true; + } + } + } + + public void showPopupMenu(final UIPopupMenu menu) { + closePopupMenus(); + _popupMenus.add(menu); + menu.setHud(this); + } + + public void showSubPopupMenu(final UIPopupMenu menu) { + _popupMenus.add(menu); + menu.setHud(this); + } +} diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UILabel.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UILabel.java new file mode 100644 index 0000000..6e6fff0 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UILabel.java @@ -0,0 +1,61 @@ +/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui;
+
+import com.ardor3d.extension.ui.util.SubTex;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Basic implementation of {@link AbstractLabelUIComponent}.
+ */
+public class UILabel extends AbstractLabelUIComponent {
+
+ private final LabelState _disabledState = new LabelState();
+ private final LabelState _defaultState = new LabelState();
+
+ /**
+ * @param text
+ * the text value of this label.
+ */
+ public UILabel(final String text) {
+ this(text, null);
+ }
+
+ /**
+ *
+ * @param text
+ * the text value of this label.
+ * @param icon
+ * the icon value of this label.
+ */
+ public UILabel(final String text, final SubTex icon) {
+ setText(text);
+ setIcon(icon);
+
+ applySkin();
+ switchState(getDefaultState());
+ }
+
+ @Override
+ public LabelState getDefaultState() {
+ return _defaultState;
+ }
+
+ @Override
+ public LabelState getDisabledState() {
+ return _disabledState;
+ }
+
+ @Override
+ public ImmutableSet<UIState> getStates() {
+ return ImmutableSet.of((UIState) _defaultState, _disabledState);
+ }
+}
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIMenuItem.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIMenuItem.java new file mode 100644 index 0000000..05c16e0 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIMenuItem.java @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui; + +import com.ardor3d.extension.ui.event.ActionEvent; +import com.ardor3d.extension.ui.event.ActionListener; +import com.ardor3d.extension.ui.util.SubTex; + +/** + * A simple extension of Button to be used in popup menus. XXX: may be enhanced later to deal with submenus, etc. + */ +public class UIMenuItem extends UIButton { + public UIMenuItem(final String text) { + this(text, null); + } + + public UIMenuItem(final String text, final SubTex icon) { + super(text, icon); + + // Close menus when a menu item is clicked + addActionListener(new ActionListener() { + public void actionPerformed(final ActionEvent event) { + final UIHud hud = getHud(); + if (hud != null) { + hud.closePopupMenus(); + } + } + }); + } +} diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIPanel.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIPanel.java new file mode 100644 index 0000000..ad3bd5b --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIPanel.java @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui; + +import com.ardor3d.extension.ui.layout.UILayout; + +/** + * The most basic implementation of a UI container. + */ +public class UIPanel extends UIContainer { + + public UIPanel() {} + + public UIPanel(final UILayout layout) { + setLayout(layout); + } +} diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIPasswordField.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIPasswordField.java new file mode 100644 index 0000000..4476b73 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIPasswordField.java @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui; + +public class UIPasswordField extends UITextField { + + protected char _passwordChar = '*'; + + public UIPasswordField() { + super.setCopyable(false); + } + + public char getPasswordChar() { + return _passwordChar; + } + + public void setPasswordChar(final char passwordChar) { + _passwordChar = passwordChar; + } + + @Override + public void setText(final String text) { + final StringBuilder newText = new StringBuilder(); + if (text != null) { + for (int i = text.length(); --i >= 0;) { + newText.append(_passwordChar); + } + } + super.setText(newText.toString()); + if (_uiText != null) { + _uiText.setPlainText(text); + } + } + + @Override + public void setCopyable(final boolean copyable) { + ; // ignore + } + + @Override + public boolean isCopyable() { + return false; + } +} diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIPopupMenu.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIPopupMenu.java new file mode 100644 index 0000000..f06e1e3 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIPopupMenu.java @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it under the terms of its license which may be found + * in the accompanying LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui; + +import java.util.EnumSet; + +import com.ardor3d.extension.ui.layout.RowLayout; + +/** + * A special frame meant to display menu items. + */ +public class UIPopupMenu extends UIFrame { + + public UIPopupMenu() { + super(null, EnumSet.noneOf(UIFrame.FrameButtons.class)); + getContentPanel().setLayout(new RowLayout(false)); + applySkin(); + } + + public void showAt(final int x, int y) { + final int width = getLocalComponentWidth(); + final int height = getLocalComponentHeight(); + + final int displayW = getHud().getWidth(); + final int displayH = getHud().getHeight(); + + if (x + width > displayW) { + setHudX(displayW - width); + } else { + setHudX(x - getBorder().getLeft()); + } + y = y - height; + if (y < 0) { + y = 0; + } + if (y + height > displayH) { + y = displayH - height; + } + setHudY(y); + updateGeometricState(0, true); + } + + public void setHud(final UIHud hud) { + _parent = hud; + attachedToHud(); + } + + public void addItem(final UIMenuItem item) { + getContentPanel().add(item); + } + + public void removeItem(final UIMenuItem item) { + getContentPanel().remove(item); + } + + public void clearItems() { + getContentPanel().removeAllComponents(); + } +} diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIProgressBar.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIProgressBar.java new file mode 100644 index 0000000..ab153e6 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIProgressBar.java @@ -0,0 +1,151 @@ +/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui;
+
+import com.ardor3d.extension.ui.border.EmptyBorder;
+import com.ardor3d.extension.ui.layout.BorderLayout;
+import com.ardor3d.extension.ui.layout.BorderLayoutData;
+import com.ardor3d.extension.ui.util.Insets;
+
+/**
+ * This component shows progress as "percent complete" via a proportionally sized bar and an optional text label.
+ */
+public class UIProgressBar extends UIPanel {
+
+ /** Text label shown on top of the progress bar itself. */
+ private final UILabel _barLabel;
+ /** Text label shown to the side of the progress bar. */
+ private final UILabel _textLabel;
+
+ /** The panel representing our percentage progress bar. */
+ private final UIPanel _bar;
+ /** The panel shown behind our progress bar. */
+ private final UIPanel _mainPanel;
+
+ /** How much progress to show, as a percentage. */
+ private double _percentFilled = .5;
+ /** Whether to show the progress bar horizontally or vertically. */
+ private boolean _horizontal = true;
+
+ /**
+ * Construct a new, horizontal progress bar.
+ */
+ public UIProgressBar() {
+ this(null, true);
+ }
+
+ /**
+ * Construct a new progress bar with the given attributes.
+ *
+ * @param labelText
+ * text to show next to the progress bar
+ * @param horizontal
+ * true for horizontal bar, false for vertical.
+ */
+ public UIProgressBar(final String labelText, final boolean horizontal) {
+ super(new BorderLayout());
+ setHorizontal(horizontal);
+
+ _textLabel = new UILabel("");
+ _textLabel.setBorder(new EmptyBorder());
+ _textLabel.setMargin(new Insets(0, 0, 0, 0));
+ _textLabel.setPadding(new Insets(0, 0, 0, 0));
+ _textLabel.setLayoutData(BorderLayoutData.WEST);
+ setLabelText(labelText);
+ add(_textLabel);
+
+ _mainPanel = new UIPanel(new BorderLayout());
+ _mainPanel.setLayoutData(BorderLayoutData.CENTER);
+ add(_mainPanel);
+
+ _bar = new UIPanel(new BorderLayout());
+ _bar.setLayoutData(BorderLayoutData.CENTER);
+ _mainPanel.add(_bar);
+
+ _barLabel = new UILabel("");
+ _barLabel.setLayoutData(BorderLayoutData.CENTER);
+ _mainPanel.add(_barLabel);
+
+ applySkin();
+
+ updateMinimumSizeFromContents();
+ compact();
+
+ layout();
+ }
+
+ @Override
+ public void layout() {
+ super.layout();
+
+ if (isHorizontal()) {
+ _bar.setLocalComponentWidth((int) (_percentFilled * _bar.getLocalComponentWidth()));
+ } else {
+ _bar.setLocalComponentHeight((int) (_percentFilled * _bar.getLocalComponentHeight()));
+ }
+ }
+
+ public boolean isHorizontal() {
+ return _horizontal;
+ }
+
+ /**
+ * Takes affect on next call to layout()
+ *
+ * @param horizontal
+ * true for horizontal bar, false for vertical.
+ */
+ public void setHorizontal(final boolean horizontal) {
+ _horizontal = horizontal;
+ }
+
+ public double getPercentFilled() {
+ return _percentFilled;
+ }
+
+ /**
+ * Triggers layout if value is not same as current value.
+ *
+ * @param value
+ */
+ public void setPercentFilled(final double value) {
+ final double old = _percentFilled;
+ _percentFilled = Math.min(value, 1.0);
+ if (old != _percentFilled) {
+ layout();
+ }
+ }
+
+ public void setLabelText(final String text) {
+ _textLabel.setText(text);
+ _textLabel.updateMinimumSizeFromContents();
+ }
+
+ public void setBarText(final String text) {
+ _barLabel.setText(text);
+ }
+
+ public UIPanel getBar() {
+ return _bar;
+ }
+
+ public UILabel getTextLabel() {
+ return _textLabel;
+ }
+
+ public UILabel getBarLabel() {
+ return _barLabel;
+ }
+
+ public UIPanel getMainPanel() {
+ return _mainPanel;
+ }
+}
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIRadioButton.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIRadioButton.java new file mode 100644 index 0000000..78d8d6e --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIRadioButton.java @@ -0,0 +1,50 @@ +/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui;
+
+import com.ardor3d.extension.ui.util.ButtonGroup;
+import com.ardor3d.extension.ui.util.SubTex;
+
+/**
+ * A extension of button that is specifically selectable and is generally used with a {@link ButtonGroup}. This class is
+ * defined distinctly from UIButton to allow for specific skinning.
+ */
+public class UIRadioButton extends UIButton {
+
+ public UIRadioButton() {
+ this("");
+ }
+
+ public UIRadioButton(final String text) {
+ this(text, null);
+ }
+
+ public UIRadioButton(final String text, final SubTex icon) {
+ super(text, icon);
+ super.setSelectable(true);
+ }
+
+ /**
+ * Ignored
+ */
+ @Override
+ public void setSelectable(final boolean selectable) {
+ ;
+ }
+
+ /**
+ * @return true
+ */
+ @Override
+ public boolean isSelectable() {
+ return true;
+ }
+}
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIScrollBar.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIScrollBar.java new file mode 100644 index 0000000..c755a13 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIScrollBar.java @@ -0,0 +1,139 @@ +/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.ardor3d.extension.ui.event.ActionEvent;
+import com.ardor3d.extension.ui.event.ActionListener;
+import com.ardor3d.extension.ui.layout.BorderLayout;
+import com.ardor3d.extension.ui.layout.BorderLayoutData;
+
+/**
+ * NOTE: Experimental still.
+ */
+public class UIScrollBar extends UIPanel {
+
+ private final Orientation orientation;
+ private final UISlider slider;
+ private final UIButton btTopLeft;
+ private final UIButton btBottomRight;
+ private int sliderLength;
+ /** List of action listeners notified when this scrollbar is changed. */
+ private final List<ActionListener> _listeners = new ArrayList<ActionListener>();
+
+ public UIScrollBar(final Orientation orientation) {
+ setLayout(new BorderLayout());
+ this.orientation = orientation;
+ slider = new UISlider(orientation);
+ slider.setLayoutData(BorderLayoutData.CENTER);
+ btTopLeft = new UIButton(orientation == Orientation.Vertical ? "^" : "<");
+ btBottomRight = new UIButton(orientation == Orientation.Vertical ? "v" : ">");
+ add(btTopLeft);
+ add(btBottomRight);
+ add(slider);
+ if (orientation == Orientation.Vertical) {
+ btTopLeft.setLayoutData(BorderLayoutData.NORTH);
+ btBottomRight.setLayoutData(BorderLayoutData.SOUTH);
+ } else {
+ btTopLeft.setLayoutData(BorderLayoutData.WEST);
+ btBottomRight.setLayoutData(BorderLayoutData.EAST);
+ }
+ applySkin();
+
+ updateMinimumSizeFromContents();
+ compact();
+
+ layout();
+ final ActionListener al = new ActionListener() {
+ public void actionPerformed(final ActionEvent event) {
+ int direction;
+ if (event.getSource() == btTopLeft) {
+ direction = UIScrollBar.this.orientation == Orientation.Horizontal ? -1 : 1;
+ } else {
+ direction = UIScrollBar.this.orientation == Orientation.Horizontal ? 1 : -1;
+ }
+ int offset = slider.getValue();
+ if (direction < 0) {
+ offset -= 10;
+ if (offset < 0) {
+ offset = 0;
+ }
+ } else {
+ offset += 10;
+ if (offset > slider.getModel().getMaxValue()) {
+ offset = slider.getModel().getMaxValue();
+ }
+ }
+ slider.setValue(offset);
+ fireChangeEvent();
+ }
+ };
+ btTopLeft.addActionListener(al);
+ btBottomRight.addActionListener(al);
+ slider.addActionListener(new ActionListener() {
+ public void actionPerformed(final ActionEvent event) {
+ fireChangeEvent();
+ }
+ });
+ }
+
+ private void fireChangeEvent() {
+ final ActionEvent event = new ActionEvent(this);
+ for (final ActionListener l : _listeners) {
+ l.actionPerformed(event);
+ }
+ }
+
+ /**
+ * Add the specified listener to this scrollbar's list of listeners notified when it's changed.
+ *
+ * @param listener
+ */
+ public void addActionListener(final ActionListener listener) {
+ _listeners.add(listener);
+ }
+
+ public Orientation getOrientation() {
+ return orientation;
+ }
+
+ public int getSliderLength() {
+ return sliderLength;
+ }
+
+ public int getValue() {
+ return slider.getValue();
+ }
+
+ public void setValue(final int offset) {
+ slider.setValue(offset);
+ layout();
+ fireComponentDirty();
+ }
+
+ public void setMaxValue(final int maxOffset) {
+ slider.getModel().setMaxValue(maxOffset);
+ }
+
+ public UISlider getSlider() {
+ return slider;
+ }
+
+ public UIButton getBtTopLeft() {
+ return btTopLeft;
+ }
+
+ public UIButton getBtBottomRight() {
+ return btBottomRight;
+ }
+}
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIScrollPanel.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIScrollPanel.java new file mode 100644 index 0000000..e7c74cb --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIScrollPanel.java @@ -0,0 +1,115 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui; + +import com.ardor3d.extension.ui.event.ActionEvent; +import com.ardor3d.extension.ui.event.ActionListener; +import com.ardor3d.extension.ui.layout.BorderLayout; +import com.ardor3d.extension.ui.layout.BorderLayoutData; +import com.ardor3d.math.Rectangle2; +import com.ardor3d.renderer.Renderer; + +/** + * NOTE: Experimental still. + */ +public class UIScrollPanel extends UIPanel { + + private final UIScrollBar verticalScrollBar; + private final UIScrollBar horizontalScrollBar; + private UIComponent view; + private int offsetX; + private int offsetY; + + /** A store for the clip rectangle. */ + private final Rectangle2 _clipRectangleStore = new Rectangle2(); + + public UIScrollPanel() { + this(null); + } + + public UIScrollPanel(final UIComponent view) { + setLayout(new BorderLayout()); + if (view != null) { + this.view = view; + view.setLayoutData(BorderLayoutData.CENTER); + add(view); + } + horizontalScrollBar = new UIScrollBar(Orientation.Horizontal); + horizontalScrollBar.setLayoutData(BorderLayoutData.SOUTH); + verticalScrollBar = new UIScrollBar(Orientation.Vertical); + verticalScrollBar.setLayoutData(BorderLayoutData.EAST); + add(horizontalScrollBar); + add(verticalScrollBar); + setDoClip(true); + horizontalScrollBar.addActionListener(new ActionListener() { + public void actionPerformed(final ActionEvent event) { + offsetX = horizontalScrollBar.getValue(); + fireComponentDirty(); + updateScrollBarSliders(); + } + }); + verticalScrollBar.addActionListener(new ActionListener() { + public void actionPerformed(final ActionEvent event) { + offsetY = verticalScrollBar.getValue(); + fireComponentDirty(); + updateScrollBarSliders(); + } + }); + applySkin(); + } + + @Override + protected void drawComponent(final Renderer renderer) { + _clipRectangleStore.set(getHudX() + getTotalLeft(), + getHudY() + getTotalBottom() + horizontalScrollBar.getContentHeight(), getContentWidth() + - verticalScrollBar.getContentWidth(), + getContentHeight() - horizontalScrollBar.getContentHeight()); + renderer.pushClip(_clipRectangleStore); + + // temporary translate the view - this is a hack and there may be a better solution + final int x = view.getLocalX(); + final int y = view.getLocalY(); + view.setLocalXY(x - offsetX, y - offsetY); + view.updateWorldTransform(true); + view.draw(renderer); + view.setLocalXY(x, y); + renderer.popClip(); + horizontalScrollBar.onDraw(renderer); + verticalScrollBar.onDraw(renderer); + } + + @Override + public void updateMinimumSizeFromContents() { + super.updateMinimumSizeFromContents(); + setMinimumContentSize(verticalScrollBar.getLocalComponentWidth() + 1, horizontalScrollBar + .getLocalComponentHeight() + 1); + updateScrollBarSliders(); + } + + private void updateScrollBarSliders() { + if (view != null) { + verticalScrollBar.setValue(offsetY); + verticalScrollBar.setMaxValue(view.getLocalComponentHeight() - getContentHeight() + + horizontalScrollBar.getLocalComponentHeight()); + horizontalScrollBar.setValue(offsetX); + horizontalScrollBar.setMaxValue(view.getLocalComponentWidth() - getContentWidth() + + verticalScrollBar.getLocalComponentWidth()); + verticalScrollBar.fireComponentDirty(); + horizontalScrollBar.fireComponentDirty(); + } + } + + @Override + public void layout() { + super.layout(); + updateScrollBarSliders(); + } +} diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UISlider.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UISlider.java new file mode 100644 index 0000000..4ac4c61 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UISlider.java @@ -0,0 +1,262 @@ +/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui;
+
+import java.util.List;
+
+import com.ardor3d.extension.ui.event.ActionEvent;
+import com.ardor3d.extension.ui.event.ActionListener;
+import com.ardor3d.extension.ui.model.DefaultSliderModel;
+import com.ardor3d.extension.ui.model.SliderModel;
+import com.google.common.collect.Lists;
+
+/**
+ * A widget allowing display and control of a choice from a range of values.
+ */
+public class UISlider extends UIContainer {
+
+ /** Our data model */
+ private SliderModel _model;
+
+ /** The panel or decoration in the back of the slider. */
+ private final UIPanel _backPanel = new UIPanel();
+
+ /** The knob used to display and control the value of this slider. */
+ private final UISliderKnob _knob;
+
+ /** List of action listeners notified when this slider is changed. */
+ private final List<ActionListener> _listeners = Lists.newArrayList();
+
+ /** The orientation of this slider knob. */
+ private final Orientation _orientation;
+
+ /** Do we snap to the integer values? */
+ private boolean _snapToValues = true;
+
+ /**
+ * create a slider widget with a default range of [0,100]. Initial value is 50.
+ *
+ * @param orientation
+ * the orientation of the slider (Orientation.Horizontal or Orientation.Vertical)
+ */
+ public UISlider(final Orientation orientation) {
+ this(orientation, 0, 100, 50);
+ }
+
+ /**
+ * create a slider widget with a default range of [minValue,maxOffset] and the given initialValue.
+ *
+ * @param orientation
+ * the orientation of the slider (Orientation.Horizontal or Orientation.Vertical)
+ * @param minValue
+ * the minimum value the slider can take (inclusive).
+ * @param maxValue
+ * the maximum value the slider can take (inclusive). Must be greater than or equal to minValue.
+ * @param initialValue
+ * the starting value of the slider. Must be between min and max values.
+ */
+ public UISlider(final Orientation orientation, final int minValue, final int maxValue, final int initialValue) {
+ assert orientation != null : "orientation must not be null.";
+ assert minValue <= maxValue : "minValue must be less than maxValue.";
+ assert minValue <= initialValue && initialValue <= maxValue : "initialValue must be between minValue and maxValue.";
+
+ // Set our orientation
+ _orientation = orientation;
+
+ // Add our back panel
+ attachChild(_backPanel);
+
+ // Create a default data model
+ _model = new DefaultSliderModel(minValue, maxValue);
+
+ // set up our knob and attach it.
+ _knob = new UISliderKnob(this);
+ attachChild(_knob);
+
+ // Set our initial value
+ setValue(initialValue);
+
+ // Apply our skin.
+ applySkin();
+ }
+
+ /**
+ * Notifies any listeners that this slider has updated its value.
+ */
+ public void fireChangeEvent() {
+ if (!isEnabled()) {
+ return;
+ }
+
+ final ActionEvent event = new ActionEvent(this);
+ for (final ActionListener l : _listeners) {
+ l.actionPerformed(event);
+ }
+ }
+
+ /**
+ * @return our orientation.
+ */
+ public Orientation getOrientation() {
+ return _orientation;
+ }
+
+ @Override
+ public void layout() {
+ // Keep the knob sized to our content area. This lets the knob control its handle placement.
+ _knob.setLocalComponentSize(getContentWidth(), getContentHeight());
+
+ // Update the knob's relative position, based on the slider's range and value.
+ updateKnob();
+
+ // Set the backing panel's position and size based on orientation. We'll center it on the perpendicular axis.
+ if (getOrientation() == Orientation.Horizontal) {
+ _backPanel.setLocalComponentSize(getContentWidth(), _knob.getMinimumLocalComponentHeight());
+ _backPanel.setLocalXY(0, (getContentHeight() - _backPanel.getLocalComponentHeight()) / 2);
+ } else {
+ _backPanel.setLocalComponentSize(_knob.getMinimumLocalComponentWidth(), getContentHeight());
+ _backPanel.setLocalXY((getContentWidth() - _backPanel.getLocalComponentWidth()) / 2, 0);
+ }
+
+ // lay out the back panel's contents, if any.
+ _backPanel.layout();
+ }
+
+ @Override
+ public UIComponent getUIComponent(final int x, final int y) {
+ // prevent picking when disabled.
+ if (!isEnabled()) {
+ return null;
+ }
+
+ return super.getUIComponent(x, y);
+ }
+
+ @Override
+ public void updateMinimumSizeFromContents() {
+ super.updateMinimumSizeFromContents();
+
+ // Our size may have have changed, so force an update of the knob's position.
+ updateKnob();
+ }
+
+ /**
+ * Set the value on this slider
+ *
+ * @param value
+ * the new value. Clamps between min and max values.
+ */
+ public void setValue(final int value) {
+ _model.setCurrentValue(value, this);
+ updateKnob();
+ }
+
+ /**
+ * Update our knob's position.
+ */
+ private void updateKnob() {
+ if ((float) (_model.getMaxValue() - _model.getMinValue()) != 0) {
+ _knob.setPosition(_model.getCurrentValue() / (float) (_model.getMaxValue() - _model.getMinValue()));
+ } else {
+ _knob.setPosition(_model.getMinValue());
+ }
+ }
+
+ /**
+ * @return the current data model's current value.
+ */
+ public int getValue() {
+ return _model.getCurrentValue();
+ }
+
+ /**
+ * @return the data model for the slider.
+ */
+ public SliderModel getModel() {
+ return _model;
+ }
+
+ /**
+ * @param model
+ * the new data model for this slider. Must not be null.
+ */
+ public void setModel(final DefaultSliderModel model) {
+ assert model != null : "model can not be null.";
+ _model = model;
+ updateKnob();
+ }
+
+ /**
+ * Add the specified listener to this slider's list of listeners notified when it has changed.
+ *
+ * @param listener
+ * the listener to add
+ */
+ public void addActionListener(final ActionListener listener) {
+ _listeners.add(listener);
+ }
+
+ /**
+ * Remove a listener from this slider's list of listeners.
+ *
+ * @param listener
+ * the listener to remove
+ * @return true if the listener was removed.
+ */
+ public boolean removeActionListener(final ActionListener listener) {
+ return _listeners.remove(listener);
+ }
+
+ /**
+ * Called by the knob when our knob is released. Snaps to the nearest value.
+ */
+ void knobReleased() {
+ if (_snapToValues) {
+ setValue(Math.round(_knob.getPosition() * (_model.getMaxValue() - _model.getMinValue())));
+ }
+ }
+
+ @Override
+ public void setEnabled(final boolean enabled) {
+ super.setEnabled(enabled);
+ _knob.setEnabled(enabled);
+ _backPanel.setEnabled(false);
+ }
+
+ /**
+ * @return the knob associated with this slider.
+ */
+ public UISliderKnob getKnob() {
+ return _knob;
+ }
+
+ /**
+ * @return the back panel associated with this slider.
+ */
+ public UIPanel getBackPanel() {
+ return _backPanel;
+ }
+
+ /**
+ * @param snap
+ * true if we snap the slider to the integer representations on mouse release.
+ */
+ public void setSnapToValues(final boolean snap) {
+ _snapToValues = snap;
+ }
+
+ /**
+ * @return true if we snap the slider to the integer representations on mouse release.
+ */
+ public boolean isSnapToValues() {
+ return _snapToValues;
+ }
+}
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UISliderKnob.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UISliderKnob.java new file mode 100644 index 0000000..8790618 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UISliderKnob.java @@ -0,0 +1,246 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui; + +import com.ardor3d.extension.ui.event.DragListener; +import com.ardor3d.input.InputState; +import com.ardor3d.input.MouseButton; +import com.ardor3d.math.MathUtils; + +/** + * Defines the knob (aka slider or scrubber) on a slider. Generally created by UISlider directly. + */ +public class UISliderKnob extends UIContainer { + + /** The current relative position of the knob handle, as a percent. */ + protected float _position = 0; + + /** The handle for our knob. Generally decorated with an icon. */ + private UILabel _knobLabel = null; + + /** The slider we are part of. */ + private UISlider _parentSlider = null; + + /** A reusable drag listener, added to the hud when we are attached. */ + private final DragListener _dragListener = new KnobDragListener(); + + /** + * Construct a new knob for the given slider. + * + * @param slider + * the parent slider. + */ + UISliderKnob(final UISlider slider) { + super(); + + // set slider + _parentSlider = slider; + + // create and attach our knob handle + _knobLabel = new UILabel(""); + _knobLabel.getSceneHints().setAllPickingHints(true); + attachChild(_knobLabel); + } + + /** + * @return the UILabel that represents the handle of the knob + */ + public UILabel getKnobLabel() { + return _knobLabel; + } + + /** + * @return the current position (as a percent) of the knob handle [0.0, 1.0] + */ + public float getPosition() { + return _position; + } + + /** + * Sets the current position of the knob handle + * + * @param newPosition + * the new position as a percent [0.0, 1.0] + */ + public void setPosition(final float newPosition) { + // ensure we are in the valid range. + assert newPosition >= 0 && newPosition <= 1 : "newPosition must be in [0f, 1f]"; + _position = newPosition; + + // Set our handles relative location using the position, our size and the size of the handle + if (_parentSlider.getOrientation() == Orientation.Horizontal) { + _knobLabel.setLocalX((int) ((getContentWidth() - _knobLabel.getLocalComponentWidth()) * _position)); + _knobLabel.setLocalY((getContentHeight() - _knobLabel.getLocalComponentHeight()) / 2); + } else { + _knobLabel.setLocalX((getContentWidth() - _knobLabel.getLocalComponentWidth()) / 2); + _knobLabel.setLocalY((int) ((getContentHeight() - _knobLabel.getLocalComponentHeight()) * _position)); + } + + // let the ui system know we've changed something. + fireComponentDirty(); + } + + @Override + public void layout() { + ; // do nothing + } + + /** + * @return the relative location (x or y) of the leading edge of the knob handle. An x value if the we are + * horizontal or a y value if we are vertical. This is used for various mouse interactions. + */ + protected int getSliderFrontEdge() { + if (_parentSlider.getOrientation() == Orientation.Horizontal) { + final int size = getLocalComponentWidth() - _knobLabel.getLocalComponentWidth(); + return Math.round(_position * size * getWorldScale().getXf()); + } else { + final int size = getLocalComponentHeight() - _knobLabel.getLocalComponentHeight(); + return Math.round(_position * size * getWorldScale().getYf()); + } + } + + @Override + public void attachedToHud() { + super.attachedToHud(); + + // Add our drag handler to the hud + getHud().addDragListener(_dragListener); + } + + @Override + public void detachedFromHud() { + super.detachedFromHud(); + + // Remove our drag listener from the hud + if (getHud() != null) { + getHud().removeDragListener(_dragListener); + } + } + + @Override + public void setEnabled(final boolean enabled) { + super.setEnabled(enabled); + + // set knob handle enabled / disabled + _knobLabel.setEnabled(enabled); + } + + /** + * Enable clicking in slider to step the knob one way or the other. + */ + @Override + public boolean mousePressed(final MouseButton button, final InputState state) { + // XXX: perhaps we should use a variable "step size"? + // XXX: perhaps allow repeating steps until mouse up? + + // skip out if not enabled + if (!UISliderKnob.this.isEnabled()) { + return false; + } + + // Get mouse location + final int mouseX = state.getMouseState().getX(); + final int mouseY = state.getMouseState().getY(); + if (!_knobLabel.insideMargin(mouseX, mouseY)) { + if (_parentSlider.getOrientation() == Orientation.Horizontal) { + final int x = mouseX - UISliderKnob.this.getHudX(); + // check which side we are on and step + if (x < getSliderFrontEdge()) { + _parentSlider.setValue(_parentSlider.getValue() - 1); + } else { + _parentSlider.setValue(_parentSlider.getValue() + 1); + } + } else { + final int y = mouseY - UISliderKnob.this.getHudY(); + + // check which side we are on and step + if (y < getSliderFrontEdge()) { + _parentSlider.setValue(_parentSlider.getValue() - 1); + } else { + _parentSlider.setValue(_parentSlider.getValue() + 1); + } + } + return true; + } + return false; + } + + /** + * Our knob handle drag listener class + */ + private class KnobDragListener implements DragListener { + private int _initialHudLoc; + private int _delta; + + public void startDrag(final int x, final int y) { + // skip out if not enabled. + if (!isEnabled()) { + return; + } + + // remember our starting hud location + if (_parentSlider.getOrientation() == Orientation.Horizontal) { + _initialHudLoc = getHudX(); + } else { + _initialHudLoc = getHudY(); + } + + // remember the current delta to the mouse + if (_parentSlider.getOrientation() == Orientation.Horizontal) { + _delta = getSliderFrontEdge() - (x - _initialHudLoc); + } else { + _delta = getSliderFrontEdge() - (y - _initialHudLoc); + } + } + + public void drag(final int x, final int y) { + if (!isEnabled()) { + return; + } + + // calculate our new handle position based on the current mouse position. + float position; + if (_parentSlider.getOrientation() == Orientation.Horizontal) { + position = (x - _initialHudLoc + _delta) + / ((getLocalComponentWidth() - _knobLabel.getLocalComponentWidth()) * getWorldScale().getXf()); + + } else { + position = (y - _initialHudLoc + _delta) + / ((getLocalComponentHeight() - _knobLabel.getLocalComponentHeight()) * getWorldScale().getYf()); + } + + // clamp to [0, 1] and assign + position = MathUtils.clamp(position, 0f, 1f); + setPosition(position); + + // set the value on the slider's model directly to avoid circular looping logic. + _parentSlider.getModel().setCurrentValue( + Math.round(getPosition() + * (_parentSlider.getModel().getMaxValue() - _parentSlider.getModel().getMinValue())), + _parentSlider); + } + + public void endDrag(final UIComponent dropOn, final int x, final int y) { + // call back to our parent slider, allowing for snapping + _parentSlider.knobReleased(); + } + + public boolean isDragHandle(final UIComponent w, final int x, final int y) { + // if not enabled, we don't slide + if (!isEnabled()) { + return false; + } + + // Our slide handle is the label. + return w.equals(_knobLabel); + } + } +} diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIState.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIState.java new file mode 100644 index 0000000..33dde5c --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIState.java @@ -0,0 +1,70 @@ +/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui;
+
+/**
+ * Used in conjunction with {@link StateBasedUIComponent} to describe the appearance and behavior of a specific
+ * component state.
+ */
+public class UIState extends UIComponent {
+
+ public UIState() {
+ setBackdrop(null);
+ setBorder(null);
+ setForegroundColor(null);
+ setMargin(null);
+ setPadding(null);
+ }
+
+ /**
+ * Applies the local characteristics of this state to the given UIComponent.
+ *
+ * @param component
+ * the UI component to apply this state to
+ */
+ public void setupAppearance(final UIComponent component) {
+ if (getBackdrop() != null) {
+ component.setBackdrop(getBackdrop());
+ }
+ if (getBorder() != null) {
+ component.setBorder(getBorder());
+ }
+ if (getLocalForegroundColor() != null) {
+ component.setForegroundColor(getLocalForegroundColor());
+ }
+ if (getMargin() != null) {
+ component.setMargin(getMargin());
+ }
+ if (getPadding() != null) {
+ component.setPadding(getPadding());
+ }
+ if (getTooltipText() != null) {
+ component.setTooltipText(getTooltipText());
+ }
+ }
+
+ /**
+ * Called right before a state loses its status as being the "current" state of a UIComponent.
+ */
+ public void release() {}
+
+ @Deprecated
+ @Override
+ public int getHudX() {
+ throw new RuntimeException("Do not call getHudX directly on a ui state. Call on associated component instead.");
+ }
+
+ @Deprecated
+ @Override
+ public int getHudY() {
+ throw new RuntimeException("Do not call getHudY directly on a ui state. Call on associated component instead.");
+ }
+}
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UITab.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UITab.java new file mode 100644 index 0000000..c793106 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UITab.java @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui; + +import com.ardor3d.extension.ui.util.SubTex; + +/** + * An extension of UIButton to be used as the tabs in a tabbed pane. Always "Selectable" (aka. toggle style) + */ +public class UITab extends UIButton { + + private final UITabbedPane.TabPlacement placement; + + /** + * Construct a new UITabe with the given label text and icon. + * + * @param label + * optional tab label + * @param icon + * optional tab text + * @param placement + * the edge or border on which this tab will be used. + */ + public UITab(final String label, final SubTex icon, final UITabbedPane.TabPlacement placement) { + super(label, icon); + this.placement = placement; + super.setSelectable(true); + super.applySkin(); + switchState(getDefaultState()); + } + + @Override + protected void applySkin() { + ; // no-op + } + + @Override + public void setSelectable(final boolean selectable) { + ; // no-op + } + + @Override + public boolean isSelectable() { + return true; + } + + /** + * @return the placement + */ + public UITabbedPane.TabPlacement getPlacement() { + return placement; + } +} diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UITabbedPane.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UITabbedPane.java new file mode 100644 index 0000000..eaf9ea5 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UITabbedPane.java @@ -0,0 +1,344 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui; + +import java.util.ArrayList; +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.ardor3d.extension.ui.event.ActionEvent; +import com.ardor3d.extension.ui.event.ActionListener; +import com.ardor3d.extension.ui.layout.BorderLayout; +import com.ardor3d.extension.ui.layout.BorderLayoutData; +import com.ardor3d.extension.ui.layout.RowLayout; +import com.ardor3d.extension.ui.layout.UILayoutData; +import com.ardor3d.extension.ui.util.ButtonGroup; +import com.ardor3d.extension.ui.util.SubTex; +import com.ardor3d.scenegraph.Spatial; + +/** + * A container similar to Swing's {@link javax.swing.JTabbedPane} in which multiple components may be contained and + * viewed one at a time using a set of navigation buttons. + */ +public class UITabbedPane extends UIPanel { + private static final Logger logger = Logger.getLogger(UITabbedPane.class.getName()); + + /** Our contents... Used instead of the normal children field because we need to track and show just one at a time. */ + private final ArrayList<UIComponent> _contents = new ArrayList<UIComponent>(); + + /** The panel containing our navigation tab buttons. */ + private final UIPanel _tabsPanel; + + /** The placement enum describing which edge to place the tab buttons on. */ + private final TabPlacement _placement; + + /** Our button group. The tabs are toggle buttons and this allows us to toggle only one at a time. */ + private final ButtonGroup _tabButtonGroup = new ButtonGroup(); + + /** The currently viewed tab index. -1 indicates no current view (empty tab pane) */ + private int _currentTabIndex = -1; + + /** Our center panel - will hold the currently viewed content item. */ + final UIPanel _center = new UIPanel(new BorderLayout()); + + /** + * Construct a new Tabbed Pane with the given tab placement. + * + * @param placement + * which edge to place the tab buttons on + */ + public UITabbedPane(final TabPlacement placement) { + super(new BorderLayout()); + + _placement = placement; + + // Setup our center content panel + _center.setLayoutData(BorderLayoutData.CENTER); + super.add(_center); + + // Create a panel that will hold our tab buttons + final RowLayout layout = new RowLayout(_placement.isHorizontal(), false, false); + _tabsPanel = new UIPanel(layout); + _tabsPanel.setLayoutData(_placement.getLayoutData()); + super.add(_tabsPanel); + + applySkin(); + } + + /** + * @return which edge we place the tab buttons on + */ + public TabPlacement getTabPlacement() { + return _placement; + } + + /** + * @return the index of the currently viewed tab or -1 if nothing is currently viewed. + */ + public int getCurrentTab() { + return _currentTabIndex; + } + + /** + * @param index + * @return the tab button at the given index. + */ + public UITab getTabButton(final int index) { + return getTabs().get(index); + } + + /** + * @param index + * @return the component contents for the given tab index. + */ + public UIComponent getTabContents(final int index) { + return _contents.get(index); + } + + @Override + public void layout() { + super.layout(); + + // Make sure all of our visible and non-visible contents are properly resized. + if (_contents != null) { + for (int x = 0, max = _contents.size(); x < max; x++) { + final Spatial child = _contents.get(x); + if (child instanceof UIComponent) { + final UIComponent comp = (UIComponent) child; + comp.setLocalComponentSize(getViewedComponent().getLocalComponentWidth(), getViewedComponent() + .getLocalComponentHeight()); + comp.layout(); + } + } + } + } + + /** + * @return the number of components/tabs in this tabbed pane. + */ + public int getTabCount() { + return _contents.size(); + } + + /** + * @return the currently viewed tab's component. If no component is viewed, null is returned. + */ + public UIComponent getViewedComponent() { + if (_currentTabIndex >= _contents.size()) { + _currentTabIndex = -1; + } + if (_currentTabIndex < 0) { + return null; + } + return _contents.get(_currentTabIndex); + } + + /** + * Adds the given component to this tabbed pane with no icon and "unnamed" as the tab label. + */ + @Override + public void add(final UIComponent component) { + add(component, "unnamed", null); + } + + /** + * Adds the given component to this tabbed pane using the given tab label text and no icon. + * + * @param component + * the component to add + * @param label + * the text of the tab label + */ + public void add(final UIComponent component, final String label) { + add(component, label, null); + } + + /** + * Adds the given component to this tabbed pane using the given tab label text and icon. + * + * @param component + * the component to add + * @param label + * the text of the tab label + * @param icon + * the icon of the tab label + */ + public void add(final UIComponent component, final String label, final SubTex icon) { + if (component == null) { + UITabbedPane.logger.log(Level.WARNING, "Can not add a null component to a TabbedPane."); + return; + } + + // make sure the component uses center layout position + component.setLayoutData(BorderLayoutData.CENTER); + + // add our component to the local tracking + _contents.add(component); + + // Make our new tab and add it to the tab panel + final UITab tab = makeTab(label, icon); + _tabsPanel.add(tab); + + // Set as viewed, if this is our only tab + if (_contents.size() == 1) { + setCurrentTab(0); + } + } + + /** + * Remove the tab at the given tab index. + * + * @param index + * the tab index + */ + public void removeTab(final int index) { + int newIndex = _currentTabIndex; + + // clear the panel if removing the current tab + if (index == _currentTabIndex) { + clearViewedComponent(); + } + + // Remove the tab and contents for this index. + final ArrayList<UITab> tabs = getTabs(); + _tabsPanel.remove(tabs.get(index)); + _contents.remove(index); + + // If our previously viewed tab was above the removed index, or we were at the end of the stack, decrement to + // keep us on the same tab. + if (_currentTabIndex > index || newIndex >= _contents.size()) { + newIndex--; + } + + // If our new potential viewed index is valid, set it as the index + if (newIndex >= 0) { + setCurrentTab(newIndex); + } else { + // otherwise just fire that we're dirty. + fireComponentDirty(); + } + } + + /** + * Set the currently viewed component to the one associated with the given tab. + * + * @param tab + * the tab + */ + public void setCurrentTab(final UITab tab) { + setCurrentTab(getTabs().indexOf(tab)); + } + + /** + * Set the currently viewed component to the one at the given tab index. + * + * @param index + * the tab index + */ + public void setCurrentTab(final int index) { + if (index > _contents.size() || index < 0) { + throw new IndexOutOfBoundsException("" + index); + } + _currentTabIndex = index; + + // clear the current contents + clearViewedComponent(); + + // set our new contents + final UIComponent centerComp = _contents.get(_currentTabIndex); + centerComp.setLayoutData(BorderLayoutData.CENTER); + _center.add(centerComp); + + // Update our buttons + final ArrayList<UITab> buttons = getTabs(); + for (int x = buttons.size(); --x >= 0;) { + buttons.get(x).setSelected(x == _currentTabIndex); + } + + // resize and layout + updateMinimumSizeFromContents(); + layout(); + } + + /** + * @return an array of tabs from our tab panel. + */ + private ArrayList<UITab> getTabs() { + final ArrayList<UITab> buttons = new ArrayList<UITab>(); + for (int x = 0, max = _tabsPanel.getNumberOfChildren(); x < max; x++) { + final Spatial spat = _tabsPanel.getChild(x); + if (spat instanceof UITab) { + buttons.add((UITab) spat); + } + } + return buttons; + } + + /** + * Remove the currently viewed component from view. Usually the is done in preparation for setting a new view. + */ + private void clearViewedComponent() { + _center.removeAllComponents(); + } + + /** + * Make our tab button using the given label text and icon. + * + * @param label + * optional label text + * @param icon + * optional label icon + * @return the new UITab + */ + private UITab makeTab(final String label, final SubTex icon) { + final UITab button = new UITab(label, icon, _placement); + button.addActionListener(new ActionListener() { + public void actionPerformed(final ActionEvent event) { + setCurrentTab(button); + } + }); + _tabButtonGroup.add(button); + return button; + } + + /** + * An enum describing the edge on which to place tab buttons. + */ + public enum TabPlacement { + /** Place tabs along top edge of pane. */ + NORTH(BorderLayoutData.NORTH, true), + + /** Place tabs along bottom edge of pane. */ + SOUTH(BorderLayoutData.SOUTH, true), + + /** Place tabs along right edge of pane. */ + EAST(BorderLayoutData.EAST, false), + + /** Place tabs along left edge of pane. */ + WEST(BorderLayoutData.WEST, false); + + private final UILayoutData _layoutData; + private final boolean _horizontal; + + TabPlacement(final BorderLayoutData layData, final boolean horizontal) { + _layoutData = layData; + _horizontal = horizontal; + } + + UILayoutData getLayoutData() { + return _layoutData; + } + + public boolean isHorizontal() { + return _horizontal; + } + } +} diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UITextArea.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UITextArea.java new file mode 100644 index 0000000..ebf9cdb --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UITextArea.java @@ -0,0 +1,194 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui; + +import com.ardor3d.extension.ui.text.DefaultLatinTextAreaKeyHandler; +import com.ardor3d.extension.ui.text.TextSelection.SelectionState; +import com.ardor3d.extension.ui.text.UIKeyHandler; +import com.ardor3d.extension.ui.util.Alignment; +import com.ardor3d.input.InputState; +import com.ardor3d.input.Key; +import com.ardor3d.input.MouseButton; +import com.ardor3d.math.Rectangle2; +import com.ardor3d.math.Transform; +import com.ardor3d.math.Vector3; +import com.ardor3d.renderer.Renderer; + +public class UITextArea extends AbstractUITextEntryComponent { + + /** A store for the clip rectangle. */ + private final Rectangle2 _clipRectangleStore = new Rectangle2(); + + protected UIKeyHandler _keyHandler; + + public UITextArea() { + setAlignment(Alignment.TOP_LEFT); + _disabledState = new UIState(); + _defaultState = new DefaultTextEntryState(); + _writingState = new TextAreaWritingState(); + setEditable(true); + applySkin(); + switchState(getDefaultState()); + } + + /** + * Delete any currently selected text. + */ + public void deleteSelectedText() { + if (_selection.getSelectionLength() != 0) { + final String text = getText(); + final int sIndex = _selection.getStartIndex(); + final int eIndex = _selection.getEndIndex(); + if (sIndex >= 0 && sIndex <= text.length() && eIndex >= 0 && eIndex <= text.length()) { + setText(text.substring(0, sIndex) + text.substring(eIndex)); + } + } + } + + @Override + protected UIKeyHandler getKeyHandler() { + if (_keyHandler == null) { + _keyHandler = new DefaultLatinTextAreaKeyHandler(this); + } + return _keyHandler; + } + + public void setKeyHandler(final UIKeyHandler handler) { + _keyHandler = handler; + } + + @Override + protected void drawComponent(final Renderer r) { + // figure out our offsets using alignment and edge info + final double x = _alignment.alignX(getContentWidth(), _uiText != null ? _uiText.getWidth() : 1) + + getTotalLeft(); + final double y = _alignment.alignY(getContentHeight(), _uiText != null ? _uiText.getHeight() : 1) + + getTotalBottom(); + + // Draw our text, if we have any + if (_uiText != null) { + final String text = getText(); + if (text.length() > 0) { + // set our text location + final Vector3 v = Vector3.fetchTempInstance(); + // note: we round to get the text pixel aligned... otherwise it can get blurry + v.set(Math.round(x), Math.round(y), 0); + final Transform t = Transform.fetchTempInstance(); + t.set(getWorldTransform()); + t.applyForwardVector(v); + t.translate(v); + Vector3.releaseTempInstance(v); + _uiText.setWorldTransform(t); + Transform.releaseTempInstance(t); + + // draw the selection first + if (getSelection().getSelectionLength() > 0) { + getSelection().draw(r, t); + } + + // draw text using current foreground color and alpha. + // TODO: alpha of text... + final boolean needsPop = getWorldRotation().isIdentity(); + if (needsPop) { + _clipRectangleStore.set(getHudX() + getTotalLeft(), getHudY() + getTotalBottom(), + getContentWidth(), getContentHeight()); + r.pushClip(_clipRectangleStore); + } + _uiText.render(r); + if (needsPop) { + r.popClip(); + } + } + } + + // Draw our caret, if we have one. + if (isCopyable() && isEditable() && getCurrentState().equals(_writingState) && getCaret().isShowing()) { + getCaret().draw(r, this, + _uiText != null ? _uiText.getLineHeight(getCaretPosition()) : UIComponent.getDefaultFontSize(), x, + y); + } + } + + public class TextAreaWritingState extends UIState { + @Override + public boolean keyReleased(final Key key, final InputState state) { + return getKeyHandler().keyReleased(key, state); + } + + @Override + public boolean keyPressed(final Key key, final InputState state) { + return getKeyHandler().keyPressed(key, state); + } + + @Override + public boolean keyHeld(final Key key, final InputState state) { + return getKeyHandler().keyHeld(key, state); + } + + @Override + public void mouseEntered(final int mouseX, final int mouseY, final InputState state) { + // TODO: set cursor to text entry + } + + @Override + public void mouseDeparted(final int mouseX, final int mouseY, final InputState state) { + // TODO: set cursor to default + } + + @Override + public boolean mousePressed(final MouseButton button, final InputState state) { + final int x = state.getMouseState().getX() - UITextArea.this.getHudX() + - UITextArea.this.getPadding().getLeft(); + final int y = state.getMouseState().getY() - UITextArea.this.getHudY() + - UITextArea.this.getPadding().getBottom(); + + if (_uiText != null) { + final int position = _uiText.findCaretPosition(x, y); + if (isCopyable() && state.getKeyboardState().isAtLeastOneDown(Key.LSHIFT, Key.RSHIFT)) { + _selection.checkStart(); + if (_selection.getState() == SelectionState.AT_START_OF_SELECTION) { + if (position <= _selection.getEndIndex()) { + _selection.setStartIndex(position); + } else { + final int oldEnd = _selection.getEndIndex(); + _selection.setEndIndex(position); + _selection.setStartIndex(oldEnd); + _selection.setState(SelectionState.AT_END_OF_SELECTION); + } + } else { + if (position >= _selection.getStartIndex()) { + _selection.setEndIndex(position); + } else { + final int oldStart = _selection.getStartIndex(); + _selection.setStartIndex(position); + _selection.setEndIndex(oldStart); + _selection.setState(SelectionState.AT_START_OF_SELECTION); + } + } + } else { + // clear any getSelection() + clearSelection(); + } + setCaretPosition(position); + } else { + setCaretPosition(0); + } + + return true; + } + + @Override + public void lostFocus() { + switchState(_defaultState); + getSelection().setStartIndex(-1); + } + } +} diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UITextField.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UITextField.java new file mode 100644 index 0000000..3a70e1f --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UITextField.java @@ -0,0 +1,265 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui; + +import java.util.ArrayList; +import java.util.List; + +import com.ardor3d.extension.ui.event.ActionEvent; +import com.ardor3d.extension.ui.event.ActionListener; +import com.ardor3d.extension.ui.text.DefaultLatinTextFieldKeyHandler; +import com.ardor3d.extension.ui.text.UIKeyHandler; +import com.ardor3d.extension.ui.text.TextSelection.SelectionState; +import com.ardor3d.input.InputState; +import com.ardor3d.input.Key; +import com.ardor3d.input.MouseButton; +import com.ardor3d.math.Rectangle2; +import com.ardor3d.math.Transform; +import com.ardor3d.math.Vector2; +import com.ardor3d.math.Vector3; +import com.ardor3d.renderer.Renderer; + +public class UITextField extends AbstractUITextEntryComponent { + protected final Vector2 _caretLoc = new Vector2(); + // tracking variable for dirty use only + private boolean _caretIsShowing = false; + private UIKeyHandler _keyHandler; + + /** A store for the clip rectangle. */ + private final Rectangle2 _clipRectangleStore = new Rectangle2(); + + /** List of action listeners notified when the enter key is pressed. */ + private final List<ActionListener> _listeners = new ArrayList<ActionListener>(); + + public UITextField() { + _disabledState = new UIState(); + _defaultState = new DefaultTextEntryState(); + _writingState = new TextFieldWritingState(); + setEditable(true); + applySkin(); + switchState(getDefaultState()); + } + + @Override + public int setCaretPosition(final int index) { + super.setCaretPosition(index); + + if (_uiText != null) { + _uiText.findCaretTranslation(getCaretPosition(), _caretLoc); + getCaret().setPosX(Math.round(_caretLoc.getXf())); + getCaret().setPosY(Math.round(_caretLoc.getYf())); + } else { + getCaret().setPosX(0); + getCaret().setPosY(0); + } + return _caretPosition; + } + + /** + * Delete any currently selected text. + */ + public void deleteSelectedText() { + if (_selection.getSelectionLength() != 0) { + final String text = getText(); + final int sIndex = _selection.getStartIndex(); + final int eIndex = _selection.getEndIndex(); + if (sIndex >= 0 && sIndex <= text.length() && eIndex >= 0 && eIndex <= text.length()) { + setText(text.substring(0, sIndex) + text.substring(eIndex)); + } + } + } + + @Override + protected UIKeyHandler getKeyHandler() { + if (_keyHandler == null) { + _keyHandler = new DefaultLatinTextFieldKeyHandler(this); + } + return _keyHandler; + } + + public void setKeyHandler(final UIKeyHandler handler) { + _keyHandler = handler; + } + + /** + * Add the specified listener to this button's list of listeners notified when pressed. + * + * @param listener + */ + public void addActionListener(final ActionListener listener) { + _listeners.add(listener); + } + + /** + * Remove the given listener from the notification list. + * + * @param listener + */ + public boolean removeActionListener(final ActionListener listener) { + return _listeners.remove(listener); + } + + /** + * Removes all of this button's listeners from notification list. + */ + public void removeAllListeners() { + _listeners.clear(); + } + + /** + * Notifies all of this field's registered listeners + */ + public void fireActionEvent() { + if (!isEnabled()) { + return; + } + final ActionEvent event = new ActionEvent(this); + for (final ActionListener l : _listeners) { + l.actionPerformed(event); + } + } + + @Override + public void updateGeometricState(final double time, final boolean initiator) { + if (getCurrentState().equals(_writingState) && _caretIsShowing != getCaret().isShowing()) { + fireComponentDirty(); + _caretIsShowing = !_caretIsShowing; + } + super.updateGeometricState(time, initiator); + } + + @Override + protected void drawComponent(final Renderer r) { + // figure out our offsets using alignment and edge info + final double x = _alignment.alignX(getContentWidth(), _uiText != null ? _uiText.getWidth() : 1) + + getTotalLeft(); + final double y = _alignment.alignY(getContentHeight(), _uiText != null ? _uiText.getHeight() : 1) + + getTotalBottom(); + + // Draw our text, if we have any + if (_uiText != null) { + final String text = getText(); + if (text.length() > 0) { + // set our text location + final Vector3 v = Vector3.fetchTempInstance(); + // note: we round to get the text pixel aligned... otherwise it can get blurry + v.set(Math.round(x), Math.round(y), 0); + final Transform t = Transform.fetchTempInstance(); + t.set(getWorldTransform()); + t.applyForwardVector(v); + t.translate(v); + Vector3.releaseTempInstance(v); + _uiText.setWorldTransform(t); + Transform.releaseTempInstance(t); + + // draw the selection first + if (getSelection().getSelectionLength() > 0) { + getSelection().draw(r, t); + } + + // draw text using current foreground color and alpha. + // TODO: alpha of text... + final boolean needsPop = getWorldRotation().isIdentity(); + if (needsPop) { + _clipRectangleStore.set(getHudX() + getTotalLeft(), getHudY() + getTotalBottom(), + getContentWidth(), getContentHeight()); + r.pushClip(_clipRectangleStore); + } + _uiText.render(r); + if (needsPop) { + r.popClip(); + } + } + } + + // Draw our caret, if we have one. + if (isEditable() && getCurrentState().equals(_writingState) && getCaret().isShowing()) { + getCaret().draw(r, this, + _uiText != null ? _uiText.getLineHeight(getCaretPosition()) : UIComponent.getDefaultFontSize(), x, + y); + } + } + + public class TextFieldWritingState extends UIState { + @Override + public boolean keyReleased(final Key key, final InputState state) { + return getKeyHandler().keyReleased(key, state); + } + + @Override + public boolean keyPressed(final Key key, final InputState state) { + return getKeyHandler().keyPressed(key, state); + } + + @Override + public boolean keyHeld(final Key key, final InputState state) { + return getKeyHandler().keyHeld(key, state); + } + + @Override + public void mouseEntered(final int mouseX, final int mouseY, final InputState state) { + // TODO: set cursor to text entry + } + + @Override + public void mouseDeparted(final int mouseX, final int mouseY, final InputState state) { + // TODO: set cursor to default + } + + @Override + public boolean mousePressed(final MouseButton button, final InputState state) { + final int x = state.getMouseState().getX() - UITextField.this.getHudX() + - UITextField.this.getPadding().getLeft(); + final int y = state.getMouseState().getY() - UITextField.this.getHudY() + - UITextField.this.getPadding().getBottom(); + + if (_uiText != null) { + final int position = _uiText.findCaretPosition(x, y); + if (isCopyable() && state.getKeyboardState().isAtLeastOneDown(Key.LSHIFT, Key.RSHIFT)) { + _selection.checkStart(); + if (_selection.getState() == SelectionState.AT_START_OF_SELECTION) { + if (position <= _selection.getEndIndex()) { + _selection.setStartIndex(position); + } else { + final int oldEnd = _selection.getEndIndex(); + _selection.setEndIndex(position); + _selection.setStartIndex(oldEnd); + _selection.setState(SelectionState.AT_END_OF_SELECTION); + } + } else { + if (position >= _selection.getStartIndex()) { + _selection.setEndIndex(position); + } else { + final int oldStart = _selection.getStartIndex(); + _selection.setStartIndex(position); + _selection.setEndIndex(oldStart); + _selection.setState(SelectionState.AT_START_OF_SELECTION); + } + } + } else { + // clear any getSelection() + clearSelection(); + } + setCaretPosition(position); + } else { + setCaretPosition(0); + } + + return true; + } + + @Override + public void lostFocus() { + switchState(_defaultState); + getSelection().setStartIndex(-1); + } + } +} diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UITooltip.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UITooltip.java new file mode 100644 index 0000000..4bbc868 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UITooltip.java @@ -0,0 +1,47 @@ +/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui;
+
+
+/**
+ * Defines a component used by the hud to display floating tool tips.
+ */
+public class UITooltip extends FloatingUIContainer {
+
+ private final AbstractLabelUIComponent _label;
+
+ /**
+ * Construct a new UITooltip.
+ */
+ public UITooltip() {
+ // setup our text label
+ _label = new UILabel("");
+ getContentPanel().add(_label);
+
+ // initially this is not visible
+ setVisible(false);
+
+ applySuperSkin();
+ }
+
+ /**
+ * @return the label used to display tips.
+ */
+ public AbstractLabelUIComponent getLabel() {
+ return _label;
+ }
+
+ @Override
+ public UIComponent getUIComponent(final int hudX, final int hudY) {
+ // We don't want the tool tip to be "pickable", so always return null.
+ return null;
+ }
+}
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/backdrop/EmptyBackdrop.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/backdrop/EmptyBackdrop.java new file mode 100644 index 0000000..58b1a08 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/backdrop/EmptyBackdrop.java @@ -0,0 +1,27 @@ +/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui.backdrop;
+
+import com.ardor3d.extension.ui.UIComponent;
+import com.ardor3d.renderer.Renderer;
+
+/**
+ * A simple backdrop that does not alter the content area.
+ */
+public class EmptyBackdrop extends UIBackdrop {
+ public EmptyBackdrop() {}
+
+ @Override
+ public void draw(final Renderer renderer, final UIComponent comp) {
+ // We did not affect the content area, so set it as "virgin"
+ comp.setVirginContentArea(true);
+ }
+}
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/backdrop/GradientBackdrop.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/backdrop/GradientBackdrop.java new file mode 100644 index 0000000..463a0c9 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/backdrop/GradientBackdrop.java @@ -0,0 +1,164 @@ +/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui.backdrop;
+
+import com.ardor3d.extension.ui.UIComponent;
+import com.ardor3d.math.ColorRGBA;
+import com.ardor3d.math.Transform;
+import com.ardor3d.math.Vector3;
+import com.ardor3d.math.type.ReadOnlyColorRGBA;
+import com.ardor3d.renderer.IndexMode;
+import com.ardor3d.renderer.Renderer;
+import com.ardor3d.renderer.state.BlendState;
+import com.ardor3d.renderer.state.BlendState.DestinationFunction;
+import com.ardor3d.renderer.state.BlendState.SourceFunction;
+import com.ardor3d.scenegraph.Mesh;
+import com.ardor3d.util.geom.BufferUtils;
+
+/**
+ * A gradient four color backdrop. Each corner can be a different color and it will be blended across the background.
+ */
+public class GradientBackdrop extends UIBackdrop {
+
+ private final ColorRGBA _topLeft = new ColorRGBA(ColorRGBA.LIGHT_GRAY);
+ private final ColorRGBA _topRight = new ColorRGBA(ColorRGBA.GRAY);
+ private final ColorRGBA _bottomLeft = new ColorRGBA(ColorRGBA.GRAY);
+ private final ColorRGBA _bottomRight = new ColorRGBA(ColorRGBA.DARK_GRAY);
+
+ private static Mesh _mesh = GradientBackdrop.createMesh();
+ private static final float[] _vals = new float[12];
+ private static final float[] _cVals = new float[16];
+
+ /**
+ * Construct this back drop, using default colors.
+ */
+ public GradientBackdrop() {}
+
+ /**
+ * Construct this back drop, using the given corner colors.
+ *
+ * @param topLeft
+ * @param topRight
+ * @param bottomLeft
+ * @param bottomRight
+ */
+ public GradientBackdrop(final ReadOnlyColorRGBA topLeft, final ReadOnlyColorRGBA topRight,
+ final ReadOnlyColorRGBA bottomLeft, final ReadOnlyColorRGBA bottomRight) {
+ setTopLeft(topLeft);
+ setTopRight(topRight);
+ setBottomLeft(bottomLeft);
+ setBottomRight(bottomRight);
+ }
+
+ public ReadOnlyColorRGBA getBottomLeft() {
+ return _bottomLeft;
+ }
+
+ public void setBottomLeft(final ReadOnlyColorRGBA color) {
+ _bottomLeft.set(color);
+ }
+
+ public ReadOnlyColorRGBA getBottomRight() {
+ return _bottomRight;
+ }
+
+ public void setBottomRight(final ReadOnlyColorRGBA color) {
+ _bottomRight.set(color);
+ }
+
+ public ReadOnlyColorRGBA getTopLeft() {
+ return _topLeft;
+ }
+
+ public void setTopLeft(final ReadOnlyColorRGBA color) {
+ _topLeft.set(color);
+ }
+
+ public ReadOnlyColorRGBA getTopRight() {
+ return _topRight;
+ }
+
+ public void setTopRight(final ReadOnlyColorRGBA color) {
+ _topRight.set(color);
+ }
+
+ @Override
+ public void draw(final Renderer renderer, final UIComponent comp) {
+
+ final float pAlpha = UIComponent.getCurrentOpacity();
+
+ final Vector3 v = Vector3.fetchTempInstance();
+ v.set(comp.getMargin().getLeft() + comp.getBorder().getLeft(), comp.getMargin().getBottom()
+ + comp.getBorder().getBottom(), 0);
+
+ final Transform t = Transform.fetchTempInstance();
+ t.set(comp.getWorldTransform());
+ t.applyForwardVector(v);
+ t.translate(v);
+ Vector3.releaseTempInstance(v);
+
+ GradientBackdrop._mesh.setWorldTransform(t);
+ Transform.releaseTempInstance(t);
+
+ final int width = UIBackdrop.getBackdropWidth(comp);
+ final int height = UIBackdrop.getBackdropHeight(comp);
+
+ GradientBackdrop._vals[0] = 0;
+ GradientBackdrop._vals[1] = 0;
+ GradientBackdrop._vals[3] = width;
+ GradientBackdrop._vals[4] = 0;
+ GradientBackdrop._vals[6] = width;
+ GradientBackdrop._vals[7] = height;
+ GradientBackdrop._vals[9] = 0;
+ GradientBackdrop._vals[10] = height;
+
+ GradientBackdrop._cVals[0] = _bottomLeft.getRed();
+ GradientBackdrop._cVals[1] = _bottomLeft.getGreen();
+ GradientBackdrop._cVals[2] = _bottomLeft.getBlue();
+ GradientBackdrop._cVals[3] = _bottomLeft.getAlpha() * pAlpha;
+ GradientBackdrop._cVals[4] = _bottomRight.getRed();
+ GradientBackdrop._cVals[5] = _bottomRight.getGreen();
+ GradientBackdrop._cVals[6] = _bottomRight.getBlue();
+ GradientBackdrop._cVals[7] = _bottomRight.getAlpha() * pAlpha;
+ GradientBackdrop._cVals[8] = _topRight.getRed();
+ GradientBackdrop._cVals[9] = _topRight.getGreen();
+ GradientBackdrop._cVals[10] = _topRight.getBlue();
+ GradientBackdrop._cVals[11] = _topRight.getAlpha() * pAlpha;
+ GradientBackdrop._cVals[12] = _topLeft.getRed();
+ GradientBackdrop._cVals[13] = _topLeft.getGreen();
+ GradientBackdrop._cVals[14] = _topLeft.getBlue();
+ GradientBackdrop._cVals[15] = _topLeft.getAlpha() * pAlpha;
+
+ GradientBackdrop._mesh.getMeshData().getVertexBuffer().rewind();
+ GradientBackdrop._mesh.getMeshData().getVertexBuffer().put(GradientBackdrop._vals);
+
+ GradientBackdrop._mesh.getMeshData().getColorBuffer().rewind();
+ GradientBackdrop._mesh.getMeshData().getColorBuffer().put(GradientBackdrop._cVals);
+
+ GradientBackdrop._mesh.render(renderer);
+ }
+
+ private static Mesh createMesh() {
+ final Mesh mesh = new Mesh();
+ mesh.getMeshData().setVertexBuffer(BufferUtils.createVector3Buffer(4));
+ mesh.getMeshData().setColorBuffer(BufferUtils.createColorBuffer(4));
+ mesh.getMeshData().setIndexMode(IndexMode.TriangleFan);
+
+ final BlendState blend = new BlendState();
+ blend.setBlendEnabled(true);
+ blend.setSourceFunction(SourceFunction.SourceAlpha);
+ blend.setDestinationFunction(DestinationFunction.OneMinusSourceAlpha);
+ mesh.setRenderState(blend);
+ mesh.updateWorldRenderStates(false);
+
+ return mesh;
+ }
+}
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/backdrop/ImageBackdrop.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/backdrop/ImageBackdrop.java new file mode 100644 index 0000000..2cbb8c1 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/backdrop/ImageBackdrop.java @@ -0,0 +1,194 @@ +/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui.backdrop;
+
+import java.util.Arrays;
+
+import com.ardor3d.extension.ui.UIComponent;
+import com.ardor3d.extension.ui.util.Alignment;
+import com.ardor3d.extension.ui.util.SubTex;
+import com.ardor3d.extension.ui.util.SubTexUtil;
+import com.ardor3d.math.ColorRGBA;
+import com.ardor3d.math.type.ReadOnlyColorRGBA;
+import com.ardor3d.renderer.Renderer;
+
+/**
+ * This backdrop paints a single image on a colored plane behind the component, stretching it and aligning it to the
+ * component based on given settings.
+ */
+public class ImageBackdrop extends SolidBackdrop {
+
+ public enum StretchAxis {
+ /** Stretch the image on both axis */
+ Both,
+ /** Stretch the image on the horizontal axis */
+ Horizontal,
+ /** Stretch the image on the vertical axis */
+ Vertical,
+ /** Do not stretch the image */
+ None;
+ }
+
+ /** The image to draw. */
+ protected SubTex _image = null;
+ /** The axis to stretch the image on. */
+ protected StretchAxis _axis = StretchAxis.Both;
+ /** The alignment (to the component) to align the image to. */
+ protected Alignment _alignment = Alignment.MIDDLE;
+
+ /** used internally to hold component measurements prior to drawing backdrop */
+ protected final double[] _dims = new double[4];
+
+ /** Used to tint the image drawn by this backdrop. */
+ private final ColorRGBA _tintColor = new ColorRGBA(1, 1, 1, 1);
+
+ /**
+ * Construct this back drop, using the given image.
+ *
+ * @param image
+ */
+ public ImageBackdrop(final SubTex image) {
+ super(ColorRGBA.BLACK_NO_ALPHA);
+ setImage(image);
+ }
+
+ /**
+ * Construct this back drop, using the given image and color.
+ *
+ * @param image
+ * the image to draw
+ * @param color
+ * the color of the backdrop
+ */
+ public ImageBackdrop(final SubTex image, final ReadOnlyColorRGBA color) {
+ super(color);
+ setImage(image);
+ }
+
+ @Override
+ public void draw(final Renderer renderer, final UIComponent comp) {
+ super.draw(renderer, comp);
+
+ getDimensions(comp, _dims);
+ double x = _dims[0];
+ double y = _dims[1];
+ final double width = _dims[2];
+ final double height = _dims[3];
+
+ x += comp.getMargin().getLeft() + comp.getBorder().getLeft();
+ y += comp.getMargin().getBottom() + comp.getBorder().getBottom();
+
+ SubTexUtil.drawSubTex(renderer, _image, x, y, width, height, comp.getWorldTransform(), getTintColor());
+ }
+
+ public void getDimensions(final UIComponent comp, final double[] vals) {
+
+ final double bgwidth = UIBackdrop.getBackdropWidth(comp);
+ final double bgheight = UIBackdrop.getBackdropHeight(comp);
+
+ Arrays.fill(vals, 0);
+ switch (_axis) {
+ case Both:
+ vals[2] = bgwidth;
+ vals[3] = bgheight;
+ break;
+ case None:
+ case Horizontal:
+ case Vertical:
+ if (_axis.equals(StretchAxis.Horizontal)) {
+ vals[2] = bgwidth;
+ } else {
+ vals[2] = _image.getWidth();
+ }
+
+ if (_axis.equals(StretchAxis.Vertical)) {
+ vals[3] = bgheight;
+ } else {
+ vals[3] = _image.getHeight();
+ }
+
+ if (!_axis.equals(StretchAxis.Horizontal)) {
+ switch (_alignment) {
+ case TOP:
+ case MIDDLE:
+ case BOTTOM:
+ vals[0] = bgwidth / 2 - _image.getWidth() / 2;
+ break;
+ case TOP_RIGHT:
+ case RIGHT:
+ case BOTTOM_RIGHT:
+ vals[0] = bgwidth - _image.getWidth();
+ break;
+ case TOP_LEFT:
+ case LEFT:
+ case BOTTOM_LEFT:
+ vals[0] = 0;
+ }
+ }
+
+ if (!_axis.equals(StretchAxis.Vertical)) {
+ switch (_alignment) {
+ case TOP_LEFT:
+ case TOP:
+ case TOP_RIGHT:
+ vals[1] = bgheight - _image.getHeight();
+ break;
+ case LEFT:
+ case MIDDLE:
+ case RIGHT:
+ vals[1] = bgheight / 2 - _image.getHeight() / 2;
+ break;
+ case BOTTOM_LEFT:
+ case BOTTOM:
+ case BOTTOM_RIGHT:
+ vals[1] = 0;
+ }
+ }
+ }
+ }
+
+ public SubTex getImage() {
+ return _image;
+ }
+
+ public void setImage(final SubTex image) {
+ _image = image;
+ }
+
+ public StretchAxis getStretch() {
+ return _axis;
+ }
+
+ public void setStretch(final StretchAxis axis) {
+ _axis = axis;
+ }
+
+ public Alignment getAlignment() {
+ return _alignment;
+ }
+
+ public void setAlignment(final Alignment alignment) {
+ _alignment = alignment;
+ }
+
+ public ReadOnlyColorRGBA getTintColor() {
+ return _tintColor;
+ }
+
+ /**
+ * Sets a color to use for tinting the backdrop.
+ *
+ * @param color
+ */
+ public void setTintColor(final ReadOnlyColorRGBA color) {
+ _tintColor.set(color);
+ }
+}
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/backdrop/MultiImageBackdrop.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/backdrop/MultiImageBackdrop.java new file mode 100644 index 0000000..4b1dd25 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/backdrop/MultiImageBackdrop.java @@ -0,0 +1,122 @@ +/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui.backdrop;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import com.ardor3d.extension.ui.UIComponent;
+import com.ardor3d.extension.ui.util.SubTexUtil;
+import com.ardor3d.extension.ui.util.TransformedSubTex;
+import com.ardor3d.math.ColorRGBA;
+import com.ardor3d.math.type.ReadOnlyColorRGBA;
+import com.ardor3d.renderer.Renderer;
+
+/**
+ * This backdrop paints one or more transformable, ordered images on a colored plane behind the component.
+ */
+public class MultiImageBackdrop extends SolidBackdrop {
+
+ /** The image(s) to draw. */
+ private final List<TransformedSubTex> _images = new ArrayList<TransformedSubTex>();
+
+ /**
+ * Construct this back drop, using the default, no alpha backdrop color.
+ */
+ public MultiImageBackdrop() {
+ this(ColorRGBA.BLACK_NO_ALPHA);
+ }
+
+ /**
+ * Construct this back drop, using the given backdrop color.
+ *
+ * @param backDropColor
+ * the color of the backdrop
+ */
+ public MultiImageBackdrop(final ReadOnlyColorRGBA backDropColor) {
+ super(backDropColor);
+ }
+
+ public void addImage(final TransformedSubTex entry) {
+ _images.add(entry);
+ }
+
+ public boolean removeImage(final TransformedSubTex entry) {
+ return _images.remove(entry);
+ }
+
+ public List<TransformedSubTex> getImages() {
+ return _images;
+ }
+
+ @Override
+ public void draw(final Renderer renderer, final UIComponent comp) {
+ super.draw(renderer, comp);
+
+ if (_images.size() > 1) {
+ Collections.sort(_images);
+ }
+
+ final double bgwidth = UIBackdrop.getBackdropWidth(comp);
+ final double bgheight = UIBackdrop.getBackdropHeight(comp);
+
+ final double[] store = new double[2];
+ for (final TransformedSubTex entry : _images) {
+
+ MultiImageBackdrop.getDimensions(entry, comp, bgwidth, bgheight, store);
+
+ store[0] += comp.getMargin().getLeft() + comp.getBorder().getLeft();
+ store[1] += comp.getMargin().getBottom() + comp.getBorder().getBottom();
+
+ SubTexUtil.drawTransformedSubTex(renderer, entry, (int) Math.round(store[0]), (int) Math.round(store[1]),
+ entry.getWidth(), entry.getHeight(), false, comp.getWorldTransform());
+ }
+ }
+
+ public static void getDimensions(final TransformedSubTex entry, final UIComponent comp, final double bgwidth,
+ final double bgheight, final double[] store) {
+
+ switch (entry.getAlignment()) {
+ case TOP:
+ case MIDDLE:
+ case BOTTOM:
+ store[0] = bgwidth / 2;
+ break;
+ case TOP_RIGHT:
+ case RIGHT:
+ case BOTTOM_RIGHT:
+ store[0] = bgwidth;
+ break;
+ case TOP_LEFT:
+ case LEFT:
+ case BOTTOM_LEFT:
+ store[0] = 0;
+ }
+
+ switch (entry.getAlignment()) {
+ case TOP_LEFT:
+ case TOP:
+ case TOP_RIGHT:
+ store[1] = bgheight;
+ break;
+ case LEFT:
+ case MIDDLE:
+ case RIGHT:
+ store[1] = bgheight / 2;
+ break;
+ case BOTTOM_LEFT:
+ case BOTTOM:
+ case BOTTOM_RIGHT:
+ store[1] = 0;
+ }
+ }
+}
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/backdrop/SolidBackdrop.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/backdrop/SolidBackdrop.java new file mode 100644 index 0000000..cae4adb --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/backdrop/SolidBackdrop.java @@ -0,0 +1,108 @@ +/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui.backdrop;
+
+import com.ardor3d.extension.ui.UIComponent;
+import com.ardor3d.extension.ui.util.UIQuad;
+import com.ardor3d.math.ColorRGBA;
+import com.ardor3d.math.Transform;
+import com.ardor3d.math.Vector3;
+import com.ardor3d.math.type.ReadOnlyColorRGBA;
+import com.ardor3d.renderer.Renderer;
+import com.ardor3d.renderer.state.BlendState;
+import com.ardor3d.renderer.state.BlendState.DestinationFunction;
+import com.ardor3d.renderer.state.BlendState.SourceFunction;
+
+/**
+ * This backdrop paints a solid rectangle of color behind a UI component.
+ */
+public class SolidBackdrop extends UIBackdrop {
+
+ /** The color to draw */
+ private final ColorRGBA _color = new ColorRGBA(ColorRGBA.GRAY);
+ /** The quad used across all solid backdrops to render with. */
+ private static UIQuad _standin = SolidBackdrop.createStandinQuad();
+
+ /**
+ * Construct this backdrop, using the given color.
+ *
+ * @param color
+ * the color of the backdrop
+ */
+ public SolidBackdrop(final ReadOnlyColorRGBA color) {
+ setColor(color);
+ }
+
+ /**
+ * @return the color of this back drop.
+ */
+ public ReadOnlyColorRGBA getColor() {
+ return _color;
+ }
+
+ /**
+ * Set the color of this back drop.
+ *
+ * @param color
+ * the color to use
+ */
+ public void setColor(final ReadOnlyColorRGBA color) {
+ if (color != null) {
+ _color.set(color);
+ }
+ }
+
+ @Override
+ public void draw(final Renderer renderer, final UIComponent comp) {
+
+ final float oldA = _color.getAlpha();
+ if (oldA == 0) {
+ // no need to draw.
+ return;
+ }
+
+ _color.setAlpha(oldA * UIComponent.getCurrentOpacity());
+ SolidBackdrop._standin.setDefaultColor(_color);
+
+ final Vector3 v = Vector3.fetchTempInstance();
+ v.set(comp.getMargin().getLeft() + comp.getBorder().getLeft(), comp.getMargin().getBottom()
+ + comp.getBorder().getBottom(), 0);
+
+ final Transform t = Transform.fetchTempInstance();
+ t.set(comp.getWorldTransform());
+ t.applyForwardVector(v);
+ t.translate(v);
+ Vector3.releaseTempInstance(v);
+
+ SolidBackdrop._standin.setWorldTransform(t);
+ Transform.releaseTempInstance(t);
+
+ final float width = UIBackdrop.getBackdropWidth(comp);
+ final float height = UIBackdrop.getBackdropHeight(comp);
+ SolidBackdrop._standin.resize(width, height);
+ SolidBackdrop._standin.render(renderer);
+
+ _color.setAlpha(oldA);
+ }
+
+ private static UIQuad createStandinQuad() {
+ final UIQuad quad = new UIQuad("standin", 1, 1);
+
+ final BlendState blend = new BlendState();
+ blend.setBlendEnabled(true);
+ blend.setSourceFunction(SourceFunction.SourceAlpha);
+ blend.setDestinationFunction(DestinationFunction.OneMinusSourceAlpha);
+ quad.setRenderState(blend);
+ quad.updateWorldRenderStates(false);
+
+ return quad;
+ }
+}
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/backdrop/UIBackdrop.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/backdrop/UIBackdrop.java new file mode 100644 index 0000000..7028339 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/backdrop/UIBackdrop.java @@ -0,0 +1,62 @@ +/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui.backdrop;
+
+import com.ardor3d.extension.ui.UIComponent;
+import com.ardor3d.renderer.Renderer;
+
+/**
+ * Defines a class responsible for drawing a "backdrop" or screen/background that lays behind a UI component.
+ */
+public abstract class UIBackdrop {
+
+ /**
+ * Draw this backdrop. Override this method to do the actual work.
+ *
+ * @param renderer
+ * the renderer to use in drawing.
+ * @param component
+ * the component we are drawing the background for.
+ */
+ public abstract void draw(final Renderer renderer, final UIComponent comp);
+
+ /**
+ * Get the height that a backdrop should cover for a given component. The height is the component's current content
+ * area height, plus any padding on the top and bottom.
+ *
+ * @param component
+ * the component to check against
+ * @return the height as described above
+ */
+ public static int getBackdropHeight(final UIComponent component) {
+ if (component.getPadding() == null) {
+ return component.getContentHeight();
+ } else {
+ return component.getContentHeight() + component.getPadding().getTop() + component.getPadding().getBottom();
+ }
+ }
+
+ /**
+ * Get the width that a backdrop should cover for a given component. The width is the component's current content
+ * area width, plus any padding on the left and right.
+ *
+ * @param component
+ * the component to check against
+ * @return the width as described above
+ */
+ public static int getBackdropWidth(final UIComponent component) {
+ if (component.getPadding() == null) {
+ return component.getContentWidth();
+ } else {
+ return component.getContentWidth() + component.getPadding().getRight() + component.getPadding().getLeft();
+ }
+ }
+}
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/backdrop/package-info.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/backdrop/package-info.java new file mode 100644 index 0000000..533ad36 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/backdrop/package-info.java @@ -0,0 +1,5 @@ +/** + * Provides classes needed to describe and implement UI backdrops - a rendering done behind the rest of a component. + */ + +package com.ardor3d.extension.ui.backdrop;
\ No newline at end of file diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/border/EmptyBorder.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/border/EmptyBorder.java new file mode 100644 index 0000000..e277da6 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/border/EmptyBorder.java @@ -0,0 +1,41 @@ +/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui.border;
+
+import com.ardor3d.extension.ui.UIComponent;
+import com.ardor3d.renderer.Renderer;
+
+/**
+ * A simple border that does not paint in the border area. This border can be used for adding fixed size padding or
+ * spacing between components.
+ */
+public class EmptyBorder extends UIBorder {
+
+ /**
+ * Create a new border. All sides are zero size.
+ */
+ public EmptyBorder() {
+ this(0, 0, 0, 0);
+ }
+
+ /**
+ * Create a new border with the given edge sizes
+ */
+ public EmptyBorder(final int top, final int left, final int bottom, final int right) {
+ super(top, left, bottom, right);
+ }
+
+ @Override
+ public void draw(final Renderer renderer, final UIComponent comp) {
+ ; // nothing to do here
+ }
+
+}
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/border/ImageBorder.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/border/ImageBorder.java new file mode 100644 index 0000000..dda3cba --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/border/ImageBorder.java @@ -0,0 +1,215 @@ +/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui.border;
+
+import com.ardor3d.extension.ui.UIComponent;
+import com.ardor3d.extension.ui.util.SubTex;
+import com.ardor3d.extension.ui.util.SubTexUtil;
+import com.ardor3d.renderer.Renderer;
+
+/**
+ * This border takes a set of images and draws them around the edge of a UI component. There are eight possible border
+ * images - 4 for the sides of the component and 4 for the corners. Of these, only the sides must be provided. If the
+ * corners are null, the top and bottom will stretch to fill in the gaps.
+ */
+public class ImageBorder extends UIBorder {
+
+ private SubTex _leftEdge = null;
+ private SubTex _rightEdge = null;
+ private SubTex _topEdge = null;
+ private SubTex _bottomEdge = null;
+
+ private SubTex _topLeftCorner = null;
+ private SubTex _topRightCorner = null;
+ private SubTex _bottomLeftCorner = null;
+ private SubTex _bottomRightCorner = null;
+
+ /**
+ * Construct this border using the given edge images. The corners will not be drawn.
+ *
+ * @param leftEdge
+ * @param rightEdge
+ * @param topEdge
+ * @param bottomEdge
+ */
+ public ImageBorder(final SubTex leftEdge, final SubTex rightEdge, final SubTex topEdge, final SubTex bottomEdge) {
+ super(topEdge.getHeight(), leftEdge.getWidth(), bottomEdge.getHeight(), rightEdge.getWidth());
+
+ _leftEdge = leftEdge;
+ _rightEdge = rightEdge;
+ _topEdge = topEdge;
+ _bottomEdge = bottomEdge;
+ }
+
+ /**
+ * Construct this border using the given edge and side images.
+ *
+ * @param leftEdge
+ * @param rightEdge
+ * @param topEdge
+ * @param bottomEdge
+ * @param topLeftCorner
+ * @param topRightCorner
+ * @param bottomLeftCorner
+ * @param bottomRightCorner
+ */
+ public ImageBorder(final SubTex leftEdge, final SubTex rightEdge, final SubTex topEdge, final SubTex bottomEdge,
+ final SubTex topLeftCorner, final SubTex topRightCorner, final SubTex bottomLeftCorner,
+ final SubTex bottomRightCorner) {
+ super(topEdge.getHeight(), leftEdge.getWidth(), bottomEdge.getHeight(), rightEdge.getWidth());
+
+ _leftEdge = leftEdge;
+ _rightEdge = rightEdge;
+ _topEdge = topEdge;
+ _bottomEdge = bottomEdge;
+ _topLeftCorner = topLeftCorner;
+ _topRightCorner = topRightCorner;
+ _bottomLeftCorner = bottomLeftCorner;
+ _bottomRightCorner = bottomRightCorner;
+ }
+
+ public SubTex getBottomEdge() {
+ return _bottomEdge;
+ }
+
+ public void setBottomEdge(final SubTex bottomEdge) {
+ _bottomEdge = bottomEdge;
+ }
+
+ public SubTex getBottomLeftCorner() {
+ return _bottomLeftCorner;
+ }
+
+ public void setBottomLeftCorner(final SubTex bottomLeftCorner) {
+ _bottomLeftCorner = bottomLeftCorner;
+ }
+
+ public SubTex getBottomRightCorner() {
+ return _bottomRightCorner;
+ }
+
+ public void setBottomRightCorner(final SubTex bottomRightCorner) {
+ _bottomRightCorner = bottomRightCorner;
+ }
+
+ public SubTex getLeftEdge() {
+ return _leftEdge;
+ }
+
+ public void setLeftEdge(final SubTex leftEdge) {
+ _leftEdge = leftEdge;
+ }
+
+ public SubTex getRightEdge() {
+ return _rightEdge;
+ }
+
+ public void setRightEdge(final SubTex rightEdge) {
+ _rightEdge = rightEdge;
+ }
+
+ public SubTex getTopEdge() {
+ return _topEdge;
+ }
+
+ public void setTopEdge(final SubTex topEdge) {
+ _topEdge = topEdge;
+ }
+
+ public SubTex getTopLeftCorner() {
+ return _topLeftCorner;
+ }
+
+ public void setTopLeftCorner(final SubTex topLeftCorner) {
+ _topLeftCorner = topLeftCorner;
+ }
+
+ public SubTex getTopRightCorner() {
+ return _topRightCorner;
+ }
+
+ public void setTopRightCorner(final SubTex topRightCorner) {
+ _topRightCorner = topRightCorner;
+ }
+
+ @Override
+ public void draw(final Renderer renderer, final UIComponent comp) {
+
+ // get our general width and height
+ final int borderWidth = UIBorder.getBorderWidth(comp);
+ final int borderHeight = UIBorder.getBorderHeight(comp);
+
+ // Figure out our bottom left corner
+ final double dX = comp.getMargin().getLeft();
+ final double dY = comp.getMargin().getBottom();
+
+ {
+ // draw bottom - stretched to fit
+ double leftwidth = _bottomLeftCorner != null ? _bottomLeftCorner.getWidth() : 0;
+ double rightwidth = _bottomRightCorner != null ? _bottomRightCorner.getWidth() : 0;
+ double x = dX + leftwidth;
+ double y = dY;
+ double width = borderWidth - leftwidth - rightwidth;
+ double height = _bottomEdge.getHeight();
+ SubTexUtil.drawSubTex(renderer, _bottomEdge, x, y, width, height, comp.getWorldTransform());
+
+ // draw top - stretched to fit
+ leftwidth = _topLeftCorner != null ? _topLeftCorner.getWidth() : 0;
+ rightwidth = _topRightCorner != null ? _topRightCorner.getWidth() : 0;
+ x = dX + leftwidth;
+ y = dY + (borderHeight - _topEdge.getHeight());
+ width = borderWidth - leftwidth - rightwidth;
+ height = _topEdge.getHeight();
+ SubTexUtil.drawSubTex(renderer, _topEdge, x, y, width, height, comp.getWorldTransform());
+ }
+
+ {
+ // draw left - stretched to fit
+ int bottomHeight = _bottomLeftCorner != null ? _bottomLeftCorner.getHeight() : _bottomEdge.getHeight();
+ int topHeight = _topLeftCorner != null ? _topLeftCorner.getHeight() : _topEdge.getHeight();
+ double x = dX;
+ double y = dY + bottomHeight;
+ double width = _leftEdge.getWidth();
+ double height = borderHeight - bottomHeight - topHeight;
+ SubTexUtil.drawSubTex(renderer, _leftEdge, x, y, width, height, comp.getWorldTransform());
+
+ // draw right - stretched to fit
+ bottomHeight = _bottomRightCorner != null ? _bottomRightCorner.getHeight() : _bottomEdge.getHeight();
+ topHeight = _topRightCorner != null ? _topRightCorner.getHeight() : _topEdge.getHeight();
+ x = dX + (borderWidth - _rightEdge.getWidth());
+ y = dY + bottomHeight;
+ width = _rightEdge.getWidth();
+ height = borderHeight - bottomHeight - topHeight;
+ SubTexUtil.drawSubTex(renderer, _rightEdge, x, y, width, height, comp.getWorldTransform());
+ }
+
+ // draw corners - not stretched
+ if (_topLeftCorner != null) {
+ SubTexUtil.drawSubTex(renderer, _topLeftCorner, dX, dY + (borderHeight - _topLeftCorner.getHeight()),
+ _topLeftCorner.getWidth(), _topLeftCorner.getHeight(), comp.getWorldTransform());
+ }
+ if (_bottomLeftCorner != null) {
+ SubTexUtil.drawSubTex(renderer, _bottomLeftCorner, dX, dY, _bottomLeftCorner.getWidth(), _bottomLeftCorner
+ .getHeight(), comp.getWorldTransform());
+ }
+ if (_topRightCorner != null) {
+ SubTexUtil.drawSubTex(renderer, _topRightCorner, dX + (borderWidth - _topRightCorner.getWidth()), dY
+ + (borderHeight - _topRightCorner.getHeight()), _topRightCorner.getWidth(), _topRightCorner
+ .getHeight(), comp.getWorldTransform());
+ }
+ if (_bottomRightCorner != null) {
+ SubTexUtil.drawSubTex(renderer, _bottomRightCorner, dX + (borderWidth - _bottomRightCorner.getWidth()), dY,
+ _bottomRightCorner.getWidth(), _bottomRightCorner.getHeight(), comp.getWorldTransform());
+ }
+
+ }
+
+}
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/border/SolidBorder.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/border/SolidBorder.java new file mode 100644 index 0000000..45fbebd --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/border/SolidBorder.java @@ -0,0 +1,219 @@ +/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui.border;
+
+import com.ardor3d.extension.ui.UIComponent;
+import com.ardor3d.math.ColorRGBA;
+import com.ardor3d.math.Transform;
+import com.ardor3d.math.Vector3;
+import com.ardor3d.math.type.ReadOnlyColorRGBA;
+import com.ardor3d.renderer.IndexMode;
+import com.ardor3d.renderer.Renderer;
+import com.ardor3d.renderer.state.BlendState;
+import com.ardor3d.renderer.state.ShadingState;
+import com.ardor3d.renderer.state.BlendState.DestinationFunction;
+import com.ardor3d.renderer.state.BlendState.SourceFunction;
+import com.ardor3d.renderer.state.ShadingState.ShadingMode;
+import com.ardor3d.scenegraph.FloatBufferData;
+import com.ardor3d.scenegraph.Mesh;
+import com.ardor3d.util.geom.BufferUtils;
+
+/**
+ * This border draws solid colored edges around a UI component. Each edge may be a different thickness and/or color.
+ */
+public class SolidBorder extends UIBorder {
+
+ private static final Mesh _mesh = SolidBorder.createMesh();
+ private static final float[] _verts = new float[16];
+ private static final float[] _colors = new float[32];
+
+ /** Our top color - defaults to GRAY. */
+ private final ColorRGBA _topColor = new ColorRGBA(ColorRGBA.GRAY);
+ /** Our left color - defaults to GRAY. */
+ private final ColorRGBA _leftColor = new ColorRGBA(ColorRGBA.GRAY);
+ /** Our bottom color - defaults to LIGHT_GRAY. */
+ private final ColorRGBA _bottomColor = new ColorRGBA(ColorRGBA.LIGHT_GRAY);
+ /** Our right color - defaults to LIGHT_GRAY. */
+ private final ColorRGBA _rightColor = new ColorRGBA(ColorRGBA.LIGHT_GRAY);
+
+ /**
+ * Construct a border with the given thicknesses. Uses the default colors.
+ *
+ * @param top
+ * @param left
+ * @param bottom
+ * @param right
+ */
+ public SolidBorder(final int top, final int left, final int bottom, final int right) {
+ super(top, left, bottom, right);
+ }
+
+ /**
+ * Construct a border with the given thicknesses and colors
+ *
+ * @param top
+ * @param left
+ * @param bottom
+ * @param right
+ * @param topColor
+ * @param leftColor
+ * @param bottomColor
+ * @param rightColor
+ */
+ public SolidBorder(final int top, final int left, final int bottom, final int right,
+ final ReadOnlyColorRGBA topColor, final ReadOnlyColorRGBA leftColor, final ReadOnlyColorRGBA bottomColor,
+ final ReadOnlyColorRGBA rightColor) {
+ super(top, left, bottom, right);
+ setTopColor(topColor);
+ setLeftColor(leftColor);
+ setBottomColor(bottomColor);
+ setRightColor(rightColor);
+ }
+
+ public ReadOnlyColorRGBA getBottomColor() {
+ return _bottomColor;
+ }
+
+ public void setBottomColor(final ReadOnlyColorRGBA color) {
+ _bottomColor.set(color);
+ }
+
+ public ReadOnlyColorRGBA getLeftColor() {
+ return _leftColor;
+ }
+
+ public void setLeftColor(final ReadOnlyColorRGBA color) {
+ _leftColor.set(color);
+ }
+
+ public ReadOnlyColorRGBA getRightColor() {
+ return _rightColor;
+ }
+
+ public void setRightColor(final ReadOnlyColorRGBA color) {
+ _rightColor.set(color);
+ }
+
+ public ReadOnlyColorRGBA getTopColor() {
+ return _topColor;
+ }
+
+ public void setTopColor(final ReadOnlyColorRGBA color) {
+ _topColor.set(color);
+ }
+
+ /**
+ * Sets all of the border colors to the given color.
+ *
+ * @param solidColor
+ * new color for all borders
+ */
+ public void setColor(final ReadOnlyColorRGBA solidColor) {
+ setTopColor(solidColor);
+ setBottomColor(solidColor);
+ setLeftColor(solidColor);
+ setRightColor(solidColor);
+ }
+
+ @Override
+ public void draw(final Renderer renderer, final UIComponent comp) {
+ // draw this border using a triangle-strip of 8 triangles.
+
+ final float pAlpha = UIComponent.getCurrentOpacity();
+
+ final Vector3 v = Vector3.fetchTempInstance();
+ v.set(comp.getMargin().getLeft(), comp.getMargin().getBottom(), 0);
+
+ final Transform t = Transform.fetchTempInstance();
+ t.set(comp.getWorldTransform());
+ t.applyForwardVector(v);
+ t.translate(v);
+ Vector3.releaseTempInstance(v);
+
+ SolidBorder._mesh.setWorldTransform(t);
+ Transform.releaseTempInstance(t);
+
+ final int height = UIBorder.getBorderHeight(comp);
+ final int width = UIBorder.getBorderWidth(comp);
+ final int left = getLeft(), right = getRight(), top = getTop(), bottom = getBottom();
+
+ // set vertices
+ SolidBorder._verts[0] = 0;
+ SolidBorder._verts[1] = 0;
+ SolidBorder._verts[2] = left;
+ SolidBorder._verts[3] = bottom;
+ SolidBorder._verts[4] = 0;
+ SolidBorder._verts[5] = height;
+ SolidBorder._verts[6] = left;
+ SolidBorder._verts[7] = height - top;
+ SolidBorder._verts[8] = width;
+ SolidBorder._verts[9] = height;
+ SolidBorder._verts[10] = width - right;
+ SolidBorder._verts[11] = height - top;
+ SolidBorder._verts[12] = width;
+ SolidBorder._verts[13] = 0;
+ SolidBorder._verts[14] = width - right;
+ SolidBorder._verts[15] = bottom;
+
+ setColor(0, _bottomColor, pAlpha);
+ setColor(1, _bottomColor, pAlpha);
+
+ setColor(2, _leftColor, pAlpha);
+ setColor(3, _leftColor, pAlpha);
+
+ setColor(4, _topColor, pAlpha);
+ setColor(5, _topColor, pAlpha);
+
+ setColor(6, _rightColor, pAlpha);
+ setColor(7, _rightColor, pAlpha);
+
+ SolidBorder._mesh.getMeshData().getVertexBuffer().rewind();
+ SolidBorder._mesh.getMeshData().getVertexBuffer().put(SolidBorder._verts);
+
+ SolidBorder._mesh.getMeshData().getColorBuffer().rewind();
+ SolidBorder._mesh.getMeshData().getColorBuffer().put(SolidBorder._colors);
+
+ SolidBorder._mesh.render(renderer);
+ }
+
+ private void setColor(int i, final ReadOnlyColorRGBA color, final float pAlpha) {
+ i *= 4;
+ SolidBorder._colors[i] = color.getRed();
+ SolidBorder._colors[i + 1] = color.getGreen();
+ SolidBorder._colors[i + 2] = color.getBlue();
+ SolidBorder._colors[i + 3] = color.getAlpha() * pAlpha;
+ }
+
+ private static Mesh createMesh() {
+ // create a triangle strip of 8 triangles.
+ final Mesh mesh = new Mesh();
+ mesh.getMeshData().setVertexCoords(new FloatBufferData(BufferUtils.createVector2Buffer(8), 2));
+ mesh.getMeshData().setColorBuffer(BufferUtils.createColorBuffer(8));
+ mesh.getMeshData().setIndexMode(IndexMode.TriangleStrip);
+ mesh.getMeshData().setIndexBuffer(BufferUtils.createIntBuffer(new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 0, 1 }));
+
+ // set up alpha blending.
+ final BlendState blend = new BlendState();
+ blend.setBlendEnabled(true);
+ blend.setSourceFunction(SourceFunction.SourceAlpha);
+ blend.setDestinationFunction(DestinationFunction.OneMinusSourceAlpha);
+ mesh.setRenderState(blend);
+
+ // use flat shade so our borders will have a solid color.
+ final ShadingState shading = new ShadingState();
+ shading.setShadingMode(ShadingMode.Flat);
+ mesh.setRenderState(shading);
+
+ mesh.updateWorldRenderStates(false);
+
+ return mesh;
+ }
+}
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/border/UIBorder.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/border/UIBorder.java new file mode 100644 index 0000000..f0af766 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/border/UIBorder.java @@ -0,0 +1,81 @@ +/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui.border;
+
+import com.ardor3d.extension.ui.UIComponent;
+import com.ardor3d.extension.ui.util.Insets;
+import com.ardor3d.renderer.Renderer;
+
+/**
+ * Defines a class responsible for drawing a "border" or "picture frame" drawn around the edges of a UI component.
+ */
+public abstract class UIBorder extends Insets {
+
+ /**
+ * Construct a border with the given edge thicknesses.
+ *
+ * @param top
+ * @param left
+ * @param bottom
+ * @param right
+ */
+ public UIBorder(final int top, final int left, final int bottom, final int right) {
+ super(top, left, bottom, right);
+ }
+
+ /**
+ * Draw this border. Override this method to do the actual work.
+ *
+ * @param renderer
+ * the renderer to use in drawing.
+ * @param component
+ * the UIComponent we are drawing the border for.
+ */
+ public abstract void draw(Renderer renderer, UIComponent component);
+
+ /**
+ * Calculate the total height of a border for a given component. This is the current inner height of the component
+ * plus the top and bottom paddings and border thicknesses.
+ *
+ * @param comp
+ * the component to check against
+ * @return the height
+ */
+ public static int getBorderHeight(final UIComponent component) {
+ int height = component.getContentHeight();
+ if (component.getPadding() != null) {
+ height += component.getPadding().getTop() + component.getPadding().getBottom();
+ }
+ if (component.getBorder() != null) {
+ height += component.getBorder().getTop() + component.getBorder().getBottom();
+ }
+ return height;
+ }
+
+ /**
+ * Calculate the total width of a border for a given component. This is the current inner width of the component
+ * plus the left and right paddings and border thicknesses.
+ *
+ * @param comp
+ * the component to check against
+ * @return the width
+ */
+ public static int getBorderWidth(final UIComponent component) {
+ int height = component.getContentWidth();
+ if (component.getPadding() != null) {
+ height += component.getPadding().getLeft() + component.getPadding().getRight();
+ }
+ if (component.getBorder() != null) {
+ height += component.getBorder().getLeft() + component.getBorder().getRight();
+ }
+ return height;
+ }
+}
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/border/package-info.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/border/package-info.java new file mode 100644 index 0000000..f6dc475 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/border/package-info.java @@ -0,0 +1,5 @@ +/** + * Provides classes needed to describe and implement UI borders - rendering done in the margins on the edges of a component. + */ + +package com.ardor3d.extension.ui.border;
\ No newline at end of file diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/event/ActionEvent.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/event/ActionEvent.java new file mode 100644 index 0000000..82a441c --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/event/ActionEvent.java @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui.event; + +import com.ardor3d.extension.ui.UIComponent; + +public class ActionEvent { + protected final UIComponent _source; + + public ActionEvent(final UIComponent source) { + _source = source; + } + + public UIComponent getSource() { + return _source; + } +} diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/event/ActionListener.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/event/ActionListener.java new file mode 100644 index 0000000..7a2461a --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/event/ActionListener.java @@ -0,0 +1,24 @@ +/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui.event;
+
+/**
+ * Classes interested in processing component actions such as the pressing of a button should implement this interface.
+ * Similar in function to {@link java.awt.event.ActionListener}
+ */
+public interface ActionListener {
+
+ /**
+ * Implement this method to perform your action
+ */
+ public void actionPerformed(ActionEvent event);
+
+}
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/event/DragListener.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/event/DragListener.java new file mode 100644 index 0000000..4b03155 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/event/DragListener.java @@ -0,0 +1,67 @@ +/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui.event;
+
+import com.ardor3d.extension.ui.UIComponent;
+
+/**
+ * Classes interested in processing drag events should implement this interface.
+ */
+public interface DragListener {
+
+ /**
+ * Ask if the given component and coordinates indicate a drag handle for the implementor. For example, a scroll bar
+ * setting up a listener might only allow dragging if the component acted on is its button.
+ *
+ * @param component
+ * the UIComponent being acted upon in a suspected drag operation
+ * @param mouseX
+ * the x mouse coordinate
+ * @param mouseY
+ * the y mouse coordinate
+ * @return true if the given parameters describe a drag handle
+ */
+ public boolean isDragHandle(UIComponent component, int mouseX, int mouseY);
+
+ /**
+ * Let the implementor know that we've accepted this as our current drag target. This is called by the hud if a drag
+ * action is detected and isDragHandle has returned true.
+ *
+ * @param mouseX
+ * the x mouse coordinate
+ * @param mouseY
+ * the y mouse coordinate
+ */
+ public void startDrag(int mouseX, int mouseY);
+
+ /**
+ * Method called when the button is still held after startDrag and the mouse has moved again.
+ *
+ * @param mouseX
+ * the new x mouse coordinate
+ * @param mouseY
+ * the new y mouse coordinate
+ */
+ public void drag(int mouseX, int mouseY);
+
+ /**
+ * End our drag. This is called when the button is released after initDrag.
+ *
+ * @param component
+ * the UIComponent our drag ended over.
+ * @param mouseX
+ * the x mouse coordinate
+ * @param mouseY
+ * the y mouse coordinate
+ */
+ public void endDrag(UIComponent component, int mouseX, int mouseY);
+
+}
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/event/FrameDragListener.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/event/FrameDragListener.java new file mode 100644 index 0000000..66d639a --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/event/FrameDragListener.java @@ -0,0 +1,74 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui.event; + +import com.ardor3d.extension.ui.UIComponent; +import com.ardor3d.extension.ui.UIFrame; +import com.ardor3d.math.Rectangle2; + +/** + * The drag listener responsible for allowing a frame to be moved around the screen with the mouse. + */ +public class FrameDragListener implements DragListener { + int oldX = 0; + int oldY = 0; + protected final UIFrame uiFrame; + + public FrameDragListener(final UIFrame uiFrame) { + this.uiFrame = uiFrame; + } + + public void startDrag(final int mouseX, final int mouseY) { + oldX = mouseX; + oldY = mouseY; + } + + public void drag(final int mouseX, final int mouseY) { + if (!uiFrame.isDraggable()) { + return; + } + // check if we are off the edge... if so, flag for redraw (part of the frame may have been hidden) + if (!smallerThanWindow()) { + uiFrame.fireComponentDirty(); + } + + uiFrame.addTranslation(mouseX - oldX, mouseY - oldY, 0); + oldX = mouseX; + oldY = mouseY; + + // check if we are off the edge now... if so, flag for redraw (part of the frame may have been hidden) + if (!smallerThanWindow()) { + uiFrame.fireComponentDirty(); + } + } + + /** + * @return true if this frame can be fully contained by the hud. + */ + public boolean smallerThanWindow() { + final int dispWidth = uiFrame.getHud().getWidth(); + final int dispHeight = uiFrame.getHud().getHeight(); + final Rectangle2 rect = uiFrame.getRelativeComponentBounds(null); + return rect.getWidth() <= dispWidth && rect.getHeight() <= dispHeight; + } + + /** + * Do nothing. + */ + public void endDrag(final UIComponent component, final int mouseX, final int mouseY) {} + + /** + * Check if we are dragging's the frames title bar label. + */ + public boolean isDragHandle(final UIComponent component, final int mouseX, final int mouseY) { + return component == uiFrame.getTitleBar().getTitleLabel(); + } +} diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/event/FrameResizeListener.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/event/FrameResizeListener.java new file mode 100644 index 0000000..e5b96e6 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/event/FrameResizeListener.java @@ -0,0 +1,110 @@ +/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui.event;
+
+import com.ardor3d.extension.ui.UIComponent;
+import com.ardor3d.extension.ui.UIFrame;
+import com.ardor3d.extension.ui.UIFrameStatusBar;
+import com.ardor3d.math.Transform;
+import com.ardor3d.math.Vector3;
+
+public final class FrameResizeListener implements DragListener {
+ private int _initialX;
+ private int _initialY;
+ private int _initialLocalComponentWidth;
+ private int _initialLocalComponentHeight;
+ private final Transform _initFrameTransform = new Transform();
+ private final UIFrameStatusBar _uiFrameStatusBar;
+
+ public FrameResizeListener(final UIFrameStatusBar uiFrameStatusBar) {
+ _uiFrameStatusBar = uiFrameStatusBar;
+ }
+
+ public void startDrag(final int mouseX, final int mouseY) {
+ final Vector3 vec = Vector3.fetchTempInstance();
+ vec.set(mouseX, mouseY, 0);
+ _uiFrameStatusBar.getWorldTransform().applyInverseVector(vec);
+
+ _initialX = Math.round(vec.getXf());
+ _initialY = Math.round(vec.getYf());
+ Vector3.releaseTempInstance(vec);
+
+ final UIFrame frame = UIFrame.findParentFrame(_uiFrameStatusBar);
+ _initialLocalComponentWidth = frame.getLocalComponentWidth();
+ _initialLocalComponentHeight = frame.getLocalComponentHeight();
+
+ _initFrameTransform.set(frame.getWorldTransform());
+ }
+
+ public void drag(final int mouseX, final int mouseY) {
+ resizeFrameByPosition(mouseX, mouseY);
+ }
+
+ public void endDrag(final UIComponent component, final int mouseX, final int mouseY) {
+ resizeFrameByPosition(mouseX, mouseY);
+ }
+
+ private void resizeFrameByPosition(final int mouseX, final int mouseY) {
+
+ final Vector3 vec = Vector3.fetchTempInstance();
+ vec.set(mouseX, mouseY, 0);
+ _uiFrameStatusBar.getWorldTransform().applyInverseVector(vec);
+
+ final int x = Math.round(vec.getXf());
+ final int y = Math.round(vec.getYf());
+
+ final UIFrame frame = UIFrame.findParentFrame(_uiFrameStatusBar);
+
+ // Set the new width to the initial width + the change in mouse x position.
+ int newWidth = _initialLocalComponentWidth + x - _initialX;
+ if (newWidth < UIFrame.MIN_FRAME_WIDTH) {
+ // don't let us get smaller than min size
+ newWidth = UIFrame.MIN_FRAME_WIDTH;
+ }
+ if (newWidth < frame.getMinimumLocalComponentWidth()) {
+ // don't let us get smaller than frame min size
+ newWidth = frame.getMinimumLocalComponentWidth();
+ }
+ if (newWidth > frame.getMaximumLocalComponentWidth()) {
+ // don't let us get bigger than frame max size
+ newWidth = frame.getMaximumLocalComponentWidth();
+ }
+
+ // Set the new height to the initial height + the change in mouse y position.
+ int newHeight = _initialLocalComponentHeight - (y - _initialY);
+ if (newHeight < UIFrame.MIN_FRAME_HEIGHT) {
+ // don't let us get smaller than absolute min size
+ newHeight = UIFrame.MIN_FRAME_HEIGHT;
+ }
+ if (newHeight < frame.getMinimumLocalComponentHeight()) {
+ // don't let us get smaller than frame min size
+ newHeight = frame.getMinimumLocalComponentHeight();
+ }
+ if (newHeight > frame.getMaximumLocalComponentHeight()) {
+ // don't let us get bigger than frame max size
+ newHeight = frame.getMaximumLocalComponentHeight();
+ }
+
+ frame.setLocalComponentSize(newWidth, newHeight);
+
+ vec.set(0, _initialLocalComponentHeight - newHeight, 0);
+ _initFrameTransform.applyForwardVector(vec);
+ frame.setTransform(_initFrameTransform);
+ frame.addTranslation(vec);
+ Vector3.releaseTempInstance(vec);
+
+ frame.layout();
+ }
+
+ public boolean isDragHandle(final UIComponent component, final int mouseX, final int mouseY) {
+ return component == _uiFrameStatusBar.getResizeButton();
+ }
+}
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/event/SelectionListener.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/event/SelectionListener.java new file mode 100644 index 0000000..6fceb29 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/event/SelectionListener.java @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui.event; + +import com.ardor3d.extension.ui.UIComponent; + +/** + * A listener for component selection changes. + * + * @param <T> + * our expected component type. + */ +public interface SelectionListener<T extends UIComponent> { + + /** + * @param component + * the component that changed. + * @param newValue + * our new selection value. + */ + void selectionChanged(T component, Object newValue); + +} diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/event/package-info.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/event/package-info.java new file mode 100644 index 0000000..05bb0a8 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/event/package-info.java @@ -0,0 +1,5 @@ +/** + * Interfaces describing various events in the UI system. + */ + +package com.ardor3d.extension.ui.event;
\ No newline at end of file diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/layout/AnchorLayout.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/layout/AnchorLayout.java new file mode 100644 index 0000000..bdd6b28 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/layout/AnchorLayout.java @@ -0,0 +1,224 @@ +/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui.layout;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.Map;
+
+import com.ardor3d.extension.ui.UIComponent;
+import com.ardor3d.extension.ui.UIContainer;
+import com.ardor3d.extension.ui.util.Alignment;
+import com.ardor3d.math.Rectangle2;
+import com.ardor3d.math.Vector2;
+import com.ardor3d.scenegraph.Spatial;
+import com.google.common.collect.Maps;
+
+/**
+ * <p>
+ * This layout arranges components based on anchors - descriptions of hard connections between two components. These
+ * connections are specified per component, where each component may specify a dependent relationship with exactly one
+ * other component. Each relationship consists of the two dependent components, the alignment points on each, and
+ * optional x/y offsets.
+ * </p>
+ * <p>
+ * As an example, the following would setup labelA in the top left corner of the container, 5 pixels from the top and 5
+ * pixels from the bottom. Directly below that (5 pixels from the bottom of labelA) is labelB, left aligned to labelA:
+ *
+ * <pre>
+ * UIContainer container;
+ * UILabel labelA, labelB
+ *
+ * ...
+ *
+ * container.setLayout(new AnchorLayout());
+ * labelA.setLayoutData(new AnchorLayoutData(Alignment.TOP_LEFT, container, Alignment.TOP_LEFT, 5, -5));
+ * labelB.setLayoutData(new AnchorLayoutData(Alignment.TOP_LEFT, labelA, Alignment.BOTTOM_LEFT, 0, -5));
+ * </pre>
+ *
+ * </p>
+ *
+ * @see AnchorLayoutData
+ */
+public class AnchorLayout extends UILayout {
+
+ /** map used to track anchor relationship during layout. */
+ private final Map<UIComponent, AnchorRecord> _records = Maps.newHashMap();
+
+ // Various min/max values set and used during a layout operation.
+ private int _maxX = 0;
+ private int _maxY = 0;
+ private int _minX = 0;
+ private int _minY = 0;
+
+ @Override
+ public void layoutContents(final UIContainer container) {
+ _maxX = 0;
+ _maxY = 0;
+ _minX = 0;
+ _minY = 0;
+
+ // clear our records
+ _records.clear();
+
+ // add a record for the container
+ _records.put(container, new AnchorRecord());
+
+ // go through all children of a container
+ for (int x = container.getNumberOfChildren(); --x >= 0;) {
+ // set them all to relative position 0,0
+ final Spatial child = container.getChild(x);
+ if (child instanceof UIComponent) {
+ final UIComponent childComp = (UIComponent) child;
+
+ // add an anchor for the component, if missing.
+ if (_records.get(childComp) == null) {
+ _records.put(childComp, new AnchorRecord());
+ }
+
+ // add them to the records container by their dependencies, if any.
+ if (childComp.getLayoutData() instanceof AnchorLayoutData) {
+ // resets translation to 0 so we can addTranslation in applyAnchor
+ childComp.setTranslation(0, 0, childComp.getTranslation().getZ());
+
+ final AnchorLayoutData layData = (AnchorLayoutData) childComp.getLayoutData();
+ AnchorRecord aRecord = _records.get(layData.getParent());
+ if (aRecord == null) {
+ aRecord = new AnchorRecord();
+ _records.put(layData.getParent(), aRecord);
+ }
+ aRecord.dependants.add(childComp);
+ }
+ }
+ }
+
+ // Apply anchors starting at the container and working down. After traversal, remove the visited records and run
+ // through again.
+ visit(container);
+ removeVisited();
+ while (!_records.isEmpty()) {
+ visit((UIComponent) _records.keySet().toArray()[0]);
+ removeVisited();
+ }
+
+ // clear our records to allow potential cleanup of referenced components
+ _records.clear();
+ }
+
+ @Override
+ public void updateMinimumSizeFromContents(final UIContainer container) {
+ layoutContents(container);
+ container.setMinimumContentSize(_maxX - _minX, _maxY - _minY);
+ }
+
+ private void visit(final UIComponent toVisit) {
+ // get the anchor record (if any) for this component
+ final AnchorRecord aRecord = _records.get(toVisit);
+ if (aRecord != null) {
+ final Rectangle2 rect = new Rectangle2();
+ for (int x = aRecord.dependants.size(); --x >= 0;) {
+ final UIComponent dep = aRecord.dependants.get(x);
+ if (dep.getLayoutData() instanceof AnchorLayoutData) {
+ dep.getRelativeComponentBounds(rect);
+ AnchorLayout.applyAnchor(dep, (AnchorLayoutData) dep.getLayoutData());
+
+ // update min/max
+ final int posX = Math.round(dep.getTranslation().getXf()) + rect.getWidth() - rect.getX();
+ final int negX = Math.round(dep.getTranslation().getXf()) - rect.getX();
+ final int posY = Math.round(dep.getTranslation().getYf()) + rect.getHeight() - rect.getY();
+ final int negY = Math.round(dep.getTranslation().getYf()) - rect.getY();
+ if (posX > _maxX) {
+ _maxX = posX;
+ }
+ if (posY > _maxY) {
+ _maxY = posY;
+ }
+ if (negX < _minX) {
+ _minX = negX;
+ }
+ if (negY < _minY) {
+ _minY = negY;
+ }
+ }
+
+ visit(dep);
+ }
+
+ aRecord.visited = true;
+ }
+ }
+
+ private static void applyAnchor(final UIComponent comp, final AnchorLayoutData layData) {
+ final Vector2 offsetsA = AnchorLayout.getOffsets(comp, layData.getMyPoint(), null);
+ final Vector2 offsetsB = AnchorLayout.getOffsets(layData.getParent(), layData.getParentPoint(), null);
+ comp.addTranslation(offsetsB.getX() - offsetsA.getX() + layData.getXOffset(), offsetsB.getY() - offsetsA.getY()
+ + layData.getYOffset(), 0);
+ if (!comp.hasAncestor(layData.getParent())) {
+ comp.addTranslation(layData.getParent().getTranslation());
+ }
+ }
+
+ private static Vector2 getOffsets(final UIComponent comp, final Alignment point, Vector2 store) {
+ if (store == null) {
+ store = new Vector2();
+ }
+
+ final Rectangle2 rect = new Rectangle2();
+ comp.getRelativeComponentBounds(rect);
+ switch (point) {
+ case TOP_LEFT:
+ store.set(rect.getX(), rect.getHeight() + rect.getY());
+ break;
+ case TOP:
+ store.set(rect.getWidth() / 2f + rect.getX(), rect.getHeight() + rect.getY());
+ break;
+ case TOP_RIGHT:
+ store.set(rect.getWidth() + rect.getX(), rect.getHeight() + rect.getY());
+ break;
+ case LEFT:
+ store.set(rect.getX(), rect.getHeight() / 2f + rect.getY());
+ break;
+ case MIDDLE:
+ store.set(rect.getWidth() / 2f + rect.getX(), rect.getHeight() / 2f + rect.getY());
+ break;
+ case RIGHT:
+ store.set(rect.getWidth() + rect.getX(), rect.getHeight() / 2f + rect.getY());
+ break;
+ case BOTTOM_LEFT:
+ store.set(rect.getX(), rect.getY());
+ break;
+ case BOTTOM:
+ store.set(rect.getWidth() / 2f + rect.getX(), rect.getY());
+ break;
+ case BOTTOM_RIGHT:
+ store.set(rect.getWidth() + rect.getX(), rect.getY());
+ break;
+ }
+
+ return store;
+ }
+
+ private void removeVisited() {
+ final Iterator<UIComponent> it = _records.keySet().iterator();
+ while (it.hasNext()) {
+ final UIComponent comp = it.next();
+ final AnchorRecord aRecord = _records.get(comp);
+ if (aRecord != null && aRecord.visited) {
+ it.remove();
+ }
+ }
+ }
+
+ private class AnchorRecord {
+ private transient boolean visited = false;
+ private transient final ArrayList<UIComponent> dependants = new ArrayList<UIComponent>();
+ }
+}
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/layout/AnchorLayoutData.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/layout/AnchorLayoutData.java new file mode 100644 index 0000000..5e759d7 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/layout/AnchorLayoutData.java @@ -0,0 +1,111 @@ +/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui.layout;
+
+import com.ardor3d.extension.ui.UIComponent;
+import com.ardor3d.extension.ui.util.Alignment;
+
+/**
+ * A data class that is used in conjunction with AnchorLayout.
+ *
+ * @see AnchorLayout
+ */
+public class AnchorLayoutData implements UILayoutData {
+
+ /** The point on my component to align at. */
+ private Alignment _myPoint;
+ /** The component or container to align to. */
+ private UIComponent _parent;
+ /** The point on the parent to align my point to. */
+ private Alignment _parentPoint;
+ /** After aligning, we will add this x offset to the component. */
+ private int _xOffset;
+ /** After aligning, we will add this y offset to the component. */
+ private int _yOffset;
+
+ /**
+ * Construct a new AnchorLayoutData using the provided values.
+ *
+ * @param myPoint
+ * the point on our component to align at
+ * @param parent
+ * the component or container to align to
+ * @param parentPoint
+ * the point on the parent to align my point to
+ * @param xOffset
+ * a value added to our component's x position after the alignment is done.
+ * @param yOffset
+ * a value added to our component's y position after the alignment is done.
+ */
+ public AnchorLayoutData(final Alignment myPoint, final UIComponent parent, final Alignment parentPoint,
+ final int xOffset, final int yOffset) {
+ _myPoint = myPoint;
+ _parent = parent;
+ _parentPoint = parentPoint;
+ _xOffset = xOffset;
+ _yOffset = yOffset;
+ }
+
+ /**
+ * @return the point on our component to align at
+ */
+ public Alignment getMyPoint() {
+ return _myPoint;
+ }
+
+ public void setMyPoint(final Alignment myPoint) {
+ _myPoint = myPoint;
+ }
+
+ /**
+ * @return the component or container to align to
+ */
+ public UIComponent getParent() {
+ return _parent;
+ }
+
+ public void setParent(final UIComponent parent) {
+ _parent = parent;
+ }
+
+ /**
+ * @return the point on the parent to align my point to
+ */
+ public Alignment getParentPoint() {
+ return _parentPoint;
+ }
+
+ public void setParentPoint(final Alignment parentPoint) {
+ _parentPoint = parentPoint;
+ }
+
+ /**
+ * @return a value added to our component's x position after the alignment is done
+ */
+ public int getXOffset() {
+ return _xOffset;
+ }
+
+ public void setXOffset(final int offset) {
+ _xOffset = offset;
+ }
+
+ /**
+ * @return a value added to our component's y position after the alignment is done.
+ */
+ public int getYOffset() {
+ return _yOffset;
+ }
+
+ public void setYOffset(final int offset) {
+ _yOffset = offset;
+ }
+}
\ No newline at end of file diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/layout/BorderLayout.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/layout/BorderLayout.java new file mode 100644 index 0000000..96094c9 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/layout/BorderLayout.java @@ -0,0 +1,176 @@ +/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui.layout;
+
+import java.util.List;
+
+import com.ardor3d.extension.ui.UIComponent;
+import com.ardor3d.extension.ui.UIContainer;
+import com.ardor3d.math.Rectangle2;
+import com.ardor3d.scenegraph.Spatial;
+
+/**
+ * This layout places components on the edges or in the center of a container, depending on the value of the layout data
+ * object they hold. The behavior is meant to be similar to awt's {@link java.awt.BorderLayout BorderLayout}.
+ *
+ * @see BorderLayoutData
+ */
+public class BorderLayout extends UILayout {
+
+ @Override
+ public void layoutContents(final UIContainer container) {
+ if (container.getNumberOfChildren() < 1) {
+ return;
+ }
+ int widthWest = 0;
+ int widthEast = 0;
+
+ int heightNorth = 0;
+ int heightSouth = 0;
+ final List<Spatial> content = container.getChildren();
+
+ // Go through each component in the given container and determine the width and height of our edges.
+ final Rectangle2 store = new Rectangle2();
+ for (final Spatial s : content) {
+ if (!(s instanceof UIComponent)) {
+ continue;
+ }
+ final UIComponent comp = (UIComponent) s;
+ comp.getRelativeMinComponentBounds(store);
+
+ final BorderLayoutData data = (BorderLayoutData) comp.getLayoutData();
+ if (data != null) {
+ switch (data) {
+ case NORTH:
+ heightNorth = store.getHeight();
+ break;
+ case SOUTH:
+ heightSouth = store.getHeight();
+ break;
+ case EAST:
+ widthEast = store.getWidth();
+ break;
+ case WEST:
+ widthWest = store.getWidth();
+ break;
+ case CENTER:
+ // nothing to do
+ break;
+ }
+ }
+ }
+
+ // Using the information from the last pass, set the position and size of each component in the container.
+ for (final Spatial s : content) {
+ if (!(s instanceof UIComponent)) {
+ continue;
+ }
+ final UIComponent comp = (UIComponent) s;
+ comp.getRelativeMinComponentBounds(store);
+
+ final BorderLayoutData data = (BorderLayoutData) comp.getLayoutData();
+
+ if (data != null) {
+ switch (data) {
+ case NORTH:
+ comp.fitComponentIn(container.getContentWidth(), store.getHeight());
+ comp.getRelativeComponentBounds(store);
+ comp.setLocalXY(-store.getX(), container.getContentHeight() - heightNorth - store.getY());
+ break;
+ case SOUTH:
+ comp.fitComponentIn(container.getContentWidth(), store.getHeight());
+ comp.getRelativeComponentBounds(store);
+ comp.setLocalXY(-store.getX(), -store.getY());
+ break;
+ case EAST:
+ comp.fitComponentIn(store.getWidth(), container.getContentHeight() - heightNorth - heightSouth);
+ comp.getRelativeComponentBounds(store);
+ comp.setLocalXY(container.getContentWidth() - store.getWidth() - 1 - store.getX(), heightSouth
+ - store.getY());
+ break;
+ case WEST:
+ comp.fitComponentIn(store.getWidth(), container.getContentHeight() - heightNorth - heightSouth);
+ comp.getRelativeComponentBounds(store);
+ comp.setLocalXY(-store.getX(), heightSouth - store.getY());
+ break;
+ case CENTER:
+ comp.fitComponentIn(container.getContentWidth() - widthEast - widthWest, container
+ .getContentHeight()
+ - heightSouth - heightNorth);
+ comp.getRelativeComponentBounds(store);
+ comp.setLocalXY(widthWest - store.getX(), heightSouth - store.getY());
+ }
+ }
+ }
+ }
+
+ @Override
+ public void updateMinimumSizeFromContents(final UIContainer container) {
+ container.setMinimumContentSize(getMinimumWidth(container.getChildren()), getMinimumHeight(container
+ .getChildren()));
+ }
+
+ private int getMinimumHeight(final List<Spatial> content) {
+ int minH = 0;
+ int maxEWCH = 0;
+ if (content != null) {
+ final Rectangle2 store = new Rectangle2();
+ for (final Spatial s : content) {
+ if (!(s instanceof UIComponent)) {
+ continue;
+ }
+ final UIComponent comp = (UIComponent) s;
+ comp.getRelativeMinComponentBounds(store);
+ final BorderLayoutData bld = (BorderLayoutData) comp.getLayoutData();
+ if (bld == null) {
+ continue;
+ }
+ if (bld == BorderLayoutData.SOUTH || bld == BorderLayoutData.NORTH) {
+ minH += store.getHeight();
+ } else {
+ final int h = store.getHeight();
+ if (h > maxEWCH) {
+ maxEWCH = h;
+ }
+ }
+ }
+ }
+
+ return minH + maxEWCH;
+ }
+
+ private int getMinimumWidth(final List<Spatial> content) {
+ int minWidth = 0;
+ int maxNSWidth = 0;
+ if (content != null) {
+ final Rectangle2 store = new Rectangle2();
+ for (final Spatial s : content) {
+ if (!(s instanceof UIComponent)) {
+ continue;
+ }
+ final UIComponent comp = (UIComponent) s;
+ comp.getRelativeMinComponentBounds(store);
+ final BorderLayoutData data = (BorderLayoutData) comp.getLayoutData();
+ if (data == BorderLayoutData.EAST || data == BorderLayoutData.WEST || data == BorderLayoutData.CENTER
+ || data == null) {
+ minWidth += store.getWidth();
+ } else {
+ final int width = store.getWidth();
+ if (width > maxNSWidth) {
+ maxNSWidth = width;
+ }
+ }
+
+ }
+ }
+ return Math.max(minWidth, maxNSWidth);
+ }
+}
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/layout/BorderLayoutData.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/layout/BorderLayoutData.java new file mode 100644 index 0000000..d95a21d --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/layout/BorderLayoutData.java @@ -0,0 +1,18 @@ +/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui.layout;
+
+/**
+ * A data class that represents which slot a component should fall into when used with a BorderLayout.
+ */
+public enum BorderLayoutData implements UILayoutData {
+ NORTH, WEST, SOUTH, CENTER, EAST;
+}
\ No newline at end of file diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/layout/GridLayout.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/layout/GridLayout.java new file mode 100644 index 0000000..44b9666 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/layout/GridLayout.java @@ -0,0 +1,299 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui.layout; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.ardor3d.extension.ui.UIComponent; +import com.ardor3d.extension.ui.UIContainer; +import com.ardor3d.extension.ui.util.Alignment; +import com.ardor3d.scenegraph.Spatial; + +/** + * A UI Layout that puts content in rows and columns where the row and column cells are set to the minimal size of its + * content plus some inter-cell spacing. The components should be added from top to down and left to right. Set the + * layout data of the last component in a row to wrap, e.g. by setLayoutData(GridLayoutData.Wrap); You can specify a + * horizontal span bigger than one to specify that a component should use multiple cells in the current row. + * + * XXX: Note that this class does not currently support layout of rotated components. + */ +public class GridLayout extends UILayout { + + private LayoutGrid grid; + private final int interCellSpacingHorizontal; + private final int interCellSpacingVertical; + private final int leftMargin; + private final int rightMargin; + private final int topMargin; + private final int bottomMargin; + private final Alignment verticalAlignment; + private final boolean fillVerticalSpace; + private final Logger logger = Logger.getLogger(GridLayout.class.getCanonicalName()); + + /** + * Create a GridLayout with the following defaults: 15 pixels horizontal cell spacing, 5 vertical cell spacing, 10 + * pixels left, top and right margin, 0 bottom margin, vertical alignment is top and the vertical space won't be + * distributed between rows + */ + public GridLayout() { + this(15, 5, 10, 10, 10, 0, Alignment.TOP, false); + } + + /** + * Create a GridLayout with the specified parameters and a vertical alignment to top and no distribution of vertical + * space. + * + * @param interCellSpacingHorizontal + * @param interCellSpacingVertical + * @param leftMargin + * @param topMargin + * @param rightMargin + * @param bottomMargin + */ + public GridLayout(final int interCellSpacingHorizontal, final int interCellSpacingVertical, final int leftMargin, + final int topMargin, final int rightMargin, final int bottomMargin) { + this(interCellSpacingHorizontal, interCellSpacingVertical, leftMargin, topMargin, rightMargin, bottomMargin, + Alignment.TOP, false); + } + + /** + * Create a Gridlayout with the specified parameters. If vertical space is distributed the vertical alignment does + * not matter. + * + * @param interCellSpacingHorizontal + * @param interCellSpacingVertical + * @param leftMargin + * @param topMargin + * @param rightMargin + * @param bottomMargin + * @param fillVerticalSpace + */ + public GridLayout(final int interCellSpacingHorizontal, final int interCellSpacingVertical, final int leftMargin, + final int topMargin, final int rightMargin, final int bottomMargin, final boolean fillVerticalSpace) { + this(interCellSpacingHorizontal, interCellSpacingVertical, leftMargin, topMargin, rightMargin, bottomMargin, + Alignment.TOP, fillVerticalSpace); + } + + /** + * Create a GridLayout with the specified parameters. Any additional vertical space won't be distributed between + * rows. + * + * @param interCellSpacingHorizontal + * @param interCellSpacingVertical + * @param leftMargin + * @param topMargin + * @param rightMargin + * @param bottomMargin + * @param verticalAlignment + * only TOP, MIDDLE and BOTTOM are meaningful + */ + public GridLayout(final int interCellSpacingHorizontal, final int interCellSpacingVertical, final int leftMargin, + final int topMargin, final int rightMargin, final int bottomMargin, final Alignment verticalAlignment) { + this(interCellSpacingHorizontal, interCellSpacingVertical, leftMargin, topMargin, rightMargin, bottomMargin, + verticalAlignment, false); + } + + /** + * Create a GridLayout with the specified parameters. Note that the vertical alignment does not matter if you choose + * to distribute any additional space between rows. + * + * @param interCellSpacingHorizontal + * @param interCellSpacingVertical + * @param leftMargin + * @param topMargin + * @param rightMargin + * @param bottomMargin + * @param verticalAlignment + * only TOP, MIDDLE and BOTTOM are meaningful + * @param fillVerticalSpace + */ + public GridLayout(final int interCellSpacingHorizontal, final int interCellSpacingVertical, final int leftMargin, + final int topMargin, final int rightMargin, final int bottomMargin, final Alignment verticalAlignment, + final boolean fillVerticalSpace) { + this.interCellSpacingHorizontal = interCellSpacingHorizontal; + this.interCellSpacingVertical = interCellSpacingVertical; + this.leftMargin = leftMargin; + this.topMargin = topMargin; + this.rightMargin = rightMargin; + this.bottomMargin = bottomMargin; + this.verticalAlignment = verticalAlignment; + this.fillVerticalSpace = fillVerticalSpace; + } + + @Override + public void layoutContents(final UIContainer container) { + rebuildGrid(container); + grid.updateMinimalSize(); + final int height = grid.minHeight; + final int heightDiff = container.getContentHeight() > height ? container.getContentHeight() - height : 0; + int rowHeightDiff = heightDiff; + switch (verticalAlignment) { + case TOP: + rowHeightDiff = heightDiff; + break; + case MIDDLE: + rowHeightDiff = heightDiff / 2; + break; + case BOTTOM: + rowHeightDiff = 0; + break; + default: + rowHeightDiff = heightDiff; + } + for (final LayoutComponent lc : grid.components) { + if (fillVerticalSpace) { + rowHeightDiff = Math.round(heightDiff * (1f - (float) lc.firstRow / grid.maxRow)); + } + lc.component.setLocalXY(grid.columnOffsets[lc.firstColumn], rowHeightDiff + height + - grid.rowOffsets[lc.firstRow] - lc.getComponentHeight()); + if (lc.grow) { + lc.component.setLocalComponentWidth(grid.getCellsWidth(lc.firstColumn, lc.lastColumn)); + } + } + } + + @Override + public void updateMinimumSizeFromContents(final UIContainer container) { + rebuildGrid(container); + grid.updateMinimalSize(); + container.setMinimumContentSize(grid.minWidth, grid.minHeight); + } + + private void rebuildGrid(final UIContainer container) { + final List<Spatial> content = container.getChildren(); + grid = new LayoutGrid(); + for (final Spatial spatial : content) { + if (spatial instanceof UIComponent) { + final UIComponent c = (UIComponent) spatial; + grid.add(c); + } + } + } + + class LayoutGrid { + int currentRow = 0; + int currentColumn = 0; + int nextColumn = 0; + int nextRow = 0; + int maxColumn; + int maxRow; + int minWidth; + int minHeight; + int[] columnOffsets; + int[] rowOffsets; + LinkedList<LayoutComponent> components; + ArrayList<Integer> columnWidths; + + LayoutGrid() { + components = new LinkedList<LayoutComponent>(); + columnWidths = new ArrayList<Integer>(); + } + + void add(final UIComponent c) { + final UILayoutData data = c.getLayoutData(); + final LayoutComponent lc = new LayoutComponent(c); + lc.firstColumn = currentColumn; + lc.firstRow = currentRow; + lc.lastColumn = currentColumn; + lc.lastRow = currentRow; + if (data != null && data instanceof GridLayoutData) { + final GridLayoutData gld = (GridLayoutData) data; + if (gld.getSpan() > 1) { + if (!gld.isWrap()) { + nextColumn += gld.getSpan(); + } else { + nextColumn = 0; + nextRow = currentRow + 1; + } + lc.lastColumn = lc.firstColumn + gld.getSpan() - 1; + maxColumn = Math.max(maxColumn, lc.lastColumn); + } else { + if (gld.isWrap()) { + nextColumn = 0; + nextRow = currentRow + 1; + } else { + nextColumn = currentColumn + 1; + } + } + lc.grow = gld.isGrow(); + } else { + nextColumn = currentColumn + 1; + } + components.add(lc); + if (logger.isLoggable(Level.FINE)) { + logger.fine(lc.toString() + " max.col=" + maxColumn); + } + maxColumn = Math.max(maxColumn, currentColumn); + maxRow = Math.max(maxRow, currentRow); + currentColumn = nextColumn; + currentRow = nextRow; + } + + void updateMinimalSize() { + columnOffsets = new int[maxColumn + 2]; + rowOffsets = new int[maxRow + 2]; + columnOffsets[0] = leftMargin; + rowOffsets[0] = topMargin; + for (final LayoutComponent lc : components) { + columnOffsets[lc.lastColumn + 1] = Math.max(columnOffsets[lc.lastColumn + 1], lc.getComponentWidth() + + interCellSpacingHorizontal + columnOffsets[lc.firstColumn]); + rowOffsets[lc.firstRow + 1] = Math.max(rowOffsets[lc.firstRow + 1], lc.getComponentHeight() + + interCellSpacingVertical + rowOffsets[lc.firstRow]); + } + + if (logger.isLoggable(Level.FINE)) { + logger.fine("column offsets: " + Arrays.toString(columnOffsets)); + logger.fine("row offsets: " + Arrays.toString(rowOffsets)); + } + minWidth = columnOffsets[maxColumn + 1] - interCellSpacingHorizontal + rightMargin; + minHeight = rowOffsets[maxRow + 1] - interCellSpacingVertical + bottomMargin; + } + + int getCellsWidth(final int firstColumn, final int lastColumn) { + int width = columnOffsets[lastColumn + 1] - columnOffsets[firstColumn] - interCellSpacingHorizontal; + if (lastColumn >= maxColumn) { + width -= rightMargin; + } + return width; + } + } + + class LayoutComponent { + UIComponent component; + int firstRow; + int firstColumn; + int lastRow; + int lastColumn; + boolean grow; + + LayoutComponent(final UIComponent c) { + component = c; + } + + public int getComponentWidth() { + return Math.max(component.getLocalComponentWidth(), component.getMinimumLocalComponentWidth()); + } + + public int getComponentHeight() { + return Math.max(component.getLocalComponentHeight(), component.getMinimumLocalComponentHeight()); + } + + @Override + public String toString() { + return component + " " + firstColumn + "-" + lastColumn + "/" + firstRow + "-" + lastRow; + } + } +} diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/layout/GridLayoutData.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/layout/GridLayoutData.java new file mode 100644 index 0000000..e58f750 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/layout/GridLayoutData.java @@ -0,0 +1,86 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui.layout; + +/** + * This class provides layout data for the GridLayout. + */ +public class GridLayoutData implements UILayoutData { + + /** + * a shared GridLayoutData that just wraps the layout line after this component + */ + public static GridLayoutData Wrap = new GridLayoutData(1, true, false); + + /** + * a shared GridLayoutData that just wraps the layout line after this component and let it fill the space + */ + public static GridLayoutData WrapAndGrow = new GridLayoutData(1, true, true); + + private boolean wrap; + private boolean grow; + private int span; + + public GridLayoutData() { + this(1, false, false); + } + + public GridLayoutData(final int span, final boolean wrap, final boolean grow) { + this.span = span; + this.wrap = wrap; + this.grow = grow; + } + + public boolean isWrap() { + return wrap; + } + + public void setWrap(final boolean wrap) { + this.wrap = wrap; + } + + public int getSpan() { + return span; + } + + public void setSpan(final int span) { + this.span = span; + } + + public boolean isGrow() { + return grow; + } + + public void setGrow(final boolean grow) { + this.grow = grow; + } + + /** + * create a new GridLayoutData that specifies the number of cells the component should use horizontally + * + * @param columns + * @return + */ + public static GridLayoutData Span(final int columns) { + return new GridLayoutData(columns, false, false); + } + + /** + * create a new GridLayoutData that specifies the number of cells the component should use horizontally and that the + * layout line should wrap after this component + * + * @param columns + * @return + */ + public static GridLayoutData SpanAndWrap(final int columns) { + return new GridLayoutData(columns, true, false); + } +} diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/layout/RowLayout.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/layout/RowLayout.java new file mode 100644 index 0000000..b4947f9 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/layout/RowLayout.java @@ -0,0 +1,255 @@ +/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui.layout;
+
+import java.util.List;
+
+import com.ardor3d.extension.ui.UIComponent;
+import com.ardor3d.extension.ui.UIContainer;
+import com.ardor3d.math.Rectangle2;
+import com.ardor3d.scenegraph.Spatial;
+import com.google.common.collect.Lists;
+
+/**
+ * This layout places components in either a horizontal or vertical row, ordered as they are placed in their container.
+ * Depending on settings, the layout may also take any extra space in the container and divide it up equally among child
+ * components that are marked as "layout resizeable".
+ */
+public class RowLayout extends UILayout {
+
+ private static final int MAX_RELAX = 50;
+ private final boolean _horizontal;
+ private final boolean _expandsHorizontally;
+ private final boolean _expandsVertically;
+
+ /**
+ * Construct a new RowLayout
+ *
+ * @param horizontal
+ * true if we should lay out horizontally, false if vertically
+ */
+ public RowLayout(final boolean horizontal) {
+ this(horizontal, true, true);
+ }
+
+ /**
+ * Construct a new RowLayout
+ *
+ * @param horizontal
+ * true if we should lay out horizontally, false if vertically
+ * @param expandsHorizontally
+ * true (the default) if horizontal free space in the container should be divided up among the child
+ * components.
+ * @param expandsVertically
+ * true (the default) if vertical free space in the container should be divided up among the child
+ * components.
+ */
+ public RowLayout(final boolean horizontal, final boolean expandsHorizontally, final boolean expandsVertically) {
+ _horizontal = horizontal;
+ _expandsHorizontally = expandsHorizontally;
+ _expandsVertically = expandsVertically;
+ }
+
+ /**
+ * @return true if we lay out horizontally, false if vertically
+ */
+ public boolean isHorizontal() {
+ return _horizontal;
+ }
+
+ /**
+ * @return true (the default) if horizontal free space in the container should be divided up among the child
+ * components.
+ */
+ public boolean isExpandsHorizontally() {
+ return _expandsHorizontally;
+ }
+
+ /**
+ *
+ * @return true (the default) if vertical free space in the container should be divided up among the child
+ * components.
+ */
+ public boolean isExpandsVertically() {
+ return _expandsVertically;
+ }
+
+ @Override
+ public void layoutContents(final UIContainer container) {
+
+ final List<Spatial> content = container.getChildren();
+ if (content == null) {
+ return;
+ }
+
+ final Rectangle2 storeA = Rectangle2.fetchTempInstance();
+ final Rectangle2 storeB = Rectangle2.fetchTempInstance();
+
+ // Grab a list of components, squeezing them down to their min size on the flow axis
+ List<UIComponent> comps = Lists.newArrayList();
+ List<UIComponent> compsBack = Lists.newArrayList();
+ for (int i = 0; i < content.size(); i++) {
+ final Spatial spat = content.get(i);
+ if (spat instanceof UIComponent) {
+ final UIComponent comp = (UIComponent) spat;
+ final Rectangle2 rect = comp.getRelativeComponentBounds(storeA);
+ final Rectangle2 minRect = comp.getRelativeMinComponentBounds(storeB);
+ if (_horizontal) {
+ comp.fitComponentIn(minRect.getWidth(), rect.getHeight());
+ } else {
+ comp.fitComponentIn(rect.getWidth(), minRect.getHeight());
+ }
+ comps.add(comp);
+ }
+ }
+
+ // if we have components to layout...
+ if (!comps.isEmpty()) {
+
+ // Determine how much space we feel we need.
+ final int reqSpace = _horizontal ? getSumOfAllWidths(content) : getSumOfAllHeights(content);
+
+ // How much extra space do we have?
+ int freeSpace = (_horizontal ? container.getContentWidth() : container.getContentHeight()) - reqSpace;
+
+ int relaxIndex = 0;
+ // cycle through until we've given away all of the space
+ while ((freeSpace > 0 || relaxIndex == 0) && !comps.isEmpty() && relaxIndex < RowLayout.MAX_RELAX) {
+ final int extraPerComp = freeSpace / comps.size();
+ while (!comps.isEmpty()) {
+ final UIComponent comp = comps.remove(0);
+ Rectangle2 rect = comp.getRelativeComponentBounds(storeA);
+ final Rectangle2 origRect = storeB.set(rect);
+ if (freeSpace < 0) {
+ freeSpace = 0;
+ }
+ if (_horizontal) {
+ final int height = _expandsVertically ? container.getContentHeight() : rect.getHeight();
+ final int width = (_expandsHorizontally ? extraPerComp : 0) + rect.getWidth();
+ if (height == rect.getHeight() && width == rect.getWidth()) {
+ continue;
+ }
+
+ comp.fitComponentIn(width, height);
+ rect = comp.getRelativeComponentBounds(storeA);
+ if (Math.abs(rect.getWidth() - width) <= 1) {
+ compsBack.add(comp);
+ }
+ freeSpace -= rect.getWidth() - origRect.getWidth();
+ } else {
+ final int width = _expandsHorizontally ? container.getContentWidth() : rect.getWidth();
+ final int height = (_expandsVertically ? extraPerComp : 0) + rect.getHeight();
+ if (height == rect.getHeight() && width == rect.getWidth()) {
+ continue;
+ }
+
+ comp.fitComponentIn(width, height);
+ rect = comp.getRelativeComponentBounds(storeA);
+ if (Math.abs(rect.getHeight() - height) <= 1) {
+ compsBack.add(comp);
+ }
+ freeSpace -= rect.getHeight() - origRect.getHeight();
+ }
+ }
+ final List<UIComponent> compsTemp = comps;
+ comps = compsBack;
+ compsBack = compsTemp;
+ relaxIndex++;
+ }
+
+ int x = 0;
+ int y = !_expandsVertically && !_horizontal ? container.getContentHeight() - reqSpace : 0;
+
+ // Now, go through children and set proper location.
+ for (int i = 0; i < content.size(); i++) {
+ final Spatial spat = _horizontal ? content.get(i) : content.get(content.size() - i - 1);
+
+ if (!(spat instanceof UIComponent)) {
+ continue;
+ }
+ final UIComponent comp = (UIComponent) spat;
+ final Rectangle2 rect = comp.getRelativeComponentBounds(storeA);
+
+ if (_horizontal) {
+ comp.setLocalXY(x - rect.getX(), Math.max(container.getContentHeight() / 2 - rect.getHeight() / 2
+ - rect.getY(), 0));
+ x += rect.getWidth();
+ } else {
+ comp.setLocalXY(Math.max(container.getContentWidth() / 2 - rect.getWidth() / 2 - rect.getX(), 0), y
+ - rect.getY());
+ y += rect.getHeight();
+ }
+ }
+ }
+
+ Rectangle2.releaseTempInstance(storeA);
+ Rectangle2.releaseTempInstance(storeB);
+ }
+
+ @Override
+ public void updateMinimumSizeFromContents(final UIContainer container) {
+
+ int minW = 0, minH = 0;
+ if (container.getNumberOfChildren() > 0) {
+ final List<Spatial> content = container.getChildren();
+
+ // compute the min width and height of the container
+ final Rectangle2 store = new Rectangle2();
+ for (final Spatial s : content) {
+ if (!(s instanceof UIComponent)) {
+ continue;
+ }
+ final UIComponent comp = (UIComponent) s;
+ final Rectangle2 rect = comp.getRelativeMinComponentBounds(store);
+ if (_horizontal) {
+ minW += rect.getWidth();
+ if (minH < rect.getHeight()) {
+ minH = rect.getHeight();
+ }
+ } else {
+ if (minW < rect.getWidth()) {
+ minW = rect.getWidth();
+ }
+ minH += rect.getHeight();
+ }
+ }
+ }
+ container.setMinimumContentSize(minW, minH);
+ }
+
+ private int getSumOfAllHeights(final List<Spatial> content) {
+ int sum = 0;
+ if (content != null) {
+ final Rectangle2 store = new Rectangle2();
+ for (final Spatial spat : content) {
+ if (spat instanceof UIComponent) {
+ final Rectangle2 rect = ((UIComponent) spat).getRelativeMinComponentBounds(store);
+ sum += rect.getHeight();
+ }
+ }
+ }
+ return sum;
+ }
+
+ private int getSumOfAllWidths(final List<Spatial> content) {
+ int sum = 0;
+ if (content != null) {
+ final Rectangle2 store = new Rectangle2();
+ for (final Spatial spat : content) {
+ if (spat instanceof UIComponent) {
+ final Rectangle2 rect = ((UIComponent) spat).getRelativeMinComponentBounds(store);
+ sum += rect.getWidth();
+ }
+ }
+ }
+ return sum;
+ }
+}
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/layout/UILayout.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/layout/UILayout.java new file mode 100644 index 0000000..1f55be8 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/layout/UILayout.java @@ -0,0 +1,35 @@ +/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui.layout;
+
+import com.ardor3d.extension.ui.UIContainer;
+
+/**
+ * A class that can arrange the position and dimensions of the contents of a UI container.
+ */
+public abstract class UILayout {
+
+ /**
+ * Perform the actual layout of the contents in the given container.
+ *
+ * @param container
+ * the container to layout
+ */
+ public abstract void layoutContents(UIContainer container);
+
+ /**
+ * Update the minimum size of this container, based on the contents of the provided container and this layout.
+ *
+ * @param container
+ * the container to update
+ */
+ public abstract void updateMinimumSizeFromContents(UIContainer container);
+}
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/layout/UILayoutData.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/layout/UILayoutData.java new file mode 100644 index 0000000..2f69b78 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/layout/UILayoutData.java @@ -0,0 +1,16 @@ +/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui.layout;
+
+/**
+ * Interface identifying objects that provide more data about how a component should act in a specific layout.
+ */
+public interface UILayoutData {}
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/layout/package-info.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/layout/package-info.java new file mode 100644 index 0000000..3c797fb --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/layout/package-info.java @@ -0,0 +1,7 @@ +/** + * Provides classes that position and resize components within a given UI container. + * Layouts can be reused across multiple UI containers, but if done, layout should be done + * on a single thread as individual layouts may use member fields in a way that is not thread safe. + */ + +package com.ardor3d.extension.ui.layout;
\ No newline at end of file diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/model/ComboBoxModel.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/model/ComboBoxModel.java new file mode 100644 index 0000000..1d88da0 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/model/ComboBoxModel.java @@ -0,0 +1,105 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui.model; + +/** + * An interface describing a data store or model for a UIComboBox. The model should maintain a list of values for a + * combo box, as well as an optional tool tip and view String override. + */ +public interface ComboBoxModel { + + /** + * Add a new item to the end of our model. + * + * @param value + * the value to add. value.toString() is used for the view of this value by default. + * @return the index we were added at + * @see #setViewAt(int, String) + */ + int addItem(Object value); + + /** + * Add a new item to at the specified index in our model. Should pad with null entries if index > current max model + * index. + * + * @param index + * the index to add at + * @param value + * the value to add + */ + void addItem(int index, Object value); + + /** + * Get the item value at the specified index. + * + * @param index + * the index to retrieve + * @return the value of the item at the given index. + */ + Object getValueAt(int index); + + /** + * Sets the value of the item at the given index. If that item already has a name or tooltip set, it is left + * unchanged. + * + * @param index + * the index to add at. + * @param value + * the value to set + */ + void setValueAt(int index, Object value); + + /** + * @param index + * the index to retrieve + * @return the view String for the given index. If no specific view is set, the value at that location is converted + * with toString(). + */ + String getViewAt(int index); + + /** + * Sets the view String for the given index. + * + * @param index + * the index to add at. + * @param view + * the view String to set + */ + void setViewAt(int index, String view); + + /** + * @param index + * the index to retrieve + * @return the tool tip for the given index. + */ + String getToolTipAt(int index); + + /** + * Sets the tool tip for the given index. + * + * @param index + * the index to add at. + * @param toolTip + * the tool tip to set + */ + void setToolTipAt(int index, String toolTip); + + /** + * @return the number of items, including null items, in our model. + */ + int size(); + + /** + * Removes all items from this model. + */ + void clear(); + +} diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/model/DefaultComboBoxModel.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/model/DefaultComboBoxModel.java new file mode 100644 index 0000000..e2f4796 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/model/DefaultComboBoxModel.java @@ -0,0 +1,103 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui.model; + +import java.util.List; + +import com.google.common.collect.Lists; + +/** + * Default implementation of a ComboBox model. + */ +public class DefaultComboBoxModel implements ComboBoxModel { + + protected List<ModelElement> _elements = Lists.newArrayList(); + + public DefaultComboBoxModel() {} + + public DefaultComboBoxModel(final Object... data) { + if (data != null) { + for (int i = 0; i < data.length; i++) { + addItem(data[i]); + } + } + } + + @Override + public int addItem(final Object value) { + final ModelElement element = new ModelElement(); + element._value = value; + _elements.add(element); + return _elements.size() - 1; + } + + @Override + public void addItem(final int index, final Object value) { + final ModelElement element = new ModelElement(); + element._value = value; + while (_elements.size() <= index) { + _elements.add(new ModelElement()); + } + _elements.set(index, element); + } + + @Override + public void clear() { + _elements.clear(); + } + + @Override + public String getToolTipAt(final int index) { + return _elements.get(index)._toolTip; + } + + @Override + public Object getValueAt(final int index) { + return _elements.get(index)._value; + } + + @Override + public String getViewAt(final int index) { + final ModelElement elem = _elements.get(index); + return elem._view != null ? elem._view : elem._value != null ? elem._value.toString() : null; + } + + @Override + public void setToolTipAt(final int index, final String toolTip) { + final ModelElement elem = _elements.get(index); + elem._toolTip = toolTip; + } + + @Override + public void setValueAt(final int index, final Object value) { + final ModelElement elem = _elements.get(index); + elem._value = value; + } + + @Override + public void setViewAt(final int index, final String view) { + final ModelElement elem = _elements.get(index); + elem._view = view; + } + + @Override + public int size() { + return _elements.size(); + } + + protected class ModelElement { + Object _value = null; + + // these are optional + String _view = null; + String _toolTip = null; + } +} diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/model/DefaultSliderModel.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/model/DefaultSliderModel.java new file mode 100644 index 0000000..f10a7c4 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/model/DefaultSliderModel.java @@ -0,0 +1,76 @@ +/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui.model;
+
+import com.ardor3d.extension.ui.UISlider;
+import com.ardor3d.math.MathUtils;
+
+/**
+ * A backing data model for UISlider.
+ */
+public class DefaultSliderModel implements SliderModel {
+
+ /** Minimum range value */
+ private int _minValue;
+
+ /** Maximum range value */
+ private int _maxValue;
+
+ /** Current value */
+ private int _currentValue;
+
+ /**
+ * Construct a new model
+ *
+ * @param minValue
+ * lowest possible value (inclusive)
+ * @param maxValue
+ * highest possible value (inclusive)
+ */
+ public DefaultSliderModel(final int minValue, final int maxValue) {
+ setMinValue(minValue);
+ setMaxValue(maxValue);
+ }
+
+ public int getCurrentValue() {
+ return _currentValue;
+ }
+
+ public void setCurrentValue(final int currentValue) {
+ setCurrentValue(currentValue, null);
+ }
+
+ public void setCurrentValue(final int currentValue, final UISlider slider) {
+ if (_currentValue == currentValue) {
+ return;
+ }
+ _currentValue = MathUtils.clamp(currentValue, _minValue, _maxValue);
+ if (slider != null) {
+ slider.fireChangeEvent();
+ }
+ }
+
+ public int getMaxValue() {
+ return _maxValue;
+ }
+
+ public void setMaxValue(final int maxValue) {
+ _maxValue = maxValue;
+ }
+
+ public int getMinValue() {
+ return _minValue;
+ }
+
+ public void setMinValue(final int minValue) {
+ _minValue = minValue;
+ }
+}
\ No newline at end of file diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/model/SliderModel.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/model/SliderModel.java new file mode 100644 index 0000000..a6cd7b8 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/model/SliderModel.java @@ -0,0 +1,62 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui.model; + +import com.ardor3d.extension.ui.UISlider; + +public interface SliderModel { + + /** + * @return the highest possible value (inclusive) + */ + int getMaxValue(); + + /** + * @param maxValue + * the new highest possible value (inclusive) + */ + void setMaxValue(int maxValue); + + /** + * @return the current set value + */ + int getCurrentValue(); + + /** + * Set a new current value. No change event will be fired. + * + * @param currentValue + * the new current value + */ + void setCurrentValue(int currentValue); + + /** + * Set a new current value. If a slider is provided, fireChangeEvent will be called on it. + * + * @param currentValue + * the new current value + * @param slider + * the slider to call fireChangeEvent, if not null. + */ + void setCurrentValue(int value, UISlider slider); + + /** + * @return the lowest possible value (inclusive) + */ + int getMinValue(); + + /** + * @param minValue + * the new lowest possible value (inclusive) + */ + void setMinValue(int minValue); + +} diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/package-info.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/package-info.java new file mode 100644 index 0000000..c3d7348 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/package-info.java @@ -0,0 +1,5 @@ +/** + * Ardor3D's UI extension package. + */ + +package com.ardor3d.extension.ui;
\ No newline at end of file diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/skin/Skin.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/skin/Skin.java new file mode 100644 index 0000000..8d7b5bc --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/skin/Skin.java @@ -0,0 +1,118 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui.skin; + +import com.ardor3d.extension.ui.UIButton; +import com.ardor3d.extension.ui.UICheckBox; +import com.ardor3d.extension.ui.UIComboBox; +import com.ardor3d.extension.ui.UIComponent; +import com.ardor3d.extension.ui.UIFrame; +import com.ardor3d.extension.ui.UILabel; +import com.ardor3d.extension.ui.UIPanel; +import com.ardor3d.extension.ui.UIPasswordField; +import com.ardor3d.extension.ui.UIPopupMenu; +import com.ardor3d.extension.ui.UIProgressBar; +import com.ardor3d.extension.ui.UIRadioButton; +import com.ardor3d.extension.ui.UIScrollBar; +import com.ardor3d.extension.ui.UISlider; +import com.ardor3d.extension.ui.UITab; +import com.ardor3d.extension.ui.UITextArea; +import com.ardor3d.extension.ui.UITextField; +import com.ardor3d.extension.ui.UITooltip; + +public abstract class Skin { + + public void applyTo(final UIComponent component) { + // NOTE: Test for subclasses first, then parent class + + // 1. BUTTON TYPES + if (component instanceof UITab) { + applyToTab((UITab) component); + } else if (component instanceof UICheckBox) { + applyToCheckBox((UICheckBox) component); + } else if (component instanceof UIRadioButton) { + applyToRadioButton((UIRadioButton) component); + } else if (component instanceof UIButton) { + applyToButton((UIButton) component); + } + + // 2. OTHER LABEL TYPES + else if (component instanceof UILabel) { + applyToLabel((UILabel) component); + } + + // 3. TEXT ENTRY TYPES + else if (component instanceof UIPasswordField) { + applyToPasswordField((UIPasswordField) component); + } else if (component instanceof UITextField) { + applyToTextField((UITextField) component); + } else if (component instanceof UITextArea) { + applyToTextArea((UITextArea) component); + } + + // 4. PANEL TYPES + else if (component instanceof UIProgressBar) { + applyToProgressBar((UIProgressBar) component); + } else if (component instanceof UIComboBox) { + applyToComboBox((UIComboBox) component); + } else if (component instanceof UIScrollBar) { + applyToScrollBar((UIScrollBar) component); + } else if (component instanceof UIPanel) { + applyToPanel((UIPanel) component); + } + + // 5. FRAME TYPES + else if (component instanceof UITooltip) { + applyToTooltip((UITooltip) component); + } else if (component instanceof UIPopupMenu) { + applyToPopupMenu((UIPopupMenu) component); + } else if (component instanceof UIFrame) { + applyToFrame((UIFrame) component); + } + + // 6. SLIDER + else if (component instanceof UISlider) { + applyToSlider((UISlider) component); + } + } + + protected abstract void applyToTab(UITab component); + + protected abstract void applyToCheckBox(UICheckBox component); + + protected abstract void applyToRadioButton(UIRadioButton component); + + protected abstract void applyToButton(UIButton component); + + protected abstract void applyToLabel(UILabel component); + + protected abstract void applyToTextField(UITextField component); + + protected abstract void applyToPasswordField(UIPasswordField component); + + protected abstract void applyToTextArea(UITextArea component); + + protected abstract void applyToPanel(UIPanel component); + + protected abstract void applyToTooltip(UITooltip component); + + protected abstract void applyToFrame(UIFrame component); + + protected abstract void applyToProgressBar(UIProgressBar component); + + protected abstract void applyToSlider(UISlider component); + + protected abstract void applyToPopupMenu(UIPopupMenu component); + + protected abstract void applyToComboBox(UIComboBox component); + + protected abstract void applyToScrollBar(UIScrollBar component); +} diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/skin/SkinManager.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/skin/SkinManager.java new file mode 100644 index 0000000..6cc5005 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/skin/SkinManager.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui.skin; + +import com.ardor3d.extension.ui.UIComponent; +import com.ardor3d.extension.ui.skin.generic.GenericSkin; + +public class SkinManager { + + private static Skin _skin = new GenericSkin(); + + public static void setCurrentSkin(final Skin skin) { + SkinManager._skin = skin; + } + + public static void applyCurrentSkin(final UIComponent component) { + if (SkinManager._skin == null) { + return; + } + + // apply skin to component + SkinManager._skin.applyTo(component); + } + +} diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/skin/SkinningTask.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/skin/SkinningTask.java new file mode 100644 index 0000000..5907c48 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/skin/SkinningTask.java @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui.skin; + +import com.ardor3d.extension.ui.UIComponent; + +/** + * A simple call-back useful for skins in cases where skinning happens later, such as during dynamic construction of a + * menu. + */ +public interface SkinningTask { + + /** + * Perform skinning tasks on the given component + * + * @param component + * the component to be skinned. + */ + void skinComponent(UIComponent component); + +} diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/skin/generic/GenericSkin.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/skin/generic/GenericSkin.java new file mode 100644 index 0000000..d3efb0e --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/skin/generic/GenericSkin.java @@ -0,0 +1,923 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui.skin.generic; + +import com.ardor3d.extension.ui.LabelState; +import com.ardor3d.extension.ui.Orientation; +import com.ardor3d.extension.ui.UIButton; +import com.ardor3d.extension.ui.UICheckBox; +import com.ardor3d.extension.ui.UIComboBox; +import com.ardor3d.extension.ui.UIComponent; +import com.ardor3d.extension.ui.UIFrame; +import com.ardor3d.extension.ui.UIFrameBar; +import com.ardor3d.extension.ui.UIFrameStatusBar; +import com.ardor3d.extension.ui.UILabel; +import com.ardor3d.extension.ui.UIPanel; +import com.ardor3d.extension.ui.UIPasswordField; +import com.ardor3d.extension.ui.UIPopupMenu; +import com.ardor3d.extension.ui.UIProgressBar; +import com.ardor3d.extension.ui.UIRadioButton; +import com.ardor3d.extension.ui.UIScrollBar; +import com.ardor3d.extension.ui.UISlider; +import com.ardor3d.extension.ui.UISliderKnob; +import com.ardor3d.extension.ui.UIState; +import com.ardor3d.extension.ui.UITab; +import com.ardor3d.extension.ui.UITextArea; +import com.ardor3d.extension.ui.UITextField; +import com.ardor3d.extension.ui.UITooltip; +import com.ardor3d.extension.ui.UITabbedPane.TabPlacement; +import com.ardor3d.extension.ui.backdrop.EmptyBackdrop; +import com.ardor3d.extension.ui.backdrop.GradientBackdrop; +import com.ardor3d.extension.ui.backdrop.ImageBackdrop; +import com.ardor3d.extension.ui.backdrop.SolidBackdrop; +import com.ardor3d.extension.ui.border.EmptyBorder; +import com.ardor3d.extension.ui.border.ImageBorder; +import com.ardor3d.extension.ui.border.SolidBorder; +import com.ardor3d.extension.ui.border.UIBorder; +import com.ardor3d.extension.ui.layout.RowLayout; +import com.ardor3d.extension.ui.skin.Skin; +import com.ardor3d.extension.ui.skin.SkinningTask; +import com.ardor3d.extension.ui.util.Alignment; +import com.ardor3d.extension.ui.util.Insets; +import com.ardor3d.extension.ui.util.SubTex; +import com.ardor3d.image.Texture; +import com.ardor3d.image.TextureStoreFormat; +import com.ardor3d.image.Texture.MinificationFilter; +import com.ardor3d.math.ColorRGBA; +import com.ardor3d.util.TextureManager; +import com.ardor3d.util.resource.ResourceSource; + +public class GenericSkin extends Skin { + protected Texture _sharedTex; + + public GenericSkin() { + loadTexture("com/ardor3d/extension/ui/skin/generic/genericSkin.png"); + } + + public GenericSkin(final String skinTexture) { + loadTexture(skinTexture); + } + + protected void loadTexture(final String skinTexture) { + try { + _sharedTex = TextureManager.load(skinTexture, MinificationFilter.Trilinear, + TextureStoreFormat.GuessNoCompressedFormat, false); + } catch (final Exception e) { + e.printStackTrace(); + } + + } + + public GenericSkin(final ResourceSource skinTexture) { + loadTexture(skinTexture); + } + + protected void loadTexture(final ResourceSource skinTexture) { + try { + _sharedTex = TextureManager.load(skinTexture, MinificationFilter.Trilinear, + TextureStoreFormat.GuessNoCompressedFormat, false); + } catch (final Exception e) { + e.printStackTrace(); + } + + } + + @Override + protected void applyToTab(final UITab component) { + + component.setMargin(new Insets(1, 1, 1, 1)); + component.setPadding(new Insets(2, 14, 2, 14)); + + // State values... + final UIBorder defaultBorder = new ImageBorder( + // left + component.getPlacement() != TabPlacement.EAST ? new SubTex(_sharedTex, 47, 11, 4, 10) : new SubTex( + _sharedTex, 0, 0, 0, 0), + // right + component.getPlacement() != TabPlacement.WEST ? new SubTex(_sharedTex, 77, 11, 4, 10) : new SubTex( + _sharedTex, 0, 0, 0, 0), + // top + component.getPlacement() != TabPlacement.SOUTH ? new SubTex(_sharedTex, 51, 7, 26, 4) : new SubTex( + _sharedTex, 0, 0, 0, 0), + // bottom + component.getPlacement() != TabPlacement.NORTH ? new SubTex(_sharedTex, 51, 21, 26, 4) : new SubTex( + _sharedTex, 0, 0, 0, 0), + // top left + component.getPlacement() != TabPlacement.SOUTH && component.getPlacement() != TabPlacement.EAST ? new SubTex( + _sharedTex, 47, 7, 4, 4) + : null, + // top right + component.getPlacement() != TabPlacement.SOUTH && component.getPlacement() != TabPlacement.WEST ? new SubTex( + _sharedTex, 77, 7, 4, 4) + : null, + // bottom left + component.getPlacement() != TabPlacement.NORTH && component.getPlacement() != TabPlacement.EAST ? new SubTex( + _sharedTex, 47, 21, 4, 4) + : null, + // bottom right + component.getPlacement() != TabPlacement.NORTH && component.getPlacement() != TabPlacement.WEST ? new SubTex( + _sharedTex, 77, 21, 4, 4) + : null); + + final UIBorder overBorder = new ImageBorder( + // left + component.getPlacement() != TabPlacement.EAST ? new SubTex(_sharedTex, 47, 33, 4, 10) : new SubTex( + _sharedTex, 0, 0, 0, 0), + // right + component.getPlacement() != TabPlacement.WEST ? new SubTex(_sharedTex, 77, 33, 4, 10) : new SubTex( + _sharedTex, 0, 0, 0, 0), + // top + component.getPlacement() != TabPlacement.SOUTH ? new SubTex(_sharedTex, 51, 29, 26, 4) : new SubTex( + _sharedTex, 0, 0, 0, 0), + // bottom + component.getPlacement() != TabPlacement.NORTH ? new SubTex(_sharedTex, 51, 43, 26, 4) : new SubTex( + _sharedTex, 0, 0, 0, 0), + // top left + component.getPlacement() != TabPlacement.SOUTH && component.getPlacement() != TabPlacement.EAST ? new SubTex( + _sharedTex, 47, 29, 4, 4) + : null, + // top right + component.getPlacement() != TabPlacement.SOUTH && component.getPlacement() != TabPlacement.WEST ? new SubTex( + _sharedTex, 77, 29, 4, 4) + : null, + // bottom left + component.getPlacement() != TabPlacement.NORTH && component.getPlacement() != TabPlacement.EAST ? new SubTex( + _sharedTex, 47, 43, 4, 4) + : null, + // bottom right + component.getPlacement() != TabPlacement.NORTH && component.getPlacement() != TabPlacement.WEST ? new SubTex( + _sharedTex, 77, 43, 4, 4) + : null); + + final UIBorder pressedBorder = new ImageBorder( + // left + component.getPlacement() != TabPlacement.EAST ? new SubTex(_sharedTex, 47, 55, 4, 10) : new SubTex( + _sharedTex, 0, 0, 0, 0), + // right + component.getPlacement() != TabPlacement.WEST ? new SubTex(_sharedTex, 77, 55, 4, 10) : new SubTex( + _sharedTex, 0, 0, 0, 0), + // top + component.getPlacement() != TabPlacement.SOUTH ? new SubTex(_sharedTex, 51, 51, 26, 4) : new SubTex( + _sharedTex, 0, 0, 0, 0), + // bottom + component.getPlacement() != TabPlacement.NORTH ? new SubTex(_sharedTex, 51, 65, 26, 4) : new SubTex( + _sharedTex, 0, 0, 0, 0), + // top left + component.getPlacement() != TabPlacement.SOUTH && component.getPlacement() != TabPlacement.EAST ? new SubTex( + _sharedTex, 47, 51, 4, 4) + : null, + // top right + component.getPlacement() != TabPlacement.SOUTH && component.getPlacement() != TabPlacement.WEST ? new SubTex( + _sharedTex, 77, 51, 4, 4) + : null, + // bottom left + component.getPlacement() != TabPlacement.NORTH && component.getPlacement() != TabPlacement.EAST ? new SubTex( + _sharedTex, 47, 65, 4, 4) + : null, + // bottom right + component.getPlacement() != TabPlacement.NORTH && component.getPlacement() != TabPlacement.WEST ? new SubTex( + _sharedTex, 77, 65, 4, 4) + : null); + + final ColorRGBA upTop = new ColorRGBA(235 / 255f, 235 / 255f, 235 / 255f, 1); + final ColorRGBA upBottom = new ColorRGBA(200 / 255f, 200 / 255f, 200 / 255f, 1); + final GradientBackdrop upBack = new GradientBackdrop(upTop, upTop, upBottom, upBottom); + final ColorRGBA downTop = new ColorRGBA(181 / 255f, 181 / 255f, 181 / 255f, 1); + final ColorRGBA downBottom = new ColorRGBA(232 / 255f, 232 / 255f, 232 / 255f, 1); + final GradientBackdrop downBack = new GradientBackdrop(downTop, downTop, downBottom, downBottom); + // DEFAULT + { + component.getDefaultState().setBorder(defaultBorder); + component.getDefaultState().setBackdrop(upBack); + component.getDefaultState().setForegroundColor(ColorRGBA.BLACK); + } + // DISABLED + { + component.getDisabledState().setBorder(defaultBorder); + component.getDisabledState().setBackdrop(upBack); + component.getDisabledState().setForegroundColor(ColorRGBA.GRAY); + + component.getDisabledSelectedState().setBorder(pressedBorder); + component.getDisabledSelectedState().setBackdrop(downBack); + component.getDisabledSelectedState().setForegroundColor(ColorRGBA.GRAY); + } + // MOUSE OVER + { + final ColorRGBA top = new ColorRGBA(241 / 255f, 241 / 255f, 241 / 255f, 1); + final ColorRGBA bottom = new ColorRGBA(216 / 255f, 216 / 255f, 216 / 255f, 1); + final GradientBackdrop back = new GradientBackdrop(top, top, bottom, bottom); + + component.getMouseOverState().setBorder(overBorder); + component.getMouseOverState().setBackdrop(back); + component.getMouseOverState().setForegroundColor(ColorRGBA.BLACK); + } + // PRESSED AND SELECTED + { + component.getPressedState().setBorder(pressedBorder); + component.getPressedState().setBackdrop(downBack); + component.getPressedState().setForegroundColor(ColorRGBA.BLACK); + + component.getSelectedState().setBorder(pressedBorder); + component.getSelectedState().setBackdrop(downBack); + component.getSelectedState().setForegroundColor(ColorRGBA.BLACK); + + component.getMouseOverSelectedState().setBorder(pressedBorder); + component.getMouseOverSelectedState().setBackdrop(downBack); + component.getMouseOverSelectedState().setForegroundColor(ColorRGBA.GRAY); + } + } + + @Override + protected void applyToButton(final UIButton component) { + + component.setAlignment(Alignment.MIDDLE); + component.setMargin(new Insets(1, 1, 1, 1)); + component.setPadding(new Insets(2, 14, 2, 14)); + + // State values... + final UIBorder defaultBorder = new ImageBorder( + // left + new SubTex(_sharedTex, 47, 11, 4, 10), + // right + new SubTex(_sharedTex, 77, 11, 4, 10), + // top + new SubTex(_sharedTex, 51, 7, 26, 4), + // bottom + new SubTex(_sharedTex, 51, 21, 26, 4), + // top left + new SubTex(_sharedTex, 47, 7, 4, 4), + // top right + new SubTex(_sharedTex, 77, 7, 4, 4), + // bottom left + new SubTex(_sharedTex, 47, 21, 4, 4), + // bottom right + new SubTex(_sharedTex, 77, 21, 4, 4)); + + final UIBorder overBorder = new ImageBorder( + // left + new SubTex(_sharedTex, 47, 33, 4, 10), + // right + new SubTex(_sharedTex, 77, 33, 4, 10), + // top + new SubTex(_sharedTex, 51, 29, 26, 4), + // bottom + new SubTex(_sharedTex, 51, 43, 26, 4), + // top left + new SubTex(_sharedTex, 47, 29, 4, 4), + // top right + new SubTex(_sharedTex, 77, 29, 4, 4), + // bottom left + new SubTex(_sharedTex, 47, 43, 4, 4), + // bottom right + new SubTex(_sharedTex, 77, 43, 4, 4)); + + final UIBorder pressedBorder = new ImageBorder( + // left + new SubTex(_sharedTex, 47, 55, 4, 10), + // right + new SubTex(_sharedTex, 77, 55, 4, 10), + // top + new SubTex(_sharedTex, 51, 51, 26, 4), + // bottom + new SubTex(_sharedTex, 51, 65, 26, 4), + // top left + new SubTex(_sharedTex, 47, 51, 4, 4), + // top right + new SubTex(_sharedTex, 77, 51, 4, 4), + // bottom left + new SubTex(_sharedTex, 47, 65, 4, 4), + // bottom right + new SubTex(_sharedTex, 77, 65, 4, 4)); + + final ColorRGBA upTop = new ColorRGBA(235 / 255f, 235 / 255f, 235 / 255f, 1); + final ColorRGBA upBottom = new ColorRGBA(200 / 255f, 200 / 255f, 200 / 255f, 1); + final GradientBackdrop upBack = new GradientBackdrop(upTop, upTop, upBottom, upBottom); + final ColorRGBA downTop = new ColorRGBA(181 / 255f, 181 / 255f, 181 / 255f, 1); + final ColorRGBA downBottom = new ColorRGBA(232 / 255f, 232 / 255f, 232 / 255f, 1); + final GradientBackdrop downBack = new GradientBackdrop(downTop, downTop, downBottom, downBottom); + // DEFAULT + { + component.getDefaultState().setBorder(defaultBorder); + component.getDefaultState().setBackdrop(upBack); + component.getDefaultState().setForegroundColor(ColorRGBA.BLACK); + } + // DISABLED + { + component.getDisabledState().setBorder(defaultBorder); + component.getDisabledState().setBackdrop(upBack); + component.getDisabledState().setForegroundColor(ColorRGBA.GRAY); + + component.getDisabledSelectedState().setBorder(pressedBorder); + component.getDisabledSelectedState().setBackdrop(downBack); + component.getDisabledSelectedState().setForegroundColor(ColorRGBA.GRAY); + } + // MOUSE OVER + { + final ColorRGBA top = new ColorRGBA(241 / 255f, 241 / 255f, 241 / 255f, 1); + final ColorRGBA bottom = new ColorRGBA(216 / 255f, 216 / 255f, 216 / 255f, 1); + final GradientBackdrop back = new GradientBackdrop(top, top, bottom, bottom); + + component.getMouseOverState().setBorder(overBorder); + component.getMouseOverState().setBackdrop(back); + component.getMouseOverState().setForegroundColor(ColorRGBA.BLACK); + } + // PRESSED AND SELECTED + { + component.getPressedState().setBorder(pressedBorder); + component.getPressedState().setBackdrop(downBack); + component.getPressedState().setForegroundColor(ColorRGBA.BLACK); + + component.getSelectedState().setBorder(pressedBorder); + component.getSelectedState().setBackdrop(downBack); + component.getSelectedState().setForegroundColor(ColorRGBA.BLACK); + + component.getMouseOverSelectedState().setBorder(pressedBorder); + component.getMouseOverSelectedState().setBackdrop(downBack); + component.getMouseOverSelectedState().setForegroundColor(ColorRGBA.GRAY); + } + } + + @Override + protected void applyToCheckBox(final UICheckBox component) { + + component.setMargin(new Insets(1, 1, 1, 1)); + component.setPadding(new Insets(1, 1, 1, 1)); + component.setBorder(new EmptyBorder()); + component.setBackdrop(new EmptyBackdrop()); + component.setAlignment(Alignment.LEFT); + component.setGap(4); + + // DEFAULT + { + component.getDefaultState().setForegroundColor(ColorRGBA.BLACK); + component.getDefaultState().setIcon(new SubTex(_sharedTex, 94, 9, 14, 14)); + } + // DISABLED + { + component.getDisabledState().setForegroundColor(ColorRGBA.GRAY); + component.getDisabledState().setIcon(new SubTex(_sharedTex, 132, 9, 14, 14)); + } + // MOUSEOVER + { + component.getMouseOverState().setForegroundColor(ColorRGBA.BLACK); + component.getMouseOverState().setIcon(new SubTex(_sharedTex, 113, 9, 14, 14)); + } + // SELECTED + { + component.getSelectedState().setForegroundColor(ColorRGBA.BLACK); + component.getSelectedState().setIcon(new SubTex(_sharedTex, 94, 25, 14, 14)); + } + // MOUSEOVER SELECTED + { + component.getMouseOverSelectedState().setForegroundColor(ColorRGBA.BLACK); + component.getMouseOverSelectedState().setIcon(new SubTex(_sharedTex, 113, 25, 14, 14)); + } + // DISABLED SELECTED + { + component.getDisabledSelectedState().setForegroundColor(ColorRGBA.GRAY); + component.getDisabledSelectedState().setIcon(new SubTex(_sharedTex, 132, 25, 14, 14)); + } + } + + @Override + protected void applyToFrame(final UIFrame component) { + component.setOpacity(1.0f); + // TITLE BAR + { + final UIFrameBar titleBar = component.getTitleBar(); + // Make sure exists and is attached + if (titleBar != null && titleBar.getParent() == component) { + titleBar.setMargin(new Insets(0, 0, 0, 0)); + titleBar.setPadding(new Insets(0, 0, 0, 0)); + final UIBorder border = new ImageBorder( + // left + new SubTex(_sharedTex, 4, 11, 6, 6), + // right + new SubTex(_sharedTex, 30, 11, 6, 6), + // top + new SubTex(_sharedTex, 10, 5, 20, 6), + // bottom + new SubTex(_sharedTex, 9, 9, 20, 1), + // top left + new SubTex(_sharedTex, 4, 5, 6, 6), + // top right + new SubTex(_sharedTex, 30, 5, 6, 6), + // bottom left + new SubTex(_sharedTex, 4, 16, 6, 1), + // bottom right + new SubTex(_sharedTex, 30, 16, 6, 1)); + titleBar.setBorder(border); + final ColorRGBA top = new ColorRGBA(203 / 255f, 203 / 255f, 203 / 255f, 1); + final ColorRGBA bottom = new ColorRGBA(208 / 255f, 208 / 255f, 208 / 255f, 1); + final GradientBackdrop grad = new GradientBackdrop(top, top, bottom, bottom); + titleBar.setBackdrop(grad); + + titleBar.getTitleLabel().setMargin(new Insets(0, 5, 0, 0)); + titleBar.getTitleLabel().setForegroundColor(ColorRGBA.BLACK); + + // CLOSE BUTTON + { + final UIButton closeButton = titleBar.getCloseButton(); + if (closeButton != null) { + closeButton.setButtonText(""); + closeButton.setButtonIcon(new SubTex(_sharedTex, 94, 76, 16, 16)); + closeButton.getPressedState().setIcon(new SubTex(_sharedTex, 94, 94, 16, 16)); + for (final UIState state : closeButton.getStates()) { + state.setBackdrop(new EmptyBackdrop()); + state.setBorder(new EmptyBorder()); + state.setPadding(new Insets(0, 0, 0, 0)); + state.setMargin(new Insets(1, 1, 1, 1)); + } + closeButton.refreshState(); + closeButton.updateMinimumSizeFromContents(); + closeButton.compact(); + closeButton + .setMaximumContentSize(closeButton.getContentWidth(), closeButton.getContentHeight()); + } + } + + // MINIMIZE BUTTON + { + final UIButton minimizeButton = titleBar.getMinimizeButton(); + if (minimizeButton != null) { + minimizeButton.setButtonText(""); + minimizeButton.setButtonIcon(new SubTex(_sharedTex, 113, 76, 16, 16)); + minimizeButton.getPressedState().setIcon(new SubTex(_sharedTex, 113, 94, 16, 16)); + for (final UIState state : minimizeButton.getStates()) { + state.setBackdrop(new EmptyBackdrop()); + state.setBorder(new EmptyBorder()); + state.setPadding(new Insets(0, 0, 0, 0)); + state.setMargin(new Insets(1, 1, 1, 1)); + } + minimizeButton.refreshState(); + minimizeButton.updateMinimumSizeFromContents(); + minimizeButton.compact(); + minimizeButton.setMaximumContentSize(minimizeButton.getContentWidth(), minimizeButton + .getContentHeight()); + } + } + + // EXPAND BUTTON + { + final UIButton expandButton = titleBar.getExpandButton(); + if (expandButton != null) { + expandButton.setButtonText(""); + expandButton.setButtonIcon(new SubTex(_sharedTex, 132, 76, 16, 16)); + expandButton.getPressedState().setIcon(new SubTex(_sharedTex, 132, 94, 16, 16)); + for (final UIState state : expandButton.getStates()) { + state.setBackdrop(new EmptyBackdrop()); + state.setBorder(new EmptyBorder()); + state.setPadding(new Insets(0, 0, 0, 0)); + state.setMargin(new Insets(1, 1, 1, 1)); + } + expandButton.refreshState(); + expandButton.updateMinimumSizeFromContents(); + expandButton.compact(); + expandButton.setMaximumContentSize(expandButton.getContentWidth(), expandButton + .getContentHeight()); + } + } + + // MINIMIZE BUTTON + { + final UIButton helpButton = titleBar.getHelpButton(); + if (helpButton != null) { + helpButton.setButtonText(""); + helpButton.setButtonIcon(new SubTex(_sharedTex, 151, 76, 16, 16)); + helpButton.getPressedState().setIcon(new SubTex(_sharedTex, 151, 94, 16, 16)); + for (final UIState state : helpButton.getStates()) { + state.setBackdrop(new EmptyBackdrop()); + state.setBorder(new EmptyBorder()); + state.setPadding(new Insets(0, 0, 0, 0)); + state.setMargin(new Insets(1, 1, 1, 1)); + } + helpButton.refreshState(); + helpButton.updateMinimumSizeFromContents(); + helpButton.compact(); + helpButton.setMaximumContentSize(helpButton.getContentWidth(), helpButton.getContentHeight()); + } + } + } + } + + // BASE PANEL + { + final UIPanel base = component.getBasePanel(); + + base.setMargin(new Insets(0, 0, 0, 0)); + base.setPadding(new Insets(0, 0, 0, 0)); + + final UIBorder border = new ImageBorder( + // left + new SubTex(_sharedTex, 4, 17, 6, 29), + // right + new SubTex(_sharedTex, 30, 17, 6, 29), + // top + new SubTex(_sharedTex, 0, 0, 0, 0), + // bottom + new SubTex(_sharedTex, 10, 46, 20, 7), + // top left + null, + // top right + null, + // bottom left + new SubTex(_sharedTex, 4, 46, 6, 7), + // bottom right + new SubTex(_sharedTex, 30, 46, 6, 7)); + base.setBorder(border); + final ColorRGBA top = new ColorRGBA(210 / 255f, 210 / 255f, 210 / 255f, 1); + final ColorRGBA bottom = new ColorRGBA(244 / 255f, 244 / 255f, 244 / 255f, 1); + final GradientBackdrop grad = new GradientBackdrop(top, top, bottom, bottom); + base.setBackdrop(grad); + } + + // STATUS BAR + { + final UIFrameStatusBar statusBar = component.getStatusBar(); + // Make sure exists and is attached + if (statusBar != null && statusBar.getParent() == component.getBasePanel()) { + statusBar.setLocalComponentHeight(12); + statusBar.setMaximumContentHeight(statusBar.getContentHeight()); + + final UIButton resize = statusBar.getResizeButton(); + if (resize != null && resize.getParent() == statusBar) { + for (final UIState state : resize.getStates()) { + state.setBackdrop(new EmptyBackdrop()); + state.setBorder(new EmptyBorder()); + state.setPadding(new Insets(0, 0, 0, 0)); + state.setMargin(new Insets(0, 0, 0, 0)); + state.setForegroundColor(ColorRGBA.GRAY); + } + resize.refreshState(); + resize.updateMinimumSizeFromContents(); + resize.setMinimumContentSize(resize.getContentWidth(), resize.getContentHeight()); + resize.setMaximumContentSize(resize.getContentWidth(), resize.getContentHeight()); + } + } + } + } + + @Override + protected void applyToLabel(final UILabel component) { + component.getDefaultState().setForegroundColor(ColorRGBA.BLACK); + component.getDisabledState().setForegroundColor(ColorRGBA.GRAY); + } + + @Override + protected void applyToTextField(final UITextField component) { + + final SolidBorder border = new SolidBorder(1, 1, 1, 1); + border.setLeftColor(ColorRGBA.GRAY); + border.setTopColor(ColorRGBA.GRAY); + border.setRightColor(ColorRGBA.LIGHT_GRAY); + border.setBottomColor(ColorRGBA.LIGHT_GRAY); + + final SolidBackdrop backdrop = new SolidBackdrop(ColorRGBA.WHITE); + + component.setPadding(new Insets(1, 1, 1, 1)); + + for (final UIState state : component.getStates()) { + state.setBorder(border); + state.setBackdrop(backdrop); + if (state.equals(component.getDisabledState())) { + state.setForegroundColor(ColorRGBA.GRAY); + } else { + state.setForegroundColor(ColorRGBA.BLACK); + } + } + + } + + @Override + protected void applyToPasswordField(final UIPasswordField component) { + applyToTextField(component); + } + + @Override + protected void applyToTextArea(final UITextArea component) { + + final SolidBorder border = new SolidBorder(1, 1, 1, 1); + border.setLeftColor(ColorRGBA.GRAY); + border.setTopColor(ColorRGBA.GRAY); + border.setRightColor(ColorRGBA.LIGHT_GRAY); + border.setBottomColor(ColorRGBA.LIGHT_GRAY); + + final SolidBackdrop backdrop = new SolidBackdrop(ColorRGBA.WHITE); + + component.setPadding(new Insets(1, 1, 1, 1)); + + for (final UIState state : component.getStates()) { + state.setBorder(border); + state.setBackdrop(backdrop); + if (state.equals(component.getDisabledState())) { + state.setForegroundColor(ColorRGBA.GRAY); + } else { + state.setForegroundColor(ColorRGBA.BLACK); + } + } + + } + + @Override + protected void applyToPanel(final UIPanel component) { + ; // nothing to do + } + + @Override + protected void applyToProgressBar(final UIProgressBar component) { + final ColorRGBA top = new ColorRGBA(235 / 255f, 235 / 255f, 235 / 255f, 1); + final ColorRGBA bottom = new ColorRGBA(200 / 255f, 200 / 255f, 200 / 255f, 1); + final GradientBackdrop mainBack = new GradientBackdrop(top, top, bottom, bottom); + component.getMainPanel().setBackdrop(mainBack); + component.getMainPanel().setBorder(new EmptyBorder(0, 0, 0, 0)); + + final ImageBackdrop barBack = new ImageBackdrop(new SubTex(_sharedTex, 11, 59, 22, 15)); + component.getBar().setBackdrop(barBack); + } + + @Override + protected void applyToRadioButton(final UIRadioButton component) { + + component.setMargin(new Insets(1, 1, 1, 1)); + component.setPadding(new Insets(1, 1, 1, 1)); + component.setBorder(new EmptyBorder()); + component.setBackdrop(new EmptyBackdrop()); + component.setAlignment(Alignment.LEFT); + component.setGap(4); + + // DEFAULT + { + component.getDefaultState().setForegroundColor(ColorRGBA.BLACK); + component.getDefaultState().setIcon(new SubTex(_sharedTex, 94, 42, 14, 14)); + } + // DISABLED + { + component.getDisabledState().setForegroundColor(ColorRGBA.GRAY); + component.getDisabledState().setIcon(new SubTex(_sharedTex, 132, 42, 14, 14)); + } + // MOUSEOVER + { + component.getMouseOverState().setForegroundColor(ColorRGBA.BLACK); + component.getMouseOverState().setIcon(new SubTex(_sharedTex, 113, 42, 14, 14)); + } + // SELECTED + { + component.getSelectedState().setForegroundColor(ColorRGBA.BLACK); + component.getSelectedState().setIcon(new SubTex(_sharedTex, 94, 59, 14, 14)); + } + // MOUSEOVER SELECTED + { + component.getMouseOverSelectedState().setForegroundColor(ColorRGBA.BLACK); + component.getMouseOverSelectedState().setIcon(new SubTex(_sharedTex, 113, 59, 14, 14)); + } + // DISABLED SELECTED + { + component.getDisabledSelectedState().setForegroundColor(ColorRGBA.GRAY); + component.getDisabledSelectedState().setIcon(new SubTex(_sharedTex, 132, 59, 14, 14)); + } + } + + @Override + protected void applyToTooltip(final UITooltip component) { + component.setBackdrop(new SolidBackdrop(ColorRGBA.LIGHT_GRAY)); + component.setBorder(new SolidBorder(1, 1, 1, 1)); + component.setForegroundColor(ColorRGBA.BLACK); + component.setOpacity(1.0f); + } + + @Override + protected void applyToSlider(final UISlider component) { + final UISliderKnob knob = component.getKnob(); + knob.setBackdrop(null); + knob.setPadding(new Insets(0, 0, 0, 0)); + + if (component.getOrientation() == Orientation.Horizontal) { + knob.getKnobLabel().setIcon(new SubTex(_sharedTex, 42, 80, 16, 14)); + knob.setMargin(new Insets(0, 1, 0, 1)); + } else { + knob.getKnobLabel().setIcon(new SubTex(_sharedTex, 69, 72, 14, 16)); + knob.setMargin(new Insets(1, 0, 1, 0)); + } + + final UIPanel back = component.getBackPanel(); + if (component.getOrientation() == Orientation.Horizontal) { + final UIBorder border = new ImageBorder( + // left + new SubTex(_sharedTex, 7, 85, 4, 7), + // right + new SubTex(_sharedTex, 33, 85, 4, 7), + // top + new SubTex(_sharedTex, 11, 79, 22, 6), + // bottom + new SubTex(_sharedTex, 11, 92, 22, 4), + // top left + new SubTex(_sharedTex, 7, 79, 4, 6), + // top right + new SubTex(_sharedTex, 33, 79, 4, 6), + // bottom left + new SubTex(_sharedTex, 7, 92, 4, 4), + // bottom right + new SubTex(_sharedTex, 33, 92, 4, 4)); + back.setBorder(border); + back.setMinimumContentSize(1, 7); + } else { + final UIBorder border = new ImageBorder( + // left + new SubTex(_sharedTex, 67, 97, 5, 19), + // right + new SubTex(_sharedTex, 80, 97, 5, 19), + // top + new SubTex(_sharedTex, 72, 91, 8, 6), + // bottom + new SubTex(_sharedTex, 72, 117, 8, 4), + // top left + new SubTex(_sharedTex, 67, 91, 5, 6), + // top right + new SubTex(_sharedTex, 80, 91, 5, 6), + // bottom left + new SubTex(_sharedTex, 67, 117, 5, 4), + // bottom right + new SubTex(_sharedTex, 80, 117, 5, 4)); + back.setBorder(border); + back.setMinimumContentSize(8, 1); + } + back.setLayout(null); + back.setBackdrop(new SolidBackdrop(ColorRGBA.WHITE)); + } + + @Override + protected void applyToPopupMenu(final UIPopupMenu component) { + component.getTitleBar().removeFromParent(); + component.getStatusBar().removeFromParent(); + applyToFrame(component); + } + + @Override + protected void applyToComboBox(final UIComboBox component) { + final ColorRGBA upTop = new ColorRGBA(235 / 255f, 235 / 255f, 235 / 255f, 1); + final ColorRGBA upBottom = new ColorRGBA(200 / 255f, 200 / 255f, 200 / 255f, 1); + final GradientBackdrop upBack = new GradientBackdrop(upTop, upTop, upBottom, upBottom); + + // value label + { + final UIBorder labelBorder = new ImageBorder( + // left + new SubTex(_sharedTex, 155, 11, 4, 10), + // right + new SubTex(_sharedTex, 185, 11, 4, 10), + // top + new SubTex(_sharedTex, 159, 7, 16, 4), + // bottom + new SubTex(_sharedTex, 159, 21, 16, 4), + // top left + new SubTex(_sharedTex, 155, 7, 4, 4), + // top right + new SubTex(_sharedTex, 177, 7, 1, 4), + // bottom left + new SubTex(_sharedTex, 155, 21, 4, 4), + // bottom right + new SubTex(_sharedTex, 177, 21, 1, 4)); + + final UILabel label = component.getValueLabel(); + label.setBackdrop(upBack); + label.setBorder(labelBorder); + label.setAlignment(Alignment.LEFT); + label.setPadding(new Insets(0, 2, 0, 2)); + } + + // drop down button + { + final UIBorder buttonBorder = new ImageBorder( + // left + new SubTex(_sharedTex, 177, 11, 1, 10), + // right + new SubTex(_sharedTex, 185, 11, 4, 10), + // top + new SubTex(_sharedTex, 178, 7, 7, 4), + // bottom + new SubTex(_sharedTex, 178, 21, 7, 4), + // top left + new SubTex(_sharedTex, 177, 7, 1, 4), + // top right + new SubTex(_sharedTex, 185, 7, 4, 4), + // bottom left + new SubTex(_sharedTex, 177, 21, 1, 4), + // bottom right + new SubTex(_sharedTex, 185, 21, 4, 4)); + + final UIButton button = component.getOpenButton(); + button.setButtonText(""); + button.setButtonIcon(new SubTex(_sharedTex, 196, 12, 10, 9)); + button.getMouseOverState().setIcon(new SubTex(_sharedTex, 210, 12, 10, 9)); + button.setBorder(buttonBorder); + button.setBackdrop(upBack); + button.setMargin(new Insets(0, 0, 0, 0)); + button.setPadding(new Insets(0, 1, 0, 1)); + for (final UIState state : button.getStates()) { + state.setBorder(buttonBorder); + state.setBackdrop(upBack); + } + } + + // skin for menuitems + { + final EmptyBorder itemBorder = new EmptyBorder(); + final EmptyBackdrop itemBackdrop = new EmptyBackdrop(); + final SolidBackdrop overBackdrop = new SolidBackdrop(new ColorRGBA(50 / 255f, 50 / 255f, 200 / 255f, 1)); + component.setItemSkinCallback(new SkinningTask() { + @Override + public void skinComponent(final UIComponent c) { + c.setBorder(itemBorder); + c.setBackdrop(itemBackdrop); + c.setMargin(new Insets(0, 0, 0, 0)); + c.setPadding(new Insets(0, 2, 0, 2)); + c.setForegroundColor(ColorRGBA.BLACK); + if (c instanceof UIButton) { + final UIButton button = (UIButton) c; + button.setAlignment(Alignment.LEFT); + for (final UIState state : button.getStates()) { + state.setBorder(null); + state.setBackdrop(itemBackdrop); + state.setForegroundColor(ColorRGBA.BLACK); + } + final LabelState over = button.getMouseOverState(); + over.setForegroundColor(ColorRGBA.WHITE); + over.setBackdrop(overBackdrop); + } + } + }); + } + } + + @Override + protected void applyToScrollBar(final UIScrollBar component) { + final SolidBorder border = new SolidBorder(1, 1, 1, 1); + border.setColor(new ColorRGBA(165 / 255f, 165 / 255f, 165 / 255f, 1f)); + component.setMargin(new Insets()); + component.setPadding(new Insets()); + component.setBorder(border); + { + final UIButton button = component.getBtTopLeft(); + button.setBackdrop(null); + button.setBorder(new EmptyBorder()); + button.setPadding(new Insets(0, 0, 0, 0)); + button.setMargin(new Insets(0, 0, 0, 0)); + for (final UIState state : button.getStates()) { + state.setBorder(null); + state.setBackdrop(null); + } + button.setButtonText(""); + if (component.getOrientation() == Orientation.Horizontal) { + button.setButtonIcon(new SubTex(_sharedTex, 130, 121, 16, 15)); + button.getMouseOverState().setIcon(new SubTex(_sharedTex, 130, 137, 16, 15)); + } else { + button.setButtonIcon(new SubTex(_sharedTex, 97, 120, 15, 16)); + button.getMouseOverState().setIcon(new SubTex(_sharedTex, 113, 120, 15, 16)); + } + } + { + final UIButton button = component.getBtBottomRight(); + button.setBackdrop(null); + button.setBorder(new EmptyBorder()); + button.setPadding(new Insets(0, 0, 0, 0)); + button.setMargin(new Insets(0, 0, 0, 0)); + for (final UIState state : button.getStates()) { + state.setBorder(null); + state.setBackdrop(null); + } + button.setButtonText(""); + if (component.getOrientation() == Orientation.Horizontal) { + button.setButtonIcon(new SubTex(_sharedTex, 147, 121, 16, 15)); + button.getMouseOverState().setIcon(new SubTex(_sharedTex, 147, 137, 16, 15)); + } else { + button.setButtonIcon(new SubTex(_sharedTex, 97, 137, 15, 16)); + button.getMouseOverState().setIcon(new SubTex(_sharedTex, 113, 137, 15, 16)); + } + } + { + final UISlider slider = component.getSlider(); + slider.getBackPanel().setBorder(new EmptyBorder()); + slider.setMargin(new Insets()); + slider.setPadding(new Insets()); + slider.getBackPanel().setLayout(new RowLayout(false)); + + final UISliderKnob knob = slider.getKnob(); + knob.getKnobLabel().setIcon(null); + knob.setPadding(new Insets(0, 0, 0, 0)); + knob.setMargin(new Insets()); + final ColorRGBA colorTop = new ColorRGBA(235 / 255f, 235 / 255f, 235 / 255f, 1); + final ColorRGBA colorBtm = new ColorRGBA(200 / 255f, 200 / 255f, 200 / 255f, 1); + final GradientBackdrop knobColor = new GradientBackdrop(colorTop, colorTop, colorBtm, colorBtm); + knob.getKnobLabel().setBackdrop(knobColor); + knob.getKnobLabel().setBorder(border); + } + } +} diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/AwtCopyPasteImpl.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/AwtCopyPasteImpl.java new file mode 100644 index 0000000..7a67258 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/AwtCopyPasteImpl.java @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui.text; + +import java.awt.Toolkit; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.StringSelection; +import java.awt.datatransfer.Transferable; + +public class AwtCopyPasteImpl implements CopyPasteImpl { + + @Override + public String getClipBoardContents() { + final Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); + final Transferable clipboardContent = clipboard.getContents(null); + + if (clipboardContent != null && clipboardContent.isDataFlavorSupported(DataFlavor.stringFlavor)) { + try { + return (String) clipboardContent.getTransferData(DataFlavor.stringFlavor); + } catch (final Exception e) { + e.printStackTrace(); + } + } + return null; + } + + @Override + public void setClipBoardContents(final String contents) { + final Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); + final StringSelection string = new StringSelection(contents); + clipboard.setContents(string, null); + } +} diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/CharacterDescriptor.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/CharacterDescriptor.java new file mode 100644 index 0000000..2daa02f --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/CharacterDescriptor.java @@ -0,0 +1,118 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui.text; + +import com.ardor3d.math.ColorRGBA; +import com.ardor3d.math.type.ReadOnlyColorRGBA; + +public class CharacterDescriptor { + + /** The x location, in pixels, of our upper left corner */ + private final int _x; + /** The y location, in pixels, of our upper left corner */ + private final int _y; + + /** The width, in pixels, of our part of the texture */ + private final int _width; + /** The height, in pixels, of our part of the texture */ + private final int _height; + + /** pixels to advance the pen by when drawing this character */ + private final int _xAdvance; + + /** offset from character origin to draw this character */ + private final int _xOffset, _yOffset; + + /** scaling to apply - optional */ + private double _scale = 1; + + /** tiny to apply - optional */ + private ColorRGBA _tint = null; + + public CharacterDescriptor(final int x, final int y, final int width, final int height, final int xAdvance) { + this(xAdvance, y, width, height, xAdvance, 0, 0, 1, null); + } + + public CharacterDescriptor(final CharacterDescriptor source) { + this(source._x, source._y, source._width, source._height, source._xAdvance, source._xOffset, source._yOffset, + source._scale, source._tint); + } + + public CharacterDescriptor(final int x, final int y, final int width, final int height, final int xAdvance, + final int xOffset, final int yOffset, final double scale, final ReadOnlyColorRGBA tint) { + _x = x; + _y = y; + _width = width; + _height = height; + _xAdvance = xAdvance; + _xOffset = xOffset; + _yOffset = yOffset; + setTint(tint); + } + + public int getXAdvance() { + return _xAdvance; + } + + public int getXOffset() { + return _xOffset; + } + + public int getYOffset() { + return _yOffset; + } + + public int getX() { + return _x; + } + + public int getY() { + return _y; + } + + public int getHeight() { + return _height; + } + + public int getWidth() { + return _width; + } + + public double getScale() { + return _scale; + } + + public void setScale(final double scale) { + _scale = scale; + } + + public ReadOnlyColorRGBA getTint() { + return _tint; + } + + public void setTint(final ReadOnlyColorRGBA tint) { + if (tint == null) { + _tint = null; + } else if (_tint == null) { + _tint = new ColorRGBA(tint); + } else { + _tint.set(tint); + } + } + + public void setTintAlpha(final float alpha) { + if (_tint == null) { + _tint = new ColorRGBA(1.0f, 1.0f, 1.0f, alpha); + } else { + _tint.setAlpha(alpha); + } + } +} diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/CopyPasteImpl.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/CopyPasteImpl.java new file mode 100644 index 0000000..b059b98 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/CopyPasteImpl.java @@ -0,0 +1,17 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui.text; + +public interface CopyPasteImpl { + String getClipBoardContents(); + + void setClipBoardContents(String contents); +} diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/CopyPasteManager.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/CopyPasteManager.java new file mode 100644 index 0000000..a2d47b0 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/CopyPasteManager.java @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui.text; + +public enum CopyPasteManager { + INSTANCE; + + private CopyPasteImpl _impl; + + public void setCopyPasteImpl(final CopyPasteImpl impl) { + _impl = impl; + } + + public String getClipBoardContents() { + if (_impl == null) { + _impl = new AwtCopyPasteImpl(); + } + return _impl.getClipBoardContents(); + } + + public void setClipBoardContents(final String contents) { + if (_impl == null) { + _impl = new AwtCopyPasteImpl(); + } + _impl.setClipBoardContents(contents); + } +} diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/DefaultLatinTextAreaKeyHandler.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/DefaultLatinTextAreaKeyHandler.java new file mode 100644 index 0000000..b0160bb --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/DefaultLatinTextAreaKeyHandler.java @@ -0,0 +1,270 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui.text; + +import com.ardor3d.extension.ui.UITextArea; +import com.ardor3d.input.InputState; +import com.ardor3d.input.Key; + +public class DefaultLatinTextAreaKeyHandler implements UIKeyHandler { + + protected final UITextArea _textArea; + + public DefaultLatinTextAreaKeyHandler(final UITextArea textArea) { + _textArea = textArea; + } + + @Override + public boolean keyReleased(final Key key, final InputState state) { + return true; + } + + @Override + public boolean keyHeld(final Key key, final InputState state) { + return true; + } + + @Override + public boolean keyPressed(final Key key, final InputState state) { + // grab our text + String text = _textArea.getText(); + + // get some meta key states + final boolean shiftKeyDown = state.getKeyboardState().isAtLeastOneDown(Key.LSHIFT, Key.RSHIFT); + final boolean ctrlKeyDown = System.getProperty("mrj.version") == null ? + // non-mac + state.getKeyboardState().isAtLeastOneDown(Key.LCONTROL, Key.RCONTROL) + : + // mac + state.getKeyboardState().isAtLeastOneDown(Key.LMETA, Key.RMETA); + + // get our current caret location + int caretPosition = _textArea.getCaretPosition(); + if (caretPosition > text.length()) { + caretPosition = _textArea.setCaretPosition(text.length()); + } + + // get our text selection object + final TextSelection selection = _textArea.getSelection(); + + // divide the text based on caret position. + String s1 = text.substring(0, caretPosition); + String s2 = text.substring(caretPosition, text.length()); + + // look to handle special keys + switch (key) { + case X: { + // CUT + if (!_textArea.isEditable() || !ctrlKeyDown) { + break; + } + + if (_textArea.isCopyable() && selection.getSelectionLength() > 0) { + final String selectedText = text.substring(selection.getStartIndex(), _textArea.getSelection() + .getStartIndex() + + _textArea.getSelectionLength()); + CopyPasteManager.INSTANCE.setClipBoardContents(selectedText); + _textArea.deleteSelectedText(); + text = _textArea.getText(); + if (text == null) { + text = ""; + } + caretPosition = _textArea.setCaretPosition(selection.getStartIndex()); + _textArea.clearSelection(); + } + + return true; + } + + case C: { + // COPY + if (!ctrlKeyDown) { + break; + } + if (_textArea.isCopyable()) { + final String selectedText = text.substring(selection.getStartIndex(), _textArea.getSelection() + .getStartIndex() + + _textArea.getSelectionLength()); + CopyPasteManager.INSTANCE.setClipBoardContents(selectedText); + } + return true; + } + + case V: { + // PASTE + if (!_textArea.isEditable() || !ctrlKeyDown) { + break; + } + final String clipContents = CopyPasteManager.INSTANCE.getClipBoardContents(); + if (clipContents != null) { + if (selection.getStartIndex() < _textArea.getSelection().getEndIndex()) { + _textArea.deleteSelectedText(); + text = _textArea.getText(); + if (text == null) { + text = ""; + } + caretPosition = _textArea.setCaretPosition(selection.getStartIndex()); + _textArea.clearSelection(); + s1 = text.substring(0, caretPosition); + s2 = text.substring(caretPosition, text.length()); + } + _textArea.setText(s1 + clipContents + s2); + caretPosition = _textArea.setCaretPosition(caretPosition + clipContents.length()); + } + return true; + } + + case BACK: { + // Backspace + if (!_textArea.isEditable()) { + return false; + } + if (_textArea.getSelection().getSelectionLength() > 0) { + _textArea.deleteSelectedText(); + text = _textArea.getText(); + if (text == null) { + text = ""; + } + caretPosition = _textArea.setCaretPosition(selection.getStartIndex()); + _textArea.clearSelection(); + } else if (s1.length() > 0) { + _textArea.setText(s1.substring(0, s1.length() - 1) + s2); + caretPosition = _textArea.setCaretPosition(caretPosition - 1); + } else { + _textArea.setText(s2); + caretPosition = _textArea.setCaretPosition(0); + } + return true; + } + + case DELETE: { + // delete + if (!_textArea.isEditable()) { + break; + } + if (_textArea.getSelection().getSelectionLength() > 0) { + _textArea.deleteSelectedText(); + text = _textArea.getText(); + if (text == null) { + text = ""; + } + caretPosition = _textArea.setCaretPosition(selection.getStartIndex()); + _textArea.clearSelection(); + } else if (s2.length() > 0) { + _textArea.setText(s1 + s2.substring(1, s2.length())); + } + return true; + } + + case UP: + // TODO + break; + + case DOWN: + // TODO + break; + + case RIGHT: { + // check if a selection should be started + if (shiftKeyDown) { + _textArea.getSelection().checkStart(); + } + + if (caretPosition < text.length()) { + caretPosition = _textArea.setCaretPosition(caretPosition + 1); + } + if (shiftKeyDown) { + _textArea.getSelection().rightKey(); + } else { + _textArea.getSelection().reset(); + } + _textArea.fireComponentDirty(); + return true; + } + + case LEFT: { + // check if a selection should be started + if (shiftKeyDown) { + _textArea.getSelection().checkStart(); + } + + if (caretPosition > 0) { + caretPosition = _textArea.setCaretPosition(caretPosition - 1); + } + if (shiftKeyDown) { + _textArea.getSelection().leftKey(); + } else { + _textArea.getSelection().reset(); + } + _textArea.fireComponentDirty(); + return true; + } + + case HOME: { + // check if a selection should be started + if (shiftKeyDown) { + _textArea.getSelection().checkStart(); + } + + if (caretPosition > 0) { + caretPosition = _textArea.setCaretPosition(0); + } + if (shiftKeyDown) { + _textArea.getSelection().upKey(); + } else { + _textArea.getSelection().reset(); + } + _textArea.fireComponentDirty(); + return true; + } + + case END: { + // check if a selection should be started + if (shiftKeyDown) { + _textArea.getSelection().checkStart(); + } + + if (caretPosition < text.length()) { + _textArea.setCaretPosition(text.length()); + } + if (shiftKeyDown) { + _textArea.getSelection().downKey(); + } else { + _textArea.getSelection().reset(); + } + _textArea.fireComponentDirty(); + return true; + } + } + + if (_textArea.isEditable()) { + final char c = state.getKeyboardState().getKeyEvent().getKeyChar(); + if (c >= 32 && c != (char) -1) { + if (selection.getSelectionLength() > 0) { + _textArea.deleteSelectedText(); + text = _textArea.getText(); + if (text == null) { + text = ""; + } + caretPosition = _textArea.setCaretPosition(selection.getStartIndex()); + _textArea.clearSelection(); + s1 = text.substring(0, caretPosition); + s2 = text.substring(caretPosition, text.length()); + } + + _textArea.setText(s1 + c + s2); + caretPosition = _textArea.setCaretPosition(caretPosition + 1); + } + } + + return true; + } +} diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/DefaultLatinTextFieldKeyHandler.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/DefaultLatinTextFieldKeyHandler.java new file mode 100644 index 0000000..86ba8da --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/DefaultLatinTextFieldKeyHandler.java @@ -0,0 +1,269 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui.text; + +import com.ardor3d.extension.ui.UITextField; +import com.ardor3d.input.InputState; +import com.ardor3d.input.Key; + +public class DefaultLatinTextFieldKeyHandler implements UIKeyHandler { + + private final UITextField _textField; + + public DefaultLatinTextFieldKeyHandler(final UITextField textField) { + _textField = textField; + } + + @Override + public boolean keyReleased(final Key key, final InputState state) { + return true; + } + + @Override + public boolean keyHeld(final Key key, final InputState state) { + return true; + } + + @Override + public boolean keyPressed(final Key key, final InputState state) { + // grab our text + String text = _textField.getText(); + + // get some meta key states + final boolean shiftKeyDown = state.getKeyboardState().isAtLeastOneDown(Key.LSHIFT, Key.RSHIFT); + final boolean ctrlKeyDown = System.getProperty("mrj.version") == null ? + // non-mac + state.getKeyboardState().isAtLeastOneDown(Key.LCONTROL, Key.RCONTROL) + : + // mac + state.getKeyboardState().isAtLeastOneDown(Key.LMETA, Key.RMETA); + + // get our current caret location + int caretPosition = _textField.getCaretPosition(); + if (caretPosition > text.length()) { + caretPosition = _textField.setCaretPosition(text.length()); + } + + // get our text selection object + final TextSelection selection = _textField.getSelection(); + + // divide the text based on caret position. + String s1 = text.substring(0, caretPosition); + String s2 = text.substring(caretPosition, text.length()); + + // look to handle special keys + switch (key) { + case RETURN: { + // ACTION + _textField.fireActionEvent(); + return true; + } + case X: { + // CUT + if (!_textField.isEditable() || !ctrlKeyDown) { + break; + } + + if (_textField.isCopyable() && selection.getSelectionLength() > 0) { + final String selectedText = text.substring(selection.getStartIndex(), _textField.getSelection() + .getStartIndex() + + _textField.getSelectionLength()); + CopyPasteManager.INSTANCE.setClipBoardContents(selectedText); + _textField.deleteSelectedText(); + text = _textField.getText(); + if (text == null) { + text = ""; + } + caretPosition = _textField.setCaretPosition(selection.getStartIndex()); + _textField.clearSelection(); + } + + return true; + } + + case C: { + // COPY + if (!ctrlKeyDown) { + break; + } + if (_textField.isCopyable()) { + final String selectedText = text.substring(selection.getStartIndex(), _textField.getSelection() + .getStartIndex() + + _textField.getSelectionLength()); + CopyPasteManager.INSTANCE.setClipBoardContents(selectedText); + } + return true; + } + + case V: { + // PASTE + if (!_textField.isEditable() || !ctrlKeyDown) { + break; + } + final String clipContents = CopyPasteManager.INSTANCE.getClipBoardContents(); + if (clipContents != null) { + if (selection.getStartIndex() < _textField.getSelection().getEndIndex()) { + _textField.deleteSelectedText(); + text = _textField.getText(); + if (text == null) { + text = ""; + } + caretPosition = _textField.setCaretPosition(selection.getStartIndex()); + _textField.clearSelection(); + s1 = text.substring(0, caretPosition); + s2 = text.substring(caretPosition, text.length()); + } + _textField.setText(s1 + clipContents + s2); + caretPosition = _textField.setCaretPosition(caretPosition + clipContents.length()); + } + return true; + } + + case BACK: { + // Backspace + if (!_textField.isEditable()) { + return false; + } + if (_textField.getSelection().getSelectionLength() > 0) { + _textField.deleteSelectedText(); + text = _textField.getText(); + if (text == null) { + text = ""; + } + caretPosition = _textField.setCaretPosition(selection.getStartIndex()); + _textField.clearSelection(); + } else if (s1.length() > 0) { + _textField.setText(s1.substring(0, s1.length() - 1) + s2); + caretPosition = _textField.setCaretPosition(caretPosition - 1); + } else { + _textField.setText(s2); + caretPosition = _textField.setCaretPosition(0); + } + return true; + } + + case DELETE: { + // delete + if (!_textField.isEditable()) { + break; + } + if (_textField.getSelection().getSelectionLength() > 0) { + _textField.deleteSelectedText(); + text = _textField.getText(); + if (text == null) { + text = ""; + } + caretPosition = _textField.setCaretPosition(selection.getStartIndex()); + _textField.clearSelection(); + } else if (s2.length() > 0) { + _textField.setText(s1 + s2.substring(1, s2.length())); + } + return true; + } + + case RIGHT: { + // check if a selection should be started + if (shiftKeyDown) { + _textField.getSelection().checkStart(); + } + + if (caretPosition < text.length()) { + caretPosition = _textField.setCaretPosition(caretPosition + 1); + } + if (shiftKeyDown) { + _textField.getSelection().rightKey(); + } else { + _textField.getSelection().reset(); + } + _textField.fireComponentDirty(); + return true; + } + + case LEFT: { + // check if a selection should be started + if (shiftKeyDown) { + _textField.getSelection().checkStart(); + } + + if (caretPosition > 0) { + caretPosition = _textField.setCaretPosition(caretPosition - 1); + } + if (shiftKeyDown) { + _textField.getSelection().leftKey(); + } else { + _textField.getSelection().reset(); + } + _textField.fireComponentDirty(); + return true; + } + + case UP: + case HOME: { + // check if a selection should be started + if (shiftKeyDown) { + _textField.getSelection().checkStart(); + } + + if (caretPosition > 0) { + caretPosition = _textField.setCaretPosition(0); + } + if (shiftKeyDown) { + _textField.getSelection().upKey(); + } else { + _textField.getSelection().reset(); + } + _textField.fireComponentDirty(); + return true; + } + + case DOWN: + case END: { + // check if a selection should be started + if (shiftKeyDown) { + _textField.getSelection().checkStart(); + } + + if (caretPosition < text.length()) { + _textField.setCaretPosition(text.length()); + } + if (shiftKeyDown) { + _textField.getSelection().downKey(); + } else { + _textField.getSelection().reset(); + } + _textField.fireComponentDirty(); + return true; + } + } + + if (_textField.isEditable()) { + final char c = state.getKeyboardState().getKeyEvent().getKeyChar(); + if (c >= 32 && c != (char) -1) { + if (selection.getSelectionLength() > 0) { + _textField.deleteSelectedText(); + text = _textField.getText(); + if (text == null) { + text = ""; + } + caretPosition = _textField.setCaretPosition(selection.getStartIndex()); + _textField.clearSelection(); + s1 = text.substring(0, caretPosition); + s2 = text.substring(caretPosition, text.length()); + } + + _textField.setText(s1 + c + s2); + caretPosition = _textField.setCaretPosition(caretPosition + 1); + } + } + + return true; + } +} diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/RenderedText.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/RenderedText.java new file mode 100644 index 0000000..ac75b7a --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/RenderedText.java @@ -0,0 +1,229 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui.text; + +import java.util.Collection; +import java.util.List; + +import com.ardor3d.math.Vector2; +import com.ardor3d.math.type.ReadOnlyTransform; +import com.ardor3d.renderer.Renderer; +import com.ardor3d.scenegraph.Node; +import com.ardor3d.scenegraph.Renderable; +import com.ardor3d.scenegraph.Spatial; +import com.ardor3d.scenegraph.event.DirtyType; +import com.ardor3d.util.scenegraph.RenderDelegate; +import com.google.common.collect.Lists; + +public class RenderedText extends Node implements Renderable { + + protected String _plainText = null; + protected List<StyleSpan> _parsedStyles = Lists.newLinkedList(); + + protected float _width; + protected float _height; + protected final RenderedTextData data = new RenderedTextData(); + + protected boolean _styled = false; + + public RenderedText() {} + + public String getText() { + if (!isStyled()) { + return _plainText; + } else { + return TextFactory.INSTANCE.getMarkedUpText(_plainText, _parsedStyles); + } + } + + public void setPlainText(final String text) { + _plainText = text; + } + + public String getPlainText() { + return _plainText; + } + + public void setHeight(final float height) { + _height = height; + } + + public float getHeight() { + return _height; + } + + public void setWidth(final float width) { + _width = width; + } + + public float getWidth() { + return _width; + } + + public List<StyleSpan> getParsedStyleSpans() { + return _parsedStyles; + } + + public void setParsedStyleSpans(final Collection<StyleSpan> spans) { + _parsedStyles.clear(); + _parsedStyles.addAll(spans); + } + + @Override + public int attachChild(final Spatial child) { + if (!(child instanceof TextMesh)) { + throw new IllegalArgumentException("Must be a TextMesh!"); + } + return super.attachChild(child); + } + + @Override + public int attachChildAt(final Spatial child, final int index) { + if (!(child instanceof TextMesh)) { + throw new IllegalArgumentException("Must be a TextMesh!"); + } + return super.attachChildAt(child, index); + } + + @Override + public void draw(final Renderer r) { + if (!r.isProcessingQueue()) { + if (r.checkAndAdd(this)) { + return; + } + } + + final RenderDelegate delegate = getCurrentRenderDelegate(); + if (delegate == null) { + r.draw((Renderable) this); + } else { + delegate.render(this, r); + } + } + + @Override + public void updateWorldBound(final boolean recurse) { + clearDirty(DirtyType.Bounding); + } + + @Override + public void render(final Renderer renderer) { + for (int i = getNumberOfChildren() - 1; i >= 0; i--) { + ((TextMesh) _children.get(i)).render(renderer); + } + } + + @Override + public void setWorldTransform(final ReadOnlyTransform transform) { + for (int i = getNumberOfChildren() - 1; i >= 0; i--) { + ((TextMesh) _children.get(i)).setWorldTransform(transform); + } + } + + public RenderedTextData getData() { + return data; + } + + public Vector2 findCaretTranslation(final int caretPosition, final Vector2 store) { + Vector2 rVal = store; + if (rVal == null) { + rVal = new Vector2(0, 0); + } + + if (data._lineHeights == null) { + return rVal; + } + + int lineHeight = data._lineHeights.get(0); + int cursorY = 0; + for (int j = 1; j < data._lineEnds.size(); j++) { + if (data._lineEnds.get(j) < caretPosition) { + cursorY += lineHeight; + lineHeight = data._lineHeights.get(j); + } else { + break; + } + } + + if (caretPosition < data._xStarts.size()) { + rVal.setX(data._xStarts.get(caretPosition)); + } else { + final CharacterDescriptor charDesc = data._characters.get(caretPosition - 1); + rVal.setX(data._xStarts.get(caretPosition - 1) + + (int) Math.round(charDesc.getScale() * charDesc.getXAdvance())); + } + rVal.setY(cursorY); + + return rVal; + } + + public int findCaretPosition(final int x, final int y) { + int height = 0; + int position = 0; + final int max = data._lineEnds.size(); + int line; + for (line = 0; line < max; line++) { + height += data._lineHeights.get(line); + + if (height < y) { + position = data._lineEnds.get(line) + 1; + } else { + break; + } + } + + if (line < max) { + for (int i = 0, maxX = data._lineEnds.get(line); i <= maxX; i++) { + if (data._xStarts.get(position) + data._characters.get(position).getXAdvance() / 2 < x) { + position++; + } else { + break; + } + } + } + + return position; + } + + public int getLineHeight(final int caretPosition) { + if (caretPosition < data._fontHeights.size()) { + return data._fontHeights.get(caretPosition); + } else { + return data._fontHeights.get(data._fontHeights.size() - 1); + } + } + + public static class RenderedTextData { + public List<Integer> _xStarts = Lists.newArrayList(); + public List<Integer> _lineHeights = Lists.newArrayList(); + public List<Integer> _lineEnds = Lists.newArrayList(); + public List<Integer> _fontHeights = Lists.newArrayList(); + public List<CharacterDescriptor> _characters = Lists.newArrayList(); + + public RenderedTextData() {} + + public void reset() { + _xStarts.clear(); + _lineHeights.clear(); + _lineEnds.clear(); + _fontHeights.clear(); + _characters.clear(); + } + } + + public void setStyled(final boolean styled) { + _styled = styled; + } + + public boolean isStyled() { + return _styled; + } +} diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/StyleConstants.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/StyleConstants.java new file mode 100644 index 0000000..cdd2912 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/StyleConstants.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui.text; + +public class StyleConstants { + + /** Is the text bold? Expects a Boolean value. */ + public static final String KEY_BOLD = "_style_bold"; + + /** Is the text italic? Expects a Boolean value. */ + public static final String KEY_ITALICS = "_style_italics"; + + /** What font family should we use? Expects a String value. */ + public static final String KEY_FAMILY = "_style_family"; + + /** What size font should we use? Expects an Integer value. */ + public static final String KEY_SIZE = "_style_size"; + + /** What color should the text be? Expects a ReadOnlyColorRGBA value. */ + public static final String KEY_COLOR = "_style_color"; + +} diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/StyleSpan.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/StyleSpan.java new file mode 100644 index 0000000..111a287 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/StyleSpan.java @@ -0,0 +1,67 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui.text; + +public class StyleSpan implements Comparable<StyleSpan> { + protected int _spanStart; + protected int _spanLength; + protected String _style; + protected Object _value; + + public StyleSpan() {} + + public StyleSpan(final String style, final Object value, final int start, final int length) { + _style = style; + _value = value; + _spanStart = start; + _spanLength = length; + } + + public int getSpanStart() { + return _spanStart; + } + + public void setSpanStart(final int spanStart) { + _spanStart = spanStart; + } + + public int getSpanLength() { + return _spanLength; + } + + public void setSpanLength(final int length) { + _spanLength = length; + } + + public String getStyle() { + return _style; + } + + public void setStyle(final String style) { + _style = style; + } + + public Object getValue() { + return _value; + } + + public void setValue(final Object value) { + _value = value; + } + + @Override + public int compareTo(final StyleSpan span) { + if (_spanStart == span._spanStart) { + return span._spanLength - _spanLength; + } + return _spanStart - span._spanStart; + } +} diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/TextCaret.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/TextCaret.java new file mode 100644 index 0000000..4e30461 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/TextCaret.java @@ -0,0 +1,131 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui.text; + +import com.ardor3d.extension.ui.UIComponent; +import com.ardor3d.math.ColorRGBA; +import com.ardor3d.math.Transform; +import com.ardor3d.math.Vector3; +import com.ardor3d.math.type.ReadOnlyColorRGBA; +import com.ardor3d.renderer.IndexMode; +import com.ardor3d.renderer.Renderer; +import com.ardor3d.scenegraph.Mesh; +import com.ardor3d.scenegraph.MeshData; +import com.ardor3d.util.geom.BufferUtils; + +public class TextCaret { + + private long _blinkInterval = 500; // ms + private long _lastBlink = 0; + private boolean _show = true; + private int _posX, _posY; + private int _index; + + private final Mesh _strip = new Mesh(); + + /** + * Construct a new TextCaret + */ + public TextCaret() { + final MeshData md = _strip.getMeshData(); + md.setVertexBuffer(BufferUtils.createVector3Buffer(4)); + md.setIndexBuffer(BufferUtils.createIntBuffer(new int[] { 0, 1, 3, 2 })); + md.setIndexMode(IndexMode.TriangleStrip); + final float[] vals = new float[] { 0, 0, 0, // + 1, 0, 0, // + 1, 1, 0, // + 0, 1, 0 // + }; + md.getVertexBuffer().put(vals); + _strip.updateGeometricState(0); + + setCaretColor(ColorRGBA.BLACK); + } + + public boolean isShowing() { + final long curr = System.currentTimeMillis(); + if (curr - _lastBlink > _blinkInterval) { + _lastBlink = curr; + _show = !_show; + } + + return _show; + } + + public void draw(final Renderer renderer, final UIComponent comp, final int height, final double xOffset, + final double yOffset) { + final long curr = System.currentTimeMillis(); + if (curr - _lastBlink > _blinkInterval) { + _lastBlink = curr; + _show = !_show; + comp.fireComponentDirty(); + } + + if (!_show) { + return; + } + + final Vector3 v = Vector3.fetchTempInstance(); + v.set(getPosX() + xOffset, getPosY() + yOffset, 0); + + final Transform t = Transform.fetchTempInstance(); + t.set(comp.getWorldTransform()); + t.applyForwardVector(v); + t.translate(v); + Vector3.releaseTempInstance(v); + + _strip.setWorldTransform(t); + Transform.releaseTempInstance(t); + + _strip.setWorldScale(1, _strip.getWorldScale().getY() * height, 0); + _strip.render(renderer); + } + + public long getBlinkInterval() { + return _blinkInterval; + } + + public void setBlinkInterval(final long ms) { + _blinkInterval = ms; + } + + public ReadOnlyColorRGBA getCaretColor() { + return _strip.getDefaultColor(); + } + + public void setCaretColor(final ReadOnlyColorRGBA caretColor) { + _strip.setDefaultColor(caretColor); + } + + public int getIndex() { + return _index; + } + + public void setIndex(final int index) { + _index = index; + } + + public int getPosX() { + return _posX; + } + + public void setPosX(final int posX) { + _posX = posX; + } + + public int getPosY() { + return _posY; + } + + public void setPosY(final int posY) { + _posY = posY; + } +} diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/TextFactory.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/TextFactory.java new file mode 100644 index 0000000..f187d57 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/TextFactory.java @@ -0,0 +1,378 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui.text; + +import java.nio.FloatBuffer; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicReference; + +import com.ardor3d.extension.ui.text.RenderedText.RenderedTextData; +import com.ardor3d.extension.ui.text.font.BMFontProvider; +import com.ardor3d.extension.ui.text.font.FontProvider; +import com.ardor3d.extension.ui.text.font.UIFont; +import com.ardor3d.extension.ui.text.parser.ForumLikeMarkupParser; +import com.ardor3d.extension.ui.text.parser.StyleParser; +import com.ardor3d.image.Texture2D; +import com.ardor3d.math.type.ReadOnlyColorRGBA; +import com.ardor3d.renderer.state.BlendState; +import com.ardor3d.renderer.state.TextureState; +import com.ardor3d.scenegraph.FloatBufferData; +import com.ardor3d.scenegraph.MeshData; +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; + +public enum TextFactory { + INSTANCE; + + private FontProvider _fontProvider; + private StyleParser _styleParser; + private final static float[] WHITE = new float[] { 1, 1, 1, 1 }; + + TextFactory() { + final BMFontProvider fontProvider = new BMFontProvider(); + fontProvider.addFont("com/ardor3d/extension/ui/font/arial-12-regular", "Arial", 12, false, false); + fontProvider.addFont("com/ardor3d/extension/ui/font/arial-16-bold-regular", "Arial", 16, true, false); + fontProvider.addFont("com/ardor3d/extension/ui/font/arial-18-regular", "Arial", 18, false, false); + fontProvider.addFont("com/ardor3d/extension/ui/font/arial-18-bold", "Arial", 18, true, false); + fontProvider.addFont("com/ardor3d/extension/ui/font/arial-18-bold-italic", "Arial", 18, true, true); + fontProvider.addFont("com/ardor3d/extension/ui/font/arial-24-bold", "Arial", 24, false, false); + setFontProvider(fontProvider); + setStyleParser(new ForumLikeMarkupParser()); + } + + public void setFontProvider(final FontProvider provider) { + _fontProvider = provider; + } + + public FontProvider getFontProvider() { + return _fontProvider; + } + + public void setStyleParser(final StyleParser parser) { + _styleParser = parser; + } + + public StyleParser getStyleParser() { + return _styleParser; + } + + public RenderedText generateText(final String text, final boolean styled, final Map<String, Object> defaultStyles, + final RenderedText store, final int maxWidth) { + RenderedText rVal = store; + if (rVal == null) { + rVal = new RenderedText(); + } else { + rVal.detachAllChildren(); + } + + rVal.setStyled(styled); + + // note: spans must be in order by start index + final LinkedList<StyleSpan> spans = Lists.newLinkedList(); + final String plainText; + if (styled && _styleParser != null) { + // parse text for style spans + final List<StyleSpan> styleStore = Lists.newArrayList(); + plainText = _styleParser.parseStyleSpans(text, styleStore); + Collections.sort(styleStore); + if (!styleStore.isEmpty()) { + spans.addAll(styleStore); + } + } else { + plainText = text; + } + + rVal.setParsedStyleSpans(spans); + + // push defaults onto head of list + for (final String style : defaultStyles.keySet()) { + spans.addFirst(new StyleSpan(style, defaultStyles.get(style), 0, plainText.length())); + } + + rVal.setPlainText(plainText); + + final RenderedTextData textData = rVal.getData(); + textData.reset(); + + char prevChar = 0, c = 0; + final List<StyleSpan> currentStyles = Lists.newLinkedList(); + // indexed by character offset + final List<CharacterDescriptor> descs = textData._characters; + final List<Integer> descXStarts = textData._xStarts; + final List<Integer> fontHeights = textData._fontHeights; + // indexed by line number + final List<Integer> lineEnds = textData._lineEnds; + final List<Integer> lineHeights = textData._lineHeights; + // indexed by the used Texture + final Multimap<Texture2D, Integer> descIndices = ArrayListMultimap.create(); + int maxLineHeight = 0, xOffset = 0, maxSizeHeight = 0; + UIFont prevFont = null; + double scale = 1, prevScale = 0; + final Map<String, Object> stylesMap = Maps.newHashMap(); + + final char[] chars = plainText.toCharArray(); + for (int i = 0; i < chars.length; i++) { + c = chars[i]; + // update our list - remove spans we've passed by + for (final Iterator<StyleSpan> it = currentStyles.iterator(); it.hasNext();) { + final StyleSpan span = it.next(); + if (span.getSpanStart() + span.getSpanLength() <= i) { + it.remove(); + } + } + + // update our list - add spans we've entered + while (!spans.isEmpty()) { + final StyleSpan span = spans.peek(); + if (span.getSpanStart() <= i) { + spans.removeFirst(); + } else { + break; + } + + if (span.getSpanStart() + span.getSpanLength() > i) { + currentStyles.add(span); + } + } + + stylesMap.clear(); + for (final StyleSpan style : currentStyles) { + stylesMap.put(style.getStyle(), style.getValue()); + } + + // find the UIFont related to the given font family & size & styles + final AtomicReference<Double> scaleRef = new AtomicReference<Double>(); + final UIFont font = _fontProvider.getClosestMatchingFont(stylesMap, scaleRef); + if (font == null) { + return rVal; + } + + scale = scaleRef.get(); + + // check for new line + if (c == '\n') { + // add current index to lineEnds + lineEnds.add(descs.size() - 1); + + // check max height is valid + if (maxLineHeight == 0) { + maxLineHeight = (int) Math.round(scale * font.getFontHeight()); + } + + // add current max height to heights + lineHeights.add(maxLineHeight); + maxSizeHeight += maxLineHeight; + + // reset tracking vars + maxLineHeight = 0; + prevChar = 0; + prevFont = null; + xOffset = 0; + + // go to next char + continue; + } + + // pull our char descriptor + CharacterDescriptor desc = font.getDescriptor(c); + if (desc == null) { + // not a mapped char, so use '?' + c = '?'; + desc = font.getDescriptor(c); + if (desc == null) { + continue; + } + } + // clone so we can add custom values + desc = new CharacterDescriptor(desc); + desc.setTint((ReadOnlyColorRGBA) stylesMap.get(StyleConstants.KEY_COLOR)); + desc.setScale(scale); + descs.add(desc); + + // add our kerning, if applicable (must be same font) + if (prevFont == font && prevScale == scale) { + xOffset += (int) Math.round(scale * font.getKerning(prevChar, c)); + } + + // check to see if we're past the edge of our allowed width + if (maxWidth > 0 && xOffset + (int) Math.round(scale * (desc.getXOffset() + desc.getWidth())) > maxWidth) { + // add current index to lineEnds + lineEnds.add(descs.size() - 2); + + // add current max height to heights + lineHeights.add(maxLineHeight); + maxSizeHeight += maxLineHeight; + + // reset tracking vars + maxLineHeight = 0; + prevChar = 0; + prevScale = 0; + prevFont = null; + xOffset = 0; + + // keep going... + } + + // check against max line height + maxLineHeight = Math.max((int) Math.round(scale * font.getFontHeight()), maxLineHeight); + + // add a pointer to it for the associated texture + descIndices.put(font.getFontTexture(), descs.size() - 1); + + // store our xOffset and line height + descXStarts.add(xOffset); + fontHeights.add((int) Math.round(scale * font.getFontHeight())); + + // move forward for next char + xOffset += (int) Math.round(scale * desc.getXAdvance()); + + // update our previous vals + prevChar = c; + prevFont = font; + prevScale = scale; + } + + if (maxLineHeight != 0) { + // add current index to lineEnds + lineEnds.add(descs.size() - 1); + + // add current max height to heights + lineHeights.add(maxLineHeight); + maxSizeHeight += maxLineHeight; + } + + // use parsed information to create our textmeshes + Collection<Integer> indices; + float t, b, l, r, inverseTextureHeight, inverseTextureWidth; + CharacterDescriptor charDesc; + int cursorY, lineHeight, maxSizeWidth = 0; + for (final Texture2D tex : descIndices.keySet()) { + inverseTextureHeight = 1f / tex.getImage().getHeight(); + inverseTextureWidth = 1f / tex.getImage().getWidth(); + + final TextMesh tMesh = new TextMesh(); + + // apply render states + applyStates(tMesh, tex); + + indices = descIndices.get(tex); + + // setup buffers based on number of indices we have + final MeshData mData = tMesh.getMeshData(); + final int verts = indices.size() * 6; + mData.setVertexCoords(new FloatBufferData(verts * 3, 3)); + mData.setTextureCoords(new FloatBufferData(verts * 2, 2), 0); + mData.setColorCoords(new FloatBufferData(verts * 4, 4)); + + final FloatBuffer vertices = mData.getVertexBuffer(); + final FloatBuffer texs = mData.getTextureBuffer(0); + final FloatBuffer colorBufs = mData.getColorBuffer(); + final float[] colorStore = new float[4]; + + for (final int index : indices) { + // grab which line we're on, line height, x offset and char descriptor + charDesc = descs.get(index); + lineHeight = lineHeights.get(0); + cursorY = maxSizeHeight - lineHeight; + for (int j = 0; j < lineEnds.size(); j++) { + if (lineEnds.get(j) < index) { + cursorY -= lineHeight; + lineHeight = lineHeights.get(j); + } else { + break; + } + } + + maxSizeWidth = Math.max( + descXStarts.get(index) + (int) Math.round(charDesc.getScale() * charDesc.getXAdvance()), + maxSizeWidth); + + // add to buffers + + // -- vertices ----------------- + l = descXStarts.get(index) + (int) Math.round(charDesc.getScale() * charDesc.getXOffset()); + b = cursorY + lineHeight + - Math.round(charDesc.getScale() * (charDesc.getHeight() + charDesc.getYOffset())); + r = l + (int) Math.round(charDesc.getScale() * charDesc.getWidth()); + t = cursorY + lineHeight - Math.round(charDesc.getScale() * charDesc.getYOffset()); + + vertices.put(l).put(t).put(0); // left top + vertices.put(l).put(b).put(0); // left bottom + vertices.put(r).put(t).put(0); // right top + vertices.put(r).put(t).put(0); // right top + vertices.put(l).put(b).put(0); // left bottom + vertices.put(r).put(b).put(0); // right bottom + + final float[] color = charDesc.getTint() != null ? charDesc.getTint().toArray(colorStore) + : TextFactory.WHITE; + colorBufs.put(color); + colorBufs.put(color); + colorBufs.put(color); + colorBufs.put(color); + colorBufs.put(color); + colorBufs.put(color); + + // -- tex coords ---------------- + l = charDesc.getX() * inverseTextureWidth; + t = charDesc.getY() * inverseTextureHeight; + r = (charDesc.getX() + charDesc.getWidth()) * inverseTextureWidth; + b = (charDesc.getY() + charDesc.getHeight()) * inverseTextureHeight; + + texs.put(l).put(t); // left top + texs.put(l).put(b); // left bottom + texs.put(r).put(t); // right top + texs.put(r).put(t); // right top + texs.put(l).put(b); // left bottom + texs.put(r).put(b); // right bottom + } + + rVal.attachChild(tMesh); + } + + // set maxWidth and maxHeight on rVal + rVal.setWidth(maxSizeWidth); + rVal.setHeight(maxSizeHeight); + + return rVal; + } + + private void applyStates(final TextMesh mesh, final Texture2D tex) { + final TextureState textureState = new TextureState(); + textureState.setTexture(tex); + mesh.setRenderState(textureState); + + final BlendState blendState = new BlendState(); + blendState.setBlendEnabled(true); + blendState.setSourceFunction(BlendState.SourceFunction.SourceAlpha); + blendState.setDestinationFunction(BlendState.DestinationFunction.OneMinusSourceAlpha); + blendState.setTestEnabled(true); + blendState.setTestFunction(BlendState.TestFunction.GreaterThan); + blendState.setReference(0f); + mesh.setRenderState(blendState); + + mesh.updateWorldRenderStates(false); + } + + public String getMarkedUpText(final String plainText, final List<StyleSpan> spans) { + if (_styleParser == null) { + return plainText; + } else { + return _styleParser.addStyleMarkup(plainText, spans); + } + } +}
\ No newline at end of file diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/TextMesh.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/TextMesh.java new file mode 100644 index 0000000..dcc4c94 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/TextMesh.java @@ -0,0 +1,37 @@ +/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui.text;
+
+import com.ardor3d.renderer.IndexMode;
+import com.ardor3d.scenegraph.Mesh;
+import com.ardor3d.scenegraph.hint.CullHint;
+import com.ardor3d.scenegraph.hint.LightCombineMode;
+import com.ardor3d.scenegraph.hint.TextureCombineMode;
+
+/**
+ * Text spatial which uses textures generated by UIFont
+ */
+public class TextMesh extends Mesh {
+
+ public TextMesh() {
+ super("text");
+ getMeshData().setIndexMode(IndexMode.Triangles);
+ getSceneHints().setLightCombineMode(LightCombineMode.Off);
+ getSceneHints().setTextureCombineMode(TextureCombineMode.Replace);
+
+ // -- never cull
+ setModelBound(null);
+ getSceneHints().setCullHint(CullHint.Never);
+
+ // -- default to non-pickable
+ getSceneHints().setAllPickingHints(false);
+ }
+}
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/TextSelection.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/TextSelection.java new file mode 100644 index 0000000..d305b1f --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/TextSelection.java @@ -0,0 +1,295 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui.text; + +import java.nio.FloatBuffer; +import java.util.List; + +import com.ardor3d.extension.ui.UIComponent; +import com.ardor3d.extension.ui.text.RenderedText.RenderedTextData; +import com.ardor3d.math.ColorRGBA; +import com.ardor3d.math.type.ReadOnlyTransform; +import com.ardor3d.renderer.IndexMode; +import com.ardor3d.renderer.Renderer; +import com.ardor3d.renderer.state.BlendState; +import com.ardor3d.renderer.state.BlendState.DestinationFunction; +import com.ardor3d.renderer.state.BlendState.SourceFunction; +import com.ardor3d.scenegraph.Mesh; +import com.ardor3d.scenegraph.MeshData; +import com.ardor3d.util.geom.BufferUtils; +import com.google.common.collect.Lists; + +public abstract class TextSelection { + + protected int _startIndex = -1; + protected int _endIndex = -1; + protected SelectionState _state = SelectionState.NO_SELECTION; + + /** The mesh used to render this selection. */ + protected Mesh _standin; + + public TextSelection() { + _standin = createSelectionMesh(); + } + + /** + * @return the current caret position within the component whose selection we are tracking. + */ + public abstract int getCaretPosition(); + + /** + * @return the data object of the text associated with this selection. + */ + public abstract RenderedTextData getTextData(); + + public int getSelectionLength() { + if (_startIndex == -1 || _endIndex == -1) { + return 0; + } else { + return _endIndex - _startIndex; + } + } + + public void reset() { + _startIndex = _endIndex = -1; + _state = SelectionState.NO_SELECTION; + } + + public int getEndIndex() { + return _endIndex; + } + + public void setEndIndex(final int endIndex) { + _endIndex = endIndex; + updateMesh(); + } + + public int getStartIndex() { + return _startIndex; + } + + public void setStartIndex(final int startIndex) { + _startIndex = startIndex; + updateMesh(); + } + + public SelectionState getState() { + return _state; + } + + public void setState(final SelectionState state) { + _state = state; + } + + /** + * Alter the selection as if the "shift" and "up" keys are pressed. + */ + public void upKey() { + if (_state != SelectionState.NO_SELECTION && getSelectionLength() == 0) { + _state = SelectionState.AT_START_OF_SELECTION; + } + + if (_state == SelectionState.AT_END_OF_SELECTION) { + if (getCaretPosition() < _startIndex) { + _endIndex = _startIndex; + _startIndex = getCaretPosition(); + _state = SelectionState.AT_START_OF_SELECTION; + } else { + _endIndex = getCaretPosition(); + } + } else if (_state == SelectionState.AT_START_OF_SELECTION) { + _startIndex = getCaretPosition(); + } + updateMesh(); + } + + /** + * Alter the selection as if the "shift" and "down" keys are pressed. + */ + public void downKey() { + if (_state != SelectionState.NO_SELECTION && getSelectionLength() == 0) { + _state = SelectionState.AT_END_OF_SELECTION; + } + + if (_state == SelectionState.AT_END_OF_SELECTION) { + _endIndex = getCaretPosition(); + } else if (_state == SelectionState.AT_START_OF_SELECTION) { + if (getCaretPosition() > _endIndex) { + _startIndex = _endIndex; + _endIndex = getCaretPosition(); + _state = SelectionState.AT_END_OF_SELECTION; + } else { + _startIndex = getCaretPosition(); + } + } + updateMesh(); + } + + /** + * Alter the selection as if the "shift" and "left" keys are pressed. + */ + public void leftKey() { + if (_state != SelectionState.NO_SELECTION && getSelectionLength() == 0) { + _state = SelectionState.AT_START_OF_SELECTION; + } + + if (_state == SelectionState.AT_END_OF_SELECTION) { + _endIndex = getCaretPosition(); + } else if (_state == SelectionState.AT_START_OF_SELECTION) { + _startIndex = getCaretPosition(); + } + updateMesh(); + } + + /** + * Alter the selection as if the "shift" and "right" keys are pressed. + */ + public void rightKey() { + if (_state != SelectionState.NO_SELECTION && getSelectionLength() == 0) { + _state = SelectionState.AT_END_OF_SELECTION; + } + + if (_state == SelectionState.AT_END_OF_SELECTION) { + _endIndex = getCaretPosition(); + } else if (_state == SelectionState.AT_START_OF_SELECTION) { + _startIndex = getCaretPosition(); + } + updateMesh(); + } + + public void checkStart() { + if (_state == SelectionState.NO_SELECTION) { + final int caretPosition = getCaretPosition(); + _startIndex = caretPosition; + _endIndex = caretPosition; + _state = SelectionState.AT_END_OF_SELECTION; + } + } + + private void updateMesh() { + final int selLength = getSelectionLength(); + if (selLength == 0) { + return; + } + + // Make triangle strips for each line. + final RenderedTextData data = getTextData(); + float xStart = 0, xEnd = 0, height = 0, yOffset = 0; + boolean exit = false; + final List<Float> verts = Lists.newArrayList(); + for (int j = 0; !exit && j < data._lineEnds.size(); j++) { + height = data._lineHeights.get(j); + final int end = data._lineEnds.get(j); + if (_startIndex > end) { + continue; + } else if (_startIndex <= end) { + xStart = data._xStarts.get(_startIndex); + } else { + xStart = 0; + } + + if (_endIndex <= end) { + // last strip + final CharacterDescriptor charDesc = data._characters.get(_endIndex - 1); + xEnd = data._xStarts.get(_endIndex - 1) + + (int) Math.round(charDesc.getScale() * charDesc.getXAdvance()); + exit = true; + } else { + final CharacterDescriptor charDesc = data._characters.get(end); + xEnd = data._xStarts.get(end) + (int) Math.round(charDesc.getScale() * charDesc.getXAdvance()); + } + + verts.add(xStart); + verts.add(yOffset); + verts.add(0f); + + verts.add(xEnd); + verts.add(yOffset); + verts.add(0f); + + verts.add(xStart); + verts.add(yOffset + height); + verts.add(0f); + + verts.add(xStart); + verts.add(yOffset + height); + verts.add(0f); + + verts.add(xEnd); + verts.add(yOffset); + verts.add(0f); + + verts.add(xEnd); + verts.add(yOffset + height); + verts.add(0f); + + yOffset += height; + } + final MeshData mData = _standin.getMeshData(); + mData.setVertexBuffer(BufferUtils.createVector3Buffer(mData.getVertexBuffer(), verts.size())); + final FloatBuffer vertBuffer = mData.getVertexBuffer(); + for (final float f : verts) { + vertBuffer.put(f); + } + } + + public void draw(final Renderer renderer, final ReadOnlyTransform xform) { + if (getSelectionLength() == 0) { + return; + } + + // set our alpha + final ColorRGBA color = ColorRGBA.fetchTempInstance(); + color.set(_standin.getDefaultColor()).setAlpha(UIComponent.getCurrentOpacity()); + _standin.setDefaultColor(color); + ColorRGBA.releaseTempInstance(color); + + // set our location + _standin.setWorldTransform(xform); + + // draw + _standin.render(renderer); + } + + protected Mesh createSelectionMesh() { + final Mesh mesh = new Mesh("selectionMesh"); + final MeshData mData = mesh.getMeshData(); + mData.setVertexBuffer(BufferUtils.createVector3Buffer(6)); + mData.setIndexMode(IndexMode.Triangles); + + final BlendState blend = new BlendState(); + blend.setBlendEnabled(true); + blend.setSourceFunction(SourceFunction.SourceAlpha); + blend.setDestinationFunction(DestinationFunction.OneMinusSourceAlpha); + mesh.setRenderState(blend); + mesh.updateWorldRenderStates(false); + mesh.setDefaultColor(ColorRGBA.LIGHT_GRAY); + + return mesh; + } + + public enum SelectionState { + /** + * No selection is currently made. + */ + NO_SELECTION, + + /** + * We have a selection and our caret is currently at the end of that selection. + */ + AT_END_OF_SELECTION, + + /** + * We have a selection and our caret is currently at the start of that selection. + */ + AT_START_OF_SELECTION; + } +} diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/UIKeyHandler.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/UIKeyHandler.java new file mode 100644 index 0000000..fbffb75 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/UIKeyHandler.java @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui.text; + +import com.ardor3d.input.InputState; +import com.ardor3d.input.Key; + +public interface UIKeyHandler { + boolean keyPressed(Key key, InputState state); + + boolean keyReleased(Key key, InputState state); + + boolean keyHeld(Key key, InputState state); +} diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/font/BMFontProvider.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/font/BMFontProvider.java new file mode 100644 index 0000000..6e89361 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/font/BMFontProvider.java @@ -0,0 +1,162 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui.text.font; + +import java.io.IOException; +import java.net.URL; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.atomic.AtomicReference; +import java.util.logging.Logger; + +import com.ardor3d.extension.ui.UIComponent; +import com.ardor3d.extension.ui.text.CharacterDescriptor; +import com.ardor3d.extension.ui.text.StyleConstants; +import com.ardor3d.image.Texture2D; +import com.ardor3d.ui.text.BMFont; +import com.ardor3d.ui.text.BMFont.Char; +import com.ardor3d.util.export.binary.BinaryImporter; +import com.ardor3d.util.resource.ResourceLocatorTool; +import com.ardor3d.util.resource.URLResourceSource; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; + +/** + * Provides BMFonts for use in UIFont. + */ +public class BMFontProvider implements FontProvider { + + private static Logger logger = Logger.getLogger(BMFontProvider.class.getName()); + + protected Map<UIFont, Integer> _scoreMap = Maps.newHashMap(); + + protected final Set<FontInfo> _fonts = Sets.newHashSet(); + + public void addFont(final String source, final String family, final int size, final boolean bold, + final boolean italic) { + final FontInfo fontInfo = new FontInfo(); + fontInfo.source = source; + fontInfo.family = family; + fontInfo.size = size; + fontInfo.bold = bold; + fontInfo.italic = italic; + _fonts.add(fontInfo); + } + + @Override + public UIFont getClosestMatchingFont(final Map<String, Object> currentStyles, final AtomicReference<Double> scale) { + final boolean isBold = currentStyles.containsKey(StyleConstants.KEY_BOLD) ? (Boolean) currentStyles + .get(StyleConstants.KEY_BOLD) : false; + final boolean isItalic = currentStyles.containsKey(StyleConstants.KEY_ITALICS) ? (Boolean) currentStyles + .get(StyleConstants.KEY_ITALICS) : false; + final int size = currentStyles.containsKey(StyleConstants.KEY_SIZE) ? (Integer) currentStyles + .get(StyleConstants.KEY_SIZE) : UIComponent.getDefaultFontSize(); + final String family = currentStyles.containsKey(StyleConstants.KEY_FAMILY) ? currentStyles.get( + StyleConstants.KEY_FAMILY).toString() : UIComponent.getDefaultFontFamily(); + + FontInfo closest = null; + int score, bestScore = Integer.MIN_VALUE; + + for (final FontInfo info : _fonts) { + score = 0; + if (family.equalsIgnoreCase(info.family)) { + score += 200; + } + + if (info.bold) { + if (isBold) { + score += 50; + } else { + score -= 25; + } + } else if (isBold) { + score -= 25; + } + + if (info.italic) { + if (isItalic) { + score += 50; + } else { + score -= 25; + } + } else if (isItalic) { + score -= 25; + } + + score -= Math.abs(size - info.size); + + if (score > bestScore) { + closest = info; + bestScore = score; + } + } + + if (closest == null) { + return null; + } + + scale.set((double) size / closest.size); + + // now build the requested font if necessary + if (closest.uiFont == null) { + // load from file if necessary + if (closest.bmFont == null) { + // First try to load from a3d file + String resource = closest.source + ".a3d"; + URL url = ResourceLocatorTool.getClassPathResource(BMFontProvider.class, resource); + try { + if (url != null) { + final BinaryImporter binaryImporter = new BinaryImporter(); + closest.bmFont = (BMFont) binaryImporter.load(url); + } else { + // Not found, load from .fnt + resource = closest.source + ".fnt"; + url = ResourceLocatorTool.getClassPathResource(BMFontProvider.class, resource); + closest.bmFont = new BMFont(new URLResourceSource(url), false); + } + } catch (final IOException e) { + BMFontProvider.logger.severe("Unable to load font: " + closest.source); + return null; + } + } + + final Map<Character, CharacterDescriptor> descriptors = Maps.newHashMap(); + for (final int val : closest.bmFont.getMappedChars()) { + final Char c = closest.bmFont.getChar(val); + final CharacterDescriptor desc = new CharacterDescriptor(c.x, c.y, c.width, c.height, c.xadvance, + c.xoffset, c.yoffset, 1.0, null); + descriptors.put((char) val, desc); + } + + closest.uiFont = new UIFont((Texture2D) closest.bmFont.getPageTexture(), descriptors, + closest.bmFont.getLineHeight(), closest.bmFont.getSize()); + final Map<Integer, Map<Integer, Integer>> kernings = closest.bmFont.getKerningMap(); + for (final int valA : kernings.keySet()) { + final Map<Integer, Integer> kerns = kernings.get(valA); + for (final int valB : kerns.keySet()) { + closest.uiFont.addKerning((char) valA, (char) valB, kerns.get(valB)); + } + } + } + + return closest.uiFont; + } + + class FontInfo { + String source; + String family; + int size; + boolean bold; + boolean italic; + BMFont bmFont; + UIFont uiFont; + } +} diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/font/FontProvider.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/font/FontProvider.java new file mode 100644 index 0000000..16a5090 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/font/FontProvider.java @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui.text.font; + +import java.util.Map; +import java.util.concurrent.atomic.AtomicReference; + +public interface FontProvider { + + /** + * Get the closest font this provider has to the given criteria. + * + * @param currentStyles + * a map of style information. + * @param scale + * the scale needed to match out requested size. + * @return the found font, or null if none is found. + */ + UIFont getClosestMatchingFont(Map<String, Object> currentStyles, AtomicReference<Double> scale); + +} diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/font/UIFont.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/font/UIFont.java new file mode 100644 index 0000000..f0a191d --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/font/UIFont.java @@ -0,0 +1,79 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui.text.font; + +import java.util.Map; + +import com.ardor3d.extension.ui.text.CharacterDescriptor; +import com.ardor3d.image.Texture2D; +import com.google.common.collect.Maps; + +/** + * Defines a texture based font for use in the UI system. + */ +public class UIFont { + + private final Map<Character, CharacterDescriptor> _charDescriptors = Maps.newHashMap(); + private final Map<Character, Map<Character, Integer>> _kernMap = Maps.newHashMap(); + private final Texture2D _fontTexture; + private final int _fontHeight; + private final int _fontSize; + + public UIFont(final Texture2D texture, final Map<Character, CharacterDescriptor> descriptors, final int height, + final int size) { + _charDescriptors.putAll(descriptors); + _fontTexture = texture; + _fontHeight = height; + _fontSize = size; + } + + public int getFontHeight() { + return _fontHeight; + } + + public int getFontSize() { + return _fontSize; + } + + public Texture2D getFontTexture() { + return _fontTexture; + } + + /** + * @param c + * the char to retrieve descriptor for + * @return a descriptor for the given character, or null if none exists. + */ + public CharacterDescriptor getDescriptor(final char c) { + return _charDescriptors.get(c); + } + + public void addKerning(final char charA, final char charB, final int amount) { + Map<Character, Integer> map = _kernMap.get(charA); + if (map == null) { + map = Maps.newHashMap(); + _kernMap.put(charA, map); + } + + map.put(charB, amount); + } + + public int getKerning(final char charA, final char charB) { + final Map<Character, Integer> map = _kernMap.get(charA); + if (map != null) { + final Integer amt = map.get(charB); + if (amt != null) { + return amt; + } + } + return 0; + } +} diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/parser/ForumLikeMarkupParser.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/parser/ForumLikeMarkupParser.java new file mode 100644 index 0000000..405ff5b --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/parser/ForumLikeMarkupParser.java @@ -0,0 +1,253 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui.text.parser; + +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.StringTokenizer; + +import com.ardor3d.extension.ui.text.StyleConstants; +import com.ardor3d.extension.ui.text.StyleSpan; +import com.ardor3d.math.ColorRGBA; +import com.ardor3d.math.type.ReadOnlyColorRGBA; +import com.google.common.collect.Lists; + +public class ForumLikeMarkupParser implements StyleParser { + + Comparator<StyleSpan> endSorter = new Comparator<StyleSpan>() { + public int compare(final StyleSpan o1, final StyleSpan o2) { + return o1.getSpanStart() + o1.getSpanLength() - (o2.getSpanStart() + o2.getSpanLength()); + } + }; + + @Override + public String parseStyleSpans(final String text, final List<StyleSpan> store) { + final StringBuilder rVal = new StringBuilder(""); + int index = 0; + TagStatus tagStatus = TagStatus.NONE; + String currTagText = ""; + final LinkedList<StyleSpan> buildingSpans = Lists.newLinkedList(); + final StringTokenizer st = new StringTokenizer(text, "[]\\", true); + String token; + while (st.hasMoreTokens()) { + token = st.nextToken(); + // escape char + if (tagStatus == TagStatus.NONE && "\\".equals(token)) { + if (st.hasMoreTokens()) { + token = st.nextToken(); + if ("[".equals(token) || "]".equals(token)) { + rVal.append(token); + index++; + continue; + } else { + rVal.append("\\"); + rVal.append(token); + index += token.length() + 1; + continue; + } + } else { + rVal.append("\\"); + index++; + continue; + } + } + + // start token + else if (tagStatus == TagStatus.NONE && "[".equals(token)) { + tagStatus = TagStatus.START_TAG; + continue; + } + + else if (tagStatus == TagStatus.START_TAG) { + currTagText = token; + tagStatus = TagStatus.IN_TAG; + continue; + } + + // end token + else if (tagStatus == TagStatus.IN_TAG && "]".equals(token)) { + tagStatus = TagStatus.NONE; + // interpret tag: + // BOLD + if ("b".equalsIgnoreCase(currTagText)) { + // start a new bold span + buildingSpans.add(new StyleSpan(StyleConstants.KEY_BOLD, Boolean.TRUE, index, 0)); + } else if ("/b".equalsIgnoreCase(currTagText)) { + // find last BOLD entry and add length + endSpan(StyleConstants.KEY_BOLD, store, index, buildingSpans); + } + + // ITALICS + else if ("i".equalsIgnoreCase(currTagText)) { + // start a new italics span + buildingSpans.add(new StyleSpan(StyleConstants.KEY_ITALICS, Boolean.TRUE, index, 0)); + } else if ("/i".equalsIgnoreCase(currTagText)) { + // find last ITALICS entry and add length + endSpan(StyleConstants.KEY_ITALICS, store, index, buildingSpans); + } + + // COLOR + else if (currTagText.toLowerCase().startsWith("c=")) { + // start a new color span + try { + // parse a color + final String c = currTagText.substring(2); + buildingSpans.add(new StyleSpan(StyleConstants.KEY_COLOR, ColorRGBA.parseColor(c, null), index, + 0)); + } catch (final Exception e) { + e.printStackTrace(); + } + } else if ("/c".equalsIgnoreCase(currTagText)) { + // find last BOLD entry and add length + endSpan(StyleConstants.KEY_COLOR, store, index, buildingSpans); + } + + // SIZE + else if (currTagText.toLowerCase().startsWith("size=")) { + // start a new size span + try { + // parse a size + final int i = Integer.parseInt(currTagText.substring(5)); + buildingSpans.add(new StyleSpan(StyleConstants.KEY_SIZE, i, index, 0)); + } catch (final Exception e) { + e.printStackTrace(); + } + } else if ("/size".equalsIgnoreCase(currTagText)) { + // find last SIZE entry and add length + endSpan(StyleConstants.KEY_SIZE, store, index, buildingSpans); + } + + // FAMILY + else if (currTagText.toLowerCase().startsWith("f=")) { + // start a new family span + final String family = currTagText.substring(2); + buildingSpans.add(new StyleSpan(StyleConstants.KEY_FAMILY, family, index, 0)); + } else if ("/f".equalsIgnoreCase(currTagText)) { + // find last FAMILY entry and add length + endSpan(StyleConstants.KEY_FAMILY, store, index, buildingSpans); + } else { + // not really a tag, so put it back. + rVal.append("["); + rVal.append(currTagText); + rVal.append("]"); + tagStatus = TagStatus.NONE; + } + + currTagText = ""; + continue; + } + + // anything else + rVal.append(token); + index += token.length(); + } + + // close any remaining open tags + while (!buildingSpans.isEmpty()) { + final StyleSpan span = buildingSpans.getLast(); + endSpan(span.getStyle(), store, index, buildingSpans); + } + + // return plain text + return rVal.toString(); + } + + private void endSpan(final String key, final List<StyleSpan> store, final int index, + final LinkedList<StyleSpan> buildingSpans) { + for (final Iterator<StyleSpan> it = buildingSpans.descendingIterator(); it.hasNext();) { + final StyleSpan next = it.next(); + if (key.equals(next.getStyle())) { + next.setSpanLength(index - next.getSpanStart()); + store.add(next); + it.remove(); + break; + } + } + } + + @Override + public String addStyleMarkup(final String plainText, final List<StyleSpan> spans) { + if (spans.isEmpty()) { + return plainText; + } + + // list of spans, sorted by start index + final List<StyleSpan> starts = Lists.newArrayList(); + starts.addAll(spans); + Collections.sort(starts); + + // list of spans, to be sorted by end index + final List<StyleSpan> ends = Lists.newLinkedList(); + + final StringBuilder builder = new StringBuilder(); + + // go through all chars and add starts and ends + for (int index = 0, max = plainText.length(); index < max; index++) { + // close markup + while (!ends.isEmpty()) { + final StyleSpan span = ends.get(0); + if (span.getSpanStart() + span.getSpanLength() == index) { + builder.append(getMarkup(span, true)); + ends.remove(0); + } else { + break; + } + } + + // add starts + while (!starts.isEmpty()) { + final StyleSpan span = starts.get(0); + if (span.getSpanStart() == index) { + builder.append(getMarkup(span, false)); + ends.add(span); + starts.remove(0); + Collections.sort(ends, endSorter); + } else { + break; + } + } + + builder.append(plainText.charAt(index)); + } + + // close any remaining markup: + while (!ends.isEmpty()) { + final StyleSpan span = ends.get(0); + builder.append(getMarkup(span, true)); + ends.remove(0); + } + + return builder.toString(); + } + + private String getMarkup(final StyleSpan span, final boolean end) { + if (StyleConstants.KEY_BOLD.equalsIgnoreCase(span.getStyle())) { + return end ? "[/b]" : "[b]"; + } else if (StyleConstants.KEY_ITALICS.equalsIgnoreCase(span.getStyle())) { + return end ? "[/i]" : "[i]"; + } else if (StyleConstants.KEY_FAMILY.equalsIgnoreCase(span.getStyle())) { + return end ? "[/f]" : "[f=" + span.getValue() + "]"; + } else if (StyleConstants.KEY_SIZE.equalsIgnoreCase(span.getStyle())) { + return end ? "[/size]" : "[size=" + span.getValue() + "]"; + } else if (StyleConstants.KEY_COLOR.equalsIgnoreCase(span.getStyle()) && span.getValue() instanceof ColorRGBA) { + return end ? "[/c]" : "[c=" + ((ReadOnlyColorRGBA) span.getValue()).asHexRRGGBBAA() + "]"; + } + + return ""; + } + + enum TagStatus { + NONE, START_TAG, IN_TAG + } +} diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/parser/StyleParser.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/parser/StyleParser.java new file mode 100644 index 0000000..8405ed6 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/parser/StyleParser.java @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui.text.parser; + +import java.util.List; + +import com.ardor3d.extension.ui.text.StyleSpan; + +public interface StyleParser { + + /** + * Parse the given text for markup indicating style spans and store the spans in the given store, returning the + * remaining as plaintext. + * + * @param text + * The text containing both plaintext and style markup. + * @param store + * The store for our parsed style spans. + * @return the plain text portion of our incoming text. + */ + String parseStyleSpans(String text, List<StyleSpan> store); + + /** + * Add markup describing the given spans, to the given plaintext. Note: spans with styles this parser does not + * understand will be ignored. + * + * @param plainText + * the plain text to decorate with markup. + * @param spans + * our style spans + * @return the marked up text. + */ + String addStyleMarkup(String plainText, List<StyleSpan> spans); + +} diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/util/Alignment.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/util/Alignment.java new file mode 100644 index 0000000..8161513 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/util/Alignment.java @@ -0,0 +1,115 @@ +/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui.util;
+
+/**
+ * Enumeration useful for describing positioning and alignment to the edges and corners of a rectangular area. This is
+ * used in our UI system to align text, images, and handle certain layouts such as the AnchorLayout.
+ */
+public enum Alignment {
+ /** North West */
+ TOP_LEFT(0.0, 1.0),
+
+ /** North */
+ TOP(0.5, 1.0),
+
+ /** North East */
+ TOP_RIGHT(1.0, 1.0),
+
+ /** West */
+ LEFT(0.0, 0.5),
+
+ /** Center */
+ MIDDLE(0.5, 0.5),
+
+ /** East */
+ RIGHT(1.0, 0.5),
+
+ /** South West */
+ BOTTOM_LEFT(0.0, 0.0),
+
+ /** South */
+ BOTTOM(0.5, 0.0),
+
+ /** South East */
+ BOTTOM_RIGHT(1.0, 0.0);
+
+ /**
+ * How far from the left this alignment is as a percentage.
+ */
+ private double along;
+
+ /**
+ * How far from the bottom this alignment is as a percentage.
+ */
+ private double up;
+
+ /**
+ * @param along
+ * How far from the left this alignment is as a percentage.
+ * @param up
+ * How far from the bottom this alignment is as a percentage.
+ */
+ Alignment(final double along, final double up) {
+ this.along = along;
+ this.up = up;
+ }
+
+ /**
+ * @return a value in [0, 1] describing how far from the bottom this alignment is.
+ */
+ public double fromLeft() {
+ return along;
+ }
+
+ /**
+ * @return a value in [0, 1] describing how far from the bottom this alignment is.
+ */
+ public double fromBottom() {
+ return up;
+ }
+
+ /**
+ * Determine the correct relative X position for a component being aligned, using this alignment, to another
+ * component (or a box to another box, or area... etc. - anything with a "width").
+ *
+ * @param availableWidth
+ * the width of the component or area we are aligning to.
+ * @param width
+ * the width of the component or area we are setting position on.
+ * @return the new X position to use.
+ */
+ public double alignX(final double availableWidth, final double width) {
+ return fromLeft() * availableWidth - fromLeft() * width;
+ }
+
+ public int alignX(final int availableWidth, final int width) {
+ return (int) Math.round(fromLeft() * availableWidth - fromLeft() * width);
+ }
+
+ /**
+ * Determine the correct relative Y position for a component being aligned, using this alignment, to another
+ * component (or a box to another box, or area... etc. - anything with a "height").
+ *
+ * @param availableHeight
+ * the height of the component or area we are aligning to.
+ * @param height
+ * the height of the component or area we are setting position on.
+ * @return the new Y position to use.
+ */
+ public double alignY(final double availableHeight, final double height) {
+ return fromBottom() * availableHeight - fromBottom() * height;
+ }
+
+ public int alignY(final int availableHeight, final int height) {
+ return (int) Math.round(fromBottom() * availableHeight - fromBottom() * height);
+ }
+}
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/util/ButtonGroup.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/util/ButtonGroup.java new file mode 100644 index 0000000..10d38fc --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/util/ButtonGroup.java @@ -0,0 +1,130 @@ +/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui.util;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import com.ardor3d.extension.ui.UIButton;
+
+/**
+ * Defines a group of buttons. This is generally used with radio or toggle buttons to indicate a group wherein only one
+ * button should be pressed at a time.
+ */
+public class ButtonGroup {
+
+ /** The list of buttons participating in this group. */
+ private final List<UIButton> _buttons = new ArrayList<UIButton>();
+
+ /** The currently selected button. */
+ private UIButton _selected;
+
+ public ButtonGroup() {}
+
+ /**
+ * Add a button to this button group if not already present.
+ *
+ * @param button
+ * the button to be added
+ * @throws NullPointerException
+ * if button is null
+ */
+ public void add(final UIButton button) {
+
+ // Make sure the button has the right group set.
+ if (button.getGroup() != this) {
+ button.setGroup(this);
+ }
+
+ // Proceed if the button is not already part of the this.
+ if (!_buttons.contains(button)) {
+ // Add to list
+ _buttons.add(button);
+
+ // See if we're selected...
+ if (button.isSelected()) {
+ // ..if we are and nothing else is selected in this group, then this is our "selected" value.
+ if (_selected == null) {
+ _selected = button;
+ }
+ // ..otherwise, the existing "selected" takes priority, so turn off this button.
+ else {
+ button.setSelected(false);
+ }
+ }
+ }
+ }
+
+ /**
+ * Removes the button from the group.
+ *
+ * @param button
+ * the button to remove. no-op if null.
+ */
+ public void remove(final UIButton button) {
+ if (button == null) {
+ return;
+ }
+ _buttons.remove(button);
+ if (button == _selected) {
+ _selected = null;
+ }
+ button.setGroup(null);
+ }
+
+ /**
+ * @return an Iterator of buttons currently in this group
+ */
+ public Iterator<UIButton> getButtons() {
+ return _buttons.iterator();
+ }
+
+ /**
+ * @return the currently selected button or null if none have been selected yet.
+ */
+ public UIButton getSelection() {
+ return _selected;
+ }
+
+ /**
+ * Sets the selected value for the given button. Only one button in the group may be selected at a time.
+ *
+ * @param button
+ * the button we are changing
+ * @param selected
+ * true if this button is to be selected and all others in the group should be de-selected.
+ */
+ public void setSelected(final UIButton button, final boolean selected) {
+ if (selected && button != null && button != _selected) {
+ final UIButton oldSelection = _selected;
+ _selected = button;
+ if (oldSelection != null) {
+ oldSelection.setSelected(false);
+ }
+ button.setSelected(true);
+ }
+ }
+
+ /**
+ * @return true if the button is the currently selected button
+ */
+ public boolean isSelected(final UIButton button) {
+ return button == _selected;
+ }
+
+ /**
+ * @return the number of buttons currently in the group.
+ */
+ public int getButtonCount() {
+ return _buttons.size();
+ }
+}
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/util/Dimension.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/util/Dimension.java new file mode 100644 index 0000000..8564146 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/util/Dimension.java @@ -0,0 +1,103 @@ +/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui.util;
+
+/**
+ * This class is patterned after awt's {@link java.awt.Dimension Dimension} class. It describes the width and height of
+ * something (in our case, generally a UI element.)
+ */
+public class Dimension {
+
+ private int _width;
+ private int _height;
+
+ /**
+ * Construct a new 0x0 dimension object.
+ */
+ public Dimension() {
+ this(0, 0);
+ }
+
+ /**
+ * Construct a new dimension object using the given values.
+ *
+ * @param width
+ * @param height
+ */
+ public Dimension(final int width, final int height) {
+ setWidth(width);
+ setHeight(height);
+ }
+
+ /**
+ * Construct a new dimension object using the values of the given source.
+ *
+ * @param source
+ */
+ public Dimension(final Dimension source) {
+ this(source.getWidth(), source.getHeight());
+ }
+
+ public int getWidth() {
+ return _width;
+ }
+
+ public void setWidth(final int width) {
+ _width = width;
+ }
+
+ public int getHeight() {
+ return _height;
+ }
+
+ public void setHeight(final int height) {
+ _height = height;
+ }
+
+ public void set(final int width, final int height) {
+ setWidth(width);
+ setHeight(height);
+ }
+
+ public void set(final Dimension d) {
+ set(d.getWidth(), d.getHeight());
+ }
+
+ public boolean contains(final double x, final double y) {
+ return x >= 0 && x < getWidth() && y >= 0 && y < getHeight();
+ }
+
+ public boolean contains(final int x, final int y) {
+ return x >= 0 && x < getWidth() && y >= 0 && y < getHeight();
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj instanceof Dimension) {
+ final Dimension d = (Dimension) obj;
+ return getWidth() == d.getWidth() && getHeight() == d.getHeight();
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 17;
+ result += 31 * result + getWidth();
+ result += 31 * result + getHeight();
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getName() + "[width=" + getWidth() + ",height=" + getHeight() + "]";
+ }
+}
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/util/HudListener.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/util/HudListener.java new file mode 100644 index 0000000..443308a --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/util/HudListener.java @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui.util; + +import com.ardor3d.extension.ui.UIComponent; + +/** + * An interface for 3rd party objects interested in notifications about hud changes. + */ +public interface HudListener { + /** + * Called when a component is added to the UIHud. + * + * @param component + * the added component + */ + public void componentAdded(UIComponent component); + + /** + * Called when a component is removed from the UIHud. + * + * @param component + * the removed component + */ + public void componentRemoved(UIComponent component); +} diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/util/Insets.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/util/Insets.java new file mode 100644 index 0000000..1183c36 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/util/Insets.java @@ -0,0 +1,124 @@ +/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui.util;
+
+/**
+ * This class is patterned after awt's {@link java.awt.Insets Insets} class. It describes the margins on four sides of a
+ * rectangular area and is the foundation of our UIBorder class.
+ */
+public class Insets {
+
+ private int _top;
+ private int _left;
+ private int _bottom;
+ private int _right;
+
+ /**
+ * Constructs a new insets with 0 size on each side.
+ */
+ public Insets() {
+ set(0, 0, 0, 0);
+ }
+
+ /**
+ * Constructs a new insets using the given sizes.
+ *
+ * @param top
+ * @param left
+ * @param bottom
+ * @param right
+ */
+ public Insets(final int top, final int left, final int bottom, final int right) {
+ set(top, left, bottom, right);
+ }
+
+ /**
+ * Constructs a new insets using the sizes from the given source.
+ *
+ * @param source
+ */
+ public Insets(final Insets source) {
+ set(source);
+ }
+
+ /**
+ * Set the size of the sides to the given values.
+ *
+ * @param top
+ * @param left
+ * @param bottom
+ * @param right
+ */
+ public void set(final int top, final int left, final int bottom, final int right) {
+ _top = top;
+ _left = left;
+ _bottom = bottom;
+ _right = right;
+ }
+
+ public void set(final Insets other) {
+ _top = other.getTop();
+ _left = other.getLeft();
+ _bottom = other.getBottom();
+ _right = other.getRight();
+ }
+
+ public int getLeft() {
+ return _left;
+ }
+
+ public int getTop() {
+ return _top;
+ }
+
+ public int getRight() {
+ return _right;
+ }
+
+ public int getBottom() {
+ return _bottom;
+ }
+
+ public void setLeft(final int size) {
+ _left = size;
+ }
+
+ public void setRight(final int size) {
+ _right = size;
+ }
+
+ public void setTop(final int size) {
+ _top = size;
+ }
+
+ public void setBottom(final int size) {
+ _bottom = size;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj instanceof Insets) {
+ final Insets other = (Insets) obj;
+ return _top == other._top && _left == other._left && _bottom == other._bottom && _right == other._right;
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 17;
+ result += 31 * result + getLeft();
+ result += 31 * result + getRight();
+ result += 31 * result + getTop();
+ result += 31 * result + getBottom();
+ return result;
+ }
+}
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/util/SubTex.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/util/SubTex.java new file mode 100644 index 0000000..5e65857 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/util/SubTex.java @@ -0,0 +1,166 @@ +/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui.util;
+
+import com.ardor3d.image.Texture;
+import com.ardor3d.math.ColorRGBA;
+import com.ardor3d.math.type.ReadOnlyColorRGBA;
+import com.ardor3d.math.type.ReadOnlyRectangle2;
+
+/**
+ * Describes a sub-portion of a full Ardor3D Texture object. This is useful for taking a large image with lots of
+ * smaller images in it and reusing that same texture in multiple locations.
+ */
+public class SubTex {
+
+ private final Texture _texture;
+
+ /** The x location, in pixels, of our upper left corner */
+ private int _x;
+ /** The y location, in pixels, of our upper left corner */
+ private int _y;
+
+ /** The width, in pixels, of our part of the texture */
+ private int _width;
+ /** The height, in pixels, of our part of the texture */
+ private int _height;
+
+ /** The color to tint with when rendering this SubTex */
+ private ColorRGBA _tint = null;
+
+ /**
+ * Construct a new SubTex that covers the entire width and height of the supplied Texture.
+ *
+ * @param texture
+ * the base texture. Must already have a supplied image with a valid width and height.
+ */
+ public SubTex(final Texture texture) {
+ this(texture, 0, 0, texture.getImage().getWidth(), texture.getImage().getHeight());
+ }
+
+ /**
+ * Construct a new SubTex using the specified dimensions and location.
+ *
+ * @param texture
+ * the master texture we are a part of
+ * @param x
+ * the x location, in pixels, of our upper left corner.
+ * @param y
+ * the y location, in pixels, of our upper left corner.
+ * @param width
+ * the width, in pixels, of our part of the texture.
+ * @param height
+ * the height, in pixels, of our part of the texture.
+ */
+ public SubTex(final Texture texture, final int x, final int y, final int width, final int height) {
+ _texture = texture;
+ _x = x;
+ _y = y;
+ _width = width;
+ _height = height;
+ }
+
+ public Texture getTexture() {
+ return _texture;
+ }
+
+ public int getX() {
+ return _x;
+ }
+
+ public int getY() {
+ return _y;
+ }
+
+ public int getHeight() {
+ return _height;
+ }
+
+ public int getWidth() {
+ return _width;
+ }
+
+ public ReadOnlyColorRGBA getTint() {
+ return _tint;
+ }
+
+ /**
+ *
+ * @param color
+ * a color to blend our texture with when rendering SubTex objects. The default is null (which is
+ * interpreted as pure white and gives an unaltered version of the texture.)
+ */
+ public void setTint(final ReadOnlyColorRGBA color) {
+ if (color == null) {
+ _tint = null;
+ } else if (_tint == null) {
+ _tint = new ColorRGBA(color);
+ } else {
+ _tint.set(color);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "SubTex of " + _texture + ": " + _x + ", " + _y + " dims: " + _width + ", " + _height;
+ }
+
+ public void setHeight(final int height) {
+ _height = height;
+ }
+
+ public void setWidth(final int width) {
+ _width = width;
+ }
+
+ public void setX(final int x) {
+ _x = x;
+ }
+
+ public void setY(final int y) {
+ _y = y;
+ }
+
+ public void set(final ReadOnlyRectangle2 viewport) {
+ _x = viewport.getX();
+ _y = viewport.getY();
+ _width = viewport.getWidth();
+ _height = viewport.getHeight();
+ }
+
+ /**
+ * @return the uv coordinate, in [0, 1], of the right edge of this SubTex as relates to its master Texture.
+ */
+ public float getEndX() {
+ return (_width + _x) / (float) _texture.getImage().getWidth();
+ }
+
+ /**
+ * @return the uv coordinate, in [0, 1], of the top edge of this SubTex as relates to its master Texture.
+ */
+ public float getEndY() {
+ return (_height + _y) / (float) _texture.getImage().getHeight();
+ }
+
+ /**
+ * @return the uv coordinate, in [0, 1], of the left edge of this SubTex as relates to its master Texture.
+ */
+ public float getStartX() {
+ return _x / (float) _texture.getImage().getWidth();
+ }
+
+ /**
+ * @return the uv coordinate, in [0, 1], of the bottom edge of this SubTex as relates to its master Texture.
+ */
+ public float getStartY() {
+ return _y / (float) _texture.getImage().getHeight();
+ }
+}
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/util/SubTexUtil.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/util/SubTexUtil.java new file mode 100644 index 0000000..92c50f9 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/util/SubTexUtil.java @@ -0,0 +1,421 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui.util; + +import com.ardor3d.extension.ui.UIComponent; +import com.ardor3d.math.ColorRGBA; +import com.ardor3d.math.Transform; +import com.ardor3d.math.Vector3; +import com.ardor3d.math.type.ReadOnlyColorRGBA; +import com.ardor3d.math.type.ReadOnlyTransform; +import com.ardor3d.renderer.IndexMode; +import com.ardor3d.renderer.Renderer; +import com.ardor3d.renderer.state.BlendState; +import com.ardor3d.renderer.state.BlendState.DestinationFunction; +import com.ardor3d.renderer.state.BlendState.SourceFunction; +import com.ardor3d.renderer.state.TextureState; +import com.ardor3d.scenegraph.FloatBufferData; +import com.ardor3d.scenegraph.Mesh; +import com.ardor3d.util.geom.BufferUtils; + +/** + * SubTexUtil is a utility for drawing SubTex objects to a renderer. + */ +public class SubTexUtil { + + private static final Mesh _mesh = SubTexUtil.createMesh(); + private static final float[] _vals = new float[8]; + private static final float[] _texc = new float[8]; + private static TextureState _tstate = new TextureState(); + private static final Transform _helperT = new Transform(); + + /** + * Draw the given SubTex, as-is, to the screen at the given location. + * + * @param renderer + * the renderer to use + * @param subTex + * the SubTex to draw + * @param x + * the x coordinate of the screen location to draw at + * @param y + * the y coordinate of the screen location to draw at + */ + public static void drawSubTex(final Renderer renderer, final SubTex subTex, final int x, final int y) { + SubTexUtil.drawSubTex(renderer, subTex, x, y, subTex.getWidth(), subTex.getHeight(), false, null); + } + + /** + * Draw the given SubTex to the screen at the given location. Use the given width and height instead of those + * supplied in the SubTex. + * + * @param renderer + * the renderer to use + * @param subTex + * the SubTex to draw + * @param x + * the x coordinate of the screen location to draw at + * @param y + * the y coordinate of the screen location to draw at + * @param width + * the width in screen pixels to use when drawing the SubTex. + * @param height + * the height in screen pixels to use when drawing the SubTex. + * @param appliedTransform + * an optional transform to apply to the rendered subtex + */ + public static void drawSubTex(final Renderer renderer, final SubTex subTex, final int x, final int y, + final int width, final int height, final ReadOnlyTransform appliedTransform) { + SubTexUtil.drawSubTex(renderer, subTex, x, y, width, height, false, appliedTransform); + } + + /** + * Draw the given SubTex to the screen at the given location. Use the given width and height instead of those + * supplied in the SubTex. Does not flip vertically. + * + * @param renderer + * the renderer to use + * @param subTex + * the SubTex to draw + * @param x + * the x coordinate of the screen location to draw at + * @param y + * the y coordinate of the screen location to draw at + * @param width + * the width in screen pixels to use when drawing the SubTex. + * @param height + * the height in screen pixels to use when drawing the SubTex. + * @param appliedTransform + * an optional transform to apply to the rendered subtex + */ + public static void drawSubTex(final Renderer renderer, final SubTex subTex, final double x, final double y, + final double width, final double height, final ReadOnlyTransform appliedTransform) { + SubTexUtil.drawSubTex(renderer, subTex, (int) Math.round(x), (int) Math.round(y), (int) Math.round(width), + (int) Math.round(height), false, appliedTransform, null); + } + + /** + * Draw the given SubTex to the screen at the given location. Use the given width and height instead of those + * supplied in the SubTex. Does not flip vertically. + * + * @param renderer + * the renderer to use + * @param subTex + * the SubTex to draw + * @param x + * the x coordinate of the screen location to draw at + * @param y + * the y coordinate of the screen location to draw at + * @param width + * the width in screen pixels to use when drawing the SubTex. + * @param height + * the height in screen pixels to use when drawing the SubTex. + * @param appliedTransform + * an optional transform to apply to the rendered subtex + */ + public static void drawSubTex(final Renderer renderer, final SubTex subTex, final double x, final double y, + final double width, final double height, final ReadOnlyTransform appliedTransform, + final ReadOnlyColorRGBA tintOverride) { + SubTexUtil.drawSubTex(renderer, subTex, (int) Math.round(x), (int) Math.round(y), (int) Math.round(width), + (int) Math.round(height), false, appliedTransform, tintOverride); + } + + /** + * Draw the given SubTex to the screen at the given location. Use the given width and height instead of those + * supplied in the SubTex. + * + * @param renderer + * the renderer to use + * @param subTex + * the SubTex to draw + * @param x + * the x coordinate of the screen location to draw at + * @param y + * the y coordinate of the screen location to draw at + * @param width + * the width in screen pixels to use when drawing the SubTex. + * @param height + * the height in screen pixels to use when drawing the SubTex. + */ + public static void drawSubTex(final Renderer renderer, final SubTex subTex, final double x, final double y, + final double width, final double height) { + SubTexUtil.drawSubTex(renderer, subTex, (int) Math.round(x), (int) Math.round(y), (int) Math.round(width), + (int) Math.round(height), false, null); + } + + /** + * Draw the given SubTex, optionally inverted on the Y axis, to the screen at the given location. Use the given + * width and height instead of those supplied in the SubTex. + * + * @param renderer + * the renderer to use + * @param subTex + * the SubTex to draw + * @param x + * the x offset to draw at + * @param y + * the y offset to draw at + * @param width + * the width in screen pixels to use when drawing the SubTex. + * @param height + * the height in screen pixels to use when drawing the SubTex. + * @param flipVertical + * if true, invert the image vertically before drawing + * @param appliedTransform + * an optional transform to apply to the rendered subtex + */ + public static void drawSubTex(final Renderer renderer, final SubTex subTex, final int x, final int y, + final int width, final int height, final boolean flipVertical, final ReadOnlyTransform appliedTransform) { + SubTexUtil.drawSubTex(renderer, subTex, x, y, width, height, flipVertical, appliedTransform, null); + } + + /** + * Draw the given SubTex, optionally inverted on the Y axis, to the screen at the given location. Use the given + * width and height instead of those supplied in the SubTex. + * + * @param renderer + * the renderer to use + * @param subTex + * the SubTex to draw + * @param x + * the x offset to draw at + * @param y + * the y offset to draw at + * @param width + * the width in screen pixels to use when drawing the SubTex. + * @param height + * the height in screen pixels to use when drawing the SubTex. + * @param flipVertical + * if true, invert the image vertically before drawing + * @param appliedTransform + * an optional transform to apply to the rendered subtex + * @param tintOverride + * an optional override for the SubTex tintColor. + */ + public static void drawSubTex(final Renderer renderer, final SubTex subTex, final int x, final int y, + final int width, final int height, final boolean flipVertical, final ReadOnlyTransform appliedTransform, + final ReadOnlyColorRGBA tintOverride) { + + if (width == 0 || height == 0 || subTex == null || subTex.getTexture() == null) { + return; // no need to draw + } + + // Optimization: Check to see if the given SubTex's Texture is the same one we used "last time". + if (SubTexUtil._tstate.getNumberOfSetTextures() == 0 || SubTexUtil._tstate.getTexture().getTextureKey() == null + || !SubTexUtil._tstate.getTexture().getTextureKey().equals(subTex.getTexture().getTextureKey())) { + SubTexUtil._tstate.setTexture(subTex.getTexture()); + SubTexUtil._mesh.setRenderState(SubTexUtil._tstate); + SubTexUtil._mesh.updateWorldRenderStates(false); + } + + // Setup our tint color and alpha value. + final ColorRGBA defaultColor = ColorRGBA.fetchTempInstance(); + if (tintOverride != null) { + defaultColor.set(tintOverride); + defaultColor.setAlpha(UIComponent.getCurrentOpacity() * tintOverride.getAlpha()); + } else if (subTex.getTint() != null) { + defaultColor.set(subTex.getTint()); + defaultColor.setAlpha(UIComponent.getCurrentOpacity() * subTex.getTint().getAlpha()); + } else { + defaultColor.set(ColorRGBA.WHITE); + defaultColor.setAlpha(UIComponent.getCurrentOpacity()); + } + SubTexUtil._mesh.setDefaultColor(defaultColor); + ColorRGBA.releaseTempInstance(defaultColor); + + final float endY = subTex.getEndY(); + final float endX = subTex.getEndX(); + + final float startX = subTex.getStartX(); + final float startY = subTex.getStartY(); + + // Set up texture coordinates based on vertical flip + if (!flipVertical) { + SubTexUtil._texc[0] = startX; + SubTexUtil._texc[1] = endY; + SubTexUtil._texc[2] = endX; + SubTexUtil._texc[3] = endY; + SubTexUtil._texc[4] = endX; + SubTexUtil._texc[5] = startY; + SubTexUtil._texc[6] = startX; + SubTexUtil._texc[7] = startY; + } else { + SubTexUtil._texc[0] = startX; + SubTexUtil._texc[1] = startY; + SubTexUtil._texc[2] = endX; + SubTexUtil._texc[3] = startY; + SubTexUtil._texc[4] = endX; + SubTexUtil._texc[5] = endY; + SubTexUtil._texc[6] = startX; + SubTexUtil._texc[7] = endY; + } + + SubTexUtil._vals[0] = 0; + SubTexUtil._vals[1] = 0; + SubTexUtil._vals[2] = width; + SubTexUtil._vals[3] = 0; + SubTexUtil._vals[4] = width; + SubTexUtil._vals[5] = height; + SubTexUtil._vals[6] = 0; + SubTexUtil._vals[7] = height; + + // Set our transform + final ReadOnlyTransform worldT = appliedTransform != null ? appliedTransform : Transform.IDENTITY; + final Vector3 v = Vector3.fetchTempInstance(); + v.set(x, y, 0); + SubTexUtil._helperT.set(worldT); + SubTexUtil._helperT.applyForwardVector(v); + SubTexUtil._helperT.translate(v); + Vector3.releaseTempInstance(v); + SubTexUtil._mesh.setWorldTransform(SubTexUtil._helperT); + + // set our vertices into the mesh + SubTexUtil._mesh.getMeshData().getVertexBuffer().rewind(); + SubTexUtil._mesh.getMeshData().getVertexBuffer().put(SubTexUtil._vals); + + // set our texture coords into the mesh + SubTexUtil._mesh.getMeshData().getTextureBuffer(0).rewind(); + SubTexUtil._mesh.getMeshData().getTextureBuffer(0).put(SubTexUtil._texc); + + // draw mesh + SubTexUtil._mesh.render(renderer); + } + + /** + * Draw the given TransformedSubTex, optionally inverted on the Y axis, to the screen at the given location. Use the + * given width and height instead of those supplied in the TransformedSubTex. + * + * @param renderer + * the renderer to use + * @param subTex + * the TransformedSubTex to draw + * @param x + * the x coordinate of the screen location to draw at + * @param y + * the y coordinate of the screen location to draw at + * @param width + * the width in screen pixels to use when drawing the TransformedSubTex. + * @param height + * the height in screen pixels to use when drawing the TransformedSubTex. + * @param flipVertical + * if true, invert the image vertically before drawing + * @param appliedTransform + * an optional transform to apply to the rendered subtex + */ + public static void drawTransformedSubTex(final Renderer renderer, final TransformedSubTex subTex, final int x, + final int y, final int width, final int height, final boolean flipVertical, + final ReadOnlyTransform appliedTransform) { + + if (width == 0 || height == 0 || subTex == null || subTex.getTexture() == null) { + return; // no need to draw + } + + // Optimization: Check to see if the given SubTex's Texture is the same one we used "last time". + if (SubTexUtil._tstate.getNumberOfSetTextures() == 0 || SubTexUtil._tstate.getTexture().getTextureKey() == null + || !SubTexUtil._tstate.getTexture().getTextureKey().equals(subTex.getTexture().getTextureKey())) { + SubTexUtil._tstate.setTexture(subTex.getTexture()); + SubTexUtil._mesh.setRenderState(SubTexUtil._tstate); + SubTexUtil._mesh.updateWorldRenderStates(false); + } + + // Setup our tint color and alpha value. + final ColorRGBA defaultColor = ColorRGBA.fetchTempInstance(); + if (subTex.getTint() != null) { + defaultColor.set(subTex.getTint()); + defaultColor.setAlpha(UIComponent.getCurrentOpacity() * subTex.getTint().getAlpha()); + } else { + defaultColor.set(ColorRGBA.WHITE); + defaultColor.setAlpha(UIComponent.getCurrentOpacity()); + } + SubTexUtil._mesh.setDefaultColor(defaultColor); + ColorRGBA.releaseTempInstance(defaultColor); + + final float endY = subTex.getEndY(); + final float endX = subTex.getEndX(); + + final float startX = subTex.getStartX(); + final float startY = subTex.getStartY(); + + // Set up texture coordinates based on vertical flip + if (!flipVertical) { + SubTexUtil._texc[0] = startX; + SubTexUtil._texc[1] = endY; + SubTexUtil._texc[2] = endX; + SubTexUtil._texc[3] = endY; + SubTexUtil._texc[4] = endX; + SubTexUtil._texc[5] = startY; + SubTexUtil._texc[6] = startX; + SubTexUtil._texc[7] = startY; + } else { + SubTexUtil._texc[0] = startX; + SubTexUtil._texc[1] = startY; + SubTexUtil._texc[2] = endX; + SubTexUtil._texc[3] = startY; + SubTexUtil._texc[4] = endX; + SubTexUtil._texc[5] = endY; + SubTexUtil._texc[6] = startX; + SubTexUtil._texc[7] = endY; + } + + final float leftW = -subTex.getPivot().getXf() * width; + final float rightW = (1f - subTex.getPivot().getXf()) * width; + final float leftH = -subTex.getPivot().getYf() * height; + final float rightH = (1f - subTex.getPivot().getYf()) * height; + SubTexUtil._vals[0] = leftW; + SubTexUtil._vals[1] = leftH; + SubTexUtil._vals[2] = rightW; + SubTexUtil._vals[3] = leftH; + SubTexUtil._vals[4] = rightW; + SubTexUtil._vals[5] = rightH; + SubTexUtil._vals[6] = leftW; + SubTexUtil._vals[7] = rightH; + + // Set our transform + final ReadOnlyTransform worldT = appliedTransform != null ? appliedTransform : Transform.IDENTITY; + final Vector3 v = Vector3.fetchTempInstance(); + v.set(x, y, 0); + worldT.applyForwardVector(v); + worldT.multiply(subTex.getTransform(), SubTexUtil._helperT); + SubTexUtil._helperT.translate(v); + Vector3.releaseTempInstance(v); + SubTexUtil._mesh.setWorldTransform(SubTexUtil._helperT); + + // set our vertices into the mesh + SubTexUtil._mesh.getMeshData().getVertexBuffer().rewind(); + SubTexUtil._mesh.getMeshData().getVertexBuffer().put(SubTexUtil._vals); + + // set our texture coords into the mesh + SubTexUtil._mesh.getMeshData().getTextureBuffer(0).rewind(); + SubTexUtil._mesh.getMeshData().getTextureBuffer(0).put(SubTexUtil._texc); + + // draw mesh + SubTexUtil._mesh.render(renderer); + } + + private static Mesh createMesh() { + final Mesh mesh = new Mesh(); + mesh.getMeshData().setVertexCoords(new FloatBufferData(BufferUtils.createVector2Buffer(4), 2)); + mesh.getMeshData().setTextureBuffer(BufferUtils.createVector2Buffer(4), 0); + mesh.getMeshData().setIndexMode(IndexMode.TriangleFan); + + mesh.setRenderState(SubTexUtil._tstate); + + final BlendState blend = new BlendState(); + blend.setBlendEnabled(true); + blend.setSourceFunction(SourceFunction.SourceAlpha); + blend.setDestinationFunction(DestinationFunction.OneMinusSourceAlpha); + mesh.setRenderState(blend); + + mesh.updateWorldRenderStates(false); + + return mesh; + } +} diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/util/TransformedSubTex.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/util/TransformedSubTex.java new file mode 100644 index 0000000..dc3140d --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/util/TransformedSubTex.java @@ -0,0 +1,72 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui.util; + +import com.ardor3d.image.Texture; +import com.ardor3d.math.Transform; +import com.ardor3d.math.Vector2; +import com.ardor3d.math.type.ReadOnlyTransform; + +public class TransformedSubTex extends SubTex implements Comparable<TransformedSubTex> { + + final Transform _transform = new Transform(); + final Vector2 _pivot = new Vector2(.5, .5); + private int _priority = 0; + private Alignment _alignment = Alignment.BOTTOM_LEFT; + + public TransformedSubTex(final SubTex source) { + this(source.getTexture(), source.getX(), source.getY(), source.getWidth(), source.getHeight()); + } + + public TransformedSubTex(final Texture texture) { + super(texture); + } + + public TransformedSubTex(final Texture texture, final int x, final int y, final int width, final int height) { + super(texture, x, y, width, height); + } + + public void setTransform(final ReadOnlyTransform transform) { + _transform.set(transform); + } + + public Transform getTransform() { + return _transform; + } + + public void setPivot(final Vector2 pivot) { + _pivot.set(pivot); + } + + public Vector2 getPivot() { + return _pivot; + } + + public void setAlignment(final Alignment alignment) { + _alignment = alignment; + } + + public Alignment getAlignment() { + return _alignment; + } + + public void setPriority(final int priority) { + _priority = priority; + } + + public int getPriority() { + return _priority; + } + + public int compareTo(final TransformedSubTex other) { + return _priority - other._priority; + } +}
\ No newline at end of file diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/util/UIQuad.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/util/UIQuad.java new file mode 100644 index 0000000..64fd253 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/util/UIQuad.java @@ -0,0 +1,98 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui.util; + +import java.nio.FloatBuffer; + +import com.ardor3d.renderer.IndexMode; +import com.ardor3d.scenegraph.FloatBufferData; +import com.ardor3d.scenegraph.Mesh; +import com.ardor3d.util.geom.BufferUtils; + +/** + * Defines a four sided quad with its origin at the lower left corner. By default, this mesh only contains vertices (in + * the two dimensional space) and texture coordinates. + */ +public class UIQuad extends Mesh { + + /** The width of this ui quad */ + protected double _width = 0; + /** The height of this ui quad */ + protected double _height = 0; + + /** Construct a new 1x1 UI quad. */ + public UIQuad() { + this(null); + } + + /** + * Construct a new 1x1 UI quad with the given name. + * + * @param name + */ + public UIQuad(final String name) { + this(name, 1, 1); + } + + /** + * Construct a new UI quad with the given name and dimensions. + * + * @param name + * @param width + * @param height + */ + public UIQuad(final String name, final double width, final double height) { + super(name); + initialize(); + resize(width, height); + } + + /** + * Alter the vertices of this Ui quad so that it of the given size. + * + * @param width + * @param height + */ + public void resize(final double width, final double height) { + _width = width; + _height = height; + + _meshData.getVertexBuffer().clear(); + _meshData.getVertexBuffer().put(0).put((float) _height); + _meshData.getVertexBuffer().put(0).put(0); + _meshData.getVertexBuffer().put((float) _width).put(0); + _meshData.getVertexBuffer().put((float) _width).put((float) _height); + } + + /** + * Set the basic data for this mesh such as texture coordinates, index mode and our vertex buffer. + */ + private void initialize() { + _meshData.setVertexCoords(new FloatBufferData(BufferUtils.createVector2Buffer(4), 2)); + final FloatBuffer tbuf = BufferUtils.createVector2Buffer(4); + _meshData.setTextureBuffer(tbuf, 0); + + tbuf.put(0).put(1); + tbuf.put(0).put(0); + tbuf.put(1).put(0); + tbuf.put(1).put(1); + + _meshData.setIndexMode(IndexMode.TriangleFan); + } + + public double getWidth() { + return _width; + } + + public double getHeight() { + return _height; + } +}
\ No newline at end of file diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/util/package-info.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/util/package-info.java new file mode 100644 index 0000000..9332556 --- /dev/null +++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/util/package-info.java @@ -0,0 +1,5 @@ +/** + * General utility and data objects useful for the UI system. + */ + +package com.ardor3d.extension.ui.util;
\ No newline at end of file diff --git a/ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-12-regular.fnt b/ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-12-regular.fnt new file mode 100644 index 0000000..183700a --- /dev/null +++ b/ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-12-regular.fnt @@ -0,0 +1,596 @@ +<?xml version="1.0"?>
+<font>
+ <info face="Arial" size="12" bold="0" italic="0" charset="" unicode="1" stretchH="100" smooth="1" aa="1" padding="0,0,0,0" spacing="1,1" outline="0"/>
+ <common lineHeight="12" base="9" scaleW="256" scaleH="256" pages="1" packed="0" alphaChnl="0" redChnl="4" greenChnl="4" blueChnl="4"/>
+ <pages>
+ <page id="0" file="arial-12-regular_0.png" />
+ </pages>
+ <chars count="527">
+ <char id="32" x="164" y="97" width="1" height="1" xoffset="0" yoffset="9" xadvance="3" page="0" chnl="15" />
+ <char id="33" x="114" y="91" width="1" height="7" xoffset="1" yoffset="2" xadvance="3" page="0" chnl="15" />
+ <char id="34" x="122" y="98" width="3" height="2" xoffset="0" yoffset="2" xadvance="3" page="0" chnl="15" />
+ <char id="35" x="195" y="83" width="4" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="36" x="170" y="41" width="5" height="8" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="37" x="102" y="67" width="6" height="7" xoffset="1" yoffset="2" xadvance="8" page="0" chnl="15" />
+ <char id="38" x="109" y="67" width="6" height="7" xoffset="0" yoffset="2" xadvance="6" page="0" chnl="15" />
+ <char id="39" x="134" y="98" width="1" height="2" xoffset="0" yoffset="2" xadvance="2" page="0" chnl="15" />
+ <char id="40" x="252" y="20" width="3" height="9" xoffset="0" yoffset="2" xadvance="3" page="0" chnl="15" />
+ <char id="41" x="243" y="30" width="3" height="9" xoffset="0" yoffset="2" xadvance="3" page="0" chnl="15" />
+ <char id="42" x="96" y="99" width="3" height="3" xoffset="0" yoffset="2" xadvance="4" page="0" chnl="15" />
+ <char id="43" x="187" y="91" width="5" height="5" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="44" x="132" y="98" width="1" height="2" xoffset="1" yoffset="8" xadvance="3" page="0" chnl="15" />
+ <char id="45" x="155" y="97" width="2" height="1" xoffset="0" yoffset="6" xadvance="3" page="0" chnl="15" />
+ <char id="46" x="160" y="97" width="1" height="1" xoffset="1" yoffset="8" xadvance="3" page="0" chnl="15" />
+ <char id="47" x="60" y="92" width="3" height="7" xoffset="0" yoffset="2" xadvance="3" page="0" chnl="15" />
+ <char id="48" x="205" y="82" width="4" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="49" x="100" y="91" width="2" height="7" xoffset="1" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="50" x="210" y="82" width="4" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="51" x="215" y="82" width="4" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="52" x="210" y="74" width="5" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="53" x="225" y="82" width="4" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="54" x="15" y="95" width="4" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="55" x="10" y="95" width="4" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="56" x="0" y="95" width="4" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="57" x="250" y="82" width="4" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="58" x="54" y="101" width="1" height="5" xoffset="1" yoffset="4" xadvance="3" page="0" chnl="15" />
+ <char id="59" x="146" y="91" width="1" height="6" xoffset="1" yoffset="4" xadvance="3" page="0" chnl="15" />
+ <char id="60" x="34" y="102" width="3" height="5" xoffset="1" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="61" x="78" y="100" width="4" height="3" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="62" x="50" y="101" width="3" height="5" xoffset="1" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="63" x="48" y="77" width="5" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="64" x="207" y="0" width="8" height="9" xoffset="1" yoffset="2" xadvance="9" page="0" chnl="15" />
+ <char id="65" x="215" y="58" width="7" height="7" xoffset="0" yoffset="2" xadvance="6" page="0" chnl="15" />
+ <char id="66" x="190" y="83" width="4" height="7" xoffset="1" yoffset="2" xadvance="6" page="0" chnl="15" />
+ <char id="67" x="66" y="76" width="5" height="7" xoffset="1" yoffset="2" xadvance="7" page="0" chnl="15" />
+ <char id="68" x="84" y="75" width="5" height="7" xoffset="1" yoffset="2" xadvance="7" page="0" chnl="15" />
+ <char id="69" x="102" y="75" width="5" height="7" xoffset="1" yoffset="2" xadvance="6" page="0" chnl="15" />
+ <char id="70" x="185" y="83" width="4" height="7" xoffset="1" yoffset="2" xadvance="6" page="0" chnl="15" />
+ <char id="71" x="114" y="75" width="5" height="7" xoffset="1" yoffset="2" xadvance="7" page="0" chnl="15" />
+ <char id="72" x="126" y="75" width="5" height="7" xoffset="1" yoffset="2" xadvance="7" page="0" chnl="15" />
+ <char id="73" x="120" y="91" width="1" height="7" xoffset="1" yoffset="2" xadvance="3" page="0" chnl="15" />
+ <char id="74" x="170" y="83" width="4" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="75" x="150" y="75" width="5" height="7" xoffset="1" yoffset="2" xadvance="6" page="0" chnl="15" />
+ <char id="76" x="160" y="83" width="4" height="7" xoffset="1" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="77" x="56" y="68" width="7" height="7" xoffset="0" yoffset="2" xadvance="7" page="0" chnl="15" />
+ <char id="78" x="216" y="74" width="5" height="7" xoffset="1" yoffset="2" xadvance="7" page="0" chnl="15" />
+ <char id="79" x="207" y="66" width="5" height="7" xoffset="1" yoffset="2" xadvance="7" page="0" chnl="15" />
+ <char id="80" x="155" y="83" width="4" height="7" xoffset="1" yoffset="2" xadvance="6" page="0" chnl="15" />
+ <char id="81" x="84" y="50" width="5" height="8" xoffset="1" yoffset="2" xadvance="7" page="0" chnl="15" />
+ <char id="82" x="95" y="67" width="6" height="7" xoffset="1" yoffset="2" xadvance="7" page="0" chnl="15" />
+ <char id="83" x="150" y="83" width="4" height="7" xoffset="1" yoffset="2" xadvance="6" page="0" chnl="15" />
+ <char id="84" x="198" y="75" width="5" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="85" x="72" y="76" width="5" height="7" xoffset="1" yoffset="2" xadvance="7" page="0" chnl="15" />
+ <char id="86" x="118" y="59" width="9" height="7" xoffset="-1" yoffset="2" xadvance="6" page="0" chnl="15" />
+ <char id="87" x="128" y="59" width="9" height="7" xoffset="0" yoffset="2" xadvance="9" page="0" chnl="15" />
+ <char id="88" x="237" y="66" width="5" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="89" x="18" y="78" width="5" height="7" xoffset="1" yoffset="2" xadvance="7" page="0" chnl="15" />
+ <char id="90" x="130" y="67" width="6" height="7" xoffset="0" yoffset="2" xadvance="6" page="0" chnl="15" />
+ <char id="91" x="24" y="41" width="2" height="9" xoffset="1" yoffset="2" xadvance="3" page="0" chnl="15" />
+ <char id="92" x="56" y="93" width="3" height="7" xoffset="0" yoffset="2" xadvance="3" page="0" chnl="15" />
+ <char id="93" x="39" y="41" width="2" height="9" xoffset="0" yoffset="2" xadvance="3" page="0" chnl="15" />
+ <char id="94" x="100" y="99" width="3" height="3" xoffset="0" yoffset="2" xadvance="3" page="0" chnl="15" />
+ <char id="95" x="142" y="98" width="5" height="1" xoffset="0" yoffset="10" xadvance="5" page="0" chnl="15" />
+ <char id="96" x="129" y="98" width="2" height="2" xoffset="0" yoffset="2" xadvance="3" page="0" chnl="15" />
+ <char id="97" x="15" y="103" width="4" height="5" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="98" x="140" y="83" width="4" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="99" x="223" y="90" width="4" height="5" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="100" x="135" y="83" width="4" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="101" x="233" y="90" width="4" height="5" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="102" x="130" y="83" width="4" height="7" xoffset="0" yoffset="2" xadvance="4" page="0" chnl="15" />
+ <char id="103" x="125" y="83" width="4" height="7" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="104" x="120" y="83" width="4" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="105" x="112" y="91" width="1" height="7" xoffset="0" yoffset="2" xadvance="2" page="0" chnl="15" />
+ <char id="106" x="36" y="41" width="2" height="9" xoffset="-1" yoffset="2" xadvance="2" page="0" chnl="15" />
+ <char id="107" x="115" y="83" width="4" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="108" x="108" y="91" width="1" height="7" xoffset="0" yoffset="2" xadvance="2" page="0" chnl="15" />
+ <char id="109" x="165" y="91" width="7" height="5" xoffset="0" yoffset="4" xadvance="8" page="0" chnl="15" />
+ <char id="110" x="243" y="90" width="4" height="5" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="111" x="5" y="103" width="4" height="5" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="112" x="110" y="83" width="4" height="7" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="113" x="105" y="83" width="4" height="7" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="114" x="46" y="101" width="3" height="5" xoffset="0" yoffset="4" xadvance="3" page="0" chnl="15" />
+ <char id="115" x="10" y="103" width="4" height="5" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="116" x="72" y="92" width="3" height="7" xoffset="-1" yoffset="2" xadvance="3" page="0" chnl="15" />
+ <char id="117" x="25" y="102" width="4" height="5" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="118" x="211" y="90" width="5" height="5" xoffset="0" yoffset="4" xadvance="6" page="0" chnl="15" />
+ <char id="119" x="217" y="90" width="5" height="5" xoffset="0" yoffset="4" xadvance="6" page="0" chnl="15" />
+ <char id="120" x="228" y="90" width="4" height="5" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="121" x="144" y="75" width="5" height="7" xoffset="0" yoffset="4" xadvance="6" page="0" chnl="15" />
+ <char id="122" x="30" y="102" width="3" height="5" xoffset="0" yoffset="4" xadvance="4" page="0" chnl="15" />
+ <char id="123" x="0" y="43" width="3" height="9" xoffset="0" yoffset="2" xadvance="3" page="0" chnl="15" />
+ <char id="124" x="69" y="59" width="1" height="8" xoffset="1" yoffset="2" xadvance="3" page="0" chnl="15" />
+ <char id="125" x="12" y="42" width="3" height="9" xoffset="0" yoffset="2" xadvance="3" page="0" chnl="15" />
+ <char id="126" x="83" y="100" width="4" height="3" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="160" x="162" y="97" width="1" height="1" xoffset="0" yoffset="9" xadvance="3" page="0" chnl="15" />
+ <char id="161" x="118" y="91" width="1" height="7" xoffset="1" yoffset="4" xadvance="3" page="0" chnl="15" />
+ <char id="162" x="132" y="0" width="4" height="10" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="163" x="213" y="66" width="5" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="164" x="68" y="100" width="4" height="4" xoffset="1" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="165" x="243" y="66" width="5" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="166" x="254" y="40" width="1" height="8" xoffset="1" yoffset="2" xadvance="3" page="0" chnl="15" />
+ <char id="167" x="188" y="30" width="4" height="9" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="168" x="148" y="97" width="3" height="1" xoffset="0" yoffset="2" xadvance="3" page="0" chnl="15" />
+ <char id="169" x="40" y="69" width="7" height="7" xoffset="0" yoffset="2" xadvance="7" page="0" chnl="15" />
+ <char id="170" x="108" y="99" width="3" height="3" xoffset="0" yoffset="2" xadvance="3" page="0" chnl="15" />
+ <char id="171" x="56" y="101" width="5" height="4" xoffset="0" yoffset="5" xadvance="5" page="0" chnl="15" />
+ <char id="172" x="73" y="100" width="4" height="3" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="173" x="152" y="97" width="2" height="1" xoffset="0" yoffset="6" xadvance="3" page="0" chnl="15" />
+ <char id="174" x="8" y="71" width="7" height="7" xoffset="0" yoffset="2" xadvance="7" page="0" chnl="15" />
+ <char id="175" x="136" y="98" width="5" height="1" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="176" x="104" y="99" width="3" height="3" xoffset="1" yoffset="2" xadvance="4" page="0" chnl="15" />
+ <char id="177" x="129" y="91" width="5" height="6" xoffset="0" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="178" x="112" y="99" width="3" height="3" xoffset="0" yoffset="2" xadvance="3" page="0" chnl="15" />
+ <char id="179" x="88" y="99" width="3" height="3" xoffset="0" yoffset="2" xadvance="3" page="0" chnl="15" />
+ <char id="180" x="126" y="98" width="2" height="2" xoffset="1" yoffset="2" xadvance="3" page="0" chnl="15" />
+ <char id="181" x="90" y="83" width="4" height="7" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="182" x="146" y="41" width="5" height="8" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="183" x="158" y="97" width="1" height="1" xoffset="1" yoffset="5" xadvance="3" page="0" chnl="15" />
+ <char id="184" x="116" y="99" width="2" height="3" xoffset="0" yoffset="9" xadvance="3" page="0" chnl="15" />
+ <char id="185" x="119" y="99" width="2" height="3" xoffset="1" yoffset="2" xadvance="3" page="0" chnl="15" />
+ <char id="186" x="92" y="99" width="3" height="3" xoffset="0" yoffset="2" xadvance="3" page="0" chnl="15" />
+ <char id="187" x="62" y="100" width="5" height="4" xoffset="0" yoffset="5" xadvance="5" page="0" chnl="15" />
+ <char id="188" x="156" y="59" width="8" height="7" xoffset="0" yoffset="2" xadvance="8" page="0" chnl="15" />
+ <char id="189" x="0" y="71" width="7" height="7" xoffset="1" yoffset="2" xadvance="8" page="0" chnl="15" />
+ <char id="190" x="138" y="59" width="8" height="7" xoffset="0" yoffset="2" xadvance="8" page="0" chnl="15" />
+ <char id="191" x="50" y="85" width="4" height="7" xoffset="1" yoffset="4" xadvance="6" page="0" chnl="15" />
+ <char id="192" x="0" y="13" width="7" height="9" xoffset="0" yoffset="0" xadvance="6" page="0" chnl="15" />
+ <char id="193" x="8" y="12" width="7" height="9" xoffset="0" yoffset="0" xadvance="6" page="0" chnl="15" />
+ <char id="194" x="32" y="11" width="7" height="9" xoffset="0" yoffset="0" xadvance="6" page="0" chnl="15" />
+ <char id="195" x="40" y="11" width="7" height="9" xoffset="0" yoffset="0" xadvance="6" page="0" chnl="15" />
+ <char id="196" x="86" y="41" width="7" height="8" xoffset="0" yoffset="1" xadvance="6" page="0" chnl="15" />
+ <char id="197" x="16" y="12" width="7" height="9" xoffset="0" yoffset="0" xadvance="6" page="0" chnl="15" />
+ <char id="198" x="86" y="59" width="10" height="7" xoffset="-1" yoffset="2" xadvance="9" page="0" chnl="15" />
+ <char id="199" x="54" y="0" width="5" height="10" xoffset="1" yoffset="2" xadvance="6" page="0" chnl="15" />
+ <char id="200" x="0" y="33" width="5" height="9" xoffset="1" yoffset="0" xadvance="6" page="0" chnl="15" />
+ <char id="201" x="6" y="33" width="5" height="9" xoffset="1" yoffset="0" xadvance="6" page="0" chnl="15" />
+ <char id="202" x="12" y="32" width="5" height="9" xoffset="1" yoffset="0" xadvance="6" page="0" chnl="15" />
+ <char id="203" x="152" y="41" width="5" height="8" xoffset="1" yoffset="1" xadvance="6" page="0" chnl="15" />
+ <char id="204" x="33" y="41" width="2" height="9" xoffset="1" yoffset="0" xadvance="3" page="0" chnl="15" />
+ <char id="205" x="30" y="41" width="2" height="9" xoffset="0" yoffset="0" xadvance="3" page="0" chnl="15" />
+ <char id="206" x="18" y="32" width="5" height="9" xoffset="-2" yoffset="0" xadvance="3" page="0" chnl="15" />
+ <char id="207" x="39" y="60" width="3" height="8" xoffset="0" yoffset="1" xadvance="3" page="0" chnl="15" />
+ <char id="208" x="165" y="67" width="6" height="7" xoffset="0" yoffset="2" xadvance="6" page="0" chnl="15" />
+ <char id="209" x="24" y="31" width="5" height="9" xoffset="1" yoffset="0" xadvance="6" page="0" chnl="15" />
+ <char id="210" x="30" y="31" width="5" height="9" xoffset="1" yoffset="0" xadvance="7" page="0" chnl="15" />
+ <char id="211" x="36" y="31" width="5" height="9" xoffset="1" yoffset="0" xadvance="7" page="0" chnl="15" />
+ <char id="212" x="42" y="31" width="5" height="9" xoffset="1" yoffset="0" xadvance="7" page="0" chnl="15" />
+ <char id="213" x="48" y="31" width="5" height="9" xoffset="1" yoffset="0" xadvance="7" page="0" chnl="15" />
+ <char id="214" x="24" y="51" width="5" height="8" xoffset="1" yoffset="1" xadvance="7" page="0" chnl="15" />
+ <char id="215" x="180" y="91" width="6" height="5" xoffset="0" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="216" x="36" y="51" width="5" height="8" xoffset="1" yoffset="2" xadvance="7" page="0" chnl="15" />
+ <char id="217" x="54" y="31" width="5" height="9" xoffset="1" yoffset="0" xadvance="6" page="0" chnl="15" />
+ <char id="218" x="60" y="31" width="5" height="9" xoffset="1" yoffset="0" xadvance="6" page="0" chnl="15" />
+ <char id="219" x="66" y="31" width="5" height="9" xoffset="1" yoffset="0" xadvance="6" page="0" chnl="15" />
+ <char id="220" x="200" y="40" width="5" height="8" xoffset="1" yoffset="1" xadvance="6" page="0" chnl="15" />
+ <char id="221" x="72" y="31" width="5" height="9" xoffset="1" yoffset="0" xadvance="6" page="0" chnl="15" />
+ <char id="222" x="30" y="78" width="5" height="7" xoffset="1" yoffset="2" xadvance="6" page="0" chnl="15" />
+ <char id="223" x="30" y="86" width="4" height="7" xoffset="1" yoffset="2" xadvance="6" page="0" chnl="15" />
+ <char id="224" x="192" y="49" width="4" height="8" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="225" x="197" y="49" width="4" height="8" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="226" x="158" y="41" width="5" height="8" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="227" x="202" y="49" width="4" height="8" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="228" x="25" y="86" width="4" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="229" x="123" y="31" width="4" height="9" xoffset="0" yoffset="0" xadvance="5" page="0" chnl="15" />
+ <char id="230" x="157" y="91" width="7" height="5" xoffset="0" yoffset="4" xadvance="8" page="0" chnl="15" />
+ <char id="231" x="207" y="49" width="4" height="8" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="232" x="212" y="49" width="4" height="8" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="233" x="217" y="49" width="4" height="8" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="234" x="78" y="50" width="5" height="8" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="235" x="0" y="87" width="4" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="236" x="66" y="59" width="2" height="8" xoffset="0" yoffset="1" xadvance="3" page="0" chnl="15" />
+ <char id="237" x="63" y="59" width="2" height="8" xoffset="-1" yoffset="1" xadvance="3" page="0" chnl="15" />
+ <char id="238" x="66" y="50" width="5" height="8" xoffset="-1" yoffset="1" xadvance="3" page="0" chnl="15" />
+ <char id="239" x="48" y="93" width="3" height="7" xoffset="-1" yoffset="2" xadvance="3" page="0" chnl="15" />
+ <char id="240" x="238" y="74" width="4" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="241" x="222" y="49" width="4" height="8" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="242" x="227" y="49" width="4" height="8" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="243" x="232" y="49" width="4" height="8" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="244" x="54" y="50" width="5" height="8" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="245" x="237" y="49" width="4" height="8" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="246" x="233" y="74" width="4" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="247" x="205" y="90" width="5" height="5" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="248" x="135" y="91" width="5" height="6" xoffset="-1" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="249" x="242" y="49" width="4" height="8" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="250" x="247" y="49" width="4" height="8" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="251" x="30" y="51" width="5" height="8" xoffset="-1" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="252" x="228" y="74" width="4" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="253" x="96" y="0" width="5" height="10" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="254" x="158" y="31" width="4" height="9" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="255" x="205" y="10" width="5" height="9" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="256" x="94" y="41" width="7" height="8" xoffset="0" yoffset="1" xadvance="6" page="0" chnl="15" />
+ <char id="257" x="30" y="94" width="4" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="258" x="240" y="0" width="7" height="9" xoffset="0" yoffset="0" xadvance="6" page="0" chnl="15" />
+ <char id="259" x="0" y="62" width="4" height="8" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="260" x="224" y="0" width="7" height="9" xoffset="0" yoffset="2" xadvance="6" page="0" chnl="15" />
+ <char id="261" x="249" y="66" width="5" height="7" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="262" x="223" y="10" width="5" height="9" xoffset="1" yoffset="0" xadvance="7" page="0" chnl="15" />
+ <char id="263" x="25" y="60" width="4" height="8" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="264" x="90" y="31" width="5" height="9" xoffset="1" yoffset="0" xadvance="7" page="0" chnl="15" />
+ <char id="265" x="188" y="40" width="5" height="8" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="266" x="194" y="40" width="5" height="8" xoffset="1" yoffset="1" xadvance="7" page="0" chnl="15" />
+ <char id="267" x="25" y="94" width="4" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="268" x="247" y="10" width="5" height="9" xoffset="1" yoffset="0" xadvance="7" page="0" chnl="15" />
+ <char id="269" x="212" y="40" width="5" height="8" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="270" x="137" y="11" width="6" height="9" xoffset="0" yoffset="0" xadvance="7" page="0" chnl="15" />
+ <char id="271" x="144" y="67" width="6" height="7" xoffset="0" yoffset="2" xadvance="6" page="0" chnl="15" />
+ <char id="272" x="151" y="67" width="6" height="7" xoffset="0" yoffset="2" xadvance="7" page="0" chnl="15" />
+ <char id="273" x="132" y="75" width="5" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="274" x="242" y="40" width="5" height="8" xoffset="1" yoffset="1" xadvance="6" page="0" chnl="15" />
+ <char id="275" x="95" y="83" width="4" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="276" x="18" y="22" width="5" height="9" xoffset="1" yoffset="0" xadvance="6" page="0" chnl="15" />
+ <char id="277" x="5" y="62" width="4" height="8" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="278" x="12" y="52" width="5" height="8" xoffset="1" yoffset="1" xadvance="6" page="0" chnl="15" />
+ <char id="279" x="245" y="82" width="4" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="280" x="42" y="21" width="5" height="9" xoffset="1" yoffset="2" xadvance="6" page="0" chnl="15" />
+ <char id="281" x="235" y="82" width="4" height="7" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="282" x="54" y="21" width="5" height="9" xoffset="1" yoffset="0" xadvance="6" page="0" chnl="15" />
+ <char id="283" x="42" y="51" width="5" height="8" xoffset="-1" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="284" x="66" y="21" width="5" height="9" xoffset="1" yoffset="0" xadvance="7" page="0" chnl="15" />
+ <char id="285" x="84" y="0" width="5" height="10" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="286" x="72" y="21" width="5" height="9" xoffset="1" yoffset="0" xadvance="7" page="0" chnl="15" />
+ <char id="287" x="152" y="0" width="4" height="10" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="288" x="72" y="50" width="5" height="8" xoffset="1" yoffset="1" xadvance="7" page="0" chnl="15" />
+ <char id="289" x="228" y="30" width="4" height="9" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="290" x="90" y="0" width="5" height="10" xoffset="1" yoffset="2" xadvance="7" page="0" chnl="15" />
+ <char id="291" x="11" y="0" width="4" height="11" xoffset="0" yoffset="0" xadvance="5" page="0" chnl="15" />
+ <char id="292" x="235" y="10" width="5" height="9" xoffset="1" yoffset="0" xadvance="7" page="0" chnl="15" />
+ <char id="293" x="193" y="10" width="5" height="9" xoffset="-1" yoffset="0" xadvance="5" page="0" chnl="15" />
+ <char id="294" x="183" y="59" width="7" height="7" xoffset="0" yoffset="2" xadvance="7" page="0" chnl="15" />
+ <char id="295" x="230" y="82" width="4" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="296" x="113" y="31" width="4" height="9" xoffset="0" yoffset="0" xadvance="3" page="0" chnl="15" />
+ <char id="297" x="10" y="62" width="4" height="8" xoffset="-1" yoffset="1" xadvance="2" page="0" chnl="15" />
+ <char id="298" x="59" y="59" width="3" height="8" xoffset="0" yoffset="1" xadvance="3" page="0" chnl="15" />
+ <char id="299" x="92" y="91" width="3" height="7" xoffset="-1" yoffset="2" xadvance="2" page="0" chnl="15" />
+ <char id="300" x="247" y="30" width="3" height="9" xoffset="0" yoffset="0" xadvance="3" page="0" chnl="15" />
+ <char id="301" x="55" y="59" width="3" height="8" xoffset="-1" yoffset="1" xadvance="2" page="0" chnl="15" />
+ <char id="302" x="27" y="41" width="2" height="9" xoffset="1" yoffset="2" xadvance="3" page="0" chnl="15" />
+ <char id="303" x="253" y="10" width="2" height="9" xoffset="0" yoffset="2" xadvance="2" page="0" chnl="15" />
+ <char id="304" x="71" y="59" width="1" height="8" xoffset="1" yoffset="1" xadvance="3" page="0" chnl="15" />
+ <char id="305" x="253" y="90" width="1" height="5" xoffset="0" yoffset="4" xadvance="2" page="0" chnl="15" />
+ <char id="306" x="88" y="67" width="6" height="7" xoffset="1" yoffset="2" xadvance="7" page="0" chnl="15" />
+ <char id="307" x="251" y="30" width="3" height="9" xoffset="0" yoffset="2" xadvance="4" page="0" chnl="15" />
+ <char id="308" x="158" y="11" width="6" height="9" xoffset="0" yoffset="0" xadvance="5" page="0" chnl="15" />
+ <char id="309" x="114" y="0" width="5" height="10" xoffset="-2" yoffset="1" xadvance="2" page="0" chnl="15" />
+ <char id="310" x="120" y="0" width="5" height="10" xoffset="1" yoffset="2" xadvance="6" page="0" chnl="15" />
+ <char id="311" x="147" y="0" width="4" height="10" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="312" x="199" y="91" width="5" height="5" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="313" x="208" y="30" width="4" height="9" xoffset="1" yoffset="0" xadvance="5" page="0" chnl="15" />
+ <char id="314" x="42" y="41" width="2" height="9" xoffset="-1" yoffset="0" xadvance="2" page="0" chnl="15" />
+ <char id="315" x="142" y="0" width="4" height="10" xoffset="1" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="316" x="170" y="0" width="2" height="10" xoffset="0" yoffset="2" xadvance="2" page="0" chnl="15" />
+ <char id="317" x="84" y="92" width="3" height="7" xoffset="1" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="318" x="68" y="92" width="3" height="7" xoffset="0" yoffset="2" xadvance="3" page="0" chnl="15" />
+ <char id="319" x="145" y="83" width="4" height="7" xoffset="1" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="320" x="52" y="93" width="3" height="7" xoffset="0" yoffset="2" xadvance="3" page="0" chnl="15" />
+ <char id="321" x="108" y="75" width="5" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="322" x="96" y="91" width="3" height="7" xoffset="-1" yoffset="2" xadvance="2" page="0" chnl="15" />
+ <char id="323" x="211" y="10" width="5" height="9" xoffset="1" yoffset="0" xadvance="7" page="0" chnl="15" />
+ <char id="324" x="15" y="61" width="4" height="8" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="325" x="60" y="0" width="5" height="10" xoffset="1" yoffset="2" xadvance="7" page="0" chnl="15" />
+ <char id="326" x="20" y="61" width="4" height="8" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="327" x="24" y="21" width="5" height="9" xoffset="1" yoffset="0" xadvance="7" page="0" chnl="15" />
+ <char id="328" x="176" y="41" width="5" height="8" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="329" x="42" y="77" width="5" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="330" x="54" y="77" width="5" height="7" xoffset="1" yoffset="2" xadvance="7" page="0" chnl="15" />
+ <char id="331" x="180" y="83" width="4" height="7" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="332" x="18" y="52" width="5" height="8" xoffset="1" yoffset="1" xadvance="7" page="0" chnl="15" />
+ <char id="333" x="5" y="95" width="4" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="334" x="199" y="10" width="5" height="9" xoffset="1" yoffset="0" xadvance="7" page="0" chnl="15" />
+ <char id="335" x="30" y="60" width="4" height="8" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="336" x="96" y="31" width="5" height="9" xoffset="1" yoffset="0" xadvance="7" page="0" chnl="15" />
+ <char id="337" x="102" y="50" width="4" height="8" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="338" x="174" y="59" width="8" height="7" xoffset="1" yoffset="2" xadvance="9" page="0" chnl="15" />
+ <char id="339" x="148" y="91" width="8" height="5" xoffset="0" yoffset="4" xadvance="8" page="0" chnl="15" />
+ <char id="340" x="179" y="10" width="6" height="9" xoffset="1" yoffset="0" xadvance="7" page="0" chnl="15" />
+ <char id="341" x="43" y="60" width="3" height="8" xoffset="0" yoffset="1" xadvance="3" page="0" chnl="15" />
+ <char id="342" x="29" y="0" width="6" height="10" xoffset="1" yoffset="2" xadvance="7" page="0" chnl="15" />
+ <char id="343" x="51" y="59" width="3" height="8" xoffset="0" yoffset="4" xadvance="3" page="0" chnl="15" />
+ <char id="344" x="64" y="11" width="7" height="9" xoffset="0" yoffset="0" xadvance="7" page="0" chnl="15" />
+ <char id="345" x="164" y="41" width="5" height="8" xoffset="-1" yoffset="1" xadvance="3" page="0" chnl="15" />
+ <char id="346" x="153" y="31" width="4" height="9" xoffset="1" yoffset="0" xadvance="6" page="0" chnl="15" />
+ <char id="347" x="107" y="50" width="4" height="8" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="348" x="6" y="23" width="5" height="9" xoffset="1" yoffset="0" xadvance="6" page="0" chnl="15" />
+ <char id="349" x="218" y="40" width="5" height="8" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="350" x="137" y="0" width="4" height="10" xoffset="1" yoffset="2" xadvance="6" page="0" chnl="15" />
+ <char id="351" x="112" y="50" width="4" height="8" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="352" x="229" y="10" width="5" height="9" xoffset="0" yoffset="0" xadvance="6" page="0" chnl="15" />
+ <char id="353" x="224" y="40" width="5" height="8" xoffset="-1" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="354" x="42" y="0" width="5" height="10" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="355" x="162" y="0" width="3" height="10" xoffset="-1" yoffset="2" xadvance="3" page="0" chnl="15" />
+ <char id="356" x="48" y="21" width="5" height="9" xoffset="0" yoffset="0" xadvance="5" page="0" chnl="15" />
+ <char id="357" x="240" y="82" width="4" height="7" xoffset="-1" yoffset="2" xadvance="3" page="0" chnl="15" />
+ <char id="358" x="225" y="66" width="5" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="359" x="76" y="92" width="3" height="7" xoffset="-1" yoffset="2" xadvance="3" page="0" chnl="15" />
+ <char id="360" x="30" y="21" width="5" height="9" xoffset="1" yoffset="0" xadvance="7" page="0" chnl="15" />
+ <char id="361" x="117" y="50" width="4" height="8" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="362" x="248" y="40" width="5" height="8" xoffset="1" yoffset="1" xadvance="7" page="0" chnl="15" />
+ <char id="363" x="20" y="94" width="4" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="364" x="12" y="22" width="5" height="9" xoffset="1" yoffset="0" xadvance="7" page="0" chnl="15" />
+ <char id="365" x="122" y="50" width="4" height="8" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="366" x="0" y="23" width="5" height="9" xoffset="1" yoffset="0" xadvance="7" page="0" chnl="15" />
+ <char id="367" x="118" y="31" width="4" height="9" xoffset="0" yoffset="0" xadvance="5" page="0" chnl="15" />
+ <char id="368" x="241" y="10" width="5" height="9" xoffset="1" yoffset="0" xadvance="7" page="0" chnl="15" />
+ <char id="369" x="127" y="50" width="4" height="8" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="370" x="217" y="10" width="5" height="9" xoffset="1" yoffset="2" xadvance="7" page="0" chnl="15" />
+ <char id="371" x="12" y="79" width="5" height="7" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="372" x="197" y="0" width="9" height="9" xoffset="0" yoffset="0" xadvance="9" page="0" chnl="15" />
+ <char id="373" x="48" y="50" width="5" height="8" xoffset="0" yoffset="1" xadvance="6" page="0" chnl="15" />
+ <char id="374" x="102" y="31" width="5" height="9" xoffset="1" yoffset="0" xadvance="7" page="0" chnl="15" />
+ <char id="375" x="48" y="0" width="5" height="10" xoffset="0" yoffset="1" xadvance="6" page="0" chnl="15" />
+ <char id="376" x="6" y="53" width="5" height="8" xoffset="1" yoffset="1" xadvance="6" page="0" chnl="15" />
+ <char id="377" x="172" y="11" width="6" height="9" xoffset="0" yoffset="0" xadvance="6" page="0" chnl="15" />
+ <char id="378" x="35" y="60" width="3" height="8" xoffset="0" yoffset="1" xadvance="4" page="0" chnl="15" />
+ <char id="379" x="139" y="41" width="6" height="8" xoffset="0" yoffset="1" xadvance="6" page="0" chnl="15" />
+ <char id="380" x="44" y="93" width="3" height="7" xoffset="0" yoffset="2" xadvance="4" page="0" chnl="15" />
+ <char id="381" x="165" y="11" width="6" height="9" xoffset="0" yoffset="0" xadvance="6" page="0" chnl="15" />
+ <char id="382" x="96" y="50" width="5" height="8" xoffset="0" yoffset="1" xadvance="4" page="0" chnl="15" />
+ <char id="383" x="103" y="91" width="2" height="7" xoffset="0" yoffset="2" xadvance="2" page="0" chnl="15" />
+ <char id="384" x="24" y="78" width="5" height="7" xoffset="-1" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="385" x="16" y="70" width="7" height="7" xoffset="0" yoffset="2" xadvance="7" page="0" chnl="15" />
+ <char id="386" x="243" y="74" width="4" height="7" xoffset="1" yoffset="2" xadvance="6" page="0" chnl="15" />
+ <char id="387" x="248" y="74" width="4" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="388" x="78" y="76" width="5" height="7" xoffset="0" yoffset="2" xadvance="6" page="0" chnl="15" />
+ <char id="389" x="156" y="75" width="5" height="7" xoffset="-1" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="390" x="162" y="75" width="5" height="7" xoffset="1" yoffset="2" xadvance="7" page="0" chnl="15" />
+ <char id="391" x="132" y="41" width="6" height="8" xoffset="1" yoffset="1" xadvance="7" page="0" chnl="15" />
+ <char id="392" x="122" y="91" width="6" height="6" xoffset="0" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="393" x="200" y="66" width="6" height="7" xoffset="0" yoffset="2" xadvance="7" page="0" chnl="15" />
+ <char id="394" x="24" y="70" width="7" height="7" xoffset="0" yoffset="2" xadvance="7" page="0" chnl="15" />
+ <char id="395" x="5" y="87" width="4" height="7" xoffset="1" yoffset="2" xadvance="6" page="0" chnl="15" />
+ <char id="396" x="10" y="87" width="4" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="397" x="15" y="87" width="4" height="7" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="398" x="36" y="77" width="5" height="7" xoffset="0" yoffset="2" xadvance="6" page="0" chnl="15" />
+ <char id="399" x="6" y="79" width="5" height="7" xoffset="1" yoffset="2" xadvance="7" page="0" chnl="15" />
+ <char id="400" x="20" y="86" width="4" height="7" xoffset="1" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="401" x="84" y="31" width="5" height="9" xoffset="0" yoffset="2" xadvance="6" page="0" chnl="15" />
+ <char id="402" x="78" y="31" width="5" height="9" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="403" x="118" y="41" width="6" height="8" xoffset="1" yoffset="1" xadvance="7" page="0" chnl="15" />
+ <char id="404" x="95" y="11" width="6" height="9" xoffset="0" yoffset="2" xadvance="6" page="0" chnl="15" />
+ <char id="405" x="48" y="69" width="7" height="7" xoffset="0" yoffset="2" xadvance="8" page="0" chnl="15" />
+ <char id="406" x="106" y="91" width="1" height="7" xoffset="0" yoffset="2" xadvance="2" page="0" chnl="15" />
+ <char id="407" x="64" y="92" width="3" height="7" xoffset="0" yoffset="2" xadvance="3" page="0" chnl="15" />
+ <char id="408" x="137" y="67" width="6" height="7" xoffset="1" yoffset="2" xadvance="6" page="0" chnl="15" />
+ <char id="409" x="60" y="76" width="5" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="410" x="40" y="93" width="3" height="7" xoffset="-1" yoffset="2" xadvance="2" page="0" chnl="15" />
+ <char id="411" x="35" y="86" width="4" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="412" x="72" y="68" width="7" height="7" xoffset="0" yoffset="2" xadvance="8" page="0" chnl="15" />
+ <char id="413" x="109" y="11" width="6" height="9" xoffset="0" yoffset="2" xadvance="7" page="0" chnl="15" />
+ <char id="414" x="40" y="85" width="4" height="7" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="415" x="96" y="75" width="5" height="7" xoffset="1" yoffset="2" xadvance="7" page="0" chnl="15" />
+ <char id="416" x="158" y="67" width="6" height="7" xoffset="1" yoffset="2" xadvance="8" page="0" chnl="15" />
+ <char id="417" x="193" y="91" width="5" height="5" xoffset="0" yoffset="4" xadvance="6" page="0" chnl="15" />
+ <char id="418" x="123" y="11" width="6" height="9" xoffset="1" yoffset="2" xadvance="8" page="0" chnl="15" />
+ <char id="419" x="120" y="75" width="5" height="7" xoffset="0" yoffset="4" xadvance="6" page="0" chnl="15" />
+ <char id="420" x="172" y="67" width="6" height="7" xoffset="0" yoffset="2" xadvance="7" page="0" chnl="15" />
+ <char id="421" x="203" y="30" width="4" height="9" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="422" x="246" y="20" width="5" height="9" xoffset="1" yoffset="2" xadvance="6" page="0" chnl="15" />
+ <char id="423" x="45" y="85" width="4" height="7" xoffset="1" yoffset="2" xadvance="6" page="0" chnl="15" />
+ <char id="424" x="238" y="90" width="4" height="5" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="425" x="186" y="75" width="5" height="7" xoffset="1" yoffset="2" xadvance="6" page="0" chnl="15" />
+ <char id="426" x="16" y="42" width="3" height="9" xoffset="0" yoffset="2" xadvance="3" page="0" chnl="15" />
+ <char id="427" x="20" y="42" width="3" height="9" xoffset="-1" yoffset="2" xadvance="3" page="0" chnl="15" />
+ <char id="428" x="116" y="67" width="6" height="7" xoffset="0" yoffset="2" xadvance="6" page="0" chnl="15" />
+ <char id="429" x="55" y="85" width="4" height="7" xoffset="-1" yoffset="2" xadvance="3" page="0" chnl="15" />
+ <char id="430" x="116" y="11" width="6" height="9" xoffset="0" yoffset="2" xadvance="6" page="0" chnl="15" />
+ <char id="431" x="199" y="58" width="7" height="7" xoffset="1" yoffset="2" xadvance="8" page="0" chnl="15" />
+ <char id="432" x="173" y="91" width="6" height="5" xoffset="0" yoffset="4" xadvance="6" page="0" chnl="15" />
+ <char id="433" x="231" y="58" width="7" height="7" xoffset="0" yoffset="2" xadvance="7" page="0" chnl="15" />
+ <char id="434" x="138" y="75" width="5" height="7" xoffset="1" yoffset="2" xadvance="7" page="0" chnl="15" />
+ <char id="435" x="247" y="58" width="7" height="7" xoffset="0" yoffset="2" xadvance="7" page="0" chnl="15" />
+ <char id="436" x="72" y="11" width="7" height="9" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="437" x="60" y="84" width="4" height="7" xoffset="1" yoffset="2" xadvance="6" page="0" chnl="15" />
+ <char id="438" x="0" y="103" width="4" height="5" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="439" x="240" y="20" width="5" height="9" xoffset="0" yoffset="2" xadvance="6" page="0" chnl="15" />
+ <char id="440" x="234" y="20" width="5" height="9" xoffset="1" yoffset="2" xadvance="6" page="0" chnl="15" />
+ <char id="441" x="65" y="84" width="4" height="7" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="442" x="192" y="75" width="5" height="7" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="443" x="70" y="84" width="4" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="444" x="75" y="84" width="4" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="445" x="38" y="102" width="3" height="5" xoffset="0" yoffset="4" xadvance="4" page="0" chnl="15" />
+ <char id="446" x="80" y="84" width="4" height="7" xoffset="-1" yoffset="2" xadvance="4" page="0" chnl="15" />
+ <char id="447" x="85" y="83" width="4" height="7" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="448" x="116" y="91" width="1" height="7" xoffset="0" yoffset="2" xadvance="2" page="0" chnl="15" />
+ <char id="449" x="80" y="92" width="3" height="7" xoffset="0" yoffset="2" xadvance="4" page="0" chnl="15" />
+ <char id="450" x="90" y="75" width="5" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="451" x="110" y="91" width="1" height="7" xoffset="1" yoffset="2" xadvance="3" page="0" chnl="15" />
+ <char id="452" x="173" y="0" width="12" height="9" xoffset="0" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="453" x="56" y="41" width="10" height="8" xoffset="1" yoffset="1" xadvance="11" page="0" chnl="15" />
+ <char id="454" x="67" y="41" width="9" height="8" xoffset="0" yoffset="1" xadvance="9" page="0" chnl="15" />
+ <char id="455" x="147" y="59" width="8" height="7" xoffset="1" yoffset="2" xadvance="10" page="0" chnl="15" />
+ <char id="456" x="88" y="11" width="6" height="9" xoffset="1" yoffset="2" xadvance="8" page="0" chnl="15" />
+ <char id="457" x="8" y="43" width="3" height="9" xoffset="0" yoffset="2" xadvance="4" page="0" chnl="15" />
+ <char id="458" x="97" y="59" width="10" height="7" xoffset="1" yoffset="2" xadvance="11" page="0" chnl="15" />
+ <char id="459" x="216" y="0" width="7" height="9" xoffset="1" yoffset="2" xadvance="9" page="0" chnl="15" />
+ <char id="460" x="102" y="11" width="6" height="9" xoffset="0" yoffset="2" xadvance="7" page="0" chnl="15" />
+ <char id="461" x="80" y="11" width="7" height="9" xoffset="0" yoffset="0" xadvance="6" page="0" chnl="15" />
+ <char id="462" x="230" y="40" width="5" height="8" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="463" x="222" y="20" width="5" height="9" xoffset="-1" yoffset="0" xadvance="3" page="0" chnl="15" />
+ <char id="464" x="236" y="40" width="5" height="8" xoffset="-2" yoffset="1" xadvance="2" page="0" chnl="15" />
+ <char id="465" x="216" y="20" width="5" height="9" xoffset="1" yoffset="0" xadvance="7" page="0" chnl="15" />
+ <char id="466" x="182" y="41" width="5" height="8" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="467" x="210" y="20" width="5" height="9" xoffset="1" yoffset="0" xadvance="7" page="0" chnl="15" />
+ <char id="468" x="0" y="53" width="5" height="8" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="469" x="204" y="20" width="5" height="9" xoffset="1" yoffset="0" xadvance="7" page="0" chnl="15" />
+ <char id="470" x="178" y="31" width="4" height="9" xoffset="0" yoffset="0" xadvance="5" page="0" chnl="15" />
+ <char id="471" x="198" y="20" width="5" height="9" xoffset="1" yoffset="0" xadvance="7" page="0" chnl="15" />
+ <char id="472" x="213" y="30" width="4" height="9" xoffset="0" yoffset="0" xadvance="5" page="0" chnl="15" />
+ <char id="473" x="192" y="20" width="5" height="9" xoffset="1" yoffset="0" xadvance="7" page="0" chnl="15" />
+ <char id="474" x="186" y="20" width="5" height="9" xoffset="0" yoffset="0" xadvance="5" page="0" chnl="15" />
+ <char id="475" x="180" y="20" width="5" height="9" xoffset="1" yoffset="0" xadvance="7" page="0" chnl="15" />
+ <char id="476" x="198" y="30" width="4" height="9" xoffset="0" yoffset="0" xadvance="5" page="0" chnl="15" />
+ <char id="477" x="20" y="102" width="4" height="5" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="478" x="24" y="11" width="7" height="9" xoffset="0" yoffset="0" xadvance="6" page="0" chnl="15" />
+ <char id="479" x="128" y="31" width="4" height="9" xoffset="0" yoffset="0" xadvance="5" page="0" chnl="15" />
+ <char id="480" x="232" y="0" width="7" height="9" xoffset="0" yoffset="0" xadvance="6" page="0" chnl="15" />
+ <char id="481" x="148" y="31" width="4" height="9" xoffset="0" yoffset="0" xadvance="5" page="0" chnl="15" />
+ <char id="482" x="45" y="41" width="10" height="8" xoffset="-1" yoffset="1" xadvance="9" page="0" chnl="15" />
+ <char id="483" x="64" y="68" width="7" height="7" xoffset="0" yoffset="2" xadvance="8" page="0" chnl="15" />
+ <char id="484" x="123" y="67" width="6" height="7" xoffset="1" yoffset="2" xadvance="7" page="0" chnl="15" />
+ <char id="485" x="0" y="79" width="5" height="7" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="486" x="174" y="21" width="5" height="9" xoffset="1" yoffset="0" xadvance="7" page="0" chnl="15" />
+ <char id="487" x="36" y="0" width="5" height="10" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="488" x="228" y="20" width="5" height="9" xoffset="1" yoffset="0" xadvance="6" page="0" chnl="15" />
+ <char id="489" x="168" y="21" width="5" height="9" xoffset="0" yoffset="0" xadvance="5" page="0" chnl="15" />
+ <char id="490" x="162" y="21" width="5" height="9" xoffset="1" yoffset="2" xadvance="7" page="0" chnl="15" />
+ <char id="491" x="100" y="83" width="4" height="7" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="492" x="78" y="0" width="5" height="10" xoffset="1" yoffset="1" xadvance="7" page="0" chnl="15" />
+ <char id="493" x="223" y="30" width="4" height="9" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="494" x="5" y="0" width="5" height="11" xoffset="0" yoffset="0" xadvance="6" page="0" chnl="15" />
+ <char id="495" x="126" y="0" width="5" height="10" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="496" x="108" y="0" width="5" height="10" xoffset="-2" yoffset="1" xadvance="2" page="0" chnl="15" />
+ <char id="497" x="73" y="59" width="12" height="7" xoffset="0" yoffset="2" xadvance="12" page="0" chnl="15" />
+ <char id="498" x="108" y="59" width="9" height="7" xoffset="1" yoffset="2" xadvance="11" page="0" chnl="15" />
+ <char id="499" x="165" y="59" width="8" height="7" xoffset="0" yoffset="2" xadvance="9" page="0" chnl="15" />
+ <char id="500" x="156" y="21" width="5" height="9" xoffset="1" yoffset="0" xadvance="7" page="0" chnl="15" />
+ <char id="501" x="157" y="0" width="4" height="10" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="502" x="32" y="69" width="7" height="7" xoffset="1" yoffset="2" xadvance="9" page="0" chnl="15" />
+ <char id="503" x="133" y="31" width="4" height="9" xoffset="1" yoffset="2" xadvance="6" page="0" chnl="15" />
+ <char id="504" x="150" y="21" width="5" height="9" xoffset="1" yoffset="0" xadvance="7" page="0" chnl="15" />
+ <char id="505" x="132" y="50" width="4" height="8" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="506" x="21" y="0" width="7" height="10" xoffset="0" yoffset="-1" xadvance="6" page="0" chnl="15" />
+ <char id="507" x="0" y="0" width="4" height="12" xoffset="0" yoffset="-3" xadvance="5" page="0" chnl="15" />
+ <char id="508" x="186" y="0" width="10" height="9" xoffset="-1" yoffset="0" xadvance="9" page="0" chnl="15" />
+ <char id="509" x="110" y="41" width="7" height="8" xoffset="0" yoffset="1" xadvance="8" page="0" chnl="15" />
+ <char id="510" x="66" y="0" width="5" height="10" xoffset="1" yoffset="0" xadvance="7" page="0" chnl="15" />
+ <char id="511" x="60" y="50" width="5" height="8" xoffset="-1" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="512" x="48" y="11" width="7" height="9" xoffset="0" yoffset="0" xadvance="6" page="0" chnl="15" />
+ <char id="513" x="137" y="50" width="4" height="8" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="514" x="56" y="11" width="7" height="9" xoffset="0" yoffset="0" xadvance="6" page="0" chnl="15" />
+ <char id="515" x="142" y="50" width="4" height="8" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="516" x="138" y="21" width="5" height="9" xoffset="1" yoffset="0" xadvance="6" page="0" chnl="15" />
+ <char id="517" x="147" y="50" width="4" height="8" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="518" x="132" y="21" width="5" height="9" xoffset="1" yoffset="0" xadvance="6" page="0" chnl="15" />
+ <char id="519" x="152" y="50" width="4" height="8" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="520" x="163" y="31" width="4" height="9" xoffset="-1" yoffset="0" xadvance="3" page="0" chnl="15" />
+ <char id="521" x="157" y="50" width="4" height="8" xoffset="-2" yoffset="1" xadvance="2" page="0" chnl="15" />
+ <char id="522" x="4" y="43" width="3" height="9" xoffset="0" yoffset="0" xadvance="3" page="0" chnl="15" />
+ <char id="523" x="47" y="60" width="3" height="8" xoffset="-1" yoffset="1" xadvance="2" page="0" chnl="15" />
+ <char id="524" x="126" y="21" width="5" height="9" xoffset="1" yoffset="0" xadvance="7" page="0" chnl="15" />
+ <char id="525" x="162" y="50" width="4" height="8" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="526" x="144" y="21" width="5" height="9" xoffset="1" yoffset="0" xadvance="7" page="0" chnl="15" />
+ <char id="527" x="167" y="50" width="4" height="8" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="528" x="186" y="10" width="6" height="9" xoffset="1" yoffset="0" xadvance="7" page="0" chnl="15" />
+ <char id="529" x="172" y="50" width="4" height="8" xoffset="-1" yoffset="1" xadvance="3" page="0" chnl="15" />
+ <char id="530" x="130" y="11" width="6" height="9" xoffset="1" yoffset="0" xadvance="7" page="0" chnl="15" />
+ <char id="531" x="252" y="49" width="3" height="8" xoffset="0" yoffset="1" xadvance="3" page="0" chnl="15" />
+ <char id="532" x="114" y="21" width="5" height="9" xoffset="1" yoffset="0" xadvance="7" page="0" chnl="15" />
+ <char id="533" x="177" y="50" width="4" height="8" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="534" x="108" y="21" width="5" height="9" xoffset="1" yoffset="0" xadvance="7" page="0" chnl="15" />
+ <char id="535" x="182" y="50" width="4" height="8" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="536" x="16" y="0" width="4" height="11" xoffset="1" yoffset="1" xadvance="6" page="0" chnl="15" />
+ <char id="537" x="168" y="31" width="4" height="9" xoffset="0" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="538" x="102" y="0" width="5" height="10" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="539" x="166" y="0" width="3" height="10" xoffset="-1" yoffset="2" xadvance="2" page="0" chnl="15" />
+ <char id="540" x="143" y="31" width="4" height="9" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="541" x="88" y="91" width="3" height="7" xoffset="0" yoffset="4" xadvance="4" page="0" chnl="15" />
+ <char id="542" x="102" y="21" width="5" height="9" xoffset="1" yoffset="0" xadvance="7" page="0" chnl="15" />
+ <char id="543" x="96" y="21" width="5" height="9" xoffset="0" yoffset="0" xadvance="5" page="0" chnl="15" />
+ <char id="544" x="233" y="30" width="4" height="9" xoffset="1" yoffset="2" xadvance="6" page="0" chnl="15" />
+ <char id="545" x="144" y="11" width="6" height="9" xoffset="0" yoffset="2" xadvance="6" page="0" chnl="15" />
+ <char id="546" x="219" y="66" width="5" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="547" x="165" y="83" width="4" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="548" x="125" y="41" width="6" height="8" xoffset="0" yoffset="2" xadvance="6" page="0" chnl="15" />
+ <char id="549" x="141" y="91" width="4" height="6" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="550" x="102" y="41" width="7" height="8" xoffset="0" yoffset="1" xadvance="6" page="0" chnl="15" />
+ <char id="551" x="175" y="83" width="4" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="552" x="72" y="0" width="5" height="10" xoffset="1" yoffset="2" xadvance="6" page="0" chnl="15" />
+ <char id="553" x="187" y="50" width="4" height="8" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="554" x="90" y="21" width="5" height="9" xoffset="1" yoffset="0" xadvance="7" page="0" chnl="15" />
+ <char id="555" x="218" y="30" width="4" height="9" xoffset="0" yoffset="0" xadvance="5" page="0" chnl="15" />
+ <char id="556" x="84" y="21" width="5" height="9" xoffset="1" yoffset="0" xadvance="7" page="0" chnl="15" />
+ <char id="557" x="238" y="30" width="4" height="9" xoffset="0" yoffset="0" xadvance="5" page="0" chnl="15" />
+ <char id="558" x="90" y="50" width="5" height="8" xoffset="1" yoffset="1" xadvance="7" page="0" chnl="15" />
+ <char id="559" x="35" y="94" width="4" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="560" x="78" y="21" width="5" height="9" xoffset="1" yoffset="0" xadvance="7" page="0" chnl="15" />
+ <char id="561" x="193" y="30" width="4" height="9" xoffset="0" yoffset="0" xadvance="5" page="0" chnl="15" />
+ <char id="562" x="206" y="40" width="5" height="8" xoffset="1" yoffset="1" xadvance="7" page="0" chnl="15" />
+ <char id="563" x="60" y="21" width="5" height="9" xoffset="0" yoffset="2" xadvance="6" page="0" chnl="15" />
+ <char id="564" x="183" y="30" width="4" height="9" xoffset="-1" yoffset="2" xadvance="3" page="0" chnl="15" />
+ <char id="565" x="179" y="67" width="6" height="7" xoffset="0" yoffset="4" xadvance="6" page="0" chnl="15" />
+ <char id="566" x="200" y="83" width="4" height="7" xoffset="-1" yoffset="2" xadvance="3" page="0" chnl="15" />
+ <char id="567" x="253" y="74" width="2" height="7" xoffset="-1" yoffset="4" xadvance="2" page="0" chnl="15" />
+ <char id="568" x="80" y="67" width="7" height="7" xoffset="0" yoffset="2" xadvance="8" page="0" chnl="15" />
+ <char id="569" x="191" y="59" width="7" height="7" xoffset="0" yoffset="4" xadvance="8" page="0" chnl="15" />
+ <char id="570" x="77" y="41" width="8" height="8" xoffset="-1" yoffset="2" xadvance="6" page="0" chnl="15" />
+ <char id="571" x="120" y="21" width="5" height="9" xoffset="1" yoffset="1" xadvance="7" page="0" chnl="15" />
+ <char id="572" x="173" y="31" width="4" height="9" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="573" x="168" y="75" width="5" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="574" x="151" y="11" width="6" height="9" xoffset="0" yoffset="1" xadvance="6" page="0" chnl="15" />
+ <char id="575" x="220" y="82" width="4" height="7" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="576" x="174" y="75" width="5" height="7" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="577" x="180" y="75" width="5" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="578" x="42" y="101" width="3" height="5" xoffset="0" yoffset="4" xadvance="4" page="0" chnl="15" />
+ <char id="579" x="186" y="67" width="6" height="7" xoffset="0" yoffset="2" xadvance="6" page="0" chnl="15" />
+ <char id="580" x="207" y="58" width="7" height="7" xoffset="0" yoffset="2" xadvance="7" page="0" chnl="15" />
+ <char id="581" x="223" y="58" width="7" height="7" xoffset="-1" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="582" x="36" y="21" width="5" height="9" xoffset="1" yoffset="1" xadvance="6" page="0" chnl="15" />
+ <char id="583" x="138" y="31" width="4" height="9" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="584" x="204" y="74" width="5" height="7" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="585" x="108" y="31" width="4" height="9" xoffset="-2" yoffset="2" xadvance="2" page="0" chnl="15" />
+ <char id="586" x="248" y="0" width="7" height="9" xoffset="1" yoffset="2" xadvance="7" page="0" chnl="15" />
+ <char id="587" x="193" y="67" width="6" height="7" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="588" x="239" y="58" width="7" height="7" xoffset="0" yoffset="2" xadvance="7" page="0" chnl="15" />
+ <char id="589" x="248" y="90" width="4" height="5" xoffset="-1" yoffset="4" xadvance="3" page="0" chnl="15" />
+ <char id="590" x="222" y="74" width="5" height="7" xoffset="1" yoffset="2" xadvance="6" page="0" chnl="15" />
+ <char id="591" x="231" y="66" width="5" height="7" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ </chars>
+ <kernings count="57">
+ <kerning first="32" second="65" amount="-1" />
+ <kerning first="49" second="49" amount="-1" />
+ <kerning first="65" second="32" amount="-1" />
+ <kerning first="65" second="84" amount="-1" />
+ <kerning first="65" second="86" amount="-1" />
+ <kerning first="65" second="89" amount="-1" />
+ <kerning first="70" second="44" amount="-1" />
+ <kerning first="70" second="46" amount="-1" />
+ <kerning first="70" second="65" amount="-1" />
+ <kerning first="76" second="84" amount="-1" />
+ <kerning first="76" second="86" amount="-1" />
+ <kerning first="76" second="87" amount="-1" />
+ <kerning first="76" second="89" amount="-1" />
+ <kerning first="80" second="44" amount="-1" />
+ <kerning first="80" second="46" amount="-1" />
+ <kerning first="80" second="65" amount="-1" />
+ <kerning first="84" second="44" amount="-1" />
+ <kerning first="84" second="45" amount="-1" />
+ <kerning first="84" second="46" amount="-1" />
+ <kerning first="84" second="58" amount="-1" />
+ <kerning first="84" second="65" amount="-1" />
+ <kerning first="84" second="97" amount="-1" />
+ <kerning first="84" second="99" amount="-1" />
+ <kerning first="84" second="101" amount="-1" />
+ <kerning first="84" second="111" amount="-1" />
+ <kerning first="84" second="115" amount="-1" />
+ <kerning first="84" second="119" amount="-1" />
+ <kerning first="84" second="121" amount="-1" />
+ <kerning first="86" second="44" amount="-1" />
+ <kerning first="86" second="45" amount="-1" />
+ <kerning first="86" second="46" amount="-1" />
+ <kerning first="86" second="65" amount="-1" />
+ <kerning first="86" second="97" amount="-1" />
+ <kerning first="86" second="101" amount="-1" />
+ <kerning first="86" second="111" amount="-1" />
+ <kerning first="87" second="44" amount="-1" />
+ <kerning first="87" second="46" amount="-1" />
+ <kerning first="89" second="44" amount="-1" />
+ <kerning first="89" second="45" amount="-1" />
+ <kerning first="89" second="46" amount="-1" />
+ <kerning first="89" second="58" amount="-1" />
+ <kerning first="89" second="65" amount="-1" />
+ <kerning first="89" second="97" amount="-1" />
+ <kerning first="89" second="101" amount="-1" />
+ <kerning first="89" second="111" amount="-1" />
+ <kerning first="89" second="112" amount="-1" />
+ <kerning first="89" second="113" amount="-1" />
+ <kerning first="89" second="117" amount="-1" />
+ <kerning first="89" second="118" amount="-1" />
+ <kerning first="114" second="44" amount="-1" />
+ <kerning first="114" second="46" amount="-1" />
+ <kerning first="118" second="44" amount="-1" />
+ <kerning first="118" second="46" amount="-1" />
+ <kerning first="119" second="44" amount="-1" />
+ <kerning first="119" second="46" amount="-1" />
+ <kerning first="121" second="44" amount="-1" />
+ <kerning first="121" second="46" amount="-1" />
+ </kernings>
+</font>
diff --git a/ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-12-regular_0.png b/ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-12-regular_0.png Binary files differnew file mode 100644 index 0000000..a857030 --- /dev/null +++ b/ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-12-regular_0.png diff --git a/ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-16-bold-regular.fnt b/ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-16-bold-regular.fnt new file mode 100644 index 0000000..58f7d21 --- /dev/null +++ b/ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-16-bold-regular.fnt @@ -0,0 +1,1403 @@ +<?xml version="1.0"?>
+<font>
+ <info face="Arial" size="-16" bold="1" italic="0" charset="" unicode="1" stretchH="100" smooth="1" aa="1" padding="0,0,0,0" spacing="2,2" outline="0"/>
+ <common lineHeight="19" base="15" scaleW="512" scaleH="512" pages="1" packed="0" alphaChnl="0" redChnl="0" greenChnl="0" blueChnl="0"/>
+ <pages>
+ <page id="0" file="arial-16-bold-regular_00.png" />
+ </pages>
+ <chars count="994">
+ <char id="-1" x="382" y="258" width="8" height="11" xoffset="2" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="32" x="443" y="293" width="1" height="1" xoffset="0" yoffset="15" xadvance="4" page="0" chnl="15" />
+ <char id="33" x="206" y="260" width="2" height="12" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="34" x="205" y="296" width="6" height="4" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="35" x="503" y="145" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="36" x="409" y="102" width="7" height="14" xoffset="1" yoffset="2" xadvance="9" page="0" chnl="15" />
+ <char id="37" x="17" y="138" width="15" height="12" xoffset="0" yoffset="3" xadvance="16" page="0" chnl="15" />
+ <char id="38" x="403" y="160" width="11" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="39" x="220" y="295" width="2" height="4" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="40" x="106" y="104" width="4" height="15" xoffset="1" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="41" x="136" y="103" width="4" height="15" xoffset="0" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="42" x="213" y="296" width="5" height="4" xoffset="0" yoffset="3" xadvance="6" page="0" chnl="15" />
+ <char id="43" x="0" y="300" width="8" height="8" xoffset="0" yoffset="5" xadvance="9" page="0" chnl="15" />
+ <char id="44" x="175" y="297" width="2" height="5" xoffset="1" yoffset="13" xadvance="4" page="0" chnl="15" />
+ <char id="45" x="387" y="293" width="4" height="2" xoffset="1" yoffset="10" xadvance="5" page="0" chnl="15" />
+ <char id="46" x="428" y="293" width="2" height="2" xoffset="1" yoffset="13" xadvance="4" page="0" chnl="15" />
+ <char id="47" x="109" y="262" width="4" height="12" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="48" x="150" y="233" width="8" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="49" x="14" y="264" width="5" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="50" x="310" y="231" width="8" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="51" x="390" y="230" width="8" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="52" x="400" y="230" width="8" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="53" x="490" y="229" width="8" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="54" x="242" y="203" width="8" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="55" x="262" y="203" width="8" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="56" x="292" y="203" width="8" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="57" x="332" y="202" width="8" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="58" x="491" y="279" width="2" height="9" xoffset="2" yoffset="6" xadvance="6" page="0" chnl="15" />
+ <char id="59" x="170" y="261" width="2" height="12" xoffset="2" yoffset="6" xadvance="6" page="0" chnl="15" />
+ <char id="60" x="150" y="286" width="8" height="9" xoffset="0" yoffset="5" xadvance="9" page="0" chnl="15" />
+ <char id="61" x="115" y="299" width="8" height="5" xoffset="0" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="62" x="120" y="287" width="8" height="9" xoffset="0" yoffset="5" xadvance="9" page="0" chnl="15" />
+ <char id="63" x="442" y="202" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="64" x="142" y="0" width="15" height="16" xoffset="1" yoffset="3" xadvance="16" page="0" chnl="15" />
+ <char id="65" x="351" y="160" width="11" height="12" xoffset="0" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="66" x="492" y="173" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="67" x="480" y="173" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="68" x="468" y="173" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="69" x="380" y="188" width="9" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="70" x="492" y="201" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="71" x="444" y="174" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="72" x="432" y="174" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="73" x="166" y="261" width="2" height="12" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="74" x="60" y="222" width="8" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="75" x="338" y="160" width="11" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="76" x="100" y="220" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="77" x="325" y="160" width="11" height="12" xoffset="1" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="78" x="384" y="174" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="79" x="372" y="174" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="80" x="391" y="188" width="9" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="81" x="481" y="102" width="10" height="13" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="82" x="312" y="160" width="11" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="83" x="402" y="188" width="9" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="84" x="348" y="174" width="10" height="12" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="85" x="336" y="174" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="86" x="222" y="133" width="13" height="12" xoffset="-1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="87" x="481" y="117" width="15" height="12" xoffset="0" yoffset="3" xadvance="15" page="0" chnl="15" />
+ <char id="88" x="299" y="160" width="11" height="12" xoffset="0" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="89" x="448" y="145" width="12" height="12" xoffset="-1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="90" x="413" y="188" width="9" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="91" x="142" y="103" width="4" height="15" xoffset="1" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="92" x="139" y="261" width="4" height="12" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="93" x="118" y="104" width="4" height="15" xoffset="0" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="94" x="50" y="300" width="8" height="6" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="95" x="333" y="294" width="9" height="2" xoffset="0" yoffset="16" xadvance="9" page="0" chnl="15" />
+ <char id="96" x="409" y="293" width="3" height="2" xoffset="0" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="97" x="70" y="289" width="8" height="9" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="98" x="210" y="218" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="99" x="329" y="283" width="7" height="9" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="100" x="250" y="217" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="101" x="320" y="283" width="7" height="9" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="102" x="426" y="244" width="6" height="12" xoffset="0" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="103" x="280" y="217" width="8" height="12" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="104" x="340" y="216" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="105" x="154" y="261" width="2" height="12" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="106" x="112" y="104" width="4" height="15" xoffset="-1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="107" x="490" y="215" width="8" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="108" x="198" y="260" width="2" height="12" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="109" x="215" y="273" width="12" height="9" xoffset="1" yoffset="6" xadvance="14" page="0" chnl="15" />
+ <char id="110" x="60" y="289" width="8" height="9" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="111" x="50" y="289" width="8" height="9" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="112" x="170" y="232" width="8" height="12" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="113" x="210" y="232" width="8" height="12" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="114" x="484" y="280" width="5" height="9" xoffset="1" yoffset="6" xadvance="6" page="0" chnl="15" />
+ <char id="115" x="40" y="289" width="8" height="9" xoffset="0" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="116" x="7" y="264" width="5" height="12" xoffset="0" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="117" x="30" y="289" width="8" height="9" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="118" x="409" y="271" width="9" height="9" xoffset="0" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="119" x="16" y="278" width="13" height="9" xoffset="0" yoffset="6" xadvance="13" page="0" chnl="15" />
+ <char id="120" x="376" y="271" width="9" height="9" xoffset="0" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="121" x="234" y="161" width="11" height="12" xoffset="-1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="122" x="230" y="284" width="7" height="9" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="123" x="0" y="106" width="6" height="15" xoffset="0" yoffset="3" xadvance="6" page="0" chnl="15" />
+ <char id="124" x="183" y="103" width="2" height="15" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="125" x="504" y="85" width="6" height="15" xoffset="0" yoffset="3" xadvance="6" page="0" chnl="15" />
+ <char id="126" x="228" y="295" width="8" height="3" xoffset="1" yoffset="8" xadvance="9" page="0" chnl="15" />
+ <char id="160" x="449" y="293" width="1" height="1" xoffset="0" yoffset="15" xadvance="4" page="0" chnl="15" />
+ <char id="161" x="150" y="261" width="2" height="12" xoffset="1" yoffset="6" xadvance="4" page="0" chnl="15" />
+ <char id="162" x="238" y="86" width="8" height="15" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="163" x="435" y="188" width="9" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="164" x="453" y="271" width="9" height="9" xoffset="0" yoffset="5" xadvance="9" page="0" chnl="15" />
+ <char id="165" x="180" y="232" width="8" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="166" x="508" y="0" width="2" height="15" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="167" x="208" y="86" width="8" height="15" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="168" x="373" y="293" width="5" height="2" xoffset="0" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="169" x="56" y="152" width="12" height="12" xoffset="0" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="170" x="91" y="300" width="5" height="6" xoffset="0" yoffset="3" xadvance="6" page="0" chnl="15" />
+ <char id="171" x="29" y="300" width="7" height="7" xoffset="1" yoffset="7" xadvance="9" page="0" chnl="15" />
+ <char id="172" x="60" y="300" width="8" height="6" xoffset="0" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="173" x="393" y="293" width="4" height="2" xoffset="1" yoffset="10" xadvance="5" page="0" chnl="15" />
+ <char id="174" x="84" y="150" width="12" height="12" xoffset="0" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="175" x="355" y="293" width="9" height="2" xoffset="0" yoffset="1" xadvance="9" page="0" chnl="15" />
+ <char id="176" x="160" y="297" width="5" height="5" xoffset="0" yoffset="3" xadvance="6" page="0" chnl="15" />
+ <char id="177" x="332" y="258" width="8" height="11" xoffset="0" yoffset="4" xadvance="9" page="0" chnl="15" />
+ <char id="178" x="70" y="300" width="5" height="6" xoffset="0" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="179" x="77" y="300" width="5" height="6" xoffset="0" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="180" x="414" y="293" width="3" height="2" xoffset="1" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="181" x="72" y="250" width="7" height="12" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="182" x="346" y="102" width="9" height="14" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="183" x="432" y="293" width="2" height="2" xoffset="2" yoffset="9" xadvance="5" page="0" chnl="15" />
+ <char id="184" x="268" y="294" width="4" height="3" xoffset="0" yoffset="15" xadvance="5" page="0" chnl="15" />
+ <char id="185" x="98" y="300" width="4" height="6" xoffset="0" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="186" x="84" y="300" width="5" height="6" xoffset="1" yoffset="3" xadvance="6" page="0" chnl="15" />
+ <char id="187" x="20" y="300" width="7" height="7" xoffset="1" yoffset="7" xadvance="9" page="0" chnl="15" />
+ <char id="188" x="387" y="132" width="13" height="12" xoffset="0" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="189" x="126" y="149" width="12" height="12" xoffset="0" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="190" x="417" y="132" width="13" height="12" xoffset="0" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="191" x="190" y="232" width="8" height="12" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="192" x="465" y="17" width="11" height="15" xoffset="0" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="193" x="65" y="36" width="11" height="15" xoffset="0" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="194" x="374" y="17" width="11" height="15" xoffset="0" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="195" x="234" y="35" width="11" height="15" xoffset="0" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="196" x="309" y="17" width="11" height="15" xoffset="0" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="197" x="195" y="35" width="11" height="15" xoffset="0" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="198" x="324" y="118" width="16" height="12" xoffset="-1" yoffset="3" xadvance="16" page="0" chnl="15" />
+ <char id="199" x="204" y="52" width="10" height="15" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="200" x="77" y="87" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="201" x="234" y="69" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="202" x="289" y="68" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="203" x="377" y="68" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="204" x="159" y="103" width="3" height="15" xoffset="0" yoffset="0" xadvance="4" page="0" chnl="15" />
+ <char id="205" x="174" y="103" width="3" height="15" xoffset="1" yoffset="0" xadvance="4" page="0" chnl="15" />
+ <char id="206" x="29" y="106" width="5" height="15" xoffset="0" yoffset="0" xadvance="4" page="0" chnl="15" />
+ <char id="207" x="43" y="106" width="5" height="15" xoffset="0" yoffset="0" xadvance="4" page="0" chnl="15" />
+ <char id="208" x="78" y="165" width="11" height="12" xoffset="0" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="209" x="240" y="52" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="210" x="252" y="51" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="211" x="264" y="51" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="212" x="276" y="51" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="213" x="288" y="51" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="214" x="300" y="51" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="215" x="10" y="300" width="8" height="7" xoffset="0" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="216" x="221" y="103" width="12" height="14" xoffset="0" yoffset="2" xadvance="12" page="0" chnl="15" />
+ <char id="217" x="336" y="51" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="218" x="348" y="51" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="219" x="360" y="51" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="220" x="372" y="51" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="221" x="211" y="18" width="12" height="15" xoffset="-1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="222" x="446" y="188" width="9" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="223" x="140" y="233" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="224" x="110" y="233" width="8" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="225" x="10" y="236" width="8" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="226" x="470" y="215" width="8" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="227" x="460" y="216" width="8" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="228" x="440" y="216" width="8" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="229" x="379" y="102" width="8" height="14" xoffset="1" yoffset="1" xadvance="9" page="0" chnl="15" />
+ <char id="230" x="89" y="278" width="12" height="9" xoffset="1" yoffset="6" xadvance="14" page="0" chnl="15" />
+ <char id="231" x="9" y="250" width="7" height="12" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="232" x="36" y="250" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="233" x="171" y="246" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="234" x="54" y="250" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="235" x="288" y="245" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="236" x="507" y="131" width="3" height="12" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="237" x="507" y="243" width="3" height="12" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="238" x="486" y="243" width="5" height="12" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="239" x="458" y="244" width="5" height="12" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="240" x="480" y="229" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="241" x="470" y="229" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="242" x="460" y="230" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="243" x="440" y="230" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="244" x="430" y="230" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="245" x="420" y="230" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="246" x="410" y="230" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="247" x="499" y="279" width="8" height="8" xoffset="0" yoffset="5" xadvance="9" page="0" chnl="15" />
+ <char id="248" x="402" y="258" width="8" height="11" xoffset="1" yoffset="5" xadvance="10" page="0" chnl="15" />
+ <char id="249" x="380" y="230" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="250" x="370" y="230" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="251" x="360" y="230" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="252" x="350" y="230" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="253" x="91" y="36" width="11" height="15" xoffset="-1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="254" x="502" y="34" width="8" height="15" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="255" x="39" y="37" width="11" height="15" xoffset="-1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="256" x="348" y="17" width="11" height="15" xoffset="0" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="257" x="340" y="230" width="8" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="258" x="478" y="17" width="11" height="15" xoffset="0" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="259" x="330" y="230" width="8" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="260" x="322" y="17" width="11" height="15" xoffset="0" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="261" x="320" y="230" width="8" height="12" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="262" x="444" y="51" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="263" x="27" y="250" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="264" x="432" y="51" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="265" x="315" y="245" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="266" x="420" y="51" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="267" x="279" y="245" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="268" x="384" y="51" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="269" x="333" y="244" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="270" x="312" y="51" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="271" x="130" y="163" width="11" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="272" x="104" y="163" width="11" height="12" xoffset="0" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="273" x="457" y="187" width="9" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="274" x="179" y="69" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="275" x="243" y="245" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="276" x="300" y="68" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="277" x="180" y="246" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="278" x="465" y="68" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="279" x="261" y="245" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="280" x="245" y="69" width="9" height="15" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="281" x="126" y="247" width="7" height="12" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="282" x="454" y="68" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="283" x="216" y="246" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="284" x="108" y="53" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="285" x="218" y="86" width="8" height="15" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="286" x="96" y="53" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="287" x="268" y="85" width="8" height="15" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="288" x="48" y="54" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="289" x="278" y="85" width="8" height="15" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="290" x="36" y="54" width="10" height="15" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="291" x="89" y="0" width="8" height="17" xoffset="1" yoffset="1" xadvance="10" page="0" chnl="15" />
+ <char id="292" x="490" y="34" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="293" x="118" y="87" width="8" height="15" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="294" x="238" y="147" width="12" height="12" xoffset="0" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="295" x="468" y="187" width="9" height="12" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="296" x="64" y="105" width="5" height="15" xoffset="0" yoffset="0" xadvance="4" page="0" chnl="15" />
+ <char id="297" x="35" y="264" width="5" height="12" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="298" x="71" y="105" width="5" height="15" xoffset="0" yoffset="0" xadvance="4" page="0" chnl="15" />
+ <char id="299" x="500" y="243" width="5" height="12" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="300" x="78" y="104" width="5" height="15" xoffset="0" yoffset="0" xadvance="4" page="0" chnl="15" />
+ <char id="301" x="493" y="243" width="5" height="12" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="302" x="164" y="103" width="3" height="15" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="303" x="169" y="103" width="3" height="15" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="304" x="179" y="103" width="2" height="15" xoffset="1" yoffset="0" xadvance="4" page="0" chnl="15" />
+ <char id="305" x="506" y="268" width="2" height="9" xoffset="1" yoffset="6" xadvance="4" page="0" chnl="15" />
+ <char id="306" x="364" y="160" width="11" height="12" xoffset="1" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="307" x="436" y="85" width="7" height="15" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="308" x="201" y="69" width="9" height="15" xoffset="0" yoffset="0" xadvance="9" page="0" chnl="15" />
+ <char id="309" x="496" y="85" width="6" height="15" xoffset="-1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="310" x="182" y="35" width="11" height="15" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="311" x="408" y="85" width="8" height="15" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="312" x="210" y="285" width="8" height="9" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="313" x="368" y="85" width="8" height="15" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="314" x="154" y="103" width="3" height="15" xoffset="1" yoffset="0" xadvance="4" page="0" chnl="15" />
+ <char id="315" x="178" y="86" width="8" height="15" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="316" x="148" y="103" width="4" height="15" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="317" x="479" y="187" width="9" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="318" x="472" y="243" width="5" height="12" xoffset="1" yoffset="3" xadvance="6" page="0" chnl="15" />
+ <char id="319" x="120" y="233" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="320" x="465" y="244" width="5" height="12" xoffset="1" yoffset="3" xadvance="7" page="0" chnl="15" />
+ <char id="321" x="490" y="187" width="9" height="12" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="322" x="127" y="261" width="4" height="12" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="323" x="466" y="34" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="324" x="90" y="235" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="325" x="298" y="34" width="10" height="15" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="326" x="70" y="236" width="8" height="12" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="327" x="180" y="52" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="328" x="60" y="236" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="329" x="13" y="166" width="11" height="12" xoffset="0" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="330" x="168" y="176" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="331" x="50" y="236" width="8" height="12" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="332" x="216" y="52" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="333" x="40" y="236" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="334" x="324" y="51" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="335" x="0" y="236" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="336" x="408" y="51" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="337" x="500" y="215" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="338" x="396" y="118" width="15" height="12" xoffset="1" yoffset="3" xadvance="16" page="0" chnl="15" />
+ <char id="339" x="31" y="278" width="13" height="9" xoffset="1" yoffset="6" xadvance="15" page="0" chnl="15" />
+ <char id="340" x="273" y="34" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="341" x="84" y="264" width="5" height="12" xoffset="1" yoffset="3" xadvance="6" page="0" chnl="15" />
+ <char id="342" x="208" y="35" width="11" height="15" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="343" x="77" y="264" width="5" height="12" xoffset="1" yoffset="6" xadvance="6" page="0" chnl="15" />
+ <char id="344" x="221" y="35" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="345" x="70" y="264" width="5" height="12" xoffset="1" yoffset="3" xadvance="6" page="0" chnl="15" />
+ <char id="346" x="333" y="68" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="347" x="330" y="216" width="8" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="348" x="223" y="69" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="349" x="320" y="216" width="8" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="350" x="168" y="69" width="9" height="15" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="351" x="310" y="217" width="8" height="12" xoffset="0" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="352" x="33" y="89" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="353" x="290" y="217" width="8" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="354" x="228" y="52" width="10" height="15" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="355" x="22" y="106" width="5" height="15" xoffset="0" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="356" x="168" y="52" width="10" height="15" xoffset="0" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="357" x="502" y="159" width="8" height="12" xoffset="0" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="358" x="132" y="177" width="10" height="12" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="359" x="0" y="264" width="5" height="12" xoffset="0" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="360" x="84" y="53" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="361" x="220" y="218" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="362" x="72" y="53" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="363" x="200" y="218" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="364" x="430" y="34" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="365" x="190" y="218" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="366" x="418" y="34" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="367" x="389" y="102" width="8" height="14" xoffset="1" yoffset="1" xadvance="10" page="0" chnl="15" />
+ <char id="368" x="394" y="34" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="369" x="180" y="218" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="370" x="370" y="34" width="10" height="15" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="371" x="170" y="218" width="8" height="12" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="372" x="366" y="0" width="15" height="15" xoffset="0" yoffset="0" xadvance="15" page="0" chnl="15" />
+ <char id="373" x="327" y="132" width="13" height="12" xoffset="0" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="374" x="225" y="18" width="12" height="15" xoffset="-1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="375" x="130" y="35" width="11" height="15" xoffset="-1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="376" x="281" y="17" width="12" height="15" xoffset="-1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="377" x="443" y="68" width="9" height="15" xoffset="0" yoffset="0" xadvance="9" page="0" chnl="15" />
+ <char id="378" x="153" y="247" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="379" x="476" y="68" width="9" height="15" xoffset="0" yoffset="0" xadvance="9" page="0" chnl="15" />
+ <char id="380" x="117" y="247" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="381" x="0" y="89" width="9" height="15" xoffset="0" yoffset="0" xadvance="9" page="0" chnl="15" />
+ <char id="382" x="108" y="248" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="383" x="121" y="261" width="4" height="12" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="384" x="501" y="187" width="9" height="12" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="385" x="252" y="147" width="12" height="12" xoffset="0" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="386" x="144" y="191" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="387" x="462" y="201" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="388" x="168" y="190" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="389" x="0" y="208" width="9" height="12" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="390" x="144" y="177" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="391" x="207" y="103" width="12" height="14" xoffset="1" yoffset="1" xadvance="12" page="0" chnl="15" />
+ <char id="392" x="277" y="259" width="9" height="11" xoffset="1" yoffset="4" xadvance="9" page="0" chnl="15" />
+ <char id="393" x="26" y="166" width="11" height="12" xoffset="0" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="394" x="0" y="152" width="12" height="12" xoffset="0" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="395" x="216" y="175" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="396" x="382" y="202" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="397" x="372" y="202" width="8" height="12" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="398" x="22" y="208" width="9" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="399" x="312" y="174" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="400" x="33" y="208" width="9" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="401" x="382" y="34" width="10" height="15" xoffset="-1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="402" x="278" y="68" width="9" height="15" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="403" x="235" y="103" width="12" height="14" xoffset="1" yoffset="1" xadvance="12" page="0" chnl="15" />
+ <char id="404" x="71" y="19" width="12" height="15" xoffset="-1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="405" x="357" y="132" width="13" height="12" xoffset="1" yoffset="3" xadvance="15" page="0" chnl="15" />
+ <char id="406" x="190" y="260" width="2" height="12" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="407" x="97" y="263" width="4" height="12" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="408" x="39" y="166" width="11" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="409" x="302" y="203" width="8" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="410" x="103" y="263" width="4" height="12" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="411" x="91" y="164" width="11" height="12" xoffset="-1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="412" x="146" y="134" width="14" height="12" xoffset="1" yoffset="3" xadvance="16" page="0" chnl="15" />
+ <char id="413" x="43" y="20" width="12" height="15" xoffset="-1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="414" x="282" y="203" width="8" height="12" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="415" x="180" y="190" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="416" x="308" y="146" width="12" height="12" xoffset="1" yoffset="3" xadvance="14" page="0" chnl="15" />
+ <char id="417" x="341" y="271" width="10" height="9" xoffset="1" yoffset="6" xadvance="11" page="0" chnl="15" />
+ <char id="418" x="29" y="20" width="12" height="15" xoffset="1" yoffset="3" xadvance="14" page="0" chnl="15" />
+ <char id="419" x="478" y="159" width="10" height="12" xoffset="1" yoffset="6" xadvance="12" page="0" chnl="15" />
+ <char id="420" x="350" y="146" width="12" height="12" xoffset="0" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="421" x="318" y="85" width="8" height="15" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="422" x="298" y="102" width="10" height="14" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="423" x="44" y="208" width="9" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="424" x="392" y="282" width="7" height="9" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="425" x="252" y="203" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="426" x="472" y="85" width="6" height="15" xoffset="0" yoffset="3" xadvance="6" page="0" chnl="15" />
+ <char id="427" x="8" y="106" width="5" height="15" xoffset="0" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="428" x="36" y="180" width="10" height="12" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="429" x="42" y="264" width="5" height="12" xoffset="0" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="430" x="144" y="69" width="10" height="15" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="431" x="14" y="152" width="12" height="12" xoffset="1" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="432" x="268" y="272" width="11" height="9" xoffset="1" yoffset="6" xadvance="12" page="0" chnl="15" />
+ <char id="433" x="208" y="161" width="11" height="12" xoffset="1" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="434" x="84" y="179" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="435" x="28" y="152" width="12" height="12" xoffset="0" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="436" x="197" y="18" width="12" height="15" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="437" x="120" y="177" width="10" height="12" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="438" x="436" y="282" width="6" height="9" xoffset="1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="439" x="410" y="68" width="9" height="15" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="440" x="421" y="68" width="9" height="15" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="441" x="225" y="246" width="7" height="12" xoffset="1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="442" x="270" y="231" width="8" height="12" xoffset="0" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="443" x="250" y="231" width="8" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="444" x="0" y="250" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="445" x="383" y="282" width="7" height="9" xoffset="0" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="446" x="272" y="203" width="8" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="447" x="362" y="202" width="8" height="12" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="448" x="182" y="260" width="2" height="12" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="449" x="378" y="244" width="6" height="12" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="450" x="502" y="201" width="8" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="451" x="178" y="260" width="2" height="12" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="452" x="252" y="0" width="19" height="15" xoffset="1" yoffset="0" xadvance="21" page="0" chnl="15" />
+ <char id="453" x="192" y="119" width="18" height="12" xoffset="1" yoffset="3" xadvance="20" page="0" chnl="15" />
+ <char id="454" x="378" y="118" width="16" height="12" xoffset="1" yoffset="3" xadvance="18" page="0" chnl="15" />
+ <char id="455" x="251" y="119" width="17" height="12" xoffset="1" yoffset="3" xadvance="19" page="0" chnl="15" />
+ <char id="456" x="127" y="18" width="12" height="15" xoffset="1" yoffset="3" xadvance="14" page="0" chnl="15" />
+ <char id="457" x="418" y="85" width="7" height="15" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="458" x="112" y="121" width="18" height="12" xoffset="1" yoffset="3" xadvance="20" page="0" chnl="15" />
+ <char id="459" x="399" y="0" width="14" height="15" xoffset="1" yoffset="3" xadvance="16" page="0" chnl="15" />
+ <char id="460" x="239" y="17" width="12" height="15" xoffset="1" yoffset="3" xadvance="14" page="0" chnl="15" />
+ <char id="461" x="260" y="34" width="11" height="15" xoffset="0" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="462" x="0" y="222" width="8" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="463" x="36" y="106" width="5" height="15" xoffset="0" yoffset="0" xadvance="4" page="0" chnl="15" />
+ <char id="464" x="49" y="264" width="5" height="12" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="465" x="468" y="51" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="466" x="40" y="222" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="467" x="480" y="51" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="468" x="90" y="221" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="469" x="492" y="51" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="470" x="308" y="85" width="8" height="15" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="471" x="0" y="72" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="472" x="388" y="85" width="8" height="15" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="473" x="12" y="72" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="474" x="398" y="85" width="8" height="15" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="475" x="24" y="72" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="476" x="88" y="87" width="8" height="15" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="477" x="284" y="283" width="7" height="9" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="478" x="143" y="35" width="11" height="15" xoffset="0" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="479" x="108" y="87" width="8" height="15" xoffset="1" yoffset="0" xadvance="9" page="0" chnl="15" />
+ <char id="480" x="26" y="37" width="11" height="15" xoffset="0" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="481" x="128" y="86" width="8" height="15" xoffset="1" yoffset="0" xadvance="9" page="0" chnl="15" />
+ <char id="482" x="313" y="0" width="16" height="15" xoffset="-1" yoffset="0" xadvance="16" page="0" chnl="15" />
+ <char id="483" x="210" y="147" width="12" height="12" xoffset="1" yoffset="3" xadvance="14" page="0" chnl="15" />
+ <char id="484" x="52" y="166" width="11" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="485" x="55" y="208" width="9" height="12" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="486" x="36" y="71" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="487" x="148" y="86" width="8" height="15" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="488" x="13" y="38" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="489" x="168" y="86" width="8" height="15" xoffset="1" yoffset="0" xadvance="9" page="0" chnl="15" />
+ <char id="490" x="48" y="71" width="10" height="15" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="491" x="380" y="216" width="8" height="12" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="492" x="24" y="0" width="10" height="18" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="493" x="188" y="86" width="8" height="15" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="494" x="36" y="0" width="9" height="18" xoffset="0" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="495" x="463" y="85" width="7" height="15" xoffset="0" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="496" x="15" y="106" width="5" height="15" xoffset="-1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="497" x="71" y="122" width="19" height="12" xoffset="1" yoffset="3" xadvance="21" page="0" chnl="15" />
+ <char id="498" x="152" y="120" width="18" height="12" xoffset="1" yoffset="3" xadvance="20" page="0" chnl="15" />
+ <char id="499" x="306" y="118" width="16" height="12" xoffset="1" yoffset="3" xadvance="18" page="0" chnl="15" />
+ <char id="500" x="60" y="71" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="501" x="198" y="86" width="8" height="15" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="502" x="430" y="118" width="15" height="12" xoffset="1" yoffset="3" xadvance="17" page="0" chnl="15" />
+ <char id="503" x="267" y="68" width="9" height="15" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="504" x="72" y="70" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="505" x="420" y="216" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="506" x="173" y="0" width="11" height="16" xoffset="0" yoffset="-1" xadvance="11" page="0" chnl="15" />
+ <char id="507" x="228" y="86" width="8" height="15" xoffset="1" yoffset="0" xadvance="9" page="0" chnl="15" />
+ <char id="508" x="331" y="0" width="16" height="15" xoffset="-1" yoffset="0" xadvance="16" page="0" chnl="15" />
+ <char id="509" x="98" y="149" width="12" height="12" xoffset="1" yoffset="3" xadvance="14" page="0" chnl="15" />
+ <char id="510" x="159" y="0" width="12" height="16" xoffset="0" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="511" x="493" y="102" width="8" height="13" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="512" x="387" y="17" width="11" height="15" xoffset="0" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="513" x="410" y="216" width="8" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="514" x="52" y="37" width="11" height="15" xoffset="0" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="515" x="240" y="231" width="8" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="516" x="11" y="89" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="517" x="234" y="246" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="518" x="22" y="89" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="519" x="90" y="249" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="520" x="488" y="85" width="6" height="15" xoffset="-1" yoffset="0" xadvance="4" page="0" chnl="15" />
+ <char id="521" x="394" y="244" width="6" height="12" xoffset="-2" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="522" x="57" y="105" width="5" height="15" xoffset="0" yoffset="0" xadvance="4" page="0" chnl="15" />
+ <char id="523" x="479" y="243" width="5" height="12" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="524" x="84" y="70" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="525" x="290" y="231" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="526" x="96" y="70" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="527" x="450" y="230" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="528" x="247" y="34" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="529" x="504" y="173" width="6" height="12" xoffset="0" yoffset="3" xadvance="6" page="0" chnl="15" />
+ <char id="530" x="156" y="35" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="531" x="28" y="264" width="5" height="12" xoffset="1" yoffset="3" xadvance="6" page="0" chnl="15" />
+ <char id="532" x="108" y="70" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="533" x="80" y="236" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="534" x="120" y="69" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="535" x="400" y="216" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="536" x="78" y="0" width="9" height="17" xoffset="1" yoffset="2" xadvance="11" page="0" chnl="15" />
+ <char id="537" x="399" y="102" width="8" height="14" xoffset="0" yoffset="5" xadvance="9" page="0" chnl="15" />
+ <char id="538" x="66" y="0" width="10" height="17" xoffset="0" yoffset="2" xadvance="10" page="0" chnl="15" />
+ <char id="539" x="99" y="0" width="5" height="17" xoffset="0" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="540" x="445" y="85" width="7" height="15" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="541" x="402" y="244" width="6" height="12" xoffset="1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="542" x="132" y="69" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="543" x="378" y="85" width="8" height="15" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="544" x="66" y="88" width="9" height="15" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="545" x="295" y="17" width="12" height="15" xoffset="1" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="546" x="350" y="216" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="547" x="70" y="222" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="548" x="334" y="102" width="10" height="14" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="549" x="439" y="258" width="6" height="11" xoffset="1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="550" x="491" y="17" width="11" height="15" xoffset="0" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="551" x="80" y="222" width="8" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="552" x="44" y="88" width="9" height="15" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="553" x="324" y="244" width="7" height="12" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="554" x="396" y="51" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="555" x="248" y="86" width="8" height="15" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="556" x="454" y="34" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="557" x="298" y="85" width="8" height="15" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="558" x="406" y="34" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="559" x="30" y="236" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="560" x="156" y="69" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="561" x="138" y="86" width="8" height="15" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="562" x="169" y="18" width="12" height="15" xoffset="-1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="563" x="78" y="36" width="11" height="15" xoffset="-1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="564" x="288" y="85" width="8" height="15" xoffset="0" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="565" x="140" y="149" width="12" height="12" xoffset="1" yoffset="6" xadvance="13" page="0" chnl="15" />
+ <char id="566" x="412" y="202" width="8" height="12" xoffset="0" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="567" x="133" y="261" width="4" height="12" xoffset="-1" yoffset="6" xadvance="4" page="0" chnl="15" />
+ <char id="568" x="66" y="137" width="14" height="12" xoffset="0" yoffset="3" xadvance="15" page="0" chnl="15" />
+ <char id="569" x="98" y="135" width="14" height="12" xoffset="0" yoffset="6" xadvance="15" page="0" chnl="15" />
+ <char id="570" x="439" y="102" width="12" height="13" xoffset="0" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="571" x="264" y="175" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="572" x="427" y="85" width="7" height="15" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="573" x="77" y="208" width="9" height="12" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="574" x="274" y="102" width="10" height="14" xoffset="0" yoffset="2" xadvance="10" page="0" chnl="15" />
+ <char id="575" x="45" y="250" width="7" height="12" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="576" x="198" y="246" width="7" height="12" xoffset="1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="577" x="88" y="207" width="9" height="12" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="578" x="302" y="283" width="7" height="9" xoffset="0" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="579" x="221" y="161" width="11" height="12" xoffset="0" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="580" x="406" y="146" width="12" height="12" xoffset="0" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="581" x="342" y="132" width="13" height="12" xoffset="-1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="582" x="357" y="102" width="9" height="14" xoffset="1" yoffset="2" xadvance="11" page="0" chnl="15" />
+ <char id="583" x="454" y="85" width="7" height="15" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="584" x="99" y="206" width="9" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="585" x="50" y="105" width="5" height="15" xoffset="-1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="586" x="99" y="19" width="12" height="15" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="587" x="12" y="180" width="10" height="12" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="588" x="182" y="148" width="12" height="12" xoffset="0" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="589" x="468" y="282" width="6" height="9" xoffset="0" yoffset="6" xadvance="6" page="0" chnl="15" />
+ <char id="590" x="192" y="190" width="10" height="12" xoffset="0" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="591" x="260" y="217" width="8" height="12" xoffset="0" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="884" x="419" y="293" width="3" height="2" xoffset="1" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="885" x="404" y="293" width="3" height="2" xoffset="1" yoffset="16" xadvance="5" page="0" chnl="15" />
+ <char id="890" x="424" y="293" width="2" height="2" xoffset="1" yoffset="16" xadvance="5" page="0" chnl="15" />
+ <char id="891" x="410" y="282" width="7" height="9" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="892" x="140" y="286" width="8" height="9" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="893" x="10" y="289" width="8" height="9" xoffset="0" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="894" x="174" y="260" width="2" height="12" xoffset="2" yoffset="6" xadvance="6" page="0" chnl="15" />
+ <char id="900" x="399" y="293" width="3" height="2" xoffset="1" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="901" x="238" y="295" width="7" height="3" xoffset="0" yoffset="3" xadvance="7" page="0" chnl="15" />
+ <char id="902" x="169" y="162" width="11" height="12" xoffset="0" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="903" x="436" y="293" width="2" height="2" xoffset="1" yoffset="6" xadvance="5" page="0" chnl="15" />
+ <char id="904" x="267" y="133" width="13" height="12" xoffset="0" yoffset="3" xadvance="14" page="0" chnl="15" />
+ <char id="905" x="114" y="135" width="14" height="12" xoffset="0" yoffset="3" xadvance="15" page="0" chnl="15" />
+ <char id="906" x="162" y="247" width="7" height="12" xoffset="0" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="908" x="462" y="145" width="12" height="12" xoffset="0" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="910" x="288" y="118" width="16" height="12" xoffset="0" yoffset="3" xadvance="15" page="0" chnl="15" />
+ <char id="911" x="378" y="146" width="12" height="12" xoffset="0" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="912" x="10" y="123" width="7" height="13" xoffset="-1" yoffset="2" xadvance="4" page="0" chnl="15" />
+ <char id="913" x="286" y="161" width="11" height="12" xoffset="0" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="914" x="300" y="174" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="915" x="482" y="201" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="916" x="154" y="148" width="12" height="12" xoffset="0" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="917" x="110" y="205" width="9" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="918" x="121" y="205" width="9" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="919" x="276" y="175" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="920" x="252" y="175" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="921" x="186" y="260" width="2" height="12" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="922" x="273" y="161" width="11" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="923" x="192" y="133" width="13" height="12" xoffset="-1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="924" x="247" y="161" width="11" height="12" xoffset="1" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="925" x="204" y="176" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="926" x="260" y="231" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="927" x="192" y="176" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="928" x="180" y="176" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="929" x="132" y="205" width="9" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="931" x="280" y="231" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="932" x="72" y="180" width="10" height="12" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="933" x="498" y="117" width="12" height="12" xoffset="-1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="934" x="0" y="180" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="935" x="490" y="145" width="11" height="12" xoffset="0" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="936" x="454" y="159" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="937" x="156" y="162" width="11" height="12" xoffset="1" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="938" x="99" y="104" width="5" height="15" xoffset="0" yoffset="0" xadvance="4" page="0" chnl="15" />
+ <char id="939" x="57" y="19" width="12" height="15" xoffset="-1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="940" x="312" y="202" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="941" x="18" y="250" width="7" height="12" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="942" x="158" y="86" width="8" height="15" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="943" x="145" y="261" width="3" height="12" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="944" x="503" y="102" width="7" height="13" xoffset="1" yoffset="2" xadvance="9" page="0" chnl="15" />
+ <char id="945" x="20" y="289" width="8" height="9" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="946" x="98" y="87" width="8" height="15" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="947" x="228" y="175" width="10" height="12" xoffset="-1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="948" x="392" y="202" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="949" x="365" y="282" width="7" height="9" xoffset="1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="950" x="480" y="85" width="6" height="15" xoffset="1" yoffset="3" xadvance="7" page="0" chnl="15" />
+ <char id="951" x="422" y="202" width="8" height="12" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="952" x="63" y="250" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="953" x="495" y="279" width="2" height="9" xoffset="1" yoffset="6" xadvance="4" page="0" chnl="15" />
+ <char id="954" x="0" y="289" width="8" height="9" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="955" x="156" y="190" width="10" height="12" xoffset="-1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="956" x="472" y="201" width="8" height="12" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="957" x="387" y="271" width="9" height="9" xoffset="0" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="958" x="504" y="17" width="6" height="15" xoffset="1" yoffset="3" xadvance="7" page="0" chnl="15" />
+ <char id="959" x="486" y="268" width="8" height="9" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="960" x="117" y="276" width="12" height="9" xoffset="0" yoffset="6" xadvance="12" page="0" chnl="15" />
+ <char id="961" x="10" y="222" width="8" height="12" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="962" x="386" y="244" width="6" height="12" xoffset="1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="963" x="431" y="271" width="9" height="9" xoffset="1" yoffset="6" xadvance="11" page="0" chnl="15" />
+ <char id="964" x="476" y="280" width="6" height="9" xoffset="0" yoffset="6" xadvance="6" page="0" chnl="15" />
+ <char id="965" x="311" y="283" width="7" height="9" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="966" x="84" y="193" width="10" height="12" xoffset="1" yoffset="6" xadvance="12" page="0" chnl="15" />
+ <char id="967" x="143" y="205" width="9" height="12" xoffset="0" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="968" x="48" y="194" width="10" height="12" xoffset="1" yoffset="6" xadvance="12" page="0" chnl="15" />
+ <char id="969" x="61" y="278" width="12" height="9" xoffset="1" yoffset="6" xadvance="14" page="0" chnl="15" />
+ <char id="970" x="56" y="264" width="5" height="12" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="971" x="135" y="247" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="972" x="120" y="219" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="973" x="144" y="247" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="974" x="364" y="146" width="12" height="12" xoffset="1" yoffset="3" xadvance="14" page="0" chnl="15" />
+ <char id="976" x="150" y="219" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="977" x="160" y="219" width="8" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="978" x="322" y="146" width="12" height="12" xoffset="0" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="979" x="270" y="118" width="16" height="12" xoffset="0" yoffset="3" xadvance="16" page="0" chnl="15" />
+ <char id="980" x="85" y="19" width="12" height="15" xoffset="0" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="981" x="442" y="34" width="10" height="15" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="982" x="201" y="274" width="12" height="9" xoffset="1" yoffset="6" xadvance="14" page="0" chnl="15" />
+ <char id="983" x="260" y="161" width="11" height="12" xoffset="0" yoffset="6" xadvance="11" page="0" chnl="15" />
+ <char id="984" x="192" y="52" width="10" height="15" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="985" x="240" y="217" width="8" height="12" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="986" x="144" y="52" width="10" height="15" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="987" x="189" y="246" width="7" height="12" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="988" x="270" y="217" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="989" x="63" y="264" width="5" height="12" xoffset="1" yoffset="6" xadvance="7" page="0" chnl="15" />
+ <char id="990" x="294" y="146" width="12" height="12" xoffset="0" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="991" x="30" y="222" width="8" height="12" xoffset="0" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="992" x="113" y="18" width="12" height="15" xoffset="0" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="993" x="212" y="69" width="9" height="15" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="994" x="383" y="0" width="14" height="15" xoffset="1" yoffset="3" xadvance="16" page="0" chnl="15" />
+ <char id="995" x="266" y="147" width="12" height="12" xoffset="1" yoffset="6" xadvance="14" page="0" chnl="15" />
+ <char id="996" x="154" y="205" width="9" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="997" x="360" y="216" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="998" x="355" y="68" width="9" height="15" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="999" x="474" y="257" width="10" height="10" xoffset="0" yoffset="5" xadvance="10" page="0" chnl="15" />
+ <char id="1000" x="165" y="204" width="9" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="1001" x="176" y="204" width="9" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="1002" x="60" y="194" width="10" height="12" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="1003" x="293" y="272" width="10" height="9" xoffset="0" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="1004" x="0" y="194" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="1005" x="401" y="282" width="7" height="9" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="1006" x="450" y="216" width="8" height="12" xoffset="0" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="1007" x="252" y="245" width="7" height="12" xoffset="0" yoffset="3" xadvance="7" page="0" chnl="15" />
+ <char id="1008" x="255" y="272" width="11" height="9" xoffset="0" yoffset="6" xadvance="11" page="0" chnl="15" />
+ <char id="1009" x="480" y="215" width="8" height="12" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="1010" x="356" y="282" width="7" height="9" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="1011" x="124" y="104" width="4" height="15" xoffset="-1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="1012" x="360" y="174" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="1013" x="452" y="282" width="6" height="9" xoffset="1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="1014" x="444" y="282" width="6" height="9" xoffset="1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="1015" x="187" y="204" width="9" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="1016" x="338" y="85" width="8" height="15" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="1017" x="240" y="175" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="1018" x="0" y="166" width="11" height="12" xoffset="1" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="1019" x="120" y="191" width="10" height="12" xoffset="1" yoffset="6" xadvance="12" page="0" chnl="15" />
+ <char id="1020" x="198" y="204" width="9" height="12" xoffset="0" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="1021" x="420" y="174" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="1022" x="442" y="160" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="1023" x="48" y="180" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="1024" x="322" y="68" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="1025" x="311" y="68" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="1026" x="312" y="132" width="13" height="12" xoffset="0" yoffset="3" xadvance="14" page="0" chnl="15" />
+ <char id="1027" x="328" y="85" width="8" height="15" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="1028" x="209" y="204" width="9" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="1029" x="220" y="204" width="9" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="1030" x="194" y="260" width="2" height="12" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="1031" x="92" y="104" width="5" height="15" xoffset="0" yoffset="0" xadvance="4" page="0" chnl="15" />
+ <char id="1032" x="200" y="232" width="8" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="1033" x="232" y="119" width="17" height="12" xoffset="0" yoffset="3" xadvance="18" page="0" chnl="15" />
+ <char id="1034" x="413" y="118" width="15" height="12" xoffset="1" yoffset="3" xadvance="17" page="0" chnl="15" />
+ <char id="1035" x="237" y="133" width="13" height="12" xoffset="0" yoffset="3" xadvance="14" page="0" chnl="15" />
+ <char id="1036" x="55" y="88" width="9" height="15" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="1037" x="132" y="52" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="1038" x="267" y="17" width="12" height="15" xoffset="-1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="1039" x="156" y="52" width="10" height="15" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="1040" x="429" y="160" width="11" height="12" xoffset="0" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="1041" x="324" y="174" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="1042" x="396" y="174" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="1043" x="300" y="231" width="8" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="1044" x="169" y="35" width="11" height="15" xoffset="0" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="1045" x="231" y="203" width="9" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="1046" x="130" y="135" width="14" height="12" xoffset="0" yoffset="3" xadvance="14" page="0" chnl="15" />
+ <char id="1047" x="204" y="190" width="9" height="12" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="1048" x="408" y="174" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="1049" x="456" y="51" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="1050" x="215" y="190" width="9" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="1051" x="132" y="191" width="10" height="12" xoffset="0" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="1052" x="195" y="162" width="11" height="12" xoffset="1" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="1053" x="12" y="194" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="1054" x="72" y="194" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="1055" x="96" y="192" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="1056" x="226" y="189" width="9" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="1057" x="108" y="191" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="1058" x="466" y="159" width="10" height="12" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="1059" x="224" y="147" width="12" height="12" xoffset="-1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="1060" x="196" y="147" width="12" height="12" xoffset="1" yoffset="3" xadvance="14" page="0" chnl="15" />
+ <char id="1061" x="117" y="163" width="11" height="12" xoffset="0" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="1062" x="104" y="36" width="11" height="15" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="1063" x="237" y="189" width="9" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="1064" x="82" y="136" width="14" height="12" xoffset="1" yoffset="3" xadvance="16" page="0" chnl="15" />
+ <char id="1065" x="349" y="0" width="15" height="15" xoffset="1" yoffset="3" xadvance="16" page="0" chnl="15" />
+ <char id="1066" x="402" y="132" width="13" height="12" xoffset="0" yoffset="3" xadvance="14" page="0" chnl="15" />
+ <char id="1067" x="207" y="133" width="13" height="12" xoffset="1" yoffset="3" xadvance="15" page="0" chnl="15" />
+ <char id="1068" x="248" y="189" width="9" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="1069" x="259" y="189" width="9" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="1070" x="0" y="138" width="15" height="12" xoffset="1" yoffset="3" xadvance="17" page="0" chnl="15" />
+ <char id="1071" x="143" y="163" width="11" height="12" xoffset="0" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="1072" x="200" y="285" width="8" height="9" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="1073" x="500" y="229" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="1074" x="190" y="285" width="8" height="9" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="1075" x="428" y="282" width="6" height="9" xoffset="1" yoffset="6" xadvance="7" page="0" chnl="15" />
+ <char id="1076" x="310" y="259" width="9" height="11" xoffset="0" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="1077" x="248" y="284" width="7" height="9" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="1078" x="173" y="275" width="12" height="9" xoffset="0" yoffset="6" xadvance="12" page="0" chnl="15" />
+ <char id="1079" x="460" y="282" width="6" height="9" xoffset="1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="1080" x="160" y="286" width="8" height="9" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="1081" x="352" y="202" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="1082" x="266" y="283" width="7" height="9" xoffset="1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="1083" x="442" y="271" width="9" height="9" xoffset="0" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="1084" x="464" y="271" width="9" height="9" xoffset="1" yoffset="6" xadvance="11" page="0" chnl="15" />
+ <char id="1085" x="130" y="287" width="8" height="9" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="1086" x="110" y="288" width="8" height="9" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="1087" x="100" y="289" width="8" height="9" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="1088" x="20" y="222" width="8" height="12" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="1089" x="374" y="282" width="7" height="9" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="1090" x="90" y="289" width="8" height="9" xoffset="0" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="1091" x="182" y="162" width="11" height="12" xoffset="-1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="1092" x="15" y="20" width="12" height="15" xoffset="1" yoffset="3" xadvance="14" page="0" chnl="15" />
+ <char id="1093" x="420" y="271" width="9" height="9" xoffset="0" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="1094" x="299" y="259" width="9" height="11" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="1095" x="338" y="283" width="7" height="9" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="1096" x="145" y="275" width="12" height="9" xoffset="1" yoffset="6" xadvance="14" page="0" chnl="15" />
+ <char id="1097" x="210" y="260" width="13" height="11" xoffset="1" yoffset="6" xadvance="14" page="0" chnl="15" />
+ <char id="1098" x="305" y="272" width="10" height="9" xoffset="1" yoffset="6" xadvance="12" page="0" chnl="15" />
+ <char id="1099" x="131" y="275" width="12" height="9" xoffset="1" yoffset="6" xadvance="14" page="0" chnl="15" />
+ <char id="1100" x="180" y="286" width="8" height="9" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="1101" x="293" y="283" width="7" height="9" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="1102" x="103" y="277" width="12" height="9" xoffset="1" yoffset="6" xadvance="14" page="0" chnl="15" />
+ <char id="1103" x="80" y="289" width="8" height="9" xoffset="0" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="1104" x="360" y="244" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="1105" x="369" y="244" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="1106" x="190" y="69" width="9" height="15" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="1107" x="442" y="244" width="6" height="12" xoffset="1" yoffset="3" xadvance="7" page="0" chnl="15" />
+ <char id="1108" x="275" y="283" width="7" height="9" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="1109" x="220" y="284" width="8" height="9" xoffset="0" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="1110" x="202" y="260" width="2" height="12" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="1111" x="21" y="264" width="5" height="12" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="1112" x="130" y="103" width="4" height="15" xoffset="-1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="1113" x="486" y="257" width="15" height="9" xoffset="0" yoffset="6" xadvance="16" page="0" chnl="15" />
+ <char id="1114" x="46" y="278" width="13" height="9" xoffset="1" yoffset="6" xadvance="15" page="0" chnl="15" />
+ <char id="1115" x="66" y="208" width="9" height="12" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="1116" x="81" y="250" width="7" height="12" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="1117" x="370" y="216" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="1118" x="117" y="35" width="11" height="15" xoffset="-1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="1119" x="372" y="258" width="8" height="11" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="1120" x="212" y="119" width="18" height="12" xoffset="1" yoffset="3" xadvance="20" page="0" chnl="15" />
+ <char id="1121" x="75" y="278" width="12" height="9" xoffset="0" yoffset="6" xadvance="12" page="0" chnl="15" />
+ <char id="1122" x="162" y="134" width="13" height="12" xoffset="0" yoffset="3" xadvance="14" page="0" chnl="15" />
+ <char id="1123" x="24" y="180" width="10" height="12" xoffset="0" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="1124" x="50" y="138" width="14" height="12" xoffset="1" yoffset="3" xadvance="16" page="0" chnl="15" />
+ <char id="1125" x="242" y="273" width="11" height="9" xoffset="1" yoffset="6" xadvance="13" page="0" chnl="15" />
+ <char id="1126" x="65" y="166" width="11" height="12" xoffset="0" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="1127" x="475" y="269" width="9" height="9" xoffset="0" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="1128" x="34" y="138" width="14" height="12" xoffset="1" yoffset="3" xadvance="15" page="0" chnl="15" />
+ <char id="1129" x="187" y="274" width="12" height="9" xoffset="1" yoffset="6" xadvance="13" page="0" chnl="15" />
+ <char id="1130" x="168" y="148" width="12" height="12" xoffset="0" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="1131" x="353" y="271" width="10" height="9" xoffset="1" yoffset="6" xadvance="12" page="0" chnl="15" />
+ <char id="1132" x="464" y="117" width="15" height="12" xoffset="1" yoffset="3" xadvance="17" page="0" chnl="15" />
+ <char id="1133" x="0" y="278" width="14" height="9" xoffset="1" yoffset="6" xadvance="16" page="0" chnl="15" />
+ <char id="1134" x="0" y="0" width="9" height="19" xoffset="0" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="1135" x="220" y="0" width="7" height="16" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="1136" x="112" y="149" width="12" height="12" xoffset="0" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="1137" x="60" y="180" width="10" height="12" xoffset="1" yoffset="6" xadvance="12" page="0" chnl="15" />
+ <char id="1138" x="96" y="178" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="1139" x="496" y="268" width="8" height="9" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="1140" x="372" y="132" width="13" height="12" xoffset="0" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="1141" x="281" y="272" width="10" height="9" xoffset="0" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="1142" x="0" y="21" width="13" height="15" xoffset="0" yoffset="0" xadvance="13" page="0" chnl="15" />
+ <char id="1143" x="108" y="177" width="10" height="12" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="1144" x="229" y="0" width="21" height="15" xoffset="1" yoffset="3" xadvance="22" page="0" chnl="15" />
+ <char id="1145" x="92" y="121" width="18" height="12" xoffset="1" yoffset="6" xadvance="19" page="0" chnl="15" />
+ <char id="1146" x="249" y="103" width="11" height="14" xoffset="1" yoffset="2" xadvance="13" page="0" chnl="15" />
+ <char id="1147" x="342" y="258" width="8" height="11" xoffset="1" yoffset="5" xadvance="10" page="0" chnl="15" />
+ <char id="1148" x="293" y="0" width="18" height="15" xoffset="1" yoffset="0" xadvance="20" page="0" chnl="15" />
+ <char id="1149" x="467" y="102" width="12" height="13" xoffset="1" yoffset="2" xadvance="14" page="0" chnl="15" />
+ <char id="1150" x="273" y="0" width="18" height="15" xoffset="1" yoffset="0" xadvance="20" page="0" chnl="15" />
+ <char id="1151" x="70" y="151" width="12" height="12" xoffset="0" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="1152" x="120" y="52" width="10" height="15" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="1153" x="99" y="249" width="7" height="12" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="1154" x="270" y="189" width="9" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="1155" x="247" y="295" width="5" height="3" xoffset="-3" yoffset="2" xadvance="0" page="0" chnl="15" />
+ <char id="1156" x="366" y="293" width="5" height="2" xoffset="-3" yoffset="3" xadvance="0" page="0" chnl="15" />
+ <char id="1157" x="254" y="295" width="5" height="3" xoffset="-3" yoffset="2" xadvance="0" page="0" chnl="15" />
+ <char id="1158" x="261" y="294" width="5" height="3" xoffset="-2" yoffset="2" xadvance="0" page="0" chnl="15" />
+ <char id="1160" x="187" y="103" width="18" height="14" xoffset="-9" yoffset="3" xadvance="0" page="0" chnl="15" />
+ <char id="1161" x="106" y="0" width="16" height="16" xoffset="-8" yoffset="2" xadvance="0" page="0" chnl="15" />
+ <char id="1162" x="11" y="0" width="11" height="18" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="1163" x="368" y="102" width="9" height="14" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="1164" x="156" y="176" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="1165" x="281" y="189" width="9" height="12" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="1166" x="292" y="189" width="9" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="1167" x="303" y="188" width="9" height="12" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="1168" x="504" y="51" width="6" height="15" xoffset="1" yoffset="0" xadvance="8" page="0" chnl="15" />
+ <char id="1169" x="463" y="258" width="5" height="11" xoffset="1" yoffset="4" xadvance="7" page="0" chnl="15" />
+ <char id="1170" x="314" y="188" width="9" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="1171" x="503" y="257" width="7" height="9" xoffset="0" yoffset="6" xadvance="7" page="0" chnl="15" />
+ <char id="1172" x="198" y="0" width="9" height="16" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="1173" x="230" y="232" width="8" height="12" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="1174" x="447" y="0" width="14" height="15" xoffset="0" yoffset="3" xadvance="14" page="0" chnl="15" />
+ <char id="1175" x="225" y="260" width="12" height="11" xoffset="0" yoffset="6" xadvance="11" page="0" chnl="15" />
+ <char id="1176" x="344" y="68" width="9" height="15" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="1177" x="418" y="244" width="6" height="12" xoffset="1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="1178" x="366" y="68" width="9" height="15" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="1179" x="430" y="258" width="7" height="11" xoffset="1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="1180" x="325" y="188" width="9" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="1181" x="239" y="284" width="7" height="9" xoffset="1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="1182" x="288" y="175" width="10" height="12" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="1183" x="220" y="232" width="8" height="12" xoffset="0" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="1184" x="42" y="152" width="12" height="12" xoffset="0" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="1185" x="317" y="272" width="10" height="9" xoffset="0" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="1186" x="60" y="54" width="10" height="15" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="1187" x="288" y="259" width="9" height="11" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="1188" x="297" y="132" width="13" height="12" xoffset="1" yoffset="3" xadvance="14" page="0" chnl="15" />
+ <char id="1189" x="329" y="272" width="10" height="9" xoffset="1" yoffset="6" xadvance="11" page="0" chnl="15" />
+ <char id="1190" x="124" y="0" width="16" height="16" xoffset="1" yoffset="3" xadvance="18" page="0" chnl="15" />
+ <char id="1191" x="282" y="132" width="13" height="12" xoffset="1" yoffset="6" xadvance="15" page="0" chnl="15" />
+ <char id="1192" x="310" y="102" width="10" height="14" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="1193" x="421" y="258" width="7" height="11" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="1194" x="24" y="55" width="10" height="15" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="1195" x="342" y="244" width="7" height="12" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="1196" x="12" y="55" width="10" height="15" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="1197" x="352" y="258" width="8" height="11" xoffset="0" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="1198" x="160" y="233" width="8" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="1199" x="130" y="233" width="8" height="12" xoffset="0" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="1200" x="100" y="234" width="8" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="1201" x="0" y="123" width="8" height="13" xoffset="0" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="1202" x="0" y="55" width="10" height="15" xoffset="0" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="1203" x="362" y="258" width="8" height="11" xoffset="0" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="1204" x="478" y="0" width="13" height="15" xoffset="0" yoffset="3" xadvance="14" page="0" chnl="15" />
+ <char id="1205" x="239" y="260" width="11" height="11" xoffset="0" yoffset="6" xadvance="11" page="0" chnl="15" />
+ <char id="1206" x="478" y="34" width="10" height="15" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="1207" x="392" y="258" width="8" height="11" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="1208" x="430" y="216" width="8" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="1209" x="347" y="282" width="7" height="9" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="1210" x="336" y="188" width="9" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="1211" x="390" y="216" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="1212" x="252" y="133" width="13" height="12" xoffset="0" yoffset="3" xadvance="14" page="0" chnl="15" />
+ <char id="1213" x="398" y="271" width="9" height="9" xoffset="1" yoffset="6" xadvance="11" page="0" chnl="15" />
+ <char id="1214" x="463" y="0" width="13" height="15" xoffset="0" yoffset="3" xadvance="14" page="0" chnl="15" />
+ <char id="1215" x="347" y="188" width="9" height="12" xoffset="1" yoffset="6" xadvance="11" page="0" chnl="15" />
+ <char id="1216" x="158" y="261" width="2" height="12" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="1217" x="431" y="0" width="14" height="15" xoffset="0" yoffset="0" xadvance="14" page="0" chnl="15" />
+ <char id="1218" x="476" y="145" width="12" height="12" xoffset="0" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="1219" x="209" y="0" width="9" height="16" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="1220" x="230" y="218" width="8" height="12" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="1221" x="452" y="17" width="11" height="15" xoffset="0" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="1222" x="265" y="259" width="10" height="11" xoffset="0" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="1223" x="186" y="0" width="10" height="16" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="1224" x="140" y="219" width="8" height="12" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="1225" x="426" y="17" width="11" height="15" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="1226" x="321" y="259" width="9" height="11" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="1227" x="432" y="68" width="9" height="15" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="1228" x="412" y="258" width="7" height="11" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="1229" x="141" y="18" width="12" height="15" xoffset="1" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="1230" x="252" y="259" width="11" height="11" xoffset="1" yoffset="6" xadvance="12" page="0" chnl="15" />
+ <char id="1231" x="162" y="261" width="2" height="12" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="1232" x="0" y="38" width="11" height="15" xoffset="0" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="1233" x="130" y="219" width="8" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="1234" x="361" y="17" width="11" height="15" xoffset="0" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="1235" x="110" y="219" width="8" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="1236" x="342" y="118" width="16" height="12" xoffset="-1" yoffset="3" xadvance="16" page="0" chnl="15" />
+ <char id="1237" x="159" y="275" width="12" height="9" xoffset="1" yoffset="6" xadvance="14" page="0" chnl="15" />
+ <char id="1238" x="256" y="68" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="1239" x="297" y="245" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="1240" x="490" y="159" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="1241" x="257" y="283" width="7" height="9" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="1242" x="358" y="34" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="1243" x="270" y="245" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="1244" x="415" y="0" width="14" height="15" xoffset="0" yoffset="0" xadvance="14" page="0" chnl="15" />
+ <char id="1245" x="434" y="146" width="12" height="12" xoffset="0" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="1246" x="399" y="68" width="9" height="15" xoffset="0" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="1247" x="434" y="244" width="6" height="12" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="1248" x="358" y="188" width="9" height="12" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="1249" x="351" y="244" width="7" height="12" xoffset="0" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="1250" x="346" y="34" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="1251" x="432" y="202" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="1252" x="334" y="34" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="1253" x="402" y="202" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="1254" x="322" y="34" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="1255" x="342" y="202" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="1256" x="24" y="194" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="1257" x="170" y="286" width="8" height="9" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="1258" x="310" y="34" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="1259" x="322" y="202" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="1260" x="487" y="68" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="1261" x="306" y="245" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="1262" x="155" y="18" width="12" height="15" xoffset="-1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="1263" x="439" y="17" width="11" height="15" xoffset="-1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="1264" x="253" y="17" width="12" height="15" xoffset="-1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="1265" x="413" y="17" width="11" height="15" xoffset="-1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="1266" x="183" y="18" width="12" height="15" xoffset="-1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="1267" x="400" y="17" width="11" height="15" xoffset="-1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="1268" x="498" y="68" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="1269" x="207" y="246" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="1270" x="258" y="85" width="8" height="15" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="1271" x="447" y="258" width="6" height="11" xoffset="1" yoffset="6" xadvance="7" page="0" chnl="15" />
+ <char id="1272" x="493" y="0" width="13" height="15" xoffset="1" yoffset="0" xadvance="15" page="0" chnl="15" />
+ <char id="1273" x="420" y="146" width="12" height="12" xoffset="1" yoffset="3" xadvance="14" page="0" chnl="15" />
+ <char id="1274" x="286" y="34" width="10" height="15" xoffset="-1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="1275" x="20" y="236" width="8" height="12" xoffset="-1" yoffset="6" xadvance="7" page="0" chnl="15" />
+ <char id="1276" x="335" y="17" width="11" height="15" xoffset="0" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="1277" x="369" y="188" width="9" height="12" xoffset="0" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="1278" x="377" y="160" width="11" height="12" xoffset="0" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="1279" x="365" y="271" width="9" height="9" xoffset="0" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="8192" x="452" y="293" width="1" height="1" xoffset="0" yoffset="15" xadvance="8" page="0" chnl="15" />
+ <char id="8193" x="455" y="293" width="1" height="1" xoffset="0" yoffset="15" xadvance="16" page="0" chnl="15" />
+ <char id="8194" x="458" y="293" width="1" height="1" xoffset="0" yoffset="15" xadvance="8" page="0" chnl="15" />
+ <char id="8195" x="461" y="293" width="1" height="1" xoffset="0" yoffset="15" xadvance="16" page="0" chnl="15" />
+ <char id="8196" x="464" y="293" width="1" height="1" xoffset="0" yoffset="15" xadvance="5" page="0" chnl="15" />
+ <char id="8197" x="467" y="293" width="1" height="1" xoffset="0" yoffset="15" xadvance="4" page="0" chnl="15" />
+ <char id="8198" x="470" y="293" width="1" height="1" xoffset="0" yoffset="15" xadvance="3" page="0" chnl="15" />
+ <char id="8199" x="473" y="293" width="1" height="1" xoffset="0" yoffset="15" xadvance="9" page="0" chnl="15" />
+ <char id="8200" x="446" y="293" width="1" height="1" xoffset="0" yoffset="15" xadvance="4" page="0" chnl="15" />
+ <char id="8201" x="440" y="293" width="1" height="1" xoffset="0" yoffset="15" xadvance="3" page="0" chnl="15" />
+ <char id="8202" x="509" y="279" width="1" height="1" xoffset="0" yoffset="15" xadvance="1" page="0" chnl="15" />
+ <char id="8203" x="509" y="82" width="1" height="1" xoffset="0" yoffset="15" xadvance="0" page="0" chnl="15" />
+ <char id="8204" x="509" y="68" width="1" height="12" xoffset="0" yoffset="5" xadvance="0" page="0" chnl="15" />
+ <char id="8205" x="66" y="122" width="3" height="13" xoffset="-1" yoffset="4" xadvance="0" page="0" chnl="15" />
+ <char id="8206" x="54" y="122" width="4" height="13" xoffset="0" yoffset="4" xadvance="0" page="0" chnl="15" />
+ <char id="8207" x="60" y="122" width="4" height="13" xoffset="-3" yoffset="4" xadvance="0" page="0" chnl="15" />
+ <char id="8210" x="322" y="294" width="9" height="2" xoffset="0" yoffset="10" xadvance="9" page="0" chnl="15" />
+ <char id="8211" x="344" y="294" width="9" height="2" xoffset="0" yoffset="10" xadvance="9" page="0" chnl="15" />
+ <char id="8212" x="274" y="294" width="16" height="2" xoffset="0" yoffset="10" xadvance="16" page="0" chnl="15" />
+ <char id="8213" x="292" y="294" width="14" height="2" xoffset="1" yoffset="10" xadvance="16" page="0" chnl="15" />
+ <char id="8214" x="450" y="244" width="6" height="12" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="8215" x="104" y="300" width="9" height="5" xoffset="0" yoffset="14" xadvance="9" page="0" chnl="15" />
+ <char id="8216" x="179" y="297" width="2" height="5" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="8217" x="183" y="297" width="2" height="5" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="8218" x="167" y="297" width="2" height="5" xoffset="1" yoffset="13" xadvance="4" page="0" chnl="15" />
+ <char id="8219" x="171" y="297" width="2" height="5" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="8220" x="125" y="298" width="5" height="5" xoffset="2" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="8221" x="139" y="298" width="5" height="5" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="8222" x="146" y="297" width="5" height="5" xoffset="1" yoffset="13" xadvance="8" page="0" chnl="15" />
+ <char id="8223" x="153" y="297" width="5" height="5" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="8224" x="348" y="85" width="8" height="15" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="8225" x="358" y="85" width="8" height="15" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="8226" x="132" y="298" width="5" height="5" xoffset="1" yoffset="7" xadvance="6" page="0" chnl="15" />
+ <char id="8230" x="308" y="294" width="12" height="2" xoffset="1" yoffset="13" xadvance="16" page="0" chnl="15" />
+ <char id="8234" x="91" y="263" width="4" height="12" xoffset="0" yoffset="5" xadvance="0" page="0" chnl="15" />
+ <char id="8235" x="115" y="262" width="4" height="12" xoffset="-3" yoffset="5" xadvance="0" page="0" chnl="15" />
+ <char id="8236" x="418" y="102" width="5" height="14" xoffset="-2" yoffset="3" xadvance="0" page="0" chnl="15" />
+ <char id="8237" x="26" y="123" width="5" height="13" xoffset="-2" yoffset="4" xadvance="0" page="0" chnl="15" />
+ <char id="8238" x="19" y="123" width="5" height="13" xoffset="-2" yoffset="4" xadvance="0" page="0" chnl="15" />
+ <char id="8240" x="132" y="120" width="18" height="12" xoffset="0" yoffset="3" xadvance="18" page="0" chnl="15" />
+ <char id="8242" x="224" y="295" width="2" height="4" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="8243" x="197" y="296" width="6" height="4" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="8244" x="187" y="297" width="8" height="4" xoffset="0" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="8249" x="38" y="300" width="4" height="7" xoffset="0" yoffset="7" xadvance="5" page="0" chnl="15" />
+ <char id="8250" x="44" y="300" width="4" height="7" xoffset="1" yoffset="7" xadvance="5" page="0" chnl="15" />
+ <char id="8252" x="410" y="244" width="6" height="12" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="8254" x="380" y="293" width="5" height="2" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="8260" x="424" y="188" width="9" height="12" xoffset="-3" yoffset="3" xadvance="3" page="0" chnl="15" />
+ <char id="8286" x="470" y="258" width="2" height="11" xoffset="1" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="8298" x="425" y="102" width="5" height="14" xoffset="-2" yoffset="3" xadvance="0" page="0" chnl="15" />
+ <char id="8299" x="47" y="123" width="5" height="13" xoffset="-2" yoffset="4" xadvance="0" page="0" chnl="15" />
+ <char id="8300" x="40" y="123" width="5" height="13" xoffset="-2" yoffset="4" xadvance="0" page="0" chnl="15" />
+ <char id="8301" x="33" y="123" width="5" height="13" xoffset="-2" yoffset="4" xadvance="0" page="0" chnl="15" />
+ <char id="8302" x="85" y="104" width="5" height="15" xoffset="-2" yoffset="2" xadvance="0" page="0" chnl="15" />
+ <char id="8303" x="432" y="102" width="5" height="14" xoffset="-2" yoffset="3" xadvance="0" page="0" chnl="15" />
+ <char id="8352" x="300" y="217" width="8" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="8353" x="322" y="102" width="10" height="14" xoffset="1" yoffset="2" xadvance="12" page="0" chnl="15" />
+ <char id="8354" x="456" y="173" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="8355" x="50" y="222" width="8" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="8356" x="11" y="208" width="9" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="8357" x="453" y="102" width="12" height="13" xoffset="1" yoffset="4" xadvance="14" page="0" chnl="15" />
+ <char id="8358" x="280" y="147" width="12" height="12" xoffset="0" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="8359" x="360" y="118" width="16" height="12" xoffset="0" yoffset="3" xadvance="17" page="0" chnl="15" />
+ <char id="8360" x="172" y="120" width="18" height="12" xoffset="1" yoffset="3" xadvance="20" page="0" chnl="15" />
+ <char id="8361" x="447" y="117" width="15" height="12" xoffset="0" yoffset="3" xadvance="15" page="0" chnl="15" />
+ <char id="8362" x="229" y="273" width="11" height="9" xoffset="1" yoffset="6" xadvance="13" page="0" chnl="15" />
+ <char id="8363" x="455" y="258" width="6" height="11" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="8364" x="452" y="202" width="8" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="8365" x="336" y="146" width="12" height="12" xoffset="0" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="8366" x="36" y="194" width="10" height="12" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="8367" x="47" y="0" width="17" height="17" xoffset="0" yoffset="1" xadvance="17" page="0" chnl="15" />
+ <char id="8368" x="388" y="68" width="9" height="15" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="8369" x="390" y="160" width="11" height="12" xoffset="0" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="8370" x="286" y="102" width="10" height="14" xoffset="1" yoffset="2" xadvance="12" page="0" chnl="15" />
+ <char id="8371" x="392" y="146" width="12" height="12" xoffset="0" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="8372" x="416" y="160" width="11" height="12" xoffset="0" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="8373" x="262" y="102" width="10" height="14" xoffset="1" yoffset="2" xadvance="12" page="0" chnl="15" />
+ <char id="8531" x="432" y="132" width="13" height="12" xoffset="0" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="8532" x="447" y="131" width="13" height="12" xoffset="0" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="8539" x="462" y="131" width="13" height="12" xoffset="0" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="8540" x="477" y="131" width="13" height="12" xoffset="0" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="8541" x="492" y="131" width="13" height="12" xoffset="0" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="8542" x="177" y="134" width="13" height="12" xoffset="0" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="8580" x="419" y="282" width="7" height="9" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ </chars>
+ <kernings count="397">
+ <kerning first="32" second="65" amount="-1" />
+ <kerning first="32" second="902" amount="-1" />
+ <kerning first="32" second="913" amount="-1" />
+ <kerning first="32" second="916" amount="-1" />
+ <kerning first="32" second="923" amount="-1" />
+ <kerning first="49" second="49" amount="-1" />
+ <kerning first="65" second="32" amount="-1" />
+ <kerning first="65" second="84" amount="-1" />
+ <kerning first="65" second="86" amount="-1" />
+ <kerning first="65" second="87" amount="-1" />
+ <kerning first="65" second="89" amount="-1" />
+ <kerning first="65" second="118" amount="-1" />
+ <kerning first="65" second="121" amount="-1" />
+ <kerning first="65" second="8217" amount="-1" />
+ <kerning first="70" second="44" amount="-2" />
+ <kerning first="70" second="46" amount="-2" />
+ <kerning first="70" second="65" amount="-1" />
+ <kerning first="76" second="84" amount="-1" />
+ <kerning first="76" second="86" amount="-1" />
+ <kerning first="76" second="87" amount="-1" />
+ <kerning first="76" second="89" amount="-1" />
+ <kerning first="76" second="121" amount="-1" />
+ <kerning first="76" second="8217" amount="-1" />
+ <kerning first="80" second="44" amount="-2" />
+ <kerning first="80" second="46" amount="-2" />
+ <kerning first="80" second="65" amount="-1" />
+ <kerning first="82" second="89" amount="-1" />
+ <kerning first="84" second="44" amount="-2" />
+ <kerning first="84" second="45" amount="-1" />
+ <kerning first="84" second="46" amount="-2" />
+ <kerning first="84" second="58" amount="-2" />
+ <kerning first="84" second="894" amount="-2" />
+ <kerning first="84" second="65" amount="-1" />
+ <kerning first="84" second="97" amount="-1" />
+ <kerning first="84" second="99" amount="-1" />
+ <kerning first="84" second="101" amount="-1" />
+ <kerning first="84" second="111" amount="-1" />
+ <kerning first="84" second="114" amount="-1" />
+ <kerning first="84" second="115" amount="-1" />
+ <kerning first="84" second="117" amount="-1" />
+ <kerning first="84" second="119" amount="-1" />
+ <kerning first="84" second="121" amount="-1" />
+ <kerning first="86" second="44" amount="-1" />
+ <kerning first="86" second="45" amount="-1" />
+ <kerning first="86" second="46" amount="-1" />
+ <kerning first="86" second="58" amount="-1" />
+ <kerning first="86" second="894" amount="-1" />
+ <kerning first="86" second="65" amount="-1" />
+ <kerning first="86" second="97" amount="-1" />
+ <kerning first="86" second="101" amount="-1" />
+ <kerning first="86" second="111" amount="-1" />
+ <kerning first="86" second="114" amount="-1" />
+ <kerning first="86" second="117" amount="-1" />
+ <kerning first="86" second="121" amount="-1" />
+ <kerning first="87" second="44" amount="-1" />
+ <kerning first="87" second="46" amount="-1" />
+ <kerning first="87" second="65" amount="-1" />
+ <kerning first="87" second="97" amount="-1" />
+ <kerning first="89" second="44" amount="-2" />
+ <kerning first="89" second="45" amount="-1" />
+ <kerning first="89" second="46" amount="-2" />
+ <kerning first="89" second="58" amount="-1" />
+ <kerning first="89" second="894" amount="-1" />
+ <kerning first="89" second="65" amount="-1" />
+ <kerning first="89" second="97" amount="-1" />
+ <kerning first="89" second="101" amount="-1" />
+ <kerning first="89" second="105" amount="-1" />
+ <kerning first="89" second="111" amount="-1" />
+ <kerning first="89" second="112" amount="-1" />
+ <kerning first="89" second="113" amount="-1" />
+ <kerning first="89" second="117" amount="-1" />
+ <kerning first="89" second="118" amount="-1" />
+ <kerning first="114" second="44" amount="-1" />
+ <kerning first="114" second="46" amount="-1" />
+ <kerning first="114" second="8217" amount="1" />
+ <kerning first="118" second="44" amount="-1" />
+ <kerning first="118" second="46" amount="-1" />
+ <kerning first="119" second="44" amount="-1" />
+ <kerning first="119" second="46" amount="-1" />
+ <kerning first="121" second="44" amount="-1" />
+ <kerning first="121" second="46" amount="-1" />
+ <kerning first="8216" second="8216" amount="-1" />
+ <kerning first="8217" second="32" amount="-1" />
+ <kerning first="8217" second="115" amount="-1" />
+ <kerning first="8217" second="8217" amount="-1" />
+ <kerning first="8222" second="1026" amount="-2" />
+ <kerning first="8222" second="1035" amount="-2" />
+ <kerning first="8222" second="1058" amount="-1" />
+ <kerning first="8222" second="1063" amount="-2" />
+ <kerning first="8222" second="1066" amount="-1" />
+ <kerning first="915" second="44" amount="-2" />
+ <kerning first="915" second="46" amount="-2" />
+ <kerning first="915" second="913" amount="-2" />
+ <kerning first="915" second="916" amount="-2" />
+ <kerning first="915" second="923" amount="-2" />
+ <kerning first="915" second="943" amount="-1" />
+ <kerning first="915" second="953" amount="-1" />
+ <kerning first="915" second="970" amount="1" />
+ <kerning first="948" second="967" amount="-1" />
+ <kerning first="966" second="967" amount="-1" />
+ <kerning first="902" second="932" amount="-1" />
+ <kerning first="902" second="933" amount="-1" />
+ <kerning first="902" second="939" amount="-1" />
+ <kerning first="902" second="947" amount="-1" />
+ <kerning first="902" second="957" amount="-1" />
+ <kerning first="902" second="967" amount="-1" />
+ <kerning first="910" second="920" amount="-1" />
+ <kerning first="910" second="934" amount="-1" />
+ <kerning first="910" second="945" amount="-1" />
+ <kerning first="910" second="948" amount="-1" />
+ <kerning first="910" second="963" amount="-1" />
+ <kerning first="910" second="966" amount="-1" />
+ <kerning first="910" second="912" amount="2" />
+ <kerning first="910" second="913" amount="-1" />
+ <kerning first="910" second="916" amount="-1" />
+ <kerning first="910" second="923" amount="-1" />
+ <kerning first="910" second="927" amount="-1" />
+ <kerning first="910" second="937" amount="-1" />
+ <kerning first="910" second="940" amount="-1" />
+ <kerning first="910" second="942" amount="-1" />
+ <kerning first="910" second="943" amount="-1" />
+ <kerning first="910" second="951" amount="-1" />
+ <kerning first="910" second="953" amount="-1" />
+ <kerning first="910" second="954" amount="-1" />
+ <kerning first="910" second="956" amount="-1" />
+ <kerning first="910" second="959" amount="-1" />
+ <kerning first="910" second="970" amount="1" />
+ <kerning first="910" second="972" amount="-1" />
+ <kerning first="913" second="8217" amount="-1" />
+ <kerning first="913" second="932" amount="-1" />
+ <kerning first="913" second="933" amount="-1" />
+ <kerning first="913" second="939" amount="-1" />
+ <kerning first="913" second="947" amount="-1" />
+ <kerning first="913" second="957" amount="-1" />
+ <kerning first="913" second="967" amount="-1" />
+ <kerning first="916" second="932" amount="-1" />
+ <kerning first="916" second="933" amount="-1" />
+ <kerning first="916" second="939" amount="-1" />
+ <kerning first="922" second="920" amount="-1" />
+ <kerning first="922" second="934" amount="-1" />
+ <kerning first="922" second="927" amount="-1" />
+ <kerning first="923" second="932" amount="-1" />
+ <kerning first="923" second="933" amount="-1" />
+ <kerning first="923" second="939" amount="-1" />
+ <kerning first="929" second="44" amount="-2" />
+ <kerning first="929" second="46" amount="-2" />
+ <kerning first="929" second="913" amount="-1" />
+ <kerning first="929" second="916" amount="-1" />
+ <kerning first="929" second="923" amount="-1" />
+ <kerning first="932" second="44" amount="-2" />
+ <kerning first="932" second="45" amount="-1" />
+ <kerning first="932" second="46" amount="-2" />
+ <kerning first="932" second="58" amount="-2" />
+ <kerning first="932" second="894" amount="-2" />
+ <kerning first="932" second="945" amount="-1" />
+ <kerning first="932" second="948" amount="-1" />
+ <kerning first="932" second="949" amount="-1" />
+ <kerning first="932" second="963" amount="-1" />
+ <kerning first="932" second="966" amount="-1" />
+ <kerning first="932" second="912" amount="2" />
+ <kerning first="932" second="913" amount="-1" />
+ <kerning first="932" second="916" amount="-1" />
+ <kerning first="932" second="923" amount="-1" />
+ <kerning first="932" second="940" amount="-1" />
+ <kerning first="932" second="941" amount="-1" />
+ <kerning first="932" second="947" amount="-1" />
+ <kerning first="932" second="951" amount="-1" />
+ <kerning first="932" second="956" amount="-1" />
+ <kerning first="932" second="957" amount="-1" />
+ <kerning first="932" second="959" amount="-1" />
+ <kerning first="932" second="965" amount="-1" />
+ <kerning first="932" second="967" amount="-1" />
+ <kerning first="932" second="968" amount="-1" />
+ <kerning first="932" second="970" amount="1" />
+ <kerning first="932" second="971" amount="-1" />
+ <kerning first="932" second="972" amount="-1" />
+ <kerning first="932" second="973" amount="-1" />
+ <kerning first="933" second="44" amount="-2" />
+ <kerning first="933" second="45" amount="-1" />
+ <kerning first="933" second="46" amount="-2" />
+ <kerning first="933" second="58" amount="-1" />
+ <kerning first="933" second="894" amount="-1" />
+ <kerning first="933" second="920" amount="-1" />
+ <kerning first="933" second="934" amount="-1" />
+ <kerning first="933" second="945" amount="-1" />
+ <kerning first="933" second="948" amount="-1" />
+ <kerning first="933" second="963" amount="-1" />
+ <kerning first="933" second="966" amount="-1" />
+ <kerning first="933" second="912" amount="2" />
+ <kerning first="933" second="913" amount="-1" />
+ <kerning first="933" second="916" amount="-1" />
+ <kerning first="933" second="923" amount="-1" />
+ <kerning first="933" second="927" amount="-1" />
+ <kerning first="933" second="937" amount="-1" />
+ <kerning first="933" second="940" amount="-1" />
+ <kerning first="933" second="942" amount="-1" />
+ <kerning first="933" second="943" amount="-1" />
+ <kerning first="933" second="947" amount="-1" />
+ <kerning first="933" second="951" amount="-1" />
+ <kerning first="933" second="953" amount="-1" />
+ <kerning first="933" second="954" amount="-1" />
+ <kerning first="933" second="956" amount="-1" />
+ <kerning first="933" second="959" amount="-1" />
+ <kerning first="933" second="970" amount="1" />
+ <kerning first="933" second="972" amount="-1" />
+ <kerning first="939" second="920" amount="-1" />
+ <kerning first="939" second="934" amount="-1" />
+ <kerning first="939" second="945" amount="-1" />
+ <kerning first="939" second="948" amount="-1" />
+ <kerning first="939" second="963" amount="-1" />
+ <kerning first="939" second="966" amount="-1" />
+ <kerning first="939" second="912" amount="2" />
+ <kerning first="939" second="913" amount="-1" />
+ <kerning first="939" second="916" amount="-1" />
+ <kerning first="939" second="923" amount="-1" />
+ <kerning first="939" second="927" amount="-1" />
+ <kerning first="939" second="937" amount="-1" />
+ <kerning first="939" second="940" amount="-1" />
+ <kerning first="939" second="942" amount="-1" />
+ <kerning first="939" second="943" amount="-1" />
+ <kerning first="939" second="951" amount="-1" />
+ <kerning first="939" second="953" amount="-1" />
+ <kerning first="939" second="954" amount="-1" />
+ <kerning first="939" second="956" amount="-1" />
+ <kerning first="939" second="959" amount="-1" />
+ <kerning first="939" second="970" amount="1" />
+ <kerning first="939" second="972" amount="-1" />
+ <kerning first="950" second="945" amount="-1" />
+ <kerning first="950" second="948" amount="-1" />
+ <kerning first="950" second="963" amount="-1" />
+ <kerning first="950" second="964" amount="-1" />
+ <kerning first="950" second="966" amount="-1" />
+ <kerning first="950" second="940" amount="-1" />
+ <kerning first="950" second="947" amount="-1" />
+ <kerning first="950" second="952" amount="-1" />
+ <kerning first="950" second="957" amount="-1" />
+ <kerning first="950" second="959" amount="-1" />
+ <kerning first="950" second="969" amount="-1" />
+ <kerning first="950" second="972" amount="-1" />
+ <kerning first="950" second="974" amount="-1" />
+ <kerning first="950" second="960" amount="-1" />
+ <kerning first="954" second="945" amount="-1" />
+ <kerning first="954" second="948" amount="-1" />
+ <kerning first="954" second="963" amount="-1" />
+ <kerning first="954" second="966" amount="-1" />
+ <kerning first="954" second="940" amount="-1" />
+ <kerning first="954" second="950" amount="-1" />
+ <kerning first="954" second="958" amount="-1" />
+ <kerning first="954" second="959" amount="-1" />
+ <kerning first="954" second="962" amount="-1" />
+ <kerning first="954" second="969" amount="-1" />
+ <kerning first="954" second="972" amount="-1" />
+ <kerning first="954" second="974" amount="-1" />
+ <kerning first="959" second="967" amount="-1" />
+ <kerning first="967" second="945" amount="-1" />
+ <kerning first="967" second="948" amount="-1" />
+ <kerning first="967" second="963" amount="-1" />
+ <kerning first="967" second="966" amount="-1" />
+ <kerning first="967" second="940" amount="-1" />
+ <kerning first="967" second="950" amount="-1" />
+ <kerning first="967" second="959" amount="-1" />
+ <kerning first="967" second="962" amount="-1" />
+ <kerning first="967" second="972" amount="-1" />
+ <kerning first="972" second="967" amount="-1" />
+ <kerning first="1027" second="44" amount="-2" />
+ <kerning first="1027" second="46" amount="-2" />
+ <kerning first="1027" second="171" amount="-1" />
+ <kerning first="1027" second="187" amount="-1" />
+ <kerning first="1033" second="8217" amount="-2" />
+ <kerning first="1034" second="8217" amount="-2" />
+ <kerning first="1040" second="8217" amount="-1" />
+ <kerning first="1040" second="1044" amount="1" />
+ <kerning first="1040" second="1058" amount="-1" />
+ <kerning first="1040" second="1059" amount="-1" />
+ <kerning first="1040" second="1063" amount="-1" />
+ <kerning first="1041" second="1040" amount="-1" />
+ <kerning first="1041" second="1063" amount="-1" />
+ <kerning first="1041" second="1066" amount="-1" />
+ <kerning first="1042" second="1040" amount="-1" />
+ <kerning first="1042" second="1046" amount="-1" />
+ <kerning first="1042" second="1057" amount="-1" />
+ <kerning first="1042" second="1058" amount="-1" />
+ <kerning first="1042" second="1059" amount="-1" />
+ <kerning first="1042" second="1061" amount="-1" />
+ <kerning first="1042" second="1063" amount="-1" />
+ <kerning first="1042" second="1066" amount="-1" />
+ <kerning first="1042" second="1095" amount="-1" />
+ <kerning first="1043" second="44" amount="-2" />
+ <kerning first="1043" second="46" amount="-2" />
+ <kerning first="1043" second="171" amount="-1" />
+ <kerning first="1043" second="187" amount="-1" />
+ <kerning first="1043" second="1040" amount="-1" />
+ <kerning first="1043" second="1076" amount="-1" />
+ <kerning first="1043" second="1077" amount="-1" />
+ <kerning first="1043" second="1083" amount="-1" />
+ <kerning first="1043" second="1084" amount="-1" />
+ <kerning first="1043" second="1086" amount="-1" />
+ <kerning first="1043" second="1088" amount="-1" />
+ <kerning first="1043" second="1091" amount="-1" />
+ <kerning first="1043" second="1099" amount="-1" />
+ <kerning first="1043" second="1100" amount="-1" />
+ <kerning first="1043" second="1102" amount="-1" />
+ <kerning first="1043" second="1103" amount="-1" />
+ <kerning first="1046" second="1066" amount="1" />
+ <kerning first="1047" second="1058" amount="-1" />
+ <kerning first="1047" second="1059" amount="-1" />
+ <kerning first="1047" second="1063" amount="-1" />
+ <kerning first="1050" second="1047" amount="1" />
+ <kerning first="1054" second="1061" amount="-1" />
+ <kerning first="1056" second="44" amount="-2" />
+ <kerning first="1056" second="46" amount="-2" />
+ <kerning first="1056" second="1040" amount="-1" />
+ <kerning first="1056" second="1044" amount="-1" />
+ <kerning first="1056" second="1051" amount="-1" />
+ <kerning first="1056" second="1061" amount="-1" />
+ <kerning first="1056" second="1076" amount="-1" />
+ <kerning first="1057" second="1061" amount="-1" />
+ <kerning first="1058" second="44" amount="-2" />
+ <kerning first="1058" second="46" amount="-2" />
+ <kerning first="1058" second="1040" amount="-1" />
+ <kerning first="1058" second="1060" amount="-1" />
+ <kerning first="1058" second="1074" amount="-1" />
+ <kerning first="1058" second="1077" amount="-1" />
+ <kerning first="1058" second="1080" amount="-1" />
+ <kerning first="1058" second="1082" amount="-1" />
+ <kerning first="1058" second="1083" amount="-1" />
+ <kerning first="1058" second="1084" amount="-1" />
+ <kerning first="1058" second="1086" amount="-1" />
+ <kerning first="1058" second="1088" amount="-1" />
+ <kerning first="1058" second="1089" amount="-1" />
+ <kerning first="1058" second="1091" amount="-1" />
+ <kerning first="1058" second="1093" amount="-1" />
+ <kerning first="1059" second="44" amount="-2" />
+ <kerning first="1059" second="46" amount="-2" />
+ <kerning first="1059" second="171" amount="-1" />
+ <kerning first="1059" second="187" amount="-1" />
+ <kerning first="1059" second="1040" amount="-1" />
+ <kerning first="1059" second="1044" amount="-1" />
+ <kerning first="1059" second="1051" amount="-1" />
+ <kerning first="1059" second="1060" amount="-1" />
+ <kerning first="1059" second="1074" amount="-1" />
+ <kerning first="1059" second="1075" amount="-1" />
+ <kerning first="1059" second="1076" amount="-1" />
+ <kerning first="1059" second="1077" amount="-1" />
+ <kerning first="1059" second="1079" amount="-1" />
+ <kerning first="1059" second="1080" amount="-1" />
+ <kerning first="1059" second="1081" amount="-1" />
+ <kerning first="1059" second="1082" amount="-1" />
+ <kerning first="1059" second="1083" amount="-1" />
+ <kerning first="1059" second="1084" amount="-1" />
+ <kerning first="1059" second="1085" amount="-1" />
+ <kerning first="1059" second="1086" amount="-1" />
+ <kerning first="1059" second="1087" amount="-1" />
+ <kerning first="1059" second="1088" amount="-1" />
+ <kerning first="1059" second="1089" amount="-1" />
+ <kerning first="1059" second="1094" amount="-1" />
+ <kerning first="1059" second="1096" amount="-1" />
+ <kerning first="1059" second="1097" amount="-1" />
+ <kerning first="1059" second="1102" amount="-1" />
+ <kerning first="1059" second="1103" amount="-1" />
+ <kerning first="1060" second="1044" amount="-1" />
+ <kerning first="1060" second="1051" amount="-1" />
+ <kerning first="1060" second="1058" amount="-1" />
+ <kerning first="1060" second="1059" amount="-1" />
+ <kerning first="1061" second="1057" amount="-1" />
+ <kerning first="1061" second="1060" amount="-1" />
+ <kerning first="1062" second="1072" amount="1" />
+ <kerning first="1066" second="8217" amount="-2" />
+ <kerning first="1066" second="1071" amount="-1" />
+ <kerning first="1068" second="8217" amount="-1" />
+ <kerning first="1068" second="1046" amount="-1" />
+ <kerning first="1068" second="1051" amount="-1" />
+ <kerning first="1068" second="1058" amount="-2" />
+ <kerning first="1068" second="1061" amount="-1" />
+ <kerning first="1068" second="1063" amount="-1" />
+ <kerning first="1068" second="1069" amount="-1" />
+ <kerning first="1068" second="1071" amount="-1" />
+ <kerning first="1069" second="1051" amount="-1" />
+ <kerning first="1070" second="1051" amount="-1" />
+ <kerning first="1070" second="1061" amount="-1" />
+ <kerning first="1074" second="1095" amount="-1" />
+ <kerning first="1075" second="44" amount="-1" />
+ <kerning first="1075" second="46" amount="-2" />
+ <kerning first="1075" second="1076" amount="-1" />
+ <kerning first="1079" second="1095" amount="-1" />
+ <kerning first="1090" second="44" amount="-1" />
+ <kerning first="1090" second="46" amount="-1" />
+ <kerning first="1091" second="44" amount="-1" />
+ <kerning first="1091" second="46" amount="-1" />
+ <kerning first="1100" second="1090" amount="-1" />
+ <kerning first="1100" second="1095" amount="-1" />
+ <kerning first="1102" second="1095" amount="-1" />
+ <kerning first="1118" second="44" amount="-1" />
+ <kerning first="1118" second="46" amount="-1" />
+ <kerning first="1168" second="44" amount="-1" />
+ <kerning first="1168" second="46" amount="-1" />
+ <kerning first="960" second="955" amount="-1" />
+ </kernings>
+</font>
diff --git a/ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-16-bold-regular_00.png b/ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-16-bold-regular_00.png Binary files differnew file mode 100644 index 0000000..f4a5bac --- /dev/null +++ b/ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-16-bold-regular_00.png diff --git a/ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-18-bold-italic.fnt b/ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-18-bold-italic.fnt new file mode 100644 index 0000000..1d28361 --- /dev/null +++ b/ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-18-bold-italic.fnt @@ -0,0 +1,604 @@ +<?xml version="1.0"?>
+<font>
+ <info face="Arial" size="18" bold="1" italic="1" charset="" unicode="1" stretchH="100" smooth="1" aa="1" padding="0,0,0,0" spacing="1,1" outline="0"/>
+ <common lineHeight="18" base="15" scaleW="512" scaleH="256" pages="1" packed="0" alphaChnl="0" redChnl="4" greenChnl="4" blueChnl="4"/>
+ <pages>
+ <page id="0" file="arial-18-bold-italic_0.png" />
+ </pages>
+ <chars count="527">
+ <char id="32" x="510" y="34" width="1" height="1" xoffset="0" yoffset="15" xadvance="4" page="0" chnl="15" />
+ <char id="33" x="345" y="130" width="4" height="12" xoffset="1" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="34" x="377" y="141" width="6" height="4" xoffset="2" yoffset="3" xadvance="7" page="0" chnl="15" />
+ <char id="35" x="220" y="105" width="10" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="36" x="234" y="64" width="9" height="14" xoffset="1" yoffset="2" xadvance="9" page="0" chnl="15" />
+ <char id="37" x="345" y="78" width="12" height="12" xoffset="1" yoffset="3" xadvance="14" page="0" chnl="15" />
+ <char id="38" x="385" y="90" width="11" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="39" x="384" y="141" width="3" height="4" xoffset="2" yoffset="3" xadvance="3" page="0" chnl="15" />
+ <char id="40" x="446" y="48" width="6" height="15" xoffset="1" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="41" x="453" y="48" width="6" height="15" xoffset="-1" yoffset="3" xadvance="6" page="0" chnl="15" />
+ <char id="42" x="364" y="143" width="6" height="5" xoffset="1" yoffset="3" xadvance="6" page="0" chnl="15" />
+ <char id="43" x="257" y="144" width="8" height="8" xoffset="1" yoffset="5" xadvance="9" page="0" chnl="15" />
+ <char id="44" x="388" y="141" width="3" height="4" xoffset="0" yoffset="13" xadvance="4" page="0" chnl="15" />
+ <char id="45" x="422" y="141" width="4" height="2" xoffset="1" yoffset="10" xadvance="5" page="0" chnl="15" />
+ <char id="46" x="446" y="141" width="2" height="2" xoffset="1" yoffset="13" xadvance="4" page="0" chnl="15" />
+ <char id="47" x="488" y="116" width="8" height="12" xoffset="-1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="48" x="497" y="116" width="8" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="49" x="263" y="131" width="6" height="12" xoffset="2" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="50" x="9" y="135" width="8" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="51" x="27" y="135" width="8" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="52" x="90" y="119" width="9" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="53" x="36" y="135" width="8" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="54" x="45" y="135" width="8" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="55" x="54" y="135" width="8" height="12" xoffset="2" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="56" x="63" y="135" width="8" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="57" x="470" y="116" width="8" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="58" x="275" y="144" width="3" height="8" xoffset="1" yoffset="7" xadvance="5" page="0" chnl="15" />
+ <char id="59" x="478" y="129" width="4" height="10" xoffset="0" yoffset="7" xadvance="5" page="0" chnl="15" />
+ <char id="60" x="182" y="144" width="8" height="9" xoffset="1" yoffset="5" xadvance="9" page="0" chnl="15" />
+ <char id="61" x="346" y="143" width="8" height="5" xoffset="1" yoffset="7" xadvance="9" page="0" chnl="15" />
+ <char id="62" x="200" y="144" width="8" height="9" xoffset="1" yoffset="5" xadvance="9" page="0" chnl="15" />
+ <char id="63" x="380" y="116" width="8" height="12" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="64" x="182" y="0" width="15" height="15" xoffset="1" yoffset="3" xadvance="16" page="0" chnl="15" />
+ <char id="65" x="371" y="77" width="12" height="12" xoffset="-1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="66" x="231" y="105" width="10" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="67" x="13" y="96" width="11" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="68" x="229" y="92" width="11" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="69" x="25" y="96" width="11" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="70" x="242" y="105" width="10" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="71" x="373" y="90" width="11" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="72" x="61" y="94" width="11" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="73" x="340" y="130" width="4" height="12" xoffset="1" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="74" x="30" y="122" width="9" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="75" x="488" y="77" width="12" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="76" x="461" y="116" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="77" x="141" y="79" width="14" height="12" xoffset="1" yoffset="3" xadvance="14" page="0" chnl="15" />
+ <char id="78" x="85" y="93" width="11" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="79" x="97" y="93" width="11" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="80" x="109" y="93" width="11" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="81" x="283" y="64" width="11" height="13" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="82" x="133" y="93" width="11" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="83" x="253" y="105" width="10" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="84" x="264" y="105" width="10" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="85" x="169" y="92" width="11" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="86" x="181" y="92" width="11" height="12" xoffset="2" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="87" x="34" y="83" width="15" height="12" xoffset="2" yoffset="3" xadvance="15" page="0" chnl="15" />
+ <char id="88" x="475" y="77" width="12" height="12" xoffset="0" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="89" x="193" y="92" width="11" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="90" x="297" y="104" width="10" height="12" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="91" x="481" y="48" width="6" height="15" xoffset="-1" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="92" x="350" y="130" width="4" height="12" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="93" x="488" y="48" width="6" height="15" xoffset="-1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="94" x="306" y="143" width="7" height="6" xoffset="2" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="95" x="50" y="94" width="9" height="1" xoffset="0" yoffset="17" xadvance="9" page="0" chnl="15" />
+ <char id="96" x="432" y="141" width="4" height="2" xoffset="2" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="97" x="191" y="144" width="8" height="9" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="98" x="40" y="122" width="9" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="99" x="209" y="144" width="8" height="9" xoffset="1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="100" x="70" y="120" width="9" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="101" x="227" y="144" width="8" height="9" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="102" x="242" y="131" width="6" height="12" xoffset="1" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="103" x="330" y="104" width="10" height="12" xoffset="0" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="104" x="130" y="119" width="9" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="105" x="335" y="130" width="4" height="12" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="106" x="392" y="48" width="7" height="15" xoffset="-2" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="107" x="372" y="103" width="9" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="108" x="330" y="130" width="4" height="12" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="109" x="0" y="148" width="14" height="9" xoffset="1" yoffset="6" xadvance="14" page="0" chnl="15" />
+ <char id="110" x="65" y="148" width="10" height="9" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="111" x="107" y="145" width="9" height="9" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="112" x="80" y="120" width="9" height="12" xoffset="0" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="113" x="501" y="77" width="10" height="12" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="114" x="236" y="144" width="7" height="9" xoffset="1" yoffset="6" xadvance="6" page="0" chnl="15" />
+ <char id="115" x="137" y="145" width="8" height="9" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="116" x="466" y="129" width="5" height="11" xoffset="1" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="117" x="54" y="148" width="10" height="9" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="118" x="146" y="145" width="8" height="9" xoffset="2" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="119" x="15" y="148" width="13" height="9" xoffset="1" yoffset="6" xadvance="13" page="0" chnl="15" />
+ <char id="120" x="76" y="146" width="10" height="9" xoffset="0" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="121" x="241" y="92" width="11" height="12" xoffset="0" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="122" x="155" y="145" width="8" height="9" xoffset="0" yoffset="6" xadvance="7" page="0" chnl="15" />
+ <char id="123" x="400" y="48" width="7" height="15" xoffset="1" yoffset="3" xadvance="6" page="0" chnl="15" />
+ <char id="124" x="509" y="48" width="2" height="15" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="125" x="408" y="48" width="7" height="15" xoffset="-1" yoffset="3" xadvance="6" page="0" chnl="15" />
+ <char id="126" x="392" y="141" width="8" height="3" xoffset="1" yoffset="8" xadvance="9" page="0" chnl="15" />
+ <char id="160" x="510" y="32" width="1" height="1" xoffset="0" yoffset="15" xadvance="4" page="0" chnl="15" />
+ <char id="161" x="325" y="130" width="4" height="12" xoffset="1" yoffset="6" xadvance="5" page="0" chnl="15" />
+ <char id="162" x="338" y="48" width="8" height="15" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="163" x="306" y="64" width="10" height="13" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="164" x="97" y="145" width="9" height="9" xoffset="1" yoffset="5" xadvance="9" page="0" chnl="15" />
+ <char id="165" x="313" y="91" width="11" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="166" x="509" y="16" width="2" height="15" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="167" x="208" y="48" width="9" height="15" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="168" x="416" y="141" width="5" height="2" xoffset="1" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="169" x="410" y="77" width="12" height="12" xoffset="1" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="170" x="321" y="143" width="6" height="6" xoffset="1" yoffset="3" xadvance="6" page="0" chnl="15" />
+ <char id="171" x="297" y="144" width="8" height="7" xoffset="1" yoffset="7" xadvance="9" page="0" chnl="15" />
+ <char id="172" x="355" y="143" width="8" height="5" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="173" x="427" y="141" width="4" height="2" xoffset="1" yoffset="10" xadvance="5" page="0" chnl="15" />
+ <char id="174" x="332" y="78" width="12" height="12" xoffset="1" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="175" x="406" y="141" width="9" height="2" xoffset="1" yoffset="1" xadvance="9" page="0" chnl="15" />
+ <char id="176" x="371" y="141" width="5" height="5" xoffset="1" yoffset="3" xadvance="6" page="0" chnl="15" />
+ <char id="177" x="433" y="129" width="8" height="11" xoffset="1" yoffset="4" xadvance="9" page="0" chnl="15" />
+ <char id="178" x="340" y="143" width="5" height="6" xoffset="1" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="179" x="334" y="143" width="5" height="6" xoffset="1" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="180" x="437" y="141" width="4" height="2" xoffset="3" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="181" x="337" y="91" width="11" height="12" xoffset="-1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="182" x="268" y="48" width="9" height="15" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="183" x="442" y="141" width="3" height="2" xoffset="2" yoffset="8" xadvance="5" page="0" chnl="15" />
+ <char id="184" x="401" y="141" width="4" height="3" xoffset="0" yoffset="15" xadvance="5" page="0" chnl="15" />
+ <char id="185" x="328" y="143" width="5" height="6" xoffset="2" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="186" x="314" y="143" width="6" height="6" xoffset="1" yoffset="3" xadvance="6" page="0" chnl="15" />
+ <char id="187" x="288" y="144" width="8" height="7" xoffset="0" yoffset="7" xadvance="8" page="0" chnl="15" />
+ <char id="188" x="198" y="79" width="13" height="12" xoffset="1" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="189" x="280" y="78" width="12" height="12" xoffset="1" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="190" x="170" y="79" width="13" height="12" xoffset="1" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="191" x="344" y="117" width="8" height="12" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="192" x="425" y="0" width="12" height="15" xoffset="-1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="193" x="412" y="0" width="12" height="15" xoffset="-1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="194" x="490" y="0" width="12" height="15" xoffset="-1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="195" x="26" y="18" width="12" height="15" xoffset="-1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="196" x="399" y="0" width="12" height="15" xoffset="-1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="197" x="114" y="65" width="12" height="14" xoffset="-1" yoffset="1" xadvance="12" page="0" chnl="15" />
+ <char id="198" x="451" y="64" width="18" height="12" xoffset="-1" yoffset="3" xadvance="16" page="0" chnl="15" />
+ <char id="199" x="437" y="16" width="11" height="15" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="200" x="449" y="16" width="11" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="201" x="461" y="16" width="11" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="202" x="473" y="16" width="11" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="203" x="485" y="16" width="11" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="204" x="13" y="67" width="5" height="15" xoffset="1" yoffset="0" xadvance="5" page="0" chnl="15" />
+ <char id="205" x="460" y="48" width="6" height="15" xoffset="1" yoffset="0" xadvance="5" page="0" chnl="15" />
+ <char id="206" x="19" y="67" width="5" height="15" xoffset="1" yoffset="0" xadvance="5" page="0" chnl="15" />
+ <char id="207" x="474" y="48" width="6" height="15" xoffset="1" yoffset="0" xadvance="5" page="0" chnl="15" />
+ <char id="208" x="277" y="92" width="11" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="209" x="497" y="16" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="210" x="305" y="16" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="211" x="12" y="35" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="212" x="24" y="34" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="213" x="36" y="34" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="214" x="48" y="34" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="215" x="279" y="144" width="8" height="7" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="216" x="100" y="65" width="13" height="14" xoffset="0" yoffset="2" xadvance="12" page="0" chnl="15" />
+ <char id="217" x="60" y="33" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="218" x="72" y="33" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="219" x="84" y="33" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="220" x="96" y="33" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="221" x="108" y="33" width="11" height="15" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="222" x="409" y="90" width="10" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="223" x="352" y="104" width="9" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="224" x="308" y="117" width="8" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="225" x="299" y="117" width="8" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="226" x="281" y="118" width="8" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="227" x="254" y="118" width="8" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="228" x="245" y="118" width="8" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="229" x="328" y="64" width="8" height="13" xoffset="1" yoffset="2" xadvance="9" page="0" chnl="15" />
+ <char id="230" x="498" y="129" width="13" height="9" xoffset="1" yoffset="6" xadvance="14" page="0" chnl="15" />
+ <char id="231" x="227" y="118" width="8" height="12" xoffset="1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="232" x="218" y="118" width="8" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="233" x="209" y="118" width="8" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="234" x="200" y="118" width="8" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="235" x="362" y="116" width="8" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="236" x="360" y="130" width="4" height="12" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="237" x="314" y="130" width="5" height="12" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="238" x="302" y="130" width="5" height="12" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="239" x="308" y="130" width="5" height="12" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="240" x="362" y="103" width="9" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="241" x="420" y="90" width="10" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="242" x="392" y="103" width="9" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="243" x="402" y="103" width="9" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="244" x="412" y="103" width="9" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="245" x="432" y="103" width="9" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="246" x="452" y="103" width="9" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="247" x="266" y="144" width="8" height="8" xoffset="1" yoffset="5" xadvance="9" page="0" chnl="15" />
+ <char id="248" x="392" y="129" width="10" height="11" xoffset="0" yoffset="5" xadvance="9" page="0" chnl="15" />
+ <char id="249" x="431" y="90" width="10" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="250" x="442" y="90" width="10" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="251" x="453" y="90" width="10" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="252" x="464" y="90" width="10" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="253" x="216" y="32" width="11" height="15" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="254" x="121" y="49" width="10" height="15" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="255" x="228" y="32" width="11" height="15" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="256" x="127" y="65" width="12" height="14" xoffset="-1" yoffset="1" xadvance="12" page="0" chnl="15" />
+ <char id="257" x="424" y="129" width="8" height="11" xoffset="1" yoffset="4" xadvance="9" page="0" chnl="15" />
+ <char id="258" x="360" y="0" width="12" height="15" xoffset="-1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="259" x="153" y="132" width="8" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="260" x="346" y="0" width="13" height="15" xoffset="-1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="261" x="135" y="132" width="8" height="12" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="262" x="264" y="32" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="263" x="326" y="117" width="8" height="12" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="264" x="276" y="32" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="265" x="117" y="132" width="8" height="12" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="266" x="312" y="32" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="267" x="108" y="132" width="8" height="12" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="268" x="396" y="32" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="269" x="99" y="132" width="8" height="12" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="270" x="408" y="32" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="271" x="254" y="79" width="12" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="272" x="37" y="96" width="11" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="273" x="475" y="90" width="10" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="274" x="140" y="64" width="11" height="14" xoffset="1" yoffset="1" xadvance="11" page="0" chnl="15" />
+ <char id="275" x="451" y="129" width="8" height="11" xoffset="1" yoffset="4" xadvance="9" page="0" chnl="15" />
+ <char id="276" x="65" y="17" width="11" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="277" x="81" y="133" width="8" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="278" x="89" y="17" width="11" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="279" x="72" y="133" width="8" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="280" x="101" y="17" width="11" height="15" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="281" x="317" y="117" width="8" height="12" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="282" x="113" y="17" width="11" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="283" x="353" y="117" width="8" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="284" x="125" y="16" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="285" x="132" y="48" width="10" height="15" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="286" x="149" y="16" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="287" x="77" y="49" width="10" height="15" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="288" x="161" y="16" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="289" x="110" y="49" width="10" height="15" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="290" x="173" y="16" width="11" height="15" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="291" x="96" y="0" width="10" height="16" xoffset="0" yoffset="2" xadvance="9" page="0" chnl="15" />
+ <char id="292" x="185" y="16" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="293" x="248" y="48" width="9" height="15" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="294" x="184" y="79" width="13" height="12" xoffset="0" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="295" x="100" y="119" width="9" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="296" x="0" y="67" width="6" height="15" xoffset="1" yoffset="0" xadvance="5" page="0" chnl="15" />
+ <char id="297" x="296" y="131" width="5" height="12" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="298" x="254" y="64" width="6" height="14" xoffset="1" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="299" x="460" y="129" width="5" height="11" xoffset="1" yoffset="4" xadvance="4" page="0" chnl="15" />
+ <char id="300" x="432" y="48" width="6" height="15" xoffset="1" yoffset="0" xadvance="5" page="0" chnl="15" />
+ <char id="301" x="290" y="131" width="5" height="12" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="302" x="25" y="67" width="5" height="15" xoffset="0" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="303" x="31" y="67" width="5" height="15" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="304" x="37" y="66" width="5" height="15" xoffset="1" yoffset="0" xadvance="5" page="0" chnl="15" />
+ <char id="305" x="252" y="144" width="4" height="9" xoffset="1" yoffset="6" xadvance="4" page="0" chnl="15" />
+ <char id="306" x="156" y="79" width="13" height="12" xoffset="1" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="307" x="328" y="48" width="9" height="15" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="308" x="187" y="48" width="10" height="15" xoffset="0" yoffset="0" xadvance="9" page="0" chnl="15" />
+ <char id="309" x="383" y="48" width="8" height="15" xoffset="-2" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="310" x="386" y="0" width="12" height="15" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="311" x="198" y="48" width="9" height="15" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="312" x="127" y="145" width="9" height="9" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="313" x="503" y="0" width="8" height="15" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="314" x="467" y="48" width="6" height="15" xoffset="1" yoffset="0" xadvance="4" page="0" chnl="15" />
+ <char id="315" x="356" y="48" width="8" height="15" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="316" x="7" y="67" width="5" height="15" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="317" x="502" y="103" width="9" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="318" x="203" y="131" width="7" height="12" xoffset="1" yoffset="3" xadvance="6" page="0" chnl="15" />
+ <char id="319" x="162" y="131" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="320" x="90" y="132" width="8" height="12" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="321" x="110" y="119" width="9" height="12" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="322" x="235" y="131" width="6" height="12" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="323" x="180" y="32" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="324" x="0" y="109" width="10" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="325" x="420" y="32" width="11" height="15" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="326" x="11" y="109" width="10" height="12" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="327" x="192" y="32" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="328" x="22" y="109" width="10" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="329" x="145" y="92" width="11" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="330" x="157" y="92" width="11" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="331" x="33" y="109" width="10" height="12" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="332" x="164" y="64" width="11" height="14" xoffset="1" yoffset="1" xadvance="12" page="0" chnl="15" />
+ <char id="333" x="414" y="129" width="9" height="11" xoffset="1" yoffset="4" xadvance="10" page="0" chnl="15" />
+ <char id="334" x="120" y="33" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="335" x="60" y="122" width="9" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="336" x="372" y="32" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="337" x="44" y="109" width="10" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="338" x="17" y="83" width="16" height="12" xoffset="1" yoffset="3" xadvance="16" page="0" chnl="15" />
+ <char id="339" x="483" y="129" width="14" height="9" xoffset="1" yoffset="6" xadvance="15" page="0" chnl="15" />
+ <char id="340" x="353" y="16" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="341" x="227" y="131" width="7" height="12" xoffset="1" yoffset="3" xadvance="6" page="0" chnl="15" />
+ <char id="342" x="233" y="16" width="11" height="15" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="343" x="443" y="116" width="8" height="12" xoffset="0" yoffset="6" xadvance="6" page="0" chnl="15" />
+ <char id="344" x="221" y="16" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="345" x="171" y="131" width="7" height="12" xoffset="1" yoffset="3" xadvance="6" page="0" chnl="15" />
+ <char id="346" x="99" y="49" width="10" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="347" x="398" y="116" width="8" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="348" x="22" y="51" width="10" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="349" x="389" y="116" width="8" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="350" x="55" y="50" width="10" height="15" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="351" x="371" y="116" width="8" height="12" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="352" x="165" y="48" width="10" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="353" x="335" y="117" width="8" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="354" x="154" y="48" width="10" height="15" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="355" x="261" y="64" width="6" height="14" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="356" x="11" y="51" width="10" height="15" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="357" x="442" y="129" width="8" height="11" xoffset="1" yoffset="4" xadvance="8" page="0" chnl="15" />
+ <char id="358" x="55" y="109" width="10" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="359" x="472" y="129" width="5" height="11" xoffset="1" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="360" x="432" y="32" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="361" x="66" y="107" width="10" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="362" x="152" y="64" width="11" height="14" xoffset="1" yoffset="1" xadvance="12" page="0" chnl="15" />
+ <char id="363" x="403" y="129" width="10" height="11" xoffset="1" yoffset="4" xadvance="10" page="0" chnl="15" />
+ <char id="364" x="336" y="32" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="365" x="77" y="107" width="10" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="366" x="288" y="32" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="367" x="317" y="64" width="10" height="13" xoffset="1" yoffset="2" xadvance="10" page="0" chnl="15" />
+ <char id="368" x="252" y="32" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="369" x="88" y="106" width="10" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="370" x="240" y="32" width="11" height="15" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="371" x="99" y="106" width="10" height="12" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="372" x="198" y="0" width="15" height="15" xoffset="2" yoffset="0" xadvance="15" page="0" chnl="15" />
+ <char id="373" x="212" y="79" width="13" height="12" xoffset="1" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="374" x="0" y="35" width="11" height="15" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="375" x="168" y="32" width="11" height="15" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="376" x="156" y="32" width="11" height="15" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="377" x="143" y="48" width="10" height="15" xoffset="0" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="378" x="236" y="118" width="8" height="12" xoffset="0" yoffset="3" xadvance="7" page="0" chnl="15" />
+ <char id="379" x="66" y="49" width="10" height="15" xoffset="0" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="380" x="263" y="118" width="8" height="12" xoffset="0" yoffset="3" xadvance="7" page="0" chnl="15" />
+ <char id="381" x="176" y="48" width="10" height="15" xoffset="0" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="382" x="18" y="135" width="8" height="12" xoffset="0" yoffset="3" xadvance="7" page="0" chnl="15" />
+ <char id="383" x="270" y="131" width="6" height="12" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="384" x="180" y="118" width="9" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="385" x="319" y="78" width="12" height="12" xoffset="1" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="386" x="73" y="94" width="11" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="387" x="150" y="119" width="9" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="388" x="110" y="106" width="10" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="389" x="140" y="119" width="9" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="390" x="49" y="96" width="11" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="391" x="68" y="65" width="15" height="14" xoffset="2" yoffset="1" xadvance="12" page="0" chnl="15" />
+ <char id="392" x="379" y="129" width="12" height="11" xoffset="1" yoffset="4" xadvance="9" page="0" chnl="15" />
+ <char id="393" x="349" y="91" width="11" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="394" x="397" y="77" width="12" height="12" xoffset="1" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="395" x="121" y="106" width="10" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="396" x="132" y="106" width="10" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="397" x="143" y="106" width="10" height="12" xoffset="0" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="398" x="462" y="77" width="12" height="12" xoffset="0" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="399" x="361" y="90" width="11" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="400" x="382" y="103" width="9" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="401" x="304" y="0" width="13" height="15" xoffset="-1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="402" x="444" y="32" width="10" height="15" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="403" x="84" y="65" width="15" height="14" xoffset="1" yoffset="1" xadvance="12" page="0" chnl="15" />
+ <char id="404" x="132" y="32" width="11" height="15" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="405" x="111" y="80" width="14" height="12" xoffset="1" yoffset="3" xadvance="15" page="0" chnl="15" />
+ <char id="406" x="320" y="130" width="4" height="12" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="407" x="506" y="116" width="5" height="12" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="408" x="306" y="78" width="12" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="409" x="472" y="103" width="9" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="410" x="284" y="131" width="5" height="12" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="411" x="492" y="103" width="9" height="12" xoffset="-1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="412" x="50" y="81" width="15" height="12" xoffset="1" yoffset="3" xadvance="15" page="0" chnl="15" />
+ <char id="413" x="260" y="0" width="14" height="15" xoffset="-1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="414" x="10" y="122" width="9" height="12" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="415" x="301" y="91" width="11" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="416" x="66" y="81" width="14" height="12" xoffset="1" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="417" x="29" y="148" width="12" height="9" xoffset="1" yoffset="6" xadvance="11" page="0" chnl="15" />
+ <char id="418" x="245" y="0" width="14" height="15" xoffset="1" yoffset="3" xadvance="14" page="0" chnl="15" />
+ <char id="419" x="293" y="78" width="12" height="12" xoffset="1" yoffset="6" xadvance="12" page="0" chnl="15" />
+ <char id="420" x="267" y="79" width="12" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="421" x="88" y="49" width="10" height="15" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="422" x="223" y="64" width="10" height="14" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="423" x="121" y="93" width="11" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="424" x="173" y="144" width="8" height="9" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="425" x="154" y="105" width="10" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="426" x="43" y="66" width="5" height="15" xoffset="1" yoffset="3" xadvance="6" page="0" chnl="15" />
+ <char id="427" x="424" y="48" width="7" height="15" xoffset="-1" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="428" x="289" y="91" width="11" height="12" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="429" x="211" y="131" width="7" height="12" xoffset="1" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="430" x="33" y="50" width="10" height="15" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="431" x="126" y="80" width="14" height="12" xoffset="1" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="432" x="42" y="148" width="11" height="9" xoffset="1" yoffset="6" xadvance="11" page="0" chnl="15" />
+ <char id="433" x="96" y="80" width="14" height="12" xoffset="1" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="434" x="253" y="92" width="11" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="435" x="384" y="77" width="12" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="436" x="230" y="0" width="14" height="15" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="437" x="449" y="77" width="12" height="12" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="438" x="87" y="146" width="9" height="9" xoffset="0" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="439" x="269" y="16" width="11" height="15" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="440" x="438" y="0" width="12" height="15" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="441" x="165" y="105" width="10" height="12" xoffset="0" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="442" x="462" y="103" width="9" height="12" xoffset="0" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="443" x="482" y="103" width="9" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="444" x="176" y="105" width="10" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="445" x="117" y="145" width="9" height="9" xoffset="0" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="446" x="434" y="116" width="8" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="447" x="187" y="105" width="10" height="12" xoffset="0" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="448" x="508" y="90" width="2" height="12" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="449" x="256" y="131" width="6" height="12" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="450" x="452" y="116" width="8" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="451" x="355" y="130" width="4" height="12" xoffset="1" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="452" x="123" y="0" width="22" height="15" xoffset="1" yoffset="0" xadvance="21" page="0" chnl="15" />
+ <char id="453" x="411" y="64" width="19" height="12" xoffset="1" yoffset="3" xadvance="20" page="0" chnl="15" />
+ <char id="454" x="488" y="64" width="17" height="12" xoffset="1" yoffset="3" xadvance="18" page="0" chnl="15" />
+ <char id="455" x="431" y="64" width="19" height="12" xoffset="1" yoffset="3" xadvance="19" page="0" chnl="15" />
+ <char id="456" x="275" y="0" width="14" height="15" xoffset="1" yoffset="3" xadvance="14" page="0" chnl="15" />
+ <char id="457" x="218" y="48" width="9" height="15" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="458" x="369" y="64" width="21" height="12" xoffset="1" yoffset="3" xadvance="20" page="0" chnl="15" />
+ <char id="459" x="165" y="0" width="16" height="15" xoffset="1" yoffset="3" xadvance="16" page="0" chnl="15" />
+ <char id="460" x="214" y="0" width="15" height="15" xoffset="1" yoffset="3" xadvance="14" page="0" chnl="15" />
+ <char id="461" x="373" y="0" width="12" height="15" xoffset="-1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="462" x="0" y="135" width="8" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="463" x="495" y="48" width="6" height="15" xoffset="1" yoffset="0" xadvance="5" page="0" chnl="15" />
+ <char id="464" x="249" y="131" width="6" height="12" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="465" x="384" y="32" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="466" x="442" y="103" width="9" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="467" x="360" y="32" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="468" x="198" y="105" width="10" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="469" x="348" y="32" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="470" x="0" y="51" width="10" height="15" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="471" x="324" y="32" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="472" x="499" y="32" width="10" height="15" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="473" x="300" y="32" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="474" x="466" y="32" width="10" height="15" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="475" x="377" y="16" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="476" x="455" y="32" width="10" height="15" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="477" x="164" y="144" width="8" height="9" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="478" x="0" y="19" width="12" height="15" xoffset="-1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="479" x="374" y="48" width="8" height="15" xoffset="1" yoffset="0" xadvance="9" page="0" chnl="15" />
+ <char id="480" x="332" y="0" width="13" height="15" xoffset="-1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="481" x="365" y="48" width="8" height="15" xoffset="1" yoffset="0" xadvance="9" page="0" chnl="15" />
+ <char id="482" x="49" y="66" width="18" height="14" xoffset="-1" yoffset="1" xadvance="16" page="0" chnl="15" />
+ <char id="483" x="365" y="129" width="13" height="11" xoffset="1" yoffset="4" xadvance="14" page="0" chnl="15" />
+ <char id="484" x="358" y="77" width="12" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="485" x="205" y="92" width="11" height="12" xoffset="0" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="486" x="144" y="32" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="487" x="477" y="32" width="10" height="15" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="488" x="13" y="18" width="12" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="489" x="258" y="48" width="9" height="15" xoffset="1" yoffset="0" xadvance="9" page="0" chnl="15" />
+ <char id="490" x="329" y="16" width="11" height="15" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="491" x="422" y="103" width="9" height="12" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="492" x="12" y="0" width="11" height="17" xoffset="1" yoffset="1" xadvance="12" page="0" chnl="15" />
+ <char id="493" x="244" y="64" width="9" height="14" xoffset="1" yoffset="4" xadvance="10" page="0" chnl="15" />
+ <char id="494" x="0" y="0" width="11" height="18" xoffset="0" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="495" x="238" y="48" width="9" height="15" xoffset="0" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="496" x="228" y="48" width="9" height="15" xoffset="-2" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="497" x="346" y="64" width="22" height="12" xoffset="1" yoffset="3" xadvance="21" page="0" chnl="15" />
+ <char id="498" x="391" y="64" width="19" height="12" xoffset="1" yoffset="3" xadvance="20" page="0" chnl="15" />
+ <char id="499" x="470" y="64" width="17" height="12" xoffset="1" yoffset="3" xadvance="18" page="0" chnl="15" />
+ <char id="500" x="245" y="16" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="501" x="44" y="50" width="10" height="15" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="502" x="0" y="83" width="16" height="12" xoffset="1" yoffset="3" xadvance="17" page="0" chnl="15" />
+ <char id="503" x="209" y="16" width="11" height="15" xoffset="0" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="504" x="197" y="16" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="505" x="209" y="105" width="10" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="506" x="60" y="0" width="12" height="16" xoffset="-1" yoffset="-1" xadvance="12" page="0" chnl="15" />
+ <char id="507" x="107" y="0" width="9" height="16" xoffset="1" yoffset="-1" xadvance="9" page="0" chnl="15" />
+ <char id="508" x="146" y="0" width="18" height="15" xoffset="-1" yoffset="0" xadvance="16" page="0" chnl="15" />
+ <char id="509" x="240" y="79" width="13" height="12" xoffset="1" yoffset="3" xadvance="14" page="0" chnl="15" />
+ <char id="510" x="46" y="0" width="13" height="16" xoffset="0" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="511" x="295" y="64" width="10" height="13" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="512" x="477" y="0" width="12" height="15" xoffset="-1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="513" x="479" y="116" width="8" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="514" x="39" y="18" width="12" height="15" xoffset="-1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="515" x="425" y="116" width="8" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="516" x="137" y="16" width="11" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="517" x="416" y="116" width="8" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="518" x="77" y="17" width="11" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="519" x="407" y="116" width="8" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="520" x="502" y="48" width="6" height="15" xoffset="1" yoffset="0" xadvance="5" page="0" chnl="15" />
+ <char id="521" x="277" y="131" width="6" height="12" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="522" x="439" y="48" width="6" height="15" xoffset="1" yoffset="0" xadvance="5" page="0" chnl="15" />
+ <char id="523" x="506" y="64" width="5" height="12" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="524" x="257" y="16" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="525" x="20" y="122" width="9" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="526" x="204" y="32" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="527" x="170" y="118" width="9" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="528" x="281" y="16" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="529" x="195" y="131" width="7" height="12" xoffset="1" yoffset="3" xadvance="6" page="0" chnl="15" />
+ <char id="530" x="293" y="16" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="531" x="179" y="131" width="7" height="12" xoffset="1" yoffset="3" xadvance="6" page="0" chnl="15" />
+ <char id="532" x="317" y="16" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="533" x="286" y="105" width="10" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="534" x="341" y="16" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="535" x="319" y="104" width="10" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="536" x="85" y="0" width="10" height="16" xoffset="1" yoffset="2" xadvance="11" page="0" chnl="15" />
+ <char id="537" x="337" y="64" width="8" height="13" xoffset="1" yoffset="5" xadvance="9" page="0" chnl="15" />
+ <char id="538" x="36" y="0" width="9" height="17" xoffset="2" yoffset="1" xadvance="10" page="0" chnl="15" />
+ <char id="539" x="117" y="0" width="5" height="16" xoffset="1" yoffset="2" xadvance="5" page="0" chnl="15" />
+ <char id="540" x="308" y="48" width="9" height="15" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="541" x="0" y="122" width="9" height="12" xoffset="-1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="542" x="365" y="16" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="543" x="318" y="48" width="9" height="15" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="544" x="389" y="16" width="11" height="15" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="545" x="52" y="17" width="12" height="15" xoffset="1" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="546" x="486" y="90" width="10" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="547" x="497" y="90" width="10" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="548" x="464" y="0" width="12" height="15" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="549" x="120" y="119" width="9" height="12" xoffset="0" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="550" x="451" y="0" width="12" height="15" xoffset="-1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="551" x="126" y="132" width="8" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="552" x="401" y="16" width="11" height="15" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="553" x="144" y="132" width="8" height="12" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="554" x="73" y="0" width="11" height="16" xoffset="1" yoffset="-1" xadvance="12" page="0" chnl="15" />
+ <char id="555" x="278" y="48" width="9" height="15" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="556" x="24" y="0" width="11" height="17" xoffset="1" yoffset="-2" xadvance="12" page="0" chnl="15" />
+ <char id="557" x="298" y="48" width="9" height="15" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="558" x="413" y="16" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="559" x="50" y="122" width="9" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="560" x="425" y="16" width="11" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="561" x="288" y="48" width="9" height="15" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="562" x="200" y="64" width="11" height="14" xoffset="1" yoffset="1" xadvance="10" page="0" chnl="15" />
+ <char id="563" x="188" y="64" width="11" height="14" xoffset="0" yoffset="4" xadvance="9" page="0" chnl="15" />
+ <char id="564" x="416" y="48" width="7" height="15" xoffset="0" yoffset="3" xadvance="7" page="0" chnl="15" />
+ <char id="565" x="217" y="92" width="11" height="12" xoffset="1" yoffset="6" xadvance="13" page="0" chnl="15" />
+ <char id="566" x="219" y="131" width="7" height="12" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="567" x="187" y="131" width="7" height="12" xoffset="-2" yoffset="6" xadvance="4" page="0" chnl="15" />
+ <char id="568" x="81" y="80" width="14" height="12" xoffset="1" yoffset="3" xadvance="15" page="0" chnl="15" />
+ <char id="569" x="226" y="79" width="13" height="12" xoffset="1" yoffset="6" xadvance="15" page="0" chnl="15" />
+ <char id="570" x="268" y="64" width="14" height="13" xoffset="-1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="571" x="265" y="92" width="11" height="12" xoffset="2" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="572" x="318" y="0" width="13" height="15" xoffset="-1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="573" x="190" y="118" width="9" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="574" x="176" y="64" width="11" height="14" xoffset="0" yoffset="2" xadvance="10" page="0" chnl="15" />
+ <char id="575" x="272" y="118" width="8" height="12" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="576" x="160" y="118" width="9" height="12" xoffset="0" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="577" x="290" y="118" width="8" height="12" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="578" x="244" y="144" width="7" height="9" xoffset="1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="579" x="423" y="77" width="12" height="12" xoffset="0" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="580" x="436" y="77" width="12" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="581" x="325" y="91" width="11" height="12" xoffset="-1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="582" x="212" y="64" width="10" height="14" xoffset="1" yoffset="2" xadvance="11" page="0" chnl="15" />
+ <char id="583" x="488" y="32" width="10" height="15" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="584" x="275" y="105" width="10" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="585" x="347" y="48" width="8" height="15" xoffset="-2" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="586" x="290" y="0" width="13" height="15" xoffset="1" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="587" x="308" y="104" width="10" height="12" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="588" x="0" y="96" width="12" height="12" xoffset="0" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="589" x="218" y="144" width="8" height="9" xoffset="0" yoffset="6" xadvance="6" page="0" chnl="15" />
+ <char id="590" x="397" y="90" width="11" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="591" x="341" y="104" width="10" height="12" xoffset="0" yoffset="6" xadvance="9" page="0" chnl="15" />
+ </chars>
+ <kernings count="65">
+ <kerning first="32" second="65" amount="-1" />
+ <kerning first="49" second="49" amount="-1" />
+ <kerning first="65" second="32" amount="-1" />
+ <kerning first="65" second="84" amount="-1" />
+ <kerning first="65" second="86" amount="-1" />
+ <kerning first="65" second="87" amount="-1" />
+ <kerning first="65" second="89" amount="-1" />
+ <kerning first="70" second="44" amount="-2" />
+ <kerning first="70" second="46" amount="-2" />
+ <kerning first="70" second="65" amount="-1" />
+ <kerning first="76" second="84" amount="-1" />
+ <kerning first="76" second="86" amount="-1" />
+ <kerning first="76" second="87" amount="-1" />
+ <kerning first="76" second="89" amount="-1" />
+ <kerning first="80" second="32" amount="-1" />
+ <kerning first="80" second="44" amount="-2" />
+ <kerning first="80" second="46" amount="-2" />
+ <kerning first="80" second="65" amount="-1" />
+ <kerning first="84" second="44" amount="-1" />
+ <kerning first="84" second="45" amount="-1" />
+ <kerning first="84" second="46" amount="-1" />
+ <kerning first="84" second="58" amount="-1" />
+ <kerning first="84" second="65" amount="-1" />
+ <kerning first="84" second="97" amount="-1" />
+ <kerning first="84" second="99" amount="-1" />
+ <kerning first="84" second="101" amount="-1" />
+ <kerning first="84" second="111" amount="-1" />
+ <kerning first="84" second="115" amount="-1" />
+ <kerning first="84" second="119" amount="-1" />
+ <kerning first="84" second="121" amount="-1" />
+ <kerning first="86" second="44" amount="-1" />
+ <kerning first="86" second="45" amount="-1" />
+ <kerning first="86" second="46" amount="-1" />
+ <kerning first="86" second="58" amount="-1" />
+ <kerning first="86" second="65" amount="-1" />
+ <kerning first="86" second="97" amount="-1" />
+ <kerning first="86" second="101" amount="-1" />
+ <kerning first="86" second="105" amount="-1" />
+ <kerning first="86" second="111" amount="-1" />
+ <kerning first="87" second="44" amount="-1" />
+ <kerning first="87" second="45" amount="-1" />
+ <kerning first="87" second="46" amount="-1" />
+ <kerning first="87" second="58" amount="-1" />
+ <kerning first="87" second="65" amount="-1" />
+ <kerning first="89" second="44" amount="-1" />
+ <kerning first="89" second="45" amount="-1" />
+ <kerning first="89" second="46" amount="-1" />
+ <kerning first="89" second="58" amount="-1" />
+ <kerning first="89" second="65" amount="-1" />
+ <kerning first="89" second="97" amount="-1" />
+ <kerning first="89" second="101" amount="-1" />
+ <kerning first="89" second="105" amount="-1" />
+ <kerning first="89" second="111" amount="-1" />
+ <kerning first="89" second="112" amount="-1" />
+ <kerning first="89" second="113" amount="-1" />
+ <kerning first="89" second="117" amount="-1" />
+ <kerning first="89" second="118" amount="-1" />
+ <kerning first="114" second="44" amount="-1" />
+ <kerning first="114" second="46" amount="-1" />
+ <kerning first="118" second="44" amount="-1" />
+ <kerning first="118" second="46" amount="-1" />
+ <kerning first="119" second="44" amount="-1" />
+ <kerning first="119" second="46" amount="-1" />
+ <kerning first="121" second="44" amount="-1" />
+ <kerning first="121" second="46" amount="-1" />
+ </kernings>
+</font>
diff --git a/ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-18-bold-italic_0.png b/ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-18-bold-italic_0.png Binary files differnew file mode 100644 index 0000000..0d653ba --- /dev/null +++ b/ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-18-bold-italic_0.png diff --git a/ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-18-bold.fnt b/ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-18-bold.fnt new file mode 100644 index 0000000..6e6e423 --- /dev/null +++ b/ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-18-bold.fnt @@ -0,0 +1,610 @@ +<?xml version="1.0"?>
+<font>
+ <info face="Arial" size="18" bold="1" italic="0" charset="" unicode="1" stretchH="100" smooth="1" aa="1" padding="0,0,0,0" spacing="1,1" outline="0"/>
+ <common lineHeight="18" base="14" scaleW="256" scaleH="256" pages="1" packed="0" alphaChnl="0" redChnl="4" greenChnl="4" blueChnl="4"/>
+ <pages>
+ <page id="0" file="arial-18-bold_0.png" />
+ </pages>
+ <chars count="527">
+ <char id="32" x="22" y="16" width="1" height="1" xoffset="0" yoffset="14" xadvance="4" page="0" chnl="15" />
+ <char id="33" x="73" y="218" width="2" height="11" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="34" x="221" y="222" width="6" height="4" xoffset="1" yoffset="3" xadvance="7" page="0" chnl="15" />
+ <char id="35" x="24" y="195" width="7" height="11" xoffset="0" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="36" x="110" y="106" width="7" height="13" xoffset="0" yoffset="2" xadvance="8" page="0" chnl="15" />
+ <char id="37" x="0" y="135" width="12" height="11" xoffset="0" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="38" x="55" y="146" width="10" height="11" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="39" x="239" y="222" width="2" height="4" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="40" x="247" y="90" width="4" height="14" xoffset="1" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="41" x="242" y="90" width="4" height="14" xoffset="0" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="42" x="228" y="222" width="5" height="4" xoffset="0" yoffset="3" xadvance="6" page="0" chnl="15" />
+ <char id="43" x="239" y="213" width="8" height="8" xoffset="0" yoffset="4" xadvance="9" page="0" chnl="15" />
+ <char id="44" x="242" y="222" width="2" height="4" xoffset="1" yoffset="12" xadvance="4" page="0" chnl="15" />
+ <char id="45" x="29" y="240" width="4" height="2" xoffset="1" yoffset="9" xadvance="5" page="0" chnl="15" />
+ <char id="46" x="50" y="240" width="2" height="2" xoffset="1" yoffset="12" xadvance="4" page="0" chnl="15" />
+ <char id="47" x="35" y="219" width="4" height="11" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="48" x="40" y="195" width="7" height="11" xoffset="0" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="49" x="221" y="201" width="5" height="11" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="50" x="56" y="195" width="7" height="11" xoffset="0" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="51" x="64" y="194" width="7" height="11" xoffset="0" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="52" x="72" y="194" width="7" height="11" xoffset="0" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="53" x="80" y="194" width="7" height="11" xoffset="0" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="54" x="88" y="192" width="7" height="11" xoffset="0" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="55" x="104" y="192" width="7" height="11" xoffset="0" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="56" x="112" y="192" width="7" height="11" xoffset="0" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="57" x="120" y="192" width="7" height="11" xoffset="0" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="58" x="138" y="227" width="2" height="8" xoffset="1" yoffset="6" xadvance="4" page="0" chnl="15" />
+ <char id="59" x="139" y="216" width="2" height="10" xoffset="1" yoffset="6" xadvance="4" page="0" chnl="15" />
+ <char id="60" x="17" y="231" width="7" height="8" xoffset="0" yoffset="5" xadvance="9" page="0" chnl="15" />
+ <char id="61" x="203" y="223" width="8" height="5" xoffset="0" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="62" x="57" y="231" width="7" height="8" xoffset="0" yoffset="5" xadvance="9" page="0" chnl="15" />
+ <char id="63" x="72" y="170" width="8" height="11" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="64" x="20" y="0" width="14" height="15" xoffset="0" yoffset="3" xadvance="15" page="0" chnl="15" />
+ <char id="65" x="62" y="134" width="11" height="11" xoffset="-1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="66" x="214" y="141" width="9" height="11" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="67" x="204" y="141" width="9" height="11" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="68" x="194" y="141" width="9" height="11" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="69" x="189" y="154" width="8" height="11" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="70" x="136" y="192" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="71" x="237" y="129" width="10" height="11" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="72" x="184" y="142" width="9" height="11" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="73" x="67" y="218" width="2" height="11" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="74" x="144" y="192" width="7" height="11" xoffset="0" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="75" x="226" y="129" width="10" height="11" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="76" x="160" y="192" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="77" x="98" y="132" width="11" height="11" xoffset="1" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="78" x="30" y="159" width="9" height="11" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="79" x="99" y="144" width="10" height="11" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="80" x="243" y="153" width="8" height="11" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="81" x="158" y="105" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="82" x="77" y="144" width="10" height="11" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="83" x="99" y="156" width="8" height="11" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="84" x="135" y="156" width="8" height="11" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="85" x="174" y="142" width="9" height="11" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="86" x="224" y="141" width="9" height="11" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="87" x="108" y="120" width="13" height="11" xoffset="0" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="88" x="44" y="147" width="10" height="11" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="89" x="66" y="146" width="10" height="11" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="90" x="162" y="155" width="8" height="11" xoffset="0" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="91" x="15" y="108" width="4" height="14" xoffset="1" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="92" x="30" y="219" width="4" height="11" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="93" x="10" y="108" width="4" height="14" xoffset="0" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="94" x="157" y="225" width="8" height="6" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="95" x="5" y="240" width="8" height="2" xoffset="0" yoffset="15" xadvance="8" page="0" chnl="15" />
+ <char id="96" x="39" y="240" width="3" height="2" xoffset="0" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="97" x="25" y="231" width="7" height="8" xoffset="1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="98" x="176" y="191" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="99" x="101" y="227" width="6" height="8" xoffset="1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="100" x="184" y="190" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="101" x="41" y="231" width="7" height="8" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="102" x="72" y="206" width="6" height="11" xoffset="0" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="103" x="192" y="190" width="7" height="11" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="104" x="200" y="190" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="105" x="64" y="218" width="2" height="11" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="106" x="5" y="108" width="4" height="14" xoffset="-1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="107" x="224" y="189" width="7" height="11" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="108" x="253" y="117" width="2" height="11" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="109" x="179" y="215" width="10" height="8" xoffset="1" yoffset="6" xadvance="12" page="0" chnl="15" />
+ <char id="110" x="49" y="231" width="7" height="8" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="111" x="65" y="230" width="7" height="8" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="112" x="232" y="189" width="7" height="11" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="113" x="240" y="189" width="7" height="11" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="114" x="129" y="227" width="5" height="8" xoffset="1" yoffset="6" xadvance="6" page="0" chnl="15" />
+ <char id="115" x="108" y="227" width="6" height="8" xoffset="1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="116" x="127" y="216" width="5" height="10" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="117" x="33" y="231" width="7" height="8" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="118" x="201" y="214" width="9" height="8" xoffset="0" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="119" x="155" y="216" width="11" height="8" xoffset="0" yoffset="6" xadvance="11" page="0" chnl="15" />
+ <char id="120" x="230" y="213" width="8" height="8" xoffset="0" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="121" x="248" y="189" width="7" height="11" xoffset="0" yoffset="6" xadvance="7" page="0" chnl="15" />
+ <char id="122" x="94" y="227" width="6" height="8" xoffset="1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="123" x="224" y="90" width="5" height="14" xoffset="1" yoffset="3" xadvance="6" page="0" chnl="15" />
+ <char id="124" x="31" y="108" width="2" height="14" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="125" x="236" y="90" width="5" height="14" xoffset="0" yoffset="3" xadvance="6" page="0" chnl="15" />
+ <char id="126" x="245" y="222" width="8" height="3" xoffset="0" yoffset="7" xadvance="9" page="0" chnl="15" />
+ <char id="160" x="20" y="16" width="1" height="1" xoffset="0" yoffset="14" xadvance="4" page="0" chnl="15" />
+ <char id="161" x="79" y="218" width="2" height="11" xoffset="1" yoffset="6" xadvance="4" page="0" chnl="15" />
+ <char id="162" x="236" y="75" width="7" height="14" xoffset="0" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="163" x="45" y="171" width="8" height="11" xoffset="0" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="164" x="221" y="213" width="8" height="8" xoffset="0" yoffset="5" xadvance="8" page="0" chnl="15" />
+ <char id="165" x="36" y="171" width="8" height="11" xoffset="0" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="166" x="253" y="30" width="2" height="14" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="167" x="112" y="91" width="7" height="14" xoffset="0" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="168" x="23" y="240" width="5" height="2" xoffset="0" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="169" x="74" y="132" width="11" height="11" xoffset="0" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="170" x="174" y="225" width="5" height="6" xoffset="0" yoffset="3" xadvance="6" page="0" chnl="15" />
+ <char id="171" x="141" y="227" width="7" height="7" xoffset="0" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="172" x="212" y="222" width="8" height="5" xoffset="0" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="173" x="34" y="240" width="4" height="2" xoffset="1" yoffset="9" xadvance="5" page="0" chnl="15" />
+ <char id="174" x="122" y="132" width="11" height="11" xoffset="0" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="175" x="14" y="240" width="8" height="2" xoffset="0" yoffset="1" xadvance="8" page="0" chnl="15" />
+ <char id="176" x="234" y="222" width="4" height="4" xoffset="1" yoffset="3" xadvance="6" page="0" chnl="15" />
+ <char id="177" x="171" y="154" width="8" height="11" xoffset="0" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="178" x="186" y="224" width="5" height="6" xoffset="0" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="179" x="180" y="224" width="5" height="6" xoffset="0" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="180" x="43" y="240" width="3" height="2" xoffset="1" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="181" x="0" y="207" width="7" height="11" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="182" x="110" y="60" width="9" height="14" xoffset="0" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="183" x="47" y="240" width="2" height="2" xoffset="1" yoffset="8" xadvance="5" page="0" chnl="15" />
+ <char id="184" x="0" y="240" width="4" height="3" xoffset="0" yoffset="14" xadvance="5" page="0" chnl="15" />
+ <char id="185" x="198" y="223" width="4" height="6" xoffset="0" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="186" x="192" y="223" width="5" height="6" xoffset="0" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="187" x="149" y="225" width="7" height="7" xoffset="1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="188" x="94" y="120" width="13" height="11" xoffset="0" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="189" x="227" y="117" width="12" height="11" xoffset="0" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="190" x="122" y="120" width="13" height="11" xoffset="0" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="191" x="8" y="207" width="7" height="11" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="192" x="228" y="0" width="11" height="14" xoffset="-1" yoffset="0" xadvance="9" page="0" chnl="15" />
+ <char id="193" x="12" y="18" width="11" height="14" xoffset="-1" yoffset="0" xadvance="9" page="0" chnl="15" />
+ <char id="194" x="132" y="15" width="11" height="14" xoffset="-1" yoffset="0" xadvance="9" page="0" chnl="15" />
+ <char id="195" x="216" y="0" width="11" height="14" xoffset="-1" yoffset="0" xadvance="9" page="0" chnl="15" />
+ <char id="196" x="84" y="16" width="11" height="14" xoffset="-1" yoffset="0" xadvance="9" page="0" chnl="15" />
+ <char id="197" x="72" y="16" width="11" height="14" xoffset="-1" yoffset="0" xadvance="9" page="0" chnl="15" />
+ <char id="198" x="48" y="122" width="15" height="11" xoffset="0" yoffset="3" xadvance="16" page="0" chnl="15" />
+ <char id="199" x="100" y="61" width="9" height="14" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="200" x="210" y="60" width="8" height="14" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="201" x="192" y="60" width="8" height="14" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="202" x="183" y="60" width="8" height="14" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="203" x="174" y="60" width="8" height="14" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="204" x="20" y="108" width="3" height="14" xoffset="0" yoffset="0" xadvance="4" page="0" chnl="15" />
+ <char id="205" x="252" y="0" width="3" height="14" xoffset="1" yoffset="0" xadvance="4" page="0" chnl="15" />
+ <char id="206" x="194" y="90" width="5" height="14" xoffset="0" yoffset="0" xadvance="4" page="0" chnl="15" />
+ <char id="207" x="200" y="90" width="5" height="14" xoffset="0" yoffset="0" xadvance="4" page="0" chnl="15" />
+ <char id="208" x="132" y="144" width="10" height="11" xoffset="0" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="209" x="125" y="45" width="9" height="14" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="210" x="66" y="31" width="10" height="14" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="211" x="22" y="33" width="10" height="14" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="212" x="11" y="33" width="10" height="14" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="213" x="213" y="15" width="10" height="14" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="214" x="242" y="30" width="10" height="14" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="215" x="166" y="225" width="7" height="6" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="216" x="34" y="108" width="12" height="13" xoffset="0" yoffset="2" xadvance="12" page="0" chnl="15" />
+ <char id="217" x="50" y="61" width="9" height="14" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="218" x="195" y="45" width="9" height="14" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="219" x="215" y="45" width="9" height="14" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="220" x="70" y="61" width="9" height="14" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="221" x="176" y="30" width="10" height="14" xoffset="0" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="222" x="18" y="171" width="8" height="11" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="223" x="16" y="207" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="224" x="24" y="207" width="7" height="11" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="225" x="32" y="207" width="7" height="11" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="226" x="40" y="207" width="7" height="11" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="227" x="48" y="207" width="7" height="11" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="228" x="56" y="207" width="7" height="11" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="229" x="126" y="105" width="7" height="13" xoffset="1" yoffset="1" xadvance="8" page="0" chnl="15" />
+ <char id="230" x="167" y="216" width="11" height="8" xoffset="1" yoffset="6" xadvance="13" page="0" chnl="15" />
+ <char id="231" x="135" y="204" width="6" height="11" xoffset="1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="232" x="64" y="206" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="233" x="248" y="129" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="234" x="90" y="168" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="235" x="98" y="168" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="236" x="60" y="219" width="3" height="11" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="237" x="252" y="153" width="3" height="11" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="238" x="6" y="219" width="5" height="11" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="239" x="18" y="219" width="5" height="11" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="240" x="106" y="168" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="241" x="122" y="168" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="242" x="130" y="168" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="243" x="138" y="168" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="244" x="146" y="168" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="245" x="154" y="168" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="246" x="162" y="167" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="247" x="0" y="231" width="8" height="8" xoffset="0" yoffset="4" xadvance="8" page="0" chnl="15" />
+ <char id="248" x="112" y="216" width="7" height="10" xoffset="1" yoffset="5" xadvance="9" page="0" chnl="15" />
+ <char id="249" x="170" y="167" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="250" x="178" y="166" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="251" x="186" y="166" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="252" x="194" y="166" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="253" x="40" y="93" width="7" height="14" xoffset="0" yoffset="3" xadvance="7" page="0" chnl="15" />
+ <char id="254" x="228" y="75" width="7" height="14" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="255" x="244" y="75" width="7" height="14" xoffset="0" yoffset="3" xadvance="7" page="0" chnl="15" />
+ <char id="256" x="0" y="18" width="11" height="14" xoffset="-1" yoffset="0" xadvance="9" page="0" chnl="15" />
+ <char id="257" x="202" y="165" width="7" height="11" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="258" x="240" y="0" width="11" height="14" xoffset="-1" yoffset="0" xadvance="9" page="0" chnl="15" />
+ <char id="259" x="210" y="165" width="7" height="11" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="260" x="144" y="15" width="11" height="14" xoffset="-1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="261" x="218" y="165" width="7" height="11" xoffset="1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="262" x="90" y="61" width="9" height="14" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="263" x="184" y="202" width="6" height="11" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="264" x="80" y="61" width="9" height="14" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="265" x="79" y="206" width="6" height="11" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="266" x="165" y="45" width="9" height="14" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="267" x="100" y="204" width="6" height="11" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="268" x="245" y="45" width="9" height="14" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="269" x="107" y="204" width="6" height="11" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="270" x="235" y="45" width="9" height="14" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="271" x="33" y="147" width="10" height="11" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="272" x="110" y="144" width="10" height="11" xoffset="0" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="273" x="108" y="156" width="8" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="274" x="129" y="60" width="8" height="14" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="275" x="234" y="165" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="276" x="138" y="60" width="8" height="14" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="277" x="242" y="165" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="278" x="219" y="60" width="8" height="14" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="279" x="0" y="183" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="280" x="147" y="60" width="8" height="14" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="281" x="8" y="183" width="7" height="11" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="282" x="156" y="60" width="8" height="14" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="283" x="16" y="183" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="284" x="165" y="30" width="10" height="14" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="285" x="0" y="93" width="7" height="14" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="286" x="99" y="30" width="10" height="14" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="287" x="148" y="75" width="7" height="14" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="288" x="110" y="30" width="10" height="14" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="289" x="48" y="91" width="7" height="14" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="290" x="121" y="30" width="10" height="14" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="291" x="78" y="0" width="7" height="15" xoffset="1" yoffset="2" xadvance="9" page="0" chnl="15" />
+ <char id="292" x="155" y="45" width="9" height="14" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="293" x="220" y="75" width="7" height="14" xoffset="1" yoffset="0" xadvance="9" page="0" chnl="15" />
+ <char id="294" x="158" y="130" width="11" height="11" xoffset="0" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="295" x="144" y="156" width="8" height="11" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="296" x="212" y="90" width="5" height="14" xoffset="0" yoffset="0" xadvance="4" page="0" chnl="15" />
+ <char id="297" x="197" y="202" width="5" height="11" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="298" x="188" y="90" width="5" height="14" xoffset="0" yoffset="0" xadvance="4" page="0" chnl="15" />
+ <char id="299" x="239" y="201" width="5" height="11" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="300" x="170" y="90" width="5" height="14" xoffset="0" yoffset="0" xadvance="4" page="0" chnl="15" />
+ <char id="301" x="233" y="201" width="5" height="11" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="302" x="24" y="108" width="3" height="14" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="303" x="252" y="75" width="3" height="14" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="304" x="28" y="108" width="2" height="14" xoffset="1" yoffset="0" xadvance="4" page="0" chnl="15" />
+ <char id="305" x="135" y="227" width="2" height="8" xoffset="1" yoffset="6" xadvance="4" page="0" chnl="15" />
+ <char id="306" x="215" y="129" width="10" height="11" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="307" x="163" y="90" width="6" height="14" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="308" x="36" y="78" width="8" height="14" xoffset="0" yoffset="0" xadvance="8" page="0" chnl="15" />
+ <char id="309" x="128" y="90" width="6" height="14" xoffset="-1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="310" x="143" y="30" width="10" height="14" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="311" x="204" y="75" width="7" height="14" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="312" x="248" y="213" width="7" height="8" xoffset="1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="313" x="180" y="75" width="7" height="14" xoffset="1" yoffset="0" xadvance="9" page="0" chnl="15" />
+ <char id="314" x="252" y="90" width="3" height="14" xoffset="1" yoffset="0" xadvance="4" page="0" chnl="15" />
+ <char id="315" x="32" y="93" width="7" height="14" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="316" x="0" y="108" width="4" height="14" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="317" x="54" y="171" width="8" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="318" x="191" y="202" width="5" height="11" xoffset="1" yoffset="3" xadvance="6" page="0" chnl="15" />
+ <char id="319" x="24" y="183" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="320" x="0" y="219" width="5" height="11" xoffset="1" yoffset="3" xadvance="7" page="0" chnl="15" />
+ <char id="321" x="0" y="171" width="8" height="11" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="322" x="40" y="219" width="4" height="11" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="323" x="246" y="15" width="9" height="14" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="324" x="32" y="183" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="325" x="20" y="63" width="9" height="14" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="326" x="48" y="183" width="7" height="11" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="327" x="10" y="63" width="9" height="14" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="328" x="64" y="182" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="329" x="88" y="144" width="10" height="11" xoffset="0" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="330" x="244" y="141" width="9" height="11" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="331" x="80" y="182" width="7" height="11" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="332" x="0" y="33" width="10" height="14" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="333" x="96" y="180" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="334" x="132" y="30" width="10" height="14" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="335" x="104" y="180" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="336" x="198" y="30" width="10" height="14" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="337" x="112" y="180" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="338" x="64" y="120" width="14" height="11" xoffset="1" yoffset="3" xadvance="16" page="0" chnl="15" />
+ <char id="339" x="142" y="216" width="12" height="8" xoffset="1" yoffset="6" xadvance="14" page="0" chnl="15" />
+ <char id="340" x="209" y="30" width="10" height="14" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="341" x="215" y="201" width="5" height="11" xoffset="1" yoffset="3" xadvance="6" page="0" chnl="15" />
+ <char id="342" x="154" y="30" width="10" height="14" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="343" x="250" y="165" width="5" height="11" xoffset="1" yoffset="6" xadvance="6" page="0" chnl="15" />
+ <char id="344" x="220" y="30" width="10" height="14" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="345" x="209" y="201" width="5" height="11" xoffset="1" yoffset="3" xadvance="6" page="0" chnl="15" />
+ <char id="346" x="201" y="60" width="8" height="14" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="347" x="86" y="206" width="6" height="11" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="348" x="228" y="60" width="8" height="14" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="349" x="170" y="203" width="6" height="11" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="350" x="246" y="60" width="8" height="14" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="351" x="156" y="204" width="6" height="11" xoffset="1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="352" x="45" y="76" width="8" height="14" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="353" x="142" y="204" width="6" height="11" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="354" x="237" y="60" width="8" height="14" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="355" x="134" y="105" width="5" height="13" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="356" x="18" y="78" width="8" height="14" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="357" x="234" y="153" width="8" height="11" xoffset="0" yoffset="3" xadvance="7" page="0" chnl="15" />
+ <char id="358" x="9" y="171" width="8" height="11" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="359" x="133" y="216" width="5" height="10" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="360" x="135" y="45" width="9" height="14" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="361" x="136" y="180" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="362" x="75" y="46" width="9" height="14" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="363" x="144" y="180" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="364" x="30" y="63" width="9" height="14" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="365" x="152" y="180" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="366" x="185" y="45" width="9" height="14" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="367" x="118" y="106" width="7" height="13" xoffset="1" yoffset="1" xadvance="9" page="0" chnl="15" />
+ <char id="368" x="175" y="45" width="9" height="14" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="369" x="168" y="179" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="370" x="105" y="45" width="9" height="14" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="371" x="184" y="178" width="7" height="11" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="372" x="151" y="0" width="13" height="14" xoffset="0" yoffset="0" xadvance="13" page="0" chnl="15" />
+ <char id="373" x="134" y="132" width="11" height="11" xoffset="0" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="374" x="231" y="30" width="10" height="14" xoffset="0" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="375" x="72" y="91" width="7" height="14" xoffset="0" yoffset="3" xadvance="7" page="0" chnl="15" />
+ <char id="376" x="187" y="30" width="10" height="14" xoffset="0" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="377" x="27" y="78" width="8" height="14" xoffset="0" yoffset="0" xadvance="8" page="0" chnl="15" />
+ <char id="378" x="149" y="204" width="6" height="11" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="379" x="9" y="78" width="8" height="14" xoffset="0" yoffset="0" xadvance="8" page="0" chnl="15" />
+ <char id="380" x="163" y="204" width="6" height="11" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="381" x="0" y="78" width="8" height="14" xoffset="0" yoffset="0" xadvance="8" page="0" chnl="15" />
+ <char id="382" x="177" y="203" width="6" height="11" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="383" x="45" y="219" width="4" height="11" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="384" x="198" y="153" width="8" height="11" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="385" x="214" y="117" width="12" height="11" xoffset="0" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="386" x="50" y="159" width="9" height="11" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="387" x="192" y="178" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="388" x="182" y="130" width="10" height="11" xoffset="0" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="389" x="216" y="153" width="8" height="11" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="390" x="70" y="158" width="9" height="11" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="391" x="60" y="106" width="11" height="13" xoffset="1" yoffset="1" xadvance="11" page="0" chnl="15" />
+ <char id="392" x="103" y="216" width="8" height="10" xoffset="1" yoffset="4" xadvance="8" page="0" chnl="15" />
+ <char id="393" x="204" y="129" width="10" height="11" xoffset="0" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="394" x="201" y="117" width="12" height="11" xoffset="0" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="395" x="80" y="156" width="9" height="11" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="396" x="200" y="178" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="397" x="208" y="177" width="7" height="11" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="398" x="180" y="154" width="8" height="11" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="399" x="154" y="143" width="9" height="11" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="400" x="153" y="156" width="8" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="401" x="0" y="63" width="9" height="14" xoffset="-1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="402" x="90" y="76" width="8" height="14" xoffset="0" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="403" x="47" y="108" width="12" height="13" xoffset="1" yoffset="1" xadvance="12" page="0" chnl="15" />
+ <char id="404" x="165" y="0" width="12" height="14" xoffset="-1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="405" x="240" y="117" width="12" height="11" xoffset="1" yoffset="3" xadvance="14" page="0" chnl="15" />
+ <char id="406" x="82" y="218" width="2" height="11" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="407" x="50" y="219" width="4" height="11" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="408" x="0" y="147" width="10" height="11" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="409" x="216" y="177" width="7" height="11" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="410" x="251" y="201" width="4" height="11" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="411" x="11" y="147" width="10" height="11" xoffset="-1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="412" x="188" y="117" width="12" height="11" xoffset="1" yoffset="3" xadvance="15" page="0" chnl="15" />
+ <char id="413" x="120" y="15" width="11" height="14" xoffset="-1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="414" x="224" y="177" width="7" height="11" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="415" x="22" y="147" width="10" height="11" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="416" x="136" y="119" width="12" height="11" xoffset="1" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="417" x="211" y="213" width="9" height="8" xoffset="1" yoffset="6" xadvance="11" page="0" chnl="15" />
+ <char id="418" x="96" y="15" width="11" height="14" xoffset="1" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="419" x="164" y="142" width="9" height="11" xoffset="1" yoffset="6" xadvance="11" page="0" chnl="15" />
+ <char id="420" x="110" y="132" width="11" height="11" xoffset="0" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="421" x="188" y="75" width="7" height="14" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="422" x="82" y="106" width="9" height="13" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="423" x="90" y="156" width="8" height="11" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="424" x="80" y="230" width="6" height="8" xoffset="1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="425" x="232" y="177" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="426" x="142" y="90" width="6" height="14" xoffset="0" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="427" x="140" y="105" width="5" height="13" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="428" x="234" y="141" width="9" height="11" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="429" x="227" y="201" width="5" height="11" xoffset="0" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="430" x="165" y="60" width="8" height="14" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="431" x="38" y="135" width="11" height="11" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="432" x="190" y="214" width="10" height="8" xoffset="1" yoffset="6" xadvance="11" page="0" chnl="15" />
+ <char id="433" x="121" y="144" width="10" height="11" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="434" x="0" y="159" width="9" height="11" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="435" x="13" y="135" width="12" height="11" xoffset="0" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="436" x="55" y="31" width="10" height="14" xoffset="0" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="437" x="10" y="159" width="9" height="11" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="438" x="87" y="229" width="6" height="8" xoffset="1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="439" x="120" y="60" width="8" height="14" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="440" x="99" y="76" width="8" height="14" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="441" x="240" y="177" width="7" height="11" xoffset="1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="442" x="117" y="156" width="8" height="11" xoffset="0" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="443" x="248" y="177" width="7" height="11" xoffset="0" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="444" x="121" y="204" width="6" height="11" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="445" x="115" y="227" width="6" height="8" xoffset="0" yoffset="6" xadvance="7" page="0" chnl="15" />
+ <char id="446" x="85" y="218" width="8" height="10" xoffset="0" yoffset="4" xadvance="9" page="0" chnl="15" />
+ <char id="447" x="16" y="195" width="7" height="11" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="448" x="70" y="218" width="2" height="11" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="449" x="12" y="219" width="5" height="11" xoffset="1" yoffset="3" xadvance="7" page="0" chnl="15" />
+ <char id="450" x="126" y="156" width="8" height="11" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="451" x="76" y="218" width="2" height="11" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="452" x="86" y="0" width="18" height="14" xoffset="1" yoffset="0" xadvance="20" page="0" chnl="15" />
+ <char id="453" x="221" y="105" width="16" height="11" xoffset="1" yoffset="3" xadvance="18" page="0" chnl="15" />
+ <char id="454" x="0" y="123" width="15" height="11" xoffset="1" yoffset="3" xadvance="17" page="0" chnl="15" />
+ <char id="455" x="16" y="123" width="15" height="11" xoffset="1" yoffset="3" xadvance="18" page="0" chnl="15" />
+ <char id="456" x="24" y="16" width="11" height="14" xoffset="1" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="457" x="156" y="90" width="6" height="14" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="458" x="203" y="105" width="17" height="11" xoffset="1" yoffset="3" xadvance="19" page="0" chnl="15" />
+ <char id="459" x="137" y="0" width="13" height="14" xoffset="1" yoffset="3" xadvance="15" page="0" chnl="15" />
+ <char id="460" x="204" y="0" width="11" height="14" xoffset="1" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="461" x="156" y="15" width="11" height="14" xoffset="-1" yoffset="0" xadvance="9" page="0" chnl="15" />
+ <char id="462" x="128" y="192" width="7" height="11" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="463" x="218" y="90" width="5" height="14" xoffset="0" yoffset="0" xadvance="4" page="0" chnl="15" />
+ <char id="464" x="245" y="201" width="5" height="11" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="465" x="235" y="15" width="10" height="14" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="466" x="152" y="192" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="467" x="65" y="46" width="9" height="14" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="468" x="168" y="191" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="469" x="55" y="46" width="9" height="14" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="470" x="8" y="93" width="7" height="14" xoffset="1" yoffset="0" xadvance="9" page="0" chnl="15" />
+ <char id="471" x="225" y="45" width="9" height="14" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="472" x="172" y="75" width="7" height="14" xoffset="1" yoffset="0" xadvance="9" page="0" chnl="15" />
+ <char id="473" x="40" y="61" width="9" height="14" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="474" x="164" y="75" width="7" height="14" xoffset="1" yoffset="0" xadvance="9" page="0" chnl="15" />
+ <char id="475" x="60" y="61" width="9" height="14" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="476" x="140" y="75" width="7" height="14" xoffset="1" yoffset="0" xadvance="9" page="0" chnl="15" />
+ <char id="477" x="73" y="230" width="6" height="8" xoffset="1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="478" x="48" y="16" width="11" height="14" xoffset="-1" yoffset="0" xadvance="9" page="0" chnl="15" />
+ <char id="479" x="116" y="75" width="7" height="14" xoffset="1" yoffset="0" xadvance="8" page="0" chnl="15" />
+ <char id="480" x="108" y="15" width="11" height="14" xoffset="-1" yoffset="0" xadvance="9" page="0" chnl="15" />
+ <char id="481" x="56" y="91" width="7" height="14" xoffset="1" yoffset="0" xadvance="8" page="0" chnl="15" />
+ <char id="482" x="105" y="0" width="15" height="14" xoffset="0" yoffset="0" xadvance="16" page="0" chnl="15" />
+ <char id="483" x="50" y="134" width="11" height="11" xoffset="1" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="484" x="26" y="135" width="11" height="11" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="485" x="63" y="170" width="8" height="11" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="486" x="0" y="48" width="10" height="14" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="487" x="96" y="91" width="7" height="14" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="488" x="11" y="48" width="10" height="14" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="489" x="196" y="75" width="7" height="14" xoffset="1" yoffset="0" xadvance="8" page="0" chnl="15" />
+ <char id="490" x="22" y="48" width="10" height="14" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="491" x="114" y="168" width="7" height="11" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="492" x="0" y="0" width="10" height="17" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="493" x="88" y="91" width="7" height="14" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="494" x="11" y="0" width="8" height="17" xoffset="0" yoffset="0" xadvance="9" page="0" chnl="15" />
+ <char id="495" x="108" y="76" width="7" height="14" xoffset="0" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="496" x="182" y="90" width="5" height="14" xoffset="-1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="497" x="184" y="105" width="18" height="11" xoffset="1" yoffset="3" xadvance="20" page="0" chnl="15" />
+ <char id="498" x="238" y="105" width="16" height="11" xoffset="1" yoffset="3" xadvance="18" page="0" chnl="15" />
+ <char id="499" x="32" y="123" width="15" height="11" xoffset="1" yoffset="3" xadvance="17" page="0" chnl="15" />
+ <char id="500" x="33" y="46" width="10" height="14" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="501" x="124" y="75" width="7" height="14" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="502" x="79" y="120" width="14" height="11" xoffset="1" yoffset="3" xadvance="15" page="0" chnl="15" />
+ <char id="503" x="54" y="76" width="8" height="14" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="504" x="115" y="45" width="9" height="14" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="505" x="226" y="165" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="506" x="48" y="0" width="11" height="15" xoffset="-1" yoffset="-1" xadvance="9" page="0" chnl="15" />
+ <char id="507" x="156" y="75" width="7" height="14" xoffset="1" yoffset="0" xadvance="8" page="0" chnl="15" />
+ <char id="508" x="121" y="0" width="15" height="14" xoffset="0" yoffset="0" xadvance="16" page="0" chnl="15" />
+ <char id="509" x="170" y="130" width="11" height="11" xoffset="1" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="510" x="35" y="0" width="12" height="15" xoffset="0" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="511" x="169" y="105" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="512" x="36" y="16" width="11" height="14" xoffset="-1" yoffset="0" xadvance="9" page="0" chnl="15" />
+ <char id="513" x="40" y="183" width="7" height="11" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="514" x="168" y="15" width="11" height="14" xoffset="-1" yoffset="0" xadvance="9" page="0" chnl="15" />
+ <char id="515" x="56" y="183" width="7" height="11" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="516" x="63" y="76" width="8" height="14" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="517" x="72" y="182" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="518" x="72" y="76" width="8" height="14" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="519" x="88" y="180" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="520" x="135" y="90" width="6" height="14" xoffset="-1" yoffset="0" xadvance="4" page="0" chnl="15" />
+ <char id="521" x="114" y="204" width="6" height="11" xoffset="-2" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="522" x="206" y="90" width="5" height="14" xoffset="0" yoffset="0" xadvance="4" page="0" chnl="15" />
+ <char id="523" x="203" y="202" width="5" height="11" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="524" x="44" y="46" width="10" height="14" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="525" x="120" y="180" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="526" x="88" y="31" width="10" height="14" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="527" x="128" y="180" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="528" x="180" y="15" width="10" height="14" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="529" x="93" y="204" width="6" height="11" xoffset="0" yoffset="3" xadvance="6" page="0" chnl="15" />
+ <char id="530" x="191" y="15" width="10" height="14" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="531" x="24" y="219" width="5" height="11" xoffset="1" yoffset="3" xadvance="6" page="0" chnl="15" />
+ <char id="532" x="85" y="46" width="9" height="14" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="533" x="160" y="180" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="534" x="95" y="46" width="9" height="14" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="535" x="176" y="179" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="536" x="60" y="0" width="8" height="15" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="537" x="177" y="105" width="6" height="12" xoffset="1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="538" x="69" y="0" width="8" height="15" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="539" x="176" y="90" width="5" height="14" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="540" x="16" y="93" width="7" height="14" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="541" x="128" y="204" width="6" height="11" xoffset="1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="542" x="205" y="45" width="9" height="14" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="543" x="24" y="93" width="7" height="14" xoffset="1" yoffset="0" xadvance="9" page="0" chnl="15" />
+ <char id="544" x="145" y="45" width="9" height="14" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="545" x="191" y="0" width="12" height="14" xoffset="1" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="546" x="0" y="195" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="547" x="8" y="195" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="548" x="72" y="106" width="9" height="13" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="549" x="120" y="216" width="6" height="10" xoffset="1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="550" x="60" y="16" width="11" height="14" xoffset="-1" yoffset="0" xadvance="9" page="0" chnl="15" />
+ <char id="551" x="32" y="195" width="7" height="11" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="552" x="81" y="76" width="8" height="14" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="553" x="48" y="195" width="7" height="11" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="554" x="202" y="15" width="10" height="14" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="555" x="64" y="91" width="7" height="14" xoffset="1" yoffset="0" xadvance="9" page="0" chnl="15" />
+ <char id="556" x="224" y="15" width="10" height="14" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="557" x="80" y="91" width="7" height="14" xoffset="1" yoffset="0" xadvance="9" page="0" chnl="15" />
+ <char id="558" x="33" y="31" width="10" height="14" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="559" x="96" y="192" width="7" height="11" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="560" x="44" y="31" width="10" height="14" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="561" x="104" y="91" width="7" height="14" xoffset="1" yoffset="0" xadvance="9" page="0" chnl="15" />
+ <char id="562" x="77" y="31" width="10" height="14" xoffset="0" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="563" x="120" y="90" width="7" height="14" xoffset="0" yoffset="3" xadvance="7" page="0" chnl="15" />
+ <char id="564" x="132" y="75" width="7" height="14" xoffset="0" yoffset="3" xadvance="7" page="0" chnl="15" />
+ <char id="565" x="149" y="118" width="12" height="11" xoffset="1" yoffset="6" xadvance="13" page="0" chnl="15" />
+ <char id="566" x="94" y="216" width="8" height="10" xoffset="0" yoffset="4" xadvance="8" page="0" chnl="15" />
+ <char id="567" x="55" y="219" width="4" height="11" xoffset="-1" yoffset="6" xadvance="4" page="0" chnl="15" />
+ <char id="568" x="162" y="118" width="12" height="11" xoffset="1" yoffset="3" xadvance="14" page="0" chnl="15" />
+ <char id="569" x="175" y="118" width="12" height="11" xoffset="1" yoffset="6" xadvance="14" page="0" chnl="15" />
+ <char id="570" x="146" y="105" width="11" height="12" xoffset="0" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="571" x="20" y="159" width="9" height="11" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="572" x="149" y="90" width="6" height="14" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="573" x="207" y="153" width="8" height="11" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="574" x="92" y="106" width="8" height="13" xoffset="0" yoffset="2" xadvance="9" page="0" chnl="15" />
+ <char id="575" x="208" y="189" width="7" height="11" xoffset="0" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="576" x="216" y="189" width="7" height="11" xoffset="1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="577" x="225" y="153" width="8" height="11" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="578" x="9" y="231" width="7" height="8" xoffset="0" yoffset="6" xadvance="7" page="0" chnl="15" />
+ <char id="579" x="193" y="129" width="10" height="11" xoffset="0" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="580" x="146" y="131" width="11" height="11" xoffset="0" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="581" x="40" y="159" width="9" height="11" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="582" x="101" y="106" width="8" height="13" xoffset="1" yoffset="2" xadvance="10" page="0" chnl="15" />
+ <char id="583" x="212" y="75" width="7" height="14" xoffset="0" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="584" x="27" y="171" width="8" height="11" xoffset="0" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="585" x="230" y="90" width="5" height="14" xoffset="-1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="586" x="178" y="0" width="12" height="14" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="587" x="60" y="158" width="9" height="11" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="588" x="86" y="132" width="11" height="11" xoffset="0" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="589" x="122" y="227" width="6" height="8" xoffset="0" yoffset="6" xadvance="6" page="0" chnl="15" />
+ <char id="590" x="143" y="144" width="10" height="11" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="591" x="81" y="168" width="8" height="11" xoffset="0" yoffset="6" xadvance="8" page="0" chnl="15" />
+ </chars>
+ <kernings count="71">
+ <kerning first="32" second="65" amount="-1" />
+ <kerning first="49" second="49" amount="-1" />
+ <kerning first="65" second="32" amount="-1" />
+ <kerning first="65" second="84" amount="-1" />
+ <kerning first="65" second="86" amount="-1" />
+ <kerning first="65" second="87" amount="-1" />
+ <kerning first="65" second="89" amount="-1" />
+ <kerning first="65" second="118" amount="-1" />
+ <kerning first="65" second="121" amount="-1" />
+ <kerning first="70" second="44" amount="-2" />
+ <kerning first="70" second="46" amount="-2" />
+ <kerning first="70" second="65" amount="-1" />
+ <kerning first="76" second="84" amount="-1" />
+ <kerning first="76" second="86" amount="-1" />
+ <kerning first="76" second="87" amount="-1" />
+ <kerning first="76" second="89" amount="-1" />
+ <kerning first="76" second="121" amount="-1" />
+ <kerning first="80" second="44" amount="-2" />
+ <kerning first="80" second="46" amount="-2" />
+ <kerning first="80" second="65" amount="-1" />
+ <kerning first="82" second="89" amount="-1" />
+ <kerning first="84" second="44" amount="-2" />
+ <kerning first="84" second="45" amount="-1" />
+ <kerning first="84" second="46" amount="-2" />
+ <kerning first="84" second="58" amount="-2" />
+ <kerning first="84" second="65" amount="-1" />
+ <kerning first="84" second="97" amount="-1" />
+ <kerning first="84" second="99" amount="-1" />
+ <kerning first="84" second="101" amount="-1" />
+ <kerning first="84" second="111" amount="-1" />
+ <kerning first="84" second="114" amount="-1" />
+ <kerning first="84" second="115" amount="-1" />
+ <kerning first="84" second="117" amount="-1" />
+ <kerning first="84" second="119" amount="-1" />
+ <kerning first="84" second="121" amount="-1" />
+ <kerning first="86" second="44" amount="-1" />
+ <kerning first="86" second="45" amount="-1" />
+ <kerning first="86" second="46" amount="-1" />
+ <kerning first="86" second="58" amount="-1" />
+ <kerning first="86" second="65" amount="-1" />
+ <kerning first="86" second="97" amount="-1" />
+ <kerning first="86" second="101" amount="-1" />
+ <kerning first="86" second="111" amount="-1" />
+ <kerning first="86" second="114" amount="-1" />
+ <kerning first="86" second="117" amount="-1" />
+ <kerning first="86" second="121" amount="-1" />
+ <kerning first="87" second="44" amount="-1" />
+ <kerning first="87" second="46" amount="-1" />
+ <kerning first="87" second="65" amount="-1" />
+ <kerning first="87" second="97" amount="-1" />
+ <kerning first="89" second="44" amount="-2" />
+ <kerning first="89" second="45" amount="-1" />
+ <kerning first="89" second="46" amount="-2" />
+ <kerning first="89" second="58" amount="-1" />
+ <kerning first="89" second="65" amount="-1" />
+ <kerning first="89" second="97" amount="-1" />
+ <kerning first="89" second="101" amount="-1" />
+ <kerning first="89" second="105" amount="-1" />
+ <kerning first="89" second="111" amount="-1" />
+ <kerning first="89" second="112" amount="-1" />
+ <kerning first="89" second="113" amount="-1" />
+ <kerning first="89" second="117" amount="-1" />
+ <kerning first="89" second="118" amount="-1" />
+ <kerning first="114" second="44" amount="-1" />
+ <kerning first="114" second="46" amount="-1" />
+ <kerning first="118" second="44" amount="-1" />
+ <kerning first="118" second="46" amount="-1" />
+ <kerning first="119" second="44" amount="-1" />
+ <kerning first="119" second="46" amount="-1" />
+ <kerning first="121" second="44" amount="-1" />
+ <kerning first="121" second="46" amount="-1" />
+ </kernings>
+</font>
diff --git a/ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-18-bold_0.png b/ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-18-bold_0.png Binary files differnew file mode 100644 index 0000000..363b109 --- /dev/null +++ b/ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-18-bold_0.png diff --git a/ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-18-regular.fnt b/ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-18-regular.fnt new file mode 100644 index 0000000..89872f9 --- /dev/null +++ b/ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-18-regular.fnt @@ -0,0 +1,609 @@ +<?xml version="1.0"?>
+<font>
+ <info face="Arial" size="18" bold="0" italic="0" charset="" unicode="1" stretchH="100" smooth="1" aa="1" padding="0,0,0,0" spacing="1,1" outline="0"/>
+ <common lineHeight="18" base="15" scaleW="256" scaleH="256" pages="1" packed="0" alphaChnl="0" redChnl="4" greenChnl="4" blueChnl="4"/>
+ <pages>
+ <page id="0" file="arial-18-regular_0.png" />
+ </pages>
+ <chars count="527">
+ <char id="32" x="70" y="179" width="1" height="1" xoffset="0" yoffset="15" xadvance="4" page="0" chnl="15" />
+ <char id="33" x="246" y="215" width="1" height="12" xoffset="2" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="34" x="234" y="239" width="4" height="4" xoffset="1" yoffset="3" xadvance="6" page="0" chnl="15" />
+ <char id="35" x="200" y="165" width="9" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="36" x="73" y="112" width="7" height="14" xoffset="1" yoffset="2" xadvance="9" page="0" chnl="15" />
+ <char id="37" x="91" y="140" width="12" height="12" xoffset="1" yoffset="3" xadvance="14" page="0" chnl="15" />
+ <char id="38" x="169" y="152" width="10" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="39" x="244" y="239" width="1" height="4" xoffset="1" yoffset="3" xadvance="3" page="0" chnl="15" />
+ <char id="40" x="248" y="80" width="3" height="15" xoffset="1" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="41" x="252" y="48" width="3" height="15" xoffset="1" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="42" x="228" y="239" width="5" height="5" xoffset="0" yoffset="3" xadvance="6" page="0" chnl="15" />
+ <char id="43" x="129" y="243" width="7" height="7" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="44" x="246" y="239" width="1" height="4" xoffset="2" yoffset="14" xadvance="4" page="0" chnl="15" />
+ <char id="45" x="57" y="140" width="4" height="1" xoffset="0" yoffset="11" xadvance="5" page="0" chnl="15" />
+ <char id="46" x="62" y="140" width="1" height="1" xoffset="2" yoffset="14" xadvance="4" page="0" chnl="15" />
+ <char id="47" x="183" y="217" width="4" height="12" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="48" x="200" y="191" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="49" x="168" y="217" width="4" height="12" xoffset="2" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="50" x="184" y="191" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="51" x="176" y="191" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="52" x="54" y="181" width="8" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="53" x="152" y="192" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="54" x="144" y="192" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="55" x="136" y="192" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="56" x="112" y="192" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="57" x="104" y="192" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="58" x="110" y="243" width="1" height="9" xoffset="1" yoffset="6" xadvance="4" page="0" chnl="15" />
+ <char id="59" x="250" y="215" width="1" height="12" xoffset="1" yoffset="6" xadvance="4" page="0" chnl="15" />
+ <char id="60" x="137" y="242" width="7" height="7" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="61" x="220" y="240" width="7" height="5" xoffset="1" yoffset="7" xadvance="9" page="0" chnl="15" />
+ <char id="62" x="121" y="243" width="7" height="7" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="63" x="80" y="192" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="64" x="194" y="0" width="15" height="15" xoffset="1" yoffset="3" xadvance="16" page="0" chnl="15" />
+ <char id="65" x="140" y="139" width="11" height="12" xoffset="0" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="66" x="160" y="165" width="9" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="67" x="103" y="153" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="68" x="136" y="153" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="69" x="140" y="166" width="9" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="70" x="0" y="182" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="71" x="125" y="153" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="72" x="40" y="169" width="9" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="73" x="244" y="216" width="1" height="12" xoffset="1" yoffset="3" xadvance="3" page="0" chnl="15" />
+ <char id="74" x="175" y="204" width="6" height="12" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="75" x="110" y="166" width="9" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="76" x="112" y="205" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="77" x="0" y="156" width="11" height="12" xoffset="1" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="78" x="130" y="166" width="9" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="79" x="147" y="152" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="80" x="70" y="166" width="9" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="81" x="173" y="112" width="10" height="13" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="82" x="59" y="155" width="10" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="83" x="244" y="150" width="9" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="84" x="20" y="169" width="9" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="85" x="90" y="166" width="9" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="86" x="104" y="140" width="11" height="12" xoffset="0" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="87" x="91" y="127" width="15" height="12" xoffset="0" yoffset="3" xadvance="15" page="0" chnl="15" />
+ <char id="88" x="36" y="156" width="11" height="12" xoffset="0" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="89" x="60" y="168" width="9" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="90" x="50" y="168" width="9" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="91" x="240" y="80" width="3" height="15" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="92" x="173" y="217" width="4" height="12" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="93" x="244" y="80" width="3" height="15" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="94" x="168" y="240" width="7" height="6" xoffset="0" yoffset="3" xadvance="7" page="0" chnl="15" />
+ <char id="95" x="104" y="253" width="9" height="1" xoffset="0" yoffset="17" xadvance="9" page="0" chnl="15" />
+ <char id="96" x="252" y="238" width="2" height="2" xoffset="1" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="97" x="240" y="229" width="7" height="9" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="98" x="240" y="189" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="99" x="68" y="245" width="6" height="9" xoffset="1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="100" x="40" y="195" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="101" x="32" y="246" width="7" height="9" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="102" x="151" y="218" width="5" height="12" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="103" x="242" y="176" width="7" height="12" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="104" x="182" y="204" width="6" height="12" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="105" x="236" y="216" width="1" height="12" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="106" x="236" y="80" width="3" height="15" xoffset="-1" yoffset="3" xadvance="3" page="0" chnl="15" />
+ <char id="107" x="153" y="178" width="8" height="12" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="108" x="248" y="215" width="1" height="12" xoffset="1" yoffset="3" xadvance="3" page="0" chnl="15" />
+ <char id="109" x="178" y="230" width="11" height="9" xoffset="1" yoffset="6" xadvance="13" page="0" chnl="15" />
+ <char id="110" x="61" y="245" width="6" height="9" xoffset="1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="111" x="222" y="229" width="8" height="9" xoffset="0" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="112" x="24" y="208" width="7" height="12" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="113" x="32" y="208" width="7" height="12" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="114" x="103" y="243" width="4" height="9" xoffset="1" yoffset="6" xadvance="5" page="0" chnl="15" />
+ <char id="115" x="82" y="243" width="6" height="9" xoffset="1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="116" x="178" y="217" width="4" height="12" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="117" x="47" y="246" width="6" height="9" xoffset="1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="118" x="212" y="230" width="9" height="9" xoffset="-1" yoffset="6" xadvance="7" page="0" chnl="15" />
+ <char id="119" x="190" y="230" width="11" height="9" xoffset="0" yoffset="6" xadvance="11" page="0" chnl="15" />
+ <char id="120" x="8" y="246" width="7" height="9" xoffset="0" yoffset="6" xadvance="7" page="0" chnl="15" />
+ <char id="121" x="27" y="182" width="8" height="12" xoffset="-1" yoffset="6" xadvance="7" page="0" chnl="15" />
+ <char id="122" x="248" y="228" width="7" height="9" xoffset="0" yoffset="6" xadvance="7" page="0" chnl="15" />
+ <char id="123" x="180" y="80" width="5" height="15" xoffset="0" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="124" x="254" y="0" width="1" height="15" xoffset="1" yoffset="3" xadvance="3" page="0" chnl="15" />
+ <char id="125" x="186" y="80" width="5" height="15" xoffset="0" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="126" x="82" y="253" width="8" height="2" xoffset="0" yoffset="8" xadvance="9" page="0" chnl="15" />
+ <char id="160" x="77" y="231" width="1" height="1" xoffset="0" yoffset="15" xadvance="4" page="0" chnl="15" />
+ <char id="161" x="242" y="216" width="1" height="12" xoffset="2" yoffset="6" xadvance="5" page="0" chnl="15" />
+ <char id="162" x="115" y="0" width="7" height="16" xoffset="1" yoffset="2" xadvance="9" page="0" chnl="15" />
+ <char id="163" x="126" y="179" width="8" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="164" x="159" y="241" width="8" height="6" xoffset="0" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="165" x="190" y="165" width="9" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="166" x="9" y="99" width="1" height="15" xoffset="1" yoffset="3" xadvance="3" page="0" chnl="15" />
+ <char id="167" x="27" y="83" width="8" height="15" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="168" x="72" y="218" width="3" height="1" xoffset="0" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="169" x="52" y="142" width="12" height="12" xoffset="0" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="170" x="176" y="240" width="5" height="6" xoffset="0" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="171" x="152" y="241" width="6" height="7" xoffset="1" yoffset="7" xadvance="9" page="0" chnl="15" />
+ <char id="172" x="204" y="240" width="7" height="5" xoffset="1" yoffset="7" xadvance="9" page="0" chnl="15" />
+ <char id="173" x="65" y="153" width="4" height="1" xoffset="0" yoffset="11" xadvance="5" page="0" chnl="15" />
+ <char id="174" x="13" y="143" width="12" height="12" xoffset="0" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="175" x="94" y="253" width="9" height="1" xoffset="0" yoffset="2" xadvance="9" page="0" chnl="15" />
+ <char id="176" x="239" y="239" width="4" height="4" xoffset="1" yoffset="3" xadvance="6" page="0" chnl="15" />
+ <char id="177" x="142" y="231" width="7" height="10" xoffset="1" yoffset="5" xadvance="9" page="0" chnl="15" />
+ <char id="178" x="194" y="240" width="5" height="6" xoffset="0" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="179" x="188" y="240" width="5" height="6" xoffset="0" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="180" x="91" y="253" width="2" height="2" xoffset="2" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="181" x="216" y="190" width="7" height="12" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="182" x="92" y="49" width="9" height="15" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="183" x="79" y="231" width="1" height="1" xoffset="2" yoffset="9" xadvance="5" page="0" chnl="15" />
+ <char id="184" x="248" y="238" width="3" height="3" xoffset="1" yoffset="15" xadvance="5" page="0" chnl="15" />
+ <char id="185" x="200" y="240" width="3" height="6" xoffset="1" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="186" x="182" y="240" width="5" height="6" xoffset="0" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="187" x="145" y="242" width="6" height="7" xoffset="2" yoffset="7" xadvance="9" page="0" chnl="15" />
+ <char id="188" x="224" y="124" width="12" height="12" xoffset="1" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="189" x="237" y="124" width="12" height="12" xoffset="1" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="190" x="155" y="126" width="13" height="12" xoffset="0" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="191" x="180" y="178" width="8" height="12" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
+ <char id="192" x="62" y="17" width="11" height="15" xoffset="0" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="193" x="74" y="17" width="11" height="15" xoffset="0" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="194" x="86" y="17" width="11" height="15" xoffset="0" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="195" x="50" y="17" width="11" height="15" xoffset="0" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="196" x="54" y="97" width="11" height="14" xoffset="0" yoffset="1" xadvance="11" page="0" chnl="15" />
+ <char id="197" x="66" y="97" width="11" height="14" xoffset="0" yoffset="1" xadvance="11" page="0" chnl="15" />
+ <char id="198" x="239" y="111" width="16" height="12" xoffset="-1" yoffset="3" xadvance="16" page="0" chnl="15" />
+ <char id="199" x="0" y="35" width="10" height="15" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="200" x="130" y="65" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="201" x="70" y="65" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="202" x="202" y="48" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="203" x="197" y="96" width="9" height="14" xoffset="1" yoffset="1" xadvance="11" page="0" chnl="15" />
+ <char id="204" x="3" y="99" width="2" height="15" xoffset="0" yoffset="0" xadvance="3" page="0" chnl="15" />
+ <char id="205" x="6" y="99" width="2" height="15" xoffset="1" yoffset="0" xadvance="3" page="0" chnl="15" />
+ <char id="206" x="145" y="81" width="6" height="15" xoffset="-1" yoffset="0" xadvance="3" page="0" chnl="15" />
+ <char id="207" x="131" y="112" width="3" height="14" xoffset="0" yoffset="1" xadvance="3" page="0" chnl="15" />
+ <char id="208" x="236" y="137" width="11" height="12" xoffset="0" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="209" x="110" y="65" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="210" x="55" y="33" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="211" x="77" y="33" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="212" x="110" y="33" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="213" x="132" y="33" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="214" x="90" y="97" width="10" height="14" xoffset="1" yoffset="1" xadvance="12" page="0" chnl="15" />
+ <char id="215" x="112" y="243" width="8" height="7" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="216" x="101" y="97" width="10" height="14" xoffset="1" yoffset="2" xadvance="12" page="0" chnl="15" />
+ <char id="217" x="122" y="49" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="218" x="132" y="49" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="219" x="60" y="65" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="220" x="187" y="96" width="9" height="14" xoffset="1" yoffset="1" xadvance="11" page="0" chnl="15" />
+ <char id="221" x="152" y="49" width="9" height="15" xoffset="0" yoffset="0" xadvance="9" page="0" chnl="15" />
+ <char id="222" x="224" y="150" width="9" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="223" x="192" y="191" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="224" x="248" y="189" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="225" x="168" y="191" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="226" x="248" y="137" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="227" x="64" y="194" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="228" x="57" y="233" width="7" height="11" xoffset="1" yoffset="4" xadvance="9" page="0" chnl="15" />
+ <char id="229" x="184" y="112" width="7" height="13" xoffset="1" yoffset="2" xadvance="9" page="0" chnl="15" />
+ <char id="230" x="150" y="231" width="13" height="9" xoffset="1" yoffset="6" xadvance="14" page="0" chnl="15" />
+ <char id="231" x="196" y="204" width="6" height="12" xoffset="1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="232" x="16" y="195" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="233" x="8" y="195" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="234" x="0" y="195" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="235" x="41" y="234" width="7" height="11" xoffset="1" yoffset="4" xadvance="9" page="0" chnl="15" />
+ <char id="236" x="230" y="216" width="2" height="12" xoffset="0" yoffset="3" xadvance="3" page="0" chnl="15" />
+ <char id="237" x="233" y="216" width="2" height="12" xoffset="1" yoffset="3" xadvance="3" page="0" chnl="15" />
+ <char id="238" x="203" y="204" width="6" height="12" xoffset="-1" yoffset="3" xadvance="3" page="0" chnl="15" />
+ <char id="239" x="252" y="215" width="3" height="11" xoffset="0" yoffset="4" xadvance="3" page="0" chnl="15" />
+ <char id="240" x="234" y="176" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="241" x="210" y="204" width="6" height="12" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="242" x="9" y="182" width="8" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="243" x="90" y="179" width="8" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="244" x="198" y="178" width="8" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="245" x="238" y="163" width="8" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="246" x="14" y="234" width="8" height="11" xoffset="0" yoffset="4" xadvance="9" page="0" chnl="15" />
+ <char id="247" x="212" y="240" width="7" height="5" xoffset="1" yoffset="7" xadvance="9" page="0" chnl="15" />
+ <char id="248" x="0" y="246" width="7" height="9" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="249" x="217" y="203" width="6" height="12" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="250" x="238" y="203" width="6" height="12" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="251" x="0" y="221" width="6" height="12" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="252" x="112" y="231" width="6" height="11" xoffset="1" yoffset="4" xadvance="8" page="0" chnl="15" />
+ <char id="253" x="36" y="82" width="8" height="15" xoffset="-1" yoffset="3" xadvance="7" page="0" chnl="15" />
+ <char id="254" x="101" y="81" width="7" height="15" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="255" x="56" y="112" width="8" height="14" xoffset="-1" yoffset="4" xadvance="7" page="0" chnl="15" />
+ <char id="256" x="78" y="97" width="11" height="14" xoffset="0" yoffset="1" xadvance="11" page="0" chnl="15" />
+ <char id="257" x="89" y="231" width="7" height="11" xoffset="1" yoffset="4" xadvance="9" page="0" chnl="15" />
+ <char id="258" x="122" y="17" width="11" height="15" xoffset="0" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="259" x="104" y="205" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="260" x="98" y="17" width="11" height="15" xoffset="0" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="261" x="128" y="205" width="7" height="12" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="262" x="215" y="16" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="263" x="42" y="221" width="6" height="12" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="264" x="0" y="51" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="265" x="7" y="221" width="6" height="12" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="266" x="112" y="97" width="10" height="14" xoffset="1" yoffset="1" xadvance="12" page="0" chnl="15" />
+ <char id="267" x="119" y="231" width="6" height="11" xoffset="1" yoffset="4" xadvance="8" page="0" chnl="15" />
+ <char id="268" x="154" y="33" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="269" x="14" y="221" width="6" height="12" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="270" x="242" y="32" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="271" x="10" y="169" width="9" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="272" x="152" y="139" width="11" height="12" xoffset="0" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="273" x="18" y="182" width="8" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="274" x="10" y="115" width="9" height="14" xoffset="1" yoffset="1" xadvance="11" page="0" chnl="15" />
+ <char id="275" x="97" y="231" width="7" height="11" xoffset="1" yoffset="4" xadvance="9" page="0" chnl="15" />
+ <char id="276" x="0" y="67" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="277" x="24" y="195" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="278" x="227" y="96" width="9" height="14" xoffset="1" yoffset="1" xadvance="11" page="0" chnl="15" />
+ <char id="279" x="49" y="234" width="7" height="11" xoffset="1" yoffset="4" xadvance="9" page="0" chnl="15" />
+ <char id="280" x="192" y="48" width="9" height="15" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="281" x="88" y="192" width="7" height="12" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="282" x="162" y="49" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="283" x="120" y="192" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="284" x="209" y="32" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="285" x="45" y="82" width="7" height="15" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="286" x="176" y="32" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="287" x="93" y="81" width="7" height="15" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="288" x="145" y="97" width="10" height="14" xoffset="1" yoffset="1" xadvance="12" page="0" chnl="15" />
+ <char id="289" x="89" y="112" width="7" height="14" xoffset="1" yoffset="4" xadvance="9" page="0" chnl="15" />
+ <char id="290" x="44" y="0" width="10" height="16" xoffset="1" yoffset="2" xadvance="12" page="0" chnl="15" />
+ <char id="291" x="139" y="0" width="7" height="16" xoffset="1" yoffset="2" xadvance="9" page="0" chnl="15" />
+ <char id="292" x="222" y="48" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="293" x="152" y="81" width="6" height="15" xoffset="1" yoffset="0" xadvance="8" page="0" chnl="15" />
+ <char id="294" x="200" y="138" width="11" height="12" xoffset="0" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="295" x="208" y="191" width="7" height="12" xoffset="0" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="296" x="221" y="80" width="4" height="15" xoffset="0" yoffset="0" xadvance="3" page="0" chnl="15" />
+ <char id="297" x="193" y="217" width="4" height="12" xoffset="0" yoffset="3" xadvance="3" page="0" chnl="15" />
+ <char id="298" x="125" y="112" width="5" height="14" xoffset="-1" yoffset="1" xadvance="3" page="0" chnl="15" />
+ <char id="299" x="126" y="231" width="5" height="11" xoffset="-1" yoffset="4" xadvance="3" page="0" chnl="15" />
+ <char id="300" x="204" y="80" width="5" height="15" xoffset="-1" yoffset="0" xadvance="3" page="0" chnl="15" />
+ <char id="301" x="157" y="218" width="5" height="12" xoffset="-1" yoffset="3" xadvance="3" page="0" chnl="15" />
+ <char id="302" x="252" y="80" width="2" height="15" xoffset="0" yoffset="3" xadvance="3" page="0" chnl="15" />
+ <char id="303" x="0" y="99" width="2" height="15" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="304" x="135" y="112" width="1" height="14" xoffset="1" yoffset="1" xadvance="3" page="0" chnl="15" />
+ <char id="305" x="108" y="243" width="1" height="9" xoffset="1" yoffset="6" xadvance="3" page="0" chnl="15" />
+ <char id="306" x="229" y="163" width="8" height="12" xoffset="2" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="307" x="226" y="80" width="4" height="15" xoffset="2" yoffset="3" xadvance="7" page="0" chnl="15" />
+ <char id="308" x="62" y="49" width="9" height="15" xoffset="1" yoffset="0" xadvance="8" page="0" chnl="15" />
+ <char id="309" x="117" y="81" width="6" height="15" xoffset="-1" yoffset="3" xadvance="3" page="0" chnl="15" />
+ <char id="310" x="66" y="0" width="9" height="16" xoffset="1" yoffset="2" xadvance="11" page="0" chnl="15" />
+ <char id="311" x="106" y="0" width="8" height="16" xoffset="1" yoffset="2" xadvance="8" page="0" chnl="15" />
+ <char id="312" x="24" y="246" width="7" height="9" xoffset="1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="313" x="85" y="81" width="7" height="15" xoffset="1" yoffset="0" xadvance="9" page="0" chnl="15" />
+ <char id="314" x="253" y="32" width="2" height="15" xoffset="1" yoffset="0" xadvance="3" page="0" chnl="15" />
+ <char id="315" x="131" y="0" width="7" height="16" xoffset="1" yoffset="2" xadvance="9" page="0" chnl="15" />
+ <char id="316" x="152" y="0" width="3" height="16" xoffset="0" yoffset="2" xadvance="3" page="0" chnl="15" />
+ <char id="317" x="144" y="205" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="318" x="207" y="217" width="3" height="12" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="319" x="32" y="195" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="320" x="252" y="202" width="3" height="12" xoffset="1" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="321" x="234" y="150" width="9" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="322" x="203" y="217" width="3" height="12" xoffset="0" yoffset="3" xadvance="3" page="0" chnl="15" />
+ <char id="323" x="180" y="64" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="324" x="35" y="221" width="6" height="12" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="325" x="96" y="0" width="9" height="16" xoffset="1" yoffset="2" xadvance="11" page="0" chnl="15" />
+ <char id="326" x="192" y="111" width="6" height="13" xoffset="1" yoffset="5" xadvance="8" page="0" chnl="15" />
+ <char id="327" x="190" y="64" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="328" x="168" y="204" width="6" height="12" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="329" x="135" y="179" width="8" height="12" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="330" x="81" y="153" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="331" x="49" y="221" width="6" height="12" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="332" x="156" y="97" width="10" height="14" xoffset="1" yoffset="1" xadvance="12" page="0" chnl="15" />
+ <char id="333" x="23" y="234" width="8" height="11" xoffset="0" yoffset="4" xadvance="9" page="0" chnl="15" />
+ <char id="334" x="99" y="33" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="335" x="220" y="164" width="8" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="336" x="11" y="35" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="337" x="171" y="178" width="8" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="338" x="107" y="127" width="15" height="12" xoffset="1" yoffset="3" xadvance="17" page="0" chnl="15" />
+ <char id="339" x="164" y="230" width="13" height="9" xoffset="1" yoffset="6" xadvance="15" page="0" chnl="15" />
+ <char id="340" x="220" y="32" width="10" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="341" x="163" y="217" width="4" height="12" xoffset="1" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="342" x="33" y="0" width="10" height="16" xoffset="1" yoffset="2" xadvance="11" page="0" chnl="15" />
+ <char id="343" x="213" y="111" width="4" height="13" xoffset="1" yoffset="5" xadvance="5" page="0" chnl="15" />
+ <char id="344" x="226" y="16" width="10" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="345" x="56" y="220" width="6" height="12" xoffset="0" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="346" x="210" y="64" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="347" x="63" y="220" width="6" height="12" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="348" x="150" y="65" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="349" x="70" y="220" width="6" height="12" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="350" x="140" y="65" width="9" height="15" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="351" x="77" y="218" width="6" height="12" xoffset="1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="352" x="120" y="65" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="353" x="84" y="218" width="6" height="12" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="354" x="90" y="65" width="9" height="15" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="355" x="216" y="80" width="4" height="15" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="356" x="30" y="66" width="9" height="15" xoffset="0" yoffset="0" xadvance="9" page="0" chnl="15" />
+ <char id="357" x="91" y="218" width="6" height="12" xoffset="0" yoffset="3" xadvance="6" page="0" chnl="15" />
+ <char id="358" x="0" y="169" width="9" height="12" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="359" x="198" y="217" width="4" height="12" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="360" x="232" y="48" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="361" x="98" y="218" width="6" height="12" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="362" x="217" y="96" width="9" height="14" xoffset="1" yoffset="1" xadvance="11" page="0" chnl="15" />
+ <char id="363" x="105" y="231" width="6" height="11" xoffset="1" yoffset="4" xadvance="8" page="0" chnl="15" />
+ <char id="364" x="102" y="49" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="365" x="105" y="218" width="6" height="12" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="366" x="160" y="65" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="367" x="206" y="111" width="6" height="13" xoffset="1" yoffset="2" xadvance="8" page="0" chnl="15" />
+ <char id="368" x="22" y="50" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="369" x="112" y="218" width="6" height="12" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="370" x="10" y="67" width="9" height="15" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="371" x="119" y="218" width="6" height="12" xoffset="1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="372" x="210" y="0" width="15" height="15" xoffset="0" yoffset="0" xadvance="15" page="0" chnl="15" />
+ <char id="373" x="12" y="156" width="11" height="12" xoffset="0" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="374" x="72" y="49" width="9" height="15" xoffset="0" yoffset="0" xadvance="9" page="0" chnl="15" />
+ <char id="375" x="0" y="83" width="8" height="15" xoffset="-1" yoffset="3" xadvance="7" page="0" chnl="15" />
+ <char id="376" x="0" y="115" width="9" height="14" xoffset="0" yoffset="1" xadvance="9" page="0" chnl="15" />
+ <char id="377" x="82" y="49" width="9" height="15" xoffset="0" yoffset="0" xadvance="9" page="0" chnl="15" />
+ <char id="378" x="232" y="190" width="7" height="12" xoffset="0" yoffset="3" xadvance="7" page="0" chnl="15" />
+ <char id="379" x="167" y="97" width="9" height="14" xoffset="0" yoffset="1" xadvance="9" page="0" chnl="15" />
+ <char id="380" x="81" y="231" width="7" height="11" xoffset="0" yoffset="4" xadvance="7" page="0" chnl="15" />
+ <char id="381" x="52" y="49" width="9" height="15" xoffset="0" yoffset="0" xadvance="9" page="0" chnl="15" />
+ <char id="382" x="8" y="208" width="7" height="12" xoffset="0" yoffset="3" xadvance="7" page="0" chnl="15" />
+ <char id="383" x="227" y="216" width="2" height="12" xoffset="1" yoffset="3" xadvance="3" page="0" chnl="15" />
+ <char id="384" x="216" y="177" width="8" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="385" x="188" y="139" width="11" height="12" xoffset="0" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="386" x="210" y="164" width="9" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="387" x="80" y="205" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="388" x="213" y="151" width="10" height="12" xoffset="0" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="389" x="108" y="179" width="8" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="390" x="48" y="155" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="391" x="137" y="112" width="12" height="13" xoffset="1" yoffset="2" xadvance="12" page="0" chnl="15" />
+ <char id="392" x="132" y="231" width="9" height="10" xoffset="1" yoffset="5" xadvance="8" page="0" chnl="15" />
+ <char id="393" x="24" y="156" width="11" height="12" xoffset="0" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="394" x="26" y="143" width="12" height="12" xoffset="0" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="395" x="80" y="166" width="9" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="396" x="64" y="207" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="397" x="48" y="208" width="7" height="12" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="398" x="120" y="166" width="9" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="399" x="70" y="153" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="400" x="63" y="181" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="401" x="22" y="34" width="10" height="15" xoffset="-1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="402" x="240" y="64" width="9" height="15" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="403" x="150" y="112" width="11" height="13" xoffset="1" yoffset="2" xadvance="12" page="0" chnl="15" />
+ <char id="404" x="237" y="16" width="10" height="15" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="405" x="211" y="125" width="12" height="12" xoffset="1" yoffset="3" xadvance="14" page="0" chnl="15" />
+ <char id="406" x="238" y="216" width="1" height="12" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="407" x="215" y="217" width="3" height="12" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="408" x="92" y="153" width="10" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="409" x="16" y="208" width="7" height="12" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="410" x="211" y="217" width="3" height="12" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="411" x="81" y="179" width="8" height="12" xoffset="0" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="412" x="164" y="139" width="11" height="12" xoffset="1" yoffset="3" xadvance="14" page="0" chnl="15" />
+ <char id="413" x="13" y="18" width="12" height="15" xoffset="-1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="414" x="72" y="205" width="7" height="12" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="415" x="114" y="153" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="416" x="0" y="143" width="12" height="12" xoffset="1" yoffset="3" xadvance="14" page="0" chnl="15" />
+ <char id="417" x="231" y="229" width="8" height="9" xoffset="1" yoffset="6" xadvance="11" page="0" chnl="15" />
+ <char id="418" x="0" y="19" width="12" height="15" xoffset="1" yoffset="3" xadvance="14" page="0" chnl="15" />
+ <char id="419" x="100" y="166" width="9" height="12" xoffset="1" yoffset="6" xadvance="11" page="0" chnl="15" />
+ <char id="420" x="128" y="140" width="11" height="12" xoffset="0" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="421" x="61" y="81" width="7" height="15" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="422" x="198" y="32" width="10" height="15" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="423" x="170" y="165" width="9" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="424" x="96" y="243" width="6" height="9" xoffset="1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="425" x="72" y="179" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="426" x="166" y="81" width="6" height="15" xoffset="0" yoffset="3" xadvance="6" page="0" chnl="15" />
+ <char id="427" x="231" y="80" width="4" height="15" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="428" x="158" y="152" width="10" height="12" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="429" x="188" y="217" width="4" height="12" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="430" x="112" y="49" width="9" height="15" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="431" x="116" y="140" width="11" height="12" xoffset="1" yoffset="3" xadvance="14" page="0" chnl="15" />
+ <char id="432" x="202" y="230" width="9" height="9" xoffset="1" yoffset="6" xadvance="11" page="0" chnl="15" />
+ <char id="433" x="176" y="139" width="11" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="434" x="180" y="152" width="10" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="435" x="65" y="140" width="12" height="12" xoffset="0" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="436" x="134" y="17" width="11" height="15" xoffset="0" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="437" x="225" y="177" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="438" x="75" y="245" width="6" height="9" xoffset="1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="439" x="20" y="67" width="9" height="15" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="440" x="172" y="48" width="9" height="15" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="441" x="0" y="208" width="7" height="12" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="442" x="224" y="190" width="7" height="12" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="443" x="96" y="192" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="444" x="72" y="192" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="445" x="54" y="246" width="6" height="9" xoffset="0" yoffset="6" xadvance="7" page="0" chnl="15" />
+ <char id="446" x="56" y="194" width="7" height="12" xoffset="0" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="447" x="48" y="195" width="7" height="12" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="448" x="240" y="216" width="1" height="12" xoffset="1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="449" x="219" y="216" width="3" height="12" xoffset="2" yoffset="3" xadvance="7" page="0" chnl="15" />
+ <char id="450" x="56" y="207" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="451" x="254" y="150" width="1" height="12" xoffset="2" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="452" x="156" y="0" width="20" height="15" xoffset="1" yoffset="0" xadvance="21" page="0" chnl="15" />
+ <char id="453" x="0" y="130" width="18" height="12" xoffset="1" yoffset="3" xadvance="20" page="0" chnl="15" />
+ <char id="454" x="57" y="127" width="16" height="12" xoffset="1" yoffset="3" xadvance="17" page="0" chnl="15" />
+ <char id="455" x="139" y="126" width="15" height="12" xoffset="1" yoffset="3" xadvance="17" page="0" chnl="15" />
+ <char id="456" x="38" y="17" width="11" height="15" xoffset="1" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="457" x="250" y="64" width="5" height="15" xoffset="1" yoffset="3" xadvance="7" page="0" chnl="15" />
+ <char id="458" x="38" y="129" width="18" height="12" xoffset="1" yoffset="3" xadvance="20" page="0" chnl="15" />
+ <char id="459" x="226" y="0" width="13" height="15" xoffset="1" yoffset="3" xadvance="15" page="0" chnl="15" />
+ <char id="460" x="33" y="33" width="10" height="15" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="461" x="26" y="17" width="11" height="15" xoffset="0" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="462" x="40" y="208" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="463" x="138" y="81" width="6" height="15" xoffset="-1" yoffset="0" xadvance="3" page="0" chnl="15" />
+ <char id="464" x="126" y="218" width="6" height="12" xoffset="-1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="465" x="44" y="33" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="466" x="117" y="179" width="8" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="467" x="100" y="65" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="468" x="189" y="204" width="6" height="12" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="469" x="42" y="49" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="470" x="111" y="112" width="6" height="14" xoffset="1" yoffset="1" xadvance="8" page="0" chnl="15" />
+ <char id="471" x="32" y="50" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="472" x="104" y="112" width="6" height="14" xoffset="1" yoffset="1" xadvance="8" page="0" chnl="15" />
+ <char id="473" x="230" y="64" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="474" x="97" y="112" width="6" height="14" xoffset="1" yoffset="1" xadvance="8" page="0" chnl="15" />
+ <char id="475" x="220" y="64" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="476" x="118" y="112" width="6" height="14" xoffset="1" yoffset="1" xadvance="8" page="0" chnl="15" />
+ <char id="477" x="16" y="246" width="7" height="9" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="478" x="146" y="17" width="11" height="15" xoffset="0" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="479" x="81" y="112" width="7" height="14" xoffset="1" yoffset="1" xadvance="9" page="0" chnl="15" />
+ <char id="480" x="110" y="17" width="11" height="15" xoffset="0" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="481" x="65" y="112" width="7" height="14" xoffset="1" yoffset="1" xadvance="9" page="0" chnl="15" />
+ <char id="482" x="11" y="99" width="16" height="14" xoffset="-1" yoffset="1" xadvance="16" page="0" chnl="15" />
+ <char id="483" x="0" y="234" width="13" height="11" xoffset="1" yoffset="4" xadvance="14" page="0" chnl="15" />
+ <char id="484" x="212" y="138" width="11" height="12" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="485" x="150" y="165" width="9" height="12" xoffset="0" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="486" x="231" y="32" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="487" x="53" y="81" width="7" height="15" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="488" x="170" y="65" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="489" x="9" y="83" width="8" height="15" xoffset="1" yoffset="0" xadvance="8" page="0" chnl="15" />
+ <char id="490" x="165" y="32" width="10" height="15" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="491" x="207" y="178" width="8" height="12" xoffset="0" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="492" x="10" y="0" width="10" height="17" xoffset="1" yoffset="1" xadvance="12" page="0" chnl="15" />
+ <char id="493" x="247" y="96" width="8" height="14" xoffset="0" yoffset="4" xadvance="9" page="0" chnl="15" />
+ <char id="494" x="0" y="0" width="9" height="18" xoffset="0" yoffset="0" xadvance="10" page="0" chnl="15" />
+ <char id="495" x="248" y="16" width="7" height="15" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="496" x="173" y="81" width="6" height="15" xoffset="0" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="497" x="218" y="111" width="20" height="12" xoffset="1" yoffset="3" xadvance="21" page="0" chnl="15" />
+ <char id="498" x="19" y="130" width="18" height="12" xoffset="1" yoffset="3" xadvance="20" page="0" chnl="15" />
+ <char id="499" x="74" y="127" width="16" height="12" xoffset="1" yoffset="3" xadvance="17" page="0" chnl="15" />
+ <char id="500" x="66" y="33" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="501" x="77" y="81" width="7" height="15" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="502" x="123" y="127" width="15" height="12" xoffset="1" yoffset="3" xadvance="17" page="0" chnl="15" />
+ <char id="503" x="18" y="83" width="8" height="15" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="504" x="80" y="65" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="505" x="21" y="221" width="6" height="12" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="506" x="21" y="0" width="11" height="16" xoffset="0" yoffset="-1" xadvance="11" page="0" chnl="15" />
+ <char id="507" x="123" y="0" width="7" height="16" xoffset="1" yoffset="-1" xadvance="9" page="0" chnl="15" />
+ <char id="508" x="177" y="0" width="16" height="15" xoffset="-1" yoffset="0" xadvance="16" page="0" chnl="15" />
+ <char id="509" x="197" y="125" width="13" height="12" xoffset="1" yoffset="3" xadvance="14" page="0" chnl="15" />
+ <char id="510" x="55" y="0" width="10" height="16" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="511" x="88" y="205" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="512" x="170" y="16" width="11" height="15" xoffset="0" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="513" x="96" y="205" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="514" x="158" y="16" width="11" height="15" xoffset="0" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="515" x="120" y="205" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="516" x="50" y="65" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="517" x="136" y="205" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="518" x="40" y="66" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="519" x="152" y="205" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="520" x="198" y="80" width="5" height="15" xoffset="-1" yoffset="0" xadvance="3" page="0" chnl="15" />
+ <char id="521" x="250" y="176" width="5" height="12" xoffset="-1" yoffset="3" xadvance="3" page="0" chnl="15" />
+ <char id="522" x="192" y="80" width="5" height="15" xoffset="-1" yoffset="0" xadvance="3" page="0" chnl="15" />
+ <char id="523" x="250" y="124" width="5" height="12" xoffset="-1" yoffset="3" xadvance="3" page="0" chnl="15" />
+ <char id="524" x="204" y="16" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="525" x="36" y="182" width="8" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="526" x="187" y="32" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="527" x="247" y="163" width="8" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="528" x="193" y="16" width="10" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="529" x="133" y="218" width="5" height="12" xoffset="0" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="530" x="11" y="51" width="10" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="531" x="139" y="218" width="5" height="12" xoffset="1" yoffset="3" xadvance="5" page="0" chnl="15" />
+ <char id="532" x="142" y="49" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="533" x="231" y="203" width="6" height="12" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="534" x="200" y="64" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="535" x="245" y="202" width="6" height="12" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="536" x="86" y="0" width="9" height="16" xoffset="1" yoffset="2" xadvance="11" page="0" chnl="15" />
+ <char id="537" x="199" y="111" width="6" height="13" xoffset="1" yoffset="5" xadvance="8" page="0" chnl="15" />
+ <char id="538" x="76" y="0" width="9" height="16" xoffset="0" yoffset="2" xadvance="9" page="0" chnl="15" />
+ <char id="539" x="147" y="0" width="4" height="16" xoffset="0" yoffset="2" xadvance="4" page="0" chnl="15" />
+ <char id="540" x="69" y="81" width="7" height="15" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="541" x="145" y="218" width="5" height="12" xoffset="1" yoffset="6" xadvance="7" page="0" chnl="15" />
+ <char id="542" x="242" y="48" width="9" height="15" xoffset="1" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="543" x="159" y="81" width="6" height="15" xoffset="1" yoffset="0" xadvance="8" page="0" chnl="15" />
+ <char id="544" x="212" y="48" width="9" height="15" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="545" x="143" y="33" width="10" height="15" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="546" x="45" y="182" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="547" x="128" y="192" width="7" height="12" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="548" x="123" y="97" width="10" height="14" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
+ <char id="549" x="65" y="233" width="7" height="11" xoffset="1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="550" x="42" y="98" width="11" height="14" xoffset="0" yoffset="1" xadvance="11" page="0" chnl="15" />
+ <char id="551" x="73" y="233" width="7" height="11" xoffset="1" yoffset="4" xadvance="9" page="0" chnl="15" />
+ <char id="552" x="182" y="48" width="9" height="15" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="553" x="160" y="191" width="7" height="12" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="554" x="182" y="16" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="555" x="20" y="114" width="8" height="14" xoffset="0" yoffset="1" xadvance="9" page="0" chnl="15" />
+ <char id="556" x="121" y="33" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="557" x="29" y="114" width="8" height="14" xoffset="0" yoffset="1" xadvance="9" page="0" chnl="15" />
+ <char id="558" x="134" y="97" width="10" height="14" xoffset="1" yoffset="1" xadvance="12" page="0" chnl="15" />
+ <char id="559" x="32" y="234" width="8" height="11" xoffset="0" yoffset="4" xadvance="9" page="0" chnl="15" />
+ <char id="560" x="88" y="33" width="10" height="15" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="561" x="38" y="114" width="8" height="14" xoffset="0" yoffset="1" xadvance="9" page="0" chnl="15" />
+ <char id="562" x="207" y="96" width="9" height="14" xoffset="0" yoffset="1" xadvance="9" page="0" chnl="15" />
+ <char id="563" x="47" y="113" width="8" height="14" xoffset="-1" yoffset="4" xadvance="7" page="0" chnl="15" />
+ <char id="564" x="124" y="81" width="6" height="15" xoffset="0" yoffset="3" xadvance="6" page="0" chnl="15" />
+ <char id="565" x="180" y="165" width="9" height="12" xoffset="1" yoffset="6" xadvance="11" page="0" chnl="15" />
+ <char id="566" x="224" y="203" width="6" height="12" xoffset="0" yoffset="3" xadvance="6" page="0" chnl="15" />
+ <char id="567" x="223" y="216" width="3" height="12" xoffset="0" yoffset="6" xadvance="4" page="0" chnl="15" />
+ <char id="568" x="169" y="126" width="13" height="12" xoffset="0" yoffset="3" xadvance="14" page="0" chnl="15" />
+ <char id="569" x="183" y="126" width="13" height="12" xoffset="0" yoffset="6" xadvance="14" page="0" chnl="15" />
+ <char id="570" x="28" y="99" width="13" height="14" xoffset="-1" yoffset="2" xadvance="11" page="0" chnl="15" />
+ <char id="571" x="162" y="112" width="10" height="13" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="572" x="131" y="81" width="6" height="15" xoffset="1" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="573" x="144" y="179" width="8" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="574" x="237" y="96" width="9" height="14" xoffset="0" yoffset="2" xadvance="10" page="0" chnl="15" />
+ <char id="575" x="28" y="221" width="6" height="12" xoffset="1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="576" x="160" y="204" width="7" height="12" xoffset="1" yoffset="6" xadvance="8" page="0" chnl="15" />
+ <char id="577" x="162" y="178" width="8" height="12" xoffset="0" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="578" x="89" y="243" width="6" height="9" xoffset="0" yoffset="6" xadvance="7" page="0" chnl="15" />
+ <char id="579" x="191" y="152" width="10" height="12" xoffset="0" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="580" x="78" y="140" width="12" height="12" xoffset="0" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="581" x="224" y="137" width="11" height="12" xoffset="0" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="582" x="177" y="97" width="9" height="14" xoffset="1" yoffset="2" xadvance="11" page="0" chnl="15" />
+ <char id="583" x="109" y="81" width="7" height="15" xoffset="1" yoffset="3" xadvance="9" page="0" chnl="15" />
+ <char id="584" x="189" y="178" width="8" height="12" xoffset="0" yoffset="3" xadvance="8" page="0" chnl="15" />
+ <char id="585" x="210" y="80" width="5" height="15" xoffset="-1" yoffset="3" xadvance="4" page="0" chnl="15" />
+ <char id="586" x="240" y="0" width="13" height="15" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="587" x="202" y="151" width="10" height="12" xoffset="1" yoffset="6" xadvance="9" page="0" chnl="15" />
+ <char id="588" x="39" y="142" width="12" height="12" xoffset="0" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="589" x="40" y="246" width="6" height="9" xoffset="0" yoffset="6" xadvance="5" page="0" chnl="15" />
+ <char id="590" x="30" y="169" width="9" height="12" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="591" x="99" y="179" width="8" height="12" xoffset="0" yoffset="6" xadvance="8" page="0" chnl="15" />
+ </chars>
+ <kernings count="70">
+ <kerning first="32" second="65" amount="-1" />
+ <kerning first="49" second="49" amount="-1" />
+ <kerning first="65" second="32" amount="-1" />
+ <kerning first="65" second="84" amount="-1" />
+ <kerning first="65" second="86" amount="-1" />
+ <kerning first="65" second="87" amount="-1" />
+ <kerning first="65" second="89" amount="-1" />
+ <kerning first="70" second="44" amount="-2" />
+ <kerning first="70" second="46" amount="-2" />
+ <kerning first="70" second="65" amount="-1" />
+ <kerning first="76" second="32" amount="-1" />
+ <kerning first="76" second="84" amount="-1" />
+ <kerning first="76" second="86" amount="-1" />
+ <kerning first="76" second="87" amount="-1" />
+ <kerning first="76" second="89" amount="-1" />
+ <kerning first="76" second="121" amount="-1" />
+ <kerning first="80" second="44" amount="-2" />
+ <kerning first="80" second="46" amount="-2" />
+ <kerning first="80" second="65" amount="-1" />
+ <kerning first="84" second="44" amount="-2" />
+ <kerning first="84" second="45" amount="-1" />
+ <kerning first="84" second="46" amount="-2" />
+ <kerning first="84" second="58" amount="-2" />
+ <kerning first="84" second="65" amount="-1" />
+ <kerning first="84" second="97" amount="-2" />
+ <kerning first="84" second="99" amount="-2" />
+ <kerning first="84" second="101" amount="-2" />
+ <kerning first="84" second="105" amount="-1" />
+ <kerning first="84" second="111" amount="-2" />
+ <kerning first="84" second="114" amount="-1" />
+ <kerning first="84" second="115" amount="-2" />
+ <kerning first="84" second="117" amount="-1" />
+ <kerning first="84" second="119" amount="-1" />
+ <kerning first="84" second="121" amount="-1" />
+ <kerning first="86" second="44" amount="-1" />
+ <kerning first="86" second="45" amount="-1" />
+ <kerning first="86" second="46" amount="-1" />
+ <kerning first="86" second="58" amount="-1" />
+ <kerning first="86" second="65" amount="-1" />
+ <kerning first="86" second="97" amount="-1" />
+ <kerning first="86" second="101" amount="-1" />
+ <kerning first="86" second="111" amount="-1" />
+ <kerning first="86" second="114" amount="-1" />
+ <kerning first="86" second="117" amount="-1" />
+ <kerning first="86" second="121" amount="-1" />
+ <kerning first="87" second="44" amount="-1" />
+ <kerning first="87" second="46" amount="-1" />
+ <kerning first="87" second="65" amount="-1" />
+ <kerning first="87" second="97" amount="-1" />
+ <kerning first="89" second="44" amount="-2" />
+ <kerning first="89" second="45" amount="-1" />
+ <kerning first="89" second="46" amount="-2" />
+ <kerning first="89" second="58" amount="-1" />
+ <kerning first="89" second="65" amount="-1" />
+ <kerning first="89" second="97" amount="-1" />
+ <kerning first="89" second="101" amount="-1" />
+ <kerning first="89" second="105" amount="-1" />
+ <kerning first="89" second="111" amount="-1" />
+ <kerning first="89" second="112" amount="-1" />
+ <kerning first="89" second="113" amount="-1" />
+ <kerning first="89" second="117" amount="-1" />
+ <kerning first="89" second="118" amount="-1" />
+ <kerning first="114" second="44" amount="-1" />
+ <kerning first="114" second="46" amount="-1" />
+ <kerning first="118" second="44" amount="-1" />
+ <kerning first="118" second="46" amount="-1" />
+ <kerning first="119" second="44" amount="-1" />
+ <kerning first="119" second="46" amount="-1" />
+ <kerning first="121" second="44" amount="-1" />
+ <kerning first="121" second="46" amount="-1" />
+ </kernings>
+</font>
diff --git a/ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-18-regular_0.png b/ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-18-regular_0.png Binary files differnew file mode 100644 index 0000000..3d41a54 --- /dev/null +++ b/ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-18-regular_0.png diff --git a/ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-24-bold.fnt b/ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-24-bold.fnt new file mode 100644 index 0000000..66140e7 --- /dev/null +++ b/ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-24-bold.fnt @@ -0,0 +1,610 @@ +<?xml version="1.0"?>
+<font>
+ <info face="Arial" size="24" bold="1" italic="0" charset="" unicode="1" stretchH="100" smooth="1" aa="1" padding="0,0,0,0" spacing="1,1" outline="0"/>
+ <common lineHeight="24" base="19" scaleW="512" scaleH="256" pages="1" packed="0" alphaChnl="0" redChnl="4" greenChnl="4" blueChnl="4"/>
+ <pages>
+ <page id="0" file="arial-24-bold_0.png" />
+ </pages>
+ <chars count="527">
+ <char id="32" x="508" y="56" width="1" height="1" xoffset="0" yoffset="19" xadvance="6" page="0" chnl="15" />
+ <char id="33" x="508" y="111" width="3" height="15" xoffset="2" yoffset="4" xadvance="7" page="0" chnl="15" />
+ <char id="34" x="439" y="193" width="7" height="5" xoffset="1" yoffset="4" xadvance="9" page="0" chnl="15" />
+ <char id="35" x="406" y="130" width="11" height="15" xoffset="0" yoffset="4" xadvance="11" page="0" chnl="15" />
+ <char id="36" x="346" y="79" width="9" height="18" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="37" x="483" y="78" width="15" height="16" xoffset="1" yoffset="4" xadvance="17" page="0" chnl="15" />
+ <char id="38" x="326" y="114" width="13" height="15" xoffset="1" yoffset="4" xadvance="14" page="0" chnl="15" />
+ <char id="39" x="447" y="192" width="3" height="5" xoffset="1" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="40" x="355" y="40" width="5" height="19" xoffset="1" yoffset="4" xadvance="7" page="0" chnl="15" />
+ <char id="41" x="361" y="40" width="5" height="19" xoffset="1" yoffset="4" xadvance="7" page="0" chnl="15" />
+ <char id="42" x="374" y="193" width="8" height="8" xoffset="0" yoffset="4" xadvance="8" page="0" chnl="15" />
+ <char id="43" x="77" y="197" width="11" height="11" xoffset="1" yoffset="6" xadvance="12" page="0" chnl="15" />
+ <char id="44" x="435" y="193" width="3" height="6" xoffset="1" yoffset="16" xadvance="6" page="0" chnl="15" />
+ <char id="45" x="476" y="191" width="6" height="3" xoffset="1" yoffset="12" xadvance="7" page="0" chnl="15" />
+ <char id="46" x="497" y="188" width="3" height="3" xoffset="1" yoffset="16" xadvance="6" page="0" chnl="15" />
+ <char id="47" x="476" y="160" width="6" height="15" xoffset="0" yoffset="4" xadvance="6" page="0" chnl="15" />
+ <char id="48" x="53" y="100" width="9" height="16" xoffset="1" yoffset="4" xadvance="11" page="0" chnl="15" />
+ <char id="49" x="454" y="161" width="7" height="15" xoffset="1" yoffset="4" xadvance="11" page="0" chnl="15" />
+ <char id="50" x="283" y="162" width="9" height="15" xoffset="1" yoffset="4" xadvance="11" page="0" chnl="15" />
+ <char id="51" x="293" y="162" width="9" height="15" xoffset="1" yoffset="4" xadvance="11" page="0" chnl="15" />
+ <char id="52" x="382" y="130" width="11" height="15" xoffset="0" yoffset="4" xadvance="11" page="0" chnl="15" />
+ <char id="53" x="303" y="162" width="9" height="15" xoffset="1" yoffset="4" xadvance="11" page="0" chnl="15" />
+ <char id="54" x="313" y="162" width="9" height="15" xoffset="1" yoffset="4" xadvance="11" page="0" chnl="15" />
+ <char id="55" x="323" y="162" width="9" height="15" xoffset="1" yoffset="4" xadvance="11" page="0" chnl="15" />
+ <char id="56" x="333" y="162" width="9" height="15" xoffset="1" yoffset="4" xadvance="11" page="0" chnl="15" />
+ <char id="57" x="502" y="127" width="9" height="15" xoffset="1" yoffset="4" xadvance="11" page="0" chnl="15" />
+ <char id="58" x="507" y="176" width="3" height="11" xoffset="2" yoffset="8" xadvance="7" page="0" chnl="15" />
+ <char id="59" x="461" y="177" width="3" height="14" xoffset="2" yoffset="8" xadvance="7" page="0" chnl="15" />
+ <char id="60" x="170" y="194" width="10" height="11" xoffset="1" yoffset="6" xadvance="12" page="0" chnl="15" />
+ <char id="61" x="352" y="193" width="10" height="8" xoffset="1" yoffset="8" xadvance="12" page="0" chnl="15" />
+ <char id="62" x="148" y="194" width="10" height="11" xoffset="1" yoffset="6" xadvance="12" page="0" chnl="15" />
+ <char id="63" x="92" y="148" width="10" height="15" xoffset="1" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="64" x="40" y="0" width="19" height="20" xoffset="1" yoffset="4" xadvance="20" page="0" chnl="15" />
+ <char id="65" x="368" y="114" width="13" height="15" xoffset="0" yoffset="4" xadvance="13" page="0" chnl="15" />
+ <char id="66" x="54" y="134" width="12" height="15" xoffset="1" yoffset="4" xadvance="14" page="0" chnl="15" />
+ <char id="67" x="145" y="131" width="12" height="15" xoffset="1" yoffset="4" xadvance="14" page="0" chnl="15" />
+ <char id="68" x="28" y="134" width="12" height="15" xoffset="1" yoffset="4" xadvance="14" page="0" chnl="15" />
+ <char id="69" x="418" y="130" width="11" height="15" xoffset="1" yoffset="4" xadvance="13" page="0" chnl="15" />
+ <char id="70" x="466" y="144" width="10" height="15" xoffset="1" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="71" x="191" y="114" width="14" height="15" xoffset="1" yoffset="4" xadvance="16" page="0" chnl="15" />
+ <char id="72" x="249" y="130" width="12" height="15" xoffset="1" yoffset="4" xadvance="14" page="0" chnl="15" />
+ <char id="73" x="34" y="182" width="3" height="15" xoffset="1" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="74" x="81" y="148" width="10" height="15" xoffset="0" yoffset="4" xadvance="11" page="0" chnl="15" />
+ <char id="75" x="354" y="114" width="13" height="15" xoffset="1" yoffset="4" xadvance="14" page="0" chnl="15" />
+ <char id="76" x="444" y="145" width="10" height="15" xoffset="1" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="77" x="66" y="116" width="15" height="15" xoffset="1" yoffset="4" xadvance="17" page="0" chnl="15" />
+ <char id="78" x="210" y="130" width="12" height="15" xoffset="1" yoffset="4" xadvance="14" page="0" chnl="15" />
+ <char id="79" x="251" y="114" width="14" height="15" xoffset="1" yoffset="4" xadvance="16" page="0" chnl="15" />
+ <char id="80" x="274" y="130" width="11" height="15" xoffset="1" yoffset="4" xadvance="13" page="0" chnl="15" />
+ <char id="81" x="0" y="101" width="15" height="16" xoffset="1" yoffset="4" xadvance="16" page="0" chnl="15" />
+ <char id="82" x="236" y="130" width="12" height="15" xoffset="1" yoffset="4" xadvance="14" page="0" chnl="15" />
+ <char id="83" x="394" y="130" width="11" height="15" xoffset="1" yoffset="4" xadvance="13" page="0" chnl="15" />
+ <char id="84" x="430" y="129" width="11" height="15" xoffset="1" yoffset="4" xadvance="13" page="0" chnl="15" />
+ <char id="85" x="41" y="134" width="12" height="15" xoffset="1" yoffset="4" xadvance="14" page="0" chnl="15" />
+ <char id="86" x="14" y="134" width="13" height="15" xoffset="0" yoffset="4" xadvance="13" page="0" chnl="15" />
+ <char id="87" x="254" y="98" width="19" height="15" xoffset="0" yoffset="4" xadvance="19" page="0" chnl="15" />
+ <char id="88" x="494" y="111" width="13" height="15" xoffset="0" yoffset="4" xadvance="13" page="0" chnl="15" />
+ <char id="89" x="130" y="115" width="15" height="15" xoffset="-1" yoffset="4" xadvance="13" page="0" chnl="15" />
+ <char id="90" x="454" y="129" width="11" height="15" xoffset="0" yoffset="4" xadvance="11" page="0" chnl="15" />
+ <char id="91" x="379" y="40" width="5" height="19" xoffset="1" yoffset="4" xadvance="7" page="0" chnl="15" />
+ <char id="92" x="462" y="161" width="6" height="15" xoffset="0" yoffset="4" xadvance="6" page="0" chnl="15" />
+ <char id="93" x="373" y="40" width="5" height="19" xoffset="1" yoffset="4" xadvance="7" page="0" chnl="15" />
+ <char id="94" x="363" y="193" width="10" height="8" xoffset="1" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="95" x="12" y="210" width="11" height="2" xoffset="0" yoffset="21" xadvance="11" page="0" chnl="15" />
+ <char id="96" x="488" y="190" width="4" height="3" xoffset="0" yoffset="4" xadvance="7" page="0" chnl="15" />
+ <char id="97" x="181" y="194" width="10" height="11" xoffset="1" yoffset="8" xadvance="11" page="0" chnl="15" />
+ <char id="98" x="400" y="146" width="10" height="15" xoffset="1" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="99" x="234" y="193" width="9" height="11" xoffset="1" yoffset="8" xadvance="11" page="0" chnl="15" />
+ <char id="100" x="411" y="146" width="10" height="15" xoffset="1" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="101" x="254" y="193" width="9" height="11" xoffset="1" yoffset="8" xadvance="11" page="0" chnl="15" />
+ <char id="102" x="438" y="161" width="7" height="15" xoffset="0" yoffset="4" xadvance="7" page="0" chnl="15" />
+ <char id="103" x="33" y="166" width="10" height="15" xoffset="1" yoffset="8" xadvance="12" page="0" chnl="15" />
+ <char id="104" x="455" y="145" width="10" height="15" xoffset="1" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="105" x="22" y="182" width="3" height="15" xoffset="1" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="106" x="385" y="40" width="5" height="19" xoffset="-1" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="107" x="477" y="144" width="10" height="15" xoffset="1" yoffset="4" xadvance="11" page="0" chnl="15" />
+ <char id="108" x="26" y="182" width="3" height="15" xoffset="1" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="109" x="33" y="198" width="15" height="11" xoffset="1" yoffset="8" xadvance="17" page="0" chnl="15" />
+ <char id="110" x="192" y="194" width="10" height="11" xoffset="1" yoffset="8" xadvance="12" page="0" chnl="15" />
+ <char id="111" x="159" y="194" width="10" height="11" xoffset="1" yoffset="8" xadvance="12" page="0" chnl="15" />
+ <char id="112" x="77" y="164" width="10" height="15" xoffset="1" yoffset="8" xadvance="12" page="0" chnl="15" />
+ <char id="113" x="88" y="164" width="10" height="15" xoffset="1" yoffset="8" xadvance="12" page="0" chnl="15" />
+ <char id="114" x="310" y="193" width="7" height="11" xoffset="1" yoffset="8" xadvance="8" page="0" chnl="15" />
+ <char id="115" x="214" y="193" width="9" height="11" xoffset="1" yoffset="8" xadvance="11" page="0" chnl="15" />
+ <char id="116" x="483" y="160" width="6" height="15" xoffset="0" yoffset="4" xadvance="7" page="0" chnl="15" />
+ <char id="117" x="137" y="194" width="10" height="11" xoffset="1" yoffset="8" xadvance="12" page="0" chnl="15" />
+ <char id="118" x="101" y="195" width="11" height="11" xoffset="0" yoffset="8" xadvance="11" page="0" chnl="15" />
+ <char id="119" x="17" y="198" width="15" height="11" xoffset="0" yoffset="8" xadvance="15" page="0" chnl="15" />
+ <char id="120" x="89" y="195" width="11" height="11" xoffset="0" yoffset="8" xadvance="11" page="0" chnl="15" />
+ <char id="121" x="410" y="114" width="13" height="15" xoffset="-1" yoffset="8" xadvance="11" page="0" chnl="15" />
+ <char id="122" x="274" y="193" width="8" height="11" xoffset="1" yoffset="8" xadvance="10" page="0" chnl="15" />
+ <char id="123" x="316" y="40" width="7" height="19" xoffset="1" yoffset="4" xadvance="8" page="0" chnl="15" />
+ <char id="124" x="423" y="40" width="2" height="19" xoffset="2" yoffset="4" xadvance="6" page="0" chnl="15" />
+ <char id="125" x="340" y="40" width="7" height="19" xoffset="0" yoffset="4" xadvance="8" page="0" chnl="15" />
+ <char id="126" x="451" y="192" width="11" height="4" xoffset="0" yoffset="10" xadvance="12" page="0" chnl="15" />
+ <char id="160" x="510" y="0" width="1" height="1" xoffset="0" yoffset="19" xadvance="6" page="0" chnl="15" />
+ <char id="161" x="508" y="40" width="3" height="15" xoffset="2" yoffset="8" xadvance="7" page="0" chnl="15" />
+ <char id="162" x="96" y="41" width="10" height="19" xoffset="1" yoffset="4" xadvance="11" page="0" chnl="15" />
+ <char id="163" x="213" y="146" width="10" height="15" xoffset="0" yoffset="4" xadvance="11" page="0" chnl="15" />
+ <char id="164" x="113" y="195" width="11" height="11" xoffset="0" yoffset="7" xadvance="11" page="0" chnl="15" />
+ <char id="165" x="334" y="130" width="11" height="15" xoffset="0" yoffset="4" xadvance="11" page="0" chnl="15" />
+ <char id="166" x="420" y="40" width="2" height="19" xoffset="2" yoffset="4" xadvance="6" page="0" chnl="15" />
+ <char id="167" x="217" y="40" width="10" height="19" xoffset="0" yoffset="4" xadvance="11" page="0" chnl="15" />
+ <char id="168" x="501" y="188" width="6" height="2" xoffset="0" yoffset="4" xadvance="7" page="0" chnl="15" />
+ <char id="169" x="98" y="115" width="15" height="15" xoffset="0" yoffset="4" xadvance="15" page="0" chnl="15" />
+ <char id="170" x="423" y="193" width="6" height="7" xoffset="0" yoffset="4" xadvance="7" page="0" chnl="15" />
+ <char id="171" x="322" y="193" width="9" height="9" xoffset="1" yoffset="9" xadvance="11" page="0" chnl="15" />
+ <char id="172" x="383" y="193" width="10" height="7" xoffset="1" yoffset="8" xadvance="12" page="0" chnl="15" />
+ <char id="173" x="469" y="191" width="6" height="3" xoffset="1" yoffset="12" xadvance="7" page="0" chnl="15" />
+ <char id="174" x="50" y="118" width="15" height="15" xoffset="0" yoffset="4" xadvance="15" page="0" chnl="15" />
+ <char id="175" x="0" y="210" width="11" height="2" xoffset="0" yoffset="2" xadvance="11" page="0" chnl="15" />
+ <char id="176" x="394" y="193" width="7" height="7" xoffset="1" yoffset="4" xadvance="8" page="0" chnl="15" />
+ <char id="177" x="298" y="130" width="11" height="15" xoffset="0" yoffset="4" xadvance="11" page="0" chnl="15" />
+ <char id="178" x="416" y="193" width="6" height="7" xoffset="0" yoffset="4" xadvance="7" page="0" chnl="15" />
+ <char id="179" x="402" y="193" width="6" height="7" xoffset="0" yoffset="4" xadvance="7" page="0" chnl="15" />
+ <char id="180" x="483" y="190" width="4" height="3" xoffset="2" yoffset="4" xadvance="7" page="0" chnl="15" />
+ <char id="181" x="235" y="146" width="10" height="15" xoffset="1" yoffset="8" xadvance="12" page="0" chnl="15" />
+ <char id="182" x="214" y="79" width="10" height="18" xoffset="0" yoffset="4" xadvance="11" page="0" chnl="15" />
+ <char id="183" x="493" y="188" width="3" height="3" xoffset="2" yoffset="10" xadvance="7" page="0" chnl="15" />
+ <char id="184" x="463" y="192" width="5" height="4" xoffset="0" yoffset="19" xadvance="6" page="0" chnl="15" />
+ <char id="185" x="430" y="193" width="4" height="7" xoffset="1" yoffset="4" xadvance="7" page="0" chnl="15" />
+ <char id="186" x="409" y="193" width="6" height="7" xoffset="1" yoffset="4" xadvance="7" page="0" chnl="15" />
+ <char id="187" x="332" y="193" width="9" height="9" xoffset="1" yoffset="9" xadvance="11" page="0" chnl="15" />
+ <char id="188" x="438" y="97" width="16" height="15" xoffset="1" yoffset="4" xadvance="17" page="0" chnl="15" />
+ <char id="189" x="489" y="95" width="16" height="15" xoffset="0" yoffset="4" xadvance="17" page="0" chnl="15" />
+ <char id="190" x="386" y="98" width="17" height="15" xoffset="0" yoffset="4" xadvance="17" page="0" chnl="15" />
+ <char id="191" x="55" y="166" width="10" height="15" xoffset="1" yoffset="8" xadvance="12" page="0" chnl="15" />
+ <char id="192" x="126" y="21" width="13" height="19" xoffset="0" yoffset="0" xadvance="14" page="0" chnl="15" />
+ <char id="193" x="28" y="22" width="13" height="19" xoffset="0" yoffset="0" xadvance="14" page="0" chnl="15" />
+ <char id="194" x="167" y="60" width="13" height="18" xoffset="0" yoffset="1" xadvance="14" page="0" chnl="15" />
+ <char id="195" x="84" y="21" width="13" height="19" xoffset="0" yoffset="0" xadvance="14" page="0" chnl="15" />
+ <char id="196" x="237" y="60" width="13" height="18" xoffset="0" yoffset="1" xadvance="14" page="0" chnl="15" />
+ <char id="197" x="251" y="60" width="13" height="18" xoffset="0" yoffset="1" xadvance="14" page="0" chnl="15" />
+ <char id="198" x="191" y="98" width="20" height="15" xoffset="-1" yoffset="4" xadvance="20" page="0" chnl="15" />
+ <char id="199" x="413" y="20" width="12" height="19" xoffset="1" yoffset="4" xadvance="14" page="0" chnl="15" />
+ <char id="200" x="72" y="41" width="11" height="19" xoffset="1" yoffset="0" xadvance="13" page="0" chnl="15" />
+ <char id="201" x="463" y="20" width="11" height="19" xoffset="1" yoffset="0" xadvance="13" page="0" chnl="15" />
+ <char id="202" x="135" y="80" width="11" height="18" xoffset="1" yoffset="1" xadvance="13" page="0" chnl="15" />
+ <char id="203" x="147" y="80" width="11" height="18" xoffset="1" yoffset="1" xadvance="13" page="0" chnl="15" />
+ <char id="204" x="406" y="40" width="4" height="19" xoffset="0" yoffset="0" xadvance="6" page="0" chnl="15" />
+ <char id="205" x="411" y="40" width="4" height="19" xoffset="1" yoffset="0" xadvance="6" page="0" chnl="15" />
+ <char id="206" x="372" y="79" width="7" height="18" xoffset="-1" yoffset="1" xadvance="6" page="0" chnl="15" />
+ <char id="207" x="394" y="79" width="6" height="18" xoffset="0" yoffset="1" xadvance="6" page="0" chnl="15" />
+ <char id="208" x="424" y="113" width="13" height="15" xoffset="0" yoffset="4" xadvance="14" page="0" chnl="15" />
+ <char id="209" x="374" y="20" width="12" height="19" xoffset="1" yoffset="0" xadvance="14" page="0" chnl="15" />
+ <char id="210" x="405" y="0" width="14" height="19" xoffset="1" yoffset="0" xadvance="16" page="0" chnl="15" />
+ <char id="211" x="465" y="0" width="14" height="19" xoffset="1" yoffset="0" xadvance="16" page="0" chnl="15" />
+ <char id="212" x="92" y="61" width="14" height="18" xoffset="1" yoffset="1" xadvance="16" page="0" chnl="15" />
+ <char id="213" x="285" y="0" width="14" height="19" xoffset="1" yoffset="0" xadvance="16" page="0" chnl="15" />
+ <char id="214" x="32" y="63" width="14" height="18" xoffset="1" yoffset="1" xadvance="16" page="0" chnl="15" />
+ <char id="215" x="342" y="193" width="9" height="9" xoffset="1" yoffset="8" xadvance="12" page="0" chnl="15" />
+ <char id="216" x="425" y="79" width="16" height="17" xoffset="0" yoffset="3" xadvance="16" page="0" chnl="15" />
+ <char id="217" x="179" y="20" width="12" height="19" xoffset="1" yoffset="0" xadvance="14" page="0" chnl="15" />
+ <char id="218" x="166" y="20" width="12" height="19" xoffset="1" yoffset="0" xadvance="14" page="0" chnl="15" />
+ <char id="219" x="490" y="59" width="12" height="18" xoffset="1" yoffset="1" xadvance="14" page="0" chnl="15" />
+ <char id="220" x="13" y="82" width="12" height="18" xoffset="1" yoffset="1" xadvance="14" page="0" chnl="15" />
+ <char id="221" x="238" y="0" width="15" height="19" xoffset="-1" yoffset="0" xadvance="13" page="0" chnl="15" />
+ <char id="222" x="389" y="146" width="10" height="15" xoffset="2" yoffset="4" xadvance="13" page="0" chnl="15" />
+ <char id="223" x="378" y="146" width="10" height="15" xoffset="1" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="224" x="367" y="146" width="10" height="15" xoffset="1" yoffset="4" xadvance="11" page="0" chnl="15" />
+ <char id="225" x="356" y="146" width="10" height="15" xoffset="1" yoffset="4" xadvance="11" page="0" chnl="15" />
+ <char id="226" x="97" y="180" width="10" height="14" xoffset="1" yoffset="5" xadvance="11" page="0" chnl="15" />
+ <char id="227" x="323" y="146" width="10" height="15" xoffset="1" yoffset="4" xadvance="11" page="0" chnl="15" />
+ <char id="228" x="86" y="180" width="10" height="14" xoffset="1" yoffset="5" xadvance="11" page="0" chnl="15" />
+ <char id="229" x="499" y="78" width="10" height="16" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15" />
+ <char id="230" x="0" y="198" width="16" height="11" xoffset="1" yoffset="8" xadvance="18" page="0" chnl="15" />
+ <char id="231" x="143" y="163" width="9" height="15" xoffset="1" yoffset="8" xadvance="11" page="0" chnl="15" />
+ <char id="232" x="153" y="163" width="9" height="15" xoffset="1" yoffset="4" xadvance="11" page="0" chnl="15" />
+ <char id="233" x="163" y="163" width="9" height="15" xoffset="1" yoffset="4" xadvance="11" page="0" chnl="15" />
+ <char id="234" x="374" y="178" width="9" height="14" xoffset="1" yoffset="5" xadvance="11" page="0" chnl="15" />
+ <char id="235" x="304" y="178" width="9" height="14" xoffset="1" yoffset="5" xadvance="11" page="0" chnl="15" />
+ <char id="236" x="17" y="182" width="4" height="15" xoffset="0" yoffset="4" xadvance="6" page="0" chnl="15" />
+ <char id="237" x="12" y="182" width="4" height="15" xoffset="1" yoffset="4" xadvance="6" page="0" chnl="15" />
+ <char id="238" x="418" y="178" width="7" height="14" xoffset="-1" yoffset="5" xadvance="6" page="0" chnl="15" />
+ <char id="239" x="441" y="177" width="6" height="14" xoffset="0" yoffset="5" xadvance="6" page="0" chnl="15" />
+ <char id="240" x="312" y="146" width="10" height="15" xoffset="1" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="241" x="202" y="146" width="10" height="15" xoffset="1" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="242" x="191" y="146" width="10" height="15" xoffset="1" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="243" x="180" y="147" width="10" height="15" xoffset="1" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="244" x="75" y="182" width="10" height="14" xoffset="1" yoffset="5" xadvance="12" page="0" chnl="15" />
+ <char id="245" x="169" y="147" width="10" height="15" xoffset="1" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="246" x="251" y="178" width="10" height="14" xoffset="1" yoffset="5" xadvance="12" page="0" chnl="15" />
+ <char id="247" x="125" y="194" width="11" height="11" xoffset="0" yoffset="6" xadvance="11" page="0" chnl="15" />
+ <char id="248" x="478" y="176" width="10" height="13" xoffset="1" yoffset="7" xadvance="12" page="0" chnl="15" />
+ <char id="249" x="290" y="146" width="10" height="15" xoffset="1" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="250" x="147" y="147" width="10" height="15" xoffset="1" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="251" x="174" y="179" width="10" height="14" xoffset="1" yoffset="5" xadvance="12" page="0" chnl="15" />
+ <char id="252" x="163" y="179" width="10" height="14" xoffset="1" yoffset="5" xadvance="12" page="0" chnl="15" />
+ <char id="253" x="42" y="21" width="13" height="19" xoffset="-1" yoffset="4" xadvance="11" page="0" chnl="15" />
+ <char id="254" x="184" y="40" width="10" height="19" xoffset="1" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="255" x="209" y="60" width="13" height="18" xoffset="-1" yoffset="5" xadvance="11" page="0" chnl="15" />
+ <char id="256" x="195" y="60" width="13" height="18" xoffset="0" yoffset="1" xadvance="13" page="0" chnl="15" />
+ <char id="257" x="152" y="179" width="10" height="14" xoffset="1" yoffset="5" xadvance="11" page="0" chnl="15" />
+ <char id="258" x="181" y="60" width="13" height="18" xoffset="0" yoffset="1" xadvance="13" page="0" chnl="15" />
+ <char id="259" x="119" y="179" width="10" height="14" xoffset="1" yoffset="5" xadvance="11" page="0" chnl="15" />
+ <char id="260" x="495" y="0" width="14" height="19" xoffset="0" yoffset="4" xadvance="13" page="0" chnl="15" />
+ <char id="261" x="466" y="128" width="11" height="15" xoffset="1" yoffset="8" xadvance="11" page="0" chnl="15" />
+ <char id="262" x="192" y="20" width="12" height="19" xoffset="1" yoffset="0" xadvance="14" page="0" chnl="15" />
+ <char id="263" x="233" y="162" width="9" height="15" xoffset="1" yoffset="4" xadvance="11" page="0" chnl="15" />
+ <char id="264" x="26" y="82" width="12" height="18" xoffset="1" yoffset="1" xadvance="14" page="0" chnl="15" />
+ <char id="265" x="314" y="178" width="9" height="14" xoffset="1" yoffset="5" xadvance="11" page="0" chnl="15" />
+ <char id="266" x="296" y="20" width="12" height="19" xoffset="1" yoffset="0" xadvance="14" page="0" chnl="15" />
+ <char id="267" x="173" y="163" width="9" height="15" xoffset="1" yoffset="4" xadvance="11" page="0" chnl="15" />
+ <char id="268" x="464" y="59" width="12" height="18" xoffset="1" yoffset="1" xadvance="14" page="0" chnl="15" />
+ <char id="269" x="324" y="178" width="9" height="14" xoffset="1" yoffset="5" xadvance="11" page="0" chnl="15" />
+ <char id="270" x="477" y="59" width="12" height="18" xoffset="1" yoffset="1" xadvance="14" page="0" chnl="15" />
+ <char id="271" x="266" y="114" width="14" height="15" xoffset="1" yoffset="4" xadvance="14" page="0" chnl="15" />
+ <char id="272" x="438" y="113" width="13" height="15" xoffset="0" yoffset="4" xadvance="14" page="0" chnl="15" />
+ <char id="273" x="12" y="150" width="11" height="15" xoffset="1" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="274" x="87" y="80" width="11" height="18" xoffset="1" yoffset="1" xadvance="13" page="0" chnl="15" />
+ <char id="275" x="334" y="178" width="9" height="14" xoffset="1" yoffset="5" xadvance="11" page="0" chnl="15" />
+ <char id="276" x="111" y="80" width="11" height="18" xoffset="1" yoffset="1" xadvance="13" page="0" chnl="15" />
+ <char id="277" x="344" y="178" width="9" height="14" xoffset="1" yoffset="5" xadvance="11" page="0" chnl="15" />
+ <char id="278" x="487" y="20" width="11" height="19" xoffset="1" yoffset="0" xadvance="13" page="0" chnl="15" />
+ <char id="279" x="183" y="163" width="9" height="15" xoffset="1" yoffset="4" xadvance="11" page="0" chnl="15" />
+ <char id="280" x="451" y="20" width="11" height="19" xoffset="1" yoffset="4" xadvance="13" page="0" chnl="15" />
+ <char id="281" x="223" y="162" width="9" height="15" xoffset="1" yoffset="8" xadvance="11" page="0" chnl="15" />
+ <char id="282" x="75" y="80" width="11" height="18" xoffset="1" yoffset="1" xadvance="13" page="0" chnl="15" />
+ <char id="283" x="364" y="178" width="9" height="14" xoffset="1" yoffset="5" xadvance="11" page="0" chnl="15" />
+ <char id="284" x="62" y="61" width="14" height="18" xoffset="1" yoffset="1" xadvance="16" page="0" chnl="15" />
+ <char id="285" x="192" y="79" width="10" height="18" xoffset="1" yoffset="5" xadvance="12" page="0" chnl="15" />
+ <char id="286" x="77" y="61" width="14" height="18" xoffset="1" yoffset="1" xadvance="16" page="0" chnl="15" />
+ <char id="287" x="335" y="79" width="10" height="18" xoffset="1" yoffset="5" xadvance="12" page="0" chnl="15" />
+ <char id="288" x="375" y="0" width="14" height="19" xoffset="1" yoffset="0" xadvance="16" page="0" chnl="15" />
+ <char id="289" x="173" y="40" width="10" height="19" xoffset="1" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="290" x="450" y="0" width="14" height="19" xoffset="1" yoffset="4" xadvance="16" page="0" chnl="15" />
+ <char id="291" x="101" y="0" width="10" height="20" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="292" x="0" y="82" width="12" height="18" xoffset="1" yoffset="1" xadvance="14" page="0" chnl="15" />
+ <char id="293" x="280" y="79" width="10" height="18" xoffset="1" yoffset="1" xadvance="12" page="0" chnl="15" />
+ <char id="294" x="206" y="114" width="14" height="15" xoffset="0" yoffset="4" xadvance="14" page="0" chnl="15" />
+ <char id="295" x="346" y="130" width="11" height="15" xoffset="0" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="296" x="324" y="40" width="7" height="19" xoffset="-1" yoffset="0" xadvance="5" page="0" chnl="15" />
+ <char id="297" x="398" y="162" width="7" height="15" xoffset="-1" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="298" x="387" y="79" width="6" height="18" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="299" x="434" y="178" width="6" height="14" xoffset="0" yoffset="5" xadvance="5" page="0" chnl="15" />
+ <char id="300" x="380" y="79" width="6" height="18" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="301" x="448" y="177" width="6" height="14" xoffset="0" yoffset="5" xadvance="5" page="0" chnl="15" />
+ <char id="302" x="401" y="40" width="4" height="19" xoffset="1" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="303" x="396" y="40" width="4" height="19" xoffset="1" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="304" x="416" y="40" width="3" height="19" xoffset="1" yoffset="0" xadvance="5" page="0" chnl="15" />
+ <char id="305" x="318" y="193" width="3" height="11" xoffset="1" yoffset="8" xadvance="5" page="0" chnl="15" />
+ <char id="306" x="176" y="114" width="14" height="15" xoffset="1" yoffset="4" xadvance="16" page="0" chnl="15" />
+ <char id="307" x="260" y="40" width="9" height="19" xoffset="1" yoffset="4" xadvance="11" page="0" chnl="15" />
+ <char id="308" x="399" y="60" width="12" height="18" xoffset="0" yoffset="1" xadvance="11" page="0" chnl="15" />
+ <char id="309" x="364" y="79" width="7" height="18" xoffset="-1" yoffset="5" xadvance="5" page="0" chnl="15" />
+ <char id="310" x="56" y="21" width="13" height="19" xoffset="1" yoffset="4" xadvance="14" page="0" chnl="15" />
+ <char id="311" x="151" y="40" width="10" height="19" xoffset="1" yoffset="4" xadvance="11" page="0" chnl="15" />
+ <char id="312" x="203" y="193" width="10" height="11" xoffset="1" yoffset="8" xadvance="11" page="0" chnl="15" />
+ <char id="313" x="118" y="41" width="10" height="19" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="314" x="391" y="40" width="4" height="19" xoffset="1" yoffset="0" xadvance="5" page="0" chnl="15" />
+ <char id="315" x="162" y="40" width="10" height="19" xoffset="1" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="316" x="367" y="40" width="5" height="19" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="317" x="48" y="150" width="10" height="15" xoffset="1" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="318" x="446" y="161" width="7" height="15" xoffset="1" yoffset="4" xadvance="8" page="0" chnl="15" />
+ <char id="319" x="44" y="166" width="10" height="15" xoffset="1" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="320" x="414" y="162" width="7" height="15" xoffset="1" yoffset="4" xadvance="10" page="0" chnl="15" />
+ <char id="321" x="93" y="131" width="12" height="15" xoffset="-1" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="322" x="497" y="160" width="5" height="15" xoffset="0" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="323" x="348" y="20" width="12" height="19" xoffset="1" yoffset="0" xadvance="14" page="0" chnl="15" />
+ <char id="324" x="257" y="146" width="10" height="15" xoffset="1" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="325" x="309" y="20" width="12" height="19" xoffset="1" yoffset="4" xadvance="14" page="0" chnl="15" />
+ <char id="326" x="224" y="146" width="10" height="15" xoffset="1" yoffset="8" xadvance="12" page="0" chnl="15" />
+ <char id="327" x="438" y="59" width="12" height="18" xoffset="1" yoffset="1" xadvance="14" page="0" chnl="15" />
+ <char id="328" x="218" y="178" width="10" height="14" xoffset="1" yoffset="5" xadvance="12" page="0" chnl="15" />
+ <char id="329" x="296" y="114" width="14" height="15" xoffset="-1" yoffset="4" xadvance="14" page="0" chnl="15" />
+ <char id="330" x="106" y="131" width="12" height="15" xoffset="1" yoffset="4" xadvance="14" page="0" chnl="15" />
+ <char id="331" x="110" y="163" width="10" height="15" xoffset="1" yoffset="8" xadvance="12" page="0" chnl="15" />
+ <char id="332" x="47" y="62" width="14" height="18" xoffset="1" yoffset="1" xadvance="16" page="0" chnl="15" />
+ <char id="333" x="229" y="178" width="10" height="14" xoffset="1" yoffset="5" xadvance="12" page="0" chnl="15" />
+ <char id="334" x="152" y="60" width="14" height="18" xoffset="1" yoffset="1" xadvance="16" page="0" chnl="15" />
+ <char id="335" x="207" y="178" width="10" height="14" xoffset="1" yoffset="5" xadvance="12" page="0" chnl="15" />
+ <char id="336" x="435" y="0" width="14" height="19" xoffset="1" yoffset="0" xadvance="16" page="0" chnl="15" />
+ <char id="337" x="433" y="145" width="10" height="15" xoffset="1" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="338" x="274" y="98" width="19" height="15" xoffset="0" yoffset="4" xadvance="20" page="0" chnl="15" />
+ <char id="339" x="489" y="176" width="17" height="11" xoffset="1" yoffset="8" xadvance="19" page="0" chnl="15" />
+ <char id="340" x="231" y="20" width="12" height="19" xoffset="1" yoffset="0" xadvance="14" page="0" chnl="15" />
+ <char id="341" x="422" y="162" width="7" height="15" xoffset="1" yoffset="4" xadvance="8" page="0" chnl="15" />
+ <char id="342" x="400" y="20" width="12" height="19" xoffset="1" yoffset="4" xadvance="14" page="0" chnl="15" />
+ <char id="343" x="430" y="162" width="7" height="15" xoffset="1" yoffset="8" xadvance="8" page="0" chnl="15" />
+ <char id="344" x="451" y="59" width="12" height="18" xoffset="1" yoffset="1" xadvance="14" page="0" chnl="15" />
+ <char id="345" x="402" y="178" width="7" height="14" xoffset="1" yoffset="5" xadvance="8" page="0" chnl="15" />
+ <char id="346" x="84" y="41" width="11" height="19" xoffset="1" yoffset="0" xadvance="13" page="0" chnl="15" />
+ <char id="347" x="243" y="162" width="9" height="15" xoffset="1" yoffset="4" xadvance="11" page="0" chnl="15" />
+ <char id="348" x="123" y="80" width="11" height="18" xoffset="1" yoffset="1" xadvance="13" page="0" chnl="15" />
+ <char id="349" x="294" y="178" width="9" height="14" xoffset="1" yoffset="5" xadvance="11" page="0" chnl="15" />
+ <char id="350" x="36" y="42" width="11" height="19" xoffset="1" yoffset="4" xadvance="13" page="0" chnl="15" />
+ <char id="351" x="253" y="162" width="9" height="15" xoffset="1" yoffset="8" xadvance="11" page="0" chnl="15" />
+ <char id="352" x="51" y="81" width="11" height="18" xoffset="1" yoffset="1" xadvance="13" page="0" chnl="15" />
+ <char id="353" x="284" y="178" width="9" height="14" xoffset="1" yoffset="5" xadvance="11" page="0" chnl="15" />
+ <char id="354" x="48" y="41" width="11" height="19" xoffset="1" yoffset="4" xadvance="13" page="0" chnl="15" />
+ <char id="355" x="348" y="40" width="6" height="19" xoffset="0" yoffset="4" xadvance="7" page="0" chnl="15" />
+ <char id="356" x="39" y="82" width="11" height="18" xoffset="1" yoffset="1" xadvance="13" page="0" chnl="15" />
+ <char id="357" x="158" y="147" width="10" height="15" xoffset="0" yoffset="4" xadvance="10" page="0" chnl="15" />
+ <char id="358" x="310" y="130" width="11" height="15" xoffset="1" yoffset="4" xadvance="13" page="0" chnl="15" />
+ <char id="359" x="469" y="160" width="6" height="15" xoffset="0" yoffset="4" xadvance="7" page="0" chnl="15" />
+ <char id="360" x="257" y="20" width="12" height="19" xoffset="1" yoffset="0" xadvance="14" page="0" chnl="15" />
+ <char id="361" x="246" y="146" width="10" height="15" xoffset="1" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="362" x="425" y="60" width="12" height="18" xoffset="1" yoffset="1" xadvance="14" page="0" chnl="15" />
+ <char id="363" x="262" y="178" width="10" height="14" xoffset="1" yoffset="5" xadvance="12" page="0" chnl="15" />
+ <char id="364" x="412" y="60" width="12" height="18" xoffset="1" yoffset="1" xadvance="14" page="0" chnl="15" />
+ <char id="365" x="273" y="178" width="10" height="14" xoffset="1" yoffset="5" xadvance="12" page="0" chnl="15" />
+ <char id="366" x="322" y="20" width="12" height="19" xoffset="1" yoffset="0" xadvance="14" page="0" chnl="15" />
+ <char id="367" x="42" y="101" width="10" height="16" xoffset="1" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="368" x="335" y="20" width="12" height="19" xoffset="1" yoffset="0" xadvance="14" page="0" chnl="15" />
+ <char id="369" x="301" y="146" width="10" height="15" xoffset="1" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="370" x="270" y="20" width="12" height="19" xoffset="1" yoffset="4" xadvance="14" page="0" chnl="15" />
+ <char id="371" x="478" y="128" width="11" height="15" xoffset="1" yoffset="8" xadvance="12" page="0" chnl="15" />
+ <char id="372" x="472" y="40" width="19" height="18" xoffset="0" yoffset="1" xadvance="19" page="0" chnl="15" />
+ <char id="373" x="59" y="182" width="15" height="14" xoffset="0" yoffset="5" xadvance="15" page="0" chnl="15" />
+ <char id="374" x="492" y="40" width="15" height="18" xoffset="-1" yoffset="1" xadvance="13" page="0" chnl="15" />
+ <char id="375" x="265" y="60" width="13" height="18" xoffset="-1" yoffset="5" xadvance="11" page="0" chnl="15" />
+ <char id="376" x="0" y="63" width="15" height="18" xoffset="-1" yoffset="1" xadvance="13" page="0" chnl="15" />
+ <char id="377" x="439" y="20" width="11" height="19" xoffset="0" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="378" x="353" y="162" width="8" height="15" xoffset="1" yoffset="4" xadvance="10" page="0" chnl="15" />
+ <char id="379" x="60" y="41" width="11" height="19" xoffset="0" yoffset="0" xadvance="11" page="0" chnl="15" />
+ <char id="380" x="389" y="162" width="8" height="15" xoffset="1" yoffset="4" xadvance="10" page="0" chnl="15" />
+ <char id="381" x="63" y="80" width="11" height="18" xoffset="0" yoffset="1" xadvance="11" page="0" chnl="15" />
+ <char id="382" x="393" y="178" width="8" height="14" xoffset="1" yoffset="5" xadvance="10" page="0" chnl="15" />
+ <char id="383" x="506" y="95" width="5" height="15" xoffset="1" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="384" x="286" y="130" width="11" height="15" xoffset="0" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="385" x="404" y="98" width="16" height="15" xoffset="0" yoffset="4" xadvance="17" page="0" chnl="15" />
+ <char id="386" x="67" y="132" width="12" height="15" xoffset="1" yoffset="4" xadvance="14" page="0" chnl="15" />
+ <char id="387" x="279" y="146" width="10" height="15" xoffset="1" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="388" x="340" y="114" width="13" height="15" xoffset="0" yoffset="4" xadvance="14" page="0" chnl="15" />
+ <char id="389" x="322" y="130" width="11" height="15" xoffset="0" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="390" x="119" y="131" width="12" height="15" xoffset="1" yoffset="4" xadvance="14" page="0" chnl="15" />
+ <char id="391" x="442" y="78" width="15" height="17" xoffset="1" yoffset="2" xadvance="14" page="0" chnl="15" />
+ <char id="392" x="465" y="177" width="12" height="13" xoffset="1" yoffset="6" xadvance="11" page="0" chnl="15" />
+ <char id="393" x="452" y="113" width="13" height="15" xoffset="0" yoffset="4" xadvance="14" page="0" chnl="15" />
+ <char id="394" x="472" y="96" width="16" height="15" xoffset="0" yoffset="4" xadvance="17" page="0" chnl="15" />
+ <char id="395" x="132" y="131" width="12" height="15" xoffset="1" yoffset="4" xadvance="14" page="0" chnl="15" />
+ <char id="396" x="334" y="146" width="10" height="15" xoffset="1" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="397" x="121" y="163" width="10" height="15" xoffset="1" yoffset="8" xadvance="12" page="0" chnl="15" />
+ <char id="398" x="36" y="150" width="11" height="15" xoffset="1" yoffset="4" xadvance="13" page="0" chnl="15" />
+ <char id="399" x="396" y="114" width="13" height="15" xoffset="1" yoffset="4" xadvance="15" page="0" chnl="15" />
+ <char id="400" x="223" y="130" width="12" height="15" xoffset="1" yoffset="4" xadvance="13" page="0" chnl="15" />
+ <char id="401" x="244" y="20" width="12" height="19" xoffset="-1" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="402" x="499" y="20" width="11" height="19" xoffset="0" yoffset="4" xadvance="11" page="0" chnl="15" />
+ <char id="403" x="407" y="79" width="17" height="17" xoffset="1" yoffset="2" xadvance="16" page="0" chnl="15" />
+ <char id="404" x="0" y="23" width="13" height="19" xoffset="0" yoffset="4" xadvance="13" page="0" chnl="15" />
+ <char id="405" x="368" y="98" width="17" height="15" xoffset="1" yoffset="4" xadvance="19" page="0" chnl="15" />
+ <char id="406" x="30" y="182" width="3" height="15" xoffset="1" yoffset="4" xadvance="6" page="0" chnl="15" />
+ <char id="407" x="0" y="182" width="5" height="15" xoffset="0" yoffset="4" xadvance="6" page="0" chnl="15" />
+ <char id="408" x="480" y="112" width="13" height="15" xoffset="1" yoffset="4" xadvance="14" page="0" chnl="15" />
+ <char id="409" x="99" y="164" width="10" height="15" xoffset="1" yoffset="4" xadvance="11" page="0" chnl="15" />
+ <char id="410" x="503" y="160" width="5" height="15" xoffset="0" yoffset="4" xadvance="6" page="0" chnl="15" />
+ <char id="411" x="24" y="150" width="11" height="15" xoffset="0" yoffset="4" xadvance="11" page="0" chnl="15" />
+ <char id="412" x="350" y="98" width="17" height="15" xoffset="1" yoffset="4" xadvance="20" page="0" chnl="15" />
+ <char id="413" x="420" y="0" width="14" height="19" xoffset="-1" yoffset="4" xadvance="14" page="0" chnl="15" />
+ <char id="414" x="132" y="163" width="10" height="15" xoffset="1" yoffset="8" xadvance="12" page="0" chnl="15" />
+ <char id="415" x="311" y="114" width="14" height="15" xoffset="1" yoffset="4" xadvance="16" page="0" chnl="15" />
+ <char id="416" x="0" y="118" width="16" height="15" xoffset="1" yoffset="4" xadvance="17" page="0" chnl="15" />
+ <char id="417" x="49" y="197" width="13" height="11" xoffset="1" yoffset="8" xadvance="14" page="0" chnl="15" />
+ <char id="418" x="170" y="0" width="16" height="19" xoffset="1" yoffset="4" xadvance="18" page="0" chnl="15" />
+ <char id="419" x="281" y="114" width="14" height="15" xoffset="0" yoffset="8" xadvance="15" page="0" chnl="15" />
+ <char id="420" x="114" y="115" width="15" height="15" xoffset="0" yoffset="4" xadvance="16" page="0" chnl="15" />
+ <char id="421" x="239" y="40" width="10" height="19" xoffset="1" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="422" x="347" y="60" width="12" height="18" xoffset="1" yoffset="4" xadvance="13" page="0" chnl="15" />
+ <char id="423" x="370" y="130" width="11" height="15" xoffset="1" yoffset="4" xadvance="13" page="0" chnl="15" />
+ <char id="424" x="244" y="193" width="9" height="11" xoffset="1" yoffset="8" xadvance="11" page="0" chnl="15" />
+ <char id="425" x="70" y="148" width="10" height="15" xoffset="1" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="426" x="299" y="40" width="8" height="19" xoffset="0" yoffset="4" xadvance="7" page="0" chnl="15" />
+ <char id="427" x="308" y="40" width="7" height="19" xoffset="0" yoffset="4" xadvance="7" page="0" chnl="15" />
+ <char id="428" x="80" y="132" width="12" height="15" xoffset="0" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="429" x="406" y="162" width="7" height="15" xoffset="0" yoffset="4" xadvance="7" page="0" chnl="15" />
+ <char id="430" x="24" y="43" width="11" height="19" xoffset="0" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="431" x="455" y="96" width="16" height="15" xoffset="1" yoffset="4" xadvance="17" page="0" chnl="15" />
+ <char id="432" x="63" y="197" width="13" height="11" xoffset="1" yoffset="8" xadvance="14" page="0" chnl="15" />
+ <char id="433" x="146" y="115" width="14" height="15" xoffset="1" yoffset="4" xadvance="16" page="0" chnl="15" />
+ <char id="434" x="158" y="131" width="12" height="15" xoffset="1" yoffset="4" xadvance="14" page="0" chnl="15" />
+ <char id="435" x="34" y="118" width="15" height="15" xoffset="0" yoffset="4" xadvance="15" page="0" chnl="15" />
+ <char id="436" x="360" y="0" width="14" height="19" xoffset="0" yoffset="4" xadvance="11" page="0" chnl="15" />
+ <char id="437" x="171" y="131" width="12" height="15" xoffset="0" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="438" x="292" y="193" width="8" height="11" xoffset="1" yoffset="8" xadvance="10" page="0" chnl="15" />
+ <char id="439" x="140" y="40" width="10" height="19" xoffset="1" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="440" x="129" y="41" width="10" height="19" xoffset="1" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="441" x="103" y="147" width="10" height="15" xoffset="1" yoffset="8" xadvance="11" page="0" chnl="15" />
+ <char id="442" x="125" y="147" width="10" height="15" xoffset="1" yoffset="8" xadvance="11" page="0" chnl="15" />
+ <char id="443" x="263" y="162" width="9" height="15" xoffset="1" yoffset="4" xadvance="11" page="0" chnl="15" />
+ <char id="444" x="273" y="162" width="9" height="15" xoffset="1" yoffset="4" xadvance="11" page="0" chnl="15" />
+ <char id="445" x="264" y="193" width="9" height="11" xoffset="0" yoffset="8" xadvance="10" page="0" chnl="15" />
+ <char id="446" x="358" y="130" width="11" height="15" xoffset="0" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="447" x="22" y="166" width="10" height="15" xoffset="1" yoffset="8" xadvance="12" page="0" chnl="15" />
+ <char id="448" x="509" y="160" width="2" height="15" xoffset="2" yoffset="4" xadvance="6" page="0" chnl="15" />
+ <char id="449" x="490" y="160" width="6" height="15" xoffset="2" yoffset="4" xadvance="10" page="0" chnl="15" />
+ <char id="450" x="11" y="166" width="10" height="15" xoffset="1" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="451" x="38" y="182" width="3" height="15" xoffset="2" yoffset="4" xadvance="7" page="0" chnl="15" />
+ <char id="452" x="426" y="40" width="24" height="18" xoffset="1" yoffset="1" xadvance="27" page="0" chnl="15" />
+ <char id="453" x="146" y="99" width="22" height="15" xoffset="1" yoffset="4" xadvance="24" page="0" chnl="15" />
+ <char id="454" x="212" y="98" width="20" height="15" xoffset="1" yoffset="4" xadvance="22" page="0" chnl="15" />
+ <char id="455" x="169" y="98" width="21" height="15" xoffset="1" yoffset="4" xadvance="23" page="0" chnl="15" />
+ <char id="456" x="254" y="0" width="15" height="19" xoffset="1" yoffset="4" xadvance="18" page="0" chnl="15" />
+ <char id="457" x="270" y="40" width="9" height="19" xoffset="1" yoffset="4" xadvance="11" page="0" chnl="15" />
+ <char id="458" x="73" y="99" width="24" height="15" xoffset="1" yoffset="4" xadvance="26" page="0" chnl="15" />
+ <char id="459" x="151" y="0" width="18" height="19" xoffset="1" yoffset="4" xadvance="20" page="0" chnl="15" />
+ <char id="460" x="187" y="0" width="16" height="19" xoffset="1" yoffset="4" xadvance="18" page="0" chnl="15" />
+ <char id="461" x="293" y="60" width="13" height="18" xoffset="0" yoffset="1" xadvance="13" page="0" chnl="15" />
+ <char id="462" x="108" y="180" width="10" height="14" xoffset="1" yoffset="5" xadvance="11" page="0" chnl="15" />
+ <char id="463" x="503" y="59" width="7" height="18" xoffset="-1" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="464" x="410" y="178" width="7" height="14" xoffset="-1" yoffset="5" xadvance="5" page="0" chnl="15" />
+ <char id="465" x="122" y="61" width="14" height="18" xoffset="1" yoffset="1" xadvance="16" page="0" chnl="15" />
+ <char id="466" x="130" y="179" width="10" height="14" xoffset="1" yoffset="5" xadvance="12" page="0" chnl="15" />
+ <char id="467" x="373" y="60" width="12" height="18" xoffset="1" yoffset="1" xadvance="14" page="0" chnl="15" />
+ <char id="468" x="141" y="179" width="10" height="14" xoffset="1" yoffset="5" xadvance="12" page="0" chnl="15" />
+ <char id="469" x="361" y="20" width="12" height="19" xoffset="1" yoffset="0" xadvance="14" page="0" chnl="15" />
+ <char id="470" x="228" y="40" width="10" height="19" xoffset="1" yoffset="0" xadvance="12" page="0" chnl="15" />
+ <char id="471" x="283" y="20" width="12" height="19" xoffset="1" yoffset="0" xadvance="14" page="0" chnl="15" />
+ <char id="472" x="225" y="79" width="10" height="18" xoffset="1" yoffset="1" xadvance="12" page="0" chnl="15" />
+ <char id="473" x="387" y="20" width="12" height="19" xoffset="1" yoffset="0" xadvance="14" page="0" chnl="15" />
+ <char id="474" x="159" y="79" width="10" height="18" xoffset="1" yoffset="1" xadvance="12" page="0" chnl="15" />
+ <char id="475" x="218" y="20" width="12" height="19" xoffset="1" yoffset="0" xadvance="14" page="0" chnl="15" />
+ <char id="476" x="247" y="79" width="10" height="18" xoffset="1" yoffset="1" xadvance="12" page="0" chnl="15" />
+ <char id="477" x="224" y="193" width="9" height="11" xoffset="1" yoffset="8" xadvance="11" page="0" chnl="15" />
+ <char id="478" x="14" y="23" width="13" height="19" xoffset="0" yoffset="0" xadvance="13" page="0" chnl="15" />
+ <char id="479" x="258" y="79" width="10" height="18" xoffset="1" yoffset="1" xadvance="11" page="0" chnl="15" />
+ <char id="480" x="98" y="21" width="13" height="19" xoffset="0" yoffset="0" xadvance="13" page="0" chnl="15" />
+ <char id="481" x="269" y="79" width="10" height="18" xoffset="1" yoffset="1" xadvance="11" page="0" chnl="15" />
+ <char id="482" x="451" y="40" width="20" height="18" xoffset="-1" yoffset="1" xadvance="20" page="0" chnl="15" />
+ <char id="483" x="42" y="182" width="16" height="14" xoffset="1" yoffset="5" xadvance="18" page="0" chnl="15" />
+ <char id="484" x="82" y="115" width="15" height="15" xoffset="1" yoffset="4" xadvance="16" page="0" chnl="15" />
+ <char id="485" x="262" y="130" width="11" height="15" xoffset="1" yoffset="8" xadvance="12" page="0" chnl="15" />
+ <char id="486" x="137" y="61" width="14" height="18" xoffset="1" yoffset="1" xadvance="16" page="0" chnl="15" />
+ <char id="487" x="291" y="79" width="10" height="18" xoffset="1" yoffset="5" xadvance="12" page="0" chnl="15" />
+ <char id="488" x="223" y="60" width="13" height="18" xoffset="1" yoffset="1" xadvance="14" page="0" chnl="15" />
+ <char id="489" x="203" y="79" width="10" height="18" xoffset="1" yoffset="1" xadvance="11" page="0" chnl="15" />
+ <char id="490" x="480" y="0" width="14" height="19" xoffset="1" yoffset="4" xadvance="16" page="0" chnl="15" />
+ <char id="491" x="499" y="144" width="10" height="15" xoffset="1" yoffset="8" xadvance="12" page="0" chnl="15" />
+ <char id="492" x="0" y="0" width="14" height="22" xoffset="1" yoffset="1" xadvance="16" page="0" chnl="15" />
+ <char id="493" x="324" y="79" width="10" height="18" xoffset="1" yoffset="5" xadvance="12" page="0" chnl="15" />
+ <char id="494" x="15" y="0" width="10" height="22" xoffset="1" yoffset="1" xadvance="12" page="0" chnl="15" />
+ <char id="495" x="170" y="79" width="10" height="18" xoffset="0" yoffset="5" xadvance="11" page="0" chnl="15" />
+ <char id="496" x="356" y="79" width="7" height="18" xoffset="0" yoffset="5" xadvance="6" page="0" chnl="15" />
+ <char id="497" x="98" y="99" width="24" height="15" xoffset="1" yoffset="4" xadvance="27" page="0" chnl="15" />
+ <char id="498" x="123" y="99" width="22" height="15" xoffset="1" yoffset="4" xadvance="24" page="0" chnl="15" />
+ <char id="499" x="233" y="98" width="20" height="15" xoffset="1" yoffset="4" xadvance="22" page="0" chnl="15" />
+ <char id="500" x="270" y="0" width="14" height="19" xoffset="1" yoffset="0" xadvance="16" page="0" chnl="15" />
+ <char id="501" x="206" y="40" width="10" height="19" xoffset="1" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="502" x="294" y="98" width="19" height="15" xoffset="1" yoffset="4" xadvance="21" page="0" chnl="15" />
+ <char id="503" x="12" y="43" width="11" height="19" xoffset="1" yoffset="4" xadvance="13" page="0" chnl="15" />
+ <char id="504" x="140" y="20" width="12" height="19" xoffset="1" yoffset="0" xadvance="14" page="0" chnl="15" />
+ <char id="505" x="0" y="166" width="10" height="15" xoffset="1" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="506" x="26" y="0" width="13" height="21" xoffset="0" yoffset="-2" xadvance="13" page="0" chnl="15" />
+ <char id="507" x="112" y="0" width="10" height="20" xoffset="1" yoffset="-1" xadvance="11" page="0" chnl="15" />
+ <char id="508" x="130" y="0" width="20" height="19" xoffset="-1" yoffset="0" xadvance="20" page="0" chnl="15" />
+ <char id="509" x="421" y="97" width="16" height="15" xoffset="1" yoffset="4" xadvance="18" page="0" chnl="15" />
+ <char id="510" x="60" y="0" width="16" height="20" xoffset="0" yoffset="0" xadvance="16" page="0" chnl="15" />
+ <char id="511" x="31" y="101" width="10" height="16" xoffset="1" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="512" x="112" y="21" width="13" height="19" xoffset="0" yoffset="0" xadvance="13" page="0" chnl="15" />
+ <char id="513" x="59" y="150" width="10" height="15" xoffset="1" yoffset="4" xadvance="11" page="0" chnl="15" />
+ <char id="514" x="307" y="60" width="13" height="18" xoffset="0" yoffset="1" xadvance="13" page="0" chnl="15" />
+ <char id="515" x="196" y="178" width="10" height="14" xoffset="1" yoffset="5" xadvance="11" page="0" chnl="15" />
+ <char id="516" x="475" y="20" width="11" height="19" xoffset="1" yoffset="0" xadvance="13" page="0" chnl="15" />
+ <char id="517" x="343" y="162" width="9" height="15" xoffset="1" yoffset="4" xadvance="11" page="0" chnl="15" />
+ <char id="518" x="99" y="80" width="11" height="18" xoffset="1" yoffset="1" xadvance="13" page="0" chnl="15" />
+ <char id="519" x="354" y="178" width="9" height="14" xoffset="1" yoffset="5" xadvance="11" page="0" chnl="15" />
+ <char id="520" x="290" y="40" width="8" height="19" xoffset="-2" yoffset="0" xadvance="5" page="0" chnl="15" />
+ <char id="521" x="371" y="162" width="8" height="15" xoffset="-2" yoffset="4" xadvance="5" page="0" chnl="15" />
+ <char id="522" x="401" y="79" width="5" height="18" xoffset="0" yoffset="1" xadvance="5" page="0" chnl="15" />
+ <char id="523" x="455" y="177" width="5" height="14" xoffset="0" yoffset="5" xadvance="5" page="0" chnl="15" />
+ <char id="524" x="300" y="0" width="14" height="19" xoffset="1" yoffset="0" xadvance="16" page="0" chnl="15" />
+ <char id="525" x="114" y="147" width="10" height="15" xoffset="1" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="526" x="107" y="61" width="14" height="18" xoffset="1" yoffset="1" xadvance="16" page="0" chnl="15" />
+ <char id="527" x="240" y="178" width="10" height="14" xoffset="1" yoffset="5" xadvance="12" page="0" chnl="15" />
+ <char id="528" x="205" y="20" width="12" height="19" xoffset="1" yoffset="0" xadvance="14" page="0" chnl="15" />
+ <char id="529" x="380" y="162" width="8" height="15" xoffset="0" yoffset="4" xadvance="8" page="0" chnl="15" />
+ <char id="530" x="321" y="60" width="12" height="18" xoffset="1" yoffset="1" xadvance="14" page="0" chnl="15" />
+ <char id="531" x="426" y="178" width="7" height="14" xoffset="1" yoffset="5" xadvance="8" page="0" chnl="15" />
+ <char id="532" x="153" y="20" width="12" height="19" xoffset="1" yoffset="0" xadvance="14" page="0" chnl="15" />
+ <char id="533" x="136" y="147" width="10" height="15" xoffset="1" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="534" x="334" y="60" width="12" height="18" xoffset="1" yoffset="1" xadvance="14" page="0" chnl="15" />
+ <char id="535" x="185" y="179" width="10" height="14" xoffset="1" yoffset="5" xadvance="12" page="0" chnl="15" />
+ <char id="536" x="89" y="0" width="11" height="20" xoffset="1" yoffset="4" xadvance="13" page="0" chnl="15" />
+ <char id="537" x="63" y="99" width="9" height="16" xoffset="1" yoffset="8" xadvance="11" page="0" chnl="15" />
+ <char id="538" x="77" y="0" width="11" height="20" xoffset="1" yoffset="4" xadvance="13" page="0" chnl="15" />
+ <char id="539" x="123" y="0" width="6" height="20" xoffset="0" yoffset="4" xadvance="7" page="0" chnl="15" />
+ <char id="540" x="107" y="41" width="10" height="19" xoffset="1" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="541" x="362" y="162" width="8" height="15" xoffset="1" yoffset="8" xadvance="10" page="0" chnl="15" />
+ <char id="542" x="360" y="60" width="12" height="18" xoffset="1" yoffset="1" xadvance="14" page="0" chnl="15" />
+ <char id="543" x="313" y="79" width="10" height="18" xoffset="1" yoffset="1" xadvance="12" page="0" chnl="15" />
+ <char id="544" x="426" y="20" width="12" height="19" xoffset="1" yoffset="4" xadvance="14" page="0" chnl="15" />
+ <char id="545" x="204" y="0" width="16" height="19" xoffset="1" yoffset="4" xadvance="17" page="0" chnl="15" />
+ <char id="546" x="490" y="128" width="11" height="15" xoffset="1" yoffset="4" xadvance="13" page="0" chnl="15" />
+ <char id="547" x="442" y="129" width="11" height="15" xoffset="1" yoffset="4" xadvance="13" page="0" chnl="15" />
+ <char id="548" x="386" y="60" width="12" height="18" xoffset="0" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="549" x="384" y="178" width="8" height="14" xoffset="1" yoffset="8" xadvance="10" page="0" chnl="15" />
+ <char id="550" x="70" y="21" width="13" height="19" xoffset="0" yoffset="0" xadvance="13" page="0" chnl="15" />
+ <char id="551" x="268" y="146" width="10" height="15" xoffset="1" yoffset="4" xadvance="11" page="0" chnl="15" />
+ <char id="552" x="0" y="43" width="11" height="19" xoffset="1" yoffset="4" xadvance="13" page="0" chnl="15" />
+ <char id="553" x="193" y="162" width="9" height="15" xoffset="1" yoffset="8" xadvance="11" page="0" chnl="15" />
+ <char id="554" x="315" y="0" width="14" height="19" xoffset="1" yoffset="0" xadvance="16" page="0" chnl="15" />
+ <char id="555" x="181" y="79" width="10" height="18" xoffset="1" yoffset="1" xadvance="12" page="0" chnl="15" />
+ <char id="556" x="390" y="0" width="14" height="19" xoffset="1" yoffset="0" xadvance="16" page="0" chnl="15" />
+ <char id="557" x="236" y="79" width="10" height="18" xoffset="1" yoffset="1" xadvance="12" page="0" chnl="15" />
+ <char id="558" x="330" y="0" width="14" height="19" xoffset="1" yoffset="0" xadvance="16" page="0" chnl="15" />
+ <char id="559" x="345" y="146" width="10" height="15" xoffset="1" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="560" x="345" y="0" width="14" height="19" xoffset="1" yoffset="0" xadvance="16" page="0" chnl="15" />
+ <char id="561" x="302" y="79" width="10" height="18" xoffset="1" yoffset="1" xadvance="12" page="0" chnl="15" />
+ <char id="562" x="16" y="63" width="15" height="18" xoffset="-1" yoffset="1" xadvance="13" page="0" chnl="15" />
+ <char id="563" x="279" y="60" width="13" height="18" xoffset="-1" yoffset="5" xadvance="11" page="0" chnl="15" />
+ <char id="564" x="195" y="40" width="10" height="19" xoffset="0" yoffset="4" xadvance="10" page="0" chnl="15" />
+ <char id="565" x="17" y="118" width="16" height="15" xoffset="1" yoffset="8" xadvance="17" page="0" chnl="15" />
+ <char id="566" x="422" y="146" width="10" height="15" xoffset="0" yoffset="4" xadvance="10" page="0" chnl="15" />
+ <char id="567" x="6" y="182" width="5" height="15" xoffset="0" yoffset="8" xadvance="6" page="0" chnl="15" />
+ <char id="568" x="332" y="98" width="17" height="15" xoffset="1" yoffset="4" xadvance="19" page="0" chnl="15" />
+ <char id="569" x="314" y="98" width="17" height="15" xoffset="1" yoffset="8" xadvance="19" page="0" chnl="15" />
+ <char id="570" x="16" y="101" width="14" height="16" xoffset="0" yoffset="4" xadvance="14" page="0" chnl="15" />
+ <char id="571" x="184" y="130" width="12" height="15" xoffset="1" yoffset="4" xadvance="14" page="0" chnl="15" />
+ <char id="572" x="250" y="40" width="9" height="19" xoffset="1" yoffset="4" xadvance="11" page="0" chnl="15" />
+ <char id="573" x="488" y="144" width="10" height="15" xoffset="1" yoffset="4" xadvance="12" page="0" chnl="15" />
+ <char id="574" x="458" y="78" width="12" height="17" xoffset="0" yoffset="3" xadvance="12" page="0" chnl="15" />
+ <char id="575" x="203" y="162" width="9" height="15" xoffset="1" yoffset="8" xadvance="11" page="0" chnl="15" />
+ <char id="576" x="213" y="162" width="9" height="15" xoffset="1" yoffset="8" xadvance="10" page="0" chnl="15" />
+ <char id="577" x="197" y="130" width="12" height="15" xoffset="1" yoffset="4" xadvance="13" page="0" chnl="15" />
+ <char id="578" x="283" y="193" width="8" height="11" xoffset="1" yoffset="8" xadvance="10" page="0" chnl="15" />
+ <char id="579" x="236" y="114" width="14" height="15" xoffset="-1" yoffset="4" xadvance="14" page="0" chnl="15" />
+ <char id="580" x="221" y="114" width="14" height="15" xoffset="0" yoffset="4" xadvance="14" page="0" chnl="15" />
+ <char id="581" x="382" y="114" width="13" height="15" xoffset="0" yoffset="4" xadvance="13" page="0" chnl="15" />
+ <char id="582" x="471" y="78" width="11" height="17" xoffset="1" yoffset="3" xadvance="13" page="0" chnl="15" />
+ <char id="583" x="280" y="40" width="9" height="19" xoffset="1" yoffset="4" xadvance="11" page="0" chnl="15" />
+ <char id="584" x="66" y="166" width="10" height="15" xoffset="0" yoffset="4" xadvance="11" page="0" chnl="15" />
+ <char id="585" x="332" y="40" width="7" height="19" xoffset="-2" yoffset="4" xadvance="6" page="0" chnl="15" />
+ <char id="586" x="221" y="0" width="16" height="19" xoffset="1" yoffset="4" xadvance="16" page="0" chnl="15" />
+ <char id="587" x="0" y="134" width="13" height="15" xoffset="1" yoffset="8" xadvance="12" page="0" chnl="15" />
+ <char id="588" x="161" y="115" width="14" height="15" xoffset="0" yoffset="4" xadvance="14" page="0" chnl="15" />
+ <char id="589" x="301" y="193" width="8" height="11" xoffset="0" yoffset="8" xadvance="8" page="0" chnl="15" />
+ <char id="590" x="466" y="112" width="13" height="15" xoffset="0" yoffset="4" xadvance="13" page="0" chnl="15" />
+ <char id="591" x="0" y="150" width="11" height="15" xoffset="0" yoffset="8" xadvance="11" page="0" chnl="15" />
+ </chars>
+ <kernings count="71">
+ <kerning first="32" second="65" amount="-1" />
+ <kerning first="49" second="49" amount="-1" />
+ <kerning first="65" second="32" amount="-1" />
+ <kerning first="65" second="84" amount="-2" />
+ <kerning first="65" second="86" amount="-2" />
+ <kerning first="65" second="87" amount="-1" />
+ <kerning first="65" second="89" amount="-2" />
+ <kerning first="65" second="118" amount="-1" />
+ <kerning first="65" second="121" amount="-1" />
+ <kerning first="70" second="44" amount="-2" />
+ <kerning first="70" second="46" amount="-2" />
+ <kerning first="70" second="65" amount="-1" />
+ <kerning first="76" second="84" amount="-2" />
+ <kerning first="76" second="86" amount="-2" />
+ <kerning first="76" second="87" amount="-1" />
+ <kerning first="76" second="89" amount="-2" />
+ <kerning first="76" second="121" amount="-1" />
+ <kerning first="80" second="44" amount="-3" />
+ <kerning first="80" second="46" amount="-3" />
+ <kerning first="80" second="65" amount="-2" />
+ <kerning first="82" second="89" amount="-1" />
+ <kerning first="84" second="44" amount="-2" />
+ <kerning first="84" second="45" amount="-1" />
+ <kerning first="84" second="46" amount="-2" />
+ <kerning first="84" second="58" amount="-2" />
+ <kerning first="84" second="65" amount="-2" />
+ <kerning first="84" second="97" amount="-2" />
+ <kerning first="84" second="99" amount="-2" />
+ <kerning first="84" second="101" amount="-2" />
+ <kerning first="84" second="111" amount="-2" />
+ <kerning first="84" second="114" amount="-1" />
+ <kerning first="84" second="115" amount="-2" />
+ <kerning first="84" second="117" amount="-2" />
+ <kerning first="84" second="119" amount="-2" />
+ <kerning first="84" second="121" amount="-2" />
+ <kerning first="86" second="44" amount="-2" />
+ <kerning first="86" second="45" amount="-1" />
+ <kerning first="86" second="46" amount="-2" />
+ <kerning first="86" second="58" amount="-1" />
+ <kerning first="86" second="65" amount="-2" />
+ <kerning first="86" second="97" amount="-1" />
+ <kerning first="86" second="101" amount="-1" />
+ <kerning first="86" second="111" amount="-2" />
+ <kerning first="86" second="114" amount="-1" />
+ <kerning first="86" second="117" amount="-1" />
+ <kerning first="86" second="121" amount="-1" />
+ <kerning first="87" second="44" amount="-1" />
+ <kerning first="87" second="46" amount="-1" />
+ <kerning first="87" second="65" amount="-1" />
+ <kerning first="87" second="97" amount="-1" />
+ <kerning first="89" second="44" amount="-2" />
+ <kerning first="89" second="45" amount="-1" />
+ <kerning first="89" second="46" amount="-2" />
+ <kerning first="89" second="58" amount="-2" />
+ <kerning first="89" second="65" amount="-2" />
+ <kerning first="89" second="97" amount="-1" />
+ <kerning first="89" second="101" amount="-1" />
+ <kerning first="89" second="105" amount="-1" />
+ <kerning first="89" second="111" amount="-2" />
+ <kerning first="89" second="112" amount="-1" />
+ <kerning first="89" second="113" amount="-2" />
+ <kerning first="89" second="117" amount="-1" />
+ <kerning first="89" second="118" amount="-1" />
+ <kerning first="114" second="44" amount="-1" />
+ <kerning first="114" second="46" amount="-1" />
+ <kerning first="118" second="44" amount="-2" />
+ <kerning first="118" second="46" amount="-2" />
+ <kerning first="119" second="44" amount="-1" />
+ <kerning first="119" second="46" amount="-1" />
+ <kerning first="121" second="44" amount="-2" />
+ <kerning first="121" second="46" amount="-2" />
+ </kernings>
+</font>
diff --git a/ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-24-bold_0.png b/ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-24-bold_0.png Binary files differnew file mode 100644 index 0000000..144ab6b --- /dev/null +++ b/ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-24-bold_0.png diff --git a/ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/skin/generic/genericSkin.png b/ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/skin/generic/genericSkin.png Binary files differnew file mode 100644 index 0000000..8de8d1a --- /dev/null +++ b/ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/skin/generic/genericSkin.png diff --git a/ardor3d-ui/src/main/test/com/ardor3d/extension/ui/text/parser/ForumLikeMarkupParserTest.java b/ardor3d-ui/src/main/test/com/ardor3d/extension/ui/text/parser/ForumLikeMarkupParserTest.java new file mode 100644 index 0000000..ccd67cc --- /dev/null +++ b/ardor3d-ui/src/main/test/com/ardor3d/extension/ui/text/parser/ForumLikeMarkupParserTest.java @@ -0,0 +1,107 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.ui.text.parser; + +import java.util.Iterator; +import java.util.List; +import java.util.SortedSet; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.ardor3d.extension.ui.text.StyleConstants; +import com.ardor3d.extension.ui.text.StyleSpan; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; + +public class ForumLikeMarkupParserTest { + + private ForumLikeMarkupParser parser; + + @Before + public void setUp() throws Exception { + parser = new ForumLikeMarkupParser(); + } + + @Test + public void parseWithoutMarkup() { + final String text = "A text without any markup what so ever [13] dum di dum [/23]"; + final List<StyleSpan> spans = Lists.newArrayList(); + final String result = parser.parseStyleSpans(text, spans); + + Assert.assertEquals(text, result); + + Assert.assertTrue(spans.isEmpty()); + } + + @Test + public void parseWithSimpleStyle() throws Exception { + final String text = "A text with [size=30]simple markup[/size] dum di dum"; + final List<StyleSpan> spans = Lists.newArrayList(); + final String result = parser.parseStyleSpans(text, spans); + + Assert.assertEquals("A text with simple markup dum di dum", result); + + Assert.assertEquals(1, spans.size()); + final StyleSpan span = spans.get(0); + Assert.assertEquals(12, span.getSpanStart()); + Assert.assertEquals(13, span.getSpanLength()); + Assert.assertEquals(StyleConstants.KEY_SIZE, span.getStyle()); + Assert.assertEquals(30, span.getValue()); + } + + @Test + public void parseWithNestedStyle() throws Exception { + final String text = "A text [size=30]with [f=arial]simple markup[/f][/size] dum di dum"; + final List<StyleSpan> spans = Lists.newArrayList(); + final String result = parser.parseStyleSpans(text, spans); + + Assert.assertEquals("A text with simple markup dum di dum", result); + + Assert.assertEquals(2, spans.size()); + final SortedSet<StyleSpan> sortedSpans = Sets.newTreeSet(spans); + final Iterator<StyleSpan> spanIterator = sortedSpans.iterator(); + final StyleSpan span1 = spanIterator.next(); + Assert.assertEquals(7, span1.getSpanStart()); + Assert.assertEquals(18, span1.getSpanLength()); + Assert.assertEquals(StyleConstants.KEY_SIZE, span1.getStyle()); + final StyleSpan span2 = spanIterator.next(); + Assert.assertEquals(12, span2.getSpanStart()); + Assert.assertEquals(13, span2.getSpanLength()); + Assert.assertEquals(StyleConstants.KEY_FAMILY, span2.getStyle()); + } + + @Test + public void parseWithNestedSameStyleBackToBackTags() throws Exception { + final String text = "[size=10][size=20]A text [/size]with simple markup[/size] dum di dum"; + final List<StyleSpan> spans = Lists.newArrayList(); + final String result = parser.parseStyleSpans(text, spans); + + Assert.assertEquals("A text with simple markup dum di dum", result); + + Assert.assertEquals(2, spans.size()); + final SortedSet<StyleSpan> sortedSpans = Sets.newTreeSet(spans); + final Iterator<StyleSpan> spanIterator = sortedSpans.iterator(); + final StyleSpan span1 = spanIterator.next(); + Assert.assertEquals(0, span1.getSpanStart()); + Assert.assertEquals(25, span1.getSpanLength()); + Assert.assertEquals(StyleConstants.KEY_SIZE, span1.getStyle()); + Assert.assertEquals(10, span1.getValue()); + + final StyleSpan span2 = spanIterator.next(); + Assert.assertEquals(0, span2.getSpanStart()); + Assert.assertEquals(7, span2.getSpanLength()); + Assert.assertEquals(StyleConstants.KEY_SIZE, span2.getStyle()); + Assert.assertEquals(20, span2.getValue()); + } + +} diff --git a/ardor3d-ui/src/test/java/com/ardor3d/extension/ui/UIComponentTest.java b/ardor3d-ui/src/test/java/com/ardor3d/extension/ui/UIComponentTest.java new file mode 100644 index 0000000..ad9b63e --- /dev/null +++ b/ardor3d-ui/src/test/java/com/ardor3d/extension/ui/UIComponentTest.java @@ -0,0 +1 @@ +
package com.ardor3d.extension.ui;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
public class UIComponentTest {
private UIComponent component;
@Before
public void setUp() throws Exception {
component = new UIComponent() {
};
}
@Test
public void minimumSizeSetsContentSize() throws Exception {
final int contentHeight = component.getContentHeight();
final int contentWidth = component.getContentWidth();
Assert.assertTrue(contentHeight < 200);
Assert.assertTrue(contentWidth < 100);
component.setMinimumContentSize(100, 200);
Assert.assertEquals(100, component.getMinimumLocalComponentWidth());
Assert.assertEquals(200, component.getMinimumLocalComponentHeight());
Assert.assertEquals(100, component.getContentWidth());
Assert.assertEquals(200, component.getContentHeight());
}
@Test
public void cantSetContentSizeSmallerThanMinimum() throws Exception {
final int minWidth = component.getMinimumLocalComponentWidth();
final int minHeight = component.getMinimumLocalComponentHeight();
final int contentHeight = component.getContentHeight();
final int contentWidth = component.getContentWidth();
Assert.assertTrue(contentWidth >= minWidth);
Assert.assertTrue(contentHeight >= minHeight);
component.setContentSize(minWidth - 2, minHeight - 1);
Assert.assertEquals(minWidth, component.getContentWidth());
Assert.assertEquals(minHeight, component.getContentHeight());
}
@Test
public void cantSetContentSizeLargerThanMaximum() throws Exception {
final int maxWidth = component.getMaximumLocalComponentWidth();
final int maxHeight = component.getMaximumLocalComponentHeight();
final int contentHeight = component.getContentHeight();
final int contentWidth = component.getContentWidth();
Assert.assertTrue(contentWidth <= maxWidth);
Assert.assertTrue(contentHeight <= maxHeight);
component.setContentSize(maxWidth + 2, maxHeight + 3);
Assert.assertEquals(maxWidth, component.getContentWidth());
Assert.assertEquals(maxHeight, component.getContentHeight());
}
}
\ No newline at end of file |