aboutsummaryrefslogtreecommitdiffstats
path: root/ardor3d-ui
diff options
context:
space:
mode:
authorneothemachine <[email protected]>2012-12-05 17:03:16 +0100
committerneothemachine <[email protected]>2012-12-05 17:03:16 +0100
commit9dd02f103042cb8a196f8a3ed2278da443e345bf (patch)
tree422449f0c62ff9518316ce5d4219bb2b12f0ed15 /ardor3d-ui
parent2b26b12fd794de0f03a064a10024a3d9f5583756 (diff)
move all files from trunk to root folder
Diffstat (limited to 'ardor3d-ui')
-rw-r--r--ardor3d-ui/.classpath8
-rw-r--r--ardor3d-ui/.project17
-rw-r--r--ardor3d-ui/.settings/org.eclipse.jdt.core.prefs268
-rw-r--r--ardor3d-ui/.settings/org.eclipse.jdt.ui.prefs110
-rw-r--r--ardor3d-ui/pom.xml32
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/AbstractLabelUIComponent.java268
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/AbstractUITextEntryComponent.java249
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/FloatingUIContainer.java39
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/LabelState.java107
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/Orientation.java15
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/StateBasedUIComponent.java174
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/Textable.java26
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIButton.java450
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UICheckBox.java49
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIComboBox.java239
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIComponent.java1599
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIContainer.java611
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIFrame.java436
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIFrameBar.java128
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIFrameStatusBar.java127
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIHud.java895
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UILabel.java61
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIMenuItem.java38
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIPanel.java25
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIPasswordField.java52
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIPopupMenu.java66
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIProgressBar.java151
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIRadioButton.java50
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIScrollBar.java139
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIScrollPanel.java115
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UISlider.java262
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UISliderKnob.java246
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIState.java70
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UITab.java61
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UITabbedPane.java344
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UITextArea.java194
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UITextField.java265
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UITooltip.java47
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/backdrop/EmptyBackdrop.java27
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/backdrop/GradientBackdrop.java164
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/backdrop/ImageBackdrop.java194
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/backdrop/MultiImageBackdrop.java122
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/backdrop/SolidBackdrop.java108
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/backdrop/UIBackdrop.java62
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/backdrop/package-info.java5
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/border/EmptyBorder.java41
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/border/ImageBorder.java215
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/border/SolidBorder.java219
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/border/UIBorder.java81
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/border/package-info.java5
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/event/ActionEvent.java25
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/event/ActionListener.java24
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/event/DragListener.java67
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/event/FrameDragListener.java74
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/event/FrameResizeListener.java110
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/event/SelectionListener.java31
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/event/package-info.java5
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/layout/AnchorLayout.java224
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/layout/AnchorLayoutData.java111
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/layout/BorderLayout.java176
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/layout/BorderLayoutData.java18
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/layout/GridLayout.java299
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/layout/GridLayoutData.java86
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/layout/RowLayout.java255
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/layout/UILayout.java35
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/layout/UILayoutData.java16
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/layout/package-info.java7
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/model/ComboBoxModel.java105
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/model/DefaultComboBoxModel.java103
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/model/DefaultSliderModel.java76
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/model/SliderModel.java62
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/package-info.java5
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/skin/Skin.java118
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/skin/SkinManager.java33
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/skin/SkinningTask.java29
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/skin/generic/GenericSkin.java923
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/AwtCopyPasteImpl.java42
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/CharacterDescriptor.java118
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/CopyPasteImpl.java17
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/CopyPasteManager.java35
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/DefaultLatinTextAreaKeyHandler.java270
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/DefaultLatinTextFieldKeyHandler.java269
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/RenderedText.java229
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/StyleConstants.java30
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/StyleSpan.java67
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/TextCaret.java131
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/TextFactory.java378
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/TextMesh.java37
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/TextSelection.java295
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/UIKeyHandler.java22
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/font/BMFontProvider.java162
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/font/FontProvider.java29
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/font/UIFont.java79
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/parser/ForumLikeMarkupParser.java253
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/text/parser/StyleParser.java43
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/util/Alignment.java115
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/util/ButtonGroup.java130
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/util/Dimension.java103
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/util/HudListener.java34
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/util/Insets.java124
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/util/SubTex.java166
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/util/SubTexUtil.java421
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/util/TransformedSubTex.java72
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/util/UIQuad.java98
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/util/package-info.java5
-rw-r--r--ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-12-regular.fnt596
-rw-r--r--ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-12-regular_0.pngbin0 -> 14661 bytes
-rw-r--r--ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-16-bold-regular.fnt1403
-rw-r--r--ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-16-bold-regular_00.pngbin0 -> 67883 bytes
-rw-r--r--ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-18-bold-italic.fnt604
-rw-r--r--ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-18-bold-italic_0.pngbin0 -> 41324 bytes
-rw-r--r--ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-18-bold.fnt610
-rw-r--r--ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-18-bold_0.pngbin0 -> 27253 bytes
-rw-r--r--ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-18-regular.fnt609
-rw-r--r--ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-18-regular_0.pngbin0 -> 30048 bytes
-rw-r--r--ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-24-bold.fnt610
-rw-r--r--ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-24-bold_0.pngbin0 -> 43460 bytes
-rw-r--r--ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/skin/generic/genericSkin.pngbin0 -> 20798 bytes
-rw-r--r--ardor3d-ui/src/main/test/com/ardor3d/extension/ui/text/parser/ForumLikeMarkupParserTest.java107
-rw-r--r--ardor3d-ui/src/test/java/com/ardor3d/extension/ui/UIComponentTest.java1
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 &lt;http\://www.ardor3d.com/LICENSE&gt;.\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
new file mode 100644
index 0000000..a857030
--- /dev/null
+++ b/ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-12-regular_0.png
Binary files differ
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
new 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
Binary files differ
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
new 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
Binary files differ
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
new file mode 100644
index 0000000..363b109
--- /dev/null
+++ b/ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-18-bold_0.png
Binary files differ
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
new file mode 100644
index 0000000..3d41a54
--- /dev/null
+++ b/ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-18-regular_0.png
Binary files differ
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
new file mode 100644
index 0000000..144ab6b
--- /dev/null
+++ b/ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/font/arial-24-bold_0.png
Binary files differ
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
new file mode 100644
index 0000000..8de8d1a
--- /dev/null
+++ b/ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/skin/generic/genericSkin.png
Binary files differ
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