diff --git a/media/BUILD.gn b/media/BUILD.gn index c7b1a87d4d9d..d62f338d50c5 100644 --- a/media/BUILD.gn +++ b/media/BUILD.gn @@ -13,7 +13,10 @@ # limitations under the License. config("media_config") { - include_dirs = [ "//third_party/abseil-cpp" ] + include_dirs = [ + "//third_party/abseil-cpp", + "//third_party/libwebm/source", + ] if (is_win) { cflags = [ "/wd4267", # Conversion from 'size_t' to 'type', possible loss of data. @@ -37,15 +40,17 @@ config("media_config_public") { # TODO: Make include_dirs other than the first one private. include_dirs = [ "//third_party/abseil-cpp", + "//third_party/libwebm/source", + "//third_party/skia", "..", "cobalt", - "//third_party/skia", ] } config("external_config") { include_dirs = [ "//third_party/abseil-cpp", + "//third_party/libwebm/source", "..", "cobalt", "../../skia", @@ -263,4 +268,4 @@ target(gtest_target_type, "chromium_media_test") { "//testing/gmock", "//testing/gtest", ] -} \ No newline at end of file +} diff --git a/media/formats/webm/webm_colour_parser.cc b/media/formats/webm/webm_colour_parser.cc index f765b9e1cc14..38f2c50a1559 100644 --- a/media/formats/webm/webm_colour_parser.cc +++ b/media/formats/webm/webm_colour_parser.cc @@ -7,27 +7,7 @@ #include "base/check.h" #include "base/logging.h" #include "media/formats/webm/webm_constants.h" - -#if defined(STARBOARD) - -// Taken from mkvmuxer.h as is to avoid introducing the whole libwebm library. -namespace mkvmuxer { - -class Colour { - public: - enum Range { - kUnspecifiedCr = 0, - kBroadcastRange = 1, - kFullRange = 2, - kMcTcDefined = 3, // Defined by MatrixCoefficients/TransferCharacteristics. - }; -}; - -} // namespace mkvmuxer - -#else // defined(STARBOARD) #include "third_party/libwebm/source/mkvmuxer/mkvmuxer.h" -#endif // defined(STARBOARD) namespace media { diff --git a/third_party/libwebm/BUILD.gn b/third_party/libwebm/BUILD.gn new file mode 100644 index 000000000000..c6a30c901631 --- /dev/null +++ b/third_party/libwebm/BUILD.gn @@ -0,0 +1,18 @@ +# Copyright 2015 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +config("libwebm_config") { + include_dirs = [ "./source" ] +} + +static_library("libwebm") { + configs += [ ":libwebm_config" ] + public_configs = [ ":libwebm_config" ] + + sources = [ + "source/mkvmuxer/mkvmuxer.cc", + "source/mkvmuxer/mkvmuxerutil.cc", + "source/mkvmuxer/mkvwriter.cc", + ] +} diff --git a/third_party/libwebm/DIR_METADATA b/third_party/libwebm/DIR_METADATA new file mode 100644 index 000000000000..698e49353d57 --- /dev/null +++ b/third_party/libwebm/DIR_METADATA @@ -0,0 +1,3 @@ +monorail: { + component: "Blink>MediaRecording" +} diff --git a/third_party/libwebm/METADATA b/third_party/libwebm/METADATA new file mode 100644 index 000000000000..48a15b262b01 --- /dev/null +++ b/third_party/libwebm/METADATA @@ -0,0 +1,19 @@ +name: "third_party/libwebm" +description: + "Subtree at third_party/libwebm." + +third_party { + identifier { + type: "ChromiumVersion" + value: "114.0.5735.358" # from https://chromereleases.googleblog.com/2024/03/long-term-support-channel-update-for_26.html + } + identifier { + type: "Git" + value: "https://chromium.googlesource.com/chromium/src.git" + version: "1759c6ae9316996b9f150c0ce9d0ca78a3d15c02" + } + identifier { + type: "UpstreamSubdir" + value: "third_party/libwebm" + } +} \ No newline at end of file diff --git a/third_party/libwebm/OWNERS b/third_party/libwebm/OWNERS new file mode 100644 index 000000000000..e4e65437691b --- /dev/null +++ b/third_party/libwebm/OWNERS @@ -0,0 +1,9 @@ +# The following OWNERS refer to libwebm Chromium integration. +niklase@chromium.org + +# The following OWNER refer to libwebm content. +tomfinegan@chromium.org + +# Original (legacy) owner. +emircan@chromium.org +mcasas@chromium.org diff --git a/third_party/libwebm/README.chromium b/third_party/libwebm/README.chromium new file mode 100644 index 000000000000..965f3fc7db40 --- /dev/null +++ b/third_party/libwebm/README.chromium @@ -0,0 +1,14 @@ +Name: WebM container parser and writer. +Short Name: libwebm +URL: https://chromium.googlesource.com/webm/libwebm +Version: 1.0.0.28 +Revision: e4fbea0c9751ae8aa86629b197a28d8276a2b0da +CPEPrefix: cpe:/a:webmproject:libwebm:1.0.0.28 +License: BSD +License File: source/LICENSE.TXT +Security Critical: yes + +Description: +libwebm is a library to read and write WebM files. It's used by MediaStream +Recording API to multiplex encoded audio and video into a WebM container. Only +the writing parts are used for this purpose, the rest is not compiled. diff --git a/third_party/libwebm/source/.clang-format b/third_party/libwebm/source/.clang-format new file mode 100644 index 000000000000..7ce4e926b406 --- /dev/null +++ b/third_party/libwebm/source/.clang-format @@ -0,0 +1,152 @@ +--- +Language: Cpp +# BasedOnStyle: Google +# Generated with clang-format 7.0.1 +AccessModifierOffset: -1 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlinesLeft: true +AlignOperands: true +AlignTrailingComments: false +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: All +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: true +AlwaysBreakTemplateDeclarations: true +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterClass: false + AfterControlStatement: false + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Attach +BreakBeforeTernaryOperators: false +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeColon +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: true +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: true +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] +IncludeCategories: +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^' + Priority: 2 + - Regex: '^<.*\.h>' + Priority: 1 + - Regex: '^<.*' + Priority: 2 + - Regex: '.*' + Priority: 3 +IncludeIsMainRegex: '([-_](test|unittest))?$' +IndentCaseLabels: true +IndentPPDirectives: None +IndentWidth: 2 +IndentWrappedFunctionNames: false +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: false +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Never +ObjCBlockIndentWidth: 2 +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: false +ObjCSpaceBeforeProtocolList: true +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 1 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 200 +PointerAlignment: Left +RawStringFormats: + - Language: Cpp + Delimiters: + - cc + - CC + - cpp + - Cpp + - CPP + - 'c++' + - 'C++' + CanonicalDelimiter: '' + BasedOnStyle: google + - Language: TextProto + Delimiters: + - pb + - PB + - proto + - PROTO + EnclosingFunctions: + - EqualsProto + - EquivToProto + - PARSE_PARTIAL_TEXT_PROTO + - PARSE_TEST_PROTO + - PARSE_TEXT_PROTO + - ParseTextOrDie + - ParseTextProtoOrDie + CanonicalDelimiter: '' + BasedOnStyle: google +ReflowComments: true +SortIncludes: true +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 2 +SpacesInAngles: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Auto +TabWidth: 8 +UseTab: Never +... diff --git a/third_party/libwebm/source/.gitattributes b/third_party/libwebm/source/.gitattributes new file mode 100644 index 000000000000..2b5cda5f04ee --- /dev/null +++ b/third_party/libwebm/source/.gitattributes @@ -0,0 +1,6 @@ +*.sln eol=crlf +*.vcproj eol=crlf +*.vsprops eol=crlf +*.vcxproj eol=crlf +*.mkv -text -diff +*.webm -text -diff diff --git a/third_party/libwebm/source/.gitignore b/third_party/libwebm/source/.gitignore new file mode 100644 index 000000000000..2abbaa6cce01 --- /dev/null +++ b/third_party/libwebm/source/.gitignore @@ -0,0 +1,35 @@ +*.mkv +*.MKV +core +*.a +*.d +*.so* +*.o +*~ +*.swp +*.ncb +*.user +*.suo +*.exe +/*.webm +Debug +Release +*.sdf +*.opensdf +ipch +dumpvtt +mkvmuxer_sample +mkvparser_sample +vttdemux +mkvmuxer_tests +mkvparser_tests +webm_info +webm2pes +webm2pes_tests +webm2ts +vp9_header_parser_tests +vp9_level_stats_tests +Makefile +CMakeFiles +CMakeCache.txt +*.cmake diff --git a/third_party/libwebm/source/AUTHORS.TXT b/third_party/libwebm/source/AUTHORS.TXT new file mode 100644 index 000000000000..9686ac13eb0c --- /dev/null +++ b/third_party/libwebm/source/AUTHORS.TXT @@ -0,0 +1,4 @@ +# Names should be added to this file like so: +# Name or Organization + +Google Inc. diff --git a/third_party/libwebm/source/Android.mk b/third_party/libwebm/source/Android.mk new file mode 100644 index 000000000000..b46ba101d420 --- /dev/null +++ b/third_party/libwebm/source/Android.mk @@ -0,0 +1,17 @@ +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_MODULE:= libwebm +LOCAL_CPPFLAGS:=-D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS +LOCAL_CPPFLAGS+=-D__STDC_LIMIT_MACROS -std=c++11 +LOCAL_C_INCLUDES:= $(LOCAL_PATH) +LOCAL_EXPORT_C_INCLUDES:= $(LOCAL_PATH) + +LOCAL_SRC_FILES:= common/file_util.cc \ + common/hdr_util.cc \ + mkvparser/mkvparser.cc \ + mkvparser/mkvreader.cc \ + mkvmuxer/mkvmuxer.cc \ + mkvmuxer/mkvmuxerutil.cc \ + mkvmuxer/mkvwriter.cc +include $(BUILD_STATIC_LIBRARY) diff --git a/third_party/libwebm/source/CMakeLists.txt b/third_party/libwebm/source/CMakeLists.txt new file mode 100644 index 000000000000..a83d23bafca1 --- /dev/null +++ b/third_party/libwebm/source/CMakeLists.txt @@ -0,0 +1,453 @@ +## Copyright (c) 2015 The WebM project authors. All Rights Reserved. +## +## Use of this source code is governed by a BSD-style license +## that can be found in the LICENSE file in the root of the source +## tree. An additional intellectual property rights grant can be found +## in the file PATENTS. All contributing project authors may +## be found in the AUTHORS file in the root of the source tree. +cmake_minimum_required(VERSION 3.2) +project(LIBWEBM CXX) + +include(GNUInstallDirs) +include("${CMAKE_CURRENT_SOURCE_DIR}/build/cxx_flags.cmake") + +if (NOT BUILD_SHARED_LIBS) + include("${CMAKE_CURRENT_SOURCE_DIR}/build/msvc_runtime.cmake") +endif () + +set(LIBWEBM_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}") + +# Build/test configuration flags. +option(ENABLE_WEBMTS "Enables WebM PES/TS support." ON) +option(ENABLE_WEBMINFO "Enables building webm_info." ON) +option(ENABLE_TESTS "Enables tests." OFF) +option(ENABLE_IWYU "Enables include-what-you-use support." OFF) +option(ENABLE_WERROR "Enable warnings as errors." OFF) +option(ENABLE_WEBM_PARSER "Enables new parser API." OFF) + +if(WIN32 OR CYGWIN OR MSYS) + # Allow use of rand_r() / fdopen() and other POSIX functions. + require_cxx_flag_nomsvc("-std=gnu++11") +else() + require_cxx_flag_nomsvc("-std=c++11") +endif() + +add_cxx_preproc_definition("__STDC_CONSTANT_MACROS") +add_cxx_preproc_definition("__STDC_FORMAT_MACROS") +add_cxx_preproc_definition("__STDC_LIMIT_MACROS") + +# Set up compiler flags and build properties. +include_directories("${LIBWEBM_SRC_DIR}") + +if (MSVC) + add_cxx_flag_if_supported("/W4") + # Disable MSVC warnings that suggest making code non-portable. + add_cxx_flag_if_supported("/wd4996") + if (ENABLE_WERROR) + add_cxx_flag_if_supported("/WX") + endif () +else () + add_cxx_flag_if_supported("-Wall") + add_cxx_flag_if_supported("-Wextra") + add_cxx_flag_if_supported("-Wnarrowing") + add_cxx_flag_if_supported("-Wno-deprecated") + add_cxx_flag_if_supported("-Wshorten-64-to-32") + if (ENABLE_WERROR) + add_cxx_flag_if_supported("-Werror") + endif () +endif () + +# Source list variables. +set(dumpvtt_sources "${LIBWEBM_SRC_DIR}/dumpvtt.cc") + +set(libwebm_common_sources + "${LIBWEBM_SRC_DIR}/common/file_util.cc" + "${LIBWEBM_SRC_DIR}/common/file_util.h" + "${LIBWEBM_SRC_DIR}/common/hdr_util.cc" + "${LIBWEBM_SRC_DIR}/common/hdr_util.h" + "${LIBWEBM_SRC_DIR}/common/webmids.h") + +set(mkvmuxer_sources + "${LIBWEBM_SRC_DIR}/mkvmuxer/mkvmuxer.cc" + "${LIBWEBM_SRC_DIR}/mkvmuxer/mkvmuxer.h" + "${LIBWEBM_SRC_DIR}/mkvmuxer/mkvmuxertypes.h" + "${LIBWEBM_SRC_DIR}/mkvmuxer/mkvmuxerutil.cc" + "${LIBWEBM_SRC_DIR}/mkvmuxer/mkvmuxerutil.h" + "${LIBWEBM_SRC_DIR}/mkvmuxer/mkvwriter.cc" + "${LIBWEBM_SRC_DIR}/mkvmuxer/mkvwriter.h" + "${LIBWEBM_SRC_DIR}/common/webmids.h") + +set(mkvmuxer_sample_sources + "${LIBWEBM_SRC_DIR}/mkvmuxer_sample.cc" + "${LIBWEBM_SRC_DIR}/sample_muxer_metadata.cc" + "${LIBWEBM_SRC_DIR}/sample_muxer_metadata.h") + +set(mkvmuxer_tests_sources + "${LIBWEBM_SRC_DIR}/testing/mkvmuxer_tests.cc" + "${LIBWEBM_SRC_DIR}/testing/test_util.cc" + "${LIBWEBM_SRC_DIR}/testing/test_util.h") + +set(mkvparser_sources + "${LIBWEBM_SRC_DIR}/mkvparser/mkvparser.cc" + "${LIBWEBM_SRC_DIR}/mkvparser/mkvparser.h" + "${LIBWEBM_SRC_DIR}/mkvparser/mkvreader.cc" + "${LIBWEBM_SRC_DIR}/mkvparser/mkvreader.h" + "${LIBWEBM_SRC_DIR}/common/webmids.h") + +set(mkvparser_sample_sources "${LIBWEBM_SRC_DIR}/mkvparser_sample.cc") +set(mkvparser_tests_sources + "${LIBWEBM_SRC_DIR}/testing/mkvparser_tests.cc" + "${LIBWEBM_SRC_DIR}/testing/test_util.cc" + "${LIBWEBM_SRC_DIR}/testing/test_util.h") + +set(vp9_header_parser_tests_sources + "${LIBWEBM_SRC_DIR}/common/vp9_header_parser_tests.cc" + "${LIBWEBM_SRC_DIR}/common/vp9_header_parser.cc" + "${LIBWEBM_SRC_DIR}/common/vp9_header_parser.h" + "${LIBWEBM_SRC_DIR}/testing/test_util.cc" + "${LIBWEBM_SRC_DIR}/testing/test_util.h") + +set(vp9_level_stats_tests_sources + "${LIBWEBM_SRC_DIR}/common/vp9_header_parser.cc" + "${LIBWEBM_SRC_DIR}/common/vp9_header_parser.h" + "${LIBWEBM_SRC_DIR}/common/vp9_level_stats_tests.cc" + "${LIBWEBM_SRC_DIR}/common/vp9_level_stats.cc" + "${LIBWEBM_SRC_DIR}/common/vp9_level_stats.h" + "${LIBWEBM_SRC_DIR}/testing/test_util.cc" + "${LIBWEBM_SRC_DIR}/testing/test_util.h") + +set(vttdemux_sources + "${LIBWEBM_SRC_DIR}/vttdemux.cc" + "${LIBWEBM_SRC_DIR}/webvtt/webvttparser.cc" + "${LIBWEBM_SRC_DIR}/webvtt/webvttparser.h") + +set(webm_parser_public_headers + "${LIBWEBM_SRC_DIR}/webm_parser/include/webm/buffer_reader.h" + "${LIBWEBM_SRC_DIR}/webm_parser/include/webm/callback.h" + "${LIBWEBM_SRC_DIR}/webm_parser/include/webm/dom_types.h" + "${LIBWEBM_SRC_DIR}/webm_parser/include/webm/element.h" + "${LIBWEBM_SRC_DIR}/webm_parser/include/webm/file_reader.h" + "${LIBWEBM_SRC_DIR}/webm_parser/include/webm/id.h" + "${LIBWEBM_SRC_DIR}/webm_parser/include/webm/istream_reader.h" + "${LIBWEBM_SRC_DIR}/webm_parser/include/webm/reader.h" + "${LIBWEBM_SRC_DIR}/webm_parser/include/webm/status.h" + "${LIBWEBM_SRC_DIR}/webm_parser/include/webm/webm_parser.h") + +set(webm_parser_sources + ${webm_parser_public_headers} + "${LIBWEBM_SRC_DIR}/webm_parser/src/ancestory.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/src/ancestory.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/audio_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/bit_utils.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/src/bit_utils.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/block_additions_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/block_group_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/block_header_parser.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/src/block_header_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/block_more_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/block_parser.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/src/block_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/bool_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/buffer_reader.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/src/byte_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/callback.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/src/chapter_atom_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/chapter_display_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/chapters_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/cluster_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/colour_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/content_enc_aes_settings_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/content_encoding_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/content_encodings_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/content_encryption_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/cue_point_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/cue_track_positions_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/cues_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/date_parser.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/src/date_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/ebml_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/edition_entry_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/element_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/file_reader.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/src/float_parser.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/src/float_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/id_element_parser.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/src/id_element_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/id_parser.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/src/id_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/info_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/int_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/istream_reader.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/src/master_parser.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/src/master_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/master_value_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/mastering_metadata_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/parser_utils.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/src/parser_utils.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/projection_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/recursive_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/seek_head_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/seek_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/segment_parser.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/src/segment_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/simple_tag_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/size_parser.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/src/size_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/skip_callback.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/skip_parser.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/src/skip_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/slices_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/tag_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/tags_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/targets_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/time_slice_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/track_entry_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/tracks_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/unknown_parser.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/src/unknown_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/var_int_parser.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/src/var_int_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/video_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/virtual_block_parser.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/src/virtual_block_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/void_parser.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/src/void_parser.h" + "${LIBWEBM_SRC_DIR}/webm_parser/src/webm_parser.cc") + +set(webm_parser_demo_sources "${LIBWEBM_SRC_DIR}/webm_parser/demo/demo.cc") +set(webm_parser_tests_sources + "${LIBWEBM_SRC_DIR}/webm_parser/tests/audio_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/bit_utils_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/block_additions_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/block_group_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/block_header_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/block_more_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/block_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/bool_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/buffer_reader_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/byte_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/callback_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/chapter_atom_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/chapter_display_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/chapters_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/cluster_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/colour_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/content_enc_aes_settings_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/content_encoding_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/content_encodings_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/content_encryption_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/cue_point_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/cue_track_positions_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/cues_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/date_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/ebml_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/edition_entry_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/element_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/float_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/id_element_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/id_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/info_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/int_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/istream_reader_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/limited_reader_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/master_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/master_value_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/mastering_metadata_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/parser_utils_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/projection_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/recursive_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/seek_head_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/seek_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/segment_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/simple_tag_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/size_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/skip_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/slices_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/tag_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/tags_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/targets_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/time_slice_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/track_entry_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/tracks_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/unknown_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/var_int_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/video_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/virtual_block_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/void_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/webm_parser_test.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/test_utils/element_parser_test.h" + "${LIBWEBM_SRC_DIR}/webm_parser/test_utils/limited_reader.cc" + "${LIBWEBM_SRC_DIR}/webm_parser/test_utils/limited_reader.h" + "${LIBWEBM_SRC_DIR}/webm_parser/test_utils/mock_callback.h" + "${LIBWEBM_SRC_DIR}/webm_parser/test_utils/parser_test.h" + "${LIBWEBM_SRC_DIR}/webm_parser/tests/webm_parser_tests.cc") + +set(webm_info_sources + "${LIBWEBM_SRC_DIR}/common/indent.cc" + "${LIBWEBM_SRC_DIR}/common/indent.h" + "${LIBWEBM_SRC_DIR}/common/vp9_header_parser.cc" + "${LIBWEBM_SRC_DIR}/common/vp9_header_parser.h" + "${LIBWEBM_SRC_DIR}/common/vp9_level_stats.cc" + "${LIBWEBM_SRC_DIR}/common/vp9_level_stats.h" + "${LIBWEBM_SRC_DIR}/common/webm_constants.h" + "${LIBWEBM_SRC_DIR}/common/webm_endian.cc" + "${LIBWEBM_SRC_DIR}/common/webm_endian.h" + "${LIBWEBM_SRC_DIR}/webm_info.cc") + +set(webmts_sources + "${LIBWEBM_SRC_DIR}/common/libwebm_util.cc" + "${LIBWEBM_SRC_DIR}/common/libwebm_util.h" + "${LIBWEBM_SRC_DIR}/common/video_frame.cc" + "${LIBWEBM_SRC_DIR}/common/video_frame.h" + "${LIBWEBM_SRC_DIR}/m2ts/vpxpes2ts.cc" + "${LIBWEBM_SRC_DIR}/m2ts/vpxpes2ts.h" + "${LIBWEBM_SRC_DIR}/m2ts/vpxpes_parser.cc" + "${LIBWEBM_SRC_DIR}/m2ts/vpxpes_parser.h" + "${LIBWEBM_SRC_DIR}/m2ts/webm2pes.cc" + "${LIBWEBM_SRC_DIR}/m2ts/webm2pes.h") + +set(webm2pes_sources "${LIBWEBM_SRC_DIR}/m2ts/webm2pes_main.cc") +set(webm2pes_tests_sources + "${LIBWEBM_SRC_DIR}/testing/test_util.cc" + "${LIBWEBM_SRC_DIR}/testing/test_util.h" + "${LIBWEBM_SRC_DIR}/testing/video_frame_tests.cc" + "${LIBWEBM_SRC_DIR}/m2ts/tests/webm2pes_tests.cc") +set(webm2ts_sources "${LIBWEBM_SRC_DIR}/m2ts/vpxpes2ts_main.cc") + +set(webvtt_common_sources + "${LIBWEBM_SRC_DIR}/webvtt/vttreader.cc" + "${LIBWEBM_SRC_DIR}/webvtt/vttreader.h" + "${LIBWEBM_SRC_DIR}/webvtt/webvttparser.cc" + "${LIBWEBM_SRC_DIR}/webvtt/webvttparser.h") + +# Targets. +add_library(mkvmuxer OBJECT ${mkvmuxer_sources}) +add_library(mkvparser OBJECT ${mkvparser_sources}) +add_library(webvtt_common OBJECT ${webvtt_common_sources}) + +add_library(webm ${libwebm_common_sources} + $ + $) + +if (WIN32) + # Use libwebm and libwebm.lib for project and library name on Windows (instead + # webm and webm.lib). + set_target_properties(webm PROPERTIES PROJECT_LABEL libwebm) + set_target_properties(webm PROPERTIES PREFIX lib) +endif () + +add_executable(mkvparser_sample ${mkvparser_sample_sources}) +target_link_libraries(mkvparser_sample LINK_PUBLIC webm) + +add_executable(mkvmuxer_sample ${mkvmuxer_sample_sources} + $) +target_link_libraries(mkvmuxer_sample LINK_PUBLIC webm) + +add_executable(dumpvtt ${dumpvtt_sources} $) +target_link_libraries(dumpvtt LINK_PUBLIC webm) + +add_executable(vttdemux ${vttdemux_sources}) +target_link_libraries(vttdemux LINK_PUBLIC webm) + +if (ENABLE_WEBMINFO) + add_executable(webm_info ${webm_info_sources}) + target_link_libraries(webm_info LINK_PUBLIC webm) +endif () + +if (ENABLE_WEBM_PARSER) + include_directories(webm_parser webm_parser/include) + add_library(webm_parser OBJECT ${webm_parser_sources}) + target_sources(webm PUBLIC $) + set_target_properties(webm PROPERTIES PUBLIC_HEADER + "${webm_parser_public_headers}") + + add_executable(webm_parser_demo ${webm_parser_demo_sources}) + target_link_libraries(webm_parser_demo LINK_PUBLIC webm) + + install(TARGETS webm + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/webm) +endif () + +if (ENABLE_WEBMTS) + add_library(webmts OBJECT ${webmts_sources}) + + add_executable(webm2pes ${webm2pes_sources} $) + target_link_libraries(webm2pes LINK_PUBLIC webm) + + add_executable(webm2ts ${webm2ts_sources} $) + target_link_libraries(webm2ts LINK_PUBLIC webm) +endif () + +if (ENABLE_TESTS) + set(GTEST_SRC_DIR "${LIBWEBM_SRC_DIR}/../googletest" CACHE PATH + "Path to Googletest git repository.") + # This directory is where libwebm will build googletest dependencies. + set(GTEST_BUILD_DIR "${CMAKE_BINARY_DIR}/googletest_build") + + if (LIBWEBM_DISABLE_GTEST_CMAKE) + add_library(gtest STATIC "${GTEST_SRC_DIR}/googletest/src/gtest-all.cc") + include_directories("${GTEST_SRC_DIR}/googletest") + else () + add_subdirectory("${GTEST_SRC_DIR}" "${GTEST_BUILD_DIR}") + endif () + include_directories("${GTEST_SRC_DIR}/googletest/include") + + add_executable(mkvmuxer_tests ${mkvmuxer_tests_sources}) + target_link_libraries(mkvmuxer_tests LINK_PUBLIC gtest webm) + + add_executable(mkvparser_tests ${mkvparser_tests_sources}) + target_link_libraries(mkvparser_tests LINK_PUBLIC gtest webm) + + add_executable(vp9_header_parser_tests ${vp9_header_parser_tests_sources}) + target_link_libraries(vp9_header_parser_tests LINK_PUBLIC gtest webm) + + add_executable(vp9_level_stats_tests ${vp9_level_stats_tests_sources}) + target_link_libraries(vp9_level_stats_tests LINK_PUBLIC gtest webm) + + if (ENABLE_WEBMTS) + add_executable(webm2pes_tests ${webm2pes_tests_sources} + $) + target_link_libraries(webm2pes_tests LINK_PUBLIC gtest webm) + endif () + + if (ENABLE_WEBM_PARSER) + include_directories("${GTEST_SRC_DIR}/googlemock/include") + add_executable(webm_parser_tests ${webm_parser_tests_sources}) + target_link_libraries(webm_parser_tests LINK_PUBLIC gmock gtest webm) + endif () +endif () + +# Include-what-you-use. +if (ENABLE_IWYU) + # Make sure all the tools necessary for IWYU are present. + find_program(iwyu_path NAMES include-what-you-use) + find_program(iwyu_tool_path NAMES iwyu_tool.py) + + # Some odd behavior on cmake's part: PYTHON_EXECUTABLE and PYTHON_VERSION_* + # are set by cmake when it does its internal python check, but + # PYTHONINTERP_FOUND is empty without explicitly looking for it. + find_package(PythonInterp) + + if (iwyu_path AND iwyu_tool_path AND PYTHONINTERP_FOUND) + # Enable compilation command export (needed for iwyu_tool.py) + set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + + # Add a custom target to run iwyu across all targets. + add_custom_target(iwyu + ALL + COMMAND "${PYTHON_EXECUTABLE}" "${iwyu_tool_path}" -p + "${CMAKE_BINARY_DIR}" + COMMENT "Running include-what-you-use..." + VERBATIM) + else () + message(STATUS "Ignoring ENABLE_IWYU because reasons:") + message(STATUS " iwyu_path=" ${iwyu_path}) + message(STATUS " iwyu_tool_path=" ${iwyu_tool_path}) + message(STATUS " PYTHONINTERP_FOUND=" ${PYTHONINTERP_FOUND}) + message(STATUS " See README.libwebm for more information.") + endif () +endif () diff --git a/third_party/libwebm/source/CONTRIBUTING.md b/third_party/libwebm/source/CONTRIBUTING.md new file mode 100644 index 000000000000..7a73a30317af --- /dev/null +++ b/third_party/libwebm/source/CONTRIBUTING.md @@ -0,0 +1,29 @@ +# How to Contribute + +We'd love to accept your patches and contributions to this project. There are +just a few small guidelines you need to follow. + +## Contributor License Agreement + +Contributions to this project must be accompanied by a Contributor License +Agreement. You (or your employer) retain the copyright to your contribution; +this simply gives us permission to use and redistribute your contributions as +part of the project. Head over to to see +your current agreements on file or to sign a new one. + +You generally only need to submit a CLA once, so if you've already submitted one +(even if it was for a different project), you probably don't need to do it +again. + +## Code reviews + +All submissions, including submissions by project members, require review. We +use a [Gerrit](https://www.gerritcodereview.com) instance hosted at +https://chromium-review.googlesource.com for this purpose. See the +[WebM Project page](https://www.webmproject.org/code/contribute/submitting-patches/) +for additional details. + +## Community Guidelines + +This project follows +[Google's Open Source Community Guidelines](https://opensource.google.com/conduct/). diff --git a/third_party/libwebm/source/LICENSE.TXT b/third_party/libwebm/source/LICENSE.TXT new file mode 100644 index 000000000000..7a6f99547d4d --- /dev/null +++ b/third_party/libwebm/source/LICENSE.TXT @@ -0,0 +1,30 @@ +Copyright (c) 2010, Google Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * Neither the name of Google nor the names of its contributors may + be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/third_party/libwebm/source/METADATA b/third_party/libwebm/source/METADATA new file mode 100644 index 000000000000..20df252193a0 --- /dev/null +++ b/third_party/libwebm/source/METADATA @@ -0,0 +1,21 @@ +name: "libwebm" +description: + "Subtree at third_party/libwebm/source." + +third_party { + identifier { + type: "ChromiumVersion" + value: "114.0.5735.358" # from https://chromereleases.googleblog.com/2024/03/long-term-support-channel-update-for_26.html + } + identifier { + type: "Git" + value: "https://chromium.googlesource.com/webm/libwebm.git" + version: "e4fbea0c9751ae8aa86629b197a28d8276a2b0da" + # from https://chromium.googlesource.com/chromium/src/+/114.0.5735.358/DEPS#1545 + } + last_upgrade_date { + year: 2024 + month: 5 + day: 6 + } +} diff --git a/third_party/libwebm/source/Makefile.unix b/third_party/libwebm/source/Makefile.unix new file mode 100644 index 000000000000..0430d17a06b1 --- /dev/null +++ b/third_party/libwebm/source/Makefile.unix @@ -0,0 +1,57 @@ +CXX := g++ +DEFINES := -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS +DEFINES += -D__STDC_LIMIT_MACROS +INCLUDES := -I. +CXXFLAGS := -W -Wall -g -std=c++11 +ALL_CXXFLAGS := -MMD -MP $(DEFINES) $(INCLUDES) $(CXXFLAGS) +LIBWEBMA := libwebm.a +LIBWEBMSO := libwebm.so +WEBMOBJS := mkvmuxer/mkvmuxer.o mkvmuxer/mkvmuxerutil.o mkvmuxer/mkvwriter.o +WEBMOBJS += mkvparser/mkvparser.o mkvparser/mkvreader.o +WEBMOBJS += common/file_util.o common/hdr_util.o +OBJSA := $(WEBMOBJS:.o=_a.o) +OBJSSO := $(WEBMOBJS:.o=_so.o) +VTTOBJS := webvtt/vttreader.o webvtt/webvttparser.o sample_muxer_metadata.o +EXEOBJS := mkvmuxer_sample.o mkvparser_sample.o dumpvtt.o vttdemux.o +EXES := mkvparser_sample mkvmuxer_sample dumpvtt vttdemux +DEPS := $(WEBMOBJS:.o=.d) $(OBJECTS1:.o=.d) $(OBJECTS2:.o=.d) +DEPS += $(OBJECTS3:.o=.d) $(OBJECTS4:.o=.d) $(OBJSA:.o=.d) $(OBJSSO:.o=.d) +DEPS += $(VTTOBJS:.o=.d) $(EXEOBJS:.o=.d) +CLEAN := $(EXEOBJS) $(VTTOBJS) $(WEBMOBJS) $(OBJSA) $(OBJSSO) $(LIBWEBMA) +CLEAN += $(LIBWEBMSO) $(EXES) $(DEPS) $(INFOOBJS) + +all: $(EXES) + +mkvparser_sample: mkvparser_sample.o $(LIBWEBMA) + $(CXX) $^ -o $@ + +mkvmuxer_sample: mkvmuxer_sample.o $(VTTOBJS) $(LIBWEBMA) + $(CXX) $^ -o $@ + +dumpvtt: dumpvtt.o $(VTTOBJS) $(WEBMOBJS) + $(CXX) $^ -o $@ + +vttdemux: vttdemux.o $(VTTOBJS) $(LIBWEBMA) + $(CXX) $^ -o $@ + +shared: $(LIBWEBMSO) + +libwebm.a: $(OBJSA) + $(AR) rcs $@ $^ + +libwebm.so: $(OBJSSO) + $(CXX) $(ALL_CXXFLAGS) -shared $(OBJSSO) -o $(LIBWEBMSO) + +%.o: %.cc + $(CXX) -c $(ALL_CXXFLAGS) $< -o $@ +%_a.o: %.cc + $(CXX) -c $(ALL_CXXFLAGS) $< -o $@ +%_so.o: %.cc + $(CXX) -c $(ALL_CXXFLAGS) -fPIC $< -o $@ + +clean: + $(RM) -f $(CLEAN) Makefile.bak + +ifneq ($(MAKECMDGOALS), clean) + -include $(DEPS) +endif diff --git a/third_party/libwebm/source/PATENTS.TXT b/third_party/libwebm/source/PATENTS.TXT new file mode 100644 index 000000000000..caedf607e95a --- /dev/null +++ b/third_party/libwebm/source/PATENTS.TXT @@ -0,0 +1,23 @@ +Additional IP Rights Grant (Patents) +------------------------------------ + +"These implementations" means the copyrightable works that implement the WebM +codecs distributed by Google as part of the WebM Project. + +Google hereby grants to you a perpetual, worldwide, non-exclusive, no-charge, +royalty-free, irrevocable (except as stated in this section) patent license to +make, have made, use, offer to sell, sell, import, transfer, and otherwise +run, modify and propagate the contents of these implementations of WebM, where +such license applies only to those patent claims, both currently owned by +Google and acquired in the future, licensable by Google that are necessarily +infringed by these implementations of WebM. This grant does not include claims +that would be infringed only as a consequence of further modification of these +implementations. If you or your agent or exclusive licensee institute or order +or agree to the institution of patent litigation or any other patent +enforcement activity against any entity (including a cross-claim or +counterclaim in a lawsuit) alleging that any of these implementations of WebM +or any code incorporated within any of these implementations of WebM +constitute direct or contributory patent infringement, or inducement of +patent infringement, then any patent rights granted to you under this License +for these implementations of WebM shall terminate as of the date such +litigation is filed. diff --git a/third_party/libwebm/source/README.libwebm b/third_party/libwebm/source/README.libwebm new file mode 100644 index 000000000000..3406f80dbd38 --- /dev/null +++ b/third_party/libwebm/source/README.libwebm @@ -0,0 +1,143 @@ +Building Libwebm + +To build libwebm you must first create project files. To do this run cmake +and pass it the path to your libwebm repo. + +Makefile.unix can be used as a fallback on systems that cmake does not +support. + + +CMake Basics + +To generate project/make files for the default toolchain on your system simply +run cmake with the path to the libwebm repo: + +$ cmake path/to/libwebm + +On Windows the above command will produce Visual Studio project files for the +newest Visual Studio detected on the system. On Mac OS X and Linux systems, the +above command will produce a makefile. + +To control what types of projects are generated the -G parameter is added to +the cmake command line. This argument must be followed by the name of a +generator. Running cmake with the --help argument will list the available +generators for your system. + +On Mac OS X you would run the following command to generate Xcode projects: + +$ cmake path/to/libwebm -G Xcode + +On a Windows box you would run the following command to generate Visual Studio +2013 projects: + +$ cmake path/to/libwebm -G "Visual Studio 12" + +To generate 64-bit Windows Visual Studio 2013 projects: + +$ cmake path/to/libwebm "Visual Studio 12 Win64" + + +CMake Makefiles: Debugging and Optimization + +Unlike Visual Studio and Xcode projects, the build configuration for make builds +is controlled when you run cmake. The following examples demonstrate various +build configurations. + +Omitting the build type produces makefiles that use build flags containing +neither optimization nor debug flags: +$ cmake path/to/libwebm + +A makefile using release (optimized) flags is produced like this: +$ cmake path/to/libwebm -DCMAKE_BUILD_TYPE=release + +A release build with debug info can be produced as well: +$ cmake path/to/libwebm -DCMAKE_BUILD_TYPE=relwithdebinfo + +And your standard debug build will be produced using: +$ cmake path/to/libwebm -DCMAKE_BUILD_TYPE=debug + + +Tests + +To enable libwebm tests add -DENABLE_TESTS=ON CMake generation command line. For +example: + +$ cmake path/to/libwebm -G Xcode -DENABLE_TESTS=ON + +Libwebm tests depend on googletest. By default googletest is expected to be a +sibling directory of the Libwebm repository. To change that, update your CMake +command to be similar to the following: + +$ cmake path/to/libwebm -G Xcode -DENABLE_TESTS=ON \ + -DGTEST_SRC_DIR=/path/to/googletest + +The tests rely upon the LIBWEBM_TEST_DATA_PATH environment variable to locate +test input. The following example demonstrates running the muxer tests from the +build directory: + +$ LIBWEBM_TEST_DATA_PATH=path/to/libwebm/testing/testdata ./mkvmuxer_tests + +Note: Libwebm Googletest integration was built with googletest from + https://github.com/google/googletest.git at git revision + ddb8012eb48bc203aa93dcc2b22c1db516302b29. + + +CMake Include-what-you-use integration + +Include-what-you-use is an analysis tool that helps ensure libwebm includes the +C/C++ header files actually in use. To enable the integration support +ENABLE_IWYU must be turned on at cmake run time: + +$ cmake path/to/libwebm -G "Unix Makefiles" -DENABLE_IWYU=ON + +This adds the iwyu target to the build. To run include-what-you-use: + +$ make iwyu + +The following requirements must be met for ENABLE_IWYU to enable the iwyu +target: + +1. include-what-you-use and iwyu_tool.py must be in your PATH. +2. A python interpreter must be on the system and available to CMake. + +The values of the following variables are used to determine if the requirements +have been met. Values to the right of the equals sign are what a successful run +might look like: + iwyu_path=/path/to/iwyu_tool.py + iwyu_tool_path=/path/to/include-what-you-use + PYTHONINTERP_FOUND=TRUE + +An empty PYTHONINTERP_FOUND, or iwyu_path/iwyu_tool_path suffixed with NOTFOUND +are failures. + +For Include-what-you-use setup instructions, see: +https://github.com/include-what-you-use/include-what-you-use/blob/master/docs/InstructionsForUsers.md + +If, when building the iwyu target, compile errors reporting failures loading +standard include files occur, one solution can be found here: +https://github.com/include-what-you-use/include-what-you-use/issues/100 + + +CMake cross compile +To cross compile libwebm for Windows using mingw-w64 run cmake with the +following arguments: + +$ cmake -DCMAKE_TOOLCHAIN_FILE=path/to/libwebm/build/mingw-w64_toolchain.cmake \ + path/to/libwebm + +Note1: As of this writing googletest will not build via mingw-w64 without +disabling pthreads. +googletest hash: d225acc90bc3a8c420a9bcd1f033033c1ccd7fe0 + +To build with tests when using mingw-w64 use the following arguments when +running CMake: + +$ cmake -DCMAKE_TOOLCHAIN_FILE=path/to/libwebm/build/mingw-w64_toolchain.cmake \ + -DENABLE_TESTS=ON -Dgtest_disable_pthreads=ON path/to/libwebm + +Note2: i686-w64-mingw32 is the default compiler. This can be controlled using +the MINGW_PREFIX variable: + +$ cmake -DCMAKE_TOOLCHAIN_FILE=path/to/libwebm/build/mingw-w64_toolchain.cmake \ + -DMINGW_PREFIX=x86_64-w64-mingw32 path/to/libwebm + diff --git a/third_party/libwebm/source/build/cxx_flags.cmake b/third_party/libwebm/source/build/cxx_flags.cmake new file mode 100644 index 000000000000..1aa6a86cce97 --- /dev/null +++ b/third_party/libwebm/source/build/cxx_flags.cmake @@ -0,0 +1,72 @@ +## Copyright (c) 2016 The WebM project authors. All Rights Reserved. +## +## Use of this source code is governed by a BSD-style license +## that can be found in the LICENSE file in the root of the source +## tree. An additional intellectual property rights grant can be found +## in the file PATENTS. All contributing project authors may +## be found in the AUTHORS file in the root of the source tree. + +include(CheckCXXCompilerFlag) + +# String used to cache failed CXX flags. +set(LIBWEBM_FAILED_CXX_FLAGS) + +# Checks C++ compiler for support of $cxx_flag. Adds $cxx_flag to +# $CMAKE_CXX_FLAGS when the compile test passes. Caches $c_flag in +# $LIBWEBM_FAILED_CXX_FLAGS when the test fails. +function (add_cxx_flag_if_supported cxx_flag) + unset(CXX_FLAG_FOUND CACHE) + string(FIND "${CMAKE_CXX_FLAGS}" "${cxx_flag}" CXX_FLAG_FOUND) + unset(CXX_FLAG_FAILED CACHE) + string(FIND "${LIBWEBM_FAILED_CXX_FLAGS}" "${cxx_flag}" CXX_FLAG_FAILED) + + if (${CXX_FLAG_FOUND} EQUAL -1 AND ${CXX_FLAG_FAILED} EQUAL -1) + unset(CXX_FLAG_SUPPORTED CACHE) + message("Checking CXX compiler flag support for: " ${cxx_flag}) + check_cxx_compiler_flag("${cxx_flag}" CXX_FLAG_SUPPORTED) + if (CXX_FLAG_SUPPORTED) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${cxx_flag}" CACHE STRING "" + FORCE) + else () + set(LIBWEBM_FAILED_CXX_FLAGS "${LIBWEBM_FAILED_CXX_FLAGS} ${cxx_flag}" + CACHE STRING "" FORCE) + endif () + endif () +endfunction () + +# Checks CXX compiler for support of $cxx_flag and terminates generation when +# support is not present. +function (require_cxx_flag cxx_flag) + unset(CXX_FLAG_FOUND CACHE) + string(FIND "${CMAKE_CXX_FLAGS}" "${cxx_flag}" CXX_FLAG_FOUND) + + if (${CXX_FLAG_FOUND} EQUAL -1) + unset(LIBWEBM_HAVE_CXX_FLAG CACHE) + message("Checking CXX compiler flag support for: " ${cxx_flag}) + check_cxx_compiler_flag("${cxx_flag}" LIBWEBM_HAVE_CXX_FLAG) + if (NOT LIBWEBM_HAVE_CXX_FLAG) + message(FATAL_ERROR + "${PROJECT_NAME} requires support for CXX flag: ${cxx_flag}.") + endif () + set(CMAKE_CXX_FLAGS "${cxx_flag} ${CMAKE_CXX_FLAGS}" CACHE STRING "" FORCE) + endif () +endfunction () + +# Checks only non-MSVC targets for support of $cxx_flag. +function (require_cxx_flag_nomsvc cxx_flag) + if (NOT MSVC) + require_cxx_flag(${cxx_flag}) + endif () +endfunction () + +# Adds $preproc_def to CXX compiler command line (as -D$preproc_def) if not +# already present. +function (add_cxx_preproc_definition preproc_def) + unset(PREPROC_DEF_FOUND CACHE) + string(FIND "${CMAKE_CXX_FLAGS}" "${preproc_def}" PREPROC_DEF_FOUND) + + if (${PREPROC_DEF_FOUND} EQUAL -1) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D${preproc_def}" CACHE STRING "" + FORCE) + endif () +endfunction () diff --git a/third_party/libwebm/source/build/msvc_runtime.cmake b/third_party/libwebm/source/build/msvc_runtime.cmake new file mode 100644 index 000000000000..4f53a3631885 --- /dev/null +++ b/third_party/libwebm/source/build/msvc_runtime.cmake @@ -0,0 +1,22 @@ +## Copyright (c) 2015 The WebM project authors. All Rights Reserved. +## +## Use of this source code is governed by a BSD-style license +## that can be found in the LICENSE file in the root of the source +## tree. An additional intellectual property rights grant can be found +## in the file PATENTS. All contributing project authors may +## be found in the AUTHORS file in the root of the source tree. + +if (MSVC) + # CMake defaults to producing code linked to the DLL MSVC runtime. In libwebm + # static is typically desired. Force static code generation unless the user + # running CMake set MSVC_RUNTIME to dll. + if (NOT "${MSVC_RUNTIME}" STREQUAL "dll") + foreach (flag_var + CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE + CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) + if (${flag_var} MATCHES "/MD") + string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}") + endif (${flag_var} MATCHES "/MD") + endforeach (flag_var) + endif () +endif () diff --git a/third_party/libwebm/source/build/x86-mingw-gcc.cmake b/third_party/libwebm/source/build/x86-mingw-gcc.cmake new file mode 100644 index 000000000000..8416eaf784f5 --- /dev/null +++ b/third_party/libwebm/source/build/x86-mingw-gcc.cmake @@ -0,0 +1,26 @@ +## Copyright (c) 2017 The WebM project authors. All Rights Reserved. +## +## Use of this source code is governed by a BSD-style license +## that can be found in the LICENSE file in the root of the source +## tree. An additional intellectual property rights grant can be found +## in the file PATENTS. All contributing project authors may +## be found in the AUTHORS file in the root of the source tree. +if (NOT LIBWEBM_BUILD_X86_MINGW_GCC_CMAKE_) +set(LIBWEBM_BUILD_X86_MINGW_GCC_CMAKE_ 1) + +set(CMAKE_SYSTEM_PROCESSOR "x86") +set(CMAKE_SYSTEM_NAME "Windows") +set(CMAKE_C_COMPILER_ARG1 "-m32") +set(CMAKE_CXX_COMPILER_ARG1 "-m32") + +if ("${CROSS}" STREQUAL "") + set(CROSS i686-w64-mingw32-) +endif () + +set(CMAKE_C_COMPILER ${CROSS}gcc) +set(CMAKE_CXX_COMPILER ${CROSS}g++) + +# Disable googletest CMake usage for mingw cross compiles. +set(LIBWEBM_DISABLE_GTEST_CMAKE 1) + +endif () # LIBWEBM_BUILD_X86_MINGW_GCC_CMAKE_ diff --git a/third_party/libwebm/source/build/x86_64-mingw-gcc.cmake b/third_party/libwebm/source/build/x86_64-mingw-gcc.cmake new file mode 100644 index 000000000000..9db28b744225 --- /dev/null +++ b/third_party/libwebm/source/build/x86_64-mingw-gcc.cmake @@ -0,0 +1,24 @@ +## Copyright (c) 2017 The WebM project authors. All Rights Reserved. +## +## Use of this source code is governed by a BSD-style license +## that can be found in the LICENSE file in the root of the source +## tree. An additional intellectual property rights grant can be found +## in the file PATENTS. All contributing project authors may +## be found in the AUTHORS file in the root of the source tree. +if (NOT LIBWEBM_BUILD_X86_64_MINGW_GCC_CMAKE_) +set(LIBWEBM_BUILD_X86_64_MINGW_GCC_CMAKE_ 1) + +set(CMAKE_SYSTEM_PROCESSOR "x86_64") +set(CMAKE_SYSTEM_NAME "Windows") + +if ("${CROSS}" STREQUAL "") + set(CROSS x86_64-w64-mingw32-) +endif () + +set(CMAKE_C_COMPILER ${CROSS}gcc) +set(CMAKE_CXX_COMPILER ${CROSS}g++) + +# Disable googletest CMake usage for mingw cross compiles. +set(LIBWEBM_DISABLE_GTEST_CMAKE 1) + +endif () # LIBWEBM_BUILD_X86_64_MINGW_GCC_CMAKE_ diff --git a/third_party/libwebm/source/codereview.settings b/third_party/libwebm/source/codereview.settings new file mode 100644 index 000000000000..ccba2eeed246 --- /dev/null +++ b/third_party/libwebm/source/codereview.settings @@ -0,0 +1,4 @@ +# This file is used by git cl to get repository specific information. +GERRIT_HOST: True +CODE_REVIEW_SERVER: chromium-review.googlesource.com +GERRIT_SQUASH_UPLOADS: False diff --git a/third_party/libwebm/source/common/common.sh b/third_party/libwebm/source/common/common.sh new file mode 100644 index 000000000000..49fec7984f38 --- /dev/null +++ b/third_party/libwebm/source/common/common.sh @@ -0,0 +1,62 @@ +#!/bin/sh +## +## Copyright (c) 2015 The WebM project authors. All Rights Reserved. +## +## Use of this source code is governed by a BSD-style license +## that can be found in the LICENSE file in the root of the source +## tree. An additional intellectual property rights grant can be found +## in the file PATENTS. All contributing project authors may +## be found in the AUTHORS file in the root of the source tree. +## +set -e +devnull='> /dev/null 2>&1' + +readonly ORIG_PWD="$(pwd)" + +elog() { + echo "${0##*/} failed because: $@" 1>&2 +} + +vlog() { + if [ "${VERBOSE}" = "yes" ]; then + echo "$@" + fi +} + +# Terminates script when name of current directory does not match $1. +check_dir() { + current_dir="$(pwd)" + required_dir="$1" + if [ "${current_dir##*/}" != "${required_dir}" ]; then + elog "This script must be run from the ${required_dir} directory." + exit 1 + fi +} + +# Terminates the script when $1 is not in $PATH. Any arguments required for +# the tool being tested to return a successful exit code can be passed as +# additional arguments. +check_tool() { + tool="$1" + shift + tool_args="$@" + if ! eval "${tool}" ${tool_args} > /dev/null 2>&1; then + elog "${tool} must be in your path." + exit 1 + fi +} + +# Echoes git describe output for the directory specified by $1 to stdout. +git_describe() { + git_dir="$1" + check_git + echo $(git -C "${git_dir}" describe) +} + +# Echoes current git revision for the directory specifed by $1 to stdout. +git_revision() { + git_dir="$1" + check_git + echo $(git -C "${git_dir}" rev-parse HEAD) +} + diff --git a/third_party/libwebm/source/common/file_util.cc b/third_party/libwebm/source/common/file_util.cc new file mode 100644 index 000000000000..6eb6428b987a --- /dev/null +++ b/third_party/libwebm/source/common/file_util.cc @@ -0,0 +1,93 @@ +// Copyright (c) 2016 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +#include "common/file_util.h" + +#include +#ifndef _MSC_VER +#include // close() +#endif + +#include +#include +#include +#include +#include +#include + +namespace libwebm { + +std::string GetTempFileName() { +#if !defined _MSC_VER && !defined __MINGW32__ + std::string temp_file_name_template_str = + std::string(std::getenv("TEST_TMPDIR") ? std::getenv("TEST_TMPDIR") + : ".") + + "/libwebm_temp.XXXXXX"; + char* temp_file_name_template = + new char[temp_file_name_template_str.length() + 1]; + memset(temp_file_name_template, 0, temp_file_name_template_str.length() + 1); + temp_file_name_template_str.copy(temp_file_name_template, + temp_file_name_template_str.length(), 0); + int fd = mkstemp(temp_file_name_template); + std::string temp_file_name = + (fd != -1) ? std::string(temp_file_name_template) : std::string(); + delete[] temp_file_name_template; + if (fd != -1) { + close(fd); + } + return temp_file_name; +#else + char tmp_file_name[_MAX_PATH]; +#if defined _MSC_VER || defined MINGW_HAS_SECURE_API + errno_t err = tmpnam_s(tmp_file_name); +#else + char* fname_pointer = tmpnam(tmp_file_name); + int err = (fname_pointer == &tmp_file_name[0]) ? 0 : -1; +#endif + if (err == 0) { + return std::string(tmp_file_name); + } + return std::string(); +#endif +} + +uint64_t GetFileSize(const std::string& file_name) { + uint64_t file_size = 0; +#ifndef _MSC_VER + struct stat st; + st.st_size = 0; + if (stat(file_name.c_str(), &st) == 0) { +#else + struct _stat st; + st.st_size = 0; + if (_stat(file_name.c_str(), &st) == 0) { +#endif + file_size = st.st_size; + } + return file_size; +} + +bool GetFileContents(const std::string& file_name, std::string* contents) { + std::ifstream file(file_name.c_str()); + *contents = std::string(static_cast(GetFileSize(file_name)), 0); + if (file.good() && contents->size()) { + file.read(&(*contents)[0], contents->size()); + } + return !file.fail(); +} + +TempFileDeleter::TempFileDeleter() { file_name_ = GetTempFileName(); } + +TempFileDeleter::~TempFileDeleter() { + std::ifstream file(file_name_.c_str()); + if (file.good()) { + file.close(); + std::remove(file_name_.c_str()); + } +} + +} // namespace libwebm diff --git a/third_party/libwebm/source/common/file_util.h b/third_party/libwebm/source/common/file_util.h new file mode 100644 index 000000000000..a87373464187 --- /dev/null +++ b/third_party/libwebm/source/common/file_util.h @@ -0,0 +1,44 @@ +// Copyright (c) 2016 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +#ifndef LIBWEBM_COMMON_FILE_UTIL_H_ +#define LIBWEBM_COMMON_FILE_UTIL_H_ + +#include + +#include + +#include "mkvmuxer/mkvmuxertypes.h" // LIBWEBM_DISALLOW_COPY_AND_ASSIGN() + +namespace libwebm { + +// Returns a temporary file name. +std::string GetTempFileName(); + +// Returns size of file specified by |file_name|, or 0 upon failure. +uint64_t GetFileSize(const std::string& file_name); + +// Gets the contents file_name as a string. Returns false on error. +bool GetFileContents(const std::string& file_name, std::string* contents); + +// Manages life of temporary file specified at time of construction. Deletes +// file upon destruction. +class TempFileDeleter { + public: + TempFileDeleter(); + explicit TempFileDeleter(std::string file_name) : file_name_(file_name) {} + ~TempFileDeleter(); + const std::string& name() const { return file_name_; } + + private: + std::string file_name_; + LIBWEBM_DISALLOW_COPY_AND_ASSIGN(TempFileDeleter); +}; + +} // namespace libwebm + +#endif // LIBWEBM_COMMON_FILE_UTIL_H_ diff --git a/third_party/libwebm/source/common/hdr_util.cc b/third_party/libwebm/source/common/hdr_util.cc new file mode 100644 index 000000000000..916f7170b676 --- /dev/null +++ b/third_party/libwebm/source/common/hdr_util.cc @@ -0,0 +1,220 @@ +// Copyright (c) 2016 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +#include "hdr_util.h" + +#include +#include +#include + +#include "mkvparser/mkvparser.h" + +namespace libwebm { +const int Vp9CodecFeatures::kValueNotPresent = INT_MAX; + +bool CopyPrimaryChromaticity(const mkvparser::PrimaryChromaticity& parser_pc, + PrimaryChromaticityPtr* muxer_pc) { + muxer_pc->reset(new (std::nothrow) + mkvmuxer::PrimaryChromaticity(parser_pc.x, parser_pc.y)); + if (!muxer_pc->get()) + return false; + return true; +} + +bool MasteringMetadataValuePresent(double value) { + return value != mkvparser::MasteringMetadata::kValueNotPresent; +} + +bool CopyMasteringMetadata(const mkvparser::MasteringMetadata& parser_mm, + mkvmuxer::MasteringMetadata* muxer_mm) { + if (MasteringMetadataValuePresent(parser_mm.luminance_max)) + muxer_mm->set_luminance_max(parser_mm.luminance_max); + if (MasteringMetadataValuePresent(parser_mm.luminance_min)) + muxer_mm->set_luminance_min(parser_mm.luminance_min); + + PrimaryChromaticityPtr r_ptr(nullptr); + PrimaryChromaticityPtr g_ptr(nullptr); + PrimaryChromaticityPtr b_ptr(nullptr); + PrimaryChromaticityPtr wp_ptr(nullptr); + + if (parser_mm.r) { + if (!CopyPrimaryChromaticity(*parser_mm.r, &r_ptr)) + return false; + } + if (parser_mm.g) { + if (!CopyPrimaryChromaticity(*parser_mm.g, &g_ptr)) + return false; + } + if (parser_mm.b) { + if (!CopyPrimaryChromaticity(*parser_mm.b, &b_ptr)) + return false; + } + if (parser_mm.white_point) { + if (!CopyPrimaryChromaticity(*parser_mm.white_point, &wp_ptr)) + return false; + } + + if (!muxer_mm->SetChromaticity(r_ptr.get(), g_ptr.get(), b_ptr.get(), + wp_ptr.get())) { + return false; + } + + return true; +} + +bool ColourValuePresent(long long value) { + return value != mkvparser::Colour::kValueNotPresent; +} + +bool CopyColour(const mkvparser::Colour& parser_colour, + mkvmuxer::Colour* muxer_colour) { + if (!muxer_colour) + return false; + + if (ColourValuePresent(parser_colour.matrix_coefficients)) + muxer_colour->set_matrix_coefficients(parser_colour.matrix_coefficients); + if (ColourValuePresent(parser_colour.bits_per_channel)) + muxer_colour->set_bits_per_channel(parser_colour.bits_per_channel); + if (ColourValuePresent(parser_colour.chroma_subsampling_horz)) { + muxer_colour->set_chroma_subsampling_horz( + parser_colour.chroma_subsampling_horz); + } + if (ColourValuePresent(parser_colour.chroma_subsampling_vert)) { + muxer_colour->set_chroma_subsampling_vert( + parser_colour.chroma_subsampling_vert); + } + if (ColourValuePresent(parser_colour.cb_subsampling_horz)) + muxer_colour->set_cb_subsampling_horz(parser_colour.cb_subsampling_horz); + if (ColourValuePresent(parser_colour.cb_subsampling_vert)) + muxer_colour->set_cb_subsampling_vert(parser_colour.cb_subsampling_vert); + if (ColourValuePresent(parser_colour.chroma_siting_horz)) + muxer_colour->set_chroma_siting_horz(parser_colour.chroma_siting_horz); + if (ColourValuePresent(parser_colour.chroma_siting_vert)) + muxer_colour->set_chroma_siting_vert(parser_colour.chroma_siting_vert); + if (ColourValuePresent(parser_colour.range)) + muxer_colour->set_range(parser_colour.range); + if (ColourValuePresent(parser_colour.transfer_characteristics)) { + muxer_colour->set_transfer_characteristics( + parser_colour.transfer_characteristics); + } + if (ColourValuePresent(parser_colour.primaries)) + muxer_colour->set_primaries(parser_colour.primaries); + if (ColourValuePresent(parser_colour.max_cll)) + muxer_colour->set_max_cll(parser_colour.max_cll); + if (ColourValuePresent(parser_colour.max_fall)) + muxer_colour->set_max_fall(parser_colour.max_fall); + + if (parser_colour.mastering_metadata) { + mkvmuxer::MasteringMetadata muxer_mm; + if (!CopyMasteringMetadata(*parser_colour.mastering_metadata, &muxer_mm)) + return false; + if (!muxer_colour->SetMasteringMetadata(muxer_mm)) + return false; + } + return true; +} + +// Format of VPx private data: +// +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | ID Byte | Length | | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | +// | | +// : Bytes 1..Length of Codec Feature : +// | | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// +// ID Byte Format +// ID byte is an unsigned byte. +// 0 1 2 3 4 5 6 7 +// +-+-+-+-+-+-+-+-+ +// |X| ID | +// +-+-+-+-+-+-+-+-+ +// +// The X bit is reserved. +// +// See the following link for more information: +// http://www.webmproject.org/vp9/profiles/ +bool ParseVpxCodecPrivate(const uint8_t* private_data, int32_t length, + Vp9CodecFeatures* features) { + const int kVpxCodecPrivateMinLength = 3; + if (!private_data || !features || length < kVpxCodecPrivateMinLength) + return false; + + const uint8_t kVp9ProfileId = 1; + const uint8_t kVp9LevelId = 2; + const uint8_t kVp9BitDepthId = 3; + const uint8_t kVp9ChromaSubsamplingId = 4; + const int kVpxFeatureLength = 1; + int offset = 0; + + // Set features to not set. + features->profile = Vp9CodecFeatures::kValueNotPresent; + features->level = Vp9CodecFeatures::kValueNotPresent; + features->bit_depth = Vp9CodecFeatures::kValueNotPresent; + features->chroma_subsampling = Vp9CodecFeatures::kValueNotPresent; + do { + const uint8_t id_byte = private_data[offset++]; + const uint8_t length_byte = private_data[offset++]; + if (length_byte != kVpxFeatureLength) + return false; + if (id_byte == kVp9ProfileId) { + const int priv_profile = static_cast(private_data[offset++]); + if (priv_profile < 0 || priv_profile > 3) + return false; + if (features->profile != Vp9CodecFeatures::kValueNotPresent && + features->profile != priv_profile) { + return false; + } + features->profile = priv_profile; + } else if (id_byte == kVp9LevelId) { + const int priv_level = static_cast(private_data[offset++]); + + const int kNumLevels = 14; + const int levels[kNumLevels] = {10, 11, 20, 21, 30, 31, 40, + 41, 50, 51, 52, 60, 61, 62}; + + for (int i = 0; i < kNumLevels; ++i) { + if (priv_level == levels[i]) { + if (features->level != Vp9CodecFeatures::kValueNotPresent && + features->level != priv_level) { + return false; + } + features->level = priv_level; + break; + } + } + if (features->level == Vp9CodecFeatures::kValueNotPresent) + return false; + } else if (id_byte == kVp9BitDepthId) { + const int priv_profile = static_cast(private_data[offset++]); + if (priv_profile != 8 && priv_profile != 10 && priv_profile != 12) + return false; + if (features->bit_depth != Vp9CodecFeatures::kValueNotPresent && + features->bit_depth != priv_profile) { + return false; + } + features->bit_depth = priv_profile; + } else if (id_byte == kVp9ChromaSubsamplingId) { + const int priv_profile = static_cast(private_data[offset++]); + if (priv_profile != 0 && priv_profile != 2 && priv_profile != 3) + return false; + if (features->chroma_subsampling != Vp9CodecFeatures::kValueNotPresent && + features->chroma_subsampling != priv_profile) { + return false; + } + features->chroma_subsampling = priv_profile; + } else { + // Invalid ID. + return false; + } + } while (offset + kVpxCodecPrivateMinLength <= length); + + return true; +} +} // namespace libwebm diff --git a/third_party/libwebm/source/common/hdr_util.h b/third_party/libwebm/source/common/hdr_util.h new file mode 100644 index 000000000000..78e2eeb7058e --- /dev/null +++ b/third_party/libwebm/source/common/hdr_util.h @@ -0,0 +1,71 @@ +// Copyright (c) 2016 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +#ifndef LIBWEBM_COMMON_HDR_UTIL_H_ +#define LIBWEBM_COMMON_HDR_UTIL_H_ + +#include + +#include + +#include "mkvmuxer/mkvmuxer.h" + +namespace mkvparser { +struct Colour; +struct MasteringMetadata; +struct PrimaryChromaticity; +} // namespace mkvparser + +namespace libwebm { +// Utility types and functions for working with the Colour element and its +// children. Copiers return true upon success. Presence functions return true +// when the specified element is present. + +// TODO(tomfinegan): These should be moved to libwebm_utils once c++11 is +// required by libwebm. + +// Features of the VP9 codec that may be set in the CodecPrivate of a VP9 video +// stream. A value of kValueNotPresent represents that the value was not set in +// the CodecPrivate. +struct Vp9CodecFeatures { + static const int kValueNotPresent; + + Vp9CodecFeatures() + : profile(kValueNotPresent), + level(kValueNotPresent), + bit_depth(kValueNotPresent), + chroma_subsampling(kValueNotPresent) {} + ~Vp9CodecFeatures() {} + + int profile; + int level; + int bit_depth; + int chroma_subsampling; +}; + +typedef std::unique_ptr PrimaryChromaticityPtr; + +bool CopyPrimaryChromaticity(const mkvparser::PrimaryChromaticity& parser_pc, + PrimaryChromaticityPtr* muxer_pc); + +bool MasteringMetadataValuePresent(double value); + +bool CopyMasteringMetadata(const mkvparser::MasteringMetadata& parser_mm, + mkvmuxer::MasteringMetadata* muxer_mm); + +bool ColourValuePresent(long long value); + +bool CopyColour(const mkvparser::Colour& parser_colour, + mkvmuxer::Colour* muxer_colour); + +// Returns true if |features| is set to one or more valid values. +bool ParseVpxCodecPrivate(const uint8_t* private_data, int32_t length, + Vp9CodecFeatures* features); + +} // namespace libwebm + +#endif // LIBWEBM_COMMON_HDR_UTIL_H_ diff --git a/third_party/libwebm/source/common/indent.cc b/third_party/libwebm/source/common/indent.cc new file mode 100644 index 000000000000..87d656c44b49 --- /dev/null +++ b/third_party/libwebm/source/common/indent.cc @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2012 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "common/indent.h" + +#include + +namespace libwebm { + +Indent::Indent(int indent) : indent_(indent), indent_str_() { Update(); } + +void Indent::Adjust(int indent) { + indent_ += indent; + if (indent_ < 0) + indent_ = 0; + + Update(); +} + +void Indent::Update() { indent_str_ = std::string(indent_, ' '); } + +} // namespace libwebm diff --git a/third_party/libwebm/source/common/indent.h b/third_party/libwebm/source/common/indent.h new file mode 100644 index 000000000000..22d3d2695ed6 --- /dev/null +++ b/third_party/libwebm/source/common/indent.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2012 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef LIBWEBM_COMMON_INDENT_H_ +#define LIBWEBM_COMMON_INDENT_H_ + +#include + +#include "mkvmuxer/mkvmuxertypes.h" + +namespace libwebm { + +const int kIncreaseIndent = 2; +const int kDecreaseIndent = -2; + +// Used for formatting output so objects only have to keep track of spacing +// within their scope. +class Indent { + public: + explicit Indent(int indent); + + // Changes the number of spaces output. The value adjusted is relative to + // |indent_|. + void Adjust(int indent); + + std::string indent_str() const { return indent_str_; } + + private: + // Called after |indent_| is changed. This will set |indent_str_| to the + // proper number of spaces. + void Update(); + + int indent_; + std::string indent_str_; + + LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Indent); +}; + +} // namespace libwebm + +#endif // LIBWEBM_COMMON_INDENT_H_ diff --git a/third_party/libwebm/source/common/libwebm_util.cc b/third_party/libwebm/source/common/libwebm_util.cc new file mode 100644 index 000000000000..d158250fb6b4 --- /dev/null +++ b/third_party/libwebm/source/common/libwebm_util.cc @@ -0,0 +1,110 @@ +// Copyright (c) 2015 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +#include "common/libwebm_util.h" + +#include +#include +#include +#include + +namespace libwebm { + +std::int64_t NanosecondsTo90KhzTicks(std::int64_t nanoseconds) { + const double pts_seconds = nanoseconds / kNanosecondsPerSecond; + return static_cast(pts_seconds * 90000); +} + +std::int64_t Khz90TicksToNanoseconds(std::int64_t ticks) { + const double seconds = ticks / 90000.0; + return static_cast(seconds * kNanosecondsPerSecond); +} + +bool ParseVP9SuperFrameIndex(const std::uint8_t* frame, + std::size_t frame_length, Ranges* frame_ranges, + bool* error) { + if (frame == nullptr || frame_length == 0 || frame_ranges == nullptr || + error == nullptr) { + return false; + } + + bool parse_ok = false; + const std::uint8_t marker = frame[frame_length - 1]; + const std::uint32_t kHasSuperFrameIndexMask = 0xe0; + const std::uint32_t kSuperFrameMarker = 0xc0; + const std::uint32_t kLengthFieldSizeMask = 0x3; + + if ((marker & kHasSuperFrameIndexMask) == kSuperFrameMarker) { + const std::uint32_t kFrameCountMask = 0x7; + const int num_frames = (marker & kFrameCountMask) + 1; + const int length_field_size = ((marker >> 3) & kLengthFieldSizeMask) + 1; + const std::size_t index_length = 2 + length_field_size * num_frames; + + if (frame_length < index_length) { + std::fprintf(stderr, + "VP9ParseSuperFrameIndex: Invalid superframe index size.\n"); + *error = true; + return false; + } + + // Consume the super frame index. Note: it's at the end of the super frame. + const std::size_t length = frame_length - index_length; + + if (length >= index_length && + frame[frame_length - index_length] == marker) { + // Found a valid superframe index. + const std::uint8_t* byte = frame + length + 1; + + std::size_t frame_offset = 0; + + for (int i = 0; i < num_frames; ++i) { + std::uint32_t child_frame_length = 0; + + for (int j = 0; j < length_field_size; ++j) { + child_frame_length |= (*byte++) << (j * 8); + } + + if (length - frame_offset < child_frame_length) { + std::fprintf(stderr, + "ParseVP9SuperFrameIndex: Invalid superframe, sub frame " + "larger than entire frame.\n"); + *error = true; + return false; + } + + frame_ranges->push_back(Range(frame_offset, child_frame_length)); + frame_offset += child_frame_length; + } + + if (static_cast(frame_ranges->size()) != num_frames) { + std::fprintf(stderr, "VP9Parse: superframe index parse failed.\n"); + *error = true; + return false; + } + + parse_ok = true; + } else { + std::fprintf(stderr, "VP9Parse: Invalid superframe index.\n"); + *error = true; + } + } + return parse_ok; +} + +bool WriteUint8(std::uint8_t val, std::FILE* fileptr) { + if (fileptr == nullptr) + return false; + return (std::fputc(val, fileptr) == val); +} + +std::uint16_t ReadUint16(const std::uint8_t* buf) { + if (buf == nullptr) + return 0; + return ((buf[0] << 8) | buf[1]); +} + +} // namespace libwebm diff --git a/third_party/libwebm/source/common/libwebm_util.h b/third_party/libwebm/source/common/libwebm_util.h new file mode 100644 index 000000000000..71d805fcf912 --- /dev/null +++ b/third_party/libwebm/source/common/libwebm_util.h @@ -0,0 +1,65 @@ +// Copyright (c) 2015 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +#ifndef LIBWEBM_COMMON_LIBWEBM_UTIL_H_ +#define LIBWEBM_COMMON_LIBWEBM_UTIL_H_ + +#include +#include +#include +#include +#include + +namespace libwebm { + +const double kNanosecondsPerSecond = 1000000000.0; + +// fclose functor for wrapping FILE in std::unique_ptr. +// TODO(tomfinegan): Move this to file_util once c++11 restrictions are +// relaxed. +struct FILEDeleter { + int operator()(std::FILE* f) { + if (f != nullptr) + return fclose(f); + return 0; + } +}; +typedef std::unique_ptr FilePtr; + +struct Range { + Range(std::size_t off, std::size_t len) : offset(off), length(len) {} + Range() = delete; + Range(const Range&) = default; + Range(Range&&) = default; + ~Range() = default; + const std::size_t offset; + const std::size_t length; +}; +typedef std::vector Ranges; + +// Converts |nanoseconds| to 90000 Hz clock ticks and vice versa. Each return +// the converted value. +std::int64_t NanosecondsTo90KhzTicks(std::int64_t nanoseconds); +std::int64_t Khz90TicksToNanoseconds(std::int64_t khz90_ticks); + +// Returns true and stores frame offsets and lengths in |frame_ranges| when +// |frame| has a valid VP9 super frame index. Sets |error| to true when parsing +// fails for any reason. +bool ParseVP9SuperFrameIndex(const std::uint8_t* frame, + std::size_t frame_length, Ranges* frame_ranges, + bool* error); + +// Writes |val| to |fileptr| and returns true upon success. +bool WriteUint8(std::uint8_t val, std::FILE* fileptr); + +// Reads 2 bytes from |buf| and returns them as a uint16_t. Returns 0 when |buf| +// is a nullptr. +std::uint16_t ReadUint16(const std::uint8_t* buf); + +} // namespace libwebm + +#endif // LIBWEBM_COMMON_LIBWEBM_UTIL_H_ diff --git a/third_party/libwebm/source/common/video_frame.cc b/third_party/libwebm/source/common/video_frame.cc new file mode 100644 index 000000000000..00aa8dadcf68 --- /dev/null +++ b/third_party/libwebm/source/common/video_frame.cc @@ -0,0 +1,45 @@ +// Copyright (c) 2016 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +#include "common/video_frame.h" + +#include + +namespace libwebm { + +bool VideoFrame::Buffer::Init(std::size_t new_length) { + capacity = 0; + length = 0; + data.reset(new std::uint8_t[new_length]); + + if (data.get() == nullptr) { + fprintf(stderr, "VideoFrame: Out of memory."); + return false; + } + + capacity = new_length; + length = 0; + return true; +} + +bool VideoFrame::Init(std::size_t length) { return buffer_.Init(length); } + +bool VideoFrame::Init(std::size_t length, std::int64_t nano_pts, Codec codec) { + nanosecond_pts_ = nano_pts; + codec_ = codec; + return Init(length); +} + +bool VideoFrame::SetBufferLength(std::size_t length) { + if (length > buffer_.capacity || buffer_.data.get() == nullptr) + return false; + + buffer_.length = length; + return true; +} + +} // namespace libwebm diff --git a/third_party/libwebm/source/common/video_frame.h b/third_party/libwebm/source/common/video_frame.h new file mode 100644 index 000000000000..3031ef207a32 --- /dev/null +++ b/third_party/libwebm/source/common/video_frame.h @@ -0,0 +1,68 @@ +// Copyright (c) 2016 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +#ifndef LIBWEBM_COMMON_VIDEO_FRAME_H_ +#define LIBWEBM_COMMON_VIDEO_FRAME_H_ + +#include +#include + +namespace libwebm { + +// VideoFrame is a storage class for compressed video frames. +class VideoFrame { + public: + enum Codec { kVP8, kVP9 }; + struct Buffer { + Buffer() = default; + ~Buffer() = default; + + // Resets |data| to be of size |new_length| bytes, sets |capacity| to + // |new_length|, sets |length| to 0 (aka empty). Returns true for success. + bool Init(std::size_t new_length); + + std::unique_ptr data; + std::size_t length = 0; + std::size_t capacity = 0; + }; + + VideoFrame() = default; + ~VideoFrame() = default; + VideoFrame(std::int64_t pts_in_nanoseconds, Codec vpx_codec) + : nanosecond_pts_(pts_in_nanoseconds), codec_(vpx_codec) {} + VideoFrame(bool keyframe, std::int64_t pts_in_nanoseconds, Codec vpx_codec) + : keyframe_(keyframe), + nanosecond_pts_(pts_in_nanoseconds), + codec_(vpx_codec) {} + bool Init(std::size_t length); + bool Init(std::size_t length, std::int64_t nano_pts, Codec codec); + + // Updates actual length of data stored in |buffer_.data| when it's been + // written via the raw pointer returned from buffer_.data.get(). + // Returns false when buffer_.data.get() return nullptr and/or when + // |length| > |buffer_.length|. Returns true otherwise. + bool SetBufferLength(std::size_t length); + + // Accessors. + const Buffer& buffer() const { return buffer_; } + bool keyframe() const { return keyframe_; } + std::int64_t nanosecond_pts() const { return nanosecond_pts_; } + Codec codec() const { return codec_; } + + // Mutators. + void set_nanosecond_pts(std::int64_t nano_pts) { nanosecond_pts_ = nano_pts; } + + private: + Buffer buffer_; + bool keyframe_ = false; + std::int64_t nanosecond_pts_ = 0; + Codec codec_ = kVP9; +}; + +} // namespace libwebm + +#endif // LIBWEBM_COMMON_VIDEO_FRAME_H_ \ No newline at end of file diff --git a/third_party/libwebm/source/common/vp9_header_parser.cc b/third_party/libwebm/source/common/vp9_header_parser.cc new file mode 100644 index 000000000000..c017d7f57354 --- /dev/null +++ b/third_party/libwebm/source/common/vp9_header_parser.cc @@ -0,0 +1,269 @@ +// Copyright (c) 2016 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +#include "common/vp9_header_parser.h" + +#include + +namespace vp9_parser { + +bool Vp9HeaderParser::SetFrame(const uint8_t* frame, size_t length) { + if (!frame || length == 0) + return false; + + frame_ = frame; + frame_size_ = length; + bit_offset_ = 0; + profile_ = -1; + show_existing_frame_ = 0; + key_ = 0; + altref_ = 0; + error_resilient_mode_ = 0; + intra_only_ = 0; + reset_frame_context_ = 0; + color_space_ = 0; + color_range_ = 0; + subsampling_x_ = 0; + subsampling_y_ = 0; + refresh_frame_flags_ = 0; + return true; +} + +bool Vp9HeaderParser::ParseUncompressedHeader(const uint8_t* frame, + size_t length) { + if (!SetFrame(frame, length)) + return false; + const int frame_marker = VpxReadLiteral(2); + if (frame_marker != kVp9FrameMarker) { + fprintf(stderr, "Invalid VP9 frame_marker:%d\n", frame_marker); + return false; + } + + profile_ = ReadBit(); + profile_ |= ReadBit() << 1; + if (profile_ > 2) + profile_ += ReadBit(); + + // TODO(fgalligan): Decide how to handle show existing frames. + show_existing_frame_ = ReadBit(); + if (show_existing_frame_) + return true; + + key_ = !ReadBit(); + altref_ = !ReadBit(); + error_resilient_mode_ = ReadBit(); + if (key_) { + if (!ValidateVp9SyncCode()) { + fprintf(stderr, "Invalid Sync code!\n"); + return false; + } + + ParseColorSpace(); + ParseFrameResolution(); + ParseFrameParallelMode(); + ParseTileInfo(); + } else { + intra_only_ = altref_ ? ReadBit() : 0; + reset_frame_context_ = error_resilient_mode_ ? 0 : VpxReadLiteral(2); + if (intra_only_) { + if (!ValidateVp9SyncCode()) { + fprintf(stderr, "Invalid Sync code!\n"); + return false; + } + + if (profile_ > 0) { + ParseColorSpace(); + } else { + // NOTE: The intra-only frame header does not include the specification + // of either the color format or color sub-sampling in profile 0. VP9 + // specifies that the default color format should be YUV 4:2:0 in this + // case (normative). + color_space_ = kVpxCsBt601; + color_range_ = kVpxCrStudioRange; + subsampling_y_ = subsampling_x_ = 1; + bit_depth_ = 8; + } + + refresh_frame_flags_ = VpxReadLiteral(kRefFrames); + ParseFrameResolution(); + } else { + refresh_frame_flags_ = VpxReadLiteral(kRefFrames); + for (int i = 0; i < kRefsPerFrame; ++i) { + VpxReadLiteral(kRefFrames_LOG2); // Consume ref. + ReadBit(); // Consume ref sign bias. + } + + bool found = false; + for (int i = 0; i < kRefsPerFrame; ++i) { + if (ReadBit()) { + // Found previous reference, width and height did not change since + // last frame. + found = true; + break; + } + } + + if (!found) + ParseFrameResolution(); + } + } + return true; +} + +int Vp9HeaderParser::ReadBit() { + const size_t off = bit_offset_; + const size_t byte_offset = off >> 3; + const int bit_shift = 7 - static_cast(off & 0x7); + if (byte_offset < frame_size_) { + const int bit = (frame_[byte_offset] >> bit_shift) & 1; + bit_offset_++; + return bit; + } else { + return 0; + } +} + +int Vp9HeaderParser::VpxReadLiteral(int bits) { + int value = 0; + for (int bit = bits - 1; bit >= 0; --bit) + value |= ReadBit() << bit; + return value; +} + +bool Vp9HeaderParser::ValidateVp9SyncCode() { + const int sync_code_0 = VpxReadLiteral(8); + const int sync_code_1 = VpxReadLiteral(8); + const int sync_code_2 = VpxReadLiteral(8); + return (sync_code_0 == 0x49 && sync_code_1 == 0x83 && sync_code_2 == 0x42); +} + +void Vp9HeaderParser::ParseColorSpace() { + bit_depth_ = 0; + if (profile_ >= 2) + bit_depth_ = ReadBit() ? 12 : 10; + else + bit_depth_ = 8; + color_space_ = VpxReadLiteral(3); + if (color_space_ != kVpxCsSrgb) { + color_range_ = ReadBit(); + if (profile_ == 1 || profile_ == 3) { + subsampling_x_ = ReadBit(); + subsampling_y_ = ReadBit(); + ReadBit(); + } else { + subsampling_y_ = subsampling_x_ = 1; + } + } else { + color_range_ = kVpxCrFullRange; + if (profile_ == 1 || profile_ == 3) { + subsampling_y_ = subsampling_x_ = 0; + ReadBit(); + } + } +} + +void Vp9HeaderParser::ParseFrameResolution() { + width_ = VpxReadLiteral(16) + 1; + height_ = VpxReadLiteral(16) + 1; + if (ReadBit()) { + display_width_ = VpxReadLiteral(16) + 1; + display_height_ = VpxReadLiteral(16) + 1; + } else { + display_width_ = width_; + display_height_ = height_; + } +} + +void Vp9HeaderParser::ParseFrameParallelMode() { + if (!error_resilient_mode_) { + ReadBit(); // Consume refresh frame context + frame_parallel_mode_ = ReadBit(); + } else { + frame_parallel_mode_ = 1; + } +} + +void Vp9HeaderParser::ParseTileInfo() { + VpxReadLiteral(2); // Consume frame context index + + // loopfilter + VpxReadLiteral(6); // Consume filter level + VpxReadLiteral(3); // Consume sharpness level + + const bool mode_ref_delta_enabled = ReadBit(); + if (mode_ref_delta_enabled) { + const bool mode_ref_delta_update = ReadBit(); + if (mode_ref_delta_update) { + const int kMaxRefLFDeltas = 4; + for (int i = 0; i < kMaxRefLFDeltas; ++i) { + if (ReadBit()) + VpxReadLiteral(7); // Consume ref_deltas + sign + } + + const int kMaxModeDeltas = 2; + for (int i = 0; i < kMaxModeDeltas; ++i) { + if (ReadBit()) + VpxReadLiteral(7); // Consume mode_delta + sign + } + } + } + + // quantization + VpxReadLiteral(8); // Consume base_q + SkipDeltaQ(); // y dc + SkipDeltaQ(); // uv ac + SkipDeltaQ(); // uv dc + + // segmentation + const bool segmentation_enabled = ReadBit(); + if (!segmentation_enabled) { + const int aligned_width = AlignPowerOfTwo(width_, kMiSizeLog2); + const int mi_cols = aligned_width >> kMiSizeLog2; + const int aligned_mi_cols = AlignPowerOfTwo(mi_cols, kMiSizeLog2); + const int sb_cols = aligned_mi_cols >> 3; // to_sbs(mi_cols); + int min_log2_n_tiles, max_log2_n_tiles; + + for (max_log2_n_tiles = 0; + (sb_cols >> max_log2_n_tiles) >= kMinTileWidthB64; + max_log2_n_tiles++) { + } + max_log2_n_tiles--; + if (max_log2_n_tiles < 0) + max_log2_n_tiles = 0; + + for (min_log2_n_tiles = 0; (kMaxTileWidthB64 << min_log2_n_tiles) < sb_cols; + min_log2_n_tiles++) { + } + + // columns + const int max_log2_tile_cols = max_log2_n_tiles; + const int min_log2_tile_cols = min_log2_n_tiles; + int max_ones = max_log2_tile_cols - min_log2_tile_cols; + int log2_tile_cols = min_log2_tile_cols; + while (max_ones-- && ReadBit()) + log2_tile_cols++; + + // rows + int log2_tile_rows = ReadBit(); + if (log2_tile_rows) + log2_tile_rows += ReadBit(); + + row_tiles_ = 1 << log2_tile_rows; + column_tiles_ = 1 << log2_tile_cols; + } +} + +void Vp9HeaderParser::SkipDeltaQ() { + if (ReadBit()) + VpxReadLiteral(4); +} + +int Vp9HeaderParser::AlignPowerOfTwo(int value, int n) { + return (((value) + ((1 << (n)) - 1)) & ~((1 << (n)) - 1)); +} + +} // namespace vp9_parser diff --git a/third_party/libwebm/source/common/vp9_header_parser.h b/third_party/libwebm/source/common/vp9_header_parser.h new file mode 100644 index 000000000000..3e57514d9aa9 --- /dev/null +++ b/third_party/libwebm/source/common/vp9_header_parser.h @@ -0,0 +1,129 @@ +// Copyright (c) 2016 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +#ifndef LIBWEBM_COMMON_VP9_HEADER_PARSER_H_ +#define LIBWEBM_COMMON_VP9_HEADER_PARSER_H_ + +#include +#include + +namespace vp9_parser { + +const int kVp9FrameMarker = 2; +const int kMinTileWidthB64 = 4; +const int kMaxTileWidthB64 = 64; +const int kRefFrames = 8; +const int kRefsPerFrame = 3; +const int kRefFrames_LOG2 = 3; +const int kVpxCsBt601 = 1; +const int kVpxCsSrgb = 7; +const int kVpxCrStudioRange = 0; +const int kVpxCrFullRange = 1; +const int kMiSizeLog2 = 3; + +// Class to parse the header of a VP9 frame. +class Vp9HeaderParser { + public: + Vp9HeaderParser() + : frame_(NULL), + frame_size_(0), + bit_offset_(0), + profile_(-1), + show_existing_frame_(0), + key_(0), + altref_(0), + error_resilient_mode_(0), + intra_only_(0), + reset_frame_context_(0), + bit_depth_(0), + color_space_(0), + color_range_(0), + subsampling_x_(0), + subsampling_y_(0), + refresh_frame_flags_(0), + width_(0), + height_(0), + row_tiles_(0), + column_tiles_(0), + frame_parallel_mode_(0) {} + + // Parse the VP9 uncompressed header. The return values of the remaining + // functions are only valid on success. + bool ParseUncompressedHeader(const uint8_t* frame, size_t length); + + size_t frame_size() const { return frame_size_; } + int profile() const { return profile_; } + int key() const { return key_; } + int altref() const { return altref_; } + int error_resilient_mode() const { return error_resilient_mode_; } + int bit_depth() const { return bit_depth_; } + int color_space() const { return color_space_; } + int width() const { return width_; } + int height() const { return height_; } + int display_width() const { return display_width_; } + int display_height() const { return display_height_; } + int refresh_frame_flags() const { return refresh_frame_flags_; } + int row_tiles() const { return row_tiles_; } + int column_tiles() const { return column_tiles_; } + int frame_parallel_mode() const { return frame_parallel_mode_; } + + private: + // Set the compressed VP9 frame. + bool SetFrame(const uint8_t* frame, size_t length); + + // Returns the next bit of the frame. + int ReadBit(); + + // Returns the next |bits| of the frame. + int VpxReadLiteral(int bits); + + // Returns true if the vp9 sync code is valid. + bool ValidateVp9SyncCode(); + + // Parses bit_depth_, color_space_, subsampling_x_, subsampling_y_, and + // color_range_. + void ParseColorSpace(); + + // Parses width and height of the frame. + void ParseFrameResolution(); + + // Parses frame_parallel_mode_. This function skips over some features. + void ParseFrameParallelMode(); + + // Parses row and column tiles. This function skips over some features. + void ParseTileInfo(); + void SkipDeltaQ(); + int AlignPowerOfTwo(int value, int n); + + const uint8_t* frame_; + size_t frame_size_; + size_t bit_offset_; + int profile_; + int show_existing_frame_; + int key_; + int altref_; + int error_resilient_mode_; + int intra_only_; + int reset_frame_context_; + int bit_depth_; + int color_space_; + int color_range_; + int subsampling_x_; + int subsampling_y_; + int refresh_frame_flags_; + int width_; + int height_; + int display_width_; + int display_height_; + int row_tiles_; + int column_tiles_; + int frame_parallel_mode_; +}; + +} // namespace vp9_parser + +#endif // LIBWEBM_COMMON_VP9_HEADER_PARSER_H_ diff --git a/third_party/libwebm/source/common/vp9_header_parser_tests.cc b/third_party/libwebm/source/common/vp9_header_parser_tests.cc new file mode 100644 index 000000000000..d13bff2689ed --- /dev/null +++ b/third_party/libwebm/source/common/vp9_header_parser_tests.cc @@ -0,0 +1,181 @@ +// Copyright (c) 2016 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +#include "common/vp9_header_parser.h" + +#include + +#include "gtest/gtest.h" + +#include "common/hdr_util.h" +#include "mkvparser/mkvparser.h" +#include "mkvparser/mkvreader.h" +#include "testing/test_util.h" + +namespace { + +class Vp9HeaderParserTests : public ::testing::Test { + public: + Vp9HeaderParserTests() : is_reader_open_(false), segment_(NULL) {} + + ~Vp9HeaderParserTests() override { + CloseReader(); + if (segment_ != NULL) { + delete segment_; + segment_ = NULL; + } + } + + void CloseReader() { + if (is_reader_open_) { + reader_.Close(); + } + is_reader_open_ = false; + } + + void CreateAndLoadSegment(const std::string& filename, + int expected_doc_type_ver) { + filename_ = test::GetTestFilePath(filename); + ASSERT_EQ(0, reader_.Open(filename_.c_str())); + is_reader_open_ = true; + pos_ = 0; + mkvparser::EBMLHeader ebml_header; + ebml_header.Parse(&reader_, pos_); + ASSERT_EQ(1, ebml_header.m_version); + ASSERT_EQ(1, ebml_header.m_readVersion); + ASSERT_STREQ("webm", ebml_header.m_docType); + ASSERT_EQ(expected_doc_type_ver, ebml_header.m_docTypeVersion); + ASSERT_EQ(2, ebml_header.m_docTypeReadVersion); + ASSERT_EQ(0, mkvparser::Segment::CreateInstance(&reader_, pos_, segment_)); + ASSERT_FALSE(HasFailure()); + ASSERT_GE(0, segment_->Load()); + } + + void CreateAndLoadSegment(const std::string& filename) { + CreateAndLoadSegment(filename, 4); + } + + // Load a corrupted segment with no expectation of correctness. + void CreateAndLoadInvalidSegment(const std::string& filename) { + filename_ = test::GetTestFilePath(filename); + ASSERT_EQ(0, reader_.Open(filename_.c_str())); + is_reader_open_ = true; + pos_ = 0; + mkvparser::EBMLHeader ebml_header; + ebml_header.Parse(&reader_, pos_); + ASSERT_EQ(0, mkvparser::Segment::CreateInstance(&reader_, pos_, segment_)); + ASSERT_GE(0, segment_->Load()); + } + + void ProcessTheFrames(bool invalid_bitstream) { + unsigned char* data = NULL; + size_t data_len = 0; + const mkvparser::Tracks* const parser_tracks = segment_->GetTracks(); + ASSERT_TRUE(parser_tracks != NULL); + const mkvparser::Cluster* cluster = segment_->GetFirst(); + ASSERT_TRUE(cluster != NULL); + + while ((cluster != NULL) && !cluster->EOS()) { + const mkvparser::BlockEntry* block_entry; + long status = cluster->GetFirst(block_entry); // NOLINT + ASSERT_EQ(0, status); + + while ((block_entry != NULL) && !block_entry->EOS()) { + const mkvparser::Block* const block = block_entry->GetBlock(); + ASSERT_TRUE(block != NULL); + const long long trackNum = block->GetTrackNumber(); // NOLINT + const mkvparser::Track* const parser_track = + parser_tracks->GetTrackByNumber( + static_cast(trackNum)); // NOLINT + ASSERT_TRUE(parser_track != NULL); + const long long track_type = parser_track->GetType(); // NOLINT + + if (track_type == mkvparser::Track::kVideo) { + const int frame_count = block->GetFrameCount(); + + for (int i = 0; i < frame_count; ++i) { + const mkvparser::Block::Frame& frame = block->GetFrame(i); + + if (static_cast(frame.len) > data_len) { + delete[] data; + data = new unsigned char[frame.len]; + ASSERT_TRUE(data != NULL); + data_len = static_cast(frame.len); + } + ASSERT_FALSE(frame.Read(&reader_, data)); + ASSERT_EQ(parser_.ParseUncompressedHeader(data, data_len), + !invalid_bitstream); + } + } + + status = cluster->GetNext(block_entry, block_entry); + ASSERT_EQ(0, status); + } + + cluster = segment_->GetNext(cluster); + } + delete[] data; + } + + protected: + mkvparser::MkvReader reader_; + bool is_reader_open_; + mkvparser::Segment* segment_; + std::string filename_; + long long pos_; // NOLINT + vp9_parser::Vp9HeaderParser parser_; +}; + +TEST_F(Vp9HeaderParserTests, VideoOnlyFile) { + ASSERT_NO_FATAL_FAILURE(CreateAndLoadSegment("test_stereo_left_right.webm")); + ProcessTheFrames(false); + EXPECT_EQ(256, parser_.width()); + EXPECT_EQ(144, parser_.height()); + EXPECT_EQ(1, parser_.column_tiles()); + EXPECT_EQ(0, parser_.frame_parallel_mode()); +} + +TEST_F(Vp9HeaderParserTests, Muxed) { + ASSERT_NO_FATAL_FAILURE( + CreateAndLoadSegment("bbb_480p_vp9_opus_1second.webm", 4)); + ProcessTheFrames(false); + EXPECT_EQ(854, parser_.width()); + EXPECT_EQ(480, parser_.height()); + EXPECT_EQ(2, parser_.column_tiles()); + EXPECT_EQ(1, parser_.frame_parallel_mode()); +} + +TEST_F(Vp9HeaderParserTests, Invalid) { + const char* files[] = { + "invalid/invalid_vp9_bitstream-bug_1416.webm", + "invalid/invalid_vp9_bitstream-bug_1417.webm", + }; + + for (int i = 0; i < static_cast(sizeof(files) / sizeof(files[0])); ++i) { + SCOPED_TRACE(files[i]); + ASSERT_NO_FATAL_FAILURE(CreateAndLoadInvalidSegment(files[i])); + ProcessTheFrames(true); + CloseReader(); + delete segment_; + segment_ = NULL; + } +} + +TEST_F(Vp9HeaderParserTests, API) { + vp9_parser::Vp9HeaderParser parser; + uint8_t data; + EXPECT_FALSE(parser.ParseUncompressedHeader(NULL, 0)); + EXPECT_FALSE(parser.ParseUncompressedHeader(NULL, 10)); + EXPECT_FALSE(parser.ParseUncompressedHeader(&data, 0)); +} + +} // namespace + +int main(int argc, char* argv[]) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/third_party/libwebm/source/common/vp9_level_stats.cc b/third_party/libwebm/source/common/vp9_level_stats.cc new file mode 100644 index 000000000000..76891e6823e4 --- /dev/null +++ b/third_party/libwebm/source/common/vp9_level_stats.cc @@ -0,0 +1,269 @@ +// Copyright (c) 2016 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +#include "common/vp9_level_stats.h" + +#include + +#include +#include + +#include "common/webm_constants.h" + +namespace vp9_parser { + +const Vp9LevelRow Vp9LevelStats::Vp9LevelTable[kNumVp9Levels] = { + {LEVEL_1, 829440, 36864, 200, 400, 2, 1, 4, 8, 512}, + {LEVEL_1_1, 2764800, 73728, 800, 1000, 2, 1, 4, 8, 768}, + {LEVEL_2, 4608000, 122880, 1800, 1500, 2, 1, 4, 8, 960}, + {LEVEL_2_1, 9216000, 245760, 3600, 2800, 2, 2, 4, 8, 1344}, + {LEVEL_3, 20736000, 552960, 7200, 6000, 2, 4, 4, 8, 2048}, + {LEVEL_3_1, 36864000, 983040, 12000, 10000, 2, 4, 4, 8, 2752}, + {LEVEL_4, 83558400, 2228224, 18000, 16000, 4, 4, 4, 8, 4160}, + {LEVEL_4_1, 160432128, 2228224, 30000, 18000, 4, 4, 5, 6, 4160}, + {LEVEL_5, 311951360, 8912896, 60000, 36000, 6, 8, 6, 4, 8384}, + {LEVEL_5_1, 588251136, 8912896, 120000, 46000, 8, 8, 10, 4, 8384}, + // CPB Size = 0 for levels 5_2 to 6_2 + {LEVEL_5_2, 1176502272, 8912896, 180000, 0, 8, 8, 10, 4, 8384}, + {LEVEL_6, 1176502272, 35651584, 180000, 0, 8, 16, 10, 4, 16832}, + {LEVEL_6_1, 2353004544, 35651584, 240000, 0, 8, 16, 10, 4, 16832}, + {LEVEL_6_2, 4706009088, 35651584, 480000, 0, 8, 16, 10, 4, 16832}}; + +void Vp9LevelStats::AddFrame(const Vp9HeaderParser& parser, int64_t time_ns) { + ++frames; + if (start_ns_ == -1) + start_ns_ = time_ns; + end_ns_ = time_ns; + + const int width = parser.width(); + const int height = parser.height(); + const int64_t luma_picture_size = width * height; + const int64_t luma_picture_breadth = (width > height) ? width : height; + if (luma_picture_size > max_luma_picture_size_) + max_luma_picture_size_ = luma_picture_size; + if (luma_picture_breadth > max_luma_picture_breadth_) + max_luma_picture_breadth_ = luma_picture_breadth; + + total_compressed_size_ += parser.frame_size(); + + while (!luma_window_.empty() && + luma_window_.front().first < + (time_ns - (libwebm::kNanosecondsPerSecondi - 1))) { + current_luma_size_ -= luma_window_.front().second; + luma_window_.pop(); + } + current_luma_size_ += luma_picture_size; + luma_window_.push(std::make_pair(time_ns, luma_picture_size)); + if (current_luma_size_ > max_luma_size_) { + max_luma_size_ = current_luma_size_; + max_luma_end_ns_ = luma_window_.back().first; + } + + // Record CPB stats. + // Remove all frames that are less than window size. + while (cpb_window_.size() > 3) { + current_cpb_size_ -= cpb_window_.front().second; + cpb_window_.pop(); + } + cpb_window_.push(std::make_pair(time_ns, parser.frame_size())); + + current_cpb_size_ += parser.frame_size(); + if (current_cpb_size_ > max_cpb_size_) { + max_cpb_size_ = current_cpb_size_; + max_cpb_start_ns_ = cpb_window_.front().first; + max_cpb_end_ns_ = cpb_window_.back().first; + } + + if (max_cpb_window_size_ < static_cast(cpb_window_.size())) { + max_cpb_window_size_ = cpb_window_.size(); + max_cpb_window_end_ns_ = time_ns; + } + + // Record altref stats. + if (parser.altref()) { + const int delta_altref = frames_since_last_altref; + if (first_altref) { + first_altref = false; + } else if (delta_altref < minimum_altref_distance) { + minimum_altref_distance = delta_altref; + min_altref_end_ns = time_ns; + } + frames_since_last_altref = 0; + } else { + ++frames_since_last_altref; + ++displayed_frames; + // TODO(fgalligan): Add support for other color formats. Currently assuming + // 420. + total_uncompressed_bits_ += + (luma_picture_size * parser.bit_depth() * 3) / 2; + } + + // Count max reference frames. + if (parser.key() == 1) { + frames_refreshed_ = 0; + } else { + frames_refreshed_ |= parser.refresh_frame_flags(); + + int ref_frame_count = frames_refreshed_ & 1; + for (int i = 1; i < kMaxVp9RefFrames; ++i) { + ref_frame_count += (frames_refreshed_ >> i) & 1; + } + + if (ref_frame_count > max_frames_refreshed_) + max_frames_refreshed_ = ref_frame_count; + } + + // Count max tiles. + const int tiles = parser.column_tiles(); + if (tiles > max_column_tiles_) + max_column_tiles_ = tiles; +} + +Vp9Level Vp9LevelStats::GetLevel() const { + const int64_t max_luma_sample_rate = GetMaxLumaSampleRate(); + const int64_t max_luma_picture_size = GetMaxLumaPictureSize(); + const int64_t max_luma_picture_breadth = GetMaxLumaPictureBreadth(); + const double average_bitrate = GetAverageBitRate(); + const double max_cpb_size = GetMaxCpbSize(); + const double compresion_ratio = GetCompressionRatio(); + const int max_column_tiles = GetMaxColumnTiles(); + const int min_altref_distance = GetMinimumAltrefDistance(); + const int max_ref_frames = GetMaxReferenceFrames(); + + int level_index = 0; + Vp9Level max_level = LEVEL_UNKNOWN; + const double grace_multiplier = + max_luma_sample_rate_grace_percent_ / 100.0 + 1.0; + for (int i = 0; i < kNumVp9Levels; ++i) { + if (max_luma_sample_rate <= + Vp9LevelTable[i].max_luma_sample_rate * grace_multiplier) { + if (max_level < Vp9LevelTable[i].level) { + max_level = Vp9LevelTable[i].level; + level_index = i; + } + break; + } + } + for (int i = 0; i < kNumVp9Levels; ++i) { + if (max_luma_picture_size <= Vp9LevelTable[i].max_luma_picture_size) { + if (max_level < Vp9LevelTable[i].level) { + max_level = Vp9LevelTable[i].level; + level_index = i; + } + break; + } + } + for (int i = 0; i < kNumVp9Levels; ++i) { + if (max_luma_picture_breadth <= Vp9LevelTable[i].max_luma_picture_breadth) { + if (max_level < Vp9LevelTable[i].level) { + max_level = Vp9LevelTable[i].level; + level_index = i; + } + break; + } + } + for (int i = 0; i < kNumVp9Levels; ++i) { + if (average_bitrate <= Vp9LevelTable[i].average_bitrate) { + if (max_level < Vp9LevelTable[i].level) { + max_level = Vp9LevelTable[i].level; + level_index = i; + } + break; + } + } + for (int i = 0; i < kNumVp9Levels; ++i) { + // Only check CPB size for levels that are defined. + if (Vp9LevelTable[i].max_cpb_size > 0 && + max_cpb_size <= Vp9LevelTable[i].max_cpb_size) { + if (max_level < Vp9LevelTable[i].level) { + max_level = Vp9LevelTable[i].level; + level_index = i; + } + break; + } + } + for (int i = 0; i < kNumVp9Levels; ++i) { + if (max_column_tiles <= Vp9LevelTable[i].max_tiles) { + if (max_level < Vp9LevelTable[i].level) { + max_level = Vp9LevelTable[i].level; + level_index = i; + } + break; + } + } + + for (int i = 0; i < kNumVp9Levels; ++i) { + if (max_ref_frames <= Vp9LevelTable[i].max_ref_frames) { + if (max_level < Vp9LevelTable[i].level) { + max_level = Vp9LevelTable[i].level; + level_index = i; + } + break; + } + } + + // Check if the current level meets the minimum altref distance requirement. + // If not, set to unknown level as we can't move up a level as the minimum + // altref distance get farther apart and we can't move down a level as we are + // already at the minimum level for all the other requirements. + if (min_altref_distance < Vp9LevelTable[level_index].min_altref_distance) + max_level = LEVEL_UNKNOWN; + + // The minimum compression ratio has the same behavior as minimum altref + // distance. + if (compresion_ratio < Vp9LevelTable[level_index].compresion_ratio) + max_level = LEVEL_UNKNOWN; + return max_level; +} + +int64_t Vp9LevelStats::GetMaxLumaSampleRate() const { return max_luma_size_; } + +int64_t Vp9LevelStats::GetMaxLumaPictureSize() const { + return max_luma_picture_size_; +} + +int64_t Vp9LevelStats::GetMaxLumaPictureBreadth() const { + return max_luma_picture_breadth_; +} + +double Vp9LevelStats::GetAverageBitRate() const { + const int64_t frame_duration_ns = end_ns_ - start_ns_; + double duration_seconds = + ((duration_ns_ == -1) ? frame_duration_ns : duration_ns_) / + libwebm::kNanosecondsPerSecond; + if (estimate_last_frame_duration_ && + (duration_ns_ == -1 || duration_ns_ <= frame_duration_ns)) { + const double sec_per_frame = frame_duration_ns / + libwebm::kNanosecondsPerSecond / + (displayed_frames - 1); + duration_seconds += sec_per_frame; + } + + return total_compressed_size_ / duration_seconds / 125.0; +} + +double Vp9LevelStats::GetMaxCpbSize() const { return max_cpb_size_ / 125.0; } + +double Vp9LevelStats::GetCompressionRatio() const { + return total_uncompressed_bits_ / + static_cast(total_compressed_size_ * 8); +} + +int Vp9LevelStats::GetMaxColumnTiles() const { return max_column_tiles_; } + +int Vp9LevelStats::GetMinimumAltrefDistance() const { + if (minimum_altref_distance != std::numeric_limits::max()) + return minimum_altref_distance; + else + return -1; +} + +int Vp9LevelStats::GetMaxReferenceFrames() const { + return max_frames_refreshed_; +} + +} // namespace vp9_parser diff --git a/third_party/libwebm/source/common/vp9_level_stats.h b/third_party/libwebm/source/common/vp9_level_stats.h new file mode 100644 index 000000000000..45d6f5cecb0e --- /dev/null +++ b/third_party/libwebm/source/common/vp9_level_stats.h @@ -0,0 +1,215 @@ +// Copyright (c) 2016 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +#ifndef LIBWEBM_COMMON_VP9_LEVEL_STATS_H_ +#define LIBWEBM_COMMON_VP9_LEVEL_STATS_H_ + +#include +#include +#include + +#include "common/vp9_header_parser.h" + +namespace vp9_parser { + +const int kMaxVp9RefFrames = 8; + +// Defined VP9 levels. See http://www.webmproject.org/vp9/profiles/ for +// detailed information on VP9 levels. +const int kNumVp9Levels = 14; +enum Vp9Level { + LEVEL_UNKNOWN = 0, + LEVEL_1 = 10, + LEVEL_1_1 = 11, + LEVEL_2 = 20, + LEVEL_2_1 = 21, + LEVEL_3 = 30, + LEVEL_3_1 = 31, + LEVEL_4 = 40, + LEVEL_4_1 = 41, + LEVEL_5 = 50, + LEVEL_5_1 = 51, + LEVEL_5_2 = 52, + LEVEL_6 = 60, + LEVEL_6_1 = 61, + LEVEL_6_2 = 62 +}; + +struct Vp9LevelRow { + Vp9LevelRow() = default; + ~Vp9LevelRow() = default; + Vp9LevelRow(Vp9LevelRow&& other) = default; + Vp9LevelRow(const Vp9LevelRow& other) = default; + Vp9LevelRow& operator=(Vp9LevelRow&& other) = delete; + Vp9LevelRow& operator=(const Vp9LevelRow& other) = delete; + + Vp9Level level; + int64_t max_luma_sample_rate; + int64_t max_luma_picture_size; + int64_t max_luma_picture_breadth; + double average_bitrate; + double max_cpb_size; + double compresion_ratio; + int max_tiles; + int min_altref_distance; + int max_ref_frames; +}; + +// Class to determine the VP9 level of a VP9 bitstream. +class Vp9LevelStats { + public: + static const Vp9LevelRow Vp9LevelTable[kNumVp9Levels]; + + Vp9LevelStats() + : frames(0), + displayed_frames(0), + start_ns_(-1), + end_ns_(-1), + duration_ns_(-1), + max_luma_picture_size_(0), + max_luma_picture_breadth_(0), + current_luma_size_(0), + max_luma_size_(0), + max_luma_end_ns_(0), + max_luma_sample_rate_grace_percent_(1.5), + first_altref(true), + frames_since_last_altref(0), + minimum_altref_distance(std::numeric_limits::max()), + min_altref_end_ns(0), + max_cpb_window_size_(0), + max_cpb_window_end_ns_(0), + current_cpb_size_(0), + max_cpb_size_(0), + max_cpb_start_ns_(0), + max_cpb_end_ns_(0), + total_compressed_size_(0), + total_uncompressed_bits_(0), + frames_refreshed_(0), + max_frames_refreshed_(0), + max_column_tiles_(0), + estimate_last_frame_duration_(true) {} + + ~Vp9LevelStats() = default; + Vp9LevelStats(Vp9LevelStats&& other) = delete; + Vp9LevelStats(const Vp9LevelStats& other) = delete; + Vp9LevelStats& operator=(Vp9LevelStats&& other) = delete; + Vp9LevelStats& operator=(const Vp9LevelStats& other) = delete; + + // Collects stats on a VP9 frame. The frame must already be parsed by + // |parser|. |time_ns| is the start time of the frame in nanoseconds. + void AddFrame(const Vp9HeaderParser& parser, int64_t time_ns); + + // Returns the current VP9 level. All of the video frames should have been + // processed with AddFrame before calling this function. + Vp9Level GetLevel() const; + + // Returns the maximum luma samples (pixels) per second. The Alt-Ref frames + // are taken into account, therefore this number may be larger than the + // display luma samples per second + int64_t GetMaxLumaSampleRate() const; + + // The maximum frame size (width * height) in samples. + int64_t GetMaxLumaPictureSize() const; + + // The maximum frame breadth (max of width and height) in samples. + int64_t GetMaxLumaPictureBreadth() const; + + // The average bitrate of the video in kbps. + double GetAverageBitRate() const; + + // The largest data size for any 4 consecutive frames in kilobits. + double GetMaxCpbSize() const; + + // The ratio of total bytes decompressed over total bytes compressed. + double GetCompressionRatio() const; + + // The maximum number of VP9 column tiles. + int GetMaxColumnTiles() const; + + // The minimum distance in frames between two consecutive alternate reference + // frames. + int GetMinimumAltrefDistance() const; + + // The maximum number of reference frames that had to be stored. + int GetMaxReferenceFrames() const; + + // Sets the duration of the video stream in nanoseconds. If the duration is + // not explictly set by this function then this class will use end - start + // as the duration. + void set_duration(int64_t time_ns) { duration_ns_ = time_ns; } + double max_luma_sample_rate_grace_percent() const { + return max_luma_sample_rate_grace_percent_; + } + void set_max_luma_sample_rate_grace_percent(double percent) { + max_luma_sample_rate_grace_percent_ = percent; + } + bool estimate_last_frame_duration() const { + return estimate_last_frame_duration_; + } + + // If true try to estimate the last frame's duration if the stream's duration + // is not set or the stream's duration equals the last frame's timestamp. + void set_estimate_last_frame_duration(bool flag) { + estimate_last_frame_duration_ = flag; + } + + private: + int frames; + int displayed_frames; + + int64_t start_ns_; + int64_t end_ns_; + int64_t duration_ns_; + + int64_t max_luma_picture_size_; + int64_t max_luma_picture_breadth_; + + // This is used to calculate the maximum number of luma samples per second. + // The first value is the luma picture size and the second value is the time + // in nanoseconds of one frame. + std::queue> luma_window_; + int64_t current_luma_size_; + int64_t max_luma_size_; + int64_t max_luma_end_ns_; + + // MaxLumaSampleRate = (ExampleFrameRate + ExampleFrameRate / + // MinimumAltrefDistance) * MaxLumaPictureSize. For levels 1-4 + // ExampleFrameRate / MinimumAltrefDistance is non-integer, so using a sliding + // window of one frame to calculate MaxLumaSampleRate may have frames > + // (ExampleFrameRate + ExampleFrameRate / MinimumAltrefDistance) in the + // window. In order to address this issue, a grace percent of 1.5 was added. + double max_luma_sample_rate_grace_percent_; + + bool first_altref; + int frames_since_last_altref; + int minimum_altref_distance; + int64_t min_altref_end_ns; + + // This is used to calculate the maximum number of compressed bytes for four + // consecutive frames. The first value is the compressed frame size and the + // second value is the time in nanoseconds of one frame. + std::queue> cpb_window_; + int64_t max_cpb_window_size_; + int64_t max_cpb_window_end_ns_; + int64_t current_cpb_size_; + int64_t max_cpb_size_; + int64_t max_cpb_start_ns_; + int64_t max_cpb_end_ns_; + + int64_t total_compressed_size_; + int64_t total_uncompressed_bits_; + int frames_refreshed_; + int max_frames_refreshed_; + + int max_column_tiles_; + + bool estimate_last_frame_duration_; +}; + +} // namespace vp9_parser + +#endif // LIBWEBM_COMMON_VP9_LEVEL_STATS_H_ diff --git a/third_party/libwebm/source/common/vp9_level_stats_tests.cc b/third_party/libwebm/source/common/vp9_level_stats_tests.cc new file mode 100644 index 000000000000..0dec07174b6f --- /dev/null +++ b/third_party/libwebm/source/common/vp9_level_stats_tests.cc @@ -0,0 +1,191 @@ +// Copyright (c) 2016 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +#include "common/vp9_level_stats.h" + +#include +#include +#include + +#include "gtest/gtest.h" + +#include "common/hdr_util.h" +#include "common/vp9_header_parser.h" +#include "mkvparser/mkvparser.h" +#include "mkvparser/mkvreader.h" +#include "testing/test_util.h" + +namespace { + +// TODO(fgalligan): Refactor this test with other test files in this directory. +class Vp9LevelStatsTests : public ::testing::Test { + public: + Vp9LevelStatsTests() : is_reader_open_(false) {} + + ~Vp9LevelStatsTests() override { CloseReader(); } + + void CloseReader() { + if (is_reader_open_) { + reader_.Close(); + } + is_reader_open_ = false; + } + + void CreateAndLoadSegment(const std::string& filename, + int expected_doc_type_ver) { + ASSERT_NE(0u, filename.length()); + filename_ = test::GetTestFilePath(filename); + ASSERT_EQ(0, reader_.Open(filename_.c_str())); + is_reader_open_ = true; + pos_ = 0; + mkvparser::EBMLHeader ebml_header; + ebml_header.Parse(&reader_, pos_); + ASSERT_EQ(1, ebml_header.m_version); + ASSERT_EQ(1, ebml_header.m_readVersion); + ASSERT_STREQ("webm", ebml_header.m_docType); + ASSERT_EQ(expected_doc_type_ver, ebml_header.m_docTypeVersion); + ASSERT_EQ(2, ebml_header.m_docTypeReadVersion); + mkvparser::Segment* temp; + ASSERT_EQ(0, mkvparser::Segment::CreateInstance(&reader_, pos_, temp)); + segment_.reset(temp); + ASSERT_FALSE(HasFailure()); + ASSERT_GE(0, segment_->Load()); + } + + void CreateAndLoadSegment(const std::string& filename) { + CreateAndLoadSegment(filename, 4); + } + + void ProcessTheFrames() { + std::vector data; + size_t data_len = 0; + const mkvparser::Tracks* const parser_tracks = segment_->GetTracks(); + ASSERT_TRUE(parser_tracks != NULL); + const mkvparser::Cluster* cluster = segment_->GetFirst(); + ASSERT_TRUE(cluster); + + while ((cluster != NULL) && !cluster->EOS()) { + const mkvparser::BlockEntry* block_entry; + long status = cluster->GetFirst(block_entry); // NOLINT + ASSERT_EQ(0, status); + + while ((block_entry != NULL) && !block_entry->EOS()) { + const mkvparser::Block* const block = block_entry->GetBlock(); + ASSERT_TRUE(block != NULL); + const long long trackNum = block->GetTrackNumber(); // NOLINT + const mkvparser::Track* const parser_track = + parser_tracks->GetTrackByNumber( + static_cast(trackNum)); // NOLINT + ASSERT_TRUE(parser_track != NULL); + const long long track_type = parser_track->GetType(); // NOLINT + + if (track_type == mkvparser::Track::kVideo) { + const int frame_count = block->GetFrameCount(); + const long long time_ns = block->GetTime(cluster); // NOLINT + + for (int i = 0; i < frame_count; ++i) { + const mkvparser::Block::Frame& frame = block->GetFrame(i); + if (static_cast(frame.len) > data.size()) { + data.resize(frame.len); + data_len = static_cast(frame.len); + } + ASSERT_FALSE(frame.Read(&reader_, &data[0])); + parser_.ParseUncompressedHeader(&data[0], data_len); + stats_.AddFrame(parser_, time_ns); + } + } + + status = cluster->GetNext(block_entry, block_entry); + ASSERT_EQ(0, status); + } + + cluster = segment_->GetNext(cluster); + } + } + + protected: + mkvparser::MkvReader reader_; + bool is_reader_open_; + std::unique_ptr segment_; + std::string filename_; + long long pos_; // NOLINT + vp9_parser::Vp9HeaderParser parser_; + vp9_parser::Vp9LevelStats stats_; +}; + +TEST_F(Vp9LevelStatsTests, VideoOnlyFile) { + CreateAndLoadSegment("test_stereo_left_right.webm"); + ProcessTheFrames(); + EXPECT_EQ(256, parser_.width()); + EXPECT_EQ(144, parser_.height()); + EXPECT_EQ(1, parser_.column_tiles()); + EXPECT_EQ(0, parser_.frame_parallel_mode()); + + EXPECT_EQ(11, stats_.GetLevel()); + EXPECT_EQ(479232, stats_.GetMaxLumaSampleRate()); + EXPECT_EQ(36864, stats_.GetMaxLumaPictureSize()); + EXPECT_DOUBLE_EQ(264.03233333333333, stats_.GetAverageBitRate()); + EXPECT_DOUBLE_EQ(147.136, stats_.GetMaxCpbSize()); + EXPECT_DOUBLE_EQ(19.267458404715583, stats_.GetCompressionRatio()); + EXPECT_EQ(1, stats_.GetMaxColumnTiles()); + EXPECT_EQ(11, stats_.GetMinimumAltrefDistance()); + EXPECT_EQ(3, stats_.GetMaxReferenceFrames()); + + EXPECT_TRUE(stats_.estimate_last_frame_duration()); + stats_.set_estimate_last_frame_duration(false); + EXPECT_DOUBLE_EQ(275.512, stats_.GetAverageBitRate()); +} + +TEST_F(Vp9LevelStatsTests, Muxed) { + CreateAndLoadSegment("bbb_480p_vp9_opus_1second.webm", 4); + ProcessTheFrames(); + EXPECT_EQ(854, parser_.width()); + EXPECT_EQ(480, parser_.height()); + EXPECT_EQ(2, parser_.column_tiles()); + EXPECT_EQ(1, parser_.frame_parallel_mode()); + + EXPECT_EQ(30, stats_.GetLevel()); + EXPECT_EQ(9838080, stats_.GetMaxLumaSampleRate()); + EXPECT_EQ(409920, stats_.GetMaxLumaPictureSize()); + EXPECT_DOUBLE_EQ(447.09394572025053, stats_.GetAverageBitRate()); + EXPECT_DOUBLE_EQ(118.464, stats_.GetMaxCpbSize()); + EXPECT_DOUBLE_EQ(241.17670131398313, stats_.GetCompressionRatio()); + EXPECT_EQ(2, stats_.GetMaxColumnTiles()); + EXPECT_EQ(9, stats_.GetMinimumAltrefDistance()); + EXPECT_EQ(3, stats_.GetMaxReferenceFrames()); + + stats_.set_estimate_last_frame_duration(false); + EXPECT_DOUBLE_EQ(468.38413361169108, stats_.GetAverageBitRate()); +} + +TEST_F(Vp9LevelStatsTests, SetDuration) { + CreateAndLoadSegment("test_stereo_left_right.webm"); + ProcessTheFrames(); + const int64_t kDurationNano = 2080000000; // 2.08 seconds + stats_.set_duration(kDurationNano); + EXPECT_EQ(256, parser_.width()); + EXPECT_EQ(144, parser_.height()); + EXPECT_EQ(1, parser_.column_tiles()); + EXPECT_EQ(0, parser_.frame_parallel_mode()); + + EXPECT_EQ(11, stats_.GetLevel()); + EXPECT_EQ(479232, stats_.GetMaxLumaSampleRate()); + EXPECT_EQ(36864, stats_.GetMaxLumaPictureSize()); + EXPECT_DOUBLE_EQ(264.9153846153846, stats_.GetAverageBitRate()); + EXPECT_DOUBLE_EQ(147.136, stats_.GetMaxCpbSize()); + EXPECT_DOUBLE_EQ(19.267458404715583, stats_.GetCompressionRatio()); + EXPECT_EQ(1, stats_.GetMaxColumnTiles()); + EXPECT_EQ(11, stats_.GetMinimumAltrefDistance()); + EXPECT_EQ(3, stats_.GetMaxReferenceFrames()); +} + +} // namespace + +int main(int argc, char* argv[]) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/third_party/libwebm/source/common/webm_constants.h b/third_party/libwebm/source/common/webm_constants.h new file mode 100644 index 000000000000..a082ce86aa2a --- /dev/null +++ b/third_party/libwebm/source/common/webm_constants.h @@ -0,0 +1,20 @@ +// Copyright (c) 2012 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. + +#ifndef LIBWEBM_COMMON_WEBM_CONSTANTS_H_ +#define LIBWEBM_COMMON_WEBM_CONSTANTS_H_ + +namespace libwebm { + +const double kNanosecondsPerSecond = 1000000000.0; +const int kNanosecondsPerSecondi = 1000000000; +const int kNanosecondsPerMillisecond = 1000000; + +} // namespace libwebm + +#endif // LIBWEBM_COMMON_WEBM_CONSTANTS_H_ diff --git a/third_party/libwebm/source/common/webm_endian.cc b/third_party/libwebm/source/common/webm_endian.cc new file mode 100644 index 000000000000..b1ef7cad6ce1 --- /dev/null +++ b/third_party/libwebm/source/common/webm_endian.cc @@ -0,0 +1,85 @@ +// Copyright (c) 2012 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. + +#include "common/webm_endian.h" + +#include + +namespace { + +// Swaps unsigned 32 bit values to big endian if needed. Returns |value| +// unmodified if architecture is big endian. Returns swapped bytes of |value| +// if architecture is little endian. Returns 0 otherwise. +uint32_t swap32_check_little_endian(uint32_t value) { + // Check endianness. + union { + uint32_t val32; + uint8_t c[4]; + } check; + check.val32 = 0x01234567U; + + // Check for big endian. + if (check.c[3] == 0x67) + return value; + + // Check for not little endian. + if (check.c[0] != 0x67) + return 0; + + return value << 24 | ((value << 8) & 0x0000FF00U) | + ((value >> 8) & 0x00FF0000U) | value >> 24; +} + +// Swaps unsigned 64 bit values to big endian if needed. Returns |value| +// unmodified if architecture is big endian. Returns swapped bytes of |value| +// if architecture is little endian. Returns 0 otherwise. +uint64_t swap64_check_little_endian(uint64_t value) { + // Check endianness. + union { + uint64_t val64; + uint8_t c[8]; + } check; + check.val64 = 0x0123456789ABCDEFULL; + + // Check for big endian. + if (check.c[7] == 0xEF) + return value; + + // Check for not little endian. + if (check.c[0] != 0xEF) + return 0; + + return value << 56 | ((value << 40) & 0x00FF000000000000ULL) | + ((value << 24) & 0x0000FF0000000000ULL) | + ((value << 8) & 0x000000FF00000000ULL) | + ((value >> 8) & 0x00000000FF000000ULL) | + ((value >> 24) & 0x0000000000FF0000ULL) | + ((value >> 40) & 0x000000000000FF00ULL) | value >> 56; +} + +} // namespace + +namespace libwebm { + +uint32_t host_to_bigendian(uint32_t value) { + return swap32_check_little_endian(value); +} + +uint32_t bigendian_to_host(uint32_t value) { + return swap32_check_little_endian(value); +} + +uint64_t host_to_bigendian(uint64_t value) { + return swap64_check_little_endian(value); +} + +uint64_t bigendian_to_host(uint64_t value) { + return swap64_check_little_endian(value); +} + +} // namespace libwebm diff --git a/third_party/libwebm/source/common/webm_endian.h b/third_party/libwebm/source/common/webm_endian.h new file mode 100644 index 000000000000..351778b7351f --- /dev/null +++ b/third_party/libwebm/source/common/webm_endian.h @@ -0,0 +1,38 @@ +// Copyright (c) 2012 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. + +#ifndef LIBWEBM_COMMON_WEBM_ENDIAN_H_ +#define LIBWEBM_COMMON_WEBM_ENDIAN_H_ + +#include + +namespace libwebm { + +// Swaps unsigned 32 bit values to big endian if needed. Returns |value| if +// architecture is big endian. Returns big endian value if architecture is +// little endian. Returns 0 otherwise. +uint32_t host_to_bigendian(uint32_t value); + +// Swaps unsigned 32 bit values to little endian if needed. Returns |value| if +// architecture is big endian. Returns little endian value if architecture is +// little endian. Returns 0 otherwise. +uint32_t bigendian_to_host(uint32_t value); + +// Swaps unsigned 64 bit values to big endian if needed. Returns |value| if +// architecture is big endian. Returns big endian value if architecture is +// little endian. Returns 0 otherwise. +uint64_t host_to_bigendian(uint64_t value); + +// Swaps unsigned 64 bit values to little endian if needed. Returns |value| if +// architecture is big endian. Returns little endian value if architecture is +// little endian. Returns 0 otherwise. +uint64_t bigendian_to_host(uint64_t value); + +} // namespace libwebm + +#endif // LIBWEBM_COMMON_WEBM_ENDIAN_H_ diff --git a/third_party/libwebm/source/common/webmids.h b/third_party/libwebm/source/common/webmids.h new file mode 100644 index 000000000000..fc0c2081409d --- /dev/null +++ b/third_party/libwebm/source/common/webmids.h @@ -0,0 +1,193 @@ +// Copyright (c) 2012 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. + +#ifndef COMMON_WEBMIDS_H_ +#define COMMON_WEBMIDS_H_ + +namespace libwebm { + +enum MkvId { + kMkvEBML = 0x1A45DFA3, + kMkvEBMLVersion = 0x4286, + kMkvEBMLReadVersion = 0x42F7, + kMkvEBMLMaxIDLength = 0x42F2, + kMkvEBMLMaxSizeLength = 0x42F3, + kMkvDocType = 0x4282, + kMkvDocTypeVersion = 0x4287, + kMkvDocTypeReadVersion = 0x4285, + kMkvVoid = 0xEC, + kMkvSignatureSlot = 0x1B538667, + kMkvSignatureAlgo = 0x7E8A, + kMkvSignatureHash = 0x7E9A, + kMkvSignaturePublicKey = 0x7EA5, + kMkvSignature = 0x7EB5, + kMkvSignatureElements = 0x7E5B, + kMkvSignatureElementList = 0x7E7B, + kMkvSignedElement = 0x6532, + // segment + kMkvSegment = 0x18538067, + // Meta Seek Information + kMkvSeekHead = 0x114D9B74, + kMkvSeek = 0x4DBB, + kMkvSeekID = 0x53AB, + kMkvSeekPosition = 0x53AC, + // Segment Information + kMkvInfo = 0x1549A966, + kMkvTimecodeScale = 0x2AD7B1, + kMkvDuration = 0x4489, + kMkvDateUTC = 0x4461, + kMkvTitle = 0x7BA9, + kMkvMuxingApp = 0x4D80, + kMkvWritingApp = 0x5741, + // Cluster + kMkvCluster = 0x1F43B675, + kMkvTimecode = 0xE7, + kMkvPrevSize = 0xAB, + kMkvBlockGroup = 0xA0, + kMkvBlock = 0xA1, + kMkvBlockDuration = 0x9B, + kMkvReferenceBlock = 0xFB, + kMkvLaceNumber = 0xCC, + kMkvSimpleBlock = 0xA3, + kMkvBlockAdditions = 0x75A1, + kMkvBlockMore = 0xA6, + kMkvBlockAddID = 0xEE, + kMkvBlockAdditional = 0xA5, + kMkvDiscardPadding = 0x75A2, + // Track + kMkvTracks = 0x1654AE6B, + kMkvTrackEntry = 0xAE, + kMkvTrackNumber = 0xD7, + kMkvTrackUID = 0x73C5, + kMkvTrackType = 0x83, + kMkvFlagEnabled = 0xB9, + kMkvFlagDefault = 0x88, + kMkvFlagForced = 0x55AA, + kMkvFlagLacing = 0x9C, + kMkvDefaultDuration = 0x23E383, + kMkvMaxBlockAdditionID = 0x55EE, + kMkvName = 0x536E, + kMkvLanguage = 0x22B59C, + kMkvCodecID = 0x86, + kMkvCodecPrivate = 0x63A2, + kMkvCodecName = 0x258688, + kMkvCodecDelay = 0x56AA, + kMkvSeekPreRoll = 0x56BB, + // video + kMkvVideo = 0xE0, + kMkvFlagInterlaced = 0x9A, + kMkvStereoMode = 0x53B8, + kMkvAlphaMode = 0x53C0, + kMkvPixelWidth = 0xB0, + kMkvPixelHeight = 0xBA, + kMkvPixelCropBottom = 0x54AA, + kMkvPixelCropTop = 0x54BB, + kMkvPixelCropLeft = 0x54CC, + kMkvPixelCropRight = 0x54DD, + kMkvDisplayWidth = 0x54B0, + kMkvDisplayHeight = 0x54BA, + kMkvDisplayUnit = 0x54B2, + kMkvAspectRatioType = 0x54B3, + kMkvColourSpace = 0x2EB524, + kMkvFrameRate = 0x2383E3, + // end video + // colour + kMkvColour = 0x55B0, + kMkvMatrixCoefficients = 0x55B1, + kMkvBitsPerChannel = 0x55B2, + kMkvChromaSubsamplingHorz = 0x55B3, + kMkvChromaSubsamplingVert = 0x55B4, + kMkvCbSubsamplingHorz = 0x55B5, + kMkvCbSubsamplingVert = 0x55B6, + kMkvChromaSitingHorz = 0x55B7, + kMkvChromaSitingVert = 0x55B8, + kMkvRange = 0x55B9, + kMkvTransferCharacteristics = 0x55BA, + kMkvPrimaries = 0x55BB, + kMkvMaxCLL = 0x55BC, + kMkvMaxFALL = 0x55BD, + // mastering metadata + kMkvMasteringMetadata = 0x55D0, + kMkvPrimaryRChromaticityX = 0x55D1, + kMkvPrimaryRChromaticityY = 0x55D2, + kMkvPrimaryGChromaticityX = 0x55D3, + kMkvPrimaryGChromaticityY = 0x55D4, + kMkvPrimaryBChromaticityX = 0x55D5, + kMkvPrimaryBChromaticityY = 0x55D6, + kMkvWhitePointChromaticityX = 0x55D7, + kMkvWhitePointChromaticityY = 0x55D8, + kMkvLuminanceMax = 0x55D9, + kMkvLuminanceMin = 0x55DA, + // end mastering metadata + // end colour + // projection + kMkvProjection = 0x7670, + kMkvProjectionType = 0x7671, + kMkvProjectionPrivate = 0x7672, + kMkvProjectionPoseYaw = 0x7673, + kMkvProjectionPosePitch = 0x7674, + kMkvProjectionPoseRoll = 0x7675, + // end projection + // audio + kMkvAudio = 0xE1, + kMkvSamplingFrequency = 0xB5, + kMkvOutputSamplingFrequency = 0x78B5, + kMkvChannels = 0x9F, + kMkvBitDepth = 0x6264, + // end audio + // ContentEncodings + kMkvContentEncodings = 0x6D80, + kMkvContentEncoding = 0x6240, + kMkvContentEncodingOrder = 0x5031, + kMkvContentEncodingScope = 0x5032, + kMkvContentEncodingType = 0x5033, + kMkvContentCompression = 0x5034, + kMkvContentCompAlgo = 0x4254, + kMkvContentCompSettings = 0x4255, + kMkvContentEncryption = 0x5035, + kMkvContentEncAlgo = 0x47E1, + kMkvContentEncKeyID = 0x47E2, + kMkvContentSignature = 0x47E3, + kMkvContentSigKeyID = 0x47E4, + kMkvContentSigAlgo = 0x47E5, + kMkvContentSigHashAlgo = 0x47E6, + kMkvContentEncAESSettings = 0x47E7, + kMkvAESSettingsCipherMode = 0x47E8, + kMkvAESSettingsCipherInitData = 0x47E9, + // end ContentEncodings + // Cueing Data + kMkvCues = 0x1C53BB6B, + kMkvCuePoint = 0xBB, + kMkvCueTime = 0xB3, + kMkvCueTrackPositions = 0xB7, + kMkvCueTrack = 0xF7, + kMkvCueClusterPosition = 0xF1, + kMkvCueBlockNumber = 0x5378, + // Chapters + kMkvChapters = 0x1043A770, + kMkvEditionEntry = 0x45B9, + kMkvChapterAtom = 0xB6, + kMkvChapterUID = 0x73C4, + kMkvChapterStringUID = 0x5654, + kMkvChapterTimeStart = 0x91, + kMkvChapterTimeEnd = 0x92, + kMkvChapterDisplay = 0x80, + kMkvChapString = 0x85, + kMkvChapLanguage = 0x437C, + kMkvChapCountry = 0x437E, + // Tags + kMkvTags = 0x1254C367, + kMkvTag = 0x7373, + kMkvSimpleTag = 0x67C8, + kMkvTagName = 0x45A3, + kMkvTagString = 0x4487 +}; + +} // namespace libwebm + +#endif // COMMON_WEBMIDS_H_ diff --git a/third_party/libwebm/source/dumpvtt.cc b/third_party/libwebm/source/dumpvtt.cc new file mode 100644 index 000000000000..472da5238bde --- /dev/null +++ b/third_party/libwebm/source/dumpvtt.cc @@ -0,0 +1,91 @@ +// Copyright (c) 2012 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. + +#include +#include +#include "webvtt/vttreader.h" +#include "webvtt/webvttparser.h" + +int main(int argc, const char* argv[]) { + if (argc != 2) { + fprintf(stdout, "usage: dumpvtt \n"); + return EXIT_SUCCESS; + } + + libwebvtt::VttReader reader; + const char* const filename = argv[1]; + + if (int e = reader.Open(filename)) { + (void)e; + fprintf(stderr, "open failed\n"); + return EXIT_FAILURE; + } + + libwebvtt::Parser parser(&reader); + + if (int e = parser.Init()) { + (void)e; + fprintf(stderr, "parser init failed\n"); + return EXIT_FAILURE; + } + + for (libwebvtt::Cue cue;;) { + const int e = parser.Parse(&cue); + + if (e < 0) { // error + fprintf(stderr, "error parsing cue\n"); + return EXIT_FAILURE; + } + + if (e > 0) // EOF + return EXIT_SUCCESS; + + fprintf(stdout, "cue identifier: \"%s\"\n", cue.identifier.c_str()); + + const libwebvtt::Time& st = cue.start_time; + fprintf(stdout, "cue start time: \"HH=%i MM=%i SS=%i SSS=%i\"\n", st.hours, + st.minutes, st.seconds, st.milliseconds); + + const libwebvtt::Time& sp = cue.stop_time; + fprintf(stdout, "cue stop time: \"HH=%i MM=%i SS=%i SSS=%i\"\n", sp.hours, + sp.minutes, sp.seconds, sp.milliseconds); + + { + typedef libwebvtt::Cue::settings_t::const_iterator iter_t; + iter_t i = cue.settings.begin(); + const iter_t j = cue.settings.end(); + + if (i == j) { + fprintf(stdout, "cue setting: \n"); + } else { + while (i != j) { + const libwebvtt::Setting& setting = *i++; + fprintf(stdout, "cue setting: name=%s value=%s\n", + setting.name.c_str(), setting.value.c_str()); + } + } + } + + { + typedef libwebvtt::Cue::payload_t::const_iterator iter_t; + iter_t i = cue.payload.begin(); + const iter_t j = cue.payload.end(); + + int idx = 1; + while (i != j) { + const std::string& payload = *i++; + const char* const payload_str = payload.c_str(); + fprintf(stdout, "cue payload[%i]: \"%s\"\n", idx, payload_str); + ++idx; + } + } + + fprintf(stdout, "\n"); + fflush(stdout); + } +} diff --git a/third_party/libwebm/source/hdr_util.hpp b/third_party/libwebm/source/hdr_util.hpp new file mode 100644 index 000000000000..7abcb3a71741 --- /dev/null +++ b/third_party/libwebm/source/hdr_util.hpp @@ -0,0 +1,15 @@ +// Copyright (c) 2016 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +#ifndef LIBWEBM_HDR_UTIL_HPP_ +#define LIBWEBM_HDR_UTIL_HPP_ + +// This file is a wrapper for the file included immediately after this comment. +// New projects should not include this file: include the file included below. +#include "common/hdr_util.h" + +#endif // LIBWEBM_HDR_UTIL_HPP_ diff --git a/third_party/libwebm/source/iosbuild.sh b/third_party/libwebm/source/iosbuild.sh new file mode 100755 index 000000000000..a183af36e8f8 --- /dev/null +++ b/third_party/libwebm/source/iosbuild.sh @@ -0,0 +1,207 @@ +#!/bin/sh +## +## Copyright (c) 2015 The WebM project authors. All Rights Reserved. +## +## Use of this source code is governed by a BSD-style license +## that can be found in the LICENSE file in the root of the source +## tree. An additional intellectual property rights grant can be found +## in the file PATENTS. All contributing project authors may +## be found in the AUTHORS file in the root of the source tree. +## +## This script generates 'WebM.framework'. An iOS app can mux/demux WebM +## container files by including 'WebM.framework'. +## +## Run ./iosbuild.sh to generate 'WebM.framework'. By default the framework +## bundle will be created in a directory called framework. Use --out-dir to +## change the output directory. +## +## This script is based on iosbuild.sh from the libwebp project. +. $(dirname $0)/common/common.sh + +# Trap function. Cleans up build output. +cleanup() { + local readonly res=$? + cd "${ORIG_PWD}" + + for dir in ${LIBDIRS}; do + if [ -d "${dir}" ]; then + rm -rf "${dir}" + fi + done + + if [ $res -ne 0 ]; then + elog "build exited with error ($res)" + fi +} + +trap cleanup EXIT + +check_dir libwebm + +iosbuild_usage() { +cat << EOF + Usage: ${0##*/} [arguments] + --help: Display this message and exit. + --out-dir: Override output directory (default is ${OUTDIR}). + --show-build-output: Show output from each library build. + --verbose: Output information about the environment and each stage of the + build. +EOF +} + +# Extract the latest SDK version from the final field of the form: iphoneosX.Y +readonly SDK=$(xcodebuild -showsdks \ + | grep iphoneos | sort | tail -n 1 | awk '{print substr($NF, 9)}' +) + +# Extract Xcode version. +readonly XCODE=$(xcodebuild -version | grep Xcode | cut -d " " -f2) +if [ -z "${XCODE}" ]; then + echo "Xcode not available" + exit 1 +fi + +# Add iPhoneOS-V6 to the list of platforms below if you need armv6 support. +# Note that iPhoneOS-V6 support is not available with the iOS6 SDK. +readonly INCLUDES="common/file_util.h + common/hdr_util.h + common/webmids.h + mkvmuxer/mkvmuxer.h + mkvmuxer/mkvmuxertypes.h + mkvmuxer/mkvmuxerutil.h + mkvmuxer/mkvwriter.h + mkvparser/mkvparser.h + mkvparser/mkvreader.h" +readonly PLATFORMS="iPhoneSimulator + iPhoneSimulator64 + iPhoneOS-V7 + iPhoneOS-V7s + iPhoneOS-V7-arm64" +readonly TARGETDIR="WebM.framework" +readonly DEVELOPER="$(xcode-select --print-path)" +readonly PLATFORMSROOT="${DEVELOPER}/Platforms" +readonly LIPO="$(xcrun -sdk iphoneos${SDK} -find lipo)" +LIBLIST="" +OPT_FLAGS="-DNDEBUG -O3" +readonly SDK_MAJOR_VERSION="$(echo ${SDK} | awk -F '.' '{ print $1 }')" + +if [ -z "${SDK_MAJOR_VERSION}" ]; then + elog "iOS SDK not available" + exit 1 +elif [ "${SDK_MAJOR_VERSION}" -lt "6" ]; then + elog "You need iOS SDK version 6 or above" + exit 1 +else + vlog "iOS SDK Version ${SDK}" +fi + + +# Parse the command line. +while [ -n "$1" ]; do + case "$1" in + --help) + iosbuild_usage + exit + ;; + --out-dir) + OUTDIR="$2" + shift + ;; + --enable-debug) + OPT_FLAGS="-g" + ;; + --show-build-output) + devnull= + ;; + --verbose) + VERBOSE=yes + ;; + *) + iosbuild_usage + exit 1 + ;; + esac + shift +done + +readonly OPT_FLAGS="${OPT_FLAGS}" +readonly OUTDIR="${OUTDIR:-framework}" + +if [ "${VERBOSE}" = "yes" ]; then +cat << EOF + OUTDIR=${OUTDIR} + INCLUDES=${INCLUDES} + PLATFORMS=${PLATFORMS} + TARGETDIR=${TARGETDIR} + DEVELOPER=${DEVELOPER} + LIPO=${LIPO} + OPT_FLAGS=${OPT_FLAGS} + ORIG_PWD=${ORIG_PWD} +EOF +fi + +rm -rf "${OUTDIR}/${TARGETDIR}" +mkdir -p "${OUTDIR}/${TARGETDIR}/Headers/" + +for PLATFORM in ${PLATFORMS}; do + ARCH2="" + if [ "${PLATFORM}" = "iPhoneOS-V7-arm64" ]; then + PLATFORM="iPhoneOS" + ARCH="aarch64" + ARCH2="arm64" + elif [ "${PLATFORM}" = "iPhoneOS-V7s" ]; then + PLATFORM="iPhoneOS" + ARCH="armv7s" + elif [ "${PLATFORM}" = "iPhoneOS-V7" ]; then + PLATFORM="iPhoneOS" + ARCH="armv7" + elif [ "${PLATFORM}" = "iPhoneOS-V6" ]; then + PLATFORM="iPhoneOS" + ARCH="armv6" + elif [ "${PLATFORM}" = "iPhoneSimulator64" ]; then + PLATFORM="iPhoneSimulator" + ARCH="x86_64" + else + ARCH="i386" + fi + + LIBDIR="${OUTDIR}/${PLATFORM}-${SDK}-${ARCH}" + LIBDIRS="${LIBDIRS} ${LIBDIR}" + LIBFILE="${LIBDIR}/libwebm.a" + eval mkdir -p "${LIBDIR}" ${devnull} + + DEVROOT="${DEVELOPER}/Toolchains/XcodeDefault.xctoolchain" + SDKROOT="${PLATFORMSROOT}/" + SDKROOT="${SDKROOT}${PLATFORM}.platform/Developer/SDKs/${PLATFORM}${SDK}.sdk/" + CXXFLAGS="-arch ${ARCH2:-${ARCH}} -isysroot ${SDKROOT} ${OPT_FLAGS} + -miphoneos-version-min=6.0" + + # enable bitcode if available + if [ "${SDK_MAJOR_VERSION}" -gt 8 ]; then + CXXFLAGS="${CXXFLAGS} -fembed-bitcode" + fi + + # Build using the legacy makefile (instead of generating via cmake). + eval make -f Makefile.unix libwebm.a CXXFLAGS=\"${CXXFLAGS}\" ${devnull} + + # copy lib and add it to LIBLIST. + eval cp libwebm.a "${LIBFILE}" ${devnull} + LIBLIST="${LIBLIST} ${LIBFILE}" + + # clean build so we can go again. + eval make -f Makefile.unix clean ${devnull} +done + +# create include sub dirs in framework dir. +readonly framework_header_dir="${OUTDIR}/${TARGETDIR}/Headers" +readonly framework_header_sub_dirs="common mkvmuxer mkvparser" +for dir in ${framework_header_sub_dirs}; do + mkdir "${framework_header_dir}/${dir}" +done + +for header_file in ${INCLUDES}; do + eval cp -p ${header_file} "${framework_header_dir}/${header_file}" ${devnull} +done + +eval ${LIPO} -create ${LIBLIST} -output "${OUTDIR}/${TARGETDIR}/WebM" ${devnull} +echo "Succesfully built ${TARGETDIR} in ${OUTDIR}." diff --git a/third_party/libwebm/source/m2ts/tests/webm2pes_tests.cc b/third_party/libwebm/source/m2ts/tests/webm2pes_tests.cc new file mode 100644 index 000000000000..664856f1feea --- /dev/null +++ b/third_party/libwebm/source/m2ts/tests/webm2pes_tests.cc @@ -0,0 +1,158 @@ +// Copyright (c) 2016 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +#include "m2ts/webm2pes.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "gtest/gtest.h" + +#include "common/file_util.h" +#include "common/libwebm_util.h" +#include "m2ts/vpxpes_parser.h" +#include "testing/test_util.h" + +namespace { + +class Webm2PesTests : public ::testing::Test { + public: + // Constants for validating known values from input data. + const std::uint8_t kMinVideoStreamId = 0xE0; + const std::uint8_t kMaxVideoStreamId = 0xEF; + const int kPesHeaderSize = 6; + const int kPesOptionalHeaderStartOffset = kPesHeaderSize; + const int kPesOptionalHeaderSize = 9; + const int kPesOptionalHeaderMarkerValue = 0x2; + const int kWebm2PesOptHeaderRemainingSize = 6; + const int kBcmvHeaderSize = 10; + + Webm2PesTests() = default; + ~Webm2PesTests() = default; + + void CreateAndLoadTestInput() { + libwebm::Webm2Pes converter(input_file_name_, temp_file_name_.name()); + ASSERT_TRUE(converter.ConvertToFile()); + ASSERT_TRUE(parser_.Open(pes_file_name())); + } + + bool VerifyPacketStartCode(const libwebm::VpxPesParser::PesHeader& header) { + // PES packets all start with the byte sequence 0x0 0x0 0x1. + if (header.start_code[0] != 0 || header.start_code[1] != 0 || + header.start_code[2] != 1) { + return false; + } + return true; + } + + const std::string& pes_file_name() const { return temp_file_name_.name(); } + libwebm::VpxPesParser* parser() { return &parser_; } + + private: + const libwebm::TempFileDeleter temp_file_name_; + const std::string input_file_name_ = + test::GetTestFilePath("bbb_480p_vp9_opus_1second.webm"); + libwebm::VpxPesParser parser_; +}; + +TEST_F(Webm2PesTests, CreatePesFile) { CreateAndLoadTestInput(); } + +TEST_F(Webm2PesTests, CanParseFirstPacket) { + CreateAndLoadTestInput(); + libwebm::VpxPesParser::PesHeader header; + libwebm::VideoFrame frame; + ASSERT_TRUE(parser()->ParseNextPacket(&header, &frame)); + EXPECT_TRUE(VerifyPacketStartCode(header)); + + // 9 bytes: PES optional header + // 10 bytes: BCMV Header + // 83 bytes: frame + // 102 bytes total in packet length field: + const std::size_t kPesPayloadLength = 102; + EXPECT_EQ(kPesPayloadLength, header.packet_length); + + EXPECT_GE(header.stream_id, kMinVideoStreamId); + EXPECT_LE(header.stream_id, kMaxVideoStreamId); + + // Test PesOptionalHeader values. + EXPECT_EQ(kPesOptionalHeaderMarkerValue, header.opt_header.marker); + EXPECT_EQ(kWebm2PesOptHeaderRemainingSize, header.opt_header.remaining_size); + EXPECT_EQ(0, header.opt_header.scrambling); + EXPECT_EQ(0, header.opt_header.priority); + EXPECT_EQ(0, header.opt_header.data_alignment); + EXPECT_EQ(0, header.opt_header.copyright); + EXPECT_EQ(0, header.opt_header.original); + EXPECT_EQ(1, header.opt_header.has_pts); + EXPECT_EQ(0, header.opt_header.has_dts); + EXPECT_EQ(0, header.opt_header.unused_fields); + + // Test the BCMV header. + // Note: The length field of the BCMV header includes its own length. + const std::size_t kBcmvBaseLength = 10; + const std::size_t kFirstFrameLength = 83; + const libwebm::VpxPesParser::BcmvHeader kFirstBcmvHeader(kFirstFrameLength + + kBcmvBaseLength); + EXPECT_TRUE(header.bcmv_header.Valid()); + EXPECT_EQ(kFirstBcmvHeader, header.bcmv_header); + + // Parse the next packet to confirm correct parse and consumption of payload. + EXPECT_TRUE(parser()->ParseNextPacket(&header, &frame)); +} + +TEST_F(Webm2PesTests, CanMuxLargeBuffers) { + const std::size_t kBufferSize = 100 * 1024; + const std::int64_t kFakeTimestamp = libwebm::kNanosecondsPerSecond; + libwebm::VideoFrame fake_frame(kFakeTimestamp, libwebm::VideoFrame::kVP9); + ASSERT_TRUE(fake_frame.Init(kBufferSize)); + std::memset(fake_frame.buffer().data.get(), 0x80, kBufferSize); + ASSERT_TRUE(fake_frame.SetBufferLength(kBufferSize)); + libwebm::PacketDataBuffer pes_packet_buffer; + ASSERT_TRUE( + libwebm::Webm2Pes::WritePesPacket(fake_frame, &pes_packet_buffer)); + + // TODO(tomfinegan): Change VpxPesParser so it can read from a buffer, and get + // rid of this extra step. + libwebm::FilePtr pes_file(std::fopen(pes_file_name().c_str(), "wb"), + libwebm::FILEDeleter()); + ASSERT_EQ(pes_packet_buffer.size(), + fwrite(&pes_packet_buffer[0], 1, pes_packet_buffer.size(), + pes_file.get())); + fclose(pes_file.get()); + pes_file.release(); + + libwebm::VpxPesParser parser; + ASSERT_TRUE(parser.Open(pes_file_name())); + libwebm::VpxPesParser::PesHeader header; + libwebm::VideoFrame parsed_frame; + ASSERT_TRUE(parser.ParseNextPacket(&header, &parsed_frame)); + EXPECT_EQ(fake_frame.nanosecond_pts(), parsed_frame.nanosecond_pts()); + EXPECT_EQ(fake_frame.buffer().length, parsed_frame.buffer().length); + EXPECT_EQ(0, std::memcmp(fake_frame.buffer().data.get(), + parsed_frame.buffer().data.get(), kBufferSize)); +} + +TEST_F(Webm2PesTests, ParserConsumesAllInput) { + CreateAndLoadTestInput(); + libwebm::VpxPesParser::PesHeader header; + libwebm::VideoFrame frame; + while (parser()->ParseNextPacket(&header, &frame) == true) { + EXPECT_TRUE(VerifyPacketStartCode(header)); + } + EXPECT_EQ(0, parser()->BytesAvailable()); +} + +} // namespace + +int main(int argc, char* argv[]) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/third_party/libwebm/source/m2ts/vpxpes2ts.cc b/third_party/libwebm/source/m2ts/vpxpes2ts.cc new file mode 100644 index 000000000000..7684b56bd783 --- /dev/null +++ b/third_party/libwebm/source/m2ts/vpxpes2ts.cc @@ -0,0 +1,217 @@ +// Copyright (c) 2016 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +#include "m2ts/vpxpes2ts.h" + +#include +#include +#include +#include + +namespace libwebm { +// TODO(tomfinegan): Dedupe this and PesHeaderField. +// Stores a value and its size in bits for writing into a MPEG2 TS Header. +// Maximum size is 64 bits. Users may call the Check() method to perform minimal +// validation (size > 0 and <= 64). +struct TsHeaderField { + TsHeaderField(std::uint64_t value, std::uint32_t size_in_bits, + std::uint8_t byte_index, std::uint8_t bits_to_shift) + : bits(value), + num_bits(size_in_bits), + index(byte_index), + shift(bits_to_shift) {} + TsHeaderField() = delete; + TsHeaderField(const TsHeaderField&) = default; + TsHeaderField(TsHeaderField&&) = default; + ~TsHeaderField() = default; + bool Check() const { + return num_bits > 0 && num_bits <= 64 && shift >= 0 && shift < 64; + } + + // Value to be stored in the field. + std::uint64_t bits; + + // Number of bits in the value. + const int num_bits; + + // Index into the header for the byte in which |bits| will be written. + const std::uint8_t index; + + // Number of bits to left shift value before or'ing. Ignored for whole bytes. + const int shift; +}; + +// Data storage for MPEG2 Transport Stream headers. +// https://en.wikipedia.org/wiki/MPEG_transport_stream#Packet +struct TsHeader { + TsHeader(bool payload_start, bool adaptation_flag, std::uint8_t counter) + : is_payload_start(payload_start), + has_adaptation(adaptation_flag), + counter_value(counter) {} + TsHeader() = delete; + TsHeader(const TsHeader&) = default; + TsHeader(TsHeader&&) = default; + ~TsHeader() = default; + + void Write(PacketDataBuffer* buffer) const; + + // Indicates the packet is the beginning of a new fragmented payload. + const bool is_payload_start; + + // Indicates the packet contains an adaptation field. + const bool has_adaptation; + + // The sync byte is the bit pattern of 0x47 (ASCII char 'G'). + const std::uint8_t kTsHeaderSyncByte = 0x47; + const std::uint8_t sync_byte = kTsHeaderSyncByte; + + // Value for |continuity_counter|. Used to detect gaps when demuxing. + const std::uint8_t counter_value; + + // Set when FEC is impossible. Always 0. + const TsHeaderField transport_error_indicator = TsHeaderField(0, 1, 1, 7); + + // This MPEG2 TS header is the start of a new payload (aka PES packet). + const TsHeaderField payload_unit_start_indicator = + TsHeaderField(is_payload_start ? 1 : 0, 1, 1, 6); + + // Set when the current packet has a higher priority than other packets with + // the same PID. Always 0 for VPX. + const TsHeaderField transport_priority = TsHeaderField(0, 1, 1, 5); + + // https://en.wikipedia.org/wiki/MPEG_transport_stream#Packet_Identifier_.28PID.29 + // 0x0020-0x1FFA May be assigned as needed to Program Map Tables, elementary + // streams and other data tables. + // Note: Though we hard code to 0x20, this value is actually 13 bits-- the + // buffer for the header is always set to 0, so it doesn't matter in practice. + const TsHeaderField pid = TsHeaderField(0x20, 8, 2, 0); + + // Indicates scrambling key. Unused; always 0. + const TsHeaderField scrambling_control = TsHeaderField(0, 2, 3, 6); + + // Adaptation field flag. Unused; always 0. + // TODO(tomfinegan): Not sure this is OK. Might need to add support for + // writing the Adaptation Field. + const TsHeaderField adaptation_field_flag = + TsHeaderField(has_adaptation ? 1 : 0, 1, 3, 5); + + // Payload flag. All output packets created here have payloads. Always 1. + const TsHeaderField payload_flag = TsHeaderField(1, 1, 3, 4); + + // Continuity counter. Two bit field that is incremented for every packet. + const TsHeaderField continuity_counter = + TsHeaderField(counter_value, 4, 3, 3); +}; + +void TsHeader::Write(PacketDataBuffer* buffer) const { + std::uint8_t* byte = &(*buffer)[0]; + *byte = sync_byte; + + *++byte = 0; + *byte |= transport_error_indicator.bits << transport_error_indicator.shift; + *byte |= payload_unit_start_indicator.bits + << payload_unit_start_indicator.shift; + *byte |= transport_priority.bits << transport_priority.shift; + + *++byte = pid.bits & 0xff; + + *++byte = 0; + *byte |= scrambling_control.bits << scrambling_control.shift; + *byte |= adaptation_field_flag.bits << adaptation_field_flag.shift; + *byte |= payload_flag.bits << payload_flag.shift; + *byte |= continuity_counter.bits; // last 4 bits. +} + +bool VpxPes2Ts::ConvertToFile() { + output_file_ = FilePtr(fopen(output_file_name_.c_str(), "wb"), FILEDeleter()); + if (output_file_ == nullptr) { + std::fprintf(stderr, "VpxPes2Ts: Cannot open %s for output.\n", + output_file_name_.c_str()); + return false; + } + pes_converter_.reset(new Webm2Pes(input_file_name_, this)); + if (pes_converter_ == nullptr) { + std::fprintf(stderr, "VpxPes2Ts: Out of memory.\n"); + return false; + } + return pes_converter_->ConvertToPacketReceiver(); +} + +bool VpxPes2Ts::ReceivePacket(const PacketDataBuffer& packet_data) { + const int kTsHeaderSize = 4; + const int kTsPayloadSize = 184; + const int kTsPacketSize = kTsHeaderSize + kTsPayloadSize; + int bytes_to_packetize = static_cast(packet_data.size()); + std::uint8_t continuity_counter = 0; + std::size_t read_pos = 0; + + ts_buffer_.reserve(kTsPacketSize); + + while (bytes_to_packetize > 0) { + if (continuity_counter > 0xf) + continuity_counter = 0; + + // Calculate payload size (need to know if we'll have to pad with an empty + // adaptation field). + int payload_size = std::min(bytes_to_packetize, kTsPayloadSize); + + // Write the TS header. + const TsHeader header( + bytes_to_packetize == static_cast(packet_data.size()), + payload_size != kTsPayloadSize, continuity_counter); + header.Write(&ts_buffer_); + int write_pos = kTsHeaderSize; + + // (pre)Pad payload with an empty adaptation field. All packets must be + // |kTsPacketSize| (188). + if (payload_size < kTsPayloadSize) { + // We need at least 2 bytes to write an empty adaptation field. + if (payload_size == (kTsPayloadSize - 1)) { + payload_size--; + } + + // Padding adaptation field: + // 8 bits: number of adaptation field bytes following this byte. + // 8 bits: unused (in this program) flags. + // This is followed by a run of 0xff to reach |kTsPayloadSize| (184) + // bytes. + const int pad_size = kTsPayloadSize - payload_size - 1 - 1; + ts_buffer_[write_pos++] = pad_size + 1; + ts_buffer_[write_pos++] = 0; + + const std::uint8_t kStuffingByte = 0xff; + for (int i = 0; i < pad_size; ++i) { + ts_buffer_[write_pos++] = kStuffingByte; + } + } + + for (int i = 0; i < payload_size; ++i) { + ts_buffer_[write_pos++] = packet_data[read_pos++]; + } + + bytes_to_packetize -= payload_size; + continuity_counter++; + + if (write_pos != kTsPacketSize) { + fprintf(stderr, "VpxPes2Ts: Invalid packet length.\n"); + return false; + } + + // Write contents of |ts_buffer_| to |output_file_|. + // TODO(tomfinegan): Writing 188 bytes at a time isn't exactly efficient... + // Fix me. + if (static_cast(std::fwrite(&ts_buffer_[0], 1, kTsPacketSize, + output_file_.get())) != kTsPacketSize) { + std::fprintf(stderr, "VpxPes2Ts: TS packet write failed.\n"); + return false; + } + } + + return true; +} + +} // namespace libwebm diff --git a/third_party/libwebm/source/m2ts/vpxpes2ts.h b/third_party/libwebm/source/m2ts/vpxpes2ts.h new file mode 100644 index 000000000000..2609a1f1b1a4 --- /dev/null +++ b/third_party/libwebm/source/m2ts/vpxpes2ts.h @@ -0,0 +1,45 @@ +// Copyright (c) 2016 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +#ifndef LIBWEBM_M2TS_VPXPES2TS_H_ +#define LIBWEBM_M2TS_VPXPES2TS_H_ + +#include +#include + +#include "common/libwebm_util.h" +#include "m2ts/webm2pes.h" + +namespace libwebm { + +class VpxPes2Ts : public PacketReceiverInterface { + public: + VpxPes2Ts(const std::string& input_file_name, + const std::string& output_file_name) + : input_file_name_(input_file_name), + output_file_name_(output_file_name) {} + virtual ~VpxPes2Ts() = default; + VpxPes2Ts() = delete; + VpxPes2Ts(const VpxPes2Ts&) = delete; + VpxPes2Ts(VpxPes2Ts&&) = delete; + + bool ConvertToFile(); + + private: + bool ReceivePacket(const PacketDataBuffer& packet_data) override; + + const std::string input_file_name_; + const std::string output_file_name_; + + FilePtr output_file_; + std::unique_ptr pes_converter_; + PacketDataBuffer ts_buffer_; +}; + +} // namespace libwebm + +#endif // LIBWEBM_M2TS_VPXPES2TS_H_ diff --git a/third_party/libwebm/source/m2ts/vpxpes2ts_main.cc b/third_party/libwebm/source/m2ts/vpxpes2ts_main.cc new file mode 100644 index 000000000000..435d8055a624 --- /dev/null +++ b/third_party/libwebm/source/m2ts/vpxpes2ts_main.cc @@ -0,0 +1,33 @@ +// Copyright (c) 2016 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +#include "m2ts/vpxpes2ts.h" + +#include +#include +#include + +namespace { + +void Usage(const char* argv[]) { + printf("Usage: %s ", argv[0]); +} + +} // namespace + +int main(int argc, const char* argv[]) { + if (argc < 3) { + Usage(argv); + return EXIT_FAILURE; + } + + const std::string input_path = argv[1]; + const std::string output_path = argv[2]; + + libwebm::VpxPes2Ts converter(input_path, output_path); + return converter.ConvertToFile() == true ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/third_party/libwebm/source/m2ts/vpxpes_parser.cc b/third_party/libwebm/source/m2ts/vpxpes_parser.cc new file mode 100644 index 000000000000..4f6fe5ced5df --- /dev/null +++ b/third_party/libwebm/source/m2ts/vpxpes_parser.cc @@ -0,0 +1,409 @@ +// Copyright (c) 2016 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +#include "vpxpes_parser.h" + +#include +#include +#include +#include +#include + +#include "common/file_util.h" + +namespace libwebm { + +VpxPesParser::BcmvHeader::BcmvHeader(std::uint32_t len) : length(len) { + id[0] = 'B'; + id[1] = 'C'; + id[2] = 'M'; + id[3] = 'V'; +} + +bool VpxPesParser::BcmvHeader::operator==(const BcmvHeader& other) const { + return (other.length == length && other.id[0] == id[0] && + other.id[1] == id[1] && other.id[2] == id[2] && other.id[3] == id[3]); +} + +bool VpxPesParser::BcmvHeader::Valid() const { + return (length > 0 && id[0] == 'B' && id[1] == 'C' && id[2] == 'M' && + id[3] == 'V'); +} + +// TODO(tomfinegan): Break Open() into separate functions. One that opens the +// file, and one that reads one packet at a time. As things are files larger +// than the maximum availble memory for the current process cannot be loaded. +bool VpxPesParser::Open(const std::string& pes_file) { + pes_file_size_ = static_cast(libwebm::GetFileSize(pes_file)); + if (pes_file_size_ <= 0) + return false; + pes_file_data_.reserve(static_cast(pes_file_size_)); + libwebm::FilePtr file = libwebm::FilePtr(std::fopen(pes_file.c_str(), "rb"), + libwebm::FILEDeleter()); + int byte; + while ((byte = fgetc(file.get())) != EOF) { + pes_file_data_.push_back(static_cast(byte)); + } + + if (!feof(file.get()) || ferror(file.get()) || + pes_file_size_ != pes_file_data_.size()) { + return false; + } + + read_pos_ = 0; + parse_state_ = kFindStartCode; + return true; +} + +bool VpxPesParser::VerifyPacketStartCode() const { + if (read_pos_ + 2 > pes_file_data_.size()) + return false; + + // PES packets all start with the byte sequence 0x0 0x0 0x1. + if (pes_file_data_[read_pos_] != 0 || pes_file_data_[read_pos_ + 1] != 0 || + pes_file_data_[read_pos_ + 2] != 1) { + return false; + } + + return true; +} + +bool VpxPesParser::ReadStreamId(std::uint8_t* stream_id) const { + if (!stream_id || BytesAvailable() < 4) + return false; + + *stream_id = pes_file_data_[read_pos_ + 3]; + return true; +} + +bool VpxPesParser::ReadPacketLength(std::uint16_t* packet_length) const { + if (!packet_length || BytesAvailable() < 6) + return false; + + // Read and byte swap 16 bit big endian length. + *packet_length = + (pes_file_data_[read_pos_ + 4] << 8) | pes_file_data_[read_pos_ + 5]; + + return true; +} + +bool VpxPesParser::ParsePesHeader(PesHeader* header) { + if (!header || parse_state_ != kParsePesHeader) + return false; + + if (!VerifyPacketStartCode()) + return false; + + std::size_t pos = read_pos_; + for (auto& a : header->start_code) { + a = pes_file_data_[pos++]; + } + + // PES Video stream IDs start at E0. + if (!ReadStreamId(&header->stream_id)) + return false; + + if (header->stream_id < kMinVideoStreamId || + header->stream_id > kMaxVideoStreamId) + return false; + + if (!ReadPacketLength(&header->packet_length)) + return false; + + read_pos_ += kPesHeaderSize; + parse_state_ = kParsePesOptionalHeader; + return true; +} + +// TODO(tomfinegan): Make these masks constants. +bool VpxPesParser::ParsePesOptionalHeader(PesOptionalHeader* header) { + if (!header || parse_state_ != kParsePesOptionalHeader || + read_pos_ >= pes_file_size_) { + return false; + } + + std::size_t consumed = 0; + PacketData poh_buffer; + if (!RemoveStartCodeEmulationPreventionBytes(&pes_file_data_[read_pos_], + kPesOptionalHeaderSize, + &poh_buffer, &consumed)) { + return false; + } + + std::size_t offset = 0; + header->marker = (poh_buffer[offset] & 0x80) >> 6; + header->scrambling = (poh_buffer[offset] & 0x30) >> 4; + header->priority = (poh_buffer[offset] & 0x8) >> 3; + header->data_alignment = (poh_buffer[offset] & 0xc) >> 2; + header->copyright = (poh_buffer[offset] & 0x2) >> 1; + header->original = poh_buffer[offset] & 0x1; + offset++; + + header->has_pts = (poh_buffer[offset] & 0x80) >> 7; + header->has_dts = (poh_buffer[offset] & 0x40) >> 6; + header->unused_fields = poh_buffer[offset] & 0x3f; + offset++; + + header->remaining_size = poh_buffer[offset]; + if (header->remaining_size != + static_cast(kWebm2PesOptHeaderRemainingSize)) + return false; + + size_t bytes_left = header->remaining_size; + offset++; + + if (header->has_pts) { + // Read PTS markers. Format: + // PTS: 5 bytes + // 4 bits (flag: PTS present, but no DTS): 0x2 ('0010') + // 36 bits (90khz PTS): + // top 3 bits + // marker ('1') + // middle 15 bits + // marker ('1') + // bottom 15 bits + // marker ('1') + // TODO(tomfinegan): read/store the timestamp. + header->pts_dts_flag = (poh_buffer[offset] & 0x20) >> 4; + // Check the marker bits. + if ((poh_buffer[offset + 0] & 1) != 1 || + (poh_buffer[offset + 2] & 1) != 1 || + (poh_buffer[offset + 4] & 1) != 1) { + return false; + } + + header->pts = (poh_buffer[offset] & 0xe) << 29 | + ((ReadUint16(&poh_buffer[offset + 1]) & ~1) << 14) | + (ReadUint16(&poh_buffer[offset + 3]) >> 1); + offset += 5; + bytes_left -= 5; + } + + // Validate stuffing byte(s). + for (size_t i = 0; i < bytes_left; ++i) { + if (poh_buffer[offset + i] != 0xff) + return false; + } + + read_pos_ += consumed; + parse_state_ = kParseBcmvHeader; + + return true; +} + +// Parses and validates a BCMV header. +bool VpxPesParser::ParseBcmvHeader(BcmvHeader* header) { + if (!header || parse_state_ != kParseBcmvHeader) + return false; + + PacketData bcmv_buffer; + std::size_t consumed = 0; + if (!RemoveStartCodeEmulationPreventionBytes(&pes_file_data_[read_pos_], + kBcmvHeaderSize, &bcmv_buffer, + &consumed)) { + return false; + } + + std::size_t offset = 0; + header->id[0] = bcmv_buffer[offset++]; + header->id[1] = bcmv_buffer[offset++]; + header->id[2] = bcmv_buffer[offset++]; + header->id[3] = bcmv_buffer[offset++]; + + header->length = 0; + header->length |= bcmv_buffer[offset++] << 24; + header->length |= bcmv_buffer[offset++] << 16; + header->length |= bcmv_buffer[offset++] << 8; + header->length |= bcmv_buffer[offset++]; + + // Length stored in the BCMV header is followed by 2 bytes of 0 padding. + if (bcmv_buffer[offset++] != 0 || bcmv_buffer[offset++] != 0) + return false; + + if (!header->Valid()) + return false; + + parse_state_ = kFindStartCode; + read_pos_ += consumed; + + return true; +} + +bool VpxPesParser::FindStartCode(std::size_t origin, + std::size_t* offset) const { + if (read_pos_ + 2 >= pes_file_size_) + return false; + + const std::size_t length = pes_file_size_ - origin; + if (length < 3) + return false; + + const uint8_t* const data = &pes_file_data_[origin]; + for (std::size_t i = 0; i < length - 3; ++i) { + if (data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 1) { + *offset = origin + i; + return true; + } + } + + return false; +} + +bool VpxPesParser::IsPayloadFragmented(const PesHeader& header) const { + return (header.packet_length != 0 && + (header.packet_length - kPesOptionalHeaderSize) != + header.bcmv_header.length); +} + +bool VpxPesParser::AccumulateFragmentedPayload(std::size_t pes_packet_length, + std::size_t payload_length) { + const std::size_t first_fragment_length = + pes_packet_length - kPesOptionalHeaderSize - kBcmvHeaderSize; + for (std::size_t i = 0; i < first_fragment_length; ++i) { + payload_.push_back(pes_file_data_[read_pos_ + i]); + } + read_pos_ += first_fragment_length; + parse_state_ = kFindStartCode; + + while (payload_.size() < payload_length) { + PesHeader header; + std::size_t packet_start_pos = read_pos_; + if (!FindStartCode(read_pos_, &packet_start_pos)) { + return false; + } + parse_state_ = kParsePesHeader; + read_pos_ = packet_start_pos; + + if (!ParsePesHeader(&header)) { + return false; + } + if (!ParsePesOptionalHeader(&header.opt_header)) { + return false; + } + + const std::size_t fragment_length = + header.packet_length - kPesOptionalHeaderSize; + std::size_t consumed = 0; + if (!RemoveStartCodeEmulationPreventionBytes(&pes_file_data_[read_pos_], + fragment_length, &payload_, + &consumed)) { + return false; + } + read_pos_ += consumed; + } + return true; +} + +bool VpxPesParser::RemoveStartCodeEmulationPreventionBytes( + const std::uint8_t* raw_data, std::size_t bytes_required, + PacketData* processed_data, std::size_t* bytes_consumed) const { + if (bytes_required == 0 || !processed_data) + return false; + + std::size_t num_zeros = 0; + std::size_t bytes_copied = 0; + const std::uint8_t* const end_of_input = + &pes_file_data_[0] + pes_file_data_.size(); + std::size_t i; + for (i = 0; bytes_copied < bytes_required; ++i) { + if (raw_data + i > end_of_input) + return false; + + bool skip = false; + + const std::uint8_t byte = raw_data[i]; + if (byte == 0) { + ++num_zeros; + } else if (byte == 0x3 && num_zeros == 2) { + skip = true; + num_zeros = 0; + } else { + num_zeros = 0; + } + + if (skip == false) { + processed_data->push_back(byte); + ++bytes_copied; + } + } + *bytes_consumed = i; + return true; +} + +int VpxPesParser::BytesAvailable() const { + return static_cast(pes_file_data_.size() - read_pos_); +} + +bool VpxPesParser::ParseNextPacket(PesHeader* header, VideoFrame* frame) { + if (!header || !frame || parse_state_ != kFindStartCode || + BytesAvailable() == 0) { + return false; + } + + std::size_t packet_start_pos = read_pos_; + if (!FindStartCode(read_pos_, &packet_start_pos)) { + return false; + } + parse_state_ = kParsePesHeader; + read_pos_ = packet_start_pos; + + if (!ParsePesHeader(header)) { + return false; + } + if (!ParsePesOptionalHeader(&header->opt_header)) { + return false; + } + if (!ParseBcmvHeader(&header->bcmv_header)) { + return false; + } + + // BCMV header length includes the length of the BCMVHeader itself. Adjust: + const std::size_t payload_length = + header->bcmv_header.length - BcmvHeader::size(); + + // Make sure there's enough input data to read the entire frame. + if (read_pos_ + payload_length > pes_file_data_.size()) { + // Need more data. + printf("VpxPesParser: Not enough data. Required: %u Available: %u\n", + static_cast(payload_length), + static_cast(pes_file_data_.size() - read_pos_)); + parse_state_ = kFindStartCode; + read_pos_ = packet_start_pos; + return false; + } + + if (IsPayloadFragmented(*header)) { + if (!AccumulateFragmentedPayload(header->packet_length, payload_length)) { + fprintf(stderr, "VpxPesParser: Failed parsing fragmented payload!\n"); + return false; + } + } else { + std::size_t consumed = 0; + if (!RemoveStartCodeEmulationPreventionBytes( + &pes_file_data_[read_pos_], payload_length, &payload_, &consumed)) { + return false; + } + read_pos_ += consumed; + } + + if (frame->buffer().capacity < payload_.size()) { + if (frame->Init(payload_.size()) == false) { + fprintf(stderr, "VpxPesParser: Out of memory.\n"); + return false; + } + } + frame->set_nanosecond_pts(Khz90TicksToNanoseconds(header->opt_header.pts)); + std::memcpy(frame->buffer().data.get(), &payload_[0], payload_.size()); + frame->SetBufferLength(payload_.size()); + + payload_.clear(); + parse_state_ = kFindStartCode; + + return true; +} + +} // namespace libwebm diff --git a/third_party/libwebm/source/m2ts/vpxpes_parser.h b/third_party/libwebm/source/m2ts/vpxpes_parser.h new file mode 100644 index 000000000000..d18b4b79d812 --- /dev/null +++ b/third_party/libwebm/source/m2ts/vpxpes_parser.h @@ -0,0 +1,177 @@ +// Copyright (c) 2016 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +#ifndef LIBWEBM_M2TS_VPXPES_PARSER_H_ +#define LIBWEBM_M2TS_VPXPES_PARSER_H_ + +#include +#include +#include + +#include "common/libwebm_util.h" +#include "common/video_frame.h" + +namespace libwebm { + +// Parser for VPx PES. Requires that the _entire_ PES stream can be stored in +// a std::vector and read into memory when Open() is called. +// TODO(tomfinegan): Support incremental parse. +class VpxPesParser { + public: + typedef std::vector PesFileData; + typedef std::vector PacketData; + + enum ParseState { + kFindStartCode, + kParsePesHeader, + kParsePesOptionalHeader, + kParseBcmvHeader, + }; + + struct PesOptionalHeader { + int marker = 0; + int scrambling = 0; + int priority = 0; + int data_alignment = 0; + int copyright = 0; + int original = 0; + int has_pts = 0; + int has_dts = 0; + int unused_fields = 0; + int remaining_size = 0; + int pts_dts_flag = 0; + std::uint64_t pts = 0; + int stuffing_byte = 0; + }; + + struct BcmvHeader { + BcmvHeader() = default; + ~BcmvHeader() = default; + BcmvHeader(const BcmvHeader&) = delete; + BcmvHeader(BcmvHeader&&) = delete; + + // Convenience ctor for quick validation of expected values via operator== + // after parsing input. + explicit BcmvHeader(std::uint32_t len); + + bool operator==(const BcmvHeader& other) const; + + void Reset(); + bool Valid() const; + static std::size_t size() { return 10; } + + char id[4] = {0}; + std::uint32_t length = 0; + }; + + struct PesHeader { + std::uint8_t start_code[4] = {0}; + std::uint16_t packet_length = 0; + std::uint8_t stream_id = 0; + PesOptionalHeader opt_header; + BcmvHeader bcmv_header; + }; + + // Constants for validating known values from input data. + const std::uint8_t kMinVideoStreamId = 0xE0; + const std::uint8_t kMaxVideoStreamId = 0xEF; + const std::size_t kPesHeaderSize = 6; + const std::size_t kPesOptionalHeaderStartOffset = kPesHeaderSize; + const std::size_t kPesOptionalHeaderSize = 9; + const std::size_t kPesOptionalHeaderMarkerValue = 0x2; + const std::size_t kWebm2PesOptHeaderRemainingSize = 6; + const std::size_t kBcmvHeaderSize = 10; + + VpxPesParser() = default; + ~VpxPesParser() = default; + + // Opens file specified by |pes_file_path| and reads its contents. Returns + // true after successful read of input file. + bool Open(const std::string& pes_file_path); + + // Parses the next packet in the PES. PES header information is stored in + // |header|, and the frame payload is stored in |frame|. Returns true when + // a full frame has been consumed from the PES. + bool ParseNextPacket(PesHeader* header, VideoFrame* frame); + + // PES Header parsing utility functions. + // PES Header structure: + // Start code Stream ID Packet length (16 bits) + // / / ____/ + // | | / + // Byte0 Byte1 Byte2 Byte3 Byte4 Byte5 + // 0 0 1 X Y + bool VerifyPacketStartCode() const; + bool ReadStreamId(std::uint8_t* stream_id) const; + bool ReadPacketLength(std::uint16_t* packet_length) const; + + std::uint64_t pes_file_size() const { return pes_file_size_; } + const PesFileData& pes_file_data() const { return pes_file_data_; } + + // Returns number of unparsed bytes remaining. + int BytesAvailable() const; + + private: + // Parses and verifies the static 6 byte portion that begins every PES packet. + bool ParsePesHeader(PesHeader* header); + + // Parses a PES optional header, the optional header following the static + // header that begins the VPX PES packet. + // https://en.wikipedia.org/wiki/Packetized_elementary_stream + bool ParsePesOptionalHeader(PesOptionalHeader* header); + + // Parses and validates the BCMV header. This immediately follows the optional + // header. + bool ParseBcmvHeader(BcmvHeader* header); + + // Returns true when a start code is found and sets |offset| to the position + // of the start code relative to |pes_file_data_[read_pos_]|. + // Does not set |offset| value if the end of |pes_file_data_| is reached + // without locating a start code. + // Note: A start code is the byte sequence 0x00 0x00 0x01. + bool FindStartCode(std::size_t origin, std::size_t* offset) const; + + // Returns true when a PES packet containing a BCMV header contains only a + // portion of the frame payload length reported by the BCMV header. + bool IsPayloadFragmented(const PesHeader& header) const; + + // Parses PES and PES Optional header while accumulating payload data in + // |payload_|. + // Returns true once all payload fragments have been stored in |payload_|. + // Returns false if unable to accumulate full payload. + bool AccumulateFragmentedPayload(std::size_t pes_packet_length, + std::size_t payload_length); + + // The byte sequence 0x0 0x0 0x1 is a start code in PES. When PES muxers + // encounter 0x0 0x0 0x1 or 0x0 0x0 0x3, an additional 0x3 is inserted into + // the PES. The following change occurs: + // 0x0 0x0 0x1 => 0x0 0x0 0x3 0x1 + // 0x0 0x0 0x3 => 0x0 0x0 0x3 0x3 + // PES demuxers must reverse the change: + // 0x0 0x0 0x3 0x1 => 0x0 0x0 0x1 + // 0x0 0x0 0x3 0x3 => 0x0 0x0 0x3 + // PES optional header, BCMV header, and payload data must be preprocessed to + // avoid potentially invalid data due to the presence of inserted bytes. + // + // Removes start code emulation prevention bytes while copying data from + // |raw_data| to |processed_data|. Returns true when |bytes_required| bytes + // have been written to |processed_data|. Reports bytes consumed during the + // operation via |bytes_consumed|. + bool RemoveStartCodeEmulationPreventionBytes( + const std::uint8_t* raw_data, std::size_t bytes_required, + PacketData* processed_data, std::size_t* bytes_consumed) const; + + std::size_t pes_file_size_ = 0; + PacketData payload_; + PesFileData pes_file_data_; + std::size_t read_pos_ = 0; + ParseState parse_state_ = kFindStartCode; +}; + +} // namespace libwebm + +#endif // LIBWEBM_M2TS_VPXPES_PARSER_H_ diff --git a/third_party/libwebm/source/m2ts/webm2pes.cc b/third_party/libwebm/source/m2ts/webm2pes.cc new file mode 100644 index 000000000000..fc4b3144f302 --- /dev/null +++ b/third_party/libwebm/source/m2ts/webm2pes.cc @@ -0,0 +1,551 @@ +// Copyright (c) 2015 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +#include "m2ts/webm2pes.h" + +#include +#include +#include +#include +#include +#include + +#include "common/libwebm_util.h" + +namespace libwebm { + +const std::size_t Webm2Pes::kMaxPayloadSize = 32768; + +namespace { + +std::string ToString(const char* str) { + return std::string((str == nullptr) ? "" : str); +} + +} // namespace + +// +// PesOptionalHeader methods. +// + +void PesOptionalHeader::SetPtsBits(std::int64_t pts_90khz) { + std::uint64_t* pts_bits = &pts.bits; + *pts_bits = 0; + + // PTS is broken up and stored in 40 bits as shown: + // + // PES PTS Only flag + // / Marker Marker Marker + // | / / / + // | | | | + // 7654 321 0 765432107654321 0 765432107654321 0 + // 0010 PTS 32-30 1 PTS 29-15 1 PTS 14-0 1 + const std::uint32_t pts1 = (pts_90khz >> 30) & 0x7; + const std::uint32_t pts2 = (pts_90khz >> 15) & 0x7FFF; + const std::uint32_t pts3 = pts_90khz & 0x7FFF; + + std::uint8_t buffer[5] = {0}; + // PTS only flag. + buffer[0] |= 1 << 5; + // Top 3 bits of PTS and 1 bit marker. + buffer[0] |= pts1 << 1; + // Marker. + buffer[0] |= 1; + + // Next 15 bits of pts and 1 bit marker. + // Top 8 bits of second PTS chunk. + buffer[1] |= (pts2 >> 7) & 0xff; + // bottom 7 bits of second PTS chunk. + buffer[2] |= (pts2 << 1); + // Marker. + buffer[2] |= 1; + + // Last 15 bits of pts and 1 bit marker. + // Top 8 bits of second PTS chunk. + buffer[3] |= (pts3 >> 7) & 0xff; + // bottom 7 bits of second PTS chunk. + buffer[4] |= (pts3 << 1); + // Marker. + buffer[4] |= 1; + + // Write bits into PesHeaderField. + std::memcpy(reinterpret_cast(pts_bits), buffer, 5); +} + +// Writes fields to |buffer| and returns true. Returns false when write or +// field value validation fails. +bool PesOptionalHeader::Write(bool write_pts, PacketDataBuffer* buffer) const { + if (buffer == nullptr) { + std::fprintf(stderr, "Webm2Pes: nullptr in opt header writer.\n"); + return false; + } + + const int kHeaderSize = 9; + std::uint8_t header[kHeaderSize] = {0}; + std::uint8_t* byte = header; + + if (marker.Check() != true || scrambling.Check() != true || + priority.Check() != true || data_alignment.Check() != true || + copyright.Check() != true || original.Check() != true || + has_pts.Check() != true || has_dts.Check() != true || + pts.Check() != true || stuffing_byte.Check() != true) { + std::fprintf(stderr, "Webm2Pes: Invalid PES Optional Header field.\n"); + return false; + } + + // TODO(tomfinegan): As noted in above, the PesHeaderFields should be an + // array (or some data structure) that can be iterated over. + + // First byte of header, fields: marker, scrambling, priority, alignment, + // copyright, original. + *byte = 0; + *byte |= marker.bits << marker.shift; + *byte |= scrambling.bits << scrambling.shift; + *byte |= priority.bits << priority.shift; + *byte |= data_alignment.bits << data_alignment.shift; + *byte |= copyright.bits << copyright.shift; + *byte |= original.bits << original.shift; + + // Second byte of header, fields: has_pts, has_dts, unused fields. + *++byte = 0; + if (write_pts == true) + *byte |= has_pts.bits << has_pts.shift; + + *byte |= has_dts.bits << has_dts.shift; + + // Third byte of header, fields: remaining size of header. + *++byte = remaining_size.bits & 0xff; // Field is 8 bits wide. + + int num_stuffing_bytes = + (pts.num_bits + 7) / 8 + 1 /* always 1 stuffing byte */; + if (write_pts == true) { + // Write the PTS value as big endian and adjust stuffing byte count + // accordingly. + *++byte = pts.bits & 0xff; + *++byte = (pts.bits >> 8) & 0xff; + *++byte = (pts.bits >> 16) & 0xff; + *++byte = (pts.bits >> 24) & 0xff; + *++byte = (pts.bits >> 32) & 0xff; + num_stuffing_bytes = 1; + } + + // Add the stuffing byte(s). + for (int i = 0; i < num_stuffing_bytes; ++i) + *++byte = stuffing_byte.bits & 0xff; + + return CopyAndEscapeStartCodes(&header[0], kHeaderSize, buffer); +} + +// +// BCMVHeader methods. +// + +bool BCMVHeader::Write(PacketDataBuffer* buffer) const { + if (buffer == nullptr) { + std::fprintf(stderr, "Webm2Pes: nullptr for buffer in BCMV Write.\n"); + return false; + } + const int kBcmvSize = 4; + for (int i = 0; i < kBcmvSize; ++i) + buffer->push_back(bcmv[i]); + + // Note: The 4 byte length field must include the size of the BCMV header. + const int kRemainingBytes = 6; + const uint32_t bcmv_total_length = length + static_cast(size()); + const uint8_t bcmv_buffer[kRemainingBytes] = { + static_cast((bcmv_total_length >> 24) & 0xff), + static_cast((bcmv_total_length >> 16) & 0xff), + static_cast((bcmv_total_length >> 8) & 0xff), + static_cast(bcmv_total_length & 0xff), + 0, + 0 /* 2 bytes 0 padding */}; + + return CopyAndEscapeStartCodes(bcmv_buffer, kRemainingBytes, buffer); +} + +// +// PesHeader methods. +// + +// Writes out the header to |buffer|. Calls PesOptionalHeader::Write() to write +// |optional_header| contents. Returns true when successful, false otherwise. +bool PesHeader::Write(bool write_pts, PacketDataBuffer* buffer) const { + if (buffer == nullptr) { + std::fprintf(stderr, "Webm2Pes: nullptr in header writer.\n"); + return false; + } + + // Write |start_code|. + const int kStartCodeLength = 4; + for (int i = 0; i < kStartCodeLength; ++i) + buffer->push_back(start_code[i]); + + // The length field here reports number of bytes following the field. The + // length of the optional header must be added to the payload length set by + // the user. + const std::size_t header_length = + packet_length + optional_header.size_in_bytes(); + if (header_length > UINT16_MAX) + return false; + + // Write |header_length| as big endian. + std::uint8_t byte = (header_length >> 8) & 0xff; + buffer->push_back(byte); + byte = header_length & 0xff; + buffer->push_back(byte); + + // Write the (not really) optional header. + if (optional_header.Write(write_pts, buffer) != true) { + std::fprintf(stderr, "Webm2Pes: PES optional header write failed."); + return false; + } + return true; +} + +// +// Webm2Pes methods. +// + +bool Webm2Pes::ConvertToFile() { + if (input_file_name_.empty() || output_file_name_.empty()) { + std::fprintf(stderr, "Webm2Pes: input and/or output file name(s) empty.\n"); + return false; + } + + output_file_ = FilePtr(fopen(output_file_name_.c_str(), "wb"), FILEDeleter()); + if (output_file_ == nullptr) { + std::fprintf(stderr, "Webm2Pes: Cannot open %s for output.\n", + output_file_name_.c_str()); + return false; + } + + if (InitWebmParser() != true) { + std::fprintf(stderr, "Webm2Pes: Cannot initialize WebM parser.\n"); + return false; + } + + // Walk clusters in segment. + const mkvparser::Cluster* cluster = webm_parser_->GetFirst(); + while (cluster != nullptr && cluster->EOS() == false) { + const mkvparser::BlockEntry* block_entry = nullptr; + std::int64_t block_status = cluster->GetFirst(block_entry); + if (block_status < 0) { + std::fprintf(stderr, "Webm2Pes: Cannot parse first block in %s.\n", + input_file_name_.c_str()); + return false; + } + + // Walk blocks in cluster. + while (block_entry != nullptr && block_entry->EOS() == false) { + const mkvparser::Block* block = block_entry->GetBlock(); + if (block->GetTrackNumber() == video_track_num_) { + const int frame_count = block->GetFrameCount(); + + // Walk frames in block. + for (int frame_num = 0; frame_num < frame_count; ++frame_num) { + const mkvparser::Block::Frame& mkvparser_frame = + block->GetFrame(frame_num); + + // Read the frame. + VideoFrame vpx_frame(block->GetTime(cluster), codec_); + if (ReadVideoFrame(mkvparser_frame, &vpx_frame) == false) { + fprintf(stderr, "Webm2Pes: frame read failed.\n"); + return false; + } + + // Write frame out as PES packet(s). + if (WritePesPacket(vpx_frame, &packet_data_) == false) { + std::fprintf(stderr, "Webm2Pes: WritePesPacket failed.\n"); + return false; + } + + // Write contents of |packet_data_| to |output_file_|. + if (std::fwrite(&packet_data_[0], 1, packet_data_.size(), + output_file_.get()) != packet_data_.size()) { + std::fprintf(stderr, "Webm2Pes: packet payload write failed.\n"); + return false; + } + bytes_written_ += packet_data_.size(); + } + } + block_status = cluster->GetNext(block_entry, block_entry); + if (block_status < 0) { + std::fprintf(stderr, "Webm2Pes: Cannot parse block in %s.\n", + input_file_name_.c_str()); + return false; + } + } + + cluster = webm_parser_->GetNext(cluster); + } + + std::fflush(output_file_.get()); + return true; +} + +bool Webm2Pes::ConvertToPacketReceiver() { + if (input_file_name_.empty() || packet_sink_ == nullptr) { + std::fprintf(stderr, "Webm2Pes: input file name empty or null sink.\n"); + return false; + } + + if (InitWebmParser() != true) { + std::fprintf(stderr, "Webm2Pes: Cannot initialize WebM parser.\n"); + return false; + } + + // Walk clusters in segment. + const mkvparser::Cluster* cluster = webm_parser_->GetFirst(); + while (cluster != nullptr && cluster->EOS() == false) { + const mkvparser::BlockEntry* block_entry = nullptr; + std::int64_t block_status = cluster->GetFirst(block_entry); + if (block_status < 0) { + std::fprintf(stderr, "Webm2Pes: Cannot parse first block in %s.\n", + input_file_name_.c_str()); + return false; + } + + // Walk blocks in cluster. + while (block_entry != nullptr && block_entry->EOS() == false) { + const mkvparser::Block* block = block_entry->GetBlock(); + if (block->GetTrackNumber() == video_track_num_) { + const int frame_count = block->GetFrameCount(); + + // Walk frames in block. + for (int frame_num = 0; frame_num < frame_count; ++frame_num) { + const mkvparser::Block::Frame& mkvparser_frame = + block->GetFrame(frame_num); + + // Read the frame. + VideoFrame frame(block->GetTime(cluster), codec_); + if (ReadVideoFrame(mkvparser_frame, &frame) == false) { + fprintf(stderr, "Webm2Pes: frame read failed.\n"); + return false; + } + + // Write frame out as PES packet(s). + if (WritePesPacket(frame, &packet_data_) == false) { + std::fprintf(stderr, "Webm2Pes: WritePesPacket failed.\n"); + return false; + } + if (packet_sink_->ReceivePacket(packet_data_) != true) { + std::fprintf(stderr, "Webm2Pes: ReceivePacket failed.\n"); + return false; + } + bytes_written_ += packet_data_.size(); + } + } + block_status = cluster->GetNext(block_entry, block_entry); + if (block_status < 0) { + std::fprintf(stderr, "Webm2Pes: Cannot parse block in %s.\n", + input_file_name_.c_str()); + return false; + } + } + + cluster = webm_parser_->GetNext(cluster); + } + + return true; +} + +bool Webm2Pes::InitWebmParser() { + if (webm_reader_.Open(input_file_name_.c_str()) != 0) { + std::fprintf(stderr, "Webm2Pes: Cannot open %s as input.\n", + input_file_name_.c_str()); + return false; + } + + using mkvparser::Segment; + Segment* webm_parser = nullptr; + if (Segment::CreateInstance(&webm_reader_, 0 /* pos */, + webm_parser /* Segment*& */) != 0) { + std::fprintf(stderr, "Webm2Pes: Cannot create WebM parser.\n"); + return false; + } + webm_parser_.reset(webm_parser); + + if (webm_parser_->Load() != 0) { + std::fprintf(stderr, "Webm2Pes: Cannot parse %s.\n", + input_file_name_.c_str()); + return false; + } + + // Make sure there's a video track. + const mkvparser::Tracks* tracks = webm_parser_->GetTracks(); + if (tracks == nullptr) { + std::fprintf(stderr, "Webm2Pes: %s has no tracks.\n", + input_file_name_.c_str()); + return false; + } + + timecode_scale_ = webm_parser_->GetInfo()->GetTimeCodeScale(); + + for (int track_index = 0; + track_index < static_cast(tracks->GetTracksCount()); + ++track_index) { + const mkvparser::Track* track = tracks->GetTrackByIndex(track_index); + if (track && track->GetType() == mkvparser::Track::kVideo) { + const std::string codec_id = ToString(track->GetCodecId()); + if (codec_id == std::string("V_VP8")) { + codec_ = VideoFrame::kVP8; + } else if (codec_id == std::string("V_VP9")) { + codec_ = VideoFrame::kVP9; + } else { + fprintf(stderr, "Webm2Pes: Codec must be VP8 or VP9.\n"); + return false; + } + video_track_num_ = track_index + 1; + break; + } + } + if (video_track_num_ < 1) { + std::fprintf(stderr, "Webm2Pes: No video track found in %s.\n", + input_file_name_.c_str()); + return false; + } + return true; +} + +bool Webm2Pes::ReadVideoFrame(const mkvparser::Block::Frame& mkvparser_frame, + VideoFrame* frame) { + if (mkvparser_frame.len < 1 || frame == nullptr) + return false; + + const std::size_t mkv_len = static_cast(mkvparser_frame.len); + if (mkv_len > frame->buffer().capacity) { + const std::size_t new_size = 2 * mkv_len; + if (frame->Init(new_size) == false) { + std::fprintf(stderr, "Webm2Pes: Out of memory.\n"); + return false; + } + } + if (mkvparser_frame.Read(&webm_reader_, frame->buffer().data.get()) != 0) { + std::fprintf(stderr, "Webm2Pes: Error reading VPx frame!\n"); + return false; + } + return frame->SetBufferLength(mkv_len); +} + +bool Webm2Pes::WritePesPacket(const VideoFrame& frame, + PacketDataBuffer* packet_data) { + if (frame.buffer().data.get() == nullptr || frame.buffer().length < 1) + return false; + + Ranges frame_ranges; + if (frame.codec() == VideoFrame::kVP9) { + bool error = false; + const bool has_superframe_index = + ParseVP9SuperFrameIndex(frame.buffer().data.get(), + frame.buffer().length, &frame_ranges, &error); + if (error) { + std::fprintf(stderr, "Webm2Pes: Superframe index parse failed.\n"); + return false; + } + if (has_superframe_index == false) { + frame_ranges.push_back(Range(0, frame.buffer().length)); + } + } else { + frame_ranges.push_back(Range(0, frame.buffer().length)); + } + + const std::int64_t khz90_pts = + NanosecondsTo90KhzTicks(frame.nanosecond_pts()); + PesHeader header; + header.optional_header.SetPtsBits(khz90_pts); + + packet_data->clear(); + + for (const Range& packet_payload_range : frame_ranges) { + std::size_t extra_bytes = 0; + if (packet_payload_range.length > kMaxPayloadSize) { + extra_bytes = packet_payload_range.length - kMaxPayloadSize; + } + if (packet_payload_range.length + packet_payload_range.offset > + frame.buffer().length) { + std::fprintf(stderr, "Webm2Pes: Invalid frame length.\n"); + return false; + } + + // First packet of new frame. Always include PTS and BCMV header. + header.packet_length = + packet_payload_range.length - extra_bytes + BCMVHeader::size(); + if (header.Write(true, packet_data) != true) { + std::fprintf(stderr, "Webm2Pes: packet header write failed.\n"); + return false; + } + + BCMVHeader bcmv_header(static_cast(packet_payload_range.length)); + if (bcmv_header.Write(packet_data) != true) { + std::fprintf(stderr, "Webm2Pes: BCMV write failed.\n"); + return false; + } + + // Insert the payload at the end of |packet_data|. + const std::uint8_t* const payload_start = + frame.buffer().data.get() + packet_payload_range.offset; + + const std::size_t bytes_to_copy = packet_payload_range.length - extra_bytes; + if (CopyAndEscapeStartCodes(payload_start, bytes_to_copy, packet_data) == + false) { + fprintf(stderr, "Webm2Pes: Payload write failed.\n"); + return false; + } + + std::size_t bytes_copied = bytes_to_copy; + while (extra_bytes) { + // Write PES packets for the remaining data, but omit the PTS and BCMV + // header. + const std::size_t extra_bytes_to_copy = + std::min(kMaxPayloadSize, extra_bytes); + extra_bytes -= extra_bytes_to_copy; + header.packet_length = extra_bytes_to_copy; + if (header.Write(false, packet_data) != true) { + fprintf(stderr, "Webm2pes: fragment write failed.\n"); + return false; + } + + const std::uint8_t* fragment_start = payload_start + bytes_copied; + if (CopyAndEscapeStartCodes(fragment_start, extra_bytes_to_copy, + packet_data) == false) { + fprintf(stderr, "Webm2Pes: Payload write failed.\n"); + return false; + } + + bytes_copied += extra_bytes_to_copy; + } + } + + return true; +} + +bool CopyAndEscapeStartCodes(const std::uint8_t* raw_input, + std::size_t raw_input_length, + PacketDataBuffer* packet_buffer) { + if (raw_input == nullptr || raw_input_length < 1 || packet_buffer == nullptr) + return false; + + int num_zeros = 0; + for (std::size_t i = 0; i < raw_input_length; ++i) { + const uint8_t byte = raw_input[i]; + + if (byte == 0) { + ++num_zeros; + } else if (num_zeros >= 2 && (byte == 0x1 || byte == 0x3)) { + packet_buffer->push_back(0x3); + num_zeros = 0; + } else { + num_zeros = 0; + } + + packet_buffer->push_back(byte); + } + + return true; +} + +} // namespace libwebm diff --git a/third_party/libwebm/source/m2ts/webm2pes.h b/third_party/libwebm/source/m2ts/webm2pes.h new file mode 100644 index 000000000000..6dcb0fdd9312 --- /dev/null +++ b/third_party/libwebm/source/m2ts/webm2pes.h @@ -0,0 +1,274 @@ +// Copyright (c) 2015 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +#ifndef LIBWEBM_M2TS_WEBM2PES_H_ +#define LIBWEBM_M2TS_WEBM2PES_H_ + +#include +#include +#include +#include +#include + +#include "common/libwebm_util.h" +#include "common/video_frame.h" +#include "mkvparser/mkvparser.h" +#include "mkvparser/mkvreader.h" + +// Webm2pes +// +// Webm2pes consumes a WebM file containing a VP8 or VP9 video stream and +// outputs a PES stream suitable for inclusion in a MPEG2 Transport Stream. +// +// In the simplest case the PES stream output by Webm2pes consists of a sequence +// of PES packets with the following structure: +// | PES Header w/PTS | BCMV Header | Payload (VPx frame) | +// +// More typically the output will look like the following due to the PES +// payload size limitations caused by the format of the PES header. +// The PES header contains only 2 bytes of storage for expressing payload size. +// VPx PES streams containing fragmented packets look like this: +// +// | PH PTS | BCMV | Payload fragment 1 | PH | Payload fragment 2 | ... +// +// PH = PES Header +// PH PTS = PES Header with PTS +// BCMV = BCMV Header +// +// Note that start codes are properly escaped by Webm2pes, and start code +// emulation prevention bytes must be stripped from the output stream before +// it can be parsed. + +namespace libwebm { + +// Stores a value and its size in bits for writing into a PES Optional Header. +// Maximum size is 64 bits. Users may call the Check() method to perform minimal +// validation (size > 0 and <= 64). +struct PesHeaderField { + PesHeaderField(std::uint64_t value, std::uint32_t size_in_bits, + std::uint8_t byte_index, std::uint8_t bits_to_shift) + : bits(value), + num_bits(size_in_bits), + index(byte_index), + shift(bits_to_shift) {} + PesHeaderField() = delete; + PesHeaderField(const PesHeaderField&) = default; + PesHeaderField(PesHeaderField&&) = default; + ~PesHeaderField() = default; + bool Check() const { + return num_bits > 0 && num_bits <= 64 && shift >= 0 && shift < 64; + } + + // Value to be stored in the field. + std::uint64_t bits; + + // Number of bits in the value. + const int num_bits; + + // Index into the header for the byte in which |bits| will be written. + const std::uint8_t index; + + // Number of bits to shift value before or'ing. + const int shift; +}; + +// Data is stored in buffers before being written to output files. +typedef std::vector PacketDataBuffer; + +// Storage for PES Optional Header values. Fields written in order using sizes +// specified. +struct PesOptionalHeader { + // TODO(tomfinegan): The fields could be in an array, which would allow the + // code writing the optional header to iterate over the fields instead of + // having code for dealing with each one. + + // 2 bits (marker): 2 ('10') + const PesHeaderField marker = PesHeaderField(2, 2, 0, 6); + + // 2 bits (no scrambling): 0x0 ('00') + const PesHeaderField scrambling = PesHeaderField(0, 2, 0, 4); + + // 1 bit (priority): 0x0 ('0') + const PesHeaderField priority = PesHeaderField(0, 1, 0, 3); + + // TODO(tomfinegan): The BCMV header could be considered a sync word, and this + // field should be 1 when a sync word follows the packet. Clarify. + // 1 bit (data alignment): 0x0 ('0') + const PesHeaderField data_alignment = PesHeaderField(0, 1, 0, 2); + + // 1 bit (copyright): 0x0 ('0') + const PesHeaderField copyright = PesHeaderField(0, 1, 0, 1); + + // 1 bit (original/copy): 0x0 ('0') + const PesHeaderField original = PesHeaderField(0, 1, 0, 0); + + // 1 bit (has_pts): 0x1 ('1') + const PesHeaderField has_pts = PesHeaderField(1, 1, 1, 7); + + // 1 bit (has_dts): 0x0 ('0') + const PesHeaderField has_dts = PesHeaderField(0, 1, 1, 6); + + // 6 bits (unused fields): 0x0 ('000000') + const PesHeaderField unused = PesHeaderField(0, 6, 1, 0); + + // 8 bits (size of remaining data in the Header). + const PesHeaderField remaining_size = PesHeaderField(6, 8, 2, 0); + + // PTS: 5 bytes + // 4 bits (flag: PTS present, but no DTS): 0x2 ('0010') + // 36 bits (90khz PTS): + // top 3 bits + // marker ('1') + // middle 15 bits + // marker ('1') + // bottom 15 bits + // marker ('1') + PesHeaderField pts = PesHeaderField(0, 40, 3, 0); + + PesHeaderField stuffing_byte = PesHeaderField(0xFF, 8, 8, 0); + + // PTS omitted in fragments. Size remains unchanged: More stuffing bytes. + bool fragment = false; + + static std::size_t size_in_bytes() { return 9; } + + // Writes |pts_90khz| to |pts| per format described at its declaration above. + void SetPtsBits(std::int64_t pts_90khz); + + // Writes fields to |buffer| and returns true. Returns false when write or + // field value validation fails. + bool Write(bool write_pts, PacketDataBuffer* buffer) const; +}; + +// Describes custom 10 byte header that immediately follows the PES Optional +// Header in each PES packet output by Webm2Pes: +// 4 byte 'B' 'C' 'M' 'V' +// 4 byte big-endian length of frame +// 2 bytes 0 padding +struct BCMVHeader { + explicit BCMVHeader(std::uint32_t frame_length) : length(frame_length) {} + BCMVHeader() = delete; + BCMVHeader(const BCMVHeader&) = delete; + BCMVHeader(BCMVHeader&&) = delete; + ~BCMVHeader() = default; + const std::uint8_t bcmv[4] = {'B', 'C', 'M', 'V'}; + const std::uint32_t length; + + static std::size_t size() { return 10; } + + // Write the BCMV Header into |buffer|. Caller responsible for ensuring + // destination buffer is of size >= BCMVHeader::size(). + bool Write(PacketDataBuffer* buffer) const; + bool Write(uint8_t* buffer); +}; + +struct PesHeader { + const std::uint8_t start_code[4] = { + 0x00, 0x00, + 0x01, // 0x000001 is the PES packet start code prefix. + 0xE0}; // 0xE0 is the minimum video stream ID. + std::uint16_t packet_length = 0; // Number of bytes _after_ this field. + PesOptionalHeader optional_header; + std::size_t size() const { + return optional_header.size_in_bytes() + + 6 /* start_code + packet_length */ + packet_length; + } + + // Writes out the header to |buffer|. Calls PesOptionalHeader::Write() to + // write |optional_header| contents. Returns true when successful, false + // otherwise. + bool Write(bool write_pts, PacketDataBuffer* buffer) const; +}; + +class PacketReceiverInterface { + public: + virtual ~PacketReceiverInterface() {} + virtual bool ReceivePacket(const PacketDataBuffer& packet) = 0; +}; + +// Converts the VP9 track of a WebM file to a Packetized Elementary Stream +// suitable for use in a MPEG2TS. +// https://en.wikipedia.org/wiki/Packetized_elementary_stream +// https://en.wikipedia.org/wiki/MPEG_transport_stream +class Webm2Pes { + public: + static const std::size_t kMaxPayloadSize; + + Webm2Pes(const std::string& input_file, const std::string& output_file) + : input_file_name_(input_file), output_file_name_(output_file) {} + Webm2Pes(const std::string& input_file, PacketReceiverInterface* packet_sink) + : input_file_name_(input_file), packet_sink_(packet_sink) {} + + Webm2Pes() = delete; + Webm2Pes(const Webm2Pes&) = delete; + Webm2Pes(Webm2Pes&&) = delete; + ~Webm2Pes() = default; + + // Converts the VPx video stream to a PES file and returns true. Returns false + // to report failure. + bool ConvertToFile(); + + // Converts the VPx video stream to a sequence of PES packets, and calls the + // PacketReceiverInterface::ReceivePacket() once for each VPx frame. The + // packet sent to the receiver may contain multiple PES packets. Returns only + // after full conversion or error. Returns true for success, and false when + // an error occurs. + bool ConvertToPacketReceiver(); + + // Writes |vpx_frame| out as PES packet[s] and stores output in |packet_data|. + // Returns true for success, false for failure. + static bool WritePesPacket(const VideoFrame& frame, + PacketDataBuffer* packet_data); + + uint64_t bytes_written() const { return bytes_written_; } + + private: + bool InitWebmParser(); + bool ReadVideoFrame(const mkvparser::Block::Frame& mkvparser_frame, + VideoFrame* frame); + + const std::string input_file_name_; + const std::string output_file_name_; + std::unique_ptr webm_parser_; + mkvparser::MkvReader webm_reader_; + FilePtr output_file_; + + // Video track num in the WebM file. + int video_track_num_ = 0; + + // Video codec reported by CodecName from Video TrackEntry. + VideoFrame::Codec codec_; + + // Input timecode scale. + std::int64_t timecode_scale_ = 1000000; + + // Packet sink; when constructed with a PacketReceiverInterface*, packet and + // type of packet are sent to |packet_sink_| instead of written to an output + // file. + PacketReceiverInterface* packet_sink_ = nullptr; + + PacketDataBuffer packet_data_; + + std::uint64_t bytes_written_ = 0; +}; + +// Copies |raw_input_length| bytes from |raw_input| to |packet_buffer| while +// escaping start codes. Returns true when bytes are successfully copied. +// A start code is the 3 byte sequence 0x00 0x00 0x01. When +// the sequence is encountered, the value 0x03 is inserted. To avoid +// any ambiguity at reassembly time, the same is done for the sequence +// 0x00 0x00 0x03. So, the following transformation occurs for when either +// of the noted sequences is encountered: +// +// 0x00 0x00 0x01 => 0x00 0x00 0x03 0x01 +// 0x00 0x00 0x03 => 0x00 0x00 0x03 0x03 +bool CopyAndEscapeStartCodes(const std::uint8_t* raw_input, + std::size_t raw_input_length, + PacketDataBuffer* packet_buffer); +} // namespace libwebm + +#endif // LIBWEBM_M2TS_WEBM2PES_H_ diff --git a/third_party/libwebm/source/m2ts/webm2pes_main.cc b/third_party/libwebm/source/m2ts/webm2pes_main.cc new file mode 100644 index 000000000000..075e55cd5c27 --- /dev/null +++ b/third_party/libwebm/source/m2ts/webm2pes_main.cc @@ -0,0 +1,33 @@ +// Copyright (c) 2015 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +#include "m2ts/webm2pes.h" + +#include +#include +#include + +namespace { + +void Usage(const char* argv[]) { + printf("Usage: %s ", argv[0]); +} + +} // namespace + +int main(int argc, const char* argv[]) { + if (argc < 3) { + Usage(argv); + return EXIT_FAILURE; + } + + const std::string input_path = argv[1]; + const std::string output_path = argv[2]; + + libwebm::Webm2Pes converter(input_path, output_path); + return converter.ConvertToFile() == true ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/third_party/libwebm/source/mkvmuxer.hpp b/third_party/libwebm/source/mkvmuxer.hpp new file mode 100644 index 000000000000..092592baa553 --- /dev/null +++ b/third_party/libwebm/source/mkvmuxer.hpp @@ -0,0 +1,15 @@ +// Copyright (c) 2016 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +#ifndef LIBWEBM_MKVMUXER_HPP_ +#define LIBWEBM_MKVMUXER_HPP_ + +// This file is a wrapper for the file included immediately after this comment. +// New projects should not include this file: include the file included below. +#include "mkvmuxer/mkvmuxer.h" + +#endif // LIBWEBM_MKVMUXER_HPP_ diff --git a/third_party/libwebm/source/mkvmuxer/mkvmuxer.cc b/third_party/libwebm/source/mkvmuxer/mkvmuxer.cc new file mode 100644 index 000000000000..183d2d1db962 --- /dev/null +++ b/third_party/libwebm/source/mkvmuxer/mkvmuxer.cc @@ -0,0 +1,4231 @@ +// Copyright (c) 2012 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. + +#include "mkvmuxer/mkvmuxer.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common/webmids.h" +#include "mkvmuxer/mkvmuxerutil.h" +#include "mkvmuxer/mkvwriter.h" +#include "mkvparser/mkvparser.h" + +namespace mkvmuxer { + +const float PrimaryChromaticity::kChromaticityMin = 0.0f; +const float PrimaryChromaticity::kChromaticityMax = 1.0f; +const float MasteringMetadata::kMinLuminance = 0.0f; +const float MasteringMetadata::kMinLuminanceMax = 999.99f; +const float MasteringMetadata::kMaxLuminanceMax = 9999.99f; +const float MasteringMetadata::kValueNotPresent = FLT_MAX; +const uint64_t Colour::kValueNotPresent = UINT64_MAX; + +namespace { + +const char kDocTypeWebm[] = "webm"; +const char kDocTypeMatroska[] = "matroska"; + +// Deallocate the string designated by |dst|, and then copy the |src| +// string to |dst|. The caller owns both the |src| string and the +// |dst| copy (hence the caller is responsible for eventually +// deallocating the strings, either directly, or indirectly via +// StrCpy). Returns true if the source string was successfully copied +// to the destination. +bool StrCpy(const char* src, char** dst_ptr) { + if (dst_ptr == NULL) + return false; + + char*& dst = *dst_ptr; + + delete[] dst; + dst = NULL; + + if (src == NULL) + return true; + + const size_t size = strlen(src) + 1; + + dst = new (std::nothrow) char[size]; // NOLINT + if (dst == NULL) + return false; + + strcpy(dst, src); // NOLINT + return true; +} + +typedef std::unique_ptr PrimaryChromaticityPtr; +bool CopyChromaticity(const PrimaryChromaticity* src, + PrimaryChromaticityPtr* dst) { + if (!dst) + return false; + + dst->reset(new (std::nothrow) PrimaryChromaticity(src->x(), src->y())); + if (!dst->get()) + return false; + + return true; +} + +} // namespace + +/////////////////////////////////////////////////////////////// +// +// IMkvWriter Class + +IMkvWriter::IMkvWriter() {} + +IMkvWriter::~IMkvWriter() {} + +bool WriteEbmlHeader(IMkvWriter* writer, uint64_t doc_type_version, + const char* const doc_type) { + // Level 0 + uint64_t size = + EbmlElementSize(libwebm::kMkvEBMLVersion, static_cast(1)); + size += EbmlElementSize(libwebm::kMkvEBMLReadVersion, static_cast(1)); + size += EbmlElementSize(libwebm::kMkvEBMLMaxIDLength, static_cast(4)); + size += + EbmlElementSize(libwebm::kMkvEBMLMaxSizeLength, static_cast(8)); + size += EbmlElementSize(libwebm::kMkvDocType, doc_type); + size += EbmlElementSize(libwebm::kMkvDocTypeVersion, + static_cast(doc_type_version)); + size += + EbmlElementSize(libwebm::kMkvDocTypeReadVersion, static_cast(2)); + + if (!WriteEbmlMasterElement(writer, libwebm::kMkvEBML, size)) + return false; + if (!WriteEbmlElement(writer, libwebm::kMkvEBMLVersion, + static_cast(1))) { + return false; + } + if (!WriteEbmlElement(writer, libwebm::kMkvEBMLReadVersion, + static_cast(1))) { + return false; + } + if (!WriteEbmlElement(writer, libwebm::kMkvEBMLMaxIDLength, + static_cast(4))) { + return false; + } + if (!WriteEbmlElement(writer, libwebm::kMkvEBMLMaxSizeLength, + static_cast(8))) { + return false; + } + if (!WriteEbmlElement(writer, libwebm::kMkvDocType, doc_type)) + return false; + if (!WriteEbmlElement(writer, libwebm::kMkvDocTypeVersion, + static_cast(doc_type_version))) { + return false; + } + if (!WriteEbmlElement(writer, libwebm::kMkvDocTypeReadVersion, + static_cast(2))) { + return false; + } + + return true; +} + +bool WriteEbmlHeader(IMkvWriter* writer, uint64_t doc_type_version) { + return WriteEbmlHeader(writer, doc_type_version, kDocTypeWebm); +} + +bool WriteEbmlHeader(IMkvWriter* writer) { + return WriteEbmlHeader(writer, mkvmuxer::Segment::kDefaultDocTypeVersion); +} + +bool ChunkedCopy(mkvparser::IMkvReader* source, mkvmuxer::IMkvWriter* dst, + int64_t start, int64_t size) { + // TODO(vigneshv): Check if this is a reasonable value. + const uint32_t kBufSize = 2048; + uint8_t* buf = new uint8_t[kBufSize]; + int64_t offset = start; + while (size > 0) { + const int64_t read_len = (size > kBufSize) ? kBufSize : size; + if (source->Read(offset, static_cast(read_len), buf)) + return false; + dst->Write(buf, static_cast(read_len)); + offset += read_len; + size -= read_len; + } + delete[] buf; + return true; +} + +/////////////////////////////////////////////////////////////// +// +// Frame Class + +Frame::Frame() + : add_id_(0), + additional_(NULL), + additional_length_(0), + duration_(0), + duration_set_(false), + frame_(NULL), + is_key_(false), + length_(0), + track_number_(0), + timestamp_(0), + discard_padding_(0), + reference_block_timestamp_(0), + reference_block_timestamp_set_(false) {} + +Frame::~Frame() { + delete[] frame_; + delete[] additional_; +} + +bool Frame::CopyFrom(const Frame& frame) { + delete[] frame_; + frame_ = NULL; + length_ = 0; + if (frame.length() > 0 && frame.frame() != NULL && + !Init(frame.frame(), frame.length())) { + return false; + } + add_id_ = 0; + delete[] additional_; + additional_ = NULL; + additional_length_ = 0; + if (frame.additional_length() > 0 && frame.additional() != NULL && + !AddAdditionalData(frame.additional(), frame.additional_length(), + frame.add_id())) { + return false; + } + duration_ = frame.duration(); + duration_set_ = frame.duration_set(); + is_key_ = frame.is_key(); + track_number_ = frame.track_number(); + timestamp_ = frame.timestamp(); + discard_padding_ = frame.discard_padding(); + reference_block_timestamp_ = frame.reference_block_timestamp(); + reference_block_timestamp_set_ = frame.reference_block_timestamp_set(); + return true; +} + +bool Frame::Init(const uint8_t* frame, uint64_t length) { + uint8_t* const data = + new (std::nothrow) uint8_t[static_cast(length)]; // NOLINT + if (!data) + return false; + + delete[] frame_; + frame_ = data; + length_ = length; + + memcpy(frame_, frame, static_cast(length_)); + return true; +} + +bool Frame::AddAdditionalData(const uint8_t* additional, uint64_t length, + uint64_t add_id) { + uint8_t* const data = + new (std::nothrow) uint8_t[static_cast(length)]; // NOLINT + if (!data) + return false; + + delete[] additional_; + additional_ = data; + additional_length_ = length; + add_id_ = add_id; + + memcpy(additional_, additional, static_cast(additional_length_)); + return true; +} + +bool Frame::IsValid() const { + if (length_ == 0 || !frame_) { + return false; + } + if ((additional_length_ != 0 && !additional_) || + (additional_ != NULL && additional_length_ == 0)) { + return false; + } + if (track_number_ == 0 || track_number_ > kMaxTrackNumber) { + return false; + } + if (!CanBeSimpleBlock() && !is_key_ && !reference_block_timestamp_set_) { + return false; + } + return true; +} + +bool Frame::CanBeSimpleBlock() const { + return additional_ == NULL && discard_padding_ == 0 && duration_ == 0; +} + +void Frame::set_duration(uint64_t duration) { + duration_ = duration; + duration_set_ = true; +} + +void Frame::set_reference_block_timestamp(int64_t reference_block_timestamp) { + reference_block_timestamp_ = reference_block_timestamp; + reference_block_timestamp_set_ = true; +} + +/////////////////////////////////////////////////////////////// +// +// CuePoint Class + +CuePoint::CuePoint() + : time_(0), + track_(0), + cluster_pos_(0), + block_number_(1), + output_block_number_(true) {} + +CuePoint::~CuePoint() {} + +bool CuePoint::Write(IMkvWriter* writer) const { + if (!writer || track_ < 1 || cluster_pos_ < 1) + return false; + + uint64_t size = EbmlElementSize(libwebm::kMkvCueClusterPosition, + static_cast(cluster_pos_)); + size += EbmlElementSize(libwebm::kMkvCueTrack, static_cast(track_)); + if (output_block_number_ && block_number_ > 1) + size += EbmlElementSize(libwebm::kMkvCueBlockNumber, + static_cast(block_number_)); + const uint64_t track_pos_size = + EbmlMasterElementSize(libwebm::kMkvCueTrackPositions, size) + size; + const uint64_t payload_size = + EbmlElementSize(libwebm::kMkvCueTime, static_cast(time_)) + + track_pos_size; + + if (!WriteEbmlMasterElement(writer, libwebm::kMkvCuePoint, payload_size)) + return false; + + const int64_t payload_position = writer->Position(); + if (payload_position < 0) + return false; + + if (!WriteEbmlElement(writer, libwebm::kMkvCueTime, + static_cast(time_))) { + return false; + } + + if (!WriteEbmlMasterElement(writer, libwebm::kMkvCueTrackPositions, size)) + return false; + if (!WriteEbmlElement(writer, libwebm::kMkvCueTrack, + static_cast(track_))) { + return false; + } + if (!WriteEbmlElement(writer, libwebm::kMkvCueClusterPosition, + static_cast(cluster_pos_))) { + return false; + } + if (output_block_number_ && block_number_ > 1) { + if (!WriteEbmlElement(writer, libwebm::kMkvCueBlockNumber, + static_cast(block_number_))) { + return false; + } + } + + const int64_t stop_position = writer->Position(); + if (stop_position < 0) + return false; + + if (stop_position - payload_position != static_cast(payload_size)) + return false; + + return true; +} + +uint64_t CuePoint::PayloadSize() const { + uint64_t size = EbmlElementSize(libwebm::kMkvCueClusterPosition, + static_cast(cluster_pos_)); + size += EbmlElementSize(libwebm::kMkvCueTrack, static_cast(track_)); + if (output_block_number_ && block_number_ > 1) + size += EbmlElementSize(libwebm::kMkvCueBlockNumber, + static_cast(block_number_)); + const uint64_t track_pos_size = + EbmlMasterElementSize(libwebm::kMkvCueTrackPositions, size) + size; + const uint64_t payload_size = + EbmlElementSize(libwebm::kMkvCueTime, static_cast(time_)) + + track_pos_size; + + return payload_size; +} + +uint64_t CuePoint::Size() const { + const uint64_t payload_size = PayloadSize(); + return EbmlMasterElementSize(libwebm::kMkvCuePoint, payload_size) + + payload_size; +} + +/////////////////////////////////////////////////////////////// +// +// Cues Class + +Cues::Cues() + : cue_entries_capacity_(0), + cue_entries_size_(0), + cue_entries_(NULL), + output_block_number_(true) {} + +Cues::~Cues() { + if (cue_entries_) { + for (int32_t i = 0; i < cue_entries_size_; ++i) { + CuePoint* const cue = cue_entries_[i]; + delete cue; + } + delete[] cue_entries_; + } +} + +bool Cues::AddCue(CuePoint* cue) { + if (!cue) + return false; + + if ((cue_entries_size_ + 1) > cue_entries_capacity_) { + // Add more CuePoints. + const int32_t new_capacity = + (!cue_entries_capacity_) ? 2 : cue_entries_capacity_ * 2; + + if (new_capacity < 1) + return false; + + CuePoint** const cues = + new (std::nothrow) CuePoint*[new_capacity]; // NOLINT + if (!cues) + return false; + + for (int32_t i = 0; i < cue_entries_size_; ++i) { + cues[i] = cue_entries_[i]; + } + + delete[] cue_entries_; + + cue_entries_ = cues; + cue_entries_capacity_ = new_capacity; + } + + cue->set_output_block_number(output_block_number_); + cue_entries_[cue_entries_size_++] = cue; + return true; +} + +CuePoint* Cues::GetCueByIndex(int32_t index) const { + if (cue_entries_ == NULL) + return NULL; + + if (index >= cue_entries_size_) + return NULL; + + return cue_entries_[index]; +} + +uint64_t Cues::Size() { + uint64_t size = 0; + for (int32_t i = 0; i < cue_entries_size_; ++i) + size += GetCueByIndex(i)->Size(); + size += EbmlMasterElementSize(libwebm::kMkvCues, size); + return size; +} + +bool Cues::Write(IMkvWriter* writer) const { + if (!writer) + return false; + + uint64_t size = 0; + for (int32_t i = 0; i < cue_entries_size_; ++i) { + const CuePoint* const cue = GetCueByIndex(i); + + if (!cue) + return false; + + size += cue->Size(); + } + + if (!WriteEbmlMasterElement(writer, libwebm::kMkvCues, size)) + return false; + + const int64_t payload_position = writer->Position(); + if (payload_position < 0) + return false; + + for (int32_t i = 0; i < cue_entries_size_; ++i) { + const CuePoint* const cue = GetCueByIndex(i); + + if (!cue->Write(writer)) + return false; + } + + const int64_t stop_position = writer->Position(); + if (stop_position < 0) + return false; + + if (stop_position - payload_position != static_cast(size)) + return false; + + return true; +} + +/////////////////////////////////////////////////////////////// +// +// ContentEncAESSettings Class + +ContentEncAESSettings::ContentEncAESSettings() : cipher_mode_(kCTR) {} + +uint64_t ContentEncAESSettings::Size() const { + const uint64_t payload = PayloadSize(); + const uint64_t size = + EbmlMasterElementSize(libwebm::kMkvContentEncAESSettings, payload) + + payload; + return size; +} + +bool ContentEncAESSettings::Write(IMkvWriter* writer) const { + const uint64_t payload = PayloadSize(); + + if (!WriteEbmlMasterElement(writer, libwebm::kMkvContentEncAESSettings, + payload)) + return false; + + const int64_t payload_position = writer->Position(); + if (payload_position < 0) + return false; + + if (!WriteEbmlElement(writer, libwebm::kMkvAESSettingsCipherMode, + static_cast(cipher_mode_))) { + return false; + } + + const int64_t stop_position = writer->Position(); + if (stop_position < 0 || + stop_position - payload_position != static_cast(payload)) + return false; + + return true; +} + +uint64_t ContentEncAESSettings::PayloadSize() const { + uint64_t size = EbmlElementSize(libwebm::kMkvAESSettingsCipherMode, + static_cast(cipher_mode_)); + return size; +} + +/////////////////////////////////////////////////////////////// +// +// ContentEncoding Class + +ContentEncoding::ContentEncoding() + : enc_algo_(5), + enc_key_id_(NULL), + encoding_order_(0), + encoding_scope_(1), + encoding_type_(1), + enc_key_id_length_(0) {} + +ContentEncoding::~ContentEncoding() { delete[] enc_key_id_; } + +bool ContentEncoding::SetEncryptionID(const uint8_t* id, uint64_t length) { + if (!id || length < 1) + return false; + + delete[] enc_key_id_; + + enc_key_id_ = + new (std::nothrow) uint8_t[static_cast(length)]; // NOLINT + if (!enc_key_id_) + return false; + + memcpy(enc_key_id_, id, static_cast(length)); + enc_key_id_length_ = length; + + return true; +} + +uint64_t ContentEncoding::Size() const { + const uint64_t encryption_size = EncryptionSize(); + const uint64_t encoding_size = EncodingSize(0, encryption_size); + const uint64_t encodings_size = + EbmlMasterElementSize(libwebm::kMkvContentEncoding, encoding_size) + + encoding_size; + + return encodings_size; +} + +bool ContentEncoding::Write(IMkvWriter* writer) const { + const uint64_t encryption_size = EncryptionSize(); + const uint64_t encoding_size = EncodingSize(0, encryption_size); + const uint64_t size = + EbmlMasterElementSize(libwebm::kMkvContentEncoding, encoding_size) + + encoding_size; + + const int64_t payload_position = writer->Position(); + if (payload_position < 0) + return false; + + if (!WriteEbmlMasterElement(writer, libwebm::kMkvContentEncoding, + encoding_size)) + return false; + if (!WriteEbmlElement(writer, libwebm::kMkvContentEncodingOrder, + static_cast(encoding_order_))) + return false; + if (!WriteEbmlElement(writer, libwebm::kMkvContentEncodingScope, + static_cast(encoding_scope_))) + return false; + if (!WriteEbmlElement(writer, libwebm::kMkvContentEncodingType, + static_cast(encoding_type_))) + return false; + + if (!WriteEbmlMasterElement(writer, libwebm::kMkvContentEncryption, + encryption_size)) + return false; + if (!WriteEbmlElement(writer, libwebm::kMkvContentEncAlgo, + static_cast(enc_algo_))) { + return false; + } + if (!WriteEbmlElement(writer, libwebm::kMkvContentEncKeyID, enc_key_id_, + enc_key_id_length_)) + return false; + + if (!enc_aes_settings_.Write(writer)) + return false; + + const int64_t stop_position = writer->Position(); + if (stop_position < 0 || + stop_position - payload_position != static_cast(size)) + return false; + + return true; +} + +uint64_t ContentEncoding::EncodingSize(uint64_t compresion_size, + uint64_t encryption_size) const { + // TODO(fgalligan): Add support for compression settings. + if (compresion_size != 0) + return 0; + + uint64_t encoding_size = 0; + + if (encryption_size > 0) { + encoding_size += + EbmlMasterElementSize(libwebm::kMkvContentEncryption, encryption_size) + + encryption_size; + } + encoding_size += EbmlElementSize(libwebm::kMkvContentEncodingType, + static_cast(encoding_type_)); + encoding_size += EbmlElementSize(libwebm::kMkvContentEncodingScope, + static_cast(encoding_scope_)); + encoding_size += EbmlElementSize(libwebm::kMkvContentEncodingOrder, + static_cast(encoding_order_)); + + return encoding_size; +} + +uint64_t ContentEncoding::EncryptionSize() const { + const uint64_t aes_size = enc_aes_settings_.Size(); + + uint64_t encryption_size = EbmlElementSize(libwebm::kMkvContentEncKeyID, + enc_key_id_, enc_key_id_length_); + encryption_size += EbmlElementSize(libwebm::kMkvContentEncAlgo, + static_cast(enc_algo_)); + + return encryption_size + aes_size; +} + +/////////////////////////////////////////////////////////////// +// +// Track Class + +Track::Track(unsigned int* seed) + : codec_id_(NULL), + codec_private_(NULL), + language_(NULL), + max_block_additional_id_(0), + name_(NULL), + number_(0), + type_(0), + uid_(MakeUID(seed)), + codec_delay_(0), + seek_pre_roll_(0), + default_duration_(0), + codec_private_length_(0), + content_encoding_entries_(NULL), + content_encoding_entries_size_(0) {} + +Track::~Track() { + delete[] codec_id_; + delete[] codec_private_; + delete[] language_; + delete[] name_; + + if (content_encoding_entries_) { + for (uint32_t i = 0; i < content_encoding_entries_size_; ++i) { + ContentEncoding* const encoding = content_encoding_entries_[i]; + delete encoding; + } + delete[] content_encoding_entries_; + } +} + +bool Track::AddContentEncoding() { + const uint32_t count = content_encoding_entries_size_ + 1; + + ContentEncoding** const content_encoding_entries = + new (std::nothrow) ContentEncoding*[count]; // NOLINT + if (!content_encoding_entries) + return false; + + ContentEncoding* const content_encoding = + new (std::nothrow) ContentEncoding(); // NOLINT + if (!content_encoding) { + delete[] content_encoding_entries; + return false; + } + + for (uint32_t i = 0; i < content_encoding_entries_size_; ++i) { + content_encoding_entries[i] = content_encoding_entries_[i]; + } + + delete[] content_encoding_entries_; + + content_encoding_entries_ = content_encoding_entries; + content_encoding_entries_[content_encoding_entries_size_] = content_encoding; + content_encoding_entries_size_ = count; + return true; +} + +ContentEncoding* Track::GetContentEncodingByIndex(uint32_t index) const { + if (content_encoding_entries_ == NULL) + return NULL; + + if (index >= content_encoding_entries_size_) + return NULL; + + return content_encoding_entries_[index]; +} + +uint64_t Track::PayloadSize() const { + uint64_t size = + EbmlElementSize(libwebm::kMkvTrackNumber, static_cast(number_)); + size += EbmlElementSize(libwebm::kMkvTrackUID, static_cast(uid_)); + size += EbmlElementSize(libwebm::kMkvTrackType, static_cast(type_)); + if (codec_id_) + size += EbmlElementSize(libwebm::kMkvCodecID, codec_id_); + if (codec_private_) + size += EbmlElementSize(libwebm::kMkvCodecPrivate, codec_private_, + codec_private_length_); + if (language_) + size += EbmlElementSize(libwebm::kMkvLanguage, language_); + if (name_) + size += EbmlElementSize(libwebm::kMkvName, name_); + if (max_block_additional_id_) { + size += EbmlElementSize(libwebm::kMkvMaxBlockAdditionID, + static_cast(max_block_additional_id_)); + } + if (codec_delay_) { + size += EbmlElementSize(libwebm::kMkvCodecDelay, + static_cast(codec_delay_)); + } + if (seek_pre_roll_) { + size += EbmlElementSize(libwebm::kMkvSeekPreRoll, + static_cast(seek_pre_roll_)); + } + if (default_duration_) { + size += EbmlElementSize(libwebm::kMkvDefaultDuration, + static_cast(default_duration_)); + } + + if (content_encoding_entries_size_ > 0) { + uint64_t content_encodings_size = 0; + for (uint32_t i = 0; i < content_encoding_entries_size_; ++i) { + ContentEncoding* const encoding = content_encoding_entries_[i]; + content_encodings_size += encoding->Size(); + } + + size += EbmlMasterElementSize(libwebm::kMkvContentEncodings, + content_encodings_size) + + content_encodings_size; + } + + return size; +} + +uint64_t Track::Size() const { + uint64_t size = PayloadSize(); + size += EbmlMasterElementSize(libwebm::kMkvTrackEntry, size); + return size; +} + +bool Track::Write(IMkvWriter* writer) const { + if (!writer) + return false; + + // mandatory elements without a default value. + if (!type_ || !codec_id_) + return false; + + // AV1 tracks require a CodecPrivate. See + // https://github.com/Matroska-Org/matroska-specification/blob/av1-mappin/codec/av1.md + // TODO(tomfinegan): Update the above link to the AV1 Matroska mappings to + // point to a stable version once it is finalized, or our own WebM mappings + // page on webmproject.org should we decide to release them. + if (!strcmp(codec_id_, Tracks::kAv1CodecId) && !codec_private_) + return false; + + // |size| may be bigger than what is written out in this function because + // derived classes may write out more data in the Track element. + const uint64_t payload_size = PayloadSize(); + + if (!WriteEbmlMasterElement(writer, libwebm::kMkvTrackEntry, payload_size)) + return false; + + uint64_t size = + EbmlElementSize(libwebm::kMkvTrackNumber, static_cast(number_)); + size += EbmlElementSize(libwebm::kMkvTrackUID, static_cast(uid_)); + size += EbmlElementSize(libwebm::kMkvTrackType, static_cast(type_)); + if (codec_id_) + size += EbmlElementSize(libwebm::kMkvCodecID, codec_id_); + if (codec_private_) + size += EbmlElementSize(libwebm::kMkvCodecPrivate, codec_private_, + static_cast(codec_private_length_)); + if (language_) + size += EbmlElementSize(libwebm::kMkvLanguage, language_); + if (name_) + size += EbmlElementSize(libwebm::kMkvName, name_); + if (max_block_additional_id_) + size += EbmlElementSize(libwebm::kMkvMaxBlockAdditionID, + static_cast(max_block_additional_id_)); + if (codec_delay_) + size += EbmlElementSize(libwebm::kMkvCodecDelay, + static_cast(codec_delay_)); + if (seek_pre_roll_) + size += EbmlElementSize(libwebm::kMkvSeekPreRoll, + static_cast(seek_pre_roll_)); + if (default_duration_) + size += EbmlElementSize(libwebm::kMkvDefaultDuration, + static_cast(default_duration_)); + + const int64_t payload_position = writer->Position(); + if (payload_position < 0) + return false; + + if (!WriteEbmlElement(writer, libwebm::kMkvTrackNumber, + static_cast(number_))) + return false; + if (!WriteEbmlElement(writer, libwebm::kMkvTrackUID, + static_cast(uid_))) + return false; + if (!WriteEbmlElement(writer, libwebm::kMkvTrackType, + static_cast(type_))) + return false; + if (max_block_additional_id_) { + if (!WriteEbmlElement(writer, libwebm::kMkvMaxBlockAdditionID, + static_cast(max_block_additional_id_))) { + return false; + } + } + if (codec_delay_) { + if (!WriteEbmlElement(writer, libwebm::kMkvCodecDelay, + static_cast(codec_delay_))) + return false; + } + if (seek_pre_roll_) { + if (!WriteEbmlElement(writer, libwebm::kMkvSeekPreRoll, + static_cast(seek_pre_roll_))) + return false; + } + if (default_duration_) { + if (!WriteEbmlElement(writer, libwebm::kMkvDefaultDuration, + static_cast(default_duration_))) + return false; + } + if (codec_id_) { + if (!WriteEbmlElement(writer, libwebm::kMkvCodecID, codec_id_)) + return false; + } + if (codec_private_) { + if (!WriteEbmlElement(writer, libwebm::kMkvCodecPrivate, codec_private_, + static_cast(codec_private_length_))) + return false; + } + if (language_) { + if (!WriteEbmlElement(writer, libwebm::kMkvLanguage, language_)) + return false; + } + if (name_) { + if (!WriteEbmlElement(writer, libwebm::kMkvName, name_)) + return false; + } + + int64_t stop_position = writer->Position(); + if (stop_position < 0 || + stop_position - payload_position != static_cast(size)) + return false; + + if (content_encoding_entries_size_ > 0) { + uint64_t content_encodings_size = 0; + for (uint32_t i = 0; i < content_encoding_entries_size_; ++i) { + ContentEncoding* const encoding = content_encoding_entries_[i]; + content_encodings_size += encoding->Size(); + } + + if (!WriteEbmlMasterElement(writer, libwebm::kMkvContentEncodings, + content_encodings_size)) + return false; + + for (uint32_t i = 0; i < content_encoding_entries_size_; ++i) { + ContentEncoding* const encoding = content_encoding_entries_[i]; + if (!encoding->Write(writer)) + return false; + } + } + + stop_position = writer->Position(); + if (stop_position < 0) + return false; + return true; +} + +bool Track::SetCodecPrivate(const uint8_t* codec_private, uint64_t length) { + if (!codec_private || length < 1) + return false; + + delete[] codec_private_; + + codec_private_ = + new (std::nothrow) uint8_t[static_cast(length)]; // NOLINT + if (!codec_private_) + return false; + + memcpy(codec_private_, codec_private, static_cast(length)); + codec_private_length_ = length; + + return true; +} + +void Track::set_codec_id(const char* codec_id) { + if (codec_id) { + delete[] codec_id_; + + const size_t length = strlen(codec_id) + 1; + codec_id_ = new (std::nothrow) char[length]; // NOLINT + if (codec_id_) { +#ifdef _MSC_VER + strcpy_s(codec_id_, length, codec_id); +#else + strcpy(codec_id_, codec_id); +#endif + } + } +} + +// TODO(fgalligan): Vet the language parameter. +void Track::set_language(const char* language) { + if (language) { + delete[] language_; + + const size_t length = strlen(language) + 1; + language_ = new (std::nothrow) char[length]; // NOLINT + if (language_) { +#ifdef _MSC_VER + strcpy_s(language_, length, language); +#else + strcpy(language_, language); +#endif + } + } +} + +void Track::set_name(const char* name) { + if (name) { + delete[] name_; + + const size_t length = strlen(name) + 1; + name_ = new (std::nothrow) char[length]; // NOLINT + if (name_) { +#ifdef _MSC_VER + strcpy_s(name_, length, name); +#else + strcpy(name_, name); +#endif + } + } +} + +/////////////////////////////////////////////////////////////// +// +// Colour and its child elements + +uint64_t PrimaryChromaticity::PrimaryChromaticitySize( + libwebm::MkvId x_id, libwebm::MkvId y_id) const { + return EbmlElementSize(x_id, x_) + EbmlElementSize(y_id, y_); +} + +bool PrimaryChromaticity::Write(IMkvWriter* writer, libwebm::MkvId x_id, + libwebm::MkvId y_id) const { + if (!Valid()) { + return false; + } + return WriteEbmlElement(writer, x_id, x_) && + WriteEbmlElement(writer, y_id, y_); +} + +bool PrimaryChromaticity::Valid() const { + return (x_ >= kChromaticityMin && x_ <= kChromaticityMax && + y_ >= kChromaticityMin && y_ <= kChromaticityMax); +} + +uint64_t MasteringMetadata::MasteringMetadataSize() const { + uint64_t size = PayloadSize(); + + if (size > 0) + size += EbmlMasterElementSize(libwebm::kMkvMasteringMetadata, size); + + return size; +} + +bool MasteringMetadata::Valid() const { + if (luminance_min_ != kValueNotPresent) { + if (luminance_min_ < kMinLuminance || luminance_min_ > kMinLuminanceMax || + luminance_min_ > luminance_max_) { + return false; + } + } + if (luminance_max_ != kValueNotPresent) { + if (luminance_max_ < kMinLuminance || luminance_max_ > kMaxLuminanceMax || + luminance_max_ < luminance_min_) { + return false; + } + } + if (r_ && !r_->Valid()) + return false; + if (g_ && !g_->Valid()) + return false; + if (b_ && !b_->Valid()) + return false; + if (white_point_ && !white_point_->Valid()) + return false; + + return true; +} + +bool MasteringMetadata::Write(IMkvWriter* writer) const { + const uint64_t size = PayloadSize(); + + // Don't write an empty element. + if (size == 0) + return true; + + if (!WriteEbmlMasterElement(writer, libwebm::kMkvMasteringMetadata, size)) + return false; + if (luminance_max_ != kValueNotPresent && + !WriteEbmlElement(writer, libwebm::kMkvLuminanceMax, luminance_max_)) { + return false; + } + if (luminance_min_ != kValueNotPresent && + !WriteEbmlElement(writer, libwebm::kMkvLuminanceMin, luminance_min_)) { + return false; + } + if (r_ && !r_->Write(writer, libwebm::kMkvPrimaryRChromaticityX, + libwebm::kMkvPrimaryRChromaticityY)) { + return false; + } + if (g_ && !g_->Write(writer, libwebm::kMkvPrimaryGChromaticityX, + libwebm::kMkvPrimaryGChromaticityY)) { + return false; + } + if (b_ && !b_->Write(writer, libwebm::kMkvPrimaryBChromaticityX, + libwebm::kMkvPrimaryBChromaticityY)) { + return false; + } + if (white_point_ && + !white_point_->Write(writer, libwebm::kMkvWhitePointChromaticityX, + libwebm::kMkvWhitePointChromaticityY)) { + return false; + } + + return true; +} + +bool MasteringMetadata::SetChromaticity( + const PrimaryChromaticity* r, const PrimaryChromaticity* g, + const PrimaryChromaticity* b, const PrimaryChromaticity* white_point) { + PrimaryChromaticityPtr r_ptr(nullptr); + if (r) { + if (!CopyChromaticity(r, &r_ptr)) + return false; + } + PrimaryChromaticityPtr g_ptr(nullptr); + if (g) { + if (!CopyChromaticity(g, &g_ptr)) + return false; + } + PrimaryChromaticityPtr b_ptr(nullptr); + if (b) { + if (!CopyChromaticity(b, &b_ptr)) + return false; + } + PrimaryChromaticityPtr wp_ptr(nullptr); + if (white_point) { + if (!CopyChromaticity(white_point, &wp_ptr)) + return false; + } + + r_ = r_ptr.release(); + g_ = g_ptr.release(); + b_ = b_ptr.release(); + white_point_ = wp_ptr.release(); + return true; +} + +uint64_t MasteringMetadata::PayloadSize() const { + uint64_t size = 0; + + if (luminance_max_ != kValueNotPresent) + size += EbmlElementSize(libwebm::kMkvLuminanceMax, luminance_max_); + if (luminance_min_ != kValueNotPresent) + size += EbmlElementSize(libwebm::kMkvLuminanceMin, luminance_min_); + + if (r_) { + size += r_->PrimaryChromaticitySize(libwebm::kMkvPrimaryRChromaticityX, + libwebm::kMkvPrimaryRChromaticityY); + } + if (g_) { + size += g_->PrimaryChromaticitySize(libwebm::kMkvPrimaryGChromaticityX, + libwebm::kMkvPrimaryGChromaticityY); + } + if (b_) { + size += b_->PrimaryChromaticitySize(libwebm::kMkvPrimaryBChromaticityX, + libwebm::kMkvPrimaryBChromaticityY); + } + if (white_point_) { + size += white_point_->PrimaryChromaticitySize( + libwebm::kMkvWhitePointChromaticityX, + libwebm::kMkvWhitePointChromaticityY); + } + + return size; +} + +uint64_t Colour::ColourSize() const { + uint64_t size = PayloadSize(); + + if (size > 0) + size += EbmlMasterElementSize(libwebm::kMkvColour, size); + + return size; +} + +bool Colour::Valid() const { + if (mastering_metadata_ && !mastering_metadata_->Valid()) + return false; + if (matrix_coefficients_ != kValueNotPresent && + !IsMatrixCoefficientsValueValid(matrix_coefficients_)) { + return false; + } + if (chroma_siting_horz_ != kValueNotPresent && + !IsChromaSitingHorzValueValid(chroma_siting_horz_)) { + return false; + } + if (chroma_siting_vert_ != kValueNotPresent && + !IsChromaSitingVertValueValid(chroma_siting_vert_)) { + return false; + } + if (range_ != kValueNotPresent && !IsColourRangeValueValid(range_)) + return false; + if (transfer_characteristics_ != kValueNotPresent && + !IsTransferCharacteristicsValueValid(transfer_characteristics_)) { + return false; + } + if (primaries_ != kValueNotPresent && !IsPrimariesValueValid(primaries_)) + return false; + + return true; +} + +bool Colour::Write(IMkvWriter* writer) const { + const uint64_t size = PayloadSize(); + + // Don't write an empty element. + if (size == 0) + return true; + + // Don't write an invalid element. + if (!Valid()) + return false; + + if (!WriteEbmlMasterElement(writer, libwebm::kMkvColour, size)) + return false; + + if (matrix_coefficients_ != kValueNotPresent && + !WriteEbmlElement(writer, libwebm::kMkvMatrixCoefficients, + static_cast(matrix_coefficients_))) { + return false; + } + if (bits_per_channel_ != kValueNotPresent && + !WriteEbmlElement(writer, libwebm::kMkvBitsPerChannel, + static_cast(bits_per_channel_))) { + return false; + } + if (chroma_subsampling_horz_ != kValueNotPresent && + !WriteEbmlElement(writer, libwebm::kMkvChromaSubsamplingHorz, + static_cast(chroma_subsampling_horz_))) { + return false; + } + if (chroma_subsampling_vert_ != kValueNotPresent && + !WriteEbmlElement(writer, libwebm::kMkvChromaSubsamplingVert, + static_cast(chroma_subsampling_vert_))) { + return false; + } + + if (cb_subsampling_horz_ != kValueNotPresent && + !WriteEbmlElement(writer, libwebm::kMkvCbSubsamplingHorz, + static_cast(cb_subsampling_horz_))) { + return false; + } + if (cb_subsampling_vert_ != kValueNotPresent && + !WriteEbmlElement(writer, libwebm::kMkvCbSubsamplingVert, + static_cast(cb_subsampling_vert_))) { + return false; + } + if (chroma_siting_horz_ != kValueNotPresent && + !WriteEbmlElement(writer, libwebm::kMkvChromaSitingHorz, + static_cast(chroma_siting_horz_))) { + return false; + } + if (chroma_siting_vert_ != kValueNotPresent && + !WriteEbmlElement(writer, libwebm::kMkvChromaSitingVert, + static_cast(chroma_siting_vert_))) { + return false; + } + if (range_ != kValueNotPresent && + !WriteEbmlElement(writer, libwebm::kMkvRange, + static_cast(range_))) { + return false; + } + if (transfer_characteristics_ != kValueNotPresent && + !WriteEbmlElement(writer, libwebm::kMkvTransferCharacteristics, + static_cast(transfer_characteristics_))) { + return false; + } + if (primaries_ != kValueNotPresent && + !WriteEbmlElement(writer, libwebm::kMkvPrimaries, + static_cast(primaries_))) { + return false; + } + if (max_cll_ != kValueNotPresent && + !WriteEbmlElement(writer, libwebm::kMkvMaxCLL, + static_cast(max_cll_))) { + return false; + } + if (max_fall_ != kValueNotPresent && + !WriteEbmlElement(writer, libwebm::kMkvMaxFALL, + static_cast(max_fall_))) { + return false; + } + + if (mastering_metadata_ && !mastering_metadata_->Write(writer)) + return false; + + return true; +} + +bool Colour::SetMasteringMetadata(const MasteringMetadata& mastering_metadata) { + std::unique_ptr mm_ptr(new MasteringMetadata()); + if (!mm_ptr.get()) + return false; + + mm_ptr->set_luminance_max(mastering_metadata.luminance_max()); + mm_ptr->set_luminance_min(mastering_metadata.luminance_min()); + + if (!mm_ptr->SetChromaticity(mastering_metadata.r(), mastering_metadata.g(), + mastering_metadata.b(), + mastering_metadata.white_point())) { + return false; + } + + delete mastering_metadata_; + mastering_metadata_ = mm_ptr.release(); + return true; +} + +uint64_t Colour::PayloadSize() const { + uint64_t size = 0; + + if (matrix_coefficients_ != kValueNotPresent) { + size += EbmlElementSize(libwebm::kMkvMatrixCoefficients, + static_cast(matrix_coefficients_)); + } + if (bits_per_channel_ != kValueNotPresent) { + size += EbmlElementSize(libwebm::kMkvBitsPerChannel, + static_cast(bits_per_channel_)); + } + if (chroma_subsampling_horz_ != kValueNotPresent) { + size += EbmlElementSize(libwebm::kMkvChromaSubsamplingHorz, + static_cast(chroma_subsampling_horz_)); + } + if (chroma_subsampling_vert_ != kValueNotPresent) { + size += EbmlElementSize(libwebm::kMkvChromaSubsamplingVert, + static_cast(chroma_subsampling_vert_)); + } + if (cb_subsampling_horz_ != kValueNotPresent) { + size += EbmlElementSize(libwebm::kMkvCbSubsamplingHorz, + static_cast(cb_subsampling_horz_)); + } + if (cb_subsampling_vert_ != kValueNotPresent) { + size += EbmlElementSize(libwebm::kMkvCbSubsamplingVert, + static_cast(cb_subsampling_vert_)); + } + if (chroma_siting_horz_ != kValueNotPresent) { + size += EbmlElementSize(libwebm::kMkvChromaSitingHorz, + static_cast(chroma_siting_horz_)); + } + if (chroma_siting_vert_ != kValueNotPresent) { + size += EbmlElementSize(libwebm::kMkvChromaSitingVert, + static_cast(chroma_siting_vert_)); + } + if (range_ != kValueNotPresent) { + size += EbmlElementSize(libwebm::kMkvRange, static_cast(range_)); + } + if (transfer_characteristics_ != kValueNotPresent) { + size += EbmlElementSize(libwebm::kMkvTransferCharacteristics, + static_cast(transfer_characteristics_)); + } + if (primaries_ != kValueNotPresent) { + size += EbmlElementSize(libwebm::kMkvPrimaries, + static_cast(primaries_)); + } + if (max_cll_ != kValueNotPresent) { + size += EbmlElementSize(libwebm::kMkvMaxCLL, static_cast(max_cll_)); + } + if (max_fall_ != kValueNotPresent) { + size += + EbmlElementSize(libwebm::kMkvMaxFALL, static_cast(max_fall_)); + } + + if (mastering_metadata_) + size += mastering_metadata_->MasteringMetadataSize(); + + return size; +} + +/////////////////////////////////////////////////////////////// +// +// Projection element + +uint64_t Projection::ProjectionSize() const { + uint64_t size = PayloadSize(); + + if (size > 0) + size += EbmlMasterElementSize(libwebm::kMkvProjection, size); + + return size; +} + +bool Projection::Write(IMkvWriter* writer) const { + const uint64_t size = PayloadSize(); + + // Don't write an empty element. + if (size == 0) + return true; + + if (!WriteEbmlMasterElement(writer, libwebm::kMkvProjection, size)) + return false; + + if (!WriteEbmlElement(writer, libwebm::kMkvProjectionType, + static_cast(type_))) { + return false; + } + + if (private_data_length_ > 0 && private_data_ != NULL && + !WriteEbmlElement(writer, libwebm::kMkvProjectionPrivate, private_data_, + private_data_length_)) { + return false; + } + + if (!WriteEbmlElement(writer, libwebm::kMkvProjectionPoseYaw, pose_yaw_)) + return false; + + if (!WriteEbmlElement(writer, libwebm::kMkvProjectionPosePitch, + pose_pitch_)) { + return false; + } + + if (!WriteEbmlElement(writer, libwebm::kMkvProjectionPoseRoll, pose_roll_)) { + return false; + } + + return true; +} + +bool Projection::SetProjectionPrivate(const uint8_t* data, + uint64_t data_length) { + if (data == NULL || data_length == 0) { + return false; + } + + if (data_length != static_cast(data_length)) { + return false; + } + + uint8_t* new_private_data = + new (std::nothrow) uint8_t[static_cast(data_length)]; + if (new_private_data == NULL) { + return false; + } + + delete[] private_data_; + private_data_ = new_private_data; + private_data_length_ = data_length; + memcpy(private_data_, data, static_cast(data_length)); + + return true; +} + +uint64_t Projection::PayloadSize() const { + uint64_t size = + EbmlElementSize(libwebm::kMkvProjection, static_cast(type_)); + + if (private_data_length_ > 0 && private_data_ != NULL) { + size += EbmlElementSize(libwebm::kMkvProjectionPrivate, private_data_, + private_data_length_); + } + + size += EbmlElementSize(libwebm::kMkvProjectionPoseYaw, pose_yaw_); + size += EbmlElementSize(libwebm::kMkvProjectionPosePitch, pose_pitch_); + size += EbmlElementSize(libwebm::kMkvProjectionPoseRoll, pose_roll_); + + return size; +} + +/////////////////////////////////////////////////////////////// +// +// VideoTrack Class + +VideoTrack::VideoTrack(unsigned int* seed) + : Track(seed), + display_height_(0), + display_width_(0), + pixel_height_(0), + pixel_width_(0), + crop_left_(0), + crop_right_(0), + crop_top_(0), + crop_bottom_(0), + frame_rate_(0.0), + height_(0), + stereo_mode_(0), + alpha_mode_(0), + width_(0), + colour_space_(NULL), + colour_(NULL), + projection_(NULL) {} + +VideoTrack::~VideoTrack() { + delete colour_; + delete projection_; +} + +bool VideoTrack::SetStereoMode(uint64_t stereo_mode) { + if (stereo_mode != kMono && stereo_mode != kSideBySideLeftIsFirst && + stereo_mode != kTopBottomRightIsFirst && + stereo_mode != kTopBottomLeftIsFirst && + stereo_mode != kSideBySideRightIsFirst) + return false; + + stereo_mode_ = stereo_mode; + return true; +} + +bool VideoTrack::SetAlphaMode(uint64_t alpha_mode) { + if (alpha_mode != kNoAlpha && alpha_mode != kAlpha) + return false; + + alpha_mode_ = alpha_mode; + return true; +} + +uint64_t VideoTrack::PayloadSize() const { + const uint64_t parent_size = Track::PayloadSize(); + + uint64_t size = VideoPayloadSize(); + size += EbmlMasterElementSize(libwebm::kMkvVideo, size); + + return parent_size + size; +} + +bool VideoTrack::Write(IMkvWriter* writer) const { + if (!Track::Write(writer)) + return false; + + const uint64_t size = VideoPayloadSize(); + + if (!WriteEbmlMasterElement(writer, libwebm::kMkvVideo, size)) + return false; + + const int64_t payload_position = writer->Position(); + if (payload_position < 0) + return false; + + if (!WriteEbmlElement( + writer, libwebm::kMkvPixelWidth, + static_cast((pixel_width_ > 0) ? pixel_width_ : width_))) + return false; + if (!WriteEbmlElement( + writer, libwebm::kMkvPixelHeight, + static_cast((pixel_height_ > 0) ? pixel_height_ : height_))) + return false; + if (display_width_ > 0) { + if (!WriteEbmlElement(writer, libwebm::kMkvDisplayWidth, + static_cast(display_width_))) + return false; + } + if (display_height_ > 0) { + if (!WriteEbmlElement(writer, libwebm::kMkvDisplayHeight, + static_cast(display_height_))) + return false; + } + if (crop_left_ > 0) { + if (!WriteEbmlElement(writer, libwebm::kMkvPixelCropLeft, + static_cast(crop_left_))) + return false; + } + if (crop_right_ > 0) { + if (!WriteEbmlElement(writer, libwebm::kMkvPixelCropRight, + static_cast(crop_right_))) + return false; + } + if (crop_top_ > 0) { + if (!WriteEbmlElement(writer, libwebm::kMkvPixelCropTop, + static_cast(crop_top_))) + return false; + } + if (crop_bottom_ > 0) { + if (!WriteEbmlElement(writer, libwebm::kMkvPixelCropBottom, + static_cast(crop_bottom_))) + return false; + } + if (stereo_mode_ > kMono) { + if (!WriteEbmlElement(writer, libwebm::kMkvStereoMode, + static_cast(stereo_mode_))) + return false; + } + if (alpha_mode_ > kNoAlpha) { + if (!WriteEbmlElement(writer, libwebm::kMkvAlphaMode, + static_cast(alpha_mode_))) + return false; + } + if (colour_space_) { + if (!WriteEbmlElement(writer, libwebm::kMkvColourSpace, colour_space_)) + return false; + } + if (frame_rate_ > 0.0) { + if (!WriteEbmlElement(writer, libwebm::kMkvFrameRate, + static_cast(frame_rate_))) { + return false; + } + } + if (colour_) { + if (!colour_->Write(writer)) + return false; + } + if (projection_) { + if (!projection_->Write(writer)) + return false; + } + + const int64_t stop_position = writer->Position(); + if (stop_position < 0 || + stop_position - payload_position != static_cast(size)) { + return false; + } + + return true; +} + +void VideoTrack::set_colour_space(const char* colour_space) { + if (colour_space) { + delete[] colour_space_; + + const size_t length = strlen(colour_space) + 1; + colour_space_ = new (std::nothrow) char[length]; // NOLINT + if (colour_space_) { +#ifdef _MSC_VER + strcpy_s(colour_space_, length, colour_space); +#else + strcpy(colour_space_, colour_space); +#endif + } + } +} + +bool VideoTrack::SetColour(const Colour& colour) { + std::unique_ptr colour_ptr(new Colour()); + if (!colour_ptr.get()) + return false; + + if (colour.mastering_metadata()) { + if (!colour_ptr->SetMasteringMetadata(*colour.mastering_metadata())) + return false; + } + + colour_ptr->set_matrix_coefficients(colour.matrix_coefficients()); + colour_ptr->set_bits_per_channel(colour.bits_per_channel()); + colour_ptr->set_chroma_subsampling_horz(colour.chroma_subsampling_horz()); + colour_ptr->set_chroma_subsampling_vert(colour.chroma_subsampling_vert()); + colour_ptr->set_cb_subsampling_horz(colour.cb_subsampling_horz()); + colour_ptr->set_cb_subsampling_vert(colour.cb_subsampling_vert()); + colour_ptr->set_chroma_siting_horz(colour.chroma_siting_horz()); + colour_ptr->set_chroma_siting_vert(colour.chroma_siting_vert()); + colour_ptr->set_range(colour.range()); + colour_ptr->set_transfer_characteristics(colour.transfer_characteristics()); + colour_ptr->set_primaries(colour.primaries()); + colour_ptr->set_max_cll(colour.max_cll()); + colour_ptr->set_max_fall(colour.max_fall()); + delete colour_; + colour_ = colour_ptr.release(); + return true; +} + +bool VideoTrack::SetProjection(const Projection& projection) { + std::unique_ptr projection_ptr(new Projection()); + if (!projection_ptr.get()) + return false; + + if (projection.private_data()) { + if (!projection_ptr->SetProjectionPrivate( + projection.private_data(), projection.private_data_length())) { + return false; + } + } + + projection_ptr->set_type(projection.type()); + projection_ptr->set_pose_yaw(projection.pose_yaw()); + projection_ptr->set_pose_pitch(projection.pose_pitch()); + projection_ptr->set_pose_roll(projection.pose_roll()); + delete projection_; + projection_ = projection_ptr.release(); + return true; +} + +uint64_t VideoTrack::VideoPayloadSize() const { + uint64_t size = EbmlElementSize( + libwebm::kMkvPixelWidth, + static_cast((pixel_width_ > 0) ? pixel_width_ : width_)); + size += EbmlElementSize( + libwebm::kMkvPixelHeight, + static_cast((pixel_height_ > 0) ? pixel_height_ : height_)); + if (display_width_ > 0) + size += EbmlElementSize(libwebm::kMkvDisplayWidth, + static_cast(display_width_)); + if (display_height_ > 0) + size += EbmlElementSize(libwebm::kMkvDisplayHeight, + static_cast(display_height_)); + if (crop_left_ > 0) + size += EbmlElementSize(libwebm::kMkvPixelCropLeft, + static_cast(crop_left_)); + if (crop_right_ > 0) + size += EbmlElementSize(libwebm::kMkvPixelCropRight, + static_cast(crop_right_)); + if (crop_top_ > 0) + size += EbmlElementSize(libwebm::kMkvPixelCropTop, + static_cast(crop_top_)); + if (crop_bottom_ > 0) + size += EbmlElementSize(libwebm::kMkvPixelCropBottom, + static_cast(crop_bottom_)); + if (stereo_mode_ > kMono) + size += EbmlElementSize(libwebm::kMkvStereoMode, + static_cast(stereo_mode_)); + if (alpha_mode_ > kNoAlpha) + size += EbmlElementSize(libwebm::kMkvAlphaMode, + static_cast(alpha_mode_)); + if (frame_rate_ > 0.0) + size += EbmlElementSize(libwebm::kMkvFrameRate, + static_cast(frame_rate_)); + if (colour_space_) + size += EbmlElementSize(libwebm::kMkvColourSpace, colour_space_); + if (colour_) + size += colour_->ColourSize(); + if (projection_) + size += projection_->ProjectionSize(); + + return size; +} + +/////////////////////////////////////////////////////////////// +// +// AudioTrack Class + +AudioTrack::AudioTrack(unsigned int* seed) + : Track(seed), bit_depth_(0), channels_(1), sample_rate_(0.0) {} + +AudioTrack::~AudioTrack() {} + +uint64_t AudioTrack::PayloadSize() const { + const uint64_t parent_size = Track::PayloadSize(); + + uint64_t size = EbmlElementSize(libwebm::kMkvSamplingFrequency, + static_cast(sample_rate_)); + size += + EbmlElementSize(libwebm::kMkvChannels, static_cast(channels_)); + if (bit_depth_ > 0) + size += + EbmlElementSize(libwebm::kMkvBitDepth, static_cast(bit_depth_)); + size += EbmlMasterElementSize(libwebm::kMkvAudio, size); + + return parent_size + size; +} + +bool AudioTrack::Write(IMkvWriter* writer) const { + if (!Track::Write(writer)) + return false; + + // Calculate AudioSettings size. + uint64_t size = EbmlElementSize(libwebm::kMkvSamplingFrequency, + static_cast(sample_rate_)); + size += + EbmlElementSize(libwebm::kMkvChannels, static_cast(channels_)); + if (bit_depth_ > 0) + size += + EbmlElementSize(libwebm::kMkvBitDepth, static_cast(bit_depth_)); + + if (!WriteEbmlMasterElement(writer, libwebm::kMkvAudio, size)) + return false; + + const int64_t payload_position = writer->Position(); + if (payload_position < 0) + return false; + + if (!WriteEbmlElement(writer, libwebm::kMkvSamplingFrequency, + static_cast(sample_rate_))) + return false; + if (!WriteEbmlElement(writer, libwebm::kMkvChannels, + static_cast(channels_))) + return false; + if (bit_depth_ > 0) + if (!WriteEbmlElement(writer, libwebm::kMkvBitDepth, + static_cast(bit_depth_))) + return false; + + const int64_t stop_position = writer->Position(); + if (stop_position < 0 || + stop_position - payload_position != static_cast(size)) + return false; + + return true; +} + +/////////////////////////////////////////////////////////////// +// +// Tracks Class + +const char Tracks::kOpusCodecId[] = "A_OPUS"; +const char Tracks::kVorbisCodecId[] = "A_VORBIS"; +const char Tracks::kAv1CodecId[] = "V_AV1"; +const char Tracks::kVp8CodecId[] = "V_VP8"; +const char Tracks::kVp9CodecId[] = "V_VP9"; +const char Tracks::kWebVttCaptionsId[] = "D_WEBVTT/CAPTIONS"; +const char Tracks::kWebVttDescriptionsId[] = "D_WEBVTT/DESCRIPTIONS"; +const char Tracks::kWebVttMetadataId[] = "D_WEBVTT/METADATA"; +const char Tracks::kWebVttSubtitlesId[] = "D_WEBVTT/SUBTITLES"; + +Tracks::Tracks() + : track_entries_(NULL), track_entries_size_(0), wrote_tracks_(false) {} + +Tracks::~Tracks() { + if (track_entries_) { + for (uint32_t i = 0; i < track_entries_size_; ++i) { + Track* const track = track_entries_[i]; + delete track; + } + delete[] track_entries_; + } +} + +bool Tracks::AddTrack(Track* track, int32_t number) { + if (number < 0 || wrote_tracks_) + return false; + + // This muxer only supports track numbers in the range [1, 126], in + // order to be able (to use Matroska integer representation) to + // serialize the block header (of which the track number is a part) + // for a frame using exactly 4 bytes. + + if (number > 0x7E) + return false; + + uint32_t track_num = number; + + if (track_num > 0) { + // Check to make sure a track does not already have |track_num|. + for (uint32_t i = 0; i < track_entries_size_; ++i) { + if (track_entries_[i]->number() == track_num) + return false; + } + } + + const uint32_t count = track_entries_size_ + 1; + + Track** const track_entries = new (std::nothrow) Track*[count]; // NOLINT + if (!track_entries) + return false; + + for (uint32_t i = 0; i < track_entries_size_; ++i) { + track_entries[i] = track_entries_[i]; + } + + delete[] track_entries_; + + // Find the lowest availible track number > 0. + if (track_num == 0) { + track_num = count; + + // Check to make sure a track does not already have |track_num|. + bool exit = false; + do { + exit = true; + for (uint32_t i = 0; i < track_entries_size_; ++i) { + if (track_entries[i]->number() == track_num) { + track_num++; + exit = false; + break; + } + } + } while (!exit); + } + track->set_number(track_num); + + track_entries_ = track_entries; + track_entries_[track_entries_size_] = track; + track_entries_size_ = count; + return true; +} + +const Track* Tracks::GetTrackByIndex(uint32_t index) const { + if (track_entries_ == NULL) + return NULL; + + if (index >= track_entries_size_) + return NULL; + + return track_entries_[index]; +} + +Track* Tracks::GetTrackByNumber(uint64_t track_number) const { + const int32_t count = track_entries_size(); + for (int32_t i = 0; i < count; ++i) { + if (track_entries_[i]->number() == track_number) + return track_entries_[i]; + } + + return NULL; +} + +bool Tracks::TrackIsAudio(uint64_t track_number) const { + const Track* const track = GetTrackByNumber(track_number); + + if (track->type() == kAudio) + return true; + + return false; +} + +bool Tracks::TrackIsVideo(uint64_t track_number) const { + const Track* const track = GetTrackByNumber(track_number); + + if (track->type() == kVideo) + return true; + + return false; +} + +bool Tracks::Write(IMkvWriter* writer) const { + uint64_t size = 0; + const int32_t count = track_entries_size(); + for (int32_t i = 0; i < count; ++i) { + const Track* const track = GetTrackByIndex(i); + + if (!track) + return false; + + size += track->Size(); + } + + if (!WriteEbmlMasterElement(writer, libwebm::kMkvTracks, size)) + return false; + + const int64_t payload_position = writer->Position(); + if (payload_position < 0) + return false; + + for (int32_t i = 0; i < count; ++i) { + const Track* const track = GetTrackByIndex(i); + if (!track->Write(writer)) + return false; + } + + const int64_t stop_position = writer->Position(); + if (stop_position < 0 || + stop_position - payload_position != static_cast(size)) + return false; + + wrote_tracks_ = true; + return true; +} + +/////////////////////////////////////////////////////////////// +// +// Chapter Class + +bool Chapter::set_id(const char* id) { return StrCpy(id, &id_); } + +void Chapter::set_time(const Segment& segment, uint64_t start_ns, + uint64_t end_ns) { + const SegmentInfo* const info = segment.GetSegmentInfo(); + const uint64_t timecode_scale = info->timecode_scale(); + start_timecode_ = start_ns / timecode_scale; + end_timecode_ = end_ns / timecode_scale; +} + +bool Chapter::add_string(const char* title, const char* language, + const char* country) { + if (!ExpandDisplaysArray()) + return false; + + Display& d = displays_[displays_count_++]; + d.Init(); + + if (!d.set_title(title)) + return false; + + if (!d.set_language(language)) + return false; + + if (!d.set_country(country)) + return false; + + return true; +} + +Chapter::Chapter() { + // This ctor only constructs the object. Proper initialization is + // done in Init() (called in Chapters::AddChapter()). The only + // reason we bother implementing this ctor is because we had to + // declare it as private (along with the dtor), in order to prevent + // clients from creating Chapter instances (a privelege we grant + // only to the Chapters class). Doing no initialization here also + // means that creating arrays of chapter objects is more efficient, + // because we only initialize each new chapter object as it becomes + // active on the array. +} + +Chapter::~Chapter() {} + +void Chapter::Init(unsigned int* seed) { + id_ = NULL; + start_timecode_ = 0; + end_timecode_ = 0; + displays_ = NULL; + displays_size_ = 0; + displays_count_ = 0; + uid_ = MakeUID(seed); +} + +void Chapter::ShallowCopy(Chapter* dst) const { + dst->id_ = id_; + dst->start_timecode_ = start_timecode_; + dst->end_timecode_ = end_timecode_; + dst->uid_ = uid_; + dst->displays_ = displays_; + dst->displays_size_ = displays_size_; + dst->displays_count_ = displays_count_; +} + +void Chapter::Clear() { + StrCpy(NULL, &id_); + + while (displays_count_ > 0) { + Display& d = displays_[--displays_count_]; + d.Clear(); + } + + delete[] displays_; + displays_ = NULL; + + displays_size_ = 0; +} + +bool Chapter::ExpandDisplaysArray() { + if (displays_size_ > displays_count_) + return true; // nothing to do yet + + const int size = (displays_size_ == 0) ? 1 : 2 * displays_size_; + + Display* const displays = new (std::nothrow) Display[size]; // NOLINT + if (displays == NULL) + return false; + + for (int idx = 0; idx < displays_count_; ++idx) { + displays[idx] = displays_[idx]; // shallow copy + } + + delete[] displays_; + + displays_ = displays; + displays_size_ = size; + + return true; +} + +uint64_t Chapter::WriteAtom(IMkvWriter* writer) const { + uint64_t payload_size = + EbmlElementSize(libwebm::kMkvChapterStringUID, id_) + + EbmlElementSize(libwebm::kMkvChapterUID, static_cast(uid_)) + + EbmlElementSize(libwebm::kMkvChapterTimeStart, + static_cast(start_timecode_)) + + EbmlElementSize(libwebm::kMkvChapterTimeEnd, + static_cast(end_timecode_)); + + for (int idx = 0; idx < displays_count_; ++idx) { + const Display& d = displays_[idx]; + payload_size += d.WriteDisplay(NULL); + } + + const uint64_t atom_size = + EbmlMasterElementSize(libwebm::kMkvChapterAtom, payload_size) + + payload_size; + + if (writer == NULL) + return atom_size; + + const int64_t start = writer->Position(); + + if (!WriteEbmlMasterElement(writer, libwebm::kMkvChapterAtom, payload_size)) + return 0; + + if (!WriteEbmlElement(writer, libwebm::kMkvChapterStringUID, id_)) + return 0; + + if (!WriteEbmlElement(writer, libwebm::kMkvChapterUID, + static_cast(uid_))) + return 0; + + if (!WriteEbmlElement(writer, libwebm::kMkvChapterTimeStart, + static_cast(start_timecode_))) + return 0; + + if (!WriteEbmlElement(writer, libwebm::kMkvChapterTimeEnd, + static_cast(end_timecode_))) + return 0; + + for (int idx = 0; idx < displays_count_; ++idx) { + const Display& d = displays_[idx]; + + if (!d.WriteDisplay(writer)) + return 0; + } + + const int64_t stop = writer->Position(); + + if (stop >= start && uint64_t(stop - start) != atom_size) + return 0; + + return atom_size; +} + +void Chapter::Display::Init() { + title_ = NULL; + language_ = NULL; + country_ = NULL; +} + +void Chapter::Display::Clear() { + StrCpy(NULL, &title_); + StrCpy(NULL, &language_); + StrCpy(NULL, &country_); +} + +bool Chapter::Display::set_title(const char* title) { + return StrCpy(title, &title_); +} + +bool Chapter::Display::set_language(const char* language) { + return StrCpy(language, &language_); +} + +bool Chapter::Display::set_country(const char* country) { + return StrCpy(country, &country_); +} + +uint64_t Chapter::Display::WriteDisplay(IMkvWriter* writer) const { + uint64_t payload_size = EbmlElementSize(libwebm::kMkvChapString, title_); + + if (language_) + payload_size += EbmlElementSize(libwebm::kMkvChapLanguage, language_); + + if (country_) + payload_size += EbmlElementSize(libwebm::kMkvChapCountry, country_); + + const uint64_t display_size = + EbmlMasterElementSize(libwebm::kMkvChapterDisplay, payload_size) + + payload_size; + + if (writer == NULL) + return display_size; + + const int64_t start = writer->Position(); + + if (!WriteEbmlMasterElement(writer, libwebm::kMkvChapterDisplay, + payload_size)) + return 0; + + if (!WriteEbmlElement(writer, libwebm::kMkvChapString, title_)) + return 0; + + if (language_) { + if (!WriteEbmlElement(writer, libwebm::kMkvChapLanguage, language_)) + return 0; + } + + if (country_) { + if (!WriteEbmlElement(writer, libwebm::kMkvChapCountry, country_)) + return 0; + } + + const int64_t stop = writer->Position(); + + if (stop >= start && uint64_t(stop - start) != display_size) + return 0; + + return display_size; +} + +/////////////////////////////////////////////////////////////// +// +// Chapters Class + +Chapters::Chapters() : chapters_size_(0), chapters_count_(0), chapters_(NULL) {} + +Chapters::~Chapters() { + while (chapters_count_ > 0) { + Chapter& chapter = chapters_[--chapters_count_]; + chapter.Clear(); + } + + delete[] chapters_; + chapters_ = NULL; +} + +int Chapters::Count() const { return chapters_count_; } + +Chapter* Chapters::AddChapter(unsigned int* seed) { + if (!ExpandChaptersArray()) + return NULL; + + Chapter& chapter = chapters_[chapters_count_++]; + chapter.Init(seed); + + return &chapter; +} + +bool Chapters::Write(IMkvWriter* writer) const { + if (writer == NULL) + return false; + + const uint64_t payload_size = WriteEdition(NULL); // return size only + + if (!WriteEbmlMasterElement(writer, libwebm::kMkvChapters, payload_size)) + return false; + + const int64_t start = writer->Position(); + + if (WriteEdition(writer) == 0) // error + return false; + + const int64_t stop = writer->Position(); + + if (stop >= start && uint64_t(stop - start) != payload_size) + return false; + + return true; +} + +bool Chapters::ExpandChaptersArray() { + if (chapters_size_ > chapters_count_) + return true; // nothing to do yet + + const int size = (chapters_size_ == 0) ? 1 : 2 * chapters_size_; + + Chapter* const chapters = new (std::nothrow) Chapter[size]; // NOLINT + if (chapters == NULL) + return false; + + for (int idx = 0; idx < chapters_count_; ++idx) { + const Chapter& src = chapters_[idx]; + Chapter* const dst = chapters + idx; + src.ShallowCopy(dst); + } + + delete[] chapters_; + + chapters_ = chapters; + chapters_size_ = size; + + return true; +} + +uint64_t Chapters::WriteEdition(IMkvWriter* writer) const { + uint64_t payload_size = 0; + + for (int idx = 0; idx < chapters_count_; ++idx) { + const Chapter& chapter = chapters_[idx]; + payload_size += chapter.WriteAtom(NULL); + } + + const uint64_t edition_size = + EbmlMasterElementSize(libwebm::kMkvEditionEntry, payload_size) + + payload_size; + + if (writer == NULL) // return size only + return edition_size; + + const int64_t start = writer->Position(); + + if (!WriteEbmlMasterElement(writer, libwebm::kMkvEditionEntry, payload_size)) + return 0; // error + + for (int idx = 0; idx < chapters_count_; ++idx) { + const Chapter& chapter = chapters_[idx]; + + const uint64_t chapter_size = chapter.WriteAtom(writer); + if (chapter_size == 0) // error + return 0; + } + + const int64_t stop = writer->Position(); + + if (stop >= start && uint64_t(stop - start) != edition_size) + return 0; + + return edition_size; +} + +// Tag Class + +bool Tag::add_simple_tag(const char* tag_name, const char* tag_string) { + if (!ExpandSimpleTagsArray()) + return false; + + SimpleTag& st = simple_tags_[simple_tags_count_++]; + st.Init(); + + if (!st.set_tag_name(tag_name)) + return false; + + if (!st.set_tag_string(tag_string)) + return false; + + return true; +} + +Tag::Tag() { + simple_tags_ = NULL; + simple_tags_size_ = 0; + simple_tags_count_ = 0; +} + +Tag::~Tag() {} + +void Tag::ShallowCopy(Tag* dst) const { + dst->simple_tags_ = simple_tags_; + dst->simple_tags_size_ = simple_tags_size_; + dst->simple_tags_count_ = simple_tags_count_; +} + +void Tag::Clear() { + while (simple_tags_count_ > 0) { + SimpleTag& st = simple_tags_[--simple_tags_count_]; + st.Clear(); + } + + delete[] simple_tags_; + simple_tags_ = NULL; + + simple_tags_size_ = 0; +} + +bool Tag::ExpandSimpleTagsArray() { + if (simple_tags_size_ > simple_tags_count_) + return true; // nothing to do yet + + const int size = (simple_tags_size_ == 0) ? 1 : 2 * simple_tags_size_; + + SimpleTag* const simple_tags = new (std::nothrow) SimpleTag[size]; // NOLINT + if (simple_tags == NULL) + return false; + + for (int idx = 0; idx < simple_tags_count_; ++idx) { + simple_tags[idx] = simple_tags_[idx]; // shallow copy + } + + delete[] simple_tags_; + + simple_tags_ = simple_tags; + simple_tags_size_ = size; + + return true; +} + +uint64_t Tag::Write(IMkvWriter* writer) const { + uint64_t payload_size = 0; + + for (int idx = 0; idx < simple_tags_count_; ++idx) { + const SimpleTag& st = simple_tags_[idx]; + payload_size += st.Write(NULL); + } + + const uint64_t tag_size = + EbmlMasterElementSize(libwebm::kMkvTag, payload_size) + payload_size; + + if (writer == NULL) + return tag_size; + + const int64_t start = writer->Position(); + + if (!WriteEbmlMasterElement(writer, libwebm::kMkvTag, payload_size)) + return 0; + + for (int idx = 0; idx < simple_tags_count_; ++idx) { + const SimpleTag& st = simple_tags_[idx]; + + if (!st.Write(writer)) + return 0; + } + + const int64_t stop = writer->Position(); + + if (stop >= start && uint64_t(stop - start) != tag_size) + return 0; + + return tag_size; +} + +// Tag::SimpleTag + +void Tag::SimpleTag::Init() { + tag_name_ = NULL; + tag_string_ = NULL; +} + +void Tag::SimpleTag::Clear() { + StrCpy(NULL, &tag_name_); + StrCpy(NULL, &tag_string_); +} + +bool Tag::SimpleTag::set_tag_name(const char* tag_name) { + return StrCpy(tag_name, &tag_name_); +} + +bool Tag::SimpleTag::set_tag_string(const char* tag_string) { + return StrCpy(tag_string, &tag_string_); +} + +uint64_t Tag::SimpleTag::Write(IMkvWriter* writer) const { + uint64_t payload_size = EbmlElementSize(libwebm::kMkvTagName, tag_name_); + + payload_size += EbmlElementSize(libwebm::kMkvTagString, tag_string_); + + const uint64_t simple_tag_size = + EbmlMasterElementSize(libwebm::kMkvSimpleTag, payload_size) + + payload_size; + + if (writer == NULL) + return simple_tag_size; + + const int64_t start = writer->Position(); + + if (!WriteEbmlMasterElement(writer, libwebm::kMkvSimpleTag, payload_size)) + return 0; + + if (!WriteEbmlElement(writer, libwebm::kMkvTagName, tag_name_)) + return 0; + + if (!WriteEbmlElement(writer, libwebm::kMkvTagString, tag_string_)) + return 0; + + const int64_t stop = writer->Position(); + + if (stop >= start && uint64_t(stop - start) != simple_tag_size) + return 0; + + return simple_tag_size; +} + +// Tags Class + +Tags::Tags() : tags_size_(0), tags_count_(0), tags_(NULL) {} + +Tags::~Tags() { + while (tags_count_ > 0) { + Tag& tag = tags_[--tags_count_]; + tag.Clear(); + } + + delete[] tags_; + tags_ = NULL; +} + +int Tags::Count() const { return tags_count_; } + +Tag* Tags::AddTag() { + if (!ExpandTagsArray()) + return NULL; + + Tag& tag = tags_[tags_count_++]; + + return &tag; +} + +bool Tags::Write(IMkvWriter* writer) const { + if (writer == NULL) + return false; + + uint64_t payload_size = 0; + + for (int idx = 0; idx < tags_count_; ++idx) { + const Tag& tag = tags_[idx]; + payload_size += tag.Write(NULL); + } + + if (!WriteEbmlMasterElement(writer, libwebm::kMkvTags, payload_size)) + return false; + + const int64_t start = writer->Position(); + + for (int idx = 0; idx < tags_count_; ++idx) { + const Tag& tag = tags_[idx]; + + const uint64_t tag_size = tag.Write(writer); + if (tag_size == 0) // error + return 0; + } + + const int64_t stop = writer->Position(); + + if (stop >= start && uint64_t(stop - start) != payload_size) + return false; + + return true; +} + +bool Tags::ExpandTagsArray() { + if (tags_size_ > tags_count_) + return true; // nothing to do yet + + const int size = (tags_size_ == 0) ? 1 : 2 * tags_size_; + + Tag* const tags = new (std::nothrow) Tag[size]; // NOLINT + if (tags == NULL) + return false; + + for (int idx = 0; idx < tags_count_; ++idx) { + const Tag& src = tags_[idx]; + Tag* const dst = tags + idx; + src.ShallowCopy(dst); + } + + delete[] tags_; + + tags_ = tags; + tags_size_ = size; + + return true; +} + +/////////////////////////////////////////////////////////////// +// +// Cluster class + +Cluster::Cluster(uint64_t timecode, int64_t cues_pos, uint64_t timecode_scale, + bool write_last_frame_with_duration, bool fixed_size_timecode) + : blocks_added_(0), + finalized_(false), + fixed_size_timecode_(fixed_size_timecode), + header_written_(false), + payload_size_(0), + position_for_cues_(cues_pos), + size_position_(-1), + timecode_(timecode), + timecode_scale_(timecode_scale), + write_last_frame_with_duration_(write_last_frame_with_duration), + writer_(NULL) {} + +Cluster::~Cluster() { + // Delete any stored frames that are left behind. This will happen if the + // Cluster was not Finalized for whatever reason. + while (!stored_frames_.empty()) { + while (!stored_frames_.begin()->second.empty()) { + delete stored_frames_.begin()->second.front(); + stored_frames_.begin()->second.pop_front(); + } + stored_frames_.erase(stored_frames_.begin()->first); + } +} + +bool Cluster::Init(IMkvWriter* ptr_writer) { + if (!ptr_writer) { + return false; + } + writer_ = ptr_writer; + return true; +} + +bool Cluster::AddFrame(const Frame* const frame) { + return QueueOrWriteFrame(frame); +} + +bool Cluster::AddFrame(const uint8_t* data, uint64_t length, + uint64_t track_number, uint64_t abs_timecode, + bool is_key) { + Frame frame; + if (!frame.Init(data, length)) + return false; + frame.set_track_number(track_number); + frame.set_timestamp(abs_timecode); + frame.set_is_key(is_key); + return QueueOrWriteFrame(&frame); +} + +bool Cluster::AddFrameWithAdditional(const uint8_t* data, uint64_t length, + const uint8_t* additional, + uint64_t additional_length, + uint64_t add_id, uint64_t track_number, + uint64_t abs_timecode, bool is_key) { + if (!additional || additional_length == 0) { + return false; + } + Frame frame; + if (!frame.Init(data, length) || + !frame.AddAdditionalData(additional, additional_length, add_id)) { + return false; + } + frame.set_track_number(track_number); + frame.set_timestamp(abs_timecode); + frame.set_is_key(is_key); + return QueueOrWriteFrame(&frame); +} + +bool Cluster::AddFrameWithDiscardPadding(const uint8_t* data, uint64_t length, + int64_t discard_padding, + uint64_t track_number, + uint64_t abs_timecode, bool is_key) { + Frame frame; + if (!frame.Init(data, length)) + return false; + frame.set_discard_padding(discard_padding); + frame.set_track_number(track_number); + frame.set_timestamp(abs_timecode); + frame.set_is_key(is_key); + return QueueOrWriteFrame(&frame); +} + +bool Cluster::AddMetadata(const uint8_t* data, uint64_t length, + uint64_t track_number, uint64_t abs_timecode, + uint64_t duration_timecode) { + Frame frame; + if (!frame.Init(data, length)) + return false; + frame.set_track_number(track_number); + frame.set_timestamp(abs_timecode); + frame.set_duration(duration_timecode); + frame.set_is_key(true); // All metadata blocks are keyframes. + return QueueOrWriteFrame(&frame); +} + +void Cluster::AddPayloadSize(uint64_t size) { payload_size_ += size; } + +bool Cluster::Finalize() { + return !write_last_frame_with_duration_ && Finalize(false, 0); +} + +bool Cluster::Finalize(bool set_last_frame_duration, uint64_t duration) { + if (!writer_ || finalized_) + return false; + + if (write_last_frame_with_duration_) { + // Write out held back Frames. This essentially performs a k-way merge + // across all tracks in the increasing order of timestamps. + while (!stored_frames_.empty()) { + Frame* frame = stored_frames_.begin()->second.front(); + + // Get the next frame to write (frame with least timestamp across all + // tracks). + for (FrameMapIterator frames_iterator = ++stored_frames_.begin(); + frames_iterator != stored_frames_.end(); ++frames_iterator) { + if (frames_iterator->second.front()->timestamp() < frame->timestamp()) { + frame = frames_iterator->second.front(); + } + } + + // Set the duration if it's the last frame for the track. + if (set_last_frame_duration && + stored_frames_[frame->track_number()].size() == 1 && + !frame->duration_set()) { + frame->set_duration(duration - frame->timestamp()); + if (!frame->is_key() && !frame->reference_block_timestamp_set()) { + frame->set_reference_block_timestamp( + last_block_timestamp_[frame->track_number()]); + } + } + + // Write the frame and remove it from |stored_frames_|. + const bool wrote_frame = DoWriteFrame(frame); + stored_frames_[frame->track_number()].pop_front(); + if (stored_frames_[frame->track_number()].empty()) { + stored_frames_.erase(frame->track_number()); + } + delete frame; + if (!wrote_frame) + return false; + } + } + + if (size_position_ == -1) + return false; + + if (writer_->Seekable()) { + const int64_t pos = writer_->Position(); + + if (writer_->Position(size_position_)) + return false; + + if (WriteUIntSize(writer_, payload_size(), 8)) + return false; + + if (writer_->Position(pos)) + return false; + } + + finalized_ = true; + + return true; +} + +uint64_t Cluster::Size() const { + const uint64_t element_size = + EbmlMasterElementSize(static_cast(libwebm::kMkvCluster), + uint64_t{0xFFFFFFFFFFFFFFFFU}) + + payload_size_; + return element_size; +} + +bool Cluster::PreWriteBlock() { + if (finalized_) + return false; + + if (!header_written_) { + if (!WriteClusterHeader()) + return false; + } + + return true; +} + +void Cluster::PostWriteBlock(uint64_t element_size) { + AddPayloadSize(element_size); + ++blocks_added_; +} + +int64_t Cluster::GetRelativeTimecode(int64_t abs_timecode) const { + const int64_t cluster_timecode = this->Cluster::timecode(); + const int64_t rel_timecode = + static_cast(abs_timecode) - cluster_timecode; + + if (rel_timecode < 0 || rel_timecode > kMaxBlockTimecode) + return -1; + + return rel_timecode; +} + +bool Cluster::DoWriteFrame(const Frame* const frame) { + if (!frame || !frame->IsValid()) + return false; + + if (!PreWriteBlock()) + return false; + + const uint64_t element_size = WriteFrame(writer_, frame, this); + if (element_size == 0) + return false; + + PostWriteBlock(element_size); + last_block_timestamp_[frame->track_number()] = frame->timestamp(); + return true; +} + +bool Cluster::QueueOrWriteFrame(const Frame* const frame) { + if (!frame || !frame->IsValid()) + return false; + + // If |write_last_frame_with_duration_| is not set, then write the frame right + // away. + if (!write_last_frame_with_duration_) { + return DoWriteFrame(frame); + } + + // Queue the current frame. + uint64_t track_number = frame->track_number(); + Frame* const frame_to_store = new Frame(); + frame_to_store->CopyFrom(*frame); + stored_frames_[track_number].push_back(frame_to_store); + + // Iterate through all queued frames in the current track except the last one + // and write it if it is okay to do so (i.e.) no other track has an held back + // frame with timestamp <= the timestamp of the frame in question. + std::vector::iterator> frames_to_erase; + for (std::list::iterator + current_track_iterator = stored_frames_[track_number].begin(), + end = --stored_frames_[track_number].end(); + current_track_iterator != end; ++current_track_iterator) { + const Frame* const frame_to_write = *current_track_iterator; + bool okay_to_write = true; + for (FrameMapIterator track_iterator = stored_frames_.begin(); + track_iterator != stored_frames_.end(); ++track_iterator) { + if (track_iterator->first == track_number) { + continue; + } + if (track_iterator->second.front()->timestamp() < + frame_to_write->timestamp()) { + okay_to_write = false; + break; + } + } + if (okay_to_write) { + const bool wrote_frame = DoWriteFrame(frame_to_write); + delete frame_to_write; + if (!wrote_frame) + return false; + frames_to_erase.push_back(current_track_iterator); + } else { + break; + } + } + for (std::vector::iterator>::iterator iterator = + frames_to_erase.begin(); + iterator != frames_to_erase.end(); ++iterator) { + stored_frames_[track_number].erase(*iterator); + } + return true; +} + +bool Cluster::WriteClusterHeader() { + if (finalized_) + return false; + + if (WriteID(writer_, libwebm::kMkvCluster)) + return false; + + // Save for later. + size_position_ = writer_->Position(); + + // Write "unknown" (EBML coded -1) as cluster size value. We need to write 8 + // bytes because we do not know how big our cluster will be. + if (SerializeInt(writer_, kEbmlUnknownValue, 8)) + return false; + + if (!WriteEbmlElement(writer_, libwebm::kMkvTimecode, timecode(), + fixed_size_timecode_ ? 8 : 0)) { + return false; + } + AddPayloadSize(EbmlElementSize(libwebm::kMkvTimecode, timecode(), + fixed_size_timecode_ ? 8 : 0)); + header_written_ = true; + + return true; +} + +/////////////////////////////////////////////////////////////// +// +// SeekHead Class + +SeekHead::SeekHead() : start_pos_(0ULL) { + for (int32_t i = 0; i < kSeekEntryCount; ++i) { + seek_entry_id_[i] = 0; + seek_entry_pos_[i] = 0; + } +} + +SeekHead::~SeekHead() {} + +bool SeekHead::Finalize(IMkvWriter* writer) const { + if (writer->Seekable()) { + if (start_pos_ == -1) + return false; + + uint64_t payload_size = 0; + uint64_t entry_size[kSeekEntryCount]; + + for (int32_t i = 0; i < kSeekEntryCount; ++i) { + if (seek_entry_id_[i] != 0) { + entry_size[i] = EbmlElementSize(libwebm::kMkvSeekID, + static_cast(seek_entry_id_[i])); + entry_size[i] += EbmlElementSize( + libwebm::kMkvSeekPosition, static_cast(seek_entry_pos_[i])); + + payload_size += + EbmlMasterElementSize(libwebm::kMkvSeek, entry_size[i]) + + entry_size[i]; + } + } + + // No SeekHead elements + if (payload_size == 0) + return true; + + const int64_t pos = writer->Position(); + if (writer->Position(start_pos_)) + return false; + + if (!WriteEbmlMasterElement(writer, libwebm::kMkvSeekHead, payload_size)) + return false; + + for (int32_t i = 0; i < kSeekEntryCount; ++i) { + if (seek_entry_id_[i] != 0) { + if (!WriteEbmlMasterElement(writer, libwebm::kMkvSeek, entry_size[i])) + return false; + + if (!WriteEbmlElement(writer, libwebm::kMkvSeekID, + static_cast(seek_entry_id_[i]))) + return false; + + if (!WriteEbmlElement(writer, libwebm::kMkvSeekPosition, + static_cast(seek_entry_pos_[i]))) + return false; + } + } + + const uint64_t total_entry_size = kSeekEntryCount * MaxEntrySize(); + const uint64_t total_size = + EbmlMasterElementSize(libwebm::kMkvSeekHead, total_entry_size) + + total_entry_size; + const int64_t size_left = total_size - (writer->Position() - start_pos_); + + const uint64_t bytes_written = WriteVoidElement(writer, size_left); + if (!bytes_written) + return false; + + if (writer->Position(pos)) + return false; + } + + return true; +} + +bool SeekHead::Write(IMkvWriter* writer) { + const uint64_t entry_size = kSeekEntryCount * MaxEntrySize(); + const uint64_t size = + EbmlMasterElementSize(libwebm::kMkvSeekHead, entry_size); + + start_pos_ = writer->Position(); + + const uint64_t bytes_written = WriteVoidElement(writer, size + entry_size); + if (!bytes_written) + return false; + + return true; +} + +bool SeekHead::AddSeekEntry(uint32_t id, uint64_t pos) { + for (int32_t i = 0; i < kSeekEntryCount; ++i) { + if (seek_entry_id_[i] == 0) { + seek_entry_id_[i] = id; + seek_entry_pos_[i] = pos; + return true; + } + } + return false; +} + +uint32_t SeekHead::GetId(int index) const { + if (index < 0 || index >= kSeekEntryCount) + return UINT_MAX; + return seek_entry_id_[index]; +} + +uint64_t SeekHead::GetPosition(int index) const { + if (index < 0 || index >= kSeekEntryCount) + return ULLONG_MAX; + return seek_entry_pos_[index]; +} + +bool SeekHead::SetSeekEntry(int index, uint32_t id, uint64_t position) { + if (index < 0 || index >= kSeekEntryCount) + return false; + seek_entry_id_[index] = id; + seek_entry_pos_[index] = position; + return true; +} + +uint64_t SeekHead::MaxEntrySize() const { + const uint64_t max_entry_payload_size = + EbmlElementSize(libwebm::kMkvSeekID, + static_cast(UINT64_C(0xffffffff))) + + EbmlElementSize(libwebm::kMkvSeekPosition, + static_cast(UINT64_C(0xffffffffffffffff))); + const uint64_t max_entry_size = + EbmlMasterElementSize(libwebm::kMkvSeek, max_entry_payload_size) + + max_entry_payload_size; + + return max_entry_size; +} + +/////////////////////////////////////////////////////////////// +// +// SegmentInfo Class + +SegmentInfo::SegmentInfo() + : duration_(-1.0), + muxing_app_(NULL), + timecode_scale_(1000000ULL), + writing_app_(NULL), + date_utc_(LLONG_MIN), + duration_pos_(-1) {} + +SegmentInfo::~SegmentInfo() { + delete[] muxing_app_; + delete[] writing_app_; +} + +bool SegmentInfo::Init() { + int32_t major; + int32_t minor; + int32_t build; + int32_t revision; + GetVersion(&major, &minor, &build, &revision); + char temp[256]; +#ifdef _MSC_VER + sprintf_s(temp, sizeof(temp) / sizeof(temp[0]), "libwebm-%d.%d.%d.%d", major, + minor, build, revision); +#else + snprintf(temp, sizeof(temp) / sizeof(temp[0]), "libwebm-%d.%d.%d.%d", major, + minor, build, revision); +#endif + + const size_t app_len = strlen(temp) + 1; + + delete[] muxing_app_; + + muxing_app_ = new (std::nothrow) char[app_len]; // NOLINT + if (!muxing_app_) + return false; + +#ifdef _MSC_VER + strcpy_s(muxing_app_, app_len, temp); +#else + strcpy(muxing_app_, temp); +#endif + + set_writing_app(temp); + if (!writing_app_) + return false; + return true; +} + +bool SegmentInfo::Finalize(IMkvWriter* writer) const { + if (!writer) + return false; + + if (duration_ > 0.0) { + if (writer->Seekable()) { + if (duration_pos_ == -1) + return false; + + const int64_t pos = writer->Position(); + + if (writer->Position(duration_pos_)) + return false; + + if (!WriteEbmlElement(writer, libwebm::kMkvDuration, + static_cast(duration_))) + return false; + + if (writer->Position(pos)) + return false; + } + } + + return true; +} + +bool SegmentInfo::Write(IMkvWriter* writer) { + if (!writer || !muxing_app_ || !writing_app_) + return false; + + uint64_t size = EbmlElementSize(libwebm::kMkvTimecodeScale, + static_cast(timecode_scale_)); + if (duration_ > 0.0) + size += + EbmlElementSize(libwebm::kMkvDuration, static_cast(duration_)); + if (date_utc_ != LLONG_MIN) + size += EbmlDateElementSize(libwebm::kMkvDateUTC); + size += EbmlElementSize(libwebm::kMkvMuxingApp, muxing_app_); + size += EbmlElementSize(libwebm::kMkvWritingApp, writing_app_); + + if (!WriteEbmlMasterElement(writer, libwebm::kMkvInfo, size)) + return false; + + const int64_t payload_position = writer->Position(); + if (payload_position < 0) + return false; + + if (!WriteEbmlElement(writer, libwebm::kMkvTimecodeScale, + static_cast(timecode_scale_))) + return false; + + if (duration_ > 0.0) { + // Save for later + duration_pos_ = writer->Position(); + + if (!WriteEbmlElement(writer, libwebm::kMkvDuration, + static_cast(duration_))) + return false; + } + + if (date_utc_ != LLONG_MIN) + WriteEbmlDateElement(writer, libwebm::kMkvDateUTC, date_utc_); + + if (!WriteEbmlElement(writer, libwebm::kMkvMuxingApp, muxing_app_)) + return false; + if (!WriteEbmlElement(writer, libwebm::kMkvWritingApp, writing_app_)) + return false; + + const int64_t stop_position = writer->Position(); + if (stop_position < 0 || + stop_position - payload_position != static_cast(size)) + return false; + + return true; +} + +void SegmentInfo::set_muxing_app(const char* app) { + if (app) { + const size_t length = strlen(app) + 1; + char* temp_str = new (std::nothrow) char[length]; // NOLINT + if (!temp_str) + return; + +#ifdef _MSC_VER + strcpy_s(temp_str, length, app); +#else + strcpy(temp_str, app); +#endif + + delete[] muxing_app_; + muxing_app_ = temp_str; + } +} + +void SegmentInfo::set_writing_app(const char* app) { + if (app) { + const size_t length = strlen(app) + 1; + char* temp_str = new (std::nothrow) char[length]; // NOLINT + if (!temp_str) + return; + +#ifdef _MSC_VER + strcpy_s(temp_str, length, app); +#else + strcpy(temp_str, app); +#endif + + delete[] writing_app_; + writing_app_ = temp_str; + } +} + +/////////////////////////////////////////////////////////////// +// +// Segment Class + +Segment::Segment() + : chunk_count_(0), + chunk_name_(NULL), + chunk_writer_cluster_(NULL), + chunk_writer_cues_(NULL), + chunk_writer_header_(NULL), + chunking_(false), + chunking_base_name_(NULL), + cluster_list_(NULL), + cluster_list_capacity_(0), + cluster_list_size_(0), + cues_position_(kAfterClusters), + cues_track_(0), + force_new_cluster_(false), + frames_(NULL), + frames_capacity_(0), + frames_size_(0), + has_video_(false), + header_written_(false), + last_block_duration_(0), + last_timestamp_(0), + max_cluster_duration_(kDefaultMaxClusterDuration), + max_cluster_size_(0), + mode_(kFile), + new_cuepoint_(false), + output_cues_(true), + accurate_cluster_duration_(false), + fixed_size_cluster_timecode_(false), + estimate_file_duration_(false), + ebml_header_size_(0), + payload_pos_(0), + size_position_(0), + doc_type_version_(kDefaultDocTypeVersion), + doc_type_version_written_(0), + duration_(0.0), + writer_cluster_(NULL), + writer_cues_(NULL), + writer_header_(NULL) { + const time_t curr_time = time(NULL); + seed_ = static_cast(curr_time); +#ifdef _WIN32 + srand(seed_); +#endif +} + +Segment::~Segment() { + if (cluster_list_) { + for (int32_t i = 0; i < cluster_list_size_; ++i) { + Cluster* const cluster = cluster_list_[i]; + delete cluster; + } + delete[] cluster_list_; + } + + if (frames_) { + for (int32_t i = 0; i < frames_size_; ++i) { + Frame* const frame = frames_[i]; + delete frame; + } + delete[] frames_; + } + + delete[] chunk_name_; + delete[] chunking_base_name_; + + if (chunk_writer_cluster_) { + chunk_writer_cluster_->Close(); + delete chunk_writer_cluster_; + } + if (chunk_writer_cues_) { + chunk_writer_cues_->Close(); + delete chunk_writer_cues_; + } + if (chunk_writer_header_) { + chunk_writer_header_->Close(); + delete chunk_writer_header_; + } +} + +void Segment::MoveCuesBeforeClustersHelper(uint64_t diff, int32_t index, + uint64_t* cues_size) { + CuePoint* const cue_point = cues_.GetCueByIndex(index); + if (cue_point == NULL) + return; + const uint64_t old_cue_point_size = cue_point->Size(); + const uint64_t cluster_pos = cue_point->cluster_pos() + diff; + cue_point->set_cluster_pos(cluster_pos); // update the new cluster position + // New size of the cue is computed as follows + // Let a = current sum of size of all CuePoints + // Let b = Increase in Cue Point's size due to this iteration + // Let c = Increase in size of Cues Element's length due to this iteration + // (This is computed as CodedSize(a + b) - CodedSize(a)) + // Let d = b + c. Now d is the |diff| passed to the next recursive call. + // Let e = a + b. Now e is the |cues_size| passed to the next recursive + // call. + const uint64_t cue_point_size_diff = cue_point->Size() - old_cue_point_size; + const uint64_t cue_size_diff = + GetCodedUIntSize(*cues_size + cue_point_size_diff) - + GetCodedUIntSize(*cues_size); + *cues_size += cue_point_size_diff; + diff = cue_size_diff + cue_point_size_diff; + if (diff > 0) { + for (int32_t i = 0; i < cues_.cue_entries_size(); ++i) { + MoveCuesBeforeClustersHelper(diff, i, cues_size); + } + } +} + +void Segment::MoveCuesBeforeClusters() { + const uint64_t current_cue_size = cues_.Size(); + uint64_t cue_size = 0; + for (int32_t i = 0; i < cues_.cue_entries_size(); ++i) + cue_size += cues_.GetCueByIndex(i)->Size(); + for (int32_t i = 0; i < cues_.cue_entries_size(); ++i) + MoveCuesBeforeClustersHelper(current_cue_size, i, &cue_size); + + // Adjust the Seek Entry to reflect the change in position + // of Cluster and Cues + int32_t cluster_index = 0; + int32_t cues_index = 0; + for (int32_t i = 0; i < SeekHead::kSeekEntryCount; ++i) { + if (seek_head_.GetId(i) == libwebm::kMkvCluster) + cluster_index = i; + if (seek_head_.GetId(i) == libwebm::kMkvCues) + cues_index = i; + } + seek_head_.SetSeekEntry(cues_index, libwebm::kMkvCues, + seek_head_.GetPosition(cluster_index)); + seek_head_.SetSeekEntry(cluster_index, libwebm::kMkvCluster, + cues_.Size() + seek_head_.GetPosition(cues_index)); +} + +bool Segment::Init(IMkvWriter* ptr_writer) { + if (!ptr_writer) { + return false; + } + writer_cluster_ = ptr_writer; + writer_cues_ = ptr_writer; + writer_header_ = ptr_writer; + memset(&track_frames_written_, 0, + sizeof(track_frames_written_[0]) * kMaxTrackNumber); + memset(&last_track_timestamp_, 0, + sizeof(last_track_timestamp_[0]) * kMaxTrackNumber); + return segment_info_.Init(); +} + +bool Segment::CopyAndMoveCuesBeforeClusters(mkvparser::IMkvReader* reader, + IMkvWriter* writer) { + if (!writer->Seekable() || chunking_) + return false; + const int64_t cluster_offset = + cluster_list_[0]->size_position() - GetUIntSize(libwebm::kMkvCluster); + + // Copy the headers. + if (!ChunkedCopy(reader, writer, 0, cluster_offset)) + return false; + + // Recompute cue positions and seek entries. + MoveCuesBeforeClusters(); + + // Write cues and seek entries. + // TODO(vigneshv): As of now, it's safe to call seek_head_.Finalize() for the + // second time with a different writer object. But the name Finalize() doesn't + // indicate something we want to call more than once. So consider renaming it + // to write() or some such. + if (!cues_.Write(writer) || !seek_head_.Finalize(writer)) + return false; + + // Copy the Clusters. + if (!ChunkedCopy(reader, writer, cluster_offset, + cluster_end_offset_ - cluster_offset)) + return false; + + // Update the Segment size in case the Cues size has changed. + const int64_t pos = writer->Position(); + const int64_t segment_size = writer->Position() - payload_pos_; + if (writer->Position(size_position_) || + WriteUIntSize(writer, segment_size, 8) || writer->Position(pos)) + return false; + return true; +} + +bool Segment::Finalize() { + if (WriteFramesAll() < 0) + return false; + + // In kLive mode, call Cluster::Finalize only if |accurate_cluster_duration_| + // is set. In all other modes, always call Cluster::Finalize. + if ((mode_ == kLive ? accurate_cluster_duration_ : true) && + cluster_list_size_ > 0) { + // Update last cluster's size + Cluster* const old_cluster = cluster_list_[cluster_list_size_ - 1]; + + // For the last frame of the last Cluster, we don't write it as a BlockGroup + // with Duration unless the frame itself has duration set explicitly. + if (!old_cluster || !old_cluster->Finalize(false, 0)) + return false; + } + + if (mode_ == kFile) { + if (chunking_ && chunk_writer_cluster_) { + chunk_writer_cluster_->Close(); + chunk_count_++; + } + + double duration = + (static_cast(last_timestamp_) + last_block_duration_) / + segment_info_.timecode_scale(); + if (duration_ > 0.0) { + duration = duration_; + } else { + if (last_block_duration_ == 0 && estimate_file_duration_) { + const int num_tracks = static_cast(tracks_.track_entries_size()); + for (int i = 0; i < num_tracks; ++i) { + if (track_frames_written_[i] < 2) + continue; + + // Estimate the duration for the last block of a Track. + const double nano_per_frame = + static_cast(last_track_timestamp_[i]) / + (track_frames_written_[i] - 1); + const double track_duration = + (last_track_timestamp_[i] + nano_per_frame) / + segment_info_.timecode_scale(); + if (track_duration > duration) + duration = track_duration; + } + } + } + segment_info_.set_duration(duration); + if (!segment_info_.Finalize(writer_header_)) + return false; + + if (output_cues_) + if (!seek_head_.AddSeekEntry(libwebm::kMkvCues, MaxOffset())) + return false; + + if (chunking_) { + if (!chunk_writer_cues_) + return false; + + char* name = NULL; + if (!UpdateChunkName("cues", &name)) + return false; + + const bool cues_open = chunk_writer_cues_->Open(name); + delete[] name; + if (!cues_open) + return false; + } + + cluster_end_offset_ = writer_cluster_->Position(); + + // Write the seek headers and cues + if (output_cues_) + if (!cues_.Write(writer_cues_)) + return false; + + if (!seek_head_.Finalize(writer_header_)) + return false; + + if (writer_header_->Seekable()) { + if (size_position_ == -1) + return false; + + const int64_t segment_size = MaxOffset(); + if (segment_size < 1) + return false; + + const int64_t pos = writer_header_->Position(); + UpdateDocTypeVersion(); + if (doc_type_version_ != doc_type_version_written_) { + if (writer_header_->Position(0)) + return false; + + const char* const doc_type = + DocTypeIsWebm() ? kDocTypeWebm : kDocTypeMatroska; + if (!WriteEbmlHeader(writer_header_, doc_type_version_, doc_type)) + return false; + if (writer_header_->Position() != ebml_header_size_) + return false; + + doc_type_version_written_ = doc_type_version_; + } + + if (writer_header_->Position(size_position_)) + return false; + + if (WriteUIntSize(writer_header_, segment_size, 8)) + return false; + + if (writer_header_->Position(pos)) + return false; + } + + if (chunking_) { + // Do not close any writers until the segment size has been written, + // otherwise the size may be off. + if (!chunk_writer_cues_ || !chunk_writer_header_) + return false; + + chunk_writer_cues_->Close(); + chunk_writer_header_->Close(); + } + } + + return true; +} + +Track* Segment::AddTrack(int32_t number) { + Track* const track = new (std::nothrow) Track(&seed_); // NOLINT + + if (!track) + return NULL; + + if (!tracks_.AddTrack(track, number)) { + delete track; + return NULL; + } + + return track; +} + +Chapter* Segment::AddChapter() { return chapters_.AddChapter(&seed_); } + +Tag* Segment::AddTag() { return tags_.AddTag(); } + +uint64_t Segment::AddVideoTrack(int32_t width, int32_t height, int32_t number) { + VideoTrack* const track = new (std::nothrow) VideoTrack(&seed_); // NOLINT + if (!track) + return 0; + + track->set_type(Tracks::kVideo); + track->set_codec_id(Tracks::kVp8CodecId); + track->set_width(width); + track->set_height(height); + + if (!tracks_.AddTrack(track, number)) { + delete track; + return 0; + } + has_video_ = true; + + return track->number(); +} + +bool Segment::AddCuePoint(uint64_t timestamp, uint64_t track) { + if (cluster_list_size_ < 1) + return false; + + const Cluster* const cluster = cluster_list_[cluster_list_size_ - 1]; + if (!cluster) + return false; + + CuePoint* const cue = new (std::nothrow) CuePoint(); // NOLINT + if (!cue) + return false; + + cue->set_time(timestamp / segment_info_.timecode_scale()); + cue->set_block_number(cluster->blocks_added()); + cue->set_cluster_pos(cluster->position_for_cues()); + cue->set_track(track); + if (!cues_.AddCue(cue)) { + delete cue; + return false; + } + + new_cuepoint_ = false; + return true; +} + +uint64_t Segment::AddAudioTrack(int32_t sample_rate, int32_t channels, + int32_t number) { + AudioTrack* const track = new (std::nothrow) AudioTrack(&seed_); // NOLINT + if (!track) + return 0; + + track->set_type(Tracks::kAudio); + track->set_codec_id(Tracks::kVorbisCodecId); + track->set_sample_rate(sample_rate); + track->set_channels(channels); + + if (!tracks_.AddTrack(track, number)) { + delete track; + return 0; + } + + return track->number(); +} + +bool Segment::AddFrame(const uint8_t* data, uint64_t length, + uint64_t track_number, uint64_t timestamp, bool is_key) { + if (!data) + return false; + + Frame frame; + if (!frame.Init(data, length)) + return false; + frame.set_track_number(track_number); + frame.set_timestamp(timestamp); + frame.set_is_key(is_key); + return AddGenericFrame(&frame); +} + +bool Segment::AddFrameWithAdditional(const uint8_t* data, uint64_t length, + const uint8_t* additional, + uint64_t additional_length, + uint64_t add_id, uint64_t track_number, + uint64_t timestamp, bool is_key) { + if (!data || !additional) + return false; + + Frame frame; + if (!frame.Init(data, length) || + !frame.AddAdditionalData(additional, additional_length, add_id)) { + return false; + } + frame.set_track_number(track_number); + frame.set_timestamp(timestamp); + frame.set_is_key(is_key); + return AddGenericFrame(&frame); +} + +bool Segment::AddFrameWithDiscardPadding(const uint8_t* data, uint64_t length, + int64_t discard_padding, + uint64_t track_number, + uint64_t timestamp, bool is_key) { + if (!data) + return false; + + Frame frame; + if (!frame.Init(data, length)) + return false; + frame.set_discard_padding(discard_padding); + frame.set_track_number(track_number); + frame.set_timestamp(timestamp); + frame.set_is_key(is_key); + return AddGenericFrame(&frame); +} + +bool Segment::AddMetadata(const uint8_t* data, uint64_t length, + uint64_t track_number, uint64_t timestamp_ns, + uint64_t duration_ns) { + if (!data) + return false; + + Frame frame; + if (!frame.Init(data, length)) + return false; + frame.set_track_number(track_number); + frame.set_timestamp(timestamp_ns); + frame.set_duration(duration_ns); + frame.set_is_key(true); // All metadata blocks are keyframes. + return AddGenericFrame(&frame); +} + +bool Segment::AddGenericFrame(const Frame* frame) { + if (!frame) + return false; + + if (!CheckHeaderInfo()) + return false; + + // Check for non-monotonically increasing timestamps. + if (frame->timestamp() < last_timestamp_) + return false; + + // Check if the track number is valid. + if (!tracks_.GetTrackByNumber(frame->track_number())) + return false; + + if (frame->discard_padding() != 0) + doc_type_version_ = 4; + + if (cluster_list_size_ > 0) { + const uint64_t timecode_scale = segment_info_.timecode_scale(); + const uint64_t frame_timecode = frame->timestamp() / timecode_scale; + + const Cluster* const last_cluster = cluster_list_[cluster_list_size_ - 1]; + const uint64_t last_cluster_timecode = last_cluster->timecode(); + + const uint64_t rel_timecode = frame_timecode - last_cluster_timecode; + if (rel_timecode > kMaxBlockTimecode) { + force_new_cluster_ = true; + } + } + + // If the segment has a video track hold onto audio frames to make sure the + // audio that is associated with the start time of a video key-frame is + // muxed into the same cluster. + if (has_video_ && tracks_.TrackIsAudio(frame->track_number()) && + !force_new_cluster_) { + Frame* const new_frame = new (std::nothrow) Frame(); + if (!new_frame || !new_frame->CopyFrom(*frame)) { + delete new_frame; + return false; + } + if (!QueueFrame(new_frame)) { + delete new_frame; + return false; + } + track_frames_written_[frame->track_number() - 1]++; + return true; + } + + if (!DoNewClusterProcessing(frame->track_number(), frame->timestamp(), + frame->is_key())) { + return false; + } + + if (cluster_list_size_ < 1) + return false; + + Cluster* const cluster = cluster_list_[cluster_list_size_ - 1]; + if (!cluster) + return false; + + // If the Frame is not a SimpleBlock, then set the reference_block_timestamp + // if it is not set already. + bool frame_created = false; + if (!frame->CanBeSimpleBlock() && !frame->is_key() && + !frame->reference_block_timestamp_set()) { + Frame* const new_frame = new (std::nothrow) Frame(); + if (!new_frame || !new_frame->CopyFrom(*frame)) { + delete new_frame; + return false; + } + new_frame->set_reference_block_timestamp( + last_track_timestamp_[frame->track_number() - 1]); + frame = new_frame; + frame_created = true; + } + + if (!cluster->AddFrame(frame)) + return false; + + if (new_cuepoint_ && cues_track_ == frame->track_number()) { + if (!AddCuePoint(frame->timestamp(), cues_track_)) + return false; + } + + last_timestamp_ = frame->timestamp(); + last_track_timestamp_[frame->track_number() - 1] = frame->timestamp(); + last_block_duration_ = frame->duration(); + track_frames_written_[frame->track_number() - 1]++; + + if (frame_created) + delete frame; + return true; +} + +void Segment::OutputCues(bool output_cues) { output_cues_ = output_cues; } + +void Segment::AccurateClusterDuration(bool accurate_cluster_duration) { + accurate_cluster_duration_ = accurate_cluster_duration; +} + +void Segment::UseFixedSizeClusterTimecode(bool fixed_size_cluster_timecode) { + fixed_size_cluster_timecode_ = fixed_size_cluster_timecode; +} + +bool Segment::SetChunking(bool chunking, const char* filename) { + if (chunk_count_ > 0) + return false; + + if (chunking) { + if (!filename) + return false; + + // Check if we are being set to what is already set. + if (chunking_ && !strcmp(filename, chunking_base_name_)) + return true; + + const size_t name_length = strlen(filename) + 1; + char* const temp = new (std::nothrow) char[name_length]; // NOLINT + if (!temp) + return false; + +#ifdef _MSC_VER + strcpy_s(temp, name_length, filename); +#else + strcpy(temp, filename); +#endif + + delete[] chunking_base_name_; + chunking_base_name_ = temp; + + if (!UpdateChunkName("chk", &chunk_name_)) + return false; + + if (!chunk_writer_cluster_) { + chunk_writer_cluster_ = new (std::nothrow) MkvWriter(); // NOLINT + if (!chunk_writer_cluster_) + return false; + } + + if (!chunk_writer_cues_) { + chunk_writer_cues_ = new (std::nothrow) MkvWriter(); // NOLINT + if (!chunk_writer_cues_) + return false; + } + + if (!chunk_writer_header_) { + chunk_writer_header_ = new (std::nothrow) MkvWriter(); // NOLINT + if (!chunk_writer_header_) + return false; + } + + if (!chunk_writer_cluster_->Open(chunk_name_)) + return false; + + const size_t header_length = strlen(filename) + strlen(".hdr") + 1; + char* const header = new (std::nothrow) char[header_length]; // NOLINT + if (!header) + return false; + +#ifdef _MSC_VER + strcpy_s(header, header_length - strlen(".hdr"), chunking_base_name_); + strcat_s(header, header_length, ".hdr"); +#else + strcpy(header, chunking_base_name_); + strcat(header, ".hdr"); +#endif + if (!chunk_writer_header_->Open(header)) { + delete[] header; + return false; + } + + writer_cluster_ = chunk_writer_cluster_; + writer_cues_ = chunk_writer_cues_; + writer_header_ = chunk_writer_header_; + + delete[] header; + } + + chunking_ = chunking; + + return true; +} + +bool Segment::CuesTrack(uint64_t track_number) { + const Track* const track = GetTrackByNumber(track_number); + if (!track) + return false; + + cues_track_ = track_number; + return true; +} + +void Segment::ForceNewClusterOnNextFrame() { force_new_cluster_ = true; } + +Track* Segment::GetTrackByNumber(uint64_t track_number) const { + return tracks_.GetTrackByNumber(track_number); +} + +bool Segment::WriteSegmentHeader() { + UpdateDocTypeVersion(); + + const char* const doc_type = + DocTypeIsWebm() ? kDocTypeWebm : kDocTypeMatroska; + if (!WriteEbmlHeader(writer_header_, doc_type_version_, doc_type)) + return false; + doc_type_version_written_ = doc_type_version_; + ebml_header_size_ = static_cast(writer_header_->Position()); + + // Write "unknown" (-1) as segment size value. If mode is kFile, Segment + // will write over duration when the file is finalized. + if (WriteID(writer_header_, libwebm::kMkvSegment)) + return false; + + // Save for later. + size_position_ = writer_header_->Position(); + + // Write "unknown" (EBML coded -1) as segment size value. We need to write 8 + // bytes because if we are going to overwrite the segment size later we do + // not know how big our segment will be. + if (SerializeInt(writer_header_, kEbmlUnknownValue, 8)) + return false; + + payload_pos_ = writer_header_->Position(); + + if (mode_ == kFile && writer_header_->Seekable()) { + // Set the duration > 0.0 so SegmentInfo will write out the duration. When + // the muxer is done writing we will set the correct duration and have + // SegmentInfo upadte it. + segment_info_.set_duration(1.0); + + if (!seek_head_.Write(writer_header_)) + return false; + } + + if (!seek_head_.AddSeekEntry(libwebm::kMkvInfo, MaxOffset())) + return false; + if (!segment_info_.Write(writer_header_)) + return false; + + if (!seek_head_.AddSeekEntry(libwebm::kMkvTracks, MaxOffset())) + return false; + if (!tracks_.Write(writer_header_)) + return false; + + if (chapters_.Count() > 0) { + if (!seek_head_.AddSeekEntry(libwebm::kMkvChapters, MaxOffset())) + return false; + if (!chapters_.Write(writer_header_)) + return false; + } + + if (tags_.Count() > 0) { + if (!seek_head_.AddSeekEntry(libwebm::kMkvTags, MaxOffset())) + return false; + if (!tags_.Write(writer_header_)) + return false; + } + + if (chunking_ && (mode_ == kLive || !writer_header_->Seekable())) { + if (!chunk_writer_header_) + return false; + + chunk_writer_header_->Close(); + } + + header_written_ = true; + + return true; +} + +// Here we are testing whether to create a new cluster, given a frame +// having time frame_timestamp_ns. +// +int Segment::TestFrame(uint64_t track_number, uint64_t frame_timestamp_ns, + bool is_key) const { + if (force_new_cluster_) + return 1; + + // If no clusters have been created yet, then create a new cluster + // and write this frame immediately, in the new cluster. This path + // should only be followed once, the first time we attempt to write + // a frame. + + if (cluster_list_size_ <= 0) + return 1; + + // There exists at least one cluster. We must compare the frame to + // the last cluster, in order to determine whether the frame is + // written to the existing cluster, or that a new cluster should be + // created. + + const uint64_t timecode_scale = segment_info_.timecode_scale(); + const uint64_t frame_timecode = frame_timestamp_ns / timecode_scale; + + const Cluster* const last_cluster = cluster_list_[cluster_list_size_ - 1]; + const uint64_t last_cluster_timecode = last_cluster->timecode(); + + // For completeness we test for the case when the frame's timecode + // is less than the cluster's timecode. Although in principle that + // is allowed, this muxer doesn't actually write clusters like that, + // so this indicates a bug somewhere in our algorithm. + + if (frame_timecode < last_cluster_timecode) // should never happen + return -1; + + // If the frame has a timestamp significantly larger than the last + // cluster (in Matroska, cluster-relative timestamps are serialized + // using a 16-bit signed integer), then we cannot write this frame + // to that cluster, and so we must create a new cluster. + + const int64_t delta_timecode = frame_timecode - last_cluster_timecode; + + if (delta_timecode > kMaxBlockTimecode) + return 2; + + // We decide to create a new cluster when we have a video keyframe. + // This will flush queued (audio) frames, and write the keyframe + // immediately, in the newly-created cluster. + + if (is_key && tracks_.TrackIsVideo(track_number)) + return 1; + + // Create a new cluster if we have accumulated too many frames + // already, where "too many" is defined as "the total time of frames + // in the cluster exceeds a threshold". + + const uint64_t delta_ns = delta_timecode * timecode_scale; + + if (max_cluster_duration_ > 0 && delta_ns >= max_cluster_duration_) + return 1; + + // This is similar to the case above, with the difference that a new + // cluster is created when the size of the current cluster exceeds a + // threshold. + + const uint64_t cluster_size = last_cluster->payload_size(); + + if (max_cluster_size_ > 0 && cluster_size >= max_cluster_size_) + return 1; + + // There's no need to create a new cluster, so emit this frame now. + + return 0; +} + +bool Segment::MakeNewCluster(uint64_t frame_timestamp_ns) { + const int32_t new_size = cluster_list_size_ + 1; + + if (new_size > cluster_list_capacity_) { + // Add more clusters. + const int32_t new_capacity = + (cluster_list_capacity_ <= 0) ? 1 : cluster_list_capacity_ * 2; + Cluster** const clusters = + new (std::nothrow) Cluster*[new_capacity]; // NOLINT + if (!clusters) + return false; + + for (int32_t i = 0; i < cluster_list_size_; ++i) { + clusters[i] = cluster_list_[i]; + } + + delete[] cluster_list_; + + cluster_list_ = clusters; + cluster_list_capacity_ = new_capacity; + } + + if (!WriteFramesLessThan(frame_timestamp_ns)) + return false; + + if (cluster_list_size_ > 0) { + // Update old cluster's size + Cluster* const old_cluster = cluster_list_[cluster_list_size_ - 1]; + + if (!old_cluster || !old_cluster->Finalize(true, frame_timestamp_ns)) + return false; + } + + if (output_cues_) + new_cuepoint_ = true; + + if (chunking_ && cluster_list_size_ > 0) { + chunk_writer_cluster_->Close(); + chunk_count_++; + + if (!UpdateChunkName("chk", &chunk_name_)) + return false; + if (!chunk_writer_cluster_->Open(chunk_name_)) + return false; + } + + const uint64_t timecode_scale = segment_info_.timecode_scale(); + const uint64_t frame_timecode = frame_timestamp_ns / timecode_scale; + + uint64_t cluster_timecode = frame_timecode; + + if (frames_size_ > 0) { + const Frame* const f = frames_[0]; // earliest queued frame + const uint64_t ns = f->timestamp(); + const uint64_t tc = ns / timecode_scale; + + if (tc < cluster_timecode) + cluster_timecode = tc; + } + + Cluster*& cluster = cluster_list_[cluster_list_size_]; + const int64_t offset = MaxOffset(); + cluster = new (std::nothrow) + Cluster(cluster_timecode, offset, segment_info_.timecode_scale(), + accurate_cluster_duration_, fixed_size_cluster_timecode_); + if (!cluster) + return false; + + if (!cluster->Init(writer_cluster_)) + return false; + + cluster_list_size_ = new_size; + return true; +} + +bool Segment::DoNewClusterProcessing(uint64_t track_number, + uint64_t frame_timestamp_ns, bool is_key) { + for (;;) { + // Based on the characteristics of the current frame and current + // cluster, decide whether to create a new cluster. + const int result = TestFrame(track_number, frame_timestamp_ns, is_key); + if (result < 0) // error + return false; + + // Always set force_new_cluster_ to false after TestFrame. + force_new_cluster_ = false; + + // A non-zero result means create a new cluster. + if (result > 0 && !MakeNewCluster(frame_timestamp_ns)) + return false; + + // Write queued (audio) frames. + const int frame_count = WriteFramesAll(); + if (frame_count < 0) // error + return false; + + // Write the current frame to the current cluster (if TestFrame + // returns 0) or to a newly created cluster (TestFrame returns 1). + if (result <= 1) + return true; + + // TestFrame returned 2, which means there was a large time + // difference between the cluster and the frame itself. Do the + // test again, comparing the frame to the new cluster. + } +} + +bool Segment::CheckHeaderInfo() { + if (!header_written_) { + if (!WriteSegmentHeader()) + return false; + + if (!seek_head_.AddSeekEntry(libwebm::kMkvCluster, MaxOffset())) + return false; + + if (output_cues_ && cues_track_ == 0) { + // Check for a video track + for (uint32_t i = 0; i < tracks_.track_entries_size(); ++i) { + const Track* const track = tracks_.GetTrackByIndex(i); + if (!track) + return false; + + if (tracks_.TrackIsVideo(track->number())) { + cues_track_ = track->number(); + break; + } + } + + // Set first track found + if (cues_track_ == 0) { + const Track* const track = tracks_.GetTrackByIndex(0); + if (!track) + return false; + + cues_track_ = track->number(); + } + } + } + return true; +} + +void Segment::UpdateDocTypeVersion() { + for (uint32_t index = 0; index < tracks_.track_entries_size(); ++index) { + const Track* track = tracks_.GetTrackByIndex(index); + if (track == NULL) + break; + if ((track->codec_delay() || track->seek_pre_roll()) && + doc_type_version_ < 4) { + doc_type_version_ = 4; + break; + } + } +} + +bool Segment::UpdateChunkName(const char* ext, char** name) const { + if (!name || !ext) + return false; + + char ext_chk[64]; +#ifdef _MSC_VER + sprintf_s(ext_chk, sizeof(ext_chk), "_%06d.%s", chunk_count_, ext); +#else + snprintf(ext_chk, sizeof(ext_chk), "_%06d.%s", chunk_count_, ext); +#endif + + const size_t length = strlen(chunking_base_name_) + strlen(ext_chk) + 1; + char* const str = new (std::nothrow) char[length]; // NOLINT + if (!str) + return false; + +#ifdef _MSC_VER + strcpy_s(str, length - strlen(ext_chk), chunking_base_name_); + strcat_s(str, length, ext_chk); +#else + strcpy(str, chunking_base_name_); + strcat(str, ext_chk); +#endif + + delete[] * name; + *name = str; + + return true; +} + +int64_t Segment::MaxOffset() { + if (!writer_header_) + return -1; + + int64_t offset = writer_header_->Position() - payload_pos_; + + if (chunking_) { + for (int32_t i = 0; i < cluster_list_size_; ++i) { + Cluster* const cluster = cluster_list_[i]; + offset += cluster->Size(); + } + + if (writer_cues_) + offset += writer_cues_->Position(); + } + + return offset; +} + +bool Segment::QueueFrame(Frame* frame) { + const int32_t new_size = frames_size_ + 1; + + if (new_size > frames_capacity_) { + // Add more frames. + const int32_t new_capacity = (!frames_capacity_) ? 2 : frames_capacity_ * 2; + + if (new_capacity < 1) + return false; + + Frame** const frames = new (std::nothrow) Frame*[new_capacity]; // NOLINT + if (!frames) + return false; + + for (int32_t i = 0; i < frames_size_; ++i) { + frames[i] = frames_[i]; + } + + delete[] frames_; + frames_ = frames; + frames_capacity_ = new_capacity; + } + + frames_[frames_size_++] = frame; + + return true; +} + +int Segment::WriteFramesAll() { + if (frames_ == NULL) + return 0; + + if (cluster_list_size_ < 1) + return -1; + + Cluster* const cluster = cluster_list_[cluster_list_size_ - 1]; + + if (!cluster) + return -1; + + for (int32_t i = 0; i < frames_size_; ++i) { + Frame*& frame = frames_[i]; + // TODO(jzern/vigneshv): using Segment::AddGenericFrame here would limit the + // places where |doc_type_version_| needs to be updated. + if (frame->discard_padding() != 0) + doc_type_version_ = 4; + if (!cluster->AddFrame(frame)) { + delete frame; + continue; + } + + if (new_cuepoint_ && cues_track_ == frame->track_number()) { + if (!AddCuePoint(frame->timestamp(), cues_track_)) { + delete frame; + continue; + } + } + + if (frame->timestamp() > last_timestamp_) { + last_timestamp_ = frame->timestamp(); + last_track_timestamp_[frame->track_number() - 1] = frame->timestamp(); + } + + delete frame; + frame = NULL; + } + + const int result = frames_size_; + frames_size_ = 0; + + return result; +} + +bool Segment::WriteFramesLessThan(uint64_t timestamp) { + // Check |cluster_list_size_| to see if this is the first cluster. If it is + // the first cluster the audio frames that are less than the first video + // timesatmp will be written in a later step. + if (frames_size_ > 0 && cluster_list_size_ > 0) { + if (!frames_) + return false; + + Cluster* const cluster = cluster_list_[cluster_list_size_ - 1]; + if (!cluster) + return false; + + int32_t shift_left = 0; + + // TODO(fgalligan): Change this to use the durations of frames instead of + // the next frame's start time if the duration is accurate. + for (int32_t i = 1; i < frames_size_; ++i) { + const Frame* const frame_curr = frames_[i]; + + if (frame_curr->timestamp() > timestamp) + break; + + const Frame* const frame_prev = frames_[i - 1]; + if (frame_prev->discard_padding() != 0) + doc_type_version_ = 4; + if (!cluster->AddFrame(frame_prev)) { + delete frame_prev; + continue; + } + + if (new_cuepoint_ && cues_track_ == frame_prev->track_number()) { + if (!AddCuePoint(frame_prev->timestamp(), cues_track_)) { + delete frame_prev; + continue; + } + } + + ++shift_left; + if (frame_prev->timestamp() > last_timestamp_) { + last_timestamp_ = frame_prev->timestamp(); + last_track_timestamp_[frame_prev->track_number() - 1] = + frame_prev->timestamp(); + } + + delete frame_prev; + } + + if (shift_left > 0) { + if (shift_left >= frames_size_) + return false; + + const int32_t new_frames_size = frames_size_ - shift_left; + for (int32_t i = 0; i < new_frames_size; ++i) { + frames_[i] = frames_[i + shift_left]; + } + + frames_size_ = new_frames_size; + } + } + + return true; +} + +bool Segment::DocTypeIsWebm() const { + const int kNumCodecIds = 9; + + // TODO(vigneshv): Tweak .clang-format. + const char* kWebmCodecIds[kNumCodecIds] = { + Tracks::kOpusCodecId, Tracks::kVorbisCodecId, + Tracks::kAv1CodecId, Tracks::kVp8CodecId, + Tracks::kVp9CodecId, Tracks::kWebVttCaptionsId, + Tracks::kWebVttDescriptionsId, Tracks::kWebVttMetadataId, + Tracks::kWebVttSubtitlesId}; + + const int num_tracks = static_cast(tracks_.track_entries_size()); + for (int track_index = 0; track_index < num_tracks; ++track_index) { + const Track* const track = tracks_.GetTrackByIndex(track_index); + const std::string codec_id = track->codec_id(); + + bool id_is_webm = false; + for (int id_index = 0; id_index < kNumCodecIds; ++id_index) { + if (codec_id == kWebmCodecIds[id_index]) { + id_is_webm = true; + break; + } + } + + if (!id_is_webm) + return false; + } + + return true; +} + +} // namespace mkvmuxer diff --git a/third_party/libwebm/source/mkvmuxer/mkvmuxer.h b/third_party/libwebm/source/mkvmuxer/mkvmuxer.h new file mode 100644 index 000000000000..f2db37714539 --- /dev/null +++ b/third_party/libwebm/source/mkvmuxer/mkvmuxer.h @@ -0,0 +1,1924 @@ +// Copyright (c) 2012 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. + +#ifndef MKVMUXER_MKVMUXER_H_ +#define MKVMUXER_MKVMUXER_H_ + +#include + +#include +#include +#include + +#include "common/webmids.h" +#include "mkvmuxer/mkvmuxertypes.h" + +// For a description of the WebM elements see +// http://www.webmproject.org/code/specs/container/. + +namespace mkvparser { +class IMkvReader; +} // namespace mkvparser + +namespace mkvmuxer { + +class MkvWriter; +class Segment; + +const uint64_t kMaxTrackNumber = 126; + +/////////////////////////////////////////////////////////////// +// Interface used by the mkvmuxer to write out the Mkv data. +class IMkvWriter { + public: + // Writes out |len| bytes of |buf|. Returns 0 on success. + virtual int32 Write(const void* buf, uint32 len) = 0; + + // Returns the offset of the output position from the beginning of the + // output. + virtual int64 Position() const = 0; + + // Set the current File position. Returns 0 on success. + virtual int32 Position(int64 position) = 0; + + // Returns true if the writer is seekable. + virtual bool Seekable() const = 0; + + // Element start notification. Called whenever an element identifier is about + // to be written to the stream. |element_id| is the element identifier, and + // |position| is the location in the WebM stream where the first octet of the + // element identifier will be written. + // Note: the |MkvId| enumeration in webmids.hpp defines element values. + virtual void ElementStartNotify(uint64 element_id, int64 position) = 0; + + protected: + IMkvWriter(); + virtual ~IMkvWriter(); + + private: + LIBWEBM_DISALLOW_COPY_AND_ASSIGN(IMkvWriter); +}; + +// Writes out the EBML header for a WebM file, but allows caller to specify +// DocType. This function must be called before any other libwebm writing +// functions are called. +bool WriteEbmlHeader(IMkvWriter* writer, uint64_t doc_type_version, + const char* const doc_type); + +// Writes out the EBML header for a WebM file. This function must be called +// before any other libwebm writing functions are called. +bool WriteEbmlHeader(IMkvWriter* writer, uint64_t doc_type_version); + +// Deprecated. Writes out EBML header with doc_type_version as +// kDefaultDocTypeVersion. Exists for backward compatibility. +bool WriteEbmlHeader(IMkvWriter* writer); + +// Copies in Chunk from source to destination between the given byte positions +bool ChunkedCopy(mkvparser::IMkvReader* source, IMkvWriter* dst, int64_t start, + int64_t size); + +/////////////////////////////////////////////////////////////// +// Class to hold data the will be written to a block. +class Frame { + public: + Frame(); + ~Frame(); + + // Sets this frame's contents based on |frame|. Returns true on success. On + // failure, this frame's existing contents may be lost. + bool CopyFrom(const Frame& frame); + + // Copies |frame| data into |frame_|. Returns true on success. + bool Init(const uint8_t* frame, uint64_t length); + + // Copies |additional| data into |additional_|. Returns true on success. + bool AddAdditionalData(const uint8_t* additional, uint64_t length, + uint64_t add_id); + + // Returns true if the frame has valid parameters. + bool IsValid() const; + + // Returns true if the frame can be written as a SimpleBlock based on current + // parameters. + bool CanBeSimpleBlock() const; + + uint64_t add_id() const { return add_id_; } + const uint8_t* additional() const { return additional_; } + uint64_t additional_length() const { return additional_length_; } + void set_duration(uint64_t duration); + uint64_t duration() const { return duration_; } + bool duration_set() const { return duration_set_; } + const uint8_t* frame() const { return frame_; } + void set_is_key(bool key) { is_key_ = key; } + bool is_key() const { return is_key_; } + uint64_t length() const { return length_; } + void set_track_number(uint64_t track_number) { track_number_ = track_number; } + uint64_t track_number() const { return track_number_; } + void set_timestamp(uint64_t timestamp) { timestamp_ = timestamp; } + uint64_t timestamp() const { return timestamp_; } + void set_discard_padding(int64_t discard_padding) { + discard_padding_ = discard_padding; + } + int64_t discard_padding() const { return discard_padding_; } + void set_reference_block_timestamp(int64_t reference_block_timestamp); + int64_t reference_block_timestamp() const { + return reference_block_timestamp_; + } + bool reference_block_timestamp_set() const { + return reference_block_timestamp_set_; + } + + private: + // Id of the Additional data. + uint64_t add_id_; + + // Pointer to additional data. Owned by this class. + uint8_t* additional_; + + // Length of the additional data. + uint64_t additional_length_; + + // Duration of the frame in nanoseconds. + uint64_t duration_; + + // Flag indicating that |duration_| has been set. Setting duration causes the + // frame to be written out as a Block with BlockDuration instead of as a + // SimpleBlock. + bool duration_set_; + + // Pointer to the data. Owned by this class. + uint8_t* frame_; + + // Flag telling if the data should set the key flag of a block. + bool is_key_; + + // Length of the data. + uint64_t length_; + + // Mkv track number the data is associated with. + uint64_t track_number_; + + // Timestamp of the data in nanoseconds. + uint64_t timestamp_; + + // Discard padding for the frame. + int64_t discard_padding_; + + // Reference block timestamp. + int64_t reference_block_timestamp_; + + // Flag indicating if |reference_block_timestamp_| has been set. + bool reference_block_timestamp_set_; + + LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Frame); +}; + +/////////////////////////////////////////////////////////////// +// Class to hold one cue point in a Cues element. +class CuePoint { + public: + CuePoint(); + ~CuePoint(); + + // Returns the size in bytes for the entire CuePoint element. + uint64_t Size() const; + + // Output the CuePoint element to the writer. Returns true on success. + bool Write(IMkvWriter* writer) const; + + void set_time(uint64_t time) { time_ = time; } + uint64_t time() const { return time_; } + void set_track(uint64_t track) { track_ = track; } + uint64_t track() const { return track_; } + void set_cluster_pos(uint64_t cluster_pos) { cluster_pos_ = cluster_pos; } + uint64_t cluster_pos() const { return cluster_pos_; } + void set_block_number(uint64_t block_number) { block_number_ = block_number; } + uint64_t block_number() const { return block_number_; } + void set_output_block_number(bool output_block_number) { + output_block_number_ = output_block_number; + } + bool output_block_number() const { return output_block_number_; } + + private: + // Returns the size in bytes for the payload of the CuePoint element. + uint64_t PayloadSize() const; + + // Absolute timecode according to the segment time base. + uint64_t time_; + + // The Track element associated with the CuePoint. + uint64_t track_; + + // The position of the Cluster containing the Block. + uint64_t cluster_pos_; + + // Number of the Block within the Cluster, starting from 1. + uint64_t block_number_; + + // If true the muxer will write out the block number for the cue if the + // block number is different than the default of 1. Default is set to true. + bool output_block_number_; + + LIBWEBM_DISALLOW_COPY_AND_ASSIGN(CuePoint); +}; + +/////////////////////////////////////////////////////////////// +// Cues element. +class Cues { + public: + Cues(); + ~Cues(); + + // Adds a cue point to the Cues element. Returns true on success. + bool AddCue(CuePoint* cue); + + // Returns the cue point by index. Returns NULL if there is no cue point + // match. + CuePoint* GetCueByIndex(int32_t index) const; + + // Returns the total size of the Cues element + uint64_t Size(); + + // Output the Cues element to the writer. Returns true on success. + bool Write(IMkvWriter* writer) const; + + int32_t cue_entries_size() const { return cue_entries_size_; } + void set_output_block_number(bool output_block_number) { + output_block_number_ = output_block_number; + } + bool output_block_number() const { return output_block_number_; } + + private: + // Number of allocated elements in |cue_entries_|. + int32_t cue_entries_capacity_; + + // Number of CuePoints in |cue_entries_|. + int32_t cue_entries_size_; + + // CuePoint list. + CuePoint** cue_entries_; + + // If true the muxer will write out the block number for the cue if the + // block number is different than the default of 1. Default is set to true. + bool output_block_number_; + + LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Cues); +}; + +/////////////////////////////////////////////////////////////// +// ContentEncAESSettings element +class ContentEncAESSettings { + public: + enum { kCTR = 1 }; + + ContentEncAESSettings(); + ~ContentEncAESSettings() {} + + // Returns the size in bytes for the ContentEncAESSettings element. + uint64_t Size() const; + + // Writes out the ContentEncAESSettings element to |writer|. Returns true on + // success. + bool Write(IMkvWriter* writer) const; + + uint64_t cipher_mode() const { return cipher_mode_; } + + private: + // Returns the size in bytes for the payload of the ContentEncAESSettings + // element. + uint64_t PayloadSize() const; + + // Sub elements + uint64_t cipher_mode_; + + LIBWEBM_DISALLOW_COPY_AND_ASSIGN(ContentEncAESSettings); +}; + +/////////////////////////////////////////////////////////////// +// ContentEncoding element +// Elements used to describe if the track data has been encrypted or +// compressed with zlib or header stripping. +// Currently only whole frames can be encrypted with AES. This dictates that +// ContentEncodingOrder will be 0, ContentEncodingScope will be 1, +// ContentEncodingType will be 1, and ContentEncAlgo will be 5. +class ContentEncoding { + public: + ContentEncoding(); + ~ContentEncoding(); + + // Sets the content encryption id. Copies |length| bytes from |id| to + // |enc_key_id_|. Returns true on success. + bool SetEncryptionID(const uint8_t* id, uint64_t length); + + // Returns the size in bytes for the ContentEncoding element. + uint64_t Size() const; + + // Writes out the ContentEncoding element to |writer|. Returns true on + // success. + bool Write(IMkvWriter* writer) const; + + uint64_t enc_algo() const { return enc_algo_; } + uint64_t encoding_order() const { return encoding_order_; } + uint64_t encoding_scope() const { return encoding_scope_; } + uint64_t encoding_type() const { return encoding_type_; } + ContentEncAESSettings* enc_aes_settings() { return &enc_aes_settings_; } + + private: + // Returns the size in bytes for the encoding elements. + uint64_t EncodingSize(uint64_t compresion_size, + uint64_t encryption_size) const; + + // Returns the size in bytes for the encryption elements. + uint64_t EncryptionSize() const; + + // Track element names + uint64_t enc_algo_; + uint8_t* enc_key_id_; + uint64_t encoding_order_; + uint64_t encoding_scope_; + uint64_t encoding_type_; + + // ContentEncAESSettings element. + ContentEncAESSettings enc_aes_settings_; + + // Size of the ContentEncKeyID data in bytes. + uint64_t enc_key_id_length_; + + LIBWEBM_DISALLOW_COPY_AND_ASSIGN(ContentEncoding); +}; + +/////////////////////////////////////////////////////////////// +// Colour element. +class PrimaryChromaticity { + public: + static const float kChromaticityMin; + static const float kChromaticityMax; + + PrimaryChromaticity(float x_val, float y_val) : x_(x_val), y_(y_val) {} + PrimaryChromaticity() : x_(0), y_(0) {} + ~PrimaryChromaticity() {} + + // Returns sum of |x_id| and |y_id| element id sizes and payload sizes. + uint64_t PrimaryChromaticitySize(libwebm::MkvId x_id, + libwebm::MkvId y_id) const; + bool Valid() const; + bool Write(IMkvWriter* writer, libwebm::MkvId x_id, + libwebm::MkvId y_id) const; + + float x() const { return x_; } + void set_x(float new_x) { x_ = new_x; } + float y() const { return y_; } + void set_y(float new_y) { y_ = new_y; } + + private: + float x_; + float y_; +}; + +class MasteringMetadata { + public: + static const float kValueNotPresent; + static const float kMinLuminance; + static const float kMinLuminanceMax; + static const float kMaxLuminanceMax; + + MasteringMetadata() + : luminance_max_(kValueNotPresent), + luminance_min_(kValueNotPresent), + r_(NULL), + g_(NULL), + b_(NULL), + white_point_(NULL) {} + ~MasteringMetadata() { + delete r_; + delete g_; + delete b_; + delete white_point_; + } + + // Returns total size of the MasteringMetadata element. + uint64_t MasteringMetadataSize() const; + bool Valid() const; + bool Write(IMkvWriter* writer) const; + + // Copies non-null chromaticity. + bool SetChromaticity(const PrimaryChromaticity* r, + const PrimaryChromaticity* g, + const PrimaryChromaticity* b, + const PrimaryChromaticity* white_point); + const PrimaryChromaticity* r() const { return r_; } + const PrimaryChromaticity* g() const { return g_; } + const PrimaryChromaticity* b() const { return b_; } + const PrimaryChromaticity* white_point() const { return white_point_; } + + float luminance_max() const { return luminance_max_; } + void set_luminance_max(float luminance_max) { + luminance_max_ = luminance_max; + } + float luminance_min() const { return luminance_min_; } + void set_luminance_min(float luminance_min) { + luminance_min_ = luminance_min; + } + + private: + // Returns size of MasteringMetadata child elements. + uint64_t PayloadSize() const; + + float luminance_max_; + float luminance_min_; + PrimaryChromaticity* r_; + PrimaryChromaticity* g_; + PrimaryChromaticity* b_; + PrimaryChromaticity* white_point_; +}; + +class Colour { + public: + enum MatrixCoefficients { + kGbr = 0, + kBt709 = 1, + kUnspecifiedMc = 2, + kReserved = 3, + kFcc = 4, + kBt470bg = 5, + kSmpte170MMc = 6, + kSmpte240MMc = 7, + kYcocg = 8, + kBt2020NonConstantLuminance = 9, + kBt2020ConstantLuminance = 10, + }; + enum ChromaSitingHorz { + kUnspecifiedCsh = 0, + kLeftCollocated = 1, + kHalfCsh = 2, + }; + enum ChromaSitingVert { + kUnspecifiedCsv = 0, + kTopCollocated = 1, + kHalfCsv = 2, + }; + enum Range { + kUnspecifiedCr = 0, + kBroadcastRange = 1, + kFullRange = 2, + kMcTcDefined = 3, // Defined by MatrixCoefficients/TransferCharacteristics. + }; + enum TransferCharacteristics { + kIturBt709Tc = 1, + kUnspecifiedTc = 2, + kReservedTc = 3, + kGamma22Curve = 4, + kGamma28Curve = 5, + kSmpte170MTc = 6, + kSmpte240MTc = 7, + kLinear = 8, + kLog = 9, + kLogSqrt = 10, + kIec6196624 = 11, + kIturBt1361ExtendedColourGamut = 12, + kIec6196621 = 13, + kIturBt202010bit = 14, + kIturBt202012bit = 15, + kSmpteSt2084 = 16, + kSmpteSt4281Tc = 17, + kAribStdB67Hlg = 18, + }; + enum Primaries { + kReservedP0 = 0, + kIturBt709P = 1, + kUnspecifiedP = 2, + kReservedP3 = 3, + kIturBt470M = 4, + kIturBt470Bg = 5, + kSmpte170MP = 6, + kSmpte240MP = 7, + kFilm = 8, + kIturBt2020 = 9, + kSmpteSt4281P = 10, + kJedecP22Phosphors = 22, + }; + static const uint64_t kValueNotPresent; + Colour() + : matrix_coefficients_(kValueNotPresent), + bits_per_channel_(kValueNotPresent), + chroma_subsampling_horz_(kValueNotPresent), + chroma_subsampling_vert_(kValueNotPresent), + cb_subsampling_horz_(kValueNotPresent), + cb_subsampling_vert_(kValueNotPresent), + chroma_siting_horz_(kValueNotPresent), + chroma_siting_vert_(kValueNotPresent), + range_(kValueNotPresent), + transfer_characteristics_(kValueNotPresent), + primaries_(kValueNotPresent), + max_cll_(kValueNotPresent), + max_fall_(kValueNotPresent), + mastering_metadata_(NULL) {} + ~Colour() { delete mastering_metadata_; } + + // Returns total size of the Colour element. + uint64_t ColourSize() const; + bool Valid() const; + bool Write(IMkvWriter* writer) const; + + // Deep copies |mastering_metadata|. + bool SetMasteringMetadata(const MasteringMetadata& mastering_metadata); + + const MasteringMetadata* mastering_metadata() const { + return mastering_metadata_; + } + + uint64_t matrix_coefficients() const { return matrix_coefficients_; } + void set_matrix_coefficients(uint64_t matrix_coefficients) { + matrix_coefficients_ = matrix_coefficients; + } + uint64_t bits_per_channel() const { return bits_per_channel_; } + void set_bits_per_channel(uint64_t bits_per_channel) { + bits_per_channel_ = bits_per_channel; + } + uint64_t chroma_subsampling_horz() const { return chroma_subsampling_horz_; } + void set_chroma_subsampling_horz(uint64_t chroma_subsampling_horz) { + chroma_subsampling_horz_ = chroma_subsampling_horz; + } + uint64_t chroma_subsampling_vert() const { return chroma_subsampling_vert_; } + void set_chroma_subsampling_vert(uint64_t chroma_subsampling_vert) { + chroma_subsampling_vert_ = chroma_subsampling_vert; + } + uint64_t cb_subsampling_horz() const { return cb_subsampling_horz_; } + void set_cb_subsampling_horz(uint64_t cb_subsampling_horz) { + cb_subsampling_horz_ = cb_subsampling_horz; + } + uint64_t cb_subsampling_vert() const { return cb_subsampling_vert_; } + void set_cb_subsampling_vert(uint64_t cb_subsampling_vert) { + cb_subsampling_vert_ = cb_subsampling_vert; + } + uint64_t chroma_siting_horz() const { return chroma_siting_horz_; } + void set_chroma_siting_horz(uint64_t chroma_siting_horz) { + chroma_siting_horz_ = chroma_siting_horz; + } + uint64_t chroma_siting_vert() const { return chroma_siting_vert_; } + void set_chroma_siting_vert(uint64_t chroma_siting_vert) { + chroma_siting_vert_ = chroma_siting_vert; + } + uint64_t range() const { return range_; } + void set_range(uint64_t range) { range_ = range; } + uint64_t transfer_characteristics() const { + return transfer_characteristics_; + } + void set_transfer_characteristics(uint64_t transfer_characteristics) { + transfer_characteristics_ = transfer_characteristics; + } + uint64_t primaries() const { return primaries_; } + void set_primaries(uint64_t primaries) { primaries_ = primaries; } + uint64_t max_cll() const { return max_cll_; } + void set_max_cll(uint64_t max_cll) { max_cll_ = max_cll; } + uint64_t max_fall() const { return max_fall_; } + void set_max_fall(uint64_t max_fall) { max_fall_ = max_fall; } + + private: + // Returns size of Colour child elements. + uint64_t PayloadSize() const; + + uint64_t matrix_coefficients_; + uint64_t bits_per_channel_; + uint64_t chroma_subsampling_horz_; + uint64_t chroma_subsampling_vert_; + uint64_t cb_subsampling_horz_; + uint64_t cb_subsampling_vert_; + uint64_t chroma_siting_horz_; + uint64_t chroma_siting_vert_; + uint64_t range_; + uint64_t transfer_characteristics_; + uint64_t primaries_; + uint64_t max_cll_; + uint64_t max_fall_; + + MasteringMetadata* mastering_metadata_; +}; + +/////////////////////////////////////////////////////////////// +// Projection element. +class Projection { + public: + enum ProjectionType { + kTypeNotPresent = -1, + kRectangular = 0, + kEquirectangular = 1, + kCubeMap = 2, + kMesh = 3, + }; + static const uint64_t kValueNotPresent; + Projection() + : type_(kRectangular), + pose_yaw_(0.0), + pose_pitch_(0.0), + pose_roll_(0.0), + private_data_(NULL), + private_data_length_(0) {} + ~Projection() { delete[] private_data_; } + + uint64_t ProjectionSize() const; + bool Write(IMkvWriter* writer) const; + + bool SetProjectionPrivate(const uint8_t* private_data, + uint64_t private_data_length); + + ProjectionType type() const { return type_; } + void set_type(ProjectionType type) { type_ = type; } + float pose_yaw() const { return pose_yaw_; } + void set_pose_yaw(float pose_yaw) { pose_yaw_ = pose_yaw; } + float pose_pitch() const { return pose_pitch_; } + void set_pose_pitch(float pose_pitch) { pose_pitch_ = pose_pitch; } + float pose_roll() const { return pose_roll_; } + void set_pose_roll(float pose_roll) { pose_roll_ = pose_roll; } + uint8_t* private_data() const { return private_data_; } + uint64_t private_data_length() const { return private_data_length_; } + + private: + // Returns size of VideoProjection child elements. + uint64_t PayloadSize() const; + + ProjectionType type_; + float pose_yaw_; + float pose_pitch_; + float pose_roll_; + uint8_t* private_data_; + uint64_t private_data_length_; +}; + +/////////////////////////////////////////////////////////////// +// Track element. +class Track { + public: + // The |seed| parameter is used to synthesize a UID for the track. + explicit Track(unsigned int* seed); + virtual ~Track(); + + // Adds a ContentEncoding element to the Track. Returns true on success. + virtual bool AddContentEncoding(); + + // Returns the ContentEncoding by index. Returns NULL if there is no + // ContentEncoding match. + ContentEncoding* GetContentEncodingByIndex(uint32_t index) const; + + // Returns the size in bytes for the payload of the Track element. + virtual uint64_t PayloadSize() const; + + // Returns the size in bytes of the Track element. + virtual uint64_t Size() const; + + // Output the Track element to the writer. Returns true on success. + virtual bool Write(IMkvWriter* writer) const; + + // Sets the CodecPrivate element of the Track element. Copies |length| + // bytes from |codec_private| to |codec_private_|. Returns true on success. + bool SetCodecPrivate(const uint8_t* codec_private, uint64_t length); + + void set_codec_id(const char* codec_id); + const char* codec_id() const { return codec_id_; } + const uint8_t* codec_private() const { return codec_private_; } + void set_language(const char* language); + const char* language() const { return language_; } + void set_max_block_additional_id(uint64_t max_block_additional_id) { + max_block_additional_id_ = max_block_additional_id; + } + uint64_t max_block_additional_id() const { return max_block_additional_id_; } + void set_name(const char* name); + const char* name() const { return name_; } + void set_number(uint64_t number) { number_ = number; } + uint64_t number() const { return number_; } + void set_type(uint64_t type) { type_ = type; } + uint64_t type() const { return type_; } + void set_uid(uint64_t uid) { uid_ = uid; } + uint64_t uid() const { return uid_; } + void set_codec_delay(uint64_t codec_delay) { codec_delay_ = codec_delay; } + uint64_t codec_delay() const { return codec_delay_; } + void set_seek_pre_roll(uint64_t seek_pre_roll) { + seek_pre_roll_ = seek_pre_roll; + } + uint64_t seek_pre_roll() const { return seek_pre_roll_; } + void set_default_duration(uint64_t default_duration) { + default_duration_ = default_duration; + } + uint64_t default_duration() const { return default_duration_; } + + uint64_t codec_private_length() const { return codec_private_length_; } + uint32_t content_encoding_entries_size() const { + return content_encoding_entries_size_; + } + + private: + // Track element names. + char* codec_id_; + uint8_t* codec_private_; + char* language_; + uint64_t max_block_additional_id_; + char* name_; + uint64_t number_; + uint64_t type_; + uint64_t uid_; + uint64_t codec_delay_; + uint64_t seek_pre_roll_; + uint64_t default_duration_; + + // Size of the CodecPrivate data in bytes. + uint64_t codec_private_length_; + + // ContentEncoding element list. + ContentEncoding** content_encoding_entries_; + + // Number of ContentEncoding elements added. + uint32_t content_encoding_entries_size_; + + LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Track); +}; + +/////////////////////////////////////////////////////////////// +// Track that has video specific elements. +class VideoTrack : public Track { + public: + // Supported modes for stereo 3D. + enum StereoMode { + kMono = 0, + kSideBySideLeftIsFirst = 1, + kTopBottomRightIsFirst = 2, + kTopBottomLeftIsFirst = 3, + kSideBySideRightIsFirst = 11 + }; + + enum AlphaMode { kNoAlpha = 0, kAlpha = 1 }; + + // The |seed| parameter is used to synthesize a UID for the track. + explicit VideoTrack(unsigned int* seed); + virtual ~VideoTrack(); + + // Returns the size in bytes for the payload of the Track element plus the + // video specific elements. + virtual uint64_t PayloadSize() const; + + // Output the VideoTrack element to the writer. Returns true on success. + virtual bool Write(IMkvWriter* writer) const; + + // Sets the video's stereo mode. Returns true on success. + bool SetStereoMode(uint64_t stereo_mode); + + // Sets the video's alpha mode. Returns true on success. + bool SetAlphaMode(uint64_t alpha_mode); + + void set_display_height(uint64_t height) { display_height_ = height; } + uint64_t display_height() const { return display_height_; } + void set_display_width(uint64_t width) { display_width_ = width; } + uint64_t display_width() const { return display_width_; } + void set_pixel_height(uint64_t height) { pixel_height_ = height; } + uint64_t pixel_height() const { return pixel_height_; } + void set_pixel_width(uint64_t width) { pixel_width_ = width; } + uint64_t pixel_width() const { return pixel_width_; } + + void set_crop_left(uint64_t crop_left) { crop_left_ = crop_left; } + uint64_t crop_left() const { return crop_left_; } + void set_crop_right(uint64_t crop_right) { crop_right_ = crop_right; } + uint64_t crop_right() const { return crop_right_; } + void set_crop_top(uint64_t crop_top) { crop_top_ = crop_top; } + uint64_t crop_top() const { return crop_top_; } + void set_crop_bottom(uint64_t crop_bottom) { crop_bottom_ = crop_bottom; } + uint64_t crop_bottom() const { return crop_bottom_; } + + void set_frame_rate(double frame_rate) { frame_rate_ = frame_rate; } + double frame_rate() const { return frame_rate_; } + void set_height(uint64_t height) { height_ = height; } + uint64_t height() const { return height_; } + uint64_t stereo_mode() { return stereo_mode_; } + uint64_t alpha_mode() { return alpha_mode_; } + void set_width(uint64_t width) { width_ = width; } + uint64_t width() const { return width_; } + void set_colour_space(const char* colour_space); + const char* colour_space() const { return colour_space_; } + + Colour* colour() { return colour_; } + + // Deep copies |colour|. + bool SetColour(const Colour& colour); + + Projection* projection() { return projection_; } + + // Deep copies |projection|. + bool SetProjection(const Projection& projection); + + private: + // Returns the size in bytes of the Video element. + uint64_t VideoPayloadSize() const; + + // Video track element names. + uint64_t display_height_; + uint64_t display_width_; + uint64_t pixel_height_; + uint64_t pixel_width_; + uint64_t crop_left_; + uint64_t crop_right_; + uint64_t crop_top_; + uint64_t crop_bottom_; + double frame_rate_; + uint64_t height_; + uint64_t stereo_mode_; + uint64_t alpha_mode_; + uint64_t width_; + char* colour_space_; + + Colour* colour_; + Projection* projection_; + + LIBWEBM_DISALLOW_COPY_AND_ASSIGN(VideoTrack); +}; + +/////////////////////////////////////////////////////////////// +// Track that has audio specific elements. +class AudioTrack : public Track { + public: + // The |seed| parameter is used to synthesize a UID for the track. + explicit AudioTrack(unsigned int* seed); + virtual ~AudioTrack(); + + // Returns the size in bytes for the payload of the Track element plus the + // audio specific elements. + virtual uint64_t PayloadSize() const; + + // Output the AudioTrack element to the writer. Returns true on success. + virtual bool Write(IMkvWriter* writer) const; + + void set_bit_depth(uint64_t bit_depth) { bit_depth_ = bit_depth; } + uint64_t bit_depth() const { return bit_depth_; } + void set_channels(uint64_t channels) { channels_ = channels; } + uint64_t channels() const { return channels_; } + void set_sample_rate(double sample_rate) { sample_rate_ = sample_rate; } + double sample_rate() const { return sample_rate_; } + + private: + // Audio track element names. + uint64_t bit_depth_; + uint64_t channels_; + double sample_rate_; + + LIBWEBM_DISALLOW_COPY_AND_ASSIGN(AudioTrack); +}; + +/////////////////////////////////////////////////////////////// +// Tracks element +class Tracks { + public: + // Audio and video type defined by the Matroska specs. + enum { kVideo = 0x1, kAudio = 0x2 }; + + static const char kOpusCodecId[]; + static const char kVorbisCodecId[]; + static const char kAv1CodecId[]; + static const char kVp8CodecId[]; + static const char kVp9CodecId[]; + static const char kWebVttCaptionsId[]; + static const char kWebVttDescriptionsId[]; + static const char kWebVttMetadataId[]; + static const char kWebVttSubtitlesId[]; + + Tracks(); + ~Tracks(); + + // Adds a Track element to the Tracks object. |track| will be owned and + // deleted by the Tracks object. Returns true on success. |number| is the + // number to use for the track. |number| must be >= 0. If |number| == 0 + // then the muxer will decide on the track number. + bool AddTrack(Track* track, int32_t number); + + // Returns the track by index. Returns NULL if there is no track match. + const Track* GetTrackByIndex(uint32_t idx) const; + + // Search the Tracks and return the track that matches |tn|. Returns NULL + // if there is no track match. + Track* GetTrackByNumber(uint64_t track_number) const; + + // Returns true if the track number is an audio track. + bool TrackIsAudio(uint64_t track_number) const; + + // Returns true if the track number is a video track. + bool TrackIsVideo(uint64_t track_number) const; + + // Output the Tracks element to the writer. Returns true on success. + bool Write(IMkvWriter* writer) const; + + uint32_t track_entries_size() const { return track_entries_size_; } + + private: + // Track element list. + Track** track_entries_; + + // Number of Track elements added. + uint32_t track_entries_size_; + + // Whether or not Tracks element has already been written via IMkvWriter. + mutable bool wrote_tracks_; + + LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Tracks); +}; + +/////////////////////////////////////////////////////////////// +// Chapter element +// +class Chapter { + public: + // Set the identifier for this chapter. (This corresponds to the + // Cue Identifier line in WebVTT.) + // TODO(matthewjheaney): the actual serialization of this item in + // MKV is pending. + bool set_id(const char* id); + + // Converts the nanosecond start and stop times of this chapter to + // their corresponding timecode values, and stores them that way. + void set_time(const Segment& segment, uint64_t start_time_ns, + uint64_t end_time_ns); + + // Sets the uid for this chapter. Primarily used to enable + // deterministic output from the muxer. + void set_uid(const uint64_t uid) { uid_ = uid; } + + // Add a title string to this chapter, per the semantics described + // here: + // http://www.matroska.org/technical/specs/index.html + // + // The title ("chapter string") is a UTF-8 string. + // + // The language has ISO 639-2 representation, described here: + // http://www.loc.gov/standards/iso639-2/englangn.html + // http://www.loc.gov/standards/iso639-2/php/English_list.php + // If you specify NULL as the language value, this implies + // English ("eng"). + // + // The country value corresponds to the codes listed here: + // http://www.iana.org/domains/root/db/ + // + // The function returns false if the string could not be allocated. + bool add_string(const char* title, const char* language, const char* country); + + private: + friend class Chapters; + + // For storage of chapter titles that differ by language. + class Display { + public: + // Establish representation invariant for new Display object. + void Init(); + + // Reclaim resources, in anticipation of destruction. + void Clear(); + + // Copies the title to the |title_| member. Returns false on + // error. + bool set_title(const char* title); + + // Copies the language to the |language_| member. Returns false + // on error. + bool set_language(const char* language); + + // Copies the country to the |country_| member. Returns false on + // error. + bool set_country(const char* country); + + // If |writer| is non-NULL, serialize the Display sub-element of + // the Atom into the stream. Returns the Display element size on + // success, 0 if error. + uint64_t WriteDisplay(IMkvWriter* writer) const; + + private: + char* title_; + char* language_; + char* country_; + }; + + Chapter(); + ~Chapter(); + + // Establish the representation invariant for a newly-created + // Chapter object. The |seed| parameter is used to create the UID + // for this chapter atom. + void Init(unsigned int* seed); + + // Copies this Chapter object to a different one. This is used when + // expanding a plain array of Chapter objects (see Chapters). + void ShallowCopy(Chapter* dst) const; + + // Reclaim resources used by this Chapter object, pending its + // destruction. + void Clear(); + + // If there is no storage remaining on the |displays_| array for a + // new display object, creates a new, longer array and copies the + // existing Display objects to the new array. Returns false if the + // array cannot be expanded. + bool ExpandDisplaysArray(); + + // If |writer| is non-NULL, serialize the Atom sub-element into the + // stream. Returns the total size of the element on success, 0 if + // error. + uint64_t WriteAtom(IMkvWriter* writer) const; + + // The string identifier for this chapter (corresponds to WebVTT cue + // identifier). + char* id_; + + // Start timecode of the chapter. + uint64_t start_timecode_; + + // Stop timecode of the chapter. + uint64_t end_timecode_; + + // The binary identifier for this chapter. + uint64_t uid_; + + // The Atom element can contain multiple Display sub-elements, as + // the same logical title can be rendered in different languages. + Display* displays_; + + // The physical length (total size) of the |displays_| array. + int displays_size_; + + // The logical length (number of active elements) on the |displays_| + // array. + int displays_count_; + + LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Chapter); +}; + +/////////////////////////////////////////////////////////////// +// Chapters element +// +class Chapters { + public: + Chapters(); + ~Chapters(); + + Chapter* AddChapter(unsigned int* seed); + + // Returns the number of chapters that have been added. + int Count() const; + + // Output the Chapters element to the writer. Returns true on success. + bool Write(IMkvWriter* writer) const; + + private: + // Expands the chapters_ array if there is not enough space to contain + // another chapter object. Returns true on success. + bool ExpandChaptersArray(); + + // If |writer| is non-NULL, serialize the Edition sub-element of the + // Chapters element into the stream. Returns the Edition element + // size on success, 0 if error. + uint64_t WriteEdition(IMkvWriter* writer) const; + + // Total length of the chapters_ array. + int chapters_size_; + + // Number of active chapters on the chapters_ array. + int chapters_count_; + + // Array for storage of chapter objects. + Chapter* chapters_; + + LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Chapters); +}; + +/////////////////////////////////////////////////////////////// +// Tag element +// +class Tag { + public: + bool add_simple_tag(const char* tag_name, const char* tag_string); + + private: + // Tags calls Clear and the destructor of Tag + friend class Tags; + + // For storage of simple tags + class SimpleTag { + public: + // Establish representation invariant for new SimpleTag object. + void Init(); + + // Reclaim resources, in anticipation of destruction. + void Clear(); + + // Copies the title to the |tag_name_| member. Returns false on + // error. + bool set_tag_name(const char* tag_name); + + // Copies the language to the |tag_string_| member. Returns false + // on error. + bool set_tag_string(const char* tag_string); + + // If |writer| is non-NULL, serialize the SimpleTag sub-element of + // the Atom into the stream. Returns the SimpleTag element size on + // success, 0 if error. + uint64_t Write(IMkvWriter* writer) const; + + private: + char* tag_name_; + char* tag_string_; + }; + + Tag(); + ~Tag(); + + // Copies this Tag object to a different one. This is used when + // expanding a plain array of Tag objects (see Tags). + void ShallowCopy(Tag* dst) const; + + // Reclaim resources used by this Tag object, pending its + // destruction. + void Clear(); + + // If there is no storage remaining on the |simple_tags_| array for a + // new display object, creates a new, longer array and copies the + // existing SimpleTag objects to the new array. Returns false if the + // array cannot be expanded. + bool ExpandSimpleTagsArray(); + + // If |writer| is non-NULL, serialize the Tag sub-element into the + // stream. Returns the total size of the element on success, 0 if + // error. + uint64_t Write(IMkvWriter* writer) const; + + // The Atom element can contain multiple SimpleTag sub-elements + SimpleTag* simple_tags_; + + // The physical length (total size) of the |simple_tags_| array. + int simple_tags_size_; + + // The logical length (number of active elements) on the |simple_tags_| + // array. + int simple_tags_count_; + + LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Tag); +}; + +/////////////////////////////////////////////////////////////// +// Tags element +// +class Tags { + public: + Tags(); + ~Tags(); + + Tag* AddTag(); + + // Returns the number of tags that have been added. + int Count() const; + + // Output the Tags element to the writer. Returns true on success. + bool Write(IMkvWriter* writer) const; + + private: + // Expands the tags_ array if there is not enough space to contain + // another tag object. Returns true on success. + bool ExpandTagsArray(); + + // Total length of the tags_ array. + int tags_size_; + + // Number of active tags on the tags_ array. + int tags_count_; + + // Array for storage of tag objects. + Tag* tags_; + + LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Tags); +}; + +/////////////////////////////////////////////////////////////// +// Cluster element +// +// Notes: +// |Init| must be called before any other method in this class. +class Cluster { + public: + // |timecode| is the absolute timecode of the cluster. |cues_pos| is the + // position for the cluster within the segment that should be written in + // the cues element. |timecode_scale| is the timecode scale of the segment. + Cluster(uint64_t timecode, int64_t cues_pos, uint64_t timecode_scale, + bool write_last_frame_with_duration = false, + bool fixed_size_timecode = false); + ~Cluster(); + + bool Init(IMkvWriter* ptr_writer); + + // Adds a frame to be output in the file. The frame is written out through + // |writer_| if successful. Returns true on success. + bool AddFrame(const Frame* frame); + + // Adds a frame to be output in the file. The frame is written out through + // |writer_| if successful. Returns true on success. + // Inputs: + // data: Pointer to the data + // length: Length of the data + // track_number: Track to add the data to. Value returned by Add track + // functions. The range of allowed values is [1, 126]. + // timecode: Absolute (not relative to cluster) timestamp of the + // frame, expressed in timecode units. + // is_key: Flag telling whether or not this frame is a key frame. + bool AddFrame(const uint8_t* data, uint64_t length, uint64_t track_number, + uint64_t timecode, // timecode units (absolute) + bool is_key); + + // Adds a frame to be output in the file. The frame is written out through + // |writer_| if successful. Returns true on success. + // Inputs: + // data: Pointer to the data + // length: Length of the data + // additional: Pointer to the additional data + // additional_length: Length of the additional data + // add_id: Value of BlockAddID element + // track_number: Track to add the data to. Value returned by Add track + // functions. The range of allowed values is [1, 126]. + // abs_timecode: Absolute (not relative to cluster) timestamp of the + // frame, expressed in timecode units. + // is_key: Flag telling whether or not this frame is a key frame. + bool AddFrameWithAdditional(const uint8_t* data, uint64_t length, + const uint8_t* additional, + uint64_t additional_length, uint64_t add_id, + uint64_t track_number, uint64_t abs_timecode, + bool is_key); + + // Adds a frame to be output in the file. The frame is written out through + // |writer_| if successful. Returns true on success. + // Inputs: + // data: Pointer to the data. + // length: Length of the data. + // discard_padding: DiscardPadding element value. + // track_number: Track to add the data to. Value returned by Add track + // functions. The range of allowed values is [1, 126]. + // abs_timecode: Absolute (not relative to cluster) timestamp of the + // frame, expressed in timecode units. + // is_key: Flag telling whether or not this frame is a key frame. + bool AddFrameWithDiscardPadding(const uint8_t* data, uint64_t length, + int64_t discard_padding, + uint64_t track_number, uint64_t abs_timecode, + bool is_key); + + // Writes a frame of metadata to the output medium; returns true on + // success. + // Inputs: + // data: Pointer to the data + // length: Length of the data + // track_number: Track to add the data to. Value returned by Add track + // functions. The range of allowed values is [1, 126]. + // timecode: Absolute (not relative to cluster) timestamp of the + // metadata frame, expressed in timecode units. + // duration: Duration of metadata frame, in timecode units. + // + // The metadata frame is written as a block group, with a duration + // sub-element but no reference time sub-elements (indicating that + // it is considered a keyframe, per Matroska semantics). + bool AddMetadata(const uint8_t* data, uint64_t length, uint64_t track_number, + uint64_t timecode, uint64_t duration); + + // Increments the size of the cluster's data in bytes. + void AddPayloadSize(uint64_t size); + + // Closes the cluster so no more data can be written to it. Will update the + // cluster's size if |writer_| is seekable. Returns true on success. This + // variant of Finalize() fails when |write_last_frame_with_duration_| is set + // to true. + bool Finalize(); + + // Closes the cluster so no more data can be written to it. Will update the + // cluster's size if |writer_| is seekable. Returns true on success. + // Inputs: + // set_last_frame_duration: Boolean indicating whether or not the duration + // of the last frame should be set. If set to + // false, the |duration| value is ignored and + // |write_last_frame_with_duration_| will not be + // honored. + // duration: Duration of the Cluster in timecode scale. + bool Finalize(bool set_last_frame_duration, uint64_t duration); + + // Returns the size in bytes for the entire Cluster element. + uint64_t Size() const; + + // Given |abs_timecode|, calculates timecode relative to most recent timecode. + // Returns -1 on failure, or a relative timecode. + int64_t GetRelativeTimecode(int64_t abs_timecode) const; + + int64_t size_position() const { return size_position_; } + int32_t blocks_added() const { return blocks_added_; } + uint64_t payload_size() const { return payload_size_; } + int64_t position_for_cues() const { return position_for_cues_; } + uint64_t timecode() const { return timecode_; } + uint64_t timecode_scale() const { return timecode_scale_; } + void set_write_last_frame_with_duration(bool write_last_frame_with_duration) { + write_last_frame_with_duration_ = write_last_frame_with_duration; + } + bool write_last_frame_with_duration() const { + return write_last_frame_with_duration_; + } + + private: + // Iterator type for the |stored_frames_| map. + typedef std::map >::iterator FrameMapIterator; + + // Utility method that confirms that blocks can still be added, and that the + // cluster header has been written. Used by |DoWriteFrame*|. Returns true + // when successful. + bool PreWriteBlock(); + + // Utility method used by the |DoWriteFrame*| methods that handles the book + // keeping required after each block is written. + void PostWriteBlock(uint64_t element_size); + + // Does some verification and calls WriteFrame. + bool DoWriteFrame(const Frame* const frame); + + // Either holds back the given frame, or writes it out depending on whether or + // not |write_last_frame_with_duration_| is set. + bool QueueOrWriteFrame(const Frame* const frame); + + // Outputs the Cluster header to |writer_|. Returns true on success. + bool WriteClusterHeader(); + + // Number of blocks added to the cluster. + int32_t blocks_added_; + + // Flag telling if the cluster has been closed. + bool finalized_; + + // Flag indicating whether the cluster's timecode will always be written out + // using 8 bytes. + bool fixed_size_timecode_; + + // Flag telling if the cluster's header has been written. + bool header_written_; + + // The size of the cluster elements in bytes. + uint64_t payload_size_; + + // The file position used for cue points. + const int64_t position_for_cues_; + + // The file position of the cluster's size element. + int64_t size_position_; + + // The absolute timecode of the cluster. + const uint64_t timecode_; + + // The timecode scale of the Segment containing the cluster. + const uint64_t timecode_scale_; + + // Flag indicating whether the last frame of the cluster should be written as + // a Block with Duration. If set to true, then it will result in holding back + // of frames and the parameterized version of Finalize() must be called to + // finish writing the Cluster. + bool write_last_frame_with_duration_; + + // Map used to hold back frames, if required. Track number is the key. + std::map > stored_frames_; + + // Map from track number to the timestamp of the last block written for that + // track. + std::map last_block_timestamp_; + + // Pointer to the writer object. Not owned by this class. + IMkvWriter* writer_; + + LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Cluster); +}; + +/////////////////////////////////////////////////////////////// +// SeekHead element +class SeekHead { + public: + SeekHead(); + ~SeekHead(); + + // TODO(fgalligan): Change this to reserve a certain size. Then check how + // big the seek entry to be added is as not every seek entry will be the + // maximum size it could be. + // Adds a seek entry to be written out when the element is finalized. |id| + // must be the coded mkv element id. |pos| is the file position of the + // element. Returns true on success. + bool AddSeekEntry(uint32_t id, uint64_t pos); + + // Writes out SeekHead and SeekEntry elements. Returns true on success. + bool Finalize(IMkvWriter* writer) const; + + // Returns the id of the Seek Entry at the given index. Returns -1 if index is + // out of range. + uint32_t GetId(int index) const; + + // Returns the position of the Seek Entry at the given index. Returns -1 if + // index is out of range. + uint64_t GetPosition(int index) const; + + // Sets the Seek Entry id and position at given index. + // Returns true on success. + bool SetSeekEntry(int index, uint32_t id, uint64_t position); + + // Reserves space by writing out a Void element which will be updated with + // a SeekHead element later. Returns true on success. + bool Write(IMkvWriter* writer); + + // We are going to put a cap on the number of Seek Entries. + const static int32_t kSeekEntryCount = 5; + + private: + // Returns the maximum size in bytes of one seek entry. + uint64_t MaxEntrySize() const; + + // Seek entry id element list. + uint32_t seek_entry_id_[kSeekEntryCount]; + + // Seek entry pos element list. + uint64_t seek_entry_pos_[kSeekEntryCount]; + + // The file position of SeekHead element. + int64_t start_pos_; + + LIBWEBM_DISALLOW_COPY_AND_ASSIGN(SeekHead); +}; + +/////////////////////////////////////////////////////////////// +// Segment Information element +class SegmentInfo { + public: + SegmentInfo(); + ~SegmentInfo(); + + // Will update the duration if |duration_| is > 0.0. Returns true on success. + bool Finalize(IMkvWriter* writer) const; + + // Sets |muxing_app_| and |writing_app_|. + bool Init(); + + // Output the Segment Information element to the writer. Returns true on + // success. + bool Write(IMkvWriter* writer); + + void set_duration(double duration) { duration_ = duration; } + double duration() const { return duration_; } + void set_muxing_app(const char* app); + const char* muxing_app() const { return muxing_app_; } + void set_timecode_scale(uint64_t scale) { timecode_scale_ = scale; } + uint64_t timecode_scale() const { return timecode_scale_; } + void set_writing_app(const char* app); + const char* writing_app() const { return writing_app_; } + void set_date_utc(int64_t date_utc) { date_utc_ = date_utc; } + int64_t date_utc() const { return date_utc_; } + + private: + // Segment Information element names. + // Initially set to -1 to signify that a duration has not been set and should + // not be written out. + double duration_; + // Set to libwebm-%d.%d.%d.%d, major, minor, build, revision. + char* muxing_app_; + uint64_t timecode_scale_; + // Initially set to libwebm-%d.%d.%d.%d, major, minor, build, revision. + char* writing_app_; + // LLONG_MIN when DateUTC is not set. + int64_t date_utc_; + + // The file position of the duration element. + int64_t duration_pos_; + + LIBWEBM_DISALLOW_COPY_AND_ASSIGN(SegmentInfo); +}; + +/////////////////////////////////////////////////////////////// +// This class represents the main segment in a WebM file. Currently only +// supports one Segment element. +// +// Notes: +// |Init| must be called before any other method in this class. +class Segment { + public: + enum Mode { kLive = 0x1, kFile = 0x2 }; + + enum CuesPosition { + kAfterClusters = 0x0, // Position Cues after Clusters - Default + kBeforeClusters = 0x1 // Position Cues before Clusters + }; + + static const uint32_t kDefaultDocTypeVersion = 4; + static const uint64_t kDefaultMaxClusterDuration = 30000000000ULL; + + Segment(); + ~Segment(); + + // Initializes |SegmentInfo| and returns result. Always returns false when + // |ptr_writer| is NULL. + bool Init(IMkvWriter* ptr_writer); + + // Adds a generic track to the segment. Returns the newly-allocated + // track object (which is owned by the segment) on success, NULL on + // error. |number| is the number to use for the track. |number| + // must be >= 0. If |number| == 0 then the muxer will decide on the + // track number. + Track* AddTrack(int32_t number); + + // Adds a Vorbis audio track to the segment. Returns the number of the track + // on success, 0 on error. |number| is the number to use for the audio track. + // |number| must be >= 0. If |number| == 0 then the muxer will decide on + // the track number. + uint64_t AddAudioTrack(int32_t sample_rate, int32_t channels, int32_t number); + + // Adds an empty chapter to the chapters of this segment. Returns + // non-NULL on success. After adding the chapter, the caller should + // populate its fields via the Chapter member functions. + Chapter* AddChapter(); + + // Adds an empty tag to the tags of this segment. Returns + // non-NULL on success. After adding the tag, the caller should + // populate its fields via the Tag member functions. + Tag* AddTag(); + + // Adds a cue point to the Cues element. |timestamp| is the time in + // nanoseconds of the cue's time. |track| is the Track of the Cue. This + // function must be called after AddFrame to calculate the correct + // BlockNumber for the CuePoint. Returns true on success. + bool AddCuePoint(uint64_t timestamp, uint64_t track); + + // Adds a frame to be output in the file. Returns true on success. + // Inputs: + // data: Pointer to the data + // length: Length of the data + // track_number: Track to add the data to. Value returned by Add track + // functions. + // timestamp: Timestamp of the frame in nanoseconds from 0. + // is_key: Flag telling whether or not this frame is a key frame. + bool AddFrame(const uint8_t* data, uint64_t length, uint64_t track_number, + uint64_t timestamp_ns, bool is_key); + + // Writes a frame of metadata to the output medium; returns true on + // success. + // Inputs: + // data: Pointer to the data + // length: Length of the data + // track_number: Track to add the data to. Value returned by Add track + // functions. + // timecode: Absolute timestamp of the metadata frame, expressed + // in nanosecond units. + // duration: Duration of metadata frame, in nanosecond units. + // + // The metadata frame is written as a block group, with a duration + // sub-element but no reference time sub-elements (indicating that + // it is considered a keyframe, per Matroska semantics). + bool AddMetadata(const uint8_t* data, uint64_t length, uint64_t track_number, + uint64_t timestamp_ns, uint64_t duration_ns); + + // Writes a frame with additional data to the output medium; returns true on + // success. + // Inputs: + // data: Pointer to the data. + // length: Length of the data. + // additional: Pointer to additional data. + // additional_length: Length of additional data. + // add_id: Additional ID which identifies the type of additional data. + // track_number: Track to add the data to. Value returned by Add track + // functions. + // timestamp: Absolute timestamp of the frame, expressed in nanosecond + // units. + // is_key: Flag telling whether or not this frame is a key frame. + bool AddFrameWithAdditional(const uint8_t* data, uint64_t length, + const uint8_t* additional, + uint64_t additional_length, uint64_t add_id, + uint64_t track_number, uint64_t timestamp, + bool is_key); + + // Writes a frame with DiscardPadding to the output medium; returns true on + // success. + // Inputs: + // data: Pointer to the data. + // length: Length of the data. + // discard_padding: DiscardPadding element value. + // track_number: Track to add the data to. Value returned by Add track + // functions. + // timestamp: Absolute timestamp of the frame, expressed in nanosecond + // units. + // is_key: Flag telling whether or not this frame is a key frame. + bool AddFrameWithDiscardPadding(const uint8_t* data, uint64_t length, + int64_t discard_padding, + uint64_t track_number, uint64_t timestamp, + bool is_key); + + // Writes a Frame to the output medium. Chooses the correct way of writing + // the frame (Block vs SimpleBlock) based on the parameters passed. + // Inputs: + // frame: frame object + bool AddGenericFrame(const Frame* frame); + + // Adds a VP8 video track to the segment. Returns the number of the track on + // success, 0 on error. |number| is the number to use for the video track. + // |number| must be >= 0. If |number| == 0 then the muxer will decide on + // the track number. + uint64_t AddVideoTrack(int32_t width, int32_t height, int32_t number); + + // This function must be called after Finalize() if you need a copy of the + // output with Cues written before the Clusters. It will return false if the + // writer is not seekable of if chunking is set to true. + // Input parameters: + // reader - an IMkvReader object created with the same underlying file of the + // current writer object. Make sure to close the existing writer + // object before creating this so that all the data is properly + // flushed and available for reading. + // writer - an IMkvWriter object pointing to a *different* file than the one + // pointed by the current writer object. This file will contain the + // Cues element before the Clusters. + bool CopyAndMoveCuesBeforeClusters(mkvparser::IMkvReader* reader, + IMkvWriter* writer); + + // Sets which track to use for the Cues element. Must have added the track + // before calling this function. Returns true on success. |track_number| is + // returned by the Add track functions. + bool CuesTrack(uint64_t track_number); + + // This will force the muxer to create a new Cluster when the next frame is + // added. + void ForceNewClusterOnNextFrame(); + + // Writes out any frames that have not been written out. Finalizes the last + // cluster. May update the size and duration of the segment. May output the + // Cues element. May finalize the SeekHead element. Returns true on success. + bool Finalize(); + + // Returns the Cues object. + Cues* GetCues() { return &cues_; } + + // Returns the Segment Information object. + const SegmentInfo* GetSegmentInfo() const { return &segment_info_; } + SegmentInfo* GetSegmentInfo() { return &segment_info_; } + + // Search the Tracks and return the track that matches |track_number|. + // Returns NULL if there is no track match. + Track* GetTrackByNumber(uint64_t track_number) const; + + // Toggles whether to output a cues element. + void OutputCues(bool output_cues); + + // Toggles whether to write the last frame in each Cluster with Duration. + void AccurateClusterDuration(bool accurate_cluster_duration); + + // Toggles whether to write the Cluster Timecode using exactly 8 bytes. + void UseFixedSizeClusterTimecode(bool fixed_size_cluster_timecode); + + // Sets if the muxer will output files in chunks or not. |chunking| is a + // flag telling whether or not to turn on chunking. |filename| is the base + // filename for the chunk files. The header chunk file will be named + // |filename|.hdr and the data chunks will be named + // |filename|_XXXXXX.chk. Chunking implies that the muxer will be writing + // to files so the muxer will use the default MkvWriter class to control + // what data is written to what files. Returns true on success. + // TODO: Should we change the IMkvWriter Interface to add Open and Close? + // That will force the interface to be dependent on files. + bool SetChunking(bool chunking, const char* filename); + + bool chunking() const { return chunking_; } + uint64_t cues_track() const { return cues_track_; } + void set_max_cluster_duration(uint64_t max_cluster_duration) { + max_cluster_duration_ = max_cluster_duration; + } + uint64_t max_cluster_duration() const { return max_cluster_duration_; } + void set_max_cluster_size(uint64_t max_cluster_size) { + max_cluster_size_ = max_cluster_size; + } + uint64_t max_cluster_size() const { return max_cluster_size_; } + void set_mode(Mode mode) { mode_ = mode; } + Mode mode() const { return mode_; } + CuesPosition cues_position() const { return cues_position_; } + bool output_cues() const { return output_cues_; } + void set_estimate_file_duration(bool estimate_duration) { + estimate_file_duration_ = estimate_duration; + } + bool estimate_file_duration() const { return estimate_file_duration_; } + const SegmentInfo* segment_info() const { return &segment_info_; } + void set_duration(double duration) { duration_ = duration; } + double duration() const { return duration_; } + + // Returns true when codec IDs are valid for WebM. + bool DocTypeIsWebm() const; + + private: + // Checks if header information has been output and initialized. If not it + // will output the Segment element and initialize the SeekHead elment and + // Cues elements. + bool CheckHeaderInfo(); + + // Sets |doc_type_version_| based on the current element requirements. + void UpdateDocTypeVersion(); + + // Sets |name| according to how many chunks have been written. |ext| is the + // file extension. |name| must be deleted by the calling app. Returns true + // on success. + bool UpdateChunkName(const char* ext, char** name) const; + + // Returns the maximum offset within the segment's payload. When chunking + // this function is needed to determine offsets of elements within the + // chunked files. Returns -1 on error. + int64_t MaxOffset(); + + // Adds the frame to our frame array. + bool QueueFrame(Frame* frame); + + // Output all frames that are queued. Returns -1 on error, otherwise + // it returns the number of frames written. + int WriteFramesAll(); + + // Output all frames that are queued that have an end time that is less + // then |timestamp|. Returns true on success and if there are no frames + // queued. + bool WriteFramesLessThan(uint64_t timestamp); + + // Outputs the segment header, Segment Information element, SeekHead element, + // and Tracks element to |writer_|. + bool WriteSegmentHeader(); + + // Given a frame with the specified timestamp (nanosecond units) and + // keyframe status, determine whether a new cluster should be + // created, before writing enqueued frames and the frame itself. The + // function returns one of the following values: + // -1 = error: an out-of-order frame was detected + // 0 = do not create a new cluster, and write frame to the existing cluster + // 1 = create a new cluster, and write frame to that new cluster + // 2 = create a new cluster, and re-run test + int TestFrame(uint64_t track_num, uint64_t timestamp_ns, bool key) const; + + // Create a new cluster, using the earlier of the first enqueued + // frame, or the indicated time. Returns true on success. + bool MakeNewCluster(uint64_t timestamp_ns); + + // Checks whether a new cluster needs to be created, and if so + // creates a new cluster. Returns false if creation of a new cluster + // was necessary but creation was not successful. + bool DoNewClusterProcessing(uint64_t track_num, uint64_t timestamp_ns, + bool key); + + // Adjusts Cue Point values (to place Cues before Clusters) so that they + // reflect the correct offsets. + void MoveCuesBeforeClusters(); + + // This function recursively computes the correct cluster offsets (this is + // done to move the Cues before Clusters). It recursively updates the change + // in size (which indicates a change in cluster offset) until no sizes change. + // Parameters: + // diff - indicates the difference in size of the Cues element that needs to + // accounted for. + // index - index in the list of Cues which is currently being adjusted. + // cue_size - sum of size of all the CuePoint elements. + void MoveCuesBeforeClustersHelper(uint64_t diff, int index, + uint64_t* cue_size); + + // Seeds the random number generator used to make UIDs. + unsigned int seed_; + + // WebM elements + Cues cues_; + SeekHead seek_head_; + SegmentInfo segment_info_; + Tracks tracks_; + Chapters chapters_; + Tags tags_; + + // Number of chunks written. + int chunk_count_; + + // Current chunk filename. + char* chunk_name_; + + // Default MkvWriter object created by this class used for writing clusters + // out in separate files. + MkvWriter* chunk_writer_cluster_; + + // Default MkvWriter object created by this class used for writing Cues + // element out to a file. + MkvWriter* chunk_writer_cues_; + + // Default MkvWriter object created by this class used for writing the + // Matroska header out to a file. + MkvWriter* chunk_writer_header_; + + // Flag telling whether or not the muxer is chunking output to multiple + // files. + bool chunking_; + + // Base filename for the chunked files. + char* chunking_base_name_; + + // File position offset where the Clusters end. + int64_t cluster_end_offset_; + + // List of clusters. + Cluster** cluster_list_; + + // Number of cluster pointers allocated in the cluster list. + int32_t cluster_list_capacity_; + + // Number of clusters in the cluster list. + int32_t cluster_list_size_; + + // Indicates whether Cues should be written before or after Clusters + CuesPosition cues_position_; + + // Track number that is associated with the cues element for this segment. + uint64_t cues_track_; + + // Tells the muxer to force a new cluster on the next Block. + bool force_new_cluster_; + + // List of stored audio frames. These variables are used to store frames so + // the muxer can follow the guideline "Audio blocks that contain the video + // key frame's timecode should be in the same cluster as the video key frame + // block." + Frame** frames_; + + // Number of frame pointers allocated in the frame list. + int32_t frames_capacity_; + + // Number of frames in the frame list. + int32_t frames_size_; + + // Flag telling if a video track has been added to the segment. + bool has_video_; + + // Flag telling if the segment's header has been written. + bool header_written_; + + // Duration of the last block in nanoseconds. + uint64_t last_block_duration_; + + // Last timestamp in nanoseconds added to a cluster. + uint64_t last_timestamp_; + + // Last timestamp in nanoseconds by track number added to a cluster. + uint64_t last_track_timestamp_[kMaxTrackNumber]; + + // Number of frames written per track. + uint64_t track_frames_written_[kMaxTrackNumber]; + + // Maximum time in nanoseconds for a cluster duration. This variable is a + // guideline and some clusters may have a longer duration. Default is 30 + // seconds. + uint64_t max_cluster_duration_; + + // Maximum size in bytes for a cluster. This variable is a guideline and + // some clusters may have a larger size. Default is 0 which signifies that + // the muxer will decide the size. + uint64_t max_cluster_size_; + + // The mode that segment is in. If set to |kLive| the writer must not + // seek backwards. + Mode mode_; + + // Flag telling the muxer that a new cue point should be added. + bool new_cuepoint_; + + // TODO(fgalligan): Should we add support for more than one Cues element? + // Flag whether or not the muxer should output a Cues element. + bool output_cues_; + + // Flag whether or not the last frame in each Cluster will have a Duration + // element in it. + bool accurate_cluster_duration_; + + // Flag whether or not to write the Cluster Timecode using exactly 8 bytes. + bool fixed_size_cluster_timecode_; + + // Flag whether or not to estimate the file duration. + bool estimate_file_duration_; + + // The size of the EBML header, used to validate the header if + // WriteEbmlHeader() is called more than once. + int32_t ebml_header_size_; + + // The file position of the segment's payload. + int64_t payload_pos_; + + // The file position of the element's size. + int64_t size_position_; + + // Current DocTypeVersion (|doc_type_version_|) and that written in + // WriteSegmentHeader(). + // WriteEbmlHeader() will be called from Finalize() if |doc_type_version_| + // differs from |doc_type_version_written_|. + uint32_t doc_type_version_; + uint32_t doc_type_version_written_; + + // If |duration_| is > 0, then explicitly set the duration of the segment. + double duration_; + + // Pointer to the writer objects. Not owned by this class. + IMkvWriter* writer_cluster_; + IMkvWriter* writer_cues_; + IMkvWriter* writer_header_; + + LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Segment); +}; + +} // namespace mkvmuxer + +#endif // MKVMUXER_MKVMUXER_H_ diff --git a/third_party/libwebm/source/mkvmuxer/mkvmuxertypes.h b/third_party/libwebm/source/mkvmuxer/mkvmuxertypes.h new file mode 100644 index 000000000000..e5db121605f6 --- /dev/null +++ b/third_party/libwebm/source/mkvmuxer/mkvmuxertypes.h @@ -0,0 +1,28 @@ +// Copyright (c) 2012 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. + +#ifndef MKVMUXER_MKVMUXERTYPES_H_ +#define MKVMUXER_MKVMUXERTYPES_H_ + +namespace mkvmuxer { +typedef unsigned char uint8; +typedef short int16; +typedef int int32; +typedef unsigned int uint32; +typedef long long int64; +typedef unsigned long long uint64; +} // namespace mkvmuxer + +// Copied from Chromium basictypes.h +// A macro to disallow the copy constructor and operator= functions +// This should be used in the private: declarations for a class +#define LIBWEBM_DISALLOW_COPY_AND_ASSIGN(TypeName) \ + TypeName(const TypeName&); \ + void operator=(const TypeName&) + +#endif // MKVMUXER_MKVMUXERTYPES_HPP_ diff --git a/third_party/libwebm/source/mkvmuxer/mkvmuxerutil.cc b/third_party/libwebm/source/mkvmuxer/mkvmuxerutil.cc new file mode 100644 index 000000000000..bd2f76913811 --- /dev/null +++ b/third_party/libwebm/source/mkvmuxer/mkvmuxerutil.cc @@ -0,0 +1,743 @@ +// Copyright (c) 2012 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. + +#include "mkvmuxer/mkvmuxerutil.h" + +#ifdef __ANDROID__ +#include +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include "common/webmids.h" +#include "mkvmuxer/mkvmuxer.h" +#include "mkvmuxer/mkvwriter.h" + +namespace mkvmuxer { + +namespace { + +// Date elements are always 8 octets in size. +const int kDateElementSize = 8; + +uint64 WriteBlock(IMkvWriter* writer, const Frame* const frame, int64 timecode, + uint64 timecode_scale) { + uint64 block_additional_elem_size = 0; + uint64 block_addid_elem_size = 0; + uint64 block_more_payload_size = 0; + uint64 block_more_elem_size = 0; + uint64 block_additions_payload_size = 0; + uint64 block_additions_elem_size = 0; + if (frame->additional()) { + block_additional_elem_size = + EbmlElementSize(libwebm::kMkvBlockAdditional, frame->additional(), + frame->additional_length()); + block_addid_elem_size = EbmlElementSize( + libwebm::kMkvBlockAddID, static_cast(frame->add_id())); + + block_more_payload_size = + block_addid_elem_size + block_additional_elem_size; + block_more_elem_size = + EbmlMasterElementSize(libwebm::kMkvBlockMore, block_more_payload_size) + + block_more_payload_size; + block_additions_payload_size = block_more_elem_size; + block_additions_elem_size = + EbmlMasterElementSize(libwebm::kMkvBlockAdditions, + block_additions_payload_size) + + block_additions_payload_size; + } + + uint64 discard_padding_elem_size = 0; + if (frame->discard_padding() != 0) { + discard_padding_elem_size = + EbmlElementSize(libwebm::kMkvDiscardPadding, + static_cast(frame->discard_padding())); + } + + const uint64 reference_block_timestamp = + frame->reference_block_timestamp() / timecode_scale; + uint64 reference_block_elem_size = 0; + if (!frame->is_key()) { + reference_block_elem_size = + EbmlElementSize(libwebm::kMkvReferenceBlock, reference_block_timestamp); + } + + const uint64 duration = frame->duration() / timecode_scale; + uint64 block_duration_elem_size = 0; + if (duration > 0) + block_duration_elem_size = + EbmlElementSize(libwebm::kMkvBlockDuration, duration); + + const uint64 block_payload_size = 4 + frame->length(); + const uint64 block_elem_size = + EbmlMasterElementSize(libwebm::kMkvBlock, block_payload_size) + + block_payload_size; + + const uint64 block_group_payload_size = + block_elem_size + block_additions_elem_size + block_duration_elem_size + + discard_padding_elem_size + reference_block_elem_size; + + if (!WriteEbmlMasterElement(writer, libwebm::kMkvBlockGroup, + block_group_payload_size)) { + return 0; + } + + if (!WriteEbmlMasterElement(writer, libwebm::kMkvBlock, block_payload_size)) + return 0; + + if (WriteUInt(writer, frame->track_number())) + return 0; + + if (SerializeInt(writer, timecode, 2)) + return 0; + + // For a Block, flags is always 0. + if (SerializeInt(writer, 0, 1)) + return 0; + + if (writer->Write(frame->frame(), static_cast(frame->length()))) + return 0; + + if (frame->additional()) { + if (!WriteEbmlMasterElement(writer, libwebm::kMkvBlockAdditions, + block_additions_payload_size)) { + return 0; + } + + if (!WriteEbmlMasterElement(writer, libwebm::kMkvBlockMore, + block_more_payload_size)) + return 0; + + if (!WriteEbmlElement(writer, libwebm::kMkvBlockAddID, + static_cast(frame->add_id()))) + return 0; + + if (!WriteEbmlElement(writer, libwebm::kMkvBlockAdditional, + frame->additional(), frame->additional_length())) { + return 0; + } + } + + if (frame->discard_padding() != 0 && + !WriteEbmlElement(writer, libwebm::kMkvDiscardPadding, + static_cast(frame->discard_padding()))) { + return false; + } + + if (!frame->is_key() && !WriteEbmlElement(writer, libwebm::kMkvReferenceBlock, + reference_block_timestamp)) { + return false; + } + + if (duration > 0 && + !WriteEbmlElement(writer, libwebm::kMkvBlockDuration, duration)) { + return false; + } + return EbmlMasterElementSize(libwebm::kMkvBlockGroup, + block_group_payload_size) + + block_group_payload_size; +} + +uint64 WriteSimpleBlock(IMkvWriter* writer, const Frame* const frame, + int64 timecode) { + if (WriteID(writer, libwebm::kMkvSimpleBlock)) + return 0; + + const int32 size = static_cast(frame->length()) + 4; + if (WriteUInt(writer, size)) + return 0; + + if (WriteUInt(writer, static_cast(frame->track_number()))) + return 0; + + if (SerializeInt(writer, timecode, 2)) + return 0; + + uint64 flags = 0; + if (frame->is_key()) + flags |= 0x80; + + if (SerializeInt(writer, flags, 1)) + return 0; + + if (writer->Write(frame->frame(), static_cast(frame->length()))) + return 0; + + return GetUIntSize(libwebm::kMkvSimpleBlock) + GetCodedUIntSize(size) + 4 + + frame->length(); +} + +} // namespace + +int32 GetCodedUIntSize(uint64 value) { + if (value < 0x000000000000007FULL) + return 1; + else if (value < 0x0000000000003FFFULL) + return 2; + else if (value < 0x00000000001FFFFFULL) + return 3; + else if (value < 0x000000000FFFFFFFULL) + return 4; + else if (value < 0x00000007FFFFFFFFULL) + return 5; + else if (value < 0x000003FFFFFFFFFFULL) + return 6; + else if (value < 0x0001FFFFFFFFFFFFULL) + return 7; + return 8; +} + +int32 GetUIntSize(uint64 value) { + if (value < 0x0000000000000100ULL) + return 1; + else if (value < 0x0000000000010000ULL) + return 2; + else if (value < 0x0000000001000000ULL) + return 3; + else if (value < 0x0000000100000000ULL) + return 4; + else if (value < 0x0000010000000000ULL) + return 5; + else if (value < 0x0001000000000000ULL) + return 6; + else if (value < 0x0100000000000000ULL) + return 7; + return 8; +} + +int32 GetIntSize(int64 value) { + // Doubling the requested value ensures positive values with their high bit + // set are written with 0-padding to avoid flipping the signedness. + const uint64 v = (value < 0) ? value ^ -1LL : value; + return GetUIntSize(2 * v); +} + +uint64 EbmlMasterElementSize(uint64 type, uint64 value) { + // Size of EBML ID + int32 ebml_size = GetUIntSize(type); + + // Datasize + ebml_size += GetCodedUIntSize(value); + + return ebml_size; +} + +uint64 EbmlElementSize(uint64 type, int64 value) { + // Size of EBML ID + int32 ebml_size = GetUIntSize(type); + + // Datasize + ebml_size += GetIntSize(value); + + // Size of Datasize + ebml_size++; + + return ebml_size; +} + +uint64 EbmlElementSize(uint64 type, uint64 value) { + return EbmlElementSize(type, value, 0); +} + +uint64 EbmlElementSize(uint64 type, uint64 value, uint64 fixed_size) { + // Size of EBML ID + uint64 ebml_size = GetUIntSize(type); + + // Datasize + ebml_size += (fixed_size > 0) ? fixed_size : GetUIntSize(value); + + // Size of Datasize + ebml_size++; + + return ebml_size; +} + +uint64 EbmlElementSize(uint64 type, float /* value */) { + // Size of EBML ID + uint64 ebml_size = GetUIntSize(type); + + // Datasize + ebml_size += sizeof(float); + + // Size of Datasize + ebml_size++; + + return ebml_size; +} + +uint64 EbmlElementSize(uint64 type, const char* value) { + if (!value) + return 0; + + // Size of EBML ID + uint64 ebml_size = GetUIntSize(type); + + // Datasize + ebml_size += strlen(value); + + // Size of Datasize + ebml_size += GetCodedUIntSize(strlen(value)); + + return ebml_size; +} + +uint64 EbmlElementSize(uint64 type, const uint8* value, uint64 size) { + if (!value) + return 0; + + // Size of EBML ID + uint64 ebml_size = GetUIntSize(type); + + // Datasize + ebml_size += size; + + // Size of Datasize + ebml_size += GetCodedUIntSize(size); + + return ebml_size; +} + +uint64 EbmlDateElementSize(uint64 type) { + // Size of EBML ID + uint64 ebml_size = GetUIntSize(type); + + // Datasize + ebml_size += kDateElementSize; + + // Size of Datasize + ebml_size++; + + return ebml_size; +} + +int32 SerializeInt(IMkvWriter* writer, int64 value, int32 size) { + if (!writer || size < 1 || size > 8) + return -1; + + for (int32 i = 1; i <= size; ++i) { + const int32 byte_count = size - i; + const int32 bit_count = byte_count * 8; + + const int64 bb = value >> bit_count; + const uint8 b = static_cast(bb); + + const int32 status = writer->Write(&b, 1); + + if (status < 0) + return status; + } + + return 0; +} + +int32 SerializeFloat(IMkvWriter* writer, float f) { + if (!writer) + return -1; + + assert(sizeof(uint32) == sizeof(float)); + // This union is merely used to avoid a reinterpret_cast from float& to + // uint32& which will result in violation of strict aliasing. + union U32 { + uint32 u32; + float f; + } value; + value.f = f; + + for (int32 i = 1; i <= 4; ++i) { + const int32 byte_count = 4 - i; + const int32 bit_count = byte_count * 8; + + const uint8 byte = static_cast(value.u32 >> bit_count); + + const int32 status = writer->Write(&byte, 1); + + if (status < 0) + return status; + } + + return 0; +} + +int32 WriteUInt(IMkvWriter* writer, uint64 value) { + if (!writer) + return -1; + + int32 size = GetCodedUIntSize(value); + + return WriteUIntSize(writer, value, size); +} + +int32 WriteUIntSize(IMkvWriter* writer, uint64 value, int32 size) { + if (!writer || size < 0 || size > 8) + return -1; + + if (size > 0) { + const uint64 bit = 1LL << (size * 7); + + if (value > (bit - 2)) + return -1; + + value |= bit; + } else { + size = 1; + int64 bit; + + for (;;) { + bit = 1LL << (size * 7); + const uint64 max = bit - 2; + + if (value <= max) + break; + + ++size; + } + + if (size > 8) + return false; + + value |= bit; + } + + return SerializeInt(writer, value, size); +} + +int32 WriteID(IMkvWriter* writer, uint64 type) { + if (!writer) + return -1; + + writer->ElementStartNotify(type, writer->Position()); + + const int32 size = GetUIntSize(type); + + return SerializeInt(writer, type, size); +} + +bool WriteEbmlMasterElement(IMkvWriter* writer, uint64 type, uint64 size) { + if (!writer) + return false; + + if (WriteID(writer, type)) + return false; + + if (WriteUInt(writer, size)) + return false; + + return true; +} + +bool WriteEbmlElement(IMkvWriter* writer, uint64 type, uint64 value) { + return WriteEbmlElement(writer, type, value, 0); +} + +bool WriteEbmlElement(IMkvWriter* writer, uint64 type, uint64 value, + uint64 fixed_size) { + if (!writer) + return false; + + if (WriteID(writer, type)) + return false; + + uint64 size = GetUIntSize(value); + if (fixed_size > 0) { + if (size > fixed_size) + return false; + size = fixed_size; + } + if (WriteUInt(writer, size)) + return false; + + if (SerializeInt(writer, value, static_cast(size))) + return false; + + return true; +} + +bool WriteEbmlElement(IMkvWriter* writer, uint64 type, int64 value) { + if (!writer) + return false; + + if (WriteID(writer, type)) + return 0; + + const uint64 size = GetIntSize(value); + if (WriteUInt(writer, size)) + return false; + + if (SerializeInt(writer, value, static_cast(size))) + return false; + + return true; +} + +bool WriteEbmlElement(IMkvWriter* writer, uint64 type, float value) { + if (!writer) + return false; + + if (WriteID(writer, type)) + return false; + + if (WriteUInt(writer, 4)) + return false; + + if (SerializeFloat(writer, value)) + return false; + + return true; +} + +bool WriteEbmlElement(IMkvWriter* writer, uint64 type, const char* value) { + if (!writer || !value) + return false; + + if (WriteID(writer, type)) + return false; + + const uint64 length = strlen(value); + if (WriteUInt(writer, length)) + return false; + + if (writer->Write(value, static_cast(length))) + return false; + + return true; +} + +bool WriteEbmlElement(IMkvWriter* writer, uint64 type, const uint8* value, + uint64 size) { + if (!writer || !value || size < 1) + return false; + + if (WriteID(writer, type)) + return false; + + if (WriteUInt(writer, size)) + return false; + + if (writer->Write(value, static_cast(size))) + return false; + + return true; +} + +bool WriteEbmlDateElement(IMkvWriter* writer, uint64 type, int64 value) { + if (!writer) + return false; + + if (WriteID(writer, type)) + return false; + + if (WriteUInt(writer, kDateElementSize)) + return false; + + if (SerializeInt(writer, value, kDateElementSize)) + return false; + + return true; +} + +uint64 WriteFrame(IMkvWriter* writer, const Frame* const frame, + Cluster* cluster) { + if (!writer || !frame || !frame->IsValid() || !cluster || + !cluster->timecode_scale()) + return 0; + + // Technically the timecode for a block can be less than the + // timecode for the cluster itself (remember that block timecode + // is a signed, 16-bit integer). However, as a simplification we + // only permit non-negative cluster-relative timecodes for blocks. + const int64 relative_timecode = cluster->GetRelativeTimecode( + frame->timestamp() / cluster->timecode_scale()); + if (relative_timecode < 0 || relative_timecode > kMaxBlockTimecode) + return 0; + + return frame->CanBeSimpleBlock() + ? WriteSimpleBlock(writer, frame, relative_timecode) + : WriteBlock(writer, frame, relative_timecode, + cluster->timecode_scale()); +} + +uint64 WriteVoidElement(IMkvWriter* writer, uint64 size) { + if (!writer) + return false; + + // Subtract one for the void ID and the coded size. + uint64 void_entry_size = size - 1 - GetCodedUIntSize(size - 1); + uint64 void_size = EbmlMasterElementSize(libwebm::kMkvVoid, void_entry_size) + + void_entry_size; + + if (void_size != size) + return 0; + + const int64 payload_position = writer->Position(); + if (payload_position < 0) + return 0; + + if (WriteID(writer, libwebm::kMkvVoid)) + return 0; + + if (WriteUInt(writer, void_entry_size)) + return 0; + + const uint8 value = 0; + for (int32 i = 0; i < static_cast(void_entry_size); ++i) { + if (writer->Write(&value, 1)) + return 0; + } + + const int64 stop_position = writer->Position(); + if (stop_position < 0 || + stop_position - payload_position != static_cast(void_size)) + return 0; + + return void_size; +} + +void GetVersion(int32* major, int32* minor, int32* build, int32* revision) { + *major = 0; + *minor = 3; + *build = 0; + *revision = 0; +} + +uint64 MakeUID(unsigned int* seed) { + uint64 uid = 0; + +#ifdef __MINGW32__ + srand(*seed); +#endif + + for (int i = 0; i < 7; ++i) { // avoid problems with 8-byte values + uid <<= 8; + +// TODO(fgalligan): Move random number generation to platform specific code. +#ifdef _MSC_VER + (void)seed; + const int32 nn = rand(); +#elif __ANDROID__ + (void)seed; + int32 temp_num = 1; + int fd = open("/dev/urandom", O_RDONLY); + if (fd != -1) { + read(fd, &temp_num, sizeof(temp_num)); + close(fd); + } + const int32 nn = temp_num; +#elif defined __MINGW32__ + const int32 nn = rand(); +#else + const int32 nn = rand_r(seed); +#endif + const int32 n = 0xFF & (nn >> 4); // throw away low-order bits + + uid |= n; + } + + return uid; +} + +bool IsMatrixCoefficientsValueValid(uint64_t value) { + switch (value) { + case mkvmuxer::Colour::kGbr: + case mkvmuxer::Colour::kBt709: + case mkvmuxer::Colour::kUnspecifiedMc: + case mkvmuxer::Colour::kReserved: + case mkvmuxer::Colour::kFcc: + case mkvmuxer::Colour::kBt470bg: + case mkvmuxer::Colour::kSmpte170MMc: + case mkvmuxer::Colour::kSmpte240MMc: + case mkvmuxer::Colour::kYcocg: + case mkvmuxer::Colour::kBt2020NonConstantLuminance: + case mkvmuxer::Colour::kBt2020ConstantLuminance: + return true; + } + return false; +} + +bool IsChromaSitingHorzValueValid(uint64_t value) { + switch (value) { + case mkvmuxer::Colour::kUnspecifiedCsh: + case mkvmuxer::Colour::kLeftCollocated: + case mkvmuxer::Colour::kHalfCsh: + return true; + } + return false; +} + +bool IsChromaSitingVertValueValid(uint64_t value) { + switch (value) { + case mkvmuxer::Colour::kUnspecifiedCsv: + case mkvmuxer::Colour::kTopCollocated: + case mkvmuxer::Colour::kHalfCsv: + return true; + } + return false; +} + +bool IsColourRangeValueValid(uint64_t value) { + switch (value) { + case mkvmuxer::Colour::kUnspecifiedCr: + case mkvmuxer::Colour::kBroadcastRange: + case mkvmuxer::Colour::kFullRange: + case mkvmuxer::Colour::kMcTcDefined: + return true; + } + return false; +} + +bool IsTransferCharacteristicsValueValid(uint64_t value) { + switch (value) { + case mkvmuxer::Colour::kIturBt709Tc: + case mkvmuxer::Colour::kUnspecifiedTc: + case mkvmuxer::Colour::kReservedTc: + case mkvmuxer::Colour::kGamma22Curve: + case mkvmuxer::Colour::kGamma28Curve: + case mkvmuxer::Colour::kSmpte170MTc: + case mkvmuxer::Colour::kSmpte240MTc: + case mkvmuxer::Colour::kLinear: + case mkvmuxer::Colour::kLog: + case mkvmuxer::Colour::kLogSqrt: + case mkvmuxer::Colour::kIec6196624: + case mkvmuxer::Colour::kIturBt1361ExtendedColourGamut: + case mkvmuxer::Colour::kIec6196621: + case mkvmuxer::Colour::kIturBt202010bit: + case mkvmuxer::Colour::kIturBt202012bit: + case mkvmuxer::Colour::kSmpteSt2084: + case mkvmuxer::Colour::kSmpteSt4281Tc: + case mkvmuxer::Colour::kAribStdB67Hlg: + return true; + } + return false; +} + +bool IsPrimariesValueValid(uint64_t value) { + switch (value) { + case mkvmuxer::Colour::kReservedP0: + case mkvmuxer::Colour::kIturBt709P: + case mkvmuxer::Colour::kUnspecifiedP: + case mkvmuxer::Colour::kReservedP3: + case mkvmuxer::Colour::kIturBt470M: + case mkvmuxer::Colour::kIturBt470Bg: + case mkvmuxer::Colour::kSmpte170MP: + case mkvmuxer::Colour::kSmpte240MP: + case mkvmuxer::Colour::kFilm: + case mkvmuxer::Colour::kIturBt2020: + case mkvmuxer::Colour::kSmpteSt4281P: + case mkvmuxer::Colour::kJedecP22Phosphors: + return true; + } + return false; +} + +} // namespace mkvmuxer diff --git a/third_party/libwebm/source/mkvmuxer/mkvmuxerutil.h b/third_party/libwebm/source/mkvmuxer/mkvmuxerutil.h new file mode 100644 index 000000000000..3355428bd1e5 --- /dev/null +++ b/third_party/libwebm/source/mkvmuxer/mkvmuxerutil.h @@ -0,0 +1,115 @@ +// Copyright (c) 2012 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +#ifndef MKVMUXER_MKVMUXERUTIL_H_ +#define MKVMUXER_MKVMUXERUTIL_H_ + +#include "mkvmuxertypes.h" + +#include "stdint.h" + +namespace mkvmuxer { +class Cluster; +class Frame; +class IMkvWriter; + +// TODO(tomfinegan): mkvmuxer:: integer types continue to be used here because +// changing them causes pain for downstream projects. It would be nice if a +// solution that allows removal of the mkvmuxer:: integer types while avoiding +// pain for downstream users of libwebm. Considering that mkvmuxerutil.{cc,h} +// are really, for the great majority of cases, EBML size calculation and writer +// functions, perhaps a more EBML focused utility would be the way to go as a +// first step. + +const uint64 kEbmlUnknownValue = 0x01FFFFFFFFFFFFFFULL; +const int64 kMaxBlockTimecode = 0x07FFFLL; + +// Writes out |value| in Big Endian order. Returns 0 on success. +int32 SerializeInt(IMkvWriter* writer, int64 value, int32 size); + +// Writes out |f| in Big Endian order. Returns 0 on success. +int32 SerializeFloat(IMkvWriter* writer, float f); + +// Returns the size in bytes of the element. +int32 GetUIntSize(uint64 value); +int32 GetIntSize(int64 value); +int32 GetCodedUIntSize(uint64 value); +uint64 EbmlMasterElementSize(uint64 type, uint64 value); +uint64 EbmlElementSize(uint64 type, int64 value); +uint64 EbmlElementSize(uint64 type, uint64 value); +uint64 EbmlElementSize(uint64 type, float value); +uint64 EbmlElementSize(uint64 type, const char* value); +uint64 EbmlElementSize(uint64 type, const uint8* value, uint64 size); +uint64 EbmlDateElementSize(uint64 type); + +// Returns the size in bytes of the element assuming that the element was +// written using |fixed_size| bytes. If |fixed_size| is set to zero, then it +// computes the necessary number of bytes based on |value|. +uint64 EbmlElementSize(uint64 type, uint64 value, uint64 fixed_size); + +// Creates an EBML coded number from |value| and writes it out. The size of +// the coded number is determined by the value of |value|. |value| must not +// be in a coded form. Returns 0 on success. +int32 WriteUInt(IMkvWriter* writer, uint64 value); + +// Creates an EBML coded number from |value| and writes it out. The size of +// the coded number is determined by the value of |size|. |value| must not +// be in a coded form. Returns 0 on success. +int32 WriteUIntSize(IMkvWriter* writer, uint64 value, int32 size); + +// Output an Mkv master element. Returns true if the element was written. +bool WriteEbmlMasterElement(IMkvWriter* writer, uint64 value, uint64 size); + +// Outputs an Mkv ID, calls |IMkvWriter::ElementStartNotify|, and passes the +// ID to |SerializeInt|. Returns 0 on success. +int32 WriteID(IMkvWriter* writer, uint64 type); + +// Output an Mkv non-master element. Returns true if the element was written. +bool WriteEbmlElement(IMkvWriter* writer, uint64 type, uint64 value); +bool WriteEbmlElement(IMkvWriter* writer, uint64 type, int64 value); +bool WriteEbmlElement(IMkvWriter* writer, uint64 type, float value); +bool WriteEbmlElement(IMkvWriter* writer, uint64 type, const char* value); +bool WriteEbmlElement(IMkvWriter* writer, uint64 type, const uint8* value, + uint64 size); +bool WriteEbmlDateElement(IMkvWriter* writer, uint64 type, int64 value); + +// Output an Mkv non-master element using fixed size. The element will be +// written out using exactly |fixed_size| bytes. If |fixed_size| is set to zero +// then it computes the necessary number of bytes based on |value|. Returns true +// if the element was written. +bool WriteEbmlElement(IMkvWriter* writer, uint64 type, uint64 value, + uint64 fixed_size); + +// Output a Mkv Frame. It decides the correct element to write (Block vs +// SimpleBlock) based on the parameters of the Frame. +uint64 WriteFrame(IMkvWriter* writer, const Frame* const frame, + Cluster* cluster); + +// Output a void element. |size| must be the entire size in bytes that will be +// void. The function will calculate the size of the void header and subtract +// it from |size|. +uint64 WriteVoidElement(IMkvWriter* writer, uint64 size); + +// Returns the version number of the muxer in |major|, |minor|, |build|, +// and |revision|. +void GetVersion(int32* major, int32* minor, int32* build, int32* revision); + +// Returns a random number to be used for UID, using |seed| to seed +// the random-number generator (see POSIX rand_r() for semantics). +uint64 MakeUID(unsigned int* seed); + +// Colour field validation helpers. All return true when |value| is valid. +bool IsMatrixCoefficientsValueValid(uint64_t value); +bool IsChromaSitingHorzValueValid(uint64_t value); +bool IsChromaSitingVertValueValid(uint64_t value); +bool IsColourRangeValueValid(uint64_t value); +bool IsTransferCharacteristicsValueValid(uint64_t value); +bool IsPrimariesValueValid(uint64_t value); + +} // namespace mkvmuxer + +#endif // MKVMUXER_MKVMUXERUTIL_H_ diff --git a/third_party/libwebm/source/mkvmuxer/mkvwriter.cc b/third_party/libwebm/source/mkvmuxer/mkvwriter.cc new file mode 100644 index 000000000000..d668384d85f4 --- /dev/null +++ b/third_party/libwebm/source/mkvmuxer/mkvwriter.cc @@ -0,0 +1,92 @@ +// Copyright (c) 2012 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. + +#include "mkvmuxer/mkvwriter.h" + +#include + +#ifdef _MSC_VER +#include // for _SH_DENYWR +#endif + +namespace mkvmuxer { + +MkvWriter::MkvWriter() : file_(NULL), writer_owns_file_(true) {} + +MkvWriter::MkvWriter(FILE* fp) : file_(fp), writer_owns_file_(false) {} + +MkvWriter::~MkvWriter() { Close(); } + +int32 MkvWriter::Write(const void* buffer, uint32 length) { + if (!file_) + return -1; + + if (length == 0) + return 0; + + if (buffer == NULL) + return -1; + + const size_t bytes_written = fwrite(buffer, 1, length, file_); + + return (bytes_written == length) ? 0 : -1; +} + +bool MkvWriter::Open(const char* filename) { + if (filename == NULL) + return false; + + if (file_) + return false; + +#ifdef _MSC_VER + file_ = _fsopen(filename, "wb", _SH_DENYWR); +#else + file_ = fopen(filename, "wb"); +#endif + if (file_ == NULL) + return false; + return true; +} + +void MkvWriter::Close() { + if (file_ && writer_owns_file_) { + fclose(file_); + } + file_ = NULL; +} + +int64 MkvWriter::Position() const { + if (!file_) + return 0; + +#ifdef _MSC_VER + return _ftelli64(file_); +#else + return ftell(file_); +#endif +} + +int32 MkvWriter::Position(int64 position) { + if (!file_) + return -1; + +#ifdef _MSC_VER + return _fseeki64(file_, position, SEEK_SET); +#elif defined(_WIN32) + return fseeko64(file_, static_cast(position), SEEK_SET); +#else + return fseeko(file_, static_cast(position), SEEK_SET); +#endif +} + +bool MkvWriter::Seekable() const { return true; } + +void MkvWriter::ElementStartNotify(uint64, int64) {} + +} // namespace mkvmuxer diff --git a/third_party/libwebm/source/mkvmuxer/mkvwriter.h b/third_party/libwebm/source/mkvmuxer/mkvwriter.h new file mode 100644 index 000000000000..4227c63748aa --- /dev/null +++ b/third_party/libwebm/source/mkvmuxer/mkvwriter.h @@ -0,0 +1,51 @@ +// Copyright (c) 2012 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. + +#ifndef MKVMUXER_MKVWRITER_H_ +#define MKVMUXER_MKVWRITER_H_ + +#include + +#include "mkvmuxer/mkvmuxer.h" +#include "mkvmuxer/mkvmuxertypes.h" + +namespace mkvmuxer { + +// Default implementation of the IMkvWriter interface on Windows. +class MkvWriter : public IMkvWriter { + public: + MkvWriter(); + explicit MkvWriter(FILE* fp); + virtual ~MkvWriter(); + + // IMkvWriter interface + virtual int64 Position() const; + virtual int32 Position(int64 position); + virtual bool Seekable() const; + virtual int32 Write(const void* buffer, uint32 length); + virtual void ElementStartNotify(uint64 element_id, int64 position); + + // Creates and opens a file for writing. |filename| is the name of the file + // to open. This function will overwrite the contents of |filename|. Returns + // true on success. + bool Open(const char* filename); + + // Closes an opened file. + void Close(); + + private: + // File handle to output file. + FILE* file_; + bool writer_owns_file_; + + LIBWEBM_DISALLOW_COPY_AND_ASSIGN(MkvWriter); +}; + +} // namespace mkvmuxer + +#endif // MKVMUXER_MKVWRITER_H_ diff --git a/third_party/libwebm/source/mkvmuxer_sample.cc b/third_party/libwebm/source/mkvmuxer_sample.cc new file mode 100644 index 000000000000..0b84d7255634 --- /dev/null +++ b/third_party/libwebm/source/mkvmuxer_sample.cc @@ -0,0 +1,802 @@ +// Copyright (c) 2011 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +#include + +#include +#include +#include +#include +#include +#include + +// libwebm common includes. +#include "common/file_util.h" +#include "common/hdr_util.h" + +// libwebm mkvparser includes +#include "mkvparser/mkvparser.h" +#include "mkvparser/mkvreader.h" + +// libwebm mkvmuxer includes +#include "mkvmuxer/mkvmuxer.h" +#include "mkvmuxer/mkvmuxertypes.h" +#include "mkvmuxer/mkvwriter.h" + +#include "sample_muxer_metadata.h" + +namespace { + +void Usage() { + printf("Usage: mkvmuxer_sample -i input -o output [options]\n"); + printf("\n"); + printf("Main options:\n"); + printf(" -h | -? show help\n"); + printf(" -video >0 outputs video\n"); + printf(" -audio >0 outputs audio\n"); + printf(" -live >0 puts the muxer into live mode\n"); + printf(" 0 puts the muxer into file mode\n"); + printf(" -output_cues >0 outputs cues element\n"); + printf(" -cues_on_video_track >0 outputs cues on video track\n"); + printf(" -cues_on_audio_track >0 outputs cues on audio track\n"); + printf(" -max_cluster_duration in seconds\n"); + printf(" -max_cluster_size in bytes\n"); + printf(" -switch_tracks >0 switches tracks in output\n"); + printf(" -audio_track_number >0 Changes the audio track number\n"); + printf(" -video_track_number >0 Changes the video track number\n"); + printf(" -chunking Chunk output\n"); + printf(" -copy_tags >0 Copies the tags\n"); + printf(" -accurate_cluster_duration "); + printf(">0 Writes the last frame in each cluster with Duration\n"); + printf(" -fixed_size_cluster_timecode "); + printf(">0 Writes the cluster timecode using exactly 8 bytes\n"); + printf(" -copy_input_duration >0 Copies the input duration\n"); + printf("\n"); + printf("Video options:\n"); + printf(" -display_width Display width in pixels\n"); + printf(" -display_height Display height in pixels\n"); + printf(" -pixel_width Override pixel width\n"); + printf(" -pixel_height Override pixel height\n"); + printf(" -projection_type Set/override projection type:\n"); + printf(" 0: Rectangular\n"); + printf(" 1: Equirectangular\n"); + printf(" 2: Cube map\n"); + printf(" 3: Mesh\n"); + printf(" -projection_file Override projection private data\n"); + printf(" with contents of this file\n"); + printf(" -projection_pose_yaw Projection pose yaw\n"); + printf(" -projection_pose_pitch Projection pose pitch\n"); + printf(" -projection_pose_roll Projection pose roll\n"); + printf(" -stereo_mode 3D video mode\n"); + printf("\n"); + printf("VP9 options:\n"); + printf(" -profile VP9 profile\n"); + printf(" -level VP9 level\n"); + printf("\n"); + printf("Cues options:\n"); + printf(" -output_cues_block_number >0 outputs cue block number\n"); + printf(" -cues_before_clusters >0 puts Cues before Clusters\n"); + printf("\n"); + printf("Metadata options:\n"); + printf(" -webvtt-subtitles "); + printf("add WebVTT subtitles as metadata track\n"); + printf(" -webvtt-captions "); + printf("add WebVTT captions as metadata track\n"); + printf(" -webvtt-descriptions "); + printf("add WebVTT descriptions as metadata track\n"); + printf(" -webvtt-metadata "); + printf("add WebVTT subtitles as metadata track\n"); + printf(" -webvtt-chapters "); + printf("add WebVTT chapters as MKV chapters element\n"); +} + +struct MetadataFile { + const char* name; + SampleMuxerMetadata::Kind kind; +}; + +typedef std::list metadata_files_t; + +// Cache the WebVTT filenames specified as command-line args. +bool LoadMetadataFiles(const metadata_files_t& files, + SampleMuxerMetadata* metadata) { + typedef metadata_files_t::const_iterator iter_t; + + iter_t i = files.begin(); + const iter_t j = files.end(); + + while (i != j) { + const metadata_files_t::value_type& v = *i++; + + if (!metadata->Load(v.name, v.kind)) + return false; + } + + return true; +} + +int ParseArgWebVTT(char* argv[], int* argv_index, int argc_check, + metadata_files_t* metadata_files) { + int& i = *argv_index; + + enum { kCount = 5 }; + struct Arg { + const char* name; + SampleMuxerMetadata::Kind kind; + }; + const Arg args[kCount] = { + {"-webvtt-subtitles", SampleMuxerMetadata::kSubtitles}, + {"-webvtt-captions", SampleMuxerMetadata::kCaptions}, + {"-webvtt-descriptions", SampleMuxerMetadata::kDescriptions}, + {"-webvtt-metadata", SampleMuxerMetadata::kMetadata}, + {"-webvtt-chapters", SampleMuxerMetadata::kChapters}}; + + for (int idx = 0; idx < kCount; ++idx) { + const Arg& arg = args[idx]; + + if (strcmp(arg.name, argv[i]) != 0) // no match + continue; + + ++i; // consume arg name here + + if (i > argc_check) { + printf("missing value for %s\n", arg.name); + return -1; // error + } + + MetadataFile f; + f.name = argv[i]; // arg value is consumed via caller's loop idx + f.kind = arg.kind; + + metadata_files->push_back(f); + return 1; // successfully parsed WebVTT arg + } + + return 0; // not a WebVTT arg +} + +bool CopyVideoProjection(const mkvparser::Projection& parser_projection, + mkvmuxer::Projection* muxer_projection) { + typedef mkvmuxer::Projection::ProjectionType MuxerProjType; + const int kTypeNotPresent = mkvparser::Projection::kTypeNotPresent; + if (parser_projection.type != kTypeNotPresent) { + muxer_projection->set_type( + static_cast(parser_projection.type)); + } + if (parser_projection.private_data && + parser_projection.private_data_length > 0) { + if (!muxer_projection->SetProjectionPrivate( + parser_projection.private_data, + parser_projection.private_data_length)) { + return false; + } + } + + const float kValueNotPresent = mkvparser::Projection::kValueNotPresent; + if (parser_projection.pose_yaw != kValueNotPresent) + muxer_projection->set_pose_yaw(parser_projection.pose_yaw); + if (parser_projection.pose_pitch != kValueNotPresent) + muxer_projection->set_pose_pitch(parser_projection.pose_pitch); + if (parser_projection.pose_roll != kValueNotPresent) + muxer_projection->set_pose_roll(parser_projection.pose_roll); + return true; +} +} // end namespace + +int main(int argc, char* argv[]) { + char* input = NULL; + char* output = NULL; + + // Segment variables + bool output_video = true; + bool output_audio = true; + bool live_mode = false; + bool output_cues = true; + bool cues_before_clusters = false; + bool cues_on_video_track = true; + bool cues_on_audio_track = false; + uint64_t max_cluster_duration = 0; + uint64_t max_cluster_size = 0; + bool switch_tracks = false; + int audio_track_number = 0; // 0 tells muxer to decide. + int video_track_number = 0; // 0 tells muxer to decide. + bool chunking = false; + bool copy_tags = false; + const char* chunk_name = NULL; + bool accurate_cluster_duration = false; + bool fixed_size_cluster_timecode = false; + bool copy_input_duration = false; + + bool output_cues_block_number = true; + + uint64_t display_width = 0; + uint64_t display_height = 0; + uint64_t pixel_width = 0; + uint64_t pixel_height = 0; + uint64_t stereo_mode = 0; + const char* projection_file = 0; + int64_t projection_type = mkvparser::Projection::kTypeNotPresent; + float projection_pose_roll = mkvparser::Projection::kValueNotPresent; + float projection_pose_pitch = mkvparser::Projection::kValueNotPresent; + float projection_pose_yaw = mkvparser::Projection::kValueNotPresent; + int vp9_profile = -1; // No profile set. + int vp9_level = -1; // No level set. + + metadata_files_t metadata_files; + + const int argc_check = argc - 1; + for (int i = 1; i < argc; ++i) { + char* end; + + if (!strcmp("-h", argv[i]) || !strcmp("-?", argv[i])) { + Usage(); + return EXIT_SUCCESS; + } else if (!strcmp("-i", argv[i]) && i < argc_check) { + input = argv[++i]; + } else if (!strcmp("-o", argv[i]) && i < argc_check) { + output = argv[++i]; + } else if (!strcmp("-video", argv[i]) && i < argc_check) { + output_video = strtol(argv[++i], &end, 10) == 0 ? false : true; + } else if (!strcmp("-audio", argv[i]) && i < argc_check) { + output_audio = strtol(argv[++i], &end, 10) == 0 ? false : true; + } else if (!strcmp("-live", argv[i]) && i < argc_check) { + live_mode = strtol(argv[++i], &end, 10) == 0 ? false : true; + } else if (!strcmp("-output_cues", argv[i]) && i < argc_check) { + output_cues = strtol(argv[++i], &end, 10) == 0 ? false : true; + } else if (!strcmp("-cues_before_clusters", argv[i]) && i < argc_check) { + cues_before_clusters = strtol(argv[++i], &end, 10) == 0 ? false : true; + } else if (!strcmp("-cues_on_video_track", argv[i]) && i < argc_check) { + cues_on_video_track = strtol(argv[++i], &end, 10) == 0 ? false : true; + if (cues_on_video_track) + cues_on_audio_track = false; + } else if (!strcmp("-cues_on_audio_track", argv[i]) && i < argc_check) { + cues_on_audio_track = strtol(argv[++i], &end, 10) == 0 ? false : true; + if (cues_on_audio_track) + cues_on_video_track = false; + } else if (!strcmp("-max_cluster_duration", argv[i]) && i < argc_check) { + const double seconds = strtod(argv[++i], &end); + max_cluster_duration = static_cast(seconds * 1000000000.0); + } else if (!strcmp("-max_cluster_size", argv[i]) && i < argc_check) { + max_cluster_size = strtol(argv[++i], &end, 10); + } else if (!strcmp("-switch_tracks", argv[i]) && i < argc_check) { + switch_tracks = strtol(argv[++i], &end, 10) == 0 ? false : true; + } else if (!strcmp("-audio_track_number", argv[i]) && i < argc_check) { + audio_track_number = static_cast(strtol(argv[++i], &end, 10)); + } else if (!strcmp("-video_track_number", argv[i]) && i < argc_check) { + video_track_number = static_cast(strtol(argv[++i], &end, 10)); + } else if (!strcmp("-chunking", argv[i]) && i < argc_check) { + chunking = true; + chunk_name = argv[++i]; + } else if (!strcmp("-copy_tags", argv[i]) && i < argc_check) { + copy_tags = strtol(argv[++i], &end, 10) == 0 ? false : true; + } else if (!strcmp("-accurate_cluster_duration", argv[i]) && + i < argc_check) { + accurate_cluster_duration = + strtol(argv[++i], &end, 10) == 0 ? false : true; + } else if (!strcmp("-fixed_size_cluster_timecode", argv[i]) && + i < argc_check) { + fixed_size_cluster_timecode = + strtol(argv[++i], &end, 10) == 0 ? false : true; + } else if (!strcmp("-copy_input_duration", argv[i]) && i < argc_check) { + copy_input_duration = strtol(argv[++i], &end, 10) == 0 ? false : true; + } else if (!strcmp("-display_width", argv[i]) && i < argc_check) { + display_width = strtol(argv[++i], &end, 10); + } else if (!strcmp("-display_height", argv[i]) && i < argc_check) { + display_height = strtol(argv[++i], &end, 10); + } else if (!strcmp("-pixel_width", argv[i]) && i < argc_check) { + pixel_width = strtol(argv[++i], &end, 10); + } else if (!strcmp("-pixel_height", argv[i]) && i < argc_check) { + pixel_height = strtol(argv[++i], &end, 10); + } else if (!strcmp("-stereo_mode", argv[i]) && i < argc_check) { + stereo_mode = strtol(argv[++i], &end, 10); + } else if (!strcmp("-projection_type", argv[i]) && i < argc_check) { + projection_type = strtol(argv[++i], &end, 10); + } else if (!strcmp("-projection_file", argv[i]) && i < argc_check) { + projection_file = argv[++i]; + } else if (!strcmp("-projection_pose_roll", argv[i]) && i < argc_check) { + projection_pose_roll = strtof(argv[++i], &end); + } else if (!strcmp("-projection_pose_pitch", argv[i]) && i < argc_check) { + projection_pose_pitch = strtof(argv[++i], &end); + } else if (!strcmp("-projection_pose_yaw", argv[i]) && i < argc_check) { + projection_pose_yaw = strtof(argv[++i], &end); + } else if (!strcmp("-profile", argv[i]) && i < argc_check) { + vp9_profile = static_cast(strtol(argv[++i], &end, 10)); + } else if (!strcmp("-level", argv[i]) && i < argc_check) { + vp9_level = static_cast(strtol(argv[++i], &end, 10)); + } else if (!strcmp("-output_cues_block_number", argv[i]) && + i < argc_check) { + output_cues_block_number = + strtol(argv[++i], &end, 10) == 0 ? false : true; + } else if (int e = ParseArgWebVTT(argv, &i, argc_check, &metadata_files)) { + if (e < 0) + return EXIT_FAILURE; + } + } + + if (input == NULL || output == NULL) { + Usage(); + return EXIT_FAILURE; + } + + // Get parser header info + mkvparser::MkvReader reader; + + if (reader.Open(input)) { + printf("\n Filename is invalid or error while opening.\n"); + return EXIT_FAILURE; + } + + long long pos = 0; + mkvparser::EBMLHeader ebml_header; + long long ret = ebml_header.Parse(&reader, pos); + if (ret) { + printf("\n EBMLHeader::Parse() failed."); + return EXIT_FAILURE; + } + + mkvparser::Segment* parser_segment_; + ret = mkvparser::Segment::CreateInstance(&reader, pos, parser_segment_); + if (ret) { + printf("\n Segment::CreateInstance() failed."); + return EXIT_FAILURE; + } + + const std::unique_ptr parser_segment(parser_segment_); + ret = parser_segment->Load(); + if (ret < 0) { + printf("\n Segment::Load() failed."); + return EXIT_FAILURE; + } + + const mkvparser::SegmentInfo* const segment_info = parser_segment->GetInfo(); + if (segment_info == NULL) { + printf("\n Segment::GetInfo() failed."); + return EXIT_FAILURE; + } + const long long timeCodeScale = segment_info->GetTimeCodeScale(); + + // Set muxer header info + mkvmuxer::MkvWriter writer; + + const std::string temp_file = + cues_before_clusters ? libwebm::GetTempFileName() : output; + if (!writer.Open(temp_file.c_str())) { + printf("\n Filename is invalid or error while opening.\n"); + return EXIT_FAILURE; + } + + // Set Segment element attributes + mkvmuxer::Segment muxer_segment; + + if (!muxer_segment.Init(&writer)) { + printf("\n Could not initialize muxer segment!\n"); + return EXIT_FAILURE; + } + + muxer_segment.AccurateClusterDuration(accurate_cluster_duration); + muxer_segment.UseFixedSizeClusterTimecode(fixed_size_cluster_timecode); + + if (live_mode) + muxer_segment.set_mode(mkvmuxer::Segment::kLive); + else + muxer_segment.set_mode(mkvmuxer::Segment::kFile); + + if (chunking) + muxer_segment.SetChunking(true, chunk_name); + + if (max_cluster_duration > 0) + muxer_segment.set_max_cluster_duration(max_cluster_duration); + if (max_cluster_size > 0) + muxer_segment.set_max_cluster_size(max_cluster_size); + muxer_segment.OutputCues(output_cues); + + // Set SegmentInfo element attributes + mkvmuxer::SegmentInfo* const info = muxer_segment.GetSegmentInfo(); + info->set_timecode_scale(timeCodeScale); + info->set_writing_app("mkvmuxer_sample"); + + const mkvparser::Tags* const tags = parser_segment->GetTags(); + if (copy_tags && tags) { + for (int i = 0; i < tags->GetTagCount(); i++) { + const mkvparser::Tags::Tag* const tag = tags->GetTag(i); + mkvmuxer::Tag* muxer_tag = muxer_segment.AddTag(); + + for (int j = 0; j < tag->GetSimpleTagCount(); j++) { + const mkvparser::Tags::SimpleTag* const simple_tag = + tag->GetSimpleTag(j); + muxer_tag->add_simple_tag(simple_tag->GetTagName(), + simple_tag->GetTagString()); + } + } + } + + // Set Tracks element attributes + const mkvparser::Tracks* const parser_tracks = parser_segment->GetTracks(); + unsigned long i = 0; + uint64_t vid_track = 0; // no track added + uint64_t aud_track = 0; // no track added + + using mkvparser::Track; + + while (i != parser_tracks->GetTracksCount()) { + unsigned long track_num = i++; + if (switch_tracks) + track_num = i % parser_tracks->GetTracksCount(); + + const Track* const parser_track = parser_tracks->GetTrackByIndex(track_num); + + if (parser_track == NULL) + continue; + + // TODO(fgalligan): Add support for language to parser. + const char* const track_name = parser_track->GetNameAsUTF8(); + + const long long track_type = parser_track->GetType(); + + if (track_type == Track::kVideo && output_video) { + // Get the video track from the parser + const mkvparser::VideoTrack* const pVideoTrack = + static_cast(parser_track); + const long long width = pVideoTrack->GetWidth(); + const long long height = pVideoTrack->GetHeight(); + + // Add the video track to the muxer + vid_track = muxer_segment.AddVideoTrack(static_cast(width), + static_cast(height), + video_track_number); + if (!vid_track) { + printf("\n Could not add video track.\n"); + return EXIT_FAILURE; + } + + mkvmuxer::VideoTrack* const video = static_cast( + muxer_segment.GetTrackByNumber(vid_track)); + if (!video) { + printf("\n Could not get video track.\n"); + return EXIT_FAILURE; + } + + if (pVideoTrack->GetColour()) { + mkvmuxer::Colour muxer_colour; + if (!libwebm::CopyColour(*pVideoTrack->GetColour(), &muxer_colour)) + return EXIT_FAILURE; + if (!video->SetColour(muxer_colour)) + return EXIT_FAILURE; + } + + if (pVideoTrack->GetProjection() || + projection_type != mkvparser::Projection::kTypeNotPresent) { + mkvmuxer::Projection muxer_projection; + const mkvparser::Projection* const parser_projection = + pVideoTrack->GetProjection(); + typedef mkvmuxer::Projection::ProjectionType MuxerProjType; + if (parser_projection && + !CopyVideoProjection(*parser_projection, &muxer_projection)) { + printf("\n Unable to copy video projection.\n"); + return EXIT_FAILURE; + } + // Override the values that came from parser if set on command line. + if (projection_type != mkvparser::Projection::kTypeNotPresent) { + muxer_projection.set_type( + static_cast(projection_type)); + if (projection_type == mkvparser::Projection::kRectangular && + projection_file != NULL) { + printf("\n Rectangular projection must not have private data.\n"); + return EXIT_FAILURE; + } else if ((projection_type == mkvparser::Projection::kCubeMap || + projection_type == mkvparser::Projection::kMesh) && + projection_file == NULL) { + printf("\n Mesh or CubeMap projection must have private data.\n"); + return EXIT_FAILURE; + } + if (projection_file != NULL) { + std::string contents; + if (!libwebm::GetFileContents(projection_file, &contents) || + contents.size() == 0) { + printf("\n Failed to read file \"%s\" or file is empty\n", + projection_file); + return EXIT_FAILURE; + } + if (!muxer_projection.SetProjectionPrivate( + reinterpret_cast(&contents[0]), + contents.size())) { + printf("\n Failed to SetProjectionPrivate of length %zu.\n", + contents.size()); + return EXIT_FAILURE; + } + } + } + const float kValueNotPresent = mkvparser::Projection::kValueNotPresent; + if (projection_pose_yaw != kValueNotPresent) + muxer_projection.set_pose_yaw(projection_pose_yaw); + if (projection_pose_pitch != kValueNotPresent) + muxer_projection.set_pose_pitch(projection_pose_pitch); + if (projection_pose_roll != kValueNotPresent) + muxer_projection.set_pose_roll(projection_pose_roll); + + if (!video->SetProjection(muxer_projection)) + return EXIT_FAILURE; + } + + if (track_name) + video->set_name(track_name); + + video->set_codec_id(pVideoTrack->GetCodecId()); + + if (display_width > 0) + video->set_display_width(display_width); + if (display_height > 0) + video->set_display_height(display_height); + if (pixel_width > 0) + video->set_pixel_width(pixel_width); + if (pixel_height > 0) + video->set_pixel_height(pixel_height); + if (stereo_mode > 0) + video->SetStereoMode(stereo_mode); + + const double rate = pVideoTrack->GetFrameRate(); + if (rate > 0.0) { + video->set_frame_rate(rate); + } + + size_t parser_private_size; + const unsigned char* const parser_private_data = + pVideoTrack->GetCodecPrivate(parser_private_size); + + if (!strcmp(video->codec_id(), mkvmuxer::Tracks::kAv1CodecId)) { + if (parser_private_data == NULL || parser_private_size == 0) { + printf("AV1 input track has no CodecPrivate. %s is invalid.", input); + return EXIT_FAILURE; + } + } + + if (!strcmp(video->codec_id(), mkvmuxer::Tracks::kVp9CodecId) && + (vp9_profile >= 0 || vp9_level >= 0)) { + const int kMaxVp9PrivateSize = 6; + unsigned char vp9_private_data[kMaxVp9PrivateSize]; + int vp9_private_size = 0; + if (vp9_profile >= 0) { + if (vp9_profile < 0 || vp9_profile > 3) { + printf("\n VP9 profile(%d) is not valid.\n", vp9_profile); + return EXIT_FAILURE; + } + const uint8_t kVp9ProfileId = 1; + const uint8_t kVp9ProfileIdLength = 1; + vp9_private_data[vp9_private_size++] = kVp9ProfileId; + vp9_private_data[vp9_private_size++] = kVp9ProfileIdLength; + vp9_private_data[vp9_private_size++] = vp9_profile; + } + + if (vp9_level >= 0) { + const int kNumLevels = 14; + const int levels[kNumLevels] = {10, 11, 20, 21, 30, 31, 40, + 41, 50, 51, 52, 60, 61, 62}; + bool level_is_valid = false; + for (int i = 0; i < kNumLevels; ++i) { + if (vp9_level == levels[i]) { + level_is_valid = true; + break; + } + } + if (!level_is_valid) { + printf("\n VP9 level(%d) is not valid.\n", vp9_level); + return EXIT_FAILURE; + } + const uint8_t kVp9LevelId = 2; + const uint8_t kVp9LevelIdLength = 1; + vp9_private_data[vp9_private_size++] = kVp9LevelId; + vp9_private_data[vp9_private_size++] = kVp9LevelIdLength; + vp9_private_data[vp9_private_size++] = vp9_level; + } + if (!video->SetCodecPrivate(vp9_private_data, vp9_private_size)) { + printf("\n Could not add video private data.\n"); + return EXIT_FAILURE; + } + } else if (parser_private_data && parser_private_size > 0) { + if (!video->SetCodecPrivate(parser_private_data, parser_private_size)) { + printf("\n Could not add video private data.\n"); + return EXIT_FAILURE; + } + } + } else if (track_type == Track::kAudio && output_audio) { + // Get the audio track from the parser + const mkvparser::AudioTrack* const pAudioTrack = + static_cast(parser_track); + const long long channels = pAudioTrack->GetChannels(); + const double sample_rate = pAudioTrack->GetSamplingRate(); + + // Add the audio track to the muxer + aud_track = muxer_segment.AddAudioTrack(static_cast(sample_rate), + static_cast(channels), + audio_track_number); + if (!aud_track) { + printf("\n Could not add audio track.\n"); + return EXIT_FAILURE; + } + + mkvmuxer::AudioTrack* const audio = static_cast( + muxer_segment.GetTrackByNumber(aud_track)); + if (!audio) { + printf("\n Could not get audio track.\n"); + return EXIT_FAILURE; + } + + if (track_name) + audio->set_name(track_name); + + audio->set_codec_id(pAudioTrack->GetCodecId()); + + size_t private_size; + const unsigned char* const private_data = + pAudioTrack->GetCodecPrivate(private_size); + if (private_size > 0) { + if (!audio->SetCodecPrivate(private_data, private_size)) { + printf("\n Could not add audio private data.\n"); + return EXIT_FAILURE; + } + } + + const long long bit_depth = pAudioTrack->GetBitDepth(); + if (bit_depth > 0) + audio->set_bit_depth(bit_depth); + + if (pAudioTrack->GetCodecDelay()) + audio->set_codec_delay(pAudioTrack->GetCodecDelay()); + if (pAudioTrack->GetSeekPreRoll()) + audio->set_seek_pre_roll(pAudioTrack->GetSeekPreRoll()); + } + } + + // We have created all the video and audio tracks. If any WebVTT + // files were specified as command-line args, then parse them and + // add a track to the output file corresponding to each metadata + // input file. + + SampleMuxerMetadata metadata; + + if (!metadata.Init(&muxer_segment)) { + printf("\n Could not initialize metadata cache.\n"); + return EXIT_FAILURE; + } + + if (!LoadMetadataFiles(metadata_files, &metadata)) + return EXIT_FAILURE; + + if (!metadata.AddChapters()) + return EXIT_FAILURE; + + // Set Cues element attributes + mkvmuxer::Cues* const cues = muxer_segment.GetCues(); + cues->set_output_block_number(output_cues_block_number); + if (cues_on_video_track && vid_track) + muxer_segment.CuesTrack(vid_track); + if (cues_on_audio_track && aud_track) + muxer_segment.CuesTrack(aud_track); + + // Write clusters + unsigned char* data = NULL; + long data_len = 0; + + const mkvparser::Cluster* cluster = parser_segment->GetFirst(); + + while (cluster != NULL && !cluster->EOS()) { + const mkvparser::BlockEntry* block_entry; + + long status = cluster->GetFirst(block_entry); + + if (status) { + printf("\n Could not get first block of cluster.\n"); + return EXIT_FAILURE; + } + + while (block_entry != NULL && !block_entry->EOS()) { + const mkvparser::Block* const block = block_entry->GetBlock(); + const long long trackNum = block->GetTrackNumber(); + const mkvparser::Track* const parser_track = + parser_tracks->GetTrackByNumber(static_cast(trackNum)); + + // When |parser_track| is NULL, it means that the track number in the + // Block is invalid (i.e.) the was no TrackEntry corresponding to the + // track number. So we reject the file. + if (!parser_track) { + return EXIT_FAILURE; + } + + const long long track_type = parser_track->GetType(); + const long long time_ns = block->GetTime(cluster); + + // Flush any metadata frames to the output file, before we write + // the current block. + if (!metadata.Write(time_ns)) + return EXIT_FAILURE; + + if ((track_type == Track::kAudio && output_audio) || + (track_type == Track::kVideo && output_video)) { + const int frame_count = block->GetFrameCount(); + + for (int i = 0; i < frame_count; ++i) { + const mkvparser::Block::Frame& frame = block->GetFrame(i); + + if (frame.len > data_len) { + delete[] data; + data = new unsigned char[frame.len]; + if (!data) + return EXIT_FAILURE; + data_len = frame.len; + } + + if (frame.Read(&reader, data)) + return EXIT_FAILURE; + + mkvmuxer::Frame muxer_frame; + if (!muxer_frame.Init(data, frame.len)) + return EXIT_FAILURE; + muxer_frame.set_track_number(track_type == Track::kAudio ? aud_track + : vid_track); + if (block->GetDiscardPadding()) + muxer_frame.set_discard_padding(block->GetDiscardPadding()); + muxer_frame.set_timestamp(time_ns); + muxer_frame.set_is_key(block->IsKey()); + if (!muxer_segment.AddGenericFrame(&muxer_frame)) { + printf("\n Could not add frame.\n"); + return EXIT_FAILURE; + } + } + } + + status = cluster->GetNext(block_entry, block_entry); + + if (status) { + printf("\n Could not get next block of cluster.\n"); + return EXIT_FAILURE; + } + } + + cluster = parser_segment->GetNext(cluster); + } + + // We have exhausted all video and audio frames in the input file. + // Flush any remaining metadata frames to the output file. + if (!metadata.Write(-1)) + return EXIT_FAILURE; + + if (copy_input_duration) { + const double input_duration = + static_cast(segment_info->GetDuration()) / timeCodeScale; + muxer_segment.set_duration(input_duration); + } + + if (!muxer_segment.Finalize()) { + printf("Finalization of segment failed.\n"); + return EXIT_FAILURE; + } + + reader.Close(); + writer.Close(); + + if (cues_before_clusters) { + if (reader.Open(temp_file.c_str())) { + printf("\n Filename is invalid or error while opening.\n"); + return EXIT_FAILURE; + } + if (!writer.Open(output)) { + printf("\n Filename is invalid or error while opening.\n"); + return EXIT_FAILURE; + } + if (!muxer_segment.CopyAndMoveCuesBeforeClusters(&reader, &writer)) { + printf("\n Unable to copy and move cues before clusters.\n"); + return EXIT_FAILURE; + } + reader.Close(); + writer.Close(); + remove(temp_file.c_str()); + } + + delete[] data; + + return EXIT_SUCCESS; +} diff --git a/third_party/libwebm/source/mkvmuxertypes.hpp b/third_party/libwebm/source/mkvmuxertypes.hpp new file mode 100644 index 000000000000..78478f45c035 --- /dev/null +++ b/third_party/libwebm/source/mkvmuxertypes.hpp @@ -0,0 +1,15 @@ +// Copyright (c) 2016 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +#ifndef LIBWEBM_MKVMUXERTYPES_HPP_ +#define LIBWEBM_MKVMUXERTYPES_HPP_ + +// This file is a wrapper for the file included immediately after this comment. +// New projects should not include this file: include the file included below. +#include "mkvmuxer/mkvmuxertypes.h" + +#endif // LIBWEBM_MKVMUXERTYPES_HPP_ diff --git a/third_party/libwebm/source/mkvmuxerutil.hpp b/third_party/libwebm/source/mkvmuxerutil.hpp new file mode 100644 index 000000000000..a26ba18a6115 --- /dev/null +++ b/third_party/libwebm/source/mkvmuxerutil.hpp @@ -0,0 +1,18 @@ +// Copyright (c) 2016 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +#ifndef LIBWEBM_MKVMUXERUTIL_HPP_ +#define LIBWEBM_MKVMUXERUTIL_HPP_ + +// This file is a wrapper for the file included immediately after this comment. +// New projects should not include this file: include the file included below. +#include "mkvmuxer/mkvmuxerutil.h" + +using mkvmuxer::EbmlElementSize; +using mkvmuxer::EbmlMasterElementSize; + +#endif // LIBWEBM_MKVMUXERUTIL_HPP_ diff --git a/third_party/libwebm/source/mkvparser.hpp b/third_party/libwebm/source/mkvparser.hpp new file mode 100644 index 000000000000..3f86292041ff --- /dev/null +++ b/third_party/libwebm/source/mkvparser.hpp @@ -0,0 +1,15 @@ +// Copyright (c) 2016 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +#ifndef LIBWEBM_MKVPARSER_HPP_ +#define LIBWEBM_MKVPARSER_HPP_ + +// This file is a wrapper for the file included immediately after this comment. +// New projects should not include this file: include the file included below. +#include "mkvparser/mkvparser.h" + +#endif // LIBWEBM_MKVPARSER_HPP_ diff --git a/third_party/libwebm/source/mkvparser/mkvparser.cc b/third_party/libwebm/source/mkvparser/mkvparser.cc new file mode 100644 index 000000000000..e7cf332cccda --- /dev/null +++ b/third_party/libwebm/source/mkvparser/mkvparser.cc @@ -0,0 +1,8098 @@ +// Copyright (c) 2012 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +#include "mkvparser/mkvparser.h" + +#if defined(_MSC_VER) && _MSC_VER < 1800 +#include // _isnan() / _finite() +#define MSC_COMPAT +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include "common/webmids.h" + +namespace mkvparser { +const long long kStringElementSizeLimit = 20 * 1000 * 1000; +const float MasteringMetadata::kValueNotPresent = FLT_MAX; +const long long Colour::kValueNotPresent = LLONG_MAX; +const float Projection::kValueNotPresent = FLT_MAX; + +#ifdef MSC_COMPAT +inline bool isnan(double val) { return !!_isnan(val); } +inline bool isinf(double val) { return !_finite(val); } +#else +inline bool isnan(double val) { return std::isnan(val); } +inline bool isinf(double val) { return std::isinf(val); } +#endif // MSC_COMPAT + +template +Type* SafeArrayAlloc(unsigned long long num_elements, + unsigned long long element_size) { + if (num_elements == 0 || element_size == 0) + return NULL; + + const size_t kMaxAllocSize = 0x80000000; // 2GiB + const unsigned long long num_bytes = num_elements * element_size; + if (element_size > (kMaxAllocSize / num_elements)) + return NULL; + if (num_bytes != static_cast(num_bytes)) + return NULL; + + return new (std::nothrow) Type[static_cast(num_bytes)]; +} + +void GetVersion(int& major, int& minor, int& build, int& revision) { + major = 1; + minor = 1; + build = 0; + revision = 0; +} + +long long ReadUInt(IMkvReader* pReader, long long pos, long& len) { + if (!pReader || pos < 0) + return E_FILE_FORMAT_INVALID; + + len = 1; + unsigned char b; + int status = pReader->Read(pos, 1, &b); + + if (status < 0) // error or underflow + return status; + + if (status > 0) // interpreted as "underflow" + return E_BUFFER_NOT_FULL; + + if (b == 0) // we can't handle u-int values larger than 8 bytes + return E_FILE_FORMAT_INVALID; + + unsigned char m = 0x80; + + while (!(b & m)) { + m >>= 1; + ++len; + } + + long long result = b & (~m); + ++pos; + + for (int i = 1; i < len; ++i) { + status = pReader->Read(pos, 1, &b); + + if (status < 0) { + len = 1; + return status; + } + + if (status > 0) { + len = 1; + return E_BUFFER_NOT_FULL; + } + + result <<= 8; + result |= b; + + ++pos; + } + + return result; +} + +// Reads an EBML ID and returns it. +// An ID must at least 1 byte long, cannot exceed 4, and its value must be +// greater than 0. +// See known EBML values and EBMLMaxIDLength: +// http://www.matroska.org/technical/specs/index.html +// Returns the ID, or a value less than 0 to report an error while reading the +// ID. +long long ReadID(IMkvReader* pReader, long long pos, long& len) { + if (pReader == NULL || pos < 0) + return E_FILE_FORMAT_INVALID; + + // Read the first byte. The length in bytes of the ID is determined by + // finding the first set bit in the first byte of the ID. + unsigned char temp_byte = 0; + int read_status = pReader->Read(pos, 1, &temp_byte); + + if (read_status < 0) + return E_FILE_FORMAT_INVALID; + else if (read_status > 0) // No data to read. + return E_BUFFER_NOT_FULL; + + if (temp_byte == 0) // ID length > 8 bytes; invalid file. + return E_FILE_FORMAT_INVALID; + + int bit_pos = 0; + const int kMaxIdLengthInBytes = 4; + const int kCheckByte = 0x80; + + // Find the first bit that's set. + bool found_bit = false; + for (; bit_pos < kMaxIdLengthInBytes; ++bit_pos) { + if ((kCheckByte >> bit_pos) & temp_byte) { + found_bit = true; + break; + } + } + + if (!found_bit) { + // The value is too large to be a valid ID. + return E_FILE_FORMAT_INVALID; + } + + // Read the remaining bytes of the ID (if any). + const int id_length = bit_pos + 1; + long long ebml_id = temp_byte; + for (int i = 1; i < id_length; ++i) { + ebml_id <<= 8; + read_status = pReader->Read(pos + i, 1, &temp_byte); + + if (read_status < 0) + return E_FILE_FORMAT_INVALID; + else if (read_status > 0) + return E_BUFFER_NOT_FULL; + + ebml_id |= temp_byte; + } + + len = id_length; + return ebml_id; +} + +long long GetUIntLength(IMkvReader* pReader, long long pos, long& len) { + if (!pReader || pos < 0) + return E_FILE_FORMAT_INVALID; + + long long total, available; + + int status = pReader->Length(&total, &available); + if (status < 0 || (total >= 0 && available > total)) + return E_FILE_FORMAT_INVALID; + + len = 1; + + if (pos >= available) + return pos; // too few bytes available + + unsigned char b; + + status = pReader->Read(pos, 1, &b); + + if (status != 0) + return status; + + if (b == 0) // we can't handle u-int values larger than 8 bytes + return E_FILE_FORMAT_INVALID; + + unsigned char m = 0x80; + + while (!(b & m)) { + m >>= 1; + ++len; + } + + return 0; // success +} + +// TODO(vigneshv): This function assumes that unsigned values never have their +// high bit set. +long long UnserializeUInt(IMkvReader* pReader, long long pos, long long size) { + if (!pReader || pos < 0 || (size <= 0) || (size > 8)) + return E_FILE_FORMAT_INVALID; + + long long result = 0; + + for (long long i = 0; i < size; ++i) { + unsigned char b; + + const long status = pReader->Read(pos, 1, &b); + + if (status < 0) + return status; + + result <<= 8; + result |= b; + + ++pos; + } + + return result; +} + +long UnserializeFloat(IMkvReader* pReader, long long pos, long long size_, + double& result) { + if (!pReader || pos < 0 || ((size_ != 4) && (size_ != 8))) + return E_FILE_FORMAT_INVALID; + + const long size = static_cast(size_); + + unsigned char buf[8]; + + const int status = pReader->Read(pos, size, buf); + + if (status < 0) // error + return status; + + if (size == 4) { + union { + float f; + unsigned long ff; + }; + + ff = 0; + + for (int i = 0;;) { + ff |= buf[i]; + + if (++i >= 4) + break; + + ff <<= 8; + } + + result = f; + } else { + union { + double d; + unsigned long long dd; + }; + + dd = 0; + + for (int i = 0;;) { + dd |= buf[i]; + + if (++i >= 8) + break; + + dd <<= 8; + } + + result = d; + } + + if (mkvparser::isinf(result) || mkvparser::isnan(result)) + return E_FILE_FORMAT_INVALID; + + return 0; +} + +long UnserializeInt(IMkvReader* pReader, long long pos, long long size, + long long& result_ref) { + if (!pReader || pos < 0 || size < 1 || size > 8) + return E_FILE_FORMAT_INVALID; + + signed char first_byte = 0; + const long status = pReader->Read(pos, 1, (unsigned char*)&first_byte); + + if (status < 0) + return status; + + unsigned long long result = first_byte; + ++pos; + + for (long i = 1; i < size; ++i) { + unsigned char b; + + const long status = pReader->Read(pos, 1, &b); + + if (status < 0) + return status; + + result <<= 8; + result |= b; + + ++pos; + } + + result_ref = static_cast(result); + return 0; +} + +long UnserializeString(IMkvReader* pReader, long long pos, long long size, + char*& str) { + delete[] str; + str = NULL; + + if (size >= LONG_MAX || size < 0 || size > kStringElementSizeLimit) + return E_FILE_FORMAT_INVALID; + + // +1 for '\0' terminator + const long required_size = static_cast(size) + 1; + + str = SafeArrayAlloc(1, required_size); + if (str == NULL) + return E_FILE_FORMAT_INVALID; + + unsigned char* const buf = reinterpret_cast(str); + + const long status = pReader->Read(pos, static_cast(size), buf); + + if (status) { + delete[] str; + str = NULL; + + return status; + } + + str[required_size - 1] = '\0'; + return 0; +} + +long ParseElementHeader(IMkvReader* pReader, long long& pos, long long stop, + long long& id, long long& size) { + if (stop >= 0 && pos >= stop) + return E_FILE_FORMAT_INVALID; + + long len; + + id = ReadID(pReader, pos, len); + + if (id < 0) + return E_FILE_FORMAT_INVALID; + + pos += len; // consume id + + if (stop >= 0 && pos >= stop) + return E_FILE_FORMAT_INVALID; + + size = ReadUInt(pReader, pos, len); + + if (size < 0 || len < 1 || len > 8) { + // Invalid: Negative payload size, negative or 0 length integer, or integer + // larger than 64 bits (libwebm cannot handle them). + return E_FILE_FORMAT_INVALID; + } + + // Avoid rolling over pos when very close to LLONG_MAX. + const unsigned long long rollover_check = + static_cast(pos) + len; + if (rollover_check > LLONG_MAX) + return E_FILE_FORMAT_INVALID; + + pos += len; // consume length of size + + // pos now designates payload + + if (stop >= 0 && pos > stop) + return E_FILE_FORMAT_INVALID; + + return 0; // success +} + +bool Match(IMkvReader* pReader, long long& pos, unsigned long expected_id, + long long& val) { + if (!pReader || pos < 0) + return false; + + long long total = 0; + long long available = 0; + + const long status = pReader->Length(&total, &available); + if (status < 0 || (total >= 0 && available > total)) + return false; + + long len = 0; + + const long long id = ReadID(pReader, pos, len); + if (id < 0 || (available - pos) > len) + return false; + + if (static_cast(id) != expected_id) + return false; + + pos += len; // consume id + + const long long size = ReadUInt(pReader, pos, len); + if (size < 0 || size > 8 || len < 1 || len > 8 || (available - pos) > len) + return false; + + pos += len; // consume length of size of payload + + val = UnserializeUInt(pReader, pos, size); + if (val < 0) + return false; + + pos += size; // consume size of payload + + return true; +} + +bool Match(IMkvReader* pReader, long long& pos, unsigned long expected_id, + unsigned char*& buf, size_t& buflen) { + if (!pReader || pos < 0) + return false; + + long long total = 0; + long long available = 0; + + long status = pReader->Length(&total, &available); + if (status < 0 || (total >= 0 && available > total)) + return false; + + long len = 0; + const long long id = ReadID(pReader, pos, len); + if (id < 0 || (available - pos) > len) + return false; + + if (static_cast(id) != expected_id) + return false; + + pos += len; // consume id + + const long long size = ReadUInt(pReader, pos, len); + if (size < 0 || len <= 0 || len > 8 || (available - pos) > len) + return false; + + unsigned long long rollover_check = + static_cast(pos) + len; + if (rollover_check > LLONG_MAX) + return false; + + pos += len; // consume length of size of payload + + rollover_check = static_cast(pos) + size; + if (rollover_check > LLONG_MAX) + return false; + + if ((pos + size) > available) + return false; + + if (size >= LONG_MAX) + return false; + + const long buflen_ = static_cast(size); + + buf = SafeArrayAlloc(1, buflen_); + if (!buf) + return false; + + status = pReader->Read(pos, buflen_, buf); + if (status != 0) + return false; + + buflen = buflen_; + + pos += size; // consume size of payload + return true; +} + +EBMLHeader::EBMLHeader() : m_docType(NULL) { Init(); } + +EBMLHeader::~EBMLHeader() { delete[] m_docType; } + +void EBMLHeader::Init() { + m_version = 1; + m_readVersion = 1; + m_maxIdLength = 4; + m_maxSizeLength = 8; + + if (m_docType) { + delete[] m_docType; + m_docType = NULL; + } + + m_docTypeVersion = 1; + m_docTypeReadVersion = 1; +} + +long long EBMLHeader::Parse(IMkvReader* pReader, long long& pos) { + if (!pReader) + return E_FILE_FORMAT_INVALID; + + long long total, available; + + long status = pReader->Length(&total, &available); + + if (status < 0) // error + return status; + + pos = 0; + + // Scan until we find what looks like the first byte of the EBML header. + const long long kMaxScanBytes = (available >= 1024) ? 1024 : available; + const unsigned char kEbmlByte0 = 0x1A; + unsigned char scan_byte = 0; + + while (pos < kMaxScanBytes) { + status = pReader->Read(pos, 1, &scan_byte); + + if (status < 0) // error + return status; + else if (status > 0) + return E_BUFFER_NOT_FULL; + + if (scan_byte == kEbmlByte0) + break; + + ++pos; + } + + long len = 0; + const long long ebml_id = ReadID(pReader, pos, len); + + if (ebml_id == E_BUFFER_NOT_FULL) + return E_BUFFER_NOT_FULL; + + if (len != 4 || ebml_id != libwebm::kMkvEBML) + return E_FILE_FORMAT_INVALID; + + // Move read pos forward to the EBML header size field. + pos += 4; + + // Read length of size field. + long long result = GetUIntLength(pReader, pos, len); + + if (result < 0) // error + return E_FILE_FORMAT_INVALID; + else if (result > 0) // need more data + return E_BUFFER_NOT_FULL; + + if (len < 1 || len > 8) + return E_FILE_FORMAT_INVALID; + + if ((total >= 0) && ((total - pos) < len)) + return E_FILE_FORMAT_INVALID; + + if ((available - pos) < len) + return pos + len; // try again later + + // Read the EBML header size. + result = ReadUInt(pReader, pos, len); + + if (result < 0) // error + return result; + + pos += len; // consume size field + + // pos now designates start of payload + + if ((total >= 0) && ((total - pos) < result)) + return E_FILE_FORMAT_INVALID; + + if ((available - pos) < result) + return pos + result; + + const long long end = pos + result; + + Init(); + + while (pos < end) { + long long id, size; + + status = ParseElementHeader(pReader, pos, end, id, size); + + if (status < 0) // error + return status; + + if (size == 0) + return E_FILE_FORMAT_INVALID; + + if (id == libwebm::kMkvEBMLVersion) { + m_version = UnserializeUInt(pReader, pos, size); + + if (m_version <= 0) + return E_FILE_FORMAT_INVALID; + } else if (id == libwebm::kMkvEBMLReadVersion) { + m_readVersion = UnserializeUInt(pReader, pos, size); + + if (m_readVersion <= 0) + return E_FILE_FORMAT_INVALID; + } else if (id == libwebm::kMkvEBMLMaxIDLength) { + m_maxIdLength = UnserializeUInt(pReader, pos, size); + + if (m_maxIdLength <= 0) + return E_FILE_FORMAT_INVALID; + } else if (id == libwebm::kMkvEBMLMaxSizeLength) { + m_maxSizeLength = UnserializeUInt(pReader, pos, size); + + if (m_maxSizeLength <= 0) + return E_FILE_FORMAT_INVALID; + } else if (id == libwebm::kMkvDocType) { + if (m_docType) + return E_FILE_FORMAT_INVALID; + + status = UnserializeString(pReader, pos, size, m_docType); + + if (status) // error + return status; + } else if (id == libwebm::kMkvDocTypeVersion) { + m_docTypeVersion = UnserializeUInt(pReader, pos, size); + + if (m_docTypeVersion <= 0) + return E_FILE_FORMAT_INVALID; + } else if (id == libwebm::kMkvDocTypeReadVersion) { + m_docTypeReadVersion = UnserializeUInt(pReader, pos, size); + + if (m_docTypeReadVersion <= 0) + return E_FILE_FORMAT_INVALID; + } + + pos += size; + } + + if (pos != end) + return E_FILE_FORMAT_INVALID; + + // Make sure DocType, DocTypeReadVersion, and DocTypeVersion are valid. + if (m_docType == NULL || m_docTypeReadVersion <= 0 || m_docTypeVersion <= 0) + return E_FILE_FORMAT_INVALID; + + // Make sure EBMLMaxIDLength and EBMLMaxSizeLength are valid. + if (m_maxIdLength <= 0 || m_maxIdLength > 4 || m_maxSizeLength <= 0 || + m_maxSizeLength > 8) + return E_FILE_FORMAT_INVALID; + + return 0; +} + +Segment::Segment(IMkvReader* pReader, long long elem_start, + // long long elem_size, + long long start, long long size) + : m_pReader(pReader), + m_element_start(elem_start), + // m_element_size(elem_size), + m_start(start), + m_size(size), + m_pos(start), + m_pUnknownSize(0), + m_pSeekHead(NULL), + m_pInfo(NULL), + m_pTracks(NULL), + m_pCues(NULL), + m_pChapters(NULL), + m_pTags(NULL), + m_clusters(NULL), + m_clusterCount(0), + m_clusterPreloadCount(0), + m_clusterSize(0) {} + +Segment::~Segment() { + const long count = m_clusterCount + m_clusterPreloadCount; + + Cluster** i = m_clusters; + Cluster** j = m_clusters + count; + + while (i != j) { + Cluster* const p = *i++; + delete p; + } + + delete[] m_clusters; + + delete m_pTracks; + delete m_pInfo; + delete m_pCues; + delete m_pChapters; + delete m_pTags; + delete m_pSeekHead; +} + +long long Segment::CreateInstance(IMkvReader* pReader, long long pos, + Segment*& pSegment) { + if (pReader == NULL || pos < 0) + return E_PARSE_FAILED; + + pSegment = NULL; + + long long total, available; + + const long status = pReader->Length(&total, &available); + + if (status < 0) // error + return status; + + if (available < 0) + return -1; + + if ((total >= 0) && (available > total)) + return -1; + + // I would assume that in practice this loop would execute + // exactly once, but we allow for other elements (e.g. Void) + // to immediately follow the EBML header. This is fine for + // the source filter case (since the entire file is available), + // but in the splitter case over a network we should probably + // just give up early. We could for example decide only to + // execute this loop a maximum of, say, 10 times. + // TODO: + // There is an implied "give up early" by only parsing up + // to the available limit. We do do that, but only if the + // total file size is unknown. We could decide to always + // use what's available as our limit (irrespective of whether + // we happen to know the total file length). This would have + // as its sense "parse this much of the file before giving up", + // which a slightly different sense from "try to parse up to + // 10 EMBL elements before giving up". + + for (;;) { + if ((total >= 0) && (pos >= total)) + return E_FILE_FORMAT_INVALID; + + // Read ID + long len; + long long result = GetUIntLength(pReader, pos, len); + + if (result) // error, or too few available bytes + return result; + + if ((total >= 0) && ((pos + len) > total)) + return E_FILE_FORMAT_INVALID; + + if ((pos + len) > available) + return pos + len; + + const long long idpos = pos; + const long long id = ReadID(pReader, pos, len); + + if (id < 0) + return E_FILE_FORMAT_INVALID; + + pos += len; // consume ID + + // Read Size + + result = GetUIntLength(pReader, pos, len); + + if (result) // error, or too few available bytes + return result; + + if ((total >= 0) && ((pos + len) > total)) + return E_FILE_FORMAT_INVALID; + + if ((pos + len) > available) + return pos + len; + + long long size = ReadUInt(pReader, pos, len); + + if (size < 0) // error + return size; + + pos += len; // consume length of size of element + + // Pos now points to start of payload + + // Handle "unknown size" for live streaming of webm files. + const long long unknown_size = (1LL << (7 * len)) - 1; + + if (id == libwebm::kMkvSegment) { + if (size == unknown_size) + size = -1; + + else if (total < 0) + size = -1; + + else if ((pos + size) > total) + size = -1; + + pSegment = new (std::nothrow) Segment(pReader, idpos, pos, size); + if (pSegment == NULL) + return E_PARSE_FAILED; + + return 0; // success + } + + if (size == unknown_size) + return E_FILE_FORMAT_INVALID; + + if ((total >= 0) && ((pos + size) > total)) + return E_FILE_FORMAT_INVALID; + + if ((pos + size) > available) + return pos + size; + + pos += size; // consume payload + } +} + +long long Segment::ParseHeaders() { + // Outermost (level 0) segment object has been constructed, + // and pos designates start of payload. We need to find the + // inner (level 1) elements. + long long total, available; + + const int status = m_pReader->Length(&total, &available); + + if (status < 0) // error + return status; + + if (total > 0 && available > total) + return E_FILE_FORMAT_INVALID; + + const long long segment_stop = (m_size < 0) ? -1 : m_start + m_size; + + if ((segment_stop >= 0 && total >= 0 && segment_stop > total) || + (segment_stop >= 0 && m_pos > segment_stop)) { + return E_FILE_FORMAT_INVALID; + } + + for (;;) { + if ((total >= 0) && (m_pos >= total)) + break; + + if ((segment_stop >= 0) && (m_pos >= segment_stop)) + break; + + long long pos = m_pos; + const long long element_start = pos; + + // Avoid rolling over pos when very close to LLONG_MAX. + unsigned long long rollover_check = pos + 1ULL; + if (rollover_check > LLONG_MAX) + return E_FILE_FORMAT_INVALID; + + if ((pos + 1) > available) + return (pos + 1); + + long len; + long long result = GetUIntLength(m_pReader, pos, len); + + if (result < 0) // error + return result; + + if (result > 0) { + // MkvReader doesn't have enough data to satisfy this read attempt. + return (pos + 1); + } + + if ((segment_stop >= 0) && ((pos + len) > segment_stop)) + return E_FILE_FORMAT_INVALID; + + if ((pos + len) > available) + return pos + len; + + const long long idpos = pos; + const long long id = ReadID(m_pReader, idpos, len); + + if (id < 0) + return E_FILE_FORMAT_INVALID; + + if (id == libwebm::kMkvCluster) + break; + + pos += len; // consume ID + + if ((pos + 1) > available) + return (pos + 1); + + // Read Size + result = GetUIntLength(m_pReader, pos, len); + + if (result < 0) // error + return result; + + if (result > 0) { + // MkvReader doesn't have enough data to satisfy this read attempt. + return (pos + 1); + } + + if ((segment_stop >= 0) && ((pos + len) > segment_stop)) + return E_FILE_FORMAT_INVALID; + + if ((pos + len) > available) + return pos + len; + + const long long size = ReadUInt(m_pReader, pos, len); + + if (size < 0 || len < 1 || len > 8) { + // TODO(tomfinegan): ReadUInt should return an error when len is < 1 or + // len > 8 is true instead of checking this _everywhere_. + return size; + } + + pos += len; // consume length of size of element + + // Avoid rolling over pos when very close to LLONG_MAX. + rollover_check = static_cast(pos) + size; + if (rollover_check > LLONG_MAX) + return E_FILE_FORMAT_INVALID; + + const long long element_size = size + pos - element_start; + + // Pos now points to start of payload + + if ((segment_stop >= 0) && ((pos + size) > segment_stop)) + return E_FILE_FORMAT_INVALID; + + // We read EBML elements either in total or nothing at all. + + if ((pos + size) > available) + return pos + size; + + if (id == libwebm::kMkvInfo) { + if (m_pInfo) + return E_FILE_FORMAT_INVALID; + + m_pInfo = new (std::nothrow) + SegmentInfo(this, pos, size, element_start, element_size); + + if (m_pInfo == NULL) + return -1; + + const long status = m_pInfo->Parse(); + + if (status) + return status; + } else if (id == libwebm::kMkvTracks) { + if (m_pTracks) + return E_FILE_FORMAT_INVALID; + + m_pTracks = new (std::nothrow) + Tracks(this, pos, size, element_start, element_size); + + if (m_pTracks == NULL) + return -1; + + const long status = m_pTracks->Parse(); + + if (status) + return status; + } else if (id == libwebm::kMkvCues) { + if (m_pCues == NULL) { + m_pCues = new (std::nothrow) + Cues(this, pos, size, element_start, element_size); + + if (m_pCues == NULL) + return -1; + } + } else if (id == libwebm::kMkvSeekHead) { + if (m_pSeekHead == NULL) { + m_pSeekHead = new (std::nothrow) + SeekHead(this, pos, size, element_start, element_size); + + if (m_pSeekHead == NULL) + return -1; + + const long status = m_pSeekHead->Parse(); + + if (status) + return status; + } + } else if (id == libwebm::kMkvChapters) { + if (m_pChapters == NULL) { + m_pChapters = new (std::nothrow) + Chapters(this, pos, size, element_start, element_size); + + if (m_pChapters == NULL) + return -1; + + const long status = m_pChapters->Parse(); + + if (status) + return status; + } + } else if (id == libwebm::kMkvTags) { + if (m_pTags == NULL) { + m_pTags = new (std::nothrow) + Tags(this, pos, size, element_start, element_size); + + if (m_pTags == NULL) + return -1; + + const long status = m_pTags->Parse(); + + if (status) + return status; + } + } + + m_pos = pos + size; // consume payload + } + + if (segment_stop >= 0 && m_pos > segment_stop) + return E_FILE_FORMAT_INVALID; + + if (m_pInfo == NULL) // TODO: liberalize this behavior + return E_FILE_FORMAT_INVALID; + + if (m_pTracks == NULL) + return E_FILE_FORMAT_INVALID; + + return 0; // success +} + +long Segment::LoadCluster(long long& pos, long& len) { + for (;;) { + const long result = DoLoadCluster(pos, len); + + if (result <= 1) + return result; + } +} + +long Segment::DoLoadCluster(long long& pos, long& len) { + if (m_pos < 0) + return DoLoadClusterUnknownSize(pos, len); + + long long total, avail; + + long status = m_pReader->Length(&total, &avail); + + if (status < 0) // error + return status; + + if (total >= 0 && avail > total) + return E_FILE_FORMAT_INVALID; + + const long long segment_stop = (m_size < 0) ? -1 : m_start + m_size; + + long long cluster_off = -1; // offset relative to start of segment + long long cluster_size = -1; // size of cluster payload + + for (;;) { + if ((total >= 0) && (m_pos >= total)) + return 1; // no more clusters + + if ((segment_stop >= 0) && (m_pos >= segment_stop)) + return 1; // no more clusters + + pos = m_pos; + + // Read ID + + if ((pos + 1) > avail) { + len = 1; + return E_BUFFER_NOT_FULL; + } + + long long result = GetUIntLength(m_pReader, pos, len); + + if (result < 0) // error + return static_cast(result); + + if (result > 0) + return E_BUFFER_NOT_FULL; + + if ((segment_stop >= 0) && ((pos + len) > segment_stop)) + return E_FILE_FORMAT_INVALID; + + if ((pos + len) > avail) + return E_BUFFER_NOT_FULL; + + const long long idpos = pos; + const long long id = ReadID(m_pReader, idpos, len); + + if (id < 0) + return E_FILE_FORMAT_INVALID; + + pos += len; // consume ID + + // Read Size + + if ((pos + 1) > avail) { + len = 1; + return E_BUFFER_NOT_FULL; + } + + result = GetUIntLength(m_pReader, pos, len); + + if (result < 0) // error + return static_cast(result); + + if (result > 0) + return E_BUFFER_NOT_FULL; + + if ((segment_stop >= 0) && ((pos + len) > segment_stop)) + return E_FILE_FORMAT_INVALID; + + if ((pos + len) > avail) + return E_BUFFER_NOT_FULL; + + const long long size = ReadUInt(m_pReader, pos, len); + + if (size < 0) // error + return static_cast(size); + + pos += len; // consume length of size of element + + // pos now points to start of payload + + if (size == 0) { + // Missing element payload: move on. + m_pos = pos; + continue; + } + + const long long unknown_size = (1LL << (7 * len)) - 1; + + if ((segment_stop >= 0) && (size != unknown_size) && + ((pos + size) > segment_stop)) { + return E_FILE_FORMAT_INVALID; + } + + if (id == libwebm::kMkvCues) { + if (size == unknown_size) { + // Cues element of unknown size: Not supported. + return E_FILE_FORMAT_INVALID; + } + + if (m_pCues == NULL) { + const long long element_size = (pos - idpos) + size; + + m_pCues = new (std::nothrow) Cues(this, pos, size, idpos, element_size); + if (m_pCues == NULL) + return -1; + } + + m_pos = pos + size; // consume payload + continue; + } + + if (id != libwebm::kMkvCluster) { + // Besides the Segment, Libwebm allows only cluster elements of unknown + // size. Fail the parse upon encountering a non-cluster element reporting + // unknown size. + if (size == unknown_size) + return E_FILE_FORMAT_INVALID; + + m_pos = pos + size; // consume payload + continue; + } + + // We have a cluster. + + cluster_off = idpos - m_start; // relative pos + + if (size != unknown_size) + cluster_size = size; + + break; + } + + if (cluster_off < 0) { + // No cluster, die. + return E_FILE_FORMAT_INVALID; + } + + long long pos_; + long len_; + + status = Cluster::HasBlockEntries(this, cluster_off, pos_, len_); + + if (status < 0) { // error, or underflow + pos = pos_; + len = len_; + + return status; + } + + // status == 0 means "no block entries found" + // status > 0 means "found at least one block entry" + + // TODO: + // The issue here is that the segment increments its own + // pos ptr past the most recent cluster parsed, and then + // starts from there to parse the next cluster. If we + // don't know the size of the current cluster, then we + // must either parse its payload (as we do below), looking + // for the cluster (or cues) ID to terminate the parse. + // This isn't really what we want: rather, we really need + // a way to create the curr cluster object immediately. + // The pity is that cluster::parse can determine its own + // boundary, and we largely duplicate that same logic here. + // + // Maybe we need to get rid of our look-ahead preloading + // in source::parse??? + // + // As we're parsing the blocks in the curr cluster + //(in cluster::parse), we should have some way to signal + // to the segment that we have determined the boundary, + // so it can adjust its own segment::m_pos member. + // + // The problem is that we're asserting in asyncreadinit, + // because we adjust the pos down to the curr seek pos, + // and the resulting adjusted len is > 2GB. I'm suspicious + // that this is even correct, but even if it is, we can't + // be loading that much data in the cache anyway. + + const long idx = m_clusterCount; + + if (m_clusterPreloadCount > 0) { + if (idx >= m_clusterSize) + return E_FILE_FORMAT_INVALID; + + Cluster* const pCluster = m_clusters[idx]; + if (pCluster == NULL || pCluster->m_index >= 0) + return E_FILE_FORMAT_INVALID; + + const long long off = pCluster->GetPosition(); + if (off < 0) + return E_FILE_FORMAT_INVALID; + + if (off == cluster_off) { // preloaded already + if (status == 0) // no entries found + return E_FILE_FORMAT_INVALID; + + if (cluster_size >= 0) + pos += cluster_size; + else { + const long long element_size = pCluster->GetElementSize(); + + if (element_size <= 0) + return E_FILE_FORMAT_INVALID; // TODO: handle this case + + pos = pCluster->m_element_start + element_size; + } + + pCluster->m_index = idx; // move from preloaded to loaded + ++m_clusterCount; + --m_clusterPreloadCount; + + m_pos = pos; // consume payload + if (segment_stop >= 0 && m_pos > segment_stop) + return E_FILE_FORMAT_INVALID; + + return 0; // success + } + } + + if (status == 0) { // no entries found + if (cluster_size >= 0) + pos += cluster_size; + + if ((total >= 0) && (pos >= total)) { + m_pos = total; + return 1; // no more clusters + } + + if ((segment_stop >= 0) && (pos >= segment_stop)) { + m_pos = segment_stop; + return 1; // no more clusters + } + + m_pos = pos; + return 2; // try again + } + + // status > 0 means we have an entry + + Cluster* const pCluster = Cluster::Create(this, idx, cluster_off); + if (pCluster == NULL) + return -1; + + if (!AppendCluster(pCluster)) { + delete pCluster; + return -1; + } + + if (cluster_size >= 0) { + pos += cluster_size; + + m_pos = pos; + + if (segment_stop > 0 && m_pos > segment_stop) + return E_FILE_FORMAT_INVALID; + + return 0; + } + + m_pUnknownSize = pCluster; + m_pos = -pos; + + return 0; // partial success, since we have a new cluster + + // status == 0 means "no block entries found" + // pos designates start of payload + // m_pos has NOT been adjusted yet (in case we need to come back here) +} + +long Segment::DoLoadClusterUnknownSize(long long& pos, long& len) { + if (m_pos >= 0 || m_pUnknownSize == NULL) + return E_PARSE_FAILED; + + const long status = m_pUnknownSize->Parse(pos, len); + + if (status < 0) // error or underflow + return status; + + if (status == 0) // parsed a block + return 2; // continue parsing + + const long long start = m_pUnknownSize->m_element_start; + const long long size = m_pUnknownSize->GetElementSize(); + + if (size < 0) + return E_FILE_FORMAT_INVALID; + + pos = start + size; + m_pos = pos; + + m_pUnknownSize = 0; + + return 2; // continue parsing +} + +bool Segment::AppendCluster(Cluster* pCluster) { + if (pCluster == NULL || pCluster->m_index < 0) + return false; + + const long count = m_clusterCount + m_clusterPreloadCount; + + long& size = m_clusterSize; + const long idx = pCluster->m_index; + + if (size < count || idx != m_clusterCount) + return false; + + if (count >= size) { + const long n = (size <= 0) ? 2048 : 2 * size; + + Cluster** const qq = new (std::nothrow) Cluster*[n]; + if (qq == NULL) + return false; + + Cluster** q = qq; + Cluster** p = m_clusters; + Cluster** const pp = p + count; + + while (p != pp) + *q++ = *p++; + + delete[] m_clusters; + + m_clusters = qq; + size = n; + } + + if (m_clusterPreloadCount > 0) { + Cluster** const p = m_clusters + m_clusterCount; + if (*p == NULL || (*p)->m_index >= 0) + return false; + + Cluster** q = p + m_clusterPreloadCount; + if (q >= (m_clusters + size)) + return false; + + for (;;) { + Cluster** const qq = q - 1; + if ((*qq)->m_index >= 0) + return false; + + *q = *qq; + q = qq; + + if (q == p) + break; + } + } + + m_clusters[idx] = pCluster; + ++m_clusterCount; + return true; +} + +bool Segment::PreloadCluster(Cluster* pCluster, ptrdiff_t idx) { + if (pCluster == NULL || pCluster->m_index >= 0 || idx < m_clusterCount) + return false; + + const long count = m_clusterCount + m_clusterPreloadCount; + + long& size = m_clusterSize; + if (size < count) + return false; + + if (count >= size) { + const long n = (size <= 0) ? 2048 : 2 * size; + + Cluster** const qq = new (std::nothrow) Cluster*[n]; + if (qq == NULL) + return false; + Cluster** q = qq; + + Cluster** p = m_clusters; + Cluster** const pp = p + count; + + while (p != pp) + *q++ = *p++; + + delete[] m_clusters; + + m_clusters = qq; + size = n; + } + + if (m_clusters == NULL) + return false; + + Cluster** const p = m_clusters + idx; + + Cluster** q = m_clusters + count; + if (q < p || q >= (m_clusters + size)) + return false; + + while (q > p) { + Cluster** const qq = q - 1; + + if ((*qq)->m_index >= 0) + return false; + + *q = *qq; + q = qq; + } + + m_clusters[idx] = pCluster; + ++m_clusterPreloadCount; + return true; +} + +long Segment::Load() { + if (m_clusters != NULL || m_clusterSize != 0 || m_clusterCount != 0) + return E_PARSE_FAILED; + + // Outermost (level 0) segment object has been constructed, + // and pos designates start of payload. We need to find the + // inner (level 1) elements. + + const long long header_status = ParseHeaders(); + + if (header_status < 0) // error + return static_cast(header_status); + + if (header_status > 0) // underflow + return E_BUFFER_NOT_FULL; + + if (m_pInfo == NULL || m_pTracks == NULL) + return E_FILE_FORMAT_INVALID; + + for (;;) { + const long status = LoadCluster(); + + if (status < 0) // error + return status; + + if (status >= 1) // no more clusters + return 0; + } +} + +SeekHead::Entry::Entry() : id(0), pos(0), element_start(0), element_size(0) {} + +SeekHead::SeekHead(Segment* pSegment, long long start, long long size_, + long long element_start, long long element_size) + : m_pSegment(pSegment), + m_start(start), + m_size(size_), + m_element_start(element_start), + m_element_size(element_size), + m_entries(0), + m_entry_count(0), + m_void_elements(0), + m_void_element_count(0) {} + +SeekHead::~SeekHead() { + delete[] m_entries; + delete[] m_void_elements; +} + +long SeekHead::Parse() { + IMkvReader* const pReader = m_pSegment->m_pReader; + + long long pos = m_start; + const long long stop = m_start + m_size; + + // first count the seek head entries + + long long entry_count = 0; + long long void_element_count = 0; + + while (pos < stop) { + long long id, size; + + const long status = ParseElementHeader(pReader, pos, stop, id, size); + + if (status < 0) // error + return status; + + if (id == libwebm::kMkvSeek) { + ++entry_count; + if (entry_count > INT_MAX) + return E_PARSE_FAILED; + } else if (id == libwebm::kMkvVoid) { + ++void_element_count; + if (void_element_count > INT_MAX) + return E_PARSE_FAILED; + } + + pos += size; // consume payload + + if (pos > stop) + return E_FILE_FORMAT_INVALID; + } + + if (pos != stop) + return E_FILE_FORMAT_INVALID; + + if (entry_count > 0) { + m_entries = new (std::nothrow) Entry[entry_count]; + + if (m_entries == NULL) + return -1; + } + + if (void_element_count > 0) { + m_void_elements = new (std::nothrow) VoidElement[void_element_count]; + + if (m_void_elements == NULL) + return -1; + } + + // now parse the entries and void elements + + Entry* pEntry = m_entries; + VoidElement* pVoidElement = m_void_elements; + + pos = m_start; + + while (pos < stop) { + const long long idpos = pos; + + long long id, size; + + const long status = ParseElementHeader(pReader, pos, stop, id, size); + + if (status < 0) // error + return status; + + if (id == libwebm::kMkvSeek && entry_count > 0) { + if (ParseEntry(pReader, pos, size, pEntry)) { + Entry& e = *pEntry++; + + e.element_start = idpos; + e.element_size = (pos + size) - idpos; + } + } else if (id == libwebm::kMkvVoid && void_element_count > 0) { + VoidElement& e = *pVoidElement++; + + e.element_start = idpos; + e.element_size = (pos + size) - idpos; + } + + pos += size; // consume payload + if (pos > stop) + return E_FILE_FORMAT_INVALID; + } + + if (pos != stop) + return E_FILE_FORMAT_INVALID; + + ptrdiff_t count_ = ptrdiff_t(pEntry - m_entries); + assert(count_ >= 0); + assert(static_cast(count_) <= entry_count); + + m_entry_count = static_cast(count_); + + count_ = ptrdiff_t(pVoidElement - m_void_elements); + assert(count_ >= 0); + assert(static_cast(count_) <= void_element_count); + + m_void_element_count = static_cast(count_); + + return 0; +} + +int SeekHead::GetCount() const { return m_entry_count; } + +const SeekHead::Entry* SeekHead::GetEntry(int idx) const { + if (idx < 0) + return 0; + + if (idx >= m_entry_count) + return 0; + + return m_entries + idx; +} + +int SeekHead::GetVoidElementCount() const { return m_void_element_count; } + +const SeekHead::VoidElement* SeekHead::GetVoidElement(int idx) const { + if (idx < 0) + return 0; + + if (idx >= m_void_element_count) + return 0; + + return m_void_elements + idx; +} + +long Segment::ParseCues(long long off, long long& pos, long& len) { + if (m_pCues) + return 0; // success + + if (off < 0) + return -1; + + long long total, avail; + + const int status = m_pReader->Length(&total, &avail); + + if (status < 0) // error + return status; + + assert((total < 0) || (avail <= total)); + + pos = m_start + off; + + if ((total < 0) || (pos >= total)) + return 1; // don't bother parsing cues + + const long long element_start = pos; + const long long segment_stop = (m_size < 0) ? -1 : m_start + m_size; + + if ((pos + 1) > avail) { + len = 1; + return E_BUFFER_NOT_FULL; + } + + long long result = GetUIntLength(m_pReader, pos, len); + + if (result < 0) // error + return static_cast(result); + + if (result > 0) // underflow (weird) + { + len = 1; + return E_BUFFER_NOT_FULL; + } + + if ((segment_stop >= 0) && ((pos + len) > segment_stop)) + return E_FILE_FORMAT_INVALID; + + if ((pos + len) > avail) + return E_BUFFER_NOT_FULL; + + const long long idpos = pos; + + const long long id = ReadID(m_pReader, idpos, len); + + if (id != libwebm::kMkvCues) + return E_FILE_FORMAT_INVALID; + + pos += len; // consume ID + assert((segment_stop < 0) || (pos <= segment_stop)); + + // Read Size + + if ((pos + 1) > avail) { + len = 1; + return E_BUFFER_NOT_FULL; + } + + result = GetUIntLength(m_pReader, pos, len); + + if (result < 0) // error + return static_cast(result); + + if (result > 0) // underflow (weird) + { + len = 1; + return E_BUFFER_NOT_FULL; + } + + if ((segment_stop >= 0) && ((pos + len) > segment_stop)) + return E_FILE_FORMAT_INVALID; + + if ((pos + len) > avail) + return E_BUFFER_NOT_FULL; + + const long long size = ReadUInt(m_pReader, pos, len); + + if (size < 0) // error + return static_cast(size); + + if (size == 0) // weird, although technically not illegal + return 1; // done + + pos += len; // consume length of size of element + assert((segment_stop < 0) || (pos <= segment_stop)); + + // Pos now points to start of payload + + const long long element_stop = pos + size; + + if ((segment_stop >= 0) && (element_stop > segment_stop)) + return E_FILE_FORMAT_INVALID; + + if ((total >= 0) && (element_stop > total)) + return 1; // don't bother parsing anymore + + len = static_cast(size); + + if (element_stop > avail) + return E_BUFFER_NOT_FULL; + + const long long element_size = element_stop - element_start; + + m_pCues = + new (std::nothrow) Cues(this, pos, size, element_start, element_size); + if (m_pCues == NULL) + return -1; + + return 0; // success +} + +bool SeekHead::ParseEntry(IMkvReader* pReader, long long start, long long size_, + Entry* pEntry) { + if (size_ <= 0) + return false; + + long long pos = start; + const long long stop = start + size_; + + long len; + + // parse the container for the level-1 element ID + + const long long seekIdId = ReadID(pReader, pos, len); + if (seekIdId < 0) + return false; + + if (seekIdId != libwebm::kMkvSeekID) + return false; + + if ((pos + len) > stop) + return false; + + pos += len; // consume SeekID id + + const long long seekIdSize = ReadUInt(pReader, pos, len); + + if (seekIdSize <= 0) + return false; + + if ((pos + len) > stop) + return false; + + pos += len; // consume size of field + + if ((pos + seekIdSize) > stop) + return false; + + pEntry->id = ReadID(pReader, pos, len); // payload + + if (pEntry->id <= 0) + return false; + + if (len != seekIdSize) + return false; + + pos += seekIdSize; // consume SeekID payload + + const long long seekPosId = ReadID(pReader, pos, len); + + if (seekPosId != libwebm::kMkvSeekPosition) + return false; + + if ((pos + len) > stop) + return false; + + pos += len; // consume id + + const long long seekPosSize = ReadUInt(pReader, pos, len); + + if (seekPosSize <= 0) + return false; + + if ((pos + len) > stop) + return false; + + pos += len; // consume size + + if ((pos + seekPosSize) > stop) + return false; + + pEntry->pos = UnserializeUInt(pReader, pos, seekPosSize); + + if (pEntry->pos < 0) + return false; + + pos += seekPosSize; // consume payload + + if (pos != stop) + return false; + + return true; +} + +Cues::Cues(Segment* pSegment, long long start_, long long size_, + long long element_start, long long element_size) + : m_pSegment(pSegment), + m_start(start_), + m_size(size_), + m_element_start(element_start), + m_element_size(element_size), + m_cue_points(NULL), + m_count(0), + m_preload_count(0), + m_pos(start_) {} + +Cues::~Cues() { + const long n = m_count + m_preload_count; + + CuePoint** p = m_cue_points; + CuePoint** const q = p + n; + + while (p != q) { + CuePoint* const pCP = *p++; + assert(pCP); + + delete pCP; + } + + delete[] m_cue_points; +} + +long Cues::GetCount() const { + if (m_cue_points == NULL) + return -1; + + return m_count; // TODO: really ignore preload count? +} + +bool Cues::DoneParsing() const { + const long long stop = m_start + m_size; + return (m_pos >= stop); +} + +bool Cues::Init() const { + if (m_cue_points) + return true; + + if (m_count != 0 || m_preload_count != 0) + return false; + + IMkvReader* const pReader = m_pSegment->m_pReader; + + const long long stop = m_start + m_size; + long long pos = m_start; + + long cue_points_size = 0; + + while (pos < stop) { + const long long idpos = pos; + + long len; + + const long long id = ReadID(pReader, pos, len); + if (id < 0 || (pos + len) > stop) { + return false; + } + + pos += len; // consume ID + + const long long size = ReadUInt(pReader, pos, len); + if (size < 0 || (pos + len > stop)) { + return false; + } + + pos += len; // consume Size field + if (pos + size > stop) { + return false; + } + + if (id == libwebm::kMkvCuePoint) { + if (!PreloadCuePoint(cue_points_size, idpos)) + return false; + } + + pos += size; // skip payload + } + return true; +} + +bool Cues::PreloadCuePoint(long& cue_points_size, long long pos) const { + if (m_count != 0) + return false; + + if (m_preload_count >= cue_points_size) { + const long n = (cue_points_size <= 0) ? 2048 : 2 * cue_points_size; + + CuePoint** const qq = new (std::nothrow) CuePoint*[n]; + if (qq == NULL) + return false; + + CuePoint** q = qq; // beginning of target + + CuePoint** p = m_cue_points; // beginning of source + CuePoint** const pp = p + m_preload_count; // end of source + + while (p != pp) + *q++ = *p++; + + delete[] m_cue_points; + + m_cue_points = qq; + cue_points_size = n; + } + + CuePoint* const pCP = new (std::nothrow) CuePoint(m_preload_count, pos); + if (pCP == NULL) + return false; + + m_cue_points[m_preload_count++] = pCP; + return true; +} + +bool Cues::LoadCuePoint() const { + const long long stop = m_start + m_size; + + if (m_pos >= stop) + return false; // nothing else to do + + if (!Init()) { + m_pos = stop; + return false; + } + + IMkvReader* const pReader = m_pSegment->m_pReader; + + while (m_pos < stop) { + const long long idpos = m_pos; + + long len; + + const long long id = ReadID(pReader, m_pos, len); + if (id < 0 || (m_pos + len) > stop) + return false; + + m_pos += len; // consume ID + + const long long size = ReadUInt(pReader, m_pos, len); + if (size < 0 || (m_pos + len) > stop) + return false; + + m_pos += len; // consume Size field + if ((m_pos + size) > stop) + return false; + + if (id != libwebm::kMkvCuePoint) { + m_pos += size; // consume payload + if (m_pos > stop) + return false; + + continue; + } + + if (m_preload_count < 1) + return false; + + CuePoint* const pCP = m_cue_points[m_count]; + if (!pCP || (pCP->GetTimeCode() < 0 && (-pCP->GetTimeCode() != idpos))) + return false; + + if (!pCP->Load(pReader)) { + m_pos = stop; + return false; + } + ++m_count; + --m_preload_count; + + m_pos += size; // consume payload + if (m_pos > stop) + return false; + + return true; // yes, we loaded a cue point + } + + return false; // no, we did not load a cue point +} + +bool Cues::Find(long long time_ns, const Track* pTrack, const CuePoint*& pCP, + const CuePoint::TrackPosition*& pTP) const { + if (time_ns < 0 || pTrack == NULL || m_cue_points == NULL || m_count == 0) + return false; + + CuePoint** const ii = m_cue_points; + CuePoint** i = ii; + + CuePoint** const jj = ii + m_count; + CuePoint** j = jj; + + pCP = *i; + if (pCP == NULL) + return false; + + if (time_ns <= pCP->GetTime(m_pSegment)) { + pTP = pCP->Find(pTrack); + return (pTP != NULL); + } + + while (i < j) { + // INVARIANT: + //[ii, i) <= time_ns + //[i, j) ? + //[j, jj) > time_ns + + CuePoint** const k = i + (j - i) / 2; + if (k >= jj) + return false; + + CuePoint* const pCP = *k; + if (pCP == NULL) + return false; + + const long long t = pCP->GetTime(m_pSegment); + + if (t <= time_ns) + i = k + 1; + else + j = k; + + if (i > j) + return false; + } + + if (i != j || i > jj || i <= ii) + return false; + + pCP = *--i; + + if (pCP == NULL || pCP->GetTime(m_pSegment) > time_ns) + return false; + + // TODO: here and elsewhere, it's probably not correct to search + // for the cue point with this time, and then search for a matching + // track. In principle, the matching track could be on some earlier + // cue point, and with our current algorithm, we'd miss it. To make + // this bullet-proof, we'd need to create a secondary structure, + // with a list of cue points that apply to a track, and then search + // that track-based structure for a matching cue point. + + pTP = pCP->Find(pTrack); + return (pTP != NULL); +} + +const CuePoint* Cues::GetFirst() const { + if (m_cue_points == NULL || m_count == 0) + return NULL; + + CuePoint* const* const pp = m_cue_points; + if (pp == NULL) + return NULL; + + CuePoint* const pCP = pp[0]; + if (pCP == NULL || pCP->GetTimeCode() < 0) + return NULL; + + return pCP; +} + +const CuePoint* Cues::GetLast() const { + if (m_cue_points == NULL || m_count <= 0) + return NULL; + + const long index = m_count - 1; + + CuePoint* const* const pp = m_cue_points; + if (pp == NULL) + return NULL; + + CuePoint* const pCP = pp[index]; + if (pCP == NULL || pCP->GetTimeCode() < 0) + return NULL; + + return pCP; +} + +const CuePoint* Cues::GetNext(const CuePoint* pCurr) const { + if (pCurr == NULL || pCurr->GetTimeCode() < 0 || m_cue_points == NULL || + m_count < 1) { + return NULL; + } + + long index = pCurr->m_index; + if (index >= m_count) + return NULL; + + CuePoint* const* const pp = m_cue_points; + if (pp == NULL || pp[index] != pCurr) + return NULL; + + ++index; + + if (index >= m_count) + return NULL; + + CuePoint* const pNext = pp[index]; + + if (pNext == NULL || pNext->GetTimeCode() < 0) + return NULL; + + return pNext; +} + +const BlockEntry* Cues::GetBlock(const CuePoint* pCP, + const CuePoint::TrackPosition* pTP) const { + if (pCP == NULL || pTP == NULL) + return NULL; + + return m_pSegment->GetBlock(*pCP, *pTP); +} + +const BlockEntry* Segment::GetBlock(const CuePoint& cp, + const CuePoint::TrackPosition& tp) { + Cluster** const ii = m_clusters; + Cluster** i = ii; + + const long count = m_clusterCount + m_clusterPreloadCount; + + Cluster** const jj = ii + count; + Cluster** j = jj; + + while (i < j) { + // INVARIANT: + //[ii, i) < pTP->m_pos + //[i, j) ? + //[j, jj) > pTP->m_pos + + Cluster** const k = i + (j - i) / 2; + assert(k < jj); + + Cluster* const pCluster = *k; + assert(pCluster); + + // const long long pos_ = pCluster->m_pos; + // assert(pos_); + // const long long pos = pos_ * ((pos_ < 0) ? -1 : 1); + + const long long pos = pCluster->GetPosition(); + assert(pos >= 0); + + if (pos < tp.m_pos) + i = k + 1; + else if (pos > tp.m_pos) + j = k; + else + return pCluster->GetEntry(cp, tp); + } + + assert(i == j); + // assert(Cluster::HasBlockEntries(this, tp.m_pos)); + + Cluster* const pCluster = Cluster::Create(this, -1, tp.m_pos); //, -1); + if (pCluster == NULL) + return NULL; + + const ptrdiff_t idx = i - m_clusters; + + if (!PreloadCluster(pCluster, idx)) { + delete pCluster; + return NULL; + } + assert(m_clusters); + assert(m_clusterPreloadCount > 0); + assert(m_clusters[idx] == pCluster); + + return pCluster->GetEntry(cp, tp); +} + +const Cluster* Segment::FindOrPreloadCluster(long long requested_pos) { + if (requested_pos < 0) + return 0; + + Cluster** const ii = m_clusters; + Cluster** i = ii; + + const long count = m_clusterCount + m_clusterPreloadCount; + + Cluster** const jj = ii + count; + Cluster** j = jj; + + while (i < j) { + // INVARIANT: + //[ii, i) < pTP->m_pos + //[i, j) ? + //[j, jj) > pTP->m_pos + + Cluster** const k = i + (j - i) / 2; + assert(k < jj); + + Cluster* const pCluster = *k; + assert(pCluster); + + // const long long pos_ = pCluster->m_pos; + // assert(pos_); + // const long long pos = pos_ * ((pos_ < 0) ? -1 : 1); + + const long long pos = pCluster->GetPosition(); + assert(pos >= 0); + + if (pos < requested_pos) + i = k + 1; + else if (pos > requested_pos) + j = k; + else + return pCluster; + } + + assert(i == j); + // assert(Cluster::HasBlockEntries(this, tp.m_pos)); + + Cluster* const pCluster = Cluster::Create(this, -1, requested_pos); + if (pCluster == NULL) + return NULL; + + const ptrdiff_t idx = i - m_clusters; + + if (!PreloadCluster(pCluster, idx)) { + delete pCluster; + return NULL; + } + assert(m_clusters); + assert(m_clusterPreloadCount > 0); + assert(m_clusters[idx] == pCluster); + + return pCluster; +} + +CuePoint::CuePoint(long idx, long long pos) + : m_element_start(0), + m_element_size(0), + m_index(idx), + m_timecode(-1 * pos), + m_track_positions(NULL), + m_track_positions_count(0) { + assert(pos > 0); +} + +CuePoint::~CuePoint() { delete[] m_track_positions; } + +bool CuePoint::Load(IMkvReader* pReader) { + // odbgstream os; + // os << "CuePoint::Load(begin): timecode=" << m_timecode << endl; + + if (m_timecode >= 0) // already loaded + return true; + + assert(m_track_positions == NULL); + assert(m_track_positions_count == 0); + + long long pos_ = -m_timecode; + const long long element_start = pos_; + + long long stop; + + { + long len; + + const long long id = ReadID(pReader, pos_, len); + if (id != libwebm::kMkvCuePoint) + return false; + + pos_ += len; // consume ID + + const long long size = ReadUInt(pReader, pos_, len); + assert(size >= 0); + + pos_ += len; // consume Size field + // pos_ now points to start of payload + + stop = pos_ + size; + } + + const long long element_size = stop - element_start; + + long long pos = pos_; + + // First count number of track positions + unsigned long long track_positions_count = 0; + while (pos < stop) { + long len; + + const long long id = ReadID(pReader, pos, len); + if ((id < 0) || (pos + len > stop)) { + return false; + } + + pos += len; // consume ID + + const long long size = ReadUInt(pReader, pos, len); + if ((size < 0) || (pos + len > stop)) { + return false; + } + + pos += len; // consume Size field + if ((pos + size) > stop) { + return false; + } + + if (id == libwebm::kMkvCueTime) + m_timecode = UnserializeUInt(pReader, pos, size); + + else if (id == libwebm::kMkvCueTrackPositions) { + ++track_positions_count; + if (track_positions_count > UINT_MAX) + return E_PARSE_FAILED; + } + + pos += size; // consume payload + } + + m_track_positions_count = static_cast(track_positions_count); + + if (m_timecode < 0 || m_track_positions_count <= 0) { + return false; + } + + // os << "CuePoint::Load(cont'd): idpos=" << idpos + // << " timecode=" << m_timecode + // << endl; + + m_track_positions = new (std::nothrow) TrackPosition[m_track_positions_count]; + if (m_track_positions == NULL) + return false; + + // Now parse track positions + + TrackPosition* p = m_track_positions; + pos = pos_; + + while (pos < stop) { + long len; + + const long long id = ReadID(pReader, pos, len); + if (id < 0 || (pos + len) > stop) + return false; + + pos += len; // consume ID + + const long long size = ReadUInt(pReader, pos, len); + assert(size >= 0); + assert((pos + len) <= stop); + + pos += len; // consume Size field + assert((pos + size) <= stop); + + if (id == libwebm::kMkvCueTrackPositions) { + TrackPosition& tp = *p++; + if (!tp.Parse(pReader, pos, size)) { + return false; + } + } + + pos += size; // consume payload + if (pos > stop) + return false; + } + + assert(size_t(p - m_track_positions) == m_track_positions_count); + + m_element_start = element_start; + m_element_size = element_size; + + return true; +} + +bool CuePoint::TrackPosition::Parse(IMkvReader* pReader, long long start_, + long long size_) { + const long long stop = start_ + size_; + long long pos = start_; + + m_track = -1; + m_pos = -1; + m_block = 1; // default + + while (pos < stop) { + long len; + + const long long id = ReadID(pReader, pos, len); + if ((id < 0) || ((pos + len) > stop)) { + return false; + } + + pos += len; // consume ID + + const long long size = ReadUInt(pReader, pos, len); + if ((size < 0) || ((pos + len) > stop)) { + return false; + } + + pos += len; // consume Size field + if ((pos + size) > stop) { + return false; + } + + if (id == libwebm::kMkvCueTrack) + m_track = UnserializeUInt(pReader, pos, size); + else if (id == libwebm::kMkvCueClusterPosition) + m_pos = UnserializeUInt(pReader, pos, size); + else if (id == libwebm::kMkvCueBlockNumber) + m_block = UnserializeUInt(pReader, pos, size); + + pos += size; // consume payload + } + + if ((m_pos < 0) || (m_track <= 0)) { + return false; + } + + return true; +} + +const CuePoint::TrackPosition* CuePoint::Find(const Track* pTrack) const { + if (pTrack == NULL) { + return NULL; + } + + const long long n = pTrack->GetNumber(); + + const TrackPosition* i = m_track_positions; + const TrackPosition* const j = i + m_track_positions_count; + + while (i != j) { + const TrackPosition& p = *i++; + + if (p.m_track == n) + return &p; + } + + return NULL; // no matching track number found +} + +long long CuePoint::GetTimeCode() const { return m_timecode; } + +long long CuePoint::GetTime(const Segment* pSegment) const { + assert(pSegment); + assert(m_timecode >= 0); + + const SegmentInfo* const pInfo = pSegment->GetInfo(); + assert(pInfo); + + const long long scale = pInfo->GetTimeCodeScale(); + assert(scale >= 1); + + const long long time = scale * m_timecode; + + return time; +} + +bool Segment::DoneParsing() const { + if (m_size < 0) { + long long total, avail; + + const int status = m_pReader->Length(&total, &avail); + + if (status < 0) // error + return true; // must assume done + + if (total < 0) + return false; // assume live stream + + return (m_pos >= total); + } + + const long long stop = m_start + m_size; + + return (m_pos >= stop); +} + +const Cluster* Segment::GetFirst() const { + if ((m_clusters == NULL) || (m_clusterCount <= 0)) + return &m_eos; + + Cluster* const pCluster = m_clusters[0]; + assert(pCluster); + + return pCluster; +} + +const Cluster* Segment::GetLast() const { + if ((m_clusters == NULL) || (m_clusterCount <= 0)) + return &m_eos; + + const long idx = m_clusterCount - 1; + + Cluster* const pCluster = m_clusters[idx]; + assert(pCluster); + + return pCluster; +} + +unsigned long Segment::GetCount() const { return m_clusterCount; } + +const Cluster* Segment::GetNext(const Cluster* pCurr) { + assert(pCurr); + assert(pCurr != &m_eos); + assert(m_clusters); + + long idx = pCurr->m_index; + + if (idx >= 0) { + assert(m_clusterCount > 0); + assert(idx < m_clusterCount); + assert(pCurr == m_clusters[idx]); + + ++idx; + + if (idx >= m_clusterCount) + return &m_eos; // caller will LoadCluster as desired + + Cluster* const pNext = m_clusters[idx]; + assert(pNext); + assert(pNext->m_index >= 0); + assert(pNext->m_index == idx); + + return pNext; + } + + assert(m_clusterPreloadCount > 0); + + long long pos = pCurr->m_element_start; + + assert(m_size >= 0); // TODO + const long long stop = m_start + m_size; // end of segment + + { + long len; + + long long result = GetUIntLength(m_pReader, pos, len); + assert(result == 0); + assert((pos + len) <= stop); // TODO + if (result != 0) + return NULL; + + const long long id = ReadID(m_pReader, pos, len); + if (id != libwebm::kMkvCluster) + return NULL; + + pos += len; // consume ID + + // Read Size + result = GetUIntLength(m_pReader, pos, len); + assert(result == 0); // TODO + assert((pos + len) <= stop); // TODO + + const long long size = ReadUInt(m_pReader, pos, len); + assert(size > 0); // TODO + // assert((pCurr->m_size <= 0) || (pCurr->m_size == size)); + + pos += len; // consume length of size of element + assert((pos + size) <= stop); // TODO + + // Pos now points to start of payload + + pos += size; // consume payload + } + + long long off_next = 0; + + while (pos < stop) { + long len; + + long long result = GetUIntLength(m_pReader, pos, len); + assert(result == 0); + assert((pos + len) <= stop); // TODO + if (result != 0) + return NULL; + + const long long idpos = pos; // pos of next (potential) cluster + + const long long id = ReadID(m_pReader, idpos, len); + if (id < 0) + return NULL; + + pos += len; // consume ID + + // Read Size + result = GetUIntLength(m_pReader, pos, len); + assert(result == 0); // TODO + assert((pos + len) <= stop); // TODO + + const long long size = ReadUInt(m_pReader, pos, len); + assert(size >= 0); // TODO + + pos += len; // consume length of size of element + assert((pos + size) <= stop); // TODO + + // Pos now points to start of payload + + if (size == 0) // weird + continue; + + if (id == libwebm::kMkvCluster) { + const long long off_next_ = idpos - m_start; + + long long pos_; + long len_; + + const long status = Cluster::HasBlockEntries(this, off_next_, pos_, len_); + + assert(status >= 0); + + if (status > 0) { + off_next = off_next_; + break; + } + } + + pos += size; // consume payload + } + + if (off_next <= 0) + return 0; + + Cluster** const ii = m_clusters + m_clusterCount; + Cluster** i = ii; + + Cluster** const jj = ii + m_clusterPreloadCount; + Cluster** j = jj; + + while (i < j) { + // INVARIANT: + //[0, i) < pos_next + //[i, j) ? + //[j, jj) > pos_next + + Cluster** const k = i + (j - i) / 2; + assert(k < jj); + + Cluster* const pNext = *k; + assert(pNext); + assert(pNext->m_index < 0); + + // const long long pos_ = pNext->m_pos; + // assert(pos_); + // pos = pos_ * ((pos_ < 0) ? -1 : 1); + + pos = pNext->GetPosition(); + + if (pos < off_next) + i = k + 1; + else if (pos > off_next) + j = k; + else + return pNext; + } + + assert(i == j); + + Cluster* const pNext = Cluster::Create(this, -1, off_next); + if (pNext == NULL) + return NULL; + + const ptrdiff_t idx_next = i - m_clusters; // insertion position + + if (!PreloadCluster(pNext, idx_next)) { + delete pNext; + return NULL; + } + assert(m_clusters); + assert(idx_next < m_clusterSize); + assert(m_clusters[idx_next] == pNext); + + return pNext; +} + +long Segment::ParseNext(const Cluster* pCurr, const Cluster*& pResult, + long long& pos, long& len) { + assert(pCurr); + assert(!pCurr->EOS()); + assert(m_clusters); + + pResult = 0; + + if (pCurr->m_index >= 0) { // loaded (not merely preloaded) + assert(m_clusters[pCurr->m_index] == pCurr); + + const long next_idx = pCurr->m_index + 1; + + if (next_idx < m_clusterCount) { + pResult = m_clusters[next_idx]; + return 0; // success + } + + // curr cluster is last among loaded + + const long result = LoadCluster(pos, len); + + if (result < 0) // error or underflow + return result; + + if (result > 0) // no more clusters + { + // pResult = &m_eos; + return 1; + } + + pResult = GetLast(); + return 0; // success + } + + assert(m_pos > 0); + + long long total, avail; + + long status = m_pReader->Length(&total, &avail); + + if (status < 0) // error + return status; + + assert((total < 0) || (avail <= total)); + + const long long segment_stop = (m_size < 0) ? -1 : m_start + m_size; + + // interrogate curr cluster + + pos = pCurr->m_element_start; + + if (pCurr->m_element_size >= 0) + pos += pCurr->m_element_size; + else { + if ((pos + 1) > avail) { + len = 1; + return E_BUFFER_NOT_FULL; + } + + long long result = GetUIntLength(m_pReader, pos, len); + + if (result < 0) // error + return static_cast(result); + + if (result > 0) // weird + return E_BUFFER_NOT_FULL; + + if ((segment_stop >= 0) && ((pos + len) > segment_stop)) + return E_FILE_FORMAT_INVALID; + + if ((pos + len) > avail) + return E_BUFFER_NOT_FULL; + + const long long id = ReadUInt(m_pReader, pos, len); + + if (id != libwebm::kMkvCluster) + return -1; + + pos += len; // consume ID + + // Read Size + + if ((pos + 1) > avail) { + len = 1; + return E_BUFFER_NOT_FULL; + } + + result = GetUIntLength(m_pReader, pos, len); + + if (result < 0) // error + return static_cast(result); + + if (result > 0) // weird + return E_BUFFER_NOT_FULL; + + if ((segment_stop >= 0) && ((pos + len) > segment_stop)) + return E_FILE_FORMAT_INVALID; + + if ((pos + len) > avail) + return E_BUFFER_NOT_FULL; + + const long long size = ReadUInt(m_pReader, pos, len); + + if (size < 0) // error + return static_cast(size); + + pos += len; // consume size field + + const long long unknown_size = (1LL << (7 * len)) - 1; + + if (size == unknown_size) // TODO: should never happen + return E_FILE_FORMAT_INVALID; // TODO: resolve this + + // assert((pCurr->m_size <= 0) || (pCurr->m_size == size)); + + if ((segment_stop >= 0) && ((pos + size) > segment_stop)) + return E_FILE_FORMAT_INVALID; + + // Pos now points to start of payload + + pos += size; // consume payload (that is, the current cluster) + if (segment_stop >= 0 && pos > segment_stop) + return E_FILE_FORMAT_INVALID; + + // By consuming the payload, we are assuming that the curr + // cluster isn't interesting. That is, we don't bother checking + // whether the payload of the curr cluster is less than what + // happens to be available (obtained via IMkvReader::Length). + // Presumably the caller has already dispensed with the current + // cluster, and really does want the next cluster. + } + + // pos now points to just beyond the last fully-loaded cluster + + for (;;) { + const long status = DoParseNext(pResult, pos, len); + + if (status <= 1) + return status; + } +} + +long Segment::DoParseNext(const Cluster*& pResult, long long& pos, long& len) { + long long total, avail; + + long status = m_pReader->Length(&total, &avail); + + if (status < 0) // error + return status; + + assert((total < 0) || (avail <= total)); + + const long long segment_stop = (m_size < 0) ? -1 : m_start + m_size; + + // Parse next cluster. This is strictly a parsing activity. + // Creation of a new cluster object happens later, after the + // parsing is done. + + long long off_next = 0; + long long cluster_size = -1; + + for (;;) { + if ((total >= 0) && (pos >= total)) + return 1; // EOF + + if ((segment_stop >= 0) && (pos >= segment_stop)) + return 1; // EOF + + if ((pos + 1) > avail) { + len = 1; + return E_BUFFER_NOT_FULL; + } + + long long result = GetUIntLength(m_pReader, pos, len); + + if (result < 0) // error + return static_cast(result); + + if (result > 0) // weird + return E_BUFFER_NOT_FULL; + + if ((segment_stop >= 0) && ((pos + len) > segment_stop)) + return E_FILE_FORMAT_INVALID; + + if ((pos + len) > avail) + return E_BUFFER_NOT_FULL; + + const long long idpos = pos; // absolute + const long long idoff = pos - m_start; // relative + + const long long id = ReadID(m_pReader, idpos, len); // absolute + + if (id < 0) // error + return static_cast(id); + + if (id == 0) // weird + return -1; // generic error + + pos += len; // consume ID + + // Read Size + + if ((pos + 1) > avail) { + len = 1; + return E_BUFFER_NOT_FULL; + } + + result = GetUIntLength(m_pReader, pos, len); + + if (result < 0) // error + return static_cast(result); + + if (result > 0) // weird + return E_BUFFER_NOT_FULL; + + if ((segment_stop >= 0) && ((pos + len) > segment_stop)) + return E_FILE_FORMAT_INVALID; + + if ((pos + len) > avail) + return E_BUFFER_NOT_FULL; + + const long long size = ReadUInt(m_pReader, pos, len); + + if (size < 0) // error + return static_cast(size); + + pos += len; // consume length of size of element + + // Pos now points to start of payload + + if (size == 0) // weird + continue; + + const long long unknown_size = (1LL << (7 * len)) - 1; + + if ((segment_stop >= 0) && (size != unknown_size) && + ((pos + size) > segment_stop)) { + return E_FILE_FORMAT_INVALID; + } + + if (id == libwebm::kMkvCues) { + if (size == unknown_size) + return E_FILE_FORMAT_INVALID; + + const long long element_stop = pos + size; + + if ((segment_stop >= 0) && (element_stop > segment_stop)) + return E_FILE_FORMAT_INVALID; + + const long long element_start = idpos; + const long long element_size = element_stop - element_start; + + if (m_pCues == NULL) { + m_pCues = new (std::nothrow) + Cues(this, pos, size, element_start, element_size); + if (m_pCues == NULL) + return false; + } + + pos += size; // consume payload + if (segment_stop >= 0 && pos > segment_stop) + return E_FILE_FORMAT_INVALID; + + continue; + } + + if (id != libwebm::kMkvCluster) { // not a Cluster ID + if (size == unknown_size) + return E_FILE_FORMAT_INVALID; + + pos += size; // consume payload + if (segment_stop >= 0 && pos > segment_stop) + return E_FILE_FORMAT_INVALID; + + continue; + } + + // We have a cluster. + off_next = idoff; + + if (size != unknown_size) + cluster_size = size; + + break; + } + + assert(off_next > 0); // have cluster + + // We have parsed the next cluster. + // We have not created a cluster object yet. What we need + // to do now is determine whether it has already be preloaded + //(in which case, an object for this cluster has already been + // created), and if not, create a new cluster object. + + Cluster** const ii = m_clusters + m_clusterCount; + Cluster** i = ii; + + Cluster** const jj = ii + m_clusterPreloadCount; + Cluster** j = jj; + + while (i < j) { + // INVARIANT: + //[0, i) < pos_next + //[i, j) ? + //[j, jj) > pos_next + + Cluster** const k = i + (j - i) / 2; + assert(k < jj); + + const Cluster* const pNext = *k; + assert(pNext); + assert(pNext->m_index < 0); + + pos = pNext->GetPosition(); + assert(pos >= 0); + + if (pos < off_next) + i = k + 1; + else if (pos > off_next) + j = k; + else { + pResult = pNext; + return 0; // success + } + } + + assert(i == j); + + long long pos_; + long len_; + + status = Cluster::HasBlockEntries(this, off_next, pos_, len_); + + if (status < 0) { // error or underflow + pos = pos_; + len = len_; + + return status; + } + + if (status > 0) { // means "found at least one block entry" + Cluster* const pNext = Cluster::Create(this, + -1, // preloaded + off_next); + if (pNext == NULL) + return -1; + + const ptrdiff_t idx_next = i - m_clusters; // insertion position + + if (!PreloadCluster(pNext, idx_next)) { + delete pNext; + return -1; + } + assert(m_clusters); + assert(idx_next < m_clusterSize); + assert(m_clusters[idx_next] == pNext); + + pResult = pNext; + return 0; // success + } + + // status == 0 means "no block entries found" + + if (cluster_size < 0) { // unknown size + const long long payload_pos = pos; // absolute pos of cluster payload + + for (;;) { // determine cluster size + if ((total >= 0) && (pos >= total)) + break; + + if ((segment_stop >= 0) && (pos >= segment_stop)) + break; // no more clusters + + // Read ID + + if ((pos + 1) > avail) { + len = 1; + return E_BUFFER_NOT_FULL; + } + + long long result = GetUIntLength(m_pReader, pos, len); + + if (result < 0) // error + return static_cast(result); + + if (result > 0) // weird + return E_BUFFER_NOT_FULL; + + if ((segment_stop >= 0) && ((pos + len) > segment_stop)) + return E_FILE_FORMAT_INVALID; + + if ((pos + len) > avail) + return E_BUFFER_NOT_FULL; + + const long long idpos = pos; + const long long id = ReadID(m_pReader, idpos, len); + + if (id < 0) // error (or underflow) + return static_cast(id); + + // This is the distinguished set of ID's we use to determine + // that we have exhausted the sub-element's inside the cluster + // whose ID we parsed earlier. + + if (id == libwebm::kMkvCluster || id == libwebm::kMkvCues) + break; + + pos += len; // consume ID (of sub-element) + + // Read Size + + if ((pos + 1) > avail) { + len = 1; + return E_BUFFER_NOT_FULL; + } + + result = GetUIntLength(m_pReader, pos, len); + + if (result < 0) // error + return static_cast(result); + + if (result > 0) // weird + return E_BUFFER_NOT_FULL; + + if ((segment_stop >= 0) && ((pos + len) > segment_stop)) + return E_FILE_FORMAT_INVALID; + + if ((pos + len) > avail) + return E_BUFFER_NOT_FULL; + + const long long size = ReadUInt(m_pReader, pos, len); + + if (size < 0) // error + return static_cast(size); + + pos += len; // consume size field of element + + // pos now points to start of sub-element's payload + + if (size == 0) // weird + continue; + + const long long unknown_size = (1LL << (7 * len)) - 1; + + if (size == unknown_size) + return E_FILE_FORMAT_INVALID; // not allowed for sub-elements + + if ((segment_stop >= 0) && ((pos + size) > segment_stop)) // weird + return E_FILE_FORMAT_INVALID; + + pos += size; // consume payload of sub-element + if (segment_stop >= 0 && pos > segment_stop) + return E_FILE_FORMAT_INVALID; + } // determine cluster size + + cluster_size = pos - payload_pos; + assert(cluster_size >= 0); // TODO: handle cluster_size = 0 + + pos = payload_pos; // reset and re-parse original cluster + } + + pos += cluster_size; // consume payload + if (segment_stop >= 0 && pos > segment_stop) + return E_FILE_FORMAT_INVALID; + + return 2; // try to find a cluster that follows next +} + +const Cluster* Segment::FindCluster(long long time_ns) const { + if ((m_clusters == NULL) || (m_clusterCount <= 0)) + return &m_eos; + + { + Cluster* const pCluster = m_clusters[0]; + assert(pCluster); + assert(pCluster->m_index == 0); + + if (time_ns <= pCluster->GetTime()) + return pCluster; + } + + // Binary search of cluster array + + long i = 0; + long j = m_clusterCount; + + while (i < j) { + // INVARIANT: + //[0, i) <= time_ns + //[i, j) ? + //[j, m_clusterCount) > time_ns + + const long k = i + (j - i) / 2; + assert(k < m_clusterCount); + + Cluster* const pCluster = m_clusters[k]; + assert(pCluster); + assert(pCluster->m_index == k); + + const long long t = pCluster->GetTime(); + + if (t <= time_ns) + i = k + 1; + else + j = k; + + assert(i <= j); + } + + assert(i == j); + assert(i > 0); + assert(i <= m_clusterCount); + + const long k = i - 1; + + Cluster* const pCluster = m_clusters[k]; + assert(pCluster); + assert(pCluster->m_index == k); + assert(pCluster->GetTime() <= time_ns); + + return pCluster; +} + +const Tracks* Segment::GetTracks() const { return m_pTracks; } +const SegmentInfo* Segment::GetInfo() const { return m_pInfo; } +const Cues* Segment::GetCues() const { return m_pCues; } +const Chapters* Segment::GetChapters() const { return m_pChapters; } +const Tags* Segment::GetTags() const { return m_pTags; } +const SeekHead* Segment::GetSeekHead() const { return m_pSeekHead; } + +long long Segment::GetDuration() const { + assert(m_pInfo); + return m_pInfo->GetDuration(); +} + +Chapters::Chapters(Segment* pSegment, long long payload_start, + long long payload_size, long long element_start, + long long element_size) + : m_pSegment(pSegment), + m_start(payload_start), + m_size(payload_size), + m_element_start(element_start), + m_element_size(element_size), + m_editions(NULL), + m_editions_size(0), + m_editions_count(0) {} + +Chapters::~Chapters() { + while (m_editions_count > 0) { + Edition& e = m_editions[--m_editions_count]; + e.Clear(); + } + delete[] m_editions; +} + +long Chapters::Parse() { + IMkvReader* const pReader = m_pSegment->m_pReader; + + long long pos = m_start; // payload start + const long long stop = pos + m_size; // payload stop + + while (pos < stop) { + long long id, size; + + long status = ParseElementHeader(pReader, pos, stop, id, size); + + if (status < 0) // error + return status; + + if (size == 0) // weird + continue; + + if (id == libwebm::kMkvEditionEntry) { + status = ParseEdition(pos, size); + + if (status < 0) // error + return status; + } + + pos += size; + if (pos > stop) + return E_FILE_FORMAT_INVALID; + } + + if (pos != stop) + return E_FILE_FORMAT_INVALID; + return 0; +} + +int Chapters::GetEditionCount() const { return m_editions_count; } + +const Chapters::Edition* Chapters::GetEdition(int idx) const { + if (idx < 0) + return NULL; + + if (idx >= m_editions_count) + return NULL; + + return m_editions + idx; +} + +bool Chapters::ExpandEditionsArray() { + if (m_editions_size > m_editions_count) + return true; // nothing else to do + + const int size = (m_editions_size == 0) ? 1 : 2 * m_editions_size; + + Edition* const editions = new (std::nothrow) Edition[size]; + + if (editions == NULL) + return false; + + for (int idx = 0; idx < m_editions_count; ++idx) { + m_editions[idx].ShallowCopy(editions[idx]); + } + + delete[] m_editions; + m_editions = editions; + + m_editions_size = size; + return true; +} + +long Chapters::ParseEdition(long long pos, long long size) { + if (!ExpandEditionsArray()) + return -1; + + Edition& e = m_editions[m_editions_count++]; + e.Init(); + + return e.Parse(m_pSegment->m_pReader, pos, size); +} + +Chapters::Edition::Edition() {} + +Chapters::Edition::~Edition() {} + +int Chapters::Edition::GetAtomCount() const { return m_atoms_count; } + +const Chapters::Atom* Chapters::Edition::GetAtom(int index) const { + if (index < 0) + return NULL; + + if (index >= m_atoms_count) + return NULL; + + return m_atoms + index; +} + +void Chapters::Edition::Init() { + m_atoms = NULL; + m_atoms_size = 0; + m_atoms_count = 0; +} + +void Chapters::Edition::ShallowCopy(Edition& rhs) const { + rhs.m_atoms = m_atoms; + rhs.m_atoms_size = m_atoms_size; + rhs.m_atoms_count = m_atoms_count; +} + +void Chapters::Edition::Clear() { + while (m_atoms_count > 0) { + Atom& a = m_atoms[--m_atoms_count]; + a.Clear(); + } + + delete[] m_atoms; + m_atoms = NULL; + + m_atoms_size = 0; +} + +long Chapters::Edition::Parse(IMkvReader* pReader, long long pos, + long long size) { + const long long stop = pos + size; + + while (pos < stop) { + long long id, size; + + long status = ParseElementHeader(pReader, pos, stop, id, size); + + if (status < 0) // error + return status; + + if (size == 0) + continue; + + if (id == libwebm::kMkvChapterAtom) { + status = ParseAtom(pReader, pos, size); + + if (status < 0) // error + return status; + } + + pos += size; + if (pos > stop) + return E_FILE_FORMAT_INVALID; + } + + if (pos != stop) + return E_FILE_FORMAT_INVALID; + return 0; +} + +long Chapters::Edition::ParseAtom(IMkvReader* pReader, long long pos, + long long size) { + if (!ExpandAtomsArray()) + return -1; + + Atom& a = m_atoms[m_atoms_count++]; + a.Init(); + + return a.Parse(pReader, pos, size); +} + +bool Chapters::Edition::ExpandAtomsArray() { + if (m_atoms_size > m_atoms_count) + return true; // nothing else to do + + const int size = (m_atoms_size == 0) ? 1 : 2 * m_atoms_size; + + Atom* const atoms = new (std::nothrow) Atom[size]; + + if (atoms == NULL) + return false; + + for (int idx = 0; idx < m_atoms_count; ++idx) { + m_atoms[idx].ShallowCopy(atoms[idx]); + } + + delete[] m_atoms; + m_atoms = atoms; + + m_atoms_size = size; + return true; +} + +Chapters::Atom::Atom() {} + +Chapters::Atom::~Atom() {} + +unsigned long long Chapters::Atom::GetUID() const { return m_uid; } + +const char* Chapters::Atom::GetStringUID() const { return m_string_uid; } + +long long Chapters::Atom::GetStartTimecode() const { return m_start_timecode; } + +long long Chapters::Atom::GetStopTimecode() const { return m_stop_timecode; } + +long long Chapters::Atom::GetStartTime(const Chapters* pChapters) const { + return GetTime(pChapters, m_start_timecode); +} + +long long Chapters::Atom::GetStopTime(const Chapters* pChapters) const { + return GetTime(pChapters, m_stop_timecode); +} + +int Chapters::Atom::GetDisplayCount() const { return m_displays_count; } + +const Chapters::Display* Chapters::Atom::GetDisplay(int index) const { + if (index < 0) + return NULL; + + if (index >= m_displays_count) + return NULL; + + return m_displays + index; +} + +void Chapters::Atom::Init() { + m_string_uid = NULL; + m_uid = 0; + m_start_timecode = -1; + m_stop_timecode = -1; + + m_displays = NULL; + m_displays_size = 0; + m_displays_count = 0; +} + +void Chapters::Atom::ShallowCopy(Atom& rhs) const { + rhs.m_string_uid = m_string_uid; + rhs.m_uid = m_uid; + rhs.m_start_timecode = m_start_timecode; + rhs.m_stop_timecode = m_stop_timecode; + + rhs.m_displays = m_displays; + rhs.m_displays_size = m_displays_size; + rhs.m_displays_count = m_displays_count; +} + +void Chapters::Atom::Clear() { + delete[] m_string_uid; + m_string_uid = NULL; + + while (m_displays_count > 0) { + Display& d = m_displays[--m_displays_count]; + d.Clear(); + } + + delete[] m_displays; + m_displays = NULL; + + m_displays_size = 0; +} + +long Chapters::Atom::Parse(IMkvReader* pReader, long long pos, long long size) { + const long long stop = pos + size; + + while (pos < stop) { + long long id, size; + + long status = ParseElementHeader(pReader, pos, stop, id, size); + + if (status < 0) // error + return status; + + if (size == 0) // 0 length payload, skip. + continue; + + if (id == libwebm::kMkvChapterDisplay) { + status = ParseDisplay(pReader, pos, size); + + if (status < 0) // error + return status; + } else if (id == libwebm::kMkvChapterStringUID) { + status = UnserializeString(pReader, pos, size, m_string_uid); + + if (status < 0) // error + return status; + } else if (id == libwebm::kMkvChapterUID) { + long long val; + status = UnserializeInt(pReader, pos, size, val); + + if (status < 0) // error + return status; + + m_uid = static_cast(val); + } else if (id == libwebm::kMkvChapterTimeStart) { + const long long val = UnserializeUInt(pReader, pos, size); + + if (val < 0) // error + return static_cast(val); + + m_start_timecode = val; + } else if (id == libwebm::kMkvChapterTimeEnd) { + const long long val = UnserializeUInt(pReader, pos, size); + + if (val < 0) // error + return static_cast(val); + + m_stop_timecode = val; + } + + pos += size; + if (pos > stop) + return E_FILE_FORMAT_INVALID; + } + + if (pos != stop) + return E_FILE_FORMAT_INVALID; + return 0; +} + +long long Chapters::Atom::GetTime(const Chapters* pChapters, + long long timecode) { + if (pChapters == NULL) + return -1; + + Segment* const pSegment = pChapters->m_pSegment; + + if (pSegment == NULL) // weird + return -1; + + const SegmentInfo* const pInfo = pSegment->GetInfo(); + + if (pInfo == NULL) + return -1; + + const long long timecode_scale = pInfo->GetTimeCodeScale(); + + if (timecode_scale < 1) // weird + return -1; + + if (timecode < 0) + return -1; + + const long long result = timecode_scale * timecode; + + return result; +} + +long Chapters::Atom::ParseDisplay(IMkvReader* pReader, long long pos, + long long size) { + if (!ExpandDisplaysArray()) + return -1; + + Display& d = m_displays[m_displays_count++]; + d.Init(); + + return d.Parse(pReader, pos, size); +} + +bool Chapters::Atom::ExpandDisplaysArray() { + if (m_displays_size > m_displays_count) + return true; // nothing else to do + + const int size = (m_displays_size == 0) ? 1 : 2 * m_displays_size; + + Display* const displays = new (std::nothrow) Display[size]; + + if (displays == NULL) + return false; + + for (int idx = 0; idx < m_displays_count; ++idx) { + m_displays[idx].ShallowCopy(displays[idx]); + } + + delete[] m_displays; + m_displays = displays; + + m_displays_size = size; + return true; +} + +Chapters::Display::Display() {} + +Chapters::Display::~Display() {} + +const char* Chapters::Display::GetString() const { return m_string; } + +const char* Chapters::Display::GetLanguage() const { return m_language; } + +const char* Chapters::Display::GetCountry() const { return m_country; } + +void Chapters::Display::Init() { + m_string = NULL; + m_language = NULL; + m_country = NULL; +} + +void Chapters::Display::ShallowCopy(Display& rhs) const { + rhs.m_string = m_string; + rhs.m_language = m_language; + rhs.m_country = m_country; +} + +void Chapters::Display::Clear() { + delete[] m_string; + m_string = NULL; + + delete[] m_language; + m_language = NULL; + + delete[] m_country; + m_country = NULL; +} + +long Chapters::Display::Parse(IMkvReader* pReader, long long pos, + long long size) { + const long long stop = pos + size; + + while (pos < stop) { + long long id, size; + + long status = ParseElementHeader(pReader, pos, stop, id, size); + + if (status < 0) // error + return status; + + if (size == 0) // No payload. + continue; + + if (id == libwebm::kMkvChapString) { + status = UnserializeString(pReader, pos, size, m_string); + + if (status) + return status; + } else if (id == libwebm::kMkvChapLanguage) { + status = UnserializeString(pReader, pos, size, m_language); + + if (status) + return status; + } else if (id == libwebm::kMkvChapCountry) { + status = UnserializeString(pReader, pos, size, m_country); + + if (status) + return status; + } + + pos += size; + if (pos > stop) + return E_FILE_FORMAT_INVALID; + } + + if (pos != stop) + return E_FILE_FORMAT_INVALID; + return 0; +} + +Tags::Tags(Segment* pSegment, long long payload_start, long long payload_size, + long long element_start, long long element_size) + : m_pSegment(pSegment), + m_start(payload_start), + m_size(payload_size), + m_element_start(element_start), + m_element_size(element_size), + m_tags(NULL), + m_tags_size(0), + m_tags_count(0) {} + +Tags::~Tags() { + while (m_tags_count > 0) { + Tag& t = m_tags[--m_tags_count]; + t.Clear(); + } + delete[] m_tags; +} + +long Tags::Parse() { + IMkvReader* const pReader = m_pSegment->m_pReader; + + long long pos = m_start; // payload start + const long long stop = pos + m_size; // payload stop + + while (pos < stop) { + long long id, size; + + long status = ParseElementHeader(pReader, pos, stop, id, size); + + if (status < 0) + return status; + + if (size == 0) // 0 length tag, read another + continue; + + if (id == libwebm::kMkvTag) { + status = ParseTag(pos, size); + + if (status < 0) + return status; + } + + pos += size; + if (pos > stop) + return E_FILE_FORMAT_INVALID; + } + + if (pos != stop) + return E_FILE_FORMAT_INVALID; + + return 0; +} + +int Tags::GetTagCount() const { return m_tags_count; } + +const Tags::Tag* Tags::GetTag(int idx) const { + if (idx < 0) + return NULL; + + if (idx >= m_tags_count) + return NULL; + + return m_tags + idx; +} + +bool Tags::ExpandTagsArray() { + if (m_tags_size > m_tags_count) + return true; // nothing else to do + + const int size = (m_tags_size == 0) ? 1 : 2 * m_tags_size; + + Tag* const tags = new (std::nothrow) Tag[size]; + + if (tags == NULL) + return false; + + for (int idx = 0; idx < m_tags_count; ++idx) { + m_tags[idx].ShallowCopy(tags[idx]); + } + + delete[] m_tags; + m_tags = tags; + + m_tags_size = size; + return true; +} + +long Tags::ParseTag(long long pos, long long size) { + if (!ExpandTagsArray()) + return -1; + + Tag& t = m_tags[m_tags_count++]; + t.Init(); + + return t.Parse(m_pSegment->m_pReader, pos, size); +} + +Tags::Tag::Tag() {} + +Tags::Tag::~Tag() {} + +int Tags::Tag::GetSimpleTagCount() const { return m_simple_tags_count; } + +const Tags::SimpleTag* Tags::Tag::GetSimpleTag(int index) const { + if (index < 0) + return NULL; + + if (index >= m_simple_tags_count) + return NULL; + + return m_simple_tags + index; +} + +void Tags::Tag::Init() { + m_simple_tags = NULL; + m_simple_tags_size = 0; + m_simple_tags_count = 0; +} + +void Tags::Tag::ShallowCopy(Tag& rhs) const { + rhs.m_simple_tags = m_simple_tags; + rhs.m_simple_tags_size = m_simple_tags_size; + rhs.m_simple_tags_count = m_simple_tags_count; +} + +void Tags::Tag::Clear() { + while (m_simple_tags_count > 0) { + SimpleTag& d = m_simple_tags[--m_simple_tags_count]; + d.Clear(); + } + + delete[] m_simple_tags; + m_simple_tags = NULL; + + m_simple_tags_size = 0; +} + +long Tags::Tag::Parse(IMkvReader* pReader, long long pos, long long size) { + const long long stop = pos + size; + + while (pos < stop) { + long long id, size; + + long status = ParseElementHeader(pReader, pos, stop, id, size); + + if (status < 0) + return status; + + if (size == 0) // 0 length tag, read another + continue; + + if (id == libwebm::kMkvSimpleTag) { + status = ParseSimpleTag(pReader, pos, size); + + if (status < 0) + return status; + } + + pos += size; + if (pos > stop) + return E_FILE_FORMAT_INVALID; + } + + if (pos != stop) + return E_FILE_FORMAT_INVALID; + return 0; +} + +long Tags::Tag::ParseSimpleTag(IMkvReader* pReader, long long pos, + long long size) { + if (!ExpandSimpleTagsArray()) + return -1; + + SimpleTag& st = m_simple_tags[m_simple_tags_count++]; + st.Init(); + + return st.Parse(pReader, pos, size); +} + +bool Tags::Tag::ExpandSimpleTagsArray() { + if (m_simple_tags_size > m_simple_tags_count) + return true; // nothing else to do + + const int size = (m_simple_tags_size == 0) ? 1 : 2 * m_simple_tags_size; + + SimpleTag* const displays = new (std::nothrow) SimpleTag[size]; + + if (displays == NULL) + return false; + + for (int idx = 0; idx < m_simple_tags_count; ++idx) { + m_simple_tags[idx].ShallowCopy(displays[idx]); + } + + delete[] m_simple_tags; + m_simple_tags = displays; + + m_simple_tags_size = size; + return true; +} + +Tags::SimpleTag::SimpleTag() {} + +Tags::SimpleTag::~SimpleTag() {} + +const char* Tags::SimpleTag::GetTagName() const { return m_tag_name; } + +const char* Tags::SimpleTag::GetTagString() const { return m_tag_string; } + +void Tags::SimpleTag::Init() { + m_tag_name = NULL; + m_tag_string = NULL; +} + +void Tags::SimpleTag::ShallowCopy(SimpleTag& rhs) const { + rhs.m_tag_name = m_tag_name; + rhs.m_tag_string = m_tag_string; +} + +void Tags::SimpleTag::Clear() { + delete[] m_tag_name; + m_tag_name = NULL; + + delete[] m_tag_string; + m_tag_string = NULL; +} + +long Tags::SimpleTag::Parse(IMkvReader* pReader, long long pos, + long long size) { + const long long stop = pos + size; + + while (pos < stop) { + long long id, size; + + long status = ParseElementHeader(pReader, pos, stop, id, size); + + if (status < 0) // error + return status; + + if (size == 0) // weird + continue; + + if (id == libwebm::kMkvTagName) { + status = UnserializeString(pReader, pos, size, m_tag_name); + + if (status) + return status; + } else if (id == libwebm::kMkvTagString) { + status = UnserializeString(pReader, pos, size, m_tag_string); + + if (status) + return status; + } + + pos += size; + if (pos > stop) + return E_FILE_FORMAT_INVALID; + } + + if (pos != stop) + return E_FILE_FORMAT_INVALID; + return 0; +} + +SegmentInfo::SegmentInfo(Segment* pSegment, long long start, long long size_, + long long element_start, long long element_size) + : m_pSegment(pSegment), + m_start(start), + m_size(size_), + m_element_start(element_start), + m_element_size(element_size), + m_pMuxingAppAsUTF8(NULL), + m_pWritingAppAsUTF8(NULL), + m_pTitleAsUTF8(NULL) {} + +SegmentInfo::~SegmentInfo() { + delete[] m_pMuxingAppAsUTF8; + m_pMuxingAppAsUTF8 = NULL; + + delete[] m_pWritingAppAsUTF8; + m_pWritingAppAsUTF8 = NULL; + + delete[] m_pTitleAsUTF8; + m_pTitleAsUTF8 = NULL; +} + +long SegmentInfo::Parse() { + assert(m_pMuxingAppAsUTF8 == NULL); + assert(m_pWritingAppAsUTF8 == NULL); + assert(m_pTitleAsUTF8 == NULL); + + IMkvReader* const pReader = m_pSegment->m_pReader; + + long long pos = m_start; + const long long stop = m_start + m_size; + + m_timecodeScale = 1000000; + m_duration = -1; + + while (pos < stop) { + long long id, size; + + const long status = ParseElementHeader(pReader, pos, stop, id, size); + + if (status < 0) // error + return status; + + if (id == libwebm::kMkvTimecodeScale) { + m_timecodeScale = UnserializeUInt(pReader, pos, size); + + if (m_timecodeScale <= 0) + return E_FILE_FORMAT_INVALID; + } else if (id == libwebm::kMkvDuration) { + const long status = UnserializeFloat(pReader, pos, size, m_duration); + + if (status < 0) + return status; + + if (m_duration < 0) + return E_FILE_FORMAT_INVALID; + } else if (id == libwebm::kMkvMuxingApp) { + const long status = + UnserializeString(pReader, pos, size, m_pMuxingAppAsUTF8); + + if (status) + return status; + } else if (id == libwebm::kMkvWritingApp) { + const long status = + UnserializeString(pReader, pos, size, m_pWritingAppAsUTF8); + + if (status) + return status; + } else if (id == libwebm::kMkvTitle) { + const long status = UnserializeString(pReader, pos, size, m_pTitleAsUTF8); + + if (status) + return status; + } + + pos += size; + + if (pos > stop) + return E_FILE_FORMAT_INVALID; + } + + const double rollover_check = m_duration * m_timecodeScale; + if (rollover_check > static_cast(LLONG_MAX)) + return E_FILE_FORMAT_INVALID; + + if (pos != stop) + return E_FILE_FORMAT_INVALID; + + return 0; +} + +long long SegmentInfo::GetTimeCodeScale() const { return m_timecodeScale; } + +long long SegmentInfo::GetDuration() const { + if (m_duration < 0) + return -1; + + assert(m_timecodeScale >= 1); + + const double dd = double(m_duration) * double(m_timecodeScale); + const long long d = static_cast(dd); + + return d; +} + +const char* SegmentInfo::GetMuxingAppAsUTF8() const { + return m_pMuxingAppAsUTF8; +} + +const char* SegmentInfo::GetWritingAppAsUTF8() const { + return m_pWritingAppAsUTF8; +} + +const char* SegmentInfo::GetTitleAsUTF8() const { return m_pTitleAsUTF8; } + +/////////////////////////////////////////////////////////////// +// ContentEncoding element +ContentEncoding::ContentCompression::ContentCompression() + : algo(0), settings(NULL), settings_len(0) {} + +ContentEncoding::ContentCompression::~ContentCompression() { + delete[] settings; +} + +ContentEncoding::ContentEncryption::ContentEncryption() + : algo(0), + key_id(NULL), + key_id_len(0), + signature(NULL), + signature_len(0), + sig_key_id(NULL), + sig_key_id_len(0), + sig_algo(0), + sig_hash_algo(0) {} + +ContentEncoding::ContentEncryption::~ContentEncryption() { + delete[] key_id; + delete[] signature; + delete[] sig_key_id; +} + +ContentEncoding::ContentEncoding() + : compression_entries_(NULL), + compression_entries_end_(NULL), + encryption_entries_(NULL), + encryption_entries_end_(NULL), + encoding_order_(0), + encoding_scope_(1), + encoding_type_(0) {} + +ContentEncoding::~ContentEncoding() { + ContentCompression** comp_i = compression_entries_; + ContentCompression** const comp_j = compression_entries_end_; + + while (comp_i != comp_j) { + ContentCompression* const comp = *comp_i++; + delete comp; + } + + delete[] compression_entries_; + + ContentEncryption** enc_i = encryption_entries_; + ContentEncryption** const enc_j = encryption_entries_end_; + + while (enc_i != enc_j) { + ContentEncryption* const enc = *enc_i++; + delete enc; + } + + delete[] encryption_entries_; +} + +const ContentEncoding::ContentCompression* +ContentEncoding::GetCompressionByIndex(unsigned long idx) const { + const ptrdiff_t count = compression_entries_end_ - compression_entries_; + assert(count >= 0); + + if (idx >= static_cast(count)) + return NULL; + + return compression_entries_[idx]; +} + +unsigned long ContentEncoding::GetCompressionCount() const { + const ptrdiff_t count = compression_entries_end_ - compression_entries_; + assert(count >= 0); + + return static_cast(count); +} + +const ContentEncoding::ContentEncryption* ContentEncoding::GetEncryptionByIndex( + unsigned long idx) const { + const ptrdiff_t count = encryption_entries_end_ - encryption_entries_; + assert(count >= 0); + + if (idx >= static_cast(count)) + return NULL; + + return encryption_entries_[idx]; +} + +unsigned long ContentEncoding::GetEncryptionCount() const { + const ptrdiff_t count = encryption_entries_end_ - encryption_entries_; + assert(count >= 0); + + return static_cast(count); +} + +long ContentEncoding::ParseContentEncAESSettingsEntry( + long long start, long long size, IMkvReader* pReader, + ContentEncAESSettings* aes) { + assert(pReader); + assert(aes); + + long long pos = start; + const long long stop = start + size; + + while (pos < stop) { + long long id, size; + const long status = ParseElementHeader(pReader, pos, stop, id, size); + if (status < 0) // error + return status; + + if (id == libwebm::kMkvAESSettingsCipherMode) { + aes->cipher_mode = UnserializeUInt(pReader, pos, size); + if (aes->cipher_mode != 1) + return E_FILE_FORMAT_INVALID; + } + + pos += size; // consume payload + if (pos > stop) + return E_FILE_FORMAT_INVALID; + } + + return 0; +} + +long ContentEncoding::ParseContentEncodingEntry(long long start, long long size, + IMkvReader* pReader) { + assert(pReader); + + long long pos = start; + const long long stop = start + size; + + // Count ContentCompression and ContentEncryption elements. + long long compression_count = 0; + long long encryption_count = 0; + + while (pos < stop) { + long long id, size; + const long status = ParseElementHeader(pReader, pos, stop, id, size); + if (status < 0) // error + return status; + + if (id == libwebm::kMkvContentCompression) { + ++compression_count; + if (compression_count > INT_MAX) + return E_PARSE_FAILED; + } + + if (id == libwebm::kMkvContentEncryption) { + ++encryption_count; + if (encryption_count > INT_MAX) + return E_PARSE_FAILED; + } + + pos += size; // consume payload + if (pos > stop) + return E_FILE_FORMAT_INVALID; + } + + if (compression_count <= 0 && encryption_count <= 0) + return -1; + + if (compression_count > 0) { + compression_entries_ = + new (std::nothrow) ContentCompression*[compression_count]; + if (!compression_entries_) + return -1; + compression_entries_end_ = compression_entries_; + } + + if (encryption_count > 0) { + encryption_entries_ = + new (std::nothrow) ContentEncryption*[encryption_count]; + if (!encryption_entries_) { + delete[] compression_entries_; + compression_entries_ = NULL; + return -1; + } + encryption_entries_end_ = encryption_entries_; + } + + pos = start; + while (pos < stop) { + long long id, size; + long status = ParseElementHeader(pReader, pos, stop, id, size); + if (status < 0) // error + return status; + + if (id == libwebm::kMkvContentEncodingOrder) { + encoding_order_ = UnserializeUInt(pReader, pos, size); + } else if (id == libwebm::kMkvContentEncodingScope) { + encoding_scope_ = UnserializeUInt(pReader, pos, size); + if (encoding_scope_ < 1) + return -1; + } else if (id == libwebm::kMkvContentEncodingType) { + encoding_type_ = UnserializeUInt(pReader, pos, size); + } else if (id == libwebm::kMkvContentCompression) { + ContentCompression* const compression = + new (std::nothrow) ContentCompression(); + if (!compression) + return -1; + + status = ParseCompressionEntry(pos, size, pReader, compression); + if (status) { + delete compression; + return status; + } + assert(compression_count > 0); + *compression_entries_end_++ = compression; + } else if (id == libwebm::kMkvContentEncryption) { + ContentEncryption* const encryption = + new (std::nothrow) ContentEncryption(); + if (!encryption) + return -1; + + status = ParseEncryptionEntry(pos, size, pReader, encryption); + if (status) { + delete encryption; + return status; + } + assert(encryption_count > 0); + *encryption_entries_end_++ = encryption; + } + + pos += size; // consume payload + if (pos > stop) + return E_FILE_FORMAT_INVALID; + } + + if (pos != stop) + return E_FILE_FORMAT_INVALID; + return 0; +} + +long ContentEncoding::ParseCompressionEntry(long long start, long long size, + IMkvReader* pReader, + ContentCompression* compression) { + assert(pReader); + assert(compression); + + long long pos = start; + const long long stop = start + size; + + bool valid = false; + + while (pos < stop) { + long long id, size; + const long status = ParseElementHeader(pReader, pos, stop, id, size); + if (status < 0) // error + return status; + + if (id == libwebm::kMkvContentCompAlgo) { + long long algo = UnserializeUInt(pReader, pos, size); + if (algo < 0) + return E_FILE_FORMAT_INVALID; + compression->algo = algo; + valid = true; + } else if (id == libwebm::kMkvContentCompSettings) { + if (size <= 0) + return E_FILE_FORMAT_INVALID; + + const size_t buflen = static_cast(size); + unsigned char* buf = SafeArrayAlloc(1, buflen); + if (buf == NULL) + return -1; + + const int read_status = + pReader->Read(pos, static_cast(buflen), buf); + if (read_status) { + delete[] buf; + return status; + } + + // There should be only one settings element per content compression. + if (compression->settings != NULL) { + delete[] buf; + return E_FILE_FORMAT_INVALID; + } + + compression->settings = buf; + compression->settings_len = buflen; + } + + pos += size; // consume payload + if (pos > stop) + return E_FILE_FORMAT_INVALID; + } + + // ContentCompAlgo is mandatory + if (!valid) + return E_FILE_FORMAT_INVALID; + + return 0; +} + +long ContentEncoding::ParseEncryptionEntry(long long start, long long size, + IMkvReader* pReader, + ContentEncryption* encryption) { + assert(pReader); + assert(encryption); + + long long pos = start; + const long long stop = start + size; + + while (pos < stop) { + long long id, size; + const long status = ParseElementHeader(pReader, pos, stop, id, size); + if (status < 0) // error + return status; + + if (id == libwebm::kMkvContentEncAlgo) { + encryption->algo = UnserializeUInt(pReader, pos, size); + if (encryption->algo != 5) + return E_FILE_FORMAT_INVALID; + } else if (id == libwebm::kMkvContentEncKeyID) { + delete[] encryption->key_id; + encryption->key_id = NULL; + encryption->key_id_len = 0; + + if (size <= 0) + return E_FILE_FORMAT_INVALID; + + const size_t buflen = static_cast(size); + unsigned char* buf = SafeArrayAlloc(1, buflen); + if (buf == NULL) + return -1; + + const int read_status = + pReader->Read(pos, static_cast(buflen), buf); + if (read_status) { + delete[] buf; + return status; + } + + encryption->key_id = buf; + encryption->key_id_len = buflen; + } else if (id == libwebm::kMkvContentSignature) { + delete[] encryption->signature; + encryption->signature = NULL; + encryption->signature_len = 0; + + if (size <= 0) + return E_FILE_FORMAT_INVALID; + + const size_t buflen = static_cast(size); + unsigned char* buf = SafeArrayAlloc(1, buflen); + if (buf == NULL) + return -1; + + const int read_status = + pReader->Read(pos, static_cast(buflen), buf); + if (read_status) { + delete[] buf; + return status; + } + + encryption->signature = buf; + encryption->signature_len = buflen; + } else if (id == libwebm::kMkvContentSigKeyID) { + delete[] encryption->sig_key_id; + encryption->sig_key_id = NULL; + encryption->sig_key_id_len = 0; + + if (size <= 0) + return E_FILE_FORMAT_INVALID; + + const size_t buflen = static_cast(size); + unsigned char* buf = SafeArrayAlloc(1, buflen); + if (buf == NULL) + return -1; + + const int read_status = + pReader->Read(pos, static_cast(buflen), buf); + if (read_status) { + delete[] buf; + return status; + } + + encryption->sig_key_id = buf; + encryption->sig_key_id_len = buflen; + } else if (id == libwebm::kMkvContentSigAlgo) { + encryption->sig_algo = UnserializeUInt(pReader, pos, size); + } else if (id == libwebm::kMkvContentSigHashAlgo) { + encryption->sig_hash_algo = UnserializeUInt(pReader, pos, size); + } else if (id == libwebm::kMkvContentEncAESSettings) { + const long status = ParseContentEncAESSettingsEntry( + pos, size, pReader, &encryption->aes_settings); + if (status) + return status; + } + + pos += size; // consume payload + if (pos > stop) + return E_FILE_FORMAT_INVALID; + } + + return 0; +} + +Track::Track(Segment* pSegment, long long element_start, long long element_size) + : m_pSegment(pSegment), + m_element_start(element_start), + m_element_size(element_size), + content_encoding_entries_(NULL), + content_encoding_entries_end_(NULL) {} + +Track::~Track() { + Info& info = const_cast(m_info); + info.Clear(); + + ContentEncoding** i = content_encoding_entries_; + ContentEncoding** const j = content_encoding_entries_end_; + + while (i != j) { + ContentEncoding* const encoding = *i++; + delete encoding; + } + + delete[] content_encoding_entries_; +} + +long Track::Create(Segment* pSegment, const Info& info, long long element_start, + long long element_size, Track*& pResult) { + if (pResult) + return -1; + + Track* const pTrack = + new (std::nothrow) Track(pSegment, element_start, element_size); + + if (pTrack == NULL) + return -1; // generic error + + const int status = info.Copy(pTrack->m_info); + + if (status) { // error + delete pTrack; + return status; + } + + pResult = pTrack; + return 0; // success +} + +Track::Info::Info() + : uid(0), + defaultDuration(0), + codecDelay(0), + seekPreRoll(0), + nameAsUTF8(NULL), + language(NULL), + codecId(NULL), + codecNameAsUTF8(NULL), + codecPrivate(NULL), + codecPrivateSize(0), + lacing(false) {} + +Track::Info::~Info() { Clear(); } + +void Track::Info::Clear() { + delete[] nameAsUTF8; + nameAsUTF8 = NULL; + + delete[] language; + language = NULL; + + delete[] codecId; + codecId = NULL; + + delete[] codecPrivate; + codecPrivate = NULL; + codecPrivateSize = 0; + + delete[] codecNameAsUTF8; + codecNameAsUTF8 = NULL; +} + +int Track::Info::CopyStr(char* Info::*str, Info& dst_) const { + if (str == static_cast(NULL)) + return -1; + + char*& dst = dst_.*str; + + if (dst) // should be NULL already + return -1; + + const char* const src = this->*str; + + if (src == NULL) + return 0; + + const size_t len = strlen(src); + + dst = SafeArrayAlloc(1, len + 1); + + if (dst == NULL) + return -1; + + strcpy(dst, src); + + return 0; +} + +int Track::Info::Copy(Info& dst) const { + if (&dst == this) + return 0; + + dst.type = type; + dst.number = number; + dst.defaultDuration = defaultDuration; + dst.codecDelay = codecDelay; + dst.seekPreRoll = seekPreRoll; + dst.uid = uid; + dst.lacing = lacing; + dst.settings = settings; + + // We now copy the string member variables from src to dst. + // This involves memory allocation so in principle the operation + // can fail (indeed, that's why we have Info::Copy), so we must + // report this to the caller. An error return from this function + // therefore implies that the copy was only partially successful. + + if (int status = CopyStr(&Info::nameAsUTF8, dst)) + return status; + + if (int status = CopyStr(&Info::language, dst)) + return status; + + if (int status = CopyStr(&Info::codecId, dst)) + return status; + + if (int status = CopyStr(&Info::codecNameAsUTF8, dst)) + return status; + + if (codecPrivateSize > 0) { + if (codecPrivate == NULL) + return -1; + + if (dst.codecPrivate) + return -1; + + if (dst.codecPrivateSize != 0) + return -1; + + dst.codecPrivate = SafeArrayAlloc(1, codecPrivateSize); + + if (dst.codecPrivate == NULL) + return -1; + + memcpy(dst.codecPrivate, codecPrivate, codecPrivateSize); + dst.codecPrivateSize = codecPrivateSize; + } + + return 0; +} + +const BlockEntry* Track::GetEOS() const { return &m_eos; } + +long Track::GetType() const { return m_info.type; } + +long Track::GetNumber() const { return m_info.number; } + +unsigned long long Track::GetUid() const { return m_info.uid; } + +const char* Track::GetNameAsUTF8() const { return m_info.nameAsUTF8; } + +const char* Track::GetLanguage() const { return m_info.language; } + +const char* Track::GetCodecNameAsUTF8() const { return m_info.codecNameAsUTF8; } + +const char* Track::GetCodecId() const { return m_info.codecId; } + +const unsigned char* Track::GetCodecPrivate(size_t& size) const { + size = m_info.codecPrivateSize; + return m_info.codecPrivate; +} + +bool Track::GetLacing() const { return m_info.lacing; } + +unsigned long long Track::GetDefaultDuration() const { + return m_info.defaultDuration; +} + +unsigned long long Track::GetCodecDelay() const { return m_info.codecDelay; } + +unsigned long long Track::GetSeekPreRoll() const { return m_info.seekPreRoll; } + +long Track::GetFirst(const BlockEntry*& pBlockEntry) const { + const Cluster* pCluster = m_pSegment->GetFirst(); + + for (int i = 0;;) { + if (pCluster == NULL) { + pBlockEntry = GetEOS(); + return 1; + } + + if (pCluster->EOS()) { + if (m_pSegment->DoneParsing()) { + pBlockEntry = GetEOS(); + return 1; + } + + pBlockEntry = 0; + return E_BUFFER_NOT_FULL; + } + + long status = pCluster->GetFirst(pBlockEntry); + + if (status < 0) // error + return status; + + if (pBlockEntry == 0) { // empty cluster + pCluster = m_pSegment->GetNext(pCluster); + continue; + } + + for (;;) { + const Block* const pBlock = pBlockEntry->GetBlock(); + assert(pBlock); + + const long long tn = pBlock->GetTrackNumber(); + + if ((tn == m_info.number) && VetEntry(pBlockEntry)) + return 0; + + const BlockEntry* pNextEntry; + + status = pCluster->GetNext(pBlockEntry, pNextEntry); + + if (status < 0) // error + return status; + + if (pNextEntry == 0) + break; + + pBlockEntry = pNextEntry; + } + + ++i; + + if (i >= 100) + break; + + pCluster = m_pSegment->GetNext(pCluster); + } + + // NOTE: if we get here, it means that we didn't find a block with + // a matching track number. We interpret that as an error (which + // might be too conservative). + + pBlockEntry = GetEOS(); // so we can return a non-NULL value + return 1; +} + +long Track::GetNext(const BlockEntry* pCurrEntry, + const BlockEntry*& pNextEntry) const { + assert(pCurrEntry); + assert(!pCurrEntry->EOS()); //? + + const Block* const pCurrBlock = pCurrEntry->GetBlock(); + assert(pCurrBlock && pCurrBlock->GetTrackNumber() == m_info.number); + if (!pCurrBlock || pCurrBlock->GetTrackNumber() != m_info.number) + return -1; + + const Cluster* pCluster = pCurrEntry->GetCluster(); + assert(pCluster); + assert(!pCluster->EOS()); + + long status = pCluster->GetNext(pCurrEntry, pNextEntry); + + if (status < 0) // error + return status; + + for (int i = 0;;) { + while (pNextEntry) { + const Block* const pNextBlock = pNextEntry->GetBlock(); + assert(pNextBlock); + + if (pNextBlock->GetTrackNumber() == m_info.number) + return 0; + + pCurrEntry = pNextEntry; + + status = pCluster->GetNext(pCurrEntry, pNextEntry); + + if (status < 0) // error + return status; + } + + pCluster = m_pSegment->GetNext(pCluster); + + if (pCluster == NULL) { + pNextEntry = GetEOS(); + return 1; + } + + if (pCluster->EOS()) { + if (m_pSegment->DoneParsing()) { + pNextEntry = GetEOS(); + return 1; + } + + // TODO: there is a potential O(n^2) problem here: we tell the + // caller to (pre)load another cluster, which he does, but then he + // calls GetNext again, which repeats the same search. This is + // a pathological case, since the only way it can happen is if + // there exists a long sequence of clusters none of which contain a + // block from this track. One way around this problem is for the + // caller to be smarter when he loads another cluster: don't call + // us back until you have a cluster that contains a block from this + // track. (Of course, that's not cheap either, since our caller + // would have to scan the each cluster as it's loaded, so that + // would just push back the problem.) + + pNextEntry = NULL; + return E_BUFFER_NOT_FULL; + } + + status = pCluster->GetFirst(pNextEntry); + + if (status < 0) // error + return status; + + if (pNextEntry == NULL) // empty cluster + continue; + + ++i; + + if (i >= 100) + break; + } + + // NOTE: if we get here, it means that we didn't find a block with + // a matching track number after lots of searching, so we give + // up trying. + + pNextEntry = GetEOS(); // so we can return a non-NULL value + return 1; +} + +bool Track::VetEntry(const BlockEntry* pBlockEntry) const { + assert(pBlockEntry); + const Block* const pBlock = pBlockEntry->GetBlock(); + assert(pBlock); + assert(pBlock->GetTrackNumber() == m_info.number); + if (!pBlock || pBlock->GetTrackNumber() != m_info.number) + return false; + + // This function is used during a seek to determine whether the + // frame is a valid seek target. This default function simply + // returns true, which means all frames are valid seek targets. + // It gets overridden by the VideoTrack class, because only video + // keyframes can be used as seek target. + + return true; +} + +long Track::Seek(long long time_ns, const BlockEntry*& pResult) const { + const long status = GetFirst(pResult); + + if (status < 0) // buffer underflow, etc + return status; + + assert(pResult); + + if (pResult->EOS()) + return 0; + + const Cluster* pCluster = pResult->GetCluster(); + assert(pCluster); + assert(pCluster->GetIndex() >= 0); + + if (time_ns <= pResult->GetBlock()->GetTime(pCluster)) + return 0; + + Cluster** const clusters = m_pSegment->m_clusters; + assert(clusters); + + const long count = m_pSegment->GetCount(); // loaded only, not preloaded + assert(count > 0); + + Cluster** const i = clusters + pCluster->GetIndex(); + assert(i); + assert(*i == pCluster); + assert(pCluster->GetTime() <= time_ns); + + Cluster** const j = clusters + count; + + Cluster** lo = i; + Cluster** hi = j; + + while (lo < hi) { + // INVARIANT: + //[i, lo) <= time_ns + //[lo, hi) ? + //[hi, j) > time_ns + + Cluster** const mid = lo + (hi - lo) / 2; + assert(mid < hi); + + pCluster = *mid; + assert(pCluster); + assert(pCluster->GetIndex() >= 0); + assert(pCluster->GetIndex() == long(mid - m_pSegment->m_clusters)); + + const long long t = pCluster->GetTime(); + + if (t <= time_ns) + lo = mid + 1; + else + hi = mid; + + assert(lo <= hi); + } + + assert(lo == hi); + assert(lo > i); + assert(lo <= j); + + while (lo > i) { + pCluster = *--lo; + assert(pCluster); + assert(pCluster->GetTime() <= time_ns); + + pResult = pCluster->GetEntry(this); + + if ((pResult != 0) && !pResult->EOS()) + return 0; + + // landed on empty cluster (no entries) + } + + pResult = GetEOS(); // weird + return 0; +} + +const ContentEncoding* Track::GetContentEncodingByIndex( + unsigned long idx) const { + const ptrdiff_t count = + content_encoding_entries_end_ - content_encoding_entries_; + assert(count >= 0); + + if (idx >= static_cast(count)) + return NULL; + + return content_encoding_entries_[idx]; +} + +unsigned long Track::GetContentEncodingCount() const { + const ptrdiff_t count = + content_encoding_entries_end_ - content_encoding_entries_; + assert(count >= 0); + + return static_cast(count); +} + +long Track::ParseContentEncodingsEntry(long long start, long long size) { + IMkvReader* const pReader = m_pSegment->m_pReader; + assert(pReader); + + long long pos = start; + const long long stop = start + size; + + // Count ContentEncoding elements. + long long count = 0; + while (pos < stop) { + long long id, size; + const long status = ParseElementHeader(pReader, pos, stop, id, size); + if (status < 0) // error + return status; + + // pos now designates start of element + if (id == libwebm::kMkvContentEncoding) { + ++count; + if (count > INT_MAX) + return E_PARSE_FAILED; + } + + pos += size; // consume payload + if (pos > stop) + return E_FILE_FORMAT_INVALID; + } + + if (count <= 0) + return -1; + + content_encoding_entries_ = new (std::nothrow) ContentEncoding*[count]; + if (!content_encoding_entries_) + return -1; + + content_encoding_entries_end_ = content_encoding_entries_; + + pos = start; + while (pos < stop) { + long long id, size; + long status = ParseElementHeader(pReader, pos, stop, id, size); + if (status < 0) // error + return status; + + // pos now designates start of element + if (id == libwebm::kMkvContentEncoding) { + ContentEncoding* const content_encoding = + new (std::nothrow) ContentEncoding(); + if (!content_encoding) + return -1; + + status = content_encoding->ParseContentEncodingEntry(pos, size, pReader); + if (status) { + delete content_encoding; + return status; + } + + *content_encoding_entries_end_++ = content_encoding; + } + + pos += size; // consume payload + if (pos > stop) + return E_FILE_FORMAT_INVALID; + } + + if (pos != stop) + return E_FILE_FORMAT_INVALID; + + return 0; +} + +Track::EOSBlock::EOSBlock() : BlockEntry(NULL, LONG_MIN) {} + +BlockEntry::Kind Track::EOSBlock::GetKind() const { return kBlockEOS; } + +const Block* Track::EOSBlock::GetBlock() const { return NULL; } + +bool PrimaryChromaticity::Parse(IMkvReader* reader, long long read_pos, + long long value_size, bool is_x, + PrimaryChromaticity** chromaticity) { + if (!reader) + return false; + + if (!*chromaticity) + *chromaticity = new PrimaryChromaticity(); + + if (!*chromaticity) + return false; + + PrimaryChromaticity* pc = *chromaticity; + float* value = is_x ? &pc->x : &pc->y; + + double parser_value = 0; + const long long parse_status = + UnserializeFloat(reader, read_pos, value_size, parser_value); + + // Valid range is [0, 1]. Make sure the double is representable as a float + // before casting. + if (parse_status < 0 || parser_value < 0.0 || parser_value > 1.0 || + (parser_value > 0.0 && parser_value < FLT_MIN)) + return false; + + *value = static_cast(parser_value); + + return true; +} + +bool MasteringMetadata::Parse(IMkvReader* reader, long long mm_start, + long long mm_size, MasteringMetadata** mm) { + if (!reader || *mm) + return false; + + std::unique_ptr mm_ptr(new MasteringMetadata()); + if (!mm_ptr.get()) + return false; + + const long long mm_end = mm_start + mm_size; + long long read_pos = mm_start; + + while (read_pos < mm_end) { + long long child_id = 0; + long long child_size = 0; + + const long long status = + ParseElementHeader(reader, read_pos, mm_end, child_id, child_size); + if (status < 0) + return false; + + if (child_id == libwebm::kMkvLuminanceMax) { + double value = 0; + const long long value_parse_status = + UnserializeFloat(reader, read_pos, child_size, value); + if (value < -FLT_MAX || value > FLT_MAX || + (value > 0.0 && value < FLT_MIN)) { + return false; + } + mm_ptr->luminance_max = static_cast(value); + if (value_parse_status < 0 || mm_ptr->luminance_max < 0.0 || + mm_ptr->luminance_max > 9999.99) { + return false; + } + } else if (child_id == libwebm::kMkvLuminanceMin) { + double value = 0; + const long long value_parse_status = + UnserializeFloat(reader, read_pos, child_size, value); + if (value < -FLT_MAX || value > FLT_MAX || + (value > 0.0 && value < FLT_MIN)) { + return false; + } + mm_ptr->luminance_min = static_cast(value); + if (value_parse_status < 0 || mm_ptr->luminance_min < 0.0 || + mm_ptr->luminance_min > 999.9999) { + return false; + } + } else { + bool is_x = false; + PrimaryChromaticity** chromaticity; + switch (child_id) { + case libwebm::kMkvPrimaryRChromaticityX: + case libwebm::kMkvPrimaryRChromaticityY: + is_x = child_id == libwebm::kMkvPrimaryRChromaticityX; + chromaticity = &mm_ptr->r; + break; + case libwebm::kMkvPrimaryGChromaticityX: + case libwebm::kMkvPrimaryGChromaticityY: + is_x = child_id == libwebm::kMkvPrimaryGChromaticityX; + chromaticity = &mm_ptr->g; + break; + case libwebm::kMkvPrimaryBChromaticityX: + case libwebm::kMkvPrimaryBChromaticityY: + is_x = child_id == libwebm::kMkvPrimaryBChromaticityX; + chromaticity = &mm_ptr->b; + break; + case libwebm::kMkvWhitePointChromaticityX: + case libwebm::kMkvWhitePointChromaticityY: + is_x = child_id == libwebm::kMkvWhitePointChromaticityX; + chromaticity = &mm_ptr->white_point; + break; + default: + return false; + } + const bool value_parse_status = PrimaryChromaticity::Parse( + reader, read_pos, child_size, is_x, chromaticity); + if (!value_parse_status) + return false; + } + + read_pos += child_size; + if (read_pos > mm_end) + return false; + } + + *mm = mm_ptr.release(); + return true; +} + +bool Colour::Parse(IMkvReader* reader, long long colour_start, + long long colour_size, Colour** colour) { + if (!reader || *colour) + return false; + + std::unique_ptr colour_ptr(new Colour()); + if (!colour_ptr.get()) + return false; + + const long long colour_end = colour_start + colour_size; + long long read_pos = colour_start; + + while (read_pos < colour_end) { + long long child_id = 0; + long long child_size = 0; + + const long status = + ParseElementHeader(reader, read_pos, colour_end, child_id, child_size); + if (status < 0) + return false; + + if (child_id == libwebm::kMkvMatrixCoefficients) { + colour_ptr->matrix_coefficients = + UnserializeUInt(reader, read_pos, child_size); + if (colour_ptr->matrix_coefficients < 0) + return false; + } else if (child_id == libwebm::kMkvBitsPerChannel) { + colour_ptr->bits_per_channel = + UnserializeUInt(reader, read_pos, child_size); + if (colour_ptr->bits_per_channel < 0) + return false; + } else if (child_id == libwebm::kMkvChromaSubsamplingHorz) { + colour_ptr->chroma_subsampling_horz = + UnserializeUInt(reader, read_pos, child_size); + if (colour_ptr->chroma_subsampling_horz < 0) + return false; + } else if (child_id == libwebm::kMkvChromaSubsamplingVert) { + colour_ptr->chroma_subsampling_vert = + UnserializeUInt(reader, read_pos, child_size); + if (colour_ptr->chroma_subsampling_vert < 0) + return false; + } else if (child_id == libwebm::kMkvCbSubsamplingHorz) { + colour_ptr->cb_subsampling_horz = + UnserializeUInt(reader, read_pos, child_size); + if (colour_ptr->cb_subsampling_horz < 0) + return false; + } else if (child_id == libwebm::kMkvCbSubsamplingVert) { + colour_ptr->cb_subsampling_vert = + UnserializeUInt(reader, read_pos, child_size); + if (colour_ptr->cb_subsampling_vert < 0) + return false; + } else if (child_id == libwebm::kMkvChromaSitingHorz) { + colour_ptr->chroma_siting_horz = + UnserializeUInt(reader, read_pos, child_size); + if (colour_ptr->chroma_siting_horz < 0) + return false; + } else if (child_id == libwebm::kMkvChromaSitingVert) { + colour_ptr->chroma_siting_vert = + UnserializeUInt(reader, read_pos, child_size); + if (colour_ptr->chroma_siting_vert < 0) + return false; + } else if (child_id == libwebm::kMkvRange) { + colour_ptr->range = UnserializeUInt(reader, read_pos, child_size); + if (colour_ptr->range < 0) + return false; + } else if (child_id == libwebm::kMkvTransferCharacteristics) { + colour_ptr->transfer_characteristics = + UnserializeUInt(reader, read_pos, child_size); + if (colour_ptr->transfer_characteristics < 0) + return false; + } else if (child_id == libwebm::kMkvPrimaries) { + colour_ptr->primaries = UnserializeUInt(reader, read_pos, child_size); + if (colour_ptr->primaries < 0) + return false; + } else if (child_id == libwebm::kMkvMaxCLL) { + colour_ptr->max_cll = UnserializeUInt(reader, read_pos, child_size); + if (colour_ptr->max_cll < 0) + return false; + } else if (child_id == libwebm::kMkvMaxFALL) { + colour_ptr->max_fall = UnserializeUInt(reader, read_pos, child_size); + if (colour_ptr->max_fall < 0) + return false; + } else if (child_id == libwebm::kMkvMasteringMetadata) { + if (!MasteringMetadata::Parse(reader, read_pos, child_size, + &colour_ptr->mastering_metadata)) + return false; + } else { + return false; + } + + read_pos += child_size; + if (read_pos > colour_end) + return false; + } + *colour = colour_ptr.release(); + return true; +} + +bool Projection::Parse(IMkvReader* reader, long long start, long long size, + Projection** projection) { + if (!reader || *projection) + return false; + + std::unique_ptr projection_ptr(new Projection()); + if (!projection_ptr.get()) + return false; + + const long long end = start + size; + long long read_pos = start; + + while (read_pos < end) { + long long child_id = 0; + long long child_size = 0; + + const long long status = + ParseElementHeader(reader, read_pos, end, child_id, child_size); + if (status < 0) + return false; + + if (child_id == libwebm::kMkvProjectionType) { + long long projection_type = kTypeNotPresent; + projection_type = UnserializeUInt(reader, read_pos, child_size); + if (projection_type < 0) + return false; + + projection_ptr->type = static_cast(projection_type); + } else if (child_id == libwebm::kMkvProjectionPrivate) { + if (projection_ptr->private_data != NULL) + return false; + unsigned char* data = SafeArrayAlloc(1, child_size); + + if (data == NULL) + return false; + + const int status = + reader->Read(read_pos, static_cast(child_size), data); + + if (status) { + delete[] data; + return false; + } + + projection_ptr->private_data = data; + projection_ptr->private_data_length = static_cast(child_size); + } else { + double value = 0; + const long long value_parse_status = + UnserializeFloat(reader, read_pos, child_size, value); + // Make sure value is representable as a float before casting. + if (value_parse_status < 0 || value < -FLT_MAX || value > FLT_MAX || + (value > 0.0 && value < FLT_MIN)) { + return false; + } + + switch (child_id) { + case libwebm::kMkvProjectionPoseYaw: + projection_ptr->pose_yaw = static_cast(value); + break; + case libwebm::kMkvProjectionPosePitch: + projection_ptr->pose_pitch = static_cast(value); + break; + case libwebm::kMkvProjectionPoseRoll: + projection_ptr->pose_roll = static_cast(value); + break; + default: + return false; + } + } + + read_pos += child_size; + if (read_pos > end) + return false; + } + + *projection = projection_ptr.release(); + return true; +} + +VideoTrack::VideoTrack(Segment* pSegment, long long element_start, + long long element_size) + : Track(pSegment, element_start, element_size), + m_colour_space(NULL), + m_colour(NULL), + m_projection(NULL) {} + +VideoTrack::~VideoTrack() { + delete[] m_colour_space; + delete m_colour; + delete m_projection; +} + +long VideoTrack::Parse(Segment* pSegment, const Info& info, + long long element_start, long long element_size, + VideoTrack*& pResult) { + if (pResult) + return -1; + + if (info.type != Track::kVideo) + return -1; + + long long width = 0; + long long height = 0; + long long display_width = 0; + long long display_height = 0; + long long display_unit = 0; + long long stereo_mode = 0; + + double rate = 0.0; + std::unique_ptr colour_space_ptr; + + IMkvReader* const pReader = pSegment->m_pReader; + + const Settings& s = info.settings; + assert(s.start >= 0); + assert(s.size >= 0); + + long long pos = s.start; + assert(pos >= 0); + + const long long stop = pos + s.size; + + std::unique_ptr colour_ptr; + std::unique_ptr projection_ptr; + + while (pos < stop) { + long long id, size; + + const long status = ParseElementHeader(pReader, pos, stop, id, size); + + if (status < 0) // error + return status; + + if (id == libwebm::kMkvPixelWidth) { + width = UnserializeUInt(pReader, pos, size); + + if (width <= 0) + return E_FILE_FORMAT_INVALID; + } else if (id == libwebm::kMkvPixelHeight) { + height = UnserializeUInt(pReader, pos, size); + + if (height <= 0) + return E_FILE_FORMAT_INVALID; + } else if (id == libwebm::kMkvDisplayWidth) { + display_width = UnserializeUInt(pReader, pos, size); + + if (display_width <= 0) + return E_FILE_FORMAT_INVALID; + } else if (id == libwebm::kMkvDisplayHeight) { + display_height = UnserializeUInt(pReader, pos, size); + + if (display_height <= 0) + return E_FILE_FORMAT_INVALID; + } else if (id == libwebm::kMkvDisplayUnit) { + display_unit = UnserializeUInt(pReader, pos, size); + + if (display_unit < 0) + return E_FILE_FORMAT_INVALID; + } else if (id == libwebm::kMkvStereoMode) { + stereo_mode = UnserializeUInt(pReader, pos, size); + + if (stereo_mode < 0) + return E_FILE_FORMAT_INVALID; + } else if (id == libwebm::kMkvFrameRate) { + const long status = UnserializeFloat(pReader, pos, size, rate); + + if (status < 0) + return status; + + if (rate <= 0) + return E_FILE_FORMAT_INVALID; + } else if (id == libwebm::kMkvColour) { + Colour* colour = NULL; + if (!Colour::Parse(pReader, pos, size, &colour)) { + return E_FILE_FORMAT_INVALID; + } else { + colour_ptr.reset(colour); + } + } else if (id == libwebm::kMkvProjection) { + Projection* projection = NULL; + if (!Projection::Parse(pReader, pos, size, &projection)) { + return E_FILE_FORMAT_INVALID; + } else { + projection_ptr.reset(projection); + } + } else if (id == libwebm::kMkvColourSpace) { + char* colour_space = NULL; + const long status = UnserializeString(pReader, pos, size, colour_space); + if (status < 0) + return status; + colour_space_ptr.reset(colour_space); + } + + pos += size; // consume payload + if (pos > stop) + return E_FILE_FORMAT_INVALID; + } + + if (pos != stop) + return E_FILE_FORMAT_INVALID; + + VideoTrack* const pTrack = + new (std::nothrow) VideoTrack(pSegment, element_start, element_size); + + if (pTrack == NULL) + return -1; // generic error + + const int status = info.Copy(pTrack->m_info); + + if (status) { // error + delete pTrack; + return status; + } + + pTrack->m_width = width; + pTrack->m_height = height; + pTrack->m_display_width = display_width; + pTrack->m_display_height = display_height; + pTrack->m_display_unit = display_unit; + pTrack->m_stereo_mode = stereo_mode; + pTrack->m_rate = rate; + pTrack->m_colour = colour_ptr.release(); + pTrack->m_colour_space = colour_space_ptr.release(); + pTrack->m_projection = projection_ptr.release(); + + pResult = pTrack; + return 0; // success +} + +bool VideoTrack::VetEntry(const BlockEntry* pBlockEntry) const { + return Track::VetEntry(pBlockEntry) && pBlockEntry->GetBlock()->IsKey(); +} + +long VideoTrack::Seek(long long time_ns, const BlockEntry*& pResult) const { + const long status = GetFirst(pResult); + + if (status < 0) // buffer underflow, etc + return status; + + assert(pResult); + + if (pResult->EOS()) + return 0; + + const Cluster* pCluster = pResult->GetCluster(); + assert(pCluster); + assert(pCluster->GetIndex() >= 0); + + if (time_ns <= pResult->GetBlock()->GetTime(pCluster)) + return 0; + + Cluster** const clusters = m_pSegment->m_clusters; + assert(clusters); + + const long count = m_pSegment->GetCount(); // loaded only, not pre-loaded + assert(count > 0); + + Cluster** const i = clusters + pCluster->GetIndex(); + assert(i); + assert(*i == pCluster); + assert(pCluster->GetTime() <= time_ns); + + Cluster** const j = clusters + count; + + Cluster** lo = i; + Cluster** hi = j; + + while (lo < hi) { + // INVARIANT: + //[i, lo) <= time_ns + //[lo, hi) ? + //[hi, j) > time_ns + + Cluster** const mid = lo + (hi - lo) / 2; + assert(mid < hi); + + pCluster = *mid; + assert(pCluster); + assert(pCluster->GetIndex() >= 0); + assert(pCluster->GetIndex() == long(mid - m_pSegment->m_clusters)); + + const long long t = pCluster->GetTime(); + + if (t <= time_ns) + lo = mid + 1; + else + hi = mid; + + assert(lo <= hi); + } + + assert(lo == hi); + assert(lo > i); + assert(lo <= j); + + pCluster = *--lo; + assert(pCluster); + assert(pCluster->GetTime() <= time_ns); + + pResult = pCluster->GetEntry(this, time_ns); + + if ((pResult != 0) && !pResult->EOS()) // found a keyframe + return 0; + + while (lo != i) { + pCluster = *--lo; + assert(pCluster); + assert(pCluster->GetTime() <= time_ns); + + pResult = pCluster->GetEntry(this, time_ns); + + if ((pResult != 0) && !pResult->EOS()) + return 0; + } + + // weird: we're on the first cluster, but no keyframe found + // should never happen but we must return something anyway + + pResult = GetEOS(); + return 0; +} + +Colour* VideoTrack::GetColour() const { return m_colour; } + +Projection* VideoTrack::GetProjection() const { return m_projection; } + +long long VideoTrack::GetWidth() const { return m_width; } + +long long VideoTrack::GetHeight() const { return m_height; } + +long long VideoTrack::GetDisplayWidth() const { + return m_display_width > 0 ? m_display_width : GetWidth(); +} + +long long VideoTrack::GetDisplayHeight() const { + return m_display_height > 0 ? m_display_height : GetHeight(); +} + +long long VideoTrack::GetDisplayUnit() const { return m_display_unit; } + +long long VideoTrack::GetStereoMode() const { return m_stereo_mode; } + +double VideoTrack::GetFrameRate() const { return m_rate; } + +AudioTrack::AudioTrack(Segment* pSegment, long long element_start, + long long element_size) + : Track(pSegment, element_start, element_size) {} + +long AudioTrack::Parse(Segment* pSegment, const Info& info, + long long element_start, long long element_size, + AudioTrack*& pResult) { + if (pResult) + return -1; + + if (info.type != Track::kAudio) + return -1; + + IMkvReader* const pReader = pSegment->m_pReader; + + const Settings& s = info.settings; + assert(s.start >= 0); + assert(s.size >= 0); + + long long pos = s.start; + assert(pos >= 0); + + const long long stop = pos + s.size; + + double rate = 8000.0; // MKV default + long long channels = 1; + long long bit_depth = 0; + + while (pos < stop) { + long long id, size; + + long status = ParseElementHeader(pReader, pos, stop, id, size); + + if (status < 0) // error + return status; + + if (id == libwebm::kMkvSamplingFrequency) { + status = UnserializeFloat(pReader, pos, size, rate); + + if (status < 0) + return status; + + if (rate <= 0) + return E_FILE_FORMAT_INVALID; + } else if (id == libwebm::kMkvChannels) { + channels = UnserializeUInt(pReader, pos, size); + + if (channels <= 0) + return E_FILE_FORMAT_INVALID; + } else if (id == libwebm::kMkvBitDepth) { + bit_depth = UnserializeUInt(pReader, pos, size); + + if (bit_depth <= 0) + return E_FILE_FORMAT_INVALID; + } + + pos += size; // consume payload + if (pos > stop) + return E_FILE_FORMAT_INVALID; + } + + if (pos != stop) + return E_FILE_FORMAT_INVALID; + + AudioTrack* const pTrack = + new (std::nothrow) AudioTrack(pSegment, element_start, element_size); + + if (pTrack == NULL) + return -1; // generic error + + const int status = info.Copy(pTrack->m_info); + + if (status) { + delete pTrack; + return status; + } + + pTrack->m_rate = rate; + pTrack->m_channels = channels; + pTrack->m_bitDepth = bit_depth; + + pResult = pTrack; + return 0; // success +} + +double AudioTrack::GetSamplingRate() const { return m_rate; } + +long long AudioTrack::GetChannels() const { return m_channels; } + +long long AudioTrack::GetBitDepth() const { return m_bitDepth; } + +Tracks::Tracks(Segment* pSegment, long long start, long long size_, + long long element_start, long long element_size) + : m_pSegment(pSegment), + m_start(start), + m_size(size_), + m_element_start(element_start), + m_element_size(element_size), + m_trackEntries(NULL), + m_trackEntriesEnd(NULL) {} + +long Tracks::Parse() { + assert(m_trackEntries == NULL); + assert(m_trackEntriesEnd == NULL); + + const long long stop = m_start + m_size; + IMkvReader* const pReader = m_pSegment->m_pReader; + + long long count = 0; + long long pos = m_start; + + while (pos < stop) { + long long id, size; + + const long status = ParseElementHeader(pReader, pos, stop, id, size); + + if (status < 0) // error + return status; + + if (size == 0) // weird + continue; + + if (id == libwebm::kMkvTrackEntry) { + ++count; + if (count > INT_MAX) + return E_PARSE_FAILED; + } + + pos += size; // consume payload + if (pos > stop) + return E_FILE_FORMAT_INVALID; + } + + if (pos != stop) + return E_FILE_FORMAT_INVALID; + + if (count <= 0) + return 0; // success + + m_trackEntries = new (std::nothrow) Track*[count]; + + if (m_trackEntries == NULL) + return -1; + + m_trackEntriesEnd = m_trackEntries; + + pos = m_start; + + while (pos < stop) { + const long long element_start = pos; + + long long id, payload_size; + + const long status = + ParseElementHeader(pReader, pos, stop, id, payload_size); + + if (status < 0) // error + return status; + + if (payload_size == 0) // weird + continue; + + const long long payload_stop = pos + payload_size; + assert(payload_stop <= stop); // checked in ParseElement + + const long long element_size = payload_stop - element_start; + + if (id == libwebm::kMkvTrackEntry) { + Track*& pTrack = *m_trackEntriesEnd; + pTrack = NULL; + + const long status = ParseTrackEntry(pos, payload_size, element_start, + element_size, pTrack); + if (status) + return status; + + if (pTrack) + ++m_trackEntriesEnd; + } + + pos = payload_stop; + if (pos > stop) + return E_FILE_FORMAT_INVALID; + } + + if (pos != stop) + return E_FILE_FORMAT_INVALID; + + return 0; // success +} + +unsigned long Tracks::GetTracksCount() const { + const ptrdiff_t result = m_trackEntriesEnd - m_trackEntries; + assert(result >= 0); + + return static_cast(result); +} + +long Tracks::ParseTrackEntry(long long track_start, long long track_size, + long long element_start, long long element_size, + Track*& pResult) const { + if (pResult) + return -1; + + IMkvReader* const pReader = m_pSegment->m_pReader; + + long long pos = track_start; + const long long track_stop = track_start + track_size; + + Track::Info info; + + info.type = 0; + info.number = 0; + info.uid = 0; + info.defaultDuration = 0; + + Track::Settings v; + v.start = -1; + v.size = -1; + + Track::Settings a; + a.start = -1; + a.size = -1; + + Track::Settings e; // content_encodings_settings; + e.start = -1; + e.size = -1; + + long long lacing = 1; // default is true + + while (pos < track_stop) { + long long id, size; + + const long status = ParseElementHeader(pReader, pos, track_stop, id, size); + + if (status < 0) // error + return status; + + if (size < 0) + return E_FILE_FORMAT_INVALID; + + const long long start = pos; + + if (id == libwebm::kMkvVideo) { + v.start = start; + v.size = size; + } else if (id == libwebm::kMkvAudio) { + a.start = start; + a.size = size; + } else if (id == libwebm::kMkvContentEncodings) { + e.start = start; + e.size = size; + } else if (id == libwebm::kMkvTrackUID) { + if (size > 8) + return E_FILE_FORMAT_INVALID; + + info.uid = 0; + + long long pos_ = start; + const long long pos_end = start + size; + + while (pos_ != pos_end) { + unsigned char b; + + const int status = pReader->Read(pos_, 1, &b); + + if (status) + return status; + + info.uid <<= 8; + info.uid |= b; + + ++pos_; + } + } else if (id == libwebm::kMkvTrackNumber) { + const long long num = UnserializeUInt(pReader, pos, size); + + if ((num <= 0) || (num > 127)) + return E_FILE_FORMAT_INVALID; + + info.number = static_cast(num); + } else if (id == libwebm::kMkvTrackType) { + const long long type = UnserializeUInt(pReader, pos, size); + + if ((type <= 0) || (type > 254)) + return E_FILE_FORMAT_INVALID; + + info.type = static_cast(type); + } else if (id == libwebm::kMkvName) { + const long status = + UnserializeString(pReader, pos, size, info.nameAsUTF8); + + if (status) + return status; + } else if (id == libwebm::kMkvLanguage) { + const long status = UnserializeString(pReader, pos, size, info.language); + + if (status) + return status; + } else if (id == libwebm::kMkvDefaultDuration) { + const long long duration = UnserializeUInt(pReader, pos, size); + + if (duration < 0) + return E_FILE_FORMAT_INVALID; + + info.defaultDuration = static_cast(duration); + } else if (id == libwebm::kMkvCodecID) { + const long status = UnserializeString(pReader, pos, size, info.codecId); + + if (status) + return status; + } else if (id == libwebm::kMkvFlagLacing) { + lacing = UnserializeUInt(pReader, pos, size); + + if ((lacing < 0) || (lacing > 1)) + return E_FILE_FORMAT_INVALID; + } else if (id == libwebm::kMkvCodecPrivate) { + delete[] info.codecPrivate; + info.codecPrivate = NULL; + info.codecPrivateSize = 0; + + const size_t buflen = static_cast(size); + + if (buflen) { + unsigned char* buf = SafeArrayAlloc(1, buflen); + + if (buf == NULL) + return -1; + + const int status = pReader->Read(pos, static_cast(buflen), buf); + + if (status) { + delete[] buf; + return status; + } + + info.codecPrivate = buf; + info.codecPrivateSize = buflen; + } + } else if (id == libwebm::kMkvCodecName) { + const long status = + UnserializeString(pReader, pos, size, info.codecNameAsUTF8); + + if (status) + return status; + } else if (id == libwebm::kMkvCodecDelay) { + info.codecDelay = UnserializeUInt(pReader, pos, size); + } else if (id == libwebm::kMkvSeekPreRoll) { + info.seekPreRoll = UnserializeUInt(pReader, pos, size); + } + + pos += size; // consume payload + if (pos > track_stop) + return E_FILE_FORMAT_INVALID; + } + + if (pos != track_stop) + return E_FILE_FORMAT_INVALID; + + if (info.number <= 0) // not specified + return E_FILE_FORMAT_INVALID; + + if (GetTrackByNumber(info.number)) + return E_FILE_FORMAT_INVALID; + + if (info.type <= 0) // not specified + return E_FILE_FORMAT_INVALID; + + info.lacing = (lacing > 0) ? true : false; + + if (info.type == Track::kVideo) { + if (v.start < 0) + return E_FILE_FORMAT_INVALID; + + if (a.start >= 0) + return E_FILE_FORMAT_INVALID; + + info.settings = v; + + VideoTrack* pTrack = NULL; + + const long status = VideoTrack::Parse(m_pSegment, info, element_start, + element_size, pTrack); + + if (status) + return status; + + pResult = pTrack; + assert(pResult); + + if (e.start >= 0) + pResult->ParseContentEncodingsEntry(e.start, e.size); + } else if (info.type == Track::kAudio) { + if (a.start < 0) + return E_FILE_FORMAT_INVALID; + + if (v.start >= 0) + return E_FILE_FORMAT_INVALID; + + info.settings = a; + + AudioTrack* pTrack = NULL; + + const long status = AudioTrack::Parse(m_pSegment, info, element_start, + element_size, pTrack); + + if (status) + return status; + + pResult = pTrack; + assert(pResult); + + if (e.start >= 0) + pResult->ParseContentEncodingsEntry(e.start, e.size); + } else { + // neither video nor audio - probably metadata or subtitles + + if (a.start >= 0) + return E_FILE_FORMAT_INVALID; + + if (v.start >= 0) + return E_FILE_FORMAT_INVALID; + + if (info.type == Track::kMetadata && e.start >= 0) + return E_FILE_FORMAT_INVALID; + + info.settings.start = -1; + info.settings.size = 0; + + Track* pTrack = NULL; + + const long status = + Track::Create(m_pSegment, info, element_start, element_size, pTrack); + + if (status) + return status; + + pResult = pTrack; + assert(pResult); + } + + return 0; // success +} + +Tracks::~Tracks() { + Track** i = m_trackEntries; + Track** const j = m_trackEntriesEnd; + + while (i != j) { + Track* const pTrack = *i++; + delete pTrack; + } + + delete[] m_trackEntries; +} + +const Track* Tracks::GetTrackByNumber(long tn) const { + if (tn < 0) + return NULL; + + Track** i = m_trackEntries; + Track** const j = m_trackEntriesEnd; + + while (i != j) { + Track* const pTrack = *i++; + + if (pTrack == NULL) + continue; + + if (tn == pTrack->GetNumber()) + return pTrack; + } + + return NULL; // not found +} + +const Track* Tracks::GetTrackByIndex(unsigned long idx) const { + const ptrdiff_t count = m_trackEntriesEnd - m_trackEntries; + + if (idx >= static_cast(count)) + return NULL; + + return m_trackEntries[idx]; +} + +long Cluster::Load(long long& pos, long& len) const { + if (m_pSegment == NULL) + return E_PARSE_FAILED; + + if (m_timecode >= 0) // at least partially loaded + return 0; + + if (m_pos != m_element_start || m_element_size >= 0) + return E_PARSE_FAILED; + + IMkvReader* const pReader = m_pSegment->m_pReader; + long long total, avail; + const int status = pReader->Length(&total, &avail); + + if (status < 0) // error + return status; + + if (total >= 0 && (avail > total || m_pos > total)) + return E_FILE_FORMAT_INVALID; + + pos = m_pos; + + long long cluster_size = -1; + + if ((pos + 1) > avail) { + len = 1; + return E_BUFFER_NOT_FULL; + } + + long long result = GetUIntLength(pReader, pos, len); + + if (result < 0) // error or underflow + return static_cast(result); + + if (result > 0) + return E_BUFFER_NOT_FULL; + + if ((pos + len) > avail) + return E_BUFFER_NOT_FULL; + + const long long id_ = ReadID(pReader, pos, len); + + if (id_ < 0) // error + return static_cast(id_); + + if (id_ != libwebm::kMkvCluster) + return E_FILE_FORMAT_INVALID; + + pos += len; // consume id + + // read cluster size + + if ((pos + 1) > avail) { + len = 1; + return E_BUFFER_NOT_FULL; + } + + result = GetUIntLength(pReader, pos, len); + + if (result < 0) // error + return static_cast(result); + + if (result > 0) + return E_BUFFER_NOT_FULL; + + if ((pos + len) > avail) + return E_BUFFER_NOT_FULL; + + const long long size = ReadUInt(pReader, pos, len); + + if (size < 0) // error + return static_cast(cluster_size); + + if (size == 0) + return E_FILE_FORMAT_INVALID; + + pos += len; // consume length of size of element + + const long long unknown_size = (1LL << (7 * len)) - 1; + + if (size != unknown_size) + cluster_size = size; + + // pos points to start of payload + long long timecode = -1; + long long new_pos = -1; + bool bBlock = false; + + long long cluster_stop = (cluster_size < 0) ? -1 : pos + cluster_size; + + for (;;) { + if ((cluster_stop >= 0) && (pos >= cluster_stop)) + break; + + // Parse ID + + if ((pos + 1) > avail) { + len = 1; + return E_BUFFER_NOT_FULL; + } + + long long result = GetUIntLength(pReader, pos, len); + + if (result < 0) // error + return static_cast(result); + + if (result > 0) + return E_BUFFER_NOT_FULL; + + if ((cluster_stop >= 0) && ((pos + len) > cluster_stop)) + return E_FILE_FORMAT_INVALID; + + if ((pos + len) > avail) + return E_BUFFER_NOT_FULL; + + const long long id = ReadID(pReader, pos, len); + + if (id < 0) // error + return static_cast(id); + + if (id == 0) + return E_FILE_FORMAT_INVALID; + + // This is the distinguished set of ID's we use to determine + // that we have exhausted the sub-element's inside the cluster + // whose ID we parsed earlier. + + if (id == libwebm::kMkvCluster) + break; + + if (id == libwebm::kMkvCues) + break; + + pos += len; // consume ID field + + // Parse Size + + if ((pos + 1) > avail) { + len = 1; + return E_BUFFER_NOT_FULL; + } + + result = GetUIntLength(pReader, pos, len); + + if (result < 0) // error + return static_cast(result); + + if (result > 0) + return E_BUFFER_NOT_FULL; + + if ((cluster_stop >= 0) && ((pos + len) > cluster_stop)) + return E_FILE_FORMAT_INVALID; + + if ((pos + len) > avail) + return E_BUFFER_NOT_FULL; + + const long long size = ReadUInt(pReader, pos, len); + + if (size < 0) // error + return static_cast(size); + + const long long unknown_size = (1LL << (7 * len)) - 1; + + if (size == unknown_size) + return E_FILE_FORMAT_INVALID; + + pos += len; // consume size field + + if ((cluster_stop >= 0) && (pos > cluster_stop)) + return E_FILE_FORMAT_INVALID; + + // pos now points to start of payload + + if (size == 0) + continue; + + if ((cluster_stop >= 0) && ((pos + size) > cluster_stop)) + return E_FILE_FORMAT_INVALID; + + if (id == libwebm::kMkvTimecode) { + len = static_cast(size); + + if ((pos + size) > avail) + return E_BUFFER_NOT_FULL; + + timecode = UnserializeUInt(pReader, pos, size); + + if (timecode < 0) // error (or underflow) + return static_cast(timecode); + + new_pos = pos + size; + + if (bBlock) + break; + } else if (id == libwebm::kMkvBlockGroup) { + bBlock = true; + break; + } else if (id == libwebm::kMkvSimpleBlock) { + bBlock = true; + break; + } + + pos += size; // consume payload + if (cluster_stop >= 0 && pos > cluster_stop) + return E_FILE_FORMAT_INVALID; + } + + if (cluster_stop >= 0 && pos > cluster_stop) + return E_FILE_FORMAT_INVALID; + + if (timecode < 0) // no timecode found + return E_FILE_FORMAT_INVALID; + + if (!bBlock) + return E_FILE_FORMAT_INVALID; + + m_pos = new_pos; // designates position just beyond timecode payload + m_timecode = timecode; // m_timecode >= 0 means we're partially loaded + + if (cluster_size >= 0) + m_element_size = cluster_stop - m_element_start; + + return 0; +} + +long Cluster::Parse(long long& pos, long& len) const { + long status = Load(pos, len); + + if (status < 0) + return status; + + if (m_pos < m_element_start || m_timecode < 0) + return E_PARSE_FAILED; + + const long long cluster_stop = + (m_element_size < 0) ? -1 : m_element_start + m_element_size; + + if ((cluster_stop >= 0) && (m_pos >= cluster_stop)) + return 1; // nothing else to do + + IMkvReader* const pReader = m_pSegment->m_pReader; + + long long total, avail; + + status = pReader->Length(&total, &avail); + + if (status < 0) // error + return status; + + if (total >= 0 && avail > total) + return E_FILE_FORMAT_INVALID; + + pos = m_pos; + + for (;;) { + if ((cluster_stop >= 0) && (pos >= cluster_stop)) + break; + + if ((total >= 0) && (pos >= total)) { + if (m_element_size < 0) + m_element_size = pos - m_element_start; + + break; + } + + // Parse ID + + if ((pos + 1) > avail) { + len = 1; + return E_BUFFER_NOT_FULL; + } + + long long result = GetUIntLength(pReader, pos, len); + + if (result < 0) // error + return static_cast(result); + + if (result > 0) + return E_BUFFER_NOT_FULL; + + if ((cluster_stop >= 0) && ((pos + len) > cluster_stop)) + return E_FILE_FORMAT_INVALID; + + if ((pos + len) > avail) + return E_BUFFER_NOT_FULL; + + const long long id = ReadID(pReader, pos, len); + + if (id < 0) + return E_FILE_FORMAT_INVALID; + + // This is the distinguished set of ID's we use to determine + // that we have exhausted the sub-element's inside the cluster + // whose ID we parsed earlier. + + if ((id == libwebm::kMkvCluster) || (id == libwebm::kMkvCues)) { + if (m_element_size < 0) + m_element_size = pos - m_element_start; + + break; + } + + pos += len; // consume ID field + + // Parse Size + + if ((pos + 1) > avail) { + len = 1; + return E_BUFFER_NOT_FULL; + } + + result = GetUIntLength(pReader, pos, len); + + if (result < 0) // error + return static_cast(result); + + if (result > 0) + return E_BUFFER_NOT_FULL; + + if ((cluster_stop >= 0) && ((pos + len) > cluster_stop)) + return E_FILE_FORMAT_INVALID; + + if ((pos + len) > avail) + return E_BUFFER_NOT_FULL; + + const long long size = ReadUInt(pReader, pos, len); + + if (size < 0) // error + return static_cast(size); + + const long long unknown_size = (1LL << (7 * len)) - 1; + + if (size == unknown_size) + return E_FILE_FORMAT_INVALID; + + pos += len; // consume size field + + if ((cluster_stop >= 0) && (pos > cluster_stop)) + return E_FILE_FORMAT_INVALID; + + // pos now points to start of payload + + if (size == 0) + continue; + + // const long long block_start = pos; + const long long block_stop = pos + size; + + if (cluster_stop >= 0) { + if (block_stop > cluster_stop) { + if (id == libwebm::kMkvBlockGroup || id == libwebm::kMkvSimpleBlock) { + return E_FILE_FORMAT_INVALID; + } + + pos = cluster_stop; + break; + } + } else if ((total >= 0) && (block_stop > total)) { + m_element_size = total - m_element_start; + pos = total; + break; + } else if (block_stop > avail) { + len = static_cast(size); + return E_BUFFER_NOT_FULL; + } + + Cluster* const this_ = const_cast(this); + + if (id == libwebm::kMkvBlockGroup) + return this_->ParseBlockGroup(size, pos, len); + + if (id == libwebm::kMkvSimpleBlock) + return this_->ParseSimpleBlock(size, pos, len); + + pos += size; // consume payload + if (cluster_stop >= 0 && pos > cluster_stop) + return E_FILE_FORMAT_INVALID; + } + + if (m_element_size < 1) + return E_FILE_FORMAT_INVALID; + + m_pos = pos; + if (cluster_stop >= 0 && m_pos > cluster_stop) + return E_FILE_FORMAT_INVALID; + + if (m_entries_count > 0) { + const long idx = m_entries_count - 1; + + const BlockEntry* const pLast = m_entries[idx]; + if (pLast == NULL) + return E_PARSE_FAILED; + + const Block* const pBlock = pLast->GetBlock(); + if (pBlock == NULL) + return E_PARSE_FAILED; + + const long long start = pBlock->m_start; + + if ((total >= 0) && (start > total)) + return E_PARSE_FAILED; // defend against trucated stream + + const long long size = pBlock->m_size; + + const long long stop = start + size; + if (cluster_stop >= 0 && stop > cluster_stop) + return E_FILE_FORMAT_INVALID; + + if ((total >= 0) && (stop > total)) + return E_PARSE_FAILED; // defend against trucated stream + } + + return 1; // no more entries +} + +long Cluster::ParseSimpleBlock(long long block_size, long long& pos, + long& len) { + const long long block_start = pos; + const long long block_stop = pos + block_size; + + IMkvReader* const pReader = m_pSegment->m_pReader; + + long long total, avail; + + long status = pReader->Length(&total, &avail); + + if (status < 0) // error + return status; + + assert((total < 0) || (avail <= total)); + + // parse track number + + if ((pos + 1) > avail) { + len = 1; + return E_BUFFER_NOT_FULL; + } + + long long result = GetUIntLength(pReader, pos, len); + + if (result < 0) // error + return static_cast(result); + + if (result > 0) // weird + return E_BUFFER_NOT_FULL; + + if ((pos + len) > block_stop) + return E_FILE_FORMAT_INVALID; + + if ((pos + len) > avail) + return E_BUFFER_NOT_FULL; + + const long long track = ReadUInt(pReader, pos, len); + + if (track < 0) // error + return static_cast(track); + + if (track == 0) + return E_FILE_FORMAT_INVALID; + + pos += len; // consume track number + + if ((pos + 2) > block_stop) + return E_FILE_FORMAT_INVALID; + + if ((pos + 2) > avail) { + len = 2; + return E_BUFFER_NOT_FULL; + } + + pos += 2; // consume timecode + + if ((pos + 1) > block_stop) + return E_FILE_FORMAT_INVALID; + + if ((pos + 1) > avail) { + len = 1; + return E_BUFFER_NOT_FULL; + } + + unsigned char flags; + + status = pReader->Read(pos, 1, &flags); + + if (status < 0) { // error or underflow + len = 1; + return status; + } + + ++pos; // consume flags byte + assert(pos <= avail); + + if (pos >= block_stop) + return E_FILE_FORMAT_INVALID; + + const int lacing = int(flags & 0x06) >> 1; + + if ((lacing != 0) && (block_stop > avail)) { + len = static_cast(block_stop - pos); + return E_BUFFER_NOT_FULL; + } + + status = CreateBlock(libwebm::kMkvSimpleBlock, block_start, block_size, + 0); // DiscardPadding + + if (status != 0) + return status; + + m_pos = block_stop; + + return 0; // success +} + +long Cluster::ParseBlockGroup(long long payload_size, long long& pos, + long& len) { + const long long payload_start = pos; + const long long payload_stop = pos + payload_size; + + IMkvReader* const pReader = m_pSegment->m_pReader; + + long long total, avail; + + long status = pReader->Length(&total, &avail); + + if (status < 0) // error + return status; + + assert((total < 0) || (avail <= total)); + + if ((total >= 0) && (payload_stop > total)) + return E_FILE_FORMAT_INVALID; + + if (payload_stop > avail) { + len = static_cast(payload_size); + return E_BUFFER_NOT_FULL; + } + + long long discard_padding = 0; + + while (pos < payload_stop) { + // parse sub-block element ID + + if ((pos + 1) > avail) { + len = 1; + return E_BUFFER_NOT_FULL; + } + + long long result = GetUIntLength(pReader, pos, len); + + if (result < 0) // error + return static_cast(result); + + if (result > 0) // weird + return E_BUFFER_NOT_FULL; + + if ((pos + len) > payload_stop) + return E_FILE_FORMAT_INVALID; + + if ((pos + len) > avail) + return E_BUFFER_NOT_FULL; + + const long long id = ReadID(pReader, pos, len); + + if (id < 0) // error + return static_cast(id); + + if (id == 0) // not a valid ID + return E_FILE_FORMAT_INVALID; + + pos += len; // consume ID field + + // Parse Size + + if ((pos + 1) > avail) { + len = 1; + return E_BUFFER_NOT_FULL; + } + + result = GetUIntLength(pReader, pos, len); + + if (result < 0) // error + return static_cast(result); + + if (result > 0) // weird + return E_BUFFER_NOT_FULL; + + if ((pos + len) > payload_stop) + return E_FILE_FORMAT_INVALID; + + if ((pos + len) > avail) + return E_BUFFER_NOT_FULL; + + const long long size = ReadUInt(pReader, pos, len); + + if (size < 0) // error + return static_cast(size); + + pos += len; // consume size field + + // pos now points to start of sub-block group payload + + if (pos > payload_stop) + return E_FILE_FORMAT_INVALID; + + if (size == 0) // weird + continue; + + const long long unknown_size = (1LL << (7 * len)) - 1; + + if (size == unknown_size) + return E_FILE_FORMAT_INVALID; + + if (id == libwebm::kMkvDiscardPadding) { + status = UnserializeInt(pReader, pos, size, discard_padding); + + if (status < 0) // error + return status; + } + + if (id != libwebm::kMkvBlock) { + pos += size; // consume sub-part of block group + + if (pos > payload_stop) + return E_FILE_FORMAT_INVALID; + + continue; + } + + const long long block_stop = pos + size; + + if (block_stop > payload_stop) + return E_FILE_FORMAT_INVALID; + + // parse track number + + if ((pos + 1) > avail) { + len = 1; + return E_BUFFER_NOT_FULL; + } + + result = GetUIntLength(pReader, pos, len); + + if (result < 0) // error + return static_cast(result); + + if (result > 0) // weird + return E_BUFFER_NOT_FULL; + + if ((pos + len) > block_stop) + return E_FILE_FORMAT_INVALID; + + if ((pos + len) > avail) + return E_BUFFER_NOT_FULL; + + const long long track = ReadUInt(pReader, pos, len); + + if (track < 0) // error + return static_cast(track); + + if (track == 0) + return E_FILE_FORMAT_INVALID; + + pos += len; // consume track number + + if ((pos + 2) > block_stop) + return E_FILE_FORMAT_INVALID; + + if ((pos + 2) > avail) { + len = 2; + return E_BUFFER_NOT_FULL; + } + + pos += 2; // consume timecode + + if ((pos + 1) > block_stop) + return E_FILE_FORMAT_INVALID; + + if ((pos + 1) > avail) { + len = 1; + return E_BUFFER_NOT_FULL; + } + + unsigned char flags; + + status = pReader->Read(pos, 1, &flags); + + if (status < 0) { // error or underflow + len = 1; + return status; + } + + ++pos; // consume flags byte + assert(pos <= avail); + + if (pos >= block_stop) + return E_FILE_FORMAT_INVALID; + + const int lacing = int(flags & 0x06) >> 1; + + if ((lacing != 0) && (block_stop > avail)) { + len = static_cast(block_stop - pos); + return E_BUFFER_NOT_FULL; + } + + pos = block_stop; // consume block-part of block group + if (pos > payload_stop) + return E_FILE_FORMAT_INVALID; + } + + if (pos != payload_stop) + return E_FILE_FORMAT_INVALID; + + status = CreateBlock(libwebm::kMkvBlockGroup, payload_start, payload_size, + discard_padding); + if (status != 0) + return status; + + m_pos = payload_stop; + + return 0; // success +} + +long Cluster::GetEntry(long index, const mkvparser::BlockEntry*& pEntry) const { + assert(m_pos >= m_element_start); + + pEntry = NULL; + + if (index < 0) + return -1; // generic error + + if (m_entries_count < 0) + return E_BUFFER_NOT_FULL; + + assert(m_entries); + assert(m_entries_size > 0); + assert(m_entries_count <= m_entries_size); + + if (index < m_entries_count) { + pEntry = m_entries[index]; + assert(pEntry); + + return 1; // found entry + } + + if (m_element_size < 0) // we don't know cluster end yet + return E_BUFFER_NOT_FULL; // underflow + + const long long element_stop = m_element_start + m_element_size; + + if (m_pos >= element_stop) + return 0; // nothing left to parse + + return E_BUFFER_NOT_FULL; // underflow, since more remains to be parsed +} + +Cluster* Cluster::Create(Segment* pSegment, long idx, long long off) { + if (!pSegment || off < 0) + return NULL; + + const long long element_start = pSegment->m_start + off; + + Cluster* const pCluster = + new (std::nothrow) Cluster(pSegment, idx, element_start); + + return pCluster; +} + +Cluster::Cluster() + : m_pSegment(NULL), + m_element_start(0), + m_index(0), + m_pos(0), + m_element_size(0), + m_timecode(0), + m_entries(NULL), + m_entries_size(0), + m_entries_count(0) // means "no entries" +{} + +Cluster::Cluster(Segment* pSegment, long idx, long long element_start + /* long long element_size */) + : m_pSegment(pSegment), + m_element_start(element_start), + m_index(idx), + m_pos(element_start), + m_element_size(-1 /* element_size */), + m_timecode(-1), + m_entries(NULL), + m_entries_size(0), + m_entries_count(-1) // means "has not been parsed yet" +{} + +Cluster::~Cluster() { + if (m_entries_count <= 0) { + delete[] m_entries; + return; + } + + BlockEntry** i = m_entries; + BlockEntry** const j = m_entries + m_entries_count; + + while (i != j) { + BlockEntry* p = *i++; + assert(p); + + delete p; + } + + delete[] m_entries; +} + +bool Cluster::EOS() const { return (m_pSegment == NULL); } + +long Cluster::GetIndex() const { return m_index; } + +long long Cluster::GetPosition() const { + const long long pos = m_element_start - m_pSegment->m_start; + assert(pos >= 0); + + return pos; +} + +long long Cluster::GetElementSize() const { return m_element_size; } + +long Cluster::HasBlockEntries( + const Segment* pSegment, + long long off, // relative to start of segment payload + long long& pos, long& len) { + assert(pSegment); + assert(off >= 0); // relative to segment + + IMkvReader* const pReader = pSegment->m_pReader; + + long long total, avail; + + long status = pReader->Length(&total, &avail); + + if (status < 0) // error + return status; + + assert((total < 0) || (avail <= total)); + + pos = pSegment->m_start + off; // absolute + + if ((total >= 0) && (pos >= total)) + return 0; // we don't even have a complete cluster + + const long long segment_stop = + (pSegment->m_size < 0) ? -1 : pSegment->m_start + pSegment->m_size; + + long long cluster_stop = -1; // interpreted later to mean "unknown size" + + { + if ((pos + 1) > avail) { + len = 1; + return E_BUFFER_NOT_FULL; + } + + long long result = GetUIntLength(pReader, pos, len); + + if (result < 0) // error + return static_cast(result); + + if (result > 0) // need more data + return E_BUFFER_NOT_FULL; + + if ((segment_stop >= 0) && ((pos + len) > segment_stop)) + return E_FILE_FORMAT_INVALID; + + if ((total >= 0) && ((pos + len) > total)) + return 0; + + if ((pos + len) > avail) + return E_BUFFER_NOT_FULL; + + const long long id = ReadID(pReader, pos, len); + + if (id < 0) // error + return static_cast(id); + + if (id != libwebm::kMkvCluster) + return E_PARSE_FAILED; + + pos += len; // consume Cluster ID field + + // read size field + + if ((pos + 1) > avail) { + len = 1; + return E_BUFFER_NOT_FULL; + } + + result = GetUIntLength(pReader, pos, len); + + if (result < 0) // error + return static_cast(result); + + if (result > 0) // weird + return E_BUFFER_NOT_FULL; + + if ((segment_stop >= 0) && ((pos + len) > segment_stop)) + return E_FILE_FORMAT_INVALID; + + if ((total >= 0) && ((pos + len) > total)) + return 0; + + if ((pos + len) > avail) + return E_BUFFER_NOT_FULL; + + const long long size = ReadUInt(pReader, pos, len); + + if (size < 0) // error + return static_cast(size); + + if (size == 0) + return 0; // cluster does not have entries + + pos += len; // consume size field + + // pos now points to start of payload + + const long long unknown_size = (1LL << (7 * len)) - 1; + + if (size != unknown_size) { + cluster_stop = pos + size; + assert(cluster_stop >= 0); + + if ((segment_stop >= 0) && (cluster_stop > segment_stop)) + return E_FILE_FORMAT_INVALID; + + if ((total >= 0) && (cluster_stop > total)) + // return E_FILE_FORMAT_INVALID; //too conservative + return 0; // cluster does not have any entries + } + } + + for (;;) { + if ((cluster_stop >= 0) && (pos >= cluster_stop)) + return 0; // no entries detected + + if ((pos + 1) > avail) { + len = 1; + return E_BUFFER_NOT_FULL; + } + + long long result = GetUIntLength(pReader, pos, len); + + if (result < 0) // error + return static_cast(result); + + if (result > 0) // need more data + return E_BUFFER_NOT_FULL; + + if ((cluster_stop >= 0) && ((pos + len) > cluster_stop)) + return E_FILE_FORMAT_INVALID; + + if ((pos + len) > avail) + return E_BUFFER_NOT_FULL; + + const long long id = ReadID(pReader, pos, len); + + if (id < 0) // error + return static_cast(id); + + // This is the distinguished set of ID's we use to determine + // that we have exhausted the sub-element's inside the cluster + // whose ID we parsed earlier. + + if (id == libwebm::kMkvCluster) + return 0; // no entries found + + if (id == libwebm::kMkvCues) + return 0; // no entries found + + pos += len; // consume id field + + if ((cluster_stop >= 0) && (pos >= cluster_stop)) + return E_FILE_FORMAT_INVALID; + + // read size field + + if ((pos + 1) > avail) { + len = 1; + return E_BUFFER_NOT_FULL; + } + + result = GetUIntLength(pReader, pos, len); + + if (result < 0) // error + return static_cast(result); + + if (result > 0) // underflow + return E_BUFFER_NOT_FULL; + + if ((cluster_stop >= 0) && ((pos + len) > cluster_stop)) + return E_FILE_FORMAT_INVALID; + + if ((pos + len) > avail) + return E_BUFFER_NOT_FULL; + + const long long size = ReadUInt(pReader, pos, len); + + if (size < 0) // error + return static_cast(size); + + pos += len; // consume size field + + // pos now points to start of payload + + if ((cluster_stop >= 0) && (pos > cluster_stop)) + return E_FILE_FORMAT_INVALID; + + if (size == 0) // weird + continue; + + const long long unknown_size = (1LL << (7 * len)) - 1; + + if (size == unknown_size) + return E_FILE_FORMAT_INVALID; // not supported inside cluster + + if ((cluster_stop >= 0) && ((pos + size) > cluster_stop)) + return E_FILE_FORMAT_INVALID; + + if (id == libwebm::kMkvBlockGroup) + return 1; // have at least one entry + + if (id == libwebm::kMkvSimpleBlock) + return 1; // have at least one entry + + pos += size; // consume payload + if (cluster_stop >= 0 && pos > cluster_stop) + return E_FILE_FORMAT_INVALID; + } +} + +long long Cluster::GetTimeCode() const { + long long pos; + long len; + + const long status = Load(pos, len); + + if (status < 0) // error + return status; + + return m_timecode; +} + +long long Cluster::GetTime() const { + const long long tc = GetTimeCode(); + + if (tc < 0) + return tc; + + const SegmentInfo* const pInfo = m_pSegment->GetInfo(); + assert(pInfo); + + const long long scale = pInfo->GetTimeCodeScale(); + assert(scale >= 1); + + const long long t = m_timecode * scale; + + return t; +} + +long long Cluster::GetFirstTime() const { + const BlockEntry* pEntry; + + const long status = GetFirst(pEntry); + + if (status < 0) // error + return status; + + if (pEntry == NULL) // empty cluster + return GetTime(); + + const Block* const pBlock = pEntry->GetBlock(); + assert(pBlock); + + return pBlock->GetTime(this); +} + +long long Cluster::GetLastTime() const { + const BlockEntry* pEntry; + + const long status = GetLast(pEntry); + + if (status < 0) // error + return status; + + if (pEntry == NULL) // empty cluster + return GetTime(); + + const Block* const pBlock = pEntry->GetBlock(); + assert(pBlock); + + return pBlock->GetTime(this); +} + +long Cluster::CreateBlock(long long id, + long long pos, // absolute pos of payload + long long size, long long discard_padding) { + if (id != libwebm::kMkvBlockGroup && id != libwebm::kMkvSimpleBlock) + return E_PARSE_FAILED; + + if (m_entries_count < 0) { // haven't parsed anything yet + assert(m_entries == NULL); + assert(m_entries_size == 0); + + m_entries_size = 1024; + m_entries = new (std::nothrow) BlockEntry*[m_entries_size]; + if (m_entries == NULL) + return -1; + + m_entries_count = 0; + } else { + assert(m_entries); + assert(m_entries_size > 0); + assert(m_entries_count <= m_entries_size); + + if (m_entries_count >= m_entries_size) { + const long entries_size = 2 * m_entries_size; + + BlockEntry** const entries = new (std::nothrow) BlockEntry*[entries_size]; + if (entries == NULL) + return -1; + + BlockEntry** src = m_entries; + BlockEntry** const src_end = src + m_entries_count; + + BlockEntry** dst = entries; + + while (src != src_end) + *dst++ = *src++; + + delete[] m_entries; + + m_entries = entries; + m_entries_size = entries_size; + } + } + + if (id == libwebm::kMkvBlockGroup) + return CreateBlockGroup(pos, size, discard_padding); + else + return CreateSimpleBlock(pos, size); +} + +long Cluster::CreateBlockGroup(long long start_offset, long long size, + long long discard_padding) { + assert(m_entries); + assert(m_entries_size > 0); + assert(m_entries_count >= 0); + assert(m_entries_count < m_entries_size); + + IMkvReader* const pReader = m_pSegment->m_pReader; + + long long pos = start_offset; + const long long stop = start_offset + size; + + // For WebM files, there is a bias towards previous reference times + //(in order to support alt-ref frames, which refer back to the previous + // keyframe). Normally a 0 value is not possible, but here we tenatively + // allow 0 as the value of a reference frame, with the interpretation + // that this is a "previous" reference time. + + long long prev = 1; // nonce + long long next = 0; // nonce + long long duration = -1; // really, this is unsigned + + long long bpos = -1; + long long bsize = -1; + + while (pos < stop) { + long len; + const long long id = ReadID(pReader, pos, len); + if (id < 0 || (pos + len) > stop) + return E_FILE_FORMAT_INVALID; + + pos += len; // consume ID + + const long long size = ReadUInt(pReader, pos, len); + assert(size >= 0); // TODO + assert((pos + len) <= stop); + + pos += len; // consume size + + if (id == libwebm::kMkvBlock) { + if (bpos < 0) { // Block ID + bpos = pos; + bsize = size; + } + } else if (id == libwebm::kMkvBlockDuration) { + if (size > 8) + return E_FILE_FORMAT_INVALID; + + duration = UnserializeUInt(pReader, pos, size); + + if (duration < 0) + return E_FILE_FORMAT_INVALID; + } else if (id == libwebm::kMkvReferenceBlock) { + if (size > 8 || size <= 0) + return E_FILE_FORMAT_INVALID; + const long size_ = static_cast(size); + + long long time; + + long status = UnserializeInt(pReader, pos, size_, time); + assert(status == 0); + if (status != 0) + return -1; + + if (time <= 0) // see note above + prev = time; + else + next = time; + } + + pos += size; // consume payload + if (pos > stop) + return E_FILE_FORMAT_INVALID; + } + if (bpos < 0) + return E_FILE_FORMAT_INVALID; + + if (pos != stop) + return E_FILE_FORMAT_INVALID; + assert(bsize >= 0); + + const long idx = m_entries_count; + + BlockEntry** const ppEntry = m_entries + idx; + BlockEntry*& pEntry = *ppEntry; + + pEntry = new (std::nothrow) + BlockGroup(this, idx, bpos, bsize, prev, next, duration, discard_padding); + + if (pEntry == NULL) + return -1; // generic error + + BlockGroup* const p = static_cast(pEntry); + + const long status = p->Parse(); + + if (status == 0) { // success + ++m_entries_count; + return 0; + } + + delete pEntry; + pEntry = 0; + + return status; +} + +long Cluster::CreateSimpleBlock(long long st, long long sz) { + assert(m_entries); + assert(m_entries_size > 0); + assert(m_entries_count >= 0); + assert(m_entries_count < m_entries_size); + + const long idx = m_entries_count; + + BlockEntry** const ppEntry = m_entries + idx; + BlockEntry*& pEntry = *ppEntry; + + pEntry = new (std::nothrow) SimpleBlock(this, idx, st, sz); + + if (pEntry == NULL) + return -1; // generic error + + SimpleBlock* const p = static_cast(pEntry); + + const long status = p->Parse(); + + if (status == 0) { + ++m_entries_count; + return 0; + } + + delete pEntry; + pEntry = 0; + + return status; +} + +long Cluster::GetFirst(const BlockEntry*& pFirst) const { + if (m_entries_count <= 0) { + long long pos; + long len; + + const long status = Parse(pos, len); + + if (status < 0) { // error + pFirst = NULL; + return status; + } + + if (m_entries_count <= 0) { // empty cluster + pFirst = NULL; + return 0; + } + } + + assert(m_entries); + + pFirst = m_entries[0]; + assert(pFirst); + + return 0; // success +} + +long Cluster::GetLast(const BlockEntry*& pLast) const { + for (;;) { + long long pos; + long len; + + const long status = Parse(pos, len); + + if (status < 0) { // error + pLast = NULL; + return status; + } + + if (status > 0) // no new block + break; + } + + if (m_entries_count <= 0) { + pLast = NULL; + return 0; + } + + assert(m_entries); + + const long idx = m_entries_count - 1; + + pLast = m_entries[idx]; + assert(pLast); + + return 0; +} + +long Cluster::GetNext(const BlockEntry* pCurr, const BlockEntry*& pNext) const { + assert(pCurr); + assert(m_entries); + assert(m_entries_count > 0); + + size_t idx = pCurr->GetIndex(); + assert(idx < size_t(m_entries_count)); + assert(m_entries[idx] == pCurr); + + ++idx; + + if (idx >= size_t(m_entries_count)) { + long long pos; + long len; + + const long status = Parse(pos, len); + + if (status < 0) { // error + pNext = NULL; + return status; + } + + if (status > 0) { + pNext = NULL; + return 0; + } + + assert(m_entries); + assert(m_entries_count > 0); + assert(idx < size_t(m_entries_count)); + } + + pNext = m_entries[idx]; + assert(pNext); + + return 0; +} + +long Cluster::GetEntryCount() const { return m_entries_count; } + +const BlockEntry* Cluster::GetEntry(const Track* pTrack, + long long time_ns) const { + assert(pTrack); + + if (m_pSegment == NULL) // this is the special EOS cluster + return pTrack->GetEOS(); + + const BlockEntry* pResult = pTrack->GetEOS(); + + long index = 0; + + for (;;) { + if (index >= m_entries_count) { + long long pos; + long len; + + const long status = Parse(pos, len); + assert(status >= 0); + + if (status > 0) // completely parsed, and no more entries + return pResult; + + if (status < 0) // should never happen + return 0; + + assert(m_entries); + assert(index < m_entries_count); + } + + const BlockEntry* const pEntry = m_entries[index]; + assert(pEntry); + assert(!pEntry->EOS()); + + const Block* const pBlock = pEntry->GetBlock(); + assert(pBlock); + + if (pBlock->GetTrackNumber() != pTrack->GetNumber()) { + ++index; + continue; + } + + if (pTrack->VetEntry(pEntry)) { + if (time_ns < 0) // just want first candidate block + return pEntry; + + const long long ns = pBlock->GetTime(this); + + if (ns > time_ns) + return pResult; + + pResult = pEntry; // have a candidate + } else if (time_ns >= 0) { + const long long ns = pBlock->GetTime(this); + + if (ns > time_ns) + return pResult; + } + + ++index; + } +} + +const BlockEntry* Cluster::GetEntry(const CuePoint& cp, + const CuePoint::TrackPosition& tp) const { + assert(m_pSegment); + const long long tc = cp.GetTimeCode(); + + if (tp.m_block > 0) { + const long block = static_cast(tp.m_block); + const long index = block - 1; + + while (index >= m_entries_count) { + long long pos; + long len; + + const long status = Parse(pos, len); + + if (status < 0) // TODO: can this happen? + return NULL; + + if (status > 0) // nothing remains to be parsed + return NULL; + } + + const BlockEntry* const pEntry = m_entries[index]; + assert(pEntry); + assert(!pEntry->EOS()); + + const Block* const pBlock = pEntry->GetBlock(); + assert(pBlock); + + if ((pBlock->GetTrackNumber() == tp.m_track) && + (pBlock->GetTimeCode(this) == tc)) { + return pEntry; + } + } + + long index = 0; + + for (;;) { + if (index >= m_entries_count) { + long long pos; + long len; + + const long status = Parse(pos, len); + + if (status < 0) // TODO: can this happen? + return NULL; + + if (status > 0) // nothing remains to be parsed + return NULL; + + assert(m_entries); + assert(index < m_entries_count); + } + + const BlockEntry* const pEntry = m_entries[index]; + assert(pEntry); + assert(!pEntry->EOS()); + + const Block* const pBlock = pEntry->GetBlock(); + assert(pBlock); + + if (pBlock->GetTrackNumber() != tp.m_track) { + ++index; + continue; + } + + const long long tc_ = pBlock->GetTimeCode(this); + + if (tc_ < tc) { + ++index; + continue; + } + + if (tc_ > tc) + return NULL; + + const Tracks* const pTracks = m_pSegment->GetTracks(); + assert(pTracks); + + const long tn = static_cast(tp.m_track); + const Track* const pTrack = pTracks->GetTrackByNumber(tn); + + if (pTrack == NULL) + return NULL; + + const long long type = pTrack->GetType(); + + if (type == 2) // audio + return pEntry; + + if (type != 1) // not video + return NULL; + + if (!pBlock->IsKey()) + return NULL; + + return pEntry; + } +} + +BlockEntry::BlockEntry(Cluster* p, long idx) : m_pCluster(p), m_index(idx) {} +BlockEntry::~BlockEntry() {} +const Cluster* BlockEntry::GetCluster() const { return m_pCluster; } +long BlockEntry::GetIndex() const { return m_index; } + +SimpleBlock::SimpleBlock(Cluster* pCluster, long idx, long long start, + long long size) + : BlockEntry(pCluster, idx), m_block(start, size, 0) {} + +long SimpleBlock::Parse() { return m_block.Parse(m_pCluster); } +BlockEntry::Kind SimpleBlock::GetKind() const { return kBlockSimple; } +const Block* SimpleBlock::GetBlock() const { return &m_block; } + +BlockGroup::BlockGroup(Cluster* pCluster, long idx, long long block_start, + long long block_size, long long prev, long long next, + long long duration, long long discard_padding) + : BlockEntry(pCluster, idx), + m_block(block_start, block_size, discard_padding), + m_prev(prev), + m_next(next), + m_duration(duration) {} + +long BlockGroup::Parse() { + const long status = m_block.Parse(m_pCluster); + + if (status) + return status; + + m_block.SetKey((m_prev > 0) && (m_next <= 0)); + + return 0; +} + +BlockEntry::Kind BlockGroup::GetKind() const { return kBlockGroup; } +const Block* BlockGroup::GetBlock() const { return &m_block; } +long long BlockGroup::GetPrevTimeCode() const { return m_prev; } +long long BlockGroup::GetNextTimeCode() const { return m_next; } +long long BlockGroup::GetDurationTimeCode() const { return m_duration; } + +Block::Block(long long start, long long size_, long long discard_padding) + : m_start(start), + m_size(size_), + m_track(0), + m_timecode(-1), + m_flags(0), + m_frames(NULL), + m_frame_count(-1), + m_discard_padding(discard_padding) {} + +Block::~Block() { delete[] m_frames; } + +long Block::Parse(const Cluster* pCluster) { + if (pCluster == NULL) + return -1; + + if (pCluster->m_pSegment == NULL) + return -1; + + assert(m_start >= 0); + assert(m_size >= 0); + assert(m_track <= 0); + assert(m_frames == NULL); + assert(m_frame_count <= 0); + + long long pos = m_start; + const long long stop = m_start + m_size; + + long len; + + IMkvReader* const pReader = pCluster->m_pSegment->m_pReader; + + m_track = ReadUInt(pReader, pos, len); + + if (m_track <= 0) + return E_FILE_FORMAT_INVALID; + + if ((pos + len) > stop) + return E_FILE_FORMAT_INVALID; + + pos += len; // consume track number + + if ((stop - pos) < 2) + return E_FILE_FORMAT_INVALID; + + long status; + long long value; + + status = UnserializeInt(pReader, pos, 2, value); + + if (status) + return E_FILE_FORMAT_INVALID; + + if (value < SHRT_MIN) + return E_FILE_FORMAT_INVALID; + + if (value > SHRT_MAX) + return E_FILE_FORMAT_INVALID; + + m_timecode = static_cast(value); + + pos += 2; + + if ((stop - pos) <= 0) + return E_FILE_FORMAT_INVALID; + + status = pReader->Read(pos, 1, &m_flags); + + if (status) + return E_FILE_FORMAT_INVALID; + + const int lacing = int(m_flags & 0x06) >> 1; + + ++pos; // consume flags byte + + if (lacing == 0) { // no lacing + if (pos > stop) + return E_FILE_FORMAT_INVALID; + + m_frame_count = 1; + m_frames = new (std::nothrow) Frame[m_frame_count]; + if (m_frames == NULL) + return -1; + + Frame& f = m_frames[0]; + f.pos = pos; + + const long long frame_size = stop - pos; + + if (frame_size > LONG_MAX || frame_size <= 0) + return E_FILE_FORMAT_INVALID; + + f.len = static_cast(frame_size); + + return 0; // success + } + + if (pos >= stop) + return E_FILE_FORMAT_INVALID; + + unsigned char biased_count; + + status = pReader->Read(pos, 1, &biased_count); + + if (status) + return E_FILE_FORMAT_INVALID; + + ++pos; // consume frame count + if (pos > stop) + return E_FILE_FORMAT_INVALID; + + m_frame_count = int(biased_count) + 1; + + m_frames = new (std::nothrow) Frame[m_frame_count]; + if (m_frames == NULL) + return -1; + + if (!m_frames) + return E_FILE_FORMAT_INVALID; + + if (lacing == 1) { // Xiph + Frame* pf = m_frames; + Frame* const pf_end = pf + m_frame_count; + + long long size = 0; + int frame_count = m_frame_count; + + while (frame_count > 1) { + long frame_size = 0; + + for (;;) { + unsigned char val; + + if (pos >= stop) + return E_FILE_FORMAT_INVALID; + + status = pReader->Read(pos, 1, &val); + + if (status) + return E_FILE_FORMAT_INVALID; + + ++pos; // consume xiph size byte + + frame_size += val; + + if (val < 255) + break; + } + + Frame& f = *pf++; + assert(pf < pf_end); + if (pf >= pf_end) + return E_FILE_FORMAT_INVALID; + + f.pos = 0; // patch later + + if (frame_size <= 0) + return E_FILE_FORMAT_INVALID; + + f.len = frame_size; + size += frame_size; // contribution of this frame + + --frame_count; + } + + if (pf >= pf_end || pos > stop) + return E_FILE_FORMAT_INVALID; + + { + Frame& f = *pf++; + + if (pf != pf_end) + return E_FILE_FORMAT_INVALID; + + f.pos = 0; // patch later + + const long long total_size = stop - pos; + + if (total_size < size) + return E_FILE_FORMAT_INVALID; + + const long long frame_size = total_size - size; + + if (frame_size > LONG_MAX || frame_size <= 0) + return E_FILE_FORMAT_INVALID; + + f.len = static_cast(frame_size); + } + + pf = m_frames; + while (pf != pf_end) { + Frame& f = *pf++; + assert((pos + f.len) <= stop); + + if ((pos + f.len) > stop) + return E_FILE_FORMAT_INVALID; + + f.pos = pos; + pos += f.len; + } + + assert(pos == stop); + if (pos != stop) + return E_FILE_FORMAT_INVALID; + + } else if (lacing == 2) { // fixed-size lacing + if (pos >= stop) + return E_FILE_FORMAT_INVALID; + + const long long total_size = stop - pos; + + if ((total_size % m_frame_count) != 0) + return E_FILE_FORMAT_INVALID; + + const long long frame_size = total_size / m_frame_count; + + if (frame_size > LONG_MAX || frame_size <= 0) + return E_FILE_FORMAT_INVALID; + + Frame* pf = m_frames; + Frame* const pf_end = pf + m_frame_count; + + while (pf != pf_end) { + assert((pos + frame_size) <= stop); + if ((pos + frame_size) > stop) + return E_FILE_FORMAT_INVALID; + + Frame& f = *pf++; + + f.pos = pos; + f.len = static_cast(frame_size); + + pos += frame_size; + } + + assert(pos == stop); + if (pos != stop) + return E_FILE_FORMAT_INVALID; + + } else { + assert(lacing == 3); // EBML lacing + + if (pos >= stop) + return E_FILE_FORMAT_INVALID; + + long long size = 0; + int frame_count = m_frame_count; + + long long frame_size = ReadUInt(pReader, pos, len); + + if (frame_size <= 0) + return E_FILE_FORMAT_INVALID; + + if (frame_size > LONG_MAX) + return E_FILE_FORMAT_INVALID; + + if ((pos + len) > stop) + return E_FILE_FORMAT_INVALID; + + pos += len; // consume length of size of first frame + + if ((pos + frame_size) > stop) + return E_FILE_FORMAT_INVALID; + + Frame* pf = m_frames; + Frame* const pf_end = pf + m_frame_count; + + { + Frame& curr = *pf; + + curr.pos = 0; // patch later + + curr.len = static_cast(frame_size); + size += curr.len; // contribution of this frame + } + + --frame_count; + + while (frame_count > 1) { + if (pos >= stop) + return E_FILE_FORMAT_INVALID; + + assert(pf < pf_end); + if (pf >= pf_end) + return E_FILE_FORMAT_INVALID; + + const Frame& prev = *pf++; + assert(prev.len == frame_size); + if (prev.len != frame_size) + return E_FILE_FORMAT_INVALID; + + assert(pf < pf_end); + if (pf >= pf_end) + return E_FILE_FORMAT_INVALID; + + Frame& curr = *pf; + + curr.pos = 0; // patch later + + const long long delta_size_ = ReadUInt(pReader, pos, len); + + if (delta_size_ < 0) + return E_FILE_FORMAT_INVALID; + + if ((pos + len) > stop) + return E_FILE_FORMAT_INVALID; + + pos += len; // consume length of (delta) size + if (pos > stop) + return E_FILE_FORMAT_INVALID; + + const long exp = 7 * len - 1; + const long long bias = (1LL << exp) - 1LL; + const long long delta_size = delta_size_ - bias; + + frame_size += delta_size; + + if (frame_size <= 0) + return E_FILE_FORMAT_INVALID; + + if (frame_size > LONG_MAX) + return E_FILE_FORMAT_INVALID; + + curr.len = static_cast(frame_size); + // Check if size + curr.len could overflow. + if (size > LLONG_MAX - curr.len) { + return E_FILE_FORMAT_INVALID; + } + size += curr.len; // contribution of this frame + + --frame_count; + } + + // parse last frame + if (frame_count > 0) { + if (pos > stop || pf >= pf_end) + return E_FILE_FORMAT_INVALID; + + const Frame& prev = *pf++; + assert(prev.len == frame_size); + if (prev.len != frame_size) + return E_FILE_FORMAT_INVALID; + + if (pf >= pf_end) + return E_FILE_FORMAT_INVALID; + + Frame& curr = *pf++; + if (pf != pf_end) + return E_FILE_FORMAT_INVALID; + + curr.pos = 0; // patch later + + const long long total_size = stop - pos; + + if (total_size < size) + return E_FILE_FORMAT_INVALID; + + frame_size = total_size - size; + + if (frame_size > LONG_MAX || frame_size <= 0) + return E_FILE_FORMAT_INVALID; + + curr.len = static_cast(frame_size); + } + + pf = m_frames; + while (pf != pf_end) { + Frame& f = *pf++; + if ((pos + f.len) > stop) + return E_FILE_FORMAT_INVALID; + + f.pos = pos; + pos += f.len; + } + + if (pos != stop) + return E_FILE_FORMAT_INVALID; + } + + return 0; // success +} + +long long Block::GetTimeCode(const Cluster* pCluster) const { + if (pCluster == 0) + return m_timecode; + + const long long tc0 = pCluster->GetTimeCode(); + assert(tc0 >= 0); + + // Check if tc0 + m_timecode would overflow. + if (tc0 < 0 || LLONG_MAX - tc0 < m_timecode) { + return -1; + } + + const long long tc = tc0 + m_timecode; + + return tc; // unscaled timecode units +} + +long long Block::GetTime(const Cluster* pCluster) const { + assert(pCluster); + + const long long tc = GetTimeCode(pCluster); + + const Segment* const pSegment = pCluster->m_pSegment; + const SegmentInfo* const pInfo = pSegment->GetInfo(); + assert(pInfo); + + const long long scale = pInfo->GetTimeCodeScale(); + assert(scale >= 1); + + // Check if tc * scale could overflow. + if (tc != 0 && scale > LLONG_MAX / tc) { + return -1; + } + const long long ns = tc * scale; + + return ns; +} + +long long Block::GetTrackNumber() const { return m_track; } + +bool Block::IsKey() const { + return ((m_flags & static_cast(1 << 7)) != 0); +} + +void Block::SetKey(bool bKey) { + if (bKey) + m_flags |= static_cast(1 << 7); + else + m_flags &= 0x7F; +} + +bool Block::IsInvisible() const { return bool(int(m_flags & 0x08) != 0); } + +Block::Lacing Block::GetLacing() const { + const int value = int(m_flags & 0x06) >> 1; + return static_cast(value); +} + +int Block::GetFrameCount() const { return m_frame_count; } + +const Block::Frame& Block::GetFrame(int idx) const { + assert(idx >= 0); + assert(idx < m_frame_count); + + const Frame& f = m_frames[idx]; + assert(f.pos > 0); + assert(f.len > 0); + + return f; +} + +long Block::Frame::Read(IMkvReader* pReader, unsigned char* buf) const { + assert(pReader); + assert(buf); + + const long status = pReader->Read(pos, len, buf); + return status; +} + +long long Block::GetDiscardPadding() const { return m_discard_padding; } + +} // namespace mkvparser diff --git a/third_party/libwebm/source/mkvparser/mkvparser.h b/third_party/libwebm/source/mkvparser/mkvparser.h new file mode 100644 index 000000000000..848d01f03ece --- /dev/null +++ b/third_party/libwebm/source/mkvparser/mkvparser.h @@ -0,0 +1,1147 @@ +// Copyright (c) 2012 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +#ifndef MKVPARSER_MKVPARSER_H_ +#define MKVPARSER_MKVPARSER_H_ + +#include + +namespace mkvparser { + +const int E_PARSE_FAILED = -1; +const int E_FILE_FORMAT_INVALID = -2; +const int E_BUFFER_NOT_FULL = -3; + +class IMkvReader { + public: + virtual int Read(long long pos, long len, unsigned char* buf) = 0; + virtual int Length(long long* total, long long* available) = 0; + + protected: + virtual ~IMkvReader() {} +}; + +template +Type* SafeArrayAlloc(unsigned long long num_elements, + unsigned long long element_size); +long long GetUIntLength(IMkvReader*, long long, long&); +long long ReadUInt(IMkvReader*, long long, long&); +long long ReadID(IMkvReader* pReader, long long pos, long& len); +long long UnserializeUInt(IMkvReader*, long long pos, long long size); + +long UnserializeFloat(IMkvReader*, long long pos, long long size, double&); +long UnserializeInt(IMkvReader*, long long pos, long long size, + long long& result); + +long UnserializeString(IMkvReader*, long long pos, long long size, char*& str); + +long ParseElementHeader(IMkvReader* pReader, + long long& pos, // consume id and size fields + long long stop, // if you know size of element's parent + long long& id, long long& size); + +bool Match(IMkvReader*, long long&, unsigned long, long long&); +bool Match(IMkvReader*, long long&, unsigned long, unsigned char*&, size_t&); + +void GetVersion(int& major, int& minor, int& build, int& revision); + +struct EBMLHeader { + EBMLHeader(); + ~EBMLHeader(); + long long m_version; + long long m_readVersion; + long long m_maxIdLength; + long long m_maxSizeLength; + char* m_docType; + long long m_docTypeVersion; + long long m_docTypeReadVersion; + + long long Parse(IMkvReader*, long long&); + void Init(); +}; + +class Segment; +class Track; +class Cluster; + +class Block { + Block(const Block&); + Block& operator=(const Block&); + + public: + const long long m_start; + const long long m_size; + + Block(long long start, long long size, long long discard_padding); + ~Block(); + + long Parse(const Cluster*); + + long long GetTrackNumber() const; + long long GetTimeCode(const Cluster*) const; // absolute, but not scaled + long long GetTime(const Cluster*) const; // absolute, and scaled (ns) + bool IsKey() const; + void SetKey(bool); + bool IsInvisible() const; + + enum Lacing { kLacingNone, kLacingXiph, kLacingFixed, kLacingEbml }; + Lacing GetLacing() const; + + int GetFrameCount() const; // to index frames: [0, count) + + struct Frame { + long long pos; // absolute offset + long len; + + long Read(IMkvReader*, unsigned char*) const; + }; + + const Frame& GetFrame(int frame_index) const; + + long long GetDiscardPadding() const; + + private: + long long m_track; // Track::Number() + short m_timecode; // relative to cluster + unsigned char m_flags; + + Frame* m_frames; + int m_frame_count; + + protected: + const long long m_discard_padding; +}; + +class BlockEntry { + BlockEntry(const BlockEntry&); + BlockEntry& operator=(const BlockEntry&); + + protected: + BlockEntry(Cluster*, long index); + + public: + virtual ~BlockEntry(); + + bool EOS() const { return (GetKind() == kBlockEOS); } + const Cluster* GetCluster() const; + long GetIndex() const; + virtual const Block* GetBlock() const = 0; + + enum Kind { kBlockEOS, kBlockSimple, kBlockGroup }; + virtual Kind GetKind() const = 0; + + protected: + Cluster* const m_pCluster; + const long m_index; +}; + +class SimpleBlock : public BlockEntry { + SimpleBlock(const SimpleBlock&); + SimpleBlock& operator=(const SimpleBlock&); + + public: + SimpleBlock(Cluster*, long index, long long start, long long size); + long Parse(); + + Kind GetKind() const; + const Block* GetBlock() const; + + protected: + Block m_block; +}; + +class BlockGroup : public BlockEntry { + BlockGroup(const BlockGroup&); + BlockGroup& operator=(const BlockGroup&); + + public: + BlockGroup(Cluster*, long index, + long long block_start, // absolute pos of block's payload + long long block_size, // size of block's payload + long long prev, long long next, long long duration, + long long discard_padding); + + long Parse(); + + Kind GetKind() const; + const Block* GetBlock() const; + + long long GetPrevTimeCode() const; // relative to block's time + long long GetNextTimeCode() const; // as above + long long GetDurationTimeCode() const; + + private: + Block m_block; + const long long m_prev; + const long long m_next; + const long long m_duration; +}; + +/////////////////////////////////////////////////////////////// +// ContentEncoding element +// Elements used to describe if the track data has been encrypted or +// compressed with zlib or header stripping. +class ContentEncoding { + public: + enum { kCTR = 1 }; + + ContentEncoding(); + ~ContentEncoding(); + + // ContentCompression element names + struct ContentCompression { + ContentCompression(); + ~ContentCompression(); + + unsigned long long algo; + unsigned char* settings; + long long settings_len; + }; + + // ContentEncAESSettings element names + struct ContentEncAESSettings { + ContentEncAESSettings() : cipher_mode(kCTR) {} + ~ContentEncAESSettings() {} + + unsigned long long cipher_mode; + }; + + // ContentEncryption element names + struct ContentEncryption { + ContentEncryption(); + ~ContentEncryption(); + + unsigned long long algo; + unsigned char* key_id; + long long key_id_len; + unsigned char* signature; + long long signature_len; + unsigned char* sig_key_id; + long long sig_key_id_len; + unsigned long long sig_algo; + unsigned long long sig_hash_algo; + + ContentEncAESSettings aes_settings; + }; + + // Returns ContentCompression represented by |idx|. Returns NULL if |idx| + // is out of bounds. + const ContentCompression* GetCompressionByIndex(unsigned long idx) const; + + // Returns number of ContentCompression elements in this ContentEncoding + // element. + unsigned long GetCompressionCount() const; + + // Parses the ContentCompression element from |pReader|. |start| is the + // starting offset of the ContentCompression payload. |size| is the size in + // bytes of the ContentCompression payload. |compression| is where the parsed + // values will be stored. + long ParseCompressionEntry(long long start, long long size, + IMkvReader* pReader, + ContentCompression* compression); + + // Returns ContentEncryption represented by |idx|. Returns NULL if |idx| + // is out of bounds. + const ContentEncryption* GetEncryptionByIndex(unsigned long idx) const; + + // Returns number of ContentEncryption elements in this ContentEncoding + // element. + unsigned long GetEncryptionCount() const; + + // Parses the ContentEncAESSettings element from |pReader|. |start| is the + // starting offset of the ContentEncAESSettings payload. |size| is the + // size in bytes of the ContentEncAESSettings payload. |encryption| is + // where the parsed values will be stored. + long ParseContentEncAESSettingsEntry(long long start, long long size, + IMkvReader* pReader, + ContentEncAESSettings* aes); + + // Parses the ContentEncoding element from |pReader|. |start| is the + // starting offset of the ContentEncoding payload. |size| is the size in + // bytes of the ContentEncoding payload. Returns true on success. + long ParseContentEncodingEntry(long long start, long long size, + IMkvReader* pReader); + + // Parses the ContentEncryption element from |pReader|. |start| is the + // starting offset of the ContentEncryption payload. |size| is the size in + // bytes of the ContentEncryption payload. |encryption| is where the parsed + // values will be stored. + long ParseEncryptionEntry(long long start, long long size, + IMkvReader* pReader, ContentEncryption* encryption); + + unsigned long long encoding_order() const { return encoding_order_; } + unsigned long long encoding_scope() const { return encoding_scope_; } + unsigned long long encoding_type() const { return encoding_type_; } + + private: + // Member variables for list of ContentCompression elements. + ContentCompression** compression_entries_; + ContentCompression** compression_entries_end_; + + // Member variables for list of ContentEncryption elements. + ContentEncryption** encryption_entries_; + ContentEncryption** encryption_entries_end_; + + // ContentEncoding element names + unsigned long long encoding_order_; + unsigned long long encoding_scope_; + unsigned long long encoding_type_; + + // LIBWEBM_DISALLOW_COPY_AND_ASSIGN(ContentEncoding); + ContentEncoding(const ContentEncoding&); + ContentEncoding& operator=(const ContentEncoding&); +}; + +class Track { + Track(const Track&); + Track& operator=(const Track&); + + public: + class Info; + static long Create(Segment*, const Info&, long long element_start, + long long element_size, Track*&); + + enum Type { kVideo = 1, kAudio = 2, kSubtitle = 0x11, kMetadata = 0x21 }; + + Segment* const m_pSegment; + const long long m_element_start; + const long long m_element_size; + virtual ~Track(); + + long GetType() const; + long GetNumber() const; + unsigned long long GetUid() const; + const char* GetNameAsUTF8() const; + const char* GetLanguage() const; + const char* GetCodecNameAsUTF8() const; + const char* GetCodecId() const; + const unsigned char* GetCodecPrivate(size_t&) const; + bool GetLacing() const; + unsigned long long GetDefaultDuration() const; + unsigned long long GetCodecDelay() const; + unsigned long long GetSeekPreRoll() const; + + const BlockEntry* GetEOS() const; + + struct Settings { + long long start; + long long size; + }; + + class Info { + public: + Info(); + ~Info(); + int Copy(Info&) const; + void Clear(); + long type; + long number; + unsigned long long uid; + unsigned long long defaultDuration; + unsigned long long codecDelay; + unsigned long long seekPreRoll; + char* nameAsUTF8; + char* language; + char* codecId; + char* codecNameAsUTF8; + unsigned char* codecPrivate; + size_t codecPrivateSize; + bool lacing; + Settings settings; + + private: + Info(const Info&); + Info& operator=(const Info&); + int CopyStr(char* Info::*str, Info&) const; + }; + + long GetFirst(const BlockEntry*&) const; + long GetNext(const BlockEntry* pCurr, const BlockEntry*& pNext) const; + virtual bool VetEntry(const BlockEntry*) const; + virtual long Seek(long long time_ns, const BlockEntry*&) const; + + const ContentEncoding* GetContentEncodingByIndex(unsigned long idx) const; + unsigned long GetContentEncodingCount() const; + + long ParseContentEncodingsEntry(long long start, long long size); + + protected: + Track(Segment*, long long element_start, long long element_size); + + Info m_info; + + class EOSBlock : public BlockEntry { + public: + EOSBlock(); + + Kind GetKind() const; + const Block* GetBlock() const; + }; + + EOSBlock m_eos; + + private: + ContentEncoding** content_encoding_entries_; + ContentEncoding** content_encoding_entries_end_; +}; + +struct PrimaryChromaticity { + PrimaryChromaticity() : x(0), y(0) {} + ~PrimaryChromaticity() {} + static bool Parse(IMkvReader* reader, long long read_pos, + long long value_size, bool is_x, + PrimaryChromaticity** chromaticity); + float x; + float y; +}; + +struct MasteringMetadata { + static const float kValueNotPresent; + + MasteringMetadata() + : r(NULL), + g(NULL), + b(NULL), + white_point(NULL), + luminance_max(kValueNotPresent), + luminance_min(kValueNotPresent) {} + ~MasteringMetadata() { + delete r; + delete g; + delete b; + delete white_point; + } + + static bool Parse(IMkvReader* reader, long long element_start, + long long element_size, + MasteringMetadata** mastering_metadata); + + PrimaryChromaticity* r; + PrimaryChromaticity* g; + PrimaryChromaticity* b; + PrimaryChromaticity* white_point; + float luminance_max; + float luminance_min; +}; + +struct Colour { + static const long long kValueNotPresent; + + // Unless otherwise noted all values assigned upon construction are the + // equivalent of unspecified/default. + Colour() + : matrix_coefficients(kValueNotPresent), + bits_per_channel(kValueNotPresent), + chroma_subsampling_horz(kValueNotPresent), + chroma_subsampling_vert(kValueNotPresent), + cb_subsampling_horz(kValueNotPresent), + cb_subsampling_vert(kValueNotPresent), + chroma_siting_horz(kValueNotPresent), + chroma_siting_vert(kValueNotPresent), + range(kValueNotPresent), + transfer_characteristics(kValueNotPresent), + primaries(kValueNotPresent), + max_cll(kValueNotPresent), + max_fall(kValueNotPresent), + mastering_metadata(NULL) {} + ~Colour() { + delete mastering_metadata; + mastering_metadata = NULL; + } + + static bool Parse(IMkvReader* reader, long long element_start, + long long element_size, Colour** colour); + + long long matrix_coefficients; + long long bits_per_channel; + long long chroma_subsampling_horz; + long long chroma_subsampling_vert; + long long cb_subsampling_horz; + long long cb_subsampling_vert; + long long chroma_siting_horz; + long long chroma_siting_vert; + long long range; + long long transfer_characteristics; + long long primaries; + long long max_cll; + long long max_fall; + + MasteringMetadata* mastering_metadata; +}; + +struct Projection { + enum ProjectionType { + kTypeNotPresent = -1, + kRectangular = 0, + kEquirectangular = 1, + kCubeMap = 2, + kMesh = 3, + }; + static const float kValueNotPresent; + Projection() + : type(kTypeNotPresent), + private_data(NULL), + private_data_length(0), + pose_yaw(kValueNotPresent), + pose_pitch(kValueNotPresent), + pose_roll(kValueNotPresent) {} + ~Projection() { delete[] private_data; } + static bool Parse(IMkvReader* reader, long long element_start, + long long element_size, Projection** projection); + + ProjectionType type; + unsigned char* private_data; + size_t private_data_length; + float pose_yaw; + float pose_pitch; + float pose_roll; +}; + +class VideoTrack : public Track { + VideoTrack(const VideoTrack&); + VideoTrack& operator=(const VideoTrack&); + + VideoTrack(Segment*, long long element_start, long long element_size); + + public: + virtual ~VideoTrack(); + static long Parse(Segment*, const Info&, long long element_start, + long long element_size, VideoTrack*&); + + long long GetWidth() const; + long long GetHeight() const; + long long GetDisplayWidth() const; + long long GetDisplayHeight() const; + long long GetDisplayUnit() const; + long long GetStereoMode() const; + double GetFrameRate() const; + + bool VetEntry(const BlockEntry*) const; + long Seek(long long time_ns, const BlockEntry*&) const; + + Colour* GetColour() const; + + Projection* GetProjection() const; + + const char* GetColourSpace() const { return m_colour_space; } + + private: + long long m_width; + long long m_height; + long long m_display_width; + long long m_display_height; + long long m_display_unit; + long long m_stereo_mode; + char* m_colour_space; + double m_rate; + + Colour* m_colour; + Projection* m_projection; +}; + +class AudioTrack : public Track { + AudioTrack(const AudioTrack&); + AudioTrack& operator=(const AudioTrack&); + + AudioTrack(Segment*, long long element_start, long long element_size); + + public: + static long Parse(Segment*, const Info&, long long element_start, + long long element_size, AudioTrack*&); + + double GetSamplingRate() const; + long long GetChannels() const; + long long GetBitDepth() const; + + private: + double m_rate; + long long m_channels; + long long m_bitDepth; +}; + +class Tracks { + Tracks(const Tracks&); + Tracks& operator=(const Tracks&); + + public: + Segment* const m_pSegment; + const long long m_start; + const long long m_size; + const long long m_element_start; + const long long m_element_size; + + Tracks(Segment*, long long start, long long size, long long element_start, + long long element_size); + + ~Tracks(); + + long Parse(); + + unsigned long GetTracksCount() const; + + const Track* GetTrackByNumber(long tn) const; + const Track* GetTrackByIndex(unsigned long idx) const; + + private: + Track** m_trackEntries; + Track** m_trackEntriesEnd; + + long ParseTrackEntry(long long payload_start, long long payload_size, + long long element_start, long long element_size, + Track*&) const; +}; + +class Chapters { + Chapters(const Chapters&); + Chapters& operator=(const Chapters&); + + public: + Segment* const m_pSegment; + const long long m_start; + const long long m_size; + const long long m_element_start; + const long long m_element_size; + + Chapters(Segment*, long long payload_start, long long payload_size, + long long element_start, long long element_size); + + ~Chapters(); + + long Parse(); + + class Atom; + class Edition; + + class Display { + friend class Atom; + Display(); + Display(const Display&); + ~Display(); + Display& operator=(const Display&); + + public: + const char* GetString() const; + const char* GetLanguage() const; + const char* GetCountry() const; + + private: + void Init(); + void ShallowCopy(Display&) const; + void Clear(); + long Parse(IMkvReader*, long long pos, long long size); + + char* m_string; + char* m_language; + char* m_country; + }; + + class Atom { + friend class Edition; + Atom(); + Atom(const Atom&); + ~Atom(); + Atom& operator=(const Atom&); + + public: + unsigned long long GetUID() const; + const char* GetStringUID() const; + + long long GetStartTimecode() const; + long long GetStopTimecode() const; + + long long GetStartTime(const Chapters*) const; + long long GetStopTime(const Chapters*) const; + + int GetDisplayCount() const; + const Display* GetDisplay(int index) const; + + private: + void Init(); + void ShallowCopy(Atom&) const; + void Clear(); + long Parse(IMkvReader*, long long pos, long long size); + static long long GetTime(const Chapters*, long long timecode); + + long ParseDisplay(IMkvReader*, long long pos, long long size); + bool ExpandDisplaysArray(); + + char* m_string_uid; + unsigned long long m_uid; + long long m_start_timecode; + long long m_stop_timecode; + + Display* m_displays; + int m_displays_size; + int m_displays_count; + }; + + class Edition { + friend class Chapters; + Edition(); + Edition(const Edition&); + ~Edition(); + Edition& operator=(const Edition&); + + public: + int GetAtomCount() const; + const Atom* GetAtom(int index) const; + + private: + void Init(); + void ShallowCopy(Edition&) const; + void Clear(); + long Parse(IMkvReader*, long long pos, long long size); + + long ParseAtom(IMkvReader*, long long pos, long long size); + bool ExpandAtomsArray(); + + Atom* m_atoms; + int m_atoms_size; + int m_atoms_count; + }; + + int GetEditionCount() const; + const Edition* GetEdition(int index) const; + + private: + long ParseEdition(long long pos, long long size); + bool ExpandEditionsArray(); + + Edition* m_editions; + int m_editions_size; + int m_editions_count; +}; + +class Tags { + Tags(const Tags&); + Tags& operator=(const Tags&); + + public: + Segment* const m_pSegment; + const long long m_start; + const long long m_size; + const long long m_element_start; + const long long m_element_size; + + Tags(Segment*, long long payload_start, long long payload_size, + long long element_start, long long element_size); + + ~Tags(); + + long Parse(); + + class Tag; + class SimpleTag; + + class SimpleTag { + friend class Tag; + SimpleTag(); + SimpleTag(const SimpleTag&); + ~SimpleTag(); + SimpleTag& operator=(const SimpleTag&); + + public: + const char* GetTagName() const; + const char* GetTagString() const; + + private: + void Init(); + void ShallowCopy(SimpleTag&) const; + void Clear(); + long Parse(IMkvReader*, long long pos, long long size); + + char* m_tag_name; + char* m_tag_string; + }; + + class Tag { + friend class Tags; + Tag(); + Tag(const Tag&); + ~Tag(); + Tag& operator=(const Tag&); + + public: + int GetSimpleTagCount() const; + const SimpleTag* GetSimpleTag(int index) const; + + private: + void Init(); + void ShallowCopy(Tag&) const; + void Clear(); + long Parse(IMkvReader*, long long pos, long long size); + + long ParseSimpleTag(IMkvReader*, long long pos, long long size); + bool ExpandSimpleTagsArray(); + + SimpleTag* m_simple_tags; + int m_simple_tags_size; + int m_simple_tags_count; + }; + + int GetTagCount() const; + const Tag* GetTag(int index) const; + + private: + long ParseTag(long long pos, long long size); + bool ExpandTagsArray(); + + Tag* m_tags; + int m_tags_size; + int m_tags_count; +}; + +class SegmentInfo { + SegmentInfo(const SegmentInfo&); + SegmentInfo& operator=(const SegmentInfo&); + + public: + Segment* const m_pSegment; + const long long m_start; + const long long m_size; + const long long m_element_start; + const long long m_element_size; + + SegmentInfo(Segment*, long long start, long long size, + long long element_start, long long element_size); + + ~SegmentInfo(); + + long Parse(); + + long long GetTimeCodeScale() const; + long long GetDuration() const; // scaled + const char* GetMuxingAppAsUTF8() const; + const char* GetWritingAppAsUTF8() const; + const char* GetTitleAsUTF8() const; + + private: + long long m_timecodeScale; + double m_duration; + char* m_pMuxingAppAsUTF8; + char* m_pWritingAppAsUTF8; + char* m_pTitleAsUTF8; +}; + +class SeekHead { + SeekHead(const SeekHead&); + SeekHead& operator=(const SeekHead&); + + public: + Segment* const m_pSegment; + const long long m_start; + const long long m_size; + const long long m_element_start; + const long long m_element_size; + + SeekHead(Segment*, long long start, long long size, long long element_start, + long long element_size); + + ~SeekHead(); + + long Parse(); + + struct Entry { + Entry(); + + // the SeekHead entry payload + long long id; + long long pos; + + // absolute pos of SeekEntry ID + long long element_start; + + // SeekEntry ID size + size size + payload + long long element_size; + }; + + int GetCount() const; + const Entry* GetEntry(int idx) const; + + struct VoidElement { + // absolute pos of Void ID + long long element_start; + + // ID size + size size + payload size + long long element_size; + }; + + int GetVoidElementCount() const; + const VoidElement* GetVoidElement(int idx) const; + + private: + Entry* m_entries; + int m_entry_count; + + VoidElement* m_void_elements; + int m_void_element_count; + + static bool ParseEntry(IMkvReader*, + long long pos, // payload + long long size, Entry*); +}; + +class Cues; +class CuePoint { + friend class Cues; + + CuePoint(long, long long); + ~CuePoint(); + + CuePoint(const CuePoint&); + CuePoint& operator=(const CuePoint&); + + public: + long long m_element_start; + long long m_element_size; + + bool Load(IMkvReader*); + + long long GetTimeCode() const; // absolute but unscaled + long long GetTime(const Segment*) const; // absolute and scaled (ns units) + + struct TrackPosition { + long long m_track; + long long m_pos; // of cluster + long long m_block; + // codec_state //defaults to 0 + // reference = clusters containing req'd referenced blocks + // reftime = timecode of the referenced block + + bool Parse(IMkvReader*, long long, long long); + }; + + const TrackPosition* Find(const Track*) const; + + private: + const long m_index; + long long m_timecode; + TrackPosition* m_track_positions; + size_t m_track_positions_count; +}; + +class Cues { + friend class Segment; + + Cues(Segment*, long long start, long long size, long long element_start, + long long element_size); + ~Cues(); + + Cues(const Cues&); + Cues& operator=(const Cues&); + + public: + Segment* const m_pSegment; + const long long m_start; + const long long m_size; + const long long m_element_start; + const long long m_element_size; + + bool Find( // lower bound of time_ns + long long time_ns, const Track*, const CuePoint*&, + const CuePoint::TrackPosition*&) const; + + const CuePoint* GetFirst() const; + const CuePoint* GetLast() const; + const CuePoint* GetNext(const CuePoint*) const; + + const BlockEntry* GetBlock(const CuePoint*, + const CuePoint::TrackPosition*) const; + + bool LoadCuePoint() const; + long GetCount() const; // loaded only + // long GetTotal() const; //loaded + preloaded + bool DoneParsing() const; + + private: + bool Init() const; + bool PreloadCuePoint(long&, long long) const; + + mutable CuePoint** m_cue_points; + mutable long m_count; + mutable long m_preload_count; + mutable long long m_pos; +}; + +class Cluster { + friend class Segment; + + Cluster(const Cluster&); + Cluster& operator=(const Cluster&); + + public: + Segment* const m_pSegment; + + public: + static Cluster* Create(Segment*, + long index, // index in segment + long long off); // offset relative to segment + // long long element_size); + + Cluster(); // EndOfStream + ~Cluster(); + + bool EOS() const; + + long long GetTimeCode() const; // absolute, but not scaled + long long GetTime() const; // absolute, and scaled (nanosecond units) + long long GetFirstTime() const; // time (ns) of first (earliest) block + long long GetLastTime() const; // time (ns) of last (latest) block + + long GetFirst(const BlockEntry*&) const; + long GetLast(const BlockEntry*&) const; + long GetNext(const BlockEntry* curr, const BlockEntry*& next) const; + + const BlockEntry* GetEntry(const Track*, long long ns = -1) const; + const BlockEntry* GetEntry(const CuePoint&, + const CuePoint::TrackPosition&) const; + // const BlockEntry* GetMaxKey(const VideoTrack*) const; + + // static bool HasBlockEntries(const Segment*, long long); + + static long HasBlockEntries(const Segment*, long long idoff, long long& pos, + long& size); + + long GetEntryCount() const; + + long Load(long long& pos, long& size) const; + + long Parse(long long& pos, long& size) const; + long GetEntry(long index, const mkvparser::BlockEntry*&) const; + + protected: + Cluster(Segment*, long index, long long element_start); + // long long element_size); + + public: + const long long m_element_start; + long long GetPosition() const; // offset relative to segment + + long GetIndex() const; + long long GetElementSize() const; + // long long GetPayloadSize() const; + + // long long Unparsed() const; + + private: + long m_index; + mutable long long m_pos; + // mutable long long m_size; + mutable long long m_element_size; + mutable long long m_timecode; + mutable BlockEntry** m_entries; + mutable long m_entries_size; + mutable long m_entries_count; + + long ParseSimpleBlock(long long, long long&, long&); + long ParseBlockGroup(long long, long long&, long&); + + long CreateBlock(long long id, long long pos, long long size, + long long discard_padding); + long CreateBlockGroup(long long start_offset, long long size, + long long discard_padding); + long CreateSimpleBlock(long long, long long); +}; + +class Segment { + friend class Cues; + friend class Track; + friend class VideoTrack; + + Segment(const Segment&); + Segment& operator=(const Segment&); + + private: + Segment(IMkvReader*, long long elem_start, + // long long elem_size, + long long pos, long long size); + + public: + IMkvReader* const m_pReader; + const long long m_element_start; + // const long long m_element_size; + const long long m_start; // posn of segment payload + const long long m_size; // size of segment payload + Cluster m_eos; // TODO: make private? + + static long long CreateInstance(IMkvReader*, long long, Segment*&); + ~Segment(); + + long Load(); // loads headers and all clusters + + // for incremental loading + // long long Unparsed() const; + bool DoneParsing() const; + long long ParseHeaders(); // stops when first cluster is found + // long FindNextCluster(long long& pos, long& size) const; + long LoadCluster(long long& pos, long& size); // load one cluster + long LoadCluster(); + + long ParseNext(const Cluster* pCurr, const Cluster*& pNext, long long& pos, + long& size); + + const SeekHead* GetSeekHead() const; + const Tracks* GetTracks() const; + const SegmentInfo* GetInfo() const; + const Cues* GetCues() const; + const Chapters* GetChapters() const; + const Tags* GetTags() const; + + long long GetDuration() const; + + unsigned long GetCount() const; + const Cluster* GetFirst() const; + const Cluster* GetLast() const; + const Cluster* GetNext(const Cluster*); + + const Cluster* FindCluster(long long time_nanoseconds) const; + // const BlockEntry* Seek(long long time_nanoseconds, const Track*) const; + + const Cluster* FindOrPreloadCluster(long long pos); + + long ParseCues(long long cues_off, // offset relative to start of segment + long long& parse_pos, long& parse_len); + + private: + long long m_pos; // absolute file posn; what has been consumed so far + Cluster* m_pUnknownSize; + + SeekHead* m_pSeekHead; + SegmentInfo* m_pInfo; + Tracks* m_pTracks; + Cues* m_pCues; + Chapters* m_pChapters; + Tags* m_pTags; + Cluster** m_clusters; + long m_clusterCount; // number of entries for which m_index >= 0 + long m_clusterPreloadCount; // number of entries for which m_index < 0 + long m_clusterSize; // array size + + long DoLoadCluster(long long&, long&); + long DoLoadClusterUnknownSize(long long&, long&); + long DoParseNext(const Cluster*&, long long&, long&); + + bool AppendCluster(Cluster*); + bool PreloadCluster(Cluster*, ptrdiff_t); + + // void ParseSeekHead(long long pos, long long size); + // void ParseSeekEntry(long long pos, long long size); + // void ParseCues(long long); + + const BlockEntry* GetBlock(const CuePoint&, const CuePoint::TrackPosition&); +}; + +} // namespace mkvparser + +inline long mkvparser::Segment::LoadCluster() { + long long pos; + long size; + + return LoadCluster(pos, size); +} + +#endif // MKVPARSER_MKVPARSER_H_ diff --git a/third_party/libwebm/source/mkvparser/mkvreader.cc b/third_party/libwebm/source/mkvparser/mkvreader.cc new file mode 100644 index 000000000000..9d19c1be569a --- /dev/null +++ b/third_party/libwebm/source/mkvparser/mkvreader.cc @@ -0,0 +1,135 @@ +// Copyright (c) 2010 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +#include "mkvparser/mkvreader.h" + +#include + +#include + +namespace mkvparser { + +MkvReader::MkvReader() : m_file(NULL), reader_owns_file_(true) {} + +MkvReader::MkvReader(FILE* fp) : m_file(fp), reader_owns_file_(false) { + GetFileSize(); +} + +MkvReader::~MkvReader() { + if (reader_owns_file_) + Close(); + m_file = NULL; +} + +int MkvReader::Open(const char* fileName) { + if (fileName == NULL) + return -1; + + if (m_file) + return -1; + +#ifdef _MSC_VER + const errno_t e = fopen_s(&m_file, fileName, "rb"); + + if (e) + return -1; // error +#else + m_file = fopen(fileName, "rb"); + + if (m_file == NULL) + return -1; +#endif + return !GetFileSize(); +} + +bool MkvReader::GetFileSize() { + if (m_file == NULL) + return false; +#ifdef _MSC_VER + int status = _fseeki64(m_file, 0L, SEEK_END); + + if (status) + return false; // error + + m_length = _ftelli64(m_file); +#else + fseek(m_file, 0L, SEEK_END); + m_length = ftell(m_file); +#endif + assert(m_length >= 0); + + if (m_length < 0) + return false; + +#ifdef _MSC_VER + status = _fseeki64(m_file, 0L, SEEK_SET); + + if (status) + return false; // error +#else + fseek(m_file, 0L, SEEK_SET); +#endif + + return true; +} + +void MkvReader::Close() { + if (m_file != NULL) { + fclose(m_file); + m_file = NULL; + } +} + +int MkvReader::Length(long long* total, long long* available) { + if (m_file == NULL) + return -1; + + if (total) + *total = m_length; + + if (available) + *available = m_length; + + return 0; +} + +int MkvReader::Read(long long offset, long len, unsigned char* buffer) { + if (m_file == NULL) + return -1; + + if (offset < 0) + return -1; + + if (len < 0) + return -1; + + if (len == 0) + return 0; + + if (offset >= m_length) + return -1; + +#ifdef _MSC_VER + const int status = _fseeki64(m_file, offset, SEEK_SET); + + if (status) + return -1; // error +#elif defined(_WIN32) + fseeko64(m_file, static_cast(offset), SEEK_SET); +#else + fseeko(m_file, static_cast(offset), SEEK_SET); +#endif + + const size_t size = fread(buffer, 1, len, m_file); + + if (size < size_t(len)) + return -1; // error + + return 0; // success +} + +} // namespace mkvparser diff --git a/third_party/libwebm/source/mkvparser/mkvreader.h b/third_party/libwebm/source/mkvparser/mkvreader.h new file mode 100644 index 000000000000..9831ecf64586 --- /dev/null +++ b/third_party/libwebm/source/mkvparser/mkvreader.h @@ -0,0 +1,45 @@ +// Copyright (c) 2010 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +#ifndef MKVPARSER_MKVREADER_H_ +#define MKVPARSER_MKVREADER_H_ + +#include + +#include "mkvparser/mkvparser.h" + +namespace mkvparser { + +class MkvReader : public IMkvReader { + public: + MkvReader(); + explicit MkvReader(FILE* fp); + virtual ~MkvReader(); + + int Open(const char*); + void Close(); + + virtual int Read(long long position, long length, unsigned char* buffer); + virtual int Length(long long* total, long long* available); + + private: + MkvReader(const MkvReader&); + MkvReader& operator=(const MkvReader&); + + // Determines the size of the file. This is called either by the constructor + // or by the Open function depending on file ownership. Returns true on + // success. + bool GetFileSize(); + + long long m_length; + FILE* m_file; + bool reader_owns_file_; +}; + +} // namespace mkvparser + +#endif // MKVPARSER_MKVREADER_H_ diff --git a/third_party/libwebm/source/mkvparser_sample.cc b/third_party/libwebm/source/mkvparser_sample.cc new file mode 100644 index 000000000000..f285c3e50a75 --- /dev/null +++ b/third_party/libwebm/source/mkvparser_sample.cc @@ -0,0 +1,459 @@ +// Copyright (c) 2010 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// +// This sample application demonstrates how to use the Matroska parser +// library, which allows clients to handle a Matroska format file. +#include +#include +#include +#include + +#include "mkvparser/mkvparser.h" +#include "mkvparser/mkvreader.h" + +namespace { +const wchar_t* utf8towcs(const char* str) { + if (str == NULL) + return NULL; + + // TODO: this probably requires that the locale be + // configured somehow: + + const size_t size = mbstowcs(NULL, str, 0); + + if (size == 0 || size == static_cast(-1)) + return NULL; + + wchar_t* const val = new (std::nothrow) wchar_t[size + 1]; + if (val == NULL) + return NULL; + + mbstowcs(val, str, size); + val[size] = L'\0'; + + return val; +} + +bool InputHasCues(const mkvparser::Segment* const segment) { + const mkvparser::Cues* const cues = segment->GetCues(); + if (cues == NULL) + return false; + + while (!cues->DoneParsing()) + cues->LoadCuePoint(); + + const mkvparser::CuePoint* const cue_point = cues->GetFirst(); + if (cue_point == NULL) + return false; + + return true; +} + +bool MasteringMetadataValuePresent(double value) { + return value != mkvparser::MasteringMetadata::kValueNotPresent; +} + +bool ColourValuePresent(long long value) { + return value != mkvparser::Colour::kValueNotPresent; +} +} // namespace + +int main(int argc, char* argv[]) { + if (argc == 1) { + printf("Mkv Parser Sample Application\n"); + printf(" Usage: %s \n", argv[0]); + return EXIT_FAILURE; + } + + mkvparser::MkvReader reader; + + if (reader.Open(argv[1])) { + printf("\n Filename is invalid or error while opening.\n"); + return EXIT_FAILURE; + } + + int maj, min, build, rev; + + mkvparser::GetVersion(maj, min, build, rev); + printf("\t\t libwebm version: %d.%d.%d.%d\n", maj, min, build, rev); + + long long pos = 0; + + mkvparser::EBMLHeader ebmlHeader; + + long long ret = ebmlHeader.Parse(&reader, pos); + if (ret < 0) { + printf("\n EBMLHeader::Parse() failed."); + return EXIT_FAILURE; + } + + printf("\t\t\t EBML Header\n"); + printf("\t\tEBML Version\t\t: %lld\n", ebmlHeader.m_version); + printf("\t\tEBML MaxIDLength\t: %lld\n", ebmlHeader.m_maxIdLength); + printf("\t\tEBML MaxSizeLength\t: %lld\n", ebmlHeader.m_maxSizeLength); + printf("\t\tDoc Type\t\t: %s\n", ebmlHeader.m_docType); + printf("\t\tPos\t\t\t: %lld\n", pos); + + typedef mkvparser::Segment seg_t; + seg_t* pSegment_; + + ret = seg_t::CreateInstance(&reader, pos, pSegment_); + if (ret) { + printf("\n Segment::CreateInstance() failed."); + return EXIT_FAILURE; + } + + const std::unique_ptr pSegment(pSegment_); + + ret = pSegment->Load(); + if (ret < 0) { + printf("\n Segment::Load() failed."); + return EXIT_FAILURE; + } + + const mkvparser::SegmentInfo* const pSegmentInfo = pSegment->GetInfo(); + if (pSegmentInfo == NULL) { + printf("\n Segment::GetInfo() failed."); + return EXIT_FAILURE; + } + + const long long timeCodeScale = pSegmentInfo->GetTimeCodeScale(); + const long long duration_ns = pSegmentInfo->GetDuration(); + + const char* const pTitle_ = pSegmentInfo->GetTitleAsUTF8(); + const wchar_t* const pTitle = utf8towcs(pTitle_); + + const char* const pMuxingApp_ = pSegmentInfo->GetMuxingAppAsUTF8(); + const wchar_t* const pMuxingApp = utf8towcs(pMuxingApp_); + + const char* const pWritingApp_ = pSegmentInfo->GetWritingAppAsUTF8(); + const wchar_t* const pWritingApp = utf8towcs(pWritingApp_); + + printf("\n"); + printf("\t\t\t Segment Info\n"); + printf("\t\tTimeCodeScale\t\t: %lld \n", timeCodeScale); + printf("\t\tDuration\t\t: %lld\n", duration_ns); + + const double duration_sec = double(duration_ns) / 1000000000; + printf("\t\tDuration(secs)\t\t: %7.3lf\n", duration_sec); + + if (pTitle == NULL) + printf("\t\tTrack Name\t\t: NULL\n"); + else { + printf("\t\tTrack Name\t\t: %ls\n", pTitle); + delete[] pTitle; + } + + if (pMuxingApp == NULL) + printf("\t\tMuxing App\t\t: NULL\n"); + else { + printf("\t\tMuxing App\t\t: %ls\n", pMuxingApp); + delete[] pMuxingApp; + } + + if (pWritingApp == NULL) + printf("\t\tWriting App\t\t: NULL\n"); + else { + printf("\t\tWriting App\t\t: %ls\n", pWritingApp); + delete[] pWritingApp; + } + + // pos of segment payload + printf("\t\tPosition(Segment)\t: %lld\n", pSegment->m_start); + + // size of segment payload + printf("\t\tSize(Segment)\t\t: %lld\n", pSegment->m_size); + + const mkvparser::Tracks* pTracks = pSegment->GetTracks(); + + unsigned long track_num = 0; + const unsigned long num_tracks = pTracks->GetTracksCount(); + + printf("\n\t\t\t Track Info\n"); + + while (track_num != num_tracks) { + const mkvparser::Track* const pTrack = + pTracks->GetTrackByIndex(track_num++); + + if (pTrack == NULL) + continue; + + const long trackType = pTrack->GetType(); + const long trackNumber = pTrack->GetNumber(); + const unsigned long long trackUid = pTrack->GetUid(); + const wchar_t* const pTrackName = utf8towcs(pTrack->GetNameAsUTF8()); + + printf("\t\tTrack Type\t\t: %ld\n", trackType); + printf("\t\tTrack Number\t\t: %ld\n", trackNumber); + printf("\t\tTrack Uid\t\t: %lld\n", trackUid); + + if (pTrackName == NULL) + printf("\t\tTrack Name\t\t: NULL\n"); + else { + printf("\t\tTrack Name\t\t: %ls \n", pTrackName); + delete[] pTrackName; + } + + const char* const pCodecId = pTrack->GetCodecId(); + + if (pCodecId == NULL) + printf("\t\tCodec Id\t\t: NULL\n"); + else + printf("\t\tCodec Id\t\t: %s\n", pCodecId); + + size_t codec_private_size = 0; + if (pTrack->GetCodecPrivate(codec_private_size)) { + printf("\t\tCodec private length: %u bytes\n", + static_cast(codec_private_size)); + } + + const char* const pCodecName_ = pTrack->GetCodecNameAsUTF8(); + const wchar_t* const pCodecName = utf8towcs(pCodecName_); + + if (pCodecName == NULL) + printf("\t\tCodec Name\t\t: NULL\n"); + else { + printf("\t\tCodec Name\t\t: %ls\n", pCodecName); + delete[] pCodecName; + } + + if (trackType == mkvparser::Track::kVideo) { + const mkvparser::VideoTrack* const pVideoTrack = + static_cast(pTrack); + + const long long width = pVideoTrack->GetWidth(); + printf("\t\tVideo Width\t\t: %lld\n", width); + + const long long height = pVideoTrack->GetHeight(); + printf("\t\tVideo Height\t\t: %lld\n", height); + + const double rate = pVideoTrack->GetFrameRate(); + printf("\t\tVideo Rate\t\t: %f\n", rate); + + const mkvparser::Colour* const colour = pVideoTrack->GetColour(); + if (colour) { + printf("\t\tVideo Colour:\n"); + if (ColourValuePresent(colour->matrix_coefficients)) + printf("\t\t\tMatrixCoefficients: %lld\n", + colour->matrix_coefficients); + if (ColourValuePresent(colour->bits_per_channel)) + printf("\t\t\tBitsPerChannel: %lld\n", colour->bits_per_channel); + if (ColourValuePresent(colour->chroma_subsampling_horz)) + printf("\t\t\tChromaSubsamplingHorz: %lld\n", + colour->chroma_subsampling_horz); + if (ColourValuePresent(colour->chroma_subsampling_vert)) + printf("\t\t\tChromaSubsamplingVert: %lld\n", + colour->chroma_subsampling_vert); + if (ColourValuePresent(colour->cb_subsampling_horz)) + printf("\t\t\tCbSubsamplingHorz: %lld\n", + colour->cb_subsampling_horz); + if (ColourValuePresent(colour->cb_subsampling_vert)) + printf("\t\t\tCbSubsamplingVert: %lld\n", + colour->cb_subsampling_vert); + if (ColourValuePresent(colour->chroma_siting_horz)) + printf("\t\t\tChromaSitingHorz: %lld\n", colour->chroma_siting_horz); + if (ColourValuePresent(colour->chroma_siting_vert)) + printf("\t\t\tChromaSitingVert: %lld\n", colour->chroma_siting_vert); + if (ColourValuePresent(colour->range)) + printf("\t\t\tRange: %lld\n", colour->range); + if (ColourValuePresent(colour->transfer_characteristics)) + printf("\t\t\tTransferCharacteristics: %lld\n", + colour->transfer_characteristics); + if (ColourValuePresent(colour->primaries)) + printf("\t\t\tPrimaries: %lld\n", colour->primaries); + if (ColourValuePresent(colour->max_cll)) + printf("\t\t\tMaxCLL: %lld\n", colour->max_cll); + if (ColourValuePresent(colour->max_fall)) + printf("\t\t\tMaxFALL: %lld\n", colour->max_fall); + if (colour->mastering_metadata) { + const mkvparser::MasteringMetadata* const mm = + colour->mastering_metadata; + printf("\t\t\tMastering Metadata:\n"); + if (MasteringMetadataValuePresent(mm->luminance_max)) + printf("\t\t\t\tLuminanceMax: %f\n", mm->luminance_max); + if (MasteringMetadataValuePresent(mm->luminance_min)) + printf("\t\t\t\tLuminanceMin: %f\n", mm->luminance_min); + if (mm->r) { + printf("\t\t\t\t\tPrimaryRChromaticityX: %f\n", mm->r->x); + printf("\t\t\t\t\tPrimaryRChromaticityY: %f\n", mm->r->y); + } + if (mm->g) { + printf("\t\t\t\t\tPrimaryGChromaticityX: %f\n", mm->g->x); + printf("\t\t\t\t\tPrimaryGChromaticityY: %f\n", mm->g->y); + } + if (mm->b) { + printf("\t\t\t\t\tPrimaryBChromaticityX: %f\n", mm->b->x); + printf("\t\t\t\t\tPrimaryBChromaticityY: %f\n", mm->b->y); + } + if (mm->white_point) { + printf("\t\t\t\t\tWhitePointChromaticityX: %f\n", + mm->white_point->x); + printf("\t\t\t\t\tWhitePointChromaticityY: %f\n", + mm->white_point->y); + } + } + } + + const mkvparser::Projection* const projection = + pVideoTrack->GetProjection(); + if (projection) { + printf("\t\tVideo Projection:\n"); + if (projection->type != mkvparser::Projection::kTypeNotPresent) + printf("\t\t\tProjectionType: %d\n", + static_cast(projection->type)); + if (projection->private_data) { + printf("\t\t\tProjectionPrivate: %u bytes\n", + static_cast(projection->private_data_length)); + } + if (projection->pose_yaw != mkvparser::Projection::kValueNotPresent) + printf("\t\t\tProjectionPoseYaw: %f\n", projection->pose_yaw); + if (projection->pose_pitch != mkvparser::Projection::kValueNotPresent) + printf("\t\t\tProjectionPosePitch: %f\n", projection->pose_pitch); + if (projection->pose_roll != mkvparser::Projection::kValueNotPresent) + printf("\t\t\tProjectionPosePitch: %f\n", projection->pose_roll); + } + } + + if (trackType == mkvparser::Track::kAudio) { + const mkvparser::AudioTrack* const pAudioTrack = + static_cast(pTrack); + + const long long channels = pAudioTrack->GetChannels(); + printf("\t\tAudio Channels\t\t: %lld\n", channels); + + const long long bitDepth = pAudioTrack->GetBitDepth(); + printf("\t\tAudio BitDepth\t\t: %lld\n", bitDepth); + + const double sampleRate = pAudioTrack->GetSamplingRate(); + printf("\t\tAddio Sample Rate\t: %.3f\n", sampleRate); + + const long long codecDelay = pAudioTrack->GetCodecDelay(); + printf("\t\tAudio Codec Delay\t\t: %lld\n", codecDelay); + + const long long seekPreRoll = pAudioTrack->GetSeekPreRoll(); + printf("\t\tAudio Seek Pre Roll\t\t: %lld\n", seekPreRoll); + } + } + + printf("\n\n\t\t\t Cluster Info\n"); + const unsigned long clusterCount = pSegment->GetCount(); + + printf("\t\tCluster Count\t: %ld\n\n", clusterCount); + + if (clusterCount == 0) { + printf("\t\tSegment has no clusters.\n"); + return EXIT_FAILURE; + } + + const mkvparser::Cluster* pCluster = pSegment->GetFirst(); + + while (pCluster != NULL && !pCluster->EOS()) { + const long long timeCode = pCluster->GetTimeCode(); + printf("\t\tCluster Time Code\t: %lld\n", timeCode); + + const long long time_ns = pCluster->GetTime(); + printf("\t\tCluster Time (ns)\t: %lld\n", time_ns); + + const mkvparser::BlockEntry* pBlockEntry; + + long status = pCluster->GetFirst(pBlockEntry); + + if (status < 0) // error + { + printf("\t\tError parsing first block of cluster\n"); + fflush(stdout); + return EXIT_FAILURE; + } + + while (pBlockEntry != NULL && !pBlockEntry->EOS()) { + const mkvparser::Block* const pBlock = pBlockEntry->GetBlock(); + const long long trackNum = pBlock->GetTrackNumber(); + const unsigned long tn = static_cast(trackNum); + const mkvparser::Track* const pTrack = pTracks->GetTrackByNumber(tn); + + if (pTrack == NULL) + printf("\t\t\tBlock\t\t:UNKNOWN TRACK TYPE\n"); + else { + const long long trackType = pTrack->GetType(); + const int frameCount = pBlock->GetFrameCount(); + const long long time_ns = pBlock->GetTime(pCluster); + const long long discard_padding = pBlock->GetDiscardPadding(); + + printf("\t\t\tBlock\t\t:%s,%s,%15lld,%lld\n", + (trackType == mkvparser::Track::kVideo) ? "V" : "A", + pBlock->IsKey() ? "I" : "P", time_ns, discard_padding); + + for (int i = 0; i < frameCount; ++i) { + const mkvparser::Block::Frame& theFrame = pBlock->GetFrame(i); + const long size = theFrame.len; + const long long offset = theFrame.pos; + printf("\t\t\t %15ld,%15llx\n", size, offset); + } + } + + status = pCluster->GetNext(pBlockEntry, pBlockEntry); + + if (status < 0) { + printf("\t\t\tError parsing next block of cluster\n"); + fflush(stdout); + return EXIT_FAILURE; + } + } + + pCluster = pSegment->GetNext(pCluster); + } + + if (InputHasCues(pSegment.get())) { + // Walk them. + const mkvparser::Cues* const cues = pSegment->GetCues(); + const mkvparser::CuePoint* cue = cues->GetFirst(); + int cue_point_num = 1; + + printf("\t\tCues\n"); + do { + for (track_num = 0; track_num < num_tracks; ++track_num) { + const mkvparser::Track* const track = + pTracks->GetTrackByIndex(track_num); + const mkvparser::CuePoint::TrackPosition* const track_pos = + cue->Find(track); + + if (track_pos != NULL) { + const char track_type = + (track->GetType() == mkvparser::Track::kVideo) ? 'V' : 'A'; + printf( + "\t\t\tCue Point %4d Track %3lu(%c) Time %14lld " + "Block %4lld Pos %8llx\n", + cue_point_num, track->GetNumber(), track_type, + cue->GetTime(pSegment.get()), track_pos->m_block, + track_pos->m_pos); + } + } + + cue = cues->GetNext(cue); + ++cue_point_num; + } while (cue != NULL); + } + + const mkvparser::Tags* const tags = pSegment->GetTags(); + if (tags && tags->GetTagCount() > 0) { + printf("\t\tTags\n"); + for (int i = 0; i < tags->GetTagCount(); ++i) { + const mkvparser::Tags::Tag* const tag = tags->GetTag(i); + printf("\t\t\tTag\n"); + for (int j = 0; j < tag->GetSimpleTagCount(); j++) { + const mkvparser::Tags::SimpleTag* const simple_tag = + tag->GetSimpleTag(j); + printf("\t\t\t\tSimple Tag \"%s\" Value \"%s\"\n", + simple_tag->GetTagName(), simple_tag->GetTagString()); + } + } + } + + fflush(stdout); + return EXIT_SUCCESS; +} diff --git a/third_party/libwebm/source/mkvreader.hpp b/third_party/libwebm/source/mkvreader.hpp new file mode 100644 index 000000000000..d1158729805d --- /dev/null +++ b/third_party/libwebm/source/mkvreader.hpp @@ -0,0 +1,15 @@ +// Copyright (c) 2016 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +#ifndef LIBWEBM_MKVREADER_HPP_ +#define LIBWEBM_MKVREADER_HPP_ + +// This file is a wrapper for the file included immediately after this comment. +// New projects should not include this file: include the file included below. +#include "mkvparser/mkvreader.h" + +#endif // LIBWEBM_MKVREADER_HPP_ diff --git a/third_party/libwebm/source/mkvwriter.hpp b/third_party/libwebm/source/mkvwriter.hpp new file mode 100644 index 000000000000..9927b3e07b5b --- /dev/null +++ b/third_party/libwebm/source/mkvwriter.hpp @@ -0,0 +1,15 @@ +// Copyright (c) 2016 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +#ifndef LIBWEBM_MKVWRITER_HPP_ +#define LIBWEBM_MKVWRITER_HPP_ + +// This file is a wrapper for the file included immediately after this comment. +// New projects should not include this file: include the file included below. +#include "mkvmuxer/mkvwriter.h" + +#endif // LIBWEBM_MKVWRITER_HPP_ diff --git a/third_party/libwebm/source/sample_muxer_metadata.cc b/third_party/libwebm/source/sample_muxer_metadata.cc new file mode 100644 index 000000000000..6eadcfddc330 --- /dev/null +++ b/third_party/libwebm/source/sample_muxer_metadata.cc @@ -0,0 +1,391 @@ +// Copyright (c) 2012 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// +// This sample application demonstrates how to use the matroska parser +// library, which allows clients to handle a matroska format file. + +#include "sample_muxer_metadata.h" + +#include +#include + +#include "mkvmuxer/mkvmuxer.h" +#include "webvtt/vttreader.h" + +SampleMuxerMetadata::SampleMuxerMetadata() : segment_(NULL) {} + +bool SampleMuxerMetadata::Init(mkvmuxer::Segment* segment) { + if (segment == NULL || segment_ != NULL) + return false; + + segment_ = segment; + return true; +} + +bool SampleMuxerMetadata::Load(const char* file, Kind kind) { + if (kind == kChapters) + return LoadChapters(file); + + uint64_t track_num; + + if (!AddTrack(kind, &track_num)) { + printf("Unable to add track for WebVTT file \"%s\"\n", file); + return false; + } + + return Parse(file, kind, track_num); +} + +bool SampleMuxerMetadata::AddChapters() { + typedef cue_list_t::const_iterator iter_t; + iter_t i = chapter_cues_.begin(); + const iter_t j = chapter_cues_.end(); + + while (i != j) { + const cue_t& chapter = *i++; + + if (!AddChapter(chapter)) + return false; + } + + return true; +} + +bool SampleMuxerMetadata::Write(int64_t time_ns) { + typedef cues_set_t::iterator iter_t; + + iter_t i = cues_set_.begin(); + const iter_t j = cues_set_.end(); + + while (i != j) { + const cues_set_t::value_type& v = *i; + + if (time_ns >= 0 && v > time_ns) + return true; // nothing else to do just yet + + if (!v.Write(segment_)) { + printf("\nCould not add metadata.\n"); + return false; // error + } + + cues_set_.erase(i++); + } + + return true; +} + +bool SampleMuxerMetadata::LoadChapters(const char* file) { + if (!chapter_cues_.empty()) { + printf("Support for more than one chapters file is not yet implemented\n"); + return false; + } + + cue_list_t cues; + + if (!ParseChapters(file, &cues)) + return false; + + // TODO(matthewjheaney): support more than one chapters file + chapter_cues_.swap(cues); + + return true; +} + +bool SampleMuxerMetadata::ParseChapters(const char* file, + cue_list_t* cues_ptr) { + cue_list_t& cues = *cues_ptr; + cues.clear(); + + libwebvtt::VttReader r; + int e = r.Open(file); + + if (e) { + printf("Unable to open WebVTT file: \"%s\"\n", file); + return false; + } + + libwebvtt::Parser p(&r); + e = p.Init(); + + if (e < 0) { // error + printf("Error parsing WebVTT file: \"%s\"\n", file); + return false; + } + + libwebvtt::Time t; + t.hours = -1; + + for (;;) { + cue_t c; + e = p.Parse(&c); + + if (e < 0) { // error + printf("Error parsing WebVTT file: \"%s\"\n", file); + return false; + } + + if (e > 0) // EOF + return true; + + if (c.start_time < t) { + printf("bad WebVTT cue timestamp (out-of-order)\n"); + return false; + } + + if (c.stop_time < c.start_time) { + printf("bad WebVTT cue timestamp (stop < start)\n"); + return false; + } + + t = c.start_time; + cues.push_back(c); + } +} + +bool SampleMuxerMetadata::AddChapter(const cue_t& cue) { + // TODO(matthewjheaney): support language and country + + mkvmuxer::Chapter* const chapter = segment_->AddChapter(); + + if (chapter == NULL) { + printf("Unable to add chapter\n"); + return false; + } + + if (cue.identifier.empty()) { + chapter->set_id(NULL); + } else { + const char* const id = cue.identifier.c_str(); + if (!chapter->set_id(id)) { + printf("Unable to set chapter id\n"); + return false; + } + } + + typedef libwebvtt::presentation_t time_ms_t; + const time_ms_t start_time_ms = cue.start_time.presentation(); + const time_ms_t stop_time_ms = cue.stop_time.presentation(); + + enum { kNsPerMs = 1000000 }; + const uint64_t start_time_ns = start_time_ms * kNsPerMs; + const uint64_t stop_time_ns = stop_time_ms * kNsPerMs; + + chapter->set_time(*segment_, start_time_ns, stop_time_ns); + + typedef libwebvtt::Cue::payload_t::const_iterator iter_t; + iter_t i = cue.payload.begin(); + const iter_t j = cue.payload.end(); + + std::string title; + + for (;;) { + title += *i++; + + if (i == j) + break; + + enum { kLF = '\x0A' }; + title += kLF; + } + + if (!chapter->add_string(title.c_str(), NULL, NULL)) { + printf("Unable to set chapter title\n"); + return false; + } + + return true; +} + +bool SampleMuxerMetadata::AddTrack(Kind kind, uint64_t* track_num) { + *track_num = 0; + + // Track number value 0 means "let muxer choose track number" + mkvmuxer::Track* const track = segment_->AddTrack(0); + + if (track == NULL) // error + return false; + + // Return the track number value chosen by the muxer + *track_num = track->number(); + + int type; + const char* codec_id; + + switch (kind) { + case kSubtitles: + type = 0x11; + codec_id = "D_WEBVTT/SUBTITLES"; + break; + + case kCaptions: + type = 0x11; + codec_id = "D_WEBVTT/CAPTIONS"; + break; + + case kDescriptions: + type = 0x21; + codec_id = "D_WEBVTT/DESCRIPTIONS"; + break; + + case kMetadata: + type = 0x21; + codec_id = "D_WEBVTT/METADATA"; + break; + + default: + return false; + } + + track->set_type(type); + track->set_codec_id(codec_id); + + // TODO(matthewjheaney): set name and language + + return true; +} + +bool SampleMuxerMetadata::Parse(const char* file, Kind /* kind */, + uint64_t track_num) { + libwebvtt::VttReader r; + int e = r.Open(file); + + if (e) { + printf("Unable to open WebVTT file: \"%s\"\n", file); + return false; + } + + libwebvtt::Parser p(&r); + + e = p.Init(); + + if (e < 0) { // error + printf("Error parsing WebVTT file: \"%s\"\n", file); + return false; + } + + SortableCue cue; + cue.track_num = track_num; + + libwebvtt::Time t; + t.hours = -1; + + for (;;) { + cue_t& c = cue.cue; + e = p.Parse(&c); + + if (e < 0) { // error + printf("Error parsing WebVTT file: \"%s\"\n", file); + return false; + } + + if (e > 0) // EOF + return true; + + if (c.start_time >= t) { + t = c.start_time; + } else { + printf("bad WebVTT cue timestamp (out-of-order)\n"); + return false; + } + + if (c.stop_time < c.start_time) { + printf("bad WebVTT cue timestamp (stop < start)\n"); + return false; + } + + cues_set_.insert(cue); + } +} + +void SampleMuxerMetadata::MakeFrame(const cue_t& c, std::string* pf) { + pf->clear(); + WriteCueIdentifier(c.identifier, pf); + WriteCueSettings(c.settings, pf); + WriteCuePayload(c.payload, pf); +} + +void SampleMuxerMetadata::WriteCueIdentifier(const std::string& identifier, + std::string* pf) { + pf->append(identifier); + pf->push_back('\x0A'); // LF +} + +void SampleMuxerMetadata::WriteCueSettings(const cue_t::settings_t& settings, + std::string* pf) { + if (settings.empty()) { + pf->push_back('\x0A'); // LF + return; + } + + typedef cue_t::settings_t::const_iterator iter_t; + + iter_t i = settings.begin(); + const iter_t j = settings.end(); + + for (;;) { + const libwebvtt::Setting& setting = *i++; + + pf->append(setting.name); + pf->push_back(':'); + pf->append(setting.value); + + if (i == j) + break; + + pf->push_back(' '); // separate settings with whitespace + } + + pf->push_back('\x0A'); // LF +} + +void SampleMuxerMetadata::WriteCuePayload(const cue_t::payload_t& payload, + std::string* pf) { + typedef cue_t::payload_t::const_iterator iter_t; + + iter_t i = payload.begin(); + const iter_t j = payload.end(); + + while (i != j) { + const std::string& line = *i++; + pf->append(line); + pf->push_back('\x0A'); // LF + } +} + +bool SampleMuxerMetadata::SortableCue::Write(mkvmuxer::Segment* segment) const { + // Cue start time expressed in milliseconds + const int64_t start_ms = cue.start_time.presentation(); + + // Cue start time expressed in nanoseconds (MKV time) + const int64_t start_ns = start_ms * 1000000; + + // Cue stop time expressed in milliseconds + const int64_t stop_ms = cue.stop_time.presentation(); + + // Cue stop time expressed in nanonseconds + const int64_t stop_ns = stop_ms * 1000000; + + // Metadata blocks always specify the block duration. + const int64_t duration_ns = stop_ns - start_ns; + + std::string frame; + MakeFrame(cue, &frame); + + typedef const uint8_t* data_t; + const data_t buf = reinterpret_cast(frame.data()); + const uint64_t len = frame.length(); + + mkvmuxer::Frame muxer_frame; + if (!muxer_frame.Init(buf, len)) + return 0; + muxer_frame.set_track_number(track_num); + muxer_frame.set_timestamp(start_ns); + muxer_frame.set_duration(duration_ns); + muxer_frame.set_is_key(true); // All metadata frames are keyframes. + return segment->AddGenericFrame(&muxer_frame); +} \ No newline at end of file diff --git a/third_party/libwebm/source/sample_muxer_metadata.h b/third_party/libwebm/source/sample_muxer_metadata.h new file mode 100644 index 000000000000..d76ccf54aac1 --- /dev/null +++ b/third_party/libwebm/source/sample_muxer_metadata.h @@ -0,0 +1,137 @@ +// Copyright (c) 2012 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. + +#ifndef SAMPLE_MUXER_METADATA_H_ // NOLINT +#define SAMPLE_MUXER_METADATA_H_ + +#include + +#include +#include +#include + +#include "webvtt/webvttparser.h" + +namespace mkvmuxer { +class Chapter; +class Frame; +class Segment; +class Track; +} // namespace mkvmuxer + +class SampleMuxerMetadata { + public: + enum Kind { kSubtitles, kCaptions, kDescriptions, kMetadata, kChapters }; + + SampleMuxerMetadata(); + + // Bind this metadata object to the muxer instance. Returns false + // if segment equals NULL, or Init has already been called. + bool Init(mkvmuxer::Segment* segment); + + // Parse the WebVTT file |filename| having the indicated |kind|, and + // create a corresponding track (or chapters element) in the + // segment. Returns false on error. + bool Load(const char* filename, Kind kind); + + bool AddChapters(); + + // Write any WebVTT cues whose time is less or equal to |time_ns| as + // a metadata block in its corresponding track. If |time_ns| is + // negative, write all remaining cues. Returns false on error. + bool Write(int64_t time_ns); + + private: + typedef libwebvtt::Cue cue_t; + + // Used to sort cues as they are loaded. + struct SortableCue { + bool operator>(int64_t time_ns) const { + // Cue start time expressed in milliseconds + const int64_t start_ms = cue.start_time.presentation(); + + // Cue start time expressed in nanoseconds (MKV time) + const int64_t start_ns = start_ms * 1000000; + + return (start_ns > time_ns); + } + + bool operator<(const SortableCue& rhs) const { + if (cue.start_time < rhs.cue.start_time) + return true; + + if (cue.start_time > rhs.cue.start_time) + return false; + + return (track_num < rhs.track_num); + } + + // Write this cue as a metablock to |segment|. Returns false on + // error. + bool Write(mkvmuxer::Segment* segment) const; + + uint64_t track_num; + cue_t cue; + }; + + typedef std::multiset cues_set_t; + typedef std::list cue_list_t; + + // Parse the WebVTT cues in the named |file|, returning false on + // error. We handle chapters as a special case, because they are + // stored in their own, dedicated level-1 element. + bool LoadChapters(const char* file); + + // Parse the WebVTT chapters in |file| to populate |cues|. Returns + // false on error. + static bool ParseChapters(const char* file, cue_list_t* cues); + + // Adds WebVTT cue |chapter| to the chapters element of the output + // file's segment element. Returns false on error. + bool AddChapter(const cue_t& chapter); + + // Add a metadata track to the segment having the indicated |kind|, + // returning the |track_num| that has been chosen for this track. + // Returns false on error. + bool AddTrack(Kind kind, uint64_t* track_num); + + // Parse the WebVTT |file| having the indicated |kind| and + // |track_num|, adding each parsed cue to cues set. Returns false + // on error. + bool Parse(const char* file, Kind kind, uint64_t track_num); + + // Converts a WebVTT cue to a Matroska metadata block. + static void MakeFrame(const cue_t& cue, std::string* frame); + + // Populate the cue identifier part of the metadata block. + static void WriteCueIdentifier(const std::string& identifier, + std::string* frame); + + // Populate the cue settings part of the metadata block. + static void WriteCueSettings(const cue_t::settings_t& settings, + std::string* frame); + + // Populate the payload part of the metadata block. + static void WriteCuePayload(const cue_t::payload_t& payload, + std::string* frame); + + mkvmuxer::Segment* segment_; + + // Set of cues ordered by time and then by track number. + cues_set_t cues_set_; + + // The cues that will be used to populate the Chapters level-1 + // element of the output file. + cue_list_t chapter_cues_; + + // Disable copy ctor and copy assign. + SampleMuxerMetadata(const SampleMuxerMetadata&); + SampleMuxerMetadata& operator=(const SampleMuxerMetadata&); +}; + +#endif // SAMPLE_MUXER_METADATA_H_ // NOLINT diff --git a/third_party/libwebm/source/testing/mkvmuxer_tests.cc b/third_party/libwebm/source/testing/mkvmuxer_tests.cc new file mode 100644 index 000000000000..3374058a5559 --- /dev/null +++ b/third_party/libwebm/source/testing/mkvmuxer_tests.cc @@ -0,0 +1,1010 @@ +// Copyright (c) 2016 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "gtest/gtest.h" + +#include "common/file_util.h" +#include "common/libwebm_util.h" +#include "mkvmuxer/mkvmuxer.h" +#include "mkvmuxer/mkvwriter.h" +#include "mkvparser/mkvreader.h" +#include "testing/test_util.h" + +using mkvmuxer::AudioTrack; +using mkvmuxer::Chapter; +using mkvmuxer::Frame; +using mkvmuxer::MkvWriter; +using mkvmuxer::Segment; +using mkvmuxer::SegmentInfo; +using mkvmuxer::Tag; +using mkvmuxer::Track; +using mkvmuxer::VideoTrack; + +namespace test { + +// Base class containing boiler plate stuff. +class MuxerTest : public testing::Test { + public: + MuxerTest() { Init(); } + + ~MuxerTest() { CloseWriter(); } + + // Simple init function for use by constructor. Calls made here to allow use + // of ASSERT_* macros-- this is necessary here because all failures in Init() + // are fatal, but the ASSERT_* gtest macros cannot be used in a constructor. + void Init() { + ASSERT_TRUE(GetTestDataDir().length() > 0); + filename_ = libwebm::GetTempFileName(); + ASSERT_GT(filename_.length(), 0u); + temp_file_ = libwebm::FilePtr(std::fopen(filename_.c_str(), "wb"), + libwebm::FILEDeleter()); + ASSERT_TRUE(temp_file_.get() != nullptr); + writer_.reset(new MkvWriter(temp_file_.get())); + is_writer_open_ = true; + memset(dummy_data_, 0, kFrameLength); + } + + void AddDummyFrameAndFinalize(int track_number) { + EXPECT_TRUE(segment_.AddFrame(&dummy_data_[0], kFrameLength, track_number, + 0, false)); + EXPECT_TRUE(segment_.Finalize()); + } + + void AddVideoTrack() { + const int vid_track = static_cast( + segment_.AddVideoTrack(kWidth, kHeight, kVideoTrackNumber)); + ASSERT_EQ(kVideoTrackNumber, vid_track); + VideoTrack* const video = + dynamic_cast(segment_.GetTrackByNumber(vid_track)); + ASSERT_TRUE(video != NULL); + video->set_uid(kVideoTrackNumber); + } + + void AddAudioTrack() { + const int aud_track = static_cast( + segment_.AddAudioTrack(kSampleRate, kChannels, kAudioTrackNumber)); + ASSERT_EQ(kAudioTrackNumber, aud_track); + AudioTrack* const audio = + dynamic_cast(segment_.GetTrackByNumber(aud_track)); + ASSERT_TRUE(audio != NULL); + audio->set_uid(kAudioTrackNumber); + audio->set_codec_id(kOpusCodecId); + } + + void CloseWriter() { + if (is_writer_open_) + writer_->Close(); + is_writer_open_ = false; + } + + bool SegmentInit(bool output_cues, bool accurate_cluster_duration, + bool fixed_size_cluster_timecode) { + if (!segment_.Init(writer_.get())) + return false; + SegmentInfo* const info = segment_.GetSegmentInfo(); + info->set_writing_app(kAppString); + info->set_muxing_app(kAppString); + segment_.OutputCues(output_cues); + segment_.AccurateClusterDuration(accurate_cluster_duration); + segment_.UseFixedSizeClusterTimecode(fixed_size_cluster_timecode); + return true; + } + + protected: + virtual void TearDown() { + remove(filename_.c_str()); + testing::Test::TearDown(); + } + + std::unique_ptr writer_; + bool is_writer_open_ = false; + Segment segment_; + std::string filename_; + libwebm::FilePtr temp_file_; + std::uint8_t dummy_data_[kFrameLength]; +}; + +TEST_F(MuxerTest, SegmentInfo) { + EXPECT_TRUE(SegmentInit(false, false, false)); + SegmentInfo* const info = segment_.GetSegmentInfo(); + info->set_timecode_scale(kTimeCodeScale); + info->set_duration(2.345); + EXPECT_STREQ(kAppString, info->muxing_app()); + EXPECT_STREQ(kAppString, info->writing_app()); + EXPECT_EQ(static_cast(kTimeCodeScale), info->timecode_scale()); + EXPECT_DOUBLE_EQ(2.345, info->duration()); + AddVideoTrack(); + + AddDummyFrameAndFinalize(kVideoTrackNumber); + CloseWriter(); + + EXPECT_TRUE(CompareFiles(GetTestFilePath("segment_info.webm"), filename_)); +} + +TEST_F(MuxerTest, AddTracks) { + EXPECT_TRUE(SegmentInit(false, false, false)); + + // Add a Video Track + AddVideoTrack(); + VideoTrack* const video = + dynamic_cast(segment_.GetTrackByNumber(kVideoTrackNumber)); + ASSERT_TRUE(video != NULL); + EXPECT_EQ(static_cast(kWidth), video->width()); + EXPECT_EQ(static_cast(kHeight), video->height()); + video->set_name(kTrackName); + video->set_display_width(kWidth - 10); + video->set_display_height(kHeight - 10); + video->set_frame_rate(0.5); + EXPECT_STREQ(kTrackName, video->name()); + const uint64_t kDisplayWidth = kWidth - 10; + EXPECT_EQ(kDisplayWidth, video->display_width()); + const uint64_t kDisplayHeight = kHeight - 10; + EXPECT_EQ(kDisplayHeight, video->display_height()); + EXPECT_DOUBLE_EQ(0.5, video->frame_rate()); + EXPECT_EQ(static_cast(kVideoTrackNumber), video->uid()); + + // Add an Audio Track + const int aud_track = static_cast( + segment_.AddAudioTrack(kSampleRate, kChannels, kAudioTrackNumber)); + EXPECT_EQ(kAudioTrackNumber, aud_track); + AudioTrack* const audio = + dynamic_cast(segment_.GetTrackByNumber(aud_track)); + EXPECT_EQ(kSampleRate, audio->sample_rate()); + EXPECT_EQ(static_cast(kChannels), audio->channels()); + ASSERT_TRUE(audio != NULL); + audio->set_name(kTrackName); + audio->set_bit_depth(kBitDepth); + audio->set_uid(kAudioTrackNumber); + EXPECT_STREQ(kTrackName, audio->name()); + EXPECT_EQ(static_cast(kBitDepth), audio->bit_depth()); + EXPECT_EQ(static_cast(kAudioTrackNumber), audio->uid()); + + AddDummyFrameAndFinalize(kVideoTrackNumber); + CloseWriter(); + + EXPECT_TRUE(CompareFiles(GetTestFilePath("tracks.webm"), filename_)); +} + +TEST_F(MuxerTest, AddChapters) { + EXPECT_TRUE(SegmentInit(false, false, false)); + AddVideoTrack(); + + // Add a Chapter + Chapter* chapter = segment_.AddChapter(); + EXPECT_TRUE(chapter->set_id("unit_test")); + chapter->set_time(segment_, 0, 1000000000); + EXPECT_TRUE(chapter->add_string("unit_test", "english", "us")); + chapter->set_uid(1); + + AddDummyFrameAndFinalize(kVideoTrackNumber); + CloseWriter(); + + EXPECT_TRUE(CompareFiles(GetTestFilePath("chapters.webm"), filename_)); +} + +TEST_F(MuxerTest, SimpleBlock) { + EXPECT_TRUE(SegmentInit(false, false, false)); + AddVideoTrack(); + + // Valid Frame + EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, 0, + false)); + + // Valid Frame + EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, + 2000000, false)); + + // Invalid Frame - Non monotonically increasing timestamp + EXPECT_FALSE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, + 1, false)); + + // Invalid Frame - Null pointer + EXPECT_FALSE(segment_.AddFrame(NULL, 0, kVideoTrackNumber, 8000000, false)); + + // Invalid Frame - Invalid track number + EXPECT_FALSE(segment_.AddFrame(NULL, 0, kInvalidTrackNumber, 8000000, false)); + + segment_.Finalize(); + CloseWriter(); + + EXPECT_TRUE(CompareFiles(GetTestFilePath("simple_block.webm"), filename_)); +} + +TEST_F(MuxerTest, SimpleBlockWithAddGenericFrame) { + EXPECT_TRUE(SegmentInit(false, false, false)); + AddVideoTrack(); + + Frame frame; + frame.Init(dummy_data_, kFrameLength); + frame.set_track_number(kVideoTrackNumber); + frame.set_is_key(false); + + // Valid Frame + frame.set_timestamp(0); + EXPECT_TRUE(segment_.AddGenericFrame(&frame)); + + // Valid Frame + frame.set_timestamp(2000000); + EXPECT_TRUE(segment_.AddGenericFrame(&frame)); + + // Invalid Frame - Non monotonically increasing timestamp + frame.set_timestamp(1); + EXPECT_FALSE(segment_.AddGenericFrame(&frame)); + + // Invalid Frame - Invalid track number + frame.set_track_number(kInvalidTrackNumber); + frame.set_timestamp(8000000); + EXPECT_FALSE(segment_.AddGenericFrame(&frame)); + + segment_.Finalize(); + CloseWriter(); + + EXPECT_TRUE(CompareFiles(GetTestFilePath("simple_block.webm"), filename_)); +} + +TEST_F(MuxerTest, MetadataBlock) { + EXPECT_TRUE(SegmentInit(false, false, false)); + Track* const track = segment_.AddTrack(kMetadataTrackNumber); + track->set_uid(kMetadataTrackNumber); + track->set_type(kMetadataTrackType); + track->set_codec_id(kMetadataCodecId); + + // Valid Frame + EXPECT_TRUE(segment_.AddMetadata(dummy_data_, kFrameLength, + kMetadataTrackNumber, 0, 2000000)); + + // Valid Frame + EXPECT_TRUE(segment_.AddMetadata(dummy_data_, kFrameLength, + kMetadataTrackNumber, 2000000, 6000000)); + + // Invalid Frame - Non monotonically increasing timestamp + EXPECT_FALSE(segment_.AddMetadata(dummy_data_, kFrameLength, + kMetadataTrackNumber, 1, 2000000)); + + // Invalid Frame - Null pointer + EXPECT_FALSE(segment_.AddMetadata(NULL, 0, kMetadataTrackNumber, 0, 8000000)); + + // Invalid Frame - Invalid track number + EXPECT_FALSE(segment_.AddMetadata(NULL, 0, kInvalidTrackNumber, 0, 8000000)); + + segment_.Finalize(); + CloseWriter(); + + EXPECT_TRUE(CompareFiles(GetTestFilePath("metadata_block.webm"), filename_)); +} + +TEST_F(MuxerTest, TrackType) { + EXPECT_TRUE(SegmentInit(false, false, false)); + Track* const track = segment_.AddTrack(kMetadataTrackNumber); + track->set_uid(kMetadataTrackNumber); + track->set_codec_id(kMetadataCodecId); + + // Invalid Frame - Incomplete track information (Track Type not set). + EXPECT_FALSE(segment_.AddMetadata(dummy_data_, kFrameLength, + kMetadataTrackNumber, 0, 2000000)); + + track->set_type(kMetadataTrackType); + + // Valid Frame + EXPECT_TRUE(segment_.AddMetadata(dummy_data_, kFrameLength, + kMetadataTrackNumber, 0, 2000000)); + + segment_.Finalize(); + CloseWriter(); +} + +TEST_F(MuxerTest, BlockWithAdditional) { + EXPECT_TRUE(SegmentInit(false, false, false)); + AddVideoTrack(); + + // Valid Frame + EXPECT_TRUE(segment_.AddFrameWithAdditional(dummy_data_, kFrameLength, + dummy_data_, kFrameLength, 1, + kVideoTrackNumber, 0, true)); + + // Valid Frame + EXPECT_TRUE(segment_.AddFrameWithAdditional( + dummy_data_, kFrameLength, dummy_data_, kFrameLength, 1, + kVideoTrackNumber, 2000000, false)); + + // Invalid Frame - Non monotonically increasing timestamp + EXPECT_FALSE(segment_.AddFrameWithAdditional(dummy_data_, kFrameLength, + dummy_data_, kFrameLength, 1, + kVideoTrackNumber, 1, false)); + + // Invalid Frame - Null frame pointer + EXPECT_FALSE( + segment_.AddFrameWithAdditional(NULL, 0, dummy_data_, kFrameLength, 1, + kVideoTrackNumber, 3000000, false)); + + // Invalid Frame - Null additional pointer + EXPECT_FALSE(segment_.AddFrameWithAdditional(dummy_data_, kFrameLength, NULL, + 0, 1, kVideoTrackNumber, 4000000, + false)); + + // Invalid Frame - Invalid track number + EXPECT_FALSE(segment_.AddFrameWithAdditional( + dummy_data_, kFrameLength, dummy_data_, kFrameLength, 1, + kInvalidTrackNumber, 8000000, false)); + + segment_.Finalize(); + CloseWriter(); + + EXPECT_TRUE( + CompareFiles(GetTestFilePath("block_with_additional.webm"), filename_)); +} + +TEST_F(MuxerTest, BlockAdditionalWithAddGenericFrame) { + EXPECT_TRUE(SegmentInit(false, false, false)); + AddVideoTrack(); + + Frame frame; + frame.Init(dummy_data_, kFrameLength); + frame.AddAdditionalData(dummy_data_, kFrameLength, 1); + frame.set_track_number(kVideoTrackNumber); + frame.set_is_key(true); + + // Valid Frame + frame.set_timestamp(0); + EXPECT_TRUE(segment_.AddGenericFrame(&frame)); + + // Valid Frame + frame.set_timestamp(2000000); + frame.set_is_key(false); + EXPECT_TRUE(segment_.AddGenericFrame(&frame)); + + // Invalid Frame - Non monotonically increasing timestamp + frame.set_timestamp(1); + EXPECT_FALSE(segment_.AddGenericFrame(&frame)); + + // Invalid Frame - Invalid track number + frame.set_track_number(kInvalidTrackNumber); + frame.set_timestamp(4000000); + EXPECT_FALSE(segment_.AddGenericFrame(&frame)); + + segment_.Finalize(); + CloseWriter(); + + EXPECT_TRUE( + CompareFiles(GetTestFilePath("block_with_additional.webm"), filename_)); +} + +TEST_F(MuxerTest, SegmentDurationComputation) { + EXPECT_TRUE(SegmentInit(false, false, false)); + AddVideoTrack(); + + Frame frame; + frame.Init(dummy_data_, kFrameLength); + frame.set_track_number(kVideoTrackNumber); + frame.set_timestamp(0); + frame.set_is_key(false); + EXPECT_TRUE(segment_.AddGenericFrame(&frame)); + frame.set_timestamp(2000000); + EXPECT_TRUE(segment_.AddGenericFrame(&frame)); + frame.set_timestamp(4000000); + EXPECT_TRUE(segment_.AddGenericFrame(&frame)); + frame.set_timestamp(6000000); + frame.set_duration(2000000); + EXPECT_TRUE(segment_.AddGenericFrame(&frame)); + segment_.Finalize(); + + // SegmentInfo's duration is in timecode scale + EXPECT_EQ(8, segment_.GetSegmentInfo()->duration()); + + CloseWriter(); + + EXPECT_TRUE( + CompareFiles(GetTestFilePath("segment_duration.webm"), filename_)); +} + +TEST_F(MuxerTest, SetSegmentDuration) { + EXPECT_TRUE(SegmentInit(false, false, false)); + AddVideoTrack(); + EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, 0, + false)); + EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, + 2000000, false)); + + segment_.set_duration(10500.0); + segment_.Finalize(); + CloseWriter(); + + EXPECT_TRUE( + CompareFiles(GetTestFilePath("set_segment_duration.webm"), filename_)); +} + +TEST_F(MuxerTest, ForceNewCluster) { + EXPECT_TRUE(SegmentInit(false, false, false)); + AddVideoTrack(); + + EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, 0, + false)); + segment_.ForceNewClusterOnNextFrame(); + EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, + 2000000, false)); + EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, + 4000000, false)); + segment_.ForceNewClusterOnNextFrame(); + EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, + 6000000, false)); + segment_.Finalize(); + + CloseWriter(); + + EXPECT_TRUE( + CompareFiles(GetTestFilePath("force_new_cluster.webm"), filename_)); +} + +TEST_F(MuxerTest, OutputCues) { + EXPECT_TRUE(SegmentInit(true, false, false)); + AddVideoTrack(); + + EXPECT_TRUE( + segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, 0, true)); + EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, + 2000000, false)); + EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, + 4000000, false)); + EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, + 6000000, true)); + EXPECT_TRUE(segment_.AddCuePoint(4000000, kVideoTrackNumber)); + segment_.Finalize(); + + CloseWriter(); + + EXPECT_TRUE(CompareFiles(GetTestFilePath("output_cues.webm"), filename_)); +} + +TEST_F(MuxerTest, CuesBeforeClusters) { + EXPECT_TRUE(SegmentInit(true, false, false)); + AddVideoTrack(); + + EXPECT_TRUE( + segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, 0, true)); + EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, + 2000000, false)); + EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, + 4000000, false)); + EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, + 6000000, true)); + segment_.Finalize(); + CloseWriter(); +#ifdef _MSC_VER + // Close the output file: the MS run time won't allow mkvparser::MkvReader + // to open a file for reading when it's still open for writing. + temp_file_.reset(); +#endif + mkvparser::MkvReader reader; + ASSERT_EQ(0, reader.Open(filename_.c_str())); + MkvWriter cues_writer; + std::string cues_filename = libwebm::GetTempFileName(); + ASSERT_GT(cues_filename.length(), 0u); + cues_writer.Open(cues_filename.c_str()); + EXPECT_TRUE(segment_.CopyAndMoveCuesBeforeClusters(&reader, &cues_writer)); + reader.Close(); + cues_writer.Close(); + + EXPECT_TRUE(CompareFiles(GetTestFilePath("cues_before_clusters.webm"), + cues_filename)); + MkvParser parser; + ASSERT_TRUE(ParseMkvFileReleaseParser(cues_filename, &parser)); + int64_t cues_offset = 0; + ASSERT_TRUE(HasCuePoints(parser.segment, &cues_offset)); + ASSERT_GT(cues_offset, 0); + ASSERT_TRUE(ValidateCues(parser.segment, parser.reader)); + remove(cues_filename.c_str()); +} + +TEST_F(MuxerTest, MaxClusterSize) { + EXPECT_TRUE(SegmentInit(false, false, false)); + AddVideoTrack(); + const uint64_t kMaxClusterSize = 20; + segment_.set_max_cluster_size(kMaxClusterSize); + EXPECT_EQ(kMaxClusterSize, segment_.max_cluster_size()); + EXPECT_TRUE(segment_.AddFrame(dummy_data_, 1, kVideoTrackNumber, 0, false)); + EXPECT_TRUE( + segment_.AddFrame(dummy_data_, 1, kVideoTrackNumber, 2000000, false)); + EXPECT_TRUE( + segment_.AddFrame(dummy_data_, 1, kVideoTrackNumber, 4000000, false)); + EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, + 6000000, false)); + EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, + 8000000, false)); + EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, + 9000000, false)); + segment_.Finalize(); + + CloseWriter(); + + EXPECT_TRUE( + CompareFiles(GetTestFilePath("max_cluster_size.webm"), filename_)); +} + +TEST_F(MuxerTest, MaxClusterDuration) { + EXPECT_TRUE(SegmentInit(false, false, false)); + AddVideoTrack(); + const uint64_t kMaxClusterDuration = 4000000; + segment_.set_max_cluster_duration(kMaxClusterDuration); + + EXPECT_EQ(kMaxClusterDuration, segment_.max_cluster_duration()); + EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, 0, + false)); + EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, + 2000000, false)); + EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, + 4000000, false)); + EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, + 6000000, false)); + EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, + 8000000, false)); + EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, + 9000000, false)); + segment_.Finalize(); + + CloseWriter(); + + EXPECT_TRUE( + CompareFiles(GetTestFilePath("max_cluster_duration.webm"), filename_)); +} + +TEST_F(MuxerTest, SetCuesTrackNumber) { + const uint64_t kTrackNumber = 10; + EXPECT_TRUE(SegmentInit(true, false, false)); + const uint64_t vid_track = + segment_.AddVideoTrack(kWidth, kHeight, kTrackNumber); + EXPECT_EQ(kTrackNumber, vid_track); + segment_.GetTrackByNumber(vid_track)->set_uid(kVideoTrackNumber); + EXPECT_TRUE(segment_.CuesTrack(vid_track)); + + EXPECT_EQ(vid_track, segment_.cues_track()); + EXPECT_TRUE( + segment_.AddFrame(dummy_data_, kFrameLength, kTrackNumber, 0, true)); + EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kTrackNumber, + 2000000, false)); + EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kTrackNumber, + 4000000, false)); + EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kTrackNumber, + 6000000, true)); + EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kTrackNumber, + 8000000, false)); + EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kTrackNumber, + 9000000, false)); + segment_.Finalize(); + + CloseWriter(); + + EXPECT_TRUE( + CompareFiles(GetTestFilePath("set_cues_track_number.webm"), filename_)); +} + +TEST_F(MuxerTest, BlockWithDiscardPadding) { + EXPECT_TRUE(SegmentInit(false, false, false)); + AddAudioTrack(); + + int timecode = 1000; + // 12810000 == 0xc37710, should be 0-extended to avoid changing the sign. + // The next two should be written as 1 byte. + std::array values = {{12810000, 127, -128}}; + for (const std::int64_t discard_padding : values) { + EXPECT_TRUE(segment_.AddFrameWithDiscardPadding( + dummy_data_, kFrameLength, discard_padding, kAudioTrackNumber, timecode, + true)) + << "discard_padding: " << discard_padding; + timecode += 1000; + } + + segment_.Finalize(); + + CloseWriter(); + + EXPECT_TRUE(CompareFiles(GetTestFilePath("discard_padding.webm"), filename_)); +} + +TEST_F(MuxerTest, AccurateClusterDuration) { + EXPECT_TRUE(SegmentInit(false, true, false)); + AddVideoTrack(); + + Frame frame; + frame.Init(dummy_data_, kFrameLength); + frame.set_track_number(kVideoTrackNumber); + frame.set_timestamp(0); + frame.set_is_key(true); + EXPECT_TRUE(segment_.AddGenericFrame(&frame)); + segment_.ForceNewClusterOnNextFrame(); + frame.set_timestamp(2000000); + frame.set_is_key(false); + EXPECT_TRUE(segment_.AddGenericFrame(&frame)); + frame.set_timestamp(4000000); + EXPECT_TRUE(segment_.AddGenericFrame(&frame)); + segment_.ForceNewClusterOnNextFrame(); + frame.set_timestamp(6000000); + EXPECT_TRUE(segment_.AddGenericFrame(&frame)); + segment_.Finalize(); + + CloseWriter(); + + EXPECT_TRUE(CompareFiles(GetTestFilePath("accurate_cluster_duration.webm"), + filename_)); +} + +// Tests AccurateClusterDuration flag with the duration of the very last block +// of the file set explicitly. +TEST_F(MuxerTest, AccurateClusterDurationExplicitLastFrameDuration) { + EXPECT_TRUE(SegmentInit(false, true, false)); + AddVideoTrack(); + + Frame frame; + frame.Init(dummy_data_, kFrameLength); + frame.set_track_number(kVideoTrackNumber); + frame.set_timestamp(0); + frame.set_is_key(true); + EXPECT_TRUE(segment_.AddGenericFrame(&frame)); + segment_.ForceNewClusterOnNextFrame(); + frame.set_timestamp(2000000); + frame.set_is_key(false); + EXPECT_TRUE(segment_.AddGenericFrame(&frame)); + frame.set_timestamp(4000000); + EXPECT_TRUE(segment_.AddGenericFrame(&frame)); + segment_.ForceNewClusterOnNextFrame(); + frame.set_timestamp(6000000); + frame.set_duration(2000000); + EXPECT_TRUE(segment_.AddGenericFrame(&frame)); + segment_.Finalize(); + + // SegmentInfo's duration is in timecode scale + EXPECT_EQ(8, segment_.GetSegmentInfo()->duration()); + + CloseWriter(); + + EXPECT_TRUE(CompareFiles( + GetTestFilePath("accurate_cluster_duration_last_frame.webm"), filename_)); +} + +TEST_F(MuxerTest, AccurateClusterDurationTwoTracks) { + EXPECT_TRUE(SegmentInit(false, true, false)); + AddVideoTrack(); + AddAudioTrack(); + + Frame video_frame; + video_frame.Init(dummy_data_, kFrameLength); + video_frame.set_track_number(kVideoTrackNumber); + Frame audio_frame; + audio_frame.Init(dummy_data_, kFrameLength); + audio_frame.set_track_number(kAudioTrackNumber); + std::array cluster_timestamps = {{0, 40000000}}; + for (const std::uint64_t cluster_timestamp : cluster_timestamps) { + // Add video and audio frames with timestamp 0. + video_frame.set_timestamp(cluster_timestamp); + video_frame.set_is_key(true); + EXPECT_TRUE(segment_.AddGenericFrame(&video_frame)); + audio_frame.set_timestamp(cluster_timestamp); + audio_frame.set_is_key(true); + EXPECT_TRUE(segment_.AddGenericFrame(&audio_frame)); + + // Add 3 consecutive audio frames. + std::array audio_timestamps = { + {10000000, 20000000, 30000000}}; + for (const std::uint64_t audio_timestamp : audio_timestamps) { + audio_frame.set_timestamp(cluster_timestamp + audio_timestamp); + // Explicitly set duration for the very last audio frame. + if (cluster_timestamp == 40000000 && audio_timestamp == 30000000) { + audio_frame.set_duration(10000000); + } + EXPECT_TRUE(segment_.AddGenericFrame(&audio_frame)); + } + + // Add a video frame with timestamp 33ms. + video_frame.set_is_key(false); + // Explicitly set duration for the very last video frame. + if (cluster_timestamp == 40000000) { + video_frame.set_duration(7000000); + } + video_frame.set_timestamp(cluster_timestamp + 33000000); + EXPECT_TRUE(segment_.AddGenericFrame(&video_frame)); + segment_.ForceNewClusterOnNextFrame(); + } + segment_.Finalize(); + + // SegmentInfo's duration is in timecode scale + EXPECT_EQ(80, segment_.GetSegmentInfo()->duration()); + + CloseWriter(); + + EXPECT_TRUE(CompareFiles( + GetTestFilePath("accurate_cluster_duration_two_tracks.webm"), filename_)); +} + +TEST_F(MuxerTest, AccurateClusterDurationWithoutFinalizingCluster) { + EXPECT_TRUE(SegmentInit(false, true, false)); + AddVideoTrack(); + + // Add a couple of frames and then bail out without finalizing the Segment + // (and thereby not finalizing the Cluster). The expectation here is that + // there shouldn't be any leaks. The test will fail under valgrind if there's + // a leak. + Frame video_frame; + video_frame.Init(dummy_data_, kFrameLength); + video_frame.set_track_number(kVideoTrackNumber); + video_frame.set_timestamp(0); + video_frame.set_is_key(true); + EXPECT_TRUE(segment_.AddGenericFrame(&video_frame)); + video_frame.set_timestamp(33000000); + EXPECT_TRUE(segment_.AddGenericFrame(&video_frame)); + + CloseWriter(); +} + +TEST_F(MuxerTest, UseFixedSizeClusterTimecode) { + EXPECT_TRUE(SegmentInit(false, false, true)); + AddVideoTrack(); + + Frame frame; + frame.Init(dummy_data_, kFrameLength); + frame.set_track_number(kVideoTrackNumber); + frame.set_timestamp(0); + frame.set_is_key(true); + EXPECT_TRUE(segment_.AddGenericFrame(&frame)); + segment_.ForceNewClusterOnNextFrame(); + frame.set_timestamp(2000000); + EXPECT_TRUE(segment_.AddGenericFrame(&frame)); + segment_.ForceNewClusterOnNextFrame(); + frame.set_timestamp(4000000); + EXPECT_TRUE(segment_.AddGenericFrame(&frame)); + segment_.Finalize(); + + CloseWriter(); + + EXPECT_TRUE(CompareFiles(GetTestFilePath("fixed_size_cluster_timecode.webm"), + filename_)); +} + +TEST_F(MuxerTest, DocTypeWebm) { + EXPECT_TRUE(SegmentInit(false, false, false)); + AddVideoTrack(); + Track* const vid_track = segment_.GetTrackByNumber(kVideoTrackNumber); + vid_track->set_codec_id(kVP9CodecId); + AddDummyFrameAndFinalize(kVideoTrackNumber); + EXPECT_TRUE(CompareFiles(GetTestFilePath("webm_doctype.webm"), filename_)); +} + +TEST_F(MuxerTest, DocTypeMatroska) { + EXPECT_TRUE(SegmentInit(false, false, false)); + AddVideoTrack(); + Track* const vid_track = segment_.GetTrackByNumber(kVideoTrackNumber); + vid_track->set_codec_id("V_SOMETHING_NOT_IN_WEBM"); + AddDummyFrameAndFinalize(kVideoTrackNumber); + EXPECT_TRUE(CompareFiles(GetTestFilePath("matroska_doctype.mkv"), filename_)); +} + +TEST_F(MuxerTest, Colour) { + EXPECT_TRUE(SegmentInit(false, false, false)); + AddVideoTrack(); + + mkvmuxer::PrimaryChromaticity muxer_pc(.1, .2); + mkvmuxer::MasteringMetadata muxer_mm; + muxer_mm.set_luminance_min(30.0); + muxer_mm.set_luminance_max(40.0); + ASSERT_TRUE( + muxer_mm.SetChromaticity(&muxer_pc, &muxer_pc, &muxer_pc, &muxer_pc)); + + mkvmuxer::Colour muxer_colour; + muxer_colour.set_matrix_coefficients(mkvmuxer::Colour::kGbr); + muxer_colour.set_bits_per_channel(1); + muxer_colour.set_chroma_subsampling_horz(2); + muxer_colour.set_chroma_subsampling_vert(3); + muxer_colour.set_cb_subsampling_horz(4); + muxer_colour.set_cb_subsampling_vert(5); + muxer_colour.set_chroma_siting_horz(mkvmuxer::Colour::kLeftCollocated); + muxer_colour.set_chroma_siting_vert(mkvmuxer::Colour::kTopCollocated); + muxer_colour.set_range(mkvmuxer::Colour::kFullRange); + muxer_colour.set_transfer_characteristics(mkvmuxer::Colour::kLog); + muxer_colour.set_primaries(mkvmuxer::Colour::kSmpteSt4281P); + muxer_colour.set_max_cll(11); + muxer_colour.set_max_fall(12); + ASSERT_TRUE(muxer_colour.SetMasteringMetadata(muxer_mm)); + + VideoTrack* const video_track = + dynamic_cast(segment_.GetTrackByNumber(kVideoTrackNumber)); + ASSERT_TRUE(video_track != nullptr); + ASSERT_TRUE(video_track->SetColour(muxer_colour)); + ASSERT_NO_FATAL_FAILURE(AddDummyFrameAndFinalize(kVideoTrackNumber)); + + MkvParser parser; + ASSERT_TRUE(ParseMkvFileReleaseParser(filename_, &parser)); + + const mkvparser::VideoTrack* const parser_track = + static_cast( + parser.segment->GetTracks()->GetTrackByIndex(0)); + const mkvparser::Colour* parser_colour = parser_track->GetColour(); + ASSERT_TRUE(parser_colour != nullptr); + EXPECT_EQ(static_cast(muxer_colour.matrix_coefficients()), + parser_colour->matrix_coefficients); + EXPECT_EQ(static_cast(muxer_colour.bits_per_channel()), + parser_colour->bits_per_channel); + EXPECT_EQ(static_cast(muxer_colour.chroma_subsampling_horz()), + parser_colour->chroma_subsampling_horz); + EXPECT_EQ(static_cast(muxer_colour.chroma_subsampling_vert()), + parser_colour->chroma_subsampling_vert); + EXPECT_EQ(static_cast(muxer_colour.cb_subsampling_horz()), + parser_colour->cb_subsampling_horz); + EXPECT_EQ(static_cast(muxer_colour.cb_subsampling_vert()), + parser_colour->cb_subsampling_vert); + EXPECT_EQ(static_cast(muxer_colour.chroma_siting_horz()), + parser_colour->chroma_siting_horz); + EXPECT_EQ(static_cast(muxer_colour.chroma_siting_vert()), + parser_colour->chroma_siting_vert); + EXPECT_EQ(static_cast(muxer_colour.range()), parser_colour->range); + EXPECT_EQ(static_cast(muxer_colour.transfer_characteristics()), + parser_colour->transfer_characteristics); + EXPECT_EQ(static_cast(muxer_colour.primaries()), + parser_colour->primaries); + EXPECT_EQ(static_cast(muxer_colour.max_cll()), + parser_colour->max_cll); + EXPECT_EQ(static_cast(muxer_colour.max_fall()), + parser_colour->max_fall); + + const mkvparser::MasteringMetadata* const parser_mm = + parser_colour->mastering_metadata; + ASSERT_TRUE(parser_mm != nullptr); + EXPECT_FLOAT_EQ(muxer_mm.luminance_min(), parser_mm->luminance_min); + EXPECT_FLOAT_EQ(muxer_mm.luminance_max(), parser_mm->luminance_max); + EXPECT_FLOAT_EQ(muxer_mm.r()->x(), parser_mm->r->x); + EXPECT_FLOAT_EQ(muxer_mm.r()->y(), parser_mm->r->y); + EXPECT_FLOAT_EQ(muxer_mm.g()->x(), parser_mm->g->x); + EXPECT_FLOAT_EQ(muxer_mm.g()->y(), parser_mm->g->y); + EXPECT_FLOAT_EQ(muxer_mm.b()->x(), parser_mm->b->x); + EXPECT_FLOAT_EQ(muxer_mm.b()->y(), parser_mm->b->y); + EXPECT_FLOAT_EQ(muxer_mm.white_point()->x(), parser_mm->white_point->x); + EXPECT_FLOAT_EQ(muxer_mm.white_point()->y(), parser_mm->white_point->y); + EXPECT_TRUE(CompareFiles(GetTestFilePath("colour.webm"), filename_)); +} + +TEST_F(MuxerTest, ColourPartial) { + EXPECT_TRUE(SegmentInit(false, false, false)); + AddVideoTrack(); + mkvmuxer::Colour muxer_colour; + muxer_colour.set_matrix_coefficients( + mkvmuxer::Colour::kBt2020NonConstantLuminance); + + VideoTrack* const video_track = + dynamic_cast(segment_.GetTrackByNumber(kVideoTrackNumber)); + ASSERT_TRUE(video_track != nullptr); + ASSERT_TRUE(video_track->SetColour(muxer_colour)); + ASSERT_NO_FATAL_FAILURE(AddDummyFrameAndFinalize(kVideoTrackNumber)); + + MkvParser parser; + ASSERT_TRUE(ParseMkvFileReleaseParser(filename_, &parser)); + + const mkvparser::VideoTrack* const parser_track = + static_cast( + parser.segment->GetTracks()->GetTrackByIndex(0)); + const mkvparser::Colour* parser_colour = parser_track->GetColour(); + EXPECT_EQ(static_cast(muxer_colour.matrix_coefficients()), + parser_colour->matrix_coefficients); +} + +TEST_F(MuxerTest, Projection) { + EXPECT_TRUE(SegmentInit(false, false, false)); + AddVideoTrack(); + + mkvmuxer::Projection muxer_proj; + muxer_proj.set_type(mkvmuxer::Projection::kRectangular); + muxer_proj.set_pose_yaw(1); + muxer_proj.set_pose_pitch(2); + muxer_proj.set_pose_roll(3); + const uint8_t muxer_proj_private[1] = {4}; + const uint64_t muxer_proj_private_length = 1; + ASSERT_TRUE(muxer_proj.SetProjectionPrivate(&muxer_proj_private[0], + muxer_proj_private_length)); + + VideoTrack* const video_track = + static_cast(segment_.GetTrackByNumber(kVideoTrackNumber)); + ASSERT_TRUE(video_track != nullptr); + ASSERT_TRUE(video_track->SetProjection(muxer_proj)); + ASSERT_NO_FATAL_FAILURE(AddDummyFrameAndFinalize(kVideoTrackNumber)); + + MkvParser parser; + ASSERT_TRUE(ParseMkvFileReleaseParser(filename_, &parser)); + + const mkvparser::VideoTrack* const parser_track = + static_cast( + parser.segment->GetTracks()->GetTrackByIndex(0)); + + const mkvparser::Projection* const parser_proj = + parser_track->GetProjection(); + ASSERT_TRUE(parser_proj != nullptr); + EXPECT_FLOAT_EQ(muxer_proj.pose_yaw(), parser_proj->pose_yaw); + EXPECT_FLOAT_EQ(muxer_proj.pose_pitch(), parser_proj->pose_pitch); + EXPECT_FLOAT_EQ(muxer_proj.pose_roll(), parser_proj->pose_roll); + ASSERT_TRUE(parser_proj->private_data != nullptr); + EXPECT_EQ(static_cast(muxer_proj.private_data_length()), + parser_proj->private_data_length); + + EXPECT_EQ(muxer_proj.private_data()[0], parser_proj->private_data[0]); + typedef mkvparser::Projection::ProjectionType ParserProjType; + EXPECT_EQ(static_cast(muxer_proj.type()), parser_proj->type); + EXPECT_TRUE(CompareFiles(GetTestFilePath("projection.webm"), filename_)); +} + +TEST_F(MuxerTest, EstimateDuration) { + EXPECT_TRUE(SegmentInit(false, false, false)); + segment_.set_estimate_file_duration(true); + AddVideoTrack(); + EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, 0, + false)); + EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, + 2000000, false)); + EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, + 4000000, false)); + EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, + 6000000, false)); + EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, + 8000000, false)); + EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, + 9000000, false)); + segment_.Finalize(); + + CloseWriter(); + + EXPECT_TRUE( + CompareFiles(GetTestFilePath("estimate_duration.webm"), filename_)); +} + +TEST_F(MuxerTest, SetPixelWidthPixelHeight) { + EXPECT_TRUE(SegmentInit(false, false, false)); + AddVideoTrack(); + VideoTrack* const video_track = + static_cast(segment_.GetTrackByNumber(kVideoTrackNumber)); + ASSERT_TRUE(video_track != nullptr); + video_track->set_pixel_width(500); + video_track->set_pixel_height(650); + + EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, 0, + false)); + EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, + 2000000, false)); + + segment_.Finalize(); + CloseWriter(); + + EXPECT_TRUE(CompareFiles(GetTestFilePath("set_pixelwidth_pixelheight.webm"), + filename_)); +} + +TEST_F(MuxerTest, LongTagString) { + EXPECT_TRUE(SegmentInit(false, false, false)); + AddVideoTrack(); + Tag* const tag = segment_.AddTag(); + // 160 needs two bytes when varint encoded. + const std::string dummy_string(160, '0'); + tag->add_simple_tag("long_tag", dummy_string.c_str()); + + EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, 0, + false)); + + segment_.Finalize(); + CloseWriter(); + + EXPECT_TRUE(CompareFiles(GetTestFilePath("long_tag_string.webm"), filename_)); +} + +} // namespace test + +int main(int argc, char* argv[]) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/third_party/libwebm/source/testing/mkvparser_tests.cc b/third_party/libwebm/source/testing/mkvparser_tests.cc new file mode 100644 index 000000000000..9c26a1ea025c --- /dev/null +++ b/third_party/libwebm/source/testing/mkvparser_tests.cc @@ -0,0 +1,823 @@ +// Copyright (c) 2016 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +#include "gtest/gtest.h" + +#include +#include +#include +#include +#include +#include + +#include "common/hdr_util.h" +#include "mkvparser/mkvparser.h" +#include "mkvparser/mkvreader.h" +#include "testing/test_util.h" + +using mkvparser::AudioTrack; +using mkvparser::Block; +using mkvparser::BlockEntry; +using mkvparser::BlockGroup; +using mkvparser::Cluster; +using mkvparser::CuePoint; +using mkvparser::Cues; +using mkvparser::MkvReader; +using mkvparser::Segment; +using mkvparser::SegmentInfo; +using mkvparser::Track; +using mkvparser::Tracks; +using mkvparser::VideoTrack; + +namespace test { + +// Base class containing boiler plate stuff. +class ParserTest : public testing::Test { + public: + ParserTest() : is_reader_open_(false), segment_(NULL) { + memset(dummy_data_, -1, kFrameLength); + memset(gold_frame_, 0, kFrameLength); + } + + virtual ~ParserTest() { + CloseReader(); + if (segment_ != NULL) { + delete segment_; + segment_ = NULL; + } + } + + void CloseReader() { + if (is_reader_open_) { + reader_.Close(); + } + is_reader_open_ = false; + } + + bool CreateAndLoadSegment(const std::string& filename, + int expected_doc_type_ver) { + filename_ = GetTestFilePath(filename); + if (reader_.Open(filename_.c_str())) { + return false; + } + is_reader_open_ = true; + pos_ = 0; + mkvparser::EBMLHeader ebml_header; + ebml_header.Parse(&reader_, pos_); + EXPECT_EQ(1, ebml_header.m_version); + EXPECT_EQ(1, ebml_header.m_readVersion); + EXPECT_STREQ("webm", ebml_header.m_docType); + EXPECT_EQ(expected_doc_type_ver, ebml_header.m_docTypeVersion); + EXPECT_EQ(2, ebml_header.m_docTypeReadVersion); + + if (mkvparser::Segment::CreateInstance(&reader_, pos_, segment_)) { + return false; + } + return !HasFailure() && segment_->Load() >= 0; + } + + bool CreateAndLoadSegment(const std::string& filename) { + return CreateAndLoadSegment(filename, 4); + } + + void CreateSegmentNoHeaderChecks(const std::string& filename) { + filename_ = GetTestFilePath(filename); + ASSERT_NE(0u, filename_.length()); + ASSERT_EQ(0, reader_.Open(filename_.c_str())); + mkvparser::EBMLHeader ebml_header; + ASSERT_EQ(0, ebml_header.Parse(&reader_, pos_)); + ASSERT_EQ(0, mkvparser::Segment::CreateInstance(&reader_, pos_, segment_)); + } + + void CompareBlockContents(const Cluster* const cluster, + const Block* const block, std::uint64_t timestamp, + int track_number, bool is_key, int frame_count) { + ASSERT_TRUE(block != NULL); + EXPECT_EQ(track_number, block->GetTrackNumber()); + EXPECT_EQ(static_cast(timestamp), block->GetTime(cluster)); + EXPECT_EQ(is_key, block->IsKey()); + EXPECT_EQ(frame_count, block->GetFrameCount()); + const Block::Frame& frame = block->GetFrame(0); + EXPECT_EQ(kFrameLength, frame.len); + std::memset(dummy_data_, -1, kFrameLength); + frame.Read(&reader_, dummy_data_); + EXPECT_EQ(0, std::memcmp(gold_frame_, dummy_data_, kFrameLength)); + } + + void CompareCuePointContents(const Track* const track, + const CuePoint* const cue_point, + std::uint64_t timestamp, int track_number, + std::uint64_t pos) { + ASSERT_TRUE(cue_point != NULL); + EXPECT_EQ(static_cast(timestamp), cue_point->GetTime(segment_)); + const CuePoint::TrackPosition* const track_position = + cue_point->Find(track); + EXPECT_EQ(track_number, track_position->m_track); + EXPECT_EQ(static_cast(pos), track_position->m_pos); + } + + protected: + MkvReader reader_; + bool is_reader_open_; + Segment* segment_; + std::string filename_; + long long pos_; + std::uint8_t dummy_data_[kFrameLength]; + std::uint8_t gold_frame_[kFrameLength]; +}; + +TEST_F(ParserTest, SegmentInfo) { + ASSERT_TRUE(CreateAndLoadSegment("segment_info.webm")); + const SegmentInfo* const info = segment_->GetInfo(); + EXPECT_EQ(kTimeCodeScale, info->GetTimeCodeScale()); + EXPECT_STREQ(kAppString, info->GetMuxingAppAsUTF8()); + EXPECT_STREQ(kAppString, info->GetWritingAppAsUTF8()); +} + +TEST_F(ParserTest, TrackEntries) { + ASSERT_TRUE(CreateAndLoadSegment("tracks.webm")); + const Tracks* const tracks = segment_->GetTracks(); + const unsigned int kTracksCount = 2; + EXPECT_EQ(kTracksCount, tracks->GetTracksCount()); + for (int i = 0; i < 2; ++i) { + const Track* const track = tracks->GetTrackByIndex(i); + ASSERT_TRUE(track != NULL); + EXPECT_STREQ(kTrackName, track->GetNameAsUTF8()); + if (track->GetType() == Track::kVideo) { + const VideoTrack* const video_track = + dynamic_cast(track); + EXPECT_EQ(kWidth, static_cast(video_track->GetWidth())); + EXPECT_EQ(kHeight, static_cast(video_track->GetHeight())); + EXPECT_STREQ(kVP8CodecId, video_track->GetCodecId()); + EXPECT_DOUBLE_EQ(kVideoFrameRate, video_track->GetFrameRate()); + const unsigned int kTrackUid = 1; + EXPECT_EQ(kTrackUid, video_track->GetUid()); + } else if (track->GetType() == Track::kAudio) { + const AudioTrack* const audio_track = + dynamic_cast(track); + EXPECT_EQ(kSampleRate, audio_track->GetSamplingRate()); + EXPECT_EQ(kChannels, audio_track->GetChannels()); + EXPECT_EQ(kBitDepth, audio_track->GetBitDepth()); + EXPECT_STREQ(kVorbisCodecId, audio_track->GetCodecId()); + const unsigned int kTrackUid = 2; + EXPECT_EQ(kTrackUid, audio_track->GetUid()); + } + } +} + +TEST_F(ParserTest, SimpleBlock) { + ASSERT_TRUE(CreateAndLoadSegment("simple_block.webm")); + const unsigned int kTracksCount = 1; + EXPECT_EQ(kTracksCount, segment_->GetTracks()->GetTracksCount()); + + // Get the cluster + const Cluster* cluster = segment_->GetFirst(); + ASSERT_TRUE(cluster != NULL); + EXPECT_FALSE(cluster->EOS()); + + // Get the first block + const BlockEntry* block_entry; + EXPECT_EQ(0, cluster->GetFirst(block_entry)); + ASSERT_TRUE(block_entry != NULL); + EXPECT_FALSE(block_entry->EOS()); + CompareBlockContents(cluster, block_entry->GetBlock(), 0, kVideoTrackNumber, + false, 1); + + // Get the second block + EXPECT_EQ(0, cluster->GetNext(block_entry, block_entry)); + ASSERT_TRUE(block_entry != NULL); + EXPECT_FALSE(block_entry->EOS()); + CompareBlockContents(cluster, block_entry->GetBlock(), 2000000, + kVideoTrackNumber, false, 1); + + // End of Stream + EXPECT_EQ(0, cluster->GetNext(block_entry, block_entry)); + ASSERT_EQ(NULL, block_entry); + cluster = segment_->GetNext(cluster); + EXPECT_TRUE(cluster->EOS()); +} + +TEST_F(ParserTest, MultipleClusters) { + ASSERT_TRUE(CreateAndLoadSegment("force_new_cluster.webm")); + const unsigned int kTracksCount = 1; + EXPECT_EQ(kTracksCount, segment_->GetTracks()->GetTracksCount()); + + // Get the first cluster + const Cluster* cluster = segment_->GetFirst(); + ASSERT_TRUE(cluster != NULL); + EXPECT_FALSE(cluster->EOS()); + + // Get the first block + const BlockEntry* block_entry; + EXPECT_EQ(0, cluster->GetFirst(block_entry)); + ASSERT_TRUE(block_entry != NULL); + EXPECT_FALSE(block_entry->EOS()); + CompareBlockContents(cluster, block_entry->GetBlock(), 0, kVideoTrackNumber, + false, 1); + + // Get the second cluster + EXPECT_EQ(0, cluster->GetNext(block_entry, block_entry)); + EXPECT_EQ(NULL, block_entry); + cluster = segment_->GetNext(cluster); + ASSERT_TRUE(cluster != NULL); + EXPECT_FALSE(cluster->EOS()); + + // Get the second block + EXPECT_EQ(0, cluster->GetFirst(block_entry)); + ASSERT_TRUE(block_entry != NULL); + EXPECT_FALSE(block_entry->EOS()); + CompareBlockContents(cluster, block_entry->GetBlock(), 2000000, + kVideoTrackNumber, false, 1); + + // Get the third block + EXPECT_EQ(0, cluster->GetNext(block_entry, block_entry)); + ASSERT_TRUE(block_entry != NULL); + EXPECT_FALSE(block_entry->EOS()); + CompareBlockContents(cluster, block_entry->GetBlock(), 4000000, + kVideoTrackNumber, false, 1); + + // Get the third cluster + EXPECT_EQ(0, cluster->GetNext(block_entry, block_entry)); + EXPECT_EQ(NULL, block_entry); + cluster = segment_->GetNext(cluster); + ASSERT_TRUE(cluster != NULL); + EXPECT_FALSE(cluster->EOS()); + + // Get the fourth block + EXPECT_EQ(0, cluster->GetFirst(block_entry)); + ASSERT_TRUE(block_entry != NULL); + EXPECT_FALSE(block_entry->EOS()); + CompareBlockContents(cluster, block_entry->GetBlock(), 6000000, + kVideoTrackNumber, false, 1); + + // End of Stream + EXPECT_EQ(0, cluster->GetNext(block_entry, block_entry)); + EXPECT_EQ(NULL, block_entry); + cluster = segment_->GetNext(cluster); + EXPECT_TRUE(cluster->EOS()); +} + +TEST_F(ParserTest, BlockGroup) { + ASSERT_TRUE(CreateAndLoadSegment("metadata_block.webm")); + const unsigned int kTracksCount = 1; + EXPECT_EQ(kTracksCount, segment_->GetTracks()->GetTracksCount()); + + // Get the cluster + const Cluster* cluster = segment_->GetFirst(); + ASSERT_TRUE(cluster != NULL); + EXPECT_FALSE(cluster->EOS()); + + // Get the first block + const BlockEntry* block_entry; + EXPECT_EQ(0, cluster->GetFirst(block_entry)); + ASSERT_TRUE(block_entry != NULL); + EXPECT_FALSE(block_entry->EOS()); + EXPECT_EQ(BlockEntry::Kind::kBlockGroup, block_entry->GetKind()); + const BlockGroup* block_group = static_cast(block_entry); + EXPECT_EQ(2, block_group->GetDurationTimeCode()); + CompareBlockContents(cluster, block_group->GetBlock(), 0, + kMetadataTrackNumber, true, 1); + + // Get the second block + EXPECT_EQ(0, cluster->GetNext(block_entry, block_entry)); + ASSERT_TRUE(block_entry != NULL); + EXPECT_FALSE(block_entry->EOS()); + EXPECT_EQ(BlockEntry::Kind::kBlockGroup, block_entry->GetKind()); + block_group = static_cast(block_entry); + EXPECT_EQ(6, block_group->GetDurationTimeCode()); + CompareBlockContents(cluster, block_group->GetBlock(), 2000000, + kMetadataTrackNumber, true, 1); + + // End of Stream + EXPECT_EQ(0, cluster->GetNext(block_entry, block_entry)); + EXPECT_EQ(NULL, block_entry); + cluster = segment_->GetNext(cluster); + EXPECT_TRUE(cluster->EOS()); +} + +TEST_F(ParserTest, Cues) { + ASSERT_TRUE(CreateAndLoadSegment("output_cues.webm")); + const unsigned int kTracksCount = 1; + EXPECT_EQ(kTracksCount, segment_->GetTracks()->GetTracksCount()); + + const Track* const track = segment_->GetTracks()->GetTrackByIndex(0); + const Cues* const cues = segment_->GetCues(); + ASSERT_TRUE(cues != NULL); + while (!cues->DoneParsing()) { + cues->LoadCuePoint(); + } + EXPECT_EQ(3, cues->GetCount()); + + // Get first Cue Point + const CuePoint* cue_point = cues->GetFirst(); + CompareCuePointContents(track, cue_point, 0, kVideoTrackNumber, 206); + + // Get second Cue Point + cue_point = cues->GetNext(cue_point); + CompareCuePointContents(track, cue_point, 6000000, kVideoTrackNumber, 269); + + // Get third (also last) Cue Point + cue_point = cues->GetNext(cue_point); + const CuePoint* last_cue_point = cues->GetLast(); + EXPECT_TRUE(cue_point == last_cue_point); + CompareCuePointContents(track, cue_point, 4000000, kVideoTrackNumber, 269); + + EXPECT_TRUE(ValidateCues(segment_, &reader_)); +} + +TEST_F(ParserTest, CuesBeforeClusters) { + ASSERT_TRUE(CreateAndLoadSegment("cues_before_clusters.webm")); + const unsigned int kTracksCount = 1; + EXPECT_EQ(kTracksCount, segment_->GetTracks()->GetTracksCount()); + + const Track* const track = segment_->GetTracks()->GetTrackByIndex(0); + const Cues* const cues = segment_->GetCues(); + ASSERT_TRUE(cues != NULL); + while (!cues->DoneParsing()) { + cues->LoadCuePoint(); + } + EXPECT_EQ(2, cues->GetCount()); + + // Get first Cue Point + const CuePoint* cue_point = cues->GetFirst(); + CompareCuePointContents(track, cue_point, 0, kVideoTrackNumber, 238); + + // Get second (also last) Cue Point + cue_point = cues->GetNext(cue_point); + const CuePoint* last_cue_point = cues->GetLast(); + EXPECT_TRUE(cue_point == last_cue_point); + CompareCuePointContents(track, cue_point, 6000000, kVideoTrackNumber, 301); + + EXPECT_TRUE(ValidateCues(segment_, &reader_)); +} + +TEST_F(ParserTest, CuesTrackNumber) { + ASSERT_TRUE(CreateAndLoadSegment("set_cues_track_number.webm")); + const unsigned int kTracksCount = 1; + EXPECT_EQ(kTracksCount, segment_->GetTracks()->GetTracksCount()); + + const Track* const track = segment_->GetTracks()->GetTrackByIndex(0); + const Cues* const cues = segment_->GetCues(); + ASSERT_TRUE(cues != NULL); + while (!cues->DoneParsing()) { + cues->LoadCuePoint(); + } + EXPECT_EQ(2, cues->GetCount()); + + // Get first Cue Point + const CuePoint* cue_point = cues->GetFirst(); + CompareCuePointContents(track, cue_point, 0, 10, 206); + + // Get second (also last) Cue Point + cue_point = cues->GetNext(cue_point); + const CuePoint* last_cue_point = cues->GetLast(); + EXPECT_TRUE(cue_point == last_cue_point); + CompareCuePointContents(track, cue_point, 6000000, 10, 269); + + EXPECT_TRUE(ValidateCues(segment_, &reader_)); +} + +TEST_F(ParserTest, Opus) { + ASSERT_TRUE(CreateAndLoadSegment("bbb_480p_vp9_opus_1second.webm", 4)); + const unsigned int kTracksCount = 2; + EXPECT_EQ(kTracksCount, segment_->GetTracks()->GetTracksCount()); + + // -------------------------------------------------------------------------- + // Track Header validation. + const Tracks* const tracks = segment_->GetTracks(); + EXPECT_EQ(kTracksCount, tracks->GetTracksCount()); + for (int i = 0; i < 2; ++i) { + const Track* const track = tracks->GetTrackByIndex(i); + ASSERT_TRUE(track != NULL); + + EXPECT_EQ(NULL, track->GetNameAsUTF8()); + EXPECT_STREQ("und", track->GetLanguage()); + EXPECT_EQ(i + 1, track->GetNumber()); + EXPECT_FALSE(track->GetLacing()); + + if (track->GetType() == Track::kVideo) { + const VideoTrack* const video_track = + dynamic_cast(track); + EXPECT_EQ(854, static_cast(video_track->GetWidth())); + EXPECT_EQ(480, static_cast(video_track->GetHeight())); + EXPECT_STREQ(kVP9CodecId, video_track->GetCodecId()); + EXPECT_DOUBLE_EQ(0., video_track->GetFrameRate()); + EXPECT_EQ(41666666, + static_cast(video_track->GetDefaultDuration())); // 24.000 + const unsigned int kVideoUid = kVideoTrackNumber; + EXPECT_EQ(kVideoUid, video_track->GetUid()); + const unsigned int kCodecDelay = 0; + EXPECT_EQ(kCodecDelay, video_track->GetCodecDelay()); + const unsigned int kSeekPreRoll = 0; + EXPECT_EQ(kSeekPreRoll, video_track->GetSeekPreRoll()); + + size_t video_codec_private_size; + EXPECT_EQ(NULL, video_track->GetCodecPrivate(video_codec_private_size)); + const unsigned int kPrivateSize = 0; + EXPECT_EQ(kPrivateSize, video_codec_private_size); + } else if (track->GetType() == Track::kAudio) { + const AudioTrack* const audio_track = + dynamic_cast(track); + EXPECT_EQ(48000, audio_track->GetSamplingRate()); + EXPECT_EQ(6, audio_track->GetChannels()); + EXPECT_EQ(32, audio_track->GetBitDepth()); + EXPECT_STREQ(kOpusCodecId, audio_track->GetCodecId()); + EXPECT_EQ(kAudioTrackNumber, static_cast(audio_track->GetUid())); + const unsigned int kDefaultDuration = 0; + EXPECT_EQ(kDefaultDuration, audio_track->GetDefaultDuration()); + EXPECT_EQ(kOpusCodecDelay, audio_track->GetCodecDelay()); + EXPECT_EQ(kOpusSeekPreroll, audio_track->GetSeekPreRoll()); + + size_t audio_codec_private_size; + EXPECT_TRUE(audio_track->GetCodecPrivate(audio_codec_private_size) != + NULL); + EXPECT_GE(audio_codec_private_size, kOpusPrivateDataSizeMinimum); + } + } + + // -------------------------------------------------------------------------- + // Parse the file to do block-level validation. + const Cluster* cluster = segment_->GetFirst(); + ASSERT_TRUE(cluster != NULL); + EXPECT_FALSE(cluster->EOS()); + + for (; cluster != NULL && !cluster->EOS(); + cluster = segment_->GetNext(cluster)) { + // Get the first block + const BlockEntry* block_entry; + EXPECT_EQ(0, cluster->GetFirst(block_entry)); + ASSERT_TRUE(block_entry != NULL); + EXPECT_FALSE(block_entry->EOS()); + + while (block_entry != NULL && !block_entry->EOS()) { + const Block* const block = block_entry->GetBlock(); + ASSERT_TRUE(block != NULL); + EXPECT_FALSE(block->IsInvisible()); + EXPECT_EQ(Block::kLacingNone, block->GetLacing()); + + const std::uint32_t track_number = + static_cast(block->GetTrackNumber()); + const Track* const track = tracks->GetTrackByNumber(track_number); + ASSERT_TRUE(track != NULL); + EXPECT_EQ(track->GetNumber(), block->GetTrackNumber()); + const unsigned int kContentEncodingCount = 0; + EXPECT_EQ(kContentEncodingCount, + track->GetContentEncodingCount()); // no encryption + + const std::int64_t track_type = track->GetType(); + EXPECT_TRUE(track_type == Track::kVideo || track_type == Track::kAudio); + if (track_type == Track::kVideo) { + EXPECT_EQ(BlockEntry::kBlockSimple, block_entry->GetKind()); + EXPECT_EQ(0, block->GetDiscardPadding()); + } else { + EXPECT_TRUE(block->IsKey()); + const std::int64_t kLastAudioTimecode = 1001; + const std::int64_t timecode = block->GetTimeCode(cluster); + // Only the final Opus block should have discard padding. + if (timecode == kLastAudioTimecode) { + EXPECT_EQ(BlockEntry::kBlockGroup, block_entry->GetKind()); + EXPECT_EQ(13500000, block->GetDiscardPadding()); + } else { + EXPECT_EQ(BlockEntry::kBlockSimple, block_entry->GetKind()); + EXPECT_EQ(0, block->GetDiscardPadding()); + } + } + + const int frame_count = block->GetFrameCount(); + const Block::Frame& frame = block->GetFrame(0); + EXPECT_EQ(1, frame_count); + EXPECT_GT(frame.len, 0); + + EXPECT_EQ(0, cluster->GetNext(block_entry, block_entry)); + } + } + + ASSERT_TRUE(cluster != NULL); + EXPECT_TRUE(cluster->EOS()); +} + +TEST_F(ParserTest, DiscardPadding) { + // Test an artificial file with some extreme DiscardPadding values. + const std::string file = "discard_padding.webm"; + ASSERT_TRUE(CreateAndLoadSegment(file, 4)); + const unsigned int kTracksCount = 1; + EXPECT_EQ(kTracksCount, segment_->GetTracks()->GetTracksCount()); + + // -------------------------------------------------------------------------- + // Track Header validation. + const Tracks* const tracks = segment_->GetTracks(); + EXPECT_EQ(kTracksCount, tracks->GetTracksCount()); + const Track* const track = tracks->GetTrackByIndex(0); + ASSERT_TRUE(track != NULL); + + EXPECT_STREQ(NULL, track->GetNameAsUTF8()); + EXPECT_EQ(NULL, track->GetLanguage()); + EXPECT_EQ(kAudioTrackNumber, track->GetNumber()); + EXPECT_TRUE(track->GetLacing()); + + EXPECT_EQ(Track::kAudio, track->GetType()); + const AudioTrack* const audio_track = dynamic_cast(track); + EXPECT_EQ(30, audio_track->GetSamplingRate()); + EXPECT_EQ(2, audio_track->GetChannels()); + EXPECT_STREQ(kOpusCodecId, audio_track->GetCodecId()); + EXPECT_EQ(kAudioTrackNumber, static_cast(audio_track->GetUid())); + const unsigned int kDefaultDuration = 0; + EXPECT_EQ(kDefaultDuration, audio_track->GetDefaultDuration()); + const unsigned int kCodecDelay = 0; + EXPECT_EQ(kCodecDelay, audio_track->GetCodecDelay()); + const unsigned int kSeekPreRoll = 0; + EXPECT_EQ(kSeekPreRoll, audio_track->GetSeekPreRoll()); + + size_t audio_codec_private_size; + EXPECT_EQ(NULL, audio_track->GetCodecPrivate(audio_codec_private_size)); + const unsigned int kPrivateSize = 0; + EXPECT_EQ(kPrivateSize, audio_codec_private_size); + + // -------------------------------------------------------------------------- + // Parse the file to do block-level validation. + const Cluster* cluster = segment_->GetFirst(); + ASSERT_TRUE(cluster != NULL); + EXPECT_FALSE(cluster->EOS()); + const unsigned int kSegmentCount = 1; + EXPECT_EQ(kSegmentCount, segment_->GetCount()); + + // Get the first block + const BlockEntry* block_entry; + EXPECT_EQ(0, cluster->GetFirst(block_entry)); + ASSERT_TRUE(block_entry != NULL); + EXPECT_FALSE(block_entry->EOS()); + + const std::array discard_padding = {{12810000, 127, -128}}; + int index = 0; + while (block_entry != NULL && !block_entry->EOS()) { + const Block* const block = block_entry->GetBlock(); + ASSERT_TRUE(block != NULL); + EXPECT_FALSE(block->IsInvisible()); + EXPECT_EQ(Block::kLacingNone, block->GetLacing()); + + const std::uint32_t track_number = + static_cast(block->GetTrackNumber()); + const Track* const track = tracks->GetTrackByNumber(track_number); + ASSERT_TRUE(track != NULL); + EXPECT_EQ(track->GetNumber(), block->GetTrackNumber()); + const unsigned int kContentEncodingCount = 0; + EXPECT_EQ(kContentEncodingCount, + track->GetContentEncodingCount()); // no encryption + + const std::int64_t track_type = track->GetType(); + EXPECT_EQ(Track::kAudio, track_type); + EXPECT_TRUE(block->IsKey()); + + // All blocks have DiscardPadding. + EXPECT_EQ(BlockEntry::kBlockGroup, block_entry->GetKind()); + ASSERT_LT(index, static_cast(discard_padding.size())); + EXPECT_EQ(discard_padding[index], block->GetDiscardPadding()); + ++index; + + const int frame_count = block->GetFrameCount(); + const Block::Frame& frame = block->GetFrame(0); + EXPECT_EQ(1, frame_count); + EXPECT_GT(frame.len, 0); + + EXPECT_EQ(0, cluster->GetNext(block_entry, block_entry)); + } + + cluster = segment_->GetNext(cluster); + ASSERT_TRUE(cluster != NULL); + EXPECT_TRUE(cluster->EOS()); +} + +TEST_F(ParserTest, StereoModeParsedCorrectly) { + ASSERT_TRUE(CreateAndLoadSegment("test_stereo_left_right.webm")); + const unsigned int kTracksCount = 1; + EXPECT_EQ(kTracksCount, segment_->GetTracks()->GetTracksCount()); + + const VideoTrack* const video_track = dynamic_cast( + segment_->GetTracks()->GetTrackByIndex(0)); + + EXPECT_EQ(1, video_track->GetStereoMode()); + EXPECT_EQ(256, video_track->GetWidth()); + EXPECT_EQ(144, video_track->GetHeight()); + EXPECT_EQ(128, video_track->GetDisplayWidth()); + EXPECT_EQ(144, video_track->GetDisplayHeight()); +} + +TEST_F(ParserTest, CanParseColour) { + ASSERT_TRUE(CreateAndLoadSegment("colour.webm")); + const unsigned int kTracksCount = 1; + EXPECT_EQ(kTracksCount, segment_->GetTracks()->GetTracksCount()); + const VideoTrack* const video_track = dynamic_cast( + segment_->GetTracks()->GetTrackByIndex(0)); + + const mkvparser::Colour* const colour = video_track->GetColour(); + ASSERT_TRUE(colour != nullptr); + EXPECT_EQ(0u, colour->matrix_coefficients); + EXPECT_EQ(1u, colour->bits_per_channel); + EXPECT_EQ(2u, colour->chroma_subsampling_horz); + EXPECT_EQ(3u, colour->chroma_subsampling_vert); + EXPECT_EQ(4u, colour->cb_subsampling_horz); + EXPECT_EQ(5u, colour->cb_subsampling_vert); + EXPECT_EQ(1u, colour->chroma_siting_horz); + EXPECT_EQ(1u, colour->chroma_siting_vert); + EXPECT_EQ(2u, colour->range); + EXPECT_EQ(9u, colour->transfer_characteristics); + EXPECT_EQ(10u, colour->primaries); + EXPECT_EQ(11u, colour->max_cll); + EXPECT_EQ(12u, colour->max_fall); + + const mkvparser::MasteringMetadata* const mm = + video_track->GetColour()->mastering_metadata; + ASSERT_TRUE(mm != nullptr); + ASSERT_TRUE(mm->r != nullptr); + ASSERT_TRUE(mm->g != nullptr); + ASSERT_TRUE(mm->b != nullptr); + ASSERT_TRUE(mm->white_point != nullptr); + EXPECT_FLOAT_EQ(.1, mm->r->x); + EXPECT_FLOAT_EQ(.2, mm->r->y); + EXPECT_FLOAT_EQ(.1, mm->g->x); + EXPECT_FLOAT_EQ(.2, mm->g->y); + EXPECT_FLOAT_EQ(.1, mm->b->x); + EXPECT_FLOAT_EQ(.2, mm->b->y); + EXPECT_FLOAT_EQ(.1, mm->white_point->x); + EXPECT_FLOAT_EQ(.2, mm->white_point->y); + EXPECT_FLOAT_EQ(30.0, mm->luminance_min); + EXPECT_FLOAT_EQ(40.0, mm->luminance_max); +} + +TEST_F(ParserTest, CanParseProjection) { + ASSERT_TRUE(CreateAndLoadSegment("projection.webm")); + const unsigned int kTracksCount = 1; + EXPECT_EQ(kTracksCount, segment_->GetTracks()->GetTracksCount()); + const VideoTrack* const video_track = + static_cast(segment_->GetTracks()->GetTrackByIndex(0)); + + const mkvparser::Projection* const projection = video_track->GetProjection(); + ASSERT_TRUE(projection != nullptr); + EXPECT_EQ(mkvparser::Projection::kRectangular, projection->type); + EXPECT_FLOAT_EQ(1, projection->pose_yaw); + EXPECT_FLOAT_EQ(2, projection->pose_pitch); + EXPECT_FLOAT_EQ(3, projection->pose_roll); + EXPECT_EQ(1u, projection->private_data_length); + ASSERT_TRUE(projection->private_data != nullptr); + EXPECT_EQ(4u, projection->private_data[0]); +} + +TEST_F(ParserTest, Vp9CodecLevelTest) { + const int kCodecPrivateLength = 3; + const uint8_t good_codec_private_level[kCodecPrivateLength] = {2, 1, 11}; + libwebm::Vp9CodecFeatures features; + EXPECT_TRUE(libwebm::ParseVpxCodecPrivate(&good_codec_private_level[0], + kCodecPrivateLength, &features)); + EXPECT_EQ(libwebm::Vp9CodecFeatures::kValueNotPresent, features.profile); + EXPECT_EQ(11, features.level); + EXPECT_EQ(libwebm::Vp9CodecFeatures::kValueNotPresent, features.bit_depth); + EXPECT_EQ(libwebm::Vp9CodecFeatures::kValueNotPresent, + features.chroma_subsampling); +} + +TEST_F(ParserTest, Vp9CodecProfileTest) { + const int kCodecPrivateLength = 3; + const uint8_t good_codec_private_profile[kCodecPrivateLength] = {1, 1, 1}; + libwebm::Vp9CodecFeatures features; + EXPECT_TRUE(libwebm::ParseVpxCodecPrivate(&good_codec_private_profile[0], + kCodecPrivateLength, &features)); + EXPECT_EQ(1, features.profile); + EXPECT_EQ(libwebm::Vp9CodecFeatures::kValueNotPresent, features.level); + EXPECT_EQ(libwebm::Vp9CodecFeatures::kValueNotPresent, features.bit_depth); + EXPECT_EQ(libwebm::Vp9CodecFeatures::kValueNotPresent, + features.chroma_subsampling); +} + +TEST_F(ParserTest, Vp9CodecBitDepthTest) { + const int kCodecPrivateLength = 3; + const uint8_t good_codec_private_profile[kCodecPrivateLength] = {3, 1, 8}; + libwebm::Vp9CodecFeatures features; + EXPECT_TRUE(libwebm::ParseVpxCodecPrivate(&good_codec_private_profile[0], + kCodecPrivateLength, &features)); + EXPECT_EQ(libwebm::Vp9CodecFeatures::kValueNotPresent, features.profile); + EXPECT_EQ(libwebm::Vp9CodecFeatures::kValueNotPresent, features.level); + EXPECT_EQ(8, features.bit_depth); + EXPECT_EQ(libwebm::Vp9CodecFeatures::kValueNotPresent, + features.chroma_subsampling); +} + +TEST_F(ParserTest, Vp9CodecChromaSubsamplingTest) { + const int kCodecPrivateLength = 3; + const uint8_t good_codec_private_profile[kCodecPrivateLength] = {4, 1, 0}; + libwebm::Vp9CodecFeatures features; + EXPECT_TRUE(libwebm::ParseVpxCodecPrivate(&good_codec_private_profile[0], + kCodecPrivateLength, &features)); + EXPECT_EQ(libwebm::Vp9CodecFeatures::kValueNotPresent, features.profile); + EXPECT_EQ(libwebm::Vp9CodecFeatures::kValueNotPresent, features.level); + EXPECT_EQ(libwebm::Vp9CodecFeatures::kValueNotPresent, features.bit_depth); + EXPECT_EQ(0, features.chroma_subsampling); +} + +TEST_F(ParserTest, Vp9CodecProfileLevelTest) { + const int kCodecPrivateLength = 6; + const uint8_t codec_private[kCodecPrivateLength] = {1, 1, 1, 2, 1, 11}; + libwebm::Vp9CodecFeatures features; + EXPECT_TRUE(libwebm::ParseVpxCodecPrivate(&codec_private[0], + kCodecPrivateLength, &features)); + EXPECT_EQ(1, features.profile); + EXPECT_EQ(11, features.level); +} + +TEST_F(ParserTest, Vp9CodecAllTest) { + const int kCodecPrivateLength = 12; + const uint8_t codec_private[kCodecPrivateLength] = {1, 1, 1, 2, 1, 11, + 3, 1, 8, 4, 1, 0}; + libwebm::Vp9CodecFeatures features; + EXPECT_TRUE(libwebm::ParseVpxCodecPrivate(&codec_private[0], + kCodecPrivateLength, &features)); + EXPECT_EQ(1, features.profile); + EXPECT_EQ(11, features.level); + EXPECT_EQ(8, features.bit_depth); + EXPECT_EQ(0, features.chroma_subsampling); +} + +TEST_F(ParserTest, Vp9CodecPrivateBadTest) { + const int kCodecPrivateLength = 3; + libwebm::Vp9CodecFeatures features; + // Test invalid codec private data; all of these should return false. + const uint8_t bad_codec_private[kCodecPrivateLength] = {0, 0, 0}; + EXPECT_FALSE( + libwebm::ParseVpxCodecPrivate(NULL, kCodecPrivateLength, &features)); + EXPECT_FALSE( + libwebm::ParseVpxCodecPrivate(&bad_codec_private[0], 0, &features)); + EXPECT_FALSE(libwebm::ParseVpxCodecPrivate(&bad_codec_private[0], + kCodecPrivateLength, &features)); + const uint8_t good_codec_private_level[kCodecPrivateLength] = {2, 1, 11}; + + // Test parse of codec private chunks, but lie about length. + EXPECT_FALSE( + libwebm::ParseVpxCodecPrivate(&bad_codec_private[0], 0, &features)); + EXPECT_FALSE(libwebm::ParseVpxCodecPrivate(&good_codec_private_level[0], 0, + &features)); + EXPECT_FALSE(libwebm::ParseVpxCodecPrivate(&good_codec_private_level[0], + kCodecPrivateLength, NULL)); +} + +TEST_F(ParserTest, InvalidTruncatedChapterString) { + ASSERT_NO_FATAL_FAILURE(CreateSegmentNoHeaderChecks( + "invalid/chapters_truncated_chapter_string.mkv")); + EXPECT_EQ(mkvparser::E_PARSE_FAILED, segment_->Load()); +} + +TEST_F(ParserTest, InvalidTruncatedChapterString2) { + ASSERT_NO_FATAL_FAILURE(CreateSegmentNoHeaderChecks( + "invalid/chapters_truncated_chapter_string_2.mkv")); + EXPECT_EQ(mkvparser::E_FILE_FORMAT_INVALID, segment_->Load()); +} + +TEST_F(ParserTest, InvalidFixedLacingSize) { + ASSERT_NO_FATAL_FAILURE( + CreateSegmentNoHeaderChecks("invalid/fixed_lacing_bad_lace_size.mkv")); + ASSERT_EQ(0, segment_->Load()); + const mkvparser::BlockEntry* block_entry = NULL; + EXPECT_EQ(mkvparser::E_FILE_FORMAT_INVALID, + segment_->GetFirst()->GetFirst(block_entry)); +} + +TEST_F(ParserTest, InvalidBlockEndsBeyondCluster) { + ASSERT_NO_FATAL_FAILURE( + CreateSegmentNoHeaderChecks("invalid/block_ends_beyond_cluster.mkv")); + ASSERT_EQ(0, segment_->Load()); + const mkvparser::BlockEntry* block_entry = NULL; + EXPECT_EQ(0, segment_->GetFirst()->GetFirst(block_entry)); + EXPECT_EQ(mkvparser::E_FILE_FORMAT_INVALID, + segment_->GetFirst()->GetNext(block_entry, block_entry)); +} + +TEST_F(ParserTest, InvalidBlockGroupBlockEndsBlockGroup) { + ASSERT_NO_FATAL_FAILURE(CreateSegmentNoHeaderChecks( + "invalid/blockgroup_block_ends_beyond_blockgroup.mkv")); + ASSERT_EQ(0, segment_->Load()); + const mkvparser::BlockEntry* block_entry = NULL; + EXPECT_EQ(0, segment_->GetFirst()->GetFirst(block_entry)); + EXPECT_EQ(mkvparser::E_FILE_FORMAT_INVALID, + segment_->GetFirst()->GetNext(block_entry, block_entry)); +} + +TEST_F(ParserTest, InvalidProjectionFloatOverflow) { + ASSERT_NO_FATAL_FAILURE( + CreateSegmentNoHeaderChecks("invalid/projection_float_overflow.webm")); + EXPECT_EQ(mkvparser::E_FILE_FORMAT_INVALID, segment_->Load()); +} + +TEST_F(ParserTest, InvalidPrimaryChromaticityParseFail) { + ASSERT_NO_FATAL_FAILURE(CreateSegmentNoHeaderChecks( + "invalid/primarychromaticity_fieldtoolarge.webm")); + EXPECT_EQ(mkvparser::E_FILE_FORMAT_INVALID, segment_->Load()); +} + +} // namespace test + +int main(int argc, char* argv[]) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/third_party/libwebm/source/testing/test_util.cc b/third_party/libwebm/source/testing/test_util.cc new file mode 100644 index 000000000000..8789b3325b24 --- /dev/null +++ b/third_party/libwebm/source/testing/test_util.cc @@ -0,0 +1,215 @@ +// Copyright (c) 2016 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +#include "testing/test_util.h" + +#include +#include +#include +#include +#include +#include + +#include "common/libwebm_util.h" +#include "common/webmids.h" + +#include "mkvparser/mkvparser.h" +#include "mkvparser/mkvreader.h" + +namespace test { + +std::string GetTestDataDir() { + const char* test_data_path = std::getenv("LIBWEBM_TEST_DATA_PATH"); + return test_data_path ? std::string(test_data_path) : std::string(); +} + +std::string GetTestFilePath(const std::string& name) { + const std::string libwebm_testdata_dir = GetTestDataDir(); + return libwebm_testdata_dir + "/" + name; +} + +bool CompareFiles(const std::string& file1, const std::string& file2) { + const std::size_t kBlockSize = 4096; + std::uint8_t buf1[kBlockSize] = {0}; + std::uint8_t buf2[kBlockSize] = {0}; + + libwebm::FilePtr f1 = + libwebm::FilePtr(std::fopen(file1.c_str(), "rb"), libwebm::FILEDeleter()); + libwebm::FilePtr f2 = + libwebm::FilePtr(std::fopen(file2.c_str(), "rb"), libwebm::FILEDeleter()); + + if (!f1.get() || !f2.get()) { + // Files cannot match if one or both couldn't be opened. + return false; + } + + do { + const std::size_t r1 = std::fread(buf1, 1, kBlockSize, f1.get()); + const std::size_t r2 = std::fread(buf2, 1, kBlockSize, f2.get()); + + // TODO(fgalligan): Add output of which byte differs. + if (r1 != r2 || std::memcmp(buf1, buf2, r1)) { + return 0; // Files are not equal + } + } while (!std::feof(f1.get()) && !std::feof(f2.get())); + + return std::feof(f1.get()) && std::feof(f2.get()); +} + +bool HasCuePoints(const mkvparser::Segment* segment, + std::int64_t* cues_offset) { + if (!segment || !cues_offset) { + return false; + } + using mkvparser::SeekHead; + const SeekHead* const seek_head = segment->GetSeekHead(); + if (!seek_head) { + return false; + } + + std::int64_t offset = 0; + for (int i = 0; i < seek_head->GetCount(); ++i) { + const SeekHead::Entry* const entry = seek_head->GetEntry(i); + if (entry->id == libwebm::kMkvCues) { + offset = entry->pos; + } + } + + if (offset <= 0) { + // No Cues found. + return false; + } + + *cues_offset = offset; + return true; +} + +bool ValidateCues(mkvparser::Segment* segment, mkvparser::IMkvReader* reader) { + if (!segment) { + return false; + } + + std::int64_t cues_offset = 0; + if (!HasCuePoints(segment, &cues_offset)) { + // No cues to validate, everything is OK. + return true; + } + + // Parse Cues. + long long cues_pos = 0; // NOLINT + long cues_len = 0; // NOLINT + if (segment->ParseCues(cues_offset, cues_pos, cues_len)) { + return false; + } + + // Get a pointer to the video track if it exists. Otherwise, we assume + // that Cues are based on the first track (which is true for all our test + // files). + const mkvparser::Tracks* const tracks = segment->GetTracks(); + const mkvparser::Track* cues_track = tracks->GetTrackByIndex(0); + for (int i = 1; i < static_cast(tracks->GetTracksCount()); ++i) { + const mkvparser::Track* const track = tracks->GetTrackByIndex(i); + if (track->GetType() == mkvparser::Track::kVideo) { + cues_track = track; + break; + } + } + + // Iterate through Cues and verify if they are pointing to the correct + // Cluster position. + const mkvparser::Cues* const cues = segment->GetCues(); + const mkvparser::CuePoint* cue_point = NULL; + while (cues->LoadCuePoint()) { + if (!cue_point) { + cue_point = cues->GetFirst(); + } else { + cue_point = cues->GetNext(cue_point); + } + const mkvparser::CuePoint::TrackPosition* const track_position = + cue_point->Find(cues_track); + const long long cluster_pos = track_position->m_pos + // NOLINT + segment->m_start; + + // If a cluster does not begin at |cluster_pos|, then the file is + // incorrect. + long length; // NOLINT + const std::int64_t id = mkvparser::ReadID(reader, cluster_pos, length); + if (id != libwebm::kMkvCluster) { + return false; + } + } + return true; +} + +MkvParser::~MkvParser() { + delete segment; + delete reader; +} + +bool ParseMkvFileReleaseParser(const std::string& webm_file, + MkvParser* parser_out) { + parser_out->reader = new (std::nothrow) mkvparser::MkvReader; + mkvparser::MkvReader& reader = *parser_out->reader; + if (!parser_out->reader || reader.Open(webm_file.c_str()) < 0) { + return false; + } + + long long pos = 0; // NOLINT + mkvparser::EBMLHeader ebml_header; + if (ebml_header.Parse(&reader, pos)) { + return false; + } + + using mkvparser::Segment; + Segment* segment_ptr = nullptr; + if (Segment::CreateInstance(&reader, pos, segment_ptr)) { + return false; + } + + std::unique_ptr segment(segment_ptr); + long result; + if ((result = segment->Load()) < 0) { + return false; + } + + const mkvparser::Cluster* cluster = segment->GetFirst(); + if (!cluster || cluster->EOS()) { + return false; + } + + while (cluster && cluster->EOS() == false) { + if (cluster->GetTimeCode() < 0) { + return false; + } + + const mkvparser::BlockEntry* block = nullptr; + if (cluster->GetFirst(block) < 0) { + return false; + } + + while (block != NULL && block->EOS() == false) { + if (cluster->GetNext(block, block) < 0) { + return false; + } + } + + cluster = segment->GetNext(cluster); + } + + parser_out->segment = segment.release(); + return true; +} + +bool ParseMkvFile(const std::string& webm_file) { + MkvParser parser; + const bool result = ParseMkvFileReleaseParser(webm_file, &parser); + delete parser.segment; + delete parser.reader; + return result; +} + +} // namespace test diff --git a/third_party/libwebm/source/testing/test_util.h b/third_party/libwebm/source/testing/test_util.h new file mode 100644 index 000000000000..5f85ec74e764 --- /dev/null +++ b/third_party/libwebm/source/testing/test_util.h @@ -0,0 +1,88 @@ +// Copyright (c) 2016 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +#ifndef LIBWEBM_TESTING_TEST_UTIL_H_ +#define LIBWEBM_TESTING_TEST_UTIL_H_ + +#include + +#include +#include + +namespace mkvparser { +class IMkvReader; +class MkvReader; +class Segment; +} // namespace mkvparser + +namespace test { + +// constants for muxer and parser tests +const char kAppString[] = "mkvmuxer_unit_tests"; +const char kOpusCodecId[] = "A_OPUS"; +const char kVorbisCodecId[] = "A_VORBIS"; +const int kAudioTrackNumber = 2; +const int kBitDepth = 2; +const int kChannels = 2; +const double kDuration = 2.345; +const int kFrameLength = 10; +const int kHeight = 180; +const int kInvalidTrackNumber = 100; +const std::uint64_t kOpusCodecDelay = 6500000; +const std::size_t kOpusPrivateDataSizeMinimum = 19; +const std::uint64_t kOpusSeekPreroll = 80000000; +const char kMetadataCodecId[] = "D_WEBVTT/METADATA"; +const int kMetadataTrackNumber = 3; +const int kMetadataTrackType = 0x21; +const int kSampleRate = 30; +const int kTimeCodeScale = 1000; +const char kTrackName[] = "unit_test"; +const char kVP8CodecId[] = "V_VP8"; +const char kVP9CodecId[] = "V_VP9"; +const double kVideoFrameRate = 0.5; +const int kVideoTrackNumber = 1; +const int kWidth = 320; + +// Returns the path to the test data directory by reading and returning the +// contents the LIBWEBM_TESTDATA_DIR environment variable. +std::string GetTestDataDir(); + +// Returns the absolute path to the file of |name| in LIBWEBM_TESTDATA_DIR. +std::string GetTestFilePath(const std::string& name); + +// Byte-wise comparison of two files |file1| and |file2|. Returns true if the +// files match exactly, false otherwise. +bool CompareFiles(const std::string& file1, const std::string& file2); + +// Returns true and sets |cues_offset| to the cues location within the MKV file +// parsed by |segment| when the MKV file has cue points. +bool HasCuePoints(const mkvparser::Segment* segment, std::int64_t* cues_offset); + +// Validates cue points. Assumes caller has already called Load() on |segment|. +// Returns true when: +// All cue points point at clusters, OR +// Data parsed by |segment| has no cue points. +bool ValidateCues(mkvparser::Segment* segment, mkvparser::IMkvReader* reader); + +// Parses |webm_file| using mkvparser and returns true when file parses +// successfully (all clusters and blocks can be successfully walked). Second +// variant allows further interaction with the parsed file via transferring +// ownership of the mkvparser Segment and MkvReader to the caller via +// |parser_out|. +struct MkvParser { + MkvParser() = default; + ~MkvParser(); + mkvparser::Segment* segment = nullptr; + mkvparser::MkvReader* reader = nullptr; +}; +bool ParseMkvFile(const std::string& webm_file); +bool ParseMkvFileReleaseParser(const std::string& webm_file, + MkvParser* parser_out); + +} // namespace test + +#endif // LIBWEBM_TESTING_TEST_UTIL_H_ \ No newline at end of file diff --git a/third_party/libwebm/source/testing/testdata/accurate_cluster_duration.webm b/third_party/libwebm/source/testing/testdata/accurate_cluster_duration.webm new file mode 100644 index 000000000000..fffe83d7d6dc Binary files /dev/null and b/third_party/libwebm/source/testing/testdata/accurate_cluster_duration.webm differ diff --git a/third_party/libwebm/source/testing/testdata/accurate_cluster_duration_last_frame.webm b/third_party/libwebm/source/testing/testdata/accurate_cluster_duration_last_frame.webm new file mode 100644 index 000000000000..8104bfcc8a84 Binary files /dev/null and b/third_party/libwebm/source/testing/testdata/accurate_cluster_duration_last_frame.webm differ diff --git a/third_party/libwebm/source/testing/testdata/accurate_cluster_duration_two_tracks.webm b/third_party/libwebm/source/testing/testdata/accurate_cluster_duration_two_tracks.webm new file mode 100644 index 000000000000..cf6985910621 Binary files /dev/null and b/third_party/libwebm/source/testing/testdata/accurate_cluster_duration_two_tracks.webm differ diff --git a/third_party/libwebm/source/testing/testdata/bbb_480p_vp9_opus_1second.webm b/third_party/libwebm/source/testing/testdata/bbb_480p_vp9_opus_1second.webm new file mode 100644 index 000000000000..c3657a74df59 Binary files /dev/null and b/third_party/libwebm/source/testing/testdata/bbb_480p_vp9_opus_1second.webm differ diff --git a/third_party/libwebm/source/testing/testdata/block_with_additional.webm b/third_party/libwebm/source/testing/testdata/block_with_additional.webm new file mode 100644 index 000000000000..2f1b22cc9169 Binary files /dev/null and b/third_party/libwebm/source/testing/testdata/block_with_additional.webm differ diff --git a/third_party/libwebm/source/testing/testdata/chapters.webm b/third_party/libwebm/source/testing/testdata/chapters.webm new file mode 100644 index 000000000000..af0c5fe21493 Binary files /dev/null and b/third_party/libwebm/source/testing/testdata/chapters.webm differ diff --git a/third_party/libwebm/source/testing/testdata/colour.webm b/third_party/libwebm/source/testing/testdata/colour.webm new file mode 100644 index 000000000000..580cb50aad5e Binary files /dev/null and b/third_party/libwebm/source/testing/testdata/colour.webm differ diff --git a/third_party/libwebm/source/testing/testdata/cues_before_clusters.webm b/third_party/libwebm/source/testing/testdata/cues_before_clusters.webm new file mode 100644 index 000000000000..c634b179d971 Binary files /dev/null and b/third_party/libwebm/source/testing/testdata/cues_before_clusters.webm differ diff --git a/third_party/libwebm/source/testing/testdata/discard_padding.webm b/third_party/libwebm/source/testing/testdata/discard_padding.webm new file mode 100644 index 000000000000..a5732260b625 Binary files /dev/null and b/third_party/libwebm/source/testing/testdata/discard_padding.webm differ diff --git a/third_party/libwebm/source/testing/testdata/estimate_duration.webm b/third_party/libwebm/source/testing/testdata/estimate_duration.webm new file mode 100644 index 000000000000..c7547414d478 Binary files /dev/null and b/third_party/libwebm/source/testing/testdata/estimate_duration.webm differ diff --git a/third_party/libwebm/source/testing/testdata/fixed_size_cluster_timecode.webm b/third_party/libwebm/source/testing/testdata/fixed_size_cluster_timecode.webm new file mode 100644 index 000000000000..c6f1cc635c55 Binary files /dev/null and b/third_party/libwebm/source/testing/testdata/fixed_size_cluster_timecode.webm differ diff --git a/third_party/libwebm/source/testing/testdata/force_new_cluster.webm b/third_party/libwebm/source/testing/testdata/force_new_cluster.webm new file mode 100644 index 000000000000..f762b0715123 Binary files /dev/null and b/third_party/libwebm/source/testing/testdata/force_new_cluster.webm differ diff --git a/third_party/libwebm/source/testing/testdata/invalid/README.libwebm b/third_party/libwebm/source/testing/testdata/invalid/README.libwebm new file mode 100644 index 000000000000..f9e9413b0d98 --- /dev/null +++ b/third_party/libwebm/source/testing/testdata/invalid/README.libwebm @@ -0,0 +1,24 @@ +Why the files in this directory are considered invalid: + +block_ends_beyond_cluster.mkv - + File containing a single cluster with two simple blocks. One valid, and the + second reporting a size that would cause the block to end far beyond the end + of its parent cluster. + +blockgroup_block_ends_beyond_blockgroup.mkv - + File containing a single cluster and two blockgroups. The first blockgroup is + valid. The second blockgroup contains a block reporting a size that spans well + past the block and the end of the file. + +chapters_truncated_chapter_string.mkv - + File with a Chapters element that ends with a ChapterAtom whose ChapterDisplay + element contains a truncated ChapterString. + +chapters_truncated_chapter_string_2.mkv - + Nearly identical to chapters_truncated_chapter_string.mkv, but with a void + element and a partial cluster. Causes mkvparser to fail in a slightly + different manner. + +fixed_lacing_bad_lace_size.mkv - + File containing a BlockGroup with fixed lacing, but reports a total laced size + that is not evenly divisible by the number of laced frames. diff --git a/third_party/libwebm/source/testing/testdata/invalid/block_ends_beyond_cluster.mkv b/third_party/libwebm/source/testing/testdata/invalid/block_ends_beyond_cluster.mkv new file mode 100644 index 000000000000..3035c8c8235d Binary files /dev/null and b/third_party/libwebm/source/testing/testdata/invalid/block_ends_beyond_cluster.mkv differ diff --git a/third_party/libwebm/source/testing/testdata/invalid/blockgroup_block_ends_beyond_blockgroup.mkv b/third_party/libwebm/source/testing/testdata/invalid/blockgroup_block_ends_beyond_blockgroup.mkv new file mode 100644 index 000000000000..da9aca9082c8 Binary files /dev/null and b/third_party/libwebm/source/testing/testdata/invalid/blockgroup_block_ends_beyond_blockgroup.mkv differ diff --git a/third_party/libwebm/source/testing/testdata/invalid/chapters_truncated_chapter_string.mkv b/third_party/libwebm/source/testing/testdata/invalid/chapters_truncated_chapter_string.mkv new file mode 100644 index 000000000000..9883e77808af Binary files /dev/null and b/third_party/libwebm/source/testing/testdata/invalid/chapters_truncated_chapter_string.mkv differ diff --git a/third_party/libwebm/source/testing/testdata/invalid/chapters_truncated_chapter_string_2.mkv b/third_party/libwebm/source/testing/testdata/invalid/chapters_truncated_chapter_string_2.mkv new file mode 100644 index 000000000000..37f04039937a Binary files /dev/null and b/third_party/libwebm/source/testing/testdata/invalid/chapters_truncated_chapter_string_2.mkv differ diff --git a/third_party/libwebm/source/testing/testdata/invalid/fixed_lacing_bad_lace_size.mkv b/third_party/libwebm/source/testing/testdata/invalid/fixed_lacing_bad_lace_size.mkv new file mode 100644 index 000000000000..bbe2025cb677 Binary files /dev/null and b/third_party/libwebm/source/testing/testdata/invalid/fixed_lacing_bad_lace_size.mkv differ diff --git a/third_party/libwebm/source/testing/testdata/invalid/invalid_vp9_bitstream-bug_1416.webm b/third_party/libwebm/source/testing/testdata/invalid/invalid_vp9_bitstream-bug_1416.webm new file mode 100644 index 000000000000..ac76dce86be6 Binary files /dev/null and b/third_party/libwebm/source/testing/testdata/invalid/invalid_vp9_bitstream-bug_1416.webm differ diff --git a/third_party/libwebm/source/testing/testdata/invalid/invalid_vp9_bitstream-bug_1417.webm b/third_party/libwebm/source/testing/testdata/invalid/invalid_vp9_bitstream-bug_1417.webm new file mode 100644 index 000000000000..0cbd724060eb Binary files /dev/null and b/third_party/libwebm/source/testing/testdata/invalid/invalid_vp9_bitstream-bug_1417.webm differ diff --git a/third_party/libwebm/source/testing/testdata/invalid/primarychromaticity_fieldtoolarge.webm b/third_party/libwebm/source/testing/testdata/invalid/primarychromaticity_fieldtoolarge.webm new file mode 100644 index 000000000000..c4324251ab8b --- /dev/null +++ b/third_party/libwebm/source/testing/testdata/invalid/primarychromaticity_fieldtoolarge.webm @@ -0,0 +1 @@ +EߣŸB00B00B00B00B‚„webmB00B00S€g0000000»‹00000000000»Œ000000000000ì¼000000000000000000000000000000000000000000000000000000000000€“0000000000000000000W0“0000000000000000000T®k@ž®@›×0s00ƒ†…00000à@‡°‚00º0U°ýU¸0U¹0Uº0U»0U¼0U½0UÐÆUÙ„0000UÚ„0000UÑ„0000UÒ000000000000000000000000000000000000000000000000000000000000000000000000000 \ No newline at end of file diff --git a/third_party/libwebm/source/testing/testdata/invalid/projection_float_overflow.webm b/third_party/libwebm/source/testing/testdata/invalid/projection_float_overflow.webm new file mode 100644 index 000000000000..46f6208e4900 Binary files /dev/null and b/third_party/libwebm/source/testing/testdata/invalid/projection_float_overflow.webm differ diff --git a/third_party/libwebm/source/testing/testdata/long_tag_string.webm b/third_party/libwebm/source/testing/testdata/long_tag_string.webm new file mode 100644 index 000000000000..e8d665300a45 Binary files /dev/null and b/third_party/libwebm/source/testing/testdata/long_tag_string.webm differ diff --git a/third_party/libwebm/source/testing/testdata/matroska_doctype.mkv b/third_party/libwebm/source/testing/testdata/matroska_doctype.mkv new file mode 100644 index 000000000000..56527855fe48 Binary files /dev/null and b/third_party/libwebm/source/testing/testdata/matroska_doctype.mkv differ diff --git a/third_party/libwebm/source/testing/testdata/max_cluster_duration.webm b/third_party/libwebm/source/testing/testdata/max_cluster_duration.webm new file mode 100644 index 000000000000..9caad9c1bd57 Binary files /dev/null and b/third_party/libwebm/source/testing/testdata/max_cluster_duration.webm differ diff --git a/third_party/libwebm/source/testing/testdata/max_cluster_size.webm b/third_party/libwebm/source/testing/testdata/max_cluster_size.webm new file mode 100644 index 000000000000..df87536fc107 Binary files /dev/null and b/third_party/libwebm/source/testing/testdata/max_cluster_size.webm differ diff --git a/third_party/libwebm/source/testing/testdata/metadata_block.webm b/third_party/libwebm/source/testing/testdata/metadata_block.webm new file mode 100644 index 000000000000..a9c686e00176 Binary files /dev/null and b/third_party/libwebm/source/testing/testdata/metadata_block.webm differ diff --git a/third_party/libwebm/source/testing/testdata/output_cues.webm b/third_party/libwebm/source/testing/testdata/output_cues.webm new file mode 100644 index 000000000000..49e2126139be Binary files /dev/null and b/third_party/libwebm/source/testing/testdata/output_cues.webm differ diff --git a/third_party/libwebm/source/testing/testdata/projection.webm b/third_party/libwebm/source/testing/testdata/projection.webm new file mode 100644 index 000000000000..0f13e8a6573b Binary files /dev/null and b/third_party/libwebm/source/testing/testdata/projection.webm differ diff --git a/third_party/libwebm/source/testing/testdata/segment_duration.webm b/third_party/libwebm/source/testing/testdata/segment_duration.webm new file mode 100644 index 000000000000..47cfb6de65e7 Binary files /dev/null and b/third_party/libwebm/source/testing/testdata/segment_duration.webm differ diff --git a/third_party/libwebm/source/testing/testdata/segment_info.webm b/third_party/libwebm/source/testing/testdata/segment_info.webm new file mode 100644 index 000000000000..0fde8f0687bf Binary files /dev/null and b/third_party/libwebm/source/testing/testdata/segment_info.webm differ diff --git a/third_party/libwebm/source/testing/testdata/set_cues_track_number.webm b/third_party/libwebm/source/testing/testdata/set_cues_track_number.webm new file mode 100644 index 000000000000..82a2b384b6cf Binary files /dev/null and b/third_party/libwebm/source/testing/testdata/set_cues_track_number.webm differ diff --git a/third_party/libwebm/source/testing/testdata/set_pixelwidth_pixelheight.webm b/third_party/libwebm/source/testing/testdata/set_pixelwidth_pixelheight.webm new file mode 100644 index 000000000000..e81c8bcd4f22 Binary files /dev/null and b/third_party/libwebm/source/testing/testdata/set_pixelwidth_pixelheight.webm differ diff --git a/third_party/libwebm/source/testing/testdata/set_segment_duration.webm b/third_party/libwebm/source/testing/testdata/set_segment_duration.webm new file mode 100644 index 000000000000..100684bfe663 Binary files /dev/null and b/third_party/libwebm/source/testing/testdata/set_segment_duration.webm differ diff --git a/third_party/libwebm/source/testing/testdata/simple_block.webm b/third_party/libwebm/source/testing/testdata/simple_block.webm new file mode 100644 index 000000000000..c311e681162c Binary files /dev/null and b/third_party/libwebm/source/testing/testdata/simple_block.webm differ diff --git a/third_party/libwebm/source/testing/testdata/test_stereo_left_right.webm b/third_party/libwebm/source/testing/testdata/test_stereo_left_right.webm new file mode 100644 index 000000000000..8c717dcbdefa Binary files /dev/null and b/third_party/libwebm/source/testing/testdata/test_stereo_left_right.webm differ diff --git a/third_party/libwebm/source/testing/testdata/tracks.webm b/third_party/libwebm/source/testing/testdata/tracks.webm new file mode 100644 index 000000000000..8aa9274fc5fe Binary files /dev/null and b/third_party/libwebm/source/testing/testdata/tracks.webm differ diff --git a/third_party/libwebm/source/testing/testdata/webm_doctype.webm b/third_party/libwebm/source/testing/testdata/webm_doctype.webm new file mode 100644 index 000000000000..4269030f390c Binary files /dev/null and b/third_party/libwebm/source/testing/testdata/webm_doctype.webm differ diff --git a/third_party/libwebm/source/testing/video_frame_tests.cc b/third_party/libwebm/source/testing/video_frame_tests.cc new file mode 100644 index 000000000000..4e5b3976c4f4 --- /dev/null +++ b/third_party/libwebm/source/testing/video_frame_tests.cc @@ -0,0 +1,75 @@ +// Copyright (c) 2016 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +#include "common/video_frame.h" + +#include "gtest/gtest.h" + +namespace { +const libwebm::VideoFrame::Codec kCodec = libwebm::VideoFrame::kVP8; +const std::int64_t kPts = 12345; +const std::size_t kSize = 1; +const std::size_t kEmptySize = 0; + +TEST(VideoFrameTests, DefaultsTest) { + libwebm::VideoFrame frame; + EXPECT_EQ(kEmptySize, frame.buffer().capacity); + EXPECT_EQ(kEmptySize, frame.buffer().length); + EXPECT_EQ(nullptr, frame.buffer().data.get()); + EXPECT_FALSE(frame.keyframe()); + EXPECT_EQ(0, frame.nanosecond_pts()); + EXPECT_EQ(libwebm::VideoFrame::kVP9, frame.codec()); +} + +TEST(VideoFrameTests, SizeTest) { + libwebm::VideoFrame frame; + EXPECT_TRUE(frame.Init(kSize)); + + // Buffer inits empty, length should be 0, aka |kEmpty|. + EXPECT_GT(kSize, frame.buffer().length); + EXPECT_EQ(kEmptySize, frame.buffer().length); + + // Capacity should be equal to |kSize|. + EXPECT_EQ(kSize, frame.buffer().capacity); + EXPECT_FALSE(frame.SetBufferLength(kSize + 1)); + + // Write a byte into the buffer via the raw data pointer, update length, and + // verify expected behavior. + uint8_t* write_ptr = reinterpret_cast(frame.buffer().data.get()); + *write_ptr = 0xFF; + EXPECT_TRUE(frame.SetBufferLength(1)); + EXPECT_EQ(frame.buffer().length, frame.buffer().capacity); +} + +TEST(VideoFrameTests, OverloadsTest) { + const bool kKeyframe = true; + + // Test VideoFrame::VideoFrame(bool keyframe, int64_t nano_pts, Codec c). + libwebm::VideoFrame keyframe(kKeyframe, kPts, kCodec); + EXPECT_EQ(kKeyframe, keyframe.keyframe()); + EXPECT_EQ(kPts, keyframe.nanosecond_pts()); + EXPECT_EQ(kCodec, keyframe.codec()); + EXPECT_EQ(kEmptySize, keyframe.buffer().capacity); + EXPECT_EQ(kEmptySize, keyframe.buffer().length); + EXPECT_EQ(nullptr, keyframe.buffer().data.get()); + + // Test VideoFrame::Init(std::size_t length). + EXPECT_TRUE(keyframe.Init(kSize)); + EXPECT_EQ(kKeyframe, keyframe.keyframe()); + EXPECT_EQ(kPts, keyframe.nanosecond_pts()); + EXPECT_EQ(kCodec, keyframe.codec()); + EXPECT_NE(nullptr, keyframe.buffer().data.get()); + + // Test VideoFrame::Init(size_t length, int64_t nano_pts, Codec c). + EXPECT_TRUE(keyframe.Init(kSize, kPts + 1, libwebm::VideoFrame::kVP9)); + EXPECT_EQ(kSize, keyframe.buffer().capacity); + EXPECT_GT(kSize, keyframe.buffer().length); + EXPECT_NE(kPts, keyframe.nanosecond_pts()); + EXPECT_NE(kCodec, keyframe.codec()); +} + +} // namespace diff --git a/third_party/libwebm/source/vttdemux.cc b/third_party/libwebm/source/vttdemux.cc new file mode 100644 index 000000000000..186783b08fb7 --- /dev/null +++ b/third_party/libwebm/source/vttdemux.cc @@ -0,0 +1,1004 @@ +// Copyright (c) 2012 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. + +#include +#include +#include +#include +#include +#include +#include + +#include "mkvparser/mkvparser.h" +#include "mkvparser/mkvreader.h" +#include "webvtt/webvttparser.h" + +using std::string; + +namespace libwebm { +namespace vttdemux { + +typedef long long mkvtime_t; // NOLINT +typedef long long mkvpos_t; // NOLINT +typedef std::unique_ptr segment_ptr_t; + +// WebVTT metadata tracks have a type (encoded in the CodecID for the track). +// We use |type| to synthesize a filename for the out-of-band WebVTT |file|. +struct MetadataInfo { + enum Type { kSubtitles, kCaptions, kDescriptions, kMetadata, kChapters } type; + FILE* file; +}; + +// We use a map, indexed by track number, to collect information about +// each track in the input file. +typedef std::map metadata_map_t; // NOLINT + +// The distinguished key value we use to store the chapters +// information in the metadata map. +enum { kChaptersKey = 0 }; + +// The data from the original WebVTT Cue is stored as a WebM block. +// The FrameParser is used to parse the lines of text out from the +// block, in order to reconstruct the original WebVTT Cue. +class FrameParser : public libwebvtt::LineReader { + public: + // Bind the FrameParser instance to a WebM block. + explicit FrameParser(const mkvparser::BlockGroup* block_group); + virtual ~FrameParser(); + + // The Webm block (group) to which this instance is bound. We + // treat the payload of the block as a stream of characters. + const mkvparser::BlockGroup* const block_group_; + + protected: + // Read the next character from the character stream (the payload + // of the WebM block). We increment the stream pointer |pos_| as + // each character from the stream is consumed. + virtual int GetChar(char* c); + + // End-of-line handling requires that we put a character back into + // the stream. Here we need only decrement the stream pointer |pos_| + // to unconsume the character. + virtual void UngetChar(char c); + + // The current position in the character stream (the payload of the block). + mkvpos_t pos_; + + // The position of the end of the character stream. When the current + // position |pos_| equals the end position |pos_end_|, the entire + // stream (block payload) has been consumed and end-of-stream is indicated. + mkvpos_t pos_end_; + + private: + // Disable copy ctor and copy assign + FrameParser(const FrameParser&); + FrameParser& operator=(const FrameParser&); +}; + +// The data from the original WebVTT Cue is stored as an MKV Chapters +// Atom element (the cue payload is stored as a Display sub-element). +// The ChapterAtomParser is used to parse the lines of text out from +// the String sub-element of the Display element (though it would be +// admittedly odd if there were more than one line). +class ChapterAtomParser : public libwebvtt::LineReader { + public: + explicit ChapterAtomParser(const mkvparser::Chapters::Display* display); + virtual ~ChapterAtomParser(); + + const mkvparser::Chapters::Display* const display_; + + protected: + // Read the next character from the character stream (the title + // member of the atom's display). We increment the stream pointer + // |str_| as each character from the stream is consumed. + virtual int GetChar(char* c); + + // End-of-line handling requires that we put a character back into + // the stream. Here we need only decrement the stream pointer |str_| + // to unconsume the character. + virtual void UngetChar(char c); + + // The current position in the character stream (the title of the + // atom's display). + const char* str_; + + // The position of the end of the character stream. When the current + // position |str_| equals the end position |str_end_|, the entire + // stream (title of the display) has been consumed and end-of-stream + // is indicated. + const char* str_end_; + + private: + ChapterAtomParser(const ChapterAtomParser&); + ChapterAtomParser& operator=(const ChapterAtomParser&); +}; + +// Parse the EBML header of the WebM input file, to determine whether we +// actually have a WebM file. Returns false if this is not a WebM file. +bool ParseHeader(mkvparser::IMkvReader* reader, mkvpos_t* pos); + +// Parse the Segment of the input file and load all of its clusters. +// Returns false if there was an error parsing the file. +bool ParseSegment(mkvparser::IMkvReader* reader, mkvpos_t pos, + segment_ptr_t* segment); + +// If |segment| has a Chapters element (in which case, there will be a +// corresponding entry in |metadata_map|), convert the MKV chapters to +// WebVTT chapter cues and write them to the output file. Returns +// false on error. +bool WriteChaptersFile(const metadata_map_t& metadata_map, + const mkvparser::Segment* segment); + +// Convert an MKV Chapters Atom to a WebVTT cue and write it to the +// output |file|. Returns false on error. +bool WriteChaptersCue(FILE* file, const mkvparser::Chapters* chapters, + const mkvparser::Chapters::Atom* atom, + const mkvparser::Chapters::Display* display); + +// Write the Cue Identifier line of the WebVTT cue, if it's present. +// Returns false on error. +bool WriteChaptersCueIdentifier(FILE* file, + const mkvparser::Chapters::Atom* atom); + +// Use the timecodes from the chapters |atom| to write just the +// timings line of the WebVTT cue. Returns false on error. +bool WriteChaptersCueTimings(FILE* file, const mkvparser::Chapters* chapters, + const mkvparser::Chapters::Atom* atom); + +// Parse the String sub-element of the |display| and write the payload +// of the WebVTT cue. Returns false on error. +bool WriteChaptersCuePayload(FILE* file, + const mkvparser::Chapters::Display* display); + +// Iterate over the tracks of the input file (and any chapters +// element) and cache information about each metadata track. +void BuildMap(const mkvparser::Segment* segment, metadata_map_t* metadata_map); + +// For each track listed in the cache, synthesize its output filename +// and open a file handle that designates the out-of-band file. +// Returns false if we were unable to open an output file for a track. +bool OpenFiles(metadata_map_t* metadata_map, const char* filename); + +// Close the file handle for each track in the cache. +void CloseFiles(metadata_map_t* metadata_map); + +// Iterate over the clusters of the input file, and write a WebVTT cue +// for each metadata block. Returns false if processing of a cluster +// failed. +bool WriteFiles(const metadata_map_t& m, mkvparser::Segment* s); + +// Write the WebVTT header for each track in the cache. We do this +// immediately before writing the actual WebVTT cues. Returns false +// if the write failed. +bool InitializeFiles(const metadata_map_t& metadata_map); + +// Iterate over the blocks of the |cluster|, writing a WebVTT cue to +// its associated output file for each block of metadata. Returns +// false if processing a block failed, or there was a parse error. +bool ProcessCluster(const metadata_map_t& metadata_map, + const mkvparser::Cluster* cluster); + +// Look up this track number in the cache, and if found (meaning this +// is a metadata track), write a WebVTT cue to the associated output +// file. Returns false if writing the WebVTT cue failed. +bool ProcessBlockEntry(const metadata_map_t& metadata_map, + const mkvparser::BlockEntry* block_entry); + +// Parse the lines of text from the |block_group| to reconstruct the +// original WebVTT cue, and write it to the associated output |file|. +// Returns false if there was an error writing to the output file. +bool WriteCue(FILE* file, const mkvparser::BlockGroup* block_group); + +// Consume a line of text from the character stream, and if the line +// is not empty write the cue identifier to the associated output +// file. Returns false if there was an error writing to the file. +bool WriteCueIdentifier(FILE* f, FrameParser* parser); + +// Consume a line of text from the character stream (which holds any +// cue settings) and write the cue timings line for this cue to the +// associated output file. Returns false if there was an error +// writing to the file. +bool WriteCueTimings(FILE* f, FrameParser* parser); + +// Write the timestamp (representating either the start time or stop +// time of the cue) to the output file. Returns false if there was an +// error writing to the file. +bool WriteCueTime(FILE* f, mkvtime_t time_ns); + +// Consume the remaining lines of text from the character stream +// (these lines are the actual payload of the WebVTT cue), and write +// them to the associated output file. Returns false if there was an +// error writing to the file. +bool WriteCuePayload(FILE* f, FrameParser* parser); +} // namespace vttdemux + +namespace vttdemux { + +FrameParser::FrameParser(const mkvparser::BlockGroup* block_group) + : block_group_(block_group) { + const mkvparser::Block* const block = block_group->GetBlock(); + const mkvparser::Block::Frame& f = block->GetFrame(0); + + // The beginning and end of the character stream corresponds to the + // position of this block's frame within the WebM input file. + + pos_ = f.pos; + pos_end_ = f.pos + f.len; +} + +FrameParser::~FrameParser() {} + +int FrameParser::GetChar(char* c) { + if (pos_ >= pos_end_) // end-of-stream + return 1; // per the semantics of libwebvtt::Reader::GetChar + + const mkvparser::Cluster* const cluster = block_group_->GetCluster(); + const mkvparser::Segment* const segment = cluster->m_pSegment; + mkvparser::IMkvReader* const reader = segment->m_pReader; + + unsigned char* const buf = reinterpret_cast(c); + const int result = reader->Read(pos_, 1, buf); + + if (result < 0) // error + return -1; + + ++pos_; // consume this character in the stream + return 0; +} + +void FrameParser::UngetChar(char /* c */) { + // All we need to do here is decrement the position in the stream. + // The next time GetChar is called the same character will be + // re-read from the input file. + --pos_; +} + +ChapterAtomParser::ChapterAtomParser( + const mkvparser::Chapters::Display* display) + : display_(display) { + str_ = display->GetString(); + if (str_ == NULL) + return; + const size_t len = strlen(str_); + str_end_ = str_ + len; +} + +ChapterAtomParser::~ChapterAtomParser() {} + +int ChapterAtomParser::GetChar(char* c) { + if (str_ == NULL || str_ >= str_end_) // end-of-stream + return 1; // per the semantics of libwebvtt::Reader::GetChar + + *c = *str_++; // consume this character in the stream + return 0; +} + +void ChapterAtomParser::UngetChar(char /* c */) { + // All we need to do here is decrement the position in the stream. + // The next time GetChar is called the same character will be + // re-read from the input file. + --str_; +} + +} // namespace vttdemux + +bool vttdemux::ParseHeader(mkvparser::IMkvReader* reader, mkvpos_t* pos) { + mkvparser::EBMLHeader h; + const mkvpos_t status = h.Parse(reader, *pos); + + if (status) { + printf("error parsing EBML header\n"); + return false; + } + + if (h.m_docType == NULL || strcmp(h.m_docType, "webm") != 0) { + printf("bad doctype\n"); + return false; + } + + return true; // success +} + +bool vttdemux::ParseSegment(mkvparser::IMkvReader* reader, mkvpos_t pos, + segment_ptr_t* segment_ptr) { + // We first create the segment object. + + mkvparser::Segment* p; + const mkvpos_t create = mkvparser::Segment::CreateInstance(reader, pos, p); + + if (create) { + printf("error parsing segment element\n"); + return false; + } + + segment_ptr->reset(p); + + // Now parse all of the segment's sub-elements, in toto. + + const long status = p->Load(); // NOLINT + + if (status < 0) { + printf("error loading segment\n"); + return false; + } + + return true; +} + +void vttdemux::BuildMap(const mkvparser::Segment* segment, + metadata_map_t* map_ptr) { + metadata_map_t& m = *map_ptr; + m.clear(); + + if (segment->GetChapters()) { + MetadataInfo info; + info.file = NULL; + info.type = MetadataInfo::kChapters; + + m[kChaptersKey] = info; + } + + const mkvparser::Tracks* const tt = segment->GetTracks(); + if (tt == NULL) + return; + + const long tc = tt->GetTracksCount(); // NOLINT + if (tc <= 0) + return; + + // Iterate over the tracks in the intput file. We determine whether + // a track holds metadata by inspecting its CodecID. + + for (long idx = 0; idx < tc; ++idx) { // NOLINT + const mkvparser::Track* const t = tt->GetTrackByIndex(idx); + + if (t == NULL) // weird + continue; + + const long tn = t->GetNumber(); // NOLINT + + if (tn <= 0) // weird + continue; + + const char* const codec_id = t->GetCodecId(); + + if (codec_id == NULL) // weird + continue; + + MetadataInfo info; + info.file = NULL; + + if (strcmp(codec_id, "D_WEBVTT/SUBTITLES") == 0) { + info.type = MetadataInfo::kSubtitles; + } else if (strcmp(codec_id, "D_WEBVTT/CAPTIONS") == 0) { + info.type = MetadataInfo::kCaptions; + } else if (strcmp(codec_id, "D_WEBVTT/DESCRIPTIONS") == 0) { + info.type = MetadataInfo::kDescriptions; + } else if (strcmp(codec_id, "D_WEBVTT/METADATA") == 0) { + info.type = MetadataInfo::kMetadata; + } else { + continue; + } + + m[tn] = info; // create an entry in the cache for this track + } +} + +bool vttdemux::OpenFiles(metadata_map_t* metadata_map, const char* filename) { + if (metadata_map == NULL || metadata_map->empty()) + return false; + + if (filename == NULL) + return false; + + // Find the position of the filename extension. We synthesize the + // output filename from the directory path and basename of the input + // filename. + + const char* const ext = strrchr(filename, '.'); + + if (ext == NULL) // TODO(matthewjheaney): liberalize? + return false; + + // Remember whether a track of this type has already been seen (the + // map key) by keeping a count (the map item). We quality the + // output filename with the track number if there is more than one + // track having a given type. + + std::map exists; + + typedef metadata_map_t::iterator iter_t; + + metadata_map_t& m = *metadata_map; + const iter_t ii = m.begin(); + const iter_t j = m.end(); + + // Make a first pass over the cache to determine whether there is + // more than one track corresponding to a given metadata type. + + iter_t i = ii; + while (i != j) { + const metadata_map_t::value_type& v = *i++; + const MetadataInfo& info = v.second; + const MetadataInfo::Type type = info.type; + ++exists[type]; + } + + // Make a second pass over the cache, synthesizing the filename of + // each output file (from the input file basename, the input track + // metadata type, and its track number if necessary), and then + // opening a WebVTT output file having that filename. + + i = ii; + while (i != j) { + metadata_map_t::value_type& v = *i++; + MetadataInfo& info = v.second; + const MetadataInfo::Type type = info.type; + + // Start with the basename of the input file. + + string name(filename, ext); + + // Next append the metadata kind. + + switch (type) { + case MetadataInfo::kSubtitles: + name += "_SUBTITLES"; + break; + + case MetadataInfo::kCaptions: + name += "_CAPTIONS"; + break; + + case MetadataInfo::kDescriptions: + name += "_DESCRIPTIONS"; + break; + + case MetadataInfo::kMetadata: + name += "_METADATA"; + break; + + case MetadataInfo::kChapters: + name += "_CHAPTERS"; + break; + + default: + return false; + } + + // If there is more than one metadata track having a given type + // (the WebVTT-in-WebM spec doesn't preclude this), then qualify + // the output filename with the input track number. + + if (exists[type] > 1) { + enum { kLen = 33 }; + char str[kLen]; // max 126 tracks, so only 4 chars really needed +#ifndef _MSC_VER + snprintf(str, kLen, "%ld", v.first); // track number +#else + _snprintf_s(str, sizeof(str), kLen, "%ld", v.first); // track number +#endif + name += str; + } + + // Finally append the output filename extension. + + name += ".vtt"; + + // We have synthesized the full output filename, so attempt to + // open the WebVTT output file. + + info.file = fopen(name.c_str(), "wb"); + const bool success = (info.file != NULL); + + if (!success) { + printf("unable to open output file %s\n", name.c_str()); + return false; + } + } + + return true; +} + +void vttdemux::CloseFiles(metadata_map_t* metadata_map) { + if (metadata_map == NULL) + return; + + metadata_map_t& m = *metadata_map; + + typedef metadata_map_t::iterator iter_t; + + iter_t i = m.begin(); + const iter_t j = m.end(); + + // Gracefully close each output file, to ensure all output gets + // propertly flushed. + + while (i != j) { + metadata_map_t::value_type& v = *i++; + MetadataInfo& info = v.second; + + if (info.file != NULL) { + fclose(info.file); + info.file = NULL; + } + } +} + +bool vttdemux::WriteFiles(const metadata_map_t& m, mkvparser::Segment* s) { + // First write the WebVTT header. + + InitializeFiles(m); + + if (!WriteChaptersFile(m, s)) + return false; + + // Now iterate over the clusters, writing the WebVTT cue as we parse + // each metadata block. + + const mkvparser::Cluster* cluster = s->GetFirst(); + + while (cluster != NULL && !cluster->EOS()) { + if (!ProcessCluster(m, cluster)) + return false; + + cluster = s->GetNext(cluster); + } + + return true; +} + +bool vttdemux::InitializeFiles(const metadata_map_t& m) { + // Write the WebVTT header for each output file in the cache. + + typedef metadata_map_t::const_iterator iter_t; + iter_t i = m.begin(); + const iter_t j = m.end(); + + while (i != j) { + const metadata_map_t::value_type& v = *i++; + const MetadataInfo& info = v.second; + FILE* const f = info.file; + + if (fputs("WEBVTT\n", f) < 0) { + printf("unable to initialize output file\n"); + return false; + } + } + + return true; +} + +bool vttdemux::WriteChaptersFile(const metadata_map_t& m, + const mkvparser::Segment* s) { + const metadata_map_t::const_iterator info_iter = m.find(kChaptersKey); + if (info_iter == m.end()) // no chapters, so nothing to do + return true; + + const mkvparser::Chapters* const chapters = s->GetChapters(); + if (chapters == NULL) // weird + return true; + + const MetadataInfo& info = info_iter->second; + FILE* const file = info.file; + + const int edition_count = chapters->GetEditionCount(); + + if (edition_count <= 0) // weird + return true; // nothing to do + + if (edition_count > 1) { + // TODO(matthewjheaney): figure what to do here + printf("more than one chapter edition detected\n"); + return false; + } + + const mkvparser::Chapters::Edition* const edition = chapters->GetEdition(0); + + const int atom_count = edition->GetAtomCount(); + + for (int idx = 0; idx < atom_count; ++idx) { + const mkvparser::Chapters::Atom* const atom = edition->GetAtom(idx); + const int display_count = atom->GetDisplayCount(); + + if (display_count <= 0) + continue; + + if (display_count > 1) { + // TODO(matthewjheaney): handle case of multiple languages + printf("more than 1 display in atom detected\n"); + return false; + } + + const mkvparser::Chapters::Display* const display = atom->GetDisplay(0); + + if (const char* language = display->GetLanguage()) { + if (strcmp(language, "eng") != 0) { + // TODO(matthewjheaney): handle case of multiple languages. + + // We must create a separate webvtt file for each language. + // This isn't a simple problem (which is why we defer it for + // now), because there's nothing in the header that tells us + // what languages we have as cues. We must parse the displays + // of each atom to determine that. + + // One solution is to make two passes over the input data. + // First parse the displays, creating an in-memory cache of + // all the chapter cues, sorted according to their language. + // After we have read all of the chapter atoms from the input + // file, we can then write separate output files for each + // language. + + printf("only English-language chapter cues are supported\n"); + return false; + } + } + + if (!WriteChaptersCue(file, chapters, atom, display)) + return false; + } + + return true; +} + +bool vttdemux::WriteChaptersCue(FILE* f, const mkvparser::Chapters* chapters, + const mkvparser::Chapters::Atom* atom, + const mkvparser::Chapters::Display* display) { + // We start a new cue by writing a cue separator (an empty line) + // into the stream. + + if (fputc('\n', f) < 0) + return false; + + // A WebVTT Cue comprises 3 things: a cue identifier, followed by + // the cue timings, followed by the payload of the cue. We write + // each part of the cue in sequence. + + if (!WriteChaptersCueIdentifier(f, atom)) + return false; + + if (!WriteChaptersCueTimings(f, chapters, atom)) + return false; + + if (!WriteChaptersCuePayload(f, display)) + return false; + + return true; +} + +bool vttdemux::WriteChaptersCueIdentifier( + FILE* f, const mkvparser::Chapters::Atom* atom) { + const char* const identifier = atom->GetStringUID(); + + if (identifier == NULL) + return true; // nothing else to do + + if (fprintf(f, "%s\n", identifier) < 0) + return false; + + return true; +} + +bool vttdemux::WriteChaptersCueTimings(FILE* f, + const mkvparser::Chapters* chapters, + const mkvparser::Chapters::Atom* atom) { + const mkvtime_t start_ns = atom->GetStartTime(chapters); + + if (start_ns < 0) + return false; + + const mkvtime_t stop_ns = atom->GetStopTime(chapters); + + if (stop_ns < 0) + return false; + + if (!WriteCueTime(f, start_ns)) + return false; + + if (fputs(" --> ", f) < 0) + return false; + + if (!WriteCueTime(f, stop_ns)) + return false; + + if (fputc('\n', f) < 0) + return false; + + return true; +} + +bool vttdemux::WriteChaptersCuePayload( + FILE* f, const mkvparser::Chapters::Display* display) { + // Bind a Chapter parser object to the display, which allows us to + // extract each line of text from the title-part of the display. + ChapterAtomParser parser(display); + + int count = 0; // count of lines of payload text written to output file + for (string line;;) { + const int e = parser.GetLine(&line); + + if (e < 0) // error (only -- we allow EOS here) + return false; + + if (line.empty()) // TODO(matthewjheaney): retain this check? + break; + + if (fprintf(f, "%s\n", line.c_str()) < 0) + return false; + + ++count; + } + + if (count <= 0) // WebVTT cue requires non-empty payload + return false; + + return true; +} + +bool vttdemux::ProcessCluster(const metadata_map_t& m, + const mkvparser::Cluster* c) { + // Visit the blocks in this cluster, writing a WebVTT cue for each + // metadata block. + + const mkvparser::BlockEntry* block_entry; + + long result = c->GetFirst(block_entry); // NOLINT + if (result < 0) { + printf("bad cluster (unable to get first block)\n"); + return false; + } + + while (block_entry != NULL && !block_entry->EOS()) { + if (!ProcessBlockEntry(m, block_entry)) + return false; + + result = c->GetNext(block_entry, block_entry); + if (result < 0) { // error + printf("bad cluster (unable to get next block)\n"); + return false; + } + } + + return true; +} + +bool vttdemux::ProcessBlockEntry(const metadata_map_t& m, + const mkvparser::BlockEntry* block_entry) { + // If the track number for this block is in the cache, then we have + // a metadata block, so write the WebVTT cue to the output file. + + const mkvparser::Block* const block = block_entry->GetBlock(); + const long long tn = block->GetTrackNumber(); // NOLINT + + typedef metadata_map_t::const_iterator iter_t; + const iter_t i = m.find(static_cast(tn)); + + if (i == m.end()) // not a metadata track + return true; // nothing else to do + + if (block_entry->GetKind() != mkvparser::BlockEntry::kBlockGroup) + return false; // weird + + typedef mkvparser::BlockGroup BG; + const BG* const block_group = static_cast(block_entry); + + const MetadataInfo& info = i->second; + FILE* const f = info.file; + + return WriteCue(f, block_group); +} + +bool vttdemux::WriteCue(FILE* f, const mkvparser::BlockGroup* block_group) { + // Bind a FrameParser object to the block, which allows us to + // extract each line of text from the payload of the block. + FrameParser parser(block_group); + + // We start a new cue by writing a cue separator (an empty line) + // into the stream. + + if (fputc('\n', f) < 0) + return false; + + // A WebVTT Cue comprises 3 things: a cue identifier, followed by + // the cue timings, followed by the payload of the cue. We write + // each part of the cue in sequence. + + if (!WriteCueIdentifier(f, &parser)) + return false; + + if (!WriteCueTimings(f, &parser)) + return false; + + if (!WriteCuePayload(f, &parser)) + return false; + + return true; +} + +bool vttdemux::WriteCueIdentifier(FILE* f, FrameParser* parser) { + string line; + int e = parser->GetLine(&line); + + if (e) // error or EOS + return false; + + // If the cue identifier line is empty, this means that the original + // WebVTT cue did not have a cue identifier, so we don't bother + // writing an extra line terminator to the output file (though doing + // so would be harmless). + + if (!line.empty()) { + if (fputs(line.c_str(), f) < 0) + return false; + + if (fputc('\n', f) < 0) + return false; + } + + return true; +} + +bool vttdemux::WriteCueTimings(FILE* f, FrameParser* parser) { + const mkvparser::BlockGroup* const block_group = parser->block_group_; + const mkvparser::Cluster* const cluster = block_group->GetCluster(); + const mkvparser::Block* const block = block_group->GetBlock(); + + // A WebVTT Cue "timings" line comprises two parts: the start and + // stop time for this cue, followed by the (optional) cue settings, + // such as orientation of the rendered text or its size. Only the + // settings part of the cue timings line is stored in the WebM + // block. We reconstruct the start and stop times of the WebVTT cue + // from the timestamp and duration of the WebM block. + + const mkvtime_t start_ns = block->GetTime(cluster); + + if (!WriteCueTime(f, start_ns)) + return false; + + if (fputs(" --> ", f) < 0) + return false; + + const mkvtime_t duration_timecode = block_group->GetDurationTimeCode(); + + if (duration_timecode < 0) + return false; + + const mkvparser::Segment* const segment = cluster->m_pSegment; + const mkvparser::SegmentInfo* const info = segment->GetInfo(); + + if (info == NULL) + return false; + + const mkvtime_t timecode_scale = info->GetTimeCodeScale(); + + if (timecode_scale <= 0) + return false; + + const mkvtime_t duration_ns = duration_timecode * timecode_scale; + const mkvtime_t stop_ns = start_ns + duration_ns; + + if (!WriteCueTime(f, stop_ns)) + return false; + + string line; + int e = parser->GetLine(&line); + + if (e) // error or EOS + return false; + + if (!line.empty()) { + if (fputc(' ', f) < 0) + return false; + + if (fputs(line.c_str(), f) < 0) + return false; + } + + if (fputc('\n', f) < 0) + return false; + + return true; +} + +bool vttdemux::WriteCueTime(FILE* f, mkvtime_t time_ns) { + mkvtime_t ms = time_ns / 1000000; // WebVTT time has millisecond resolution + + mkvtime_t sec = ms / 1000; + ms -= sec * 1000; + + mkvtime_t min = sec / 60; + sec -= 60 * min; + + mkvtime_t hr = min / 60; + min -= 60 * hr; + + if (hr > 0) { + if (fprintf(f, "%02lld:", hr) < 0) + return false; + } + + if (fprintf(f, "%02lld:%02lld.%03lld", min, sec, ms) < 0) + return false; + + return true; +} + +bool vttdemux::WriteCuePayload(FILE* f, FrameParser* parser) { + int count = 0; // count of lines of payload text written to output file + for (string line;;) { + const int e = parser->GetLine(&line); + + if (e < 0) // error (only -- we allow EOS here) + return false; + + if (line.empty()) // TODO(matthewjheaney): retain this check? + break; + + if (fprintf(f, "%s\n", line.c_str()) < 0) + return false; + + ++count; + } + + if (count <= 0) // WebVTT cue requires non-empty payload + return false; + + return true; +} + +} // namespace libwebm + +int main(int argc, const char* argv[]) { + if (argc != 2) { + printf("usage: vttdemux \n"); + return EXIT_SUCCESS; + } + + const char* const filename = argv[1]; + mkvparser::MkvReader reader; + + int e = reader.Open(filename); + + if (e) { // error + printf("unable to open file\n"); + return EXIT_FAILURE; + } + + libwebm::vttdemux::mkvpos_t pos; + + if (!libwebm::vttdemux::ParseHeader(&reader, &pos)) + return EXIT_FAILURE; + + libwebm::vttdemux::segment_ptr_t segment_ptr; + + if (!libwebm::vttdemux::ParseSegment(&reader, pos, &segment_ptr)) + return EXIT_FAILURE; + + libwebm::vttdemux::metadata_map_t metadata_map; + + BuildMap(segment_ptr.get(), &metadata_map); + + if (metadata_map.empty()) { + printf("no WebVTT metadata found\n"); + return EXIT_FAILURE; + } + + if (!OpenFiles(&metadata_map, filename)) { + CloseFiles(&metadata_map); // nothing to flush, so not strictly necessary + return EXIT_FAILURE; + } + + if (!WriteFiles(metadata_map, segment_ptr.get())) { + CloseFiles(&metadata_map); // might as well flush what we do have + return EXIT_FAILURE; + } + + CloseFiles(&metadata_map); + + return EXIT_SUCCESS; +} diff --git a/third_party/libwebm/source/vttreader.h b/third_party/libwebm/source/vttreader.h new file mode 100644 index 000000000000..2e7cc4b5479f --- /dev/null +++ b/third_party/libwebm/source/vttreader.h @@ -0,0 +1,15 @@ +// Copyright (c) 2016 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +#ifndef LIBWEBM_VTTREADER_H_ +#define LIBWEBM_VTTREADER_H_ + +// This file is a wrapper for the file included immediately after this comment. +// New projects should not include this file: include the file included below. +#include "webvtt/vttreader.h" + +#endif // LIBWEBM_VTTREADER_H_ diff --git a/third_party/libwebm/source/webm_info.cc b/third_party/libwebm/source/webm_info.cc new file mode 100644 index 000000000000..7cc7272daad4 --- /dev/null +++ b/third_party/libwebm/source/webm_info.cc @@ -0,0 +1,1336 @@ +// Copyright (c) 2012 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "common/hdr_util.h" +#include "common/indent.h" +#include "common/vp9_header_parser.h" +#include "common/vp9_level_stats.h" +#include "common/webm_constants.h" +#include "common/webm_endian.h" + +#include "mkvparser/mkvparser.h" +#include "mkvparser/mkvreader.h" + +namespace { + +using libwebm::Indent; +using libwebm::kNanosecondsPerSecond; +using libwebm::kNanosecondsPerSecondi; +using mkvparser::ContentEncoding; +using std::string; +using std::wstring; + +const char VERSION_STRING[] = "1.0.4.5"; + +struct Options { + Options(); + + // Returns true if |value| matches -|option| or -no|option|. + static bool MatchesBooleanOption(const string& option, const string& value); + + // Set all of the member variables to |value|. + void SetAll(bool value); + + bool output_video; + bool output_audio; + bool output_size; + bool output_offset; + bool output_seconds; + bool output_ebml_header; + bool output_segment; + bool output_seekhead; + bool output_segment_info; + bool output_tracks; + bool output_clusters; + bool output_blocks; + bool output_codec_info; + bool output_clusters_size; + bool output_encrypted_info; + bool output_cues; + bool output_frame_stats; + bool output_vp9_level; +}; + +Options::Options() + : output_video(true), + output_audio(true), + output_size(false), + output_offset(false), + output_seconds(true), + output_ebml_header(true), + output_segment(true), + output_seekhead(false), + output_segment_info(true), + output_tracks(true), + output_clusters(false), + output_blocks(false), + output_codec_info(false), + output_clusters_size(false), + output_encrypted_info(false), + output_cues(false), + output_frame_stats(false), + output_vp9_level(false) {} + +void Options::SetAll(bool value) { + output_video = value; + output_audio = value; + output_size = value; + output_offset = value; + output_ebml_header = value; + output_seconds = value; + output_segment = value; + output_segment_info = value; + output_tracks = value; + output_clusters = value; + output_blocks = value; + output_codec_info = value; + output_clusters_size = value; + output_encrypted_info = value; + output_cues = value; + output_frame_stats = value; + output_vp9_level = value; +} + +bool Options::MatchesBooleanOption(const string& option, const string& value) { + const string opt = "-" + option; + const string noopt = "-no" + option; + return value == opt || value == noopt; +} + +struct FrameStats { + FrameStats() + : frames(0), + displayed_frames(0), + first_altref(true), + frames_since_last_altref(0), + minimum_altref_distance(std::numeric_limits::max()), + min_altref_end_ns(0), + max_window_size(0), + max_window_end_ns(0) {} + + int frames; + int displayed_frames; + + bool first_altref; + int frames_since_last_altref; + int minimum_altref_distance; + int64_t min_altref_end_ns; + + std::queue window; + int64_t max_window_size; + int64_t max_window_end_ns; +}; + +void Usage() { + printf("Usage: webm_info [options] -i input\n"); + printf("\n"); + printf("Main options:\n"); + printf(" -h | -? show help\n"); + printf(" -v show version\n"); + printf(" -all Enable all output options.\n"); + printf(" -video Output video tracks (true)\n"); + printf(" -audio Output audio tracks (true)\n"); + printf(" -size Output element sizes (false)\n"); + printf(" -offset Output element offsets (false)\n"); + printf(" -times_seconds Output times as seconds (true)\n"); + printf(" -ebml_header Output EBML header (true)\n"); + printf(" -segment Output Segment (true)\n"); + printf(" -seekhead Output SeekHead (false)\n"); + printf(" -segment_info Output SegmentInfo (true)\n"); + printf(" -tracks Output Tracks (true)\n"); + printf(" -clusters Output Clusters (false)\n"); + printf(" -blocks Output Blocks (false)\n"); + printf(" -codec_info Output video codec information (false)\n"); + printf(" -clusters_size Output Total Clusters size (false)\n"); + printf(" -encrypted_info Output encrypted frame info (false)\n"); + printf(" -cues Output Cues entries (false)\n"); + printf(" -frame_stats Output frame stats (VP9)(false)\n"); + printf(" -vp9_level Output VP9 level(false)\n"); + printf("\nOutput options may be negated by prefixing 'no'.\n"); +} + +// TODO(fgalligan): Add support for non-ascii. +wstring UTF8ToWideString(const char* str) { + wstring wstr; + + if (str == NULL) + return wstr; + + string temp_str(str, strlen(str)); + wstr.assign(temp_str.begin(), temp_str.end()); + + return wstr; +} + +string ToString(const char* str) { return string((str == NULL) ? "" : str); } + +void OutputEBMLHeader(const mkvparser::EBMLHeader& ebml, FILE* o, + Indent* indent) { + fprintf(o, "EBML Header:\n"); + indent->Adjust(libwebm::kIncreaseIndent); + fprintf(o, "%sEBMLVersion : %lld\n", indent->indent_str().c_str(), + ebml.m_version); + fprintf(o, "%sEBMLReadVersion : %lld\n", indent->indent_str().c_str(), + ebml.m_readVersion); + fprintf(o, "%sEBMLMaxIDLength : %lld\n", indent->indent_str().c_str(), + ebml.m_maxIdLength); + fprintf(o, "%sEBMLMaxSizeLength : %lld\n", indent->indent_str().c_str(), + ebml.m_maxSizeLength); + fprintf(o, "%sDoc Type : %s\n", indent->indent_str().c_str(), + ebml.m_docType); + fprintf(o, "%sDocTypeVersion : %lld\n", indent->indent_str().c_str(), + ebml.m_docTypeVersion); + fprintf(o, "%sDocTypeReadVersion: %lld\n", indent->indent_str().c_str(), + ebml.m_docTypeReadVersion); + indent->Adjust(libwebm::kDecreaseIndent); +} + +void OutputSegment(const mkvparser::Segment& segment, const Options& options, + FILE* o) { + fprintf(o, "Segment:"); + if (options.output_offset) + fprintf(o, " @: %lld", segment.m_element_start); + if (options.output_size) + fprintf(o, " size: %lld", + segment.m_size + segment.m_start - segment.m_element_start); + fprintf(o, "\n"); +} + +bool OutputSeekHead(const mkvparser::Segment& segment, const Options& options, + FILE* o, Indent* indent) { + const mkvparser::SeekHead* const seekhead = segment.GetSeekHead(); + if (!seekhead) { + // SeekHeads are optional. + return true; + } + + fprintf(o, "%sSeekHead:", indent->indent_str().c_str()); + if (options.output_offset) + fprintf(o, " @: %lld", seekhead->m_element_start); + if (options.output_size) + fprintf(o, " size: %lld", seekhead->m_element_size); + fprintf(o, "\n"); + + indent->Adjust(libwebm::kIncreaseIndent); + + for (int i = 0; i < seekhead->GetCount(); ++i) { + const mkvparser::SeekHead::Entry* const entry = seekhead->GetEntry(i); + if (!entry) { + fprintf(stderr, "Error retrieving SeekHead entry #%d\n", i); + return false; + } + + fprintf(o, "%sEntry[%d]", indent->indent_str().c_str(), i); + if (options.output_offset) + fprintf(o, " @: %lld", entry->element_start); + if (options.output_size) + fprintf(o, " size: %lld", entry->element_size); + fprintf(o, "\n"); + + indent->Adjust(libwebm::kIncreaseIndent); + std::string entry_indent = indent->indent_str(); + // TODO(jzern): 1) known ids could be stringified. 2) ids could be + // reencoded to EBML for ease of lookup. + fprintf(o, "%sSeek ID : %llx\n", entry_indent.c_str(), entry->id); + fprintf(o, "%sSeek position : %lld\n", entry_indent.c_str(), entry->pos); + indent->Adjust(libwebm::kDecreaseIndent); + } + + for (int i = 0; i < seekhead->GetVoidElementCount(); ++i) { + const mkvparser::SeekHead::VoidElement* const entry = + seekhead->GetVoidElement(i); + if (!entry) { + fprintf(stderr, "Error retrieving SeekHead void element #%d\n", i); + return false; + } + + fprintf(o, "%sVoid element[%d]", indent->indent_str().c_str(), i); + if (options.output_offset) + fprintf(o, " @: %lld", entry->element_start); + if (options.output_size) + fprintf(o, " size: %lld", entry->element_size); + fprintf(o, "\n"); + } + + indent->Adjust(libwebm::kDecreaseIndent); + return true; +} + +bool OutputSegmentInfo(const mkvparser::Segment& segment, + const Options& options, FILE* o, Indent* indent) { + const mkvparser::SegmentInfo* const segment_info = segment.GetInfo(); + if (!segment_info) { + fprintf(stderr, "SegmentInfo was NULL.\n"); + return false; + } + + const int64_t timecode_scale = segment_info->GetTimeCodeScale(); + const int64_t duration_ns = segment_info->GetDuration(); + const wstring title = UTF8ToWideString(segment_info->GetTitleAsUTF8()); + const wstring muxing_app = + UTF8ToWideString(segment_info->GetMuxingAppAsUTF8()); + const wstring writing_app = + UTF8ToWideString(segment_info->GetWritingAppAsUTF8()); + + fprintf(o, "%sSegmentInfo:", indent->indent_str().c_str()); + if (options.output_offset) + fprintf(o, " @: %lld", segment_info->m_element_start); + if (options.output_size) + fprintf(o, " size: %lld", segment_info->m_element_size); + fprintf(o, "\n"); + + indent->Adjust(libwebm::kIncreaseIndent); + fprintf(o, "%sTimecodeScale : %" PRId64 " \n", indent->indent_str().c_str(), + timecode_scale); + if (options.output_seconds) + fprintf(o, "%sDuration(secs): %g\n", indent->indent_str().c_str(), + duration_ns / kNanosecondsPerSecond); + else + fprintf(o, "%sDuration(nano): %" PRId64 "\n", indent->indent_str().c_str(), + duration_ns); + + if (!title.empty()) + fprintf(o, "%sTitle : %ls\n", indent->indent_str().c_str(), + title.c_str()); + if (!muxing_app.empty()) + fprintf(o, "%sMuxingApp : %ls\n", indent->indent_str().c_str(), + muxing_app.c_str()); + if (!writing_app.empty()) + fprintf(o, "%sWritingApp : %ls\n", indent->indent_str().c_str(), + writing_app.c_str()); + indent->Adjust(libwebm::kDecreaseIndent); + return true; +} + +bool OutputTracks(const mkvparser::Segment& segment, const Options& options, + FILE* o, Indent* indent) { + const mkvparser::Tracks* const tracks = segment.GetTracks(); + if (!tracks) { + fprintf(stderr, "Tracks was NULL.\n"); + return false; + } + + fprintf(o, "%sTracks:", indent->indent_str().c_str()); + if (options.output_offset) + fprintf(o, " @: %lld", tracks->m_element_start); + if (options.output_size) + fprintf(o, " size: %lld", tracks->m_element_size); + fprintf(o, "\n"); + + unsigned int i = 0; + const unsigned long j = tracks->GetTracksCount(); + while (i != j) { + const mkvparser::Track* const track = tracks->GetTrackByIndex(i++); + if (track == NULL) + continue; + + indent->Adjust(libwebm::kIncreaseIndent); + fprintf(o, "%sTrack:", indent->indent_str().c_str()); + if (options.output_offset) + fprintf(o, " @: %lld", track->m_element_start); + if (options.output_size) + fprintf(o, " size: %lld", track->m_element_size); + fprintf(o, "\n"); + + const int64_t track_type = track->GetType(); + const int64_t track_number = track->GetNumber(); + const wstring track_name = UTF8ToWideString(track->GetNameAsUTF8()); + + indent->Adjust(libwebm::kIncreaseIndent); + fprintf(o, "%sTrackType : %" PRId64 "\n", indent->indent_str().c_str(), + track_type); + fprintf(o, "%sTrackNumber : %" PRId64 "\n", indent->indent_str().c_str(), + track_number); + if (!track_name.empty()) + fprintf(o, "%sName : %ls\n", indent->indent_str().c_str(), + track_name.c_str()); + + const char* const codec_id = track->GetCodecId(); + if (codec_id) + fprintf(o, "%sCodecID : %s\n", indent->indent_str().c_str(), + codec_id); + + const wstring codec_name = UTF8ToWideString(track->GetCodecNameAsUTF8()); + if (!codec_name.empty()) + fprintf(o, "%sCodecName : %ls\n", indent->indent_str().c_str(), + codec_name.c_str()); + + size_t private_size; + const unsigned char* const private_data = + track->GetCodecPrivate(private_size); + if (private_data) { + fprintf(o, "%sPrivateData(size): %d\n", indent->indent_str().c_str(), + static_cast(private_size)); + + if (track_type == mkvparser::Track::kVideo) { + const std::string codec_id = ToString(track->GetCodecId()); + const std::string v_vp9 = "V_VP9"; + if (codec_id == v_vp9) { + libwebm::Vp9CodecFeatures features; + if (!libwebm::ParseVpxCodecPrivate(private_data, + static_cast(private_size), + &features)) { + fprintf(stderr, "Error parsing VpxCodecPrivate.\n"); + return false; + } + if (features.profile != -1) + fprintf(o, "%sVP9 profile : %d\n", + indent->indent_str().c_str(), features.profile); + if (features.level != -1) + fprintf(o, "%sVP9 level : %d\n", + indent->indent_str().c_str(), features.level); + if (features.bit_depth != -1) + fprintf(o, "%sVP9 bit_depth : %d\n", + indent->indent_str().c_str(), features.bit_depth); + if (features.chroma_subsampling != -1) + fprintf(o, "%sVP9 chroma subsampling : %d\n", + indent->indent_str().c_str(), features.chroma_subsampling); + } + } + } + + const uint64_t default_duration = track->GetDefaultDuration(); + if (default_duration > 0) + fprintf(o, "%sDefaultDuration: %" PRIu64 "\n", + indent->indent_str().c_str(), default_duration); + + if (track->GetContentEncodingCount() > 0) { + // Only check the first content encoding. + const ContentEncoding* const encoding = + track->GetContentEncodingByIndex(0); + if (!encoding) { + printf("Could not get first ContentEncoding.\n"); + return false; + } + + fprintf(o, "%sContentEncodingOrder : %lld\n", + indent->indent_str().c_str(), encoding->encoding_order()); + fprintf(o, "%sContentEncodingScope : %lld\n", + indent->indent_str().c_str(), encoding->encoding_scope()); + fprintf(o, "%sContentEncodingType : %lld\n", + indent->indent_str().c_str(), encoding->encoding_type()); + + if (encoding->GetEncryptionCount() > 0) { + // Only check the first encryption. + const ContentEncoding::ContentEncryption* const encryption = + encoding->GetEncryptionByIndex(0); + if (!encryption) { + printf("Could not get first ContentEncryption.\n"); + return false; + } + + fprintf(o, "%sContentEncAlgo : %lld\n", + indent->indent_str().c_str(), encryption->algo); + + if (encryption->key_id_len > 0) { + fprintf(o, "%sContentEncKeyID : ", indent->indent_str().c_str()); + for (int k = 0; k < encryption->key_id_len; ++k) { + fprintf(o, "0x%02x, ", encryption->key_id[k]); + } + fprintf(o, "\n"); + } + + if (encryption->signature_len > 0) { + fprintf(o, "%sContentSignature : 0x", + indent->indent_str().c_str()); + for (int k = 0; k < encryption->signature_len; ++k) { + fprintf(o, "%x", encryption->signature[k]); + } + fprintf(o, "\n"); + } + + if (encryption->sig_key_id_len > 0) { + fprintf(o, "%sContentSigKeyID : 0x", + indent->indent_str().c_str()); + for (int k = 0; k < encryption->sig_key_id_len; ++k) { + fprintf(o, "%x", encryption->sig_key_id[k]); + } + fprintf(o, "\n"); + } + + fprintf(o, "%sContentSigAlgo : %lld\n", + indent->indent_str().c_str(), encryption->sig_algo); + fprintf(o, "%sContentSigHashAlgo : %lld\n", + indent->indent_str().c_str(), encryption->sig_hash_algo); + + const ContentEncoding::ContentEncAESSettings& aes = + encryption->aes_settings; + fprintf(o, "%sCipherMode : %lld\n", + indent->indent_str().c_str(), aes.cipher_mode); + } + } + + if (track_type == mkvparser::Track::kVideo) { + const mkvparser::VideoTrack* const video_track = + static_cast(track); + const int64_t width = video_track->GetWidth(); + const int64_t height = video_track->GetHeight(); + const int64_t display_width = video_track->GetDisplayWidth(); + const int64_t display_height = video_track->GetDisplayHeight(); + const int64_t display_unit = video_track->GetDisplayUnit(); + const double frame_rate = video_track->GetFrameRate(); + fprintf(o, "%sPixelWidth : %" PRId64 "\n", indent->indent_str().c_str(), + width); + fprintf(o, "%sPixelHeight : %" PRId64 "\n", indent->indent_str().c_str(), + height); + if (frame_rate > 0.0) + fprintf(o, "%sFrameRate : %g\n", indent->indent_str().c_str(), + video_track->GetFrameRate()); + if (display_unit > 0 || display_width != width || + display_height != height) { + fprintf(o, "%sDisplayWidth : %" PRId64 "\n", + indent->indent_str().c_str(), display_width); + fprintf(o, "%sDisplayHeight : %" PRId64 "\n", + indent->indent_str().c_str(), display_height); + fprintf(o, "%sDisplayUnit : %" PRId64 "\n", + indent->indent_str().c_str(), display_unit); + } + + const mkvparser::Colour* const colour = video_track->GetColour(); + if (colour) { + // TODO(fgalligan): Add support for Colour's address and size. + fprintf(o, "%sColour:\n", indent->indent_str().c_str()); + indent->Adjust(libwebm::kIncreaseIndent); + + const int64_t matrix_coefficients = colour->matrix_coefficients; + const int64_t bits_per_channel = colour->bits_per_channel; + const int64_t chroma_subsampling_horz = colour->chroma_subsampling_horz; + const int64_t chroma_subsampling_vert = colour->chroma_subsampling_vert; + const int64_t cb_subsampling_horz = colour->cb_subsampling_horz; + const int64_t cb_subsampling_vert = colour->cb_subsampling_vert; + const int64_t chroma_siting_horz = colour->chroma_siting_horz; + const int64_t chroma_siting_vert = colour->chroma_siting_vert; + const int64_t range = colour->range; + const int64_t transfer_characteristics = + colour->transfer_characteristics; + const int64_t primaries = colour->primaries; + const int64_t max_cll = colour->max_cll; + const int64_t max_fall = colour->max_fall; + if (matrix_coefficients != mkvparser::Colour::kValueNotPresent) + fprintf(o, "%sMatrixCoefficients : %" PRId64 "\n", + indent->indent_str().c_str(), matrix_coefficients); + if (bits_per_channel != mkvparser::Colour::kValueNotPresent) + fprintf(o, "%sBitsPerChannel : %" PRId64 "\n", + indent->indent_str().c_str(), bits_per_channel); + if (chroma_subsampling_horz != mkvparser::Colour::kValueNotPresent) + fprintf(o, "%sChromaSubsamplingHorz : %" PRId64 "\n", + indent->indent_str().c_str(), chroma_subsampling_horz); + if (chroma_subsampling_vert != mkvparser::Colour::kValueNotPresent) + fprintf(o, "%sChromaSubsamplingVert : %" PRId64 "\n", + indent->indent_str().c_str(), chroma_subsampling_vert); + if (cb_subsampling_horz != mkvparser::Colour::kValueNotPresent) + fprintf(o, "%sCbSubsamplingHorz : %" PRId64 "\n", + indent->indent_str().c_str(), cb_subsampling_horz); + if (cb_subsampling_vert != mkvparser::Colour::kValueNotPresent) + fprintf(o, "%sCbSubsamplingVert : %" PRId64 "\n", + indent->indent_str().c_str(), cb_subsampling_vert); + if (chroma_siting_horz != mkvparser::Colour::kValueNotPresent) + fprintf(o, "%sChromaSitingHorz : %" PRId64 "\n", + indent->indent_str().c_str(), chroma_siting_horz); + if (chroma_siting_vert != mkvparser::Colour::kValueNotPresent) + fprintf(o, "%sChromaSitingVert : %" PRId64 "\n", + indent->indent_str().c_str(), chroma_siting_vert); + if (range != mkvparser::Colour::kValueNotPresent) + fprintf(o, "%sRange : %" PRId64 "\n", + indent->indent_str().c_str(), range); + if (transfer_characteristics != mkvparser::Colour::kValueNotPresent) + fprintf(o, "%sTransferCharacteristics : %" PRId64 "\n", + indent->indent_str().c_str(), transfer_characteristics); + if (primaries != mkvparser::Colour::kValueNotPresent) + fprintf(o, "%sPrimaries : %" PRId64 "\n", + indent->indent_str().c_str(), primaries); + if (max_cll != mkvparser::Colour::kValueNotPresent) + fprintf(o, "%sMaxCLL : %" PRId64 "\n", + indent->indent_str().c_str(), max_cll); + if (max_fall != mkvparser::Colour::kValueNotPresent) + fprintf(o, "%sMaxFALL : %" PRId64 "\n", + indent->indent_str().c_str(), max_fall); + + const mkvparser::MasteringMetadata* const metadata = + colour->mastering_metadata; + if (metadata) { + // TODO(fgalligan): Add support for MasteringMetadata's address and + // size. + fprintf(o, "%sMasteringMetadata:\n", indent->indent_str().c_str()); + indent->Adjust(libwebm::kIncreaseIndent); + + const mkvparser::PrimaryChromaticity* const red = metadata->r; + const mkvparser::PrimaryChromaticity* const green = metadata->g; + const mkvparser::PrimaryChromaticity* const blue = metadata->b; + const mkvparser::PrimaryChromaticity* const white = + metadata->white_point; + const float max = metadata->luminance_max; + const float min = metadata->luminance_min; + if (red) { + fprintf(o, "%sPrimaryRChromaticityX : %g\n", + indent->indent_str().c_str(), red->x); + fprintf(o, "%sPrimaryRChromaticityY : %g\n", + indent->indent_str().c_str(), red->y); + } + if (green) { + fprintf(o, "%sPrimaryGChromaticityX : %g\n", + indent->indent_str().c_str(), green->x); + fprintf(o, "%sPrimaryGChromaticityY : %g\n", + indent->indent_str().c_str(), green->y); + } + if (blue) { + fprintf(o, "%sPrimaryBChromaticityX : %g\n", + indent->indent_str().c_str(), blue->x); + fprintf(o, "%sPrimaryBChromaticityY : %g\n", + indent->indent_str().c_str(), blue->y); + } + if (white) { + fprintf(o, "%sWhitePointChromaticityX : %g\n", + indent->indent_str().c_str(), white->x); + fprintf(o, "%sWhitePointChromaticityY : %g\n", + indent->indent_str().c_str(), white->y); + } + if (max != mkvparser::MasteringMetadata::kValueNotPresent) + fprintf(o, "%sLuminanceMax : %g\n", + indent->indent_str().c_str(), max); + if (min != mkvparser::MasteringMetadata::kValueNotPresent) + fprintf(o, "%sLuminanceMin : %g\n", + indent->indent_str().c_str(), min); + indent->Adjust(libwebm::kDecreaseIndent); + } + indent->Adjust(libwebm::kDecreaseIndent); + } + + const mkvparser::Projection* const projection = + video_track->GetProjection(); + if (projection) { + fprintf(o, "%sProjection:\n", indent->indent_str().c_str()); + indent->Adjust(libwebm::kIncreaseIndent); + + const int projection_type = static_cast(projection->type); + const int kTypeNotPresent = + static_cast(mkvparser::Projection::kTypeNotPresent); + const float kValueNotPresent = mkvparser::Projection::kValueNotPresent; + if (projection_type != kTypeNotPresent) + fprintf(o, "%sProjectionType : %d\n", + indent->indent_str().c_str(), projection_type); + if (projection->private_data) + fprintf(o, "%sProjectionPrivate(size) : %d\n", + indent->indent_str().c_str(), + static_cast(projection->private_data_length)); + if (projection->pose_yaw != kValueNotPresent) + fprintf(o, "%sProjectionPoseYaw : %g\n", + indent->indent_str().c_str(), projection->pose_yaw); + if (projection->pose_pitch != kValueNotPresent) + fprintf(o, "%sProjectionPosePitch : %g\n", + indent->indent_str().c_str(), projection->pose_pitch); + if (projection->pose_roll != kValueNotPresent) + fprintf(o, "%sProjectionPoseRoll : %g\n", + indent->indent_str().c_str(), projection->pose_roll); + indent->Adjust(libwebm::kDecreaseIndent); + } + } else if (track_type == mkvparser::Track::kAudio) { + const mkvparser::AudioTrack* const audio_track = + static_cast(track); + const int64_t channels = audio_track->GetChannels(); + const int64_t bit_depth = audio_track->GetBitDepth(); + const uint64_t codec_delay = audio_track->GetCodecDelay(); + const uint64_t seek_preroll = audio_track->GetSeekPreRoll(); + fprintf(o, "%sChannels : %" PRId64 "\n", + indent->indent_str().c_str(), channels); + if (bit_depth > 0) + fprintf(o, "%sBitDepth : %" PRId64 "\n", + indent->indent_str().c_str(), bit_depth); + fprintf(o, "%sSamplingFrequency: %g\n", indent->indent_str().c_str(), + audio_track->GetSamplingRate()); + if (codec_delay) + fprintf(o, "%sCodecDelay : %" PRIu64 "\n", + indent->indent_str().c_str(), codec_delay); + if (seek_preroll) + fprintf(o, "%sSeekPreRoll : %" PRIu64 "\n", + indent->indent_str().c_str(), seek_preroll); + } + indent->Adjust(libwebm::kDecreaseIndent * 2); + } + + return true; +} + +// libvpx reference: vp9/vp9_dx_iface.c +void ParseSuperframeIndex(const uint8_t* data, size_t data_sz, + uint32_t sizes[8], int* count) { + const uint8_t marker = data[data_sz - 1]; + *count = 0; + + if ((marker & 0xe0) == 0xc0) { + const int frames = (marker & 0x7) + 1; + const int mag = ((marker >> 3) & 0x3) + 1; + const size_t index_sz = 2 + mag * frames; + + if (data_sz >= index_sz && data[data_sz - index_sz] == marker) { + // found a valid superframe index + const uint8_t* x = data + data_sz - index_sz + 1; + + for (int i = 0; i < frames; ++i) { + uint32_t this_sz = 0; + + for (int j = 0; j < mag; ++j) { + this_sz |= (*x++) << (j * 8); + } + sizes[i] = this_sz; + } + *count = frames; + } + } +} + +void PrintVP9Info(const uint8_t* data, int size, FILE* o, int64_t time_ns, + FrameStats* stats, vp9_parser::Vp9HeaderParser* parser, + vp9_parser::Vp9LevelStats* level_stats) { + if (size < 1) + return; + + uint32_t sizes[8]; + int i = 0, count = 0; + ParseSuperframeIndex(data, size, sizes, &count); + + // Remove all frames that are less than window size. + while (!stats->window.empty() && + stats->window.front() < (time_ns - (kNanosecondsPerSecondi - 1))) + stats->window.pop(); + + do { + const size_t frame_length = (count > 0) ? sizes[i] : size; + if (frame_length > static_cast(std::numeric_limits::max()) || + static_cast(frame_length) > size) { + fprintf(o, " invalid VP9 frame size (%u)\n", + static_cast(frame_length)); + return; + } + if (!parser->ParseUncompressedHeader(data, frame_length)) + return; + level_stats->AddFrame(*parser, time_ns); + + // const int frame_marker = (data[0] >> 6) & 0x3; + const int version = parser->profile(); + const int key = parser->key(); + const int altref_frame = parser->altref(); + const int error_resilient_mode = parser->error_resilient_mode(); + const int row_tiles = parser->row_tiles(); + const int column_tiles = parser->column_tiles(); + const int frame_parallel_mode = parser->frame_parallel_mode(); + + if (key && + !(size >= 4 && data[1] == 0x49 && data[2] == 0x83 && data[3] == 0x42)) { + fprintf(o, " invalid VP9 signature"); + return; + } + + stats->window.push(time_ns); + ++stats->frames; + + if (altref_frame) { + const int delta_altref = stats->frames_since_last_altref; + if (stats->first_altref) { + stats->first_altref = false; + } else if (delta_altref < stats->minimum_altref_distance) { + stats->minimum_altref_distance = delta_altref; + stats->min_altref_end_ns = time_ns; + } + stats->frames_since_last_altref = 0; + } else { + ++stats->frames_since_last_altref; + ++stats->displayed_frames; + } + + if (count > 0) { + fprintf(o, " packed [%d]: {", i); + } + + fprintf(o, " key:%d v:%d altref:%d errm:%d rt:%d ct:%d fpm:%d", key, + version, altref_frame, error_resilient_mode, row_tiles, + column_tiles, frame_parallel_mode); + + if (key) { + if (size > 4) { + fprintf(o, " cs:%d", parser->color_space()); + } + if (parser->display_width() != parser->width() || + parser->display_height() != parser->height()) { + fprintf(o, " dw:%d dh:%d", parser->display_width(), + parser->display_height()); + } + } + + if (count > 0) { + fprintf(o, " size: %u }", sizes[i]); + data += sizes[i]; + size -= sizes[i]; + } + ++i; + } while (i < count); + + if (stats->max_window_size < static_cast(stats->window.size())) { + stats->max_window_size = stats->window.size(); + stats->max_window_end_ns = time_ns; + } +} + +void PrintVP8Info(const uint8_t* data, int size, FILE* o) { + if (size < 3) + return; + + const uint32_t bits = data[0] | (data[1] << 8) | (data[2] << 16); + const int key = !(bits & 0x1); + const int altref_frame = !((bits >> 4) & 0x1); + const int version = (bits >> 1) & 0x7; + const int partition_length = (bits >> 5) & 0x7FFFF; + if (key && + !(size >= 6 && data[3] == 0x9d && data[4] == 0x01 && data[5] == 0x2a)) { + fprintf(o, " invalid VP8 signature"); + return; + } + fprintf(o, " key:%d v:%d altref:%d partition_length:%d", key, version, + altref_frame, partition_length); +} + +// Prints the partition offsets of the sub-sample encryption. |data| must point +// to an encrypted frame just after the signal byte. Returns the number of +// bytes read from the sub-sample partition information. +int PrintSubSampleEncryption(const uint8_t* data, int size, FILE* o) { + int read_end = sizeof(uint64_t); + + // Skip past IV. + if (size < read_end) + return 0; + data += sizeof(uint64_t); + + // Read number of partitions. + read_end += sizeof(uint8_t); + if (size < read_end) + return 0; + const int num_partitions = data[0]; + data += sizeof(uint8_t); + + // Read partitions. + for (int i = 0; i < num_partitions; ++i) { + read_end += sizeof(uint32_t); + if (size < read_end) + return 0; + uint32_t partition_offset; + memcpy(&partition_offset, data, sizeof(partition_offset)); + partition_offset = libwebm::bigendian_to_host(partition_offset); + fprintf(o, " off[%d]:%u", i, partition_offset); + data += sizeof(uint32_t); + } + + return read_end; +} + +bool OutputCluster(const mkvparser::Cluster& cluster, + const mkvparser::Tracks& tracks, const Options& options, + FILE* o, mkvparser::MkvReader* reader, Indent* indent, + int64_t* clusters_size, FrameStats* stats, + vp9_parser::Vp9HeaderParser* parser, + vp9_parser::Vp9LevelStats* level_stats) { + if (clusters_size) { + // Load the Cluster. + const mkvparser::BlockEntry* block_entry; + long status = cluster.GetFirst(block_entry); + if (status) { + fprintf(stderr, "Could not get first Block of Cluster.\n"); + return false; + } + + *clusters_size += cluster.GetElementSize(); + } + + if (options.output_clusters) { + const int64_t time_ns = cluster.GetTime(); + const int64_t duration_ns = cluster.GetLastTime() - cluster.GetFirstTime(); + + fprintf(o, "%sCluster:", indent->indent_str().c_str()); + if (options.output_offset) + fprintf(o, " @: %lld", cluster.m_element_start); + if (options.output_size) + fprintf(o, " size: %lld", cluster.GetElementSize()); + fprintf(o, "\n"); + indent->Adjust(libwebm::kIncreaseIndent); + if (options.output_seconds) + fprintf(o, "%sTimecode (sec) : %g\n", indent->indent_str().c_str(), + time_ns / kNanosecondsPerSecond); + else + fprintf(o, "%sTimecode (nano): %" PRId64 "\n", + indent->indent_str().c_str(), time_ns); + if (options.output_seconds) + fprintf(o, "%sDuration (sec) : %g\n", indent->indent_str().c_str(), + duration_ns / kNanosecondsPerSecond); + else + fprintf(o, "%sDuration (nano): %" PRId64 "\n", + indent->indent_str().c_str(), duration_ns); + + fprintf(o, "%s# Blocks : %ld\n", indent->indent_str().c_str(), + cluster.GetEntryCount()); + } + + if (options.output_blocks) { + const mkvparser::BlockEntry* block_entry; + long status = cluster.GetFirst(block_entry); + if (status) { + fprintf(stderr, "Could not get first Block of Cluster.\n"); + return false; + } + + std::vector vector_data; + while (block_entry != NULL && !block_entry->EOS()) { + const mkvparser::Block* const block = block_entry->GetBlock(); + if (!block) { + fprintf(stderr, "Could not getblock entry.\n"); + return false; + } + + const unsigned int track_number = + static_cast(block->GetTrackNumber()); + const mkvparser::Track* track = tracks.GetTrackByNumber(track_number); + if (!track) { + fprintf(stderr, "Could not get Track.\n"); + return false; + } + + const int64_t track_type = track->GetType(); + if ((track_type == mkvparser::Track::kVideo && options.output_video) || + (track_type == mkvparser::Track::kAudio && options.output_audio)) { + const int64_t time_ns = block->GetTime(&cluster); + const bool is_key = block->IsKey(); + + if (block_entry->GetKind() == mkvparser::BlockEntry::kBlockGroup) { + fprintf(o, "%sBlockGroup:\n", indent->indent_str().c_str()); + indent->Adjust(libwebm::kIncreaseIndent); + } + + fprintf(o, "%sBlock: type:%s frame:%s", indent->indent_str().c_str(), + track_type == mkvparser::Track::kVideo ? "V" : "A", + is_key ? "I" : "P"); + if (options.output_seconds) + fprintf(o, " secs:%5g", time_ns / kNanosecondsPerSecond); + else + fprintf(o, " nano:%10" PRId64, time_ns); + + if (options.output_offset) + fprintf(o, " @_payload: %lld", block->m_start); + if (options.output_size) + fprintf(o, " size_payload: %lld", block->m_size); + + const uint8_t KEncryptedBit = 0x1; + const uint8_t kSubSampleBit = 0x2; + const int kSignalByteSize = 1; + bool encrypted_stream = false; + if (options.output_encrypted_info) { + if (track->GetContentEncodingCount() > 0) { + // Only check the first content encoding. + const ContentEncoding* const encoding = + track->GetContentEncodingByIndex(0); + if (encoding) { + if (encoding->GetEncryptionCount() > 0) { + const ContentEncoding::ContentEncryption* const encryption = + encoding->GetEncryptionByIndex(0); + if (encryption) { + const ContentEncoding::ContentEncAESSettings& aes = + encryption->aes_settings; + if (aes.cipher_mode == 1) { + encrypted_stream = true; + } + } + } + } + } + + if (encrypted_stream) { + const mkvparser::Block::Frame& frame = block->GetFrame(0); + if (frame.len > static_cast(vector_data.size())) { + vector_data.resize(frame.len + 1024); + } + + unsigned char* data = &vector_data[0]; + if (frame.Read(reader, data) < 0) { + fprintf(stderr, "Could not read frame.\n"); + return false; + } + + const bool encrypted_frame = !!(data[0] & KEncryptedBit); + const bool sub_sample_encrypt = !!(data[0] & kSubSampleBit); + fprintf(o, " enc: %d", encrypted_frame ? 1 : 0); + fprintf(o, " sub: %d", sub_sample_encrypt ? 1 : 0); + + if (encrypted_frame) { + uint64_t iv; + memcpy(&iv, data + kSignalByteSize, sizeof(iv)); + fprintf(o, " iv: %" PRIx64, iv); + } + } + } + + if (options.output_codec_info) { + const int frame_count = block->GetFrameCount(); + + if (frame_count > 1) { + fprintf(o, "\n"); + indent->Adjust(libwebm::kIncreaseIndent); + } + + for (int i = 0; i < frame_count; ++i) { + if (track_type == mkvparser::Track::kVideo) { + const mkvparser::Block::Frame& frame = block->GetFrame(i); + if (frame.len > static_cast(vector_data.size())) { + vector_data.resize(frame.len + 1024); + } + + unsigned char* data = &vector_data[0]; + if (frame.Read(reader, data) < 0) { + fprintf(stderr, "Could not read frame.\n"); + return false; + } + + if (frame_count > 1) + fprintf(o, "\n%sVP8 data :", indent->indent_str().c_str()); + + bool encrypted_frame = false; + bool sub_sample_encrypt = false; + int frame_size = static_cast(frame.len); + + int frame_offset = 0; + if (encrypted_stream) { + if (data[0] & KEncryptedBit) { + encrypted_frame = true; + if (data[0] & kSubSampleBit) { + sub_sample_encrypt = true; + data += kSignalByteSize; + frame_size -= kSignalByteSize; + frame_offset = + PrintSubSampleEncryption(data, frame_size, o); + } + } else { + frame_offset = kSignalByteSize; + } + } + + if (!encrypted_frame || sub_sample_encrypt) { + data += frame_offset; + frame_size -= frame_offset; + + const string codec_id = ToString(track->GetCodecId()); + if (codec_id == "V_VP8") { + PrintVP8Info(data, frame_size, o); + } else if (codec_id == "V_VP9") { + PrintVP9Info(data, frame_size, o, time_ns, stats, parser, + level_stats); + } + } + } + } + + if (frame_count > 1) + indent->Adjust(libwebm::kDecreaseIndent); + } + + if (block_entry->GetKind() == mkvparser::BlockEntry::kBlockGroup) { + const int64_t discard_padding = block->GetDiscardPadding(); + if (discard_padding != 0) { + fprintf(o, "\n%sDiscardPadding: %10" PRId64, + indent->indent_str().c_str(), discard_padding); + } + indent->Adjust(libwebm::kDecreaseIndent); + } + + fprintf(o, "\n"); + } + + status = cluster.GetNext(block_entry, block_entry); + if (status) { + printf("\n Could not get next block of cluster.\n"); + return false; + } + } + } + + if (options.output_clusters) + indent->Adjust(libwebm::kDecreaseIndent); + + return true; +} + +bool OutputCues(const mkvparser::Segment& segment, + const mkvparser::Tracks& tracks, const Options& options, + FILE* o, Indent* indent) { + const mkvparser::Cues* const cues = segment.GetCues(); + if (cues == NULL) + return true; + + // Load all of the cue points. + while (!cues->DoneParsing()) + cues->LoadCuePoint(); + + // Confirm that the input has cue points. + const mkvparser::CuePoint* const first_cue = cues->GetFirst(); + if (first_cue == NULL) { + fprintf(o, "%sNo cue points.\n", indent->indent_str().c_str()); + return true; + } + + // Input has cue points, dump them: + fprintf(o, "%sCues:", indent->indent_str().c_str()); + if (options.output_offset) + fprintf(o, " @:%lld", cues->m_element_start); + if (options.output_size) + fprintf(o, " size:%lld", cues->m_element_size); + fprintf(o, "\n"); + + const mkvparser::CuePoint* cue_point = first_cue; + int cue_point_num = 1; + const int num_tracks = static_cast(tracks.GetTracksCount()); + indent->Adjust(libwebm::kIncreaseIndent); + + do { + for (int track_num = 0; track_num < num_tracks; ++track_num) { + const mkvparser::Track* const track = tracks.GetTrackByIndex(track_num); + const mkvparser::CuePoint::TrackPosition* const track_pos = + cue_point->Find(track); + + if (track_pos != NULL) { + const char track_type = + (track->GetType() == mkvparser::Track::kVideo) ? 'V' : 'A'; + fprintf(o, "%sCue Point:%d type:%c track:%d", + indent->indent_str().c_str(), cue_point_num, track_type, + static_cast(track->GetNumber())); + + if (options.output_seconds) { + fprintf(o, " secs:%g", + cue_point->GetTime(&segment) / kNanosecondsPerSecond); + } else { + fprintf(o, " nano:%lld", cue_point->GetTime(&segment)); + } + + if (options.output_blocks) + fprintf(o, " block:%lld", track_pos->m_block); + + if (options.output_offset) + fprintf(o, " @:%lld", track_pos->m_pos); + + fprintf(o, "\n"); + } + } + + cue_point = cues->GetNext(cue_point); + ++cue_point_num; + } while (cue_point != NULL); + + indent->Adjust(libwebm::kDecreaseIndent); + return true; +} + +} // namespace + +int main(int argc, char* argv[]) { + string input; + Options options; + + const int argc_check = argc - 1; + for (int i = 1; i < argc; ++i) { + if (!strcmp("-h", argv[i]) || !strcmp("-?", argv[i])) { + Usage(); + return EXIT_SUCCESS; + } else if (!strcmp("-v", argv[i])) { + printf("version: %s\n", VERSION_STRING); + } else if (!strcmp("-i", argv[i]) && i < argc_check) { + input = argv[++i]; + } else if (!strcmp("-all", argv[i])) { + options.SetAll(true); + } else if (Options::MatchesBooleanOption("video", argv[i])) { + options.output_video = !strcmp("-video", argv[i]); + } else if (Options::MatchesBooleanOption("audio", argv[i])) { + options.output_audio = !strcmp("-audio", argv[i]); + } else if (Options::MatchesBooleanOption("size", argv[i])) { + options.output_size = !strcmp("-size", argv[i]); + } else if (Options::MatchesBooleanOption("offset", argv[i])) { + options.output_offset = !strcmp("-offset", argv[i]); + } else if (Options::MatchesBooleanOption("times_seconds", argv[i])) { + options.output_seconds = !strcmp("-times_seconds", argv[i]); + } else if (Options::MatchesBooleanOption("ebml_header", argv[i])) { + options.output_ebml_header = !strcmp("-ebml_header", argv[i]); + } else if (Options::MatchesBooleanOption("segment", argv[i])) { + options.output_segment = !strcmp("-segment", argv[i]); + } else if (Options::MatchesBooleanOption("seekhead", argv[i])) { + options.output_seekhead = !strcmp("-seekhead", argv[i]); + } else if (Options::MatchesBooleanOption("segment_info", argv[i])) { + options.output_segment_info = !strcmp("-segment_info", argv[i]); + } else if (Options::MatchesBooleanOption("tracks", argv[i])) { + options.output_tracks = !strcmp("-tracks", argv[i]); + } else if (Options::MatchesBooleanOption("clusters", argv[i])) { + options.output_clusters = !strcmp("-clusters", argv[i]); + } else if (Options::MatchesBooleanOption("blocks", argv[i])) { + options.output_blocks = !strcmp("-blocks", argv[i]); + } else if (Options::MatchesBooleanOption("codec_info", argv[i])) { + options.output_codec_info = !strcmp("-codec_info", argv[i]); + } else if (Options::MatchesBooleanOption("clusters_size", argv[i])) { + options.output_clusters_size = !strcmp("-clusters_size", argv[i]); + } else if (Options::MatchesBooleanOption("encrypted_info", argv[i])) { + options.output_encrypted_info = !strcmp("-encrypted_info", argv[i]); + } else if (Options::MatchesBooleanOption("cues", argv[i])) { + options.output_cues = !strcmp("-cues", argv[i]); + } else if (Options::MatchesBooleanOption("frame_stats", argv[i])) { + options.output_frame_stats = !strcmp("-frame_stats", argv[i]); + } else if (Options::MatchesBooleanOption("vp9_level", argv[i])) { + options.output_vp9_level = !strcmp("-vp9_level", argv[i]); + } + } + + if (argc < 3 || input.empty()) { + Usage(); + return EXIT_FAILURE; + } + + std::unique_ptr reader( + new (std::nothrow) mkvparser::MkvReader()); // NOLINT + if (reader->Open(input.c_str())) { + fprintf(stderr, "Error opening file:%s\n", input.c_str()); + return EXIT_FAILURE; + } + + long long int pos = 0; + std::unique_ptr ebml_header( + new (std::nothrow) mkvparser::EBMLHeader()); // NOLINT + if (ebml_header->Parse(reader.get(), pos) < 0) { + fprintf(stderr, "Error parsing EBML header.\n"); + return EXIT_FAILURE; + } + + Indent indent(0); + FILE* out = stdout; + + if (options.output_ebml_header) + OutputEBMLHeader(*ebml_header.get(), out, &indent); + + mkvparser::Segment* temp_segment; + if (mkvparser::Segment::CreateInstance(reader.get(), pos, temp_segment)) { + fprintf(stderr, "Segment::CreateInstance() failed.\n"); + return EXIT_FAILURE; + } + std::unique_ptr segment(temp_segment); + + if (segment->Load() < 0) { + fprintf(stderr, "Segment::Load() failed.\n"); + return EXIT_FAILURE; + } + + if (options.output_segment) { + OutputSegment(*(segment.get()), options, out); + indent.Adjust(libwebm::kIncreaseIndent); + } + + if (options.output_seekhead) + if (!OutputSeekHead(*(segment.get()), options, out, &indent)) + return EXIT_FAILURE; + + if (options.output_segment_info) + if (!OutputSegmentInfo(*(segment.get()), options, out, &indent)) + return EXIT_FAILURE; + + if (options.output_tracks) + if (!OutputTracks(*(segment.get()), options, out, &indent)) + return EXIT_FAILURE; + + const mkvparser::Tracks* const tracks = segment->GetTracks(); + if (!tracks) { + fprintf(stderr, "Could not get Tracks.\n"); + return EXIT_FAILURE; + } + + // If Cues are before the clusters output them first. + if (options.output_cues) { + const mkvparser::Cluster* cluster = segment->GetFirst(); + const mkvparser::Cues* const cues = segment->GetCues(); + if (cluster != NULL && cues != NULL) { + if (cues->m_element_start < cluster->m_element_start) { + if (!OutputCues(*segment, *tracks, options, out, &indent)) { + return EXIT_FAILURE; + } + options.output_cues = false; + } + } + } + + if (options.output_clusters) + fprintf(out, "%sClusters (count):%ld\n", indent.indent_str().c_str(), + segment->GetCount()); + + int64_t clusters_size = 0; + FrameStats stats; + vp9_parser::Vp9HeaderParser parser; + vp9_parser::Vp9LevelStats level_stats; + const mkvparser::Cluster* cluster = segment->GetFirst(); + while (cluster != NULL && !cluster->EOS()) { + if (!OutputCluster(*cluster, *tracks, options, out, reader.get(), &indent, + &clusters_size, &stats, &parser, &level_stats)) + return EXIT_FAILURE; + cluster = segment->GetNext(cluster); + } + + if (options.output_clusters_size) + fprintf(out, "%sClusters (size):%" PRId64 "\n", indent.indent_str().c_str(), + clusters_size); + + if (options.output_cues) + if (!OutputCues(*segment, *tracks, options, out, &indent)) + return EXIT_FAILURE; + + // TODO(fgalligan): Add support for VP8. + if (options.output_frame_stats && + stats.minimum_altref_distance != std::numeric_limits::max()) { + const double actual_fps = + stats.frames / + (segment->GetInfo()->GetDuration() / kNanosecondsPerSecond); + const double displayed_fps = + stats.displayed_frames / + (segment->GetInfo()->GetDuration() / kNanosecondsPerSecond); + fprintf(out, "\nActual fps:%g Displayed fps:%g\n", actual_fps, + displayed_fps); + + fprintf(out, "Minimum Altref Distance:%d at:%g seconds\n", + stats.minimum_altref_distance, + stats.min_altref_end_ns / kNanosecondsPerSecond); + + // TODO(fgalligan): Add support for window duration other than 1 second. + const double sec_end = stats.max_window_end_ns / kNanosecondsPerSecond; + const double sec_start = + stats.max_window_end_ns > kNanosecondsPerSecondi ? sec_end - 1.0 : 0.0; + fprintf(out, "Maximum Window:%g-%g seconds Window fps:%" PRId64 "\n", + sec_start, sec_end, stats.max_window_size); + } + + if (options.output_vp9_level) { + level_stats.set_duration(segment->GetInfo()->GetDuration()); + const vp9_parser::Vp9Level level = level_stats.GetLevel(); + fprintf(out, "VP9 Level:%d\n", level); + fprintf( + out, + "mlsr:%" PRId64 " mlps:%" PRId64 " mlpb:%" PRId64 + " abr:%g mcs:%g cr:%g mct:%d" + " mad:%d mrf:%d\n", + level_stats.GetMaxLumaSampleRate(), level_stats.GetMaxLumaPictureSize(), + level_stats.GetMaxLumaPictureBreadth(), level_stats.GetAverageBitRate(), + level_stats.GetMaxCpbSize(), level_stats.GetCompressionRatio(), + level_stats.GetMaxColumnTiles(), level_stats.GetMinimumAltrefDistance(), + level_stats.GetMaxReferenceFrames()); + } + return EXIT_SUCCESS; +} diff --git a/third_party/libwebm/source/webm_parser/README.md b/third_party/libwebm/source/webm_parser/README.md new file mode 100644 index 000000000000..f3d37ff56c73 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/README.md @@ -0,0 +1,325 @@ +# WebM Parser {#mainpage} + +# Introduction + +This WebM parser is a C++11-based parser that aims to be a safe and complete +parser for WebM. It supports all WebM elements (from the old deprecated ones to +the newest ones like `Colour`), including recursive elements like `ChapterAtom` +and `SimpleTag`. It supports incremental parsing; parsing may be stopped at any +point and resumed later as needed. It also supports starting at an arbitrary +WebM element, so parsing need not start from the beginning of the file. + +The parser (`WebmParser`) works by being fed input data from a data source (an +instance of `Reader`) that represents a WebM file. The parser will parse the +WebM data into various data structures that represent the encoded WebM elements, +and then call corresponding `Callback` event methods as the data structures are +parsed. + +# Building + +CMake support has been added to the root libwebm `CMakeLists.txt` file. Simply +enable the `ENABLE_WEBM_PARSER` feature if using the interactive CMake builder, +or alternatively pass the `-DENABLE_WEBM_PARSER:BOOL=ON` flag from the command +line. By default, this parser is not enabled when building libwebm, so you must +explicitly enable it. + +Alternatively, the following illustrates the minimal commands necessary to +compile the code into a static library without CMake: + +```.sh +c++ -Iinclude -I. -std=c++11 -c src/*.cc +ar rcs libwebm.a *.o +``` + +# Using the parser + +There are 3 basic components in the parser that are used: `Reader`, `Callback`, +and `WebmParser`. + +## `Reader` + +The `Reader` interface acts as a data source for the parser. You may subclass it +and implement your own data source if you wish. Alternatively, use the +`FileReader`, `IstreamReader`, or `BufferReader` if you wish to read from a +`FILE*`, `std::istream`, or `std::vector`, respectively. + +The parser supports `Reader` implementations that do short reads. If +`Reader::Skip()` or `Reader::Read()` do a partial read (returning +`Status::kOkPartial`), the parser will call them again in an attempt to read +more data. If no data is available, the `Reader` may return some other status +(like `Status::kWouldBlock`) to indicate that no data is available. In this +situation, the parser will stop parsing and return the status it received. +Parsing may be resumed later when more data is available. + +When the `Reader` has reached the end of the WebM document and no more data is +available, it should return `Status::kEndOfFile`. This will cause parsing to +stop. If the file ends at a valid location (that is, there aren't any elements +that have specified a size that indicates the file ended prematurely), the +parser will translate `Status::kEndOfFile` into `Status::kOkCompleted` and +return it. If the file ends prematurely, the parser will return +`Status::kEndOfFile` to indicate that. + +Note that if the WebM file contains elements that have an unknown size (or a +seek has been performed and the parser doesn't know the size of the root +element(s)), and the parser is parsing them and hits end-of-file, the parser may +still call `Reader::Read()`/`Reader::Skip()` multiple times (even though they've +already reported `Status::kEndOfFile`) as nested parsers terminate parsing. +Because of this, `Reader::Read()`/`Reader::Skip()` implementations should be +able to handle being called multiple times after the file's end has been +reached, and they should consistently return `Status::kEndOfFile`. + +The three provided readers (`FileReader`, `IstreamReader`, and `BufferReader`) +are blocking implementations (they won't return `Status::kWouldBlock`), so if +you're using them the parser will run until it entirely consumes all their data +(unless, of course, you request the parser to stop via `Callback`... see the +next section). + +## `Callback` + +As the parser progresses through the file, it builds objects (see +`webm/dom_types.h`) that represent parsed data structures. The parser then +notifies the `Callback` implementation as objects complete parsing. For some +data structures (like frames or Void elements), the parser notifies the +`Callback` and requests it to consume the data directly from the `Reader` (this +is done for structures that can be large/frequent binary blobs in order to allow +you to read the data directly into the object/type of your choice, rather than +just reading them into a `std::vector` and making you copy it into +a different object if you wanted to work with something other than +`std::vector`). + +The parser was designed to parse the data into objects that are small enough +that the `Callback` can be quickly and frequently notified as soon as the object +is ready, but large enough that the objects received by the `Callback` are still +useful. Having `Callback` events for every tiny integer/float/string/etc. +element would require too much assembly and work to be useful to most users, and +pasing the file into a single DOM tree (or a small handful of large conglomerate +structures) would unnecessarily delay video playback or consume too much memory +on smaller devices. + +The parser may call the following methods while nearly anywhere in the file: + +- `Callback::OnElementBegin()`: This is called for every element that the + parser encounters. This is primarily useful if you want to skip some + elements or build a map of every element in the file. +- `Callback::OnUnknownElement()`: This is called when an element is either not + a valid/recognized WebM element, or it is a WebM element but is improperly + nested (e.g. an EBMLVersion element inside of a Segment element). The parser + doesn't know how to handle the element; it could just skip it but instead + defers to the `Callback` to decide how it should be handled. The default + implementation just skips the element. +- `Callback::OnVoid()`: Void elements can appear anywhere in any master + element. This method will be called to handle the Void element. + +The parser may call the following methods in the proper nesting order, as shown +in the list. A `*Begin()` method will always be matched up with its +corresponding `*End()` method (unless a seek has been performed). The parser +will only call the methods in the proper nesting order as specified in the WebM +DOM. For example, `Callback::OnEbml()` will never be called in between +`Callback::OnSegmentBegin()`/`Callback::OnSegmentEnd()` (since the EBML element +is not a child of the Segment element), and `Callback::OnTrackEntry()` will only +ever be called in between +`Callback::OnSegmentBegin()`/`Callback::OnSegmentEnd()` (since the TrackEntry +element is a (grand-)child of the Segment element and must be contained by a +Segment element). `Callback::OnFrame()` is listed twice because it will be +called to handle frames contained in both SimpleBlock and Block elements. + +- `Callback::OnEbml()` +- `Callback::OnSegmentBegin()` + - `Callback::OnSeek()` + - `Callback::OnInfo()` + - `Callback::OnClusterBegin()` + - `Callback::OnSimpleBlockBegin()` + - `Callback::OnFrame()` + - `Callback::OnSimpleBlockEnd()` + - `Callback::OnBlockGroupBegin()` + - `Callback::OnBlockBegin()` + - `Callback::OnFrame()` + - `Callback::OnBlockEnd()` + - `Callback::OnBlockGroupEnd()` + - `Callback::OnClusterEnd()` + - `Callback::OnTrackEntry()` + - `Callback::OnCuePoint()` + - `Callback::OnEditionEntry()` + - `Callback::OnTag()` +- `Callback::OnSegmentEnd()` + +Only `Callback::OnFrame()` (and no other `Callback` methods) will be called in +between `Callback::OnSimpleBlockBegin()`/`Callback::OnSimpleBlockEnd()` or +`Callback::OnBlockBegin()`/`Callback::OnBlockEnd()`, since the SimpleBlock and +Block elements are not master elements only contain frames. + +Note that seeking into the middle of the file may cause the parser to skip some +`*Begin()` methods. For example, if a seek is performed to a SimpleBlock +element, `Callback::OnSegmentBegin()` and `Callback::OnClusterBegin()` will not +be called. In this situation, the full sequence of callback events would be +(assuming the file ended after the SimpleBlock): +`Callback::OnSimpleBlockBegin()`, `Callback::OnFrame()` (for every frame in the +SimpleBlock), `Callback::OnSimpleBlockEnd()`, `Callback::OnClusterEnd()`, and +`Callback::OnSegmentEnd()`. Since the Cluster and Segment elements were skipped, +the `Cluster` DOM object may have some members marked as absent, and the +`*End()` events for the Cluster and Segment elements will have metadata with +unknown header position, header length, and body size (see `kUnknownHeaderSize`, +`kUnknownElementSize`, and `kUnknownElementPosition`). + +When a `Callback` method has completed, it should return `Status::kOkCompleted` +to allow parsing to continue. If you would like parsing to stop, return any +other status code (except `Status::kEndOfFile`, since that's treated somewhat +specially and is intended for `Reader`s to use), which the parser will return. +If you return a non-parsing-error status code (.e.g. `Status::kOkPartial`, +`Status::kWouldBlock`, etc. or your own status code with a value > 0), parsing +may be resumed again. When parsing is resumed, the parser will call the same +callback method again (and once again, you may return `Status::kOkCompleted` to +let parsing continue or some other value to stop parsing). + +You may subclass the `Callback` element and override methods which you are +interested in receiving events for. By default, methods taking an `Action` +parameter will set it to `Action::kRead` so the entire file is parsed. The +`Callback::OnFrame()` method will just skip over the frame bytes by default. + +## `WebmParser` + +The actual parsing work is done with `WebmParser`. Simply construct a +`WebmParser` and call `WebmParser::Feed()` (providing it a `Callback` and +`Reader` instance) to parse a file. It will return `Status::kOkCompleted` when +the entire file has been successfully parsed. `WebmParser::Feed()` doesn't store +any internal references to the `Callback` or `Reader`. + +If you wish to start parsing from the middle of a file, call +`WebmParser::DidSeek()` before calling `WebmParser::Feed()` to prepare the +parser to receive data starting at an arbitrary point in the file. When seeking, +you should seek to the beginning of a WebM element; seeking to a location that +is not the start of a WebM element (e.g. seeking to a frame, rather than its +containing SimpleBlock/Block element) will cause parsing to fail. Calling +`WebmParser::DidSeek()` will reset the state of the parser and clear any +internal errors, so a `WebmParser` instance may be reused (even if it has +previously failed to parse a file). + +## Building your program + +The following program is a small program that completely parses a file from +stdin: + +```.cc +#include +#include +#include + +int main() { + webm::Callback callback; + webm::FileReader reader(std::freopen(nullptr, "rb", stdin)); + webm::WebmParser parser; + parser.Feed(&callback, &reader); +} +``` + +It completely parses the input file, but we need to make a new class that +derives from `Callback` if we want to receive any parsing events. So if we +change it to: + +```.cc +#include +#include + +#include +#include +#include +#include + +class MyCallback : public webm::Callback { + public: + webm::Status OnElementBegin(const webm::ElementMetadata& metadata, + webm::Action* action) override { + std::cout << "Element ID = 0x" + << std::hex << static_cast(metadata.id); + std::cout << std::dec; // Reset to decimal mode. + std::cout << " at position "; + if (metadata.position == webm::kUnknownElementPosition) { + // The position will only be unknown if we've done a seek. But since we + // aren't seeking in this demo, this will never be the case. However, this + // if-statement is included for completeness. + std::cout << ""; + } else { + std::cout << metadata.position; + } + std::cout << " with header size "; + if (metadata.header_size == webm::kUnknownHeaderSize) { + // The header size will only be unknown if we've done a seek. But since we + // aren't seeking in this demo, this will never be the case. However, this + // if-statement is included for completeness. + std::cout << ""; + } else { + std::cout << metadata.header_size; + } + std::cout << " and body size "; + if (metadata.size == webm::kUnknownElementSize) { + // WebM master elements may have an unknown size, though this is rare. + std::cout << ""; + } else { + std::cout << metadata.size; + } + std::cout << '\n'; + + *action = webm::Action::kRead; + return webm::Status(webm::Status::kOkCompleted); + } +}; + +int main() { + MyCallback callback; + webm::FileReader reader(std::freopen(nullptr, "rb", stdin)); + webm::WebmParser parser; + webm::Status status = parser.Feed(&callback, &reader); + if (status.completed_ok()) { + std::cout << "Parsing successfully completed\n"; + } else { + std::cout << "Parsing failed with status code: " << status.code << '\n'; + } +} +``` + +This will output information about every element in the entire file: it's ID, +position, header size, and body size. The status of the parse is also checked +and reported. + +For a more complete example, see `demo/demo.cc`, which parses an entire file and +prints out all of its information. That example overrides every `Callback` +method to show exactly what information is available while parsing and how to +access it. The example is verbose, but that's primarily due to pretty-printing +and string formatting operations. + +When compiling your program, add the `include` directory to your compiler's +header search paths and link to the compiled library. Be sure your compiler has +C++11 mode enabled (`-std=c++11` in clang++ or g++). + +# Testing + +Unit tests are located in the `tests` directory. Google Test and Google Mock are +used as testing frameworks. Building and running the tests will be supported in +the upcoming CMake scripts, but they can currently be built and run by manually +compiling them (and linking to Google Test and Google Mock). + +# Fuzzing + +The parser has been fuzzed with [AFL](http://lcamtuf.coredump.cx/afl/) and +[libFuzzer](http://llvm.org/docs/LibFuzzer.html). If you wish to fuzz the parser +with AFL or libFuzzer but don't want to write an executable that exercises the +parsing API, you may use `fuzzing/webm_fuzzer.cc`. + +When compiling for fuzzing, define the macro +`WEBM_FUZZER_BYTE_ELEMENT_SIZE_LIMIT` to be some integer in order to limit the +maximum size of ASCII/UTF-8/binary elements. It's too easy for the fuzzer to +generate elements that claim to have a ridiculously massive size, which will +cause allocations to fail or the program to allocate too much memory. AFL will +terminate the process if it allocates too much memory (by default, 50 MB), and +the [Address Sanitizer doesn't throw `std::bad_alloc` when an allocation fails] +(https://github.com/google/sanitizers/issues/295). Defining +`WEBM_FUZZER_BYTE_ELEMENT_SIZE_LIMIT` to a low number (say, 1024) will cause the +ASCII/UTF-8/binary element parsers to return `Status::kNotEnoughMemory` if the +element's size exceeds `WEBM_FUZZER_BYTE_ELEMENT_SIZE_LIMIT`, which will avoid +false positives when fuzzing. The parser expects `std::string` and `std::vector` +to throw `std::bad_alloc` when an allocation fails, which doesn't necessarily +happen due to the fuzzers' limitations. + +You may also define the macro `WEBM_FUZZER_SEEK_FIRST` to have +`fuzzing/webm_fuzzer.cc` call `WebmParser::DidSeek()` before doing any parsing. +This will test the seeking code paths. diff --git a/third_party/libwebm/source/webm_parser/demo/demo.cc b/third_party/libwebm/source/webm_parser/demo/demo.cc new file mode 100644 index 000000000000..47ecbb0de166 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/demo/demo.cc @@ -0,0 +1,1161 @@ +// Copyright (c) 2016 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +#include +#include +#include +#include + +#include "webm/callback.h" +#include "webm/file_reader.h" +#include "webm/status.h" +#include "webm/webm_parser.h" + +// We use pretty much everything in the webm namespace. Just pull +// it all in. +using namespace webm; // NOLINT + +template +std::ostream& PrintUnknownEnumValue(std::ostream& os, T value) { + return os << std::to_string(static_cast(value)) << " (?)"; +} + +// Overloads for operator<< for pretty printing enums. +std::ostream& operator<<(std::ostream& os, Id id) { + switch (id) { + case Id::kEbml: + return os << "EBML"; + case Id::kEbmlVersion: + return os << "EBMLVersion"; + case Id::kEbmlReadVersion: + return os << "EBMLReadVersion"; + case Id::kEbmlMaxIdLength: + return os << "EBMLMaxIDLength"; + case Id::kEbmlMaxSizeLength: + return os << "EBMLMaxSizeLength"; + case Id::kDocType: + return os << "DocType"; + case Id::kDocTypeVersion: + return os << "DocTypeVersion"; + case Id::kDocTypeReadVersion: + return os << "DocTypeReadVersion"; + case Id::kVoid: + return os << "Void"; + case Id::kSegment: + return os << "Segment"; + case Id::kSeekHead: + return os << "SeekHead"; + case Id::kSeek: + return os << "Seek"; + case Id::kSeekId: + return os << "SeekID"; + case Id::kSeekPosition: + return os << "SeekPosition"; + case Id::kInfo: + return os << "Info"; + case Id::kTimecodeScale: + return os << "TimecodeScale"; + case Id::kDuration: + return os << "Duration"; + case Id::kDateUtc: + return os << "DateUTC"; + case Id::kTitle: + return os << "Title"; + case Id::kMuxingApp: + return os << "MuxingApp"; + case Id::kWritingApp: + return os << "WritingApp"; + case Id::kCluster: + return os << "Cluster"; + case Id::kTimecode: + return os << "Timecode"; + case Id::kPrevSize: + return os << "PrevSize"; + case Id::kSimpleBlock: + return os << "SimpleBlock"; + case Id::kBlockGroup: + return os << "BlockGroup"; + case Id::kBlock: + return os << "Block"; + case Id::kBlockVirtual: + return os << "BlockVirtual"; + case Id::kBlockAdditions: + return os << "BlockAdditions"; + case Id::kBlockMore: + return os << "BlockMore"; + case Id::kBlockAddId: + return os << "BlockAddID"; + case Id::kBlockAdditional: + return os << "BlockAdditional"; + case Id::kBlockDuration: + return os << "BlockDuration"; + case Id::kReferenceBlock: + return os << "ReferenceBlock"; + case Id::kDiscardPadding: + return os << "DiscardPadding"; + case Id::kSlices: + return os << "Slices"; + case Id::kTimeSlice: + return os << "TimeSlice"; + case Id::kLaceNumber: + return os << "LaceNumber"; + case Id::kTracks: + return os << "Tracks"; + case Id::kTrackEntry: + return os << "TrackEntry"; + case Id::kTrackNumber: + return os << "TrackNumber"; + case Id::kTrackUid: + return os << "TrackUID"; + case Id::kTrackType: + return os << "TrackType"; + case Id::kFlagEnabled: + return os << "FlagEnabled"; + case Id::kFlagDefault: + return os << "FlagDefault"; + case Id::kFlagForced: + return os << "FlagForced"; + case Id::kFlagLacing: + return os << "FlagLacing"; + case Id::kDefaultDuration: + return os << "DefaultDuration"; + case Id::kName: + return os << "Name"; + case Id::kLanguage: + return os << "Language"; + case Id::kCodecId: + return os << "CodecID"; + case Id::kCodecPrivate: + return os << "CodecPrivate"; + case Id::kCodecName: + return os << "CodecName"; + case Id::kCodecDelay: + return os << "CodecDelay"; + case Id::kSeekPreRoll: + return os << "SeekPreRoll"; + case Id::kVideo: + return os << "Video"; + case Id::kFlagInterlaced: + return os << "FlagInterlaced"; + case Id::kStereoMode: + return os << "StereoMode"; + case Id::kAlphaMode: + return os << "AlphaMode"; + case Id::kPixelWidth: + return os << "PixelWidth"; + case Id::kPixelHeight: + return os << "PixelHeight"; + case Id::kPixelCropBottom: + return os << "PixelCropBottom"; + case Id::kPixelCropTop: + return os << "PixelCropTop"; + case Id::kPixelCropLeft: + return os << "PixelCropLeft"; + case Id::kPixelCropRight: + return os << "PixelCropRight"; + case Id::kDisplayWidth: + return os << "DisplayWidth"; + case Id::kDisplayHeight: + return os << "DisplayHeight"; + case Id::kDisplayUnit: + return os << "DisplayUnit"; + case Id::kAspectRatioType: + return os << "AspectRatioType"; + case Id::kFrameRate: + return os << "FrameRate"; + case Id::kColour: + return os << "Colour"; + case Id::kMatrixCoefficients: + return os << "MatrixCoefficients"; + case Id::kBitsPerChannel: + return os << "BitsPerChannel"; + case Id::kChromaSubsamplingHorz: + return os << "ChromaSubsamplingHorz"; + case Id::kChromaSubsamplingVert: + return os << "ChromaSubsamplingVert"; + case Id::kCbSubsamplingHorz: + return os << "CbSubsamplingHorz"; + case Id::kCbSubsamplingVert: + return os << "CbSubsamplingVert"; + case Id::kChromaSitingHorz: + return os << "ChromaSitingHorz"; + case Id::kChromaSitingVert: + return os << "ChromaSitingVert"; + case Id::kRange: + return os << "Range"; + case Id::kTransferCharacteristics: + return os << "TransferCharacteristics"; + case Id::kPrimaries: + return os << "Primaries"; + case Id::kMaxCll: + return os << "MaxCLL"; + case Id::kMaxFall: + return os << "MaxFALL"; + case Id::kMasteringMetadata: + return os << "MasteringMetadata"; + case Id::kPrimaryRChromaticityX: + return os << "PrimaryRChromaticityX"; + case Id::kPrimaryRChromaticityY: + return os << "PrimaryRChromaticityY"; + case Id::kPrimaryGChromaticityX: + return os << "PrimaryGChromaticityX"; + case Id::kPrimaryGChromaticityY: + return os << "PrimaryGChromaticityY"; + case Id::kPrimaryBChromaticityX: + return os << "PrimaryBChromaticityX"; + case Id::kPrimaryBChromaticityY: + return os << "PrimaryBChromaticityY"; + case Id::kWhitePointChromaticityX: + return os << "WhitePointChromaticityX"; + case Id::kWhitePointChromaticityY: + return os << "WhitePointChromaticityY"; + case Id::kLuminanceMax: + return os << "LuminanceMax"; + case Id::kLuminanceMin: + return os << "LuminanceMin"; + case Id::kProjection: + return os << "Projection"; + case Id::kProjectionType: + return os << "kProjectionType"; + case Id::kProjectionPrivate: + return os << "kProjectionPrivate"; + case Id::kProjectionPoseYaw: + return os << "kProjectionPoseYaw"; + case Id::kProjectionPosePitch: + return os << "kProjectionPosePitch"; + case Id::kProjectionPoseRoll: + return os << "ProjectionPoseRoll"; + case Id::kAudio: + return os << "Audio"; + case Id::kSamplingFrequency: + return os << "SamplingFrequency"; + case Id::kOutputSamplingFrequency: + return os << "OutputSamplingFrequency"; + case Id::kChannels: + return os << "Channels"; + case Id::kBitDepth: + return os << "BitDepth"; + case Id::kContentEncodings: + return os << "ContentEncodings"; + case Id::kContentEncoding: + return os << "ContentEncoding"; + case Id::kContentEncodingOrder: + return os << "ContentEncodingOrder"; + case Id::kContentEncodingScope: + return os << "ContentEncodingScope"; + case Id::kContentEncodingType: + return os << "ContentEncodingType"; + case Id::kContentEncryption: + return os << "ContentEncryption"; + case Id::kContentEncAlgo: + return os << "ContentEncAlgo"; + case Id::kContentEncKeyId: + return os << "ContentEncKeyID"; + case Id::kContentEncAesSettings: + return os << "ContentEncAESSettings"; + case Id::kAesSettingsCipherMode: + return os << "AESSettingsCipherMode"; + case Id::kCues: + return os << "Cues"; + case Id::kCuePoint: + return os << "CuePoint"; + case Id::kCueTime: + return os << "CueTime"; + case Id::kCueTrackPositions: + return os << "CueTrackPositions"; + case Id::kCueTrack: + return os << "CueTrack"; + case Id::kCueClusterPosition: + return os << "CueClusterPosition"; + case Id::kCueRelativePosition: + return os << "CueRelativePosition"; + case Id::kCueDuration: + return os << "CueDuration"; + case Id::kCueBlockNumber: + return os << "CueBlockNumber"; + case Id::kChapters: + return os << "Chapters"; + case Id::kEditionEntry: + return os << "EditionEntry"; + case Id::kChapterAtom: + return os << "ChapterAtom"; + case Id::kChapterUid: + return os << "ChapterUID"; + case Id::kChapterStringUid: + return os << "ChapterStringUID"; + case Id::kChapterTimeStart: + return os << "ChapterTimeStart"; + case Id::kChapterTimeEnd: + return os << "ChapterTimeEnd"; + case Id::kChapterDisplay: + return os << "ChapterDisplay"; + case Id::kChapString: + return os << "ChapString"; + case Id::kChapLanguage: + return os << "ChapLanguage"; + case Id::kChapCountry: + return os << "ChapCountry"; + case Id::kTags: + return os << "Tags"; + case Id::kTag: + return os << "Tag"; + case Id::kTargets: + return os << "Targets"; + case Id::kTargetTypeValue: + return os << "TargetTypeValue"; + case Id::kTargetType: + return os << "TargetType"; + case Id::kTagTrackUid: + return os << "TagTrackUID"; + case Id::kSimpleTag: + return os << "SimpleTag"; + case Id::kTagName: + return os << "TagName"; + case Id::kTagLanguage: + return os << "TagLanguage"; + case Id::kTagDefault: + return os << "TagDefault"; + case Id::kTagString: + return os << "TagString"; + case Id::kTagBinary: + return os << "TagBinary"; + default: + return PrintUnknownEnumValue(os, id); + } +} + +std::ostream& operator<<(std::ostream& os, Lacing value) { + switch (value) { + case Lacing::kNone: + return os << "0 (none)"; + case Lacing::kXiph: + return os << "2 (Xiph)"; + case Lacing::kFixed: + return os << "4 (fixed)"; + case Lacing::kEbml: + return os << "6 (EBML)"; + default: + return PrintUnknownEnumValue(os, value); + } +} + +std::ostream& operator<<(std::ostream& os, MatrixCoefficients value) { + switch (value) { + case MatrixCoefficients::kRgb: + return os << "0 (identity, RGB/XYZ)"; + case MatrixCoefficients::kBt709: + return os << "1 (Rec. ITU-R BT.709-5)"; + case MatrixCoefficients::kUnspecified: + return os << "2 (unspecified)"; + case MatrixCoefficients::kFcc: + return os << "4 (US FCC)"; + case MatrixCoefficients::kBt470Bg: + return os << "5 (Rec. ITU-R BT.470-6 System B, G)"; + case MatrixCoefficients::kSmpte170M: + return os << "6 (SMPTE 170M)"; + case MatrixCoefficients::kSmpte240M: + return os << "7 (SMPTE 240M)"; + case MatrixCoefficients::kYCgCo: + return os << "8 (YCgCo)"; + case MatrixCoefficients::kBt2020NonconstantLuminance: + return os << "9 (Rec. ITU-R BT.2020, non-constant luma)"; + case MatrixCoefficients::kBt2020ConstantLuminance: + return os << "10 (Rec. ITU-R BT.2020 , constant luma)"; + default: + return PrintUnknownEnumValue(os, value); + } +} + +std::ostream& operator<<(std::ostream& os, Range value) { + switch (value) { + case Range::kUnspecified: + return os << "0 (unspecified)"; + case Range::kBroadcast: + return os << "1 (broadcast)"; + case Range::kFull: + return os << "2 (full)"; + case Range::kDerived: + return os << "3 (defined by MatrixCoefficients/TransferCharacteristics)"; + default: + return PrintUnknownEnumValue(os, value); + } +} + +std::ostream& operator<<(std::ostream& os, TransferCharacteristics value) { + switch (value) { + case TransferCharacteristics::kBt709: + return os << "1 (Rec. ITU-R BT.709-6)"; + case TransferCharacteristics::kUnspecified: + return os << "2 (unspecified)"; + case TransferCharacteristics::kGamma22curve: + return os << "4 (gamma 2.2, Rec. ITU‑R BT.470‑6 System M)"; + case TransferCharacteristics::kGamma28curve: + return os << "5 (gamma 2.8, Rec. ITU‑R BT.470-6 System B, G)"; + case TransferCharacteristics::kSmpte170M: + return os << "6 (SMPTE 170M)"; + case TransferCharacteristics::kSmpte240M: + return os << "7 (SMPTE 240M)"; + case TransferCharacteristics::kLinear: + return os << "8 (linear)"; + case TransferCharacteristics::kLog: + return os << "9 (log, 100:1 range)"; + case TransferCharacteristics::kLogSqrt: + return os << "10 (log, 316.2:1 range)"; + case TransferCharacteristics::kIec6196624: + return os << "11 (IEC 61966-2-4)"; + case TransferCharacteristics::kBt1361ExtendedColourGamut: + return os << "12 (Rec. ITU-R BT.1361, extended colour gamut)"; + case TransferCharacteristics::kIec6196621: + return os << "13 (IEC 61966-2-1, sRGB or sYCC)"; + case TransferCharacteristics::k10BitBt2020: + return os << "14 (Rec. ITU-R BT.2020-2, 10-bit)"; + case TransferCharacteristics::k12BitBt2020: + return os << "15 (Rec. ITU-R BT.2020-2, 12-bit)"; + case TransferCharacteristics::kSmpteSt2084: + return os << "16 (SMPTE ST 2084)"; + case TransferCharacteristics::kSmpteSt4281: + return os << "17 (SMPTE ST 428-1)"; + case TransferCharacteristics::kAribStdB67Hlg: + return os << "18 (ARIB STD-B67/Rec. ITU-R BT.[HDR-TV] HLG)"; + default: + return PrintUnknownEnumValue(os, value); + } +} + +std::ostream& operator<<(std::ostream& os, Primaries value) { + switch (value) { + case Primaries::kBt709: + return os << "1 (Rec. ITU‑R BT.709-6)"; + case Primaries::kUnspecified: + return os << "2 (unspecified)"; + case Primaries::kBt470M: + return os << "4 (Rec. ITU‑R BT.470‑6 System M)"; + case Primaries::kBt470Bg: + return os << "5 (Rec. ITU‑R BT.470‑6 System B, G)"; + case Primaries::kSmpte170M: + return os << "6 (SMPTE 170M)"; + case Primaries::kSmpte240M: + return os << "7 (SMPTE 240M)"; + case Primaries::kFilm: + return os << "8 (generic film)"; + case Primaries::kBt2020: + return os << "9 (Rec. ITU-R BT.2020-2)"; + case Primaries::kSmpteSt4281: + return os << "10 (SMPTE ST 428-1)"; + case Primaries::kJedecP22Phosphors: + return os << "22 (EBU Tech. 3213-E/JEDEC P22 phosphors)"; + default: + return PrintUnknownEnumValue(os, value); + } +} + +std::ostream& operator<<(std::ostream& os, ProjectionType value) { + switch (value) { + case ProjectionType::kRectangular: + return os << "0 (rectangular)"; + case ProjectionType::kEquirectangular: + return os << "1 (equirectangular)"; + case ProjectionType::kCubeMap: + return os << "2 (cube map)"; + default: + return PrintUnknownEnumValue(os, value); + } +} + +std::ostream& operator<<(std::ostream& os, FlagInterlaced value) { + switch (value) { + case FlagInterlaced::kUnspecified: + return os << "0 (unspecified)"; + case FlagInterlaced::kInterlaced: + return os << "1 (interlaced)"; + case FlagInterlaced::kProgressive: + return os << "2 (progressive)"; + default: + return PrintUnknownEnumValue(os, value); + } +} + +std::ostream& operator<<(std::ostream& os, StereoMode value) { + switch (value) { + case StereoMode::kMono: + return os << "0 (mono)"; + case StereoMode::kSideBySideLeftFirst: + return os << "1 (side-by-side, left eye first)"; + case StereoMode::kTopBottomRightFirst: + return os << "2 (top-bottom, right eye first)"; + case StereoMode::kTopBottomLeftFirst: + return os << "3 (top-bottom, left eye first)"; + case StereoMode::kCheckboardRightFirst: + return os << "4 (checkboard, right eye first)"; + case StereoMode::kCheckboardLeftFirst: + return os << "5 (checkboard, left eye first)"; + case StereoMode::kRowInterleavedRightFirst: + return os << "6 (row interleaved, right eye first)"; + case StereoMode::kRowInterleavedLeftFirst: + return os << "7 (row interleaved, left eye first)"; + case StereoMode::kColumnInterleavedRightFirst: + return os << "8 (column interleaved, right eye first)"; + case StereoMode::kColumnInterleavedLeftFirst: + return os << "9 (column interleaved, left eye first)"; + case StereoMode::kAnaglyphCyanRed: + return os << "10 (anaglyph, cyan/red)"; + case StereoMode::kSideBySideRightFirst: + return os << "11 (side-by-side, right eye first)"; + case StereoMode::kAnaglyphGreenMagenta: + return os << "12 (anaglyph, green/magenta)"; + case StereoMode::kBlockLacedLeftFirst: + return os << "13 (block laced, left eye first)"; + case StereoMode::kBlockLacedRightFirst: + return os << "14 (block laced, right eye first)"; + default: + return PrintUnknownEnumValue(os, value); + } +} + +std::ostream& operator<<(std::ostream& os, DisplayUnit value) { + switch (value) { + case DisplayUnit::kPixels: + return os << "0 (pixels)"; + case DisplayUnit::kCentimeters: + return os << "1 (centimeters)"; + case DisplayUnit::kInches: + return os << "2 (inches)"; + case DisplayUnit::kDisplayAspectRatio: + return os << "3 (display aspect ratio)"; + default: + return PrintUnknownEnumValue(os, value); + } +} + +std::ostream& operator<<(std::ostream& os, AspectRatioType value) { + switch (value) { + case AspectRatioType::kFreeResizing: + return os << "0 (free resizing)"; + case AspectRatioType::kKeep: + return os << "1 (keep aspect ratio)"; + case AspectRatioType::kFixed: + return os << "2 (fixed)"; + default: + return PrintUnknownEnumValue(os, value); + } +} + +std::ostream& operator<<(std::ostream& os, AesSettingsCipherMode value) { + switch (value) { + case AesSettingsCipherMode::kCtr: + return os << "1 (CTR)"; + default: + return PrintUnknownEnumValue(os, value); + } +} + +std::ostream& operator<<(std::ostream& os, ContentEncAlgo value) { + switch (value) { + case ContentEncAlgo::kOnlySigned: + return os << "0 (only signed, not encrypted)"; + case ContentEncAlgo::kDes: + return os << "1 (DES)"; + case ContentEncAlgo::k3Des: + return os << "2 (3DES)"; + case ContentEncAlgo::kTwofish: + return os << "3 (Twofish)"; + case ContentEncAlgo::kBlowfish: + return os << "4 (Blowfish)"; + case ContentEncAlgo::kAes: + return os << "5 (AES)"; + default: + return PrintUnknownEnumValue(os, value); + } +} + +std::ostream& operator<<(std::ostream& os, ContentEncodingType value) { + switch (value) { + case ContentEncodingType::kCompression: + return os << "0 (compression)"; + case ContentEncodingType::kEncryption: + return os << "1 (encryption)"; + default: + return PrintUnknownEnumValue(os, value); + } +} + +std::ostream& operator<<(std::ostream& os, TrackType value) { + switch (value) { + case TrackType::kVideo: + return os << "1 (video)"; + case TrackType::kAudio: + return os << "2 (audio)"; + case TrackType::kComplex: + return os << "3 (complex)"; + case TrackType::kLogo: + return os << "16 (logo)"; + case TrackType::kSubtitle: + return os << "17 (subtitle)"; + case TrackType::kButtons: + return os << "18 (buttons)"; + case TrackType::kControl: + return os << "32 (control)"; + default: + return PrintUnknownEnumValue(os, value); + } +} + +// For binary elements, just print out its size. +std::ostream& operator<<(std::ostream& os, + const std::vector& value) { + return os << '<' << value.size() << " bytes>"; +} + +class DemoCallback : public Callback { + public: + int indent = 0; + int spaces_per_indent = 2; + + void PrintElementMetadata(const std::string& name, + const ElementMetadata& metadata) { + // Since we aren't doing any seeking in this demo, we don't have to worry + // about kUnknownHeaderSize or kUnknownElementPosition when adding the + // position and sizes. + const std::uint64_t header_start = metadata.position; + const std::uint64_t header_end = header_start + metadata.header_size; + const std::uint64_t body_start = header_end; + std::cout << std::string(indent * spaces_per_indent, ' ') << name; + // The ContentEncAESSettings element has the longest name (out of all other + // master elements) at 21 characters. It's also the deepest master element + // at a level of 6. Insert enough whitespace so there's room for it. + std::cout << std::string(21 + 6 * spaces_per_indent - + indent * spaces_per_indent - name.size(), + ' ') + << " header: [" << header_start << ", " << header_end + << ") body: [" << body_start << ", "; + if (metadata.size != kUnknownElementSize) { + const std::uint64_t body_end = body_start + metadata.size; + std::cout << body_end; + } else { + std::cout << '?'; + } + std::cout << ")\n"; + } + + template + void PrintMandatoryElement(const std::string& name, + const Element& element) { + std::cout << std::string(indent * spaces_per_indent, ' ') << name; + if (!element.is_present()) { + std::cout << " (implicit)"; + } + std::cout << ": " << element.value() << '\n'; + } + + template + void PrintMandatoryElement(const std::string& name, + const std::vector>& elements) { + for (const Element& element : elements) { + PrintMandatoryElement(name, element); + } + } + + template + void PrintOptionalElement(const std::string& name, + const Element& element) { + if (element.is_present()) { + std::cout << std::string(indent * spaces_per_indent, ' ') << name << ": " + << element.value() << '\n'; + } + } + + template + void PrintOptionalElement(const std::string& name, + const std::vector>& elements) { + for (const Element& element : elements) { + PrintOptionalElement(name, element); + } + } + + void PrintMasterElement(const BlockAdditions& block_additions) { + PrintMasterElement("BlockMore", block_additions.block_mores); + } + + void PrintMasterElement(const BlockMore& block_more) { + PrintMandatoryElement("BlockAddID", block_more.id); + PrintMandatoryElement("BlockAdditional", block_more.data); + } + + void PrintMasterElement(const Slices& slices) { + PrintMasterElement("TimeSlice", slices.slices); + } + + void PrintMasterElement(const TimeSlice& time_slice) { + PrintOptionalElement("LaceNumber", time_slice.lace_number); + } + + void PrintMasterElement(const Video& video) { + PrintMandatoryElement("FlagInterlaced", video.interlaced); + PrintOptionalElement("StereoMode", video.stereo_mode); + PrintOptionalElement("AlphaMode", video.alpha_mode); + PrintMandatoryElement("PixelWidth", video.pixel_width); + PrintMandatoryElement("PixelHeight", video.pixel_height); + PrintOptionalElement("PixelCropBottom", video.pixel_crop_bottom); + PrintOptionalElement("PixelCropTop", video.pixel_crop_top); + PrintOptionalElement("PixelCropLeft", video.pixel_crop_left); + PrintOptionalElement("PixelCropRight", video.pixel_crop_right); + PrintOptionalElement("DisplayWidth", video.display_width); + PrintOptionalElement("DisplayHeight", video.display_height); + PrintOptionalElement("DisplayUnit", video.display_unit); + PrintOptionalElement("AspectRatioType", video.aspect_ratio_type); + PrintOptionalElement("FrameRate", video.frame_rate); + PrintMasterElement("Colour", video.colour); + PrintMasterElement("Projection", video.projection); + } + + void PrintMasterElement(const Colour& colour) { + PrintOptionalElement("MatrixCoefficients", colour.matrix_coefficients); + PrintOptionalElement("BitsPerChannel", colour.bits_per_channel); + PrintOptionalElement("ChromaSubsamplingHorz", colour.chroma_subsampling_x); + PrintOptionalElement("ChromaSubsamplingVert", colour.chroma_subsampling_y); + PrintOptionalElement("CbSubsamplingHorz", colour.cb_subsampling_x); + PrintOptionalElement("CbSubsamplingVert", colour.cb_subsampling_y); + PrintOptionalElement("ChromaSitingHorz", colour.chroma_siting_x); + PrintOptionalElement("ChromaSitingVert", colour.chroma_siting_y); + PrintOptionalElement("Range", colour.range); + PrintOptionalElement("TransferCharacteristics", + colour.transfer_characteristics); + PrintOptionalElement("Primaries", colour.primaries); + PrintOptionalElement("MaxCLL", colour.max_cll); + PrintOptionalElement("MaxFALL", colour.max_fall); + PrintMasterElement("MasteringMetadata", colour.mastering_metadata); + } + + void PrintMasterElement(const MasteringMetadata& mastering_metadata) { + PrintOptionalElement("PrimaryRChromaticityX", + mastering_metadata.primary_r_chromaticity_x); + PrintOptionalElement("PrimaryRChromaticityY", + mastering_metadata.primary_r_chromaticity_y); + PrintOptionalElement("PrimaryGChromaticityX", + mastering_metadata.primary_g_chromaticity_x); + PrintOptionalElement("PrimaryGChromaticityY", + mastering_metadata.primary_g_chromaticity_y); + PrintOptionalElement("PrimaryBChromaticityX", + mastering_metadata.primary_b_chromaticity_x); + PrintOptionalElement("PrimaryBChromaticityY", + mastering_metadata.primary_b_chromaticity_y); + PrintOptionalElement("WhitePointChromaticityX", + mastering_metadata.white_point_chromaticity_x); + PrintOptionalElement("WhitePointChromaticityY", + mastering_metadata.white_point_chromaticity_y); + PrintOptionalElement("LuminanceMax", mastering_metadata.luminance_max); + PrintOptionalElement("LuminanceMin", mastering_metadata.luminance_min); + } + + void PrintMasterElement(const Projection& projection) { + PrintMandatoryElement("ProjectionType", projection.type); + PrintOptionalElement("ProjectionPrivate", projection.projection_private); + PrintMandatoryElement("ProjectionPoseYaw", projection.pose_yaw); + PrintMandatoryElement("ProjectionPosePitch", projection.pose_pitch); + PrintMandatoryElement("ProjectionPoseRoll", projection.pose_roll); + } + + void PrintMasterElement(const Audio& audio) { + PrintMandatoryElement("SamplingFrequency", audio.sampling_frequency); + PrintOptionalElement("OutputSamplingFrequency", audio.output_frequency); + PrintMandatoryElement("Channels", audio.channels); + PrintOptionalElement("BitDepth", audio.bit_depth); + } + + void PrintMasterElement(const ContentEncodings& content_encodings) { + PrintMasterElement("ContentEncoding", content_encodings.encodings); + } + + void PrintMasterElement(const ContentEncoding& content_encoding) { + PrintMandatoryElement("ContentEncodingOrder", content_encoding.order); + PrintMandatoryElement("ContentEncodingScope", content_encoding.scope); + PrintMandatoryElement("ContentEncodingType", content_encoding.type); + PrintMasterElement("ContentEncryption", content_encoding.encryption); + } + + void PrintMasterElement(const ContentEncryption& content_encryption) { + PrintOptionalElement("ContentEncAlgo", content_encryption.algorithm); + PrintOptionalElement("ContentEncKeyID", content_encryption.key_id); + PrintMasterElement("ContentEncAESSettings", + content_encryption.aes_settings); + } + + void PrintMasterElement( + const ContentEncAesSettings& content_enc_aes_settings) { + PrintMandatoryElement("AESSettingsCipherMode", + content_enc_aes_settings.aes_settings_cipher_mode); + } + + void PrintMasterElement(const CueTrackPositions& cue_track_positions) { + PrintMandatoryElement("CueTrack", cue_track_positions.track); + PrintMandatoryElement("CueClusterPosition", + cue_track_positions.cluster_position); + PrintOptionalElement("CueRelativePosition", + cue_track_positions.relative_position); + PrintOptionalElement("CueDuration", cue_track_positions.duration); + PrintOptionalElement("CueBlockNumber", cue_track_positions.block_number); + } + + void PrintMasterElement(const ChapterAtom& chapter_atom) { + PrintMandatoryElement("ChapterUID", chapter_atom.uid); + PrintOptionalElement("ChapterStringUID", chapter_atom.string_uid); + PrintMandatoryElement("ChapterTimeStart", chapter_atom.time_start); + PrintOptionalElement("ChapterTimeEnd", chapter_atom.time_end); + PrintMasterElement("ChapterDisplay", chapter_atom.displays); + PrintMasterElement("ChapterAtom", chapter_atom.atoms); + } + + void PrintMasterElement(const ChapterDisplay& chapter_display) { + PrintMandatoryElement("ChapString", chapter_display.string); + PrintMandatoryElement("ChapLanguage", chapter_display.languages); + PrintOptionalElement("ChapCountry", chapter_display.countries); + } + + void PrintMasterElement(const Targets& targets) { + PrintOptionalElement("TargetTypeValue", targets.type_value); + PrintOptionalElement("TargetType", targets.type); + PrintMandatoryElement("TagTrackUID", targets.track_uids); + } + + void PrintMasterElement(const SimpleTag& simple_tag) { + PrintMandatoryElement("TagName", simple_tag.name); + PrintMandatoryElement("TagLanguage", simple_tag.language); + PrintMandatoryElement("TagDefault", simple_tag.is_default); + PrintOptionalElement("TagString", simple_tag.string); + PrintOptionalElement("TagBinary", simple_tag.binary); + PrintMasterElement("SimpleTag", simple_tag.tags); + } + + // When printing a master element that's wrapped in Element<>, peel off the + // Element<> wrapper and print the underlying master element if it's present. + template + void PrintMasterElement(const std::string& name, const Element& element) { + if (element.is_present()) { + std::cout << std::string(indent * spaces_per_indent, ' ') << name << "\n"; + ++indent; + PrintMasterElement(element.value()); + --indent; + } + } + + template + void PrintMasterElement(const std::string& name, + const std::vector>& elements) { + for (const Element& element : elements) { + PrintMasterElement(name, element); + } + } + + template + void PrintValue(const std::string& name, const T& value) { + std::cout << std::string(indent * spaces_per_indent, ' ') << name << ": " + << value << '\n'; + } + + Status OnElementBegin(const ElementMetadata& metadata, + Action* action) override { + // Print out metadata for some level 1 elements that don't have explicit + // callbacks. + switch (metadata.id) { + case Id::kSeekHead: + indent = 1; + PrintElementMetadata("SeekHead", metadata); + break; + case Id::kTracks: + indent = 1; + PrintElementMetadata("Tracks", metadata); + break; + case Id::kCues: + indent = 1; + PrintElementMetadata("Cues", metadata); + break; + case Id::kChapters: + indent = 1; + PrintElementMetadata("Chapters", metadata); + break; + case Id::kTags: + indent = 1; + PrintElementMetadata("Tags", metadata); + break; + default: + break; + } + + *action = Action::kRead; + return Status(Status::kOkCompleted); + } + + Status OnUnknownElement(const ElementMetadata& metadata, Reader* reader, + std::uint64_t* bytes_remaining) override { + // Output unknown elements without any indentation because we aren't + // tracking which element contains them. + int original_indent = indent; + indent = 0; + PrintElementMetadata("UNKNOWN_ELEMENT!", metadata); + indent = original_indent; + // The base class's implementation will just skip the element via + // Reader::Skip(). + return Callback::OnUnknownElement(metadata, reader, bytes_remaining); + } + + Status OnEbml(const ElementMetadata& metadata, const Ebml& ebml) override { + indent = 0; + PrintElementMetadata("EBML", metadata); + indent = 1; + PrintMandatoryElement("EBMLVersion", ebml.ebml_version); + PrintMandatoryElement("EBMLReadVersion", ebml.ebml_read_version); + PrintMandatoryElement("EBMLMaxIDLength", ebml.ebml_max_id_length); + PrintMandatoryElement("EBMLMaxSizeLength", ebml.ebml_max_size_length); + PrintMandatoryElement("DocType", ebml.doc_type); + PrintMandatoryElement("DocTypeVersion", ebml.doc_type_version); + PrintMandatoryElement("DocTypeReadVersion", ebml.doc_type_read_version); + return Status(Status::kOkCompleted); + } + + Status OnVoid(const ElementMetadata& metadata, Reader* reader, + std::uint64_t* bytes_remaining) override { + // Output Void elements without any indentation because we aren't tracking + // which element contains them. + int original_indent = indent; + indent = 0; + PrintElementMetadata("Void", metadata); + indent = original_indent; + // The base class's implementation will just skip the element via + // Reader::Skip(). + return Callback::OnVoid(metadata, reader, bytes_remaining); + } + + Status OnSegmentBegin(const ElementMetadata& metadata, + Action* action) override { + indent = 0; + PrintElementMetadata("Segment", metadata); + indent = 1; + *action = Action::kRead; + return Status(Status::kOkCompleted); + } + + Status OnSeek(const ElementMetadata& metadata, const Seek& seek) override { + indent = 2; + PrintElementMetadata("Seek", metadata); + indent = 3; + PrintMandatoryElement("SeekID", seek.id); + PrintMandatoryElement("SeekPosition", seek.position); + return Status(Status::kOkCompleted); + } + + Status OnInfo(const ElementMetadata& metadata, const Info& info) override { + indent = 1; + PrintElementMetadata("Info", metadata); + indent = 2; + PrintMandatoryElement("TimecodeScale", info.timecode_scale); + PrintOptionalElement("Duration", info.duration); + PrintOptionalElement("DateUTC", info.date_utc); + PrintOptionalElement("Title", info.title); + PrintOptionalElement("MuxingApp", info.muxing_app); + PrintOptionalElement("WritingApp", info.writing_app); + return Status(Status::kOkCompleted); + } + + Status OnClusterBegin(const ElementMetadata& metadata, const Cluster& cluster, + Action* action) override { + indent = 1; + PrintElementMetadata("Cluster", metadata); + // A properly muxed file will have Timecode and PrevSize first before any + // SimpleBlock or BlockGroups. The parser takes advantage of this and delays + // calling OnClusterBegin() until it hits the first SimpleBlock or + // BlockGroup child (or the Cluster ends if it's empty). It's possible for + // an improperly muxed file to have Timecode or PrevSize after the first + // block, in which case they'll be absent here and may be accessed in + // OnClusterEnd() when the Cluster and all its children have been fully + // parsed. In this demo we assume the file has been properly muxed. + indent = 2; + PrintMandatoryElement("Timecode", cluster.timecode); + PrintOptionalElement("PrevSize", cluster.previous_size); + *action = Action::kRead; + return Status(Status::kOkCompleted); + } + + Status OnSimpleBlockBegin(const ElementMetadata& metadata, + const SimpleBlock& simple_block, + Action* action) override { + indent = 2; + PrintElementMetadata("SimpleBlock", metadata); + indent = 3; + PrintValue("track number", simple_block.track_number); + PrintValue("frames", simple_block.num_frames); + PrintValue("timecode", simple_block.timecode); + PrintValue("lacing", simple_block.lacing); + std::string flags = (simple_block.is_visible) ? "visible" : "invisible"; + if (simple_block.is_key_frame) + flags += ", key frame"; + if (simple_block.is_discardable) + flags += ", discardable"; + PrintValue("flags", flags); + *action = Action::kRead; + return Status(Status::kOkCompleted); + } + + Status OnSimpleBlockEnd(const ElementMetadata& /* metadata */, + const SimpleBlock& /* simple_block */) override { + return Status(Status::kOkCompleted); + } + + Status OnBlockGroupBegin(const ElementMetadata& metadata, + Action* action) override { + indent = 2; + PrintElementMetadata("BlockGroup", metadata); + *action = Action::kRead; + return Status(Status::kOkCompleted); + } + + Status OnBlockBegin(const ElementMetadata& metadata, const Block& block, + Action* action) override { + indent = 3; + PrintElementMetadata("Block", metadata); + indent = 4; + PrintValue("track number", block.track_number); + PrintValue("frames", block.num_frames); + PrintValue("timecode", block.timecode); + PrintValue("lacing", block.lacing); + PrintValue("flags", (block.is_visible) ? "visible" : "invisible"); + *action = Action::kRead; + return Status(Status::kOkCompleted); + } + + Status OnBlockEnd(const ElementMetadata& /* metadata */, + const Block& /* block */) override { + return Status(Status::kOkCompleted); + } + + Status OnBlockGroupEnd(const ElementMetadata& /* metadata */, + const BlockGroup& block_group) override { + if (block_group.virtual_block.is_present()) { + std::cout << std::string(indent * spaces_per_indent, ' ') + << "BlockVirtual\n"; + indent = 4; + PrintValue("track number", + block_group.virtual_block.value().track_number); + PrintValue("timecode", block_group.virtual_block.value().timecode); + } + indent = 3; + PrintMasterElement("BlockAdditions", block_group.additions); + PrintOptionalElement("BlockDuration", block_group.duration); + PrintOptionalElement("ReferenceBlock", block_group.references); + PrintOptionalElement("DiscardPadding", block_group.discard_padding); + PrintMasterElement("Slices", block_group.slices); + // BlockGroup::block has been set, but we've already printed it in + // OnBlockBegin(). + return Status(Status::kOkCompleted); + } + + Status OnFrame(const FrameMetadata& metadata, Reader* reader, + std::uint64_t* bytes_remaining) override { + PrintValue("frame byte range", + '[' + std::to_string(metadata.position) + ", " + + std::to_string(metadata.position + metadata.size) + ')'); + // The base class's implementation will just skip the frame via + // Reader::Skip(). + return Callback::OnFrame(metadata, reader, bytes_remaining); + } + + Status OnClusterEnd(const ElementMetadata& /* metadata */, + const Cluster& /* cluster */) override { + // The Cluster and all its children have been fully parsed at this point. If + // the file wasn't properly muxed and Timecode or PrevSize were missing in + // OnClusterBegin(), they'll be set here (if the Cluster contained them). In + // this demo we already handled them, though. + return Status(Status::kOkCompleted); + } + + Status OnTrackEntry(const ElementMetadata& metadata, + const TrackEntry& track_entry) override { + indent = 2; + PrintElementMetadata("TrackEntry", metadata); + indent = 3; + PrintMandatoryElement("TrackNumber", track_entry.track_number); + PrintMandatoryElement("TrackUID", track_entry.track_uid); + PrintMandatoryElement("TrackType", track_entry.track_type); + PrintMandatoryElement("FlagEnabled", track_entry.is_enabled); + PrintMandatoryElement("FlagDefault", track_entry.is_default); + PrintMandatoryElement("FlagForced", track_entry.is_forced); + PrintMandatoryElement("FlagLacing", track_entry.uses_lacing); + PrintOptionalElement("DefaultDuration", track_entry.default_duration); + PrintOptionalElement("Name", track_entry.name); + PrintOptionalElement("Language", track_entry.language); + PrintMandatoryElement("CodecID", track_entry.codec_id); + PrintOptionalElement("CodecPrivate", track_entry.codec_private); + PrintOptionalElement("CodecName", track_entry.codec_name); + PrintOptionalElement("CodecDelay", track_entry.codec_delay); + PrintMandatoryElement("SeekPreRoll", track_entry.seek_pre_roll); + PrintMasterElement("Video", track_entry.video); + PrintMasterElement("Audio", track_entry.audio); + PrintMasterElement("ContentEncodings", track_entry.content_encodings); + return Status(Status::kOkCompleted); + } + + Status OnCuePoint(const ElementMetadata& metadata, + const CuePoint& cue_point) override { + indent = 2; + PrintElementMetadata("CuePoint", metadata); + indent = 3; + PrintMandatoryElement("CueTime", cue_point.time); + PrintMasterElement("CueTrackPositions", cue_point.cue_track_positions); + return Status(Status::kOkCompleted); + } + + Status OnEditionEntry(const ElementMetadata& metadata, + const EditionEntry& edition_entry) override { + indent = 2; + PrintElementMetadata("EditionEntry", metadata); + indent = 3; + PrintMasterElement("ChapterAtom", edition_entry.atoms); + return Status(Status::kOkCompleted); + } + + Status OnTag(const ElementMetadata& metadata, const Tag& tag) override { + indent = 2; + PrintElementMetadata("Tag", metadata); + indent = 3; + PrintMasterElement("Targets", tag.targets); + PrintMasterElement("SimpleTag", tag.tags); + return Status(Status::kOkCompleted); + } + + Status OnSegmentEnd(const ElementMetadata& /* metadata */) override { + return Status(Status::kOkCompleted); + } +}; + +int main(int argc, char* argv[]) { + if ((argc != 1 && argc != 2) || + (argc == 2 && argv[1] == std::string("--help"))) { + std::cerr << "Usage:\n" + << argv[0] << " [path-to-webm-file]\n\n" + << "Prints info for the WebM file specified in the command line. " + "If no file is\n" + << "specified, stdin is used as input.\n"; + return EXIT_FAILURE; + } + + FILE* file = (argc == 2) ? std::fopen(argv[1], "rb") + : std::freopen(nullptr, "rb", stdin); + if (!file) { + std::cerr << "File cannot be opened\n"; + return EXIT_FAILURE; + } + + FileReader reader(file); + DemoCallback callback; + WebmParser parser; + Status status = parser.Feed(&callback, &reader); + if (!status.completed_ok()) { + std::cerr << "Parsing error; status code: " << status.code << '\n'; + return EXIT_FAILURE; + } + + return 0; +} diff --git a/third_party/libwebm/source/webm_parser/doxygen.config b/third_party/libwebm/source/webm_parser/doxygen.config new file mode 100644 index 000000000000..f2aae8a0edab --- /dev/null +++ b/third_party/libwebm/source/webm_parser/doxygen.config @@ -0,0 +1,319 @@ +# Doxyfile 1.8.11 + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +DOXYFILE_ENCODING = UTF-8 +PROJECT_NAME = "WebM Parser" +PROJECT_NUMBER = +PROJECT_BRIEF = +PROJECT_LOGO = +OUTPUT_DIRECTORY = +CREATE_SUBDIRS = NO +ALLOW_UNICODE_NAMES = NO +OUTPUT_LANGUAGE = English +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ABBREVIATE_BRIEF = +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = YES +STRIP_FROM_PATH = +STRIP_FROM_INC_PATH = +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = YES +QT_AUTOBRIEF = NO +MULTILINE_CPP_IS_BRIEF = NO +INHERIT_DOCS = YES +SEPARATE_MEMBER_PAGES = NO +TAB_SIZE = 2 +ALIASES = MatroskaID{1}="[\1](https://www.webmproject.org/docs/container/#\1) ([Matroska definition](https://matroska.org/technical/specs/index.html#\1))" \ + WebMID{1}="[\1](https://www.webmproject.org/docs/container/#\1)" \ + WebMTable{7}="| Type | Level | Mandatory | Multiple | Recursive | Value range | Default value |\n| ---- | ----- | --------- | -------- | --------- | ----------- | ------------- |\n| \1 | \2 | \3 | \4 | \5 | \6 | \7 |\n" +TCL_SUBST = +OPTIMIZE_OUTPUT_FOR_C = NO +OPTIMIZE_OUTPUT_JAVA = NO +OPTIMIZE_FOR_FORTRAN = NO +OPTIMIZE_OUTPUT_VHDL = NO +EXTENSION_MAPPING = +MARKDOWN_SUPPORT = YES +AUTOLINK_SUPPORT = YES +BUILTIN_STL_SUPPORT = NO +CPP_CLI_SUPPORT = NO +SIP_SUPPORT = NO +IDL_PROPERTY_SUPPORT = YES +DISTRIBUTE_GROUP_DOC = NO +GROUP_NESTED_COMPOUNDS = NO +SUBGROUPING = YES +INLINE_GROUPED_CLASSES = NO +INLINE_SIMPLE_STRUCTS = NO +TYPEDEF_HIDES_STRUCT = NO +LOOKUP_CACHE_SIZE = 0 +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- +EXTRACT_ALL = NO +EXTRACT_PRIVATE = NO +EXTRACT_PACKAGE = NO +EXTRACT_STATIC = NO +EXTRACT_LOCAL_CLASSES = YES +EXTRACT_LOCAL_METHODS = NO +EXTRACT_ANON_NSPACES = NO +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = NO +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = NO +CASE_SENSE_NAMES = NO +HIDE_SCOPE_NAMES = NO +HIDE_COMPOUND_REFERENCE= NO +SHOW_INCLUDE_FILES = YES +SHOW_GROUPED_MEMB_INC = NO +FORCE_LOCAL_INCLUDES = NO +INLINE_INFO = YES +SORT_MEMBER_DOCS = YES +SORT_BRIEF_DOCS = NO +SORT_MEMBERS_CTORS_1ST = NO +SORT_GROUP_NAMES = NO +SORT_BY_SCOPE_NAME = NO +STRICT_PROTO_MATCHING = NO +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = YES +SHOW_FILES = YES +SHOW_NAMESPACES = YES +FILE_VERSION_FILTER = +LAYOUT_FILE = +CITE_BIB_FILES = +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = NO +WARN_AS_ERROR = NO +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = README.md include/webm +INPUT_ENCODING = UTF-8 +FILE_PATTERNS = +RECURSIVE = NO +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXCLUDE_SYMBOLS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_PATTERNS = +FILTER_SOURCE_FILES = NO +FILTER_SOURCE_PATTERNS = +USE_MDFILE_AS_MAINPAGE = README.md +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = NO +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = NO +REFERENCES_RELATION = NO +REFERENCES_LINK_SOURCE = YES +SOURCE_TOOLTIPS = YES +USE_HTAGS = NO +VERBATIM_HEADERS = YES +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = YES +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_EXTRA_STYLESHEET = +HTML_EXTRA_FILES = +HTML_COLORSTYLE_HUE = 220 +HTML_COLORSTYLE_SAT = 100 +HTML_COLORSTYLE_GAMMA = 80 +HTML_TIMESTAMP = NO +HTML_DYNAMIC_SECTIONS = NO +HTML_INDEX_NUM_ENTRIES = 100 +GENERATE_DOCSET = NO +DOCSET_FEEDNAME = "Doxygen generated docs" +DOCSET_BUNDLE_ID = org.doxygen.Project +DOCSET_PUBLISHER_ID = org.doxygen.Publisher +DOCSET_PUBLISHER_NAME = Publisher +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +CHM_INDEX_ENCODING = +BINARY_TOC = NO +TOC_EXPAND = NO +GENERATE_QHP = NO +QCH_FILE = +QHP_NAMESPACE = org.doxygen.Project +QHP_VIRTUAL_FOLDER = doc +QHP_CUST_FILTER_NAME = +QHP_CUST_FILTER_ATTRS = +QHP_SECT_FILTER_ATTRS = +QHG_LOCATION = +GENERATE_ECLIPSEHELP = NO +ECLIPSE_DOC_ID = org.doxygen.Project +DISABLE_INDEX = NO +GENERATE_TREEVIEW = NO +ENUM_VALUES_PER_LINE = 4 +TREEVIEW_WIDTH = 250 +EXT_LINKS_IN_WINDOW = NO +FORMULA_FONTSIZE = 10 +FORMULA_TRANSPARENT = YES +USE_MATHJAX = NO +MATHJAX_FORMAT = HTML-CSS +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest +MATHJAX_EXTENSIONS = +MATHJAX_CODEFILE = +SEARCHENGINE = YES +SERVER_BASED_SEARCH = NO +EXTERNAL_SEARCH = NO +SEARCHENGINE_URL = +SEARCHDATA_FILE = searchdata.xml +EXTERNAL_SEARCH_ID = +EXTRA_SEARCH_MAPPINGS = +#--------------------------------------------------------------------------- +# Configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = YES +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4 +EXTRA_PACKAGES = +LATEX_HEADER = +LATEX_FOOTER = +LATEX_EXTRA_STYLESHEET = +LATEX_EXTRA_FILES = +PDF_HYPERLINKS = YES +USE_PDFLATEX = YES +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +LATEX_SOURCE_CODE = NO +LATEX_BIB_STYLE = plain +LATEX_TIMESTAMP = NO +#--------------------------------------------------------------------------- +# Configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +RTF_SOURCE_CODE = NO +#--------------------------------------------------------------------------- +# Configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_SUBDIR = +MAN_LINKS = NO +#--------------------------------------------------------------------------- +# Configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = NO +XML_OUTPUT = xml +XML_PROGRAMLISTING = YES +#--------------------------------------------------------------------------- +# Configuration options related to the DOCBOOK output +#--------------------------------------------------------------------------- +GENERATE_DOCBOOK = NO +DOCBOOK_OUTPUT = docbook +DOCBOOK_PROGRAMLISTING = NO +#--------------------------------------------------------------------------- +# Configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# Configuration options related to the Perl module output +#--------------------------------------------------------------------------- +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration options related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +EXTERNAL_PAGES = YES +PERL_PATH = /usr/bin/perl +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = YES +MSCGEN_PATH = +DIA_PATH = +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = NO +DOT_NUM_THREADS = 0 +DOT_FONTNAME = Helvetica +DOT_FONTSIZE = 10 +DOT_FONTPATH = +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +GROUP_GRAPHS = YES +UML_LOOK = NO +UML_LIMIT_NUM_FIELDS = 10 +TEMPLATE_RELATIONS = NO +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CALL_GRAPH = NO +CALLER_GRAPH = NO +GRAPHICAL_HIERARCHY = YES +DIRECTORY_GRAPH = YES +DOT_IMAGE_FORMAT = png +INTERACTIVE_SVG = NO +DOT_PATH = +DOTFILE_DIRS = +MSCFILE_DIRS = +DIAFILE_DIRS = +PLANTUML_JAR_PATH = +PLANTUML_INCLUDE_PATH = +DOT_GRAPH_MAX_NODES = 50 +MAX_DOT_GRAPH_DEPTH = 0 +DOT_TRANSPARENT = NO +DOT_MULTI_TARGETS = NO +GENERATE_LEGEND = YES +DOT_CLEANUP = YES diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/00805c2543756a5fd85652d03bfbbd2eb6192ca5 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/00805c2543756a5fd85652d03bfbbd2eb6192ca5 new file mode 100644 index 000000000000..d78507e0e3bf --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/00805c2543756a5fd85652d03bfbbd2eb6192ca5 @@ -0,0 +1 @@ +S€g‘T®kŒ®Šm€‡b@„P1S€g”T®k®m€Šb@‡P5„Gáÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/00d120eb143bb02c48d7c863e5826d2ad1a6da4b b/third_party/libwebm/source/webm_parser/fuzzing/corpus/00d120eb143bb02c48d7c863e5826d2ad1a6da4b new file mode 100644 index 000000000000..2d4403c7df20 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/00d120eb143bb02c48d7c863e5826d2ad1a6da4b @@ -0,0 +1 @@ +S€g‹T®k†®„c¢! \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/018dee8285e9e20ca3996bb2dc0284b5c57ba75a b/third_party/libwebm/source/webm_parser/fuzzing/corpus/018dee8285e9e20ca3996bb2dc0284b5c57ba75a new file mode 100644 index 000000000000..29205220f5dd --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/018dee8285e9e20ca3996bb2dc0284b5c57ba75a @@ -0,0 +1 @@ +S€g…C¶u€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/020edb59637c1e6439f19aa3a5a9d50c3377dbe9 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/020edb59637c1e6439f19aa3a5a9d50c3377dbe9 new file mode 100644 index 000000000000..c19460644f05 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/020edb59637c1e6439f19aa3a5a9d50c3377dbe9 @@ -0,0 +1 @@ +S€g“T®kŽ®Œm€‰b@†P3ƒ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/0247ce2b1a71752a3af11e1065ca90afa0df9d30 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/0247ce2b1a71752a3af11e1065ca90afa0df9d30 new file mode 100644 index 000000000000..42b852596791 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/0247ce2b1a71752a3af11e1065ca90afa0df9d30 @@ -0,0 +1 @@ +S€gC¶u‹ ‰Ž‡è…̃ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/028b19f7d79f5da7a2af13a0c1e2d13f7eaf24cd b/third_party/libwebm/source/webm_parser/fuzzing/corpus/028b19f7d79f5da7a2af13a0c1e2d13f7eaf24cd new file mode 100644 index 000000000000..863b42bec232 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/028b19f7d79f5da7a2af13a0c1e2d13f7eaf24cd @@ -0,0 +1 @@ +S€gTÿk†à®ˆTº„ÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/029ab55b16df41881f8de2351205201da334550a b/third_party/libwebm/source/webm_parser/fuzzing/corpus/029ab55b16df41881f8de2351205201da334550a new file mode 100644 index 000000000000..27523d474de3 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/029ab55b16df41881f8de2351205201da334550a @@ -0,0 +1 @@ +S€gŽC§p‰E¹†¶„VT! \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/029be5e90913b19cf5890559cf3f98aa909f0a84 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/029be5e90913b19cf5890559cf3f98aa909f0a84 new file mode 100644 index 000000000000..75abefb3957f Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/029be5e90913b19cf5890559cf3f98aa909f0a84 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/02fb96539b84bbd12de84ff05cbc9dc3faa96b7e b/third_party/libwebm/source/webm_parser/fuzzing/corpus/02fb96539b84bbd12de84ff05cbc9dc3faa96b7e new file mode 100644 index 000000000000..f6d373818e5f Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/02fb96539b84bbd12de84ff05cbc9dc3faa96b7e differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/0349f5632d21faa36b85520ad0b524d561f5e13f b/third_party/libwebm/source/webm_parser/fuzzing/corpus/0349f5632d21faa36b85520ad0b524d561f5e13f new file mode 100644 index 000000000000..f3df0a462649 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/0349f5632d21faa36b85520ad0b524d561f5e13f differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/036fc9daf7fb1b4274dd668cfd883248ebbad967 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/036fc9daf7fb1b4274dd668cfd883248ebbad967 new file mode 100644 index 000000000000..5d97ec821198 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/036fc9daf7fb1b4274dd668cfd883248ebbad967 @@ -0,0 +1 @@ +S€gS»kŠ»ƒ³»ƒ³ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/037a4edc18e475ec81081e47277cbf51f1316680 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/037a4edc18e475ec81081e47277cbf51f1316680 new file mode 100644 index 000000000000..3109c3157447 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/037a4edc18e475ec81081e47277cbf51f1316680 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/0481dad9a7d0e6fab0c703bba9b3268db96c6793 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/0481dad9a7d0e6fab0c703bba9b3268db96c6793 new file mode 100644 index 000000000000..45d388a58438 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/0481dad9a7d0e6fab0c703bba9b3268db96c6793 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/04dc2407e7142f5618aa5105377925b0b0ed544b b/third_party/libwebm/source/webm_parser/fuzzing/corpus/04dc2407e7142f5618aa5105377925b0b0ed544b new file mode 100644 index 000000000000..fa4ff2f33557 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/04dc2407e7142f5618aa5105377925b0b0ed544b differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/04fa2f34ff4a4406d136e5aaba5debe7d8129a06 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/04fa2f34ff4a4406d136e5aaba5debe7d8129a06 new file mode 100644 index 000000000000..81b5bdd76f06 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/04fa2f34ff4a4406d136e5aaba5debe7d8129a06 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/054fd0041ad81cfad0a85e3c59195485492a4493 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/054fd0041ad81cfad0a85e3c59195485492a4493 new file mode 100644 index 000000000000..e5ddccf22ecc Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/054fd0041ad81cfad0a85e3c59195485492a4493 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/056b83ab2457979ea021e7118ab847eba265df15 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/056b83ab2457979ea021e7118ab847eba265df15 new file mode 100644 index 000000000000..ef730c6298b5 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/056b83ab2457979ea021e7118ab847eba265df15 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/058326151c1d4a490964d495d35adcf15178030f b/third_party/libwebm/source/webm_parser/fuzzing/corpus/058326151c1d4a490964d495d35adcf15178030f new file mode 100644 index 000000000000..e6d60cc48952 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/058326151c1d4a490964d495d35adcf15178030f differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/05847b5be0eb200d6a6b340c939c7a654b55003e b/third_party/libwebm/source/webm_parser/fuzzing/corpus/05847b5be0eb200d6a6b340c939c7a654b55003e new file mode 100644 index 000000000000..c9282128dc6d Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/05847b5be0eb200d6a6b340c939c7a654b55003e differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/05b600ae9a9072ac2865247e69ed0736a0c58316 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/05b600ae9a9072ac2865247e69ed0736a0c58316 new file mode 100644 index 000000000000..a39b94c82caf Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/05b600ae9a9072ac2865247e69ed0736a0c58316 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/05cf976698b55df1fcd03bc07446bb9283dad9d7 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/05cf976698b55df1fcd03bc07446bb9283dad9d7 new file mode 100644 index 000000000000..effefb88d1e9 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/05cf976698b55df1fcd03bc07446bb9283dad9d7 @@ -0,0 +1 @@ +S€gTÃg˜ss•gÈ’E£€Dz€D„€D‡€D…€gÈ€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/05d4dfda5e264fffda243f2991a86e96141f579a b/third_party/libwebm/source/webm_parser/fuzzing/corpus/05d4dfda5e264fffda243f2991a86e96141f579a new file mode 100644 index 000000000000..3a3083587f9a --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/05d4dfda5e264fffda243f2991a86e96141f579a @@ -0,0 +1 @@ +S€g”T®k®m€Šb@‡P5„Gâ!S€g›T®k–®”m€‘ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/061217fc0b6af0ec3851d9728e03ed9b30c702d5 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/061217fc0b6af0ec3851d9728e03ed9b30c702d5 new file mode 100644 index 000000000000..d2dbb4d8bd02 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/061217fc0b6af0ec3851d9728e03ed9b30c702d5 @@ -0,0 +1 @@ +u¢€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/077b53a7163e51c48e8cdaf4209bb837823ffba9 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/077b53a7163e51c48e8cdaf4209bb837823ffba9 new file mode 100644 index 000000000000..f0a787c90af8 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/077b53a7163e51c48e8cdaf4209bb837823ffba9 @@ -0,0 +1 @@ +Tð€ð€€€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/07c3ade9713892bb75db2d93b48ef40b262a54e6 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/07c3ade9713892bb75db2d93b48ef40b262a54e6 new file mode 100644 index 000000000000..12d7edf1c570 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/07c3ade9713892bb75db2d93b48ef40b262a54e6 @@ -0,0 +1 @@ +S€gŒS»k‡»…·ƒñÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/07eaf3c7437032f60c905f6f8e3dfc193491b602 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/07eaf3c7437032f60c905f6f8e3dfc193491b602 new file mode 100644 index 000000000000..5686078074c7 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/07eaf3c7437032f60c905f6f8e3dfc193491b602 @@ -0,0 +1 @@ +S€g“C¶uŽ ŒŽŠìƒÌ•ƒèÌ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/07f67b922b503354b2aebcdcc4ab7b6d3150b048 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/07f67b922b503354b2aebcdcc4ab7b6d3150b048 new file mode 100644 index 000000000000..532f5d912c8d Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/07f67b922b503354b2aebcdcc4ab7b6d3150b048 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/08af8d91bb21835c50330e997d973cac8ff67766 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/08af8d91bb21835c50330e997d973cac8ff67766 new file mode 100644 index 000000000000..7fab9be0b774 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/08af8d91bb21835c50330e997d973cac8ff67766 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/0a18f05bb16402756202160225aec9c5a654f1ae b/third_party/libwebm/source/webm_parser/fuzzing/corpus/0a18f05bb16402756202160225aec9c5a654f1ae new file mode 100644 index 000000000000..11f4d8c0ec2a Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/0a18f05bb16402756202160225aec9c5a654f1ae differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/0b60823983971ee17a2590678f0fc0762c21bb73 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/0b60823983971ee17a2590678f0fc0762c21bb73 new file mode 100644 index 000000000000..14fc6def90c1 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/0b60823983971ee17a2590678f0fc0762c21bb73 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/0bae7f0976af0f75974047b5f2cf4c9645412066 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/0bae7f0976af0f75974047b5f2cf4c9645412066 new file mode 100644 index 000000000000..beeec12917f4 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/0bae7f0976af0f75974047b5f2cf4c9645412066 @@ -0,0 +1 @@ +S€gœC§p—E¹”¶’Ä€aT€€€€€€€€€€€€€ƒèÌ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/0c1862b4065eefab2535ecc6951295e38069a82e b/third_party/libwebm/source/webm_parser/fuzzing/corpus/0c1862b4065eefab2535ecc6951295e38069a82e new file mode 100644 index 000000000000..95342c8b12d9 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/0c1862b4065eefab2535ecc6951295e38069a82e differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/0c2f51d5ffc69e69680bf3d6edb91d76c353ad14 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/0c2f51d5ffc69e69680bf3d6edb91d76c353ad14 new file mode 100644 index 000000000000..f0ad094812d8 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/0c2f51d5ffc69e69680bf3d6edb91d76c353ad14 @@ -0,0 +1 @@ +S€g€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/0c3af72d69f18103383c9cd41a7f2676a9d28a40 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/0c3af72d69f18103383c9cd41a7f2676a9d28a40 new file mode 100644 index 000000000000..74f05504c850 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/0c3af72d69f18103383c9cd41a7f2676a9d28a40 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/0c43df7fc9d06187249187583c3c082520701289 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/0c43df7fc9d06187249187583c3c082520701289 new file mode 100644 index 000000000000..c0033c4693f9 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/0c43df7fc9d06187249187583c3c082520701289 @@ -0,0 +1 @@ +S€gŒC¶u‡ …ûƒ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/0cadf5ecf58a394560a1f6db72a2e21264445d13 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/0cadf5ecf58a394560a1f6db72a2e21264445d13 new file mode 100644 index 000000000000..e3e6491bb576 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/0cadf5ecf58a394560a1f6db72a2e21264445d13 @@ -0,0 +1 @@ +S€g™T®k”®’m€b@ŒP5‰á€Gç€Gç€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/0cd91a4e7bec912beb3b47a685b89d5be24d0046 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/0cd91a4e7bec912beb3b47a685b89d5be24d0046 new file mode 100644 index 000000000000..33d3668b3bc8 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/0cd91a4e7bec912beb3b47a685b89d5be24d0046 @@ -0,0 +1 @@ +S€gŽS»k‰»‡·…²ƒ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/0d0da60f91f9489af113d8484d9b6871622523d5 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/0d0da60f91f9489af113d8484d9b6871622523d5 new file mode 100644 index 000000000000..14e966c08030 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/0d0da60f91f9489af113d8484d9b6871622523d5 @@ -0,0 +1 @@ +S€g”T®i®m€‚b@‡P5„Gâ!S€gŠT®k…®ƒ¹ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/0d30a4f88e53de1ce4bf1ec724016f2f4c11bc9b b/third_party/libwebm/source/webm_parser/fuzzing/corpus/0d30a4f88e53de1ce4bf1ec724016f2f4c11bc9b new file mode 100644 index 000000000000..2de1dab5cbd0 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/0d30a4f88e53de1ce4bf1ec724016f2f4c11bc9b differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/0d6b3b1d024e7aa73fbc58b157ab53df048a2f2c b/third_party/libwebm/source/webm_parser/fuzzing/corpus/0d6b3b1d024e7aa73fbc58b157ab53df048a2f2c new file mode 100644 index 000000000000..1a5dc0ec5f49 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/0d6b3b1d024e7aa73fbc58b157ab53df048a2f2c differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/0d94310cfd8a9acdbc7fb82ad9c73cdf3f64f926 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/0d94310cfd8a9acdbc7fb82ad9c73cdf3f64f926 new file mode 100644 index 000000000000..676e417e93ce Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/0d94310cfd8a9acdbc7fb82ad9c73cdf3f64f926 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/0f5741483be8f4f6eddcb70ea418fb0c08da9443 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/0f5741483be8f4f6eddcb70ea418fb0c08da9443 new file mode 100644 index 000000000000..34838b0cbaec Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/0f5741483be8f4f6eddcb70ea418fb0c08da9443 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/109e125f729f84d69c3e3a614123547a094534ad b/third_party/libwebm/source/webm_parser/fuzzing/corpus/109e125f729f84d69c3e3a614123547a094534ad new file mode 100644 index 000000000000..841b067d598b --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/109e125f729f84d69c3e3a614123547a094534ad @@ -0,0 +1 @@ +S€g”C¶u u¡Š¦ƒî¦ƒî \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/10d257a4a314e20644fbc469cdebafe16c7f46a8 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/10d257a4a314e20644fbc469cdebafe16c7f46a8 new file mode 100644 index 000000000000..edb0d4fe0719 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/10d257a4a314e20644fbc469cdebafe16c7f46a8 @@ -0,0 +1 @@ +S€gTÃgŠss‡gÈ„D„ÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/10d951f88995a2176878501a2633b9bb4822ff96 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/10d951f88995a2176878501a2633b9bb4822ff96 new file mode 100644 index 000000000000..ca0a0946cab8 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/10d951f88995a2176878501a2633b9bb4822ff96 @@ -0,0 +1 @@ +!EߣˆB‚@webmS€g£M›t€I©f€C¶u€TS€gŒT®k‡®…®k€Sჟ»k€C§p€TÃg€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/111b8f8318a269bbe0f7d9f1cebfdc1cb43c982b b/third_party/libwebm/source/webm_parser/fuzzing/corpus/111b8f8318a269bbe0f7d9f1cebfdc1cb43c982b new file mode 100644 index 000000000000..a612d8bf3118 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/111b8f8318a269bbe0f7d9f1cebfdc1cb43c982b @@ -0,0 +1 @@ +(Á \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/11c122ce1f7d993f809a4eb5db17c738f279a707 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/11c122ce1f7d993f809a4eb5db17c738f279a707 new file mode 100644 index 000000000000..064086e01c74 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/11c122ce1f7d993f809a4eb5db17c738f279a707 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/11e288617056809208561f2a9112fd0664d378d2 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/11e288617056809208561f2a9112fd0664d378d2 new file mode 100644 index 000000000000..9e2b9d3918d1 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/11e288617056809208561f2a9112fd0664d378d2 @@ -0,0 +1 @@ +S€g”T®k®m€Šb@‡P5„Gâ!S€gŠT®k…®ƒ¹ÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/124fde9cfe7157773d8febcbb0829914bf4d17d3 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/124fde9cfe7157773d8febcbb0829914bf4d17d3 new file mode 100644 index 000000000000..1a1a2df0f576 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/124fde9cfe7157773d8febcbb0829914bf4d17d3 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/1386cc740c80ede6dfea5f3bb1d4fe1501ab5e91 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/1386cc740c80ede6dfea5f3bb1d4fe1501ab5e91 new file mode 100644 index 000000000000..f1b13fc1b2dd --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/1386cc740c80ede6dfea5f3bb1d4fe1501ab5e91 @@ -0,0 +1 @@ +S€gŒT®k‡®…%†ˆ! \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/13dd373ccb0c534402c6f7c4a0bdd723a26bc2c1 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/13dd373ccb0c534402c6f7c4a0bdd723a26bc2c1 new file mode 100644 index 000000000000..5fea3493d1d7 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/13dd373ccb0c534402c6f7c4a0bdd723a26bc2c1 @@ -0,0 +1 @@ +S€g”T®k®m€Šb@‡P5„Gá \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/13fc3d2b32d789c84be6349bb585c308289b4c3e b/third_party/libwebm/source/webm_parser/fuzzing/corpus/13fc3d2b32d789c84be6349bb585c308289b4c3e new file mode 100644 index 000000000000..94ff769286ac --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/13fc3d2b32d789c84be6349bb585c308289b4c3e @@ -0,0 +1 @@ +S€g‘TÃgŒss‰gȆD„ƒ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/148357130d1e5ac4059ad2bb6c63d78e2523f7d2 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/148357130d1e5ac4059ad2bb6c63d78e2523f7d2 new file mode 100644 index 000000000000..23129b890a1f Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/148357130d1e5ac4059ad2bb6c63d78e2523f7d2 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/15366a3aafe2590c2e3183c088dde4cc100cb956 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/15366a3aafe2590c2e3183c088dde4cc100cb956 new file mode 100644 index 000000000000..acb4e5910b25 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/15366a3aafe2590c2e3183c088dde4cc100cb956 @@ -0,0 +1 @@ +S€g½C§p¸E¹µ¶³sÄVTA‘@…@B€@”@C¶@sĶ@sĶ@sĶ@sÄ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/15feeb939fa90b25f57622a0abd9155ca88ad08b b/third_party/libwebm/source/webm_parser/fuzzing/corpus/15feeb939fa90b25f57622a0abd9155ca88ad08b new file mode 100644 index 000000000000..e8c0a654e695 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/15feeb939fa90b25f57622a0abd9155ca88ad08b differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/16282b78a2018eb78544316554a92fe1003859e3 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/16282b78a2018eb78544316554a92fe1003859e3 new file mode 100644 index 000000000000..4d9e8d516211 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/16282b78a2018eb78544316554a92fe1003859e3 @@ -0,0 +1 @@ +S€g”T®k®m€Šb@‡P5„Gâ! \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/1717628a6d6ea868febec5fb196edcf4b9eb284d b/third_party/libwebm/source/webm_parser/fuzzing/corpus/1717628a6d6ea868febec5fb196edcf4b9eb284d new file mode 100644 index 000000000000..a495a9da7bb4 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/1717628a6d6ea868febec5fb196edcf4b9eb284d @@ -0,0 +1 @@ +S€gŒT®k‡®…ჟÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/17921b1e28600e7e3faf67fc68b397ecab4e2a52 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/17921b1e28600e7e3faf67fc68b397ecab4e2a52 new file mode 100644 index 000000000000..a351f0e341a8 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/17921b1e28600e7e3faf67fc68b397ecab4e2a52 @@ -0,0 +1 @@ +S€gC§pŠE¹‡¶…€ƒ…! \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/17b8276355dd2368647b7756431820f5275cc3e2 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/17b8276355dd2368647b7756431820f5275cc3e2 new file mode 100644 index 000000000000..0aeaa9e953d5 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/17b8276355dd2368647b7756431820f5275cc3e2 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/17d0aece97973ab23a467486b177ea9722e1b90b b/third_party/libwebm/source/webm_parser/fuzzing/corpus/17d0aece97973ab23a467486b177ea9722e1b90b new file mode 100644 index 000000000000..447e51527457 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/17d0aece97973ab23a467486b177ea9722e1b90b @@ -0,0 +1 @@ +S€g¼C§p·E¹´¶“|°…@hello€€€€€€€€€…@B€@…@C¶@ sÄ€€€€€€„€–€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/17e80cf8c247d17acad56c88750da34893fcb4fd b/third_party/libwebm/source/webm_parser/fuzzing/corpus/17e80cf8c247d17acad56c88750da34893fcb4fd new file mode 100644 index 000000000000..23ff05e178f0 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/17e80cf8c247d17acad56c88750da34893fcb4fd differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/18040e106688eb1d54323927a403439ecfde6626 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/18040e106688eb1d54323927a403439ecfde6626 new file mode 100644 index 000000000000..14b59f5bdc0e --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/18040e106688eb1d54323927a403439ecfde6626 @@ -0,0 +1 @@ +S€g”T®k®m€Šb@‡P5„Gâ!S€g”T®k®m€Šb@‡P5„Gâ!S€g›T®k–®”m€;S€g›T®k–®”m€‘ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/1813261b3141faa01431c82e06292485516d3327 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/1813261b3141faa01431c82e06292485516d3327 new file mode 100644 index 000000000000..063dacd5998b --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/1813261b3141faa01431c82e06292485516d3327 @@ -0,0 +1 @@ +S€g¼C§p·E¹´¶²€ …@helloC|…lang0C~…area0C}…lang€…S|1C–T®k‘®m€Œb@‰P2€ÿ†G*lang2C~ƒGè…€ara1 \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/184ee2343d4b9f62c69383692829fd852ad8855d b/third_party/libwebm/source/webm_parser/fuzzing/corpus/184ee2343d4b9f62c69383692829fd852ad8855d new file mode 100644 index 000000000000..10ba1006a954 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/184ee2343d4b9f62c69383692829fd852ad8855d @@ -0,0 +1 @@ +Tª€g‰C¶u„ ‚¢€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/186035a2f5c09ccd6b7d15de46f8561c98d8897d b/third_party/libwebm/source/webm_parser/fuzzing/corpus/186035a2f5c09ccd6b7d15de46f8561c98d8897d new file mode 100644 index 000000000000..fdcc0a0f7d3c --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/186035a2f5c09ccd6b7d15de46f8561c98d8897d @@ -0,0 +1 @@ +S€gC§pˆE¹…¶ƒ‘ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/186292900ad9d43881b71765158c32d78d80c8f3 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/186292900ad9d43881b71765158c32d78d80c8f3 new file mode 100644 index 000000000000..35ada6f23a39 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/186292900ad9d43881b71765158c32d78d80c8f3 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/18fd762b91406d37b85a7b342a91434a15f17290 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/18fd762b91406d37b85a7b342a91434a15f17290 new file mode 100644 index 000000000000..26c44c98a73a Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/18fd762b91406d37b85a7b342a91434a15f17290 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/19334eee05eeb18c549498e7ca2e792a2a4e04f3 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/19334eee05eeb18c549498e7ca2e792a2a4e04f3 new file mode 100644 index 000000000000..cc25e67125d8 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/19334eee05eeb18c549498e7ca2e792a2a4e04f3 @@ -0,0 +1 @@ +S€gC§p‹E¹ˆ¶†€„C| \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/1a9a5df35779dd6e9e1de171b9bb0d316d2b64a5 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/1a9a5df35779dd6e9e1de171b9bb0d316d2b64a5 new file mode 100644 index 000000000000..729397426f98 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/1a9a5df35779dd6e9e1de171b9bb0d316d2b64a5 @@ -0,0 +1 @@ +S€g‘T®kŒ®Šàˆ#ƒã„@Û \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/1ab3d30f60743c2a1d3043773aae3a04f83c07c0 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/1ab3d30f60743c2a1d3043773aae3a04f83c07c0 new file mode 100644 index 000000000000..9682a0f2ab0c --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/1ab3d30f60743c2a1d3043773aae3a04f83c07c0 @@ -0,0 +1 @@ +Sg€„IŒû@D‰ÉÛ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/1ad84ed46f3fda305150bac93958a5a390e23a67 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/1ad84ed46f3fda305150bac93958a5a390e23a67 new file mode 100644 index 000000000000..7e0f66f6f1ab --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/1ad84ed46f3fda305150bac93958a5a390e23a67 @@ -0,0 +1 @@ +S€g¼C§p·E¹´¶²€°…@helloC|…lang0C|…area0C|…lang1C|…lang2C|…area1 \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/1b40a997150aa03c23ecc6efe445a2d7c3dd8368 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/1b40a997150aa03c23ecc6efe445a2d7c3dd8368 new file mode 100644 index 000000000000..b5d9ab5ff318 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/1b40a997150aa03c23ecc6efe445a2d7c3dd8368 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/1b6b3bab9032cd420f350b6bb252942484f6b527 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/1b6b3bab9032cd420f350b6bb252942484f6b527 new file mode 100644 index 000000000000..5275f036de00 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/1b6b3bab9032cd420f350b6bb252942484f6b527 @@ -0,0 +1 @@ +bdT°gŒT®‡®…ᇟ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/1b7765cb05c94581461ffcd38d38b7b272d8e9d6 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/1b7765cb05c94581461ffcd38d38b7b272d8e9d6 new file mode 100644 index 000000000000..980ae8498fa7 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/1b7765cb05c94581461ffcd38d38b7b272d8e9d6 @@ -0,0 +1 @@ +S€gT®kˆ®†à„T² \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/1b89e3fe0cbd4c2291a74bf21969a9d9d851cbf1 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/1b89e3fe0cbd4c2291a74bf21969a9d9d851cbf1 new file mode 100644 index 000000000000..24ed7222c0e5 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/1b89e3fe0cbd4c2291a74bf21969a9d9d851cbf1 @@ -0,0 +1 @@ +ã \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/1b95d4da08fe949a60f63cd59213d42d30dbd381 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/1b95d4da08fe949a60f63cd59213d42d30dbd381 new file mode 100644 index 000000000000..1326dfe5a2d0 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/1b95d4da08fe949a60f63cd59213d42d30dbd381 @@ -0,0 +1 @@ +S€gŒS»k‡»…·ƒ² \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/1bac1200e05bb3269d019903241791c917a12bd0 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/1bac1200e05bb3269d019903241791c917a12bd0 new file mode 100644 index 000000000000..a93062251649 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/1bac1200e05bb3269d019903241791c917a12bd0 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/1bb8f5f81b7f6c1d58e1f7bb13fa561fe1a146bc b/third_party/libwebm/source/webm_parser/fuzzing/corpus/1bb8f5f81b7f6c1d58e1f7bb13fa561fe1a146bc new file mode 100644 index 000000000000..b3204bca9b32 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/1bb8f5f81b7f6c1d58e1f7bb13fa561fe1a146bc @@ -0,0 +1 @@ +S€g‘C¶uŒ Šu¡‡¦…îƒ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/1c56068c6dd17e9a824db6da78d64f933267a8c0 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/1c56068c6dd17e9a824db6da78d64f933267a8c0 new file mode 100644 index 000000000000..bd3b28e3f80d --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/1c56068c6dd17e9a824db6da78d64f933267a8c0 @@ -0,0 +1 @@ +S€gTÃgŠss‡cÀ„hgÈ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/1c8db8b9d88dd3483b6f81e4224c4f985046e6ac b/third_party/libwebm/source/webm_parser/fuzzing/corpus/1c8db8b9d88dd3483b6f81e4224c4f985046e6ac new file mode 100644 index 000000000000..57d98442b6c5 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/1c8db8b9d88dd3483b6f81e4224c4f985046e6ac differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/1d29a77924602a79c0f546535a885f59cbbbc405 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/1d29a77924602a79c0f546535a885f59cbbbc405 new file mode 100644 index 000000000000..3baa1cea8e0c --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/1d29a77924602a79c0f546535a885f59cbbbc405 @@ -0,0 +1 @@ +S€g£I©f€I©f€I©f€C¶u€T®k€)S»k€ÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/1d75a65733da627e5c401625bff522eadf098315 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/1d75a65733da627e5c401625bff522eadf098315 new file mode 100644 index 000000000000..5b6200c18fb0 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/1d75a65733da627e5c401625bff522eadf098315 @@ -0,0 +1 @@ +S€gT®kˆ®†à„S¸ÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/1df9507cc2a54a369646d6d34d846d3fcc172479 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/1df9507cc2a54a369646d6d34d846d3fcc172479 new file mode 100644 index 000000000000..0826b42ba13d Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/1df9507cc2a54a369646d6d34d846d3fcc172479 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/1e7a571be5aa542c3dfec1223d2e089a3075ce1f b/third_party/libwebm/source/webm_parser/fuzzing/corpus/1e7a571be5aa542c3dfec1223d2e089a3075ce1f new file mode 100644 index 000000000000..4feebdf53c58 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/1e7a571be5aa542c3dfec1223d2e089a3075ce1f @@ -0,0 +1 @@ +S€gŒT®k‡®…ჟ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/20a6b040258fbfa09bb37c6fc07106b2e43bada7 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/20a6b040258fbfa09bb37c6fc07106b2e43bada7 new file mode 100644 index 000000000000..fcae8abfe7ed --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/20a6b040258fbfa09bb37c6fc07106b2e43bada7 @@ -0,0 +1 @@ +S€gŠS»k…»ƒ³ÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/20e8ca854d3c0c375dc943142a04ee2260f0d1fd b/third_party/libwebm/source/webm_parser/fuzzing/corpus/20e8ca854d3c0c375dc943142a04ee2260f0d1fd new file mode 100644 index 000000000000..dbaa57187e60 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/20e8ca854d3c0c375dc943142a04ee2260f0d1fd differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/212ee7d21a8cb25249644cab4f959db111f3a3c0 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/212ee7d21a8cb25249644cab4f959db111f3a3c0 new file mode 100644 index 000000000000..0474655b121f Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/212ee7d21a8cb25249644cab4f959db111f3a3c0 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/224ce7b415f7950118880fce0594734aef489fec b/third_party/libwebm/source/webm_parser/fuzzing/corpus/224ce7b415f7950118880fce0594734aef489fec new file mode 100644 index 000000000000..35aedfe3fa41 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/224ce7b415f7950118880fce0594734aef489fec differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/226e70c1beddace83862791a6555c80475640bd0 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/226e70c1beddace83862791a6555c80475640bd0 new file mode 100644 index 000000000000..028ff9d6bdc5 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/226e70c1beddace83862791a6555c80475640bd0 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/233d53e3eb21b6ea6feebd6e59e3ef888a840f49 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/233d53e3eb21b6ea6feebd6e59e3ef888a840f49 new file mode 100644 index 000000000000..ff5a962e571d Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/233d53e3eb21b6ea6feebd6e59e3ef888a840f49 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/237f7aee90f206d3a6b138cc908b8921b544e190 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/237f7aee90f206d3a6b138cc908b8921b544e190 new file mode 100644 index 000000000000..60d1eaa2e51e Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/237f7aee90f206d3a6b138cc908b8921b544e190 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/23e1ac0f77f1283cf6e9fa044df3ec51bff27fd4 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/23e1ac0f77f1283cf6e9fa044df3ec51bff27fd4 new file mode 100644 index 000000000000..b17cd82f2958 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/23e1ac0f77f1283cf6e9fa044df3ec51bff27fd4 @@ -0,0 +1 @@ +S€gŠS»k…»ƒ³ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/23fcee6c71a8f5a22447df688724c0250fb77a70 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/23fcee6c71a8f5a22447df688724c0250fb77a70 new file mode 100644 index 000000000000..6580bec4736c Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/23fcee6c71a8f5a22447df688724c0250fb77a70 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/2459eb855d8c6ebac13cb74d996565d78130f4dd b/third_party/libwebm/source/webm_parser/fuzzing/corpus/2459eb855d8c6ebac13cb74d996565d78130f4dd new file mode 100644 index 000000000000..2ad814fbad7f --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/2459eb855d8c6ebac13cb74d996565d78130f4dd @@ -0,0 +1 @@ +EߣˆB‚@webmS€g©C¶u¤ç@«@£…¾Eß#Z \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/259188e5fb0c09046df96f6d565c59e0d146f198 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/259188e5fb0c09046df96f6d565c59e0d146f198 new file mode 100644 index 000000000000..c69951ecb45f --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/259188e5fb0c09046df96f6d565c59e0d146f198 @@ -0,0 +1 @@ +S€gŠT®k…®ƒœ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/26f07f8e28e7521ed282fe5c3938c1ae225816b9 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/26f07f8e28e7521ed282fe5c3938c1ae225816b9 new file mode 100644 index 000000000000..d592c6e84707 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/26f07f8e28e7521ed282fe5c3938c1ae225816b9 @@ -0,0 +1 @@ +STŠggÀss‡g„D…! \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/276425d65d58453d03a3444c9f6662d08d449af7 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/276425d65d58453d03a3444c9f6662d08d449af7 new file mode 100644 index 000000000000..3d99d50013e3 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/276425d65d58453d03a3444c9f6662d08d449af7 @@ -0,0 +1 @@ +S€g”TÃgssŒcÀ‰hÊ€cÊ€cÅ€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/27d62874ec87a2552e7c842da65de113aa69f7aa b/third_party/libwebm/source/webm_parser/fuzzing/corpus/27d62874ec87a2552e7c842da65de113aa69f7aa new file mode 100644 index 000000000000..f83242ad0b20 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/27d62874ec87a2552e7c842da65de113aa69f7aa differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/281b259280ada5d07b07a22cbe9a78c7b0fba94b b/third_party/libwebm/source/webm_parser/fuzzing/corpus/281b259280ada5d07b07a22cbe9a78c7b0fba94b new file mode 100644 index 000000000000..d59afe9f6a4a --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/281b259280ada5d07b07a22cbe9a78c7b0fba94b @@ -0,0 +1 @@ +S€g”C¶u u¡Š¦ƒî¦ƒî \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/299ed12b98673c6c4adbcf886cb70db8adde6aa1 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/299ed12b98673c6c4adbcf886cb70db8adde6aa1 new file mode 100644 index 000000000000..2afc78536f24 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/299ed12b98673c6c4adbcf886cb70db8adde6aa1 @@ -0,0 +1 @@ +S€g–T®k‘®m€Œb@‰P3†GçƒGè€S€gg—T®kÀ®m€b@ŠP3‡Gç„Gè \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/2a40feb7480d0b31c36d5626761e948d0ae52792 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/2a40feb7480d0b31c36d5626761e948d0ae52792 new file mode 100644 index 000000000000..6828d16aeaaa Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/2a40feb7480d0b31c36d5626761e948d0ae52792 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/2a6d7e2b829ed28307b551eda0d96f1834bff899 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/2a6d7e2b829ed28307b551eda0d96f1834bff899 new file mode 100644 index 000000000000..6556c8087327 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/2a6d7e2b829ed28307b551eda0d96f1834bff899 @@ -0,0 +1 @@ +S€g¼C§p·E¹´¶²€°…@helltC|…lang0C~…area0C|…lang1C|…lang2C~…a1 \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/2a8dda90aa286175b5c683b57fae1dc7e6ac1e7e b/third_party/libwebm/source/webm_parser/fuzzing/corpus/2a8dda90aa286175b5c683b57fae1dc7e6ac1e7e new file mode 100644 index 000000000000..f453884f9a96 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/2a8dda90aa286175b5c683b57fae1dc7e6ac1e7e differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/2a9588e6fab82016b545462cff2ed014c0345551 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/2a9588e6fab82016b545462cff2ed014c0345551 new file mode 100644 index 000000000000..014063669c72 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/2a9588e6fab82016b545462cff2ed014c0345551 @@ -0,0 +1 @@ +S€gT®kˆ®†à„T°ÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/2b1d57a8e8fa7164c9ba00957c9486010754560c b/third_party/libwebm/source/webm_parser/fuzzing/corpus/2b1d57a8e8fa7164c9ba00957c9486010754560c new file mode 100644 index 000000000000..298598f506ff --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/2b1d57a8e8fa7164c9ba00957c9486010754560c @@ -0,0 +1 @@ +S€g–T®k‘®m€Œb@‰P5†GçƒGè€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/2b475d1a8f2fe4fbba92e1424f0ea96d95b12fb7 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/2b475d1a8f2fe4fbba92e1424f0ea96d95b12fb7 new file mode 100644 index 000000000000..7e8be98a0cce --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/2b475d1a8f2fe4fbba92e1424f0ea96d95b12fb7 @@ -0,0 +1 @@ +S€g˜T®k“®‘m€Žb@„P1b@€P1 \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/2bb80c6d0e2eadd73018eb2a8cae37d41602ee79 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/2bb80c6d0e2eadd73018eb2a8cae37d41602ee79 new file mode 100644 index 000000000000..8f07d6cb7b32 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/2bb80c6d0e2eadd73018eb2a8cae37d41602ee79 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/2c1389f882e256e260e37e8a67af7e32d0f4e0fc b/third_party/libwebm/source/webm_parser/fuzzing/corpus/2c1389f882e256e260e37e8a67af7e32d0f4e0fc new file mode 100644 index 000000000000..671040876640 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/2c1389f882e256e260e37e8a67af7e32d0f4e0fc @@ -0,0 +1 @@ +µÿÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/2c1f94c76e4eec607cce5311323620f349912e73 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/2c1f94c76e4eec607cce5311323620f349912e73 new file mode 100644 index 000000000000..26995d28b55c --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/2c1f94c76e4eec607cce5311323620f349912e73 @@ -0,0 +1 @@ +S€gŽS»k‰»‡·…ðƒ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/2c962c7fbceaacf8247ac9b70c8eeb1f814e435b b/third_party/libwebm/source/webm_parser/fuzzing/corpus/2c962c7fbceaacf8247ac9b70c8eeb1f814e435b new file mode 100644 index 000000000000..856cb5be8a85 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/2c962c7fbceaacf8247ac9b70c8eeb1f814e435b @@ -0,0 +1 @@ +S€gŒM›t‡M»„S¬ÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/2c9aaabacf3a3b48dec4a85767cc5d38a1736aff b/third_party/libwebm/source/webm_parser/fuzzing/corpus/2c9aaabacf3a3b48dec4a85767cc5d38a1736aff new file mode 100644 index 000000000000..28edff60145c --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/2c9aaabacf3a3b48dec4a85767cc5d38a1736aff @@ -0,0 +1 @@ +S€gC¶uˆ †Ž„y‚Ì€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/2cf086299f983d0afc7f95c5e0c86b657448af33 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/2cf086299f983d0afc7f95c5e0c86b657448af33 new file mode 100644 index 000000000000..13f182651c52 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/2cf086299f983d0afc7f95c5e0c86b657448af33 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/2d0d96b95e9a3316d1ff0ef019ada509bbde4c9d b/third_party/libwebm/source/webm_parser/fuzzing/corpus/2d0d96b95e9a3316d1ff0ef019ada509bbde4c9d new file mode 100644 index 000000000000..adcb9e1bc6b0 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/2d0d96b95e9a3316d1ff0ef019ada509bbde4c9d differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/2d414d5dfd20055393df3208009840da9cfabca9 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/2d414d5dfd20055393df3208009840da9cfabca9 new file mode 100644 index 000000000000..8e5d23f1644f Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/2d414d5dfd20055393df3208009840da9cfabca9 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/2df967edcc00ac5c8e00037f1a43680600af5cba b/third_party/libwebm/source/webm_parser/fuzzing/corpus/2df967edcc00ac5c8e00037f1a43680600af5cba new file mode 100644 index 000000000000..fb0e9b1cf79d Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/2df967edcc00ac5c8e00037f1a43680600af5cba differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/2e6b09f1eca05ce2bba920fb78f9bca2a883fda0 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/2e6b09f1eca05ce2bba920fb78f9bca2a883fda0 new file mode 100644 index 000000000000..2a3a9d3798f2 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/2e6b09f1eca05ce2bba920fb78f9bca2a883fda0 @@ -0,0 +1 @@ +Eߣ„B‚! \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/2e8bde3549723e13849b604f4deedd51c71dfef5 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/2e8bde3549723e13849b604f4deedd51c71dfef5 new file mode 100644 index 000000000000..16bf11209d99 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/2e8bde3549723e13849b604f4deedd51c71dfef5 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/2f6e92a71918d01c16762d5ca59b328f1341d326 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/2f6e92a71918d01c16762d5ca59b328f1341d326 new file mode 100644 index 000000000000..3393c8ded1aa --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/2f6e92a71918d01c16762d5ca59b328f1341d326 @@ -0,0 +1 @@ +S€g»k \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/306e2cf9aebe012cb0769b1b2a6ea68af2e8ed44 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/306e2cf9aebe012cb0769b1b2a6ea68af2e8ed44 new file mode 100644 index 000000000000..60a0f4849d3c --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/306e2cf9aebe012cb0769b1b2a6ea68af2e8ed44 @@ -0,0 +1 @@ +áEߣˆB‚@webmS€g£*M'›t€I©f€C¶u€TSkk»€®€C§p€TÃg€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/30f7348d35de0c47d2044736cb115972b800569d b/third_party/libwebm/source/webm_parser/fuzzing/corpus/30f7348d35de0c47d2044736cb115972b800569d new file mode 100644 index 000000000000..d992dbe02907 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/30f7348d35de0c47d2044736cb115972b800569d differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/310798b8d94a3a2fe649a4c871458b4d74fdcf32 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/310798b8d94a3a2fe649a4c871458b4d74fdcf32 new file mode 100644 index 000000000000..e3c32aa6faa4 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/310798b8d94a3a2fe649a4c871458b4d74fdcf32 @@ -0,0 +1 @@ +S€gC§pˆE¹…¶ƒ’ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/31ea606a9859bb29d7f98162d254348021e0d932 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/31ea606a9859bb29d7f98162d254348021e0d932 new file mode 100644 index 000000000000..038f1a9198af --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/31ea606a9859bb29d7f98162d254348021e0d932 @@ -0,0 +1 @@ +S€g½C§p¸E¹µ¶³sÄVTA‘@’@€@…@B€@…@C¶@sĶ@€ÿÿÿ¶@sÄ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/3230fc31ab8d408c484aa28bbe36431f71101243 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/3230fc31ab8d408c484aa28bbe36431f71101243 new file mode 100644 index 000000000000..cad0aa075740 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/3230fc31ab8d408c484aa28bbe36431f71101243 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/328b7c92996e480d1f11efe847c3be4b5dc0f8eb b/third_party/libwebm/source/webm_parser/fuzzing/corpus/328b7c92996e480d1f11efe847c3be4b5dc0f8eb new file mode 100644 index 000000000000..b229bcb7d68a Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/328b7c92996e480d1f11efe847c3be4b5dc0f8eb differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/32e58bb3d00863115f33707e0c8af722036676fd b/third_party/libwebm/source/webm_parser/fuzzing/corpus/32e58bb3d00863115f33707e0c8af722036676fd new file mode 100644 index 000000000000..caf3c09c4476 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/32e58bb3d00863115f33707e0c8af722036676fd differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/32fc8547b6145c502d98e5e0c296ebd05badfdb9 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/32fc8547b6145c502d98e5e0c296ebd05badfdb9 new file mode 100644 index 000000000000..67c94c838e89 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/32fc8547b6145c502d98e5e0c296ebd05badfdb9 @@ -0,0 +1 @@ +S€g˜T®k“®‘m€Žb@„P1b@€P1 \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/334cddba889265a1263feb77a2afdc454ca54f5e b/third_party/libwebm/source/webm_parser/fuzzing/corpus/334cddba889265a1263feb77a2afdc454ca54f5e new file mode 100644 index 000000000000..e37d0399997d --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/334cddba889265a1263feb77a2afdc454ca54f5e @@ -0,0 +1 @@ +S€gŒI©f‡*×±ƒ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/33c9f9990890d2baf0c30d74b34b486082782413 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/33c9f9990890d2baf0c30d74b34b486082782413 new file mode 100644 index 000000000000..9a1abea4ff7f Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/33c9f9990890d2baf0c30d74b34b486082782413 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/341f3e8689e57eeab4234fcdd6d2b8f800b9ab34 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/341f3e8689e57eeab4234fcdd6d2b8f800b9ab34 new file mode 100644 index 000000000000..090bf59c3da8 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/341f3e8689e57eeab4234fcdd6d2b8f800b9ab34 @@ -0,0 +1 @@ +S€g“C¶uŽ ŒŽŠè€Ìè€Ì \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/3457e356eac79bf1c30b59940532d360dba2c1a9 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/3457e356eac79bf1c30b59940532d360dba2c1a9 new file mode 100644 index 000000000000..3f813fb73fa3 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/3457e356eac79bf1c30b59940532d360dba2c1a9 @@ -0,0 +1 @@ +S€gC¶uŠ ˆu¡…¦ƒîÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/351185a29bdbc7bf0d584479001fb47c32c61e5b b/third_party/libwebm/source/webm_parser/fuzzing/corpus/351185a29bdbc7bf0d584479001fb47c32c61e5b new file mode 100644 index 000000000000..6033e1cbff76 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/351185a29bdbc7bf0d584479001fb47c32c61e5b @@ -0,0 +1 @@ +!EߣˆB‚@webmS€g£M›t€I©f€C¶u€T®k€S»k€C§p€TÃg€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/35ae0d43c6bfc5f4b45f16877157832fddafce77 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/35ae0d43c6bfc5f4b45f16877157832fddafce77 new file mode 100644 index 000000000000..7e7e56258a71 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/35ae0d43c6bfc5f4b45f16877157832fddafce77 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/35b2f81c573b15304cb9b13f00008b460da78942 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/35b2f81c573b15304cb9b13f00008b460da78942 new file mode 100644 index 000000000000..85f4be21d1fe --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/35b2f81c573b15304cb9b13f00008b460da78942 @@ -0,0 +1 @@ +S€gˆC¶uƒ«ÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/35d9256a4d7ef3ee54384616178af3a8092d0981 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/35d9256a4d7ef3ee54384616178af3a8092d0981 new file mode 100644 index 000000000000..42f1817f039c --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/35d9256a4d7ef3ee54384616178af3a8092d0981 @@ -0,0 +1 @@ +S€gˆTÃgƒss€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/36352efd680a747f0f2c93d760559d69399a4102 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/36352efd680a747f0f2c93d760559d69399a4102 new file mode 100644 index 000000000000..d438e9c26002 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/36352efd680a747f0f2c93d760559d69399a4102 @@ -0,0 +1 @@ +S€gŠC¶u… ƒ›ÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/3685ffbcfe28b166ced0a783b012a446f9cfea46 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/3685ffbcfe28b166ced0a783b012a446f9cfea46 new file mode 100644 index 000000000000..fe6660b7f487 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/3685ffbcfe28b166ced0a783b012a446f9cfea46 @@ -0,0 +1 @@ +S€gŒS»k‡»…·ƒ÷ÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/36def8b2661197d594756f116a750822ae1d65d5 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/36def8b2661197d594756f116a750822ae1d65d5 new file mode 100644 index 000000000000..50d822aed413 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/36def8b2661197d594756f116a750822ae1d65d5 @@ -0,0 +1 @@ +S€g‘T®kŒ®Šm€‡b@„P3 \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/371950308853fb3b1b3a940c0598bfdfeb1d0f9c b/third_party/libwebm/source/webm_parser/fuzzing/corpus/371950308853fb3b1b3a940c0598bfdfeb1d0f9c new file mode 100644 index 000000000000..d12faf884315 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/371950308853fb3b1b3a940c0598bfdfeb1d0f9c @@ -0,0 +1 @@ +S€g‹C¶u† „u¢ÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/3765e9174971dbac9cfeb7e485ca61dc4941f7a9 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/3765e9174971dbac9cfeb7e485ca61dc4941f7a9 new file mode 100644 index 000000000000..4c306d90b136 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/3765e9174971dbac9cfeb7e485ca61dc4941f7a9 @@ -0,0 +1 @@ +S€gžT®k™®—m€”b@‘P5ŽGç‹Gèˆ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/37cae036ce7ff5d0671f32d3757579f248609c9c b/third_party/libwebm/source/webm_parser/fuzzing/corpus/37cae036ce7ff5d0671f32d3757579f248609c9c new file mode 100644 index 000000000000..9183f013cc32 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/37cae036ce7ff5d0671f32d3757579f248609c9c @@ -0,0 +1 @@ +S€g”T®k®m€Šb*‡P0„Gâ!S€gŠT®k…®ƒ¹ÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/38460ea06ee847ff3d5733415c299b44b0866e58 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/38460ea06ee847ff3d5733415c299b44b0866e58 new file mode 100644 index 000000000000..6456fa51768d --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/38460ea06ee847ff3d5733415c299b44b0866e58 @@ -0,0 +1 @@ +S€g½C§p¸E¹µ¶žsÄVTA‘@’@€@…@B€@…@C¶@sĶ@€ÿÿÿ¶@sÄ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/3865de2fec3f353513d86b28e43bf936d4707f97 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/3865de2fec3f353513d86b28e43bf936d4707f97 new file mode 100644 index 000000000000..f2150f606fad --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/3865de2fec3f353513d86b28e43bf936d4707f97 @@ -0,0 +1 @@ +€gS€g½C§p¸E¹µ¶³sÄVTA‘ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/3867b18060c307e0d04e0098f195d699e4b3294f b/third_party/libwebm/source/webm_parser/fuzzing/corpus/3867b18060c307e0d04e0098f195d699e4b3294f new file mode 100644 index 000000000000..f0cfd0a28cf3 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/3867b18060c307e0d04e0098f195d699e4b3294f @@ -0,0 +1 @@ +S€g»TÃg¶ss³gțȄ#‡dgÈ„]‡egÈ„D‡dgÈ„]‡egÈ„D‡gÈ€D‡dgÈ€g \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/391920720c3609b7c1f7b51162ce3ec99329a0b4 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/391920720c3609b7c1f7b51162ce3ec99329a0b4 new file mode 100644 index 000000000000..fb057c8c30a8 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/391920720c3609b7c1f7b51162ce3ec99329a0b4 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/395027454c7d5babff9544414c04a39d712eed1c b/third_party/libwebm/source/webm_parser/fuzzing/corpus/395027454c7d5babff9544414c04a39d712eed1c new file mode 100644 index 000000000000..e34ef6fa97cb --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/395027454c7d5babff9544414c04a39d712eed1c @@ -0,0 +1 @@ +€€¶€€€¶€¶€¶ÿ6€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ²€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ²€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶ÿ¶€¶€¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€€€¶€€€¶€¶€¶ÿ6€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€D¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€IIIIÿ²€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€timeout_exitcode¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€–ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ²€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€D¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€IIIIÿ²€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€timeout_exitcode¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ²€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€timeout_exit¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶ÿ¶€¶€¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€€€¶€€€¶€¶€¶ÿ6€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€D¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€IIIIÿ²€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€timeout_exitcode¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€–ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ²€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€D¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€IIIIÿ²€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€timeout_exitcode¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ²€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€timeout_exit¶ÿ¶€¶ÿ¶;€€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ²€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ²€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ²€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶ÿ¶€¶€¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€€€¶€€€¶€¶€¶ÿ6€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€D¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€IIIIÿ²€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€timeout_exitcode¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€–ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ²€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€D¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€IIIIÿ²€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€timeout_exitcode¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ²€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€timeout_exit¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶ÿ¶€¶€¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€€€¶€€€¶€¶€¶ÿ6€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€D¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ€¶¶€€¶ÿ€¶€¶ÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/3a258c9ed48e634ed8d495f07caf21dbc6978205 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/3a258c9ed48e634ed8d495f07caf21dbc6978205 new file mode 100644 index 000000000000..a14b82b42581 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/3a258c9ed48e634ed8d495f07caf21dbc6978205 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/3a397485197e6b99c77158132eaf211389615fe5 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/3a397485197e6b99c77158132eaf211389615fe5 new file mode 100644 index 000000000000..f8697b8b9f66 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/3a397485197e6b99c77158132eaf211389615fe5 @@ -0,0 +1 @@ +S€gŠT®k…®ƒˆÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/3a66b34706b686fe0fa8ca8f10c829758b2ebb07 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/3a66b34706b686fe0fa8ca8f10c829758b2ebb07 new file mode 100644 index 000000000000..506233798e06 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/3a66b34706b686fe0fa8ca8f10c829758b2ebb07 @@ -0,0 +1 @@ +S€g˜T®k“®‘m€Žb@„P1b€P1 \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/3ba666ad891fa8009dfc961aa3c215bbfd2d81d2 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/3ba666ad891fa8009dfc961aa3c215bbfd2d81d2 new file mode 100644 index 000000000000..227e447075c9 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/3ba666ad891fa8009dfc961aa3c215bbfd2d81d2 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/3ba9769c7c23cc3c80542ad123a371cf4f69e858 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/3ba9769c7c23cc3c80542ad123a371cf4f69e858 new file mode 100644 index 000000000000..d6bae74394be Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/3ba9769c7c23cc3c80542ad123a371cf4f69e858 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/3beb4432302433e303a9ccaf34637dd3a910028e b/third_party/libwebm/source/webm_parser/fuzzing/corpus/3beb4432302433e303a9ccaf34637dd3a910028e new file mode 100644 index 000000000000..63ae212ec18b Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/3beb4432302433e303a9ccaf34637dd3a910028e differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/3c6cdebc450d20a58150a9c71335b45a6a5ee0e5 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/3c6cdebc450d20a58150a9c71335b45a6a5ee0e5 new file mode 100644 index 000000000000..b92a4edca8ad --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/3c6cdebc450d20a58150a9c71335b45a6a5ee0e5 @@ -0,0 +1 @@ +S€gS¸ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/3c867362eb6a20f573a890db87749fce3c719d14 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/3c867362eb6a20f573a890db87749fce3c719d14 new file mode 100644 index 000000000000..81756429da81 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/3c867362eb6a20f573a890db87749fce3c719d14 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/3cd69ddcd34bd874e3abade696f95c949c17198d b/third_party/libwebm/source/webm_parser/fuzzing/corpus/3cd69ddcd34bd874e3abade696f95c949c17198d new file mode 100644 index 000000000000..298c393cb91d --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/3cd69ddcd34bd874e3abade696f95c949c17198d @@ -0,0 +1 @@ +S€gŒM›t‡M»„S«! \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/3de495ebac4b80064b79844f3a9453270caec251 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/3de495ebac4b80064b79844f3a9453270caec251 new file mode 100644 index 000000000000..c4fb5a4ac3be Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/3de495ebac4b80064b79844f3a9453270caec251 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/3e04542bcc462ded0025b53371f709d8fcd25c21 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/3e04542bcc462ded0025b53371f709d8fcd25c21 new file mode 100644 index 000000000000..8089b466b902 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/3e04542bcc462ded0025b53371f709d8fcd25c21 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/3e94196e55a9214083bda470772d71aedc17eb5f b/third_party/libwebm/source/webm_parser/fuzzing/corpus/3e94196e55a9214083bda470772d71aedc17eb5f new file mode 100644 index 000000000000..18f0b8f6eb74 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/3e94196e55a9214083bda470772d71aedc17eb5f differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/3ec4ac00bb967a335b5caae0ae51488f2fda6583 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/3ec4ac00bb967a335b5caae0ae51488f2fda6583 new file mode 100644 index 000000000000..b8043e818e34 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/3ec4ac00bb967a335b5caae0ae51488f2fda6583 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/3eec38c0ac3a96856d3210a0357857e70b07a9cb b/third_party/libwebm/source/webm_parser/fuzzing/corpus/3eec38c0ac3a96856d3210a0357857e70b07a9cb new file mode 100644 index 000000000000..25f027372258 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/3eec38c0ac3a96856d3210a0357857e70b07a9cb @@ -0,0 +1 @@ +S€g™TÃg‰ss†cÀ€cÀ€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/3ef82ba46238fa46b89148a230d23e741ba5f1da b/third_party/libwebm/source/webm_parser/fuzzing/corpus/3ef82ba46238fa46b89148a230d23e741ba5f1da new file mode 100644 index 000000000000..134a456f8ffc --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/3ef82ba46238fa46b89148a230d23e741ba5f1da @@ -0,0 +1 @@ +S€g˜T®k“®‘m€b@„P1b@€b@€P1 \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/3fbd43f81888ca60e5bfe49b47e23cb115d5cd7d b/third_party/libwebm/source/webm_parser/fuzzing/corpus/3fbd43f81888ca60e5bfe49b47e23cb115d5cd7d new file mode 100644 index 000000000000..75b0d29e6d14 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/3fbd43f81888ca60e5bfe49b47e23cb115d5cd7d @@ -0,0 +1 @@ +S€g½C§p¸E¹µ¶¬sÄV…@B€@…@C¶@sĶ@sä¶@sĶ@sĶ@sÄ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/3fe56e5b06653e8a37c99da190ff8d44d14bfc06 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/3fe56e5b06653e8a37c99da190ff8d44d14bfc06 new file mode 100644 index 000000000000..7a3c719f0165 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/3fe56e5b06653e8a37c99da190ff8d44d14bfc06 @@ -0,0 +1 @@ +S€G™T®k”®’m€bŒP‰S€g“C¶uŽ ŒŽŠèƒÌá€èGƒÌâ€Gç€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/3febffec3be8b1f4bcb76a01c1d713600d8e4adb b/third_party/libwebm/source/webm_parser/fuzzing/corpus/3febffec3be8b1f4bcb76a01c1d713600d8e4adb new file mode 100644 index 000000000000..5f0a13d1eb93 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/3febffec3be8b1f4bcb76a01c1d713600d8e4adb @@ -0,0 +1 @@ +S€gŠC§p…E¹‚¶€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/43380e5a9dd29ca847e9b5bfba12a0a95d94d0da b/third_party/libwebm/source/webm_parser/fuzzing/corpus/43380e5a9dd29ca847e9b5bfba12a0a95d94d0da new file mode 100644 index 000000000000..1c630fc4cde9 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/43380e5a9dd29ca847e9b5bfba12a0a95d94d0da differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/435d3ff6ddc43ac582e740ead969397fd2bfc7f5 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/435d3ff6ddc43ac582e740ead969397fd2bfc7f5 new file mode 100644 index 000000000000..8d8a6f49518d Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/435d3ff6ddc43ac582e740ead969397fd2bfc7f5 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/448120a37132488f48ab6c46a146c995948958cc b/third_party/libwebm/source/webm_parser/fuzzing/corpus/448120a37132488f48ab6c46a146c995948958cc new file mode 100644 index 000000000000..ff3b629d3949 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/448120a37132488f48ab6c46a146c995948958cc @@ -0,0 +1 @@ +S€g‘T®kŒ®Šm€‡b@„P1S€g”T®k®m€Šb@€Ð5„Gáÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/46db501d3e9a8808118333740a22bf9c808af239 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/46db501d3e9a8808118333740a22bf9c808af239 new file mode 100644 index 000000000000..a6c8ea7187fb Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/46db501d3e9a8808118333740a22bf9c808af239 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/47a2ca2b47aa1993cb655b77a0273ff139dd2280 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/47a2ca2b47aa1993cb655b77a0273ff139dd2280 new file mode 100644 index 000000000000..21fea1ba44c1 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/47a2ca2b47aa1993cb655b77a0273ff139dd2280 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/490576c8f6c235e1ed921c4932bac028070c806a b/third_party/libwebm/source/webm_parser/fuzzing/corpus/490576c8f6c235e1ed921c4932bac028070c806a new file mode 100644 index 000000000000..c83a83efa060 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/490576c8f6c235e1ed921c4932bac028070c806a @@ -0,0 +1 @@ +S€g‘C¶uŒ Š¡‡¦…îƒ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/4930b86bf0dfb02836b0319d21aa4a63a8dd894d b/third_party/libwebm/source/webm_parser/fuzzing/corpus/4930b86bf0dfb02836b0319d21aa4a63a8dd894d new file mode 100644 index 000000000000..3bc24dbccd1b --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/4930b86bf0dfb02836b0319d21aa4a63a8dd894d @@ -0,0 +1 @@ +S€gŠC¶u… ƒûÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/49667ff0b09901223117e74d2506bc37a5ae1580 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/49667ff0b09901223117e74d2506bc37a5ae1580 new file mode 100644 index 000000000000..a7c53d42333c --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/49667ff0b09901223117e74d2506bc37a5ae1580 @@ -0,0 +1 @@ +S€gŠT®k…®ƒ× \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/49906adf7313330e29be20d51fb36e9bdf1939c3 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/49906adf7313330e29be20d51fb36e9bdf1939c3 new file mode 100644 index 000000000000..713aeb8c1f7b Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/49906adf7313330e29be20d51fb36e9bdf1939c3 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/49c0e3eed81c1827e755c70c9c6d9606e7f54b22 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/49c0e3eed81c1827e755c70c9c6d9606e7f54b22 new file mode 100644 index 000000000000..cc061ed58617 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/49c0e3eed81c1827e755c70c9c6d9606e7f54b22 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/4a3e77f5bc061fc8121ef7ebd2b8e3ebb0bdd609 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/4a3e77f5bc061fc8121ef7ebd2b8e3ebb0bdd609 new file mode 100644 index 000000000000..336e6fb261df --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/4a3e77f5bc061fc8121ef7ebd2b8e3ebb0bdd609 @@ -0,0 +1 @@ +S€g½C§p¸E¹µ¶³sÄVTA‘@’@€@…@B€€€€j€€€€€€€€€€€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/4a454e01ef09b175f3864b654cfc1104a850e871 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/4a454e01ef09b175f3864b654cfc1104a850e871 new file mode 100644 index 000000000000..f57bbfdda993 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/4a454e01ef09b175f3864b654cfc1104a850e871 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/4acd9df9a7ee34e48c6c80777159b089f417a69a b/third_party/libwebm/source/webm_parser/fuzzing/corpus/4acd9df9a7ee34e48c6c80777159b089f417a69a new file mode 100644 index 000000000000..1df1e83120c7 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/4acd9df9a7ee34e48c6c80777159b089f417a69a differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/4af5564129d7b4c9c4736a3e511926c29348a4a4 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/4af5564129d7b4c9c4736a3e511926c29348a4a4 new file mode 100644 index 000000000000..93af2dbfea79 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/4af5564129d7b4c9c4736a3e511926c29348a4a4 @@ -0,0 +1 @@ +S€g™T®k”®’m€b@ŒP5‰Gá€â€Gç€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/4b3957bcbe5975399e34485cf0e5229169ab67b9 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/4b3957bcbe5975399e34485cf0e5229169ab67b9 new file mode 100644 index 000000000000..974197f5f3a6 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/4b3957bcbe5975399e34485cf0e5229169ab67b9 @@ -0,0 +1 @@ +S€gTÃgŠss‡cÀ„cÊ! \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/4c9e40aa8a439a500f073cf5a1e060a16ad12a6f b/third_party/libwebm/source/webm_parser/fuzzing/corpus/4c9e40aa8a439a500f073cf5a1e060a16ad12a6f new file mode 100644 index 000000000000..2d31d44e24dc Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/4c9e40aa8a439a500f073cf5a1e060a16ad12a6f differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/4cb5ff0e26f5bd0bb1fca846b4843db69095f18b b/third_party/libwebm/source/webm_parser/fuzzing/corpus/4cb5ff0e26f5bd0bb1fca846b4843db69095f18b new file mode 100644 index 000000000000..db5373dde03a --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/4cb5ff0e26f5bd0bb1fca846b4843db69095f18b @@ -0,0 +1 @@ +S€gT®kˆ®†à„T³ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/4ce80549344cf5b0432e39e7b5382407f0763e8c b/third_party/libwebm/source/webm_parser/fuzzing/corpus/4ce80549344cf5b0432e39e7b5382407f0763e8c new file mode 100644 index 000000000000..742ac60115bb --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/4ce80549344cf5b0432e39e7b5382407f0763e8c @@ -0,0 +1 @@ +S€®ŽT”gk®m€Šb@‡P5„Gá \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/4d10ae0032f04fa01148a54fae6838c44e4bb5bd b/third_party/libwebm/source/webm_parser/fuzzing/corpus/4d10ae0032f04fa01148a54fae6838c44e4bb5bd new file mode 100644 index 000000000000..97f34c665ab8 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/4d10ae0032f04fa01148a54fae6838c44e4bb5bd @@ -0,0 +1 @@ +S€g½C§p¸E¹µ¶sÄV…@B€@…@C¶@sĶ@sä¶@sĶ@ sĶ@sÄ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/4db2ded939a16fb1907dc2bad7acf67a64e38c0c b/third_party/libwebm/source/webm_parser/fuzzing/corpus/4db2ded939a16fb1907dc2bad7acf67a64e38c0c new file mode 100644 index 000000000000..36747bd1ae7c --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/4db2ded939a16fb1907dc2bad7acf67a64e38c0c @@ -0,0 +1 @@ +S€gˆC¶uƒç \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/4dc3a9a9477fb452ba7a4026bbc01d4cdd3d4990 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/4dc3a9a9477fb452ba7a4026bbc01d4cdd3d4990 new file mode 100644 index 000000000000..6422ec9cc369 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/4dc3a9a9477fb452ba7a4026bbc01d4cdd3d4990 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/4e1fb006a2268fa5fc70ca6b241bbc71faa6d7ff b/third_party/libwebm/source/webm_parser/fuzzing/corpus/4e1fb006a2268fa5fc70ca6b241bbc71faa6d7ff new file mode 100644 index 000000000000..1469145a0227 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/4e1fb006a2268fa5fc70ca6b241bbc71faa6d7ff @@ -0,0 +1 @@ +S€g‚À \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/4e871bbc5089f9550533641ddf6850f8722dfc36 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/4e871bbc5089f9550533641ddf6850f8722dfc36 new file mode 100644 index 000000000000..5967f9ecac20 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/4e871bbc5089f9550533641ddf6850f8722dfc36 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/4eeb4507868732d3705d1ab10f6a31f70f579556 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/4eeb4507868732d3705d1ab10f6a31f70f579556 new file mode 100644 index 000000000000..652484d43895 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/4eeb4507868732d3705d1ab10f6a31f70f579556 @@ -0,0 +1 @@ +S€g“C¶uŽ ŒŽŠèƒÌèƒÌS€gC¶uˆ †Ž„è‚΀ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/4f21f3584c99e97453ebe513ed44c86530fbebba b/third_party/libwebm/source/webm_parser/fuzzing/corpus/4f21f3584c99e97453ebe513ed44c86530fbebba new file mode 100644 index 000000000000..b37544dc89ca --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/4f21f3584c99e97453ebe513ed44c86530fbebba @@ -0,0 +1 @@ +S€g¼C§p‹E¹ˆ¶†€„C|›C§p‹E¹ˆ¶†€„C|! \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/5103160695cd56d281faa45d9267013488cc7bde b/third_party/libwebm/source/webm_parser/fuzzing/corpus/5103160695cd56d281faa45d9267013488cc7bde new file mode 100644 index 000000000000..2a707f72c5a2 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/5103160695cd56d281faa45d9267013488cc7bde @@ -0,0 +1 @@ +S€gT®kŠ®ƒ×®ƒ× \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/521103054e395afd0f9612b47c71cfa0e62151b9 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/521103054e395afd0f9612b47c71cfa0e62151b9 new file mode 100644 index 000000000000..5849044fca81 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/521103054e395afd0f9612b47c71cfa0e62151b9 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/523511e33c8788ebb1b703d7c5ad12b5da03964e b/third_party/libwebm/source/webm_parser/fuzzing/corpus/523511e33c8788ebb1b703d7c5ad12b5da03964e new file mode 100644 index 000000000000..99e77993ee60 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/523511e33c8788ebb1b703d7c5ad12b5da03964e differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/525aedb7462311393cd01939e4734d01db48535b b/third_party/libwebm/source/webm_parser/fuzzing/corpus/525aedb7462311393cd01939e4734d01db48535b new file mode 100644 index 000000000000..a68bdd6b63b3 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/525aedb7462311393cd01939e4734d01db48535b @@ -0,0 +1 @@ +V»UT³ÿM \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/53809012a8d5cfee839c3d0961b7fdc9468329a7 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/53809012a8d5cfee839c3d0961b7fdc9468329a7 new file mode 100644 index 000000000000..50eef726cb16 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/53809012a8d5cfee839c3d0961b7fdc9468329a7 @@ -0,0 +1 @@ +S€g»TÃg¶ss³È©È„#‡dgÈ„]‡egÈ„D‡dgÈ„]‡egÈ„D‡gÈ€D‡dgÈ€g \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/53c01d820d125e57b28410ca5b3a9c72c18d4102 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/53c01d820d125e57b28410ca5b3a9c72c18d4102 new file mode 100644 index 000000000000..8f78c01ae330 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/53c01d820d125e57b28410ca5b3a9c72c18d4102 @@ -0,0 +1 @@ +S€g‘C¶uŒ Šûˆþܺ˜vT2 \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/53c27071f53df6b8d2e5c419edf95b7792b278e7 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/53c27071f53df6b8d2e5c419edf95b7792b278e7 new file mode 100644 index 000000000000..87d69ed13e91 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/53c27071f53df6b8d2e5c419edf95b7792b278e7 @@ -0,0 +1 @@ +€€¶€€€¶€¶€¶ÿ6€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€€€ÿ¶¶€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€Óÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€ÿ¶¶€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€ÿ¶¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€ÿ¶¶€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€Óÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€ÿ¶¶€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€Óÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€ÿ¶¶€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€ÿ¶¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€ÿ¶¶€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€Óÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€ÿ¶¶€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€ÿ¶¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶:€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶„¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€wÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶¶€¶ÿ¶€m¶ÿ¶€¶ÿ¶¶®®Ý€¶ÿ¶€¶ÿ¶€¶€µ¶€¶Œÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€å¶€¶€¶ÿ¶€Eߣ¶€¶À¶ÿ¶€m¶ÿ¶€¶ÿ¶¶®®Ý€¶ÿ¶€¶ÿ¶€¶€µ¶€¶Œÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/53d5307f2e7852b183839fe93c20647004d151ec b/third_party/libwebm/source/webm_parser/fuzzing/corpus/53d5307f2e7852b183839fe93c20647004d151ec new file mode 100644 index 000000000000..acecedb171cb Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/53d5307f2e7852b183839fe93c20647004d151ec differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/5466c59c9c0eff34800e19cc92faf07469865ea9 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/5466c59c9c0eff34800e19cc92faf07469865ea9 new file mode 100644 index 000000000000..2b86b64afb95 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/5466c59c9c0eff34800e19cc92faf07469865ea9 @@ -0,0 +1 @@ +VT¢€€ˆƒ€€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/54bf8d6f1f846243b6f4de81605779b0acb78406 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/54bf8d6f1f846243b6f4de81605779b0acb78406 new file mode 100644 index 000000000000..9b4a32ed85f7 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/54bf8d6f1f846243b6f4de81605779b0acb78406 @@ -0,0 +1 @@ +€€€€€€€€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/54fd1711209fb1c0781092374132c66e79e2241b b/third_party/libwebm/source/webm_parser/fuzzing/corpus/54fd1711209fb1c0781092374132c66e79e2241b new file mode 100644 index 000000000000..7937c68fbcf7 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/54fd1711209fb1c0781092374132c66e79e2241b @@ -0,0 +1 @@ +g \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/5506797514c0b214f5faa9764a9e149cd1df9d28 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/5506797514c0b214f5faa9764a9e149cd1df9d28 new file mode 100644 index 000000000000..bfc500457fdf --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/5506797514c0b214f5faa9764a9e149cd1df9d28 @@ -0,0 +1 @@ +S€gŒT®k‡®…׃ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/5566c6d599866f5e523c54e6575d7b9e557a2539 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/5566c6d599866f5e523c54e6575d7b9e557a2539 new file mode 100644 index 000000000000..8578677e2113 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/5566c6d599866f5e523c54e6575d7b9e557a2539 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/55c3d55780427eb00bde252348db1c2ede22526c b/third_party/libwebm/source/webm_parser/fuzzing/corpus/55c3d55780427eb00bde252348db1c2ede22526c new file mode 100644 index 000000000000..25c7cc755ca0 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/55c3d55780427eb00bde252348db1c2ede22526c @@ -0,0 +1 @@ +€ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/5600abaefe804c50a353bbfdd0f9e10ffc102f81 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/5600abaefe804c50a353bbfdd0f9e10ffc102f81 new file mode 100644 index 000000000000..2b5e073b26df --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/5600abaefe804c50a353bbfdd0f9e10ffc102f81 @@ -0,0 +1 @@ +S¸S€g‘TkŒ®Šm€‡b@„P1S€g”T®k®m€Šb@€Ð5„Gáÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/5611ddd40488973ee6c64c45ad57d6eefe6da100 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/5611ddd40488973ee6c64c45ad57d6eefe6da100 new file mode 100644 index 000000000000..34d12c7c56a9 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/5611ddd40488973ee6c64c45ad57d6eefe6da100 @@ -0,0 +1 @@ +S€gŠI©f…*×±ÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/56b0ddd4e44492b45ebb7e9438b0a5556c244bfb b/third_party/libwebm/source/webm_parser/fuzzing/corpus/56b0ddd4e44492b45ebb7e9438b0a5556c244bfb new file mode 100644 index 000000000000..2da35a1d59c0 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/56b0ddd4e44492b45ebb7e9438b0a5556c244bfb @@ -0,0 +1 @@ +S€g‹S»k†»„·€·€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/5729395b452092152b06fbb8976e9bf1fda06439 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/5729395b452092152b06fbb8976e9bf1fda06439 new file mode 100644 index 000000000000..df3e05b5af14 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/5729395b452092152b06fbb8976e9bf1fda06439 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/57cce6fac7c0992eb338e0e538d3e0ee3fe7f1cd b/third_party/libwebm/source/webm_parser/fuzzing/corpus/57cce6fac7c0992eb338e0e538d3e0ee3fe7f1cd new file mode 100644 index 000000000000..ab69784bb967 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/57cce6fac7c0992eb338e0e538d3e0ee3fe7f1cd @@ -0,0 +1 @@ +ñEߣˆB‚@webmS€g£*M'›t€I©f€C¶u€ÔSkk»€®€C§p€TÃg€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/5822672f068da89546838004ae59552e12e132f7 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/5822672f068da89546838004ae59552e12e132f7 new file mode 100644 index 000000000000..b5b45fedae59 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/5822672f068da89546838004ae59552e12e132f7 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/59ce13e9a22e88dac879841256ff66f02cd2f8cc b/third_party/libwebm/source/webm_parser/fuzzing/corpus/59ce13e9a22e88dac879841256ff66f02cd2f8cc new file mode 100644 index 000000000000..628eda041009 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/59ce13e9a22e88dac879841256ff66f02cd2f8cc @@ -0,0 +1 @@ +S€gC¶u‹ ‰u¡†¦„€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/5a020527fc80b0de64e279fc44635687e014a9cf b/third_party/libwebm/source/webm_parser/fuzzing/corpus/5a020527fc80b0de64e279fc44635687e014a9cf new file mode 100644 index 000000000000..50c33bd7ac23 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/5a020527fc80b0de64e279fc44635687e014a9cf differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/5a645b30948850f8efb7bdd11944bdf3112c7bfe b/third_party/libwebm/source/webm_parser/fuzzing/corpus/5a645b30948850f8efb7bdd11944bdf3112c7bfe new file mode 100644 index 000000000000..2d85ba9dfa8a --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/5a645b30948850f8efb7bdd11944bdf3112c7bfe @@ -0,0 +1 @@ +S€gTÃgŠss‡cÀ„cÅÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/5b2f727461cde3c02ffdfb300adb0b4a09734911 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/5b2f727461cde3c02ffdfb300adb0b4a09734911 new file mode 100644 index 000000000000..741671552a2e --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/5b2f727461cde3c02ffdfb300adb0b4a09734911 @@ -0,0 +1 @@ +S€gT®kŠ®ˆà†S¸ƒ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/5b5531d859ab5bbb034345bbaa2852e9d8a1e1ef b/third_party/libwebm/source/webm_parser/fuzzing/corpus/5b5531d859ab5bbb034345bbaa2852e9d8a1e1ef new file mode 100644 index 000000000000..5b800b8f5ac6 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/5b5531d859ab5bbb034345bbaa2852e9d8a1e1ef @@ -0,0 +1 @@ +S€g‘T®kŒ®Šm€‡b@„P1 \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/5b980cb94e35769ec92a140ca00d34977e7da5ec b/third_party/libwebm/source/webm_parser/fuzzing/corpus/5b980cb94e35769ec92a140ca00d34977e7da5ec new file mode 100644 index 000000000000..180ef6b3a4a5 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/5b980cb94e35769ec92a140ca00d34977e7da5ec differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/5bfec2fe795176646fa0babecf97c04045bd4814 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/5bfec2fe795176646fa0babecf97c04045bd4814 new file mode 100644 index 000000000000..9e406d3a2f52 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/5bfec2fe795176646fa0babecf97c04045bd4814 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/5c28d94242e9a5ba7e7324e59e5dd12f3e31e51c b/third_party/libwebm/source/webm_parser/fuzzing/corpus/5c28d94242e9a5ba7e7324e59e5dd12f3e31e51c new file mode 100644 index 000000000000..68b4ebc8cb66 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/5c28d94242e9a5ba7e7324e59e5dd12f3e31e51c differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/5c67728ab04ba3dfe4b2636cf609f9617c4a5974 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/5c67728ab04ba3dfe4b2636cf609f9617c4a5974 new file mode 100644 index 000000000000..f14a6f6a1ee8 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/5c67728ab04ba3dfe4b2636cf609f9617c4a5974 @@ -0,0 +1 @@ +S€g”T®k®m€Šb@‡P0„Gâ!S€gŠT®k…®ƒ¹ÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/5cd36053e269c97f5359b0a075d80bf1e23b5f47 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/5cd36053e269c97f5359b0a075d80bf1e23b5f47 new file mode 100644 index 000000000000..985bba444f55 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/5cd36053e269c97f5359b0a075d80bf1e23b5f47 @@ -0,0 +1 @@ +S€gŒC¶u‡ …u¡‚¦€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/5d6f99c2afbf68a1b15a17e07945c11db8579e5f b/third_party/libwebm/source/webm_parser/fuzzing/corpus/5d6f99c2afbf68a1b15a17e07945c11db8579e5f new file mode 100644 index 000000000000..85a0c9302c8e Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/5d6f99c2afbf68a1b15a17e07945c11db8579e5f differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/5dd149b1b8509f456c16c4ac6dac3c7d6aa217ed b/third_party/libwebm/source/webm_parser/fuzzing/corpus/5dd149b1b8509f456c16c4ac6dac3c7d6aa217ed new file mode 100644 index 000000000000..102660dbf5d6 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/5dd149b1b8509f456c16c4ac6dac3c7d6aa217ed differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/5e84011c6b092e9f0d6ba60f12fc0fae95a622ca b/third_party/libwebm/source/webm_parser/fuzzing/corpus/5e84011c6b092e9f0d6ba60f12fc0fae95a622ca new file mode 100644 index 000000000000..d4df4df8c4b6 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/5e84011c6b092e9f0d6ba60f12fc0fae95a622ca differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/5f56766993de2b8c2db87116090af546e1add3b0 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/5f56766993de2b8c2db87116090af546e1add3b0 new file mode 100644 index 000000000000..c90364d0a2d2 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/5f56766993de2b8c2db87116090af546e1add3b0 @@ -0,0 +1 @@ +S€gŽS»k‰»‡·…÷ƒ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/60571c8be9bee3b13428613df66ff36cf54309ec b/third_party/libwebm/source/webm_parser/fuzzing/corpus/60571c8be9bee3b13428613df66ff36cf54309ec new file mode 100644 index 000000000000..bfd35dceee4c --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/60571c8be9bee3b13428613df66ff36cf54309ec @@ -0,0 +1 @@ +S€g”TÃgssŒcÀ‰hÊ€cÊ€cÅ€S€gTÃgŠss‡cÀ„cÊ! \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/60ac245f262ee1ff177d351a4fe246060fb4538b b/third_party/libwebm/source/webm_parser/fuzzing/corpus/60ac245f262ee1ff177d351a4fe246060fb4538b new file mode 100644 index 000000000000..21219e91111d Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/60ac245f262ee1ff177d351a4fe246060fb4538b differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/6120aafb0db1715400e47d0a61fb9f6d8665a736 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6120aafb0db1715400e47d0a61fb9f6d8665a736 new file mode 100644 index 000000000000..2fc4e39beccc --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6120aafb0db1715400e47d0a61fb9f6d8665a736 @@ -0,0 +1 @@ +S€gŠC¶u…çƒ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/61953a8f7a9f0613020d297a6d350abeeaf6e58c b/third_party/libwebm/source/webm_parser/fuzzing/corpus/61953a8f7a9f0613020d297a6d350abeeaf6e58c new file mode 100644 index 000000000000..478128c71dab --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/61953a8f7a9f0613020d297a6d350abeeaf6e58c @@ -0,0 +1 @@ +S€g“C¶uŽ ŒŽŠèƒÌèƒÌ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/61c0a7fef46c0c1b081b1c2b40835805e5989b54 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/61c0a7fef46c0c1b081b1c2b40835805e5989b54 new file mode 100644 index 000000000000..b5ac3f692144 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/61c0a7fef46c0c1b081b1c2b40835805e5989b54 @@ -0,0 +1 @@ +ä \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/620d85870206e88db0bc3ee978c24c0bbc1821ba b/third_party/libwebm/source/webm_parser/fuzzing/corpus/620d85870206e88db0bc3ee978c24c0bbc1821ba new file mode 100644 index 000000000000..4749f9c35d3e Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/620d85870206e88db0bc3ee978c24c0bbc1821ba differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/621131d8e28a67a6b4fb03c611f4375873d69678 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/621131d8e28a67a6b4fb03c611f4375873d69678 new file mode 100644 index 000000000000..d037403d522f --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/621131d8e28a67a6b4fb03c611f4375873d69678 @@ -0,0 +1 @@ +S€gŽC¶u‰ ‡Ž…èƒÌ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/624cbd42e3ebf35a3a0ba55b3b4969b99054f84d b/third_party/libwebm/source/webm_parser/fuzzing/corpus/624cbd42e3ebf35a3a0ba55b3b4969b99054f84d new file mode 100644 index 000000000000..0b518b97103c Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/624cbd42e3ebf35a3a0ba55b3b4969b99054f84d differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/6290103200631075988aa3566d8d8922599f8b6d b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6290103200631075988aa3566d8d8922599f8b6d new file mode 100644 index 000000000000..52f240dea799 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6290103200631075988aa3566d8d8922599f8b6d @@ -0,0 +1 @@ +€ÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/62a329f65143f1571dc4a2fbb256800c8ce4d89f b/third_party/libwebm/source/webm_parser/fuzzing/corpus/62a329f65143f1571dc4a2fbb256800c8ce4d89f new file mode 100644 index 000000000000..eca1ba98fb0f Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/62a329f65143f1571dc4a2fbb256800c8ce4d89f differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/62f8a53cfb4dd625dcb31ee2ba258db3916a3bd0 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/62f8a53cfb4dd625dcb31ee2ba258db3916a3bd0 new file mode 100644 index 000000000000..a3a36dc27014 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/62f8a53cfb4dd625dcb31ee2ba258db3916a3bd0 @@ -0,0 +1 @@ +S€gTÃg˜ss•gÈ’E£€gÈ€D„€D‡€D…€gÈ€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/6318dc574b3ad7291fee7e01bfeaa674eb0feb48 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6318dc574b3ad7291fee7e01bfeaa674eb0feb48 new file mode 100644 index 000000000000..baa7b64c3fcc --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6318dc574b3ad7291fee7e01bfeaa674eb0feb48 @@ -0,0 +1 @@ +S€g˜T®k“®‘m€Žb@„P1b@„P1 \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/6457a079debb9b532255e3e6ddf276b29808b49d b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6457a079debb9b532255e3e6ddf276b29808b49d new file mode 100644 index 000000000000..640d4a1fc416 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6457a079debb9b532255e3e6ddf276b29808b49d differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/646061a4526506a0b3c62629f4f77b6072c8f9c3 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/646061a4526506a0b3c62629f4f77b6072c8f9c3 new file mode 100644 index 000000000000..beb9e5baa3be --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/646061a4526506a0b3c62629f4f77b6072c8f9c3 @@ -0,0 +1 @@ +EߣžB†‡ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/6538d0517865c8832ee9bec87609b7bd4facb025 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6538d0517865c8832ee9bec87609b7bd4facb025 new file mode 100644 index 000000000000..7230e70db9b1 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6538d0517865c8832ee9bec87609b7bd4facb025 @@ -0,0 +1 @@ +€€¶€€€¶€¶€¶ÿ6€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€;€¶ÿ¶€€€ÿ¶¶€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ„€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€ÿ¶¶€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶¶¶ÿÿ€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶Š¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿJIII|¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€²ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€ÿ¶¶€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ„€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€;€¶ÿ¶€€€ÿ¶¶€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ„€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€ÿ¶¶€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶¶¶ÿÿ€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶Š¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿJIII|¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€²ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€ÿ¶¶€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶;€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/653de28e2f085334e30ec1c964540b432a3cfbc6 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/653de28e2f085334e30ec1c964540b432a3cfbc6 new file mode 100644 index 000000000000..5748705d5a36 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/653de28e2f085334e30ec1c964540b432a3cfbc6 @@ -0,0 +1 @@ +S€gC§p‹E¹ˆ¶†€„C|!S€gŽC§p‰E¹†¶„VT \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/657c9c42bf3e1c79a6dcb9071bf123367dc37734 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/657c9c42bf3e1c79a6dcb9071bf123367dc37734 new file mode 100644 index 000000000000..8638bce90681 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/657c9c42bf3e1c79a6dcb9071bf123367dc37734 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/65ebba0df08a5484686905e99631a4ead845c08b b/third_party/libwebm/source/webm_parser/fuzzing/corpus/65ebba0df08a5484686905e99631a4ead845c08b new file mode 100644 index 000000000000..e04df80c2b8e --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/65ebba0df08a5484686905e99631a4ead845c08b @@ -0,0 +1 @@ +S€gŽM›t‰M»†S¬ƒ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/66dd27c22fe09842ac4c4f51fdef4bea500b6a70 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/66dd27c22fe09842ac4c4f51fdef4bea500b6a70 new file mode 100644 index 000000000000..2e5c016ffecb --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/66dd27c22fe09842ac4c4f51fdef4bea500b6a70 @@ -0,0 +1 @@ +EߣÿB‚è \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/66e25df2bd43c840337a49e0cb5b386e9d290d80 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/66e25df2bd43c840337a49e0cb5b386e9d290d80 new file mode 100644 index 000000000000..88bbf1f3e97c Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/66e25df2bd43c840337a49e0cb5b386e9d290d80 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/6714df1ac1c54d4c30add212454e9513c6880767 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6714df1ac1c54d4c30add212454e9513c6880767 new file mode 100644 index 000000000000..20b7616ee483 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6714df1ac1c54d4c30add212454e9513c6880767 @@ -0,0 +1 @@ +S€gŒT®k‡®…àƒ° \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/68a6f9c2f62e9f57667de9563b5d612ec2f2c829 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/68a6f9c2f62e9f57667de9563b5d612ec2f2c829 new file mode 100644 index 000000000000..d8309eadaad2 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/68a6f9c2f62e9f57667de9563b5d612ec2f2c829 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/69089b76cc62fe00615702bdd1f339e259194d42 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/69089b76cc62fe00615702bdd1f339e259194d42 new file mode 100644 index 000000000000..f925002653e1 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/69089b76cc62fe00615702bdd1f339e259194d42 @@ -0,0 +1 @@ +S€gŽT®k‰®‡à…šƒ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/69d8622d24c7315f344c424297986170f7ef2243 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/69d8622d24c7315f344c424297986170f7ef2243 new file mode 100644 index 000000000000..6182f76ecc21 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/69d8622d24c7315f344c424297986170f7ef2243 @@ -0,0 +1 @@ +S€g“C¶uŽ ŒŽŠèƒÌèƒÌS€gC¶uˆ †Ž„è‚Ì€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/6a700d958cb3a7565d5a6b74540486874d52b4c7 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6a700d958cb3a7565d5a6b74540486874d52b4c7 new file mode 100644 index 000000000000..3c4a4a45fe50 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6a700d958cb3a7565d5a6b74540486874d52b4c7 @@ -0,0 +1 @@ +S€g¼C§p·E¹´¶²€ …@helloC|…lang0C~…area0C|…lang€…S|1C–T®k‘®m€Œb@‰P2€ÿ†G*lang2C~ƒGè…€area1 \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/6a852150c5c2a12d325e78056687a8ea97b25fe7 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6a852150c5c2a12d325e78056687a8ea97b25fe7 new file mode 100644 index 000000000000..ca14558f9018 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6a852150c5c2a12d325e78056687a8ea97b25fe7 @@ -0,0 +1 @@ +S€g‡T®k‚®€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/6ac8c9f754d5ff3c0cd3f3f585de99dd73944bbe b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6ac8c9f754d5ff3c0cd3f3f585de99dd73944bbe new file mode 100644 index 000000000000..a7d88f00e039 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6ac8c9f754d5ff3c0cd3f3f585de99dd73944bbe differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/6ace27a48f12990e2169cc099007aa5fa11962d2 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6ace27a48f12990e2169cc099007aa5fa11962d2 new file mode 100644 index 000000000000..f5449305e7b2 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6ace27a48f12990e2169cc099007aa5fa11962d2 @@ -0,0 +1 @@ +S€g™T®k”®’m€b@ŒT2€P2€P3P5€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/6b10397dc3bff2ccf57be4fe3ff9d8d1acb8c76e b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6b10397dc3bff2ccf57be4fe3ff9d8d1acb8c76e new file mode 100644 index 000000000000..db9ed48f183c Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6b10397dc3bff2ccf57be4fe3ff9d8d1acb8c76e differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/6c3f1d96c06b853551f685dde821142928f55acf b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6c3f1d96c06b853551f685dde821142928f55acf new file mode 100644 index 000000000000..91f4e815dc5e Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6c3f1d96c06b853551f685dde821142928f55acf differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/6c8de4d4bbb5294154c3b140d43836757b9f08ac b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6c8de4d4bbb5294154c3b140d43836757b9f08ac new file mode 100644 index 000000000000..8aefea242d5c --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6c8de4d4bbb5294154c3b140d43836757b9f08ac @@ -0,0 +1 @@ +S€g‰I©f„{©! \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/6cf122ee328af5cf6f18d5f9546b0fe761951b8d b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6cf122ee328af5cf6f18d5f9546b0fe761951b8d new file mode 100644 index 000000000000..56346390ca16 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6cf122ee328af5cf6f18d5f9546b0fe761951b8d differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/6cfbbc25caa217e22fd7ca3e92d2051c5f661bdb b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6cfbbc25caa217e22fd7ca3e92d2051c5f661bdb new file mode 100644 index 000000000000..bc69d35561d9 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6cfbbc25caa217e22fd7ca3e92d2051c5f661bdb @@ -0,0 +1 @@ +S€gC¶uˆ †Ž„è‚Ì€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/6d703bc900e74d1a576bebcccb63e3b2701ae86d b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6d703bc900e74d1a576bebcccb63e3b2701ae86d new file mode 100644 index 000000000000..e0bdcf240a40 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6d703bc900e74d1a576bebcccb63e3b2701ae86d @@ -0,0 +1 @@ +S€g˜T®k“®‘m€Žb@„P1b@€b@€P1 \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/6e1afa81dfcd6833705d84b45881f085c19b2211 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6e1afa81dfcd6833705d84b45881f085c19b2211 new file mode 100644 index 000000000000..670dd7c2849a --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6e1afa81dfcd6833705d84b45881f085c19b2211 @@ -0,0 +1 @@ +S€gC¶uŠ ˆu¡…¦ƒ¥! \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/6e244ec3b81e0d2f8b5810854859e1b8140422d9 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6e244ec3b81e0d2f8b5810854859e1b8140422d9 new file mode 100644 index 000000000000..2e7c1a4d82d4 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6e244ec3b81e0d2f8b5810854859e1b8140422d9 @@ -0,0 +1 @@ +S€gûû \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/6e323b4c733df90d55c754e099fb5a13bd9701cb b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6e323b4c733df90d55c754e099fb5a13bd9701cb new file mode 100644 index 000000000000..89e0e79cf86b --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6e323b4c733df90d55c754e099fb5a13bd9701cb @@ -0,0 +1 @@ +S€gT®kŠ®ˆà†T°ƒ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/6e36720f3f55dc0cd5d585c6770572964719b5b8 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6e36720f3f55dc0cd5d585c6770572964719b5b8 new file mode 100644 index 000000000000..376c75bf6dda Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6e36720f3f55dc0cd5d585c6770572964719b5b8 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/6e8384ab115ac92bb7787121cfb03582e2d72585 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6e8384ab115ac92bb7787121cfb03582e2d72585 new file mode 100644 index 000000000000..7f90100c7466 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6e8384ab115ac92bb7787121cfb03582e2d72585 @@ -0,0 +1 @@ +S€g¼C§p·E¹´¶ž|°…@hello€€€€€€€€€…@B€@…@C¶@ sÄ€€€€€€„€–€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/6ebf8b74dca1657f5f7ffadeccd629984473dcb4 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6ebf8b74dca1657f5f7ffadeccd629984473dcb4 new file mode 100644 index 000000000000..0bf3c1b79417 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6ebf8b74dca1657f5f7ffadeccd629984473dcb4 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/6ec18dcca0d820fff04c03c3a1bce37dd8ada41d b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6ec18dcca0d820fff04c03c3a1bce37dd8ada41d new file mode 100644 index 000000000000..c10fff019d91 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6ec18dcca0d820fff04c03c3a1bce37dd8ada41d @@ -0,0 +1 @@ +S€gT®k‹®‰á‡xµ„@ÉÛ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/6eceebb8f46545393d217ab0111ff7dd29bc99f7 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6eceebb8f46545393d217ab0111ff7dd29bc99f7 new file mode 100644 index 000000000000..27952aad829f --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6eceebb8f46545393d217ab0111ff7dd29bc99f7 @@ -0,0 +1 @@ +S€g–T®k‘®m€Œb@‰P5€†GçƒGè€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/6ee071f654fd6b7b25725a8bdd880bb6836e8c81 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6ee071f654fd6b7b25725a8bdd880bb6836e8c81 new file mode 100644 index 000000000000..fc5bea23619c Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6ee071f654fd6b7b25725a8bdd880bb6836e8c81 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/6f1088b3d1f4cdfbc37d9b8cfc1ff4c3bde2f205 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6f1088b3d1f4cdfbc37d9b8cfc1ff4c3bde2f205 new file mode 100644 index 000000000000..9936eea3370b --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6f1088b3d1f4cdfbc37d9b8cfc1ff4c3bde2f205 @@ -0,0 +1 @@ +EߣˆB‚@webmS€g©C¶u¤ç@«@£…¾Eß# \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/6f79e36e880664c9b3b610140d2485fb6a6e5039 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6f79e36e880664c9b3b610140d2485fb6a6e5039 new file mode 100644 index 000000000000..e646c0d70016 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6f79e36e880664c9b3b610140d2485fb6a6e5039 @@ -0,0 +1 @@ +€g€g=C§p¸Ess¶³sÄVTA‘ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/6fbea59066b2b97fa45259aa87c40c4310070019 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6fbea59066b2b97fa45259aa87c40c4310070019 new file mode 100644 index 000000000000..6b33dfda5d03 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/6fbea59066b2b97fa45259aa87c40c4310070019 @@ -0,0 +1 @@ +EߣˆB‚@webmS€g©C¶u¤ç@!« \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/7056b9c294f0cff7b4ace611a19363b2fc096bb3 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/7056b9c294f0cff7b4ace611a19363b2fc096bb3 new file mode 100644 index 000000000000..b0e999e5dd64 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/7056b9c294f0cff7b4ace611a19363b2fc096bb3 @@ -0,0 +1 @@ +!EߣˆB‚@webmS€g£M'›t)€I©f€OC¶u€gT®k€S»k€C§p€TÃg€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/7073dca40b911fb22f738c99aff43a10ae6c4db5 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/7073dca40b911fb22f738c99aff43a10ae6c4db5 new file mode 100644 index 000000000000..383c77ad6a3f Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/7073dca40b911fb22f738c99aff43a10ae6c4db5 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/7164d8ca3f4c3d621cc5eed7b59e3495e7b017a0 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/7164d8ca3f4c3d621cc5eed7b59e3495e7b017a0 new file mode 100644 index 000000000000..7d8a5d138500 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/7164d8ca3f4c3d621cc5eed7b59e3495e7b017a0 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/71e3e01b3cfcd4228402cbf19b5282c965f042df b/third_party/libwebm/source/webm_parser/fuzzing/corpus/71e3e01b3cfcd4228402cbf19b5282c965f042df new file mode 100644 index 000000000000..72cc1dc0f98e --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/71e3e01b3cfcd4228402cbf19b5282c965f042df @@ -0,0 +1 @@ +ìÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/720d36ea7f9616b1a1d47fa5b746e8657b5f973f b/third_party/libwebm/source/webm_parser/fuzzing/corpus/720d36ea7f9616b1a1d47fa5b746e8657b5f973f new file mode 100644 index 000000000000..6de803d48f94 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/720d36ea7f9616b1a1d47fa5b746e8657b5f973f differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/72ccbcbc53c7fa54247a81bd1d0e62dd0779494b b/third_party/libwebm/source/webm_parser/fuzzing/corpus/72ccbcbc53c7fa54247a81bd1d0e62dd0779494b new file mode 100644 index 000000000000..20c7fa691940 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/72ccbcbc53c7fa54247a81bd1d0e62dd0779494b @@ -0,0 +1 @@ +!EߣˆB‚@webmS€g£M'›t€I©f€C¶u€T®k€S»k€C§p€TÃg€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/736c0460f94c089c9e270857a4222a21ffd9e13f b/third_party/libwebm/source/webm_parser/fuzzing/corpus/736c0460f94c089c9e270857a4222a21ffd9e13f new file mode 100644 index 000000000000..14a490eb2758 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/736c0460f94c089c9e270857a4222a21ffd9e13f differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/745e32f46833c075c8e68552e0fbbcdd5ec52641 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/745e32f46833c075c8e68552e0fbbcdd5ec52641 new file mode 100644 index 000000000000..518d182473dd Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/745e32f46833c075c8e68552e0fbbcdd5ec52641 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/74aa7256477af2c0e2511df16376dee323f3ccb6 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/74aa7256477af2c0e2511df16376dee323f3ccb6 new file mode 100644 index 000000000000..46cfdb10a9ef Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/74aa7256477af2c0e2511df16376dee323f3ccb6 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/7528086eea404dccc3ee5b214befbc2a95676feb b/third_party/libwebm/source/webm_parser/fuzzing/corpus/7528086eea404dccc3ee5b214befbc2a95676feb new file mode 100644 index 000000000000..40b7db2f24bf --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/7528086eea404dccc3ee5b214befbc2a95676feb @@ -0,0 +1 @@ +S€g‘T®kŒ®Šàˆ#ƒã„ÉÛ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/7528f9f08f80c8e85951aa1db2dc616e992c1a62 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/7528f9f08f80c8e85951aa1db2dc616e992c1a62 new file mode 100644 index 000000000000..87b29be574d0 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/7528f9f08f80c8e85951aa1db2dc616e992c1a62 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/75af94f9695c375e5eb620849f0213ad41e8f205 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/75af94f9695c375e5eb620849f0213ad41e8f205 new file mode 100644 index 000000000000..dcf5dc6230bd Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/75af94f9695c375e5eb620849f0213ad41e8f205 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/75e1ff2e016b7b80ecb7a6a1f4c3238a2a2ed130 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/75e1ff2e016b7b80ecb7a6a1f4c3238a2a2ed130 new file mode 100644 index 000000000000..9dcbbb5378a1 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/75e1ff2e016b7b80ecb7a6a1f4c3238a2a2ed130 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/76129c3bdedafb3bda93f53266bd17bffdc30682 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/76129c3bdedafb3bda93f53266bd17bffdc30682 new file mode 100644 index 000000000000..bb8e0553400d Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/76129c3bdedafb3bda93f53266bd17bffdc30682 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/7670db89e0c3fe492c91458de219c3be34a3dcb7 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/7670db89e0c3fe492c91458de219c3be34a3dcb7 new file mode 100644 index 000000000000..c57ba43505f9 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/7670db89e0c3fe492c91458de219c3be34a3dcb7 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/7673d7fdf630637c6ae2b96694a047044c1a9cb0 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/7673d7fdf630637c6ae2b96694a047044c1a9cb0 new file mode 100644 index 000000000000..b0955cb8d7b9 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/7673d7fdf630637c6ae2b96694a047044c1a9cb0 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/76903905e654ddc59acf57380bf3dc1ea136bad9 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/76903905e654ddc59acf57380bf3dc1ea136bad9 new file mode 100644 index 000000000000..f652c3548473 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/76903905e654ddc59acf57380bf3dc1ea136bad9 @@ -0,0 +1 @@ +S€gT®kˆ®†à„T²ÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/76d36e3cf3d31e0f76af08bd7ba5571f679057a1 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/76d36e3cf3d31e0f76af08bd7ba5571f679057a1 new file mode 100644 index 000000000000..3f6abf812921 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/76d36e3cf3d31e0f76af08bd7ba5571f679057a1 @@ -0,0 +1 @@ +S€gŠC¶u… ƒû \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/775ce646f7dbf50199b8e8df85c9441b8a0a5447 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/775ce646f7dbf50199b8e8df85c9441b8a0a5447 new file mode 100644 index 000000000000..3d451af7ae4c Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/775ce646f7dbf50199b8e8df85c9441b8a0a5447 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/7770a6fd33ce821e60c78b0cb67a7e8c8bb74269 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/7770a6fd33ce821e60c78b0cb67a7e8c8bb74269 new file mode 100644 index 000000000000..e25e77cadfa0 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/7770a6fd33ce821e60c78b0cb67a7e8c8bb74269 @@ -0,0 +1 @@ +S€g”C¶u u¡Š¦ƒî¦ƒîS€gC¶uŠ ˆu¡…¦ƒ¥! \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/781b24e3433ba400df3ccddf56cb8fc7b1fd52ce b/third_party/libwebm/source/webm_parser/fuzzing/corpus/781b24e3433ba400df3ccddf56cb8fc7b1fd52ce new file mode 100644 index 000000000000..536c5042e176 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/781b24e3433ba400df3ccddf56cb8fc7b1fd52ce @@ -0,0 +1 @@ +S€gŠI©f…*×± \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/784db9d87b31ffb040ad212e4018b30c3535ad18 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/784db9d87b31ffb040ad212e4018b30c3535ad18 new file mode 100644 index 000000000000..5586a9ea17dd Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/784db9d87b31ffb040ad212e4018b30c3535ad18 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/7880e2ae55d255065ad415c4c625e1b63bfd2a93 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/7880e2ae55d255065ad415c4c625e1b63bfd2a93 new file mode 100644 index 000000000000..e2fb6ac284dd --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/7880e2ae55d255065ad415c4c625e1b63bfd2a93 @@ -0,0 +1 @@ +DzS€g–T®k‘®m€Œb@‰P5ÿ†GçƒGè€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/78cb3d726e4f9e8bc89b399fa514c3b600bf8e5a b/third_party/libwebm/source/webm_parser/fuzzing/corpus/78cb3d726e4f9e8bc89b399fa514c3b600bf8e5a new file mode 100644 index 000000000000..fc42e545b9c0 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/78cb3d726e4f9e8bc89b399fa514c3b600bf8e5a differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/79ba60931988a5974328a73fe091bdf6f5992891 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/79ba60931988a5974328a73fe091bdf6f5992891 new file mode 100644 index 000000000000..c6837fd70eb1 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/79ba60931988a5974328a73fe091bdf6f5992891 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/79cdb8dec1ad07b389f544a511f89b347429837e b/third_party/libwebm/source/webm_parser/fuzzing/corpus/79cdb8dec1ad07b389f544a511f89b347429837e new file mode 100644 index 000000000000..68e6b7d0bb5a Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/79cdb8dec1ad07b389f544a511f89b347429837e differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/7ab8c6a65c39907f4afa4e2b294303aebb6b22d8 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/7ab8c6a65c39907f4afa4e2b294303aebb6b22d8 new file mode 100644 index 000000000000..fddf510be6b9 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/7ab8c6a65c39907f4afa4e2b294303aebb6b22d8 @@ -0,0 +1 @@ +°€€€€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/7b12a398a1860ac2f3930d5020e422aec061f177 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/7b12a398a1860ac2f3930d5020e422aec061f177 new file mode 100644 index 000000000000..fed31c6f1e9b --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/7b12a398a1860ac2f3930d5020e422aec061f177 @@ -0,0 +1 @@ +S€gŠT®k…®ƒ¹ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/7bf1682743405f3d5b3433830eadae4ea311807d b/third_party/libwebm/source/webm_parser/fuzzing/corpus/7bf1682743405f3d5b3433830eadae4ea311807d new file mode 100644 index 000000000000..d8666eb112c7 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/7bf1682743405f3d5b3433830eadae4ea311807d @@ -0,0 +1 @@ +S€g»TÃg¶ss³gÈ©È„#‡dgÈ„]‡egÈ„D‡dgÈ„]‡egÈ„D‡gÈ„D‡dgÈg \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/7c7ef0e305f37f833708b375271d59300d120d84 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/7c7ef0e305f37f833708b375271d59300d120d84 new file mode 100644 index 000000000000..c9cedc0700d9 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/7c7ef0e305f37f833708b375271d59300d120d84 @@ -0,0 +1 @@ +S€gŽT®k‰®‡á…Ÿƒ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/7d06bd4a7de57953ef09c2e18ca67aa7ff367c76 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/7d06bd4a7de57953ef09c2e18ca67aa7ff367c76 new file mode 100644 index 000000000000..6cce7cb531be --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/7d06bd4a7de57953ef09c2e18ca67aa7ff367c76 @@ -0,0 +1 @@ +S€gTÃgŠss‡gÈ„E£! \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/7d31bd53bb7eb7b1f354c5f85d376390760ab16f b/third_party/libwebm/source/webm_parser/fuzzing/corpus/7d31bd53bb7eb7b1f354c5f85d376390760ab16f new file mode 100644 index 000000000000..f35694970245 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/7d31bd53bb7eb7b1f354c5f85d376390760ab16f differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/7d67ef4d0c681655d4b4e93e848d56865630390b b/third_party/libwebm/source/webm_parser/fuzzing/corpus/7d67ef4d0c681655d4b4e93e848d56865630390b new file mode 100644 index 000000000000..ca4a486f2fee Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/7d67ef4d0c681655d4b4e93e848d56865630390b differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/7db9fe869081fdc855913dd000de0d493f5d5192 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/7db9fe869081fdc855913dd000de0d493f5d5192 new file mode 100644 index 000000000000..9fa0f0a7f5d6 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/7db9fe869081fdc855913dd000de0d493f5d5192 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/7f20c1e73451c3321c30223db91b891753ef77dd b/third_party/libwebm/source/webm_parser/fuzzing/corpus/7f20c1e73451c3321c30223db91b891753ef77dd new file mode 100644 index 000000000000..7f0a6dfcaf64 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/7f20c1e73451c3321c30223db91b891753ef77dd @@ -0,0 +1 @@ +S€g‰C¶u„ ‚¡€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/7fd4d999983c3fbf22763853e90ec10b03c70b17 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/7fd4d999983c3fbf22763853e90ec10b03c70b17 new file mode 100644 index 000000000000..65e61e9def6d --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/7fd4d999983c3fbf22763853e90ec10b03c70b17 @@ -0,0 +1 @@ +S€g“M›tŽM»„S¬M»„S¬ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/80039ce7eff40359bee041d75e371b55117aad3a b/third_party/libwebm/source/webm_parser/fuzzing/corpus/80039ce7eff40359bee041d75e371b55117aad3a new file mode 100644 index 000000000000..e62a685a9077 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/80039ce7eff40359bee041d75e371b55117aad3a @@ -0,0 +1 @@ +ƒ€€€€€ˆ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/8104a007bc88a0a8d81ce1fd26d8b2333061e920 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/8104a007bc88a0a8d81ce1fd26d8b2333061e920 new file mode 100644 index 000000000000..1e6fd37be052 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/8104a007bc88a0a8d81ce1fd26d8b2333061e920 @@ -0,0 +1 @@ +S€gœC§p—E¹”¶’Ä€aT€}€€€€€€€€€€ƒèÌ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/81320c48ed6eea94712c5e8594c0799fbfe30d10 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/81320c48ed6eea94712c5e8594c0799fbfe30d10 new file mode 100644 index 000000000000..28ac48fb022f Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/81320c48ed6eea94712c5e8594c0799fbfe30d10 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/81425ca3d0afb88cc10d412dcc9795905eacd6d9 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/81425ca3d0afb88cc10d412dcc9795905eacd6d9 new file mode 100644 index 000000000000..3afdbfc40932 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/81425ca3d0afb88cc10d412dcc9795905eacd6d9 @@ -0,0 +1 @@ +Eߣÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/819b4bd08ae7d758990aea8ab9739f3cb97fd42c b/third_party/libwebm/source/webm_parser/fuzzing/corpus/819b4bd08ae7d758990aea8ab9739f3cb97fd42c new file mode 100644 index 000000000000..af77557f9058 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/819b4bd08ae7d758990aea8ab9739f3cb97fd42c differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/8206d92b710c04ce0bd706cec25fbb72014c79bf b/third_party/libwebm/source/webm_parser/fuzzing/corpus/8206d92b710c04ce0bd706cec25fbb72014c79bf new file mode 100644 index 000000000000..a1233fdeb8e4 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/8206d92b710c04ce0bd706cec25fbb72014c79bf differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/822926c528d16c0a9ca4c48a25651f6a0730d797 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/822926c528d16c0a9ca4c48a25651f6a0730d797 new file mode 100644 index 000000000000..f4269d08a4a5 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/822926c528d16c0a9ca4c48a25651f6a0730d797 @@ -0,0 +1 @@ +S€gŽC§p‰E¹†¶„VT!S€g–C§p‘E¹Ž¶@sĶ@sÄ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/82d80b6051f0750777bdc37319851741144b3671 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/82d80b6051f0750777bdc37319851741144b3671 new file mode 100644 index 000000000000..43b170b730fc --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/82d80b6051f0750777bdc37319851741144b3671 @@ -0,0 +1 @@ +S€g‹C¶u† „Ž‚è€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/830c73748baaa10c2016d04b408a7f481882cd89 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/830c73748baaa10c2016d04b408a7f481882cd89 new file mode 100644 index 000000000000..11b45e96bd0b Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/830c73748baaa10c2016d04b408a7f481882cd89 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/8315ca46618bd0771353336407396df293e8c182 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/8315ca46618bd0771353336407396df293e8c182 new file mode 100644 index 000000000000..4472080c158d --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/8315ca46618bd0771353336407396df293e8c182 @@ -0,0 +1 @@ +S€g“C¶uŽ ŒŽŠìƒÌèƒÌ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/831c152337e8b2993b8cddfde7553a8c9e64631f b/third_party/libwebm/source/webm_parser/fuzzing/corpus/831c152337e8b2993b8cddfde7553a8c9e64631f new file mode 100644 index 000000000000..53875423ab98 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/831c152337e8b2993b8cddfde7553a8c9e64631f differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/832fad0e723027e5bd74726b1722a838183dada7 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/832fad0e723027e5bd74726b1722a838183dada7 new file mode 100644 index 000000000000..3545ab8820fc --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/832fad0e723027e5bd74726b1722a838183dada7 @@ -0,0 +1 @@ +S€gTÃgŠss‡gÈ„D„ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/83b78d2ad8afd0729de45b4d9fdd765a949d8073 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/83b78d2ad8afd0729de45b4d9fdd765a949d8073 new file mode 100644 index 000000000000..5cb98fecf82c --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/83b78d2ad8afd0729de45b4d9fdd765a949d8073 @@ -0,0 +1 @@ +S€g¼C§p·E¹´¶²€ …@helloC|…lang0C~…area0C|…lang1C|C§p·E \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/84a04bf3e15345f5c992bc6732a42b95857631a7 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/84a04bf3e15345f5c992bc6732a42b95857631a7 new file mode 100644 index 000000000000..e89d0d1c79d5 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/84a04bf3e15345f5c992bc6732a42b95857631a7 @@ -0,0 +1 @@ +S€g“C¶uŽ ŒŽŠèƒÌèƒÌ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/84d3a72c434074ee0d810fb2357047efd23f58f6 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/84d3a72c434074ee0d810fb2357047efd23f58f6 new file mode 100644 index 000000000000..e22f95bb90bf Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/84d3a72c434074ee0d810fb2357047efd23f58f6 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/8659fe309298ca90f201ac7ced95b9d0de510eeb b/third_party/libwebm/source/webm_parser/fuzzing/corpus/8659fe309298ca90f201ac7ced95b9d0de510eeb new file mode 100644 index 000000000000..77449c79eacc --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/8659fe309298ca90f201ac7ced95b9d0de510eeb @@ -0,0 +1 @@ +S€gˆC¶uƒ« \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/866cf21064b9e20eded44e2e096fd9ce6185ce86 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/866cf21064b9e20eded44e2e096fd9ce6185ce86 new file mode 100644 index 000000000000..f3a4ddd54547 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/866cf21064b9e20eded44e2e096fd9ce6185ce86 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/8864c6c9319ef120d3accb7b70c32c8f5c1ebccb b/third_party/libwebm/source/webm_parser/fuzzing/corpus/8864c6c9319ef120d3accb7b70c32c8f5c1ebccb new file mode 100644 index 000000000000..d6f7c00cff5a Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/8864c6c9319ef120d3accb7b70c32c8f5c1ebccb differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/88f01cffe9972bf447a21034c45f6b943ea3ec07 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/88f01cffe9972bf447a21034c45f6b943ea3ec07 new file mode 100644 index 000000000000..97754f40b8cc Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/88f01cffe9972bf447a21034c45f6b943ea3ec07 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/88f15d430469d209b72cd098405efd15a6d18b05 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/88f15d430469d209b72cd098405efd15a6d18b05 new file mode 100644 index 000000000000..adce379ab3aa Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/88f15d430469d209b72cd098405efd15a6d18b05 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/8936b35f29084151fa3755d81030386940523c07 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/8936b35f29084151fa3755d81030386940523c07 new file mode 100644 index 000000000000..e39670b10696 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/8936b35f29084151fa3755d81030386940523c07 @@ -0,0 +1 @@ +Eߣ„Bó \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/89a42d72ffe0b23309a9da4e15b8854c1cf939ea b/third_party/libwebm/source/webm_parser/fuzzing/corpus/89a42d72ffe0b23309a9da4e15b8854c1cf939ea new file mode 100644 index 000000000000..af09ae1f35bd --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/89a42d72ffe0b23309a9da4e15b8854c1cf939ea @@ -0,0 +1 @@ +S€g‹S»k†»„³€·€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/8a0cf07d2592231bd579e4399538d9f490e3e5b9 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/8a0cf07d2592231bd579e4399538d9f490e3e5b9 new file mode 100644 index 000000000000..ce2a1368cbb9 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/8a0cf07d2592231bd579e4399538d9f490e3e5b9 @@ -0,0 +1 @@ +S€gŒT®k‡®…ჟ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/8a5d1c05f894414aa5aaa66cf901c52dfcb119a1 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/8a5d1c05f894414aa5aaa66cf901c52dfcb119a1 new file mode 100644 index 000000000000..c1bfd3baec99 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/8a5d1c05f894414aa5aaa66cf901c52dfcb119a1 @@ -0,0 +1 @@ +S€g‘T®kŒ®Šm€‡b@„P1 \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/8aa514b6e6fef8d045aa049fdb52fa8adcf722d4 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/8aa514b6e6fef8d045aa049fdb52fa8adcf722d4 new file mode 100644 index 000000000000..7d3ecf2c53b1 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/8aa514b6e6fef8d045aa049fdb52fa8adcf722d4 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/8b0dcd4400fe19cf6a268af780990f47dba08189 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/8b0dcd4400fe19cf6a268af780990f47dba08189 new file mode 100644 index 000000000000..2e19cb74506c --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/8b0dcd4400fe19cf6a268af780990f47dba08189 @@ -0,0 +1 @@ +S€g»TÃg¶ss³gÈ©È„#‡dg)„]‡egÈ„D‡(gÈ„]‡egˆ„D‡gÈ€D‡dgÈg \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/8c4655e6528071edd445715ff1559f399dc9d47c b/third_party/libwebm/source/webm_parser/fuzzing/corpus/8c4655e6528071edd445715ff1559f399dc9d47c new file mode 100644 index 000000000000..fe94617d25bd Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/8c4655e6528071edd445715ff1559f399dc9d47c differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/8c695cbcc43e37ce25194c4b61b3d87488b308a1 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/8c695cbcc43e37ce25194c4b61b3d87488b308a1 new file mode 100644 index 000000000000..6219e9f2d660 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/8c695cbcc43e37ce25194c4b61b3d87488b308a1 @@ -0,0 +1 @@ +S€g‘T®kŒ®Šm€‡b@„P1S€g”T®k®m€Šb@‡P5€GáÿS€g™T®k”®’m€b@ŒP5€P5€Ps€P5€S€g˜T®k“®‘m€Žb@„P1b@„P1S€gT®kˆ®†à„Tº \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/8c9dc3c5a839f90f29256ef8c8f1369bc7383817 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/8c9dc3c5a839f90f29256ef8c8f1369bc7383817 new file mode 100644 index 000000000000..85078ca15bc3 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/8c9dc3c5a839f90f29256ef8c8f1369bc7383817 @@ -0,0 +1 @@ +WA¢€€ˆƒ€€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/8cdcf83eb89d7e5c87cfa1b8811c95f738747a6a b/third_party/libwebm/source/webm_parser/fuzzing/corpus/8cdcf83eb89d7e5c87cfa1b8811c95f738747a6a new file mode 100644 index 000000000000..8db4eecd9151 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/8cdcf83eb89d7e5c87cfa1b8811c95f738747a6a @@ -0,0 +1 @@ +S€g‰I©f„M€! \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/8d0c6e6b3d74233685c3a2c1793d1a7b0ae2e34d b/third_party/libwebm/source/webm_parser/fuzzing/corpus/8d0c6e6b3d74233685c3a2c1793d1a7b0ae2e34d new file mode 100644 index 000000000000..b4ef3d53814a Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/8d0c6e6b3d74233685c3a2c1793d1a7b0ae2e34d differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/8d444e8b311d158f854a03ca35d2c7865cd2c46b b/third_party/libwebm/source/webm_parser/fuzzing/corpus/8d444e8b311d158f854a03ca35d2c7865cd2c46b new file mode 100644 index 000000000000..c6c2f154f45b --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/8d444e8b311d158f854a03ca35d2c7865cd2c46b @@ -0,0 +1 @@ +E£Eߣ‚ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/8dc289730cc03ecbbed57d04cdca538a4fd08059 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/8dc289730cc03ecbbed57d04cdca538a4fd08059 new file mode 100644 index 000000000000..ed9c1ee20b01 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/8dc289730cc03ecbbed57d04cdca538a4fd08059 @@ -0,0 +1 @@ +S€g“C¶uŽ ŒŽŠèƒÌè€Ì \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/8dc58cfcb396a60db921901f1b0807c4f4f37619 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/8dc58cfcb396a60db921901f1b0807c4f4f37619 new file mode 100644 index 000000000000..e256d2fab57e --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/8dc58cfcb396a60db921901f1b0807c4f4f37619 @@ -0,0 +1 @@ +€€¶€€€¶€¶€¶ÿ6€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€ÿ¶¶€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€Óÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€ÿ¶¶€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€Óÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€ÿ¶¶€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€Óÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€ÿ¶¶€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€Óÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿJIII|¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€³ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€wÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶¶€¶ÿ¶€m¶ÿ¶€¶ÿ¶¶®®Ý€¶ÿ¶€¶ÿ¶€¶€µ¶€¶Œÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€å¶€¶€¶ÿ¶€Eߣ¶€¶À¶ÿ¶€m¶ÿ¶€¶ÿ¶¶®®Ý€¶ÿ¶€¶ÿ¶€¶€µ¶€¶Œÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/8e05be75b7c14c463af277559dc8ea7841a733c8 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/8e05be75b7c14c463af277559dc8ea7841a733c8 new file mode 100644 index 000000000000..caff0f1afc14 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/8e05be75b7c14c463af277559dc8ea7841a733c8 @@ -0,0 +1 @@ +S€gT®kŠ®ˆá†µ„@ÉÛ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/8e7eef00a7a6719e77544b57d1d98ff83a37e55a b/third_party/libwebm/source/webm_parser/fuzzing/corpus/8e7eef00a7a6719e77544b57d1d98ff83a37e55a new file mode 100644 index 000000000000..52c1ec41569e --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/8e7eef00a7a6719e77544b57d1d98ff83a37e55a @@ -0,0 +1 @@ +S€gŠT®k…®ƒ¹ÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/8ed6ef9af5555ce4ff12b23139add9621e7ad930 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/8ed6ef9af5555ce4ff12b23139add9621e7ad930 new file mode 100644 index 000000000000..007a5000f092 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/8ed6ef9af5555ce4ff12b23139add9621e7ad930 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/8f39f83b71d49805a451f81a5a451f5f3d74927d b/third_party/libwebm/source/webm_parser/fuzzing/corpus/8f39f83b71d49805a451f81a5a451f5f3d74927d new file mode 100644 index 000000000000..aea2062210e3 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/8f39f83b71d49805a451f81a5a451f5f3d74927d differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/8f403efbef079f1775b63bcf1061983e4c5d2162 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/8f403efbef079f1775b63bcf1061983e4c5d2162 new file mode 100644 index 000000000000..7a0e07094e40 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/8f403efbef079f1775b63bcf1061983e4c5d2162 @@ -0,0 +1 @@ +S€g”T®k®m€Šb@‡P5„Gâ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/8f8f956eaaf8f7f5e65002be888b946218f0f7ce b/third_party/libwebm/source/webm_parser/fuzzing/corpus/8f8f956eaaf8f7f5e65002be888b946218f0f7ce new file mode 100644 index 000000000000..7ebec698d390 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/8f8f956eaaf8f7f5e65002be888b946218f0f7ce @@ -0,0 +1 @@ +€€¶€€€¶€¶€¶ÿ6€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€ÿ¶¶€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ„€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€ÿ¶¶€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€!ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€ÿ¶¶€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€ÿ¶¶€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€!ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€ÿ¶¶€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ„€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€ÿ¶¶€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€!ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶Š¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿJIII|¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶Š¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿJIII|¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶¶ÿ€¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€ÿ¶¶€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ„€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€ÿ¶¶€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€!ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶Š¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿJIII|¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶Š¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿJIII|¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶¶ÿ€¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€ÿ¶¶€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ„€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿJIII|¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€wÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶¶€¶ÿ¶€m¶ÿ¶€¶ÿ¶¶®®Ý€¶ÿ¶€¶ÿ¶€¶€µ¶€¶Œÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€å¶€¶€¶ÿ¶€Eߣ¶€¶À¶ÿ¶€m¶ÿ¶€¶ÿ¶¶®®Ý€¶ÿ¶€¶ÿ¶€¶€µ¶€¶Œÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/90a03241b5cc656b7c2a4ef55664b0320fa3bd43 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/90a03241b5cc656b7c2a4ef55664b0320fa3bd43 new file mode 100644 index 000000000000..ac884827ed53 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/90a03241b5cc656b7c2a4ef55664b0320fa3bd43 @@ -0,0 +1 @@ +S€g”C¶u u¡Š¦ƒî¦€¦€î \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/925a91e7c25a43d9da8b63eba51ed66a52d833aa b/third_party/libwebm/source/webm_parser/fuzzing/corpus/925a91e7c25a43d9da8b63eba51ed66a52d833aa new file mode 100644 index 000000000000..8eac37e5ef74 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/925a91e7c25a43d9da8b63eba51ed66a52d833aa differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/92de5c217802ec24886240188dca293325eb17c9 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/92de5c217802ec24886240188dca293325eb17c9 new file mode 100644 index 000000000000..8237f0b5241e --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/92de5c217802ec24886240188dca293325eb17c9 @@ -0,0 +1 @@ +S€g‹T®k†®„Sn! \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/939da66e1fc8bb9854865066ee47b6ac4b933aa9 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/939da66e1fc8bb9854865066ee47b6ac4b933aa9 new file mode 100644 index 000000000000..f5179b146947 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/939da66e1fc8bb9854865066ee47b6ac4b933aa9 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/93a91331e7c3c060f461ae1f22e2bbf4747ffe33 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/93a91331e7c3c060f461ae1f22e2bbf4747ffe33 new file mode 100644 index 000000000000..1b2868432336 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/93a91331e7c3c060f461ae1f22e2bbf4747ffe33 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/94f6dfc499cbf2e84ffe1d69cb751ada9f2f2e3a b/third_party/libwebm/source/webm_parser/fuzzing/corpus/94f6dfc499cbf2e84ffe1d69cb751ada9f2f2e3a new file mode 100644 index 000000000000..30a5c63cef53 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/94f6dfc499cbf2e84ffe1d69cb751ada9f2f2e3a @@ -0,0 +1 @@ +S€gŠC¶u… ƒ› \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/9539fef8ffb9f7c542061f1af1f3f98e9a714cc3 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/9539fef8ffb9f7c542061f1af1f3f98e9a714cc3 new file mode 100644 index 000000000000..0ea96501d095 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/9539fef8ffb9f7c542061f1af1f3f98e9a714cc3 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/953c9a616ea56067225c88fccc6423496f2501a6 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/953c9a616ea56067225c88fccc6423496f2501a6 new file mode 100644 index 000000000000..249824c23f9a Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/953c9a616ea56067225c88fccc6423496f2501a6 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/95a60268c555a77c1010d75bb44142af47635486 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/95a60268c555a77c1010d75bb44142af47635486 new file mode 100644 index 000000000000..a95f40a96121 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/95a60268c555a77c1010d75bb44142af47635486 @@ -0,0 +1 @@ +€€¶€€€¶€¶€¶ÿ6€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€Óÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€ÿ¶¶€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€Óÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€Óÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€ÿ¶¶€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€Óÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€ÿ¶¶€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€ÿ¶¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€ÿ¶¶€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€ÿ¶¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿJIII|¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€³ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€wÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/95e410025b965cf6ab2e8e2d3559efbe71c1a972 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/95e410025b965cf6ab2e8e2d3559efbe71c1a972 new file mode 100644 index 000000000000..8eddf69a2e5f Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/95e410025b965cf6ab2e8e2d3559efbe71c1a972 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/9671f253d1eb7cd504a5617058ce4c01a80c897e b/third_party/libwebm/source/webm_parser/fuzzing/corpus/9671f253d1eb7cd504a5617058ce4c01a80c897e new file mode 100644 index 000000000000..f0b837c72389 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/9671f253d1eb7cd504a5617058ce4c01a80c897e differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/9698d3424f1581a6bbb66c764f14c95a74b87675 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/9698d3424f1581a6bbb66c764f14c95a74b87675 new file mode 100644 index 000000000000..3aedc3202fae Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/9698d3424f1581a6bbb66c764f14c95a74b87675 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/96f7f38de1f8601311733984cf51cec35500dabe b/third_party/libwebm/source/webm_parser/fuzzing/corpus/96f7f38de1f8601311733984cf51cec35500dabe new file mode 100644 index 000000000000..1230f4cafdee --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/96f7f38de1f8601311733984cf51cec35500dabe @@ -0,0 +1 @@ +Uª ÿM \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/970ab6333aa5ccf8c2dc14bb56814f7bb4303b94 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/970ab6333aa5ccf8c2dc14bb56814f7bb4303b94 new file mode 100644 index 000000000000..cf0c884ea028 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/970ab6333aa5ccf8c2dc14bb56814f7bb4303b94 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/98978113d2116dc4bdbb10265fa32bd95230bdb6 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/98978113d2116dc4bdbb10265fa32bd95230bdb6 new file mode 100644 index 000000000000..0da58250726b --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/98978113d2116dc4bdbb10265fa32bd95230bdb6 @@ -0,0 +1 @@ +S€g”C¶u u¡Š¦ƒî¦ƒîS€gC¶uŠ ˆu¡…¦ƒ¥!S€g”C¶u u¡Š¦ƒî¦ƒîS€gC¶uŠ ˆu¡…¦ƒ¥! \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/989e2872d2a34de543f23c5061db68212d8258f7 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/989e2872d2a34de543f23c5061db68212d8258f7 new file mode 100644 index 000000000000..3430234146c1 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/989e2872d2a34de543f23c5061db68212d8258f7 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/98ca9a00ad571c4454fce709d5405e5aca2a363c b/third_party/libwebm/source/webm_parser/fuzzing/corpus/98ca9a00ad571c4454fce709d5405e5aca2a363c new file mode 100644 index 000000000000..938e0bc5115c --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/98ca9a00ad571c4454fce709d5405e5aca2a363c @@ -0,0 +1 @@ +Eߣ„Bóÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/9965361765a4151902ec04fb21d9247b3a5ed10d b/third_party/libwebm/source/webm_parser/fuzzing/corpus/9965361765a4151902ec04fb21d9247b3a5ed10d new file mode 100644 index 000000000000..6ec73d46382f --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/9965361765a4151902ec04fb21d9247b3a5ed10d @@ -0,0 +1 @@ +S€g‘T®kŒ®Šàˆ#ƒã„@ÉÛ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/99d6fe94a50faa50db9d7eb38d74bc3cc8417dc1 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/99d6fe94a50faa50db9d7eb38d74bc3cc8417dc1 new file mode 100644 index 000000000000..0dcb93ea81d8 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/99d6fe94a50faa50db9d7eb38d74bc3cc8417dc1 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/9a6869cec3dc84f2051bfaf0ee0d3552aa221f89 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/9a6869cec3dc84f2051bfaf0ee0d3552aa221f89 new file mode 100644 index 000000000000..32ad695ce24e Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/9a6869cec3dc84f2051bfaf0ee0d3552aa221f89 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/9cc1f26de1e3a7df8c7c03b95ff73ce9709c85f1 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/9cc1f26de1e3a7df8c7c03b95ff73ce9709c85f1 new file mode 100644 index 000000000000..5178754240ca Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/9cc1f26de1e3a7df8c7c03b95ff73ce9709c85f1 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/9cc5b552abbd551485135fa87eab739a0a784057 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/9cc5b552abbd551485135fa87eab739a0a784057 new file mode 100644 index 000000000000..3a952191cdba Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/9cc5b552abbd551485135fa87eab739a0a784057 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/9cca361865a4fbff75abdbb79c1e91706780576c b/third_party/libwebm/source/webm_parser/fuzzing/corpus/9cca361865a4fbff75abdbb79c1e91706780576c new file mode 100644 index 000000000000..67357290814e --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/9cca361865a4fbff75abdbb79c1e91706780576c @@ -0,0 +1 @@ +S€gŽT®k‰®‡à…°ƒ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/9d8e99f07604d6cb05ef613d41cbfb93b2aff787 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/9d8e99f07604d6cb05ef613d41cbfb93b2aff787 new file mode 100644 index 000000000000..96aa349010ad --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/9d8e99f07604d6cb05ef613d41cbfb93b2aff787 @@ -0,0 +1 @@ +S€gŒT®k‡®…àƒšÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/9ecd61eaf2681a882473247a603b9f30c2663d49 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/9ecd61eaf2681a882473247a603b9f30c2663d49 new file mode 100644 index 000000000000..256c70d00542 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/9ecd61eaf2681a882473247a603b9f30c2663d49 @@ -0,0 +1 @@ +S€g“C¶uŽ ŒŽŠèÿÌèƒÌ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/9f0a3b7c0814b4f80c0745161c8769f63098981b b/third_party/libwebm/source/webm_parser/fuzzing/corpus/9f0a3b7c0814b4f80c0745161c8769f63098981b new file mode 100644 index 000000000000..fe2403bb5bd5 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/9f0a3b7c0814b4f80c0745161c8769f63098981b differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/9f711c29ccf3f54d44000d7ef6299585674be288 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/9f711c29ccf3f54d44000d7ef6299585674be288 new file mode 100644 index 000000000000..2f17a8848884 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/9f711c29ccf3f54d44000d7ef6299585674be288 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/9fae60819c28d4fcc88a6a1b93dcf69b4e458203 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/9fae60819c28d4fcc88a6a1b93dcf69b4e458203 new file mode 100644 index 000000000000..9194d9d28c18 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/9fae60819c28d4fcc88a6a1b93dcf69b4e458203 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/a02431cf7c501a5b368c91e41283419d8fa9fb03 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/a02431cf7c501a5b368c91e41283419d8fa9fb03 new file mode 100644 index 000000000000..17706ff6b3fc Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/a02431cf7c501a5b368c91e41283419d8fa9fb03 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/a0ac6c3c83817637bbbcb11a5106c57aa6654afb b/third_party/libwebm/source/webm_parser/fuzzing/corpus/a0ac6c3c83817637bbbcb11a5106c57aa6654afb new file mode 100644 index 000000000000..a5d2ab48564f Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/a0ac6c3c83817637bbbcb11a5106c57aa6654afb differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/a15fdfa620d19a92d9eaa9f3f13010e53f902796 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/a15fdfa620d19a92d9eaa9f3f13010e53f902796 new file mode 100644 index 000000000000..d5b108f3cfec --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/a15fdfa620d19a92d9eaa9f3f13010e53f902796 @@ -0,0 +1 @@ +S€g½C§p¸E¹µ¶@…@B€@…XC¶@sĶ@sĶ@sÄ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/a18e76ae792a054c2f6d0d01e0e78d58678b35e3 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/a18e76ae792a054c2f6d0d01e0e78d58678b35e3 new file mode 100644 index 000000000000..135e70d3231c --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/a18e76ae792a054c2f6d0d01e0e78d58678b35e3 @@ -0,0 +1 @@ +S€gŠT®k…®ƒ†! \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/a19d04f18f574e561d793ac0dfcffe2b38183eb1 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/a19d04f18f574e561d793ac0dfcffe2b38183eb1 new file mode 100644 index 000000000000..cb84077f43f8 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/a19d04f18f574e561d793ac0dfcffe2b38183eb1 @@ -0,0 +1 @@ +"µœŸ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/a26fb85be3d2bb8a2360bb4d9533a1651bd12d99 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/a26fb85be3d2bb8a2360bb4d9533a1651bd12d99 new file mode 100644 index 000000000000..6fb743bb3862 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/a26fb85be3d2bb8a2360bb4d9533a1651bd12d99 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/a2e860fae30005a9e75b61f54f3d019c44090fcc b/third_party/libwebm/source/webm_parser/fuzzing/corpus/a2e860fae30005a9e75b61f54f3d019c44090fcc new file mode 100644 index 000000000000..124e7d63bc69 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/a2e860fae30005a9e75b61f54f3d019c44090fcc @@ -0,0 +1 @@ +D…€ðVT€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/a3071bfcb7b2fd3c4286ea42e1f7940754b55697 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/a3071bfcb7b2fd3c4286ea42e1f7940754b55697 new file mode 100644 index 000000000000..f16be68912be Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/a3071bfcb7b2fd3c4286ea42e1f7940754b55697 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/a4ac408fb9d6def070ad3a76312ca092863048e5 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/a4ac408fb9d6def070ad3a76312ca092863048e5 new file mode 100644 index 000000000000..4e3bc519eef7 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/a4ac408fb9d6def070ad3a76312ca092863048e5 @@ -0,0 +1 @@ +Ý \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/a4fafc117cbfde8c240deccc8997c7966d9109ba b/third_party/libwebm/source/webm_parser/fuzzing/corpus/a4fafc117cbfde8c240deccc8997c7966d9109ba new file mode 100644 index 000000000000..79af6dadb3c5 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/a4fafc117cbfde8c240deccc8997c7966d9109ba @@ -0,0 +1 @@ +S€gŒS»k‡»…³‚ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/a59ffb5f6122e45136352585d3b53294a71346d0 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/a59ffb5f6122e45136352585d3b53294a71346d0 new file mode 100644 index 000000000000..b848f4362bf9 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/a59ffb5f6122e45136352585d3b53294a71346d0 @@ -0,0 +1 @@ +S€g‘C¶uŒ Š¡‡¦…îƒ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/a5b3a3c48727c26dfd625f247069d2cdbfa031f0 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/a5b3a3c48727c26dfd625f247069d2cdbfa031f0 new file mode 100644 index 000000000000..89ee740104be Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/a5b3a3c48727c26dfd625f247069d2cdbfa031f0 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/a5c829fbcd9fd760bc55bc8ab6901b8d401b65f6 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/a5c829fbcd9fd760bc55bc8ab6901b8d401b65f6 new file mode 100644 index 000000000000..13dc20007d8c --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/a5c829fbcd9fd760bc55bc8ab6901b8d401b65f6 @@ -0,0 +1 @@ +S€gŠT®k…®ƒƒ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/a5fbbce038cad4f5e0c0f97fa69ebc3601123e5c b/third_party/libwebm/source/webm_parser/fuzzing/corpus/a5fbbce038cad4f5e0c0f97fa69ebc3601123e5c new file mode 100644 index 000000000000..ec1eabd371d4 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/a5fbbce038cad4f5e0c0f97fa69ebc3601123e5c differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/a6e57b33e7a219168280e51bc98a44de40f0f9ca b/third_party/libwebm/source/webm_parser/fuzzing/corpus/a6e57b33e7a219168280e51bc98a44de40f0f9ca new file mode 100644 index 000000000000..d8f16c238737 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/a6e57b33e7a219168280e51bc98a44de40f0f9ca @@ -0,0 +1 @@ +S€g‹S»k†»„·€·€S€g‹S»k†»„·€·€Eߣˆb‚@webE \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/a78afe9e4e9f02a10ebadac64171ad49749a6965 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/a78afe9e4e9f02a10ebadac64171ad49749a6965 new file mode 100644 index 000000000000..1b8c6413d584 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/a78afe9e4e9f02a10ebadac64171ad49749a6965 @@ -0,0 +1 @@ +S€gˆM›tƒM»€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/a823a019c0b19c97a1d35722cd843109ab016c17 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/a823a019c0b19c97a1d35722cd843109ab016c17 new file mode 100644 index 000000000000..eae13196a63d --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/a823a019c0b19c97a1d35722cd843109ab016c17 @@ -0,0 +1,22 @@ +Eߣ€S€g †¡C§p †šE¹ †•¶ †‘¶ †¶ †‰¶ †…¶ †¶ †}¶ †y¶ †u¶ †q¶ †m¶ †i¶ †e¶ †a¶ †]¶ †Y¶ †U¶ †Q¶ †M¶ †I¶ †E¶ †A¶ †=¶ †9¶ †5¶ †1¶ †-¶ †)¶ †%¶ †!¶ †¶ †¶ †¶ †¶ † ¶ † ¶ †¶ †¶ …ý¶ …ù¶ …õ¶ …ñ¶ …í¶ …é¶ …å¶ …ᶠ…ݶ …Ù¶ …Õ¶ …Ѷ …Ͷ …ɶ …Ŷ …Á¶ …½¶ …¹¶ …µ¶ …±¶ …­¶ …©¶ …¥¶ …¡¶ …¶ …™¶ …•¶ …‘¶ …¶ …‰¶ ……¶ …¶ …}¶ …y¶ …u¶ …q¶ …m¶ …i¶ …e¶ …a¶ …]¶ …Y¶ …U¶ …Q¶ …M¶ …I¶ …E¶ …A¶ …=¶ …9¶ …5¶ …1¶ …-¶ …)¶ …%¶ …!¶ …¶ …¶ …¶ …¶ … ¶ … ¶ …¶ …¶ „ý¶ „ù¶ „õ¶ „ñ¶ „í¶ „é¶ „å¶ „ᶠ„ݶ „Ù¶ „Õ¶ „Ѷ „Ͷ „ɶ „Ŷ „Á¶ „½¶ „¹¶ „µ¶ „±¶ „­¶ „©¶ „¥¶ „¡¶ „¶ „™¶ „•¶ „‘¶ „¶ „‰¶ „…¶ „¶ „}¶ „y¶ „u¶ „q¶ „m¶ „i¶ „e¶ „a¶ „]¶ „Y¶ „U¶ „Q¶ „M¶ „I¶ „E¶ „A¶ „=¶ „9¶ „5¶ „1¶ „-¶ „)¶ „%¶ „!¶ „¶ „¶ „¶ „¶ „ ¶ „ ¶ „¶ „¶ ƒý¶ ƒù¶ ƒõ¶ ƒñ¶ ƒí¶ ƒé¶ ƒå¶ ƒá¶ ƒÝ¶ ƒÙ¶ ƒÕ¶ ƒÑ¶ ƒÍ¶ ƒÉ¶ ƒÅ¶ ƒÁ¶ ƒ½¶ ƒ¹¶ ƒµ¶ ƒ±¶ ƒ­¶ ƒ©¶ ƒ¥¶ ƒ¡¶ ƒ¶ ƒ™¶ ƒ•¶ ƒ‘¶ ƒ¶ ƒ‰¶ ƒ…¶ ƒ¶ ƒ}¶ ƒy¶ ƒu¶ ƒq¶ ƒm¶ ƒi¶ ƒe¶ ƒa¶ ƒ]¶ ƒY¶ ƒU¶ ƒQ¶ ƒM¶ ƒI¶ ƒE¶ ƒA¶ ƒ=¶ ƒ9¶ ƒ5¶ ƒ1¶ ƒ-¶ ƒ)¶ ƒ%¶ ƒ!¶ ƒ¶ ƒ¶ ƒ¶ ƒ¶ ƒ ¶ ƒ ¶ ƒ¶ ƒ¶ ‚ý¶ ‚ù¶ ‚õ¶ ‚ñ¶ ‚í¶ ‚é¶ ‚å¶ ‚ᶠ‚ݶ ‚Ù¶ ‚Õ¶ ‚Ѷ ‚Ͷ ‚ɶ ‚Ŷ ‚Á¶ ‚½¶ ‚¹¶ ‚µ¶ ‚±¶ ‚­¶ ‚©¶ ‚¥¶ ‚¡¶ ‚¶ ‚™¶ ‚•¶ ‚‘¶ ‚¶ ‚‰¶ ‚…¶ ‚¶ ‚}¶ ‚y¶ ‚u¶ ‚q¶ ‚m¶ ‚i¶ ‚e¶ ‚a¶ ‚]¶ ‚Y¶ ‚U¶ ‚Q¶ ‚M¶ ‚I¶ ‚E¶ ‚A¶ ‚=¶ ‚9¶ ‚5¶ ‚1¶ ‚-¶ ‚)¶ ‚%¶ ‚!¶ ‚¶ ‚¶ ‚¶ ‚¶ ‚ ¶ ‚ ¶ ‚¶ ‚¶ ý¶ ù¶ õ¶ ñ¶ í¶ é¶ å¶ á¶ Ý¶ Ù¶ Õ¶ Ѷ Ͷ ɶ Ŷ Á¶ ½¶ ¹¶ µ¶ ±¶ ­¶ ©¶ ¥¶ ¡¶ ¶ ™¶ •¶ ‘¶ ¶ ‰¶ …¶ ¶ }¶ y¶ u¶ q¶ m¶ i¶ e¶ a¶ ]¶ Y¶ U¶ Q¶ M¶ I¶ E¶ A¶ =¶ 9¶ 5¶ 1¶ -¶ )¶ %¶ !¶ ¶ ¶ ¶ ¶ ¶ ¶ ¶ ¶ €ý¶ €ù¶ €õ¶ €ñ¶ €í¶ €é¶ €å¶ €á¶ €Ý¶ €Ù¶ €Õ¶ €Ñ¶ €Í¶ €É¶ €Å¶ €Á¶ €½¶ €¹¶ €µ¶ €±¶ €­¶ €©¶ €¥¶ €¡¶ €¶ €™¶ €•¶ €‘¶ €¶ €‰¶ €…¶ €¶ €}¶ €y¶ €u¶ €q¶ €m¶ €i¶ €e¶ €a¶ €]¶ €Y¶ €U¶ €Q¶ €M¶ €I¶ €E¶ €A¶ €=¶ €9¶ €5¶ €1¶ €-¶ €)¶ €%¶ €!¶ €¶ €¶ €¶ €¶ € ¶ € ¶ €¶ €¶ ý¶ ù¶ õ¶ ñ¶ í¶ é¶ å¶ ᶠݶ Ù¶ Õ¶ Ѷ Ͷ ɶ Ŷ Á¶ ½¶ ¹¶ µ¶ ±¶ ­¶ ©¶ ¥¶ ¡¶ ¶ ™¶ •¶ ‘¶ ¶ ‰¶ …¶ ¶ }¶ y¶ u¶ q¶ m¶ i¶ e¶ a¶ ]¶ Y¶ U¶ Q¶ M¶ I¶ E¶ A¶ =¶ 9¶ 5¶ 1¶ -¶ )¶ %¶ !¶ ¶ ¶ ¶ ¶  ¶  ¶ ¶ ¶ ~ý¶ ~ù¶ ~õ¶ ~ñ¶ ~í¶ ~é¶ ~å¶ ~ᶠ~ݶ ~Ù¶ ~Õ¶ ~Ѷ ~Ͷ ~ɶ ~Ŷ ~Á¶ ~½¶ ~¹¶ ~µ¶ ~±¶ ~­¶ ~©¶ ~¥¶ ~¡¶ ~¶ ~™¶ ~•¶ ~‘¶ ~¶ ~‰¶ ~…¶ ~¶ ~}¶ ~y¶ ~u¶ ~q¶ ~m¶ ~i¶ ~e¶ ~a¶ ~]¶ ~Y¶ ~U¶ ~Q¶ ~M¶ ~I¶ ~E¶ ~A¶ ~=¶ ~9¶ ~5¶ ~1¶ ~-¶ ~)¶ ~%¶ ~!¶ ~¶ ~¶ ~¶ ~¶ ~ ¶ ~ ¶ ~¶ ~¶ }ý¶ }ù¶ }õ¶ }ñ¶ }í¶ }é¶ }å¶ }ᶠ}ݶ }Ù¶ }Õ¶ }Ѷ }Ͷ }ɶ }Ŷ }Á¶ }½¶ }¹¶ }µ¶ }±¶ }­¶ }©¶ }¥¶ }¡¶ }¶ }™¶ }•¶ }‘¶ }¶ }‰¶ }…¶ }¶ }}¶ }y¶ }u¶ }q¶ }m¶ }i¶ }e¶ }a¶ }]¶ }Y¶ }U¶ }Q¶ }M¶ }I¶ }E¶ }A¶ }=¶ }9¶ }5¶ }1¶ }-¶ })¶ }%¶ }!¶ }¶ }¶ }¶ }¶ } ¶ } ¶ }¶ }¶ |ý¶ |ù¶ |õ¶ |ñ¶ |í¶ |é¶ |å¶ |ᶠ|ݶ |Ù¶ |Õ¶ |Ѷ |Ͷ |ɶ |Ŷ |Á¶ |½¶ |¹¶ |µ¶ |±¶ |­¶ |©¶ |¥¶ |¡¶ |¶ |™¶ |•¶ |‘¶ |¶ |‰¶ |…¶ |¶ |}¶ |y¶ |u¶ |q¶ |m¶ |i¶ |e¶ |a¶ |]¶ |Y¶ |U¶ |Q¶ |M¶ |I¶ |E¶ |A¶ |=¶ |9¶ |5¶ |1¶ |-¶ |)¶ |%¶ |!¶ |¶ |¶ |¶ |¶ | ¶ | ¶ |¶ |¶ {ý¶ {ù¶ {õ¶ {ñ¶ {í¶ {é¶ {å¶ {ᶠ{ݶ {Ù¶ {Õ¶ {Ѷ {Ͷ {ɶ {Ŷ {Á¶ {½¶ {¹¶ {µ¶ {±¶ {­¶ {©¶ {¥¶ {¡¶ {¶ {™¶ {•¶ {‘¶ {¶ {‰¶ {…¶ {¶ {}¶ {y¶ {u¶ {q¶ {m¶ {i¶ {e¶ {a¶ {]¶ {Y¶ {U¶ {Q¶ {M¶ {I¶ {E¶ {A¶ {=¶ {9¶ {5¶ {1¶ {-¶ {)¶ {%¶ {!¶ {¶ {¶ {¶ {¶ { ¶ { ¶ {¶ {¶ zý¶ zù¶ zõ¶ zñ¶ zí¶ zé¶ zå¶ zᶠzݶ zÙ¶ zÕ¶ zѶ zͶ zɶ zŶ zÁ¶ z½¶ z¹¶ zµ¶ z±¶ z­¶ z©¶ z¥¶ z¡¶ z¶ z™¶ z•¶ z‘¶ z¶ z‰¶ z…¶ z¶ z}¶ zy¶ zu¶ zq¶ zm¶ zi¶ ze¶ za¶ z]¶ zY¶ zU¶ zQ¶ zM¶ zI¶ zE¶ zA¶ z=¶ z9¶ z5¶ z1¶ z-¶ z)¶ z%¶ z!¶ z¶ z¶ z¶ z¶ z ¶ z ¶ z¶ z¶ yý¶ yù¶ yõ¶ yñ¶ yí¶ yé¶ yå¶ yᶠyݶ yÙ¶ yÕ¶ yѶ yͶ yɶ yŶ yÁ¶ y½¶ y¹¶ yµ¶ y±¶ y­¶ y©¶ y¥¶ y¡¶ y¶ y™¶ y•¶ y‘¶ y¶ y‰¶ y…¶ y¶ y}¶ yy¶ yu¶ yq¶ ym¶ yi¶ ye¶ ya¶ y]¶ yY¶ yU¶ yQ¶ yM¶ yI¶ yE¶ yA¶ y=¶ y9¶ y5¶ y1¶ y-¶ y)¶ y%¶ y!¶ y¶ y¶ y¶ y¶ y ¶ y ¶ y¶ y¶ xý¶ xù¶ xõ¶ xñ¶ xí¶ xé¶ xå¶ xᶠxݶ xÙ¶ xÕ¶ xѶ xͶ xɶ xŶ xÁ¶ x½¶ x¹¶ xµ¶ x±¶ x­¶ x©¶ x¥¶ x¡¶ x¶ x™¶ x•¶ x‘¶ x¶ x‰¶ x…¶ x¶ x}¶ xy¶ xu¶ xq¶ xm¶ xi¶ xe¶ xa¶ x]¶ xY¶ xU¶ xQ¶ xM¶ xI¶ xE¶ xA¶ x=¶ x9¶ x5¶ x1¶ x-¶ x)¶ x%¶ x!¶ x¶ x¶ x¶ x¶ x ¶ x ¶ x¶ x¶ wý¶ wù¶ wõ¶ wñ¶ wí¶ wé¶ wå¶ wᶠwݶ wÙ¶ wÕ¶ wѶ wͶ wɶ wŶ wÁ¶ w½¶ w¹¶ wµ¶ w±¶ w­¶ w©¶ w¥¶ w¡¶ w¶ w™¶ w•¶ w‘¶ w¶ w‰¶ w…¶ w¶ w}¶ wy¶ wu¶ wq¶ wm¶ wi¶ we¶ wa¶ w]¶ wY¶ wU¶ wQ¶ wM¶ wI¶ wE¶ wA¶ w=¶ w9¶ w5¶ w1¶ w-¶ w)¶ w%¶ w!¶ w¶ w¶ w¶ w¶ w ¶ w ¶ w¶ w¶ vý¶ vù¶ võ¶ vñ¶ ví¶ vé¶ vå¶ vᶠvݶ vÙ¶ vÕ¶ vѶ vͶ vɶ vŶ vÁ¶ v½¶ v¹¶ vµ¶ v±¶ v­¶ v©¶ v¥¶ v¡¶ v¶ v™¶ v•¶ v‘¶ v¶ v‰¶ v…¶ v¶ v}¶ vy¶ vu¶ vq¶ vm¶ vi¶ ve¶ va¶ v]¶ vY¶ vU¶ vQ¶ vM¶ vI¶ vE¶ vA¶ v=¶ v9¶ v5¶ v1¶ v-¶ v)¶ v%¶ v!¶ v¶ v¶ v¶ v¶ v ¶ v ¶ v¶ v¶ uý¶ uù¶ uõ¶ uñ¶ uí¶ ué¶ uå¶ uᶠuݶ uÙ¶ uÕ¶ uѶ uͶ uɶ uŶ uÁ¶ u½¶ u¹¶ uµ¶ u±¶ u­¶ u©¶ u¥¶ u¡¶ u¶ u™¶ u•¶ u‘¶ u¶ u‰¶ u…¶ u¶ u}¶ uy¶ uu¶ uq¶ um¶ ui¶ ue¶ ua¶ u]¶ uY¶ uU¶ uQ¶ uM¶ uI¶ uE¶ uA¶ u=¶ u9¶ u5¶ u1¶ u-¶ u)¶ u%¶ u!¶ u¶ u¶ u¶ u¶ u ¶ u ¶ u¶ u¶ tý¶ tù¶ tõ¶ tñ¶ tí¶ té¶ tå¶ tᶠtݶ tÙ¶ tÕ¶ tѶ tͶ tɶ tŶ tÁ¶ t½¶ t¹¶ tµ¶ t±¶ t­¶ t©¶ t¥¶ t¡¶ t¶ t™¶ t•¶ t‘¶ t¶ t‰¶ t…¶ t¶ t}¶ ty¶ tu¶ tq¶ tm¶ ti¶ te¶ ta¶ t]¶ tY¶ tU¶ tQ¶ tM¶ tI¶ tE¶ tA¶ t=¶ t9¶ t5¶ t1¶ t-¶ t)¶ t%¶ t!¶ t¶ t¶ t¶ t¶ t ¶ t ¶ t¶ t¶ sý¶ sù¶ sõ¶ sñ¶ sí¶ sé¶ så¶ sᶠsݶ sÙ¶ sÕ¶ sѶ sͶ sɶ sŶ sÁ¶ s½¶ s¹¶ sµ¶ s±¶ s­¶ s©¶ s¥¶ s¡¶ s¶ s™¶ s•¶ s‘¶ s¶ s‰¶ s…¶ s¶ s}¶ sy¶ su¶ sq¶ sm¶ si¶ se¶ sa¶ s]¶ sY¶ sU¶ sQ¶ sM¶ sI¶ sE¶ sA¶ s=¶ s9¶ s5¶ s1¶ s-¶ s)¶ s%¶ s!¶ s¶ s¶ s¶ s¶ s ¶ s ¶ s¶ s¶ rý¶ rù¶ rõ¶ rñ¶ rí¶ ré¶ rå¶ rᶠrݶ rÙ¶ rÕ¶ rѶ rͶ rɶ rŶ rÁ¶ r½¶ r¹¶ rµ¶ r±¶ r­¶ r©¶ r¥¶ r¡¶ r¶ r™¶ r•¶ r‘¶ r¶ r‰¶ r…¶ r¶ r}¶ ry¶ ru¶ rq¶ rm¶ ri¶ re¶ ra¶ r]¶ rY¶ rU¶ rQ¶ rM¶ rI¶ rE¶ rA¶ r=¶ r9¶ r5¶ r1¶ r-¶ r)¶ r%¶ r!¶ r¶ r¶ r¶ r¶ r ¶ r ¶ r¶ r¶ qý¶ qù¶ qõ¶ qñ¶ qí¶ qé¶ qå¶ qᶠqݶ qÙ¶ qÕ¶ qѶ qͶ qɶ qŶ qÁ¶ q½¶ q¹¶ qµ¶ q±¶ q­¶ q©¶ q¥¶ q¡¶ q¶ q™¶ q•¶ q‘¶ q¶ q‰¶ q…¶ q¶ q}¶ qy¶ qu¶ qq¶ qm¶ qi¶ qe¶ qa¶ q]¶ qY¶ qU¶ qQ¶ qM¶ qI¶ qE¶ qA¶ q=¶ q9¶ q5¶ q1¶ q-¶ q)¶ q%¶ q!¶ q¶ q¶ q¶ q¶ q ¶ q ¶ q¶ q¶ pý¶ pù¶ põ¶ pñ¶ pí¶ pé¶ på¶ pᶠpݶ pÙ¶ pÕ¶ pѶ pͶ pɶ pŶ pÁ¶ p½¶ p¹¶ pµ¶ p±¶ p­¶ p©¶ p¥¶ p¡¶ p¶ p™¶ p•¶ p‘¶ p¶ p‰¶ p…¶ p¶ p}¶ py¶ pu¶ pq¶ pm¶ pi¶ pe¶ pa¶ p]¶ pY¶ pU¶ pQ¶ pM¶ pI¶ pE¶ pA¶ p=¶ p9¶ p5¶ p1¶ p-¶ p)¶ p%¶ p!¶ p¶ p¶ p¶ p¶ p ¶ p ¶ p¶ p¶ oý¶ où¶ oõ¶ oñ¶ oí¶ oé¶ oå¶ oᶠoݶ oÙ¶ oÕ¶ oѶ oͶ oɶ oŶ oÁ¶ o½¶ o¹¶ oµ¶ o±¶ o­¶ o©¶ o¥¶ o¡¶ o¶ o™¶ o•¶ o‘¶ o¶ o‰¶ o…¶ o¶ o}¶ oy¶ ou¶ oq¶ om¶ oi¶ oe¶ oa¶ o]¶ oY¶ oU¶ oQ¶ oM¶ oI¶ oE¶ oA¶ o=¶ o9¶ o5¶ o1¶ o-¶ o)¶ o%¶ o!¶ o¶ o¶ o¶ o¶ o ¶ o ¶ o¶ o¶ ný¶ nù¶ nõ¶ nñ¶ ní¶ né¶ nå¶ nᶠnݶ nÙ¶ nÕ¶ nѶ nͶ nɶ nŶ nÁ¶ n½¶ n¹¶ nµ¶ n±¶ n­¶ n©¶ n¥¶ n¡¶ n¶ n™¶ n•¶ n‘¶ n¶ n‰¶ n…¶ n¶ n}¶ ny¶ nu¶ nq¶ nm¶ ni¶ ne¶ na¶ n]¶ nY¶ nU¶ nQ¶ nM¶ nI¶ nE¶ nA¶ n=¶ n9¶ n5¶ n1¶ n-¶ n)¶ n%¶ n!¶ n¶ n¶ n¶ n¶ n ¶ n ¶ n¶ n¶ mý¶ mù¶ mõ¶ mñ¶ mí¶ mé¶ må¶ mᶠmݶ mÙ¶ mÕ¶ mѶ mͶ mɶ mŶ mÁ¶ m½¶ m¹¶ mµ¶ m±¶ m­¶ m©¶ m¥¶ m¡¶ m¶ m™¶ m•¶ m‘¶ m¶ m‰¶ m…¶ m¶ m}¶ my¶ mu¶ mq¶ mm¶ mi¶ me¶ ma¶ m]¶ mY¶ mU¶ mQ¶ mM¶ mI¶ mE¶ mA¶ m=¶ m9¶ m5¶ m1¶ m-¶ m)¶ m%¶ m!¶ m¶ m¶ m¶ m¶ m ¶ m ¶ m¶ m¶ lý¶ lù¶ lõ¶ lñ¶ lí¶ lé¶ lå¶ lᶠlݶ lÙ¶ lÕ¶ lѶ lͶ lɶ lŶ lÁ¶ l½¶ l¹¶ lµ¶ l±¶ l­¶ l©¶ l¥¶ l¡¶ l¶ l™¶ l•¶ l‘¶ l¶ l‰¶ l…¶ l¶ l}¶ ly¶ lu¶ lq¶ lm¶ li¶ le¶ la¶ l]¶ lY¶ lU¶ lQ¶ lM¶ lI¶ lE¶ lA¶ l=¶ l9¶ l5¶ l1¶ l-¶ l)¶ l%¶ l!¶ l¶ l¶ l¶ l¶ l ¶ l ¶ l¶ l¶ ký¶ kù¶ kõ¶ kñ¶ kí¶ ké¶ kå¶ kᶠkݶ kÙ¶ kÕ¶ kѶ kͶ kɶ kŶ kÁ¶ k½¶ k¹¶ kµ¶ k±¶ k­¶ k©¶ k¥¶ k¡¶ k¶ k™¶ k•¶ k‘¶ k¶ k‰¶ k…¶ k¶ k}¶ ky¶ ku¶ kq¶ km¶ ki¶ ke¶ ka¶ k]¶ kY¶ kU¶ kQ¶ kM¶ kI¶ kE¶ kA¶ k=¶ k9¶ k5¶ k1¶ k-¶ k)¶ k%¶ k!¶ k¶ k¶ k¶ k¶ k ¶ k ¶ k¶ k¶ jý¶ jù¶ jõ¶ jñ¶ jí¶ jé¶ jå¶ jᶠjݶ jÙ¶ jÕ¶ jѶ jͶ jɶ jŶ jÁ¶ j½¶ j¹¶ jµ¶ j±¶ j­¶ j©¶ j¥¶ j¡¶ j¶ j™¶ j•¶ j‘¶ j¶ j‰¶ j…¶ j¶ j}¶ jy¶ ju¶ jq¶ jm¶ ji¶ je¶ ja¶ j]¶ jY¶ jU¶ jQ¶ jM¶ jI¶ jE¶ jA¶ j=¶ j9¶ j5¶ j1¶ j-¶ j)¶ j%¶ j!¶ j¶ j¶ j¶ j¶ j ¶ j ¶ j¶ j¶ iý¶ iù¶ iõ¶ iñ¶ ií¶ ié¶ iå¶ iᶠiݶ iÙ¶ iÕ¶ iѶ iͶ iɶ iŶ iÁ¶ i½¶ i¹¶ iµ¶ i±¶ i­¶ i©¶ i¥¶ i¡¶ i¶ i™¶ i•¶ i‘¶ i¶ i‰¶ i…¶ i¶ i}¶ iy¶ iu¶ iq¶ im¶ ii¶ ie¶ ia¶ i]¶ iY¶ iU¶ iQ¶ iM¶ iI¶ iE¶ iA¶ i=¶ i9¶ i5¶ i1¶ i-¶ i)¶ i%¶ i!¶ i¶ i¶ i¶ i¶ i ¶ i ¶ i¶ i¶ hý¶ hù¶ hõ¶ hñ¶ hí¶ hé¶ hå¶ hᶠhݶ hÙ¶ hÕ¶ hѶ hͶ hɶ hŶ hÁ¶ h½¶ h¹¶ hµ¶ h±¶ h­¶ h©¶ h¥¶ h¡¶ h¶ h™¶ h•¶ h‘¶ h¶ h‰¶ h…¶ h¶ h}¶ hy¶ hu¶ hq¶ hm¶ hi¶ he¶ ha¶ h]¶ hY¶ hU¶ hQ¶ hM¶ hI¶ hE¶ hA¶ h=¶ h9¶ h5¶ h1¶ h-¶ h)¶ h%¶ h!¶ h¶ h¶ h¶ h¶ h ¶ h ¶ h¶ h¶ gý¶ gù¶ gõ¶ gñ¶ gí¶ gé¶ gå¶ gᶠgݶ gÙ¶ gÕ¶ gѶ gͶ gɶ gŶ gÁ¶ g½¶ g¹¶ gµ¶ g±¶ g­¶ g©¶ g¥¶ g¡¶ g¶ g™¶ g•¶ g‘¶ g¶ g‰¶ g…¶ g¶ g}¶ gy¶ gu¶ gq¶ gm¶ gi¶ ge¶ ga¶ g]¶ gY¶ gU¶ gQ¶ gM¶ gI¶ gE¶ gA¶ g=¶ g9¶ g5¶ g1¶ g-¶ g)¶ g%¶ g!¶ g¶ g¶ g¶ g¶ g ¶ g ¶ g¶ g¶ fý¶ fù¶ fõ¶ fñ¶ fí¶ fé¶ få¶ fᶠfݶ fÙ¶ fÕ¶ fѶ fͶ fɶ fŶ fÁ¶ f½¶ f¹¶ fµ¶ f±¶ f­¶ f©¶ f¥¶ f¡¶ f¶ f™¶ f•¶ f‘¶ f¶ f‰¶ f…¶ f¶ f}¶ fy¶ fu¶ fq¶ fm¶ fi¶ fe¶ fa¶ f]¶ fY¶ fU¶ fQ¶ fM¶ fI¶ fE¶ fA¶ f=¶ f9¶ f5¶ f1¶ f-¶ f)¶ f%¶ f!¶ f¶ f¶ f¶ f¶ f ¶ f ¶ f¶ f¶ eý¶ eù¶ eõ¶ eñ¶ eí¶ eé¶ eå¶ eᶠeݶ eÙ¶ eÕ¶ eѶ eͶ eɶ eŶ eÁ¶ e½¶ e¹¶ eµ¶ e±¶ e­¶ e©¶ e¥¶ e¡¶ e¶ e™¶ e•¶ e‘¶ e¶ e‰¶ e…¶ e¶ e}¶ ey¶ eu¶ eq¶ em¶ ei¶ ee¶ ea¶ e]¶ eY¶ eU¶ eQ¶ eM¶ eI¶ eE¶ eA¶ e=¶ e9¶ e5¶ e1¶ e-¶ e)¶ e%¶ e!¶ e¶ e¶ e¶ e¶ e ¶ e ¶ e¶ e¶ dý¶ dù¶ dõ¶ dñ¶ dí¶ dé¶ då¶ dᶠdݶ dÙ¶ dÕ¶ dѶ dͶ dɶ dŶ dÁ¶ d½¶ d¹¶ dµ¶ d±¶ d­¶ d©¶ d¥¶ d¡¶ d¶ d™¶ d•¶ d‘¶ d¶ d‰¶ d…¶ d¶ d}¶ dy¶ du¶ dq¶ dm¶ di¶ de¶ da¶ d]¶ dY¶ dU¶ dQ¶ dM¶ dI¶ dE¶ dA¶ d=¶ d9¶ d5¶ d1¶ d-¶ d)¶ d%¶ d!¶ d¶ d¶ d¶ d¶ d ¶ d ¶ d¶ d¶ cý¶ cù¶ cõ¶ cñ¶ cí¶ cé¶ cå¶ cᶠcݶ cÙ¶ cÕ¶ cѶ cͶ cɶ cŶ cÁ¶ c½¶ c¹¶ cµ¶ c±¶ c­¶ c©¶ c¥¶ c¡¶ c¶ c™¶ c•¶ c‘¶ c¶ c‰¶ c…¶ c¶ c}¶ cy¶ cu¶ cq¶ cm¶ ci¶ ce¶ ca¶ c]¶ cY¶ cU¶ cQ¶ cM¶ cI¶ cE¶ cA¶ c=¶ c9¶ c5¶ c1¶ c-¶ c)¶ c%¶ c!¶ c¶ c¶ c¶ c¶ c ¶ c ¶ c¶ c¶ bý¶ bù¶ bõ¶ bñ¶ bí¶ bé¶ bå¶ bᶠbݶ bÙ¶ bÕ¶ bѶ bͶ bɶ bŶ bÁ¶ b½¶ b¹¶ bµ¶ b±¶ b­¶ b©¶ b¥¶ b¡¶ b¶ b™¶ b•¶ b‘¶ b¶ b‰¶ b…¶ b¶ b}¶ by¶ bu¶ bq¶ bm¶ bi¶ be¶ ba¶ b]¶ bY¶ bU¶ bQ¶ bM¶ bI¶ bE¶ bA¶ b=¶ b9¶ b5¶ b1¶ b-¶ b)¶ b%¶ b!¶ b¶ b¶ b¶ b¶ b ¶ b ¶ b¶ b¶ aý¶ aù¶ aõ¶ añ¶ aí¶ aé¶ aå¶ aᶠaݶ aÙ¶ aÕ¶ aѶ aͶ aɶ aŶ aÁ¶ a½¶ a¹¶ aµ¶ a±¶ a­¶ a©¶ a¥¶ a¡¶ a¶ a™¶ a•¶ a‘¶ a¶ a‰¶ a…¶ a¶ a}¶ ay¶ au¶ aq¶ am¶ ai¶ ae¶ aa¶ a]¶ aY¶ aU¶ aQ¶ aM¶ aI¶ aE¶ aA¶ a=¶ a9¶ a5¶ a1¶ a-¶ a)¶ a%¶ a!¶ a¶ a¶ a¶ a¶ a ¶ a ¶ a¶ a¶ `ý¶ `ù¶ `õ¶ `ñ¶ `í¶ `é¶ `å¶ `ᶠ`ݶ `Ù¶ `Õ¶ `Ѷ `Ͷ `ɶ `Ŷ `Á¶ `½¶ `¹¶ `µ¶ `±¶ `­¶ `©¶ `¥¶ `¡¶ `¶ `™¶ `•¶ `‘¶ `¶ `‰¶ `…¶ `¶ `}¶ `y¶ `u¶ `q¶ `m¶ `i¶ `e¶ `a¶ `]¶ `Y¶ `U¶ `Q¶ `M¶ `I¶ `E¶ `A¶ `=¶ `9¶ `5¶ `1¶ `-¶ `)¶ `%¶ `!¶ `¶ `¶ `¶ `¶ ` ¶ ` ¶ `¶ `¶ _ý¶ _ù¶ _õ¶ _ñ¶ _í¶ _é¶ _å¶ _ᶠ_ݶ _Ù¶ _Õ¶ _Ѷ _Ͷ _ɶ _Ŷ _Á¶ _½¶ _¹¶ _µ¶ _±¶ _­¶ _©¶ _¥¶ _¡¶ _¶ _™¶ _•¶ _‘¶ _¶ _‰¶ _…¶ _¶ _}¶ _y¶ _u¶ _q¶ _m¶ _i¶ _e¶ _a¶ _]¶ _Y¶ _U¶ _Q¶ _M¶ _I¶ _E¶ _A¶ _=¶ _9¶ _5¶ _1¶ _-¶ _)¶ _%¶ _!¶ _¶ _¶ _¶ _¶ _ ¶ _ ¶ _¶ _¶ ^ý¶ ^ù¶ ^õ¶ ^ñ¶ ^í¶ ^é¶ ^å¶ ^ᶠ^ݶ ^Ù¶ ^Õ¶ ^Ѷ ^Ͷ ^ɶ ^Ŷ ^Á¶ ^½¶ ^¹¶ ^µ¶ ^±¶ ^­¶ ^©¶ ^¥¶ ^¡¶ ^¶ ^™¶ ^•¶ ^‘¶ ^¶ ^‰¶ ^…¶ ^¶ ^}¶ ^y¶ ^u¶ ^q¶ ^m¶ ^i¶ ^e¶ ^a¶ ^]¶ ^Y¶ ^U¶ ^Q¶ ^M¶ ^I¶ ^E¶ ^A¶ ^=¶ ^9¶ ^5¶ ^1¶ ^-¶ ^)¶ ^%¶ ^!¶ ^¶ ^¶ ^¶ ^¶ ^ ¶ ^ ¶ ^¶ ^¶ ]ý¶ ]ù¶ ]õ¶ ]ñ¶ ]í¶ ]é¶ ]å¶ ]ᶠ]ݶ ]Ù¶ ]Õ¶ ]Ѷ ]Ͷ ]ɶ ]Ŷ ]Á¶ ]½¶ ]¹¶ ]µ¶ ]±¶ ]­¶ ]©¶ ]¥¶ ]¡¶ ]¶ ]™¶ ]•¶ ]‘¶ ]¶ ]‰¶ ]…¶ ]¶ ]}¶ ]y¶ ]u¶ ]q¶ ]m¶ ]i¶ ]e¶ ]a¶ ]]¶ ]Y¶ ]U¶ ]Q¶ ]M¶ ]I¶ ]E¶ ]A¶ ]=¶ ]9¶ ]5¶ ]1¶ ]-¶ ])¶ ]%¶ ]!¶ ]¶ ]¶ ]¶ ]¶ ] ¶ ] ¶ ]¶ ]¶ \ý¶ \ù¶ \õ¶ \ñ¶ \í¶ \é¶ \å¶ \ᶠ\ݶ \Ù¶ \Õ¶ \Ѷ \Ͷ \ɶ \Ŷ \Á¶ \½¶ \¹¶ \µ¶ \±¶ \­¶ \©¶ \¥¶ \¡¶ \¶ \™¶ \•¶ \‘¶ \¶ \‰¶ \…¶ \¶ \}¶ \y¶ \u¶ \q¶ \m¶ \i¶ \e¶ \a¶ \]¶ \Y¶ \U¶ \Q¶ \M¶ \I¶ \E¶ \A¶ \=¶ \9¶ \5¶ \1¶ \-¶ \)¶ \%¶ \!¶ \¶ \¶ \¶ \¶ \ ¶ \ ¶ \¶ \¶ [ý¶ [ù¶ [õ¶ [ñ¶ [í¶ [é¶ [å¶ [ᶠ[ݶ [Ù¶ [Õ¶ [Ѷ [Ͷ [ɶ [Ŷ [Á¶ [½¶ [¹¶ [µ¶ [±¶ [­¶ [©¶ [¥¶ [¡¶ [¶ [™¶ [•¶ [‘¶ [¶ [‰¶ […¶ [¶ [}¶ [y¶ [u¶ [q¶ [m¶ [i¶ [e¶ [a¶ []¶ [Y¶ [U¶ [Q¶ [M¶ [I¶ [E¶ [A¶ [=¶ [9¶ [5¶ [1¶ [-¶ [)¶ [%¶ [!¶ [¶ [¶ [¶ [¶ [ ¶ [ ¶ [¶ [¶ Zý¶ Zù¶ Zõ¶ Zñ¶ Zí¶ Zé¶ Zå¶ ZᶠZݶ ZÙ¶ ZÕ¶ ZѶ ZͶ Zɶ ZŶ ZÁ¶ Z½¶ Z¹¶ Zµ¶ Z±¶ Z­¶ Z©¶ Z¥¶ Z¡¶ Z¶ Z™¶ Z•¶ Z‘¶ Z¶ Z‰¶ Z…¶ Z¶ Z}¶ Zy¶ Zu¶ Zq¶ Zm¶ Zi¶ Ze¶ Za¶ Z]¶ ZY¶ ZU¶ ZQ¶ ZM¶ ZI¶ ZE¶ ZA¶ Z=¶ Z9¶ Z5¶ Z1¶ Z-¶ Z)¶ Z%¶ Z!¶ Z¶ Z¶ Z¶ Z¶ Z ¶ Z ¶ Z¶ Z¶ Yý¶ Yù¶ Yõ¶ Yñ¶ Yí¶ Yé¶ Yå¶ YᶠYݶ YÙ¶ YÕ¶ YѶ YͶ Yɶ YŶ YÁ¶ Y½¶ Y¹¶ Yµ¶ Y±¶ Y­¶ Y©¶ Y¥¶ Y¡¶ Y¶ Y™¶ Y•¶ Y‘¶ Y¶ Y‰¶ Y…¶ Y¶ Y}¶ Yy¶ Yu¶ Yq¶ Ym¶ Yi¶ Ye¶ Ya¶ Y]¶ YY¶ YU¶ YQ¶ YM¶ YI¶ YE¶ YA¶ Y=¶ Y9¶ Y5¶ Y1¶ Y-¶ Y)¶ Y%¶ Y!¶ Y¶ Y¶ Y¶ Y¶ Y ¶ Y ¶ Y¶ Y¶ Xý¶ Xù¶ Xõ¶ Xñ¶ Xí¶ Xé¶ Xå¶ XᶠXݶ XÙ¶ XÕ¶ XѶ XͶ Xɶ XŶ XÁ¶ X½¶ X¹¶ Xµ¶ X±¶ X­¶ X©¶ X¥¶ X¡¶ X¶ X™¶ X•¶ X‘¶ X¶ X‰¶ X…¶ X¶ X}¶ Xy¶ Xu¶ Xq¶ Xm¶ Xi¶ Xe¶ Xa¶ X]¶ XY¶ XU¶ XQ¶ XM¶ XI¶ XE¶ XA¶ X=¶ X9¶ X5¶ X1¶ X-¶ X)¶ X%¶ X!¶ X¶ X¶ X¶ X¶ X ¶ X ¶ X¶ X¶ Wý¶ Wù¶ Wõ¶ Wñ¶ Wí¶ Wé¶ Wå¶ WᶠWݶ WÙ¶ WÕ¶ WѶ WͶ Wɶ WŶ WÁ¶ W½¶ W¹¶ Wµ¶ W±¶ W­¶ W©¶ W¥¶ W¡¶ W¶ W™¶ W•¶ W‘¶ W¶ W‰¶ W…¶ W¶ W}¶ Wy¶ Wu¶ Wq¶ Wm¶ Wi¶ We¶ Wa¶ W]¶ WY¶ WU¶ WQ¶ WM¶ WI¶ WE¶ WA¶ W=¶ W9¶ W5¶ W1¶ W-¶ W)¶ W%¶ W!¶ W¶ W¶ W¶ W¶ W ¶ W ¶ W¶ W¶ Vý¶ Vù¶ Võ¶ Vñ¶ Ví¶ Vé¶ Vå¶ VᶠVݶ VÙ¶ VÕ¶ VѶ VͶ Vɶ VŶ VÁ¶ V½¶ V¹¶ Vµ¶ V±¶ V­¶ V©¶ V¥¶ V¡¶ V¶ V™¶ V•¶ V‘¶ V¶ V‰¶ V…¶ V¶ V}¶ Vy¶ Vu¶ Vq¶ Vm¶ Vi¶ Ve¶ Va¶ V]¶ VY¶ VU¶ VQ¶ VM¶ VI¶ VE¶ VA¶ V=¶ V9¶ V5¶ V1¶ V-¶ V)¶ V%¶ V!¶ V¶ V¶ V¶ V¶ V ¶ V ¶ V¶ V¶ Uý¶ Uù¶ Uõ¶ Uñ¶ Uí¶ Ué¶ Uå¶ UᶠUݶ UÙ¶ UÕ¶ UѶ UͶ Uɶ UŶ UÁ¶ U½¶ U¹¶ Uµ¶ U±¶ U­¶ U©¶ U¥¶ U¡¶ U¶ U™¶ U•¶ U‘¶ U¶ U‰¶ U…¶ U¶ U}¶ Uy¶ Uu¶ Uq¶ Um¶ Ui¶ Ue¶ Ua¶ U]¶ UY¶ UU¶ UQ¶ UM¶ UI¶ UE¶ UA¶ U=¶ U9¶ U5¶ U1¶ U-¶ U)¶ U%¶ U!¶ U¶ U¶ U¶ U¶ U ¶ U ¶ U¶ U¶ Tý¶ Tù¶ Tõ¶ Tñ¶ Tí¶ Té¶ Tå¶ TᶠTݶ TÙ¶ TÕ¶ TѶ TͶ Tɶ TŶ TÁ¶ T½¶ T¹¶ Tµ¶ T±¶ T­¶ T©¶ T¥¶ T¡¶ T¶ T™¶ T•¶ T‘¶ T¶ T‰¶ T…¶ T¶ T}¶ Ty¶ Tu¶ Tq¶ Tm¶ Ti¶ Te¶ Ta¶ T]¶ TY¶ TU¶ TQ¶ TM¶ TI¶ TE¶ TA¶ T=¶ T9¶ T5¶ T1¶ T-¶ T)¶ T%¶ T!¶ T¶ T¶ T¶ T¶ T ¶ T ¶ T¶ T¶ Sý¶ Sù¶ Sõ¶ Sñ¶ Sí¶ Sé¶ Så¶ SᶠSݶ SÙ¶ SÕ¶ SѶ SͶ Sɶ SŶ SÁ¶ S½¶ S¹¶ Sµ¶ S±¶ S­¶ S©¶ S¥¶ S¡¶ S¶ S™¶ S•¶ S‘¶ S¶ S‰¶ S…¶ S¶ S}¶ Sy¶ Su¶ Sq¶ Sm¶ Si¶ Se¶ Sa¶ S]¶ SY¶ SU¶ SQ¶ SM¶ SI¶ SE¶ SA¶ S=¶ S9¶ S5¶ S1¶ S-¶ S)¶ S%¶ S!¶ S¶ S¶ S¶ S¶ S ¶ S ¶ S¶ S¶ Rý¶ Rù¶ Rõ¶ Rñ¶ Rí¶ Ré¶ Rå¶ RᶠRݶ RÙ¶ RÕ¶ RѶ RͶ Rɶ RŶ RÁ¶ R½¶ R¹¶ Rµ¶ R±¶ R­¶ R©¶ R¥¶ R¡¶ R¶ R™¶ R•¶ R‘¶ R¶ R‰¶ R…¶ R¶ R}¶ Ry¶ Ru¶ Rq¶ Rm¶ Ri¶ Re¶ Ra¶ R]¶ RY¶ RU¶ RQ¶ RM¶ RI¶ RE¶ RA¶ R=¶ R9¶ R5¶ R1¶ R-¶ R)¶ R%¶ R!¶ R¶ R¶ R¶ R¶ R ¶ R ¶ R¶ R¶ Qý¶ Qù¶ Qõ¶ Qñ¶ Qí¶ Qé¶ Qå¶ QᶠQݶ QÙ¶ QÕ¶ QѶ QͶ Qɶ QŶ QÁ¶ Q½¶ Q¹¶ Qµ¶ Q±¶ Q­¶ Q©¶ Q¥¶ Q¡¶ Q¶ Q™¶ Q•¶ Q‘¶ Q¶ Q‰¶ Q…¶ Q¶ Q}¶ Qy¶ Qu¶ Qq¶ Qm¶ Qi¶ Qe¶ Qa¶ Q]¶ QY¶ QU¶ QQ¶ QM¶ QI¶ QE¶ QA¶ Q=¶ Q9¶ Q5¶ Q1¶ Q-¶ Q)¶ Q%¶ Q!¶ Q¶ Q¶ Q¶ Q¶ Q ¶ Q ¶ Q¶ Q¶ Pý¶ Pù¶ Põ¶ Pñ¶ Pí¶ Pé¶ På¶ PᶠPݶ PÙ¶ PÕ¶ PѶ PͶ Pɶ PŶ PÁ¶ P½¶ P¹¶ Pµ¶ P±¶ P­¶ P©¶ P¥¶ P¡¶ P¶ P™¶ P•¶ P‘¶ P¶ P‰¶ P…¶ P¶ P}¶ Py¶ Pu¶ Pq¶ Pm¶ Pi¶ Pe¶ Pa¶ P]¶ PY¶ PU¶ PQ¶ PM¶ PI¶ PE¶ PA¶ P=¶ P9¶ P5¶ P1¶ P-¶ P)¶ P%¶ P!¶ P¶ P¶ P¶ P¶ P ¶ P ¶ P¶ P¶ Oý¶ Où¶ Oõ¶ Oñ¶ Oí¶ Oé¶ Oå¶ OᶠOݶ OÙ¶ OÕ¶ OѶ OͶ Oɶ OŶ OÁ¶ O½¶ O¹¶ Oµ¶ O±¶ O­¶ O©¶ O¥¶ O¡¶ O¶ O™¶ O•¶ O‘¶ O¶ O‰¶ O…¶ O¶ O}¶ Oy¶ Ou¶ Oq¶ Om¶ Oi¶ Oe¶ Oa¶ O]¶ OY¶ OU¶ OQ¶ OM¶ OI¶ OE¶ OA¶ O=¶ O9¶ O5¶ O1¶ O-¶ O)¶ O%¶ O!¶ O¶ O¶ O¶ O¶ O ¶ O ¶ O¶ O¶ Ný¶ Nù¶ Nõ¶ Nñ¶ Ní¶ Né¶ Nå¶ NᶠNݶ NÙ¶ NÕ¶ NѶ NͶ Nɶ NŶ NÁ¶ N½¶ N¹¶ Nµ¶ N±¶ N­¶ N©¶ N¥¶ N¡¶ N¶ N™¶ N•¶ N‘¶ N¶ N‰¶ N…¶ N¶ N}¶ Ny¶ Nu¶ Nq¶ Nm¶ Ni¶ Ne¶ Na¶ N]¶ NY¶ NU¶ NQ¶ NM¶ NI¶ NE¶ NA¶ N=¶ N9¶ N5¶ N1¶ N-¶ N)¶ N%¶ N!¶ N¶ N¶ N¶ N¶ N ¶ N ¶ N¶ N¶ Mý¶ Mù¶ Mõ¶ Mñ¶ Mí¶ Mé¶ Må¶ MᶠMݶ MÙ¶ MÕ¶ MѶ MͶ Mɶ MŶ MÁ¶ M½¶ M¹¶ Mµ¶ M±¶ M­¶ M©¶ M¥¶ M¡¶ M¶ M™¶ M•¶ M‘¶ M¶ M‰¶ M…¶ M¶ M}¶ My¶ Mu¶ Mq¶ Mm¶ Mi¶ Me¶ Ma¶ M]¶ MY¶ MU¶ MQ¶ MM¶ MI¶ ME¶ MA¶ M=¶ M9¶ M5¶ M1¶ M-¶ M)¶ M%¶ M!¶ M¶ M¶ M¶ M¶ M ¶ M ¶ M¶ M¶ Lý¶ Lù¶ Lõ¶ Lñ¶ Lí¶ Lé¶ Lå¶ LᶠLݶ LÙ¶ LÕ¶ LѶ LͶ Lɶ LŶ LÁ¶ L½¶ L¹¶ Lµ¶ L±¶ L­¶ L©¶ L¥¶ L¡¶ L¶ L™¶ L•¶ L‘¶ L¶ L‰¶ L…¶ L¶ L}¶ Ly¶ Lu¶ Lq¶ Lm¶ Li¶ Le¶ La¶ L]¶ LY¶ LU¶ LQ¶ LM¶ LI¶ LE¶ LA¶ L=¶ L9¶ L5¶ L1¶ L-¶ L)¶ L%¶ L!¶ L¶ L¶ L¶ L¶ L ¶ L ¶ L¶ L¶ Ký¶ Kù¶ Kõ¶ Kñ¶ Kí¶ Ké¶ Kå¶ KᶠKݶ KÙ¶ KÕ¶ KѶ KͶ Kɶ KŶ KÁ¶ K½¶ K¹¶ Kµ¶ K±¶ K­¶ K©¶ K¥¶ K¡¶ K¶ K™¶ K•¶ K‘¶ K¶ K‰¶ K…¶ K¶ K}¶ Ky¶ Ku¶ Kq¶ Km¶ Ki¶ Ke¶ Ka¶ K]¶ KY¶ KU¶ KQ¶ KM¶ KI¶ KE¶ KA¶ K=¶ K9¶ K5¶ K1¶ K-¶ K)¶ K%¶ K!¶ K¶ K¶ K¶ K¶ K ¶ K ¶ K¶ K¶ Jý¶ Jù¶ Jõ¶ Jñ¶ Jí¶ Jé¶ Jå¶ JᶠJݶ JÙ¶ JÕ¶ JѶ JͶ Jɶ JŶ JÁ¶ J½¶ J¹¶ Jµ¶ J±¶ J­¶ J©¶ J¥¶ J¡¶ J¶ J™¶ J•¶ J‘¶ J¶ J‰¶ J…¶ J¶ J}¶ Jy¶ Ju¶ Jq¶ Jm¶ Ji¶ Je¶ Ja¶ J]¶ JY¶ JU¶ JQ¶ JM¶ JI¶ JE¶ JA¶ J=¶ J9¶ J5¶ J1¶ J-¶ J)¶ J%¶ J!¶ J¶ J¶ J¶ J¶ J ¶ J ¶ J¶ J¶ Iý¶ Iù¶ Iõ¶ Iñ¶ Ií¶ Ié¶ Iå¶ IᶠIݶ IÙ¶ IÕ¶ IѶ IͶ Iɶ IŶ IÁ¶ I½¶ I¹¶ Iµ¶ I±¶ I­¶ I©¶ I¥¶ I¡¶ I¶ I™¶ I•¶ I‘¶ I¶ I‰¶ I…¶ I¶ I}¶ Iy¶ Iu¶ Iq¶ Im¶ Ii¶ Ie¶ Ia¶ I]¶ IY¶ IU¶ IQ¶ IM¶ II¶ IE¶ IA¶ I=¶ I9¶ I5¶ I1¶ I-¶ I)¶ I%¶ I!¶ I¶ I¶ I¶ I¶ I ¶ I ¶ I¶ I¶ Hý¶ Hù¶ Hõ¶ Hñ¶ Hí¶ Hé¶ Hå¶ HᶠHݶ HÙ¶ HÕ¶ HѶ HͶ Hɶ HŶ HÁ¶ H½¶ H¹¶ Hµ¶ H±¶ H­¶ H©¶ H¥¶ H¡¶ H¶ H™¶ H•¶ H‘¶ H¶ H‰¶ H…¶ H¶ H}¶ Hy¶ Hu¶ Hq¶ Hm¶ Hi¶ He¶ Ha¶ H]¶ HY¶ HU¶ HQ¶ HM¶ HI¶ HE¶ HA¶ H=¶ H9¶ H5¶ H1¶ H-¶ H)¶ H%¶ H!¶ H¶ H¶ H¶ H¶ H ¶ H ¶ H¶ H¶ Gý¶ Gù¶ Gõ¶ Gñ¶ Gí¶ Gé¶ Gå¶ GᶠGݶ GÙ¶ GÕ¶ GѶ GͶ Gɶ GŶ GÁ¶ G½¶ G¹¶ Gµ¶ G±¶ G­¶ G©¶ G¥¶ G¡¶ G¶ G™¶ G•¶ G‘¶ G¶ G‰¶ G…¶ G¶ G}¶ Gy¶ Gu¶ Gq¶ Gm¶ Gi¶ Ge¶ Ga¶ G]¶ GY¶ GU¶ GQ¶ GM¶ GI¶ GE¶ GA¶ G=¶ G9¶ G5¶ G1¶ G-¶ G)¶ G%¶ G!¶ G¶ G¶ G¶ G¶ G ¶ G ¶ G¶ G¶ Fý¶ Fù¶ Fõ¶ Fñ¶ Fí¶ Fé¶ Få¶ FᶠFݶ FÙ¶ FÕ¶ FѶ FͶ Fɶ FŶ FÁ¶ F½¶ F¹¶ Fµ¶ F±¶ F­¶ F©¶ F¥¶ F¡¶ F¶ F™¶ F•¶ F‘¶ F¶ F‰¶ F…¶ F¶ F}¶ Fy¶ Fu¶ Fq¶ Fm¶ Fi¶ Fe¶ Fa¶ F]¶ FY¶ FU¶ FQ¶ FM¶ FI¶ FE¶ FA¶ F=¶ F9¶ F5¶ F1¶ F-¶ F)¶ F%¶ F!¶ F¶ F¶ F¶ F¶ F ¶ F ¶ F¶ F¶ Eý¶ Eù¶ Eõ¶ Eñ¶ Eí¶ Eé¶ Eå¶ EᶠEݶ EÙ¶ EÕ¶ EѶ EͶ Eɶ EŶ EÁ¶ E½¶ E¹¶ Eµ¶ E±¶ E­¶ E©¶ E¥¶ E¡¶ E¶ E™¶ E•¶ E‘¶ E¶ E‰¶ E…¶ E¶ E}¶ Ey¶ Eu¶ Eq¶ Em¶ Ei¶ Ee¶ Ea¶ E]¶ EY¶ EU¶ EQ¶ EM¶ EI¶ EE¶ EA¶ E=¶ E9¶ E5¶ E1¶ E-¶ E)¶ E%¶ E!¶ E¶ E¶ E¶ E¶ E ¶ E ¶ E¶ E¶ Dý¶ Dù¶ Dõ¶ Dñ¶ Dí¶ Dé¶ Då¶ DᶠDݶ DÙ¶ DÕ¶ DѶ DͶ Dɶ DŶ DÁ¶ D½¶ D¹¶ Dµ¶ D±¶ D­¶ D©¶ D¥¶ D¡¶ D¶ D™¶ D•¶ D‘¶ D¶ D‰¶ D…¶ D¶ D}¶ Dy¶ Du¶ Dq¶ Dm¶ Di¶ De¶ Da¶ D]¶ DY¶ DU¶ DQ¶ DM¶ DI¶ DE¶ DA¶ D=¶ D9¶ D5¶ D1¶ D-¶ D)¶ D%¶ D!¶ D¶ D¶ D¶ D¶ D ¶ D ¶ D¶ D¶ Cý¶ Cù¶ Cõ¶ Cñ¶ Cí¶ Cé¶ Cå¶ CᶠCݶ CÙ¶ CÕ¶ CѶ CͶ Cɶ CŶ CÁ¶ C½¶ C¹¶ Cµ¶ C±¶ C­¶ C©¶ C¥¶ C¡¶ C¶ C™¶ C•¶ C‘¶ C¶ C‰¶ C…¶ C¶ C}¶ Cy¶ Cu¶ Cq¶ Cm¶ Ci¶ Ce¶ Ca¶ C]¶ CY¶ CU¶ CQ¶ CM¶ CI¶ CE¶ CA¶ C=¶ C9¶ C5¶ C1¶ C-¶ C)¶ C%¶ C!¶ C¶ C¶ C¶ C¶ C ¶ C ¶ C¶ C¶ Bý¶ Bù¶ Bõ¶ Bñ¶ Bí¶ Bé¶ Bå¶ BᶠBݶ BÙ¶ BÕ¶ BѶ BͶ Bɶ BŶ BÁ¶ B½¶ B¹¶ Bµ¶ B±¶ B­¶ B©¶ B¥¶ B¡¶ B¶ B™¶ B•¶ B‘¶ B¶ B‰¶ B…¶ B¶ B}¶ By¶ Bu¶ Bq¶ Bm¶ Bi¶ Be¶ Ba¶ B]¶ BY¶ BU¶ BQ¶ BM¶ BI¶ BE¶ BA¶ B=¶ B9¶ B5¶ B1¶ B-¶ B)¶ B%¶ B!¶ B¶ B¶ B¶ B¶ B ¶ B ¶ B¶ B¶ Aý¶ Aù¶ Aõ¶ Añ¶ Aí¶ Aé¶ Aå¶ AᶠAݶ AÙ¶ AÕ¶ AѶ AͶ Aɶ AŶ AÁ¶ A½¶ A¹¶ Aµ¶ A±¶ A­¶ A©¶ A¥¶ A¡¶ A¶ A™¶ A•¶ A‘¶ A¶ A‰¶ A…¶ A¶ A}¶ Ay¶ Au¶ Aq¶ Am¶ Ai¶ Ae¶ Aa¶ A]¶ AY¶ AU¶ AQ¶ AM¶ AI¶ AE¶ AA¶ A=¶ A9¶ A5¶ A1¶ A-¶ A)¶ A%¶ A!¶ A¶ A¶ A¶ A¶ A ¶ A ¶ A¶ A¶ @ý¶ @ù¶ @õ¶ @ñ¶ @í¶ @é¶ @å¶ @ᶠ@ݶ @Ù¶ @Õ¶ @Ѷ @Ͷ @ɶ @Ŷ @Á¶ @½¶ @¹¶ @µ¶ @±¶ @­¶ @©¶ @¥¶ @¡¶ @¶ @™¶ @•¶ @‘¶ @¶ @‰¶ @…¶ @¶ @}¶ @y¶ @u¶ @q¶ @m¶ @i¶ @e¶ @a¶ @]¶ @Y¶ @U¶ @Q¶ @M¶ @I¶ @E¶ @A¶ @=¶ @9¶ @5¶ @1¶ @-¶ @)¶ @%¶ @!¶ @¶ @¶ @¶ @¶ @ ¶ @ ¶ @¶ @¶þ¶û¶ø¶õ¶ò¶ï¶ì¶é¶æ¶ã¶à¶ݶÚ¶׶Ô¶Ѷζ˶ȶŶ¶¿¶¼¶¹¶¶¶³¶°¶­¶ª¶§¶¤¶¡¶ž¶›¶˜¶•¶’¶¶Œ¶‰¶†¶ƒ¶€¶}¶z¶w¶t¶q¶n¶k¶h¶e¶b¶_¶\¶Y¶V¶S¶P¶M¶J¶G¶D¶A¶>¶;¶8¶5¶2¶/¶,¶)¶&¶#¶ ¶¶¶¶¶¶¶ ¶¶¶¶~ÿ¶~ü¶~ù¶~ö¶~ó¶~ð¶~í¶~ê¶~ç¶~ä¶~á¶~Þ¶~Û¶~ض~Õ¶~Ò¶~϶~̶~ɶ~ƶ~ö~À¶~½¶~º¶~·¶~´¶~±¶~®¶~«¶~¨¶~¥¶~¢¶~Ÿ¶~œ¶~™¶~–¶~“¶~¶~¶~Š¶~‡¶~„¶~¶~~¶~{¶~x¶~u¶~r¶~o¶~l¶~i¶~f¶~c¶~`¶~]¶~Z¶~W¶~T¶~Q¶~N¶~K¶~H¶~E¶~B¶~?¶~<¶~9¶~6¶~3¶~0¶~-¶~*¶~'¶~$¶~!¶~¶~¶~¶~¶~¶~¶~ ¶~ ¶~¶~¶~¶}ý¶}ú¶}÷¶}ô¶}ñ¶}î¶}ë¶}è¶}å¶}â¶}߶}ܶ}Ù¶}Ö¶}Ó¶}ж}Ͷ}ʶ}Ƕ}Ķ}Á¶}¾¶}»¶}¸¶}µ¶}²¶}¯¶}¬¶}©¶}¦¶}£¶} ¶}¶}š¶}—¶}”¶}‘¶}Ž¶}‹¶}ˆ¶}…¶}‚¶}¶}|¶}y¶}v¶}s¶}p¶}m¶}j¶}g¶}d¶}a¶}^¶}[¶}X¶}U¶}R¶}O¶}L¶}I¶}F¶}C¶}@¶}=¶}:¶}7¶}4¶}1¶}.¶}+¶}(¶}%¶}"¶}¶}¶}¶}¶}¶}¶} ¶} +¶}¶}¶}¶|þ¶|û¶|ø¶|õ¶|ò¶|ï¶|ì¶|é¶|æ¶|ã¶|à¶|ݶ|Ú¶|׶|Ô¶|Ѷ|ζ|˶|ȶ|Ŷ|¶|¿¶|¼¶|¹¶|¶¶|³¶|°¶|­¶|ª¶|§¶|¤¶|¡¶|ž¶|›¶|˜¶|•¶|’¶|¶|Œ¶|‰¶|†¶|ƒ¶|€¶|}¶|z¶|w¶|t¶|q¶|n¶|k¶|h¶|e¶|b¶|_¶|\¶|Y¶|V¶|S¶|P¶|M¶|J¶|G¶|D¶|A¶|>¶|;¶|8¶|5¶|2¶|/¶|,¶|)¶|&¶|#¶| ¶|¶|¶|¶|¶|¶|¶| ¶|¶|¶|¶{ÿ¶{ü¶{ù¶{ö¶{ó¶{ð¶{í¶{ê¶{ç¶{ä¶{á¶{Þ¶{Û¶{ض{Õ¶{Ò¶{϶{̶{ɶ{ƶ{ö{À¶{½¶{º¶{·¶{´¶{±¶{®¶{«¶{¨¶{¥¶{¢¶{Ÿ¶{œ¶{™¶{–¶{“¶{¶{¶{Š¶{‡¶{„¶{¶{~¶{{¶{x¶{u¶{r¶{o¶{l¶{i¶{f¶{c¶{`¶{]¶{Z¶{W¶{T¶{Q¶{N¶{K¶{H¶{E¶{B¶{?¶{<¶{9¶{6¶{3¶{0¶{-¶{*¶{'¶{$¶{!¶{¶{¶{¶{¶{¶{¶{ ¶{ ¶{¶{¶{¶zý¶zú¶z÷¶zô¶zñ¶zî¶zë¶zè¶zå¶zâ¶z߶zܶzÙ¶zÖ¶zÓ¶zжzͶzʶzǶzĶzÁ¶z¾¶z»¶z¸¶zµ¶z²¶z¯¶z¬¶z©¶z¦¶z£¶z ¶z¶zš¶z—¶z”¶z‘¶zŽ¶z‹¶zˆ¶z…¶z‚¶z¶z|¶zy¶zv¶zs¶zp¶zm¶zj¶zg¶zd¶za¶z^¶z[¶zX¶zU¶zR¶zO¶zL¶zI¶zF¶zC¶z@¶z=¶z:¶z7¶z4¶z1¶z.¶z+¶z(¶z%¶z"¶z¶z¶z¶z¶z¶z¶z ¶z +¶z¶z¶z¶yþ¶yû¶yø¶yõ¶yò¶yï¶yì¶yé¶yæ¶yã¶yà¶yݶyÚ¶y׶yÔ¶yѶyζy˶yȶyŶy¶y¿¶y¼¶y¹¶y¶¶y³¶y°¶y­¶yª¶y§¶y¤¶y¡¶yž¶y›¶y˜¶y•¶y’¶y¶yŒ¶y‰¶y†¶yƒ¶y€¶y}¶yz¶yw¶yt¶yq¶yn¶yk¶yh¶ye¶yb¶y_¶y\¶yY¶yV¶yS¶yP¶yM¶yJ¶yG¶yD¶yA¶y>¶y;¶y8¶y5¶y2¶y/¶y,¶y)¶y&¶y#¶y ¶y¶y¶y¶y¶y¶y¶y ¶y¶y¶y¶xÿ¶xü¶xù¶xö¶xó¶xð¶xí¶xê¶xç¶xä¶xá¶xÞ¶xÛ¶xضxÕ¶xÒ¶x϶x̶xɶxƶxöxÀ¶x½¶xº¶x·¶x´¶x±¶x®¶x«¶x¨¶x¥¶x¢¶xŸ¶xœ¶x™¶x–¶x“¶x¶x¶xŠ¶x‡¶x„¶x¶x~¶x{¶xx¶xu¶xr¶xo¶xl¶xi¶xf¶xc¶x`¶x]¶xZ¶xW¶xT¶xQ¶xN¶xK¶xH¶xE¶xB¶x?¶x<¶x9¶x6¶x3¶x0¶x-¶x*¶x'¶x$¶x!¶x¶x¶x¶x¶x¶x¶x ¶x ¶x¶x¶x¶wý¶wú¶w÷¶wô¶wñ¶wî¶wë¶wè¶wå¶wâ¶w߶wܶwÙ¶wÖ¶wÓ¶wжwͶwʶwǶwĶwÁ¶w¾¶w»¶w¸¶wµ¶w²¶w¯¶w¬¶w©¶w¦¶w£¶w ¶w¶wš¶w—¶w”¶w‘¶wŽ¶w‹¶wˆ¶w…¶w‚¶w¶w|¶wy¶wv¶ws¶wp¶wm¶wj¶wg¶wd¶wa¶w^¶w[¶wX¶wU¶wR¶wO¶wL¶wI¶wF¶wC¶w@¶w=¶w:¶w7¶w4¶w1¶w.¶w+¶w(¶w%¶w"¶w¶w¶w¶w¶w¶w¶w ¶w +¶w¶w¶w¶vþ¶vû¶vø¶võ¶vò¶vï¶vì¶vé¶væ¶vã¶và¶vݶvÚ¶v׶vÔ¶vѶvζv˶vȶvŶv¶v¿¶v¼¶v¹¶v¶¶v³¶v°¶v­¶vª¶v§¶v¤¶v¡¶vž¶v›¶v˜¶v•¶v’¶v¶vŒ¶v‰¶v†¶vƒ¶v€¶v}¶vz¶vw¶vt¶vq¶vn¶vk¶vh¶ve¶vb¶v_¶v\¶vY¶vV¶vS¶vP¶vM¶vJ¶vG¶vD¶vA¶v>¶v;¶v8¶v5¶v2¶v/¶v,¶v)¶v&¶v#¶v ¶v¶v¶v¶v¶v¶v¶v ¶v¶v¶v¶uÿ¶uü¶uù¶uö¶uó¶uð¶uí¶uê¶uç¶uä¶uá¶uÞ¶uÛ¶uضuÕ¶uÒ¶u϶u̶uɶuƶuöuÀ¶u½¶uº¶u·¶u´¶u±¶u®¶u«¶u¨¶u¥¶u¢¶uŸ¶uœ¶u™¶u–¶u“¶u¶u¶uŠ¶u‡¶u„¶u¶u~¶u{¶ux¶uu¶ur¶uo¶ul¶ui¶uf¶uc¶u`¶u]¶uZ¶uW¶uT¶uQ¶uN¶uK¶uH¶uE¶uB¶u?¶u<¶u9¶u6¶u3¶u0¶u-¶u*¶u'¶u$¶u!¶u¶u¶u¶u¶u¶u¶u ¶u ¶u¶u¶u¶tý¶tú¶t÷¶tô¶tñ¶tî¶të¶tè¶tå¶tâ¶t߶tܶtÙ¶tÖ¶tÓ¶tжtͶtʶtǶtĶtÁ¶t¾¶t»¶t¸¶tµ¶t²¶t¯¶t¬¶t©¶t¦¶t£¶t ¶t¶tš¶t—¶t”¶t‘¶tŽ¶t‹¶tˆ¶t…¶t‚¶t¶t|¶ty¶tv¶ts¶tp¶tm¶tj¶tg¶td¶ta¶t^¶t[¶tX¶tU¶tR¶tO¶tL¶tI¶tF¶tC¶t@¶t=¶t:¶t7¶t4¶t1¶t.¶t+¶t(¶t%¶t"¶t¶t¶t¶t¶t¶t¶t ¶t +¶t¶t¶t¶sþ¶sû¶sø¶sõ¶sò¶sï¶sì¶sé¶sæ¶sã¶sà¶sݶsÚ¶s׶sÔ¶sѶsζs˶sȶsŶs¶s¿¶s¼¶s¹¶s¶¶s³¶s°¶s­¶sª¶s§¶s¤¶s¡¶sž¶s›¶s˜¶s•¶s’¶s¶sŒ¶s‰¶s†¶sƒ¶s€¶s}¶sz¶sw¶st¶sq¶sn¶sk¶sh¶se¶sb¶s_¶s\¶sY¶sV¶sS¶sP¶sM¶sJ¶sG¶sD¶sA¶s>¶s;¶s8¶s5¶s2¶s/¶s,¶s)¶s&¶s#¶s ¶s¶s¶s¶s¶s¶s¶s ¶s¶s¶s¶rÿ¶rü¶rù¶rö¶ró¶rð¶rí¶rê¶rç¶rä¶rá¶rÞ¶rÛ¶rضrÕ¶rÒ¶r϶r̶rɶrƶrörÀ¶r½¶rº¶r·¶r´¶r±¶r®¶r«¶r¨¶r¥¶r¢¶rŸ¶rœ¶r™¶r–¶r“¶r¶r¶rŠ¶r‡¶r„¶r¶r~¶r{¶rx¶ru¶rr¶ro¶rl¶ri¶rf¶rc¶r`¶r]¶rZ¶rW¶rT¶rQ¶rN¶rK¶rH¶rE¶rB¶r?¶r<¶r9¶r6¶r3¶r0¶r-¶r*¶r'¶r$¶r!¶r¶r¶r¶r¶r¶r¶r ¶r ¶r¶r¶r¶qý¶qú¶q÷¶qô¶qñ¶qî¶që¶qè¶qå¶qâ¶q߶qܶqÙ¶qÖ¶qÓ¶qжqͶqʶqǶqĶqÁ¶q¾¶q»¶q¸¶qµ¶q²¶q¯¶q¬¶q©¶q¦¶q£¶q ¶q¶qš¶q—¶q”¶q‘¶qŽ¶q‹¶qˆ¶q…¶q‚¶q¶q|¶qy¶qv¶qs¶qp¶qm¶qj¶qg¶qd¶qa¶q^¶q[¶qX¶qU¶qR¶qO¶qL¶qI¶qF¶qC¶q@¶q=¶q:¶q7¶q4¶q1¶q.¶q+¶q(¶q%¶q"¶q¶q¶q¶q¶q¶q¶q ¶q +¶q¶q¶q¶pþ¶pû¶pø¶põ¶pò¶pï¶pì¶pé¶pæ¶pã¶pà¶pݶpÚ¶p׶pÔ¶pѶpζp˶pȶpŶp¶p¿¶p¼¶p¹¶p¶¶p³¶p°¶p­¶pª¶p§¶p¤¶p¡¶pž¶p›¶p˜¶p•¶p’¶p¶pŒ¶p‰¶p†¶pƒ¶p€¶p}¶pz¶pw¶pt¶pq¶pn¶pk¶ph¶pe¶pb¶p_¶p\¶pY¶pV¶pS¶pP¶pM¶pJ¶pG¶pD¶pA¶p>¶p;¶p8¶p5¶p2¶p/¶p,¶p)¶p&¶p#¶p ¶p¶p¶p¶p¶p¶p¶p ¶p¶p¶p¶oÿ¶oü¶où¶oö¶oó¶oð¶oí¶oê¶oç¶oä¶oá¶oÞ¶oÛ¶oضoÕ¶oÒ¶o϶o̶oɶoƶoöoÀ¶o½¶oº¶o·¶o´¶o±¶o®¶o«¶o¨¶o¥¶o¢¶oŸ¶oœ¶o™¶o–¶o“¶o¶o¶oŠ¶o‡¶o„¶o¶o~¶o{¶ox¶ou¶or¶oo¶ol¶oi¶of¶oc¶o`¶o]¶oZ¶oW¶oT¶oQ¶oN¶oK¶oH¶oE¶oB¶o?¶o<¶o9¶o6¶o3¶o0¶o-¶o*¶o'¶o$¶o!¶o¶o¶o¶o¶o¶o¶o ¶o ¶o¶o¶o¶ný¶nú¶n÷¶nô¶nñ¶nî¶në¶nè¶nå¶nâ¶n߶nܶnÙ¶nÖ¶nÓ¶nжnͶnʶnǶnĶnÁ¶n¾¶n»¶n¸¶nµ¶n²¶n¯¶n¬¶n©¶n¦¶n£¶n ¶n¶nš¶n—¶n”¶n‘¶nŽ¶n‹¶nˆ¶n…¶n‚¶n¶n|¶ny¶nv¶ns¶np¶nm¶nj¶ng¶nd¶na¶n^¶n[¶nX¶nU¶nR¶nO¶nL¶nI¶nF¶nC¶n@¶n=¶n:¶n7¶n4¶n1¶n.¶n+¶n(¶n%¶n"¶n¶n¶n¶n¶n¶n¶n ¶n +¶n¶n¶n¶mþ¶mû¶mø¶mõ¶mò¶mï¶mì¶mé¶mæ¶mã¶mà¶mݶmÚ¶m׶mÔ¶mѶmζm˶mȶmŶm¶m¿¶m¼¶m¹¶m¶¶m³¶m°¶m­¶mª¶m§¶m¤¶m¡¶mž¶m›¶m˜¶m•¶m’¶m¶mŒ¶m‰¶m†¶mƒ¶m€¶m}¶mz¶mw¶mt¶mq¶mn¶mk¶mh¶me¶mb¶m_¶m\¶mY¶mV¶mS¶mP¶mM¶mJ¶mG¶mD¶mA¶m>¶m;¶m8¶m5¶m2¶m/¶m,¶m)¶m&¶m#¶m ¶m¶m¶m¶m¶m¶m¶m ¶m¶m¶m¶lÿ¶lü¶lù¶lö¶ló¶lð¶lí¶lê¶lç¶lä¶lá¶lÞ¶lÛ¶lضlÕ¶lÒ¶l϶l̶lɶlƶlölÀ¶l½¶lº¶l·¶l´¶l±¶l®¶l«¶l¨¶l¥¶l¢¶lŸ¶lœ¶l™¶l–¶l“¶l¶l¶lŠ¶l‡¶l„¶l¶l~¶l{¶lx¶lu¶lr¶lo¶ll¶li¶lf¶lc¶l`¶l]¶lZ¶lW¶lT¶lQ¶lN¶lK¶lH¶lE¶lB¶l?¶l<¶l9¶l6¶l3¶l0¶l-¶l*¶l'¶l$¶l!¶l¶l¶l¶l¶l¶l¶l ¶l ¶l¶l¶l¶ký¶kú¶k÷¶kô¶kñ¶kî¶kë¶kè¶kå¶kâ¶k߶kܶkÙ¶kÖ¶kÓ¶kжkͶkʶkǶkĶkÁ¶k¾¶k»¶k¸¶kµ¶k²¶k¯¶k¬¶k©¶k¦¶k£¶k ¶k¶kš¶k—¶k”¶k‘¶kŽ¶k‹¶kˆ¶k…¶k‚¶k¶k|¶ky¶kv¶ks¶kp¶km¶kj¶kg¶kd¶ka¶k^¶k[¶kX¶kU¶kR¶kO¶kL¶kI¶kF¶kC¶k@¶k=¶k:¶k7¶k4¶k1¶k.¶k+¶k(¶k%¶k"¶k¶k¶k¶k¶k¶k¶k ¶k +¶k¶k¶k¶jþ¶jû¶jø¶jõ¶jò¶jï¶jì¶jé¶jæ¶jã¶jà¶jݶjÚ¶j׶jÔ¶jѶjζj˶jȶjŶj¶j¿¶j¼¶j¹¶j¶¶j³¶j°¶j­¶jª¶j§¶j¤¶j¡¶jž¶j›¶j˜¶j•¶j’¶j¶jŒ¶j‰¶j†¶jƒ¶j€¶j}¶jz¶jw¶jt¶jq¶jn¶jk¶jh¶je¶jb¶j_¶j\¶jY¶jV¶jS¶jP¶jM¶jJ¶jG¶jD¶jA¶j>¶j;¶j8¶j5¶j2¶j/¶j,¶j)¶j&¶j#¶j ¶j¶j¶j¶j¶j¶j¶j ¶j¶j¶j¶iÿ¶iü¶iù¶iö¶ió¶ið¶ií¶iê¶iç¶iä¶iá¶iÞ¶iÛ¶iضiÕ¶iÒ¶i϶i̶iɶiƶiöiÀ¶i½¶iº¶i·¶i´¶i±¶i®¶i«¶i¨¶i¥¶i¢¶iŸ¶iœ¶i™¶i–¶i“¶i¶i¶iŠ¶i‡¶i„¶i¶i~¶i{¶ix¶iu¶ir¶io¶il¶ii¶if¶ic¶i`¶i]¶iZ¶iW¶iT¶iQ¶iN¶iK¶iH¶iE¶iB¶i?¶i<¶i9¶i6¶i3¶i0¶i-¶i*¶i'¶i$¶i!¶i¶i¶i¶i¶i¶i¶i ¶i ¶i¶i¶i¶hý¶hú¶h÷¶hô¶hñ¶hî¶hë¶hè¶hå¶hâ¶h߶hܶhÙ¶hÖ¶hÓ¶hжhͶhʶhǶhĶhÁ¶h¾¶h»¶h¸¶hµ¶h²¶h¯¶h¬¶h©¶h¦¶h£¶h ¶h¶hš¶h—¶h”¶h‘¶hŽ¶h‹¶hˆ¶h…¶h‚¶h¶h|¶hy¶hv¶hs¶hp¶hm¶hj¶hg¶hd¶ha¶h^¶h[¶hX¶hU¶hR¶hO¶hL¶hI¶hF¶hC¶h@¶h=¶h:¶h7¶h4¶h1¶h.¶h+¶h(¶h%¶h"¶h¶h¶h¶h¶h¶h¶h ¶h +¶h¶h¶h¶gþ¶gû¶gø¶gõ¶gò¶gï¶gì¶gé¶gæ¶gã¶gà¶gݶgÚ¶g׶gÔ¶gѶgζg˶gȶgŶg¶g¿¶g¼¶g¹¶g¶¶g³¶g°¶g­¶gª¶g§¶g¤¶g¡¶gž¶g›¶g˜¶g•¶g’¶g¶gŒ¶g‰¶g†¶gƒ¶g€¶g}¶gz¶gw¶gt¶gq¶gn¶gk¶gh¶ge¶gb¶g_¶g\¶gY¶gV¶gS¶gP¶gM¶gJ¶gG¶gD¶gA¶g>¶g;¶g8¶g5¶g2¶g/¶g,¶g)¶g&¶g#¶g ¶g¶g¶g¶g¶g¶g¶g ¶g¶g¶g¶fÿ¶fü¶fù¶fö¶fó¶fð¶fí¶fê¶fç¶fä¶fá¶fÞ¶fÛ¶fضfÕ¶fÒ¶f϶f̶fɶfƶföfÀ¶f½¶fº¶f·¶f´¶f±¶f®¶f«¶f¨¶f¥¶f¢¶fŸ¶fœ¶f™¶f–¶f“¶f¶f¶fŠ¶f‡¶f„¶f¶f~¶f{¶fx¶fu¶fr¶fo¶fl¶fi¶ff¶fc¶f`¶f]¶fZ¶fW¶fT¶fQ¶fN¶fK¶fH¶fE¶fB¶f?¶f<¶f9¶f6¶f3¶f0¶f-¶f*¶f'¶f$¶f!¶f¶f¶f¶f¶f¶f¶f ¶f ¶f¶f¶f¶eý¶eú¶e÷¶eô¶eñ¶eî¶eë¶eè¶eå¶eâ¶e߶eܶeÙ¶eÖ¶eÓ¶eжeͶeʶeǶeĶeÁ¶e¾¶e»¶e¸¶eµ¶e²¶e¯¶e¬¶e©¶e¦¶e£¶e ¶e¶eš¶e—¶e”¶e‘¶eŽ¶e‹¶eˆ¶e…¶e‚¶e¶e|¶ey¶ev¶es¶ep¶em¶ej¶eg¶ed¶ea¶e^¶e[¶eX¶eU¶eR¶eO¶eL¶eI¶eF¶eC¶e@¶e=¶e:¶e7¶e4¶e1¶e.¶e+¶e(¶e%¶e"¶e¶e¶e¶e¶e¶e¶e ¶e +¶e¶e¶e¶dþ¶dû¶dø¶dõ¶dò¶dï¶dì¶dé¶dæ¶dã¶dà¶dݶdÚ¶d׶dÔ¶dѶdζd˶dȶdŶd¶d¿¶d¼¶d¹¶d¶¶d³¶d°¶d­¶dª¶d§¶d¤¶d¡¶dž¶d›¶d˜¶d•¶d’¶d¶dŒ¶d‰¶d†¶dƒ¶d€¶d}¶dz¶dw¶dt¶dq¶dn¶dk¶dh¶de¶db¶d_¶d\¶dY¶dV¶dS¶dP¶dM¶dJ¶dG¶dD¶dA¶d>¶d;¶d8¶d5¶d2¶d/¶d,¶d)¶d&¶d#¶d ¶d¶d¶d¶d¶d¶d¶d ¶d¶d¶d¶cÿ¶cü¶cù¶cö¶có¶cð¶cí¶cê¶cç¶cä¶cá¶cÞ¶cÛ¶cضcÕ¶cÒ¶c϶c̶cɶcƶcöcÀ¶c½¶cº¶c·¶c´¶c±¶c®¶c«¶c¨¶c¥¶c¢¶cŸ¶cœ¶c™¶c–¶c“¶c¶c¶cŠ¶c‡¶c„¶c¶c~¶c{¶cx¶cu¶cr¶co¶cl¶ci¶cf¶cc¶c`¶c]¶cZ¶cW¶cT¶cQ¶cN¶cK¶cH¶cE¶cB¶c?¶c<¶c9¶c6¶c3¶c0¶c-¶c*¶c'¶c$¶c!¶c¶c¶c¶c¶c¶c¶c ¶c ¶c¶c¶c¶bý¶bú¶b÷¶bô¶bñ¶bî¶bë¶bè¶bå¶bâ¶b߶bܶbÙ¶bÖ¶bÓ¶bжbͶbʶbǶbĶbÁ¶b¾¶b»¶b¸¶bµ¶b²¶b¯¶b¬¶b©¶b¦¶b£¶b ¶b¶bš¶b—¶b”¶b‘¶bŽ¶b‹¶bˆ¶b…¶b‚¶b¶b|¶by¶bv¶bs¶bp¶bm¶bj¶bg¶bd¶ba¶b^¶b[¶bX¶bU¶bR¶bO¶bL¶bI¶bF¶bC¶b@¶b=¶b:¶b7¶b4¶b1¶b.¶b+¶b(¶b%¶b"¶b¶b¶b¶b¶b¶b¶b ¶b +¶b¶b¶b¶aþ¶aû¶aø¶aõ¶aò¶aï¶aì¶aé¶aæ¶aã¶aà¶aݶaÚ¶a׶aÔ¶aѶaζa˶aȶaŶa¶a¿¶a¼¶a¹¶a¶¶a³¶a°¶a­¶aª¶a§¶a¤¶a¡¶až¶a›¶a˜¶a•¶a’¶a¶aŒ¶a‰¶a†¶aƒ¶a€¶a}¶az¶aw¶at¶aq¶an¶ak¶ah¶ae¶ab¶a_¶a\¶aY¶aV¶aS¶aP¶aM¶aJ¶aG¶aD¶aA¶a>¶a;¶a8¶a5¶a2¶a/¶a,¶a)¶a&¶a#¶a ¶a¶a¶a¶a¶a¶a¶a ¶a¶a¶a¶`ÿ¶`ü¶`ù¶`ö¶`ó¶`ð¶`í¶`ê¶`ç¶`ä¶`á¶`Þ¶`Û¶`ض`Õ¶`Ò¶`϶`̶`ɶ`ƶ`ö`À¶`½¶`º¶`·¶`´¶`±¶`®¶`«¶`¨¶`¥¶`¢¶`Ÿ¶`œ¶`™¶`–¶`“¶`¶`¶`Š¶`‡¶`„¶`¶`~¶`{¶`x¶`u¶`r¶`o¶`l¶`i¶`f¶`c¶``¶`]¶`Z¶`W¶`T¶`Q¶`N¶`K¶`H¶`E¶`B¶`?¶`<¶`9¶`6¶`3¶`0¶`-¶`*¶`'¶`$¶`!¶`¶`¶`¶`¶`¶`¶` ¶` ¶`¶`¶`¶_ý¶_ú¶_÷¶_ô¶_ñ¶_î¶_ë¶_è¶_å¶_â¶_߶_ܶ_Ù¶_Ö¶_Ó¶_ж_Ͷ_ʶ_Ƕ_Ķ_Á¶_¾¶_»¶_¸¶_µ¶_²¶_¯¶_¬¶_©¶_¦¶_£¶_ ¶_¶_š¶_—¶_”¶_‘¶_Ž¶_‹¶_ˆ¶_…¶_‚¶_¶_|¶_y¶_v¶_s¶_p¶_m¶_j¶_g¶_d¶_a¶_^¶_[¶_X¶_U¶_R¶_O¶_L¶_I¶_F¶_C¶_@¶_=¶_:¶_7¶_4¶_1¶_.¶_+¶_(¶_%¶_"¶_¶_¶_¶_¶_¶_¶_ ¶_ +¶_¶_¶_¶^þ¶^û¶^ø¶^õ¶^ò¶^ï¶^ì¶^é¶^æ¶^ã¶^à¶^ݶ^Ú¶^׶^Ô¶^Ѷ^ζ^˶^ȶ^Ŷ^¶^¿¶^¼¶^¹¶^¶¶^³¶^°¶^­¶^ª¶^§¶^¤¶^¡¶^ž¶^›¶^˜¶^•¶^’¶^¶^Œ¶^‰¶^†¶^ƒ¶^€¶^}¶^z¶^w¶^t¶^q¶^n¶^k¶^h¶^e¶^b¶^_¶^\¶^Y¶^V¶^S¶^P¶^M¶^J¶^G¶^D¶^A¶^>¶^;¶^8¶^5¶^2¶^/¶^,¶^)¶^&¶^#¶^ ¶^¶^¶^¶^¶^¶^¶^ ¶^¶^¶^¶]ÿ¶]ü¶]ù¶]ö¶]ó¶]ð¶]í¶]ê¶]ç¶]ä¶]á¶]Þ¶]Û¶]ض]Õ¶]Ò¶]϶]̶]ɶ]ƶ]ö]À¶]½¶]º¶]·¶]´¶]±¶]®¶]«¶]¨¶]¥¶]¢¶]Ÿ¶]œ¶]™¶]–¶]“¶]¶]¶]Š¶]‡¶]„¶]¶]~¶]{¶]x¶]u¶]r¶]o¶]l¶]i¶]f¶]c¶]`¶]]¶]Z¶]W¶]T¶]Q¶]N¶]K¶]H¶]E¶]B¶]?¶]<¶]9¶]6¶]3¶]0¶]-¶]*¶]'¶]$¶]!¶]¶]¶]¶]¶]¶]¶] ¶] ¶]¶]¶]¶\ý¶\ú¶\÷¶\ô¶\ñ¶\î¶\ë¶\è¶\å¶\â¶\߶\ܶ\Ù¶\Ö¶\Ó¶\ж\Ͷ\ʶ\Ƕ\Ķ\Á¶\¾¶\»¶\¸¶\µ¶\²¶\¯¶\¬¶\©¶\¦¶\£¶\ ¶\¶\š¶\—¶\”¶\‘¶\Ž¶\‹¶\ˆ¶\…¶\‚¶\¶\|¶\y¶\v¶\s¶\p¶\m¶\j¶\g¶\d¶\a¶\^¶\[¶\X¶\U¶\R¶\O¶\L¶\I¶\F¶\C¶\@¶\=¶\:¶\7¶\4¶\1¶\.¶\+¶\(¶\%¶\"¶\¶\¶\¶\¶\¶\¶\ ¶\ +¶\¶\¶\¶[þ¶[û¶[ø¶[õ¶[ò¶[ï¶[ì¶[é¶[æ¶[ã¶[à¶[ݶ[Ú¶[׶[Ô¶[Ѷ[ζ[˶[ȶ[Ŷ[¶[¿¶[¼¶[¹¶[¶¶[³¶[°¶[­¶[ª¶[§¶[¤¶[¡¶[ž¶[›¶[˜¶[•¶[’¶[¶[Œ¶[‰¶[†¶[ƒ¶[€¶[}¶[z¶[w¶[t¶[q¶[n¶[k¶[h¶[e¶[b¶[_¶[\¶[Y¶[V¶[S¶[P¶[M¶[J¶[G¶[D¶[A¶[>¶[;¶[8¶[5¶[2¶[/¶[,¶[)¶[&¶[#¶[ ¶[¶[¶[¶[¶[¶[¶[ ¶[¶[¶[¶Zÿ¶Zü¶Zù¶Zö¶Zó¶Zð¶Zí¶Zê¶Zç¶Zä¶Zá¶ZÞ¶ZÛ¶ZضZÕ¶ZÒ¶Z϶Z̶ZɶZƶZöZÀ¶Z½¶Zº¶Z·¶Z´¶Z±¶Z®¶Z«¶Z¨¶Z¥¶Z¢¶ZŸ¶Zœ¶Z™¶Z–¶Z“¶Z¶Z¶ZŠ¶Z‡¶Z„¶Z¶Z~¶Z{¶Zx¶Zu¶Zr¶Zo¶Zl¶Zi¶Zf¶Zc¶Z`¶Z]¶ZZ¶ZW¶ZT¶ZQ¶ZN¶ZK¶ZH¶ZE¶ZB¶Z?¶Z<¶Z9¶Z6¶Z3¶Z0¶Z-¶Z*¶Z'¶Z$¶Z!¶Z¶Z¶Z¶Z¶Z¶Z¶Z ¶Z ¶Z¶Z¶Z¶Yý¶Yú¶Y÷¶Yô¶Yñ¶Yî¶Yë¶Yè¶Yå¶Yâ¶Y߶YܶYÙ¶YÖ¶YÓ¶YжYͶYʶYǶYĶYÁ¶Y¾¶Y»¶Y¸¶Yµ¶Y²¶Y¯¶Y¬¶Y©¶Y¦¶Y£¶Y ¶Y¶Yš¶Y—¶Y”¶Y‘¶YŽ¶Y‹¶Yˆ¶Y…¶Y‚¶Y¶Y|¶Yy¶Yv¶Ys¶Yp¶Ym¶Yj¶Yg¶Yd¶Ya¶Y^¶Y[¶YX¶YU¶YR¶YO¶YL¶YI¶YF¶YC¶Y@¶Y=¶Y:¶Y7¶Y4¶Y1¶Y.¶Y+¶Y(¶Y%¶Y"¶Y¶Y¶Y¶Y¶Y¶Y¶Y ¶Y +¶Y¶Y¶Y¶Xþ¶Xû¶Xø¶Xõ¶Xò¶Xï¶Xì¶Xé¶Xæ¶Xã¶Xà¶XݶXÚ¶X׶XÔ¶XѶXζX˶XȶXŶX¶X¿¶X¼¶X¹¶X¶¶X³¶X°¶X­¶Xª¶X§¶X¤¶X¡¶Xž¶X›¶X˜¶X•¶X’¶X¶XŒ¶X‰¶X†¶Xƒ¶X€¶X}¶Xz¶Xw¶Xt¶Xq¶Xn¶Xk¶Xh¶Xe¶Xb¶X_¶X\¶XY¶XV¶XS¶XP¶XM¶XJ¶XG¶XD¶XA¶X>¶X;¶X8¶X5¶X2¶X/¶X,¶X)¶X&¶X#¶X ¶X¶X¶X¶X¶X¶X¶X ¶X¶X¶X¶Wÿ¶Wü¶Wù¶Wö¶Wó¶Wð¶Wí¶Wê¶Wç¶Wä¶Wá¶WÞ¶WÛ¶WضWÕ¶WÒ¶W϶W̶WɶWƶWöWÀ¶W½¶Wº¶W·¶W´¶W±¶W®¶W«¶W¨¶W¥¶W¢¶WŸ¶Wœ¶W™¶W–¶W“¶W¶W¶WŠ¶W‡¶W„¶W¶W~¶W{¶Wx¶Wu¶Wr¶Wo¶Wl¶Wi¶Wf¶Wc¶W`¶W]¶WZ¶WW¶WT¶WQ¶WN¶WK¶WH¶WE¶WB¶W?¶W<¶W9¶W6¶W3¶W0¶W-¶W*¶W'¶W$¶W!¶W¶W¶W¶W¶W¶W¶W ¶W ¶W¶W¶W¶Vý¶Vú¶V÷¶Vô¶Vñ¶Vî¶Vë¶Vè¶Vå¶Vâ¶V߶VܶVÙ¶VÖ¶VÓ¶VжVͶVʶVǶVĶVÁ¶V¾¶V»¶V¸¶Vµ¶V²¶V¯¶V¬¶V©¶V¦¶V£¶V ¶V¶Vš¶V—¶V”¶V‘¶VŽ¶V‹¶Vˆ¶V…¶V‚¶V¶V|¶Vy¶Vv¶Vs¶Vp¶Vm¶Vj¶Vg¶Vd¶Va¶V^¶V[¶VX¶VU¶VR¶VO¶VL¶VI¶VF¶VC¶V@¶V=¶V:¶V7¶V4¶V1¶V.¶V+¶V(¶V%¶V"¶V¶V¶V¶V¶V¶V¶V ¶V +¶V¶V¶V¶Uþ¶Uû¶Uø¶Uõ¶Uò¶Uï¶Uì¶Ué¶Uæ¶Uã¶Uà¶UݶUÚ¶U׶UÔ¶UѶUζU˶UȶUŶU¶U¿¶U¼¶U¹¶U¶¶U³¶U°¶U­¶Uª¶U§¶U¤¶U¡¶Už¶U›¶U˜¶U•¶U’¶U¶UŒ¶U‰¶U†¶Uƒ¶U€¶U}¶Uz¶Uw¶Ut¶Uq¶Un¶Uk¶Uh¶Ue¶Ub¶U_¶U\¶UY¶UV¶US¶UP¶UM¶UJ¶UG¶UD¶UA¶U>¶U;¶U8¶U5¶U2¶U/¶U,¶U)¶U&¶U#¶U ¶U¶U¶U¶U¶U¶U¶U ¶U¶U¶U¶Tÿ¶Tü¶Tù¶Tö¶Tó¶Tð¶Tí¶Tê¶Tç¶Tä¶Tá¶TÞ¶TÛ¶TضTÕ¶TÒ¶T϶T̶TɶTƶTöTÀ¶T½¶Tº¶T·¶T´¶T±¶T®¶T«¶T¨¶T¥¶T¢¶TŸ¶Tœ¶T™¶T–¶T“¶T¶T¶TŠ¶T‡¶T„¶T¶T~¶T{¶Tx¶Tu¶Tr¶To¶Tl¶Ti¶Tf¶Tc¶T`¶T]¶TZ¶TW¶TT¶TQ¶TN¶TK¶TH¶TE¶TB¶T?¶T<¶T9¶T6¶T3¶T0¶T-¶T*¶T'¶T$¶T!¶T¶T¶T¶T¶T¶T¶T ¶T ¶T¶T¶T¶Sý¶Sú¶S÷¶Sô¶Sñ¶Sî¶Së¶Sè¶Så¶Sâ¶S߶SܶSÙ¶SÖ¶SÓ¶SжSͶSʶSǶSĶSÁ¶S¾¶S»¶S¸¶Sµ¶S²¶S¯¶S¬¶S©¶S¦¶S£¶S ¶S¶Sš¶S—¶S”¶S‘¶SŽ¶S‹¶Sˆ¶S…¶S‚¶S¶S|¶Sy¶Sv¶Ss¶Sp¶Sm¶Sj¶Sg¶Sd¶Sa¶S^¶S[¶SX¶SU¶SR¶SO¶SL¶SI¶SF¶SC¶S@¶S=¶S:¶S7¶S4¶S1¶S.¶S+¶S(¶S%¶S"¶S¶S¶S¶S¶S¶S¶S ¶S +¶S¶S¶S¶Rþ¶Rû¶Rø¶Rõ¶Rò¶Rï¶Rì¶Ré¶Ræ¶Rã¶Rà¶RݶRÚ¶R׶RÔ¶RѶRζR˶RȶRŶR¶R¿¶R¼¶R¹¶R¶¶R³¶R°¶R­¶Rª¶R§¶R¤¶R¡¶Rž¶R›¶R˜¶R•¶R’¶R¶RŒ¶R‰¶R†¶Rƒ¶R€¶R}¶Rz¶Rw¶Rt¶Rq¶Rn¶Rk¶Rh¶Re¶Rb¶R_¶R\¶RY¶RV¶RS¶RP¶RM¶RJ¶RG¶RD¶RA¶R>¶R;¶R8¶R5¶R2¶R/¶R,¶R)¶R&¶R#¶R ¶R¶R¶R¶R¶R¶R¶R ¶R¶R¶R¶Qÿ¶Qü¶Qù¶Qö¶Qó¶Qð¶Qí¶Qê¶Qç¶Qä¶Qá¶QÞ¶QÛ¶QضQÕ¶QÒ¶Q϶Q̶QɶQƶQöQÀ¶Q½¶Qº¶Q·¶Q´¶Q±¶Q®¶Q«¶Q¨¶Q¥¶Q¢¶QŸ¶Qœ¶Q™¶Q–¶Q“¶Q¶Q¶QŠ¶Q‡¶Q„¶Q¶Q~¶Q{¶Qx¶Qu¶Qr¶Qo¶Ql¶Qi¶Qf¶Qc¶Q`¶Q]¶QZ¶QW¶QT¶QQ¶QN¶QK¶QH¶QE¶QB¶Q?¶Q<¶Q9¶Q6¶Q3¶Q0¶Q-¶Q*¶Q'¶Q$¶Q!¶Q¶Q¶Q¶Q¶Q¶Q¶Q ¶Q ¶Q¶Q¶Q¶Pý¶Pú¶P÷¶Pô¶Pñ¶Pî¶Pë¶Pè¶På¶Pâ¶P߶PܶPÙ¶PÖ¶PÓ¶PжPͶPʶPǶPĶPÁ¶P¾¶P»¶P¸¶Pµ¶P²¶P¯¶P¬¶P©¶P¦¶P£¶P ¶P¶Pš¶P—¶P”¶P‘¶PŽ¶P‹¶Pˆ¶P…¶P‚¶P¶P|¶Py¶Pv¶Ps¶Pp¶Pm¶Pj¶Pg¶Pd¶Pa¶P^¶P[¶PX¶PU¶PR¶PO¶PL¶PI¶PF¶PC¶P@¶P=¶P:¶P7¶P4¶P1¶P.¶P+¶P(¶P%¶P"¶P¶P¶P¶P¶P¶P¶P ¶P +¶P¶P¶P¶Oþ¶Oû¶Oø¶Oõ¶Oò¶Oï¶Oì¶Oé¶Oæ¶Oã¶Oà¶OݶOÚ¶O׶OÔ¶OѶOζO˶OȶOŶO¶O¿¶O¼¶O¹¶O¶¶O³¶O°¶O­¶Oª¶O§¶O¤¶O¡¶Ož¶O›¶O˜¶O•¶O’¶O¶OŒ¶O‰¶O†¶Oƒ¶O€¶O}¶Oz¶Ow¶Ot¶Oq¶On¶Ok¶Oh¶Oe¶Ob¶O_¶O\¶OY¶OV¶OS¶OP¶OM¶OJ¶OG¶OD¶OA¶O>¶O;¶O8¶O5¶O2¶O/¶O,¶O)¶O&¶O#¶O ¶O¶O¶O¶O¶O¶O¶O ¶O¶O¶O¶Nÿ¶Nü¶Nù¶Nö¶Nó¶Nð¶Ní¶Nê¶Nç¶Nä¶Ná¶NÞ¶NÛ¶NضNÕ¶NÒ¶N϶N̶NɶNƶNöNÀ¶N½¶Nº¶N·¶N´¶N±¶N®¶N«¶N¨¶N¥¶N¢¶NŸ¶Nœ¶N™¶N–¶N“¶N¶N¶NŠ¶N‡¶N„¶N¶N~¶N{¶Nx¶Nu¶Nr¶No¶Nl¶Ni¶Nf¶Nc¶N`¶N]¶NZ¶NW¶NT¶NQ¶NN¶NK¶NH¶NE¶NB¶N?¶N<¶N9¶N6¶N3¶N0¶N-¶N*¶N'¶N$¶N!¶N¶N¶N¶N¶N¶N¶N ¶N ¶N¶N¶N¶Mý¶Mú¶M÷¶Mô¶Mñ¶Mî¶Më¶Mè¶Må¶Mâ¶M߶MܶMÙ¶MÖ¶MÓ¶MжMͶMʶMǶMĶMÁ¶M¾¶M»¶M¸¶Mµ¶M²¶M¯¶M¬¶M©¶M¦¶M£¶M ¶M¶Mš¶M—¶M”¶M‘¶MŽ¶M‹¶Mˆ¶M…¶M‚¶M¶M|¶My¶Mv¶Ms¶Mp¶Mm¶Mj¶Mg¶Md¶Ma¶M^¶M[¶MX¶MU¶MR¶MO¶ML¶MI¶MF¶MC¶M@¶M=¶M:¶M7¶M4¶M1¶M.¶M+¶M(¶M%¶M"¶M¶M¶M¶M¶M¶M¶M ¶M +¶M¶M¶M¶Lþ¶Lû¶Lø¶Lõ¶Lò¶Lï¶Lì¶Lé¶Læ¶Lã¶Là¶LݶLÚ¶L׶LÔ¶LѶLζL˶LȶLŶL¶L¿¶L¼¶L¹¶L¶¶L³¶L°¶L­¶Lª¶L§¶L¤¶L¡¶Lž¶L›¶L˜¶L•¶L’¶L¶LŒ¶L‰¶L†¶Lƒ¶L€¶L}¶Lz¶Lw¶Lt¶Lq¶Ln¶Lk¶Lh¶Le¶Lb¶L_¶L\¶LY¶LV¶LS¶LP¶LM¶LJ¶LG¶LD¶LA¶L>¶L;¶L8¶L5¶L2¶L/¶L,¶L)¶L&¶L#¶L ¶L¶L¶L¶L¶L¶L¶L ¶L¶L¶L¶Kÿ¶Kü¶Kù¶Kö¶Kó¶Kð¶Kí¶Kê¶Kç¶Kä¶Ká¶KÞ¶KÛ¶KضKÕ¶KÒ¶K϶K̶KɶKƶKöKÀ¶K½¶Kº¶K·¶K´¶K±¶K®¶K«¶K¨¶K¥¶K¢¶KŸ¶Kœ¶K™¶K–¶K“¶K¶K¶KŠ¶K‡¶K„¶K¶K~¶K{¶Kx¶Ku¶Kr¶Ko¶Kl¶Ki¶Kf¶Kc¶K`¶K]¶KZ¶KW¶KT¶KQ¶KN¶KK¶KH¶KE¶KB¶K?¶K<¶K9¶K6¶K3¶K0¶K-¶K*¶K'¶K$¶K!¶K¶K¶K¶K¶K¶K¶K ¶K ¶K¶K¶K¶Jý¶Jú¶J÷¶Jô¶Jñ¶Jî¶Jë¶Jè¶Jå¶Jâ¶J߶JܶJÙ¶JÖ¶JÓ¶JжJͶJʶJǶJĶJÁ¶J¾¶J»¶J¸¶Jµ¶J²¶J¯¶J¬¶J©¶J¦¶J£¶J ¶J¶Jš¶J—¶J”¶J‘¶JŽ¶J‹¶Jˆ¶J…¶J‚¶J¶J|¶Jy¶Jv¶Js¶Jp¶Jm¶Jj¶Jg¶Jd¶Ja¶J^¶J[¶JX¶JU¶JR¶JO¶JL¶JI¶JF¶JC¶J@¶J=¶J:¶J7¶J4¶J1¶J.¶J+¶J(¶J%¶J"¶J¶J¶J¶J¶J¶J¶J ¶J +¶J¶J¶J¶Iþ¶Iû¶Iø¶Iõ¶Iò¶Iï¶Iì¶Ié¶Iæ¶Iã¶Ià¶IݶIÚ¶I׶IÔ¶IѶIζI˶IȶIŶI¶I¿¶I¼¶I¹¶I¶¶I³¶I°¶I­¶Iª¶I§¶I¤¶I¡¶Iž¶I›¶I˜¶I•¶I’¶I¶IŒ¶I‰¶I†¶Iƒ¶I€¶I}¶Iz¶Iw¶It¶Iq¶In¶Ik¶Ih¶Ie¶Ib¶I_¶I\¶IY¶IV¶IS¶IP¶IM¶IJ¶IG¶ID¶IA¶I>¶I;¶I8¶I5¶I2¶I/¶I,¶I)¶I&¶I#¶I ¶I¶I¶I¶I¶I¶I¶I ¶I¶I¶I¶Hÿ¶Hü¶Hù¶Hö¶Hó¶Hð¶Hí¶Hê¶Hç¶Hä¶Há¶HÞ¶HÛ¶HضHÕ¶HÒ¶H϶H̶HɶHƶHöHÀ¶H½¶Hº¶H·¶H´¶H±¶H®¶H«¶H¨¶H¥¶H¢¶HŸ¶Hœ¶H™¶H–¶H“¶H¶H¶HŠ¶H‡¶H„¶H¶H~¶H{¶Hx¶Hu¶Hr¶Ho¶Hl¶Hi¶Hf¶Hc¶H`¶H]¶HZ¶HW¶HT¶HQ¶HN¶HK¶HH¶HE¶HB¶H?¶H<¶H9¶H6¶H3¶H0¶H-¶H*¶H'¶H$¶H!¶H¶H¶H¶H¶H¶H¶H ¶H ¶H¶H¶H¶Gý¶Gú¶G÷¶Gô¶Gñ¶Gî¶Gë¶Gè¶Gå¶Gâ¶G߶GܶGÙ¶GÖ¶GÓ¶GжGͶGʶGǶGĶGÁ¶G¾¶G»¶G¸¶Gµ¶G²¶G¯¶G¬¶G©¶G¦¶G£¶G ¶G¶Gš¶G—¶G”¶G‘¶GŽ¶G‹¶Gˆ¶G…¶G‚¶G¶G|¶Gy¶Gv¶Gs¶Gp¶Gm¶Gj¶Gg¶Gd¶Ga¶G^¶G[¶GX¶GU¶GR¶GO¶GL¶GI¶GF¶GC¶G@¶G=¶G:¶G7¶G4¶G1¶G.¶G+¶G(¶G%¶G"¶G¶G¶G¶G¶G¶G¶G ¶G +¶G¶G¶G¶Fþ¶Fû¶Fø¶Fõ¶Fò¶Fï¶Fì¶Fé¶Fæ¶Fã¶Fà¶FݶFÚ¶F׶FÔ¶FѶFζF˶FȶFŶF¶F¿¶F¼¶F¹¶F¶¶F³¶F°¶F­¶Fª¶F§¶F¤¶F¡¶Fž¶F›¶F˜¶F•¶F’¶F¶FŒ¶F‰¶F†¶Fƒ¶F€¶F}¶Fz¶Fw¶Ft¶Fq¶Fn¶Fk¶Fh¶Fe¶Fb¶F_¶F\¶FY¶FV¶FS¶FP¶FM¶FJ¶FG¶FD¶FA¶F>¶F;¶F8¶F5¶F2¶F/¶F,¶F)¶F&¶F#¶F ¶F¶F¶F¶F¶F¶F¶F ¶F¶F¶F¶Eÿ¶Eü¶Eù¶Eö¶Eó¶Eð¶Eí¶Eê¶Eç¶Eä¶Eá¶EÞ¶EÛ¶EضEÕ¶EÒ¶E϶E̶EɶEƶEöEÀ¶E½¶Eº¶E·¶E´¶E±¶E®¶E«¶E¨¶E¥¶E¢¶EŸ¶Eœ¶E™¶E–¶E“¶E¶E¶EŠ¶E‡¶E„¶E¶E~¶E{¶Ex¶Eu¶Er¶Eo¶El¶Ei¶Ef¶Ec¶E`¶E]¶EZ¶EW¶ET¶EQ¶EN¶EK¶EH¶EE¶EB¶E?¶E<¶E9¶E6¶E3¶E0¶E-¶E*¶E'¶E$¶E!¶E¶E¶E¶E¶E¶E¶E ¶E ¶E¶E¶E¶Dý¶Dú¶D÷¶Dô¶Dñ¶Dî¶Dë¶Dè¶Då¶Dâ¶D߶DܶDÙ¶DÖ¶DÓ¶DжDͶDʶDǶDĶDÁ¶D¾¶D»¶D¸¶Dµ¶D²¶D¯¶D¬¶D©¶D¦¶D£¶D ¶D¶Dš¶D—¶D”¶D‘¶DŽ¶D‹¶Dˆ¶D…¶D‚¶D¶D|¶Dy¶Dv¶Ds¶Dp¶Dm¶Dj¶Dg¶Dd¶Da¶D^¶D[¶DX¶DU¶DR¶DO¶DL¶DI¶DF¶DC¶D@¶D=¶D:¶D7¶D4¶D1¶D.¶D+¶D(¶D%¶D"¶D¶D¶D¶D¶D¶D¶D ¶D +¶D¶D¶D¶Cþ¶Cû¶Cø¶Cõ¶Cò¶Cï¶Cì¶Cé¶Cæ¶Cã¶Cà¶CݶCÚ¶C׶CÔ¶CѶCζC˶CȶCŶC¶C¿¶C¼¶C¹¶C¶¶C³¶C°¶C­¶Cª¶C§¶C¤¶C¡¶Cž¶C›¶C˜¶C•¶C’¶C¶CŒ¶C‰¶C†¶Cƒ¶C€¶C}¶Cz¶Cw¶Ct¶Cq¶Cn¶Ck¶Ch¶Ce¶Cb¶C_¶C\¶CY¶CV¶CS¶CP¶CM¶CJ¶CG¶CD¶CA¶C>¶C;¶C8¶C5¶C2¶C/¶C,¶C)¶C&¶C#¶C ¶C¶C¶C¶C¶C¶C¶C ¶C¶C¶C¶Bÿ¶Bü¶Bù¶Bö¶Bó¶Bð¶Bí¶Bê¶Bç¶Bä¶Bá¶BÞ¶BÛ¶BضBÕ¶BÒ¶B϶B̶BɶBƶBöBÀ¶B½¶Bº¶B·¶B´¶B±¶B®¶B«¶B¨¶B¥¶B¢¶BŸ¶Bœ¶B™¶B–¶B“¶B¶B¶BŠ¶B‡¶B„¶B¶B~¶B{¶Bx¶Bu¶Br¶Bo¶Bl¶Bi¶Bf¶Bc¶B`¶B]¶BZ¶BW¶BT¶BQ¶BN¶BK¶BH¶BE¶BB¶B?¶B<¶B9¶B6¶B3¶B0¶B-¶B*¶B'¶B$¶B!¶B¶B¶B¶B¶B¶B¶B ¶B ¶B¶B¶B¶Aý¶Aú¶A÷¶Aô¶Añ¶Aî¶Aë¶Aè¶Aå¶Aâ¶A߶AܶAÙ¶AÖ¶AÓ¶AжAͶAʶAǶAĶAÁ¶A¾¶A»¶A¸¶Aµ¶A²¶A¯¶A¬¶A©¶A¦¶A£¶A ¶A¶Aš¶A—¶A”¶A‘¶AŽ¶A‹¶Aˆ¶A…¶A‚¶A¶A|¶Ay¶Av¶As¶Ap¶Am¶Aj¶Ag¶Ad¶Aa¶A^¶A[¶AX¶AU¶AR¶AO¶AL¶AI¶AF¶AC¶A@¶A=¶A:¶A7¶A4¶A1¶A.¶A+¶A(¶A%¶A"¶A¶A¶A¶A¶A¶A¶A ¶A +¶A¶A¶A¶@þ¶@û¶@ø¶@õ¶@ò¶@ï¶@ì¶@é¶@æ¶@ã¶@à¶@ݶ@Ú¶@׶@Ô¶@Ѷ@ζ@˶@ȶ@Ŷ@¶@¿¶@¼¶@¹¶@¶¶@³¶@°¶@­¶@ª¶@§¶@¤¶@¡¶@ž¶@›¶@˜¶@•¶@’¶@¶@Œ¶@‰¶@†¶@ƒ¶@€¶þ¶ü¶ú¶ø¶ö¶ô¶ò¶ð¶î¶ì¶ê¶è¶æ¶ä¶â¶à¶Þ¶Ü¶Ú¶Ø¶Ö¶Ô¶Ò¶Ð¶Î¶Ì¶Ê¶È¶Æ¶Ä¶Â¶À¶¾¶¼¶º¶¸¶¶¶´¶²¶°¶®¶¬¶ª¶¨¶¦¶¤¶¢¶ ¶ž¶œ¶š¶˜¶–¶”¶’¶¶Ž¶Œ¶Š¶ˆ¶†¶„¶‚¶€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/a8468104c65a6002fd3a9d4ac39f3ee34c21ce4a b/third_party/libwebm/source/webm_parser/fuzzing/corpus/a8468104c65a6002fd3a9d4ac39f3ee34c21ce4a new file mode 100644 index 000000000000..9b15205b0f01 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/a8468104c65a6002fd3a9d4ac39f3ee34c21ce4a @@ -0,0 +1 @@ +S€gTÃgŠss‡cÀ„hÊÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/a899424027f1d69a05384355858311a6fa3940a3 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/a899424027f1d69a05384355858311a6fa3940a3 new file mode 100644 index 000000000000..3ef41ca7db10 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/a899424027f1d69a05384355858311a6fa3940a3 @@ -0,0 +1 @@ +S€gT®kˆ®†à„T° \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/a8a5de5a86a16952aacdf602120f27807294c3ec b/third_party/libwebm/source/webm_parser/fuzzing/corpus/a8a5de5a86a16952aacdf602120f27807294c3ec new file mode 100644 index 000000000000..865b44e18eb8 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/a8a5de5a86a16952aacdf602120f27807294c3ec @@ -0,0 +1 @@ +S€g‘TÃgŒss‰cÀ†hʃ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/aa65229e62d7cb8048d2f5911226b177e8e53cab b/third_party/libwebm/source/webm_parser/fuzzing/corpus/aa65229e62d7cb8048d2f5911226b177e8e53cab new file mode 100644 index 000000000000..80476c0b5e41 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/aa65229e62d7cb8048d2f5911226b177e8e53cab @@ -0,0 +1 @@ +S€gŠT®k…®ƒ×ÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/aaa96713f8ccb0bbd5c8e91715d4b86e7b338676 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/aaa96713f8ccb0bbd5c8e91715d4b86e7b338676 new file mode 100644 index 000000000000..1fa146d48d18 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/aaa96713f8ccb0bbd5c8e91715d4b86e7b338676 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/aae6354e5ba12ee3ad89fabfd72f5368a639d30f b/third_party/libwebm/source/webm_parser/fuzzing/corpus/aae6354e5ba12ee3ad89fabfd72f5368a639d30f new file mode 100644 index 000000000000..fb16013b54bd Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/aae6354e5ba12ee3ad89fabfd72f5368a639d30f differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/ab6f3dc497f93f251ebacc153409b1eb8e05e2db b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ab6f3dc497f93f251ebacc153409b1eb8e05e2db new file mode 100644 index 000000000000..182a5d9aa82b --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ab6f3dc497f93f251ebacc153409b1eb8e05e2db @@ -0,0 +1 @@ +EߣˆB‚ÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/abf5b18d1c1155d3e455c8b781948498f364965e b/third_party/libwebm/source/webm_parser/fuzzing/corpus/abf5b18d1c1155d3e455c8b781948498f364965e new file mode 100644 index 000000000000..e8c81d096d90 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/abf5b18d1c1155d3e455c8b781948498f364965e differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/abfe5dbf594a2f22173fae7ca8de28b4e3a40099 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/abfe5dbf594a2f22173fae7ca8de28b4e3a40099 new file mode 100644 index 000000000000..f0c009cdff3f --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/abfe5dbf594a2f22173fae7ca8de28b4e3a40099 @@ -0,0 +1 @@ +S€gŒT®k‡®…àƒ°ÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/ac842f2cc55d7f193273a35f8af3521bfe2317d0 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ac842f2cc55d7f193273a35f8af3521bfe2317d0 new file mode 100644 index 000000000000..77a070c56821 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ac842f2cc55d7f193273a35f8af3521bfe2317d0 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/ac923c36dd85ff5cb2a0c5b29c701999c5f2eaa0 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ac923c36dd85ff5cb2a0c5b29c701999c5f2eaa0 new file mode 100644 index 000000000000..6375039eb601 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ac923c36dd85ff5cb2a0c5b29c701999c5f2eaa0 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/acc6e100b519d6408a8c6d8aed19203d874a187a b/third_party/libwebm/source/webm_parser/fuzzing/corpus/acc6e100b519d6408a8c6d8aed19203d874a187a new file mode 100644 index 000000000000..2a83db526b15 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/acc6e100b519d6408a8c6d8aed19203d874a187a differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/aceb250195867e7d9bbf6eb6e0055251e4bb5d67 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/aceb250195867e7d9bbf6eb6e0055251e4bb5d67 new file mode 100644 index 000000000000..c75ee54bcba1 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/aceb250195867e7d9bbf6eb6e0055251e4bb5d67 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/acf1dd17e6a2848dfe17fb0d76cef2ce7d59ebdd b/third_party/libwebm/source/webm_parser/fuzzing/corpus/acf1dd17e6a2848dfe17fb0d76cef2ce7d59ebdd new file mode 100644 index 000000000000..3f65b28e9a2e --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/acf1dd17e6a2848dfe17fb0d76cef2ce7d59ebdd @@ -0,0 +1 @@ +S€gTÃgŠss‡cÀ„hÊ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/ad94c2bda2ae4afa0f7264070fd642bf37aae596 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ad94c2bda2ae4afa0f7264070fd642bf37aae596 new file mode 100644 index 000000000000..038d2d960882 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ad94c2bda2ae4afa0f7264070fd642bf37aae596 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/adad2ca7ab313add6e955f704719e03d5229e4d0 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/adad2ca7ab313add6e955f704719e03d5229e4d0 new file mode 100644 index 000000000000..2105af1f86eb --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/adad2ca7ab313add6e955f704719e03d5229e4d0 @@ -0,0 +1 @@ +ã \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/adb1f8cd3b68c076d81311071aee2a1c3785c7cb b/third_party/libwebm/source/webm_parser/fuzzing/corpus/adb1f8cd3b68c076d81311071aee2a1c3785c7cb new file mode 100644 index 000000000000..4710f7fa08d0 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/adb1f8cd3b68c076d81311071aee2a1c3785c7cb @@ -0,0 +1 @@ +S€gŒT®k‡®…œƒ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/ade30c327d9f51daf37cb3e39fdb15125b84a257 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ade30c327d9f51daf37cb3e39fdb15125b84a257 new file mode 100644 index 000000000000..4bc05f44a597 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ade30c327d9f51daf37cb3e39fdb15125b84a257 @@ -0,0 +1 @@ +S€gT®kˆ®†à„S¸ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/ae783661f52d36f9d6b87c8394ee6f2d61dae640 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ae783661f52d36f9d6b87c8394ee6f2d61dae640 new file mode 100644 index 000000000000..d5fe0e25baf9 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ae783661f52d36f9d6b87c8394ee6f2d61dae640 @@ -0,0 +1 @@ +S€g“M›tŽM»‹S«ˆMatroska \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/ae8da06c3c69076c06108219e19c8b36dba05a5c b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ae8da06c3c69076c06108219e19c8b36dba05a5c new file mode 100644 index 000000000000..78a347afda00 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ae8da06c3c69076c06108219e19c8b36dba05a5c @@ -0,0 +1 @@ +Eߣ8S€g;€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/aec8a29238dba3c37f45f2e2e4e64b0e7fa60a74 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/aec8a29238dba3c37f45f2e2e4e64b0e7fa60a74 new file mode 100644 index 000000000000..359bfe65e803 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/aec8a29238dba3c37f45f2e2e4e64b0e7fa60a74 @@ -0,0 +1 @@ +S€gI©f‹D‰ˆ?ùãw›—ô¨ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/affba8e4061bf260b1bdf8a815675cc3b4ebefa5 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/affba8e4061bf260b1bdf8a815675cc3b4ebefa5 new file mode 100644 index 000000000000..94b2f2d3efe5 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/affba8e4061bf260b1bdf8a815675cc3b4ebefa5 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/b01c4e2657a230e2b600a20da6f107b0dfe2467c b/third_party/libwebm/source/webm_parser/fuzzing/corpus/b01c4e2657a230e2b600a20da6f107b0dfe2467c new file mode 100644 index 000000000000..de433e07aa1d --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/b01c4e2657a230e2b600a20da6f107b0dfe2467c @@ -0,0 +1 @@ +S€gTÃgŠss‡gÈ„Dz! \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/b0798ecae4d9e56eefb0c1d95b657865938e62d6 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/b0798ecae4d9e56eefb0c1d95b657865938e62d6 new file mode 100644 index 000000000000..f323a5ed7a2a Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/b0798ecae4d9e56eefb0c1d95b657865938e62d6 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/b0ab4f92df810edf4371baad1d4bbd95d360c607 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/b0ab4f92df810edf4371baad1d4bbd95d360c607 new file mode 100644 index 000000000000..02f58e20212a --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/b0ab4f92df810edf4371baad1d4bbd95d360c607 @@ -0,0 +1 @@ +S€gŒC¶u‡ …›ƒ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/b14e5f5f6d29b6b71e7fec03eaf7d8237c0c6b2e b/third_party/libwebm/source/webm_parser/fuzzing/corpus/b14e5f5f6d29b6b71e7fec03eaf7d8237c0c6b2e new file mode 100644 index 000000000000..32796f0599c2 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/b14e5f5f6d29b6b71e7fec03eaf7d8237c0c6b2e differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/b1708df7f6dee0f2feb11f8b6330be0fcffc1f58 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/b1708df7f6dee0f2feb11f8b6330be0fcffc1f58 new file mode 100644 index 000000000000..4a4eccf2dbba Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/b1708df7f6dee0f2feb11f8b6330be0fcffc1f58 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/b1af4f4e86890fad6fac96a23956405c550778be b/third_party/libwebm/source/webm_parser/fuzzing/corpus/b1af4f4e86890fad6fac96a23956405c550778be new file mode 100644 index 000000000000..77bb0f015648 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/b1af4f4e86890fad6fac96a23956405c550778be differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/b1efd9e687d79e3f5a75eba02bd80bedb72350ba b/third_party/libwebm/source/webm_parser/fuzzing/corpus/b1efd9e687d79e3f5a75eba02bd80bedb72350ba new file mode 100644 index 000000000000..348fa2cfb3e9 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/b1efd9e687d79e3f5a75eba02bd80bedb72350ba differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/b25b0fbf46cef1d888fe900445c9ab95330f44cd b/third_party/libwebm/source/webm_parser/fuzzing/corpus/b25b0fbf46cef1d888fe900445c9ab95330f44cd new file mode 100644 index 000000000000..b59c5945f9f6 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/b25b0fbf46cef1d888fe900445c9ab95330f44cd @@ -0,0 +1 @@ +™ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/b2786e0b9d6e7b39165eb4e87e3110362e9e6660 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/b2786e0b9d6e7b39165eb4e87e3110362e9e6660 new file mode 100644 index 000000000000..6004cde05e03 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/b2786e0b9d6e7b39165eb4e87e3110362e9e6660 @@ -0,0 +1 @@ +EߣˆB‚@webmS€g©C¶u¤ç@«@ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/b332536a77d6efcd379cfc2f9828291516cc1ff4 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/b332536a77d6efcd379cfc2f9828291516cc1ff4 new file mode 100644 index 000000000000..20826470d462 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/b332536a77d6efcd379cfc2f9828291516cc1ff4 @@ -0,0 +1 @@ +S€g–T®k‘®m€Œb@‰P5†Gçƒ'è€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/b33962eca397f59591dbb9668e622cf99f2d7cda b/third_party/libwebm/source/webm_parser/fuzzing/corpus/b33962eca397f59591dbb9668e622cf99f2d7cda new file mode 100644 index 000000000000..9f6ee1d38de5 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/b33962eca397f59591dbb9668e622cf99f2d7cda differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/b38b6e93da1b43441f88aa53370a9f00b35c3326 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/b38b6e93da1b43441f88aa53370a9f00b35c3326 new file mode 100644 index 000000000000..7700315242dc Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/b38b6e93da1b43441f88aa53370a9f00b35c3326 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/b3e01674a1e4dd78e748782fcfc3add5523f51d8 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/b3e01674a1e4dd78e748782fcfc3add5523f51d8 new file mode 100644 index 000000000000..34164076ecce --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/b3e01674a1e4dd78e748782fcfc3add5523f51d8 @@ -0,0 +1 @@ +× \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/b53e7ef9aad70fcd80986696ebc586c03495b8ed b/third_party/libwebm/source/webm_parser/fuzzing/corpus/b53e7ef9aad70fcd80986696ebc586c03495b8ed new file mode 100644 index 000000000000..ee865d870be6 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/b53e7ef9aad70fcd80986696ebc586c03495b8ed @@ -0,0 +1 @@ +GáEߣˆB‚@webmS€g£*M'›t€I©f€C¶u€TSkk»€®€C§p€TÀ†g€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/b540412c01f960f95edd2a1bc03f1b4447f2b4f2 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/b540412c01f960f95edd2a1bc03f1b4447f2b4f2 new file mode 100644 index 000000000000..b77bc28047a8 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/b540412c01f960f95edd2a1bc03f1b4447f2b4f2 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/b62c2c591db32b26e997aa4ece577742db84428a b/third_party/libwebm/source/webm_parser/fuzzing/corpus/b62c2c591db32b26e997aa4ece577742db84428a new file mode 100644 index 000000000000..64a70accefa9 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/b62c2c591db32b26e997aa4ece577742db84428a @@ -0,0 +1 @@ +S€g“C¶uŽ ŒŽ‡èƒÌè€Ì \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/b62d99583f30c15c3c2dbed2f69c5e45075d7640 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/b62d99583f30c15c3c2dbed2f69c5e45075d7640 new file mode 100644 index 000000000000..edf7ec3ed605 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/b62d99583f30c15c3c2dbed2f69c5e45075d7640 @@ -0,0 +1 @@ +{©€gˆC¶uƒ« \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/b62f98976c11d79674b019ea78a7ce4d6d78b479 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/b62f98976c11d79674b019ea78a7ce4d6d78b479 new file mode 100644 index 000000000000..6a4f18607c79 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/b62f98976c11d79674b019ea78a7ce4d6d78b479 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/b6787dabeb5cd64ac85f1ec5a7cbeecfd48b2c5f b/third_party/libwebm/source/webm_parser/fuzzing/corpus/b6787dabeb5cd64ac85f1ec5a7cbeecfd48b2c5f new file mode 100644 index 000000000000..d04309562a69 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/b6787dabeb5cd64ac85f1ec5a7cbeecfd48b2c5f @@ -0,0 +1 @@ +S€g¼C§p·E¹´¶‘|°…@hello€€€€€€€€€…@B€@…@C¶@ sÄ€€€€€€„€–€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/b82ebcf4d09ba28d835cb9667da603e46e3438eb b/third_party/libwebm/source/webm_parser/fuzzing/corpus/b82ebcf4d09ba28d835cb9667da603e46e3438eb new file mode 100644 index 000000000000..cea92d654374 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/b82ebcf4d09ba28d835cb9667da603e46e3438eb @@ -0,0 +1 @@ +S€gC§p‹E¹ˆ¶†€„C~! \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/b85c6bc2473aa12e22f91db3546dfa9d85d8b3d1 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/b85c6bc2473aa12e22f91db3546dfa9d85d8b3d1 new file mode 100644 index 000000000000..5f82c67367f7 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/b85c6bc2473aa12e22f91db3546dfa9d85d8b3d1 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/b86e98660980680890bcbf02cacdf568d530fa64 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/b86e98660980680890bcbf02cacdf568d530fa64 new file mode 100644 index 000000000000..207162b0fcfa Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/b86e98660980680890bcbf02cacdf568d530fa64 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/b8d9beea35762009941189674c2cfcd14f81254a b/third_party/libwebm/source/webm_parser/fuzzing/corpus/b8d9beea35762009941189674c2cfcd14f81254a new file mode 100644 index 000000000000..25ec34a2745b --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/b8d9beea35762009941189674c2cfcd14f81254a @@ -0,0 +1 @@ +S€gŒT®k‡®…ˆƒ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/ba517141fc9a468142a8d03d4ee395b4d4f30edc b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ba517141fc9a468142a8d03d4ee395b4d4f30edc new file mode 100644 index 000000000000..aaea60de440b --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ba517141fc9a468142a8d03d4ee395b4d4f30edc @@ -0,0 +1 @@ +S€cŽDg‰ss†cS€g‡SÀ»€gÈk€‚»€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/bb0a596017cfc2185505d28065ab3cd238d0e2ea b/third_party/libwebm/source/webm_parser/fuzzing/corpus/bb0a596017cfc2185505d28065ab3cd238d0e2ea new file mode 100644 index 000000000000..1379811f3349 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/bb0a596017cfc2185505d28065ab3cd238d0e2ea @@ -0,0 +1 @@ +S€gˆC§pƒE¹€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/bb6232815b373e441e2acfcca015f75c680eafac b/third_party/libwebm/source/webm_parser/fuzzing/corpus/bb6232815b373e441e2acfcca015f75c680eafac new file mode 100644 index 000000000000..04a597c1fd89 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/bb6232815b373e441e2acfcca015f75c680eafac differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/bbdf4fa36ba9d645399f72c74033fd9c2631aebb b/third_party/libwebm/source/webm_parser/fuzzing/corpus/bbdf4fa36ba9d645399f72c74033fd9c2631aebb new file mode 100644 index 000000000000..d277d551df46 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/bbdf4fa36ba9d645399f72c74033fd9c2631aebb @@ -0,0 +1 @@ +C|€C|€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/bc53c9f93974b4f13382c1d49b1e3ec374005ee2 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/bc53c9f93974b4f13382c1d49b1e3ec374005ee2 new file mode 100644 index 000000000000..795792f18252 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/bc53c9f93974b4f13382c1d49b1e3ec374005ee2 @@ -0,0 +1 @@ +S€gŒT®k‡®…ƒƒ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/bcacc9bcd3b9cc7dbda9c52c6e4a06a756a9de90 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/bcacc9bcd3b9cc7dbda9c52c6e4a06a756a9de90 new file mode 100644 index 000000000000..b31cda9003ef Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/bcacc9bcd3b9cc7dbda9c52c6e4a06a756a9de90 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/bcc55f432bcf39c6ffc6d7e950612b35e9ea2ec8 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/bcc55f432bcf39c6ffc6d7e950612b35e9ea2ec8 new file mode 100644 index 000000000000..1fb28332ca21 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/bcc55f432bcf39c6ffc6d7e950612b35e9ea2ec8 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/bdb1cc868d6ced390f5d35c5f43da9f464fac464 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/bdb1cc868d6ced390f5d35c5f43da9f464fac464 new file mode 100644 index 000000000000..44bb8cdefaaf --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/bdb1cc868d6ced390f5d35c5f43da9f464fac464 @@ -0,0 +1 @@ +S€g»TÃg¶ss³gÈ©È„#‡dgÈ„]‡egÈ„D‡dgÈ„]‡egÈ„D‡gÈ€D‡dgÈ€g \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/bf67bb08e0abde692748031c297bc1c7910542f4 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/bf67bb08e0abde692748031c297bc1c7910542f4 new file mode 100644 index 000000000000..8705e840a040 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/bf67bb08e0abde692748031c297bc1c7910542f4 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/bfc07c62ef2770d53d9188b260f531a8128a5c5e b/third_party/libwebm/source/webm_parser/fuzzing/corpus/bfc07c62ef2770d53d9188b260f531a8128a5c5e new file mode 100644 index 000000000000..341f94d40eda Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/bfc07c62ef2770d53d9188b260f531a8128a5c5e differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/bfed121df31ff73b770ed7f27fc7f4da2fa73e0c b/third_party/libwebm/source/webm_parser/fuzzing/corpus/bfed121df31ff73b770ed7f27fc7f4da2fa73e0c new file mode 100644 index 000000000000..7b2c56135ecc Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/bfed121df31ff73b770ed7f27fc7f4da2fa73e0c differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/c01816206d93691165e6e3a1924cf9fbc9cf39bd b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c01816206d93691165e6e3a1924cf9fbc9cf39bd new file mode 100644 index 000000000000..b99d57aef0ef --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c01816206d93691165e6e3a1924cf9fbc9cf39bd @@ -0,0 +1 @@ +S€–gT®k‘®m€Œb@‰P5ÿ†GçƒGè€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/c02be525edae59ad9d0d9dcbd790629dc9aaee9b b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c02be525edae59ad9d0d9dcbd790629dc9aaee9b new file mode 100644 index 000000000000..67629fee4e08 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c02be525edae59ad9d0d9dcbd790629dc9aaee9b differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/c094ce0c13ee9a4ca37817d9f7dddc11b2d60177 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c094ce0c13ee9a4ca37817d9f7dddc11b2d60177 new file mode 100644 index 000000000000..9b44fb09eaeb --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c094ce0c13ee9a4ca37817d9f7dddc11b2d60177 @@ -0,0 +1 @@ +S€g‘C¶uŒ Š¡‡¦…î:ƒ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/c0aab5486ad2e80bcc12fca9fb6653984aa68274 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c0aab5486ad2e80bcc12fca9fb6653984aa68274 new file mode 100644 index 000000000000..d643dc17a03c --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c0aab5486ad2e80bcc12fca9fb6653984aa68274 @@ -0,0 +1 @@ +Eߣÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/c13ca850db259c032cf24cdf6f2833c9d74529d0 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c13ca850db259c032cf24cdf6f2833c9d74529d0 new file mode 100644 index 000000000000..46ddda2ab261 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c13ca850db259c032cf24cdf6f2833c9d74529d0 @@ -0,0 +1 @@ +EߣˆB‚@webmS€g©C¶uÿÿÿ€« \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/c1a8da6cdc8988e6a69961413803acbd1ee935e0 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c1a8da6cdc8988e6a69961413803acbd1ee935e0 new file mode 100644 index 000000000000..80a14f76ff89 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c1a8da6cdc8988e6a69961413803acbd1ee935e0 @@ -0,0 +1 @@ +S€g½C§p¸E¹µ¶³sÄVTA‘@’@€@…@B€@…@C¶@sĶ@sĶ@sÄ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/c25abc82a0470129f2d098ac65fabf34c4e11188 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c25abc82a0470129f2d098ac65fabf34c4e11188 new file mode 100644 index 000000000000..774e5f1d44e6 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c25abc82a0470129f2d098ac65fabf34c4e11188 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/c2787d2cf1d95cbcd8b9bcd15d50f67f7e92ad9f b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c2787d2cf1d95cbcd8b9bcd15d50f67f7e92ad9f new file mode 100644 index 000000000000..53359f3c570f Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c2787d2cf1d95cbcd8b9bcd15d50f67f7e92ad9f differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/c2895ff545ebdc4140951c0ca956524d7a364b77 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c2895ff545ebdc4140951c0ca956524d7a364b77 new file mode 100644 index 000000000000..61489a2e4a29 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c2895ff545ebdc4140951c0ca956524d7a364b77 @@ -0,0 +1 @@ +²Eߣ‡B \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/c2cc55849ff4858bf80f1a4713187618d14a496d b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c2cc55849ff4858bf80f1a4713187618d14a496d new file mode 100644 index 000000000000..b511eed4bf18 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c2cc55849ff4858bf80f1a4713187618d14a496d differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/c2d63b1d75cf53ee3b955bb143036ca93ef3a256 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c2d63b1d75cf53ee3b955bb143036ca93ef3a256 new file mode 100644 index 000000000000..3fbf8e455f7c Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c2d63b1d75cf53ee3b955bb143036ca93ef3a256 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/c372a27f78a62ebc013958fa4953a8bc792db53c b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c372a27f78a62ebc013958fa4953a8bc792db53c new file mode 100644 index 000000000000..8faacee041f8 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c372a27f78a62ebc013958fa4953a8bc792db53c @@ -0,0 +1 @@ +Eߣÿÿÿÿÿÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/c392963b395a7f92b3bef63fd34bc31ecd3029f3 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c392963b395a7f92b3bef63fd34bc31ecd3029f3 new file mode 100644 index 000000000000..91487caa5785 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c392963b395a7f92b3bef63fd34bc31ecd3029f3 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/c3b2749ab6c4d303bfd5da9ea9c8807e9f92d259 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c3b2749ab6c4d303bfd5da9ea9c8807e9f92d259 new file mode 100644 index 000000000000..e94d73726c06 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c3b2749ab6c4d303bfd5da9ea9c8807e9f92d259 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/c4dd3c8cdd8d7c95603dd67f1cd873d5f9148b29 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c4dd3c8cdd8d7c95603dd67f1cd873d5f9148b29 new file mode 100644 index 000000000000..c5fa78456dbd --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c4dd3c8cdd8d7c95603dd67f1cd873d5f9148b29 @@ -0,0 +1 @@ +< \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/c52fa8d16e520980e470d76e3fb4f6a612f0f3cf b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c52fa8d16e520980e470d76e3fb4f6a612f0f3cf new file mode 100644 index 000000000000..d614d4517234 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c52fa8d16e520980e470d76e3fb4f6a612f0f3cf differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/c56fb214efcd707e6fa68b803d9e7686fc2f4336 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c56fb214efcd707e6fa68b803d9e7686fc2f4336 new file mode 100644 index 000000000000..e03fe14ec1f5 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c56fb214efcd707e6fa68b803d9e7686fc2f4336 @@ -0,0 +1 @@ +S€g½C§p¸E¹µ¶žsÄVTA‘@’@€@…@B€@…@C¶@sĶ@sĶ@sÄ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/c5902afe54998ebc5d8d59043227d379a8c2eee0 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c5902afe54998ebc5d8d59043227d379a8c2eee0 new file mode 100644 index 000000000000..d71d57311e3d Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c5902afe54998ebc5d8d59043227d379a8c2eee0 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/c6a16abeea323833079e97b1830610aa6c6eba91 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c6a16abeea323833079e97b1830610aa6c6eba91 new file mode 100644 index 000000000000..b48967d06577 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c6a16abeea323833079e97b1830610aa6c6eba91 @@ -0,0 +1 @@ +€gk‹®TEߣˆB‚@®‰á‡xµ„@ÉÛwebmS€g©C¶uÿÿÿ€« \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/c6fcfd2a1f91a7f6a8c124f2637e60645be01006 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c6fcfd2a1f91a7f6a8c124f2637e60645be01006 new file mode 100644 index 000000000000..5aaebfbfad5e Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c6fcfd2a1f91a7f6a8c124f2637e60645be01006 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/c75b02a90370df1f54de2f63a4da8db22f2cf719 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c75b02a90370df1f54de2f63a4da8db22f2cf719 new file mode 100644 index 000000000000..0cb101b2669a --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c75b02a90370df1f54de2f63a4da8db22f2cf719 @@ -0,0 +1 @@ +ŸEßE£‚B; \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/c77cb763d73db279aebfb42d2b5dca3d705d3df7 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c77cb763d73db279aebfb42d2b5dca3d705d3df7 new file mode 100644 index 000000000000..cae00316302d Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c77cb763d73db279aebfb42d2b5dca3d705d3df7 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/c864ac8bce0353ecc7d5cb0ce5a1e77a5239201e b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c864ac8bce0353ecc7d5cb0ce5a1e77a5239201e new file mode 100644 index 000000000000..d74502749303 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c864ac8bce0353ecc7d5cb0ce5a1e77a5239201e @@ -0,0 +1 @@ + ÿM \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/c877c08a79a7408aed779d4a430c5db1bce26314 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c877c08a79a7408aed779d4a430c5db1bce26314 new file mode 100644 index 000000000000..de29891d259b --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c877c08a79a7408aed779d4a430c5db1bce26314 @@ -0,0 +1 @@ +S€gŒI©f‡D‰„@ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/c8aff6e2e2dfb18be385483b871ac86ff6eac63f b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c8aff6e2e2dfb18be385483b871ac86ff6eac63f new file mode 100644 index 000000000000..d553636e9bdc Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c8aff6e2e2dfb18be385483b871ac86ff6eac63f differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/c8c1c1f970bc809a75ad076bdb06275b6f72d078 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c8c1c1f970bc809a75ad076bdb06275b6f72d078 new file mode 100644 index 000000000000..f2f8214fa3a6 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c8c1c1f970bc809a75ad076bdb06275b6f72d078 @@ -0,0 +1 @@ +Eߣ„B÷ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/c995d52934ac188971f02d5dbdb3cdd70cb03267 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c995d52934ac188971f02d5dbdb3cdd70cb03267 new file mode 100644 index 000000000000..fe179c910fce --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c995d52934ac188971f02d5dbdb3cdd70cb03267 @@ -0,0 +1 @@ +Tº…éJœœœœœœ¼œ"…¼¿À>sÅœŠ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/c9e7fc3e0e1015a1c15992447f678a495c3ea5dc b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c9e7fc3e0e1015a1c15992447f678a495c3ea5dc new file mode 100644 index 000000000000..b784d77e81b6 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/c9e7fc3e0e1015a1c15992447f678a495c3ea5dc @@ -0,0 +1 @@ +S€g–C§p‘E¹Ž¶@sĶ@sÄ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/ca5b619ce1bbe23d519f5764d53458d2b85eb9fa b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ca5b619ce1bbe23d519f5764d53458d2b85eb9fa new file mode 100644 index 000000000000..a7b7c191c7fd Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ca5b619ce1bbe23d519f5764d53458d2b85eb9fa differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/cb0556c65c7381192c94324a3b1b8afb7e33fecc b/third_party/libwebm/source/webm_parser/fuzzing/corpus/cb0556c65c7381192c94324a3b1b8afb7e33fecc new file mode 100644 index 000000000000..2a7063ef0146 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/cb0556c65c7381192c94324a3b1b8afb7e33fecc differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/cb1a093e6810c7f6c002a2a54ea390cf769c9949 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/cb1a093e6810c7f6c002a2a54ea390cf769c9949 new file mode 100644 index 000000000000..6f2ab374cd29 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/cb1a093e6810c7f6c002a2a54ea390cf769c9949 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/cc1487af64aeefd7080e7678a04870dc85a7928a b/third_party/libwebm/source/webm_parser/fuzzing/corpus/cc1487af64aeefd7080e7678a04870dc85a7928a new file mode 100644 index 000000000000..815b9079dbd6 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/cc1487af64aeefd7080e7678a04870dc85a7928a differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/cc71d2c9f5eae12acee133bd9e50d84881a1bd88 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/cc71d2c9f5eae12acee133bd9e50d84881a1bd88 new file mode 100644 index 000000000000..2f87371ebbd0 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/cc71d2c9f5eae12acee133bd9e50d84881a1bd88 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/ccb8f962426683663972534c15354f70c3b34a10 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ccb8f962426683663972534c15354f70c3b34a10 new file mode 100644 index 000000000000..3b41d17a7093 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ccb8f962426683663972534c15354f70c3b34a10 @@ -0,0 +1 @@ +S€g”T®k®m€Šb@‡P5„Gáÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/cd0771c4754dfcd9c89b9b8a02df96fed974850d b/third_party/libwebm/source/webm_parser/fuzzing/corpus/cd0771c4754dfcd9c89b9b8a02df96fed974850d new file mode 100644 index 000000000000..519a31282891 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/cd0771c4754dfcd9c89b9b8a02df96fed974850d @@ -0,0 +1 @@ +’!EߣˆB‚@webm!S€g*M£'›t€I©f€C¶u€TSkk»€®€C§p€TÃg€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/cd8899c66cbd92ee57f94e000744b32662258ba3 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/cd8899c66cbd92ee57f94e000744b32662258ba3 new file mode 100644 index 000000000000..42db6e817090 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/cd8899c66cbd92ee57f94e000744b32662258ba3 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/cdf83138f69f0f7c66c13b56028610ac39038b3c b/third_party/libwebm/source/webm_parser/fuzzing/corpus/cdf83138f69f0f7c66c13b56028610ac39038b3c new file mode 100644 index 000000000000..5d6c8487ee6f --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/cdf83138f69f0f7c66c13b56028610ac39038b3c @@ -0,0 +1 @@ +€€€€€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/ce0138cd7718397b365d4c15b0b14f666c307419 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ce0138cd7718397b365d4c15b0b14f666c307419 new file mode 100644 index 000000000000..56b36df5dfc1 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ce0138cd7718397b365d4c15b0b14f666c307419 @@ -0,0 +1 @@ +Eߣ‡ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/cec5c7e50ef1d865c879563d1a6d677adb86695c b/third_party/libwebm/source/webm_parser/fuzzing/corpus/cec5c7e50ef1d865c879563d1a6d677adb86695c new file mode 100644 index 000000000000..dea66a5ba48a --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/cec5c7e50ef1d865c879563d1a6d677adb86695c @@ -0,0 +1 @@ +S€gT®kˆ®†à„Tº \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/ceff1dfaf2de4e33d2e3c20aeb7ba4b98f97784c b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ceff1dfaf2de4e33d2e3c20aeb7ba4b98f97784c new file mode 100644 index 000000000000..1826f3d96dd7 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ceff1dfaf2de4e33d2e3c20aeb7ba4b98f97784c @@ -0,0 +1 @@ +S€gŠC¶u…«ƒ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/cf04b5d28cea1971478806979b256a030a671541 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/cf04b5d28cea1971478806979b256a030a671541 new file mode 100644 index 000000000000..48b0b4c4984c --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/cf04b5d28cea1971478806979b256a030a671541 @@ -0,0 +1 @@ +S€g–T®k‘®m€Œb@‰P5†Gრ\ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/cf1cf6ad5b3554c3ffc86a859319445158665ea7 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/cf1cf6ad5b3554c3ffc86a859319445158665ea7 new file mode 100644 index 000000000000..14d1fdb04046 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/cf1cf6ad5b3554c3ffc86a859319445158665ea7 @@ -0,0 +1 @@ +S®Š€g…k\"µ;®œŸƒ× \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/cf2338960588d4a5f02a47f3ee96a556224aad75 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/cf2338960588d4a5f02a47f3ee96a556224aad75 new file mode 100644 index 000000000000..a0ed68e786a4 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/cf2338960588d4a5f02a47f3ee96a556224aad75 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/cfb09018afa0eb1a829e556d9f8bceff40cb36bc b/third_party/libwebm/source/webm_parser/fuzzing/corpus/cfb09018afa0eb1a829e556d9f8bceff40cb36bc new file mode 100644 index 000000000000..31fc35236cbf --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/cfb09018afa0eb1a829e556d9f8bceff40cb36bc @@ -0,0 +1 @@ +S€gI©f‹Daˆ4Vxš¼Þð \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/cfbe3d66d7eb3199440e8e911a93044cc3165c6c b/third_party/libwebm/source/webm_parser/fuzzing/corpus/cfbe3d66d7eb3199440e8e911a93044cc3165c6c new file mode 100644 index 000000000000..ba138c42534d Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/cfbe3d66d7eb3199440e8e911a93044cc3165c6c differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/d0a91f7984904976de592cb68e8832853fbec9bc b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d0a91f7984904976de592cb68e8832853fbec9bc new file mode 100644 index 000000000000..d61a53a0aa62 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d0a91f7984904976de592cb68e8832853fbec9bc differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/d22f52563c16725ce4a924dc05d6ac7d64798c43 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d22f52563c16725ce4a924dc05d6ac7d64798c43 new file mode 100644 index 000000000000..bf4563383c5d Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d22f52563c16725ce4a924dc05d6ac7d64798c43 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/d2709a1c9d96e72cb844eedca8bfe8440cdb0ef8 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d2709a1c9d96e72cb844eedca8bfe8440cdb0ef8 new file mode 100644 index 000000000000..c41d905e02b3 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d2709a1c9d96e72cb844eedca8bfe8440cdb0ef8 @@ -0,0 +1 @@ +S€gI©f‹Daˆþܺ˜vT2 \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/d2e385f61ad4b5d45a10a5a6cb85d72e84dea54b b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d2e385f61ad4b5d45a10a5a6cb85d72e84dea54b new file mode 100644 index 000000000000..433cbfd64221 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d2e385f61ad4b5d45a10a5a6cb85d72e84dea54b @@ -0,0 +1 @@ +@p€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/d2facb213561b30a5bcd012e4e01d0d5b0b26957 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d2facb213561b30a5bcd012e4e01d0d5b0b26957 new file mode 100644 index 000000000000..26ca8613e95e --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d2facb213561b30a5bcd012e4e01d0d5b0b26957 @@ -0,0 +1 @@ +S€gT®kŠ®ˆà†T²ƒ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/d300e5e46a825e5892fae1ba3c466c836f9e1da2 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d300e5e46a825e5892fae1ba3c466c836f9e1da2 new file mode 100644 index 000000000000..7b6f1d84b7ad Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d300e5e46a825e5892fae1ba3c466c836f9e1da2 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/d302c69c881e230e6433283007d318ba437025c3 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d302c69c881e230e6433283007d318ba437025c3 new file mode 100644 index 000000000000..055ab798c1ee --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d302c69c881e230e6433283007d318ba437025c3 @@ -0,0 +1 @@ +S€g‘T®kŒ®Šm€‡b@„P3ÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/d30c1b65bc141d1a15d4ed622ba182c96dacdf92 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d30c1b65bc141d1a15d4ed622ba182c96dacdf92 new file mode 100644 index 000000000000..aeb5e2ec6874 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d30c1b65bc141d1a15d4ed622ba182c96dacdf92 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/d3adf09fe6fb1534157c1dc68eb61365b46b1c35 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d3adf09fe6fb1534157c1dc68eb61365b46b1c35 new file mode 100644 index 000000000000..ad8336b995c9 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d3adf09fe6fb1534157c1dc68eb61365b46b1c35 @@ -0,0 +1 @@ +Eߣ’’pàÓ’ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/d3c74d3a64dba86f98a31bb726587ec97a7e4531 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d3c74d3a64dba86f98a31bb726587ec97a7e4531 new file mode 100644 index 000000000000..c2ce861d5949 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d3c74d3a64dba86f98a31bb726587ec97a7e4531 @@ -0,0 +1 @@ +€€¶€€€¶€¶€¶ÿ6€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ²€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ²€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶ÿ¶€¶€¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€€€¶€€€¶€¶€¶ÿ6€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€D¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€IIIIÿ²€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€timeout_exitcode¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€–ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ²€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€D¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€IIIIÿ²€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€timeout_exitcode¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ²€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ²€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ²€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶ÿ¶€¶€¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€€€¶€€€¶€¶€¶ÿ6€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€D¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€IIIIÿ²€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€timeout_exitcode¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€–ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ²€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€D¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€IIIIÿ²€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€timeout_exitcode¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ²€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€timeout_exit¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶ÿ¶€¶€¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€€€¶€€€¶€¶€¶ÿ6€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€D¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€IIIIÿ²€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€timeout_exitcode¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€timeout_exit¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶ÿ¶€¶€¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€€€¶€€€¶€¶€¶ÿ6€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€D¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€IIIIÿ²€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€timeout_exitcode¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€–ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ²€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€D¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€D¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€IIIIÿ²€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€timeout_exitcode¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€–ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ²€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€D¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€IIIIÿ²€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€timeout_exitcode¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ²€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€timeout_exit¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶ÿ¶€¶€¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€€€¶€€€¶€¶€¶ÿ6€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€D¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€IIIIÿ²€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€timeout_exitcode¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€–ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ²€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€D¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€IIIIÿ²€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€timeout_exitcode¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ²€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ;€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€timeout_exit¶ÿ¶€¶ÿ¶;€€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€IIIIÿ²€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€timeout_exitcode¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ²€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ;€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€timeout_exit¶ÿ¶€¶ÿ¶;€€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ²€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ€¶¶€€¶ÿ€¶€¶ÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/d3c9846ab319f12fc646c23a532c780daa9e993f b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d3c9846ab319f12fc646c23a532c780daa9e993f new file mode 100644 index 000000000000..69860029fb1e --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d3c9846ab319f12fc646c23a532c780daa9e993f @@ -0,0 +1 @@ +S€g™T®k”®’m€b@ŒP1€P2€P3€P5€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/d3f03301b52cf4a830c7dd200ed8ccbc09e6ec94 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d3f03301b52cf4a830c7dd200ed8ccbc09e6ec94 new file mode 100644 index 000000000000..3910637501cd Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d3f03301b52cf4a830c7dd200ed8ccbc09e6ec94 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/d4800745440dace38766db3520ffe7baa0bd78f2 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d4800745440dace38766db3520ffe7baa0bd78f2 new file mode 100644 index 000000000000..78d6b02b53cd Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d4800745440dace38766db3520ffe7baa0bd78f2 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/d4d6271bba704ba08c2678eb8b1bc4e457144f50 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d4d6271bba704ba08c2678eb8b1bc4e457144f50 new file mode 100644 index 000000000000..5715e682c795 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d4d6271bba704ba08c2678eb8b1bc4e457144f50 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/d54020f766061e80f445690c2b5694ed8af21e9d b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d54020f766061e80f445690c2b5694ed8af21e9d new file mode 100644 index 000000000000..d0e8288a9f52 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d54020f766061e80f445690c2b5694ed8af21e9d @@ -0,0 +1 @@ +G†\ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/d588515f125ebe968fe6a81cb6df7cfc41969e68 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d588515f125ebe968fe6a81cb6df7cfc41969e68 new file mode 100644 index 000000000000..4b30c90c8797 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d588515f125ebe968fe6a81cb6df7cfc41969e68 @@ -0,0 +1 @@ +EߣÿEߣ2 \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/d5ee5e4dc8fad9f1da43102d8322beb005a047c0 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d5ee5e4dc8fad9f1da43102d8322beb005a047c0 new file mode 100644 index 000000000000..d51648b2a91e --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d5ee5e4dc8fad9f1da43102d8322beb005a047c0 @@ -0,0 +1 @@ +Eß¾ˆB‚@webmS€g•C¶uÿÿÿÿ«@ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/d62459bb217d3050bcd9e29a6327cf81f5ed68b9 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d62459bb217d3050bcd9e29a6327cf81f5ed68b9 new file mode 100644 index 000000000000..c4ec3c43e194 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d62459bb217d3050bcd9e29a6327cf81f5ed68b9 @@ -0,0 +1 @@ +€€¶€€€¶€¶€¶ÿ6€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€ÿ¶¶€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€Óÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€ÿ¶¶€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€Óÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€ÿ¶¶€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€ÿ¶¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€ÿ¶¶€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ‚€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€Óÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€ÿ¶¶€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€ÿ¶¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€ÿ¶¶€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€ÿ¶¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€ÿ¶¶€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ‚€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€Óÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€ÿ¶¶€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€ÿ¶¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿJIII|¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€³ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶„¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€wÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶¶€¶ÿ¶€m¶ÿ¶€¶ÿ¶¶®®Ý€¶ÿ¶€¶ÿ¶€¶€µ¶€¶Œÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€å¶€¶€¶ÿ¶€Eߣ¶€¶À¶ÿ¶€m¶ÿ¶€¶ÿ¶¶®®Ý€¶ÿ¶€¶ÿ¶€¶€µ¶€¶Œÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/d6acbf1cb46845618ed0d5a322c8bd4879d16422 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d6acbf1cb46845618ed0d5a322c8bd4879d16422 new file mode 100644 index 000000000000..479a8773e7d4 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d6acbf1cb46845618ed0d5a322c8bd4879d16422 @@ -0,0 +1 @@ +S€g»TÃg¶ss³gÈ©È„#‡dgÈ„]‡egÈ„D*dgÈ„]‡egÈ„D‡gÈ€D‡dgÈg \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/d6fc8cdbb0f1517159531098e900e2dcc91edba0 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d6fc8cdbb0f1517159531098e900e2dcc91edba0 new file mode 100644 index 000000000000..d7384b79dcdb --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d6fc8cdbb0f1517159531098e900e2dcc91edba0 @@ -0,0 +1 @@ +S€g‡S»k‚»€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/d7a9bbd9875a60edf9c528b298ea72a2fad7d3d7 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d7a9bbd9875a60edf9c528b298ea72a2fad7d3d7 new file mode 100644 index 000000000000..e2c81b6263c2 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d7a9bbd9875a60edf9c528b298ea72a2fad7d3d7 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/d82e70046a544e95e81f6271dd2695f2599f0574 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d82e70046a544e95e81f6271dd2695f2599f0574 new file mode 100644 index 000000000000..a2fe29ed63c2 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d82e70046a544e95e81f6271dd2695f2599f0574 @@ -0,0 +1 @@ +S€gŽTÃg‰ss†cÀ€gÈ€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/d84bc8dca7c8fcd227254c06f5b88eaaf7cd5fde b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d84bc8dca7c8fcd227254c06f5b88eaaf7cd5fde new file mode 100644 index 000000000000..f5d0f36ac129 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d84bc8dca7c8fcd227254c06f5b88eaaf7cd5fde @@ -0,0 +1 @@ +è \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/d8bcb7dd21205e7126e700323b1d58817e9d9a6d b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d8bcb7dd21205e7126e700323b1d58817e9d9a6d new file mode 100644 index 000000000000..b32e7048f195 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d8bcb7dd21205e7126e700323b1d58817e9d9a6d differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/d8e2628b4092b9bbab4f02041647f950503eeb48 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d8e2628b4092b9bbab4f02041647f950503eeb48 new file mode 100644 index 000000000000..6aa71bd89d56 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d8e2628b4092b9bbab4f02041647f950503eeb48 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/d8ee4c2b79863a237c432efe7d43d99c8d0afb9b b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d8ee4c2b79863a237c432efe7d43d99c8d0afb9b new file mode 100644 index 000000000000..db8723cceaa7 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d8ee4c2b79863a237c432efe7d43d99c8d0afb9b differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/d8ee9724bf16ff336387723dcf27319c3be72e01 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d8ee9724bf16ff336387723dcf27319c3be72e01 new file mode 100644 index 000000000000..ce72a85b7c07 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d8ee9724bf16ff336387723dcf27319c3be72e01 @@ -0,0 +1 @@ +S€gT®kŠ®ˆà†Tºƒ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/d9379969bc956ad623e4bab8bbe47270a880a62d b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d9379969bc956ad623e4bab8bbe47270a880a62d new file mode 100644 index 000000000000..40bdf1a53e3f --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d9379969bc956ad623e4bab8bbe47270a880a62d @@ -0,0 +1 @@ +S€g‹C¶u† „u¢ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/d9ccb79b0e070dcc2f5ed8e15d99bc5ef86ecff7 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d9ccb79b0e070dcc2f5ed8e15d99bc5ef86ecff7 new file mode 100644 index 000000000000..4c2c858832c2 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/d9ccb79b0e070dcc2f5ed8e15d99bc5ef86ecff7 @@ -0,0 +1 @@ +EߣˆB‚@webmS€g©C¶u¤ç@«@£…ÿÿÿ @ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/db83586ca6266e03067e9a9772ea728ab770ad9a b/third_party/libwebm/source/webm_parser/fuzzing/corpus/db83586ca6266e03067e9a9772ea728ab770ad9a new file mode 100644 index 000000000000..0b49ef89517f Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/db83586ca6266e03067e9a9772ea728ab770ad9a differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/dcc63c06ed2790d1380bdb9281fe8677f439c76d b/third_party/libwebm/source/webm_parser/fuzzing/corpus/dcc63c06ed2790d1380bdb9281fe8677f439c76d new file mode 100644 index 000000000000..c5769be7800f Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/dcc63c06ed2790d1380bdb9281fe8677f439c76d differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/dd509e9a4660ec34b8f9dc23441c6df4ff97c34d b/third_party/libwebm/source/webm_parser/fuzzing/corpus/dd509e9a4660ec34b8f9dc23441c6df4ff97c34d new file mode 100644 index 000000000000..2a77375b70cf --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/dd509e9a4660ec34b8f9dc23441c6df4ff97c34d @@ -0,0 +1 @@ +S€g“C§pŽE¹„E¼E¹„E¼ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/dd72f8ff3a067dc7871438b6023e1ed0a4c5787b b/third_party/libwebm/source/webm_parser/fuzzing/corpus/dd72f8ff3a067dc7871438b6023e1ed0a4c5787b new file mode 100644 index 000000000000..dec5b012e936 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/dd72f8ff3a067dc7871438b6023e1ed0a4c5787b @@ -0,0 +1 @@ +S€gŽ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/dd75880c5ad488885260f4031a763c86a8084406 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/dd75880c5ad488885260f4031a763c86a8084406 new file mode 100644 index 000000000000..ad235541cb0d Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/dd75880c5ad488885260f4031a763c86a8084406 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/dd962d74d04aa4aed270fd8e6b0ae9c4ac35fd19 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/dd962d74d04aa4aed270fd8e6b0ae9c4ac35fd19 new file mode 100644 index 000000000000..dcb3af455b37 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/dd962d74d04aa4aed270fd8e6b0ae9c4ac35fd19 @@ -0,0 +1 @@ +€€¶€€€¶€¶€¶ÿ6€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€Óÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€ÿ¶¶€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€Óÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€ÿ¶¶€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€ÿ¶¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€Óÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€ÿ¶¶€¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€Óÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿö€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ–€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿJIII|¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€³ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€;€¶ÿ¶€€€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶ÿ¶€€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€¶€¶ÿ¶€¶ÿ¶€¶€wÿ¶ÿ¶€¶ÿ€€¶€¶€¶ÿ¶€¶€¶ÿ¶€¶ÿ¶€¶€¶ÿ¶€€€¶€¶€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/dd9aa9a49dd790b2ce99c5af1933232d46a7f80d b/third_party/libwebm/source/webm_parser/fuzzing/corpus/dd9aa9a49dd790b2ce99c5af1933232d46a7f80d new file mode 100644 index 000000000000..28fd4f5fe5d7 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/dd9aa9a49dd790b2ce99c5af1933232d46a7f80d @@ -0,0 +1 @@ +S€gŒI©f‡D‰„@ÉÛ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/ddad7630818a1caa8054d2d7280a1d01bdb33ca3 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ddad7630818a1caa8054d2d7280a1d01bdb33ca3 new file mode 100644 index 000000000000..5fdbe5b3e589 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ddad7630818a1caa8054d2d7280a1d01bdb33ca3 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/ddb2eaf33960ce69d579a551a7b05733adcd52aa b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ddb2eaf33960ce69d579a551a7b05733adcd52aa new file mode 100644 index 000000000000..9f07b9673a2c Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ddb2eaf33960ce69d579a551a7b05733adcd52aa differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/de0d98cb997c0a0f7be127a46d8a24d8a003931d b/third_party/libwebm/source/webm_parser/fuzzing/corpus/de0d98cb997c0a0f7be127a46d8a24d8a003931d new file mode 100644 index 000000000000..5a5f5554ae25 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/de0d98cb997c0a0f7be127a46d8a24d8a003931d differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/de0ff884898c83fb880498f1b8328f78701e6534 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/de0ff884898c83fb880498f1b8328f78701e6534 new file mode 100644 index 000000000000..b9f4c9d25963 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/de0ff884898c83fb880498f1b8328f78701e6534 @@ -0,0 +1 @@ +¦€Ý€ç¦€¦€Ý€ç¦€ÝuÝu \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/de9e0ed8ae29220e5b65e5b97eb3b254ccbe7e0c b/third_party/libwebm/source/webm_parser/fuzzing/corpus/de9e0ed8ae29220e5b65e5b97eb3b254ccbe7e0c new file mode 100644 index 000000000000..d48be42d1366 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/de9e0ed8ae29220e5b65e5b97eb3b254ccbe7e0c differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/dec5e8ffb35aa707d127a11a49e47cb59954e969 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/dec5e8ffb35aa707d127a11a49e47cb59954e969 new file mode 100644 index 000000000000..9289f7e8487c --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/dec5e8ffb35aa707d127a11a49e47cb59954e969 @@ -0,0 +1 @@ +S€gTÃgŠss‡gÈ„D‡! \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/df1b205e339e7199b5094fcf0ec3b8a8ca7a692c b/third_party/libwebm/source/webm_parser/fuzzing/corpus/df1b205e339e7199b5094fcf0ec3b8a8ca7a692c new file mode 100644 index 000000000000..337ffd01cad1 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/df1b205e339e7199b5094fcf0ec3b8a8ca7a692c differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/df254daba2299f3ff2367e284efc53a3296d136b b/third_party/libwebm/source/webm_parser/fuzzing/corpus/df254daba2299f3ff2367e284efc53a3296d136b new file mode 100644 index 000000000000..f8834a2acab3 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/df254daba2299f3ff2367e284efc53a3296d136b @@ -0,0 +1 @@ +€€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/dfdcde31231b8b3d3fd4e0ef8ea88885f488c4db b/third_party/libwebm/source/webm_parser/fuzzing/corpus/dfdcde31231b8b3d3fd4e0ef8ea88885f488c4db new file mode 100644 index 000000000000..d7b04ea457f4 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/dfdcde31231b8b3d3fd4e0ef8ea88885f488c4db differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/e01962d7dc1b94e5c4424ec7adae16a7c03b9773 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e01962d7dc1b94e5c4424ec7adae16a7c03b9773 new file mode 100644 index 000000000000..8d7f32a34129 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e01962d7dc1b94e5c4424ec7adae16a7c03b9773 @@ -0,0 +1 @@ +€€X \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/e058723f2964bf1405ae043ddb99efb17d821e15 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e058723f2964bf1405ae043ddb99efb17d821e15 new file mode 100644 index 000000000000..a2946136ac0a --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e058723f2964bf1405ae043ddb99efb17d821e15 @@ -0,0 +1 @@ +S€gC§pŠE¹‡¶…‘ƒ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/e09e306ef596dcd0e44bd3ef3c5f7019c7343f84 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e09e306ef596dcd0e44bd3ef3c5f7019c7343f84 new file mode 100644 index 000000000000..1abbf627f698 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e09e306ef596dcd0e44bd3ef3c5f7019c7343f84 @@ -0,0 +1 @@ +S€gT®k‹®‰á‡xµ„Û \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/e154eb76d096c1e545dcad591a58a02c37cd71ff b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e154eb76d096c1e545dcad591a58a02c37cd71ff new file mode 100644 index 000000000000..f575e8bfe468 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e154eb76d096c1e545dcad591a58a02c37cd71ff @@ -0,0 +1 @@ +!EߣˆB‚@webmS€g£*M'›t€I©f€C¶u€TSkk»€®€C§p€TÃg€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/e198d2e4f2f3528c2ff46d769a9281ebb3cfb44a b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e198d2e4f2f3528c2ff46d769a9281ebb3cfb44a new file mode 100644 index 000000000000..75c0df8fe21c --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e198d2e4f2f3528c2ff46d769a9281ebb3cfb44a @@ -0,0 +1 @@ +S€g”T®k®m€Šb@‡P5„Gâ!S€g”T®k®m€Šb@‡P5„Gâ!S€g›T®k–®”m€‘S€g›T®k–®”m€‘ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/e2068af1e903f4a81cd6fa5f4022e62070c259ec b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e2068af1e903f4a81cd6fa5f4022e62070c259ec new file mode 100644 index 000000000000..8ceb55924f01 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e2068af1e903f4a81cd6fa5f4022e62070c259ec differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/e2890330b5655cb277a581b8dd2eeba0d9061ba5 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e2890330b5655cb277a581b8dd2eeba0d9061ba5 new file mode 100644 index 000000000000..ffdb9c04b902 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e2890330b5655cb277a581b8dd2eeba0d9061ba5 @@ -0,0 +1 @@ +S€g”T®k®m€Šb@‡P5„Gá \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/e2e0767d055a7042c24a7acd5d5b6b7c093ad065 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e2e0767d055a7042c24a7acd5d5b6b7c093ad065 new file mode 100644 index 000000000000..145b54c473aa --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e2e0767d055a7042c24a7acd5d5b6b7c093ad065 @@ -0,0 +1 @@ +S€gŽT®k‰®‡à…ºƒ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/e394a8e21e2c43c42135daa034ad5aabb06acffb b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e394a8e21e2c43c42135daa034ad5aabb06acffb new file mode 100644 index 000000000000..3bfae2e67aa8 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e394a8e21e2c43c42135daa034ad5aabb06acffb differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/e3b200e97ec226a197e91f12103aaa53d5c37b0e b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e3b200e97ec226a197e91f12103aaa53d5c37b0e new file mode 100644 index 000000000000..a2f27b71f83b --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e3b200e97ec226a197e91f12103aaa53d5c37b0e @@ -0,0 +1 @@ +S€g½C§p¸E¹µ¶³sÄV…@¦¶@sä¶@sĶ@sĶ@sĶ@sĶ@sÄ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/e45b077cda64c380ae1b0910bc81d010c27e1c93 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e45b077cda64c380ae1b0910bc81d010c27e1c93 new file mode 100644 index 000000000000..e05b783445bb --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e45b077cda64c380ae1b0910bc81d010c27e1c93 @@ -0,0 +1 @@ +Sx€g%T:kŒ®Šm€‡b@„1 \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/e45e71ca01ebe01b01b0ca99b8f20a756c36b967 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e45e71ca01ebe01b01b0ca99b8f20a756c36b967 new file mode 100644 index 000000000000..3d1f9b0fd39e --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e45e71ca01ebe01b01b0ca99b8f20a756c36b967 @@ -0,0 +1 @@ +$ö€TÃg€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/e4ff4bd938c3737a02862fc0656a1859d384d066 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e4ff4bd938c3737a02862fc0656a1859d384d066 new file mode 100644 index 000000000000..635b8234da7b --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e4ff4bd938c3737a02862fc0656a1859d384d066 @@ -0,0 +1 @@ +S€gC§pˆE¹…¶ƒ’ÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/e5a1acb7e6f71bc1a2fedaa6173764dfd04c844c b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e5a1acb7e6f71bc1a2fedaa6173764dfd04c844c new file mode 100644 index 000000000000..ca4a19c166b5 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e5a1acb7e6f71bc1a2fedaa6173764dfd04c844c @@ -0,0 +1 @@ +S€g–T®k‘®m€Œb@‰P5†GçƒGè€S€gg—T®kÀ®m€b@ŠP5‡Gâ„;G \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/e6081eeff4ddb76e88e87ef9e4b5f199f5f11c28 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e6081eeff4ddb76e88e87ef9e4b5f199f5f11c28 new file mode 100644 index 000000000000..7b80d1b94193 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e6081eeff4ddb76e88e87ef9e4b5f199f5f11c28 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/e73c42dd266c4d9671da0c7af09e98c02fc052fd b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e73c42dd266c4d9671da0c7af09e98c02fc052fd new file mode 100644 index 000000000000..18e6ae2a8a3e Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e73c42dd266c4d9671da0c7af09e98c02fc052fd differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/e7b4559a77df21b73285243a8350b844775bb380 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e7b4559a77df21b73285243a8350b844775bb380 new file mode 100644 index 000000000000..7885c3c5d71a Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e7b4559a77df21b73285243a8350b844775bb380 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/e7dd34a80646a8c38ae1ec3a27c1358bab13b360 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e7dd34a80646a8c38ae1ec3a27c1358bab13b360 new file mode 100644 index 000000000000..8a7f10e54402 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e7dd34a80646a8c38ae1ec3a27c1358bab13b360 @@ -0,0 +1 @@ +S€gŠT®k…®ƒƒÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/e80b344f943ff0ad9219277c4578d3b4100b71dc b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e80b344f943ff0ad9219277c4578d3b4100b71dc new file mode 100644 index 000000000000..0f27b93a130a --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e80b344f943ff0ad9219277c4578d3b4100b71dc @@ -0,0 +1 @@ +Eߣÿø£b \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/e86e26200290d9d428c5e98e191ec874eb918fb6 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e86e26200290d9d428c5e98e191ec874eb918fb6 new file mode 100644 index 000000000000..dedb463b8d3b --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e86e26200290d9d428c5e98e191ec874eb918fb6 @@ -0,0 +1 @@ +S€g‘T®kŒ®Šm€‡b@„P2ÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/e873a3b8f5c3b716e6446df34279b837cf8d2c30 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e873a3b8f5c3b716e6446df34279b837cf8d2c30 new file mode 100644 index 000000000000..40a945647646 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e873a3b8f5c3b716e6446df34279b837cf8d2c30 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/e8fb71319db98d8e8cd131a4eb82879bfbec14d0 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e8fb71319db98d8e8cd131a4eb82879bfbec14d0 new file mode 100644 index 000000000000..2bf9e0dee6c8 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e8fb71319db98d8e8cd131a4eb82879bfbec14d0 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/e93c3f14614595a2675993438b4c1bfaafdc02d0 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e93c3f14614595a2675993438b4c1bfaafdc02d0 new file mode 100644 index 000000000000..b0c4d916e821 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e93c3f14614595a2675993438b4c1bfaafdc02d0 @@ -0,0 +1 @@ +S€gT®kŠ®ˆà†T³ƒ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/e93faef2d77b7c467ae280ba433928d66d63ea63 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e93faef2d77b7c467ae280ba433928d66d63ea63 new file mode 100644 index 000000000000..231c6210a31b --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e93faef2d77b7c467ae280ba433928d66d63ea63 @@ -0,0 +1 @@ +S€gT®kˆ®†à„Tºÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/e95401b11d974ba63270668d3c32c29e95ae85da b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e95401b11d974ba63270668d3c32c29e95ae85da new file mode 100644 index 000000000000..8f657f6f3a83 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e95401b11d974ba63270668d3c32c29e95ae85da @@ -0,0 +1 @@ +S€gC§pŠE¹‡¶…€ƒ… \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/e9723cebe688912f684bcd19b48e5bc8efafaf2a b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e9723cebe688912f684bcd19b48e5bc8efafaf2a new file mode 100644 index 000000000000..861afde9699e --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e9723cebe688912f684bcd19b48e5bc8efafaf2a @@ -0,0 +1 @@ +ÿÿÿ€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/e9a4389895c006d4b912e8ac1169229e6b2a66da b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e9a4389895c006d4b912e8ac1169229e6b2a66da new file mode 100644 index 000000000000..cab0d0808e6c Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e9a4389895c006d4b912e8ac1169229e6b2a66da differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/e9dc3d10b47ea580404c8e80b844a9978fcf4747 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e9dc3d10b47ea580404c8e80b844a9978fcf4747 new file mode 100644 index 000000000000..565b13feb3dc --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e9dc3d10b47ea580404c8e80b844a9978fcf4747 @@ -0,0 +1 @@ +S€gŒM›t‡M»„S« \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/e9e2ac24e5674e7ee424e2b270e5abe84f1a15c9 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e9e2ac24e5674e7ee424e2b270e5abe84f1a15c9 new file mode 100644 index 000000000000..14d396f89b25 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/e9e2ac24e5674e7ee424e2b270e5abe84f1a15c9 @@ -0,0 +1 @@ +S€gTÃgŠss‡cÀ„cÅ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/ea2b4df24b526aad253ab175334cb934b9d80b83 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ea2b4df24b526aad253ab175334cb934b9d80b83 new file mode 100644 index 000000000000..936aa37c3c2f Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ea2b4df24b526aad253ab175334cb934b9d80b83 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/ea681d11486feeab2f080b06ddd2533575b7ace4 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ea681d11486feeab2f080b06ddd2533575b7ace4 new file mode 100644 index 000000000000..e16eebaa52cf --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ea681d11486feeab2f080b06ddd2533575b7ace4 @@ -0,0 +1 @@ +S€gŽC¶u‰ ‡Ž…èƒÌÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/ebb747925360528a9f366f9a57730883c636b2c7 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ebb747925360528a9f366f9a57730883c636b2c7 new file mode 100644 index 000000000000..e6ea8c88df47 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ebb747925360528a9f366f9a57730883c636b2c7 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/ec39abab70a8e1ff072eb082caa6ca77b1ae8087 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ec39abab70a8e1ff072eb082caa6ca77b1ae8087 new file mode 100644 index 000000000000..fbefd0111a99 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ec39abab70a8e1ff072eb082caa6ca77b1ae8087 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/ecdd96d6cab2dc714a0b0ada1c4fcb18c75298e4 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ecdd96d6cab2dc714a0b0ada1c4fcb18c75298e4 new file mode 100644 index 000000000000..ed93df679dcf --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ecdd96d6cab2dc714a0b0ada1c4fcb18c75298e4 @@ -0,0 +1 @@ +S€g½C§p¸E¹µ¶³sÄV…@B€@…@C¶@sĶ@sä¶@sĶ@sĶ@sÄ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/ed008faa6c9001951f50588a1597e03931501343 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ed008faa6c9001951f50588a1597e03931501343 new file mode 100644 index 000000000000..fe1b3767bb70 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ed008faa6c9001951f50588a1597e03931501343 @@ -0,0 +1 @@ +S€gC¶uŠ ˆu¡…¦ƒî \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/ed12e272a27a2fbdbfe5a6e78e49ed722ebd3c69 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ed12e272a27a2fbdbfe5a6e78e49ed722ebd3c69 new file mode 100644 index 000000000000..a666d5172330 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ed12e272a27a2fbdbfe5a6e78e49ed722ebd3c69 @@ -0,0 +1 @@ +S€gŒT®k‡®…àƒš \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/ed799ba0608690ac68dd85c588004197b86e02bf b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ed799ba0608690ac68dd85c588004197b86e02bf new file mode 100644 index 000000000000..082e9a565b5f --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ed799ba0608690ac68dd85c588004197b86e02bf @@ -0,0 +1 @@ +S€g@äC¶u@Þ @Û¡@Øc \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/edd982c5bd3030bde8c044760e9a678c2a9306f4 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/edd982c5bd3030bde8c044760e9a678c2a9306f4 new file mode 100644 index 000000000000..48da75a2cf64 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/edd982c5bd3030bde8c044760e9a678c2a9306f4 @@ -0,0 +1 @@ +S€g‘T®kŒ®Šm€‡b@„P2 \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/ee82c97e35ec92ec3b0bbf911904a050b3aca633 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ee82c97e35ec92ec3b0bbf911904a050b3aca633 new file mode 100644 index 000000000000..696f0ebba6b4 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ee82c97e35ec92ec3b0bbf911904a050b3aca633 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/ef11f14feee00e3c198015e6bc76688e970e2d8c b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ef11f14feee00e3c198015e6bc76688e970e2d8c new file mode 100644 index 000000000000..414c1b37892b --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ef11f14feee00e3c198015e6bc76688e970e2d8c @@ -0,0 +1 @@ +S€g¯€ø \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/efa12e91e0d63c2353c120ca1ded7b36afbf57eb b/third_party/libwebm/source/webm_parser/fuzzing/corpus/efa12e91e0d63c2353c120ca1ded7b36afbf57eb new file mode 100644 index 000000000000..1673fc014bb3 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/efa12e91e0d63c2353c120ca1ded7b36afbf57eb differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/efa14cba9bbaf749067b7bb8515a5d8a289fa389 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/efa14cba9bbaf749067b7bb8515a5d8a289fa389 new file mode 100644 index 000000000000..7c34b9999308 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/efa14cba9bbaf749067b7bb8515a5d8a289fa389 @@ -0,0 +1 @@ +S€g‰I©f„WA! \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/eff9bf13cd33ea50a8eacc5f2839cc4b5d67b2de b/third_party/libwebm/source/webm_parser/fuzzing/corpus/eff9bf13cd33ea50a8eacc5f2839cc4b5d67b2de new file mode 100644 index 000000000000..5f0ecb9fec3e --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/eff9bf13cd33ea50a8eacc5f2839cc4b5d67b2de @@ -0,0 +1 @@ +Sg€„IŒë@D‡‰ÉÛ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/f0143756917f0b2e374bd03e731cd64168180054 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/f0143756917f0b2e374bd03e731cd64168180054 new file mode 100644 index 000000000000..6773d0f9407f --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/f0143756917f0b2e374bd03e731cd64168180054 @@ -0,0 +1 @@ +S€g‰C¶u„ ‚¢€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/f0b9dcd4e1845f774bb0f42653b11040baee0765 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/f0b9dcd4e1845f774bb0f42653b11040baee0765 new file mode 100644 index 000000000000..71caf1466ad9 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/f0b9dcd4e1845f774bb0f42653b11040baee0765 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/f1a41ceb420b6b3df50b10f27108c133d4d07508 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/f1a41ceb420b6b3df50b10f27108c133d4d07508 new file mode 100644 index 000000000000..a9c68c18ba37 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/f1a41ceb420b6b3df50b10f27108c133d4d07508 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/f39378fd978c6cdb4a8d08cdffc9034e2ca5b687 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/f39378fd978c6cdb4a8d08cdffc9034e2ca5b687 new file mode 100644 index 000000000000..76de32ce32f1 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/f39378fd978c6cdb4a8d08cdffc9034e2ca5b687 @@ -0,0 +1 @@ +S€g™T®k”®’m€b@ŒP5‰á€Gâ€Gç€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/f39707a104112d13d9d6bcfbef0efe8dfd98270c b/third_party/libwebm/source/webm_parser/fuzzing/corpus/f39707a104112d13d9d6bcfbef0efe8dfd98270c new file mode 100644 index 000000000000..95f4c2cf9e3f --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/f39707a104112d13d9d6bcfbef0efe8dfd98270c @@ -0,0 +1 @@ +· \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/f4341645a7d466113655d63c5aa00855904166c5 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/f4341645a7d466113655d63c5aa00855904166c5 new file mode 100644 index 000000000000..919b5442a444 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/f4341645a7d466113655d63c5aa00855904166c5 @@ -0,0 +1 @@ +çÄ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/f5511a42d83f94619ff8ca6c940cacc32bdc4834 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/f5511a42d83f94619ff8ca6c940cacc32bdc4834 new file mode 100644 index 000000000000..9ba5fc373fd9 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/f5511a42d83f94619ff8ca6c940cacc32bdc4834 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/f57a39fa918249e6941b4e770e15a8131ac16ea5 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/f57a39fa918249e6941b4e770e15a8131ac16ea5 new file mode 100644 index 000000000000..7387db39df8b --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/f57a39fa918249e6941b4e770e15a8131ac16ea5 @@ -0,0 +1 @@ +S€g½C§p¸E¹µ¶žsÄVTA‘@’@€@…@B€@…@C¶@sĶ@sĶ@sÄ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/f5ac272a1dbf362e265210869aaf70ca410f1703 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/f5ac272a1dbf362e265210869aaf70ca410f1703 new file mode 100644 index 000000000000..19acfefba1d3 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/f5ac272a1dbf362e265210869aaf70ca410f1703 @@ -0,0 +1 @@ +S€g‘TÃgŒss‰cÀ†cŃ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/f64c5ca1de57bcf323741f56754f53c642be8ab0 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/f64c5ca1de57bcf323741f56754f53c642be8ab0 new file mode 100644 index 000000000000..a5222e43d5a8 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/f64c5ca1de57bcf323741f56754f53c642be8ab0 @@ -0,0 +1 @@ +S€gC§p‹E¹ˆ¶†€„C|! \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/f64dcdee393b4b0a3343f8e684c9db91a6eaeb6e b/third_party/libwebm/source/webm_parser/fuzzing/corpus/f64dcdee393b4b0a3343f8e684c9db91a6eaeb6e new file mode 100644 index 000000000000..103c0aa4864e Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/f64dcdee393b4b0a3343f8e684c9db91a6eaeb6e differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/f69d2954da077043c6ae085e2771a702689314d5 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/f69d2954da077043c6ae085e2771a702689314d5 new file mode 100644 index 000000000000..8474e60c2fe7 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/f69d2954da077043c6ae085e2771a702689314d5 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/f74e2203adb9c94ba80f7cc3214e3b3040e5675d b/third_party/libwebm/source/webm_parser/fuzzing/corpus/f74e2203adb9c94ba80f7cc3214e3b3040e5675d new file mode 100644 index 000000000000..0caab7959074 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/f74e2203adb9c94ba80f7cc3214e3b3040e5675d differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/f7906e7dc01323b9d3d6e298e8dc2386c8d152f6 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/f7906e7dc01323b9d3d6e298e8dc2386c8d152f6 new file mode 100644 index 000000000000..d70e0accd88f --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/f7906e7dc01323b9d3d6e298e8dc2386c8d152f6 @@ -0,0 +1 @@ +×À€gˆ¶Cƒu« \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/f825cac511f3dc38a5ecf3aab3691b4c49ca8f0e b/third_party/libwebm/source/webm_parser/fuzzing/corpus/f825cac511f3dc38a5ecf3aab3691b4c49ca8f0e new file mode 100644 index 000000000000..8ea43ca78575 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/f825cac511f3dc38a5ecf3aab3691b4c49ca8f0e differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/f84c3f9e305172f2ae15dff0b4d955324b3a398e b/third_party/libwebm/source/webm_parser/fuzzing/corpus/f84c3f9e305172f2ae15dff0b4d955324b3a398e new file mode 100644 index 000000000000..c1987a9265e7 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/f84c3f9e305172f2ae15dff0b4d955324b3a398e differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/f87cfad97831c33610fbbe34a04369bd93862464 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/f87cfad97831c33610fbbe34a04369bd93862464 new file mode 100644 index 000000000000..c05f98fa1b6d Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/f87cfad97831c33610fbbe34a04369bd93862464 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/f8ebd7703fd3ba1a135b243fd947dbd61907d0f4 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/f8ebd7703fd3ba1a135b243fd947dbd61907d0f4 new file mode 100644 index 000000000000..1d9fee665fcf --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/f8ebd7703fd3ba1a135b243fd947dbd61907d0f4 @@ -0,0 +1 @@ +S€g“T®kŽ®Œm€‰b@†P2ƒ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/f926f6b2337650f8b518422c2f63a8869f47c742 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/f926f6b2337650f8b518422c2f63a8869f47c742 new file mode 100644 index 000000000000..c30c8d0280a4 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/f926f6b2337650f8b518422c2f63a8869f47c742 @@ -0,0 +1 @@ +S€gT®kˆ®†m€ƒb@€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/f939897b9fbe865c96020927dc81de9dc255d385 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/f939897b9fbe865c96020927dc81de9dc255d385 new file mode 100644 index 000000000000..12352de4d15c --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/f939897b9fbe865c96020927dc81de9dc255d385 @@ -0,0 +1 @@ +S€gˆC¶uƒçÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/f985f995ca7d1b691e6ae3b3ef57e8b3c7aa7129 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/f985f995ca7d1b691e6ae3b3ef57e8b3c7aa7129 new file mode 100644 index 000000000000..e35f109d0510 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/f985f995ca7d1b691e6ae3b3ef57e8b3c7aa7129 @@ -0,0 +1 @@ +€ÿm \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/fa79e8ad34cabea4d3c434cc02ea1499069fcafc b/third_party/libwebm/source/webm_parser/fuzzing/corpus/fa79e8ad34cabea4d3c434cc02ea1499069fcafc new file mode 100644 index 000000000000..ac147e830656 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/fa79e8ad34cabea4d3c434cc02ea1499069fcafc differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/fa7a8dfdd46845ab0fd9b5b7004e37d0232941bf b/third_party/libwebm/source/webm_parser/fuzzing/corpus/fa7a8dfdd46845ab0fd9b5b7004e37d0232941bf new file mode 100644 index 000000000000..858ffc50a793 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/fa7a8dfdd46845ab0fd9b5b7004e37d0232941bf @@ -0,0 +1 @@ +S€gT®kˆ®†à„T³ÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/fcb3054fde86111e2c346aa71af2456a1705902c b/third_party/libwebm/source/webm_parser/fuzzing/corpus/fcb3054fde86111e2c346aa71af2456a1705902c new file mode 100644 index 000000000000..318ea203f209 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/fcb3054fde86111e2c346aa71af2456a1705902c @@ -0,0 +1 @@ +S€g™TÃg”ss‡cÀ„hÊss‡cÀ„hÊ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/fce30dcdf2f23b14c580c282a39e065d7aacbfe8 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/fce30dcdf2f23b14c580c282a39e065d7aacbfe8 new file mode 100644 index 000000000000..394d54bd4e7c --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/fce30dcdf2f23b14c580c282a39e065d7aacbfe8 @@ -0,0 +1 @@ +S€gÿ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/fd15b8dd6c27bc65f90e1c988e0245b1ad7d51c5 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/fd15b8dd6c27bc65f90e1c988e0245b1ad7d51c5 new file mode 100644 index 000000000000..0e40a406e9b2 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/fd15b8dd6c27bc65f90e1c988e0245b1ad7d51c5 @@ -0,0 +1 @@ +S€g™T®k”®’m€b@ŒP5‰Gá€Gâ€ç€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/fd608012362d161cc7f3d30e1700c51f4ccef4ac b/third_party/libwebm/source/webm_parser/fuzzing/corpus/fd608012362d161cc7f3d30e1700c51f4ccef4ac new file mode 100644 index 000000000000..601a58506526 Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/fd608012362d161cc7f3d30e1700c51f4ccef4ac differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/fdce5b4f3a038ce7cfeee4deb9a4644edb78189a b/third_party/libwebm/source/webm_parser/fuzzing/corpus/fdce5b4f3a038ce7cfeee4deb9a4644edb78189a new file mode 100644 index 000000000000..5339393a5ab4 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/fdce5b4f3a038ce7cfeee4deb9a4644edb78189a @@ -0,0 +1,3 @@ +Ž +Ž +’’ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/fe203731ada762e02bf843b82e33daee4c2efbf5 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/fe203731ada762e02bf843b82e33daee4c2efbf5 new file mode 100644 index 000000000000..dcbe52b6ed33 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/fe203731ada762e02bf843b82e33daee4c2efbf5 @@ -0,0 +1 @@ +S€g—T®k’®m€b@ŠP5‡Gç„Gè \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/fe46e6ef4cd5788d89a101c77123387e3fc9d206 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/fe46e6ef4cd5788d89a101c77123387e3fc9d206 new file mode 100644 index 000000000000..a53ee8b77aec Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/fe46e6ef4cd5788d89a101c77123387e3fc9d206 differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/fe7ac2ef276b817af3487bab5fe089186ca0484b b/third_party/libwebm/source/webm_parser/fuzzing/corpus/fe7ac2ef276b817af3487bab5fe089186ca0484b new file mode 100644 index 000000000000..da2a10f540b7 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/fe7ac2ef276b817af3487bab5fe089186ca0484b @@ -0,0 +1 @@ +S€g‹M›t†M»ƒS¬€ \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/fe7ef7c0e835873b7b1cd780f248114f18adf13a b/third_party/libwebm/source/webm_parser/fuzzing/corpus/fe7ef7c0e835873b7b1cd780f248114f18adf13a new file mode 100644 index 000000000000..04e205c74e2c Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/fe7ef7c0e835873b7b1cd780f248114f18adf13a differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/ff5274cad94d590347d6cdba7637078f82e3d44a b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ff5274cad94d590347d6cdba7637078f82e3d44a new file mode 100644 index 000000000000..853a4840328e Binary files /dev/null and b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ff5274cad94d590347d6cdba7637078f82e3d44a differ diff --git a/third_party/libwebm/source/webm_parser/fuzzing/corpus/ffff6a92363e0e55a9688d9bc025cd8dea3b50d4 b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ffff6a92363e0e55a9688d9bc025cd8dea3b50d4 new file mode 100644 index 000000000000..975d9b36e2af --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/corpus/ffff6a92363e0e55a9688d9bc025cd8dea3b50d4 @@ -0,0 +1 @@ +S€gTÃgŠss‡gÈ„D…! \ No newline at end of file diff --git a/third_party/libwebm/source/webm_parser/fuzzing/webm.dict b/third_party/libwebm/source/webm_parser/fuzzing/webm.dict new file mode 100644 index 000000000000..7660ce80ec81 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/webm.dict @@ -0,0 +1,152 @@ +# Element IDs. +IdEbml = "\x1A\x45\xDF\xA3" +IdEbmlVersion = "\x42\x86" +IdEbmlReadVersion = "\x42\xF7" +IdEbmlMaxIdLength = "\x42\xF2" +IdEbmlMaxSizeLength = "\x42\xF3" +IdDocType = "\x42\x82" +IdDocTypeVersion = "\x42\x87" +IdDocTypeReadVersion = "\x42\x85" +IdVoid = "\xEC" +IdSegment = "\x18\x53\x80\x67" +IdSeekHead = "\x11\x4D\x9B\x74" +IdSeek = "\x4D\xBB" +IdSeekId = "\x53\xAB" +IdSeekPosition = "\x53\xAC" +IdInfo = "\x15\x49\xA9\x66" +IdTimecodeScale = "\x2A\xD7\xB1" +IdDuration = "\x44\x89" +IdDateUtc = "\x44\x61" +IdTitle = "\x7B\xA9" +IdMuxingApp = "\x4D\x80" +IdWritingApp = "\x57\x41" +IdCluster = "\x1F\x43\xB6\x75" +IdTimecode = "\xE7" +IdPrevSize = "\xAB" +IdSimpleBlock = "\xA3" +IdBlockGroup = "\xA0" +IdBlock = "\xA1" +IdBlockVirtual = "\xA2" +IdBlockAdditions = "\x75\xA1" +IdBlockMore = "\xA6" +IdBlockAddId = "\xEE" +IdBlockAdditional = "\xA5" +IdBlockDuration = "\x9B" +IdReferenceBlock = "\xFB" +IdDiscardPadding = "\x75\xA2" +IdSlices = "\x8E" +IdTimeSlice = "\xE8" +IdLaceNumber = "\xCC" +IdTracks = "\x16\x54\xAE\x6B" +IdTrackEntry = "\xAE" +IdTrackNumber = "\xD7" +IdTrackUid = "\x73\xC5" +IdTrackType = "\x83" +IdFlagEnabled = "\xB9" +IdFlagDefault = "\x88" +IdFlagForced = "\x55\xAA" +IdFlagLacing = "\x9C" +IdDefaultDuration = "\x23\xE3\x83" +IdName = "\x53\x6E" +IdLanguage = "\x22\xB5\x9C" +IdCodecId = "\x86" +IdCodecPrivate = "\x63\xA2" +IdCodecName = "\x25\x86\x88" +IdCodecDelay = "\x56\xAA" +IdSeekPreRoll = "\x56\xBB" +IdVideo = "\xE0" +IdFlagInterlaced = "\x9A" +IdStereoMode = "\x53\xB8" +IdAlphaMode = "\x53\xC0" +IdPixelWidth = "\xB0" +IdPixelHeight = "\xBA" +IdPixelCropBottom = "\x54\xAA" +IdPixelCropTop = "\x54\xBB" +IdPixelCropLeft = "\x54\xCC" +IdPixelCropRight = "\x54\xDD" +IdDisplayWidth = "\x54\xB0" +IdDisplayHeight = "\x54\xBA" +IdDisplayUnit = "\x54\xB2" +IdAspectRatioType = "\x54\xB3" +IdFrameRate = "\x23\x83\xE3" +IdColour = "\x55\xB0" +IdMatrixCoefficients = "\x55\xB1" +IdBitsPerChannel = "\x55\xB2" +IdChromaSubsamplingHorz = "\x55\xB3" +IdChromaSubsamplingVert = "\x55\xB4" +IdCbSubsamplingHorz = "\x55\xB5" +IdCbSubsamplingVert = "\x55\xB6" +IdChromaSitingHorz = "\x55\xB7" +IdChromaSitingVert = "\x55\xB8" +IdRange = "\x55\xB9" +IdTransferCharacteristics = "\x55\xBA" +IdPrimaries = "\x55\xBB" +IdMaxCll = "\x55\xBC" +IdMaxFall = "\x55\xBD" +IdMasteringMetadata = "\x55\xD0" +IdPrimaryRChromaticityX = "\x55\xD1" +IdPrimaryRChromaticityY = "\x55\xD2" +IdPrimaryGChromaticityX = "\x55\xD3" +IdPrimaryGChromaticityY = "\x55\xD4" +IdPrimaryBChromaticityX = "\x55\xD5" +IdPrimaryBChromaticityY = "\x55\xD6" +IdWhitePointChromaticityX = "\x55\xD7" +IdWhitePointChromaticityY = "\x55\xD8" +IdLuminanceMax = "\x55\xD9" +IdLuminanceMin = "\x55\xDA" +IdProjection = "\x76\x70" +IdProjectionType = "\x76\x71" +IdProjectionPrivate = "\x76\x72" +IdProjectionPoseYaw = "\x76\x73" +IdProjectionPosePitch = "\x76\x74" +IdProjectionPoseRoll = "\x76\x75" +IdAudio = "\xE1" +IdSamplingFrequency = "\xB5" +IdOutputSamplingFrequency = "\x78\xB5" +IdChannels = "\x9F" +IdBitDepth = "\x62\x64" +IdContentEncodings = "\x6D\x80" +IdContentEncoding = "\x62\x40" +IdContentEncodingOrder = "\x50\x31" +IdContentEncodingScope = "\x50\x32" +IdContentEncodingType = "\x50\x33" +IdContentEncryption = "\x50\x35" +IdContentEncAlgo = "\x47\xE1" +IdContentEncKeyId = "\x47\xE2" +IdContentEncAesSettings = "\x47\xE7" +IdAesSettingsCipherMode = "\x47\xE8" +IdCues = "\x1C\x53\xBB\x6B" +IdCuePoint = "\xBB" +IdCueTime = "\xB3" +IdCueTrackPositions = "\xB7" +IdCueTrack = "\xF7" +IdCueClusterPosition = "\xF1" +IdCueRelativePosition = "\xF0" +IdCueDuration = "\xB2" +IdCueBlockNumber = "\x53\x78" +IdChapters = "\x10\x43\xA7\x70" +IdEditionEntry = "\x45\xB9" +IdChapterAtom = "\xB6" +IdChapterUid = "\x73\xC4" +IdChapterStringUid = "\x56\x54" +IdChapterTimeStart = "\x91" +IdChapterTimeEnd = "\x92" +IdChapterDisplay = "\x80" +IdChapString = "\x85" +IdChapLanguage = "\x43\x7C" +IdChapCountry = "\x43\x7E" +IdTags = "\x12\x54\xC3\x67" +IdTag = "\x73\x73" +IdTargets = "\x63\xC0" +IdTargetTypeValue = "\x68\xCA" +IdTargetType = "\x63\xCA" +IdTagTrackUid = "\x63\xC5" +IdSimpleTag = "\x67\xC8" +IdTagName = "\x45\xA3" +IdTagLanguage = "\x44\x7A" +IdTagDefault = "\x44\x84" +IdTagString = "\x44\x87" +IdTagBinary = "\x44\x85" + +# Interesting sizes. +SizeUnknown = "\xFF" diff --git a/third_party/libwebm/source/webm_parser/fuzzing/webm_fuzzer.cc b/third_party/libwebm/source/webm_parser/fuzzing/webm_fuzzer.cc new file mode 100644 index 000000000000..bfc4f6271a63 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/fuzzing/webm_fuzzer.cc @@ -0,0 +1,76 @@ +// Copyright (c) 2016 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +#include +#include +#include +#include +#include +#include +#include + +#include "webm/buffer_reader.h" +#include "webm/callback.h" +#include "webm/file_reader.h" +#include "webm/reader.h" +#include "webm/status.h" +#include "webm/webm_parser.h" + +using webm::BufferReader; +using webm::Callback; +using webm::FileReader; +using webm::Reader; +using webm::Status; +using webm::WebmParser; + +static int Run(Reader* reader) { + Callback callback; + WebmParser parser; + +#if WEBM_FUZZER_SEEK_FIRST + parser.DidSeek(); +#endif + + Status status(-1); + try { + status = parser.Feed(&callback, reader); + } catch (std::bad_alloc&) { + // Failed allocations are okay. MSan doesn't throw std::bad_alloc, but + // someday it might. + } + + // BufferReader/FileReader should never return either of the following codes, + // which means the parser never should too: + assert(status.code != Status::kWouldBlock); + assert(status.code != Status::kOkPartial); + + // Only the following ranges have status codes defined: + assert((-1031 <= status.code && status.code <= -1025) || + (-3 <= status.code && status.code <= 0)); + + return 0; +} + +extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t* data, + std::size_t size) { + BufferReader reader(std::vector(data, data + size)); + return Run(&reader); +} + +#if __AFL_COMPILER +int main(int argc, char* argv[]) { + FILE* file = (argc == 2) ? std::fopen(argv[1], "rb") + : std::freopen(nullptr, "rb", stdin); + if (!file) { + std::cerr << "File cannot be opened\n"; + return EXIT_FAILURE; + } + + FileReader reader(file); + return Run(&reader); +} +#endif diff --git a/third_party/libwebm/source/webm_parser/include/webm/buffer_reader.h b/third_party/libwebm/source/webm_parser/include/webm/buffer_reader.h new file mode 100644 index 000000000000..d479b5cb4406 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/include/webm/buffer_reader.h @@ -0,0 +1,138 @@ +// Copyright (c) 2016 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +#ifndef INCLUDE_WEBM_BUFFER_READER_H_ +#define INCLUDE_WEBM_BUFFER_READER_H_ + +#include +#include +#include +#include + +#include "./reader.h" +#include "./status.h" + +/** + \file + A `Reader` implementation that reads from a `std::vector`. + */ + +namespace webm { + +/** + \addtogroup PUBLIC_API + @{ + */ + +/** + A simple reader that reads data from a buffer of bytes. + */ +class BufferReader : public Reader { + public: + /** + Constructs a new, empty reader. + */ + BufferReader() = default; + + /** + Constructs a new reader by copying the provided reader into the new reader. + + \param other The source reader to copy. + */ + BufferReader(const BufferReader& other) = default; + + /** + Copies the provided reader into this reader. + + \param other The source reader to copy. May be equal to `*this`, in which + case this is a no-op. + \return `*this`. + */ + BufferReader& operator=(const BufferReader& other) = default; + + /** + Constructs a new reader by moving the provided reader into the new reader. + + \param other The source reader to move. After moving, it will be reset to an + empty stream. + */ + BufferReader(BufferReader&&); + + /** + Moves the provided reader into this reader. + + \param other The source reader to move. After moving, it will be reset to an + empty stream. May be equal to `*this`, in which case this is a no-op. + \return `*this`. + */ + BufferReader& operator=(BufferReader&&); + + /** + Creates a new `BufferReader` populated with the provided bytes. + + \param bytes Bytes that are assigned to the internal buffer and used as the + source which is read from. + */ + BufferReader(std::initializer_list bytes); + + /** + Creates a new `BufferReader` populated with the provided data. + + \param vector A vector of bytes that is copied to the internal buffer and + used as the source which is read from. + */ + explicit BufferReader(const std::vector& vector); + + /** + Creates a new `BufferReader` populated with the provided data. + + \param vector A vector of bytes that is moved to the internal buffer and used + as the source which is read from. + */ + explicit BufferReader(std::vector&& vector); + + /** + Resets the reader to read from the given list of bytes, starting at the + beginning. + + This makes `reader = {1, 2, 3};` effectively equivalent to `reader = + BufferReader({1, 2, 3});`. + + \param bytes Bytes that are assigned to the internal buffer and used as the + source which is read from. + \return `*this`. + */ + BufferReader& operator=(std::initializer_list bytes); + + Status Read(std::size_t num_to_read, std::uint8_t* buffer, + std::uint64_t* num_actually_read) override; + + Status Skip(std::uint64_t num_to_skip, + std::uint64_t* num_actually_skipped) override; + + std::uint64_t Position() const override; + + /** + Gets the total size of the buffer. + */ + std::size_t size() const { return data_.size(); } + + private: + // Stores the byte buffer from which data is read. + std::vector data_; + + // The position of the reader in the byte buffer. + std::size_t pos_ = 0; +}; + +/** + @} + */ + +} // namespace webm + +#endif // INCLUDE_WEBM_BUFFER_READER_H_ diff --git a/third_party/libwebm/source/webm_parser/include/webm/callback.h b/third_party/libwebm/source/webm_parser/include/webm/callback.h new file mode 100644 index 000000000000..f70f1f89b222 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/include/webm/callback.h @@ -0,0 +1,363 @@ +// Copyright (c) 2016 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +#ifndef INCLUDE_WEBM_CALLBACK_H_ +#define INCLUDE_WEBM_CALLBACK_H_ + +#include + +#include "./dom_types.h" +#include "./reader.h" +#include "./status.h" + +/** + \file + The main callback type that receives parsing events. + */ + +namespace webm { + +/** + \addtogroup PUBLIC_API + @{ + */ + +/** + The action to be performed when parsing an element. + */ +enum class Action { + /** + Read and parse the element. + */ + kRead, + + /** + Skip the element. Skipped elements are not parsed or stored, and the callback + is not given any further notifications regarding the element. + */ + kSkip, +}; + +/** + A callback that receives parsing events. + + Every method that returns a `Status` should return `Status::kOkCompleted` when + the method has completed and parsing should continue. Returning any other value + will cause parsing to stop. Parsing may be resumed if the returned status was + not a parsing error (see `Status::is_parsing_error()`). When parsing is + resumed, the same `Callback` method will be called again. + + Methods that take a `Reader` expect the implementation to consume (either via + `Reader::Read()` or `Reader::Skip()`) the specified number of bytes before + returning `Status::kOkCompleted`. Default implementations will call + `Reader::Skip()` to skip the specified number of bytes and the resulting + `Status` will be returned (unless it's `Status::kOkPartial`, in which case + `Reader::Skip()` will be called again to skip more data). + + Throwing an exception from the member functions is permitted, though if the + exception will be caught and parsing resumed, then the reader should not + advance its position (for methods that take a `Reader`) before the exception is + thrown. When parsing is resumed, the same `Callback` method will be called + again. + + Users should derive from this class and override member methods as needed. + */ +class Callback { + public: + virtual ~Callback() = default; + + /** + Called when the parser starts a new element. This is called after the + elements ID and size has been parsed, but before any of its body has been + read (or validated). + + Defaults to `Action::kRead` and returning `Status::kOkCompleted`. + + \param metadata Metadata about the element that has just been encountered. + \param[out] action The action that should be taken when handling this + element. Will not be null. + */ + virtual Status OnElementBegin(const ElementMetadata& metadata, + Action* action); + + /** + Called when the parser encounters an unknown element. + + Defaults to calling (and returning the result of) `Reader::Skip()`. + + \param metadata Metadata about the element. + \param reader The reader that should be used to consume data. Will not be + null. + \param[in,out] bytes_remaining The number of remaining bytes that need to be + consumed for the element. Will not be null. + \return `Status::kOkCompleted` when the element has been fully consumed and + `bytes_remaining` is now zero. + */ + virtual Status OnUnknownElement(const ElementMetadata& metadata, + Reader* reader, + std::uint64_t* bytes_remaining); + + /** + Called when the parser encounters an `Id::kEbml` element and it has been + fully parsed. + + Defaults to returning `Status::kOkCompleted`. + + \param metadata Metadata about the element. + \param ebml The parsed element. + */ + virtual Status OnEbml(const ElementMetadata& metadata, const Ebml& ebml); + + /** + Called when the parser encounters an Id::kVoid element. + + Defaults to calling (and returning the result of) Reader::Skip. + + \param metadata Metadata about the element. + \param reader The reader that should be used to consume data. Will not be + null. + \param[in,out] bytes_remaining The number of remaining bytes that need to be + consumed for the element. Will not be null. + \return `Status::kOkCompleted` when the element has been fully consumed and + `bytes_remaining` is now zero. + */ + virtual Status OnVoid(const ElementMetadata& metadata, Reader* reader, + std::uint64_t* bytes_remaining); + + /** + Called when the parser starts an `Id::kSegment` element. + + Defaults to `Action::kRead` and returning `Status::kOkCompleted`. + + \param metadata Metadata about the element that has just been encountered. + \param[out] action The action that should be taken when handling this + element. Will not be null. + */ + virtual Status OnSegmentBegin(const ElementMetadata& metadata, + Action* action); + + /** + Called when the parser encounters an `Id::kSeek` element and it has been + fully parsed. + + Defaults to returning `Status::kOkCompleted`. + + \param metadata Metadata about the element. + \param seek The parsed element. + */ + virtual Status OnSeek(const ElementMetadata& metadata, const Seek& seek); + + /** + Called when the parser encounters an `Id::kInfo` element and it has been + fully parsed. + + Defaults to returning `Status::kOkCompleted`. + + \param metadata Metadata about the element. + \param info The parsed element. + */ + virtual Status OnInfo(const ElementMetadata& metadata, const Info& info); + + /** + Called when the parser starts an `Id::kCluster` element. + + Because Cluster elements should start with a Timecode (and optionally + PrevSize) child, this method is not invoked until a child BlockGroup or + SimpleBlock element is encountered (or the Cluster ends if no such child + exists). + + Defaults to `Action::kRead` and returning `Status::kOkCompleted`. + + \param metadata Metadata about the element. + \param cluster The element, as it has currently been parsed. + \param[out] action The action that should be taken when handling this + element. Will not be null. + */ + virtual Status OnClusterBegin(const ElementMetadata& metadata, + const Cluster& cluster, Action* action); + + /** + Called when the parser starts an `Id::kSimpleBlock` element. + + Defaults to `Action::kRead` and returning `Status::kOkCompleted`. + + \param metadata Metadata about the element. + \param simple_block The parsed SimpleBlock header. + \param[out] action The action that should be taken when handling this + element. Will not be null. + */ + virtual Status OnSimpleBlockBegin(const ElementMetadata& metadata, + const SimpleBlock& simple_block, + Action* action); + + /** + Called when the parser finishes an `Id::kSimpleBlock` element. + + Defaults to returning `Status::kOkCompleted`. + + \param metadata Metadata about the element. + \param simple_block The parsed SimpleBlock header. + */ + virtual Status OnSimpleBlockEnd(const ElementMetadata& metadata, + const SimpleBlock& simple_block); + + /** + Called when the parser starts an `Id::kBlockGroup` element. + + Defaults to `Action::kRead` and returning `Status::kOkCompleted`. + + \param metadata Metadata about the element. + \param[out] action The action that should be taken when handling this + element. Will not be null. + */ + virtual Status OnBlockGroupBegin(const ElementMetadata& metadata, + Action* action); + + /** + Called when the parser starts an `Id::kBlock` element. + + Defaults to `Action::kRead` and returning `Status::kOkCompleted`. + + \param metadata Metadata about the element. + \param block The parsed Block header. + \param[out] action The action that should be taken when handling this + element. Will not be null. + */ + virtual Status OnBlockBegin(const ElementMetadata& metadata, + const Block& block, Action* action); + + /** + Called when the parser finishes an `Id::Block` element. + + Defaults to returning `Status::kOkCompleted`. + + \param metadata Metadata about the element. + \param block The parsed Block header. + */ + virtual Status OnBlockEnd(const ElementMetadata& metadata, + const Block& block); + + /** + Called when the parser finishes an `Id::kBlockGroup` element. + + Defaults to returning `Status::kOkCompleted`. + + \param metadata Metadata about the element. + \param block_group The parsed element. + */ + virtual Status OnBlockGroupEnd(const ElementMetadata& metadata, + const BlockGroup& block_group); + + /** + Called when the parser encounters a frame within a `Id::kBlock` or + `Id::kSimpleBlock` element. + + Defaults to calling (and returning the result of) `Reader::Skip`. + + \param metadata Metadata about the frame. + \param reader The reader that should be used to consume data. Will not be + null. + \param[in,out] bytes_remaining The number of remaining bytes that need to be + consumed for the frame. Will not be null. + \return `Status::kOkCompleted` when the frame has been fully consumed and + `bytes_remaining` is now zero. + */ + virtual Status OnFrame(const FrameMetadata& metadata, Reader* reader, + std::uint64_t* bytes_remaining); + + /** + Called when the parser finishes an `Id::kCluster` element. + + Defaults to returning `Status::kOkCompleted`. + + \param metadata Metadata about the element. + \param cluster The parsed element. + */ + virtual Status OnClusterEnd(const ElementMetadata& metadata, + const Cluster& cluster); + + /** + Called when the parser starts an `Id::kTrackEntry` element. + + Defaults to returning `Status::kOkCompleted`. + + \param metadata Metadata about the element. + \param track_entry The parsed element. + */ + virtual Status OnTrackEntry(const ElementMetadata& metadata, + const TrackEntry& track_entry); + + /** + Called when the parser encounters an `Id::kCuePoint` element and it has been + fully parsed. + + Defaults to returning `Status::kOkCompleted`. + + \param metadata Metadata about the element. + \param cue_point The parsed element. + */ + virtual Status OnCuePoint(const ElementMetadata& metadata, + const CuePoint& cue_point); + + /** + Called when the parser encounters an `Id::kEditionEntry` element and it has + been fully parsed. + + Defaults to returning `Status::kOkCompleted`. + + \param metadata Metadata about the element. + \param edition_entry The parsed element. + */ + virtual Status OnEditionEntry(const ElementMetadata& metadata, + const EditionEntry& edition_entry); + + /** + Called when the parser encounters an `Id::kTag` element and it has been fully + parsed. + + Defaults to returning `Status::kOkCompleted`. + + \param metadata Metadata about the element. + \param tag The parsed element. + */ + virtual Status OnTag(const ElementMetadata& metadata, const Tag& tag); + + /** + Called when the parser finishes an `Id::kSegment` element. + + Defaults to returning `Status::kOkCompleted`. + + \param metadata Metadata about the element. + */ + virtual Status OnSegmentEnd(const ElementMetadata& metadata); + + protected: + /** + Calls (and returns the result of) `Reader::Skip()`, skipping (up to) the + requested number of bytes. + + Unlike `Reader::Skip()`, this method may be called with `*bytes_remaining == + 0`, which will result in `Status::kOkCompleted`. `Reader::Skip()` will be + called multiple times if it returns `Status::kOkPartial` until it returns a + different status (indicating the requested number of bytes has been fully + skipped or some error occurred). + + \param reader The reader that should be used to skip data. Must not be null. + \param[in,out] bytes_remaining The number of remaining bytes that need to be + skipped. Must not be null. May be zero. + \return The result of `Reader::Skip()`. + */ + static Status Skip(Reader* reader, std::uint64_t* bytes_remaining); +}; + +/** + @} + */ + +} // namespace webm + +#endif // INCLUDE_WEBM_CALLBACK_H_ diff --git a/third_party/libwebm/source/webm_parser/include/webm/dom_types.h b/third_party/libwebm/source/webm_parser/include/webm/dom_types.h new file mode 100644 index 000000000000..7ae4a0c3ee52 --- /dev/null +++ b/third_party/libwebm/source/webm_parser/include/webm/dom_types.h @@ -0,0 +1,1781 @@ +// Copyright (c) 2016 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +#ifndef INCLUDE_WEBM_DOM_TYPES_H_ +#define INCLUDE_WEBM_DOM_TYPES_H_ + +#include +#include +#include + +#include "./element.h" +#include "./id.h" + +/** + \file + Data structures representing parsed DOM objects. + + For more information on each type and member, see the WebM specification for + the element that each type/member represents. + */ + +namespace webm { + +/** + \addtogroup PUBLIC_API + @{ + */ + +/** + Metadata for a single frame. + */ +struct FrameMetadata { + /** + Metadata for the EBML element (\WebMID{Block} or \WebMID{SimpleBlock}) that + contains this frame. + */ + ElementMetadata parent_element; + + /** + Absolute byte position (from the beginning of the byte stream/file) of the + frame start. + */ + std::uint64_t position; + + /** + Size (in bytes) of the frame. + */ + std::uint64_t size; + + /** + Returns true if every member within the two objects are equal. + */ + bool operator==(const FrameMetadata& other) const { + return parent_element == other.parent_element && + position == other.position && size == other.size; + } +}; + +/** + A parsed \WebMID{BlockMore} element. + */ +struct BlockMore { + /** + A parsed \WebMID{BlockAddID} element. + */ + Element id{1}; + + /** + A parsed \WebMID{BlockAdditional} element. + */ + Element> data; + + /** + Returns true if every member within the two objects are equal. + */ + bool operator==(const BlockMore& other) const { + return id == other.id && data == other.data; + } +}; + +/** + A parsed \WebMID{BlockAdditions} element. + */ +struct BlockAdditions { + /** + Parsed \WebMID{BlockMore} elements. + */ + std::vector> block_mores; + + /** + Returns true if every member within the two objects are equal. + */ + bool operator==(const BlockAdditions& other) const { + return block_mores == other.block_mores; + } +}; + +/** + A parsed \WebMID{TimeSlice} element (deprecated). + */ +struct TimeSlice { + /** + A parsed \WebMID{LaceNumber} element (deprecated). + */ + Element lace_number; + + /** + Returns true if every member within the two objects are equal. + */ + bool operator==(const TimeSlice& other) const { + return lace_number == other.lace_number; + } +}; + +/** + A parsed \WebMID{Slices} element (deprecated). + */ +struct Slices { + /** + Parsed \WebMID{TimeSlice} elements (deprecated). + */ + std::vector> slices; + + /** + Returns true if every member within the two objects are equal. + */ + bool operator==(const Slices& other) const { return slices == other.slices; } +}; + +/** + A parsed \WebMID{BlockVirtual} element. + */ +struct VirtualBlock { + /** + The virtual block's track number. + */ + std::uint64_t track_number; + + /** + The timecode of the virtual block. + */ + std::int16_t timecode; + + /** + Returns true if every member within the two objects are equal. + */ + bool operator==(const VirtualBlock& other) const { + return track_number == other.track_number && timecode == other.timecode; + } +}; + +/** + The frame lacing used in a block. + */ +enum class Lacing : std::uint8_t { + /** + No lacing is used. + */ + kNone = 0x00, + + /** + Xiph-style lacing is used. + */ + kXiph = 0x02, + + /** + Fixed-lacing is used, where each frame has the same, fixed size. + */ + kFixed = 0x04, + + /** + EBML-style lacing is used. + */ + kEbml = 0x06, +}; + +/** + A parsed \WebMID{Block} element. + */ +struct Block { + /** + The block's track number. + */ + std::uint64_t track_number; + + /** + The number of frames in the block. + */ + int num_frames; + + /** + The timecode of the block (relative to the containing \WebMID{Cluster}'s + timecode). + */ + std::int16_t timecode; + + /** + The lacing used to store frames in the block. + */ + Lacing lacing; + + /** + True if the frames are visible, false if they are invisible. + */ + bool is_visible; + + /** + Returns true if every member within the two objects are equal. + */ + bool operator==(const Block& other) const { + return track_number == other.track_number && + num_frames == other.num_frames && timecode == other.timecode && + lacing == other.lacing && is_visible == other.is_visible; + } +}; + +/** + A parsed \WebMID{SimpleBlock} element. + */ +struct SimpleBlock : public Block { + /** + True if the frames are all key frames. + */ + bool is_key_frame; + + /** + True if frames can be discarded during playback if needed. + */ + bool is_discardable; + + /** + Returns true if every member within the two objects are equal. + */ + bool operator==(const SimpleBlock& other) const { + return Block::operator==(other) && is_key_frame == other.is_key_frame && + is_discardable == other.is_discardable; + } +}; + +/** + A parsed \WebMID{BlockGroup} element. + */ +struct BlockGroup { + /** + A parsed \WebMID{Block} element. + */ + Element block; + + /** + A parsed \WebMID{BlockVirtual} element. + */ + Element virtual_block; + + /** + A parsed \WebMID{BlockAdditions} element. + */ + Element additions; + + /** + A parsed \WebMID{BlockDuration} element. + */ + Element duration; + + /** + Parsed \WebMID{ReferenceBlock} elements. + */ + std::vector> references; + + /** + A parsed \WebMID{DiscardPadding} element. + */ + Element discard_padding; + + /** + A parsed \WebMID{Slices} element (deprecated). + */ + Element slices; + + /** + Returns true if every member within the two objects are equal. + */ + bool operator==(const BlockGroup& other) const { + return block == other.block && virtual_block == other.virtual_block && + additions == other.additions && duration == other.duration && + references == other.references && + discard_padding == other.discard_padding && slices == other.slices; + } +}; + +/** + A parsed \WebMID{Cluster} element. + */ +struct Cluster { + /** + A parsed \WebMID{Timecode} element. + */ + Element timecode; + + /** + A parsed \WebMID{PrevSize} element. + */ + Element previous_size; + + /** + Parsed \WebMID{SimpleBlock} elements. + */ + std::vector> simple_blocks; + + /** + Parsed \WebMID{BlockGroup} elements. + */ + std::vector> block_groups; + + /** + Returns true if every member within the two objects are equal. + */ + bool operator==(const Cluster& other) const { + return timecode == other.timecode && previous_size == other.previous_size && + simple_blocks == other.simple_blocks && + block_groups == other.block_groups; + } +}; + +/** + A parsed \WebMID{EBML} element. + */ +struct Ebml { + /** + A parsed \WebMID{EBMLVersion} element. + */ + Element ebml_version{1}; + + /** + A parsed \WebMID{EBMLReadVersion} element. + */ + Element ebml_read_version{1}; + + /** + A parsed \WebMID{EBMLMaxIDLength} element. + */ + Element ebml_max_id_length{4}; + + /** + A parsed \WebMID{EBMLMaxSizeLength} element. + */ + Element ebml_max_size_length{8}; + + /** + A parsed \WebMID{DocType} element. + */ + Element doc_type{"matroska"}; + + /** + A parsed \WebMID{DocTypeVersion} element. + */ + Element doc_type_version{1}; + + /** + A parsed \WebMID{DocTypeReadVersion} element. + */ + Element doc_type_read_version{1}; + + /** + Returns true if every member within the two objects are equal. + */ + bool operator==(const Ebml& other) const { + return ebml_version == other.ebml_version && + ebml_read_version == other.ebml_read_version && + ebml_max_id_length == other.ebml_max_id_length && + ebml_max_size_length == other.ebml_max_size_length && + doc_type == other.doc_type && + doc_type_version == other.doc_type_version && + doc_type_read_version == other.doc_type_read_version; + } +}; + +/** + A parsed \WebMID{Info} element. + */ +struct Info { + /** + A parsed \WebMID{TimecodeScale} element. + */ + Element timecode_scale{1000000}; + + /** + A parsed \WebMID{Duration} element. + */ + Element duration; + + /** + A parsed \WebMID{DateUTC} element. + */ + Element date_utc; + + /** + A parsed \WebMID{Title} element. + */ + Element title; + + /** + A parsed \WebMID{MuxingApp} element. + */ + Element muxing_app; + + /** + A parsed \WebMID{WritingApp} element. + */ + Element writing_app; + + /** + Returns true if every member within the two objects are equal. + */ + bool operator==(const Info& other) const { + return timecode_scale == other.timecode_scale && + duration == other.duration && date_utc == other.date_utc && + title == other.title && muxing_app == other.muxing_app && + writing_app == other.writing_app; + } +}; + +/** + A parsed \WebMID{Seek} element. + */ +struct Seek { + /** + A parsed \WebMID{SeekID} element. + */ + Element id; + + /** + A parsed \WebMID{SeekPosition} element. + */ + Element position; + + /** + Returns true if every member within the two objects are equal. + */ + bool operator==(const Seek& other) const { + return id == other.id && position == other.position; + } +}; + +/** + A parsed \WebMID{Audio} element. + */ +struct Audio { + /** + A parsed \WebMID{SamplingFrequency} element. + */ + Element sampling_frequency{8000}; + + /** + A parsed \WebMID{OutputSamplingFrequency} element. + */ + Element output_frequency{8000}; + + /** + A parsed \WebMID{Channels} element. + */ + Element channels{1}; + + /** + A parsed \WebMID{BitDepth} element. + */ + Element bit_depth; + + /** + Returns true if every member within the two objects are equal. + */ + bool operator==(const Audio& other) const { + return sampling_frequency == other.sampling_frequency && + output_frequency == other.output_frequency && + channels == other.channels && bit_depth == other.bit_depth; + } +}; + +/** + A parsed \WebMID{MasteringMetadata} element. + */ +struct MasteringMetadata { + /** + A parsed \WebMID{PrimaryRChromaticityX} element. + */ + Element primary_r_chromaticity_x; + + /** + A parsed \WebMID{PrimaryRChromaticityY} element. + */ + Element primary_r_chromaticity_y; + + /** + A parsed \WebMID{PrimaryGChromaticityX} element. + */ + Element primary_g_chromaticity_x; + + /** + A parsed \WebMID{PrimaryGChromaticityY} element. + */ + Element primary_g_chromaticity_y; + + /** + A parsed \WebMID{PrimaryBChromaticityX} element. + */ + Element primary_b_chromaticity_x; + + /** + A parsed \WebMID{PrimaryBChromaticityY} element. + */ + Element primary_b_chromaticity_y; + + /** + A parsed \WebMID{WhitePointChromaticityX} element. + */ + Element white_point_chromaticity_x; + + /** + A parsed \WebMID{WhitePointChromaticityY} element. + */ + Element white_point_chromaticity_y; + + /** + A parsed \WebMID{LuminanceMax} element. + */ + Element luminance_max; + + /** + A parsed \WebMID{LuminanceMin} element. + */ + Element luminance_min; + + /** + Returns true if every member within the two objects are equal. + */ + bool operator==(const MasteringMetadata& other) const { + return primary_r_chromaticity_x == other.primary_r_chromaticity_x && + primary_r_chromaticity_y == other.primary_r_chromaticity_y && + primary_g_chromaticity_x == other.primary_g_chromaticity_x && + primary_g_chromaticity_y == other.primary_g_chromaticity_y && + primary_b_chromaticity_x == other.primary_b_chromaticity_x && + primary_b_chromaticity_y == other.primary_b_chromaticity_y && + white_point_chromaticity_x == other.white_point_chromaticity_x && + white_point_chromaticity_y == other.white_point_chromaticity_y && + luminance_max == other.luminance_max && + luminance_min == other.luminance_min; + } +}; + +/** + A parsed \WebMID{MatrixCoefficients} element. + + Matroska/WebM adopted these values from Table 4 of ISO/IEC 23001-8:2013/DCOR1. + See that document for further details. + */ +enum class MatrixCoefficients : std::uint64_t { + /** + The identity matrix. + + Typically used for GBR (often referred to as RGB); however, may also be used + for YZX (often referred to as XYZ). + */ + kRgb = 0, + + /** + Rec. ITU-R BT.709-5. + */ + kBt709 = 1, + + /** + Image characteristics are unknown or are determined by the application. + */ + kUnspecified = 2, + + /** + United States Federal Communications Commission Title 47 Code of Federal + Regulations (2003) 73.682 (a) (20). + */ + kFcc = 4, + + /** + Rec. ITU-R BT.470‑6 System B, G (historical). + */ + kBt470Bg = 5, + + /** + Society of Motion Picture and Television Engineers 170M (2004). + */ + kSmpte170M = 6, + + /** + Society of Motion Picture and Television Engineers 240M (1999). + */ + kSmpte240M = 7, + + /** + YCgCo. + */ + kYCgCo = 8, + + /** + Rec. ITU-R BT.2020 (non-constant luminance). + */ + kBt2020NonconstantLuminance = 9, + + /** + Rec. ITU-R BT.2020 (constant luminance). + */ + kBt2020ConstantLuminance = 10, +}; + +/** + A parsed \WebMID{Range} element. + */ +enum class Range : std::uint64_t { + /** + Unspecified. + */ + kUnspecified = 0, + + /** + Broadcast range. + */ + kBroadcast = 1, + + /** + Full range (no clipping). + */ + kFull = 2, + + /** + Defined by MatrixCoefficients/TransferCharacteristics. + */ + kDerived = 3, +}; + +/** + A parsed \WebMID{TransferCharacteristics} element. + + Matroska/WebM adopted these values from Table 3 of ISO/IEC 23001-8:2013/DCOR1. + See that document for further details. + */ +enum class TransferCharacteristics : std::uint64_t { + /** + Rec. ITU-R BT.709-6. + */ + kBt709 = 1, + + /** + Image characteristics are unknown or are determined by the application. + */ + kUnspecified = 2, + + /** + Rec. ITU‑R BT.470‑6 System M (historical) with assumed display gamma 2.2. + */ + kGamma22curve = 4, + + /** + Rec. ITU‑R BT.470-6 System B, G (historical) with assumed display gamma 2.8. + */ + kGamma28curve = 5, + + /** + Society of Motion Picture and Television Engineers 170M (2004). + */ + kSmpte170M = 6, + + /** + Society of Motion Picture and Television Engineers 240M (1999). + */ + kSmpte240M = 7, + + /** + Linear transfer characteristics. + */ + kLinear = 8, + + /** + Logarithmic transfer characteristic (100:1 range). + */ + kLog = 9, + + /** + Logarithmic transfer characteristic (100 * Sqrt(10) : 1 range). + */ + kLogSqrt = 10, + + /** + IEC 61966-2-4. + */ + kIec6196624 = 11, + + /** + Rec. ITU‑R BT.1361-0 extended colour gamut system (historical). + */ + kBt1361ExtendedColourGamut = 12, + + /** + IEC 61966-2-1 sRGB or sYCC. + */ + kIec6196621 = 13, + + /** + Rec. ITU-R BT.2020-2 (10-bit system). + */ + k10BitBt2020 = 14, + + /** + Rec. ITU-R BT.2020-2 (12-bit system). + */ + k12BitBt2020 = 15, + + /** + Society of Motion Picture and Television Engineers ST 2084. + */ + kSmpteSt2084 = 16, + + /** + Society of Motion Picture and Television Engineers ST 428-1. + */ + kSmpteSt4281 = 17, + + /** + Association of Radio Industries and Businesses (ARIB) STD-B67. + */ + kAribStdB67Hlg = 18, +}; + +/** + A parsed \WebMID{Primaries} element. + + Matroska/WebM adopted these values from Table 2 of ISO/IEC 23001-8:2013/DCOR1. + See that document for further details. + */ +enum class Primaries : std::uint64_t { + /** + Rec. ITU‑R BT.709-6. + */ + kBt709 = 1, + + /** + Image characteristics are unknown or are determined by the application. + */ + kUnspecified = 2, + + /** + Rec. ITU‑R BT.470‑6 System M (historical). + */ + kBt470M = 4, + + /** + Rec. ITU‑R BT.470‑6 System B, G (historical). + */ + kBt470Bg = 5, + + /** + Society of Motion Picture and Television Engineers 170M (2004). + */ + kSmpte170M = 6, + + /** + Society of Motion Picture and Television Engineers 240M (1999). + */ + kSmpte240M = 7, + + /** + Generic film. + */ + kFilm = 8, + + /** + Rec. ITU-R BT.2020-2. + */ + kBt2020 = 9, + + /** + Society of Motion Picture and Television Engineers ST 428-1. + */ + kSmpteSt4281 = 10, + + /** + Society of Motion Picture and Television Engineers RP 431-2 (a.k.a. DCI-P3). + */ + kSmpteRp431 = 11, + + /** + Society of Motion Picture and Television Engineers EG 432-1 + (a.k.a. DCI-P3 D65). + */ + kSmpteEg432 = 12, + + /** + JEDEC P22 phosphors/EBU Tech. 3213-E (1975). + */ + kJedecP22Phosphors = 22, +}; + +/** + A parsed \WebMID{Colour} element. + */ +struct Colour { + /** + A parsed \WebMID{MatrixCoefficients} element. + */ + Element matrix_coefficients{ + MatrixCoefficients::kUnspecified}; + + /** + A parsed \WebMID{BitsPerChannel} element. + */ + Element bits_per_channel{0}; + + /** + A parsed \WebMID{ChromaSubsamplingHorz} element. + */ + Element chroma_subsampling_x; + + /** + A parsed \WebMID{ChromaSubsamplingVert} element. + */ + Element chroma_subsampling_y; + + /** + A parsed \WebMID{CbSubsamplingHorz} element. + */ + Element cb_subsampling_x; + + /** + A parsed \WebMID{CbSubsamplingVert} element. + */ + Element cb_subsampling_y; + + /** + A parsed \WebMID{ChromaSitingHorz} element. + */ + Element chroma_siting_x{0}; + + /** + A parsed \WebMID{ChromaSitingVert} element. + */ + Element chroma_siting_y{0}; + + /** + A parsed \WebMID{Range} element. + */ + Element range{Range::kUnspecified}; + + /** + A parsed \WebMID{TransferCharacteristics} element. + */ + Element transfer_characteristics{ + TransferCharacteristics::kUnspecified}; + + /** + A parsed \WebMID{Primaries} element. + */ + Element primaries{Primaries::kUnspecified}; + + /** + A parsed \WebMID{MaxCLL} element. + */ + Element max_cll; + + /** + A parsed \WebMID{MaxFALL} element. + */ + Element max_fall; + + /** + A parsed \WebMID{MasteringMetadata} element. + */ + Element mastering_metadata; + + /** + Returns true if every member within the two objects are equal. + */ + bool operator==(const Colour& other) const { + return matrix_coefficients == other.matrix_coefficients && + bits_per_channel == other.bits_per_channel && + chroma_subsampling_x == other.chroma_subsampling_x && + chroma_subsampling_y == other.chroma_subsampling_y && + cb_subsampling_x == other.cb_subsampling_x && + cb_subsampling_y == other.cb_subsampling_y && + chroma_siting_x == other.chroma_siting_x && + chroma_siting_y == other.chroma_siting_y && range == other.range && + transfer_characteristics == other.transfer_characteristics && + primaries == other.primaries && max_cll == other.max_cll && + max_fall == other.max_fall && + mastering_metadata == other.mastering_metadata; + } +}; + +/** + A parsed \WebMID{ProjectionType} element. + */ +enum class ProjectionType : std::uint64_t { + /** + Rectangular. + */ + kRectangular = 0, + + /** + Equirectangular. + */ + kEquirectangular = 1, + + /** + Cube map. + */ + kCubeMap = 2, + + /** + Mesh. + */ + kMesh = 3, +}; + +/** + A parsed \WebMID{Projection} element. + */ +struct Projection { + /** + A parsed \WebMID{ProjectionType} element. + */ + Element type; + + /** + A parsed \WebMID{ProjectionPrivate} element. + */ + Element> projection_private; + + /** + A parsed \WebMID{ProjectionPoseYaw} element. + */ + Element pose_yaw; + + /** + A parsed \WebMID{ProjectionPosePitch} element. + */ + Element pose_pitch; + + /** + A parsed \WebMID{ProjectionPoseRoll} element. + */ + Element pose_roll; + + /** + Returns true if every member within the two objects are equal. + */ + bool operator==(const Projection& other) const { + return type == other.type && + projection_private == other.projection_private && + pose_yaw == other.pose_yaw && pose_pitch == other.pose_pitch && + pose_roll == other.pose_roll; + } +}; + +/** + A parsed \WebMID{FlagInterlaced} element. + */ +enum class FlagInterlaced : std::uint64_t { + /** + Unspecified. + */ + kUnspecified = 0, + + /** + Interlaced. + */ + kInterlaced = 1, + + /** + Progressive. + */ + kProgressive = 2, +}; + +/** + A parsed \WebMID{StereoMode} element. + */ +enum class StereoMode : std::uint64_t { + /** + Mono. + */ + kMono = 0, + + /** + Side-by-side, left eye is first. + */ + kSideBySideLeftFirst = 1, + + /** + Top-bottom, right eye is first. + */ + kTopBottomRightFirst = 2, + + /** + Top-bottom, left eye is first. + */ + kTopBottomLeftFirst = 3, + + /** + Checkboard, right eye is first. + */ + kCheckboardRightFirst = 4, + + /** + Checkboard, left eye is first. + */ + kCheckboardLeftFirst = 5, + + /** + Row interleaved, right eye is first. + */ + kRowInterleavedRightFirst = 6, + + /** + Row interleaved, left eye is first. + */ + kRowInterleavedLeftFirst = 7, + + /** + Column interleaved, right eye is first. + */ + kColumnInterleavedRightFirst = 8, + + /** + Column interleaved, left eye is first. + */ + kColumnInterleavedLeftFirst = 9, + + /** + Anaglyph (cyan/read). + */ + kAnaglyphCyanRed = 10, + + /** + Side-by-side, right eye is first. + */ + kSideBySideRightFirst = 11, + + /** + Anaglyph (green/magenta). + */ + kAnaglyphGreenMagenta = 12, + + /** + Both eyes are laced in one block, left eye is first. + */ + kBlockLacedLeftFirst = 13, + + /** + Both eyes are laced in one block, right eye is first. + */ + kBlockLacedRightFirst = 14, + + /** + Stereo, but the layout for the left and right eyes is application dependent + and must be determined from other data (like the ProjectionPrivate element). + */ + kStereoCustom = 15, +}; + +/** + A parsed \WebMID{DisplayUnit} element. + + Note that WebM only supports pixel display units. Centimeters, inches, and + display aspect ratio aren't supported. + */ +enum class DisplayUnit : std::uint64_t { + // The only value legal value in WebM is 0 (pixels). + /** + Pixels. + + This is the only option supported by WebM. + */ + kPixels = 0, + + /** + Centimeters. + */ + kCentimeters = 1, + + /** + Inches. + */ + kInches = 2, + + /** + Display aspect ratio. + */ + kDisplayAspectRatio = 3, +}; + +/** + A parsed \WebMID{AspectRatioType} element. + */ +enum class AspectRatioType : std::uint64_t { + /** + Free resizing. + */ + kFreeResizing = 0, + + /** + Keep aspect ratio. + */ + kKeep = 1, + + /** + Fixed aspect ratio. + */ + kFixed = 2, +}; + +/** + A parsed \WebMID{Video} element. + */ +struct Video { + /** + A parsed \WebMID{FlagInterlaced} element. + */ + Element interlaced{FlagInterlaced::kUnspecified}; + + /** + A parsed \WebMID{StereoMode} element. + */ + Element stereo_mode{StereoMode::kMono}; + + /** + A parsed \WebMID{AlphaMode} element. + */ + Element alpha_mode{0}; + + /** + A parsed \WebMID{PixelWidth} element. + */ + Element pixel_width; + + /** + A parsed \WebMID{PixelHeight} element. + */ + Element pixel_height; + + /** + A parsed \WebMID{PixelCropBottom} element. + */ + Element pixel_crop_bottom{0}; + + /** + A parsed \WebMID{PixelCropTop} element. + */ + Element pixel_crop_top{0}; + + /** + A parsed \WebMID{PixelCropLeft} element. + */ + Element pixel_crop_left{0}; + + /** + A parsed \WebMID{PixelCropRight} element. + */ + Element pixel_crop_right{0}; + + /** + A parsed \WebMID{DisplayWidth} element. + */ + Element display_width; + + /** + A parsed \WebMID{DisplayHeight} element. + */ + Element display_height; + + /** + A parsed \WebMID{DisplayUnit} element. + */ + Element display_unit{DisplayUnit::kPixels}; + + /** + A parsed \WebMID{AspectRatioType} element. + */ + Element aspect_ratio_type{AspectRatioType::kFreeResizing}; + + /** + A parsed \WebMID{FrameRate} element (deprecated). + */ + Element frame_rate; + + /** + A parsed \WebMID{Colour} element. + */ + Element colour; + + /** + A parsed \WebMID{Projection} element. + */ + Element projection; + + /** + Returns true if every member within the two objects are equal. + */ + bool operator==(const Video& other) const { + return interlaced == other.interlaced && stereo_mode == other.stereo_mode && + alpha_mode == other.alpha_mode && pixel_width == other.pixel_width && + pixel_height == other.pixel_height && + pixel_crop_bottom == other.pixel_crop_bottom && + pixel_crop_top == other.pixel_crop_top && + pixel_crop_left == other.pixel_crop_left && + pixel_crop_right == other.pixel_crop_right && + display_width == other.display_width && + display_height == other.display_height && + display_unit == other.display_unit && + aspect_ratio_type == other.aspect_ratio_type && + frame_rate == other.frame_rate && colour == other.colour && + projection == other.projection; + } +}; + +/** + A parsed \WebMID{AESSettingsCipherMode} element. + */ +enum class AesSettingsCipherMode : std::uint64_t { + /** + Counter (CTR). + */ + kCtr = 1, +}; + +/** + A parsed \WebMID{ContentEncAESSettings} element. + */ +struct ContentEncAesSettings { + /** + A parsed \WebMID{AESSettingsCipherMode} element. + */ + Element aes_settings_cipher_mode{ + AesSettingsCipherMode::kCtr}; + + /** + Returns true if every member within the two objects are equal. + */ + bool operator==(const ContentEncAesSettings& other) const { + return aes_settings_cipher_mode == other.aes_settings_cipher_mode; + } +}; + +/** + A parsed \WebMID{ContentEncAlgo} element. + */ +enum class ContentEncAlgo : std::uint64_t { + /** + The contents have been signed but not encrypted. + */ + kOnlySigned = 0, + + /** + DES encryption. + */ + kDes = 1, + + /** + 3DES encryption. + */ + k3Des = 2, + + /** + Twofish encryption. + */ + kTwofish = 3, + + /** + Blowfish encryption. + */ + kBlowfish = 4, + + /** + AES encryption. + */ + kAes = 5, +}; + +/** + A parsed \WebMID{ContentEncryption} element. + */ +struct ContentEncryption { + /** + A parsed \WebMID{ContentEncAlgo} element. + */ + Element algorithm{ContentEncAlgo::kOnlySigned}; + + /** + A parsed \WebMID{ContentEncKeyID} element. + */ + Element> key_id; + + /** + A parsed \WebMID{ContentEncAESSettings} element. + */ + Element aes_settings; + + /** + Returns true if every member within the two objects are equal. + */ + bool operator==(const ContentEncryption& other) const { + return algorithm == other.algorithm && key_id == other.key_id && + aes_settings == other.aes_settings; + } +}; + +/** + A parsed \WebMID{ContentEncodingType} element. + */ +enum class ContentEncodingType : std::uint64_t { + /** + Compression. + */ + kCompression = 0, + + /** + Encryption. + */ + kEncryption = 1, +}; + +/** + A parsed \WebMID{ContentEncoding} element. + */ +struct ContentEncoding { + /** + A parsed \WebMID{ContentEncodingOrder} element. + */ + Element order{0}; + + /** + A parsed \WebMID{ContentEncodingScope} element. + */ + Element scope{1}; + + /** + A parsed \WebMID{ContentEncodingType} element. + */ + Element type{ContentEncodingType::kCompression}; + + /** + A parsed \WebMID{ContentEncryption} element. + */ + Element encryption; + + /** + Returns true if every member within the two objects are equal. + */ + bool operator==(const ContentEncoding& other) const { + return order == other.order && scope == other.scope && type == other.type && + encryption == other.encryption; + } +}; + +/** + A parsed \WebMID{ContentEncodings} element. + */ +struct ContentEncodings { + /** + Parsed \WebMID{ContentEncoding} elements. + */ + std::vector> encodings; + + /** + Returns true if every member within the two objects are equal. + */ + bool operator==(const ContentEncodings& other) const { + return encodings == other.encodings; + } +}; + +/** + A parsed \WebMID{TrackType} element. + */ +enum class TrackType : std::uint64_t { + /** + Video. + */ + kVideo = 0x01, + + /** + Audio. + */ + kAudio = 0x02, + + /** + Complex. + */ + kComplex = 0x03, + + /** + Logo. + */ + kLogo = 0x10, + + /** + Subtitle. + */ + kSubtitle = 0x11, + + /** + Buttons. + */ + kButtons = 0x12, + + /** + Control. + */ + kControl = 0x20, +}; + +/** + A parsed \WebMID{TrackEntry} element. + */ +struct TrackEntry { + /** + A parsed \WebMID{TrackNumber} element. + */ + Element track_number; + + /** + A parsed \WebMID{TrackUID} element. + */ + Element track_uid; + + /** + A parsed \WebMID{TrackType} element. + */ + Element track_type; + + /** + A parsed \WebMID{FlagEnabled} element. + */ + Element is_enabled{true}; + + /** + A parsed \WebMID{FlagDefault} element. + */ + Element is_default{true}; + + /** + A parsed \WebMID{FlagForced} element. + */ + Element is_forced{false}; + + /** + A parsed \WebMID{FlagLacing} element. + */ + Element uses_lacing{true}; + + /** + A parsed \WebMID{DefaultDuration} element. + */ + Element default_duration; + + /** + A parsed \WebMID{Name} element. + */ + Element name; + + /** + A parsed \WebMID{Language} element. + */ + Element language{"eng"}; + + /** + A parsed \WebMID{CodecID} element. + */ + Element codec_id; + + /** + A parsed \WebMID{CodecPrivate} element. + */ + Element> codec_private; + + /** + A parsed \WebMID{CodecName} element. + */ + Element codec_name; + + /** + A parsed \WebMID{CodecDelay} element. + */ + Element codec_delay{0}; + + /** + A parsed \WebMID{SeekPreRoll} element. + */ + Element seek_pre_roll{0}; + + /** + A parsed \WebMID{Video} element. + */ + Element