/* ============================================================================== This file is part of the JUCE library. Copyright (c) 2022 - Raw Material Software Limited JUCE is an open source library subject to commercial or open-source licensing. By using JUCE, you agree to the terms of both the JUCE 7 End-User License Agreement and JUCE Privacy Policy. End User License Agreement: www.juce.com/juce-7-licence Privacy Policy: www.juce.com/juce-privacy-policy Or: You may also use this code under the terms of the GPL v3 (see www.gnu.org/licenses). JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE DISCLAIMED. ============================================================================== */ namespace juce { // This byte-code is generated from native/java/com/rmsl/juce/ComponentPeerView.java with min sdk version 16 // See juce_core/native/java/README.txt on how to generate this byte-code. const uint8 javaComponentPeerView[] { 0x1f, 0x8b, 0x08, 0x08, 0x10, 0xaa, 0x6f, 0x64, 0x00, 0x03, 0x4a, 0x61, 0x76, 0x61, 0x44, 0x65, 0x78, 0x42, 0x79, 0x74, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x2e, 0x64, 0x65, 0x78, 0x00, 0xa5, 0x7c, 0x0b, 0x7c, 0xd4, 0xc5, 0xb5, 0xff, 0x99, 0xf9, 0xed, 0x23, 0xd9, 0xbc, 0x36, 0x9b, 0x90, 0x04, 0x48, 0x60, 0x03, 0xa8, 0x01, 0xf2, 0xe2, 0x9d, 0x98, 0x28, 0x8f, 0xf0, 0x0a, 0x49, 0x48, 0x20, 0x4b, 0x04, 0x42, 0xab, 0x4b, 0xb2, 0x81, 0xd5, 0x65, 0x77, 0xb3, 0xbb, 0x09, 0xa0, 0xb6, 0x45, 0xa4, 0xa2, 0xd5, 0x5b, 0x51, 0xa9, 0xa5, 0x6a, 0xad, 0xf5, 0x55, 0x6d, 0x6d, 0x6f, 0x55, 0x5a, 0xd1, 0xaa, 0xad, 0xd5, 0x56, 0xab, 0x5e, 0x5f, 0xb5, 0xfe, 0xfd, 0xb7, 0x5e, 0xaf, 0xda, 0x7a, 0x4b, 0xad, 0x7a, 0x6d, 0xa5, 0x0f, 0x95, 0x5b, 0xef, 0xf7, 0xcc, 0xcc, 0x6e, 0x7e, 0x21, 0xa1, 0xb6, 0xf7, 0x26, 0x9f, 0xef, 0xef, 0x9c, 0x99, 0x73, 0xe6, 0x3d, 0x73, 0xce, 0x99, 0xdf, 0x6e, 0xd2, 0x1f, 0xda, 0xe5, 0xa9, 0x9f, 0xb7, 0x80, 0xb6, 0x2e, 0x4b, 0xdc, 0xf3, 0xd1, 0xb5, 0x8f, 0x0c, 0xde, 0x7a, 0x49, 0xf7, 0xbe, 0x8f, 0xce, 0xff, 0xf9, 0xfb, 0xfe, 0x37, 0x4f, 0x5f, 0xfd, 0xd1, 0xc2, 0xe7, 0x9e, 0xd9, 0xb3, 0x81, 0x28, 0x4e, 0x44, 0xbb, 0x7a, 0xe6, 0xfb, 0xc8, 0xfc, 0x3c, 0x18, 0x20, 0xfa, 0xa1, 0xd0, 0xf9, 0x2b, 0x81, 0x88, 0x1b, 0x00, 0xdd, 0x97, 0x45, 0x34, 0x1d, 0xf4, 0x60, 0x1e, 0xd1, 0xcf, 0x41, 0xef, 0xca, 0x27, 0x82, 0x88, 0x96, 0x4f, 0x20, 0xda, 0xb2, 0x98, 0x68, 0x46, 0x09, 0xd1, 0x81, 0x3a, 0xa2, 0xab, 0x81, 0x2f, 0x01, 0x87, 0x80, 0xeb, 0x81, 0x1b, 0x81, 0x9b, 0x81, 0xdb, 0x80, 0x3b, 0x80, 0xef, 0x02, 0x87, 0x81, 0x07, 0x80, 0x1f, 0x03, 0xcf, 0x03, 0xbf, 0x03, 0xfe, 0x04, 0xfc, 0x15, 0x38, 0x0e, 0x7c, 0x0c, 0x58, 0xf5, 0xa8, 0x1f, 0xc8, 0x05, 0xbc, 0xc0, 0x04, 0x60, 0x22, 0x50, 0x0e, 0xf8, 0x81, 0x19, 0x40, 0x0b, 0xb0, 0x05, 0x38, 0x1b, 0xe8, 0x03, 0xb6, 0x03, 0x11, 0x60, 0x10, 0xd8, 0x09, 0x5c, 0x00, 0xec, 0x01, 0x3e, 0x0f, 0x5c, 0x0e, 0x1c, 0x00, 0xee, 0x00, 0x5e, 0x05, 0x3e, 0x00, 0x8a, 0xe7, 0x10, 0xd5, 0x01, 0x9d, 0x40, 0x0c, 0xb8, 0x0e, 0x38, 0x0c, 0x3c, 0x03, 0xfc, 0x16, 0xb0, 0xe6, 0x12, 0x95, 0x01, 0xb5, 0xc0, 0x2a, 0x20, 0x08, 0x7c, 0x06, 0xf8, 0x32, 0xf0, 0x30, 0xf0, 0x4b, 0xe0, 0x5d, 0xc0, 0x9a, 0x87, 0x7a, 0x80, 0x0e, 0x60, 0x00, 0xd8, 0x0b, 0x7c, 0x1b, 0xf8, 0x31, 0xf0, 0x0a, 0x50, 0x3c, 0x9f, 0x68, 0x01, 0xb0, 0x1d, 0xb8, 0x01, 0x78, 0x11, 0x70, 0x2c, 0x20, 0x9a, 0x0d, 0x9c, 0x05, 0x5c, 0x02, 0xdc, 0x07, 0xbc, 0x09, 0x9c, 0xba, 0x90, 0x28, 0x0a, 0xdc, 0x09, 0xbc, 0x02, 0x7c, 0x0c, 0x4c, 0x5f, 0x84, 0xb1, 0x02, 0x03, 0xc0, 0xe7, 0x81, 0xaf, 0x01, 0xf7, 0x00, 0x2f, 0x01, 0xc7, 0x81, 0xc2, 0x06, 0xa2, 0xf9, 0xc0, 0x6a, 0x60, 0x1b, 0x70, 0x01, 0xf0, 0x4d, 0xe0, 0xa7, 0xc0, 0xbf, 0x03, 0x73, 0x1a, 0x89, 0x96, 0x01, 0x01, 0xe0, 0x16, 0xe0, 0x2e, 0xe0, 0x1e, 0xe0, 0x51, 0xe0, 0x79, 0xe0, 0x45, 0xe0, 0x65, 0xe0, 0xdf, 0x81, 0x5f, 0x03, 0x6f, 0x01, 0xef, 0x02, 0x7f, 0x06, 0x8e, 0x03, 0xd6, 0xe9, 0x44, 0x59, 0x40, 0x1e, 0x50, 0x04, 0x94, 0x01, 0xe5, 0x40, 0x25, 0x70, 0x1a, 0x50, 0x0b, 0xcc, 0x03, 0x1a, 0x80, 0xc5, 0xc0, 0x6a, 0x60, 0x2d, 0xd0, 0x0d, 0x6c, 0x02, 0xce, 0x06, 0xfa, 0x80, 0xf3, 0x80, 0x28, 0x90, 0x04, 0x76, 0x03, 0x9f, 0x05, 0xf6, 0x02, 0x97, 0x01, 0x57, 0x02, 0xd7, 0x00, 0x87, 0x80, 0x9b, 0x80, 0x6f, 0x00, 0xdf, 0x02, 0xfe, 0x15, 0xb8, 0x17, 0x78, 0x1c, 0x78, 0x05, 0x38, 0x0a, 0x1c, 0x03, 0x44, 0x13, 0x51, 0x3e, 0x30, 0x19, 0xa8, 0x02, 0x16, 0x00, 0xcb, 0x80, 0x4e, 0x60, 0x0b, 0x10, 0x06, 0x86, 0x81, 0xbd, 0xc0, 0x95, 0xc0, 0xf5, 0xc0, 0x37, 0x80, 0x7b, 0x81, 0x1f, 0x02, 0x4f, 0x01, 0xff, 0x0f, 0xf8, 0x35, 0xf0, 0x1e, 0xf0, 0x31, 0x30, 0xa1, 0x99, 0xa8, 0x02, 0x98, 0x05, 0xcc, 0x07, 0x1a, 0x81, 0x00, 0xd0, 0x0b, 0xec, 0x00, 0x76, 0x01, 0x17, 0x00, 0x5f, 0x04, 0xae, 0x05, 0xee, 0x04, 0xee, 0x06, 0xee, 0x07, 0x1e, 0x01, 0x7e, 0x0e, 0xfc, 0x0a, 0x78, 0x0b, 0x78, 0x1f, 0xf8, 0x10, 0xc8, 0x39, 0x03, 0x7b, 0x15, 0x98, 0x05, 0x2c, 0x02, 0x56, 0x01, 0x01, 0xa0, 0x1f, 0x48, 0x02, 0x97, 0x01, 0x57, 0x03, 0x5f, 0x01, 0xbe, 0x0f, 0x3c, 0x08, 0xfc, 0x04, 0x78, 0x02, 0x78, 0x01, 0x78, 0x15, 0xf8, 0x35, 0xf0, 0x0e, 0x70, 0x0c, 0x28, 0x39, 0x13, 0xf3, 0x0e, 0x2c, 0x04, 0xce, 0x00, 0xda, 0x80, 0x8d, 0x40, 0x10, 0x18, 0x04, 0x3e, 0x03, 0x5c, 0x07, 0x1c, 0x01, 0x1e, 0x05, 0x5e, 0x04, 0x7e, 0x0f, 0xfc, 0x37, 0x50, 0x84, 0x73, 0x3a, 0x0d, 0xa8, 0x06, 0x96, 0x02, 0x1b, 0x81, 0x7e, 0x60, 0x10, 0xf8, 0x1c, 0x70, 0x1d, 0xf0, 0x20, 0xf0, 0x38, 0xf0, 0x06, 0xf0, 0x11, 0xe0, 0x5d, 0x82, 0x35, 0x06, 0x3a, 0x81, 0x2d, 0xc0, 0x0e, 0x60, 0x2f, 0x70, 0x00, 0xb8, 0x1e, 0xf8, 0x26, 0xf0, 0x03, 0xe0, 0x67, 0xc0, 0x0b, 0xc0, 0xaf, 0x80, 0xa3, 0xc0, 0x07, 0x40, 0xee, 0x52, 0xa2, 0x29, 0x40, 0x2d, 0xb0, 0x04, 0xd8, 0x00, 0x84, 0x80, 0xf3, 0x81, 0xcb, 0x80, 0xaf, 0x00, 0xf7, 0x01, 0x0f, 0x01, 0x8f, 0x02, 0x3f, 0x05, 0x5e, 0x03, 0xfe, 0x00, 0x58, 0xcb, 0xb0, 0x1e, 0xc0, 0x0c, 0x60, 0x1e, 0xb0, 0x04, 0xe8, 0x01, 0xb6, 0x01, 0xbb, 0x80, 0xfd, 0xc0, 0x41, 0xe0, 0x4e, 0xe0, 0x5e, 0xe0, 0x11, 0xe0, 0x97, 0xc0, 0x6f, 0x80, 0xb7, 0x80, 0x77, 0x80, 0x0f, 0x80, 0xbf, 0x01, 0x05, 0x2d, 0xe8, 0x07, 0x50, 0x07, 0x34, 0x03, 0xab, 0x80, 0x0d, 0xc0, 0x76, 0x20, 0x01, 0x9c, 0x0f, 0x5c, 0x02, 0x1c, 0x00, 0x6e, 0x01, 0x1e, 0x06, 0x7e, 0x06, 0xbc, 0x00, 0xfc, 0x1e, 0xf8, 0x10, 0x10, 0xcb, 0x31, 0x17, 0x40, 0x09, 0x30, 0x05, 0x98, 0x01, 0x54, 0x03, 0x75, 0xc0, 0x02, 0x60, 0x29, 0xb0, 0x0a, 0xe8, 0x02, 0x36, 0x01, 0x7d, 0xc0, 0x20, 0xb0, 0x1b, 0xb8, 0x08, 0xd8, 0x0f, 0x5c, 0x0f, 0x7c, 0x1d, 0xf8, 0x06, 0xf0, 0x00, 0xf0, 0x2c, 0xf0, 0x3a, 0x70, 0x0c, 0x28, 0x5c, 0x81, 0x3a, 0x81, 0x45, 0x40, 0x17, 0xb0, 0x11, 0xd8, 0x06, 0xec, 0x04, 0x3e, 0x0f, 0x1c, 0x00, 0xbe, 0x06, 0xdc, 0x01, 0xdc, 0x03, 0x3c, 0x02, 0x3c, 0x03, 0xfc, 0x3b, 0xf0, 0x36, 0xf0, 0x11, 0x90, 0x0d, 0x83, 0x5d, 0x08, 0x4c, 0x02, 0xa6, 0x01, 0xd5, 0xc0, 0x3c, 0xe0, 0x74, 0x60, 0x29, 0xd0, 0x01, 0x6c, 0x01, 0xfa, 0x80, 0xbd, 0xc0, 0x97, 0x80, 0xeb, 0x80, 0xaf, 0x02, 0xb7, 0x03, 0x4f, 0x02, 0x47, 0x81, 0x63, 0x80, 0x5c, 0x85, 0xfa, 0x80, 0x5c, 0x60, 0x12, 0x30, 0x0b, 0xa8, 0x03, 0x16, 0x03, 0x1d, 0xc0, 0x00, 0x70, 0x21, 0x70, 0x15, 0xf0, 0x35, 0xe0, 0x7e, 0xe0, 0x71, 0xe0, 0x39, 0xe0, 0xb7, 0x80, 0x63, 0x35, 0xce, 0x12, 0x30, 0x0b, 0x68, 0x04, 0x56, 0x00, 0x1b, 0x80, 0x3e, 0x20, 0x01, 0xec, 0x06, 0x2e, 0x03, 0x0e, 0x01, 0x37, 0x01, 0xdf, 0x06, 0x8e, 0x00, 0x2f, 0x00, 0xbf, 0x04, 0x7e, 0x03, 0xbc, 0x05, 0xe4, 0xb4, 0x12, 0xd5, 0x03, 0x9b, 0x81, 0xbd, 0xc0, 0xcd, 0xc0, 0x23, 0xc0, 0x1b, 0x80, 0x63, 0x0d, 0xec, 0x25, 0xd0, 0x06, 0x24, 0x81, 0xdd, 0xc0, 0x45, 0xc0, 0x65, 0xc0, 0x95, 0xc0, 0x57, 0x80, 0x1b, 0x81, 0x5b, 0x81, 0xc7, 0x81, 0x3f, 0x02, 0xbe, 0x36, 0xac, 0x17, 0xb0, 0x18, 0x58, 0x06, 0xb4, 0x02, 0xeb, 0x81, 0x8d, 0xc0, 0x39, 0xc0, 0x20, 0x70, 0x21, 0xf0, 0x45, 0xe0, 0x16, 0xe0, 0x1e, 0xe0, 0x61, 0xe0, 0x11, 0xe0, 0x71, 0xe0, 0x49, 0xe0, 0x19, 0xe0, 0x05, 0xe0, 0x25, 0xe0, 0x97, 0xc0, 0xab, 0x40, 0x01, 0x7c, 0x61, 0x21, 0x50, 0x06, 0x54, 0x01, 0x33, 0x81, 0x59, 0xc0, 0x6c, 0xa0, 0x1a, 0xa8, 0x01, 0x6a, 0x01, 0xb8, 0x36, 0x82, 0xeb, 0x21, 0xb8, 0x17, 0x82, 0xeb, 0x20, 0xb8, 0x07, 0x82, 0x3b, 0x20, 0x98, 0x7e, 0x82, 0xa9, 0x27, 0x98, 0x73, 0x82, 0xc9, 0x26, 0x98, 0x5d, 0x82, 0x99, 0x23, 0x98, 0x25, 0xc2, 0xb1, 0x27, 0x1c, 0x5f, 0xc2, 0x71, 0x24, 0x1c, 0x2b, 0xc2, 0xf1, 0x20, 0x6c, 0x6b, 0x6a, 0x61, 0xff, 0x0b, 0xac, 0x30, 0xbe, 0x1a, 0xd3, 0x4e, 0x98, 0x32, 0xc2, 0xd4, 0x10, 0x86, 0x4a, 0xe8, 0x16, 0xb5, 0x03, 0x1d, 0xc0, 0x5a, 0xa0, 0x13, 0xe8, 0x02, 0xd6, 0x01, 0xeb, 0x81, 0x6e, 0x00, 0xee, 0x9e, 0x10, 0x06, 0x50, 0x0f, 0x70, 0x16, 0xb0, 0x11, 0xd8, 0x04, 0x6c, 0x06, 0x7a, 0x81, 0x2d, 0xc0, 0xa7, 0x80, 0x4f, 0x03, 0x67, 0x03, 0xe7, 0x00, 0x41, 0x60, 0x2b, 0xd0, 0x07, 0xf4, 0x03, 0xdb, 0x80, 0x1d, 0xc0, 0xa5, 0x1c, 0x1f, 0x00, 0x5f, 0x02, 0xae, 0x05, 0xbe, 0x4c, 0x7a, 0x5e, 0xd2, 0x3f, 0xde, 0x34, 0xad, 0xd1, 0x73, 0x25, 0x4c, 0xba, 0xc8, 0xf0, 0x9c, 0x5f, 0x6c, 0xf8, 0x32, 0xf0, 0x13, 0x0c, 0xef, 0x07, 0x5f, 0x62, 0xf8, 0x2a, 0xf0, 0xa5, 0x86, 0xaf, 0xb7, 0xf1, 0x0d, 0x36, 0x7e, 0x49, 0x8d, 0x5e, 0x07, 0x69, 0xea, 0x9f, 0x68, 0x78, 0xae, 0x67, 0x92, 0xe1, 0x57, 0x83, 0xaf, 0x00, 0x75, 0x19, 0x1d, 0x8e, 0x6d, 0xb2, 0x78, 0x7e, 0x4c, 0x7e, 0xba, 0xaf, 0xcc, 0x17, 0xda, 0xf8, 0x89, 0x36, 0xbe, 0xc2, 0xf0, 0x95, 0x86, 0xdf, 0x88, 0xb2, 0xa7, 0x1a, 0xfe, 0x1c, 0x53, 0x8f, 0xdf, 0xa6, 0x3f, 0xcd, 0xf0, 0x53, 0x0c, 0xcf, 0xe3, 0x9d, 0x61, 0xf8, 0x88, 0xd1, 0x9f, 0x6e, 0xeb, 0x0f, 0xd7, 0x95, 0x32, 0xf9, 0xa7, 0x99, 0x7c, 0xae, 0xaf, 0xc6, 0x8c, 0x85, 0x75, 0x78, 0x4f, 0x5d, 0x08, 0x7e, 0x2a, 0xe9, 0xbd, 0x54, 0x66, 0xf4, 0xe7, 0xdb, 0xda, 0x5a, 0x64, 0xda, 0xf2, 0x1b, 0x9e, 0xcb, 0x9e, 0x62, 0xf8, 0x7d, 0x35, 0xba, 0x6e, 0xde, 0x6f, 0x57, 0x98, 0x3a, 0x99, 0x3f, 0x68, 0xea, 0x69, 0x32, 0xf5, 0x4c, 0x35, 0x3c, 0xd7, 0x3f, 0xcd, 0xf0, 0x37, 0x98, 0xb2, 0xbc, 0x3f, 0xef, 0x30, 0x65, 0x79, 0x8f, 0x7e, 0xd7, 0x8c, 0x8b, 0xf9, 0x23, 0x35, 0x7a, 0x6f, 0x2c, 0x31, 0xf5, 0x44, 0x0d, 0xcf, 0xfd, 0x89, 0x19, 0x9e, 0xeb, 0x8c, 0x1b, 0xfe, 0x47, 0xe0, 0x07, 0x0d, 0xff, 0x34, 0xf8, 0x84, 0xe1, 0xb9, 0xcf, 0x49, 0xc3, 0xbf, 0x0c, 0x3e, 0x65, 0x78, 0xee, 0xc3, 0x90, 0xe1, 0x8f, 0x82, 0x1f, 0x36, 0xfc, 0x31, 0xf0, 0xbb, 0x0c, 0x7f, 0x1c, 0xfc, 0x4e, 0xc3, 0x67, 0xd5, 0x8e, 0xf0, 0x5e, 0xf0, 0xbb, 0xd3, 0x7d, 0x00, 0x7f, 0x7e, 0xba, 0x2d, 0xf0, 0x9f, 0x33, 0x7c, 0x95, 0x2d, 0xbf, 0xde, 0xc6, 0x37, 0x80, 0xdf, 0x67, 0xf8, 0x25, 0xb6, 0xfc, 0x76, 0x1b, 0x1f, 0xb0, 0xf1, 0x5b, 0x6c, 0x3c, 0xcf, 0x4f, 0xba, 0xfe, 0x7e, 0xe4, 0x5f, 0x68, 0xf8, 0x08, 0xf8, 0x3d, 0x86, 0xdf, 0x05, 0xfe, 0x22, 0xc3, 0xef, 0xb3, 0x95, 0x3d, 0x68, 0xe3, 0x6f, 0xb0, 0xf1, 0xb7, 0x82, 0xbf, 0x20, 0x5d, 0x0f, 0xea, 0xbf, 0xd8, 0xf0, 0x77, 0xd9, 0x74, 0x8e, 0x57, 0x8f, 0xf0, 0xbc, 0x67, 0x3e, 0x9b, 0xae, 0x1f, 0xfc, 0x5e, 0xc3, 0x1f, 0xb6, 0x8d, 0xfd, 0x47, 0xe0, 0x3f, 0x6f, 0xf8, 0x27, 0x6c, 0xf5, 0xf0, 0xf9, 0xfa, 0x8c, 0xe1, 0x5f, 0xb4, 0xe5, 0xbf, 0x56, 0x3b, 0x92, 0x7f, 0xd4, 0x56, 0xcf, 0x31, 0x7b, 0xff, 0x6b, 0x6c, 0xfd, 0x41, 0xfe, 0x25, 0x86, 0x77, 0xc0, 0x30, 0xee, 0x37, 0x7c, 0x6e, 0xdd, 0x88, 0x4e, 0xb9, 0x8d, 0x9f, 0x51, 0xa7, 0x6d, 0x0c, 0xdb, 0x3f, 0xfe, 0xb9, 0xcc, 0xf0, 0xbc, 0x7f, 0xbe, 0x60, 0xf8, 0xea, 0xba, 0x11, 0xbe, 0x01, 0xfc, 0xe5, 0x86, 0x5f, 0x0e, 0xfe, 0x0a, 0xc3, 0xf3, 0x5e, 0xfa, 0x17, 0xc3, 0xb7, 0x23, 0xff, 0x8b, 0x86, 0xdf, 0x08, 0xfe, 0x80, 0xe1, 0xfb, 0xc1, 0x5f, 0x69, 0xf8, 0x88, 0x2d, 0x9f, 0xe7, 0xf6, 0x2a, 0xc3, 0xa7, 0xf8, 0xbe, 0x63, 0xf8, 0x7d, 0x36, 0x7d, 0x9e, 0x87, 0x34, 0xcf, 0xe3, 0xbd, 0xc6, 0xf0, 0x3c, 0xc6, 0x3c, 0x58, 0xa8, 0x07, 0x49, 0xd3, 0x5b, 0x61, 0xac, 0xf2, 0x41, 0xc3, 0xc4, 0xe7, 0x71, 0x1e, 0xdd, 0x6d, 0xa8, 0x5f, 0x30, 0x15, 0x34, 0xdd, 0xd0, 0x53, 0x0c, 0x3d, 0xd5, 0xd0, 0xd3, 0x0c, 0x9d, 0x29, 0xb4, 0xfe, 0x42, 0xc1, 0x3e, 0xa7, 0x89, 0x9e, 0x26, 0xa6, 0x85, 0xea, 0x7e, 0x56, 0x05, 0x2b, 0x71, 0x95, 0xca, 0xaf, 0xa5, 0xef, 0x08, 0xf6, 0x47, 0x85, 0xf4, 0x30, 0x31, 0xad, 0xa2, 0x47, 0x14, 0xd5, 0xf2, 0x99, 0x46, 0x3e, 0x0b, 0xf4, 0x26, 0x43, 0x39, 0x3d, 0x1b, 0x3d, 0x5e, 0xa0, 0x68, 0x35, 0x7d, 0x5d, 0xb0, 0x0f, 0xd3, 0xf2, 0x6a, 0x23, 0xaf, 0x86, 0xe4, 0x1e, 0xc1, 0xb6, 0x48, 0x52, 0xa5, 0x60, 0x3b, 0x54, 0x49, 0xff, 0x4a, 0x4c, 0x67, 0xd2, 0x0f, 0x15, 0x4d, 0xe7, 0x57, 0xd3, 0x7c, 0x45, 0x67, 0x51, 0x8b, 0xa2, 0x4b, 0xe9, 0x1c, 0x45, 0x73, 0x28, 0x24, 0xd8, 0x06, 0xcd, 0xa7, 0x73, 0xa1, 0xef, 0x44, 0xff, 0x63, 0x82, 0xed, 0x71, 0x1e, 0xbd, 0x49, 0x4c, 0x67, 0x90, 0x03, 0xe9, 0x6c, 0xb4, 0xc3, 0x76, 0x39, 0x1b, 0x1e, 0x69, 0x27, 0xd2, 0x1e, 0x58, 0x15, 0x4e, 0xe7, 0x98, 0xfc, 0x1c, 0xcc, 0xe0, 0x2e, 0xc1, 0xf3, 0xa9, 0xd3, 0x85, 0x68, 0xb7, 0x51, 0x30, 0xed, 0xa6, 0x41, 0x45, 0x03, 0xb4, 0x07, 0xd4, 0x87, 0x1a, 0xa4, 0xa1, 0x96, 0xa2, 0x2d, 0xf4, 0x39, 0xc1, 0x3e, 0x66, 0x9d, 0x2a, 0x57, 0x0a, 0x2f, 0xc8, 0x74, 0x22, 0x4a, 0xfc, 0x45, 0xd1, 0x95, 0x74, 0x9e, 0x60, 0x7f, 0x51, 0xa3, 0xf2, 0x27, 0xa1, 0xde, 0x5f, 0x2b, 0x7a, 0x0a, 0x1d, 0x35, 0xe9, 0x0f, 0x0d, 0xcd, 0x82, 0xde, 0x64, 0x23, 0x67, 0xfa, 0x1b, 0x45, 0x3d, 0xf4, 0xae, 0x49, 0xff, 0xb7, 0xa2, 0x16, 0xfd, 0x4d, 0x51, 0xdc, 0x35, 0x0c, 0x25, 0x55, 0x4e, 0x50, 0x9e, 0xa1, 0xf9, 0x82, 0x6d, 0x6e, 0x09, 0x3d, 0x4b, 0x4c, 0x25, 0xfd, 0x41, 0xd1, 0x25, 0x94, 0x2b, 0xd8, 0x8e, 0x37, 0xab, 0x7e, 0x4c, 0x81, 0x07, 0xee, 0x51, 0xe9, 0xb3, 0xe9, 0x2c, 0x45, 0xeb, 0x68, 0xb3, 0x60, 0xdb, 0xde, 0x46, 0x87, 0x49, 0xd3, 0xb8, 0x60, 0x9f, 0xb4, 0x85, 0xe6, 0x08, 0xb6, 0xd5, 0xad, 0xaa, 0xdc, 0x34, 0x78, 0xc4, 0x15, 0x2a, 0x3d, 0x9b, 0xa2, 0x82, 0x6d, 0xb5, 0x9e, 0xaf, 0x19, 0x88, 0x14, 0x34, 0x9d, 0x4d, 0x8f, 0x29, 0x9a, 0x45, 0x6f, 0x19, 0xfa, 0x7b, 0x45, 0xbd, 0xf4, 0x0e, 0xb1, 0x9d, 0xef, 0xa7, 0xa9, 0x82, 0xe9, 0x6a, 0x4a, 0x28, 0x3a, 0x40, 0x97, 0xa9, 0xfd, 0xb5, 0x56, 0x95, 0xaf, 0xc2, 0xba, 0x7e, 0x5f, 0xd1, 0xf5, 0xf4, 0x03, 0x45, 0x67, 0x92, 0x5b, 0xc9, 0x97, 0x53, 0xaf, 0xa2, 0x2b, 0x68, 0x8b, 0x49, 0x7f, 0x4a, 0x68, 0xbd, 0x4f, 0x2b, 0xba, 0x8c, 0x6e, 0x37, 0xf4, 0x1b, 0x86, 0xde, 0x61, 0xe8, 0x9d, 0x6a, 0x7f, 0x76, 0xa9, 0xfa, 0x67, 0x9a, 0xfe, 0xcd, 0xc4, 0xb8, 0x7e, 0xa9, 0xa8, 0xee, 0xd7, 0x4c, 0x3a, 0x8f, 0x2e, 0x54, 0xfb, 0xb6, 0x53, 0xe9, 0xcd, 0xc2, 0x4a, 0x3e, 0xab, 0xe8, 0x2c, 0x7a, 0xd9, 0xa4, 0xff, 0xbf, 0xa2, 0x9f, 0xa6, 0xed, 0x6a, 0x3f, 0xb7, 0x2b, 0xbd, 0xd9, 0xf8, 0x0d, 0xa8, 0x7d, 0xac, 0xcb, 0x55, 0x23, 0xff, 0x7a, 0x43, 0x6f, 0x50, 0xb4, 0x82, 0xbe, 0x4a, 0x7a, 0x9f, 0x5f, 0x6e, 0xf6, 0xfb, 0x15, 0x6a, 0xbf, 0xd7, 0x2b, 0x7d, 0xde, 0xf7, 0xff, 0xa9, 0xa8, 0x9b, 0x7e, 0x6b, 0xd2, 0x7f, 0x34, 0xf4, 0x7d, 0x43, 0xff, 0xaa, 0xe8, 0xa9, 0xe4, 0x34, 0xe7, 0xc4, 0xa5, 0x68, 0x0f, 0xcd, 0x56, 0x74, 0x0b, 0xd5, 0x2b, 0x5a, 0x43, 0x17, 0x28, 0x7a, 0x16, 0x5d, 0xac, 0xce, 0xc5, 0x19, 0xaa, 0xfe, 0x5a, 0x44, 0x59, 0x87, 0x14, 0x75, 0xd2, 0x57, 0x14, 0x5d, 0x44, 0xd7, 0x29, 0x9a, 0x4b, 0x37, 0x2a, 0xda, 0x41, 0x5f, 0x53, 0xb4, 0x98, 0x6e, 0x52, 0x74, 0x3b, 0x7d, 0x5d, 0xd1, 0x69, 0x74, 0xb3, 0xa1, 0xb7, 0x98, 0xf2, 0xb7, 0x2a, 0xba, 0x8d, 0x6e, 0x53, 0x74, 0x2e, 0xdd, 0xae, 0xe8, 0x69, 0xf4, 0x0d, 0x45, 0x17, 0xd2, 0x1d, 0x46, 0xef, 0x4e, 0x43, 0xbf, 0xa9, 0xa8, 0x8b, 0xbe, 0x65, 0xd2, 0x77, 0x29, 0x3a, 0x9b, 0xee, 0x37, 0xf4, 0x51, 0x43, 0x7f, 0xa2, 0xe8, 0xa7, 0xe8, 0x29, 0x45, 0xeb, 0xe9, 0x79, 0x45, 0x1b, 0xe8, 0x15, 0xd2, 0xf6, 0xe0, 0x75, 0x45, 0x27, 0xd2, 0x1b, 0x8a, 0xe6, 0xd1, 0xdb, 0x8a, 0x96, 0xd3, 0x7f, 0x91, 0x3e, 0xff, 0xef, 0x19, 0x3b, 0xf1, 0x07, 0xa3, 0x7f, 0x4c, 0xd1, 0xc9, 0xf4, 0x27, 0x45, 0x2d, 0xfa, 0xb3, 0xa2, 0xbd, 0xf4, 0x81, 0xa2, 0x45, 0x74, 0x5c, 0x51, 0x1f, 0x09, 0x35, 0x4f, 0x13, 0x28, 0x5b, 0xe8, 0xf2, 0x1e, 0x45, 0x0b, 0x28, 0x47, 0x51, 0x7d, 0x5e, 0x6a, 0x11, 0x61, 0x7b, 0x85, 0xee, 0x57, 0xa1, 0xa1, 0x3e, 0x43, 0x8b, 0x14, 0x9d, 0x4f, 0xc5, 0x8a, 0xce, 0xa3, 0x09, 0x42, 0xcf, 0x4b, 0x89, 0x91, 0x97, 0x9a, 0xf2, 0x65, 0x86, 0x4e, 0x34, 0x74, 0x92, 0xa2, 0x0b, 0x68, 0xb2, 0xa2, 0x5b, 0xa9, 0x5c, 0xe8, 0x79, 0x98, 0xa2, 0xe8, 0x16, 0xaa, 0x33, 0x74, 0xae, 0xa2, 0xa7, 0xd3, 0x1a, 0x45, 0x1b, 0xa9, 0xcd, 0xd0, 0x76, 0x43, 0x3b, 0x8c, 0x7c, 0xad, 0x49, 0x77, 0x1a, 0xda, 0xa5, 0xe8, 0x24, 0x5a, 0xa7, 0xe8, 0x99, 0xb4, 0x5e, 0xd1, 0x35, 0xd4, 0xad, 0x68, 0x88, 0x36, 0x28, 0xaa, 0xcf, 0x7f, 0xad, 0x39, 0xff, 0x9c, 0xde, 0xa8, 0xe8, 0x26, 0xda, 0xa4, 0xa8, 0xb6, 0x07, 0xac, 0x7f, 0xb6, 0xa2, 0x7d, 0x74, 0xae, 0xa2, 0x1b, 0x69, 0xb7, 0xa1, 0xe7, 0x2b, 0xba, 0x8a, 0x3e, 0x6b, 0xec, 0xf3, 0x5e, 0x45, 0x7b, 0x68, 0x9f, 0x49, 0x7f, 0xde, 0xe8, 0x5d, 0x62, 0xe8, 0x7e, 0x45, 0x6b, 0xe9, 0x52, 0xa1, 0xf7, 0xc3, 0x41, 0xa1, 0xf7, 0xc7, 0x97, 0x4c, 0xfa, 0x5a, 0x43, 0xbf, 0x6c, 0xe8, 0x21, 0xa1, 0xf7, 0xd7, 0x57, 0x4c, 0xfa, 0x3a, 0xa1, 0xf7, 0xd9, 0xf5, 0x42, 0xef, 0xeb, 0x1b, 0xcc, 0x7c, 0x7f, 0x55, 0xe8, 0x7d, 0x7d, 0xa3, 0x99, 0xf7, 0xef, 0x0a, 0x8e, 0x61, 0xa7, 0xd0, 0x17, 0x15, 0x3d, 0x85, 0x6e, 0x11, 0x1c, 0xc7, 0x56, 0xd1, 0x47, 0xc4, 0x34, 0x4c, 0xb5, 0xca, 0x5f, 0x48, 0xaa, 0x56, 0xd4, 0x4f, 0xdf, 0x16, 0x1c, 0xab, 0x6a, 0x3b, 0xd6, 0x88, 0x08, 0xf5, 0x77, 0x8a, 0xea, 0x72, 0x4d, 0xd8, 0x3f, 0x8f, 0x13, 0x53, 0x07, 0x3d, 0xa1, 0xe8, 0xb9, 0xf4, 0x92, 0xa2, 0xda, 0x3f, 0x70, 0xfe, 0x2a, 0x45, 0x4f, 0xa5, 0x2b, 0x05, 0xc7, 0xb0, 0xd3, 0xa9, 0x46, 0xf0, 0x3d, 0x4b, 0xd7, 0x77, 0x26, 0xda, 0xbb, 0x97, 0xf4, 0x5d, 0xce, 0x4b, 0x3a, 0x26, 0x3e, 0x56, 0xcd, 0x7e, 0x06, 0xb1, 0x01, 0xe8, 0xd9, 0x7c, 0x81, 0x22, 0x7d, 0xcf, 0xf3, 0x92, 0x8e, 0x77, 0x89, 0xb4, 0xfc, 0x42, 0xc8, 0xbf, 0x6a, 0xe4, 0xb3, 0x8c, 0x7c, 0xba, 0x4d, 0x7e, 0x05, 0xe4, 0xf7, 0x19, 0xf9, 0x6c, 0x93, 0xcf, 0xf5, 0x1f, 0x37, 0xf5, 0xdf, 0x0a, 0xfa, 0x92, 0x91, 0x57, 0xdb, 0xda, 0x4f, 0x97, 0x3f, 0x8c, 0xcc, 0xdf, 0x19, 0x39, 0xdf, 0x05, 0xc4, 0x09, 0xf2, 0xc7, 0x20, 0x2f, 0xec, 0xd6, 0x69, 0xbe, 0x1f, 0xf0, 0xfd, 0x85, 0xef, 0x01, 0x8e, 0x1a, 0x2d, 0x7f, 0x05, 0xf2, 0x56, 0x23, 0xe7, 0xbb, 0xd0, 0x97, 0x71, 0x21, 0xbc, 0x71, 0x9d, 0xae, 0xe7, 0xce, 0x75, 0x23, 0x79, 0x8f, 0xd9, 0xf8, 0x67, 0x8d, 0xfc, 0x97, 0x26, 0xef, 0xbf, 0x40, 0xff, 0x0c, 0x58, 0x46, 0x2e, 0xd0, 0x9f, 0xdc, 0xf5, 0x23, 0xfa, 0x13, 0xd6, 0x9b, 0xbb, 0x9b, 0xa1, 0x8b, 0x0c, 0x5d, 0xbd, 0x9e, 0x7d, 0xbb, 0x43, 0xe9, 0xbd, 0xde, 0xa6, 0xfb, 0x16, 0xf7, 0x3e, 0x8e, 0x74, 0xef, 0xf4, 0x7c, 0xea, 0x9d, 0x91, 0x4b, 0xbd, 0xa7, 0xe4, 0x51, 0xc0, 0x9f, 0x4b, 0x81, 0xca, 0x3c, 0x1a, 0xf4, 0x2f, 0xc6, 0xe8, 0xf3, 0x89, 0xef, 0x66, 0x42, 0xb5, 0xf5, 0xc7, 0x36, 0x7d, 0x77, 0xf6, 0xb9, 0x06, 0xbd, 0x73, 0x61, 0x7b, 0x3d, 0x72, 0xd0, 0x3b, 0x87, 0x29, 0x9d, 0x2e, 0x1d, 0x6a, 0x55, 0x7d, 0xa2, 0x50, 0x44, 0xbd, 0x3f, 0x43, 0x5e, 0xae, 0x35, 0x4d, 0x9c, 0x89, 0xda, 0x9f, 0x47, 0xd9, 0x69, 0x8e, 0x52, 0x8a, 0xd6, 0x3f, 0x45, 0x7d, 0xd2, 0xe3, 0x1c, 0xf4, 0xfe, 0x14, 0xbb, 0x32, 0xd7, 0xa9, 0xd2, 0xe4, 0x71, 0x71, 0xda, 0x45, 0xb9, 0xae, 0x78, 0xbd, 0x97, 0x02, 0xae, 0xa8, 0xff, 0x05, 0xf8, 0xb2, 0xaa, 0x57, 0xf9, 0xfd, 0xb6, 0x54, 0x6d, 0x96, 0xb4, 0xeb, 0xf9, 0xf3, 0x39, 0xa2, 0xde, 0x8d, 0xd0, 0xf4, 0xa0, 0xfe, 0x4d, 0x4c, 0xe9, 0x74, 0xe1, 0x50, 0x3b, 0x2d, 0x9f, 0xb8, 0x45, 0xd4, 0x29, 0xa3, 0xf5, 0xcf, 0xd0, 0x32, 0xe1, 0xb1, 0x14, 0x25, 0x8f, 0x63, 0xb0, 0x3e, 0x9f, 0x16, 0x38, 0xaa, 0xde, 0xb3, 0x50, 0x17, 0x8f, 0x79, 0x61, 0xbb, 0xbe, 0x67, 0x0e, 0x7a, 0x4f, 0x47, 0xaf, 0x72, 0x29, 0xea, 0x3f, 0x07, 0xf9, 0xf9, 0x4a, 0xca, 0xf2, 0xa5, 0xed, 0xfa, 0xbd, 0xfa, 0xa0, 0x7f, 0x19, 0x46, 0x3e, 0xe8, 0x5f, 0x62, 0xc6, 0x9f, 0xee, 0x4b, 0x47, 0xa6, 0x2f, 0x83, 0xde, 0x3c, 0xb4, 0xe8, 0x11, 0x83, 0xde, 0x5c, 0xa6, 0xe3, 0xf6, 0xe5, 0x29, 0xd3, 0x97, 0xa7, 0x54, 0x5f, 0xa2, 0xf5, 0x67, 0xd3, 0x42, 0xf4, 0x45, 0x9a, 0x9b, 0xf1, 0x8e, 0x76, 0xbd, 0x26, 0x5c, 0xbf, 0x0b, 0x25, 0x98, 0x1f, 0x32, 0xed, 0x27, 0xbc, 0x3f, 0x86, 0x16, 0x56, 0xc3, 0x9b, 0x63, 0xda, 0x77, 0xaa, 0x52, 0xfb, 0x4c, 0xff, 0x47, 0x56, 0x68, 0xa9, 0xea, 0x61, 0xb6, 0xea, 0x21, 0x62, 0xdd, 0x93, 0xc8, 0xd3, 0xe5, 0x6f, 0x3f, 0x89, 0x9c, 0xc7, 0xc0, 0xe3, 0xfb, 0x5e, 0xbb, 0xfe, 0xbc, 0xc1, 0xe7, 0x0a, 0x24, 0x72, 0x69, 0xde, 0x5e, 0x17, 0x05, 0x12, 0x39, 0xd4, 0x28, 0x79, 0x5c, 0x07, 0x64, 0x76, 0x4e, 0xa2, 0xfe, 0x11, 0x3a, 0x24, 0x73, 0xa5, 0xe9, 0x9f, 0xf0, 0xd1, 0x24, 0x29, 0x31, 0x8b, 0x4f, 0xc3, 0x7f, 0x78, 0x64, 0xa3, 0xf4, 0x20, 0x6d, 0x65, 0xd2, 0x0d, 0xd8, 0x13, 0x45, 0x18, 0xfb, 0x24, 0x84, 0x7e, 0xa3, 0xf3, 0xce, 0x40, 0xbd, 0xd8, 0x67, 0xc9, 0x1c, 0xbd, 0x2b, 0xb2, 0x3d, 0x56, 0x20, 0x95, 0x43, 0x07, 0x9c, 0xd9, 0x1e, 0x4e, 0xf7, 0x3b, 0xf5, 0x6c, 0xcd, 0x75, 0xb0, 0x56, 0x03, 0xaf, 0x93, 0xf7, 0xdf, 0x30, 0x3f, 0x1e, 0xeb, 0x65, 0xcb, 0xfa, 0x38, 0x5a, 0xff, 0x2c, 0x05, 0xad, 0x5c, 0x11, 0xf5, 0x7f, 0x0a, 0xde, 0x88, 0xa5, 0x81, 0x44, 0x3e, 0x4d, 0xb3, 0x26, 0x51, 0xbc, 0xbe, 0x08, 0x3b, 0x2a, 0x5a, 0x7f, 0x1b, 0x49, 0x8b, 0xfb, 0x1f, 0x48, 0xea, 0x11, 0xce, 0x25, 0x9f, 0xec, 0xc5, 0x38, 0xaa, 0x6e, 0x74, 0x60, 0x87, 0xf2, 0x38, 0x7f, 0x63, 0xe6, 0x21, 0x5e, 0x5f, 0x47, 0x5e, 0xd9, 0x8b, 0x71, 0xf4, 0x5a, 0x85, 0x18, 0xa3, 0x03, 0xad, 0xf0, 0x3c, 0xbd, 0xdf, 0xae, 0xcf, 0xbe, 0x4f, 0x06, 0xea, 0x0b, 0xd0, 0x06, 0xfa, 0x8a, 0xdd, 0xd9, 0x80, 0x79, 0xe6, 0x74, 0x60, 0x8e, 0x97, 0x12, 0x7e, 0x0f, 0x66, 0xae, 0x77, 0x6e, 0x01, 0x50, 0x48, 0xbc, 0x8b, 0x8a, 0x44, 0x19, 0xcd, 0xf7, 0x7a, 0x29, 0xe6, 0xad, 0x47, 0x1b, 0x3a, 0x67, 0x2a, 0x72, 0x5c, 0xe8, 0x65, 0xd4, 0xbf, 0xca, 0xec, 0x8d, 0x15, 0xa0, 0x55, 0xc7, 0xf9, 0x3c, 0x39, 0xf9, 0xfc, 0x77, 0xe8, 0xf7, 0x47, 0x3c, 0xdf, 0x68, 0x47, 0x3a, 0x89, 0x69, 0xa1, 0x0c, 0x24, 0x0a, 0x31, 0xeb, 0xd9, 0xa8, 0x6b, 0x1e, 0x9f, 0x24, 0xf4, 0xbe, 0x80, 0xaa, 0xfe, 0xc4, 0xb9, 0x51, 0xef, 0x16, 0xe5, 0x73, 0x15, 0x5f, 0xdf, 0x4b, 0x5b, 0x45, 0x2e, 0x4d, 0x93, 0x13, 0x28, 0xee, 0x2f, 0xe0, 0x53, 0x0c, 0xbd, 0x69, 0xb2, 0x0a, 0x23, 0xf7, 0x51, 0x20, 0x85, 0x9e, 0x0e, 0x15, 0x52, 0x7c, 0xc9, 0x22, 0x9a, 0x1b, 0xe8, 0x4d, 0x78, 0x55, 0xdd, 0x81, 0xa4, 0x57, 0x49, 0x12, 0xde, 0x6c, 0x8c, 0xd6, 0xe3, 0x28, 0x72, 0xfa, 0x28, 0xb1, 0x21, 0x87, 0xe6, 0xae, 0x64, 0x69, 0xd5, 0xa3, 0x6c, 0x53, 0x2c, 0x6d, 0x3b, 0x3a, 0xf4, 0x1c, 0xf5, 0x8a, 0x22, 0x9c, 0x62, 0xb6, 0x64, 0xbd, 0xb2, 0x18, 0x63, 0xc8, 0x41, 0x3b, 0xdc, 0xf7, 0xd9, 0x1d, 0xfa, 0xdd, 0x96, 0x4f, 0x16, 0x65, 0x4d, 0xa1, 0xc0, 0x35, 0x45, 0x38, 0x55, 0x21, 0x94, 0xcd, 0x71, 0x94, 0xb8, 0x60, 0x25, 0x2c, 0x87, 0xab, 0xd1, 0x72, 0x90, 0xbb, 0xb2, 0x50, 0xb0, 0x2c, 0x70, 0x50, 0xcb, 0x1d, 0x90, 0x0f, 0x2e, 0xd9, 0x46, 0x2d, 0xb7, 0xe5, 0x62, 0x3e, 0xdd, 0x18, 0x4f, 0x25, 0xea, 0xc8, 0x15, 0x55, 0xef, 0x9c, 0x63, 0x49, 0x9a, 0x7f, 0xb1, 0x9f, 0xa6, 0x89, 0x69, 0xa8, 0xad, 0x18, 0x6b, 0x33, 0x9b, 0xe6, 0x78, 0xc6, 0x94, 0x5d, 0xb7, 0x1d, 0x65, 0x3d, 0x56, 0xa3, 0xf5, 0x8b, 0x8f, 0xb9, 0xc4, 0x82, 0x8b, 0x9d, 0xa8, 0xa3, 0x06, 0x3d, 0x76, 0x57, 0x56, 0x3d, 0xc5, 0xe5, 0x06, 0xfd, 0xd5, 0x88, 0xbd, 0x50, 0x23, 0x2e, 0x04, 0x0e, 0x33, 0x96, 0x40, 0x87, 0x7e, 0xd7, 0x34, 0x8d, 0xb4, 0x45, 0x62, 0xcb, 0x97, 0x65, 0xce, 0xf4, 0xa7, 0x3b, 0xf4, 0xfb, 0x3f, 0x9f, 0x08, 0x6c, 0xd5, 0xed, 0x48, 0xca, 0x91, 0x25, 0x0e, 0x8c, 0x41, 0x4a, 0x07, 0xef, 0xfd, 0x42, 0xe1, 0xf3, 0xcd, 0x3b, 0x6d, 0x22, 0xb1, 0x3c, 0xd0, 0x37, 0x32, 0xce, 0xc1, 0xfa, 0x30, 0x2d, 0x73, 0xf2, 0x38, 0xde, 0xfb, 0x38, 0xea, 0xe5, 0x78, 0x0c, 0xb6, 0xc9, 0xdf, 0x8a, 0x3b, 0x04, 0x5a, 0xff, 0xcf, 0xb1, 0xda, 0xe7, 0x2a, 0xed, 0xaa, 0xdf, 0xf1, 0xbd, 0xc9, 0xa1, 0xfa, 0x93, 0xea, 0xd0, 0xf6, 0x24, 0x10, 0xd7, 0x7a, 0x2c, 0x29, 0x91, 0xca, 0xc6, 0xca, 0x46, 0xb6, 0xa6, 0x88, 0xab, 0x02, 0x83, 0x45, 0x76, 0xb9, 0x14, 0xfb, 0xc4, 0x97, 0xdc, 0xb7, 0xef, 0x74, 0x45, 0xf8, 0x44, 0x90, 0xb6, 0x6d, 0x3c, 0xc6, 0xbd, 0x1d, 0x7c, 0x4f, 0xc3, 0x2a, 0xf9, 0x4a, 0x94, 0x4d, 0x17, 0x28, 0xbd, 0xc5, 0x3b, 0x61, 0x94, 0xfd, 0xbe, 0xbc, 0x43, 0xbf, 0x5b, 0x2c, 0x72, 0x15, 0x63, 0x9f, 0xe4, 0x41, 0x8f, 0x67, 0x21, 0x90, 0x2c, 0xa1, 0xc0, 0x3c, 0x58, 0x68, 0xef, 0xe7, 0xa1, 0x95, 0x2b, 0x1a, 0x45, 0xf3, 0x48, 0x9e, 0xff, 0x32, 0x78, 0xcf, 0x11, 0x8d, 0xcf, 0x41, 0xc3, 0x63, 0xad, 0x87, 0xc3, 0x5d, 0x8f, 0x8b, 0xf1, 0xdd, 0x81, 0xab, 0xc8, 0x72, 0x2c, 0x38, 0x67, 0x12, 0x6d, 0x48, 0x4e, 0xa0, 0x06, 0xab, 0x84, 0x7c, 0xd6, 0x16, 0x70, 0x69, 0xfd, 0x40, 0xaa, 0x04, 0xfd, 0x5e, 0x8f, 0x91, 0xe4, 0x3a, 0x32, 0x2b, 0x58, 0x3f, 0x40, 0x2d, 0x4e, 0xd6, 0x6f, 0xb4, 0xdc, 0xb4, 0xe8, 0x1c, 0x27, 0xf9, 0x8a, 0xb8, 0x0c, 0x4e, 0x87, 0x7f, 0x3a, 0x6c, 0x44, 0xd4, 0x3b, 0x4d, 0x9d, 0xf5, 0xd1, 0x6d, 0x54, 0x3d, 0xc3, 0x6b, 0xc9, 0x67, 0xf3, 0xfb, 0x1d, 0xfa, 0xbd, 0x66, 0xaf, 0xaf, 0xd4, 0x8c, 0x93, 0x6f, 0x55, 0x71, 0x6c, 0x57, 0x9c, 0x47, 0xef, 0x44, 0xea, 0x2d, 0x2a, 0x53, 0x63, 0x16, 0xea, 0x97, 0xe8, 0xa7, 0x1d, 0xbc, 0x0f, 0xd8, 0xcf, 0x75, 0x93, 0xbe, 0xf1, 0xeb, 0xfc, 0x67, 0x32, 0xf9, 0x01, 0x95, 0x2f, 0xcd, 0x1b, 0xd1, 0x97, 0x3a, 0xb4, 0x5f, 0x0d, 0x78, 0xcb, 0x94, 0x7f, 0xb4, 0x8c, 0x4d, 0x78, 0x15, 0xf9, 0xb9, 0xca, 0x76, 0x96, 0xa1, 0x8f, 0xfc, 0xe6, 0x84, 0x6d, 0xe8, 0x44, 0xf4, 0xba, 0x4a, 0xd9, 0xd0, 0xb4, 0xde, 0x9b, 0x27, 0xd5, 0x9b, 0xa9, 0xf4, 0xd2, 0x7b, 0xf2, 0x6d, 0xb3, 0x27, 0xf5, 0x18, 0x36, 0xfb, 0x26, 0xd9, 0xea, 0x38, 0xd6, 0xa1, 0xfd, 0x40, 0xb7, 0x7f, 0x12, 0xf6, 0x73, 0x1c, 0xe5, 0x3c, 0x6a, 0xcc, 0x0e, 0xb3, 0x67, 0x3f, 0xb4, 0xcb, 0xeb, 0x13, 0xe4, 0xb5, 0xb4, 0x3c, 0x5d, 0x5e, 0xae, 0xb5, 0x97, 0xef, 0xcb, 0x94, 0x4f, 0xcb, 0xb3, 0x46, 0xc9, 0xcf, 0x1b, 0x23, 0xcf, 0x1f, 0x25, 0x4f, 0x66, 0xe4, 0xec, 0x25, 0x78, 0xce, 0x8a, 0xed, 0xf2, 0x25, 0x51, 0xf2, 0xb6, 0xe4, 0x8e, 0x9a, 0xab, 0x29, 0xa3, 0xca, 0x0f, 0x8e, 0xe9, 0xff, 0x8c, 0xb5, 0x7a, 0xec, 0xba, 0xff, 0x31, 0xf4, 0x7f, 0x64, 0xec, 0xd5, 0xa3, 0xca, 0x6e, 0x1d, 0xd3, 0xf6, 0x5c, 0x7b, 0xd9, 0x25, 0x3b, 0xd0, 0x76, 0x7e, 0xa6, 0xde, 0xe6, 0x51, 0xf5, 0xf6, 0xab, 0x7a, 0xf3, 0x55, 0x49, 0x49, 0xad, 0x90, 0xbd, 0xc0, 0xe7, 0xdc, 0xed, 0x2b, 0x89, 0xfb, 0x67, 0xe0, 0xbe, 0x35, 0xcd, 0x91, 0x83, 0xd9, 0xe7, 0x78, 0xa8, 0xf7, 0x60, 0x25, 0x52, 0xd5, 0xb0, 0x39, 0x9d, 0x74, 0x30, 0xbb, 0xf7, 0xe0, 0x14, 0xa4, 0x66, 0x21, 0xb5, 0x5a, 0xa5, 0xa6, 0x62, 0x1d, 0x2f, 0xc4, 0xd9, 0xca, 0x75, 0x4c, 0x72, 0x7e, 0x07, 0xeb, 0x88, 0x13, 0x03, 0x7e, 0xaa, 0xa3, 0x12, 0xe5, 0x26, 0x53, 0xb9, 0x03, 0x16, 0xc8, 0xff, 0x18, 0xee, 0x79, 0x1e, 0x47, 0x83, 0x03, 0xf7, 0x74, 0x0f, 0xa7, 0x09, 0xf7, 0xc5, 0xcd, 0x37, 0x54, 0x80, 0xbb, 0x97, 0x76, 0xd3, 0x96, 0xeb, 0xfd, 0xe0, 0xee, 0x42, 0x54, 0x1b, 0xf5, 0x7f, 0x5b, 0x3d, 0xbf, 0x83, 0x7b, 0xe5, 0x34, 0xd4, 0x19, 0xf7, 0x72, 0xbf, 0x8b, 0x1c, 0xc5, 0x34, 0x7d, 0xe9, 0x32, 0x3a, 0x55, 0xf0, 0x27, 0x00, 0x51, 0xbf, 0x03, 0xa3, 0x0e, 0x70, 0x9f, 0x9c, 0x1e, 0xec, 0x6c, 0x27, 0x71, 0x8d, 0x6e, 0xb4, 0xea, 0xb3, 0xa2, 0xde, 0x27, 0x4c, 0x4f, 0x3e, 0x23, 0x7c, 0xa7, 0x4e, 0x1f, 0x58, 0x8e, 0xf1, 0x6c, 0xcd, 0x9a, 0x46, 0x1d, 0x59, 0x2e, 0xb7, 0xaf, 0xb4, 0x3c, 0x2b, 0x47, 0x71, 0xd1, 0xfa, 0x47, 0x11, 0x4b, 0xe5, 0x5a, 0x0d, 0x56, 0x31, 0xec, 0xb3, 0x6f, 0xc6, 0xf4, 0xe5, 0x2b, 0xc8, 0xa7, 0x22, 0x2f, 0x78, 0x6d, 0x57, 0x87, 0xcb, 0xe1, 0xf4, 0x4d, 0xf0, 0x29, 0x1a, 0xad, 0x7f, 0x8e, 0xae, 0x71, 0x0c, 0xaa, 0xd5, 0xcb, 0x75, 0x44, 0xfd, 0x3e, 0x3a, 0xa8, 0xfc, 0x14, 0xdb, 0x16, 0x1e, 0xa3, 0x1e, 0xcb, 0x41, 0xaa, 0xba, 0x2e, 0xcf, 0x51, 0xf5, 0x0e, 0xf0, 0x7b, 0xe0, 0x77, 0xc0, 0xcf, 0x81, 0xe7, 0x71, 0x30, 0xd5, 0x67, 0x06, 0x23, 0x3f, 0x7b, 0x16, 0xd3, 0x3f, 0x95, 0x3e, 0xf1, 0x47, 0xcb, 0xf9, 0xb3, 0x8e, 0x12, 0xd8, 0x42, 0x7e, 0xf7, 0xe8, 0xe5, 0x7d, 0x61, 0x2d, 0xbc, 0x49, 0x2c, 0xb8, 0x51, 0x34, 0xdf, 0x20, 0xe4, 0xe9, 0xb7, 0x8a, 0x86, 0x9b, 0x85, 0xde, 0x4b, 0xbc, 0x5f, 0x1e, 0x58, 0x4b, 0xca, 0x1f, 0x0d, 0xfa, 0x1f, 0x82, 0xa7, 0x1f, 0xd9, 0x67, 0x2c, 0x7b, 0x24, 0x23, 0xbb, 0x2f, 0x23, 0xb3, 0xd4, 0x2f, 0xd1, 0x13, 0x6b, 0xf5, 0xf9, 0x1f, 0xac, 0xff, 0x21, 0x62, 0x80, 0x7c, 0x73, 0x2a, 0x89, 0x9e, 0x5f, 0xab, 0xcf, 0x7f, 0xb7, 0xbf, 0x42, 0xc5, 0xfe, 0x0e, 0xa3, 0xff, 0xb2, 0xd1, 0x8f, 0xd7, 0x5f, 0x45, 0x95, 0x16, 0xef, 0x2a, 0x87, 0x4a, 0xbf, 0x6e, 0xda, 0x88, 0x2f, 0xd9, 0x47, 0x95, 0xe6, 0x1c, 0x70, 0x3c, 0xc7, 0x79, 0x6f, 0xa7, 0x65, 0x1b, 0xbe, 0x05, 0x59, 0xba, 0x6f, 0xba, 0xbe, 0x0f, 0xd2, 0xb2, 0xfa, 0x3d, 0xa8, 0x4f, 0x97, 0x4b, 0xcb, 0x64, 0x67, 0x5a, 0x76, 0xbe, 0x4d, 0xa6, 0xc7, 0x94, 0xd3, 0x99, 0x1e, 0xd3, 0x91, 0xcc, 0x98, 0xdc, 0x68, 0x91, 0xf7, 0xbd, 0xcf, 0xc8, 0x86, 0x5d, 0xd7, 0x2a, 0xef, 0xa0, 0xdb, 0xd3, 0xfd, 0xac, 0xec, 0x34, 0xe3, 0x5d, 0xf2, 0x30, 0x79, 0xe7, 0xe6, 0xab, 0x7b, 0x00, 0xa7, 0xab, 0xd3, 0xf5, 0x2d, 0x79, 0x00, 0x71, 0x42, 0xfa, 0x1c, 0xeb, 0x7e, 0x2c, 0x4a, 0x97, 0xa9, 0x7f, 0x50, 0xcd, 0x51, 0xba, 0x0f, 0x4b, 0x32, 0x7d, 0xf8, 0xde, 0x98, 0x39, 0x5f, 0x95, 0x91, 0xfd, 0x20, 0x23, 0x73, 0x9a, 0xfa, 0xd6, 0xa6, 0x65, 0xf5, 0xdf, 0x47, 0x74, 0x37, 0xba, 0xdc, 0x59, 0x99, 0x72, 0xf7, 0x67, 0xca, 0x65, 0x99, 0x72, 0x9f, 0xee, 0xe4, 0x77, 0x86, 0x3c, 0x1f, 0x9f, 0xa5, 0x90, 0xdb, 0xf8, 0x48, 0x14, 0x6b, 0x90, 0x59, 0xf0, 0x63, 0x35, 0xc8, 0xdf, 0x40, 0x52, 0x14, 0x4a, 0x9f, 0xac, 0xfa, 0x5b, 0xda, 0x8e, 0x47, 0x3a, 0xf5, 0xfd, 0x6b, 0xb6, 0x28, 0xe7, 0x99, 0x41, 0x7d, 0xc5, 0xda, 0x63, 0x1e, 0xf7, 0xf9, 0xab, 0x3e, 0x2c, 0x22, 0xe9, 0xaf, 0xfa, 0x4b, 0xb1, 0x8a, 0x03, 0xaa, 0xde, 0x2f, 0x86, 0xdf, 0x01, 0xfd, 0x2f, 0x5f, 0x7d, 0xd5, 0x3b, 0xc5, 0x74, 0x11, 0xf3, 0xbf, 0x23, 0xe1, 0x56, 0xf5, 0x70, 0x9f, 0xd8, 0xaf, 0xe6, 0x90, 0x8e, 0xd5, 0x7d, 0xa4, 0x3f, 0x0f, 0x2b, 0x53, 0x32, 0xed, 0x57, 0x2f, 0xee, 0xd4, 0x3e, 0xa9, 0x7b, 0x49, 0x85, 0xcd, 0x7f, 0x73, 0xc4, 0xc7, 0x39, 0xf1, 0xfa, 0x7f, 0x21, 0x87, 0xa8, 0xfa, 0x90, 0x32, 0x7b, 0xec, 0x72, 0x33, 0x56, 0xae, 0x67, 0x33, 0xf6, 0x59, 0x3e, 0x8d, 0xd8, 0xce, 0xab, 0x3b, 0xf5, 0xe7, 0x70, 0x51, 0xef, 0x45, 0xea, 0x0e, 0xa0, 0xeb, 0x09, 0x54, 0x96, 0x53, 0x03, 0x7a, 0xc4, 0x34, 0xea, 0x5d, 0x4e, 0x1c, 0x51, 0x2f, 0xc0, 0x2d, 0xbc, 0xea, 0x7d, 0x1d, 0xd1, 0x12, 0xdd, 0xdc, 0xa9, 0xef, 0x7f, 0x3e, 0x6f, 0x81, 0x9a, 0x37, 0xae, 0xff, 0xae, 0x4e, 0xdd, 0x46, 0x77, 0xd7, 0x98, 0x7e, 0x21, 0x27, 0x7e, 0xd6, 0x17, 0xc9, 0x19, 0x34, 0x67, 0x9f, 0xf8, 0xec, 0x77, 0xa1, 0xbe, 0xf4, 0xfc, 0xdd, 0xd7, 0x99, 0xf6, 0x83, 0x53, 0x47, 0xd9, 0xf6, 0x87, 0x3a, 0xf5, 0x3d, 0x96, 0x6d, 0x22, 0xf7, 0x6f, 0x92, 0x98, 0x25, 0xd8, 0x26, 0x7a, 0xc1, 0x4f, 0xa5, 0xd3, 0xcc, 0x5e, 0xd5, 0xf3, 0xf2, 0x68, 0xa7, 0xfe, 0x1c, 0x91, 0xc7, 0x62, 0x65, 0xc6, 0x12, 0xf5, 0x5e, 0xaa, 0xe2, 0x0c, 0x1f, 0xee, 0x48, 0xf3, 0xb1, 0xaf, 0x02, 0x73, 0xa6, 0x20, 0x4a, 0x58, 0x87, 0x32, 0x55, 0x7f, 0xa4, 0x8c, 0x1f, 0x7e, 0xc1, 0xb4, 0xbf, 0xc1, 0xeb, 0x57, 0x73, 0x2b, 0x8d, 0xdf, 0x7e, 0xb9, 0x93, 0xdf, 0x43, 0x73, 0x9d, 0xfb, 0xd5, 0x7a, 0xaa, 0x38, 0x09, 0x63, 0xf6, 0x51, 0xd5, 0xdf, 0x2c, 0x33, 0x17, 0xaf, 0x76, 0x8e, 0xdc, 0xad, 0xd2, 0xf7, 0xad, 0xa3, 0x9d, 0xf6, 0xfb, 0x96, 0xf6, 0x17, 0xef, 0x7d, 0xc2, 0xba, 0x5d, 0x6e, 0xd6, 0x2d, 0xad, 0xff, 0xe1, 0x27, 0xe8, 0x5f, 0x91, 0x59, 0x67, 0xdd, 0x0f, 0x47, 0xd7, 0xd8, 0x7e, 0xe4, 0x8f, 0x93, 0x57, 0x62, 0xcb, 0xe3, 0x88, 0x8c, 0xcf, 0xdc, 0x94, 0x2e, 0x73, 0x37, 0xb0, 0x7c, 0x7f, 0xec, 0xee, 0xe7, 0xda, 0x3f, 0x43, 0x2b, 0x9d, 0xb9, 0xea, 0x3d, 0x58, 0xef, 0xa0, 0x65, 0xa8, 0x83, 0x36, 0x25, 0x5d, 0x88, 0x40, 0xeb, 0x88, 0x6f, 0xc7, 0x1c, 0x81, 0x6e, 0x1a, 0xcc, 0x42, 0xda, 0x45, 0x7c, 0x4b, 0x46, 0x5a, 0x6e, 0x4a, 0xb8, 0x8d, 0xae, 0x87, 0xdf, 0xb5, 0x75, 0x6d, 0x1a, 0x74, 0x42, 0x8e, 0x78, 0xc4, 0xbb, 0x59, 0xe9, 0x0f, 0x7a, 0xf7, 0xf2, 0x3c, 0xa2, 0x5c, 0x36, 0x62, 0xef, 0x99, 0xe4, 0xf3, 0xc5, 0x97, 0xb4, 0x50, 0x50, 0xf6, 0x06, 0xcb, 0x29, 0x00, 0x14, 0x0a, 0x51, 0x59, 0xf5, 0x92, 0x98, 0x53, 0xf5, 0x9e, 0x9e, 0x07, 0xde, 0x57, 0xa7, 0x77, 0xe9, 0x77, 0x07, 0xe3, 0xcf, 0x43, 0x60, 0x59, 0x25, 0xc5, 0xd7, 0x7f, 0x89, 0x1c, 0xeb, 0xaa, 0xfe, 0xca, 0xb6, 0x49, 0xfb, 0xed, 0xe5, 0x27, 0x2d, 0x33, 0x6f, 0xc5, 0xc7, 0x1f, 0xab, 0xf9, 0x5b, 0xb2, 0x9b, 0x1c, 0x41, 0x2e, 0xe3, 0xe1, 0xf7, 0xfa, 0xd0, 0x5d, 0xd7, 0xa5, 0x3f, 0xef, 0x0c, 0xec, 0x99, 0x8c, 0xfe, 0xf2, 0xdb, 0x1c, 0x0f, 0xfa, 0x3e, 0x89, 0xba, 0x2f, 0x82, 0x67, 0x45, 0xac, 0x97, 0x8d, 0x38, 0x31, 0xea, 0xad, 0x60, 0xea, 0x88, 0x7a, 0xa7, 0x30, 0x75, 0x46, 0xbd, 0x93, 0x40, 0x73, 0x5c, 0xee, 0x3d, 0xc3, 0x59, 0x5f, 0x30, 0xe7, 0x81, 0xf7, 0x86, 0x07, 0x6d, 0xb1, 0x8d, 0xfc, 0x74, 0x97, 0xfe, 0x8c, 0xdf, 0xe7, 0xed, 0x4e, 0xa0, 0x27, 0x1c, 0xe7, 0x0b, 0xc4, 0xf9, 0x42, 0x47, 0xdb, 0x51, 0xef, 0x30, 0x7a, 0x5c, 0x9d, 0xc5, 0x36, 0x83, 0xe5, 0x51, 0x6f, 0xa9, 0xa9, 0xb5, 0x84, 0xa9, 0xcb, 0x3d, 0x28, 0xf6, 0x0d, 0xbb, 0xae, 0xe4, 0xbd, 0xfa, 0x56, 0xac, 0xfe, 0x14, 0xda, 0x9f, 0x0d, 0x8b, 0xf2, 0x66, 0xd4, 0x9b, 0x42, 0xa9, 0xaa, 0xd7, 0xe1, 0xa8, 0xd4, 0x58, 0xd9, 0x36, 0x4c, 0x34, 0xb4, 0xc8, 0x20, 0xd7, 0xc4, 0xfc, 0x9f, 0xe9, 0xd2, 0x9f, 0xd9, 0x16, 0x39, 0x2a, 0xd0, 0x62, 0xf7, 0x5e, 0xf4, 0xc1, 0xa5, 0xfa, 0xe0, 0x6a, 0x14, 0x16, 0x7a, 0xd0, 0x98, 0x9d, 0x47, 0xe7, 0x08, 0xdc, 0x6c, 0x96, 0xf2, 0x49, 0x29, 0x86, 0xdd, 0xf1, 0x08, 0xdf, 0xb4, 0xb9, 0x95, 0x6e, 0x8a, 0x2d, 0x39, 0x95, 0x0e, 0x3d, 0x80, 0xf6, 0xde, 0xd5, 0xf2, 0xdf, 0xe3, 0xd6, 0x31, 0x01, 0xf2, 0x5c, 0xd1, 0x20, 0xde, 0xcc, 0xf0, 0x51, 0xff, 0x93, 0xbc, 0x9e, 0x4e, 0xae, 0x99, 0x7b, 0x9d, 0xc3, 0xbd, 0xbe, 0x48, 0x1c, 0xd4, 0xbd, 0xf6, 0x79, 0xab, 0x9e, 0xd5, 0x6b, 0xc2, 0xeb, 0x78, 0x7d, 0x97, 0x3e, 0x9f, 0xa3, 0xd7, 0x44, 0xcf, 0x04, 0xe7, 0xf1, 0xe8, 0x5d, 0xd8, 0x43, 0xf1, 0xf5, 0x07, 0xb0, 0x9a, 0x28, 0xfb, 0x27, 0x32, 0x9e, 0x86, 0xe8, 0x4e, 0xdb, 0x9e, 0xcd, 0x36, 0xfe, 0xee, 0x7e, 0xb3, 0xc6, 0xb1, 0x8d, 0xa7, 0x51, 0x60, 0xd8, 0x5e, 0x2b, 0xdf, 0xf5, 0xf4, 0x19, 0xf9, 0x11, 0xce, 0x08, 0x97, 0x29, 0x30, 0x6b, 0xfc, 0x24, 0xca, 0xf0, 0xbb, 0xdc, 0xee, 0xe7, 0xa1, 0x6d, 0xf1, 0x4c, 0x08, 0x4b, 0xad, 0x86, 0x28, 0x10, 0x51, 0x2f, 0xc7, 0xf2, 0x9e, 0x6c, 0x5e, 0x53, 0xdc, 0x3c, 0xdd, 0xbf, 0xb8, 0xea, 0x63, 0xd8, 0x73, 0x7e, 0x33, 0xed, 0x13, 0x55, 0x7f, 0xe8, 0x7e, 0x01, 0x33, 0x88, 0xf1, 0x96, 0xe3, 0x0e, 0xc5, 0xeb, 0xcf, 0x76, 0x94, 0x57, 0x6a, 0x0a, 0x53, 0x97, 0xfb, 0xf9, 0xe1, 0xac, 0xab, 0x79, 0xc4, 0x85, 0x55, 0xaf, 0x7c, 0xb2, 0xe6, 0x41, 0xad, 0xf9, 0xf8, 0x27, 0x6b, 0x5e, 0xc3, 0xb6, 0xd7, 0x3b, 0x99, 0xd3, 0x39, 0xbe, 0xc2, 0x45, 0x93, 0x67, 0x91, 0xaf, 0x72, 0x7a, 0x79, 0x0b, 0xec, 0xe7, 0xc5, 0xf4, 0x6f, 0xe4, 0x9b, 0xb4, 0xe0, 0x81, 0x4a, 0xe2, 0x5a, 0xb8, 0x8e, 0xef, 0x70, 0x1d, 0xfe, 0xa9, 0x4c, 0x85, 0xcf, 0xb9, 0xdc, 0x99, 0xeb, 0xdc, 0xbb, 0xe1, 0xa7, 0x13, 0xa2, 0x7e, 0xbf, 0xce, 0x29, 0x59, 0xee, 0xca, 0x75, 0xed, 0x1d, 0xf8, 0x69, 0x49, 0xba, 0xde, 0x97, 0x3d, 0x1e, 0x51, 0xf5, 0x1a, 0xfa, 0x71, 0x71, 0xb1, 0xe0, 0x0f, 0xaa, 0xbe, 0x77, 0xd5, 0xeb, 0x1e, 0x91, 0xd5, 0xe8, 0x29, 0xa3, 0x7f, 0x74, 0x04, 0x33, 0x69, 0xe0, 0x63, 0x7b, 0x7f, 0xfe, 0x37, 0x3d, 0xe1, 0x9a, 0xaa, 0x7e, 0xf5, 0xcf, 0xf7, 0xe0, 0x6a, 0xd3, 0x83, 0x53, 0xfe, 0xcf, 0x3d, 0xb8, 0x5a, 0xf5, 0x00, 0xcb, 0x6c, 0xf3, 0xc1, 0xfc, 0xdd, 0x91, 0x3a, 0x43, 0xd9, 0xba, 0xf2, 0xe7, 0x6d, 0x49, 0xb5, 0xf7, 0xa4, 0x8a, 0xef, 0x5b, 0xd6, 0x69, 0x7f, 0x8f, 0x3e, 0x22, 0x46, 0xe6, 0xb7, 0x26, 0x93, 0xac, 0x8b, 0x84, 0xaf, 0x78, 0xfa, 0x72, 0xc4, 0xc8, 0xce, 0xad, 0x2e, 0xc4, 0xc8, 0x2a, 0xde, 0x7d, 0x14, 0x91, 0x07, 0xdf, 0x71, 0xdd, 0xe8, 0x77, 0x1e, 0xec, 0x42, 0x1e, 0x47, 0x04, 0xbe, 0xe9, 0xd3, 0x10, 0x21, 0x5b, 0x1c, 0x21, 0x67, 0x21, 0xee, 0xed, 0x70, 0x48, 0x8b, 0x23, 0xe3, 0x41, 0x59, 0xf5, 0x6e, 0x9e, 0xac, 0x7a, 0x1b, 0x78, 0x0b, 0x38, 0xca, 0xfb, 0xbd, 0x10, 0x7d, 0x9b, 0xac, 0xce, 0x33, 0xac, 0xa1, 0x3c, 0xbd, 0xa4, 0xa1, 0xcc, 0x5a, 0x58, 0xb5, 0xa0, 0xba, 0x79, 0x96, 0xcd, 0x9e, 0xc7, 0xd6, 0x8d, 0x9c, 0x8d, 0xf4, 0xbb, 0xc7, 0x9d, 0xeb, 0x74, 0x1c, 0xd1, 0x20, 0xdd, 0xea, 0x8d, 0xd0, 0xdd, 0xfc, 0x99, 0x23, 0xf9, 0x96, 0x54, 0x7d, 0xa4, 0xdf, 0xc9, 0xf2, 0x98, 0x2e, 0x5a, 0x37, 0x9e, 0xef, 0xd7, 0x9e, 0x1e, 0xe3, 0xaa, 0x5f, 0x48, 0x7e, 0x11, 0xa8, 0x64, 0x6f, 0xd9, 0xc5, 0x33, 0xf4, 0x3e, 0x7f, 0xef, 0x97, 0x7f, 0xb4, 0xc7, 0xd4, 0xdf, 0x59, 0xaa, 0x47, 0x5e, 0x83, 0xc9, 0x4f, 0xff, 0x2c, 0x3f, 0x41, 0x8f, 0xbf, 0x9f, 0xd4, 0x85, 0xbc, 0x8d, 0x27, 0xe8, 0xf5, 0x9f, 0x90, 0x4e, 0x9d, 0x50, 0xee, 0x1c, 0x60, 0x0f, 0xf2, 0x2e, 0x3d, 0x21, 0x9f, 0x3f, 0x73, 0x3e, 0x50, 0xa2, 0xe3, 0x8f, 0x22, 0x44, 0x1c, 0x9c, 0x3f, 0xd5, 0xac, 0x53, 0x39, 0xc6, 0x56, 0x66, 0x74, 0x05, 0x69, 0x9d, 0xf4, 0x1d, 0x5c, 0x66, 0x90, 0xab, 0xd2, 0xb9, 0x46, 0x27, 0xfd, 0x3d, 0xa4, 0x79, 0x86, 0xd6, 0x1a, 0x9a, 0x95, 0xd1, 0xd7, 0xf1, 0x45, 0xad, 0x89, 0x16, 0x38, 0xaf, 0xc2, 0xd4, 0x79, 0x8a, 0xd1, 0xad, 0x36, 0xf9, 0xb5, 0x66, 0xfe, 0x1b, 0xe1, 0x4d, 0x39, 0xbf, 0xc9, 0xf4, 0x4b, 0xda, 0xfa, 0xd0, 0x44, 0xcb, 0x49, 0xaf, 0x6d, 0x3a, 0xad, 0xeb, 0x4f, 0xf7, 0xd3, 0x91, 0xe1, 0xcd, 0x7b, 0x3b, 0x33, 0x72, 0x69, 0x64, 0xd2, 0xc8, 0x74, 0xdf, 0xa4, 0xa9, 0xdf, 0xad, 0x62, 0x46, 0x9d, 0xd7, 0x64, 0xe8, 0x62, 0x43, 0x97, 0xaa, 0x1a, 0x2c, 0x23, 0x67, 0xbb, 0x3f, 0xd2, 0x8e, 0xbe, 0xc3, 0x5a, 0x8a, 0x2e, 0x35, 0xf3, 0xa5, 0xef, 0xc4, 0x4c, 0xb3, 0x0d, 0xcd, 0x33, 0x65, 0x0b, 0xa9, 0x46, 0xe9, 0x16, 0xdb, 0xfa, 0x5a, 0x8c, 0xd1, 0x72, 0xca, 0x65, 0xe3, 0xd3, 0x63, 0x49, 0xaf, 0x45, 0xb9, 0xa1, 0x15, 0x99, 0xf9, 0x5b, 0x6a, 0xe6, 0xb4, 0x50, 0x7d, 0xae, 0xa1, 0xe7, 0xae, 0xd6, 0xe4, 0x2d, 0x55, 0x79, 0x0e, 0xb5, 0x26, 0x23, 0x75, 0x35, 0x9a, 0xbc, 0x46, 0xdb, 0xf8, 0x1b, 0x55, 0x4a, 0x7f, 0xff, 0x88, 0xe9, 0x52, 0xd2, 0xe7, 0x77, 0xa9, 0xad, 0x1c, 0x63, 0x99, 0xa1, 0x2d, 0x66, 0xac, 0x2c, 0x29, 0xb0, 0xf1, 0xe9, 0xef, 0x8a, 0x31, 0x37, 0x32, 0xc7, 0x05, 0x99, 0xb5, 0x9b, 0x66, 0xe4, 0x5e, 0x53, 0xe7, 0x64, 0xd3, 0x4e, 0x6d, 0x46, 0x53, 0xf7, 0xad, 0x36, 0xa3, 0x2d, 0xb2, 0x49, 0x78, 0x48, 0xe4, 0x91, 0xa8, 0x22, 0x59, 0xb5, 0x86, 0x10, 0xec, 0x88, 0x66, 0x72, 0x35, 0x87, 0xa3, 0xe1, 0xd4, 0x99, 0x24, 0xcf, 0x6c, 0x22, 0xc7, 0x99, 0x4d, 0x78, 0xba, 0xf8, 0x39, 0xb3, 0x87, 0xf2, 0x5a, 0xb6, 0x07, 0xa3, 0xdb, 0x42, 0x67, 0x05, 0x53, 0x7d, 0xdb, 0x43, 0x09, 0x2a, 0x69, 0x89, 0xed, 0x88, 0xc7, 0xa2, 0xa1, 0x68, 0xaa, 0x2b, 0x14, 0x4a, 0xf4, 0x84, 0x43, 0x3b, 0x6b, 0xcf, 0x0d, 0x0e, 0x07, 0xc9, 0xd3, 0x12, 0x8b, 0x46, 0x43, 0x7d, 0xa9, 0x70, 0x2c, 0x4a, 0x62, 0x25, 0xc9, 0x95, 0xad, 0x24, 0x5a, 0x49, 0xb6, 0xce, 0x04, 0x5a, 0xc9, 0x6a, 0x6d, 0xe5, 0xc4, 0x1a, 0x30, 0x6b, 0xda, 0xc1, 0xb4, 0x93, 0x58, 0x43, 0x72, 0x0d, 0xa3, 0x9d, 0x2a, 0xd6, 0x0c, 0xf5, 0x85, 0x96, 0xf6, 0xf5, 0x85, 0x92, 0xc9, 0xf0, 0xd6, 0x70, 0x24, 0x9c, 0xda, 0xbd, 0x36, 0xd6, 0x1f, 0xea, 0x4a, 0xc4, 0x86, 0xc3, 0xfd, 0x68, 0xb1, 0xb4, 0x2d, 0xb4, 0x7b, 0x6b, 0x2c, 0x98, 0xe8, 0x5f, 0x1e, 0x4e, 0xee, 0x08, 0x27, 0x93, 0xed, 0xe1, 0x64, 0x2a, 0x14, 0x85, 0x40, 0xa0, 0xa6, 0x76, 0xd4, 0xdd, 0xce, 0x75, 0xb7, 0xa3, 0xee, 0xf6, 0x35, 0xad, 0xe4, 0xc0, 0x83, 0x93, 0xed, 0x48, 0x2a, 0x21, 0x04, 0x8e, 0x76, 0x96, 0x80, 0x6d, 0xa7, 0x92, 0xf6, 0x60, 0xb4, 0x3f, 0x11, 0x0b, 0xf7, 0xd7, 0x05, 0xe3, 0xf1, 0xba, 0xa5, 0xe8, 0xef, 0x30, 0xda, 0x6b, 0xa2, 0xf9, 0xa3, 0xf3, 0xe3, 0xf1, 0x48, 0xb8, 0x2f, 0xc8, 0x83, 0x99, 0x91, 0xd6, 0x69, 0x0f, 0x0f, 0x84, 0xfa, 0x76, 0xf7, 0x45, 0x42, 0x2d, 0xc1, 0x48, 0x64, 0x6b, 0xb0, 0xef, 0xbc, 0x64, 0x13, 0x4d, 0x3c, 0x59, 0x29, 0xbb, 0xa8, 0x2f, 0x16, 0x45, 0x7f, 0x53, 0x75, 0x2d, 0x4c, 0x77, 0xa5, 0xec, 0xa2, 0x6d, 0x89, 0x60, 0x7c, 0x7b, 0xb8, 0x2f, 0x59, 0xd7, 0x12, 0x8c, 0x0e, 0x07, 0x51, 0xe1, 0x94, 0x71, 0x44, 0xb1, 0x48, 0x2c, 0xb1, 0x32, 0x1c, 0x49, 0x85, 0x12, 0x27, 0x97, 0x77, 0x04, 0x53, 0x89, 0xf0, 0xae, 0x26, 0x9a, 0xf9, 0x77, 0xe5, 0xa3, 0xaa, 0x2a, 0x1b, 0xab, 0xda, 0x15, 0x0c, 0x47, 0x53, 0xe3, 0x4b, 0x62, 0x4a, 0x52, 0x3a, 0x56, 0xb2, 0x1e, 0x6b, 0xde, 0x44, 0x93, 0x32, 0x82, 0x58, 0xb2, 0x6e, 0xd9, 0x50, 0x38, 0xd2, 0x3f, 0xa3, 0x67, 0xc5, 0xfa, 0xee, 0xd6, 0xce, 0xb5, 0x4d, 0x54, 0x34, 0x5a, 0x16, 0xed, 0x8f, 0x84, 0x9a, 0xa8, 0xd8, 0x9e, 0xd9, 0xba, 0x2c, 0x1c, 0xed, 0xe7, 0x3e, 0x8d, 0xd4, 0xcf, 0x33, 0x55, 0xb7, 0xa2, 0x3f, 0x9c, 0x0a, 0x6e, 0x65, 0xf5, 0xb2, 0xd1, 0x82, 0xee, 0x50, 0x44, 0x6f, 0x35, 0x7b, 0xcb, 0x5a, 0x12, 0x0f, 0x46, 0xcd, 0x56, 0x1d, 0x5b, 0x0a, 0xb2, 0xa8, 0xae, 0xef, 0x94, 0x93, 0x48, 0xba, 0x31, 0x4d, 0xd1, 0x6d, 0x6a, 0x00, 0x5c, 0xc1, 0x09, 0x95, 0x07, 0xf0, 0xc8, 0x54, 0xee, 0xcb, 0xc8, 0x86, 0x52, 0xe1, 0x08, 0xcf, 0x5d, 0xc2, 0x36, 0xd4, 0x4c, 0x5e, 0x13, 0xcd, 0xca, 0x64, 0x0e, 0xe3, 0xb4, 0xd4, 0xb5, 0x6c, 0x8f, 0x25, 0x42, 0x31, 0x35, 0x7f, 0xa1, 0xc4, 0x8c, 0x95, 0x89, 0xe0, 0x8e, 0xcc, 0x8e, 0x6a, 0xa2, 0xf2, 0xbf, 0xa3, 0x6b, 0x9f, 0x1e, 0x25, 0xc5, 0xb9, 0x58, 0x31, 0x1c, 0x8a, 0x8e, 0x9a, 0x7e, 0x25, 0xe8, 0x88, 0xf1, 0xdc, 0x18, 0xd9, 0xcc, 0xd1, 0x32, 0x3e, 0xb1, 0x33, 0x3a, 0xa3, 0x2b, 0x63, 0x7d, 0x43, 0x49, 0x7d, 0xb2, 0xd3, 0xe7, 0xc9, 0xbe, 0x52, 0x19, 0x55, 0xfb, 0x24, 0x66, 0x32, 0x57, 0x25, 0x62, 0x43, 0xf1, 0x26, 0x5a, 0x38, 0x56, 0x12, 0x48, 0x84, 0x42, 0x9d, 0x5b, 0x93, 0xa1, 0xc4, 0x30, 0xc6, 0xd6, 0x19, 0x5d, 0x15, 0x89, 0x6d, 0x0d, 0x46, 0xda, 0x83, 0xbb, 0x63, 0x43, 0xa9, 0x91, 0x66, 0xa6, 0xfe, 0xfd, 0x72, 0x4d, 0x34, 0x67, 0xb4, 0x42, 0xd0, 0x6e, 0x1a, 0xea, 0x46, 0x19, 0x8a, 0x8e, 0x60, 0x34, 0xb8, 0x8d, 0x8b, 0xcc, 0xfd, 0x87, 0x8b, 0xb0, 0x6d, 0x69, 0x8d, 0x0e, 0xc4, 0xc6, 0xf4, 0xff, 0x13, 0xca, 0xa4, 0xed, 0x51, 0x13, 0xd5, 0x8e, 0x2e, 0x17, 0x8e, 0xc6, 0x87, 0x52, 0x3b, 0x42, 0xa9, 0xed, 0xb1, 0xfe, 0xba, 0x65, 0xc1, 0x24, 0x2a, 0x47, 0x7a, 0xc4, 0x1a, 0xda, 0x37, 0xdb, 0x18, 0x7d, 0xde, 0xe1, 0xb1, 0x84, 0xee, 0xce, 0xac, 0x93, 0xab, 0x8d, 0xa9, 0xb2, 0xe6, 0x13, 0x74, 0x3b, 0x14, 0x9f, 0x99, 0x9d, 0xba, 0xf6, 0xbe, 0xd8, 0x8e, 0xba, 0xc4, 0x8e, 0x64, 0xa4, 0xee, 0x5c, 0xd8, 0xda, 0xba, 0x31, 0x36, 0x7c, 0xc6, 0x28, 0x23, 0xdf, 0x44, 0xd5, 0x9f, 0x5c, 0xc0, 0xd6, 0x9b, 0xc5, 0x9f, 0xa8, 0xfd, 0x77, 0x2d, 0x7c, 0x13, 0xad, 0xfc, 0xc4, 0x0a, 0x4e, 0xe2, 0x03, 0x66, 0x8c, 0xde, 0x38, 0x8d, 0xff, 0xdb, 0x7a, 0x78, 0xcf, 0x7d, 0x52, 0x51, 0x3e, 0xfd, 0x6a, 0x72, 0x03, 0xc1, 0xc4, 0xb6, 0x10, 0x4e, 0x56, 0xe5, 0x27, 0x15, 0x69, 0xa2, 0x69, 0xed, 0xfd, 0xc1, 0xc8, 0x70, 0xf8, 0xbc, 0x3a, 0xd8, 0x97, 0x58, 0x4a, 0xb9, 0x86, 0xba, 0x15, 0xd1, 0xbe, 0x48, 0x2c, 0x09, 0x33, 0xd3, 0x12, 0x09, 0x26, 0x95, 0xcd, 0x1f, 0xab, 0xd3, 0x8a, 0xc9, 0x4d, 0x18, 0x79, 0xe5, 0x38, 0xf2, 0x8e, 0xd0, 0x8e, 0xad, 0x46, 0x21, 0x04, 0x95, 0x8a, 0x71, 0x54, 0xba, 0xc3, 0xdb, 0xa2, 0xc1, 0xd4, 0x50, 0x42, 0x59, 0x4f, 0x76, 0xd1, 0x75, 0x11, 0x2c, 0x31, 0x4c, 0x4a, 0x30, 0xd1, 0x1d, 0x1a, 0x1c, 0x0a, 0x45, 0xfb, 0x20, 0x29, 0xb4, 0x4b, 0x74, 0x73, 0xd3, 0x6c, 0x59, 0xad, 0x91, 0x48, 0x68, 0x5b, 0x30, 0xa2, 0x57, 0x6e, 0xc5, 0xae, 0xbe, 0x50, 0x5c, 0x2f, 0xf8, 0x8c, 0x71, 0x74, 0x12, 0xdb, 0x86, 0x76, 0x60, 0xec, 0x36, 0xad, 0x22, 0xbb, 0x16, 0x7c, 0x9f, 0xda, 0x8a, 0x95, 0xb6, 0xcc, 0xb5, 0xb1, 0xee, 0xa1, 0xbe, 0xed, 0x7a, 0xaf, 0xda, 0xca, 0xf9, 0x6c, 0x2a, 0x9d, 0x5b, 0xcf, 0x55, 0x0e, 0xa6, 0xc2, 0x96, 0xd7, 0x1d, 0xea, 0x1b, 0x4a, 0x60, 0x0f, 0x9d, 0xa4, 0x88, 0xb6, 0xe1, 0x7c, 0x46, 0x46, 0xf2, 0x12, 0xa1, 0x01, 0xf6, 0x18, 0xe8, 0xc6, 0x70, 0x4c, 0x7b, 0x68, 0xbd, 0x88, 0xb6, 0x2a, 0x26, 0x8d, 0xa3, 0xae, 0xbb, 0xd6, 0x44, 0x13, 0xb4, 0x4c, 0x19, 0xf5, 0xa5, 0x89, 0x44, 0x70, 0x37, 0xef, 0x9b, 0x26, 0x5a, 0x3f, 0x5e, 0x76, 0xf3, 0x58, 0x1f, 0xd0, 0x3c, 0xce, 0x44, 0x8c, 0x93, 0xa5, 0xc2, 0xae, 0x02, 0x5b, 0x9d, 0x5c, 0x1d, 0x79, 0x4f, 0xc8, 0x68, 0xa2, 0x8e, 0x13, 0x72, 0xfe, 0x8f, 0x2d, 0xba, 0xbb, 0x97, 0xb7, 0x9d, 0xdd, 0xba, 0x36, 0x40, 0x8e, 0xc0, 0xa6, 0xae, 0x15, 0x54, 0x70, 0xc2, 0x3e, 0xa7, 0x5c, 0xfb, 0x19, 0x23, 0xd1, 0x43, 0xb2, 0x07, 0xc1, 0x54, 0x0f, 0xa2, 0x2c, 0x47, 0x0f, 0x87, 0x75, 0x4e, 0x7e, 0x22, 0xe4, 0xea, 0x59, 0x43, 0xae, 0x9e, 0x35, 0xad, 0x2b, 0x57, 0x22, 0xe0, 0xea, 0x59, 0xa3, 0x04, 0x6b, 0x58, 0x60, 0xf5, 0x20, 0xce, 0xc3, 0xa3, 0x9d, 0xb3, 0x39, 0x2e, 0xeb, 0x59, 0xb3, 0x19, 0xda, 0xcc, 0xb4, 0x73, 0x1d, 0xed, 0x4a, 0xb5, 0x5d, 0xab, 0x72, 0x18, 0xd7, 0x03, 0x25, 0x64, 0x70, 0xbe, 0x5b, 0x11, 0xd5, 0x54, 0xbb, 0x2a, 0xda, 0xbe, 0x99, 0xd9, 0xcd, 0x6b, 0xd4, 0x13, 0xf1, 0x5f, 0xcf, 0x66, 0x34, 0xba, 0x59, 0xa9, 0x88, 0xcd, 0x64, 0x6d, 0x66, 0x55, 0x3c, 0xda, 0x99, 0x85, 0x18, 0x8a, 0xce, 0xcd, 0x6b, 0x38, 0xed, 0x00, 0xe1, 0x0c, 0x96, 0xa0, 0x59, 0xd7, 0xe6, 0x76, 0x95, 0xed, 0x64, 0xca, 0xf9, 0xe8, 0x52, 0x2f, 0xc2, 0xd6, 0xde, 0x56, 0xf2, 0xf5, 0x8e, 0x3d, 0x14, 0x45, 0xbd, 0xe3, 0xec, 0x49, 0x8f, 0xf6, 0x18, 0x33, 0xea, 0xeb, 0xeb, 0x33, 0xfc, 0x1c, 0xf0, 0x39, 0x23, 0xbc, 0x2d, 0x31, 0x4a, 0x32, 0xd7, 0x9e, 0x98, 0x67, 0x4f, 0xcc, 0xb7, 0x27, 0x16, 0xd8, 0x13, 0x0b, 0xed, 0x89, 0x45, 0xf6, 0x44, 0x83, 0x3d, 0xd1, 0x68, 0xeb, 0x8d, 0xbd, 0x99, 0xb9, 0xf6, 0x6e, 0xce, 0xb3, 0xf1, 0xf3, 0x6d, 0xfc, 0x02, 0x1b, 0xbf, 0xd0, 0xc6, 0x2f, 0xb2, 0xf1, 0x0d, 0x36, 0xbe, 0x71, 0xa4, 0x81, 0x95, 0x91, 0xe0, 0xb6, 0x24, 0xe5, 0x8d, 0xf2, 0xa2, 0x54, 0x1c, 0x1c, 0xc7, 0x5b, 0x93, 0x2b, 0xa8, 0xef, 0x09, 0x39, 0x9a, 0xb6, 0x07, 0xb7, 0x86, 0x22, 0x94, 0x15, 0x34, 0x81, 0x36, 0x59, 0xc1, 0xfe, 0x7e, 0x9a, 0x88, 0xc7, 0xf8, 0x01, 0x04, 0x39, 0x83, 0x03, 0x88, 0x60, 0xc9, 0xab, 0x08, 0xef, 0x56, 0xed, 0xbc, 0xfa, 0x29, 0x3b, 0x68, 0x8c, 0x50, 0x92, 0xc4, 0x56, 0x2a, 0xe4, 0x90, 0x6a, 0xd9, 0x50, 0x2a, 0x15, 0x8b, 0x76, 0x25, 0xd0, 0x09, 0x28, 0xb8, 0xb6, 0x86, 0x06, 0x10, 0x51, 0x41, 0xa4, 0xa8, 0xbd, 0xac, 0x6b, 0x6b, 0x0c, 0x9a, 0x3b, 0x40, 0x55, 0x84, 0x4a, 0xae, 0xbe, 0x20, 0x5c, 0x61, 0x3f, 0x79, 0x35, 0xb5, 0xdd, 0x6e, 0x20, 0xe1, 0x60, 0x9d, 0xf2, 0xfa, 0x46, 0x5d, 0x8c, 0xdc, 0x7d, 0xa6, 0x26, 0x27, 0xee, 0x08, 0xc1, 0x04, 0x15, 0xb0, 0x95, 0x0f, 0xd9, 0xca, 0x95, 0xaa, 0x0c, 0x9b, 0x7b, 0x36, 0x17, 0x02, 0x72, 0xf4, 0xc1, 0x19, 0x52, 0x0e, 0x3f, 0x55, 0x9c, 0xbd, 0x34, 0x45, 0xf9, 0x99, 0x44, 0x4b, 0x6c, 0x28, 0x9a, 0x62, 0x61, 0x26, 0x8a, 0x67, 0x21, 0x12, 0x81, 0x44, 0x30, 0x9a, 0xc4, 0x28, 0x76, 0xa0, 0x23, 0xa8, 0x08, 0xa1, 0x7b, 0x52, 0x15, 0xa0, 0x62, 0x73, 0xe1, 0x48, 0x2e, 0x53, 0x83, 0xd4, 0x03, 0x44, 0xf7, 0x4c, 0x6b, 0xce, 0x3e, 0x55, 0xe3, 0xe4, 0xbe, 0x44, 0x28, 0x98, 0x1a, 0xeb, 0x94, 0x39, 0x16, 0x21, 0x47, 0x7f, 0x78, 0x60, 0x80, 0xdc, 0xfd, 0x31, 0x15, 0x9e, 0x92, 0x08, 0x51, 0x56, 0xc8, 0xc4, 0xe2, 0xe4, 0x49, 0x73, 0xad, 0x51, 0xb2, 0x42, 0xd1, 0x7e, 0x88, 0xa2, 0xfd, 0xc9, 0xb3, 0xc2, 0xa9, 0xed, 0xe4, 0x0c, 0x71, 0xc8, 0x49, 0xfe, 0x01, 0x84, 0xf3, 0xe3, 0x56, 0x9c, 0x5c, 0xb6, 0x9b, 0xe7, 0x9c, 0xb2, 0x59, 0x43, 0x85, 0xa0, 0x54, 0x04, 0x36, 0x9c, 0xdc, 0xae, 0x7c, 0x27, 0x3b, 0x45, 0x25, 0x77, 0x0e, 0x28, 0x59, 0xee, 0xc0, 0x48, 0x94, 0xda, 0x4f, 0x39, 0x2a, 0xc5, 0x7e, 0xb5, 0xb5, 0x9f, 0xdc, 0x2a, 0x81, 0xdc, 0xfc, 0x01, 0xee, 0x62, 0x20, 0xbc, 0x23, 0xb4, 0x36, 0x18, 0x8d, 0x25, 0xc9, 0x33, 0x30, 0x14, 0x89, 0xe8, 0xb0, 0x8a, 0x26, 0xc3, 0x7c, 0x8d, 0xea, 0xc7, 0x4a, 0x5b, 0x0d, 0xe5, 0x27, 0x0a, 0x47, 0x5d, 0x3a, 0xb3, 0x95, 0x54, 0xad, 0x5b, 0x41, 0x86, 0xed, 0x08, 0x26, 0xcf, 0x43, 0x93, 0x13, 0x38, 0x63, 0xe4, 0xae, 0x97, 0x5e, 0x46, 0x2f, 0xb2, 0x5b, 0x82, 0x89, 0x50, 0xaa, 0x0b, 0x03, 0x51, 0x25, 0x8b, 0x39, 0x07, 0xfe, 0xb6, 0x15, 0xb7, 0x9b, 0x5d, 0x2b, 0x63, 0x09, 0xbd, 0x3e, 0x79, 0x26, 0x17, 0xfb, 0x3d, 0x94, 0x48, 0x52, 0x16, 0x27, 0xd9, 0xca, 0x50, 0x11, 0x73, 0xe9, 0x79, 0xe0, 0x2b, 0xc9, 0x8a, 0xa8, 0x6e, 0x6c, 0x54, 0x66, 0x77, 0x2a, 0x98, 0x48, 0x91, 0x47, 0x65, 0xeb, 0x86, 0x73, 0xd8, 0x91, 0xa5, 0x97, 0x27, 0x97, 0x13, 0xbc, 0x0c, 0x3c, 0x25, 0x34, 0x11, 0xa9, 0x95, 0x7a, 0xa6, 0x4e, 0x34, 0xeb, 0xfe, 0x93, 0x8a, 0x54, 0x37, 0xcd, 0x1c, 0xac, 0x0e, 0x85, 0xb7, 0x6d, 0x4f, 0xa9, 0x7a, 0x56, 0x83, 0x8b, 0x70, 0x2a, 0xd4, 0xbf, 0x3e, 0xb4, 0x0d, 0xe3, 0x5b, 0x86, 0x27, 0xb6, 0xf5, 0x78, 0x22, 0xee, 0x39, 0x0f, 0x47, 0xd5, 0x6a, 0x9f, 0xf5, 0x09, 0xe9, 0xcc, 0x51, 0x11, 0x2a, 0x9d, 0x9a, 0xce, 0x0e, 0xec, 0x8e, 0x87, 0x30, 0x53, 0x1c, 0x2f, 0xf6, 0x84, 0x13, 0xa9, 0xa1, 0x60, 0x24, 0x1d, 0xb1, 0xb1, 0x44, 0x0d, 0xb5, 0x35, 0x9a, 0x4c, 0x05, 0x11, 0xbd, 0xa8, 0x85, 0x19, 0x25, 0xe5, 0x16, 0xdb, 0x8d, 0x7f, 0xef, 0x8c, 0x76, 0x63, 0x87, 0x87, 0xa2, 0x6a, 0x42, 0xd0, 0x58, 0x10, 0xf3, 0x96, 0x0a, 0xa9, 0x31, 0xe9, 0xa6, 0xd5, 0x3a, 0xac, 0x85, 0xee, 0x70, 0x88, 0xfb, 0xa6, 0x6a, 0x33, 0x23, 0xd7, 0x67, 0x2e, 0x77, 0x24, 0x83, 0x37, 0x1c, 0x52, 0xeb, 0x83, 0x3b, 0x37, 0xa6, 0x99, 0x4d, 0xaa, 0x2f, 0xeb, 0x63, 0xb1, 0x54, 0xa6, 0x74, 0xe6, 0x56, 0xca, 0xa3, 0x2f, 0xb4, 0x67, 0xe8, 0x35, 0xe3, 0x0d, 0xd2, 0xbd, 0x1b, 0x46, 0x6c, 0x47, 0x37, 0x7c, 0x69, 0x18, 0x23, 0xc8, 0x47, 0x8e, 0x9e, 0xfc, 0xf5, 0xea, 0x90, 0xb2, 0x46, 0x00, 0x01, 0x5c, 0x64, 0xed, 0xd0, 0x0e, 0xde, 0x22, 0x7a, 0x4f, 0x6c, 0xe0, 0xcb, 0x71, 0x24, 0x1c, 0xc5, 0xe4, 0xb2, 0x56, 0x52, 0x15, 0xdb, 0x10, 0x0d, 0xb3, 0x8d, 0x60, 0x2d, 0xa5, 0x74, 0xe2, 0x2d, 0x4a, 0x0d, 0xaf, 0x27, 0x9c, 0xb1, 0xc4, 0x5c, 0xe6, 0x2c, 0x9c, 0xba, 0xd8, 0xce, 0x40, 0xec, 0x3c, 0x4c, 0x4b, 0x79, 0x26, 0xad, 0x94, 0x22, 0x21, 0x44, 0xc4, 0xf1, 0x48, 0x70, 0xb7, 0x3e, 0xf1, 0x0e, 0x48, 0x37, 0xaa, 0xe7, 0x26, 0x12, 0xdb, 0xa9, 0x0c, 0x47, 0x10, 0x46, 0x71, 0xd4, 0x71, 0x59, 0x1d, 0xe3, 0x56, 0x0a, 0x8c, 0x24, 0x1e, 0xef, 0x0a, 0xaa, 0xf3, 0xe8, 0xcd, 0x64, 0xac, 0x0f, 0x25, 0x61, 0x8c, 0x33, 0x39, 0xcb, 0x32, 0xd6, 0x98, 0xf2, 0x74, 0xce, 0x72, 0x63, 0x5e, 0x4c, 0x12, 0x4b, 0xb9, 0x3c, 0xb6, 0x13, 0x5e, 0x21, 0x93, 0xdc, 0x10, 0xa7, 0xe2, 0x4c, 0x42, 0x2d, 0xf3, 0xea, 0x70, 0x7f, 0x3f, 0x3a, 0x6f, 0x5a, 0xed, 0x88, 0xa1, 0x49, 0x55, 0x66, 0x54, 0x46, 0x22, 0xb8, 0x2d, 0x5d, 0xa7, 0xca, 0x40, 0x35, 0xa6, 0x4e, 0xf5, 0x82, 0x83, 0x8a, 0x4c, 0x22, 0x94, 0x60, 0xf3, 0x69, 0x4e, 0x79, 0xd6, 0xf6, 0x60, 0x52, 0x5b, 0xa4, 0xdc, 0xed, 0xb0, 0x00, 0xe9, 0x06, 0xa9, 0x94, 0x53, 0xdd, 0xb1, 0x01, 0xb3, 0x95, 0x13, 0xb1, 0x1d, 0x7a, 0xd6, 0x50, 0x00, 0x75, 0x29, 0x6b, 0xe5, 0xd8, 0x1e, 0x43, 0x9c, 0x26, 0xc2, 0xe4, 0xc1, 0x91, 0xeb, 0x54, 0xe1, 0x64, 0x92, 0xac, 0xf0, 0x8e, 0x1d, 0x54, 0xc0, 0x2f, 0xd5, 0xc2, 0xc1, 0x48, 0x4b, 0x30, 0x9e, 0xec, 0x60, 0x23, 0x9f, 0x67, 0x32, 0xb0, 0x33, 0x78, 0x93, 0x14, 0x8c, 0x24, 0xf5, 0x16, 0xc9, 0x31, 0x19, 0xda, 0x4a, 0x86, 0xd3, 0x27, 0x82, 0x72, 0x15, 0x7b, 0xb6, 0xbe, 0xe2, 0x51, 0x21, 0x6c, 0x7d, 0x28, 0xa1, 0x1a, 0x5f, 0xaa, 0x4d, 0x0e, 0x65, 0xa1, 0x33, 0x3d, 0xc1, 0xc8, 0x10, 0x1c, 0x57, 0x18, 0x31, 0xee, 0x79, 0xb0, 0xd3, 0xe1, 0x64, 0xe6, 0xa4, 0x64, 0x85, 0x93, 0x9d, 0xf1, 0x20, 0x82, 0x7e, 0x14, 0x4d, 0x66, 0x4e, 0xbb, 0x7a, 0xb3, 0x05, 0x1b, 0x81, 0xac, 0x18, 0xe2, 0xf0, 0x15, 0xbb, 0xe2, 0x70, 0x2b, 0x41, 0xbd, 0x81, 0xd9, 0x96, 0xc0, 0xa1, 0x86, 0x93, 0x66, 0x77, 0x90, 0xfb, 0xbc, 0xd0, 0xee, 0x16, 0x1e, 0x42, 0xe9, 0x79, 0x27, 0x79, 0x1d, 0x97, 0x97, 0x16, 0x74, 0x6f, 0xe7, 0x25, 0x71, 0x46, 0x94, 0x5b, 0xcf, 0xc3, 0x9e, 0x82, 0x97, 0xc6, 0x20, 0xd6, 0xe2, 0x6e, 0x44, 0x8e, 0x48, 0x68, 0x20, 0x45, 0xae, 0x48, 0x28, 0xba, 0x0d, 0x0e, 0xc3, 0x11, 0xe1, 0x08, 0xd7, 0x65, 0x86, 0x25, 0xa2, 0xe4, 0x88, 0xf2, 0x86, 0xf0, 0x44, 0x47, 0x8e, 0xa5, 0x23, 0xca, 0x3e, 0xc6, 0x1d, 0x0d, 0xed, 0x5c, 0xcb, 0x22, 0x66, 0xd4, 0xe4, 0x64, 0x45, 0xd3, 0xce, 0x2a, 0x37, 0x6a, 0x37, 0xdc, 0x2e, 0x1e, 0x33, 0x66, 0xd2, 0x15, 0xdb, 0xca, 0x3e, 0x91, 0x1c, 0x31, 0x2e, 0xef, 0x8b, 0x0d, 0x0c, 0x24, 0x43, 0xa9, 0x65, 0x6a, 0x08, 0xea, 0x50, 0x27, 0x21, 0x89, 0xf4, 0x6f, 0x57, 0xcf, 0x9d, 0x54, 0x18, 0x8b, 0xa6, 0xdf, 0xf3, 0xb5, 0x28, 0xbf, 0x08, 0xf3, 0x35, 0x92, 0xb5, 0x3c, 0x94, 0x4c, 0x25, 0x62, 0xbb, 0x79, 0x2f, 0x8f, 0x64, 0x9a, 0xfd, 0x6e, 0x2b, 0x99, 0xde, 0xf0, 0x93, 0x47, 0xb2, 0xba, 0x83, 0xc3, 0xa1, 0xf4, 0x2a, 0x68, 0x03, 0x64, 0xd3, 0x57, 0x4b, 0x3e, 0xba, 0x8a, 0xee, 0x54, 0x2c, 0x1e, 0x47, 0x56, 0x29, 0xdc, 0x8a, 0xea, 0xc7, 0x09, 0x37, 0x7f, 0x0c, 0x2b, 0x8a, 0xfd, 0xbd, 0x93, 0xf2, 0x62, 0xf6, 0x57, 0x38, 0x94, 0x1f, 0x1b, 0x15, 0x2a, 0x51, 0x6e, 0x2c, 0xaa, 0xce, 0xa7, 0xf2, 0x04, 0x94, 0x1d, 0x8b, 0xa6, 0x0f, 0x57, 0x9e, 0x62, 0x3b, 0x86, 0x22, 0xa9, 0x70, 0x9c, 0x57, 0x55, 0x25, 0x71, 0x40, 0xb2, 0x38, 0x0c, 0x53, 0x45, 0xa1, 0xd1, 0x1d, 0x3e, 0x3f, 0x94, 0xf1, 0xba, 0x48, 0xc2, 0xeb, 0x2c, 0xc5, 0xb9, 0xeb, 0x57, 0x32, 0x24, 0xd2, 0x32, 0x93, 0x5c, 0x1f, 0xda, 0x81, 0xb6, 0x54, 0xd2, 0x1e, 0x51, 0xa1, 0x0f, 0x7a, 0x5f, 0xa9, 0x3e, 0xb8, 0x62, 0x7a, 0x03, 0xba, 0x35, 0x3d, 0x1b, 0x19, 0x7a, 0xa1, 0xb2, 0xd0, 0xe8, 0xd2, 0x54, 0x0a, 0xb6, 0xce, 0x89, 0x0e, 0x72, 0x78, 0x17, 0x57, 0xa7, 0x94, 0x09, 0x32, 0x3d, 0x71, 0xec, 0xef, 0xa8, 0x36, 0xb2, 0x79, 0xf1, 0x51, 0x47, 0xd6, 0x19, 0x57, 0xfe, 0xb4, 0x22, 0x1e, 0x8b, 0x0f, 0x45, 0x4e, 0x1a, 0xcb, 0x14, 0xc2, 0x75, 0xa6, 0x46, 0xbd, 0x66, 0x23, 0x2b, 0x9e, 0xc2, 0x45, 0x06, 0x21, 0x5b, 0x42, 0xbf, 0xd1, 0xa5, 0x69, 0x09, 0x78, 0x2d, 0x6c, 0xe3, 0xc4, 0xc9, 0x5f, 0xf6, 0x52, 0x79, 0x42, 0x0d, 0xf3, 0x24, 0x31, 0xa9, 0x47, 0x4b, 0x79, 0x3a, 0x28, 0x17, 0xd1, 0x26, 0x0f, 0x4d, 0xad, 0x1d, 0x39, 0x13, 0xca, 0x83, 0x0a, 0x18, 0x96, 0xa4, 0xdd, 0x41, 0xe4, 0x27, 0x47, 0x7b, 0x07, 0x0b, 0xfb, 0x93, 0x33, 0x53, 0xb6, 0xb7, 0xb4, 0x5c, 0x44, 0xbb, 0x4f, 0xe5, 0xdb, 0x4b, 0xed, 0xa9, 0x56, 0x3d, 0xbb, 0xca, 0xac, 0x14, 0x27, 0xc7, 0xf1, 0xc1, 0x54, 0x84, 0xdc, 0xd6, 0x1d, 0x1c, 0x82, 0xf2, 0xbe, 0x4c, 0xea, 0xee, 0x70, 0x8d, 0xed, 0xe9, 0x23, 0x49, 0x65, 0x48, 0x8d, 0xfb, 0x32, 0x50, 0xe9, 0x65, 0xfc, 0x17, 0xb9, 0x39, 0xc5, 0x63, 0x9b, 0x90, 0x4c, 0xfb, 0xb0, 0x0d, 0x61, 0x9b, 0x77, 0x99, 0x3c, 0x6e, 0x36, 0xc7, 0x2d, 0xc1, 0x94, 0xea, 0x76, 0x20, 0x84, 0x10, 0x26, 0x11, 0x4c, 0xec, 0x4e, 0x3b, 0x33, 0x44, 0x33, 0x94, 0x93, 0xd4, 0x7e, 0x4b, 0x9d, 0xec, 0xbc, 0xe4, 0x28, 0x7f, 0xe5, 0x49, 0x27, 0x31, 0x6e, 0x9e, 0x95, 0xb3, 0xc2, 0x91, 0xc8, 0xda, 0x58, 0x4a, 0x6d, 0xfe, 0xdc, 0x24, 0x2c, 0x4c, 0xc6, 0x42, 0xe7, 0x71, 0x2a, 0x63, 0xa1, 0xc9, 0xa9, 0xb7, 0x55, 0xbe, 0x22, 0x7a, 0x38, 0xdc, 0x56, 0x5e, 0x12, 0x47, 0x6b, 0x24, 0xe9, 0x4a, 0xaa, 0xb7, 0x04, 0xe8, 0xc2, 0xd0, 0xd6, 0xf4, 0xeb, 0x10, 0xca, 0x46, 0xc2, 0xe4, 0x97, 0x25, 0xf5, 0x68, 0x5a, 0x47, 0xba, 0x64, 0xc2, 0x06, 0x57, 0x4a, 0xc7, 0x4f, 0x59, 0x9a, 0x22, 0x0a, 0x76, 0xa8, 0x28, 0x6c, 0x6a, 0x6a, 0x74, 0x14, 0xb5, 0xea, 0xc4, 0x68, 0x70, 0xfa, 0x38, 0x0a, 0x63, 0x82, 0xc3, 0xaa, 0xb1, 0x4a, 0x27, 0x89, 0xbb, 0x4e, 0xfd, 0x07, 0x34, 0x79, 0x9f, 0x4d, 0x19, 0xab, 0x37, 0x2a, 0x68, 0xaa, 0x18, 0x2b, 0xb7, 0x87, 0x24, 0xe3, 0x0c, 0x6b, 0x74, 0x84, 0xe2, 0x3f, 0x41, 0xa1, 0x75, 0x8c, 0x6f, 0x1a, 0xa3, 0x31, 0xc6, 0x05, 0x9d, 0x38, 0x35, 0xdd, 0xe3, 0x6d, 0xe7, 0x13, 0x07, 0xdc, 0x7d, 0x92, 0x5d, 0xe5, 0x48, 0x6d, 0x0f, 0x27, 0xb1, 0x4c, 0x78, 0xce, 0xa8, 0x37, 0x74, 0x0e, 0x72, 0x39, 0x1e, 0xce, 0x4a, 0xc5, 0xf4, 0xeb, 0x21, 0xb2, 0xb0, 0x1d, 0x90, 0xc9, 0x33, 0x50, 0x39, 0x14, 0xef, 0x87, 0xf9, 0x48, 0x87, 0xd0, 0x99, 0x5d, 0xcf, 0xce, 0xde, 0x04, 0xcb, 0x33, 0xb5, 0x8a, 0x4e, 0x99, 0x70, 0x9c, 0x55, 0x74, 0x40, 0xc6, 0x8a, 0x99, 0x00, 0x7c, 0x8a, 0x5d, 0x75, 0x1c, 0x79, 0xa5, 0x5d, 0x3e, 0xaa, 0xad, 0x8c, 0x4a, 0xd6, 0x50, 0x6a, 0xa0, 0x41, 0x45, 0x76, 0x62, 0x98, 0x9c, 0xc3, 0xca, 0xad, 0xbb, 0x15, 0xe9, 0x1c, 0x20, 0x07, 0xbf, 0xf1, 0x25, 0x17, 0x3f, 0xb1, 0xf7, 0x0a, 0x98, 0xda, 0xed, 0x75, 0x36, 0x67, 0x04, 0x62, 0x1b, 0x92, 0x88, 0x26, 0x87, 0x4f, 0x8c, 0x09, 0x8b, 0x86, 0xc7, 0x89, 0xa9, 0xf3, 0x4c, 0xa6, 0x89, 0xd0, 0x3d, 0xc3, 0x23, 0x87, 0x50, 0xc0, 0xff, 0xee, 0xdc, 0x8e, 0x23, 0x2c, 0x76, 0x91, 0xdc, 0x55, 0x0f, 0xcc, 0x01, 0xe6, 0x02, 0xf3, 0x80, 0xf9, 0x24, 0x76, 0xd3, 0x4d, 0x0e, 0xeb, 0xbb, 0xd6, 0x2f, 0xc4, 0x35, 0x96, 0x3b, 0xbf, 0xb9, 0xa6, 0xa6, 0x76, 0x17, 0xed, 0x71, 0x8a, 0x17, 0x85, 0xbb, 0xa2, 0xcd, 0x92, 0x97, 0x5b, 0xb2, 0xdd, 0xa2, 0x97, 0x84, 0x6c, 0x9b, 0x3e, 0xb1, 0xdd, 0xb2, 0xbe, 0x68, 0x35, 0x6f, 0x76, 0x88, 0xdf, 0xca, 0xc5, 0x03, 0xf4, 0xa6, 0x43, 0xbe, 0x28, 0x0e, 0x5a, 0xac, 0x25, 0x32, 0x5a, 0xeb, 0xa0, 0x24, 0xa1, 0xd4, 0xb6, 0x9a, 0xae, 0x74, 0x42, 0x7e, 0x35, 0xaa, 0xdc, 0x45, 0x07, 0xd3, 0x6c, 0x73, 0x33, 0xbd, 0xef, 0xd0, 0xfc, 0xa8, 0x62, 0x5d, 0x93, 0xda, 0x74, 0xb1, 0x56, 0x7a, 0xc8, 0x21, 0xfe, 0x24, 0xdd, 0xf9, 0xf4, 0x63, 0x87, 0xe3, 0x4f, 0x68, 0xfd, 0x59, 0xf1, 0x7d, 0xe1, 0xce, 0x0f, 0xd3, 0xb7, 0x1c, 0x8e, 0x83, 0xd6, 0x11, 0xeb, 0x72, 0xeb, 0x25, 0xc1, 0x35, 0xde, 0xe7, 0x70, 0x71, 0xf2, 0xd7, 0xf2, 0x71, 0xf9, 0x13, 0xf9, 0x23, 0xc9, 0x59, 0x77, 0x8f, 0xd6, 0x78, 0x42, 0x97, 0xff, 0x81, 0x78, 0x16, 0x03, 0x91, 0x13, 0x2f, 0x91, 0xe7, 0x56, 0xdc, 0x6e, 0x89, 0x1f, 0xcb, 0xe6, 0xa9, 0x16, 0x3d, 0x2e, 0xe4, 0xc7, 0xb5, 0xfb, 0x6b, 0x1f, 0x6d, 0x3d, 0x43, 0xe4, 0x3b, 0xc5, 0x92, 0x9a, 0xdb, 0x77, 0xd1, 0xcd, 0x4e, 0x4c, 0xc1, 0xeb, 0xe9, 0x29, 0xa0, 0x9f, 0x38, 0xc9, 0x5d, 0xb1, 0x7f, 0x77, 0x4d, 0xed, 0xb9, 0x67, 0x84, 0xbb, 0x26, 0xd3, 0x37, 0x39, 0xd9, 0x26, 0xf3, 0xaa, 0xe5, 0x50, 0x45, 0xdb, 0xee, 0xb0, 0x25, 0x1e, 0x90, 0x32, 0x6c, 0xd1, 0x9d, 0xb2, 0xf9, 0x82, 0x17, 0xde, 0xa3, 0x7d, 0x6e, 0x49, 0xf7, 0xa0, 0xe0, 0xe6, 0x1a, 0xba, 0xdc, 0x2d, 0xbe, 0x67, 0xb9, 0x9b, 0xe4, 0xe4, 0xe7, 0xe5, 0xf6, 0x8a, 0xc7, 0x2c, 0xfa, 0xa1, 0x9c, 0x52, 0xf3, 0xa9, 0xf6, 0xcf, 0x5a, 0xe2, 0x51, 0x39, 0xfd, 0x8d, 0xb6, 0x76, 0xb9, 0xab, 0xc2, 0x29, 0x84, 0xcb, 0x25, 0xe8, 0x2e, 0xb7, 0x3c, 0x68, 0x41, 0x35, 0x9f, 0xee, 0x71, 0x8b, 0x57, 0xd0, 0xc5, 0xa7, 0xe4, 0xf9, 0x15, 0x7f, 0xb4, 0xe8, 0x55, 0xd1, 0x50, 0x73, 0xb5, 0x93, 0xe8, 0x11, 0x37, 0xa4, 0x77, 0x8b, 0x23, 0x18, 0xcb, 0xa3, 0x53, 0xe9, 0x3d, 0x4b, 0x10, 0xea, 0x6f, 0xa6, 0xbf, 0x58, 0xe4, 0xae, 0xee, 0xb5, 0xe4, 0xbb, 0x32, 0xff, 0x32, 0x4b, 0x1c, 0x95, 0x53, 0x6a, 0x77, 0xfd, 0xd5, 0xa2, 0xe7, 0x85, 0x3c, 0xb7, 0x59, 0x14, 0x16, 0x86, 0x9b, 0x65, 0xb2, 0xc2, 0x49, 0xcd, 0x22, 0xc7, 0x45, 0xf4, 0x1f, 0x96, 0xee, 0x95, 0x5c, 0xb4, 0x49, 0xae, 0xd9, 0x59, 0x43, 0xaf, 0xa0, 0xd7, 0xdc, 0xde, 0x89, 0xf4, 0x4d, 0x54, 0x99, 0x7f, 0x98, 0xde, 0xd2, 0xe4, 0x5a, 0x29, 0xde, 0xe4, 0xe9, 0xbf, 0x51, 0x22, 0x49, 0x37, 0x49, 0xf1, 0x16, 0xa7, 0xbe, 0xa2, 0x52, 0xd7, 0xa9, 0xe7, 0xd7, 0xd5, 0xf3, 0x06, 0x29, 0xef, 0x17, 0x3f, 0x47, 0xef, 0xe8, 0x6b, 0x2a, 0xfd, 0x55, 0xc9, 0x7b, 0x21, 0x9f, 0x0e, 0xa9, 0xd4, 0xf5, 0x19, 0xe9, 0xcd, 0x52, 0x90, 0xc3, 0xfa, 0x81, 0x5c, 0x12, 0x46, 0x62, 0xb5, 0xf5, 0x8c, 0x78, 0x43, 0xde, 0x2c, 0xdd, 0xd5, 0xf2, 0x3f, 0xa9, 0x49, 0xfe, 0x5e, 0xee, 0x94, 0x77, 0x5b, 0x3b, 0x77, 0xc9, 0x8f, 0x77, 0xbd, 0x76, 0xa9, 0x90, 0x4e, 0xcf, 0xb2, 0x9a, 0xe6, 0xda, 0xe6, 0xe6, 0x33, 0x7b, 0x2d, 0x7a, 0x52, 0x78, 0x2e, 0xb4, 0xc4, 0x53, 0xa2, 0xa5, 0xf9, 0xf6, 0x4a, 0xcb, 0x7a, 0x50, 0x9e, 0x29, 0x4a, 0x4b, 0xeb, 0xa7, 0x58, 0xf2, 0x88, 0x94, 0x32, 0x4f, 0x14, 0xe6, 0x3b, 0xe5, 0x2e, 0xb9, 0x06, 0x43, 0x75, 0x0a, 0xa7, 0xe5, 0xf2, 0xc8, 0xfa, 0x5b, 0x9d, 0x1e, 0x17, 0xb9, 0x84, 0x4b, 0xba, 0xac, 0x99, 0x33, 0xe5, 0x50, 0xb5, 0x53, 0xce, 0x94, 0x89, 0x6a, 0x6a, 0xd1, 0x43, 0x4c, 0x13, 0xf9, 0x80, 0xf5, 0x83, 0x71, 0xd3, 0x16, 0x33, 0x0f, 0x2a, 0xd6, 0xa1, 0xd9, 0x87, 0x46, 0x2b, 0x9c, 0x58, 0xd2, 0x99, 0xd6, 0x7a, 0xf8, 0xc4, 0xf2, 0x36, 0xf6, 0xc4, 0x42, 0xe3, 0xf7, 0xe2, 0x88, 0x14, 0x98, 0x91, 0xfc, 0x36, 0x8b, 0xde, 0x91, 0x16, 0x3d, 0x26, 0xc5, 0xed, 0xbc, 0x68, 0x53, 0x9a, 0x64, 0xa8, 0xba, 0xb3, 0x6e, 0xf1, 0xda, 0xb5, 0xb5, 0x72, 0xdb, 0x1a, 0xba, 0x9a, 0x57, 0xe7, 0x0b, 0xe5, 0xf4, 0x05, 0xde, 0x07, 0x6d, 0xf4, 0x36, 0xcf, 0x32, 0x8e, 0xce, 0x6d, 0xb2, 0x6a, 0xde, 0xc4, 0xb6, 0x5e, 0xfa, 0xb1, 0x4b, 0xde, 0x6f, 0xfd, 0x90, 0x6b, 0xbb, 0x51, 0x88, 0xd7, 0x30, 0xef, 0x57, 0x4c, 0xea, 0xa5, 0xe7, 0xdc, 0xbc, 0x14, 0xbf, 0x55, 0x0b, 0xb2, 0xdf, 0xca, 0x14, 0x98, 0x33, 0x79, 0x3f, 0xff, 0x45, 0x3c, 0xb7, 0xec, 0xe2, 0xe7, 0x51, 0x97, 0xbc, 0x57, 0x3c, 0xcc, 0x6b, 0xf5, 0x86, 0x4b, 0xdc, 0xcb, 0xf4, 0x69, 0x4d, 0xd1, 0xdc, 0xfb, 0x9a, 0xbb, 0xbc, 0x9c, 0x5e, 0xc9, 0x68, 0xbd, 0x6b, 0xb4, 0x5e, 0x32, 0xf4, 0x75, 0xa7, 0xf8, 0x0d, 0x56, 0xf4, 0x5c, 0x8b, 0xfe, 0x43, 0xd4, 0xb6, 0xb5, 0xd5, 0xec, 0xdf, 0xdf, 0xd6, 0x71, 0x5b, 0xed, 0x7e, 0x39, 0xbc, 0x66, 0x1e, 0x5d, 0x23, 0xc4, 0x23, 0xba, 0xa6, 0xcb, 0x5c, 0xf2, 0x2e, 0xeb, 0x46, 0x8c, 0xf3, 0xf2, 0xc9, 0x35, 0xf4, 0x05, 0x29, 0x5e, 0x46, 0xf6, 0xa5, 0xa2, 0xa4, 0xc0, 0x4f, 0xd7, 0x5b, 0xf2, 0xb0, 0x44, 0xb2, 0x62, 0xbf, 0x9c, 0x5c, 0x81, 0x53, 0x7a, 0x86, 0x2c, 0x68, 0xaa, 0x6d, 0x0b, 0xc9, 0xa1, 0x35, 0x5b, 0xe4, 0xee, 0x35, 0xf4, 0xb8, 0x65, 0x1d, 0x96, 0xcf, 0xb2, 0x7e, 0x93, 0x2c, 0xbc, 0x44, 0x26, 0x2a, 0x5e, 0xe8, 0xbd, 0xfd, 0x52, 0xcb, 0xf9, 0x2d, 0x4b, 0xd6, 0x85, 0x16, 0xd3, 0x43, 0xa6, 0x70, 0xfe, 0x7e, 0x7f, 0xf9, 0xb5, 0xb4, 0xd7, 0xe5, 0x7c, 0x54, 0xdc, 0x2f, 0x6f, 0xb3, 0x8e, 0xc9, 0x87, 0xb8, 0x6b, 0x1f, 0x38, 0x1d, 0xf7, 0x59, 0x07, 0xe4, 0x93, 0xf2, 0x67, 0x68, 0xf8, 0x8c, 0xfd, 0x9b, 0xe9, 0x7e, 0xa1, 0x1a, 0xde, 0x2f, 0x9f, 0xa4, 0x0a, 0x79, 0xe4, 0x73, 0xb0, 0x41, 0xd9, 0x77, 0x0b, 0xd8, 0x20, 0xf7, 0x2d, 0x96, 0x25, 0x7f, 0x42, 0x9b, 0xe4, 0xc3, 0x9f, 0xab, 0x16, 0x45, 0x05, 0xf5, 0x1a, 0xde, 0x76, 0x2b, 0xe7, 0x21, 0x29, 0xcf, 0x68, 0xb6, 0x72, 0xdf, 0x92, 0xcb, 0xcf, 0x10, 0xc2, 0xf2, 0xdc, 0x22, 0x65, 0x8d, 0x28, 0xcf, 0x5b, 0xec, 0xf4, 0x38, 0x73, 0xe7, 0x38, 0x73, 0xce, 0x75, 0x79, 0x6a, 0x45, 0x51, 0xa9, 0xbc, 0xa0, 0xa9, 0xd9, 0x95, 0x7b, 0x86, 0xa8, 0x98, 0xc0, 0xf9, 0xa3, 0x33, 0xe5, 0x72, 0x51, 0x81, 0x63, 0xe1, 0x12, 0xdf, 0xc7, 0xf2, 0xf8, 0x2d, 0x71, 0x95, 0x75, 0xa6, 0xf0, 0x95, 0xc9, 0x82, 0x6a, 0x19, 0xae, 0x80, 0x29, 0xfa, 0xb9, 0x68, 0x9a, 0xea, 0x24, 0xc5, 0x34, 0x4e, 0x77, 0xd2, 0x1b, 0x73, 0x67, 0xd2, 0x41, 0x97, 0x78, 0x84, 0x0f, 0xdd, 0x43, 0x2e, 0x71, 0x3f, 0xdb, 0xbe, 0x72, 0xfa, 0x40, 0x5a, 0x87, 0xad, 0xbf, 0xc8, 0x3f, 0xcb, 0xf4, 0x1a, 0xce, 0x9f, 0xd4, 0xdc, 0x46, 0xb2, 0x4e, 0xdc, 0x65, 0x95, 0xd5, 0xca, 0x7a, 0xf9, 0x6d, 0xe1, 0x98, 0xf4, 0x90, 0x2c, 0xcd, 0x95, 0x73, 0x91, 0x53, 0xee, 0x29, 0x75, 0x94, 0x2e, 0x2c, 0x75, 0x95, 0x0e, 0x94, 0xba, 0x4b, 0x9b, 0x81, 0x4f, 0xe1, 0xd7, 0x33, 0xa2, 0x95, 0xaf, 0x59, 0x1f, 0xd8, 0xc9, 0xba, 0x80, 0x1b, 0x05, 0x82, 0xa5, 0x3e, 0x55, 0x60, 0x75, 0x69, 0xb6, 0xae, 0xb7, 0x5a, 0xab, 0x49, 0xa8, 0x45, 0x46, 0x4a, 0x94, 0xcb, 0x39, 0x5c, 0x42, 0x94, 0xcd, 0xd6, 0x79, 0xd9, 0xc8, 0x3b, 0x4f, 0xd7, 0x92, 0x85, 0x5a, 0xec, 0x4d, 0xe6, 0x68, 0x55, 0x67, 0x59, 0x75, 0xd9, 0xac, 0xb2, 0x9a, 0xb2, 0x99, 0x65, 0x55, 0x69, 0x3d, 0xe7, 0x68, 0x3d, 0x72, 0xb8, 0x5c, 0x39, 0x52, 0xf8, 0xf8, 0x77, 0xd1, 0x45, 0x7b, 0x1c, 0x87, 0x6a, 0x2c, 0xcf, 0xd3, 0x35, 0x4e, 0xcf, 0x8f, 0x6a, 0x85, 0xe7, 0x8a, 0x3a, 0xe1, 0xb9, 0x0b, 0x78, 0xba, 0xae, 0x41, 0x1c, 0xaa, 0x17, 0xe2, 0xae, 0x7a, 0x29, 0x9e, 0x06, 0x7d, 0x1b, 0xb8, 0x62, 0x0e, 0xd2, 0x08, 0x0a, 0x84, 0x2c, 0x90, 0x42, 0xfd, 0xb6, 0xec, 0xd9, 0xe3, 0x38, 0x38, 0x6f, 0xb9, 0x38, 0x3c, 0x4f, 0x8a, 0x1b, 0xe6, 0x93, 0x14, 0x8e, 0xa2, 0x03, 0x7e, 0xe1, 0x5b, 0x8d, 0x4a, 0x8f, 0x2c, 0x68, 0x15, 0x2f, 0x2f, 0x10, 0x62, 0xdf, 0x22, 0x21, 0x6e, 0x02, 0x6e, 0x68, 0x80, 0x58, 0x4c, 0x90, 0xe2, 0x80, 0xbf, 0x03, 0xa5, 0x8e, 0x36, 0xac, 0x15, 0x57, 0x34, 0x92, 0xe5, 0xa2, 0x52, 0x2e, 0x21, 0x7c, 0x9d, 0x28, 0xf3, 0xdc, 0xe9, 0xe2, 0x52, 0xff, 0x9e, 0x26, 0x3c, 0x0e, 0xf1, 0xe3, 0xbb, 0x4d, 0x42, 0x3e, 0x01, 0xbc, 0xd7, 0x44, 0x42, 0xe4, 0x4c, 0xf2, 0x6d, 0xe0, 0xbe, 0x36, 0xf7, 0x88, 0xc3, 0xcd, 0x42, 0xbc, 0x08, 0x1c, 0x03, 0x0e, 0x62, 0x97, 0x1c, 0x06, 0x5e, 0x04, 0x8e, 0x01, 0x07, 0xcf, 0x14, 0xe2, 0xbb, 0xc0, 0x73, 0xc0, 0xdb, 0x67, 0x92, 0x7b, 0xfe, 0xd4, 0xc9, 0x3e, 0xd5, 0x57, 0x9f, 0xfe, 0x0d, 0xa2, 0x8e, 0x4b, 0x17, 0xa3, 0xf2, 0xd7, 0x96, 0xe1, 0x71, 0x9c, 0x1f, 0x87, 0x5a, 0xb8, 0x2d, 0x7e, 0x3c, 0xc1, 0x8f, 0xd7, 0xf8, 0x71, 0x9c, 0x1f, 0x87, 0x96, 0xe3, 0x71, 0x98, 0x1f, 0xcf, 0xf1, 0xe3, 0x6d, 0x7e, 0x5c, 0xba, 0x02, 0x8f, 0x9b, 0xf8, 0xf1, 0x20, 0x3f, 0x5e, 0xe4, 0xc7, 0x7b, 0xfc, 0xb8, 0x62, 0x25, 0x1e, 0x77, 0xac, 0x74, 0xed, 0x95, 0x24, 0x00, 0x4b, 0x3e, 0xb6, 0x92, 0xa9, 0x64, 0x78, 0xfe, 0xba, 0x92, 0x69, 0x5a, 0xf6, 0xcf, 0x60, 0x02, 0xe0, 0xf9, 0x02, 0xf8, 0x7f, 0x14, 0xd0, 0x4f, 0x89, 0xdf, 0xac, 0xc2, 0x4c, 0xac, 0xc6, 0x4c, 0x00, 0x47, 0x81, 0xe3, 0xab, 0x2d, 0x71, 0xa4, 0xd5, 0x45, 0xcf, 0xb5, 0x96, 0x88, 0xe3, 0xad, 0x42, 0x1c, 0x59, 0x83, 0x19, 0x02, 0x8e, 0x01, 0x97, 0xb6, 0x61, 0x71, 0x80, 0xa7, 0x81, 0xe3, 0xc0, 0x81, 0x76, 0x21, 0x6e, 0x05, 0x8e, 0x00, 0x2f, 0x76, 0x40, 0xbe, 0x56, 0x88, 0x07, 0x81, 0x03, 0x9d, 0x40, 0x17, 0x74, 0xd7, 0x09, 0xc7, 0xcb, 0xc0, 0xdb, 0xeb, 0xb0, 0xb0, 0xeb, 0x9d, 0xe2, 0x68, 0x0f, 0xea, 0x39, 0x4b, 0x8a, 0x4b, 0x37, 0x4a, 0x71, 0xd7, 0xc6, 0xcc, 0xff, 0xdf, 0x12, 0x36, 0x9a, 0xfe, 0xbf, 0xa4, 0xfc, 0x9d, 0xab, 0xf4, 0xff, 0x26, 0xe5, 0xef, 0x62, 0xa5, 0xff, 0x3f, 0x29, 0x7f, 0xd7, 0x2a, 0xfd, 0x3f, 0x4a, 0xf9, 0x7b, 0x58, 0xe9, 0xff, 0x53, 0xea, 0xa2, 0x91, 0xff, 0x55, 0x6a, 0x79, 0xf5, 0xdf, 0x51, 0xf0, 0xf7, 0x16, 0x85, 0x5f, 0xff, 0x7f, 0xb3, 0x43, 0xe0, 0x5d, 0x7e, 0xad, 0xc3, 0x7f, 0xdb, 0x2f, 0xbc, 0xba, 0x7e, 0xfe, 0x7b, 0x7f, 0xe9, 0xd7, 0xed, 0xf2, 0xff, 0x36, 0xb5, 0x8c, 0x3e, 0xff, 0xdd, 0xba, 0xc3, 0xaf, 0xbf, 0x5b, 0xc9, 0x7f, 0xeb, 0x4e, 0xa6, 0xac, 0xfa, 0x9f, 0x00, 0x5e, 0xdd, 0x57, 0xfe, 0x3f, 0xaa, 0xff, 0x03, 0x52, 0x5b, 0x3b, 0x13, 0x80, 0x55, 0x00, 0x00, 0x00, 0x00, }; //============================================================================== #if JUCE_PUSH_NOTIFICATIONS && JUCE_MODULE_AVAILABLE_juce_gui_extra bool juce_handleNotificationIntent (void*); void juce_firebaseDeviceNotificationsTokenRefreshed (void*); void juce_firebaseRemoteNotificationReceived (void*); void juce_firebaseRemoteMessagesDeleted(); void juce_firebaseRemoteMessageSent(void*); void juce_firebaseRemoteMessageSendError (void*, void*); #endif #if JUCE_IN_APP_PURCHASES && JUCE_MODULE_AVAILABLE_juce_product_unlocking void juce_handleOnResume(); #else static void juce_handleOnResume() {} #endif //============================================================================== #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \ METHOD (create, "", "(II)V") DECLARE_JNI_CLASS (AndroidLayoutParams, "android/view/ViewGroup$LayoutParams") #undef JNI_CLASS_MEMBERS #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \ METHOD (addView, "addView", "(Landroid/view/View;Landroid/view/ViewGroup$LayoutParams;)V") \ METHOD (removeView, "removeView", "(Landroid/view/View;)V") \ METHOD (updateViewLayout, "updateViewLayout", "(Landroid/view/View;Landroid/view/ViewGroup$LayoutParams;)V") DECLARE_JNI_CLASS (AndroidViewManager, "android/view/ViewManager") #undef JNI_CLASS_MEMBERS #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \ METHOD (create, "", "(IIIIIII)V") \ FIELD (gravity, "gravity", "I") \ FIELD (windowAnimations, "windowAnimations", "I") DECLARE_JNI_CLASS (AndroidWindowManagerLayoutParams, "android/view/WindowManager$LayoutParams") #undef JNI_CLASS_MEMBERS #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \ FIELD (layoutInDisplayCutoutMode, "layoutInDisplayCutoutMode", "I") DECLARE_JNI_CLASS_WITH_MIN_SDK (AndroidWindowManagerLayoutParams28, "android/view/WindowManager$LayoutParams", 28) #undef JNI_CLASS_MEMBERS #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \ METHOD (getDisplayCutout, "getDisplayCutout", "()Landroid/view/DisplayCutout;") \ METHOD (consumeDisplayCutout, "consumeDisplayCutout", "()Landroid/view/WindowInsets;") DECLARE_JNI_CLASS_WITH_MIN_SDK (AndroidWindowInsets28, "android/view/WindowInsets", 28) #undef JNI_CLASS_MEMBERS #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \ METHOD (getInsets, "getInsets", "(I)Landroid/graphics/Insets;") \ STATICFIELD (CONSUMED, "CONSUMED", "Landroid/view/WindowInsets;") DECLARE_JNI_CLASS_WITH_MIN_SDK (AndroidWindowInsets30, "android/view/WindowInsets", 30) #undef JNI_CLASS_MEMBERS #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \ METHOD (getSafeInsetBottom, "getSafeInsetBottom", "()I") \ METHOD (getSafeInsetLeft, "getSafeInsetLeft", "()I") \ METHOD (getSafeInsetRight, "getSafeInsetRight", "()I") \ METHOD (getSafeInsetTop, "getSafeInsetTop", "()I") DECLARE_JNI_CLASS_WITH_MIN_SDK (AndroidDisplayCutout, "android/view/DisplayCutout", 28) #undef JNI_CLASS_MEMBERS #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \ FIELD (bottom, "bottom", "I") \ FIELD (left, "left", "I") \ FIELD (right, "right", "I") \ FIELD (top, "top", "I") DECLARE_JNI_CLASS_WITH_MIN_SDK (AndroidGraphicsInsets, "android/graphics/Insets", 29) #undef JNI_CLASS_MEMBERS #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \ STATICMETHOD (ime, "ime", "()I") \ STATICMETHOD (displayCutout, "displayCutout", "()I") DECLARE_JNI_CLASS_WITH_MIN_SDK (AndroidWindowInsetsType, "android/view/WindowInsets$Type", 30) #undef JNI_CLASS_MEMBERS #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \ FIELD (first, "first", "Ljava/lang/Object;") \ FIELD (second, "second", "Ljava/lang/Object;") \ DECLARE_JNI_CLASS (AndroidPair, "android/util/Pair") #undef JNI_CLASS_MEMBERS //============================================================================== namespace { enum { SYSTEM_UI_FLAG_VISIBLE = 0, SYSTEM_UI_FLAG_LOW_PROFILE = 1, SYSTEM_UI_FLAG_HIDE_NAVIGATION = 2, SYSTEM_UI_FLAG_FULLSCREEN = 4, SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 512, SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 1024, SYSTEM_UI_FLAG_IMMERSIVE = 2048, SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 4096 }; constexpr int fullScreenFlags = SYSTEM_UI_FLAG_HIDE_NAVIGATION | SYSTEM_UI_FLAG_FULLSCREEN | SYSTEM_UI_FLAG_IMMERSIVE_STICKY; constexpr int FLAG_NOT_FOCUSABLE = 0x8; } //============================================================================== static bool supportsDisplayCutout() { return getAndroidSDKVersion() >= 28; } static BorderSize androidDisplayCutoutToBorderSize (LocalRef displayCutout, double displayScale) { if (displayCutout == nullptr) return {}; auto* env = getEnv(); const auto getInset = [&] (jmethodID methodID) { return roundToInt (env->CallIntMethod (displayCutout, methodID) / displayScale); }; return { getInset (AndroidDisplayCutout.getSafeInsetTop), getInset (AndroidDisplayCutout.getSafeInsetLeft), getInset (AndroidDisplayCutout.getSafeInsetBottom), getInset (AndroidDisplayCutout.getSafeInsetRight) }; } static BorderSize androidInsetsToBorderSize (LocalRef insets, double displayScale) { if (insets == nullptr) return {}; auto* env = getEnv(); const auto getInset = [&] (jfieldID fieldID) { return roundToInt (env->GetIntField (insets, fieldID) / displayScale); }; return { getInset (AndroidGraphicsInsets.top), getInset (AndroidGraphicsInsets.left), getInset (AndroidGraphicsInsets.bottom), getInset (AndroidGraphicsInsets.right) }; } class JuceInsets { template static auto tieDisplay (Display& d) { return std::tie (d.safeAreaInsets, d.keyboardInsets); } public: BorderSize displayCutout, keyboard; static auto tie ( Displays::Display& d) { return tieDisplay (d); } static auto tie (const Displays::Display& d) { return tieDisplay (d); } auto tie() const { return std::tie (displayCutout, keyboard); } }; static JuceInsets getInsetsFromAndroidWindowInsets (LocalRef windowInsets, double scale) { auto* env = getEnv(); if (windowInsets == nullptr) return {}; const auto displayCutout = [&]() -> BorderSize { if (AndroidWindowInsets28.getDisplayCutout == nullptr) return {}; const LocalRef insets { env->CallObjectMethod (windowInsets, AndroidWindowInsets28.getDisplayCutout) }; return androidDisplayCutoutToBorderSize (insets, scale); }(); const auto keyboard = [&]() -> BorderSize { if (AndroidWindowInsetsType.ime == nullptr || AndroidWindowInsets30.getInsets == nullptr) return {}; const auto mask = env->CallStaticIntMethod (AndroidWindowInsetsType, AndroidWindowInsetsType.ime); const LocalRef insets { env->CallObjectMethod (windowInsets, AndroidWindowInsets30.getInsets, mask) }; return androidInsetsToBorderSize (insets, scale); }(); return { displayCutout, keyboard }; } /* The usage of the KeyPress class relies on its keyCode member having the standard ASCII values represent ASCII keycodes. However in the native Android keycodes the values for special keys e.g. RETURN, F1-F12 overlap with the ASCII range. Hence we need to translate them. */ static constexpr int translateAndroidKeyCode (int keyCode) noexcept { switch (keyCode) { case 7: return '0'; case 8: return '1'; case 9: return '2'; case 10: return '3'; case 11: return '4'; case 12: return '5'; case 13: return '6'; case 14: return '7'; case 15: return '8'; case 16: return '9'; case 17: return '*'; case 18: return '#'; case 19: return KeyPress::upKey; // KEYCODE_DPAD_UP case 20: return KeyPress::downKey; // KEYCODE_DPAD_DOWN case 21: return KeyPress::leftKey; // KEYCODE_DPAD_LEFT case 22: return KeyPress::rightKey; // KEYCODE_DPAD_RIGHT case 29: return 'A'; case 30: return 'B'; case 31: return 'C'; case 32: return 'D'; case 33: return 'E'; case 34: return 'F'; case 35: return 'G'; case 36: return 'H'; case 37: return 'I'; case 38: return 'J'; case 39: return 'K'; case 40: return 'L'; case 41: return 'M'; case 42: return 'N'; case 43: return 'O'; case 44: return 'P'; case 45: return 'Q'; case 46: return 'R'; case 47: return 'S'; case 48: return 'T'; case 49: return 'U'; case 50: return 'V'; case 51: return 'W'; case 52: return 'X'; case 53: return 'Y'; case 54: return 'Z'; case 55: return ','; case 56: return '.'; case 61: return KeyPress::tabKey; // KEYCODE_TAB case 62: return KeyPress::spaceKey; // KEYCODE_SPACE case 66: return KeyPress::returnKey; // KEYCODE_ENTER case 67: return KeyPress::backspaceKey; // KEYCODE_DEL case 68: return '`'; case 69: return '-'; case 70: return '='; case 71: return '['; case 72: return ']'; case 73: return '\\'; case 74: return ';'; case 75: return '\''; case 76: return '/'; case 77: return '@'; case 81: return '+'; case 85: return KeyPress::playKey; // KEYCODE_MEDIA_PLAY_PAUSE case 86: return KeyPress::stopKey; // KEYCODE_MEDIA_STOP case 87: return KeyPress::fastForwardKey; // KEYCODE_MEDIA_NEXT case 88: return KeyPress::rewindKey; // KEYCODE_MEDIA_PREVIOUS case 92: return KeyPress::pageUpKey; // KEYCODE_PAGE_UP case 93: return KeyPress::pageDownKey; // KEYCODE_PAGE_DOWN case 111: return KeyPress::escapeKey; // KEYCODE_ESCAPE case 112: return KeyPress::deleteKey; // KEYCODE_FORWARD_DEL case 122: return KeyPress::homeKey; // KEYCODE_MOVE_HOME case 123: return KeyPress::endKey; // KEYCODE_MOVE_END case 124: return KeyPress::insertKey; // KEYCODE_INSERT case 131: return KeyPress::F1Key; // KEYCODE_F1 case 132: return KeyPress::F2Key; // KEYCODE_F2 case 133: return KeyPress::F3Key; // KEYCODE_F3 case 134: return KeyPress::F4Key; // KEYCODE_F4 case 135: return KeyPress::F5Key; // KEYCODE_F5 case 136: return KeyPress::F6Key; // KEYCODE_F6 case 137: return KeyPress::F7Key; // KEYCODE_F7 case 138: return KeyPress::F8Key; // KEYCODE_F8 case 139: return KeyPress::F9Key; // KEYCODE_F9 case 140: return KeyPress::F10Key; // KEYCODE_F10 case 141: return KeyPress::F11Key; // KEYCODE_F11 case 142: return KeyPress::F12Key; // KEYCODE_F12 case 144: return '0'; case 145: return '1'; case 146: return '2'; case 147: return '3'; case 148: return '4'; case 149: return '5'; case 150: return '6'; case 151: return '7'; case 152: return '8'; case 153: return '9'; case 154: return '/'; case 155: return '*'; case 156: return '-'; case 157: return '+'; case 158: return '.'; case 159: return ','; case 161: return '='; case 162: return '('; case 163: return ')'; default: return 0; } } static constexpr int translateAndroidKeyboardFlags (int javaFlags) noexcept { constexpr int metaShiftOn = 0x1; constexpr int metaAltOn = 0x02; constexpr int metaCtrlOn = 0x1000; int flags = 0; if ((javaFlags & metaShiftOn) != 0) flags |= ModifierKeys::shiftModifier; if ((javaFlags & metaAltOn) != 0) flags |= ModifierKeys::altModifier; if ((javaFlags & metaCtrlOn) != 0) flags |= ModifierKeys::ctrlModifier; return flags; } //============================================================================== class AndroidComponentPeer : public ComponentPeer, private Timer { public: AndroidComponentPeer (Component& comp, int windowStyleFlags, void* nativeViewHandle) : ComponentPeer (comp, windowStyleFlags) { auto* env = getEnv(); // NB: must not put this in the initialiser list, as it invokes a callback, // which will fail if the peer is only half-constructed. view = GlobalRef (LocalRef (env->NewObject (ComponentPeerView, ComponentPeerView.create, getAppContext().get(), (jboolean) component.isOpaque(), (jlong) this))); if (nativeViewHandle != nullptr) { viewGroupIsWindow = false; // we don't know if the user is holding on to a local ref to this, so // explicitly create a new one auto nativeView = LocalRef (env->NewLocalRef (static_cast (nativeViewHandle))); if (env->IsInstanceOf (nativeView.get(), AndroidActivity)) { viewGroup = GlobalRef (nativeView); env->CallVoidMethod (viewGroup.get(), AndroidActivity.setContentView, view.get()); } else if (env->IsInstanceOf (nativeView.get(), AndroidViewGroup)) { viewGroup = GlobalRef (nativeView); LocalRef layoutParams (env->NewObject (AndroidLayoutParams, AndroidLayoutParams.create, -2, -2)); env->CallVoidMethod (view.get(), AndroidView.setLayoutParams, layoutParams.get()); env->CallVoidMethod ((jobject) viewGroup.get(), AndroidViewGroup.addView, view.get()); } else { // the native handle you passed as a second argument to Component::addToDesktop must // either be an Activity or a ViewGroup jassertfalse; } } else { viewGroupIsWindow = true; LocalRef viewLayoutParams (env->NewObject (AndroidLayoutParams, AndroidLayoutParams.create, -2, -2)); env->CallVoidMethod (view.get(), AndroidView.setLayoutParams, viewLayoutParams.get()); auto physicalBounds = (comp.getBoundsInParent().toFloat() * scale).toNearestInt(); view.callVoidMethod (AndroidView.layout, physicalBounds.getX(), physicalBounds.getY(), physicalBounds.getRight(), physicalBounds.getBottom()); LocalRef windowLayoutParams (env->NewObject (AndroidWindowManagerLayoutParams, AndroidWindowManagerLayoutParams.create, physicalBounds.getWidth(), physicalBounds.getHeight(), physicalBounds.getX(), physicalBounds.getY(), TYPE_APPLICATION, FLAG_NOT_TOUCH_MODAL | FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_NO_LIMITS | FLAG_NOT_FOCUSABLE, component.isOpaque() ? PIXEL_FORMAT_OPAQUE : PIXEL_FORMAT_TRANSPARENT)); env->SetIntField (windowLayoutParams.get(), AndroidWindowManagerLayoutParams.gravity, GRAVITY_LEFT | GRAVITY_TOP); env->SetIntField (windowLayoutParams.get(), AndroidWindowManagerLayoutParams.windowAnimations, 0x01030000 /* android.R.style.Animation */); if (supportsDisplayCutout()) { if (const auto fieldID = AndroidWindowManagerLayoutParams28.layoutInDisplayCutoutMode) env->SetIntField (windowLayoutParams, fieldID, LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS); } if (Desktop::getInstance().getKioskModeComponent() != nullptr) setNavBarsHidden (true); LocalRef activity (getCurrentActivity()); if (activity == nullptr) activity = getMainActivity(); viewGroup = GlobalRef (LocalRef (env->CallObjectMethod (activity.get(), AndroidContext.getSystemService, javaString ("window").get()))); env->CallVoidMethod (viewGroup.get(), AndroidViewManager.addView, view.get(), windowLayoutParams.get()); } if (supportsDisplayCutout()) { if (const auto methodID = AndroidView23.setOnApplyWindowInsetsListener) { env->CallVoidMethod (view, methodID, CreateJavaInterface (new ViewWindowInsetsListener, "android/view/View$OnApplyWindowInsetsListener").get()); } } if (isFocused()) handleFocusGain(); } ~AndroidComponentPeer() override { stopTimer(); auto* env = getEnv(); env->CallVoidMethod (view, ComponentPeerView.clear); frontWindow = nullptr; GlobalRef localView (view); GlobalRef localViewGroup (viewGroup); callOnMessageThread ([env, localView, localViewGroup] { if (env->IsInstanceOf (localViewGroup.get(), AndroidActivity)) env->CallVoidMethod (localViewGroup.get(), AndroidActivity.setContentView, nullptr); else env->CallVoidMethod (localViewGroup.get(), AndroidViewManager.removeView, localView.get()); }); } void* getNativeHandle() const override { return (void*) view.get(); } void setVisible (bool shouldBeVisible) override { GlobalRef localView (view); callOnMessageThread ([localView, shouldBeVisible] { localView.callVoidMethod (ComponentPeerView.setVisible, shouldBeVisible); }); } void setTitle (const String& title) override { view.callVoidMethod (ComponentPeerView.setViewName, javaString (title).get()); } void setBounds (const Rectangle& userRect, bool isNowFullScreen) override { auto bounds = (userRect.toFloat() * scale).toNearestInt(); if (MessageManager::getInstance()->isThisTheMessageThread()) { fullScreen = isNowFullScreen; view.callVoidMethod (AndroidView.layout, bounds.getX(), bounds.getY(), bounds.getRight(), bounds.getBottom()); if (viewGroup != nullptr && viewGroupIsWindow) { auto* env = getEnv(); LocalRef windowLayoutParams (env->NewObject (AndroidWindowManagerLayoutParams, AndroidWindowManagerLayoutParams.create, bounds.getWidth(), bounds.getHeight(), bounds.getX(), bounds.getY(), TYPE_APPLICATION, FLAG_NOT_TOUCH_MODAL | FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_NO_LIMITS, component.isOpaque() ? PIXEL_FORMAT_OPAQUE : PIXEL_FORMAT_TRANSPARENT)); env->SetIntField (windowLayoutParams.get(), AndroidWindowManagerLayoutParams.gravity, GRAVITY_LEFT | GRAVITY_TOP); env->CallVoidMethod (viewGroup.get(), AndroidViewManager.updateViewLayout, view.get(), windowLayoutParams.get()); } } else { GlobalRef localView (view); MessageManager::callAsync ([localView, bounds] { localView.callVoidMethod (AndroidView.layout, bounds.getX(), bounds.getY(), bounds.getRight(), bounds.getBottom()); }); } } Rectangle getBounds() const override { Rectangle bounds (view.callIntMethod (AndroidView.getLeft), view.callIntMethod (AndroidView.getTop), view.callIntMethod (AndroidView.getWidth), view.callIntMethod (AndroidView.getHeight)); return (bounds.toFloat() / scale).toNearestInt(); } void handleScreenSizeChange() override { ComponentPeer::handleScreenSizeChange(); if (isFullScreen()) setFullScreen (true); } Point getScreenPosition() const { auto* env = getEnv(); LocalRef position (env->NewIntArray (2)); env->CallVoidMethod (view.get(), AndroidView.getLocationOnScreen, position.get()); jint* const screenPosition = env->GetIntArrayElements (position.get(), nullptr); Point pos (screenPosition[0], screenPosition[1]); env->ReleaseIntArrayElements (position.get(), screenPosition, 0); return pos; } Point localToGlobal (Point relativePosition) override { return relativePosition + (getScreenPosition().toFloat() / scale); } using ComponentPeer::localToGlobal; Point globalToLocal (Point screenPosition) override { return screenPosition - (getScreenPosition().toFloat() / scale); } using ComponentPeer::globalToLocal; void setMinimised (bool /*shouldBeMinimised*/) override { // n/a } bool isMinimised() const override { return false; } void setFullScreen (bool shouldBeFullScreen) override { if (shouldNavBarsBeHidden (shouldBeFullScreen)) { if (isTimerRunning()) return; startTimer (500); } else { setNavBarsHidden (false); } auto newBounds = [&] { if (navBarsHidden || shouldBeFullScreen) if (auto* display = Desktop::getInstance().getDisplays().getPrimaryDisplay()) return navBarsHidden ? display->totalArea : display->userArea; return lastNonFullscreenBounds.isEmpty() ? getBounds() : lastNonFullscreenBounds; }(); if (! newBounds.isEmpty()) setBounds (newBounds, shouldBeFullScreen); component.repaint(); } bool isFullScreen() const override { return fullScreen; } void setIcon (const Image& /*newIcon*/) override { // n/a } bool contains (Point localPos, bool trueIfInAChildWindow) const override { return isPositiveAndBelow (localPos.x, component.getWidth()) && isPositiveAndBelow (localPos.y, component.getHeight()) && ((! trueIfInAChildWindow) || view.callBooleanMethod (ComponentPeerView.containsPoint, (float) localPos.x * scale, (float) localPos.y * scale)); } OptionalBorderSize getFrameSizeIfPresent() const override { // TODO return {}; } BorderSize getFrameSize() const override { // TODO return {}; } bool setAlwaysOnTop (bool /*alwaysOnTop*/) override { // TODO return false; } void toFront (bool makeActive) override { // Avoid calling bringToFront excessively: it's very slow if (frontWindow != this) { view.callVoidMethod (AndroidView.bringToFront); frontWindow = this; } if (makeActive) grabFocus(); handleBroughtToFront(); } void toBehind (ComponentPeer*) override { // TODO } //============================================================================== void handleMouseDownCallback (int index, Point sysPos, int64 time) { lastMousePos = sysPos / scale; auto pos = globalToLocal (lastMousePos); // this forces a mouse-enter/up event, in case for some reason we didn't get a mouse-up before. handleMouseEvent (MouseInputSource::InputSourceType::touch, pos, ModifierKeys::currentModifiers.withoutMouseButtons(), MouseInputSource::defaultPressure, MouseInputSource::defaultOrientation, time, {}, index); if (isValidPeer (this)) handleMouseDragCallback (index, sysPos, time); } void handleMouseDragCallback (int index, Point sysPos, int64 time) { lastMousePos = sysPos / scale; auto pos = globalToLocal (lastMousePos); jassert (index < 64); touchesDown = (touchesDown | (1 << (index & 63))); ModifierKeys::currentModifiers = ModifierKeys::currentModifiers.withoutMouseButtons().withFlags (ModifierKeys::leftButtonModifier); handleMouseEvent (MouseInputSource::InputSourceType::touch, pos, ModifierKeys::currentModifiers.withoutMouseButtons().withFlags (ModifierKeys::leftButtonModifier), MouseInputSource::defaultPressure, MouseInputSource::defaultOrientation, time, {}, index); } void handleMouseUpCallback (int index, Point sysPos, int64 time) { lastMousePos = sysPos / scale; auto pos = globalToLocal (lastMousePos); jassert (index < 64); touchesDown = (touchesDown & ~(1 << (index & 63))); if (touchesDown == 0) ModifierKeys::currentModifiers = ModifierKeys::currentModifiers.withoutMouseButtons(); handleMouseEvent (MouseInputSource::InputSourceType::touch, pos, ModifierKeys::currentModifiers.withoutMouseButtons(), MouseInputSource::defaultPressure, MouseInputSource::defaultOrientation, time, {}, index); handleMouseEvent (MouseInputSource::InputSourceType::touch, MouseInputSource::offscreenMousePos, ModifierKeys::currentModifiers.withoutMouseButtons(), MouseInputSource::defaultPressure, MouseInputSource::defaultOrientation, time, {}, index); } void handleAccessibilityHoverCallback (int command, Point sysPos, int64) { enum { TYPE_VIEW_HOVER_ENTER = 0x00000080, TYPE_VIEW_HOVER_EXIT = 0x00000100, ACTION_HOVER_ENTER = 0x00000009, ACTION_HOVER_MOVE = 0x00000007, ACTION_HOVER_EXIT = 0x0000000a }; if (auto* topHandler = component.getAccessibilityHandler()) { if (auto* virtualHandler = topHandler->getChildAt ((sysPos / scale).roundToInt())) { switch (command) { case ACTION_HOVER_ENTER: case ACTION_HOVER_MOVE: AccessibilityNativeHandle::sendAccessibilityEventImpl (*virtualHandler, TYPE_VIEW_HOVER_ENTER, 0); break; case ACTION_HOVER_EXIT: AccessibilityNativeHandle::sendAccessibilityEventImpl (*virtualHandler, TYPE_VIEW_HOVER_EXIT, 0); break; } } } } static void handleKeyDownCallback (JNIEnv*, AndroidComponentPeer& t, int k, int kc, int kbFlags) { ModifierKeys::currentModifiers = ModifierKeys::currentModifiers.withOnlyMouseButtons() .withFlags (translateAndroidKeyboardFlags (kbFlags)); t.handleKeyPress (translateAndroidKeyCode (k), static_cast (kc)); } static void handleKeyUpCallback (JNIEnv*, [[maybe_unused]] AndroidComponentPeer& t, [[maybe_unused]] int k, [[maybe_unused]] int kc) { } static void handleBackButtonCallback (JNIEnv* env, AndroidComponentPeer& t) { bool handled = false; if (auto* app = JUCEApplicationBase::getInstance()) handled = app->backButtonPressed(); if (t.isKioskModeComponent()) t.setNavBarsHidden (t.navBarsHidden); if (! handled) { LocalRef activity (getCurrentActivity()); if (activity != nullptr) { if (const auto finishMethod = AndroidActivity.finish) env->CallVoidMethod (activity.get(), finishMethod); } } } static void handleKeyboardHiddenCallback (JNIEnv*, [[maybe_unused]] AndroidComponentPeer& t) { Component::unfocusAllComponents(); } static void handleAppPausedCallback (JNIEnv*, [[maybe_unused]] AndroidComponentPeer& t) {} static void handleAppResumedCallback (JNIEnv*, AndroidComponentPeer& t) { if (t.isKioskModeComponent()) t.setNavBarsHidden (t.navBarsHidden); } static jlong handleGetFocusedTextInputTargetCallback (JNIEnv*, AndroidComponentPeer& t) { return reinterpret_cast (t.findCurrentTextInputTarget()); } static void handleMovedOrResizedCallback (JNIEnv*, AndroidComponentPeer& t) { t.handleMovedOrResized(); } //============================================================================== AccessibilityNativeHandle* getNativeHandleForViewId (jint virtualViewId) const { if (auto* handler = (virtualViewId == HOST_VIEW_ID ? component.getAccessibilityHandler() : AccessibilityNativeHandle::getAccessibilityHandlerForVirtualViewId (virtualViewId))) { return handler->getNativeImplementation(); } return nullptr; } static jobject getNativeViewCallback (JNIEnv*, const AndroidComponentPeer& t, jint virtualViewId) { if (auto* handle = t.getNativeHandleForViewId (virtualViewId)) return handle->getNativeView (virtualViewId); return nullptr; } static jboolean populateAccessibilityNodeInfoCallback (JNIEnv*, const AndroidComponentPeer& t, jint virtualViewId, jobject info) { if (auto* handle = t.getNativeHandleForViewId (virtualViewId)) { handle->populateNodeInfo (info, virtualViewId); return true; } return false; } static jboolean handlePerformActionCallback (JNIEnv*, const AndroidComponentPeer& t, jint virtualViewId, jint action, jobject arguments) { if (auto* handle = t.getNativeHandleForViewId (virtualViewId)) return handle->performAction (action, arguments); return false; } static jobject getFocusViewIdForHandler (JNIEnv* env, const AccessibilityHandler* handler) { if (handler != nullptr) return env->NewObject (JavaInteger, JavaInteger.constructor, handler->getNativeImplementation()->getVirtualViewId()); return nullptr; } static jobject getInputFocusViewIdCallback (JNIEnv* env, AndroidComponentPeer& t) { if (auto* comp = dynamic_cast (t.findCurrentTextInputTarget())) return getFocusViewIdForHandler (env, comp->getAccessibilityHandler()); return nullptr; } static jobject getAccessibilityFocusViewIdCallback (JNIEnv* env, const AndroidComponentPeer& t) { if (auto* handler = t.component.getAccessibilityHandler()) { if (auto* modal = Component::getCurrentlyModalComponent()) { if (! t.component.isParentOf (modal) && t.component.isCurrentlyBlockedByAnotherModalComponent()) { if (auto* modalHandler = modal->getAccessibilityHandler()) { if (auto* focusChild = modalHandler->getChildFocus()) return getFocusViewIdForHandler (env, focusChild); return getFocusViewIdForHandler (env, modalHandler); } } } if (auto* focusChild = handler->getChildFocus()) return getFocusViewIdForHandler (env, focusChild); } return nullptr; } //============================================================================== bool isFocused() const override { if (view != nullptr) return view.callBooleanMethod (AndroidView.hasFocus); return false; } void grabFocus() override { if (view != nullptr) view.callBooleanMethod (AndroidView.requestFocus); } static void handleFocusChangeCallback (JNIEnv*, AndroidComponentPeer& t, bool hasFocus) { if (t.isFullScreen()) t.setFullScreen (true); if (hasFocus) t.handleFocusGain(); else t.handleFocusLoss(); } void textInputRequired (Point, TextInputTarget& target) override { const auto region = target.getHighlightedRegion(); view.callVoidMethod (ComponentPeerView.showKeyboard, static_cast (target.getKeyboardType()), static_cast (region.getStart()), static_cast (region.getEnd())); } void closeInputMethodContext() override { getEnv()->CallVoidMethod (view, ComponentPeerView.closeInputMethodContext); } void dismissPendingTextInput() override { closeInputMethodContext(); view.callVoidMethod (ComponentPeerView.hideKeyboard); if (! isTimerRunning()) startTimer (500); } //============================================================================== static void handleDoFrameCallback (JNIEnv*, AndroidComponentPeer& t, [[maybe_unused]] int64 frameTimeNanos) { t.vBlankListeners.call ([] (auto& l) { l.onVBlank(); }); } static void handlePaintCallback (JNIEnv* env, AndroidComponentPeer& t, jobject canvas, jobject paint) { jobject rect = env->CallObjectMethod (canvas, AndroidCanvas.getClipBounds); auto left = env->GetIntField (rect, AndroidRect.left); auto top = env->GetIntField (rect, AndroidRect.top); auto right = env->GetIntField (rect, AndroidRect.right); auto bottom = env->GetIntField (rect, AndroidRect.bottom); env->DeleteLocalRef (rect); auto clip = Rectangle::leftTopRightBottom (left, top, right, bottom); if (clip.isEmpty()) return; auto sizeNeeded = clip.getWidth() * clip.getHeight(); if (t.sizeAllocated < sizeNeeded) { t.buffer.clear(); t.sizeAllocated = sizeNeeded; t.buffer = GlobalRef (LocalRef ((jobject) env->NewIntArray (sizeNeeded))); } if (jint* dest = env->GetIntArrayElements ((jintArray) t.buffer.get(), nullptr)) { { Image temp (new PreallocatedImage (clip.getWidth(), clip.getHeight(), dest, ! t.component.isOpaque())); { LowLevelGraphicsSoftwareRenderer g (temp); g.setOrigin (-clip.getPosition()); g.addTransform (AffineTransform::scale (t.scale)); t.handlePaint (g); } } env->ReleaseIntArrayElements ((jintArray) t.buffer.get(), dest, 0); env->CallVoidMethod (canvas, AndroidCanvas.drawBitmap, (jintArray) t.buffer.get(), 0, clip.getWidth(), (jfloat) clip.getX(), (jfloat) clip.getY(), clip.getWidth(), clip.getHeight(), true, paint); } } void repaint (const Rectangle& userArea) override { auto area = (userArea.toFloat() * scale).toNearestInt(); GlobalRef localView (view); callOnMessageThread ([area, localView] { localView.callVoidMethod (AndroidView.invalidate, area.getX(), area.getY(), area.getRight(), area.getBottom()); }); } void performAnyPendingRepaintsNow() override { // TODO } void setAlpha (float /*newAlpha*/) override { // TODO } StringArray getAvailableRenderingEngines() override { return StringArray ("Software Renderer"); } //============================================================================== static Point lastMousePos; static int64 touchesDown; //============================================================================== struct StartupActivityCallbackListener : public ActivityLifecycleCallbacks { void onActivityStarted (jobject /*activity*/) override { auto* env = getEnv(); LocalRef appContext (getAppContext()); if (appContext.get() != nullptr) { env->CallVoidMethod (appContext.get(), AndroidApplication.unregisterActivityLifecycleCallbacks, activityCallbackListener.get()); clear(); activityCallbackListener.clear(); forceDisplayUpdate(); } } }; private: template static void mouseCallbackWrapper (JNIEnv*, AndroidComponentPeer& t, jint i, jfloat x, jfloat y, jlong time) { return (t.*Member) (i, Point { x, y }, time); } //============================================================================== #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \ METHOD (create, "", "(Landroid/content/Context;ZJ)V") \ METHOD (clear, "clear", "()V") \ METHOD (setViewName, "setViewName", "(Ljava/lang/String;)V") \ METHOD (setVisible, "setVisible", "(Z)V") \ METHOD (isVisible, "isVisible", "()Z") \ METHOD (containsPoint, "containsPoint", "(II)Z") \ METHOD (showKeyboard, "showKeyboard", "(III)V") \ METHOD (hideKeyboard, "hideKeyboard", "()V") \ METHOD (closeInputMethodContext, "closeInputMethodContext", "()V") \ METHOD (setSystemUiVisibilityCompat, "setSystemUiVisibilityCompat", "(I)V") \ CALLBACK (generatedCallback<&AndroidComponentPeer::handleDoFrameCallback>, "handleDoFrame", "(JJ)V") \ CALLBACK (generatedCallback<&AndroidComponentPeer::handlePaintCallback>, "handlePaint", "(JLandroid/graphics/Canvas;Landroid/graphics/Paint;)V") \ CALLBACK (generatedCallback<&AndroidComponentPeer::handleKeyDownCallback>, "handleKeyDown", "(JIII)V") \ CALLBACK (generatedCallback<&AndroidComponentPeer::handleKeyUpCallback>, "handleKeyUp", "(JII)V") \ CALLBACK (generatedCallback<&AndroidComponentPeer::handleBackButtonCallback>, "handleBackButton", "(J)V") \ CALLBACK (generatedCallback<&AndroidComponentPeer::handleKeyboardHiddenCallback>, "handleKeyboardHidden", "(J)V") \ CALLBACK (generatedCallback<&AndroidComponentPeer::handleGetFocusedTextInputTargetCallback>, "getFocusedTextInputTargetPointer", "(J)J") \ CALLBACK (generatedCallback<&AndroidComponentPeer::handleMovedOrResizedCallback>, "viewSizeChanged", "(J)V") \ CALLBACK (generatedCallback<&AndroidComponentPeer::handleFocusChangeCallback>, "focusChanged", "(JZ)V") \ CALLBACK (generatedCallback<&AndroidComponentPeer::handleAppPausedCallback>, "handleAppPaused", "(J)V") \ CALLBACK (generatedCallback<&AndroidComponentPeer::handleAppResumedCallback>, "handleAppResumed", "(J)V") \ CALLBACK (generatedCallback<&AndroidComponentPeer::getNativeViewCallback>, "getNativeView", "(JI)Landroid/view/View;") \ CALLBACK (generatedCallback<&AndroidComponentPeer::populateAccessibilityNodeInfoCallback>, "populateAccessibilityNodeInfo", "(JILandroid/view/accessibility/AccessibilityNodeInfo;)Z") \ CALLBACK (generatedCallback<&AndroidComponentPeer::handlePerformActionCallback>, "handlePerformAction", "(JIILandroid/os/Bundle;)Z") \ CALLBACK (generatedCallback<&AndroidComponentPeer::getInputFocusViewIdCallback>, "getInputFocusViewId", "(J)Ljava/lang/Integer;") \ CALLBACK (generatedCallback<&AndroidComponentPeer::getAccessibilityFocusViewIdCallback>, "getAccessibilityFocusViewId", "(J)Ljava/lang/Integer;") \ CALLBACK (generatedCallback<&AndroidComponentPeer::textInputTargetIsTextInputActive>, "textInputTargetIsTextInputActive", "(J)Z") \ CALLBACK (generatedCallback<&AndroidComponentPeer::textInputTargetGetHighlightedRegionBegin>, "textInputTargetGetHighlightedRegionBegin", "(J)I") \ CALLBACK (generatedCallback<&AndroidComponentPeer::textInputTargetGetHighlightedRegionEnd>, "textInputTargetGetHighlightedRegionEnd", "(J)I") \ CALLBACK (generatedCallback<&AndroidComponentPeer::textInputTargetSetHighlightedRegion>, "textInputTargetSetHighlightedRegion", "(JII)V") \ CALLBACK (generatedCallback<&AndroidComponentPeer::textInputTargetGetTextInRange>, "textInputTargetGetTextInRange", "(JII)Ljava/lang/String;") \ CALLBACK (generatedCallback<&AndroidComponentPeer::textInputTargetInsertTextAtCaret>, "textInputTargetInsertTextAtCaret", "(JLjava/lang/String;)V") \ CALLBACK (generatedCallback<&AndroidComponentPeer::textInputTargetGetCaretPosition>, "textInputTargetGetCaretPosition", "(J)I") \ CALLBACK (generatedCallback<&AndroidComponentPeer::textInputTargetGetTotalNumChars>, "textInputTargetGetTotalNumChars", "(J)I") \ CALLBACK (generatedCallback<&AndroidComponentPeer::textInputTargetGetCharIndexForPoint>, "textInputTargetGetCharIndexForPoint", "(JLandroid/graphics/Point;)I") \ CALLBACK (generatedCallback<&AndroidComponentPeer::textInputTargetGetKeyboardType>, "textInputTargetGetKeyboardType", "(J)I") \ CALLBACK (generatedCallback<&AndroidComponentPeer::textInputTargetSetTemporaryUnderlining>, "textInputTargetSetTemporaryUnderlining", "(JLjava/util/List;)V") \ CALLBACK (generatedCallback<&AndroidComponentPeer::mouseCallbackWrapper<&AndroidComponentPeer::handleMouseDownCallback>>, "handleMouseDown", "(JIFFJ)V") \ CALLBACK (generatedCallback<&AndroidComponentPeer::mouseCallbackWrapper<&AndroidComponentPeer::handleMouseDragCallback>>, "handleMouseDrag", "(JIFFJ)V") \ CALLBACK (generatedCallback<&AndroidComponentPeer::mouseCallbackWrapper<&AndroidComponentPeer::handleMouseUpCallback>>, "handleMouseUp", "(JIFFJ)V") \ CALLBACK (generatedCallback<&AndroidComponentPeer::mouseCallbackWrapper<&AndroidComponentPeer::handleAccessibilityHoverCallback>>, "handleAccessibilityHover", "(JIFFJ)V") \ DECLARE_JNI_CLASS_WITH_BYTECODE (ComponentPeerView, "com/rmsl/juce/ComponentPeerView", 16, javaComponentPeerView) #undef JNI_CLASS_MEMBERS static jboolean textInputTargetIsTextInputActive (JNIEnv*, const TextInputTarget& t) { return t.isTextInputActive(); } static jint textInputTargetGetHighlightedRegionBegin (JNIEnv*, const TextInputTarget& t) { return t.getHighlightedRegion().getStart(); } static jint textInputTargetGetHighlightedRegionEnd (JNIEnv*, const TextInputTarget& t) { return t.getHighlightedRegion().getEnd(); } static void textInputTargetSetHighlightedRegion (JNIEnv*, TextInputTarget& t, jint b, jint e) { t.setHighlightedRegion ({ b, e }); } static jstring textInputTargetGetTextInRange (JNIEnv* env, const TextInputTarget& t, jint b, jint e) { return env->NewStringUTF (t.getTextInRange ({ b, e }).toUTF8()); } static void textInputTargetInsertTextAtCaret (JNIEnv*, TextInputTarget& t, jstring text) { t.insertTextAtCaret (juceString (text)); } static jint textInputTargetGetCaretPosition (JNIEnv*, const TextInputTarget& t) { return t.getCaretPosition(); } static jint textInputTargetGetTotalNumChars (JNIEnv*, const TextInputTarget& t) { return t.getTotalNumChars(); } static jint textInputTargetGetCharIndexForPoint (JNIEnv* env, const TextInputTarget& t, jobject point) { return t.getCharIndexForPoint ({ env->GetIntField (point, AndroidPoint.x), env->GetIntField (point, AndroidPoint.y) }); } static jint textInputTargetGetKeyboardType (JNIEnv*, TextInputTarget& t) { return t.getKeyboardType(); } static std::optional> getRangeFromPair (JNIEnv* env, jobject pair) { if (pair == nullptr) return {}; const auto first = env->GetObjectField (pair, AndroidPair.first); const auto second = env->GetObjectField (pair, AndroidPair.second); if (first == nullptr || second == nullptr) return {}; const auto begin = env->CallIntMethod (first, JavaInteger.intValue); const auto end = env->CallIntMethod (second, JavaInteger.intValue); return Range { begin, end }; } static Array> javaListOfPairToArrayOfRange (JNIEnv* env, jobject list) { if (list == nullptr) return {}; Array> result; for (jint i = 0; i < env->CallIntMethod (list, JavaList.size); ++i) if (const auto range = getRangeFromPair (env, env->CallObjectMethod (list, JavaList.get, i))) result.add (*range); return result; } static void textInputTargetSetTemporaryUnderlining (JNIEnv* env, TextInputTarget& t, jobject list) { t.setTemporaryUnderlining (javaListOfPairToArrayOfRange (env, list)); } //============================================================================== class ViewWindowInsetsListener : public juce::AndroidInterfaceImplementer { public: jobject onApplyWindowInsets (LocalRef, LocalRef insets) { auto* env = getEnv(); const auto& mainDisplay = *Desktop::getInstance().getDisplays().getPrimaryDisplay(); const auto newInsets = getInsetsFromAndroidWindowInsets (insets, mainDisplay.scale); if (newInsets.tie() != JuceInsets::tie (mainDisplay)) forceDisplayUpdate(); if (const auto fieldId = AndroidWindowInsets30.CONSUMED) return env->GetStaticObjectField (AndroidWindowInsets30, fieldId); return env->CallObjectMethod (insets, AndroidWindowInsets28.consumeDisplayCutout); } private: jobject invoke (jobject proxy, jobject method, jobjectArray args) override { auto* env = getEnv(); auto methodName = juce::juceString ((jstring) env->CallObjectMethod (method, JavaMethod.getName)); if (methodName == "onApplyWindowInsets") { jassert (env->GetArrayLength (args) == 2); LocalRef windowView (env->GetObjectArrayElement (args, 0)); LocalRef insets (env->GetObjectArrayElement (args, 1)); return onApplyWindowInsets (std::move (windowView), std::move (insets)); } // invoke base class return AndroidInterfaceImplementer::invoke (proxy, method, args); } }; //============================================================================== struct PreallocatedImage : public ImagePixelData { PreallocatedImage (int width_, int height_, jint* data_, bool hasAlpha_) : ImagePixelData (Image::ARGB, width_, height_), data (data_), hasAlpha (hasAlpha_) { if (hasAlpha_) zeromem (data_, static_cast (width * height) * sizeof (jint)); } ~PreallocatedImage() override { if (hasAlpha) { auto pix = (PixelARGB*) data; for (int i = width * height; --i >= 0;) { pix->unpremultiply(); ++pix; } } } std::unique_ptr createType() const override { return std::make_unique(); } std::unique_ptr createLowLevelContext() override { return std::make_unique (Image (this)); } void initialiseBitmapData (Image::BitmapData& bm, int x, int y, Image::BitmapData::ReadWriteMode /*mode*/) override { bm.lineStride = width * static_cast (sizeof (jint)); bm.pixelStride = static_cast (sizeof (jint)); bm.pixelFormat = Image::ARGB; const auto offset = (size_t) x + (size_t) y * (size_t) width; bm.data = (uint8*) (data + offset); bm.size = sizeof (jint) * (((size_t) height * (size_t) width) - offset); } ImagePixelData::Ptr clone() override { auto s = new PreallocatedImage (width, height, nullptr, hasAlpha); s->allocatedData.malloc (sizeof (jint) * static_cast (width * height)); s->data = s->allocatedData; memcpy (s->data, data, sizeof (jint) * static_cast (width * height)); return s; } private: jint* data; HeapBlock allocatedData; bool hasAlpha; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PreallocatedImage) }; //============================================================================== void timerCallback() override { setNavBarsHidden (shouldNavBarsBeHidden (fullScreen)); setFullScreen (fullScreen); stopTimer(); } bool isKioskModeComponent() const { if (auto* kiosk = Desktop::getInstance().getKioskModeComponent()) return kiosk->getPeer() == this; return false; } bool shouldNavBarsBeHidden (bool shouldBeFullScreen) const { return (shouldBeFullScreen && isKioskModeComponent()); } void setNavBarsHidden (bool hidden) { if (navBarsHidden != hidden) { navBarsHidden = hidden; view.callVoidMethod (ComponentPeerView.setSystemUiVisibilityCompat, (navBarsHidden ? (jint) (fullScreenFlags) : (jint) (SYSTEM_UI_FLAG_VISIBLE))); } } template static void callOnMessageThread (Callback&& callback) { if (MessageManager::getInstance()->isThisTheMessageThread()) callback(); else MessageManager::callAsync (std::forward (callback)); } //============================================================================== friend class Displays; static AndroidComponentPeer* frontWindow; static GlobalRef activityCallbackListener; static constexpr int GRAVITY_LEFT = 0x3, GRAVITY_TOP = 0x30; static constexpr int TYPE_APPLICATION = 0x2; static constexpr int FLAG_NOT_TOUCH_MODAL = 0x20, FLAG_LAYOUT_IN_SCREEN = 0x100, FLAG_LAYOUT_NO_LIMITS = 0x200; static constexpr int PIXEL_FORMAT_OPAQUE = -1, PIXEL_FORMAT_TRANSPARENT = -2; static constexpr int LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS = 0x3; GlobalRef view, viewGroup, buffer; bool viewGroupIsWindow = false, fullScreen = false, navBarsHidden = false; int sizeAllocated = 0; float scale = (float) Desktop::getInstance().getDisplays().getPrimaryDisplay()->scale; //============================================================================== JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AndroidComponentPeer) }; Point AndroidComponentPeer::lastMousePos; int64 AndroidComponentPeer::touchesDown = 0; AndroidComponentPeer* AndroidComponentPeer::frontWindow = nullptr; GlobalRef AndroidComponentPeer::activityCallbackListener; //============================================================================== ComponentPeer* Component::createNewPeer (int styleFlags, void* nativeWindow) { return new AndroidComponentPeer (*this, styleFlags, nativeWindow); } //============================================================================== bool Desktop::canUseSemiTransparentWindows() noexcept { return true; } class Desktop::NativeDarkModeChangeDetectorImpl : public ActivityLifecycleCallbacks { public: NativeDarkModeChangeDetectorImpl() { LocalRef appContext (getAppContext()); if (appContext != nullptr) { auto* env = getEnv(); myself = GlobalRef (CreateJavaInterface (this, "android/app/Application$ActivityLifecycleCallbacks")); env->CallVoidMethod (appContext.get(), AndroidApplication.registerActivityLifecycleCallbacks, myself.get()); } } ~NativeDarkModeChangeDetectorImpl() override { LocalRef appContext (getAppContext()); if (appContext != nullptr && myself != nullptr) { auto* env = getEnv(); env->CallVoidMethod (appContext.get(), AndroidApplication.unregisterActivityLifecycleCallbacks, myself.get()); clear(); myself.clear(); } } bool isDarkModeEnabled() const noexcept { return darkModeEnabled; } void onActivityStarted (jobject /*activity*/) override { const auto isEnabled = getDarkModeSetting(); if (darkModeEnabled != isEnabled) { darkModeEnabled = isEnabled; Desktop::getInstance().darkModeChanged(); } } private: static bool getDarkModeSetting() { auto* env = getEnv(); const LocalRef resources (env->CallObjectMethod (getAppContext().get(), AndroidContext.getResources)); const LocalRef configuration (env->CallObjectMethod (resources, AndroidResources.getConfiguration)); const auto uiMode = env->GetIntField (configuration, AndroidConfiguration.uiMode); return ((uiMode & UI_MODE_NIGHT_MASK) == UI_MODE_NIGHT_YES); } static constexpr int UI_MODE_NIGHT_MASK = 0x00000030, UI_MODE_NIGHT_NO = 0x00000010, UI_MODE_NIGHT_UNDEFINED = 0x00000000, UI_MODE_NIGHT_YES = 0x00000020; GlobalRef myself; bool darkModeEnabled = getDarkModeSetting(); //============================================================================== JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NativeDarkModeChangeDetectorImpl) }; std::unique_ptr Desktop::createNativeDarkModeChangeDetectorImpl() { return std::make_unique(); } bool Desktop::isDarkModeActive() const { return nativeDarkModeChangeDetectorImpl->isDarkModeEnabled(); } double Desktop::getDefaultMasterScale() { return 1.0; } Desktop::DisplayOrientation Desktop::getCurrentOrientation() const { enum { ROTATION_0 = 0, ROTATION_90 = 1, ROTATION_180 = 2, ROTATION_270 = 3 }; JNIEnv* env = getEnv(); LocalRef windowServiceString (javaString ("window")); LocalRef windowManager = LocalRef (env->CallObjectMethod (getAppContext().get(), AndroidContext.getSystemService, windowServiceString.get())); if (windowManager.get() != nullptr) { LocalRef display = LocalRef (env->CallObjectMethod (windowManager, AndroidWindowManager.getDefaultDisplay)); if (display.get() != nullptr) { int rotation = env->CallIntMethod (display, AndroidDisplay.getRotation); switch (rotation) { case ROTATION_0: return upright; case ROTATION_90: return rotatedAntiClockwise; case ROTATION_180: return upsideDown; case ROTATION_270: return rotatedClockwise; } } } jassertfalse; return upright; } bool detail::MouseInputSourceList::addSource() { addSource (sources.size(), MouseInputSource::InputSourceType::touch); return true; } bool detail::MouseInputSourceList::canUseTouch() const { return true; } Point MouseInputSource::getCurrentRawMousePosition() { return AndroidComponentPeer::lastMousePos; } void MouseInputSource::setRawMousePosition (Point) { // not needed } //============================================================================== bool KeyPress::isKeyCurrentlyDown (int /*keyCode*/) { // TODO return false; } JUCE_API void JUCE_CALLTYPE Process::hide() { auto* env = getEnv(); LocalRef currentActivity (getCurrentActivity().get()); if (env->CallBooleanMethod (currentActivity.get(), AndroidActivity.moveTaskToBack, true) == 0) { GlobalRef intent (LocalRef (env->NewObject (AndroidIntent, AndroidIntent.constructor))); env->CallObjectMethod (intent, AndroidIntent.setAction, javaString ("android.intent.action.MAIN") .get()); env->CallObjectMethod (intent, AndroidIntent.addCategory, javaString ("android.intent.category.HOME").get()); env->CallVoidMethod (currentActivity.get(), AndroidContext.startActivity, intent.get()); } } //============================================================================== // TODO JUCE_API bool JUCE_CALLTYPE Process::isForegroundProcess() { return true; } JUCE_API void JUCE_CALLTYPE Process::makeForegroundProcess() {} //============================================================================== #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \ METHOD (show, "show", "()V") \ METHOD (getWindow, "getWindow", "()Landroid/view/Window;") DECLARE_JNI_CLASS (AndroidDialog, "android/app/Dialog") #undef JNI_CLASS_MEMBERS #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \ METHOD (construct, "", "(Landroid/content/Context;)V") \ METHOD (create, "create", "()Landroid/app/AlertDialog;") \ METHOD (setTitle, "setTitle", "(Ljava/lang/CharSequence;)Landroid/app/AlertDialog$Builder;") \ METHOD (setMessage, "setMessage", "(Ljava/lang/CharSequence;)Landroid/app/AlertDialog$Builder;") \ METHOD (setCancelable, "setCancelable", "(Z)Landroid/app/AlertDialog$Builder;") \ METHOD (setOnCancelListener, "setOnCancelListener", "(Landroid/content/DialogInterface$OnCancelListener;)Landroid/app/AlertDialog$Builder;") \ METHOD (setPositiveButton, "setPositiveButton", "(Ljava/lang/CharSequence;Landroid/content/DialogInterface$OnClickListener;)Landroid/app/AlertDialog$Builder;") \ METHOD (setNegativeButton, "setNegativeButton", "(Ljava/lang/CharSequence;Landroid/content/DialogInterface$OnClickListener;)Landroid/app/AlertDialog$Builder;") \ METHOD (setNeutralButton, "setNeutralButton", "(Ljava/lang/CharSequence;Landroid/content/DialogInterface$OnClickListener;)Landroid/app/AlertDialog$Builder;") DECLARE_JNI_CLASS (AndroidAlertDialogBuilder, "android/app/AlertDialog$Builder") #undef JNI_CLASS_MEMBERS #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \ METHOD (dismiss, "dismiss", "()V") DECLARE_JNI_CLASS (AndroidDialogInterface, "android/content/DialogInterface") #undef JNI_CLASS_MEMBERS #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \ DECLARE_JNI_CLASS (AndroidDialogOnClickListener, "android/content/DialogInterface$OnClickListener") #undef JNI_CLASS_MEMBERS //============================================================================== class DialogListener : public juce::AndroidInterfaceImplementer { public: explicit DialogListener (std::function cb) : callback (std::move (cb)) {} jobject invoke (jobject proxy, jobject method, jobjectArray args) override { auto* env = getEnv(); auto methodName = juce::juceString ((jstring) env->CallObjectMethod (method, JavaMethod.getName)); if (methodName == "onCancel" || methodName == "onClick") { auto* dialog = env->GetObjectArrayElement (args, 0); env->CallVoidMethod (dialog, AndroidDialogInterface.dismiss); NullCheckedInvocation::invoke (callback); return nullptr; } // invoke base class return AndroidInterfaceImplementer::invoke (proxy, method, args); } private: std::function callback; }; //============================================================================== static bool androidScreenSaverEnabled = true; void Desktop::setScreenSaverEnabled (bool shouldEnable) { constexpr auto FLAG_KEEP_SCREEN_ON = 0x80; if (shouldEnable != androidScreenSaverEnabled) { LocalRef activity (getMainActivity()); if (activity != nullptr) { auto* env = getEnv(); LocalRef mainWindow (env->CallObjectMethod (activity.get(), AndroidActivity.getWindow)); env->CallVoidMethod (mainWindow.get(), AndroidWindow.setFlags, shouldEnable ? 0 : FLAG_KEEP_SCREEN_ON, FLAG_KEEP_SCREEN_ON); } androidScreenSaverEnabled = shouldEnable; } } bool Desktop::isScreenSaverEnabled() { return androidScreenSaverEnabled; } //============================================================================== void Desktop::setKioskComponent (Component* kioskComp, bool enableOrDisable, [[maybe_unused]] bool allowMenusAndBars) { if (AndroidComponentPeer* peer = dynamic_cast (kioskComp->getPeer())) peer->setFullScreen (enableOrDisable); else jassertfalse; // (this should have been checked by the caller) } //============================================================================== static jint getAndroidOrientationFlag (int orientations) noexcept { enum { SCREEN_ORIENTATION_LANDSCAPE = 0, SCREEN_ORIENTATION_PORTRAIT = 1, SCREEN_ORIENTATION_USER = 2, SCREEN_ORIENTATION_REVERSE_LANDSCAPE = 8, SCREEN_ORIENTATION_REVERSE_PORTRAIT = 9, SCREEN_ORIENTATION_USER_LANDSCAPE = 11, SCREEN_ORIENTATION_USER_PORTRAIT = 12, }; switch (orientations) { case Desktop::upright: return (jint) SCREEN_ORIENTATION_PORTRAIT; case Desktop::upsideDown: return (jint) SCREEN_ORIENTATION_REVERSE_PORTRAIT; case Desktop::upright + Desktop::upsideDown: return (jint) SCREEN_ORIENTATION_USER_PORTRAIT; case Desktop::rotatedAntiClockwise: return (jint) SCREEN_ORIENTATION_LANDSCAPE; case Desktop::rotatedClockwise: return (jint) SCREEN_ORIENTATION_REVERSE_LANDSCAPE; case Desktop::rotatedClockwise + Desktop::rotatedAntiClockwise: return (jint) SCREEN_ORIENTATION_USER_LANDSCAPE; default: return (jint) SCREEN_ORIENTATION_USER; } } void Desktop::allowedOrientationsChanged() { LocalRef activity (getMainActivity()); if (activity != nullptr) getEnv()->CallVoidMethod (activity.get(), AndroidActivity.setRequestedOrientation, getAndroidOrientationFlag (allowedOrientations)); } //============================================================================== #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \ METHOD (create, "", "()V") \ FIELD (density, "density", "F") \ FIELD (widthPixels, "widthPixels", "I") \ FIELD (heightPixels, "heightPixels", "I") DECLARE_JNI_CLASS (AndroidDisplayMetrics, "android/util/DisplayMetrics") #undef JNI_CLASS_MEMBERS //============================================================================== class LayoutChangeListener : public juce::AndroidInterfaceImplementer { public: virtual void onLayoutChange (LocalRef view, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) = 0; private: jobject invoke (jobject proxy, jobject method, jobjectArray args) override { auto* env = getEnv(); auto methodName = juce::juceString ((jstring) env->CallObjectMethod (method, JavaMethod.getName)); if (methodName == "onLayoutChange") { jassert (env->GetArrayLength (args) == 9); LocalRef view (env->GetObjectArrayElement (args, 0)); int dims[8]; for (int i = 1; i < 9; ++i) { LocalRef integer (env->GetObjectArrayElement (args, i)); dims[i - 1] = env->CallIntMethod (integer.get(), JavaInteger.intValue); } onLayoutChange (std::move (view), dims[0], dims[1], dims[2], dims[3], dims[4], dims[5], dims[6], dims[7]); return nullptr; } // invoke base class return AndroidInterfaceImplementer::invoke (proxy, method, args); } std::unique_ptr callback; }; //============================================================================== struct MainActivityWindowLayoutListener : public LayoutChangeListener { MainActivityWindowLayoutListener (std::function&& updateDisplaysCb) : forceDisplayUpdate (std::move (updateDisplaysCb)) { } void onLayoutChange (LocalRef /*view*/, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) override { auto newBounds = Rectangle::leftTopRightBottom (left, top, right, bottom); auto oldBounds = Rectangle::leftTopRightBottom (oldLeft, oldTop, oldRight, oldBottom); if (newBounds != oldBounds) { const auto& mainDisplay = *Desktop::getInstance().getDisplays().getPrimaryDisplay(); auto userArea = (newBounds.toFloat() / mainDisplay.scale).toNearestInt(); if (userArea != mainDisplay.userArea) forceDisplayUpdate(); } } std::function forceDisplayUpdate; }; //============================================================================== void Displays::findDisplays (float masterScale) { auto* env = getEnv(); LocalRef usableSize (makeAndroidPoint ({})); LocalRef windowServiceString (javaString ("window")); LocalRef displayMetrics (env->NewObject (AndroidDisplayMetrics, AndroidDisplayMetrics.create)); LocalRef windowManager (env->CallObjectMethod (getAppContext().get(), AndroidContext.getSystemService, windowServiceString.get())); LocalRef display (env->CallObjectMethod (windowManager, AndroidWindowManager.getDefaultDisplay)); if (const auto getRealMetricsMethod = AndroidDisplay17.getRealMetrics) env->CallVoidMethod (display, getRealMetricsMethod, displayMetrics.get()); else env->CallVoidMethod (display, AndroidDisplay.getMetrics, displayMetrics.get()); env->CallVoidMethod (display, AndroidDisplay.getSize, usableSize.get()); Display d; d.isMain = true; d.scale = env->GetFloatField (displayMetrics.get(), AndroidDisplayMetrics.density); d.dpi = (d.scale * 160.f); d.scale *= masterScale; d.totalArea = Rectangle (env->GetIntField (displayMetrics.get(), AndroidDisplayMetrics.widthPixels), env->GetIntField (displayMetrics.get(), AndroidDisplayMetrics.heightPixels)) / d.scale; d.userArea = Rectangle (env->GetIntField (usableSize.get(), AndroidPoint.x), env->GetIntField (usableSize.get(), AndroidPoint.y)) / d.scale; // unfortunately usableSize still contains the nav bar // the best workaround is to try to get the size of the top-level view of // the main activity LocalRef activity (getMainActivity()); if (activity != nullptr) { LocalRef mainWindow (env->CallObjectMethod (activity.get(), AndroidActivity.getWindow)); LocalRef decorView (env->CallObjectMethod (mainWindow.get(), AndroidWindow.getDecorView)); LocalRef contentView (env->CallObjectMethod (decorView.get(), AndroidView.findViewById, 0x01020002 /* android.R.id.content */)); if (contentView != nullptr) { Rectangle activityArea (env->CallIntMethod (contentView.get(), AndroidView.getLeft), env->CallIntMethod (contentView.get(), AndroidView.getTop), env->CallIntMethod (contentView.get(), AndroidView.getWidth), env->CallIntMethod (contentView.get(), AndroidView.getHeight)); if (! activityArea.isEmpty()) d.userArea = activityArea / d.scale; if (const auto getRootWindowInsetsMethodId = AndroidView23.getRootWindowInsets) { LocalRef insets (env->CallObjectMethod (contentView.get(), getRootWindowInsetsMethodId)); JuceInsets::tie (d) = getInsetsFromAndroidWindowInsets (insets, d.scale).tie(); } static bool hasAddedMainActivityListener = false; if (! hasAddedMainActivityListener) { hasAddedMainActivityListener = true; env->CallVoidMethod (contentView.get(), AndroidView.addOnLayoutChangeListener, CreateJavaInterface (new MainActivityWindowLayoutListener ([this] { refresh(); }), "android/view/View$OnLayoutChangeListener").get()); } } } else { // the main activity may have not started yet so add an activity listener if (AndroidComponentPeer::activityCallbackListener == nullptr) { LocalRef appContext (getAppContext()); if (appContext.get() != nullptr) { AndroidComponentPeer::activityCallbackListener = GlobalRef (CreateJavaInterface ( new AndroidComponentPeer::StartupActivityCallbackListener, "android/app/Application$ActivityLifecycleCallbacks")); env->CallVoidMethod (appContext.get(), AndroidApplication.registerActivityLifecycleCallbacks, AndroidComponentPeer::activityCallbackListener.get()); } } } displays.add (d); } //============================================================================== Image detail::WindowingHelpers::createIconForFile (const File& /*file*/) { return {}; } //============================================================================== class MouseCursor::PlatformSpecificHandle { public: PlatformSpecificHandle (const MouseCursor::StandardCursorType) {} PlatformSpecificHandle (const detail::CustomMouseCursorInfo&) {} static void showInWindow (PlatformSpecificHandle*, ComponentPeer*) {} }; //============================================================================== bool DragAndDropContainer::performExternalDragDropOfFiles (const StringArray& /*files*/, bool /*canMove*/, Component* /*srcComp*/, std::function /*callback*/) { jassertfalse; // no such thing on Android! return false; } bool DragAndDropContainer::performExternalDragDropOfText (const String& /*text*/, Component* /*srcComp*/, std::function /*callback*/) { jassertfalse; // no such thing on Android! return false; } //============================================================================== void LookAndFeel::playAlertSound() { } //============================================================================== #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \ METHOD (getText, "getText", "()Ljava/lang/CharSequence;") \ METHOD (setText, "setText", "(Ljava/lang/CharSequence;)V") DECLARE_JNI_CLASS (AndroidClipboardManager, "android/content/ClipboardManager") #undef JNI_CLASS_MEMBERS //============================================================================== void SystemClipboard::copyTextToClipboard (const String& text) { auto* env = getEnv(); LocalRef clipboardManager (env->CallObjectMethod (getAppContext().get(), AndroidContext.getSystemService, javaString ("clipboard").get())); env->CallVoidMethod (clipboardManager.get(), AndroidClipboardManager.setText, javaString(text).get()); } String SystemClipboard::getTextFromClipboard() { auto* env = getEnv(); LocalRef clipboardManager (env->CallObjectMethod (getAppContext().get(), AndroidContext.getSystemService, javaString ("clipboard").get())); LocalRef charSequence (env->CallObjectMethod (clipboardManager.get(), AndroidClipboardManager.getText)); if (charSequence == nullptr) return {}; return juceString(LocalRef ((jstring) env->CallObjectMethod(charSequence.get(), JavaCharSequence.toString))); } //============================================================================== constexpr int extendedKeyModifier = 0x10000; const int KeyPress::spaceKey = ' '; const int KeyPress::returnKey = extendedKeyModifier + 2; const int KeyPress::escapeKey = extendedKeyModifier + 3; const int KeyPress::backspaceKey = extendedKeyModifier + 4; const int KeyPress::leftKey = extendedKeyModifier + 5; const int KeyPress::rightKey = extendedKeyModifier + 6; const int KeyPress::upKey = extendedKeyModifier + 7; const int KeyPress::downKey = extendedKeyModifier + 8; const int KeyPress::pageUpKey = extendedKeyModifier + 9; const int KeyPress::pageDownKey = extendedKeyModifier + 10; const int KeyPress::endKey = extendedKeyModifier + 11; const int KeyPress::homeKey = extendedKeyModifier + 12; const int KeyPress::deleteKey = extendedKeyModifier + 13; const int KeyPress::insertKey = extendedKeyModifier + 14; const int KeyPress::tabKey = extendedKeyModifier + 15; const int KeyPress::F1Key = extendedKeyModifier + 16; const int KeyPress::F2Key = extendedKeyModifier + 17; const int KeyPress::F3Key = extendedKeyModifier + 18; const int KeyPress::F4Key = extendedKeyModifier + 19; const int KeyPress::F5Key = extendedKeyModifier + 20; const int KeyPress::F6Key = extendedKeyModifier + 21; const int KeyPress::F7Key = extendedKeyModifier + 22; const int KeyPress::F8Key = extendedKeyModifier + 23; const int KeyPress::F9Key = extendedKeyModifier + 24; const int KeyPress::F10Key = extendedKeyModifier + 25; const int KeyPress::F11Key = extendedKeyModifier + 26; const int KeyPress::F12Key = extendedKeyModifier + 27; const int KeyPress::F13Key = extendedKeyModifier + 28; const int KeyPress::F14Key = extendedKeyModifier + 29; const int KeyPress::F15Key = extendedKeyModifier + 30; const int KeyPress::F16Key = extendedKeyModifier + 31; const int KeyPress::F17Key = extendedKeyModifier + 32; const int KeyPress::F18Key = extendedKeyModifier + 33; const int KeyPress::F19Key = extendedKeyModifier + 34; const int KeyPress::F20Key = extendedKeyModifier + 35; const int KeyPress::F21Key = extendedKeyModifier + 36; const int KeyPress::F22Key = extendedKeyModifier + 37; const int KeyPress::F23Key = extendedKeyModifier + 38; const int KeyPress::F24Key = extendedKeyModifier + 39; const int KeyPress::F25Key = extendedKeyModifier + 40; const int KeyPress::F26Key = extendedKeyModifier + 41; const int KeyPress::F27Key = extendedKeyModifier + 42; const int KeyPress::F28Key = extendedKeyModifier + 43; const int KeyPress::F29Key = extendedKeyModifier + 44; const int KeyPress::F30Key = extendedKeyModifier + 45; const int KeyPress::F31Key = extendedKeyModifier + 46; const int KeyPress::F32Key = extendedKeyModifier + 47; const int KeyPress::F33Key = extendedKeyModifier + 48; const int KeyPress::F34Key = extendedKeyModifier + 49; const int KeyPress::F35Key = extendedKeyModifier + 50; const int KeyPress::numberPad0 = extendedKeyModifier + 51; const int KeyPress::numberPad1 = extendedKeyModifier + 52; const int KeyPress::numberPad2 = extendedKeyModifier + 53; const int KeyPress::numberPad3 = extendedKeyModifier + 54; const int KeyPress::numberPad4 = extendedKeyModifier + 55; const int KeyPress::numberPad5 = extendedKeyModifier + 56; const int KeyPress::numberPad6 = extendedKeyModifier + 57; const int KeyPress::numberPad7 = extendedKeyModifier + 58; const int KeyPress::numberPad8 = extendedKeyModifier + 59; const int KeyPress::numberPad9 = extendedKeyModifier + 60; const int KeyPress::numberPadAdd = extendedKeyModifier + 61; const int KeyPress::numberPadSubtract = extendedKeyModifier + 62; const int KeyPress::numberPadMultiply = extendedKeyModifier + 63; const int KeyPress::numberPadDivide = extendedKeyModifier + 64; const int KeyPress::numberPadSeparator = extendedKeyModifier + 65; const int KeyPress::numberPadDecimalPoint = extendedKeyModifier + 66; const int KeyPress::numberPadEquals = extendedKeyModifier + 67; const int KeyPress::numberPadDelete = extendedKeyModifier + 68; const int KeyPress::playKey = extendedKeyModifier + 69; const int KeyPress::stopKey = extendedKeyModifier + 70; const int KeyPress::fastForwardKey = extendedKeyModifier + 71; const int KeyPress::rewindKey = extendedKeyModifier + 72; //============================================================================== #ifdef JUCE_PUSH_NOTIFICATIONS_ACTIVITY struct JuceActivityNewIntentListener { #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \ CALLBACK (appNewIntent, "appNewIntent", "(Landroid/content/Intent;)V") \ CALLBACK (appOnResume, "appOnResume", "()V") DECLARE_JNI_CLASS (JavaActivity, JUCE_PUSH_NOTIFICATIONS_ACTIVITY) #undef JNI_CLASS_MEMBERS static void JNICALL appNewIntent (JNIEnv*, jobject /*activity*/, jobject intentData) { juce_handleNotificationIntent (static_cast (intentData)); } static void JNICALL appOnResume (JNIEnv*, jobject) { juce_handleOnResume(); } }; #endif } // namespace juce